返回 DeepSeek-Reasonix
sessionLifecycleBindings.ts
根目录 / desktop / frontend / src / lib / sessionLifecycleBindings.ts
1 import type { AppBindings } from "./bridge";
2 import type { SessionRef } from "./sessionRef";
3 import type { WorkspaceSnapshot } from "../generated/desktopContract.generated";
4 import type { HistoryPage } from "./types";
5
6 export interface CanonicalProjectNodeFields {
7 session?: SessionRef;
8 canArchive?: boolean;
9 }
10
11 export interface SessionLifecycleBindings {
12 ListHistoricalSessions?(): Promise<import("../generated/desktopContract.generated").HistoricalImportStatus>;
13 GetHistoricalImportStatus?(): Promise<import("../generated/desktopContract.generated").HistoricalImportStatus>;
14 ImportHistoricalSession?(id: string): Promise<import("../generated/desktopContract.generated").SessionRestoreResult>;
15 PrepareSession?(selector: import("../generated/desktopContract.generated").SessionSelector): Promise<import("../generated/desktopContract.generated").SessionPreparationView>;
16 GetSessionPreparation?(operationId: string): Promise<import("../generated/desktopContract.generated").SessionPreparationView>;
17 CancelSessionPreparation?(operationId: string): Promise<import("../generated/desktopContract.generated").SessionPreparationView>;
18 CheckHistoricalSourceUpdate?(selector: import("../generated/desktopContract.generated").SessionSelector): Promise<import("../generated/desktopContract.generated").HistoricalSourceUpdateView>;
19 PrepareHistoricalSourceVersion?(source: import("../generated/desktopContract.generated").SessionSourceRef, version: string): Promise<import("../generated/desktopContract.generated").SessionPreparationView>;
20 StartHistoricalImport?(ids: string[]): Promise<import("../generated/desktopContract.generated").HistoricalImportStatus>;
21 ControlHistoricalImport?(action: string): Promise<import("../generated/desktopContract.generated").HistoricalImportStatus>;
22 ApplySessionLifecycle(request: import("../generated/desktopContract.generated").SessionLifecycleRequest): Promise<import("../generated/desktopContract.generated").SessionLifecycleResult>;
23 ListTrashEntries(query: string, cursor: string, limit: number): Promise<import("../generated/desktopContract.generated").TrashEntryPage>;
24 ListRecoveryEntries(query: string, cursor: string, limit: number): Promise<import("../generated/desktopContract.generated").RecoveryEntryPage>;
25 PreviewRecoveryEntry(id: string): Promise<HistoryPage>;
26 RestoreRecoveryEntry(id: string, operationId: string): Promise<import("../generated/desktopContract.generated").SessionRestoreResult>;
27 GetSessionUpgradeStatus(): Promise<import("../generated/desktopContract.generated").SessionUpgradeStatus>;
28 PurgeCanonicalSession(ref: SessionRef): Promise<void>;
29 }
30
31 export function makeMockSessionLifecycleBindings(mockWorkspaceSnapshot: () => WorkspaceSnapshot, mockArchivedSessionIDs: Set<string>, mockPurgedSessionIDs: Set<string>, notifyMockProjectTreeChanged: () => void): SessionLifecycleBindings {
32 const mockLifecycleResults = new Map<string, { request: string; result: import("../generated/desktopContract.generated").SessionLifecycleResult }>();
33 return {
34 async PurgeCanonicalSession(ref: SessionRef) {
35 if (!mockArchivedSessionIDs.has(ref.sessionId) && !mockPurgedSessionIDs.has(ref.sessionId)) throw new Error("Only archived sessions can be permanently deleted");
36 mockPurgedSessionIDs.add(ref.sessionId); mockArchivedSessionIDs.delete(ref.sessionId); notifyMockProjectTreeChanged();
37 },
38 async ListTrashEntries(this: AppBindings, query, cursor, limit) {
39 const items: import("../generated/desktopContract.generated").TrashEntry[] = [];
40 for (const workspace of mockWorkspaceSnapshot().workspaces) {
41 const page = await this.ListWorkspaceSessions(workspace.id, query, "", 1000, true);
42 items.push(...page.sessions.filter(row => row.archived).map(row => ({ id: row.ref.sessionId, ref: row.ref, title: row.title,
43 workspaceId: workspace.id, workspaceTitle: workspace.title, archivedAt: 0, health: "ready", canPreview: true, canRestore: true, canPurge: true })));
44 }
45 const offset = Number(cursor || 0), end = offset + limit;
46 return { items: items.slice(offset, end), generation: 1, nextCursor: end < items.length ? String(end) : "" };
47 },
48 async ApplySessionLifecycle(this: AppBindings, request) {
49 const previous = mockLifecycleResults.get(request.operationId), encoded = JSON.stringify(request);
50 if (previous) { if (previous.request !== encoded) throw new Error("Lifecycle request conflict"); return previous.result; }
51 const result: import("../generated/desktopContract.generated").SessionLifecycleResult = { operationId: request.operationId, generation: 1, committed: true, items: [] };
52 for (const target of request.targets) {
53 if (!target.ref) throw new Error("Unknown mock recovery entry");
54 if (request.action === "archive") await this.ArchiveCanonicalSession(target.ref);
55 else if (request.action === "restore") await this.RestoreCanonicalSession(target.ref);
56 else await this.PurgeCanonicalSession(target.ref);
57 const workspace = mockWorkspaceSnapshot().workspaces.find(row => row.sessionIds.includes(target.ref!.sessionId));
58 result.items.push({ target, ref: target.ref, workspaceId: workspace?.id || "global", committed: true, retryable: false });
59 }
60 mockLifecycleResults.set(request.operationId, { request: encoded, result });
61 return result;
62 },
63 async ListRecoveryEntries() { return { items: [], generation: 1 }; },
64 async PreviewRecoveryEntry() { return { messages: [], startTurn: 0, endTurn: 0, totalTurns: 0, hasOlder: false }; },
65 async RestoreRecoveryEntry() { throw new Error("recovery entry is unavailable"); },
66 async GetSessionUpgradeStatus() { return { sources: 0, sessions: 0, operations: 0, discovered: 0, migrated: 0, pending: 0, failed: 0, conflicts: 0, pendingOperations: 0 }; },
67 };
68 }
69
69 lines TYPESCRIPT