返回 DeepSeek-Reasonix
useProjectTreeFrontendDiagnostics.ts
根目录 / desktop / frontend / src / lib / useProjectTreeFrontendDiagnostics.ts
1 import { useCallback, useEffect, useRef } from "react";
2 import { recordFrontendDiagnostic, registerFrontendDiagnosticStartHook } from "./frontendDiagnosticBridge";
3 import type { ProjectTreeVariant } from "./projectTreeTopic";
4 import type { ProjectTreeSessionDiagnosticSummary } from "./projectTreeDiagnostics";
5
6 export type ProjectTreeDiagnosticSnapshot = ProjectTreeSessionDiagnosticSummary & {
7 directoryState: string;
8 scope: string;
9 variant: ProjectTreeVariant;
10 queryActive: boolean;
11 catalogPartial: boolean;
12 catalogRebuilding: boolean;
13 catalogRevision: number;
14 catalogIndexed: number;
15 catalogTotal: number;
16 unloadedSessions: number;
17 repairPending: number;
18 treeRevision: number;
19 organizationRevision: number;
20 };
21
22 function changeReason(previous: ProjectTreeDiagnosticSnapshot | null, current: ProjectTreeDiagnosticSnapshot): string {
23 if (!previous) return "initial";
24 if (previous.recoveryCopies !== current.recoveryCopies || previous.recoveryCopySessions !== current.recoveryCopySessions) return "recovery-copy";
25 if (previous.runtimeOnlySessions !== current.runtimeOnlySessions || previous.runtimeSessions !== current.runtimeSessions) return "runtime-session";
26 if (previous.activeSessions !== current.activeSessions || previous.activeVisibleSessions !== current.activeVisibleSessions) return "active-session";
27 if (previous.queryActive !== current.queryActive || previous.hiddenByFilter !== current.hiddenByFilter) return "filter";
28 if (previous.visibleSessions !== current.visibleSessions || previous.hiddenSessions !== current.hiddenSessions || previous.hiddenByCollapsed !== current.hiddenByCollapsed || previous.hiddenByTruncation !== current.hiddenByTruncation || previous.expandedFolders !== current.expandedFolders || previous.showAllFolders !== current.showAllFolders) return "visibility";
29 if (previous.workspaceSessions !== current.workspaceSessions || previous.folderCount !== current.folderCount || previous.catalogRevision !== current.catalogRevision || previous.catalogIndexed !== current.catalogIndexed || previous.catalogTotal !== current.catalogTotal || previous.unloadedSessions !== current.unloadedSessions || previous.repairPending !== current.repairPending || previous.treeRevision !== current.treeRevision || previous.organizationRevision !== current.organizationRevision || previous.directoryState !== current.directoryState) return "catalog";
30 return "directory-update";
31 }
32
33 export function useProjectTreeFrontendDiagnostics(snapshot: ProjectTreeDiagnosticSnapshot): void {
34 const currentRef = useRef(snapshot);
35 const previousRef = useRef<ProjectTreeDiagnosticSnapshot | null>(null);
36 const lastSignatureRef = useRef("");
37 currentRef.current = snapshot;
38 const signature = JSON.stringify(snapshot);
39 const emit = useCallback((force = false, reasonOverride?: string) => {
40 const current = currentRef.current;
41 if (!force && signature === lastSignatureRef.current) return;
42 const previous = previousRef.current;
43 recordFrontendDiagnostic("workspace", "workspace.session-directory", {
44 ...current,
45 changeReason: reasonOverride ?? changeReason(previous, current),
46 deltaWorkspaceSessions: previous ? current.workspaceSessions - previous.workspaceSessions : 0,
47 deltaVisibleSessions: previous ? current.visibleSessions - previous.visibleSessions : 0,
48 deltaHiddenSessions: previous ? current.hiddenSessions - previous.hiddenSessions : 0,
49 deltaRecoveryCopies: previous ? current.recoveryCopies - previous.recoveryCopies : 0,
50 deltaRuntimeOnlySessions: previous ? current.runtimeOnlySessions - previous.runtimeOnlySessions : 0,
51 });
52 previousRef.current = current;
53 lastSignatureRef.current = signature;
54 }, [signature]);
55 useEffect(() => emit(), [emit]);
56 useEffect(() => registerFrontendDiagnosticStartHook(() => emit(true, "recorder-start")), [emit]);
57 }
58
58 lines TYPESCRIPT