返回 DeepSeek-Reasonix
sessionSubmissionOwner.ts
根目录 / desktop / frontend / src / app-runtime / sessionSubmissionOwner.ts
1 import type { CollaborationMode, ToolApprovalMode } from "../lib/types";
2 import type { StructuredInvocationSubmit } from "../lib/invocationDisplay";
3 import type { SessionOperationAuthority, SessionResource } from "./useSessionOperations";
4
5 export type InitialGoal = { goal: string; collaborationMode: CollaborationMode; toolApprovalMode: ToolApprovalMode };
6 export type SubmissionResource = {
7 target: SessionResource; remote: boolean; ready: boolean; unavailable: string; goalDraft: boolean;
8 collaboration: CollaborationMode; approval: ToolApprovalMode;
9 };
10 export type Submission = { display: string; submit?: string; structured?: StructuredInvocationSubmit; initialGoal?: InitialGoal };
11 export type SubmissionPorts = {
12 send(tab: string, display: string, submit?: string, structured?: StructuredInvocationSubmit, goal?: InitialGoal): Promise<void>;
13 clearUndo(tab: string): void;
14 setGoal(tab: string, goal: string, remote: boolean): Promise<void>;
15 patchGoal(tab: string, goal: string): void;
16 profile(tab: string, propagateError: boolean): Promise<boolean>;
17 };
18 export type SubmissionInput = {
19 target: SessionResource; read(target: SessionResource): SubmissionResource; ports: SubmissionPorts;
20 request: { kind: "direct" | "composer"; content: Submission } | { kind: "goal"; goal: string };
21 };
22
23 export function buildInitialGoalSubmission(
24 content: Submission,
25 collaborationMode: CollaborationMode,
26 toolApprovalMode: ToolApprovalMode,
27 ): Submission {
28 const display = content.display.trim();
29 const submit = (content.submit ?? content.display).trim();
30 return {
31 display,
32 submit: content.structured ? submit : `/goal ${submit}`,
33 structured: content.structured,
34 initialGoal: { goal: display, collaborationMode, toolApprovalMode },
35 };
36 }
37 const legacyFlags = new Set(["--research", "--auto-research", "--deep", "--simple", "--no-research"]);
38 export function goalCommand(input: string) {
39 const match = /^\/goal(?:\s+(.*))?$/.exec(input);
40 if (!match) return undefined;
41 const parts = (match[1] ?? "").trim().split(/\s+/).filter(Boolean);
42 const legacy = legacyFlags.has(parts[0]?.toLowerCase());
43 while (legacyFlags.has(parts[0]?.toLowerCase())) parts.shift();
44 const value = parts.join(" ");
45 const action = value.toLowerCase();
46 return { value, legacy, activate: Boolean(value) && !["status", "clear", "off", "stop", "done", "pause", "resume"].includes(action),
47 clear: ["clear", "off", "stop", "done"].includes(action) };
48 }
49
50 async function applyGoal(input: SubmissionInput, goal: string, authority: SessionOperationAuthority) {
51 authority.checkpoint();
52 await input.ports.setGoal(input.target.tabId, goal, input.read(input.target).remote);
53 authority.checkpoint();
54 input.ports.patchGoal(input.target.tabId, goal);
55 }
56
57 async function send(input: SubmissionInput, content: Submission, authority: SessionOperationAuthority) {
58 authority.checkpoint();
59 const source = input.read(input.target);
60 if (!source.ready || source.unavailable) throw Error(source.unavailable);
61 input.ports.clearUndo(input.target.tabId);
62 await input.ports.send(input.target.tabId, content.display, content.submit, content.structured, content.initialGoal);
63 authority.checkpoint();
64 }
65
66 /** Only minimal source data survives awaits. No active-tab reads or render refs. */
67 export async function executeSubmission(input: SubmissionInput, authority: SessionOperationAuthority): Promise<void> {
68 authority.checkpoint();
69 if (input.request.kind === "goal") return applyGoal(input, input.request.goal.trim(), authority);
70 const { content } = input.request;
71 if (input.request.kind === "direct") return send(input, content, authority);
72 const source = input.read(input.target);
73 const display = content.display.trim();
74 const submit = content.submit ?? content.display;
75 const command = goalCommand(display);
76 if (command) {
77 if (command.activate) {
78 if (command.legacy) input.ports.patchGoal(input.target.tabId, command.value);
79 else await applyGoal(input, command.value, authority);
80 } else if (command.clear) await applyGoal(input, "", authority);
81 authority.checkpoint();
82 if (input.read(input.target).ready) await send(input, { display, submit: submit.trim() }, authority);
83 return;
84 }
85 if (!source.ready) return;
86 if (source.goalDraft) {
87 await send(input, buildInitialGoalSubmission(
88 { display, submit, structured: content.structured }, source.collaboration, source.approval,
89 ), authority);
90 authority.checkpoint();
91 input.ports.patchGoal(input.target.tabId, display);
92 return;
93 }
94 if (!await input.ports.profile(input.target.tabId, false)) return;
95 authority.checkpoint();
96 await send(input, { display, submit: submit.trim(), structured: content.structured }, authority);
97 }
98
98 lines TYPESCRIPT