import { scopeProjectRef } from "@t3tools/client-runtime/environment"; import type { EnvironmentId, ProjectId, ScopedProjectRef } from "@t3tools/contracts"; import type { DraftThreadEnvMode } from "../composerDraftStore"; interface ThreadContextLike { environmentId: EnvironmentId; projectId: ProjectId; branch: string | null; worktreePath: string | null; } interface DraftThreadContextLike extends ThreadContextLike { envMode: DraftThreadEnvMode; startFromOrigin: boolean; } interface NewThreadHandler { ( projectRef: ScopedProjectRef, options?: { branch?: string | null; worktreePath?: string | null; envMode?: DraftThreadEnvMode; startFromOrigin?: boolean; }, ): Promise; } type NewThreadOptions = NonNullable[1]>; export interface ChatThreadActionContext { readonly activeDraftThread: DraftThreadContextLike | null; readonly activeThread: ThreadContextLike | undefined; readonly defaultProjectRef: ScopedProjectRef | null; readonly handleNewThread: NewThreadHandler; } export function resolveNewDraftStartFromOrigin(input: { envMode: DraftThreadEnvMode; newWorktreesStartFromOrigin: boolean; }): boolean { return input.envMode === "worktree" && input.newWorktreesStartFromOrigin; } export function resolveThreadActionProjectRef( context: ChatThreadActionContext, ): ScopedProjectRef | null { if (context.activeThread) { return scopeProjectRef(context.activeThread.environmentId, context.activeThread.projectId); } if (context.activeDraftThread) { return scopeProjectRef( context.activeDraftThread.environmentId, context.activeDraftThread.projectId, ); } return context.defaultProjectRef; } function buildContextualThreadOptions(context: ChatThreadActionContext): NewThreadOptions { return { branch: context.activeThread?.branch ?? context.activeDraftThread?.branch ?? null, worktreePath: context.activeThread?.worktreePath ?? context.activeDraftThread?.worktreePath ?? null, envMode: context.activeDraftThread?.envMode ?? (context.activeThread?.worktreePath ? "worktree" : "local"), ...(context.activeDraftThread ? { startFromOrigin: context.activeDraftThread.startFromOrigin } : {}), }; } export async function startNewThreadInProjectFromContext( context: ChatThreadActionContext, projectRef: ScopedProjectRef, ): Promise { await context.handleNewThread(projectRef, buildContextualThreadOptions(context)); } export async function startNewThreadFromContext( context: ChatThreadActionContext, ): Promise { const projectRef = resolveThreadActionProjectRef(context); if (!projectRef) { return false; } await startNewThreadInProjectFromContext(context, projectRef); return true; } export async function startNewLocalThreadFromContext( context: ChatThreadActionContext, ): Promise { const projectRef = resolveThreadActionProjectRef(context); if (!projectRef) { return false; } await context.handleNewThread(projectRef); return true; }