返回 DeepSeek-Reasonix
sessionLifecycleMock.ts
根目录 / desktop / frontend / src / lib / sessionLifecycleMock.ts
1 import type { AppBindings } from "./bridge";
2 import type { MockSessionLifecycleBindings } from "./sessionLifecycleBindings";
3 import type { SessionRef } from "./sessionRef";
4 import type { WorkspaceSnapshot } from "../generated/desktopContract.generated";
5 import type { ProjectNode } from "./types";
6 import { trash, recover, inspect, remove } from "./topicRemovalMock";
7 export function makeMockSessionLifecycleBindings(mockWorkspaceSnapshot: () => WorkspaceSnapshot, mockArchivedSessionIDs: Set<string>, mockPurgedSessionIDs: Set<string>, notifyMockProjectTreeChanged: () => void, tree: ProjectNode[] = []): MockSessionLifecycleBindings {
8 const mockLifecycleResults = new Map<string, { request: string; result: import("../generated/desktopContract.generated").SessionLifecycleResult }>();
9 return {
10 async InspectTopicRemoval(target) { return inspect(tree, target); },
11 async RemoveTopic(request) { return remove(tree, request); },
12 async PurgeCanonicalSession(ref: SessionRef) {
13 if (!mockArchivedSessionIDs.has(ref.sessionId) && !mockPurgedSessionIDs.has(ref.sessionId)) throw new Error("Only archived sessions can be permanently deleted");
14 mockPurgedSessionIDs.add(ref.sessionId); mockArchivedSessionIDs.delete(ref.sessionId); notifyMockProjectTreeChanged();
15 },
16 async ListTrashEntries(this: AppBindings, query, cursor, limit) {
17 const items: import("../generated/desktopContract.generated").TrashEntry[] = [];
18 for (const workspace of mockWorkspaceSnapshot().workspaces) {
19 const page = await this.ListWorkspaceSessions(workspace.id, query, "", 1000, true);
20 items.push(...page.sessions.filter(row => row.archived).map(row => ({ id: row.ref.sessionId, ref: row.ref, title: row.title,
21 workspaceId: workspace.id, workspaceTitle: workspace.title, archivedAt: 0, health: "ready", canPreview: true, canRestore: true, canPurge: true })));
22 }
23 const metadata = trash(tree);
24 items.push(...metadata.items.filter(item => item.title.toLowerCase().includes(query.toLowerCase())));
25 const offset = Number(cursor || 0), end = offset + limit;
26 return { items: items.slice(offset, end), generation: metadata.generation, nextCursor: end < items.length ? String(end) : "" };
27 },
28 async ApplySessionLifecycle(this: AppBindings, request) {
29 const previous = mockLifecycleResults.get(request.operationId), encoded = JSON.stringify(request);
30 if (previous) { if (previous.request !== encoded) throw new Error("Lifecycle request conflict"); return previous.result; }
31 const result: import("../generated/desktopContract.generated").SessionLifecycleResult = { operationId: request.operationId, generation: 1, committed: true, items: [] };
32 for (const target of request.targets) {
33 if (target.recoveryEntryId?.startsWith("topic-removal:")) {
34 if (!target.workspaceId) throw new Error("Missing recovery workspace");
35 recover(tree, target.recoveryEntryId, target.workspaceId, request.action);
36 result.items.push({ target, workspaceId: target.workspaceId, committed: true, retryable: false });
37 result.generation = trash(tree).generation;
38 continue;
39 }
40 if (!target.ref) throw new Error("Unknown mock recovery entry");
41 if (request.action === "archive") await this.ArchiveCanonicalSession(target.ref);
42 else if (request.action === "restore") await this.RestoreCanonicalSession(target.ref);
43 else await this.PurgeCanonicalSession(target.ref);
44 const workspace = mockWorkspaceSnapshot().workspaces.find(row => row.sessionIds.includes(target.ref!.sessionId));
45 result.items.push({ target, ref: target.ref, workspaceId: workspace?.id || "global", committed: true, retryable: false });
46 }
47 mockLifecycleResults.set(request.operationId, { request: encoded, result });
48 return result;
49 },
50 async ListRecoveryEntries() { return { items: [], generation: 1 }; },
51 async PreviewRecoveryEntry() { return { messages: [], startTurn: 0, endTurn: 0, totalTurns: 0, hasOlder: false }; },
52 async RestoreRecoveryEntry() { throw new Error("recovery entry is unavailable"); },
53 async GetSessionUpgradeStatus() { return { sources: 0, sessions: 0, operations: 0, discovered: 0, migrated: 0, pending: 0, failed: 0, conflicts: 0, pendingOperations: 0 }; },
54 };
55 }
56
56 lines TYPESCRIPT