返回 DeepSeek-Reasonix
manualCreationRequests.ts
根目录 / desktop / frontend / src / lib / manualCreationRequests.ts
1 import { app } from "./bridge";
2 import type { ManualSessionCreationRequest, ManualSessionCreationView } from "../generated/desktopContract.generated";
3
4 /** Ephemeral presentation only; the host owns durable recovery and drafts. */
5 export type ManualCreationObservation = {
6 request: ManualSessionCreationRequest;
7 operation?: ManualSessionCreationView;
8 pending: boolean;
9 failed: boolean;
10 };
11
12 export async function createManualSession(request: ManualSessionCreationRequest, options?: {
13 onSurfaceReady: (operation: ManualSessionCreationView) => Promise<void>;
14 isObservationCurrent?: () => boolean;
15 onProgress?: (operation: ManualSessionCreationView) => void;
16 retry?: boolean;
17 }) {
18 let operation;
19 try { operation = await app.BeginManualSessionCreation(request); }
20 catch (error) {
21 // A lost response is resolved against the original persisted identity.
22 try { operation = await app.GetManualSessionCreation(request.operationId); }
23 catch { throw error; }
24 }
25 if (options?.retry && operation.phase !== "ready") operation = await app.RetryManualSessionCreation(request.operationId);
26 let surfaceOpened = false;
27 let lastProgress = "";
28 while (true) {
29 // Acknowledgement transfers creation to the host. Leaving this surface
30 // stops only its observer, never the durable operation or its recovery.
31 if (options?.isObservationCurrent?.() === false) return operation;
32 // Elapsed milliseconds change on every read; repaint only meaningful state.
33 const progress = JSON.stringify([operation.phase, operation.surfaceReady, operation.ref, operation.error,
34 operation.progress?.status, operation.progress?.slow, operation.progress?.errorCode]);
35 if (progress !== lastProgress) { lastProgress = progress; options?.onProgress?.(operation); }
36 // The host publishes a formal session before constructing its runtime. Open
37 // that identity once so typing can start; completion must never reselect it.
38 // Older hosts only publish a usable surface at ready.
39 if (!surfaceOpened && (operation.surfaceReady || operation.phase === "ready")) {
40 surfaceOpened = true;
41 await options?.onSurfaceReady(operation);
42 }
43 const status = operation.progress?.status;
44 const recovering = status && ["queued", "running", "waiting_lock", "waiting_workspace", "retrying_storage"].includes(status);
45 if (options?.isObservationCurrent?.() === false || operation.phase === "ready" || status === "blocked" || status === "stopped" || status === "stopping"
46 || (!recovering && operation.phase !== "reserved" && operation.phase !== "starting")) return operation;
47 await new Promise(resolve => setTimeout(resolve, 150));
48 if (options?.isObservationCurrent?.() === false) return operation;
49 operation = await app.GetManualSessionCreation(request.operationId);
50 }
51 }
52
52 lines TYPESCRIPT