| 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 |