Skip to content
Source
Sign inSign up

chatThreadActions.ts

95 lines2.7 KB

1import { scopeProjectRef } from "@t3tools/client-runtime/environment";
2import type {
3 EnvironmentId,
4 ModelSelection,
5 ProjectId,
6 ScopedProjectRef,
7} from "@t3tools/contracts";
8import type { ComposerThreadDraftState, DraftThreadEnvMode } from "../composerDraftStore";
9​
10type ComposerModelSelectionState = Pick<
11 ComposerThreadDraftState,
12 "activeProvider" | "modelSelectionByProvider" | "modelSelectionExplicit"
13>;
14​
15interface ThreadContextLike {
16 environmentId: EnvironmentId;
17 projectId: ProjectId;
19​
20interface NewThreadHandler {
21 (
22 projectRef: ScopedProjectRef,
23 options?: {
24 branch?: string | null;
25 worktreePath?: string | null;
26 envMode?: DraftThreadEnvMode;
27 startFromOrigin?: boolean;
28 },
29 ): Promise<unknown>;
31​
32export interface ChatThreadActionContext {
33 readonly activeDraftThread: ThreadContextLike | null;
34 readonly activeThread: ThreadContextLike | undefined;
35 readonly defaultProjectRef: ScopedProjectRef | null;
36 readonly handleNewThread: NewThreadHandler;
38​
39export function resolveNewDraftStartFromOrigin(input: {
40 envMode: DraftThreadEnvMode;
41 newWorktreesStartFromOrigin: boolean;
42}): boolean {
43 return input.envMode === "worktree" && input.newWorktreesStartFromOrigin;
45​
46export function resolveNewThreadModelSelectionOverride(input: {
47 readonly projectDefaultSelection: ModelSelection | null;
48 readonly carrySelection: ModelSelection | null;
49 readonly carrySourceDraftId: string | null;
50 readonly destinationDraftId: string;
51}): ModelSelection | null {
52 return (
53 input.projectDefaultSelection ??
54 (input.carrySourceDraftId === input.destinationDraftId ? null : input.carrySelection)
55 );
57​
58export function hasExplicitComposerModelSelection(
59 draft: ComposerModelSelectionState | null | undefined,
60): boolean {
61 const activeProvider = draft?.activeProvider;
62 return (
63 draft?.modelSelectionExplicit === true &&
64 activeProvider !== null &&
65 activeProvider !== undefined &&
66 draft.modelSelectionByProvider[activeProvider] !== undefined
67 );
69​
70export function resolveThreadActionProjectRef(
71 context: ChatThreadActionContext,
72): ScopedProjectRef | null {
73 if (context.activeThread) {
74 return scopeProjectRef(context.activeThread.environmentId, context.activeThread.projectId);
75 }
76 if (context.activeDraftThread) {
77 return scopeProjectRef(
78 context.activeDraftThread.environmentId,
79 context.activeDraftThread.projectId,
80 );
81 }
82 return context.defaultProjectRef;
84​
85export async function startNewThreadFromContext(
86 context: ChatThreadActionContext,
87): Promise<boolean> {
88 const projectRef = resolveThreadActionProjectRef(context);
89 if (!projectRef) {
90 return false;
91 }
92​
93 await context.handleNewThread(projectRef);
94 return true;