1import { scopeThreadRef } from "@t3tools/client-runtime/environment";
2import type { EnvironmentId, ScopedThreadRef } from "@t3tools/contracts";
3
4import { useProjects } from "~/state/entities";
5
6import { useHandleNewThread } from "./useHandleNewThread";
7
8export interface ActiveProjectTarget {
9 readonly environmentId: EnvironmentId;
10 readonly cwd: string;
11 readonly projectName: string;
12 readonly threadRef: ScopedThreadRef;
13}
14
15/**
16 * Resolves the project workspace behind the active thread (or draft) so
17 * project-scoped surfaces like the file picker and content search know which
18 * workspace to query and which thread's right panel opens their results.
19 */
20export function useActiveProjectTarget(): ActiveProjectTarget | null {
21 const { activeDraftThread, activeThread } = useHandleNewThread();
22 const projects = useProjects();
23 const thread = activeThread ?? activeDraftThread;
24 const threadId = activeThread?.id ?? activeDraftThread?.threadId;
25 const project = thread
26 ? projects.find(
27 (candidate) =>
28 candidate.environmentId === thread.environmentId && candidate.id === thread.projectId,
29 )
30 : null;
31 const cwd = thread?.worktreePath ?? project?.workspaceRoot;
32
33 if (!thread || !threadId || !project || !cwd) return null;
34
35 return {
36 environmentId: project.environmentId,
37 cwd,
38 projectName: project.title,
39 threadRef: scopeThreadRef(thread.environmentId, threadId),
40 };
41}