@yumiai/chat-widget 0.1.2 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (107) hide show
  1. package/CHANGELOG.md +100 -0
  2. package/README.md +119 -22
  3. package/dist/ExcelCore-DJOIVQMI.js +11 -0
  4. package/dist/ExcelCore-DJOIVQMI.js.map +1 -0
  5. package/dist/ExcelViewer-3YLLYYIQ.js +65 -0
  6. package/dist/ExcelViewer-3YLLYYIQ.js.map +1 -0
  7. package/dist/GerberViewerA2UI-7CNT7HX4.css +693 -0
  8. package/dist/GerberViewerA2UI-7CNT7HX4.css.map +1 -0
  9. package/dist/GerberViewerA2UI-X5FWAD5M.js +57 -0
  10. package/dist/GerberViewerA2UI-X5FWAD5M.js.map +1 -0
  11. package/dist/GraphStatsLegend-D5bPeXB_.d.cts +607 -0
  12. package/dist/GraphStatsLegend-D5bPeXB_.d.ts +607 -0
  13. package/dist/JsonRenderStandalone-EIZM62JU.js +18 -0
  14. package/dist/JsonRenderStandalone-EIZM62JU.js.map +1 -0
  15. package/dist/JsonRenderStandalone-POB4Q3N3.css +2384 -0
  16. package/dist/JsonRenderStandalone-POB4Q3N3.css.map +1 -0
  17. package/dist/JsonRenderStandalone-UsTcST4G.d.cts +23 -0
  18. package/dist/JsonRenderStandalone-UsTcST4G.d.ts +23 -0
  19. package/dist/KicadViewer-GV6ZC4AQ.js +124 -0
  20. package/dist/KicadViewer-GV6ZC4AQ.js.map +1 -0
  21. package/dist/KicadViewerCore-U7BWZHKJ.js +11 -0
  22. package/dist/KicadViewerCore-U7BWZHKJ.js.map +1 -0
  23. package/dist/PdfViewer-CHPDRK46.js +51 -0
  24. package/dist/PdfViewer-CHPDRK46.js.map +1 -0
  25. package/dist/PdfViewer-LPYGQETK.css +1899 -0
  26. package/dist/PdfViewer-LPYGQETK.css.map +1 -0
  27. package/dist/PdfViewerCore-HJPEHSRA.js +364 -0
  28. package/dist/PdfViewerCore-HJPEHSRA.js.map +1 -0
  29. package/dist/PowerPointCore-FPDR2BL4.js +11 -0
  30. package/dist/PowerPointCore-FPDR2BL4.js.map +1 -0
  31. package/dist/PowerPointViewer-LQTO6UCU.js +61 -0
  32. package/dist/PowerPointViewer-LQTO6UCU.js.map +1 -0
  33. package/dist/StepViewerCore-7W3L3R4E.js +285 -0
  34. package/dist/StepViewerCore-7W3L3R4E.js.map +1 -0
  35. package/dist/ThreeViewerCore-N3QJD5QI.js +161 -0
  36. package/dist/ThreeViewerCore-N3QJD5QI.js.map +1 -0
  37. package/dist/WordCore-JKSXK2XD.js +11 -0
  38. package/dist/WordCore-JKSXK2XD.js.map +1 -0
  39. package/dist/WordViewer-ZHCQMHOH.js +61 -0
  40. package/dist/WordViewer-ZHCQMHOH.js.map +1 -0
  41. package/dist/chunk-2SKA3F5U.js +88 -0
  42. package/dist/chunk-2SKA3F5U.js.map +1 -0
  43. package/dist/chunk-2UC7YLVX.js +318 -0
  44. package/dist/chunk-2UC7YLVX.js.map +1 -0
  45. package/dist/chunk-3R6T3LBR.js +24 -0
  46. package/dist/chunk-3R6T3LBR.js.map +1 -0
  47. package/dist/chunk-56WRZM3R.js +398 -0
  48. package/dist/chunk-56WRZM3R.js.map +1 -0
  49. package/dist/chunk-7A4FY6FK.js +10226 -0
  50. package/dist/chunk-7A4FY6FK.js.map +1 -0
  51. package/dist/chunk-7D4SUZUM.js +38 -0
  52. package/dist/chunk-7D4SUZUM.js.map +1 -0
  53. package/dist/chunk-7S67DOHQ.js +436 -0
  54. package/dist/chunk-7S67DOHQ.js.map +1 -0
  55. package/dist/chunk-CFKGNAJM.js +14013 -0
  56. package/dist/chunk-CFKGNAJM.js.map +1 -0
  57. package/dist/chunk-GAMA3VA7.js +99 -0
  58. package/dist/chunk-GAMA3VA7.js.map +1 -0
  59. package/dist/chunk-GYXTSY22.js +639 -0
  60. package/dist/chunk-GYXTSY22.js.map +1 -0
  61. package/dist/chunk-K4KGNVL5.js +77 -0
  62. package/dist/chunk-K4KGNVL5.js.map +1 -0
  63. package/dist/chunk-KQV7IKET.js +1621 -0
  64. package/dist/chunk-KQV7IKET.js.map +1 -0
  65. package/dist/chunk-O3NXUM6C.js +1871 -0
  66. package/dist/chunk-O3NXUM6C.js.map +1 -0
  67. package/dist/chunk-PZXSASDY.js +83 -0
  68. package/dist/chunk-PZXSASDY.js.map +1 -0
  69. package/dist/chunk-QLVPIM6R.js +595 -0
  70. package/dist/chunk-QLVPIM6R.js.map +1 -0
  71. package/dist/chunk-VXJWGLZ7.js +21 -0
  72. package/dist/chunk-VXJWGLZ7.js.map +1 -0
  73. package/dist/chunk-XQ562W7I.js +116 -0
  74. package/dist/chunk-XQ562W7I.js.map +1 -0
  75. package/dist/components/JsonRender/standalone.cjs +39368 -0
  76. package/dist/components/JsonRender/standalone.cjs.map +1 -0
  77. package/dist/components/JsonRender/standalone.css +2384 -0
  78. package/dist/components/JsonRender/standalone.css.map +1 -0
  79. package/dist/components/JsonRender/standalone.d.cts +16 -0
  80. package/dist/components/JsonRender/standalone.d.ts +16 -0
  81. package/dist/components/JsonRender/standalone.js +38 -0
  82. package/dist/components/JsonRender/standalone.js.map +1 -0
  83. package/dist/gerber-2d-entry-OQ4SQRBY.js +3950 -0
  84. package/dist/gerber-2d-entry-OQ4SQRBY.js.map +1 -0
  85. package/dist/gerber-3d-entry-DEHDBOO2.js +3679 -0
  86. package/dist/gerber-3d-entry-DEHDBOO2.js.map +1 -0
  87. package/dist/gerber-simulation-entry-EBDX72XE.js +1801 -0
  88. package/dist/gerber-simulation-entry-EBDX72XE.js.map +1 -0
  89. package/dist/index.cjs +60113 -2970
  90. package/dist/index.cjs.map +1 -1
  91. package/dist/index.css +11342 -1708
  92. package/dist/index.css.map +1 -1
  93. package/dist/index.d.cts +3275 -77
  94. package/dist/index.d.ts +3275 -77
  95. package/dist/index.js +18078 -2540
  96. package/dist/index.js.map +1 -1
  97. package/dist/provenance/index.cjs +2248 -0
  98. package/dist/provenance/index.cjs.map +1 -0
  99. package/dist/provenance/index.css +52 -0
  100. package/dist/provenance/index.css.map +1 -0
  101. package/dist/provenance/index.d.cts +12 -0
  102. package/dist/provenance/index.d.ts +12 -0
  103. package/dist/provenance/index.js +27 -0
  104. package/dist/provenance/index.js.map +1 -0
  105. package/dist/resolveToArrayBuffer-AQIDZHSQ.js +23 -0
  106. package/dist/resolveToArrayBuffer-AQIDZHSQ.js.map +1 -0
  107. package/package.json +98 -17
