返回 DeepSeek-Reasonix
transcriptDiagnostics.ts
根目录 / desktop / frontend / src / lib / transcriptDiagnostics.ts
1 import { addBreadcrumb } from "./breadcrumbs";
2 import { desktopHost, type RendererDiagnosticPayload } from "./desktopHost";
3
4 export type TranscriptDiagnosticStage =
5 | "none"
6 | "baseline_read"
7 | "baseline_validate"
8 | "snapshot_install"
9 | "delta_read"
10 | "delta_validate"
11 | "delta_apply";
12
13 export type TranscriptDiagnosticReason =
14 | "transport_rejected"
15 | "protocol_version"
16 | "snapshot_missing"
17 | "history_not_ready"
18 | "revision_regressed"
19 | "revision_gap"
20 | "business_gap"
21 | "frame_cut_mismatch"
22 | "sampling_identity_missing"
23 | "sampling_gap"
24 | "settlement_not_committed"
25 | "settlement_identity_mismatch"
26 | "resync_required"
27 | "consumer_error"
28 | "service_stopping"
29 | "unknown";
30
31 export type TranscriptDiagnostic = RendererDiagnosticPayload & {
32 kind: "transcript";
33 event: "failure" | "summary" | "recovered" | "stopped";
34 stage: TranscriptDiagnosticStage;
35 reason: TranscriptDiagnosticReason;
36 transport: "local" | "remote";
37 errorType: "classified" | "error" | "string" | "object" | "unknown";
38 };
39
40 const active = new Map<number, string>();
41 let nextOwner = 1;
42 const crashSnapshotHost = globalThis as typeof globalThis & { __reasonixTranscriptDiagnostics?: string };
43
44 function formatDiagnostic(event: TranscriptDiagnostic): string {
45 return `${event.event} stage=${event.stage} reason=${event.reason} type=${event.errorType} transport=${event.transport} revision=${event.revision} commit=${event.commit} attempts=${event.attempts} failures=${event.failures} duration_ms=${event.durationMs}`;
46 }
47
48 function syncCrashSnapshot(): void {
49 crashSnapshotHost.__reasonixTranscriptDiagnostics = [...active.values()].join("\n");
50 }
51
52 export function newTranscriptDiagnosticOwner(): number {
53 return nextOwner++;
54 }
55
56 export function publishTranscriptDiagnostic(owner: number, event: TranscriptDiagnostic, visible = true): void {
57 const message = formatDiagnostic(event);
58 if (event.event === "failure" || event.event === "summary") active.set(owner, message);
59 else active.delete(owner);
60 syncCrashSnapshot();
61 if (!visible) return;
62 addBreadcrumb("transcript.v2", message);
63 try {
64 void desktopHost().native.recordRendererDiagnostic(event).catch(() => undefined);
65 } catch {
66 // Diagnostics are optional; a broken host must not interrupt following.
67 }
68 }
69
70 export function clearTranscriptDiagnostic(owner: number): void {
71 active.delete(owner);
72 syncCrashSnapshot();
73 }
74
74 lines TYPESCRIPT