@@ -0,0 +1,2248 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
+
30
+ // src/provenance/index.ts
31
+ var provenance_exports = {};
32
+ __export(provenance_exports, {
33
+ FilterBar: () => FilterBar,
34
+ GraphBuilder: () => GraphBuilder,
35
+ GraphStatsLegend: () => GraphStatsLegend,
36
+ GraphToolbar: () => GraphToolbar,
37
+ NodeDetailPanel: () => NodeDetailPanel,
38
+ ProvenanceGraph3D: () => ProvenanceGraph3D,
39
+ ProvenanceGraphDrawerContent: () => ProvenanceGraphDrawerContent_default,
40
+ ProvenanceI18nProvider: () => ProvenanceI18nProvider,
41
+ fetchProvenanceGraph: () => fetchProvenanceGraph,
42
+ useProvenanceGraph: () => useProvenanceGraph
43
+ });
44
+ module.exports = __toCommonJS(provenance_exports);
45
+
46
+ // src/provenance/ProvenanceGraphDrawerContent.tsx
47
+ var import_react6 = __toESM(require("react"), 1);
48
+ var import_antd3 = require("antd");
49
+
50
+ // src/provenance/hooks/useProvenanceGraph.ts
51
+ var import_react = require("react");
52
+
53
+ // src/provenance/GraphBuilder.ts
54
+ var GraphBuilder = class _GraphBuilder {
55
+ sessionId = 0;
56
+ agents = /* @__PURE__ */ new Map();
57
+ actions = /* @__PURE__ */ new Map();
58
+ files = /* @__PURE__ */ new Map();
59
+ tasks = /* @__PURE__ */ new Map();
60
+ reasonings = /* @__PURE__ */ new Map();
61
+ edges = [];
62
+ edgeKeys = /* @__PURE__ */ new Set();
63
+ lastCompletedActions = /* @__PURE__ */ new Map();
64
+ handlers = {
65
+ agent_start: (p) => this.handleAgentStart(p),
66
+ agent_end: (p) => this.handleAgentEnd(p),
67
+ mcp_start: (p) => this.handleMcpStart(p),
68
+ mcp_end: (p) => this.handleMcpEnd(p),
69
+ artifact_result: (p) => this.handleArtifactResult(p),
70
+ plan_result: (p) => this.handlePlanResult(p),
71
+ model_start: (p) => this.handleModelStart(p),
72
+ model_result: (p) => this.handleModelResult(p),
73
+ model_end: (p) => this.handleModelEnd(p)
74
+ };
75
+ /** Apply an SSE event. Returns true if the event was handled. */
76
+ applyEvent(payload) {
77
+ const type = payload.notification_type ?? "";
78
+ const handler = this.handlers[type];
79
+ if (!handler) return false;
80
+ handler(payload);
81
+ return true;
82
+ }
83
+ /** Replace all state from a backend snapshot (initial load). */
84
+ replaceWithSnapshot(snapshot) {
85
+ this.sessionId = snapshot.session_id;
86
+ this.agents.clear();
87
+ this.actions.clear();
88
+ this.files.clear();
89
+ this.tasks.clear();
90
+ this.reasonings.clear();
91
+ this.edges = [];
92
+ this.edgeKeys.clear();
93
+ for (const n of snapshot.nodes.agents) this.agents.set(n.agent_instance_id, { ...n });
94
+ for (const n of snapshot.nodes.actions) this.actions.set(n.tool_call_id, { ...n });
95
+ for (const n of snapshot.nodes.files) this.files.set(n.id, { ...n });
96
+ for (const n of snapshot.nodes.tasks) this.tasks.set(n.id, { ...n });
97
+ for (const n of snapshot.nodes.reasonings) this.reasonings.set(n.id, { ...n });
98
+ for (const e of snapshot.edges) {
99
+ const key = this.edgeKey(e.source, e.target, e.type, e.label);
100
+ if (!this.edgeKeys.has(key)) {
101
+ this.edgeKeys.add(key);
102
+ this.edges.push({ ...e });
103
+ }
104
+ }
105
+ }
106
+ /** Merge an incremental snapshot (reconnection). */
107
+ mergeSnapshot(snapshot) {
108
+ for (const n of snapshot.nodes.agents) this.agents.set(n.agent_instance_id, { ...n });
109
+ for (const n of snapshot.nodes.actions) this.actions.set(n.tool_call_id, { ...n });
110
+ for (const n of snapshot.nodes.files) this.files.set(n.id, { ...n });
111
+ for (const n of snapshot.nodes.tasks) this.tasks.set(n.id, { ...n });
112
+ for (const n of snapshot.nodes.reasonings) this.reasonings.set(n.id, { ...n });
113
+ for (const e of snapshot.edges) {
114
+ const key = this.edgeKey(e.source, e.target, e.type, e.label);
115
+ if (!this.edgeKeys.has(key)) {
116
+ this.edgeKeys.add(key);
117
+ this.edges.push({ ...e });
118
+ }
119
+ }
120
+ }
121
+ /** Produce an immutable snapshot for React state. */
122
+ getSnapshot() {
123
+ const agents = Array.from(this.agents.values());
124
+ const actions = Array.from(this.actions.values());
125
+ const files = Array.from(this.files.values());
126
+ const tasks = Array.from(this.tasks.values());
127
+ const reasonings = Array.from(this.reasonings.values());
128
+ const nodeCount = agents.length + actions.length + files.length + tasks.length + reasonings.length;
129
+ const maxDepth = agents.length > 0 ? Math.max(...agents.map((a) => a.level)) : 0;
130
+ return {
131
+ session_id: this.sessionId,
132
+ generated_at: Date.now(),
133
+ node_count: nodeCount,
134
+ edge_count: this.edges.length,
135
+ max_turn_id: null,
136
+ nodes: { agents, actions, files, tasks, reasonings },
137
+ edges: [...this.edges],
138
+ stats: {
139
+ agent_count: agents.length,
140
+ action_count: actions.length,
141
+ file_count: files.length,
142
+ task_count: tasks.length,
143
+ reasoning_count: reasonings.length,
144
+ max_depth: maxDepth
145
+ }
146
+ };
147
+ }
148
+ // -----------------------------------------------------------------------
149
+ // Handlers
150
+ // -----------------------------------------------------------------------
151
+ handleAgentStart(p) {
152
+ const callee = p.callee_instance_id ?? p.agent_instance_id ?? 0;
153
+ const caller = p.caller_instance_id ?? null;
154
+ const ts = this.parseTimestamp(p.timestamp);
155
+ const node = {
156
+ id: `agent-inst-${callee}`,
157
+ type: "agent",
158
+ label: p.agent_name ?? p.agent_id ?? `agent-${callee}`,
159
+ timestamp: ts,
160
+ metadata: {},
161
+ agent_id: p.agent_id ?? `agent-${callee}`,
162
+ agent_instance_id: callee,
163
+ agent_name: p.agent_name ?? `agent-${callee}`,
164
+ level: p.level ?? 0,
165
+ parent_agent_instance_id: caller != null && caller >= 0 ? caller : null,
166
+ status: "running"
167
+ };
168
+ this.agents.set(callee, node);
169
+ if (caller != null && caller >= 0 && this.agents.has(caller)) {
170
+ this.addEdge(`agent-inst-${caller}`, `agent-inst-${callee}`, "spawns", ts);
171
+ }
172
+ }
173
+ handleAgentEnd(p) {
174
+ const callee = p.callee_instance_id ?? p.agent_instance_id;
175
+ if (callee == null) return;
176
+ const existing = this.agents.get(callee);
177
+ if (existing) {
178
+ this.agents.set(callee, { ...existing, status: "completed" });
179
+ }
180
+ }
181
+ handleMcpStart(p) {
182
+ const tcid = this.extractString(p.ext, "tool_call_id") ?? p.tool_call_id;
183
+ if (!tcid) return;
184
+ const callee = p.callee_instance_id ?? p.agent_instance_id ?? 0;
185
+ const ts = this.parseTimestamp(p.timestamp);
186
+ const node = {
187
+ id: `action-${tcid}`,
188
+ type: "action",
189
+ label: this.extractString(p.ext, "tool_name") ?? p.tool_name ?? tcid,
190
+ timestamp: ts,
191
+ metadata: {},
192
+ tool_name: this.extractString(p.ext, "tool_name") ?? p.tool_name ?? "",
193
+ tool_call_id: tcid,
194
+ task_purpose: this.extractString(p.ext, "task_purpose") ?? p.task_purpose ?? "",
195
+ agent_instance_id: callee,
196
+ status: "running",
197
+ duration_ms: null
198
+ };
199
+ this.actions.set(tcid, node);
200
+ if (this.agents.has(callee)) {
201
+ this.addEdge(`agent-inst-${callee}`, `action-${tcid}`, "executes", ts);
202
+ }
203
+ const latestReasoning = this.findLatestReasoning(callee);
204
+ if (latestReasoning) {
205
+ this.addEdge(latestReasoning.id, `action-${tcid}`, "triggers", ts);
206
+ }
207
+ for (const [fid, fileNode] of this.files) {
208
+ if (fileNode.tool_call_id === tcid) {
209
+ const op = fileNode.operation;
210
+ const et = op === "create" ? "produces" : op === "delete" ? "deletes" : "modifies";
211
+ this.addEdge(`action-${tcid}`, fid, et, ts);
212
+ }
213
+ }
214
+ }
215
+ handleMcpEnd(p) {
216
+ const tcid = this.extractString(p.ext, "tool_call_id") ?? p.tool_call_id;
217
+ if (!tcid) return;
218
+ const existing = this.actions.get(tcid);
219
+ if (!existing) return;
220
+ const statusStr = this.extractString(p.ext, "status") ?? p.tool_status ?? "success";
221
+ const status = statusStr === "error" ? "error" : "success";
222
+ const endTs = this.parseTimestamp(p.timestamp);
223
+ const duration = endTs - existing.timestamp;
224
+ this.actions.set(tcid, { ...existing, status, duration_ms: duration > 0 ? duration : null });
225
+ const callee = p.callee_instance_id ?? p.agent_instance_id ?? 0;
226
+ const prev = this.lastCompletedActions.get(callee) ?? [];
227
+ prev.push(tcid);
228
+ this.lastCompletedActions.set(callee, prev);
229
+ }
230
+ handleArtifactResult(p) {
231
+ if (p.ext?.xref_scan_result) {
232
+ this.handleXrefScanResult(p);
233
+ return;
234
+ }
235
+ const data = this.extractArtifactData(p.content);
236
+ if (!data) return;
237
+ const fileId = data.file_id ?? data.identifier ?? "";
238
+ if (!fileId) return;
239
+ const fid = `file-${fileId}`;
240
+ const op = this.normalizeOperation(data.operation_type);
241
+ const tcid = this.extractString(p.ext, "tool_call_id") ?? p.tool_call_id ?? null;
242
+ const callee = p.callee_instance_id ?? p.agent_instance_id ?? 0;
243
+ const ts = this.parseTimestamp(p.timestamp);
244
+ const existing = this.files.get(fid);
245
+ const node = {
246
+ id: fid,
247
+ type: "file",
248
+ label: data.file_name ?? data.git_path ?? fileId,
249
+ timestamp: existing?.timestamp ?? ts,
250
+ metadata: {},
251
+ file_id: fileId,
252
+ file_name: data.file_name ?? "",
253
+ git_path: data.git_path ?? "",
254
+ operation: op,
255
+ agent_instance_id: callee,
256
+ tool_call_id: tcid,
257
+ task_purpose: this.extractString(p.ext, "task_purpose") ?? p.task_purpose ?? null
258
+ };
259
+ this.files.set(fid, node);
260
+ this.absorbPlaceholders(node);
261
+ const edgeType = op === "create" ? "produces" : op === "delete" ? "deletes" : "modifies";
262
+ if (tcid && this.actions.has(tcid)) {
263
+ this.addEdge(`action-${tcid}`, fid, edgeType, ts);
264
+ } else if (this.reasonings.size > 0) {
265
+ let latest = null;
266
+ for (const r of this.reasonings.values()) {
267
+ if (!latest || r.timestamp > latest.timestamp) latest = r;
268
+ }
269
+ if (latest) {
270
+ this.addEdge(latest.id, fid, edgeType, ts);
271
+ }
272
+ }
273
+ }
274
+ /** JETP-026: create references edges from xref scan result. */
275
+ handleXrefScanResult(p) {
276
+ const ext = p.ext;
277
+ if (!ext) return;
278
+ const sourceFileId = ext.source_file_id;
279
+ const xrefs = ext.xrefs;
280
+ if (!sourceFileId || !xrefs) return;
281
+ const ts = this.parseTimestamp(p.timestamp);
282
+ const sourceNodeId = `file-${sourceFileId}`;
283
+ for (const xref of xrefs) {
284
+ const targetFileId = xref.target_file_id;
285
+ const targetResource = xref.target_resource ?? "";
286
+ let targetNodeId;
287
+ if (targetFileId) {
288
+ targetNodeId = `file-${targetFileId}`;
289
+ if (!this.files.has(targetNodeId)) {
290
+ const resolved = this.resolveFileByName(targetFileId);
291
+ if (resolved) {
292
+ targetNodeId = resolved;
293
+ } else {
294
+ this.files.set(targetNodeId, {
295
+ id: targetNodeId,
296
+ type: "file",
297
+ label: targetFileId,
298
+ timestamp: ts,
299
+ metadata: { placeholder: true },
300
+ file_id: targetFileId,
301
+ file_name: "",
302
+ git_path: "",
303
+ operation: "referenced",
304
+ agent_instance_id: 0,
305
+ tool_call_id: null,
306
+ task_purpose: null
307
+ });
308
+ }
309
+ }
310
+ } else {
311
+ const hash = this.simpleHash(targetResource);
312
+ targetNodeId = `file-ext-url-${hash}`;
313
+ if (!this.files.has(targetNodeId)) {
314
+ const displayUrl = targetResource.replace("url://", "");
315
+ this.files.set(targetNodeId, {
316
+ id: targetNodeId,
317
+ type: "file",
318
+ label: displayUrl.length > 50 ? displayUrl.slice(0, 47) + "..." : displayUrl,
319
+ timestamp: ts,
320
+ metadata: { external: true },
321
+ file_id: `ext-url-${hash}`,
322
+ file_name: displayUrl,
323
+ git_path: targetResource,
324
+ operation: "external",
325
+ agent_instance_id: 0,
326
+ tool_call_id: null,
327
+ task_purpose: null
328
+ });
329
+ }
330
+ }
331
+ const description = xref.description ?? "";
332
+ this.addEdge(sourceNodeId, targetNodeId, "references", ts, description);
333
+ }
334
+ }
335
+ handlePlanResult(p) {
336
+ const checklist = this.extractChecklist(p.content);
337
+ if (!checklist) return;
338
+ for (const task of checklist) {
339
+ const tid = task.id ? `task-${task.id}` : `task-${task.description.slice(0, 20)}`;
340
+ const node = {
341
+ id: tid,
342
+ type: "task",
343
+ label: task.description,
344
+ timestamp: Date.now(),
345
+ metadata: {},
346
+ task_id: task.id ?? tid,
347
+ description: task.description,
348
+ status: task.status ?? "pending"
349
+ };
350
+ this.tasks.set(tid, node);
351
+ }
352
+ }
353
+ handleModelStart(p) {
354
+ const callee = p.callee_instance_id ?? p.agent_instance_id ?? 0;
355
+ const ts = this.parseTimestamp(p.timestamp);
356
+ const rid = `reasoning-${callee}-${ts}`;
357
+ const node = {
358
+ id: rid,
359
+ type: "reasoning",
360
+ label: this.extractString(p.ext, "model") ?? "reasoning",
361
+ timestamp: ts,
362
+ metadata: {},
363
+ agent_instance_id: callee,
364
+ model: this.extractString(p.ext, "model") ?? "",
365
+ content_preview: "",
366
+ token_count: null,
367
+ duration_ms: null,
368
+ status: "thinking"
369
+ };
370
+ this.reasonings.set(rid, node);
371
+ if (this.agents.has(callee)) {
372
+ this.addEdge(`agent-inst-${callee}`, rid, "thinks", ts);
373
+ }
374
+ const prevActions = this.lastCompletedActions.get(callee) ?? [];
375
+ for (const tcid of prevActions) {
376
+ this.addEdge(`action-${tcid}`, rid, "informs", ts);
377
+ }
378
+ this.lastCompletedActions.delete(callee);
379
+ }
380
+ handleModelResult(p) {
381
+ const callee = p.callee_instance_id ?? p.agent_instance_id ?? 0;
382
+ const latest = this.findLatestReasoning(callee);
383
+ if (!latest) return;
384
+ const preview = String(this.extractString(p.ext, "content_preview") ?? "").slice(0, 200);
385
+ this.reasonings.set(latest.id, {
386
+ ...latest,
387
+ status: "completed",
388
+ ...preview ? { content_preview: preview } : {}
389
+ });
390
+ }
391
+ handleModelEnd(p) {
392
+ const callee = p.callee_instance_id ?? p.agent_instance_id ?? 0;
393
+ const latest = this.findLatestReasoning(callee);
394
+ if (!latest) return;
395
+ const endTs = this.parseTimestamp(p.timestamp);
396
+ const duration = endTs - latest.timestamp;
397
+ const tokens = this.extractNumber(p.ext, "total_tokens");
398
+ this.reasonings.set(latest.id, {
399
+ ...latest,
400
+ status: "completed",
401
+ duration_ms: duration > 0 ? duration : null,
402
+ token_count: tokens
403
+ });
404
+ }
405
+ // -----------------------------------------------------------------------
406
+ // Helpers
407
+ // -----------------------------------------------------------------------
408
+ addEdge(source, target, type, ts, label) {
409
+ const key = this.edgeKey(source, target, type, label);
410
+ if (this.edgeKeys.has(key)) return;
411
+ this.edgeKeys.add(key);
412
+ this.edges.push({ source, target, type, label, timestamp: ts });
413
+ }
414
+ edgeKey(source, target, type, label) {
415
+ return label ? `${source}:${target}:${type}:${label}` : `${source}:${target}:${type}`;
416
+ }
417
+ findLatestReasoning(agentInstanceId) {
418
+ let latest = null;
419
+ for (const r of this.reasonings.values()) {
420
+ if (r.agent_instance_id === agentInstanceId) {
421
+ if (!latest || r.timestamp > latest.timestamp) latest = r;
422
+ }
423
+ }
424
+ return latest;
425
+ }
426
+ parseTimestamp(ts) {
427
+ if (ts == null) return Date.now();
428
+ if (typeof ts === "number") return ts;
429
+ const n = Date.parse(ts);
430
+ return Number.isNaN(n) ? Date.now() : n;
431
+ }
432
+ extractString(ext, key) {
433
+ if (!ext) return null;
434
+ const v = ext[key];
435
+ return typeof v === "string" ? v : null;
436
+ }
437
+ extractNumber(ext, key) {
438
+ if (!ext) return null;
439
+ const v = ext[key];
440
+ return typeof v === "number" ? v : null;
441
+ }
442
+ extractArtifactData(content) {
443
+ if (!content || !Array.isArray(content)) return null;
444
+ for (const part of content) {
445
+ const c = part?.content;
446
+ if (c?.data) return c.data;
447
+ }
448
+ return null;
449
+ }
450
+ normalizeOperation(op) {
451
+ const o = (op ?? "create").toLowerCase();
452
+ if (o === "create" || o === "update" || o === "delete" || o === "external" || o === "referenced") return o;
453
+ if (o.includes("create") || o.includes("add")) return "create";
454
+ if (o.includes("delete") || o.includes("remove")) return "delete";
455
+ return "update";
456
+ }
457
+ /** Merge placeholder file nodes into a real node, remapping all edges.
458
+ * Uses exact + stem matching (same ambiguity-safe logic as resolveFileByName). */
459
+ absorbPlaceholders(realNode) {
460
+ const names = /* @__PURE__ */ new Set();
461
+ if (realNode.file_name) {
462
+ names.add(realNode.file_name);
463
+ const fnStem = _GraphBuilder.fileStem(realNode.file_name);
464
+ if (fnStem !== realNode.file_name) names.add(fnStem);
465
+ }
466
+ if (realNode.git_path) {
467
+ names.add(realNode.git_path);
468
+ const gpStem = _GraphBuilder.fileStem(realNode.git_path);
469
+ if (gpStem !== realNode.git_path) names.add(gpStem);
470
+ if (realNode.git_path.includes("/")) {
471
+ const basename = realNode.git_path.split("/").pop();
472
+ names.add(basename);
473
+ const bnStem = _GraphBuilder.fileStem(basename);
474
+ if (bnStem !== basename) names.add(bnStem);
475
+ }
476
+ }
477
+ const stemHits = /* @__PURE__ */ new Map();
478
+ for (const [id, node] of this.files) {
479
+ if (id === realNode.id) continue;
480
+ if (!node.metadata?.placeholder) continue;
481
+ const matchKey = node.file_id || node.label;
482
+ if (names.has(matchKey)) {
483
+ stemHits.set(id, [...stemHits.get(id) ?? [], matchKey]);
484
+ }
485
+ }
486
+ const toRemove = [];
487
+ for (const [id] of stemHits) {
488
+ for (const edge of this.edges) {
489
+ if (edge.source === id) edge.source = realNode.id;
490
+ if (edge.target === id) edge.target = realNode.id;
491
+ }
492
+ toRemove.push(id);
493
+ }
494
+ for (const id of toRemove) this.files.delete(id);
495
+ }
496
+ /** Match a file name/path against existing FileNodes by git_path or file_name.
497
+ * Pass 1 — exact match. Pass 2 — stem match (extension stripped) when
498
+ * *name* has no extension and exactly one non-placeholder candidate exists. */
499
+ resolveFileByName(name) {
500
+ for (const node of this.files.values()) {
501
+ if (node.git_path === name || node.file_name === name) return node.id;
502
+ if (node.git_path && node.git_path.endsWith("/" + name)) return node.id;
503
+ }
504
+ if (_GraphBuilder.nameHasExtension(name)) return null;
505
+ const candidates = [];
506
+ for (const node of this.files.values()) {
507
+ if (node.operation === "referenced" || node.operation === "external") continue;
508
+ if (node.file_name && _GraphBuilder.fileStem(node.file_name) === name) {
509
+ candidates.push(node.id);
510
+ continue;
511
+ }
512
+ if (node.git_path) {
513
+ const gpStem = _GraphBuilder.fileStem(node.git_path);
514
+ if (gpStem === name || gpStem.endsWith("/" + name)) {
515
+ candidates.push(node.id);
516
+ continue;
517
+ }
518
+ }
519
+ }
520
+ const unique = [...new Set(candidates)];
521
+ return unique.length === 1 ? unique[0] : null;
522
+ }
523
+ /** Strip trailing extension: 'arch.md' → 'arch', 'a/b.txt' → 'a/b'. */
524
+ static fileStem(name) {
525
+ const slash = name.lastIndexOf("/");
526
+ const basename = name.slice(slash + 1);
527
+ const dot = basename.lastIndexOf(".");
528
+ if (dot > 0) return name.slice(0, slash + 1 + dot);
529
+ return name;
530
+ }
531
+ /** True when the trailing path component carries a dot-extension (ignores dotfiles). */
532
+ static nameHasExtension(name) {
533
+ const slash = name.lastIndexOf("/");
534
+ const basename = name.slice(slash + 1);
535
+ return basename.lastIndexOf(".") > 0;
536
+ }
537
+ simpleHash(s) {
538
+ let h = 0;
539
+ for (let i = 0; i < s.length; i++) {
540
+ h = (h << 5) - h + s.charCodeAt(i) | 0;
541
+ }
542
+ return Math.abs(h).toString(16).padStart(8, "0").slice(0, 8);
543
+ }
544
+ extractChecklist(content) {
545
+ if (!content || !Array.isArray(content)) return null;
546
+ for (const part of content) {
547
+ const typed = part;
548
+ if (typed.type === "checklist" && typed.content?.tasks) {
549
+ return typed.content.tasks;
550
+ }
551
+ }
552
+ return null;
553
+ }
554
+ };
555
+
556
+ // src/provenance/api.ts
557
+ async function fetchProvenanceGraph(fetcher, opts) {
558
+ const params = {};
559
+ if (opts.sinceTurnId != null && opts.sinceTurnId > 0) {
560
+ params.since_turn_id = opts.sinceTurnId;
561
+ }
562
+ if (opts.limit != null && opts.limit > 0) {
563
+ params.limit = opts.limit;
564
+ }
565
+ return fetcher(opts.sessionId, Object.keys(params).length > 0 ? params : void 0);
566
+ }
567
+
568
+ // src/provenance/hooks/useProvenanceGraph.ts
569
+ var EMPTY_SNAPSHOT = {
570
+ session_id: 0,
571
+ generated_at: 0,
572
+ node_count: 0,
573
+ edge_count: 0,
574
+ max_turn_id: null,
575
+ nodes: { agents: [], actions: [], files: [], tasks: [], reasonings: [] },
576
+ edges: [],
577
+ stats: { agent_count: 0, action_count: 0, file_count: 0, task_count: 0, reasoning_count: 0, max_depth: 0 }
578
+ };
579
+ var DEBOUNCE_MS = 80;
580
+ function useProvenanceGraph(opts) {
581
+ const { sessionId, fetcher, enabled = true, pollInterval = 3e3 } = opts;
582
+ const builderRef = (0, import_react.useRef)(new GraphBuilder());
583
+ const maxTurnIdRef = (0, import_react.useRef)(null);
584
+ const debounceTimerRef = (0, import_react.useRef)(null);
585
+ const mountedRef = (0, import_react.useRef)(true);
586
+ const [graph, setGraph] = (0, import_react.useState)(null);
587
+ const [loading, setLoading] = (0, import_react.useState)(false);
588
+ const [error, setError] = (0, import_react.useState)(null);
589
+ const flushSnapshot = (0, import_react.useCallback)(() => {
590
+ if (!mountedRef.current) return;
591
+ const snap = builderRef.current.getSnapshot();
592
+ setGraph(snap);
593
+ }, []);
594
+ const scheduleFlush = (0, import_react.useCallback)(() => {
595
+ if (debounceTimerRef.current) clearTimeout(debounceTimerRef.current);
596
+ debounceTimerRef.current = setTimeout(flushSnapshot, DEBOUNCE_MS);
597
+ }, [flushSnapshot]);
598
+ const fetchSnapshot = (0, import_react.useCallback)(
599
+ async (sinceTurnId) => {
600
+ if (!sessionId || !fetcher) return;
601
+ setLoading(true);
602
+ setError(null);
603
+ try {
604
+ const snap = await fetchProvenanceGraph(fetcher, {
605
+ sessionId,
606
+ sinceTurnId
607
+ });
608
+ if (!mountedRef.current) return;
609
+ if (sinceTurnId != null && sinceTurnId > 0) {
610
+ builderRef.current.mergeSnapshot(snap);
611
+ } else {
612
+ builderRef.current.replaceWithSnapshot(snap);
613
+ }
614
+ maxTurnIdRef.current = snap.max_turn_id;
615
+ flushSnapshot();
616
+ } catch (e) {
617
+ if (!mountedRef.current) return;
618
+ const err = e instanceof Error ? e : new Error(String(e));
619
+ setError(err);
620
+ } finally {
621
+ if (mountedRef.current) setLoading(false);
622
+ }
623
+ },
624
+ [sessionId, fetcher, flushSnapshot]
625
+ );
626
+ const processEvent = (0, import_react.useCallback)(
627
+ (payload) => {
628
+ const handled = builderRef.current.applyEvent(payload);
629
+ if (handled) scheduleFlush();
630
+ },
631
+ [scheduleFlush]
632
+ );
633
+ const refetch = (0, import_react.useCallback)(() => {
634
+ fetchSnapshot(maxTurnIdRef.current);
635
+ }, [fetchSnapshot]);
636
+ (0, import_react.useEffect)(() => {
637
+ mountedRef.current = true;
638
+ if (sessionId && enabled) {
639
+ builderRef.current = new GraphBuilder();
640
+ maxTurnIdRef.current = null;
641
+ fetchSnapshot(null);
642
+ } else {
643
+ setGraph(sessionId ? null : EMPTY_SNAPSHOT);
644
+ }
645
+ return () => {
646
+ mountedRef.current = false;
647
+ if (debounceTimerRef.current) clearTimeout(debounceTimerRef.current);
648
+ };
649
+ }, [sessionId, enabled, fetchSnapshot]);
650
+ (0, import_react.useEffect)(() => {
651
+ if (!sessionId || !enabled || pollInterval <= 0) return;
652
+ const id = setInterval(() => {
653
+ if (!mountedRef.current) return;
654
+ fetchSnapshot(maxTurnIdRef.current);
655
+ }, pollInterval);
656
+ return () => clearInterval(id);
657
+ }, [sessionId, enabled, pollInterval, fetchSnapshot]);
658
+ return { graph, loading, error, processEvent, refetch };
659
+ }
660
+
661
+ // src/provenance/components/ProvenanceGraph3D.tsx
662
+ var import_react2 = __toESM(require("react"), 1);
663
+ var import_react_force_graph_3d = __toESM(require("react-force-graph-3d"), 1);
664
+ var THREE2 = __toESM(require("three"), 1);
665
+ var import_three_spritetext = __toESM(require("three-spritetext"), 1);
666
+
667
+ // src/provenance/components/NodeMeshFactory.ts
668
+ var THREE = __toESM(require("three"), 1);
669
+
670
+ // src/provenance/constants.ts
671
+ var NODE_COLORS = {
672
+ agent: "#667eea",
673
+ action: "#f5a623",
674
+ file: "#50c878",
675
+ task: "#e74c8b",
676
+ reasoning: "#9b59b6"
677
+ };
678
+ var NODE_COLORS_HEX = {
679
+ agent: 6717162,
680
+ action: 16098851,
681
+ file: 5294200,
682
+ task: 15158411,
683
+ reasoning: 10181046
684
+ };
685
+ var NODE_EMISSIVE = {
686
+ agent: 3363008,
687
+ action: 12614160,
688
+ file: 2787912,
689
+ task: 12071024,
690
+ reasoning: 7223946
691
+ };
692
+ var NODE_SIZES = {
693
+ agent: 6,
694
+ action: 4.5,
695
+ file: 3.5,
696
+ task: 4,
697
+ reasoning: 5
698
+ };
699
+ var EDGE_COLORS = {
700
+ spawns: "#667eea",
701
+ executes: "#f5a623",
702
+ produces: "#50c878",
703
+ modifies: "#36a3d9",
704
+ deletes: "#e74c3c",
705
+ thinks: "#9b59b6",
706
+ triggers: "#e67e22",
707
+ informs: "#3498db",
708
+ references: "#8e44ad"
709
+ // JETP-026: purple for cross-references
710
+ };
711
+ var EDGE_WIDTHS = {
712
+ spawns: 3,
713
+ executes: 2,
714
+ produces: 1.8,
715
+ modifies: 1.8,
716
+ deletes: 1.5,
717
+ thinks: 2.5,
718
+ triggers: 2,
719
+ informs: 1.8,
720
+ references: 1
721
+ // JETP-026: thin for cross-references
722
+ };
723
+ var SCENE_BG = 16119802;
724
+ var CAMERA_DISTANCE = 400;
725
+ var CAMERA_FOCUS_DURATION_MS = 600;
726
+ var LINK_PARTICLE_COUNT = 2;
727
+ var LINK_PARTICLE_WIDTH = 3;
728
+ var LINK_PARTICLE_SPEED = 4e-3;
729
+ var DIM_OPACITY = 0.08;
730
+ var SELECTED_SCALE = 1.4;
731
+ var NORMAL_OPACITY = 0.9;
732
+ var LABEL_FONT_SIZE = 3;
733
+ var LABEL_COLOR = "#333";
734
+
735
+ // src/provenance/components/NodeMeshFactory.ts
736
+ var geoCache = /* @__PURE__ */ new Map();
737
+ function getOrCreateGeometry(type) {
738
+ const cached = geoCache.get(type);
739
+ if (cached) return cached;
740
+ let geo;
741
+ const s = NODE_SIZES[type];
742
+ switch (type) {
743
+ case "agent":
744
+ geo = new THREE.SphereGeometry(s, 24, 16);
745
+ break;
746
+ case "action":
747
+ geo = new THREE.IcosahedronGeometry(s, 0);
748
+ break;
749
+ case "file":
750
+ geo = new THREE.BoxGeometry(s * 1.2, s * 1.2, s * 1.2);
751
+ break;
752
+ case "task":
753
+ geo = new THREE.OctahedronGeometry(s, 0);
754
+ break;
755
+ case "reasoning":
756
+ geo = new THREE.TorusGeometry(s * 0.7, s * 0.3, 12, 24);
757
+ break;
758
+ default:
759
+ geo = new THREE.SphereGeometry(s, 16, 12);
760
+ }
761
+ geoCache.set(type, geo);
762
+ return geo;
763
+ }
764
+ function createNodeMesh(type, opts = {}) {
765
+ const geo = getOrCreateGeometry(type);
766
+ const mat = new THREE.MeshStandardMaterial({
767
+ color: NODE_COLORS_HEX[type],
768
+ emissive: NODE_EMISSIVE[type],
769
+ emissiveIntensity: opts.selected ? 0.6 : 0.25,
770
+ metalness: 0.15,
771
+ roughness: 0.55,
772
+ transparent: true,
773
+ opacity: opts.dimmed ? DIM_OPACITY : NORMAL_OPACITY
774
+ });
775
+ const mesh = new THREE.Mesh(geo, mat);
776
+ if (opts.selected) {
777
+ mesh.scale.setScalar(SELECTED_SCALE);
778
+ }
779
+ mesh.castShadow = false;
780
+ mesh.receiveShadow = false;
781
+ return mesh;
782
+ }
783
+ function disposeGeometryCache() {
784
+ for (const geo of geoCache.values()) {
785
+ geo.dispose();
786
+ }
787
+ geoCache.clear();
788
+ }
789
+
790
+ // src/provenance/components/ProvenanceGraph3D.tsx
791
+ var import_jsx_runtime = require("react/jsx-runtime");
792
+ var HIDDEN_EDGE_TYPES = /* @__PURE__ */ new Set(["spawns", "executes", "thinks"]);
793
+ function flattenNodes(snap) {
794
+ const { actions, files, tasks, reasonings } = snap.nodes;
795
+ return [...actions, ...files, ...tasks, ...reasonings];
796
+ }
797
+ function getConnectedIds(nodeId, edges, hops) {
798
+ const visited = /* @__PURE__ */ new Set([nodeId]);
799
+ let frontier = /* @__PURE__ */ new Set([nodeId]);
800
+ for (let h = 0; h < hops; h++) {
801
+ const next = /* @__PURE__ */ new Set();
802
+ for (const e of edges) {
803
+ if (frontier.has(e.source) && !visited.has(e.target)) {
804
+ visited.add(e.target);
805
+ next.add(e.target);
806
+ }
807
+ if (frontier.has(e.target) && !visited.has(e.source)) {
808
+ visited.add(e.source);
809
+ next.add(e.source);
810
+ }
811
+ }
812
+ if (next.size === 0) break;
813
+ frontier = next;
814
+ }
815
+ return visited;
816
+ }
817
+ function truncate(s, maxLen) {
818
+ return s.length > maxLen ? s.slice(0, maxLen - 1) + "\u2026" : s;
819
+ }
820
+ function wrapText(s, lineWidth, maxLines) {
821
+ const clean = s.replace(/\n/g, " ").trim();
822
+ const lines = [];
823
+ let pos = 0;
824
+ for (let i = 0; i < maxLines && pos < clean.length; i++) {
825
+ const remaining = clean.slice(pos);
826
+ if (remaining.length <= lineWidth) {
827
+ lines.push(remaining);
828
+ break;
829
+ }
830
+ lines.push(remaining.slice(0, lineWidth));
831
+ pos += lineWidth;
832
+ }
833
+ const result = lines.join("\n");
834
+ return pos < clean.length ? result + "\u2026" : result;
835
+ }
836
+ var ProvenanceGraph3DInner = ({
837
+ graph,
838
+ width,
839
+ height,
840
+ selectedNodeId = null,
841
+ onNodeClick,
842
+ onNodeHover,
843
+ onBackgroundClick,
844
+ depthFilter
845
+ }) => {
846
+ const fgRef = (0, import_react2.useRef)(void 0);
847
+ const [hoveredNodeId, setHoveredNodeId] = (0, import_react2.useState)(null);
848
+ const graphData = (0, import_react2.useMemo)(() => {
849
+ const allNodes = flattenNodes(graph);
850
+ const nodeMap = new Set(allNodes.map((n) => n.id));
851
+ const purposeByNodeId = /* @__PURE__ */ new Map();
852
+ for (const a of graph.nodes.actions) {
853
+ if (a.task_purpose) purposeByNodeId.set(a.id, a.task_purpose);
854
+ }
855
+ for (const f of graph.nodes.files) {
856
+ if (f.task_purpose) purposeByNodeId.set(f.id, f.task_purpose);
857
+ }
858
+ const previewById = /* @__PURE__ */ new Map();
859
+ for (const r of graph.nodes.reasonings) {
860
+ if (r.content_preview) previewById.set(r.id, r.content_preview);
861
+ }
862
+ const agentNameByInstId = /* @__PURE__ */ new Map();
863
+ for (const a of graph.nodes.agents) {
864
+ agentNameByInstId.set(a.agent_instance_id, a.agent_name || a.agent_id || `agent-${a.agent_instance_id}`);
865
+ }
866
+ const nodes = allNodes.map((n) => {
867
+ const instId = "agent_instance_id" in n ? n.agent_instance_id : void 0;
868
+ return {
869
+ id: n.id,
870
+ type: n.type,
871
+ label: n.label,
872
+ subtitle: purposeByNodeId.get(n.id),
873
+ contentPreview: previewById.get(n.id),
874
+ agentLabel: instId != null ? agentNameByInstId.get(instId) : void 0,
875
+ status: "status" in n ? n.status : void 0,
876
+ level: "level" in n ? n.level : void 0,
877
+ agentInstanceId: instId
878
+ };
879
+ });
880
+ const links = graph.edges.filter((e) => !HIDDEN_EDGE_TYPES.has(e.type) && nodeMap.has(e.source) && nodeMap.has(e.target)).map((e) => {
881
+ const purpose = purposeByNodeId.get(e.target) ?? purposeByNodeId.get(e.source) ?? void 0;
882
+ return {
883
+ source: e.source,
884
+ target: e.target,
885
+ type: e.type,
886
+ timestamp: e.timestamp,
887
+ label: e.label || purpose
888
+ };
889
+ });
890
+ return { nodes, links };
891
+ }, [graph]);
892
+ const connectedSet = (0, import_react2.useMemo)(() => {
893
+ if (!selectedNodeId) return null;
894
+ return getConnectedIds(selectedNodeId, graph.edges, depthFilter ?? 2);
895
+ }, [selectedNodeId, graph.edges, depthFilter]);
896
+ const nodeThreeObject = (0, import_react2.useCallback)(
897
+ (node) => {
898
+ const isDimmed = connectedSet != null && !connectedSet.has(node.id);
899
+ const isSelected = node.id === selectedNodeId;
900
+ const isRunning = node.status === "running" || node.status === "thinking";
901
+ const group = new THREE2.Group();
902
+ if (node.type === "reasoning") {
903
+ const agentName = node.agentLabel ?? "Agent";
904
+ const bodyText = node.contentPreview ? wrapText(node.contentPreview, 28, 2) : isRunning ? "Thinking\u2026" : "";
905
+ const dimAlpha = isDimmed ? 0.15 : 1;
906
+ const header = new import_three_spritetext.default(
907
+ (isRunning ? "\u25CF " : "") + agentName,
908
+ 2,
909
+ isDimmed ? "#bbb" : isRunning ? "#9b59b6" : "#667eea"
910
+ );
911
+ header.fontFace = "Inter, system-ui, sans-serif";
912
+ header.fontWeight = "600";
913
+ header.backgroundColor = "transparent";
914
+ header.padding = [0, 0];
915
+ header.position.y = bodyText ? 4.5 : 0;
916
+ header.material.opacity = dimAlpha;
917
+ group.add(header);
918
+ if (bodyText) {
919
+ const body = new import_three_spritetext.default(
920
+ bodyText,
921
+ 2.2,
922
+ isDimmed ? "#ccc" : "#444"
923
+ );
924
+ body.fontFace = "Inter, system-ui, sans-serif";
925
+ body.backgroundColor = isDimmed ? "rgba(245,245,245,0.2)" : isSelected ? "rgba(102,126,234,0.08)" : "rgba(255,255,255,0.92)";
926
+ body.borderWidth = isSelected ? 1 : 0.4;
927
+ body.borderColor = isDimmed ? "transparent" : isSelected ? "rgba(102,126,234,0.5)" : "rgba(0,0,0,0.08)";
928
+ body.borderRadius = 3;
929
+ body.padding = [2.5, 4];
930
+ body.material.opacity = dimAlpha;
931
+ group.add(body);
932
+ }
933
+ return group;
934
+ }
935
+ const mesh = createNodeMesh(node.type, {
936
+ selected: isSelected,
937
+ dimmed: isDimmed,
938
+ running: isRunning
939
+ });
940
+ group.add(mesh);
941
+ const nodeRadius = NODE_SIZES[node.type] ?? 5;
942
+ if (isRunning && !isDimmed) {
943
+ const ringGeo = new THREE2.RingGeometry(nodeRadius * 1.6, nodeRadius * 1.8, 32);
944
+ const ringMat = new THREE2.MeshBasicMaterial({
945
+ color: NODE_COLORS[node.type] ?? "#667eea",
946
+ transparent: true,
947
+ opacity: 0.4,
948
+ side: THREE2.DoubleSide
949
+ });
950
+ const ring = new THREE2.Mesh(ringGeo, ringMat);
951
+ ring.rotation.x = Math.PI / 2;
952
+ ring.userData.__orbitRing = true;
953
+ group.add(ring);
954
+ }
955
+ if (!isDimmed) {
956
+ const nameLabel = new import_three_spritetext.default(
957
+ truncate(node.label, 20),
958
+ LABEL_FONT_SIZE,
959
+ LABEL_COLOR
960
+ );
961
+ nameLabel.backgroundColor = "rgba(255,255,255,0.85)";
962
+ nameLabel.borderRadius = 2;
963
+ nameLabel.padding = [1, 3];
964
+ nameLabel.position.y = -(nodeRadius + 4);
965
+ group.add(nameLabel);
966
+ if (node.subtitle) {
967
+ const purposeLabel = new import_three_spritetext.default(
968
+ truncate(node.subtitle, 16),
969
+ 2.2,
970
+ "#888"
971
+ );
972
+ purposeLabel.backgroundColor = "rgba(245,247,250,0.9)";
973
+ purposeLabel.borderRadius = 1.5;
974
+ purposeLabel.padding = [0.5, 2];
975
+ purposeLabel.position.y = -(nodeRadius + 8);
976
+ group.add(purposeLabel);
977
+ }
978
+ }
979
+ return group;
980
+ },
981
+ [connectedSet, selectedNodeId]
982
+ );
983
+ const CAUSAL_EDGES = /* @__PURE__ */ new Set(["triggers", "informs"]);
984
+ const linkColor = (0, import_react2.useCallback)(
985
+ (link) => {
986
+ const edgeColor = EDGE_COLORS[link.type] ?? "#c0c0c0";
987
+ if (connectedSet) {
988
+ const srcId = typeof link.source === "object" ? link.source.id : link.source;
989
+ const tgtId = typeof link.target === "object" ? link.target.id : link.target;
990
+ if (!connectedSet.has(srcId) || !connectedSet.has(tgtId)) {
991
+ return `rgba(200,200,200,${DIM_OPACITY})`;
992
+ }
993
+ }
994
+ return edgeColor;
995
+ },
996
+ [connectedSet]
997
+ );
998
+ const linkWidth = (0, import_react2.useCallback)(
999
+ (link) => {
1000
+ const base = EDGE_WIDTHS[link.type] ?? 1.5;
1001
+ return base * 1.2;
1002
+ },
1003
+ []
1004
+ );
1005
+ const linkCurvature = (0, import_react2.useCallback)(
1006
+ (link) => {
1007
+ if (link.type === "references") return 0.35;
1008
+ if (link.type === "informs") return 0.3;
1009
+ if (link.type === "triggers") return 0.2;
1010
+ return 0.06;
1011
+ },
1012
+ []
1013
+ );
1014
+ const linkParticleSpeed = (0, import_react2.useCallback)(
1015
+ (link) => {
1016
+ if (CAUSAL_EDGES.has(link.type)) return 8e-3;
1017
+ return LINK_PARTICLE_SPEED;
1018
+ },
1019
+ []
1020
+ );
1021
+ const linkArrowLength = (0, import_react2.useCallback)(
1022
+ (link) => {
1023
+ if (CAUSAL_EDGES.has(link.type)) return 7;
1024
+ return 4;
1025
+ },
1026
+ []
1027
+ );
1028
+ const linkParticles = (0, import_react2.useCallback)(
1029
+ (link) => {
1030
+ if (link.type === "references") return 0;
1031
+ if (connectedSet) {
1032
+ const srcId = typeof link.source === "object" ? link.source.id : link.source;
1033
+ const tgtId = typeof link.target === "object" ? link.target.id : link.target;
1034
+ if (!connectedSet.has(srcId) || !connectedSet.has(tgtId)) return 0;
1035
+ }
1036
+ return LINK_PARTICLE_COUNT;
1037
+ },
1038
+ [connectedSet]
1039
+ );
1040
+ (0, import_react2.useEffect)(() => {
1041
+ if (!fgRef.current) return;
1042
+ const fg = fgRef.current;
1043
+ try {
1044
+ fg.d3Force("charge")?.strength(-420);
1045
+ fg.d3Force("link")?.distance((link) => {
1046
+ switch (link.type) {
1047
+ case "references":
1048
+ return 160;
1049
+ case "informs":
1050
+ return 120;
1051
+ case "triggers":
1052
+ return 100;
1053
+ case "spawns":
1054
+ return 140;
1055
+ default:
1056
+ return 80;
1057
+ }
1058
+ });
1059
+ fg.d3Force("center")?.strength(0.04);
1060
+ } catch {
1061
+ }
1062
+ }, [graphData]);
1063
+ (0, import_react2.useEffect)(() => {
1064
+ if (!selectedNodeId || !fgRef.current) return;
1065
+ const node = graphData.nodes.find((n) => n.id === selectedNodeId);
1066
+ if (!node || node.x == null || node.y == null || node.z == null) return;
1067
+ fgRef.current.cameraPosition(
1068
+ { x: node.x + CAMERA_DISTANCE * 0.3, y: node.y + CAMERA_DISTANCE * 0.2, z: node.z + CAMERA_DISTANCE * 0.5 },
1069
+ { x: node.x, y: node.y, z: node.z },
1070
+ CAMERA_FOCUS_DURATION_MS
1071
+ );
1072
+ }, [selectedNodeId, graphData.nodes]);
1073
+ (0, import_react2.useEffect)(() => {
1074
+ if (!fgRef.current) return;
1075
+ try {
1076
+ const scene = fgRef.current.scene();
1077
+ if (!scene) return;
1078
+ if (scene.userData.__lightsConfigured) return;
1079
+ scene.userData.__lightsConfigured = true;
1080
+ const ambient = new THREE2.AmbientLight(16777215, 0.7);
1081
+ const directional = new THREE2.DirectionalLight(16777215, 0.8);
1082
+ directional.position.set(100, 200, 150);
1083
+ scene.add(ambient, directional);
1084
+ scene.fog = new THREE2.Fog(SCENE_BG, 600, 1600);
1085
+ } catch {
1086
+ }
1087
+ });
1088
+ (0, import_react2.useEffect)(() => {
1089
+ let frameId;
1090
+ const animate = () => {
1091
+ if (!fgRef.current) return;
1092
+ try {
1093
+ const scene = fgRef.current.scene();
1094
+ if (!scene) return;
1095
+ scene.traverse((obj) => {
1096
+ if (obj.userData.__orbitRing) {
1097
+ obj.rotation.z += 0.02;
1098
+ }
1099
+ });
1100
+ } catch {
1101
+ }
1102
+ frameId = requestAnimationFrame(animate);
1103
+ };
1104
+ frameId = requestAnimationFrame(animate);
1105
+ return () => cancelAnimationFrame(frameId);
1106
+ }, []);
1107
+ (0, import_react2.useEffect)(() => {
1108
+ return () => {
1109
+ disposeGeometryCache();
1110
+ };
1111
+ }, []);
1112
+ const handleNodeClick = (0, import_react2.useCallback)(
1113
+ (node) => {
1114
+ onNodeClick?.(node.id, node.type);
1115
+ },
1116
+ [onNodeClick]
1117
+ );
1118
+ const handleNodeHover = (0, import_react2.useCallback)(
1119
+ (node) => {
1120
+ const id = node?.id ?? null;
1121
+ setHoveredNodeId(id);
1122
+ onNodeHover?.(id);
1123
+ },
1124
+ [onNodeHover]
1125
+ );
1126
+ const handleBgClick = (0, import_react2.useCallback)(() => {
1127
+ onBackgroundClick?.();
1128
+ }, [onBackgroundClick]);
1129
+ const EDGE_TYPE_LABELS = {
1130
+ spawns: "Spawns",
1131
+ executes: "Executes",
1132
+ produces: "Produces",
1133
+ modifies: "Modifies",
1134
+ deletes: "Deletes",
1135
+ thinks: "Thinks",
1136
+ triggers: "Triggers",
1137
+ informs: "Informs",
1138
+ references: "\u5F15\u7528"
1139
+ // JETP-026
1140
+ };
1141
+ const linkLabel = (0, import_react2.useCallback)(
1142
+ (link) => {
1143
+ const typeLabel = EDGE_TYPE_LABELS[link.type] ?? link.type;
1144
+ const color = EDGE_COLORS[link.type] ?? "#888";
1145
+ const lines = [
1146
+ `<span style="color:${color};font-weight:600">${typeLabel}</span>`
1147
+ ];
1148
+ if (link.label) lines.push(link.label);
1149
+ return `<div style="background:rgba(255,255,255,0.96);color:#444;padding:8px 12px;border-radius:6px;font-size:13px;line-height:1.6;box-shadow:0 2px 8px rgba(0,0,0,0.12);max-width:320px;word-break:break-all;border:1px solid #e8e8e8">${lines.join("<br/>")}</div>`;
1150
+ },
1151
+ []
1152
+ );
1153
+ const nodeLabel = (0, import_react2.useCallback)(
1154
+ (node) => {
1155
+ if (hoveredNodeId !== node.id) return "";
1156
+ const lines = [];
1157
+ if (node.type === "reasoning") {
1158
+ lines.push(`<b>${node.agentLabel ?? "Reasoning"}</b>`);
1159
+ if (node.status) lines.push(`Status: ${node.status}`);
1160
+ if (node.contentPreview) {
1161
+ const preview = node.contentPreview.length > 120 ? node.contentPreview.slice(0, 120) + "\u2026" : node.contentPreview;
1162
+ lines.push(`<span style="color:#666">${preview}</span>`);
1163
+ }
1164
+ } else {
1165
+ lines.push(`<b>${node.label}</b>`);
1166
+ if (node.subtitle) lines.push(`Purpose: ${node.subtitle}`);
1167
+ if (node.status) lines.push(`Status: ${node.status}`);
1168
+ }
1169
+ return `<div style="background:rgba(255,255,255,0.96);color:#333;padding:8px 12px;border-radius:6px;font-size:13px;line-height:1.6;box-shadow:0 2px 8px rgba(0,0,0,0.15);border:1px solid #e8e8e8;max-width:360px;word-break:break-all">${lines.join("<br/>")}</div>`;
1170
+ },
1171
+ [hoveredNodeId]
1172
+ );
1173
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1174
+ import_react_force_graph_3d.default,
1175
+ {
1176
+ ref: fgRef,
1177
+ graphData,
1178
+ width,
1179
+ height,
1180
+ backgroundColor: `#${SCENE_BG.toString(16).padStart(6, "0")}`,
1181
+ showNavInfo: false,
1182
+ nodeThreeObject,
1183
+ nodeLabel,
1184
+ linkLabel,
1185
+ linkColor,
1186
+ linkWidth,
1187
+ linkOpacity: 0.75,
1188
+ linkCurvature,
1189
+ linkDirectionalParticles: linkParticles,
1190
+ linkDirectionalParticleWidth: LINK_PARTICLE_WIDTH,
1191
+ linkDirectionalParticleSpeed: linkParticleSpeed,
1192
+ linkDirectionalParticleColor: linkColor,
1193
+ linkDirectionalArrowLength: linkArrowLength,
1194
+ linkDirectionalArrowRelPos: 0.92,
1195
+ linkDirectionalArrowColor: linkColor,
1196
+ d3AlphaDecay: 0.04,
1197
+ d3VelocityDecay: 0.4,
1198
+ warmupTicks: 200,
1199
+ cooldownTicks: 0,
1200
+ cooldownTime: 3e3,
1201
+ onNodeClick: handleNodeClick,
1202
+ onNodeHover: handleNodeHover,
1203
+ onBackgroundClick: handleBgClick,
1204
+ enableNodeDrag: true,
1205
+ enableNavigationControls: true
1206
+ }
1207
+ );
1208
+ };
1209
+ var ProvenanceGraph3D = import_react2.default.memo(ProvenanceGraph3DInner);
1210
+
1211
+ // src/provenance/components/GraphStatsLegend.tsx
1212
+ var import_react4 = __toESM(require("react"), 1);
1213
+ var import_antd = require("antd");
1214
+
1215
+ // src/i18n/context.ts
1216
+ var import_react3 = require("react");
1217
+
1218
+ // src/i18n/messages.ts
1219
+ var zhCN = {
1220
+ "header.title": "YumiAI",
1221
+ "header.icon": "",
1222
+ "status.connecting": "\u8FDE\u63A5\u4E2D...",
1223
+ "status.running": "\u6267\u884C\u4E2D...",
1224
+ "status.compressing": "\u4E0A\u4E0B\u6587\u538B\u7F29\u4E2D...",
1225
+ "status.error": "\u8FDE\u63A5\u9519\u8BEF",
1226
+ "status.idle": "\u5F85\u547D",
1227
+ "empty.waiting": "\u7B49\u5F85\u5BF9\u8BDD\u5F00\u59CB...",
1228
+ "empty.icon": "",
1229
+ "round.separator": "\u4E0A\u4E00\u8F6E\u5BF9\u8BDD",
1230
+ "round.status.running": "\u6267\u884C\u4E2D",
1231
+ "round.status.completed": "\u5DF2\u5B8C\u6210",
1232
+ "round.status.error": "\u6267\u884C\u5931\u8D25",
1233
+ "round.noMessage": "(\u65E0\u6D88\u606F)",
1234
+ "footer.attribution": "",
1235
+ "selection.ask": "\u95EE\u4E00\u4E0B",
1236
+ "viewer.loading": "\u52A0\u8F7D\u4E2D...",
1237
+ "viewer.error": "\u65E0\u6CD5\u83B7\u53D6\u6587\u4EF6\u5185\u5BB9",
1238
+ "viewer.back": "\u2190 \u8FD4\u56DE",
1239
+ "viewer.defaultTitle": "\u6587\u4EF6\u9884\u89C8",
1240
+ "viewer.copyFull": "\u590D\u5236\u5168\u6587",
1241
+ "viewer.copyFullTitle": "\u590D\u5236\u5168\u6587\u5230\u526A\u8D34\u677F\u5E76\u5F15\u7528",
1242
+ "viewer.referenceFile": "\u5F15\u7528\u6B64\u6587\u4EF6",
1243
+ "viewer.referenceFileTitle": "\u5F15\u7528\u6B64\u6587\u4EF6",
1244
+ "viewer.referencePage": "\u5F15\u7528\u5F53\u524D\u9875\u9762",
1245
+ "viewer.referencePageTitle": "\u5F15\u7528\u5F53\u524D\u9875\u9762\u5230\u5BF9\u8BDD",
1246
+ "viewer.download": "\u4E0B\u8F7D",
1247
+ "viewer.fullscreen": "\u5168\u5C4F (\u2318L)",
1248
+ "viewer.fullscreenExit": "\u9000\u51FA\u5168\u5C4F",
1249
+ "viewer.close": "\u5173\u95ED",
1250
+ "viewer.unknownType": "\u672A\u77E5\u7C7B\u578B",
1251
+ "viewer.iframeHint": "iframe \u5185\u5BB9\u65E0\u6CD5\u76F4\u63A5\u9009\u4E2D\u6587\u672C\uFF0C\u8BF7\u4F7F\u7528\u4E0A\u65B9\u300C\u5F15\u7528\u6B64\u6587\u4EF6\u300D\u6309\u94AE",
1252
+ "viewer.copySnippet": "\u590D\u5236\u7247\u6BB5",
1253
+ "viewer.loadingPdf": "\u52A0\u8F7D PDF \u67E5\u770B\u5668...",
1254
+ "viewer.pdfPages": "\u5171 {{count}} \u9875",
1255
+ "viewer.loadingKicad": "\u52A0\u8F7D KiCad \u67E5\u770B\u5668...",
1256
+ "viewer.loading3d": "\u52A0\u8F7D 3D \u67E5\u770B\u5668...",
1257
+ "viewer.loadingStep": "\u52A0\u8F7D STEP \u67E5\u770B\u5668...",
1258
+ "viewer.gerberTitle": "DFX Copilot \u2014 Gerber \u9884\u89C8",
1259
+ "viewer.gerberBlobWarning": "DFX Copilot \u9700\u8981\u4ECE\u516C\u7F51\u53EF\u8BBF\u95EE\u7684\u5730\u5740\u62C9\u53D6\u6587\u4EF6\u3002\u5F53\u524D\u4E3A\u672C\u5730 blob/data URL\uFF0Ciframe \u5185\u65E0\u6CD5\u4F7F\u7528\u3002\u8BF7\u5728 Adapter \u4E2D\u8FD4\u56DE content_url\uFF0C\u6216\u5B9E\u73B0 getResourceUrl \u63D0\u4F9B HTTPS \u9884\u7B7E\u540D\u94FE\u63A5\u3002",
1260
+ "viewer.gerberNoHttpUrl": "\u5F53\u524D\u8D44\u6E90\u5730\u5740\u4E0D\u662F http(s)\uFF0C\u65E0\u6CD5\u5D4C\u5165 DFX Copilot\u3002\u8BF7\u4F7F\u7528\u76F4\u94FE\u6216\u9884\u7B7E\u540D URL\u3002",
1261
+ "viewer.pdfPreview": "PDF \u9884\u89C8",
1262
+ "viewer.htmlPreview": "HTML \u9884\u89C8",
1263
+ "viewer.htmlProjectLoading": "\u6B63\u5728\u52A0\u8F7D HTML \u9879\u76EE\u6587\u4EF6\u2026",
1264
+ "viewer.htmlProjectNoEntry": "HTML \u9879\u76EE\u7F3A\u5C11\u5165\u53E3\u6587\u4EF6\uFF08\u5982 index.html\uFF09\uFF0C\u65E0\u6CD5\u9884\u89C8",
1265
+ "viewer.htmlProjectSizeLimit": "HTML \u9879\u76EE\u8D85\u51FA\u5927\u5C0F\u9650\u5236\uFF0C\u4EC5\u663E\u793A\u5165\u53E3\u6587\u4EF6",
1266
+ "viewer.htmlStrategyForcedInlineWarning": "\u68C0\u6D4B\u5230 ESM \u6A21\u5757\uFF0C\u4F46\u5DF2\u5F3A\u5236 inline \u7B56\u7565\uFF0C\u53EF\u80FD\u52A0\u8F7D\u5931\u8D25",
1267
+ "viewer.htmlStrategyFallbackCspWarning": "\u5BBF\u4E3B CSP \u7981\u6B62 blob:\uFF0C\u5DF2\u81EA\u52A8\u964D\u7EA7\u5230 inline \u7B56\u7565",
1268
+ "viewer.copyFullKicadTitle": "\u590D\u5236\u5168\u6587 KiCad \u539F\u6587\u5230\u526A\u8D34\u677F\u5E76\u5F15\u7528\uFF0C\u7C98\u8D34\u5230\u8F93\u5165\u6846\u5373\u53EF\u5E26\u5165",
1269
+ "viewer.zoomIn": "\u653E\u5927",
1270
+ "viewer.zoomOut": "\u7F29\u5C0F",
1271
+ "viewer.zoomReset": "\u91CD\u7F6E",
1272
+ "viewer.loadingWord": "\u52A0\u8F7D Word \u67E5\u770B\u5668...",
1273
+ "viewer.loadingExcel": "\u52A0\u8F7D Excel \u67E5\u770B\u5668...",
1274
+ "viewer.loadingPowerPoint": "\u52A0\u8F7D PowerPoint \u67E5\u770B\u5668...",
1275
+ "viewer.pptPrev": "\u2039 \u4E0A\u4E00\u9875",
1276
+ "viewer.pptNext": "\u4E0B\u4E00\u9875 \u203A",
1277
+ "viewer.pptSlide": "\u5E7B\u706F\u7247",
1278
+ "viewer.pptThumbnails": "\u7F29\u7565\u56FE",
1279
+ "viewer.excelRows": "\u884C",
1280
+ "viewer.excelColumns": "\u5217",
1281
+ "childAgent.status.running": "\u6267\u884C\u4E2D",
1282
+ "childAgent.status.completed": "\u5DF2\u5B8C\u6210",
1283
+ "hitl.form.defaultTitle": "\u8BF7\u586B\u5199\u8868\u5355",
1284
+ "hitl.wait.default": "\u7B49\u5F85\u7528\u6237\u8F93\u5165...",
1285
+ "todo.completed.count": "\u5DF2\u5B8C\u6210 {{completed}}/{{total}}",
1286
+ "todo.blocked.count": "{{count}} \u9879\u963B\u585E",
1287
+ "todo.more": "+ {{count}} \u66F4\u591A",
1288
+ "todo.header.done": "\u5DF2\u5B8C\u6210",
1289
+ "tool.phase.generating": "\u751F\u6210\u4E2D",
1290
+ "tool.phase.executing": "\u6267\u884C\u4E2D",
1291
+ "tool.phase.complete": "\u5B8C\u6210",
1292
+ "tool.phase.error": "\u5931\u8D25",
1293
+ "tool.executing": "\u6267\u884C\u5DE5\u5177: {{name}}",
1294
+ "tool.mcp.running": "\u6267\u884C\u4E2D",
1295
+ "tool.mcp.success": "\u5B8C\u6210",
1296
+ "tool.mcp.error": "\u5931\u8D25",
1297
+ "form.placeholder.select": "\u8BF7\u9009\u62E9",
1298
+ "form.required.default": "\u6B64\u9879\u4E3A\u5FC5\u586B\u9879",
1299
+ "form.submit.submit": "\u63D0\u4EA4",
1300
+ "form.submit.submitting": "\u63D0\u4EA4\u4E2D...",
1301
+ "form.requestId": "\u8BF7\u6C42 ID: ",
1302
+ "pinned.label": "\u7F6E\u9876",
1303
+ "plan.title": "\u6267\u884C\u8BA1\u5212",
1304
+ "plan.step": "\u6B65\u9AA4 {{index}}",
1305
+ "thinking.inProgress": "\u601D\u8003\u4E2D...",
1306
+ "thinking.completed": "\u601D\u8003\u5B8C\u6210",
1307
+ "split.unreadCount": "{{count}} \u6761\u65B0\u6D88\u606F",
1308
+ "split.askQuestion": "\u63D0\u95EE (\u2318/)",
1309
+ "split.exitFullscreen": "\u9000\u51FA\u5168\u5C4F (Esc)",
1310
+ "context.inputPlaceholder": "\u5728\u8FD9\u91CC\u63D0\u95EE\u2026",
1311
+ "context.inputPlaceholderWithFile": "\u5173\u4E8E {{fileName}} \u63D0\u95EE\u2026",
1312
+ "context.send": "\u53D1\u9001",
1313
+ "context.removeReference": "\u79FB\u9664\u5F15\u7528",
1314
+ "split.home": "\u4E3B\u5BF9\u8BDD",
1315
+ "split.workspace": "\u5DE5\u4F5C\u7A7A\u95F4",
1316
+ "split.annotation": "\u6279\u6CE8",
1317
+ "split.tabClose": "\u5173\u95ED\u6807\u7B7E\u9875",
1318
+ "split.tabNew": "\u65B0\u6807\u7B7E\u9875",
1319
+ "workspace.title": "\u5DE5\u4F5C\u7A7A\u95F4",
1320
+ "workspace.searchPlaceholder": "\u641C\u7D22\u6587\u4EF6\u2026",
1321
+ "workspace.empty": "\u6682\u65E0\u6587\u4EF6",
1322
+ "workspace.downloadAll": "\u6253\u5305\u4E0B\u8F7D\u5168\u90E8\u6587\u4EF6",
1323
+ "workspace.recent": "\u6700\u8FD1\u4FEE\u6539",
1324
+ "workspace.open": "\u6253\u5F00",
1325
+ "workspace.openInNewTab": "\u5728\u65B0\u6807\u7B7E\u9875\u6253\u5F00",
1326
+ "workspace.download": "\u4E0B\u8F7D",
1327
+ "workspace.copyPath": "\u590D\u5236\u8DEF\u5F84",
1328
+ "workspace.expandAll": "\u5C55\u5F00\u5168\u90E8",
1329
+ "workspace.collapseAll": "\u6298\u53E0\u5168\u90E8",
1330
+ "annotation.title": "\u6279\u6CE8",
1331
+ "annotation.empty": "\u6682\u65E0\u6279\u6CE8",
1332
+ "annotation.fileLevelTitle": "\u6587\u4EF6\u5BF9\u8BDD",
1333
+ "annotation.fileLevelPlaceholder": "\u5173\u4E8E\u6B64\u6587\u4EF6\u63D0\u95EE\u2026",
1334
+ "annotation.anchoredPlaceholder": "\u5173\u4E8E\u6240\u9009\u5185\u5BB9\u63D0\u95EE\u2026",
1335
+ "annotation.inlineInputPlaceholder": "\u5C31\u6B64\u5904\u63D0\u95EE\u2026",
1336
+ "annotation.replyPlaceholder": "\u7EE7\u7EED\u8FFD\u95EE\u2026",
1337
+ "annotation.anchorLabel": "\u951A\u70B9: {{text}}",
1338
+ "annotation.close": "\u5173\u95ED",
1339
+ "annotation.fabLabel": "\u6587\u4EF6\u6279\u6CE8",
1340
+ "annotation.fabHeader": "{{fileName}} \xB7 \u6587\u4EF6\u5BF9\u8BDD",
1341
+ "annotation.messageCount": "{{count}} \u6761\u6D88\u606F",
1342
+ "annotation.anchorInvalid": "\u951A\u70B9\u5DF2\u5931\u6548",
1343
+ "annotation.errorRetry": "\u53D1\u9001\u5931\u8D25\uFF0C\u70B9\u51FB\u91CD\u8BD5",
1344
+ "annotation.queuedHint": "\u6392\u961F\u4E2D\uFF0C\u8BF7\u7A0D\u5019\u2026",
1345
+ "annotation.selectionLabel": "\u9009\u4E2D\u5185\u5BB9",
1346
+ "agentControl.pause": "\u6682\u505C",
1347
+ "agentControl.resume": "\u7EE7\u7EED",
1348
+ "agentControl.stop": "\u505C\u6B62",
1349
+ "agentControl.paused": "\u5DF2\u6682\u505C",
1350
+ "agentControl.groupTitle": "\u5DE5\u4F5C\u7EC4",
1351
+ "aria.fileNavigation": "\u6587\u4EF6\u5BFC\u822A",
1352
+ "kicad.loadFailed": "KiCanvas \u52A0\u8F7D\u5931\u8D25\uFF0C\u5DF2\u5207\u6362\u81F3\u6E90\u7801\u89C6\u56FE",
1353
+ "kicad.urlNotReady": "\u8D44\u6E90 URL \u672A\u5C31\u7EEA\uFF0C\u5F53\u524D\u663E\u793A\u6E90\u7801",
1354
+ "kicad.loadingEngine": "\u52A0\u8F7D KiCanvas \u53EF\u89C6\u5316\u5F15\u64CE...",
1355
+ "kicad.sidebarTitle": "KiCanvas \u4FA7\u680F\u63D0\u4F9B\uFF1A\u5C5E\u6027\u3001\u7B26\u53F7/\u5C01\u88C5\u5217\u8868\u3001\u6587\u6863\u4FE1\u606F\u7B49",
1356
+ "kicad.sidebarPcb": "PCB\uFF1A\u4FA7\u680F\u53EF\u67E5\u5C5E\u6027\u3001\u5C01\u88C5\u5217\u8868",
1357
+ "kicad.sidebarSch": "SCH\uFF1A\u4FA7\u680F\u53EF\u67E5\u7B26\u53F7/\u5B50\u56FE\u5C5E\u6027",
1358
+ "kicad.sidebarGeneric": "\u4FA7\u680F\u67E5\u770B\u5C5E\u6027",
1359
+ "kicad.viewVisual": "\u53EF\u89C6\u5316",
1360
+ "kicad.viewSource": "\u6E90\u7801",
1361
+ "provenance.filter.type.agent": "\u667A\u80FD\u4F53",
1362
+ "provenance.filter.type.action": "\u5DE5\u5177",
1363
+ "provenance.filter.type.file": "\u6587\u4EF6",
1364
+ "provenance.filter.type.task": "\u4EFB\u52A1",
1365
+ "provenance.filter.type.reasoning": "\u63A8\u7406",
1366
+ "provenance.filter.depth": "\u6DF1\u5EA6:",
1367
+ "provenance.toolbar.zoomToFit": "\u81EA\u9002\u5E94",
1368
+ "provenance.toolbar.resetCamera": "\u91CD\u7F6E\u89C6\u89D2",
1369
+ "provenance.toolbar.refresh": "\u5237\u65B0",
1370
+ "provenance.legend.reasoning": "\u63A8\u7406",
1371
+ "provenance.legend.action": "\u5DE5\u5177",
1372
+ "provenance.legend.file": "\u6587\u4EF6",
1373
+ "provenance.legend.task": "\u4EFB\u52A1",
1374
+ "provenance.legend.references": "\u5F15\u7528",
1375
+ "provenance.legend.edges": "\u8FB9: ",
1376
+ "provenance.legend.depth": "\u6DF1\u5EA6: ",
1377
+ "provenance.detail.title": "\u8282\u70B9\u8BE6\u60C5",
1378
+ "provenance.detail.noSelection": "\u672A\u9009\u4E2D\u8282\u70B9",
1379
+ "provenance.detail.label.name": "\u540D\u79F0",
1380
+ "provenance.detail.label.id": "ID",
1381
+ "provenance.detail.label.timestamp": "\u65F6\u95F4",
1382
+ "provenance.detail.label.agentId": "Agent ID",
1383
+ "provenance.detail.label.instanceId": "\u5B9E\u4F8B ID",
1384
+ "provenance.detail.label.level": "\u5C42\u7EA7",
1385
+ "provenance.detail.label.status": "\u72B6\u6001",
1386
+ "provenance.detail.label.tool": "\u5DE5\u5177",
1387
+ "provenance.detail.label.purpose": "\u76EE\u7684",
1388
+ "provenance.detail.label.duration": "\u8017\u65F6",
1389
+ "provenance.detail.label.path": "\u8DEF\u5F84",
1390
+ "provenance.detail.label.operation": "\u64CD\u4F5C",
1391
+ "provenance.detail.label.taskId": "\u4EFB\u52A1 ID",
1392
+ "provenance.detail.label.description": "\u63CF\u8FF0",
1393
+ "provenance.detail.label.model": "\u6A21\u578B",
1394
+ "provenance.detail.label.tokenCount": "Token \u6570",
1395
+ "provenance.detail.label.reasoningPreview": "\u63A8\u7406\u9884\u89C8",
1396
+ "provenance.detail.relatedEdges": "\u5173\u8054\u8FB9 ({{count}})",
1397
+ "provenance.page.noSessionHint": "\u8BF7\u901A\u8FC7 URL \u53C2\u6570\u6307\u5B9A\u4F1A\u8BDD: ?session_id=NNN",
1398
+ "provenance.page.loading": "\u52A0\u8F7D\u63A8\u7406\u56FE\u8C31...",
1399
+ "provenance.page.emptyGraph": "\u5F53\u524D\u4F1A\u8BDD\u6682\u65E0\u56FE\u8C31\u6570\u636E",
1400
+ "provenance.drawer.emptyGraph": "\u6682\u65E0\u56FE\u8C31\u6570\u636E",
1401
+ "provenance.graph.edgeType.references": "\u5F15\u7528",
1402
+ "toolResult.label": "\u6267\u884C\u7ED3\u679C",
1403
+ "toolResult.expandAll": "\u5C55\u5F00\u5168\u90E8 ({{count}} \u884C)",
1404
+ "toolResult.searchSummary": "\u641C\u7D22\u7ED3\u679C \xB7 {{count}} \u6761",
1405
+ "toolResult.scrapeSummary": "\u6293\u53D6\u7ED3\u679C \xB7 {{title}}",
1406
+ "toolResult.more": "+{{count}} more",
1407
+ "plan.status.active": "\u6267\u884C\u4E2D",
1408
+ "pinned.noMessage": "(\u65E0\u6D88\u606F\u5185\u5BB9)",
1409
+ "viewer.fallback.unknownType": "\u672A\u77E5\u7C7B\u578B",
1410
+ "viewer.fallback.download": "\u4E0B\u8F7D\u6587\u4EF6",
1411
+ "fileSize.B": "{{size}} B",
1412
+ "fileSize.KB": "{{size}} KB",
1413
+ "fileSize.MB": "{{size}} MB",
1414
+ "thinking.title": "\u601D\u8003\u63A8\u7406",
1415
+ "thinking.step": "\u6B65\u9AA4 {{step}}",
1416
+ "viewer.stepHint": "\u9F20\u6807\u62D6\u62FD\u65CB\u8F6C\uFF0C\u6EDA\u8F6E\u7F29\u653E\uFF0C\u53F3\u952E\u5E73\u79FB",
1417
+ "viewer.threeHint": "\u9F20\u6807\u62D6\u62FD\u65CB\u8F6C\uFF0C\u6EDA\u8F6E\u7F29\u653E\uFF0C\u53F3\u952E\u5E73\u79FB",
1418
+ "viewer.3d.wireframe": "\u7EBF\u6846\u6A21\u5F0F",
1419
+ "viewer.3d.resetView": "\u91CD\u7F6E\u89C6\u89D2",
1420
+ "reference.header": "[\u5F15\u7528\u6587\u4EF6: {{fileName}}]",
1421
+ "history.noMessage": "(\u5386\u53F2\u6D88\u606F)",
1422
+ "agent.defaultName": "\u52A9\u624B",
1423
+ "error.unknown": "\u672A\u77E5\u9519\u8BEF",
1424
+ "locale": "zh-CN",
1425
+ "skill.inlineLabel": "\u5148\u67E5\u770B\u5E76\u4F7F\u7528{{name}}\u6280\u80FD\uFF0C\u53BB\u89E3\u51B3\uFF1A",
1426
+ "skill.empty": "\u6682\u65E0\u53EF\u7528\u6280\u80FD",
1427
+ "skill.searchPlaceholder": "\u641C\u7D22\u6280\u80FD...",
1428
+ "skill.removeLabel": "\u79FB\u9664\u6280\u80FD",
1429
+ "skill.loading": "\u52A0\u8F7D\u4E2D...",
1430
+ "skill.loadError": "\u52A0\u8F7D\u6280\u80FD\u5931\u8D25",
1431
+ "skill.loadMore": "\u52A0\u8F7D\u66F4\u591A",
1432
+ "skill.selectorLabel": "\u6280\u80FD\u9009\u62E9",
1433
+ "pool.idle": "\u5F85\u547D",
1434
+ "pool.collaborating": "{{count}} \u534F\u4F5C\u4E2D",
1435
+ "pool.awaiting": "{{count}} \u7B49\u5F85\u4EBA\u5DE5",
1436
+ "pool.title": "\u667A\u80FD\u4F53\u6C60",
1437
+ "pool.empty": "\u6682\u65E0\u6D3B\u8DC3\u667A\u80FD\u4F53",
1438
+ "pool.state.running": "\u6267\u884C\u4E2D",
1439
+ "pool.state.paused": "\u7B49\u5F85\u4EBA\u5DE5",
1440
+ "pool.state.completed": "\u5DF2\u5B8C\u6210",
1441
+ "pool.state.lost": "\u5DF2\u5931\u8054",
1442
+ "pool.state.unknown": "\u672A\u77E5",
1443
+ "input.placeholder": "\u8F93\u5165\u6D88\u606F\uFF0C/ \u9009\u62E9\u6280\u80FD",
1444
+ "input.placeholderLoading": "\u7B49\u5F85\u56DE\u590D\u4E2D\u2026",
1445
+ "discussion.title": "\u8BA8\u8BBA",
1446
+ "discussion.empty": "\u6682\u65E0\u8BA8\u8BBA",
1447
+ "discussion.active": "\u8FDB\u884C\u4E2D",
1448
+ "discussion.resolved": "\u5DF2\u7ED3\u8BBA",
1449
+ "discussion.archived": "\u5DF2\u5F52\u6863",
1450
+ "round.foreign.label": "\u6765\u81EA\u5176\u4ED6\u7A97\u53E3\u7684\u5BF9\u8BDD",
1451
+ "round.foreign.unread": "{{count}} \u6761\u65B0\u6D88\u606F",
1452
+ "round.foreign.expand": "\u70B9\u51FB\u5C55\u5F00",
1453
+ "sidebar.mainChat": "\u4E3B\u5BF9\u8BDD",
1454
+ "sidebar.chat": "\u5BF9\u8BDD",
1455
+ "sidebar.fileQA": "\u6587\u4EF6\u95EE\u7B54",
1456
+ "sidebar.selectionQA": "\u9009\u533A\u95EE\u7B54",
1457
+ "sessionList.title": "\u5386\u53F2\u4F1A\u8BDD",
1458
+ "sessionList.newSession": "+ \u65B0\u4F1A\u8BDD",
1459
+ "sessionList.logout": "\u9000\u51FA",
1460
+ "sessionList.loading": "\u52A0\u8F7D\u4E2D...",
1461
+ "sessionList.empty": "\u6682\u65E0\u4F1A\u8BDD",
1462
+ "sessionList.unsupported": "\u5F53\u524D adapter \u672A\u5B9E\u73B0 listSessions",
1463
+ "sessionList.untitled": "\u65E0\u6807\u9898",
1464
+ "sessionList.deleteTitle": "\u5220\u9664\u4F1A\u8BDD",
1465
+ "sessionList.deleteConfirm": "\u786E\u5B9A\u5220\u9664\u8BE5\u4F1A\u8BDD\uFF1F",
1466
+ "sessionList.prevPage": "\u2190",
1467
+ "sessionList.nextPage": "\u2192",
1468
+ "sessionList.pageInfo": "\u7B2C {page} / {totalPages} \u9875",
1469
+ "modelPicker.menu.head": "\u672C\u6B21\u4F7F\u7528\u7684\u6A21\u578B",
1470
+ "modelPicker.menu.aria": "\u9009\u62E9\u672C\u6B21\u4F7F\u7528\u7684\u6A21\u578B",
1471
+ "modelPicker.auto.title": "\u9ED8\u8BA4\uFF08\u8DDF\u968F Agent\uFF09",
1472
+ "modelPicker.auto.hint.knownChannel": "\u5F53\u524D Agent \u9ED8\u8BA4\uFF1A{{name}} \xB7 {{channel}}",
1473
+ "modelPicker.auto.hint.knownBasename": "\u5F53\u524D Agent \u9ED8\u8BA4\uFF1A{{name}}",
1474
+ "modelPicker.auto.hint.fallback": "\u4F7F\u7528 Agent \u6CE8\u518C\u7684\u9ED8\u8BA4\u6A21\u578B\uFF0C\u8DE8\u5B50 Agent \u81EA\u52A8\u5207\u6362",
1475
+ "modelPicker.row.hint.channelMulti": "{{available}}/{{total}} \u4E2A\u6E20\u9053\u53EF\u7528",
1476
+ "modelPicker.row.hint.channelSingle": "\u6E20\u9053\uFF1A{{channel}}",
1477
+ "modelPicker.row.hint.versionMulti": "{{count}} \u4E2A\u7248\u672C\u53EF\u7528",
1478
+ "modelPicker.fallback.placeholder": "\u9ED8\u8BA4\u6A21\u578B",
1479
+ "modelPicker.inert.title": "\u6A21\u578B\u9009\u62E9\u5F53\u524D\u4E0D\u53EF\u7528",
1480
+ "modelPicker.guestLocked.label": "\u9ED8\u8BA4\u6A21\u578B \xB7 \u767B\u5F55\u540E\u53EF\u9009",
1481
+ "modelPicker.guestLocked.title": "\u767B\u5F55\u540E\u53EF\u5728\u591A\u4E2A\u6A21\u578B\u95F4\u5207\u6362\uFF1B\u6E38\u5BA2\u5148\u7528\u9ED8\u8BA4\u6A21\u578B\u5373\u53EF\u5F00\u5E72\u3002",
1482
+ "modelPicker.loadingList": "\u52A0\u8F7D\u6A21\u578B\u6E05\u5355\u2026",
1483
+ "modelPicker.trigger.title.stale": "{{name}}\uFF08\u5DF2\u4E0D\u5728\u6E05\u5355\u4E2D\uFF0C\u53D1\u9001\u65F6\u4ECD\u4F1A\u5C1D\u8BD5\u4F7F\u7528\uFF09",
1484
+ "modelPicker.trigger.title.agentDefault.withChannel": "\u5F53\u524D Agent \u9ED8\u8BA4\uFF1A{{name}} \xB7 {{channel}}\uFF08\u53D1\u9001\u65F6\u8DDF\u968F Agent\uFF09",
1485
+ "modelPicker.trigger.title.agentDefault": "\u5F53\u524D Agent \u9ED8\u8BA4\uFF1A{{name}}\uFF08\u53D1\u9001\u65F6\u8DDF\u968F Agent\uFF09",
1486
+ "modelPicker.trigger.title.current": "\u5F53\u524D\u6A21\u578B\uFF1A{{name}}",
1487
+ "modelPicker.row.title.pickDefault": "\u9009\u9ED8\u8BA4\u6E20\u9053\uFF08{{hint}}\uFF09",
1488
+ "modelPicker.row.title.pick": "\u9009\u7528 {{name}}",
1489
+ "modelPicker.chip.aria": "{{title}} \u6E20\u9053",
1490
+ "modelPicker.chip.title.available": "\u6E20\u9053 {{channel}} \xB7 \u6A21\u578B {{name}}",
1491
+ "modelPicker.chip.title.unavailable": "\u6E20\u9053 {{channel}} \xB7 \u5F53\u524D\u4E0D\u53EF\u7528",
1492
+ "jr.confirmDialog.cancel": "\u53D6\u6D88",
1493
+ "jr.confirmDialog.confirm": "\u786E\u8BA4",
1494
+ "jr.confirmDialog.loading": "\u5904\u7406\u4E2D"
1495
+ };
1496
+ var enUS = {
1497
+ "header.title": "AI Assistant",
1498
+ "header.icon": "",
1499
+ "status.connecting": "Connecting...",
1500
+ "status.running": "Running...",
1501
+ "status.compressing": "Compressing context...",
1502
+ "status.error": "Connection error",
1503
+ "status.idle": "Idle",
1504
+ "empty.waiting": "Waiting for conversation...",
1505
+ "empty.icon": "",
1506
+ "round.separator": "Previous round",
1507
+ "round.status.running": "Running",
1508
+ "round.status.completed": "Completed",
1509
+ "round.status.error": "Failed",
1510
+ "round.noMessage": "(no message)",
1511
+ "footer.attribution": "",
1512
+ "selection.ask": "Ask",
1513
+ "viewer.loading": "Loading...",
1514
+ "viewer.error": "Failed to load file content",
1515
+ "viewer.back": "\u2190 Back",
1516
+ "viewer.defaultTitle": "File Preview",
1517
+ "viewer.copyFull": "Copy full",
1518
+ "viewer.copyFullTitle": "Copy full content to clipboard",
1519
+ "viewer.referenceFile": "Reference file",
1520
+ "viewer.referenceFileTitle": "Reference this file",
1521
+ "viewer.referencePage": "Reference page",
1522
+ "viewer.referencePageTitle": "Reference this page in chat",
1523
+ "viewer.download": "Download",
1524
+ "viewer.fullscreen": "Fullscreen (\u2318L)",
1525
+ "viewer.fullscreenExit": "Exit fullscreen",
1526
+ "viewer.close": "Close",
1527
+ "viewer.unknownType": "Unknown type",
1528
+ "viewer.iframeHint": 'iframe content cannot be selected directly. Use the "Reference file" button above.',
1529
+ "viewer.copySnippet": "Copy snippet",
1530
+ "viewer.loadingPdf": "Loading PDF viewer...",
1531
+ "viewer.pdfPages": "{{count}} pages",
1532
+ "viewer.loadingKicad": "Loading KiCad viewer...",
1533
+ "viewer.loading3d": "Loading 3D viewer...",
1534
+ "viewer.loadingStep": "Loading STEP viewer...",
1535
+ "viewer.gerberTitle": "DFX Copilot \u2014 Gerber preview",
1536
+ "viewer.gerberBlobWarning": "DFX Copilot must fetch the file from a public URL. Local blob/data URLs cannot be used inside a cross-origin iframe. Return content_url from getResourceContent or implement getResourceUrl with an HTTPS presigned link.",
1537
+ "viewer.gerberNoHttpUrl": "The resource URL is not http(s); it cannot be passed to DFX Copilot. Use a direct or presigned URL.",
1538
+ "viewer.pdfPreview": "PDF Preview",
1539
+ "viewer.htmlPreview": "HTML Preview",
1540
+ "viewer.htmlProjectLoading": "Loading HTML project files\u2026",
1541
+ "viewer.htmlProjectNoEntry": "HTML project is missing an entry file (e.g. index.html); cannot render",
1542
+ "viewer.htmlProjectSizeLimit": "HTML project exceeds size limit; only the entry file is rendered",
1543
+ "viewer.htmlStrategyForcedInlineWarning": "ESM modules detected, but inline strategy is forced; imports may fail",
1544
+ "viewer.htmlStrategyFallbackCspWarning": "Host CSP blocks blob: URLs; automatically falling back to inline strategy",
1545
+ "viewer.copyFullKicadTitle": "Copy full KiCad source to clipboard and reference",
1546
+ "viewer.zoomIn": "Zoom in",
1547
+ "viewer.zoomOut": "Zoom out",
1548
+ "viewer.zoomReset": "Reset",
1549
+ "viewer.loadingWord": "Loading Word viewer...",
1550
+ "viewer.loadingExcel": "Loading Excel viewer...",
1551
+ "viewer.loadingPowerPoint": "Loading PowerPoint viewer...",
1552
+ "viewer.pptPrev": "\u2039 Prev",
1553
+ "viewer.pptNext": "Next \u203A",
1554
+ "viewer.pptSlide": "Slide",
1555
+ "viewer.pptThumbnails": "Thumbnails",
1556
+ "viewer.excelRows": "rows",
1557
+ "viewer.excelColumns": "columns",
1558
+ "childAgent.status.running": "Running",
1559
+ "childAgent.status.completed": "Completed",
1560
+ "hitl.form.defaultTitle": "Please fill the form",
1561
+ "hitl.wait.default": "Waiting for user input...",
1562
+ "todo.completed.count": "{{completed}}/{{total}} completed",
1563
+ "todo.blocked.count": "{{count}} blocked",
1564
+ "todo.more": "+ {{count}} more",
1565
+ "todo.header.done": "Done",
1566
+ "tool.phase.generating": "Generating",
1567
+ "tool.phase.executing": "Executing",
1568
+ "tool.phase.complete": "Complete",
1569
+ "tool.phase.error": "Failed",
1570
+ "tool.executing": "Execute tool: {{name}}",
1571
+ "tool.mcp.running": "Running",
1572
+ "tool.mcp.success": "Complete",
1573
+ "tool.mcp.error": "Failed",
1574
+ "form.placeholder.select": "Please select",
1575
+ "form.required.default": "This field is required",
1576
+ "form.submit.submit": "Submit",
1577
+ "form.submit.submitting": "Submitting...",
1578
+ "form.requestId": "Request ID: ",
1579
+ "pinned.label": "Pinned",
1580
+ "plan.title": "Execution Plan",
1581
+ "plan.step": "Step {{index}}",
1582
+ "thinking.inProgress": "Thinking...",
1583
+ "thinking.completed": "Thinking completed",
1584
+ "split.unreadCount": "{{count}} new messages",
1585
+ "split.askQuestion": "Ask (\u2318/)",
1586
+ "split.exitFullscreen": "Exit fullscreen (Esc)",
1587
+ "context.inputPlaceholder": "Ask here...",
1588
+ "context.inputPlaceholderWithFile": "Ask about {{fileName}}...",
1589
+ "context.send": "Send",
1590
+ "context.removeReference": "Remove reference",
1591
+ "split.home": "Main Chat",
1592
+ "split.workspace": "Workspace",
1593
+ "split.annotation": "Annotations",
1594
+ "split.tabClose": "Close tab",
1595
+ "split.tabNew": "New tab",
1596
+ "workspace.title": "Workspace",
1597
+ "workspace.searchPlaceholder": "Search files...",
1598
+ "workspace.empty": "No files yet",
1599
+ "workspace.downloadAll": "Download all files as zip",
1600
+ "workspace.recent": "Recent changes",
1601
+ "workspace.open": "Open",
1602
+ "workspace.openInNewTab": "Open in new tab",
1603
+ "workspace.download": "Download",
1604
+ "workspace.copyPath": "Copy path",
1605
+ "workspace.expandAll": "Expand all",
1606
+ "workspace.collapseAll": "Collapse all",
1607
+ "annotation.title": "Annotations",
1608
+ "annotation.empty": "No annotations",
1609
+ "annotation.fileLevelTitle": "File Conversation",
1610
+ "annotation.fileLevelPlaceholder": "Ask about this file...",
1611
+ "annotation.anchoredPlaceholder": "Ask about selection...",
1612
+ "annotation.inlineInputPlaceholder": "Ask about this...",
1613
+ "annotation.replyPlaceholder": "Follow up...",
1614
+ "annotation.anchorLabel": "Anchor: {{text}}",
1615
+ "annotation.close": "Close",
1616
+ "annotation.fabLabel": "File annotation",
1617
+ "annotation.fabHeader": "{{fileName}} \xB7 File Conversation",
1618
+ "annotation.messageCount": "{{count}} messages",
1619
+ "annotation.anchorInvalid": "Anchor invalidated",
1620
+ "annotation.errorRetry": "Send failed, click to retry",
1621
+ "annotation.queuedHint": "Queued, please wait...",
1622
+ "annotation.selectionLabel": "Selected text",
1623
+ "agentControl.pause": "Pause",
1624
+ "agentControl.resume": "Resume",
1625
+ "agentControl.stop": "Stop",
1626
+ "agentControl.paused": "Paused",
1627
+ "agentControl.groupTitle": "Agent Group",
1628
+ "aria.fileNavigation": "File navigation",
1629
+ "kicad.loadFailed": "KiCanvas load failed, switched to source view",
1630
+ "kicad.urlNotReady": "Resource URL not ready, showing source",
1631
+ "kicad.loadingEngine": "Loading KiCanvas engine...",
1632
+ "kicad.sidebarTitle": "KiCanvas sidebar: properties, symbol/footprint list, docs",
1633
+ "kicad.sidebarPcb": "PCB: view properties, footprint list",
1634
+ "kicad.sidebarSch": "SCH: view symbol/sub-sheet properties",
1635
+ "kicad.sidebarGeneric": "View properties",
1636
+ "kicad.viewVisual": "Visual",
1637
+ "kicad.viewSource": "Source",
1638
+ "provenance.filter.type.agent": "Agent",
1639
+ "provenance.filter.type.action": "Action",
1640
+ "provenance.filter.type.file": "File",
1641
+ "provenance.filter.type.task": "Task",
1642
+ "provenance.filter.type.reasoning": "Reasoning",
1643
+ "provenance.filter.depth": "Depth:",
1644
+ "provenance.toolbar.zoomToFit": "Zoom to fit",
1645
+ "provenance.toolbar.resetCamera": "Reset camera",
1646
+ "provenance.toolbar.refresh": "Refresh",
1647
+ "provenance.legend.reasoning": "Reasoning",
1648
+ "provenance.legend.action": "Action",
1649
+ "provenance.legend.file": "File",
1650
+ "provenance.legend.task": "Task",
1651
+ "provenance.legend.references": "References",
1652
+ "provenance.legend.edges": "Edges: ",
1653
+ "provenance.legend.depth": "Depth: ",
1654
+ "provenance.detail.title": "Node details",
1655
+ "provenance.detail.noSelection": "No node selected",
1656
+ "provenance.detail.label.name": "Name",
1657
+ "provenance.detail.label.id": "ID",
1658
+ "provenance.detail.label.timestamp": "Timestamp",
1659
+ "provenance.detail.label.agentId": "Agent ID",
1660
+ "provenance.detail.label.instanceId": "Instance ID",
1661
+ "provenance.detail.label.level": "Level",
1662
+ "provenance.detail.label.status": "Status",
1663
+ "provenance.detail.label.tool": "Tool",
1664
+ "provenance.detail.label.purpose": "Purpose",
1665
+ "provenance.detail.label.duration": "Duration",
1666
+ "provenance.detail.label.path": "Path",
1667
+ "provenance.detail.label.operation": "Operation",
1668
+ "provenance.detail.label.taskId": "Task ID",
1669
+ "provenance.detail.label.description": "Description",
1670
+ "provenance.detail.label.model": "Model",
1671
+ "provenance.detail.label.tokenCount": "Token count",
1672
+ "provenance.detail.label.reasoningPreview": "Reasoning preview",
1673
+ "provenance.detail.relatedEdges": "Related edges ({{count}})",
1674
+ "provenance.page.noSessionHint": "Please specify session via URL: ?session_id=NNN",
1675
+ "provenance.page.loading": "Loading provenance graph...",
1676
+ "provenance.page.emptyGraph": "No graph data for this session",
1677
+ "provenance.drawer.emptyGraph": "No graph data",
1678
+ "provenance.graph.edgeType.references": "References",
1679
+ "toolResult.label": "Result",
1680
+ "toolResult.expandAll": "Expand all ({{count}} lines)",
1681
+ "toolResult.searchSummary": "Search results \xB7 {{count}}",
1682
+ "toolResult.scrapeSummary": "Scrape result \xB7 {{title}}",
1683
+ "toolResult.more": "+{{count}} more",
1684
+ "plan.status.active": "Running",
1685
+ "pinned.noMessage": "(no message content)",
1686
+ "viewer.fallback.unknownType": "Unknown type",
1687
+ "viewer.fallback.download": "Download file",
1688
+ "fileSize.B": "{{size}} B",
1689
+ "fileSize.KB": "{{size}} KB",
1690
+ "fileSize.MB": "{{size}} MB",
1691
+ "thinking.title": "Thinking",
1692
+ "thinking.step": "Step {{step}}",
1693
+ "viewer.stepHint": "Drag to rotate, scroll to zoom, right-click to pan",
1694
+ "viewer.threeHint": "Drag to rotate, scroll to zoom, right-click to pan",
1695
+ "viewer.3d.wireframe": "Wireframe",
1696
+ "viewer.3d.resetView": "Reset view",
1697
+ "reference.header": "[Reference: {{fileName}}]",
1698
+ "history.noMessage": "(history message)",
1699
+ "agent.defaultName": "Assistant",
1700
+ "error.unknown": "Unknown error",
1701
+ "locale": "en-US",
1702
+ "skill.inlineLabel": "First check and use the {{name}} skill to solve: ",
1703
+ "skill.empty": "No skills available",
1704
+ "skill.searchPlaceholder": "Search skills...",
1705
+ "skill.removeLabel": "Remove skill",
1706
+ "skill.loading": "Loading...",
1707
+ "skill.loadError": "Failed to load skills",
1708
+ "skill.loadMore": "Load more",
1709
+ "skill.selectorLabel": "Skill selector",
1710
+ "pool.idle": "Idle",
1711
+ "pool.collaborating": "{{count}} working",
1712
+ "pool.awaiting": "{{count}} awaiting human",
1713
+ "pool.title": "Agent Pool",
1714
+ "pool.empty": "No active agents",
1715
+ "pool.state.running": "Running",
1716
+ "pool.state.paused": "Awaiting human",
1717
+ "pool.state.completed": "Completed",
1718
+ "pool.state.lost": "Lost",
1719
+ "pool.state.unknown": "Unknown",
1720
+ "input.placeholder": "Type a message, / for skills",
1721
+ "input.placeholderLoading": "Waiting for response\u2026",
1722
+ "discussion.title": "Discussions",
1723
+ "discussion.empty": "No discussions",
1724
+ "discussion.active": "Active",
1725
+ "discussion.resolved": "Resolved",
1726
+ "discussion.archived": "Archived",
1727
+ "round.foreign.label": "Conversation from another tab",
1728
+ "round.foreign.unread": "{{count}} new messages",
1729
+ "round.foreign.expand": "Click to expand",
1730
+ "sidebar.mainChat": "Main chat",
1731
+ "sidebar.chat": "Chat",
1732
+ "sidebar.fileQA": "File Q&A",
1733
+ "sidebar.selectionQA": "Selection Q&A",
1734
+ "sessionList.title": "Sessions",
1735
+ "sessionList.newSession": "+ New chat",
1736
+ "sessionList.logout": "Logout",
1737
+ "sessionList.loading": "Loading...",
1738
+ "sessionList.empty": "No sessions yet",
1739
+ "sessionList.unsupported": "Adapter does not implement listSessions",
1740
+ "sessionList.untitled": "Untitled",
1741
+ "sessionList.deleteTitle": "Delete session",
1742
+ "sessionList.deleteConfirm": "Delete this session?",
1743
+ "sessionList.prevPage": "\u2190",
1744
+ "sessionList.nextPage": "\u2192",
1745
+ "sessionList.pageInfo": "Page {page} / {totalPages}",
1746
+ "modelPicker.menu.head": "Model for this turn",
1747
+ "modelPicker.menu.aria": "Choose the model for this turn",
1748
+ "modelPicker.auto.title": "Default (follow agent)",
1749
+ "modelPicker.auto.hint.knownChannel": "Agent default: {{name}} \xB7 {{channel}}",
1750
+ "modelPicker.auto.hint.knownBasename": "Agent default: {{name}}",
1751
+ "modelPicker.auto.hint.fallback": "Use the agent's registered default model; sub-agents follow automatically",
1752
+ "modelPicker.row.hint.channelMulti": "{{available}} of {{total}} channels available",
1753
+ "modelPicker.row.hint.channelSingle": "Channel: {{channel}}",
1754
+ "modelPicker.row.hint.versionMulti": "{{count}} versions available",
1755
+ "modelPicker.fallback.placeholder": "Default model",
1756
+ "modelPicker.inert.title": "Model picker is unavailable",
1757
+ "modelPicker.guestLocked.label": "Default model \xB7 sign in to choose",
1758
+ "modelPicker.guestLocked.title": "Signed-in users can switch among multiple models. As a guest you start with the default \u2014 sign in any time to swap.",
1759
+ "modelPicker.loadingList": "Loading model list\u2026",
1760
+ "modelPicker.trigger.title.stale": "{{name}} (no longer listed \u2014 will still be attempted on send)",
1761
+ "modelPicker.trigger.title.agentDefault.withChannel": "Agent default: {{name}} \xB7 {{channel}} (sent value follows the agent)",
1762
+ "modelPicker.trigger.title.agentDefault": "Agent default: {{name}} (sent value follows the agent)",
1763
+ "modelPicker.trigger.title.current": "Current model: {{name}}",
1764
+ "modelPicker.row.title.pickDefault": "Use default channel ({{hint}})",
1765
+ "modelPicker.row.title.pick": "Use {{name}}",
1766
+ "modelPicker.chip.aria": "{{title}} channels",
1767
+ "modelPicker.chip.title.available": "Channel {{channel}} \xB7 model {{name}}",
1768
+ "modelPicker.chip.title.unavailable": "Channel {{channel}} \xB7 currently unavailable",
1769
+ "jr.confirmDialog.cancel": "Cancel",
1770
+ "jr.confirmDialog.confirm": "Confirm",
1771
+ "jr.confirmDialog.loading": "Processing"
1772
+ };
1773
+ var builtinMessages = {
1774
+ "zh-CN": zhCN,
1775
+ "en-US": enUS
1776
+ };
1777
+ function resolveMessages(locale = "zh-CN", overrides) {
1778
+ const base = builtinMessages[locale] ?? zhCN;
1779
+ if (!overrides) return base;
1780
+ return { ...base, ...overrides };
1781
+ }
1782
+ function interpolate(template, params) {
1783
+ if (!params) return template;
1784
+ return template.replace(
1785
+ /\{\{(\w+)\}\}/g,
1786
+ (_, key) => String(params[key] ?? "")
1787
+ );
1788
+ }
1789
+
1790
+ // src/i18n/context.ts
1791
+ var I18nContext = (0, import_react3.createContext)(zhCN);
1792
+ function useChatWidgetI18n() {
1793
+ const messages = (0, import_react3.useContext)(I18nContext);
1794
+ const locale = messages["locale"] || "zh-CN";
1795
+ const t = (0, import_react3.useCallback)(
1796
+ (key, params) => {
1797
+ const template = messages[key] ?? key;
1798
+ return interpolate(template, params);
1799
+ },
1800
+ [messages]
1801
+ );
1802
+ return { messages, t, locale };
1803
+ }
1804
+
1805
+ // src/provenance/components/GraphStatsLegend.tsx
1806
+ var import_jsx_runtime2 = require("react/jsx-runtime");
1807
+ var LEGEND_LABEL_KEYS = {
1808
+ reasoning: "provenance.legend.reasoning",
1809
+ action: "provenance.legend.action",
1810
+ file: "provenance.legend.file",
1811
+ task: "provenance.legend.task"
1812
+ };
1813
+ var LEGEND_TYPES = ["reasoning", "action", "file", "task"];
1814
+ var statKey = (type) => {
1815
+ const map = {
1816
+ agent: "agent_count",
1817
+ action: "action_count",
1818
+ file: "file_count",
1819
+ task: "task_count",
1820
+ reasoning: "reasoning_count"
1821
+ };
1822
+ return map[type];
1823
+ };
1824
+ var GraphStatsLegendInner = ({
1825
+ stats,
1826
+ edgeCount
1827
+ }) => {
1828
+ const { t } = useChatWidgetI18n();
1829
+ const legendItems = (0, import_react4.useMemo)(
1830
+ () => LEGEND_TYPES.map((type) => ({ type, label: t(LEGEND_LABEL_KEYS[type]) })),
1831
+ [t]
1832
+ );
1833
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1834
+ "div",
1835
+ {
1836
+ style: {
1837
+ position: "absolute",
1838
+ left: 16,
1839
+ bottom: 16,
1840
+ zIndex: 10,
1841
+ background: "rgba(255,255,255,0.92)",
1842
+ backdropFilter: "blur(8px)",
1843
+ padding: "10px 14px",
1844
+ borderRadius: 10,
1845
+ boxShadow: "0 1px 6px rgba(0,0,0,0.08)",
1846
+ fontSize: 12,
1847
+ lineHeight: 1.8
1848
+ },
1849
+ children: /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_antd.Space, { orientation: "vertical", size: 2, children: [
1850
+ legendItems.map(({ type, label }) => {
1851
+ const count = stats[statKey(type)];
1852
+ if (count === 0) return null;
1853
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: { display: "flex", alignItems: "center", gap: 6 }, children: [
1854
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_antd.Badge, { color: NODE_COLORS[type] }),
1855
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { style: { color: "#555" }, children: label }),
1856
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { style: { fontWeight: 600, color: "#333" }, children: count })
1857
+ ] }, type);
1858
+ }),
1859
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: { display: "flex", alignItems: "center", gap: 6 }, children: [
1860
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1861
+ "div",
1862
+ {
1863
+ style: {
1864
+ width: 14,
1865
+ height: 0,
1866
+ borderTop: `2px dashed ${EDGE_COLORS.references}`
1867
+ }
1868
+ }
1869
+ ),
1870
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { style: { color: "#555" }, children: t("provenance.legend.references") })
1871
+ ] }),
1872
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: { borderTop: "1px solid #eee", paddingTop: 4, marginTop: 2 }, children: [
1873
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { style: { color: "#999" }, children: t("provenance.legend.edges") }),
1874
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { style: { fontWeight: 600, color: "#333" }, children: edgeCount }),
1875
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { style: { color: "#999", marginLeft: 8 }, children: [
1876
+ t("provenance.legend.depth"),
1877
+ stats.max_depth
1878
+ ] })
1879
+ ] })
1880
+ ] })
1881
+ }
1882
+ );
1883
+ };
1884
+ var GraphStatsLegend = import_react4.default.memo(GraphStatsLegendInner);
1885
+
1886
+ // src/provenance/components/NodeDetailPanel.tsx
1887
+ var import_react5 = __toESM(require("react"), 1);
1888
+ var import_antd2 = require("antd");
1889
+ var import_jsx_runtime3 = require("react/jsx-runtime");
1890
+ var { Text, Paragraph } = import_antd2.Typography;
1891
+ var TYPE_LABEL_KEYS = {
1892
+ agent: "provenance.filter.type.agent",
1893
+ action: "provenance.filter.type.action",
1894
+ file: "provenance.filter.type.file",
1895
+ task: "provenance.filter.type.task",
1896
+ reasoning: "provenance.filter.type.reasoning"
1897
+ };
1898
+ function findNode(graph, nodeId) {
1899
+ const all = [
1900
+ ...graph.nodes.agents,
1901
+ ...graph.nodes.actions,
1902
+ ...graph.nodes.files,
1903
+ ...graph.nodes.tasks,
1904
+ ...graph.nodes.reasonings
1905
+ ];
1906
+ return all.find((n) => n.id === nodeId) ?? null;
1907
+ }
1908
+ function formatTimestamp(ts) {
1909
+ return new Date(ts).toLocaleString("zh-CN");
1910
+ }
1911
+ function formatDuration(ms) {
1912
+ if (ms == null) return "-";
1913
+ if (ms < 1e3) return `${ms}ms`;
1914
+ return `${(ms / 1e3).toFixed(1)}s`;
1915
+ }
1916
+ var NodeDetailPanelInner = ({
1917
+ open,
1918
+ nodeId,
1919
+ graph,
1920
+ onClose
1921
+ }) => {
1922
+ const { t } = useChatWidgetI18n();
1923
+ const node = (0, import_react5.useMemo)(() => nodeId ? findNode(graph, nodeId) : null, [graph, nodeId]);
1924
+ const relatedEdges = (0, import_react5.useMemo)(() => {
1925
+ if (!nodeId) return [];
1926
+ return graph.edges.filter((e) => e.source === nodeId || e.target === nodeId);
1927
+ }, [graph.edges, nodeId]);
1928
+ if (!node) {
1929
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_antd2.Drawer, { title: t("provenance.detail.title"), open, onClose, width: 360, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Text, { type: "secondary", children: t("provenance.detail.noSelection") }) });
1930
+ }
1931
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
1932
+ import_antd2.Drawer,
1933
+ {
1934
+ title: /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_antd2.Space, { children: [
1935
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_antd2.Badge, { color: NODE_COLORS[node.type] }),
1936
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { children: t(TYPE_LABEL_KEYS[node.type]) }),
1937
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_antd2.Tag, { children: node.type })
1938
+ ] }),
1939
+ open,
1940
+ onClose,
1941
+ width: 380,
1942
+ destroyOnHidden: true,
1943
+ children: [
1944
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_antd2.Descriptions, { column: 1, size: "small", bordered: true, children: [
1945
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_antd2.Descriptions.Item, { label: t("provenance.detail.label.name"), children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Text, { strong: true, children: node.label }) }),
1946
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_antd2.Descriptions.Item, { label: t("provenance.detail.label.id"), children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Text, { code: true, copyable: true, children: node.id }) }),
1947
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_antd2.Descriptions.Item, { label: t("provenance.detail.label.timestamp"), children: formatTimestamp(node.timestamp) }),
1948
+ node.type === "agent" && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_jsx_runtime3.Fragment, { children: [
1949
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_antd2.Descriptions.Item, { label: t("provenance.detail.label.agentId"), children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Text, { code: true, children: node.agent_id }) }),
1950
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_antd2.Descriptions.Item, { label: t("provenance.detail.label.instanceId"), children: node.agent_instance_id }),
1951
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_antd2.Descriptions.Item, { label: t("provenance.detail.label.level"), children: node.level }),
1952
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_antd2.Descriptions.Item, { label: t("provenance.detail.label.status"), children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_antd2.Tag, { color: node.status === "running" ? "processing" : node.status === "completed" ? "success" : "error", children: node.status ?? "unknown" }) })
1953
+ ] }),
1954
+ node.type === "action" && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_jsx_runtime3.Fragment, { children: [
1955
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_antd2.Descriptions.Item, { label: t("provenance.detail.label.tool"), children: node.tool_name }),
1956
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_antd2.Descriptions.Item, { label: t("provenance.detail.label.purpose"), children: node.task_purpose || "-" }),
1957
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_antd2.Descriptions.Item, { label: t("provenance.detail.label.status"), children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_antd2.Tag, { color: node.status === "success" ? "success" : node.status === "error" ? "error" : "processing", children: node.status }) }),
1958
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_antd2.Descriptions.Item, { label: t("provenance.detail.label.duration"), children: formatDuration(node.duration_ms) })
1959
+ ] }),
1960
+ node.type === "file" && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_jsx_runtime3.Fragment, { children: [
1961
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_antd2.Descriptions.Item, { label: t("provenance.detail.label.path"), children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Text, { code: true, children: node.git_path }) }),
1962
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_antd2.Descriptions.Item, { label: t("provenance.detail.label.operation"), children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_antd2.Tag, { color: node.operation === "create" ? "green" : node.operation === "delete" ? "red" : "blue", children: node.operation }) })
1963
+ ] }),
1964
+ node.type === "task" && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_jsx_runtime3.Fragment, { children: [
1965
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_antd2.Descriptions.Item, { label: t("provenance.detail.label.taskId"), children: node.task_id }),
1966
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_antd2.Descriptions.Item, { label: t("provenance.detail.label.status"), children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_antd2.Tag, { children: node.status }) }),
1967
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_antd2.Descriptions.Item, { label: t("provenance.detail.label.description"), children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Paragraph, { ellipsis: { rows: 3 }, children: node.description }) })
1968
+ ] }),
1969
+ node.type === "reasoning" && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_jsx_runtime3.Fragment, { children: [
1970
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_antd2.Descriptions.Item, { label: t("provenance.detail.label.model"), children: node.model || "-" }),
1971
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_antd2.Descriptions.Item, { label: t("provenance.detail.label.tokenCount"), children: node.token_count ?? "-" }),
1972
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_antd2.Descriptions.Item, { label: t("provenance.detail.label.duration"), children: formatDuration(node.duration_ms) }),
1973
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_antd2.Descriptions.Item, { label: t("provenance.detail.label.reasoningPreview"), children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Paragraph, { ellipsis: { rows: 5 }, children: node.content_preview || "(empty)" }) })
1974
+ ] })
1975
+ ] }),
1976
+ relatedEdges.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_jsx_runtime3.Fragment, { children: [
1977
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Text, { strong: true, style: { display: "block", marginTop: 16, marginBottom: 8 }, children: t("provenance.detail.relatedEdges", { count: relatedEdges.length }) }),
1978
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_antd2.Space, { orientation: "vertical", size: 4, style: { width: "100%" }, children: relatedEdges.slice(0, 20).map((e, i) => /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: { fontSize: 12, color: "#666" }, children: [
1979
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_antd2.Tag, { color: "default", style: { fontSize: 11 }, children: e.type }),
1980
+ e.source === nodeId ? `\u2192 ${e.target}` : `\u2190 ${e.source}`
1981
+ ] }, i)) })
1982
+ ] })
1983
+ ]
1984
+ }
1985
+ );
1986
+ };
1987
+ var NodeDetailPanel = import_react5.default.memo(NodeDetailPanelInner);
1988
+
1989
+ // src/provenance/ProvenanceGraphDrawerContent.tsx
1990
+ var import_jsx_runtime4 = require("react/jsx-runtime");
1991
+ function useContainerSize(ref) {
1992
+ const [size, setSize] = import_react6.default.useState({ width: 600, height: 500 });
1993
+ import_react6.default.useEffect(() => {
1994
+ if (!ref.current) return;
1995
+ const observer = new ResizeObserver((entries) => {
1996
+ for (const entry of entries) {
1997
+ const { width, height } = entry.contentRect;
1998
+ setSize({ width: Math.floor(width), height: Math.floor(height) });
1999
+ }
2000
+ });
2001
+ observer.observe(ref.current);
2002
+ return () => observer.disconnect();
2003
+ }, [ref]);
2004
+ return size;
2005
+ }
2006
+ var ProvenanceGraphDrawerContent = ({
2007
+ sessionId,
2008
+ onProcessEventRef
2009
+ }) => {
2010
+ const { t } = useChatWidgetI18n();
2011
+ const containerRef = (0, import_react6.useRef)(null);
2012
+ const { width, height } = useContainerSize(containerRef);
2013
+ const { graph, loading, error, processEvent } = useProvenanceGraph({
2014
+ sessionId,
2015
+ enabled: true
2016
+ });
2017
+ (0, import_react6.useEffect)(() => {
2018
+ if (onProcessEventRef) {
2019
+ onProcessEventRef.current = processEvent;
2020
+ }
2021
+ return () => {
2022
+ if (onProcessEventRef) {
2023
+ onProcessEventRef.current = null;
2024
+ }
2025
+ };
2026
+ }, [onProcessEventRef, processEvent]);
2027
+ const [selectedNodeId, setSelectedNodeId] = (0, import_react6.useState)(null);
2028
+ const [detailOpen, setDetailOpen] = (0, import_react6.useState)(false);
2029
+ const handleNodeClick = (0, import_react6.useCallback)((nodeId, _nodeType) => {
2030
+ setSelectedNodeId(nodeId);
2031
+ setDetailOpen(true);
2032
+ }, []);
2033
+ const handleBackgroundClick = (0, import_react6.useCallback)(() => {
2034
+ setSelectedNodeId(null);
2035
+ setDetailOpen(false);
2036
+ }, []);
2037
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
2038
+ "div",
2039
+ {
2040
+ ref: containerRef,
2041
+ style: { width: "100%", height: "100%", minHeight: 400, position: "relative" },
2042
+ children: [
2043
+ loading && !graph && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "ycw-provenance-loading", children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_antd3.Spin, { size: "large" }) }),
2044
+ error && !graph && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "ycw-provenance-empty", children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { style: { color: "#ff4d4f" }, children: error.message }) }),
2045
+ graph && graph.node_count === 0 && !loading && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_antd3.Empty, { description: t("provenance.drawer.emptyGraph"), style: { paddingTop: 80 } }),
2046
+ graph && graph.node_count > 0 && /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_jsx_runtime4.Fragment, { children: [
2047
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
2048
+ ProvenanceGraph3D,
2049
+ {
2050
+ graph,
2051
+ width,
2052
+ height,
2053
+ selectedNodeId,
2054
+ onNodeClick: handleNodeClick,
2055
+ onBackgroundClick: handleBackgroundClick
2056
+ }
2057
+ ),
2058
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(GraphStatsLegend, { stats: graph.stats, edgeCount: graph.edges.length })
2059
+ ] }),
2060
+ graph && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
2061
+ NodeDetailPanel,
2062
+ {
2063
+ open: detailOpen,
2064
+ nodeId: selectedNodeId,
2065
+ graph,
2066
+ onClose: () => {
2067
+ setDetailOpen(false);
2068
+ setSelectedNodeId(null);
2069
+ }
2070
+ }
2071
+ )
2072
+ ]
2073
+ }
2074
+ );
2075
+ };
2076
+ var ProvenanceGraphDrawerContent_default = ProvenanceGraphDrawerContent;
2077
+
2078
+ // src/provenance/ProvenanceI18nProvider.tsx
2079
+ var import_react7 = __toESM(require("react"), 1);
2080
+ var import_jsx_runtime5 = require("react/jsx-runtime");
2081
+ var ProvenanceI18nProvider = ({
2082
+ locale = "zh-CN",
2083
+ messages: overrides,
2084
+ children
2085
+ }) => {
2086
+ const resolved = import_react7.default.useMemo(
2087
+ () => resolveMessages(locale, overrides),
2088
+ [locale, overrides]
2089
+ );
2090
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(I18nContext.Provider, { value: resolved, children });
2091
+ };
2092
+
2093
+ // src/provenance/components/FilterBar.tsx
2094
+ var import_react8 = __toESM(require("react"), 1);
2095
+ var import_antd4 = require("antd");
2096
+ var import_jsx_runtime6 = require("react/jsx-runtime");
2097
+ var { Text: Text2 } = import_antd4.Typography;
2098
+ var ALL_TYPES = ["agent", "action", "file", "task", "reasoning"];
2099
+ var TYPE_LABEL_KEYS2 = {
2100
+ agent: "provenance.filter.type.agent",
2101
+ action: "provenance.filter.type.action",
2102
+ file: "provenance.filter.type.file",
2103
+ task: "provenance.filter.type.task",
2104
+ reasoning: "provenance.filter.type.reasoning"
2105
+ };
2106
+ var FilterBarInner = ({
2107
+ visibleTypes,
2108
+ onVisibleTypesChange,
2109
+ depth,
2110
+ onDepthChange,
2111
+ hasSelection
2112
+ }) => {
2113
+ const { t } = useChatWidgetI18n();
2114
+ const typeOptions = (0, import_react8.useMemo)(() => ALL_TYPES.map((tp) => ({
2115
+ label: /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_antd4.Space, { size: 4, children: [
2116
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_antd4.Badge, { color: NODE_COLORS[tp] }),
2117
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { children: t(TYPE_LABEL_KEYS2[tp]) })
2118
+ ] }),
2119
+ value: tp
2120
+ })), [t]);
2121
+ const handleTypeChange = (0, import_react8.useCallback)(
2122
+ (values) => {
2123
+ onVisibleTypesChange(new Set(values));
2124
+ },
2125
+ [onVisibleTypesChange]
2126
+ );
2127
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
2128
+ "div",
2129
+ {
2130
+ style: {
2131
+ display: "flex",
2132
+ alignItems: "center",
2133
+ gap: 16,
2134
+ padding: "8px 16px",
2135
+ background: "rgba(255,255,255,0.92)",
2136
+ backdropFilter: "blur(8px)",
2137
+ borderBottom: "1px solid #eee"
2138
+ },
2139
+ children: [
2140
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2141
+ import_antd4.Checkbox.Group,
2142
+ {
2143
+ options: typeOptions,
2144
+ value: Array.from(visibleTypes),
2145
+ onChange: handleTypeChange
2146
+ }
2147
+ ),
2148
+ hasSelection && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_antd4.Space, { size: 8, style: { marginLeft: "auto" }, children: [
2149
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(Text2, { type: "secondary", style: { fontSize: 12 }, children: t("provenance.filter.depth") }),
2150
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2151
+ import_antd4.Slider,
2152
+ {
2153
+ min: 1,
2154
+ max: 5,
2155
+ value: depth,
2156
+ onChange: onDepthChange,
2157
+ style: { width: 100 },
2158
+ tooltip: { open: false }
2159
+ }
2160
+ ),
2161
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(Text2, { style: { fontSize: 12, minWidth: 20 }, children: depth })
2162
+ ] })
2163
+ ]
2164
+ }
2165
+ );
2166
+ };
2167
+ var FilterBar = import_react8.default.memo(FilterBarInner);
2168
+
2169
+ // src/provenance/components/GraphToolbar.tsx
2170
+ var import_react9 = __toESM(require("react"), 1);
2171
+ var import_antd5 = require("antd");
2172
+ var import_icons = require("@ant-design/icons");
2173
+ var import_jsx_runtime7 = require("react/jsx-runtime");
2174
+ var GraphToolbarInner = ({
2175
+ onZoomToFit,
2176
+ onResetCamera,
2177
+ onRefresh,
2178
+ loading
2179
+ }) => {
2180
+ const { t } = useChatWidgetI18n();
2181
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
2182
+ "div",
2183
+ {
2184
+ style: {
2185
+ position: "absolute",
2186
+ right: 16,
2187
+ top: 16,
2188
+ zIndex: 10,
2189
+ display: "flex",
2190
+ flexDirection: "column",
2191
+ gap: 4
2192
+ },
2193
+ children: /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_antd5.Space, { orientation: "vertical", size: 4, children: [
2194
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_antd5.Tooltip, { title: t("provenance.toolbar.zoomToFit"), placement: "left", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
2195
+ import_antd5.Button,
2196
+ {
2197
+ type: "text",
2198
+ icon: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_icons.ExpandOutlined, {}),
2199
+ onClick: onZoomToFit,
2200
+ style: toolBtnStyle
2201
+ }
2202
+ ) }),
2203
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_antd5.Tooltip, { title: t("provenance.toolbar.resetCamera"), placement: "left", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
2204
+ import_antd5.Button,
2205
+ {
2206
+ type: "text",
2207
+ icon: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_icons.AimOutlined, {}),
2208
+ onClick: onResetCamera,
2209
+ style: toolBtnStyle
2210
+ }
2211
+ ) }),
2212
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_antd5.Tooltip, { title: t("provenance.toolbar.refresh"), placement: "left", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
2213
+ import_antd5.Button,
2214
+ {
2215
+ type: "text",
2216
+ icon: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_icons.ReloadOutlined, {}),
2217
+ onClick: onRefresh,
2218
+ loading,
2219
+ style: toolBtnStyle
2220
+ }
2221
+ ) })
2222
+ ] })
2223
+ }
2224
+ );
2225
+ };
2226
+ var toolBtnStyle = {
2227
+ background: "rgba(255,255,255,0.92)",
2228
+ backdropFilter: "blur(8px)",
2229
+ boxShadow: "0 1px 4px rgba(0,0,0,0.08)",
2230
+ borderRadius: 8,
2231
+ width: 36,
2232
+ height: 36
2233
+ };
2234
+ var GraphToolbar = import_react9.default.memo(GraphToolbarInner);
2235
+ // Annotate the CommonJS export names for ESM import in node:
2236
+ 0 && (module.exports = {
2237
+ FilterBar,
2238
+ GraphBuilder,
2239
+ GraphStatsLegend,
2240
+ GraphToolbar,
2241
+ NodeDetailPanel,
2242
+ ProvenanceGraph3D,
2243
+ ProvenanceGraphDrawerContent,
2244
+ ProvenanceI18nProvider,
2245
+ fetchProvenanceGraph,
2246
+ useProvenanceGraph
2247
+ });
2248
+ //# sourceMappingURL=index.cjs.map