chain-insights 0.3.4 → 0.3.6

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 (54) hide show
  1. package/README.md +28 -11
  2. package/dist/canvas-Cn-maEIh.mjs +203 -0
  3. package/dist/canvas-Cn-maEIh.mjs.map +1 -0
  4. package/dist/canvas-p-oKCMjc.cjs +251 -0
  5. package/dist/cases-Bz_9XKEw.cjs +19 -0
  6. package/dist/cases-TVcAifxu.mjs +16 -0
  7. package/dist/cases-TVcAifxu.mjs.map +1 -0
  8. package/dist/cli.cjs +74 -28
  9. package/dist/cli.mjs +74 -28
  10. package/dist/cli.mjs.map +1 -1
  11. package/dist/{data-extractor-DZUJu1Bz.mjs → data-extractor-B4nHw1wZ.mjs} +2 -2
  12. package/dist/{data-extractor-DZUJu1Bz.mjs.map → data-extractor-B4nHw1wZ.mjs.map} +1 -1
  13. package/dist/{data-extractor-Cavd7wHk.cjs → data-extractor-DS4rzy3M.cjs} +1 -1
  14. package/dist/{export-BqTCO9lP.mjs → export-CBhcJuZ6.mjs} +8 -205
  15. package/dist/export-CBhcJuZ6.mjs.map +1 -0
  16. package/dist/{export-DsXgtCwO.cjs → export-D4v4-6F4.cjs} +16 -214
  17. package/dist/index.cjs +1 -1
  18. package/dist/index.mjs +1 -1
  19. package/dist/{init-DLBL_nVG.mjs → init-CKQ6F07J.mjs} +22 -5
  20. package/dist/init-CKQ6F07J.mjs.map +1 -0
  21. package/dist/{init-zqbd7i-_.cjs → init-Dhw8F23z.cjs} +21 -4
  22. package/dist/mcp-proxy.cjs +20 -20
  23. package/dist/mcp-proxy.mjs +20 -20
  24. package/dist/mcp-proxy.mjs.map +1 -1
  25. package/dist/{public-tools-wJoAFDFa.mjs → public-tools-CyUZEz9B.mjs} +3 -3
  26. package/dist/{public-tools-wJoAFDFa.mjs.map → public-tools-CyUZEz9B.mjs.map} +1 -1
  27. package/dist/{public-tools-BvMb3H2P.cjs → public-tools-xfVNz9NE.cjs} +2 -2
  28. package/dist/{runner-BhZ4lnF1.cjs → runner-CVo41fjz.cjs} +2 -2
  29. package/dist/{runner-DIJSbkjc.mjs → runner-DWuSy1Se.mjs} +3 -3
  30. package/dist/{runner-DIJSbkjc.mjs.map → runner-DWuSy1Se.mjs.map} +1 -1
  31. package/dist/{selector-CF2o5gxN.mjs → selector-BvXM9jbe.mjs} +2 -2
  32. package/dist/{selector-CF2o5gxN.mjs.map → selector-BvXM9jbe.mjs.map} +1 -1
  33. package/dist/{selector-DfAMZEC9.cjs → selector-Dps_ZFxq.cjs} +1 -1
  34. package/dist/{store-CTtqQtaE.mjs → store-C2B_AssI.mjs} +2 -2
  35. package/dist/{store-CTtqQtaE.mjs.map → store-C2B_AssI.mjs.map} +1 -1
  36. package/dist/{store-CqPfs47P.cjs → store-CQhU8dz8.cjs} +0 -18
  37. package/dist/vault-B2y78Ypu.cjs +560 -0
  38. package/dist/vault-z35Dohdq.mjs +560 -0
  39. package/dist/vault-z35Dohdq.mjs.map +1 -0
  40. package/dist/{viz-Dqp3C5kb.cjs → viz-D1620cBX.cjs} +3 -3
  41. package/dist/{viz-5y24S5X1.mjs → viz-DB5XFG1z.mjs} +4 -4
  42. package/dist/{viz-5y24S5X1.mjs.map → viz-DB5XFG1z.mjs.map} +1 -1
  43. package/docs/graph-tools.md +24 -8
  44. package/docs/investigation-workspaces.md +36 -10
  45. package/docs/knowledge-exports.md +6 -2
  46. package/docs/mcp-proxy.md +29 -7
  47. package/docs/obsidian-vault.md +130 -0
  48. package/package.json +1 -1
  49. package/skills/chain-insights-developer-experience/SKILL.md +2 -2
  50. package/skills/chain-insights-investigation/SKILL.md +1 -1
  51. package/dist/cases-Cp9DUbEV.mjs +0 -6
  52. package/dist/cases-sTY5aXav.cjs +0 -9
  53. package/dist/export-BqTCO9lP.mjs.map +0 -1
  54. package/dist/init-DLBL_nVG.mjs.map +0 -1
@@ -0,0 +1,560 @@
1
+ import { n as extractGraphFromCase } from "./data-extractor-B4nHw1wZ.mjs";
2
+ import { t as parseFrontmatter } from "./frontmatter-D0ccQnUM.mjs";
3
+ import { n as workspaceOutputPaths } from "./output-root-BRhzhhXZ.mjs";
4
+ import { t as DossierStore } from "./dossier-Bjpcbcxa.mjs";
5
+ import { t as CaseStore } from "./store-C2B_AssI.mjs";
6
+ import { t as EvidenceStore } from "./evidence-D96PTzOQ.mjs";
7
+ import "./cases-TVcAifxu.mjs";
8
+ import { o as safeFilename, r as graphToCanvas } from "./canvas-Cn-maEIh.mjs";
9
+ import { t as normalizeGraphPayload } from "./graph-normalizer-CXP06jKh.mjs";
10
+ import { dirname, join, resolve } from "node:path";
11
+ import { access, mkdir, readFile, readdir, writeFile } from "node:fs/promises";
12
+ //#region src/vault/schema.ts
13
+ const VAULT_DIRS = [
14
+ ".obsidian",
15
+ "Canvases",
16
+ "Entities",
17
+ "Evidence",
18
+ "published"
19
+ ];
20
+ //#endregion
21
+ //#region src/vault/markdown.ts
22
+ function yamlString(value) {
23
+ return JSON.stringify(value);
24
+ }
25
+ function frontmatter(values) {
26
+ const lines = ["---"];
27
+ for (const [key, value] of Object.entries(values)) if (Array.isArray(value)) {
28
+ lines.push(`${key}:`);
29
+ for (const item of value) lines.push(` - ${yamlString(item)}`);
30
+ } else lines.push(`${key}: ${typeof value === "boolean" ? String(value) : yamlString(value)}`);
31
+ lines.push("---", "");
32
+ return lines.join("\n");
33
+ }
34
+ function renderLiveCaseNote(input) {
35
+ return frontmatter({
36
+ type: "chain-insights-case",
37
+ case_id: input.id,
38
+ status: input.status,
39
+ tags: input.tags,
40
+ contains_sensitive_data: true,
41
+ source_of_truth: `cases/${input.id}/`
42
+ }) + [
43
+ `# ${input.name}`,
44
+ "",
45
+ input.description,
46
+ "",
47
+ "## Live Workspace",
48
+ "",
49
+ `Status: ${input.status}`,
50
+ `Evidence files: ${input.evidenceCount}`,
51
+ `Evidence manifest verified: ${input.evidenceVerified ? "yes" : "no"}`,
52
+ `Entities: ${input.entityCount}`,
53
+ "",
54
+ "## Navigation",
55
+ "",
56
+ "- [[Agent Console]]",
57
+ "- [[Graph.canvas]]",
58
+ "- [[Cases]]",
59
+ `- [[cases/${input.id}/Evidence|Evidence]]`,
60
+ `- [[cases/${input.id}/Entities|Entities]]`,
61
+ "- [[Graphs]]",
62
+ ""
63
+ ].join("\n");
64
+ }
65
+ function renderCaseAgentConsole(input) {
66
+ return frontmatter({
67
+ type: "chain-insights-case-agent-console",
68
+ case_id: input.id,
69
+ contains_sensitive_data: true
70
+ }) + [
71
+ `# Agent Console: ${input.name}`,
72
+ "",
73
+ `Canonical case state: \`cases/${input.id}/\``,
74
+ "",
75
+ "## Case Files",
76
+ "",
77
+ "- [[Case]]",
78
+ "- [[Graph.canvas]]",
79
+ `- [[cases/${input.id}/Evidence|Evidence]]`,
80
+ `- [[cases/${input.id}/Entities|Entities]]`,
81
+ "",
82
+ "## Current Counts",
83
+ "",
84
+ `- Evidence files: ${input.evidenceCount}`,
85
+ `- Entities: ${input.entityCount}`,
86
+ `- Manifest verified: ${input.evidenceVerified ? "yes" : "no"}`,
87
+ ""
88
+ ].join("\n");
89
+ }
90
+ function renderCaseEvidenceIndex(input, evidence) {
91
+ return frontmatter({
92
+ type: "chain-insights-case-evidence-index",
93
+ case_id: input.id,
94
+ contains_sensitive_data: true
95
+ }) + [
96
+ `# Evidence: ${input.name}`,
97
+ "",
98
+ `Canonical evidence directory: \`cases/${input.id}/evidence/\``,
99
+ `Evidence files: ${input.evidenceCount}`,
100
+ `Manifest verified: ${input.evidenceVerified ? "yes" : "no"}`,
101
+ "",
102
+ "## Evidence Notes",
103
+ "",
104
+ ...evidence.length > 0 ? evidence.map((item) => `- [[${item.notePath.replace(/\.md$/, "")}|${item.id}]] (${item.source})`) : ["No evidence files recorded yet."],
105
+ ""
106
+ ].join("\n");
107
+ }
108
+ function renderEvidenceNote(input, caseId) {
109
+ return frontmatter({
110
+ type: "chain-insights-evidence",
111
+ case_id: caseId,
112
+ evidence_id: input.id,
113
+ source: input.source,
114
+ source_file: `cases/${caseId}/evidence/${input.filename}`,
115
+ contains_sensitive_data: true
116
+ }) + [
117
+ `# Evidence: ${input.source}`,
118
+ "",
119
+ `Evidence ID: \`${input.id}\``,
120
+ `Source file: \`cases/${caseId}/evidence/${input.filename}\``,
121
+ `Captured: ${input.timestamp || "unknown"}`,
122
+ `Query params: ${input.queryParams || "none"}`,
123
+ "",
124
+ "## Case",
125
+ "",
126
+ `- [[cases/${caseId}/Case|${caseId}]]`,
127
+ "",
128
+ "## Body",
129
+ "",
130
+ input.body.trim() || "No evidence body recorded.",
131
+ ""
132
+ ].join("\n");
133
+ }
134
+ function renderCaseEntityIndex(input, entities) {
135
+ return frontmatter({
136
+ type: "chain-insights-case-entity-index",
137
+ case_id: input.id,
138
+ contains_sensitive_data: true
139
+ }) + [
140
+ `# Entities: ${input.name}`,
141
+ "",
142
+ `Canonical dossier directory: \`cases/${input.id}/dossiers/\``,
143
+ `Entities: ${entities.length}`,
144
+ "",
145
+ "## Entity Notes",
146
+ "",
147
+ ...entities.length > 0 ? entities.map((item) => `- [[${item.notePath.replace(/\.md$/, "")}|${item.label}]] (${item.entityType})`) : ["No entities recorded yet."],
148
+ ""
149
+ ].join("\n");
150
+ }
151
+ function renderEntityNote(address, caseId, entityType) {
152
+ return frontmatter({
153
+ type: "chain-insights-entity",
154
+ case_id: caseId,
155
+ address,
156
+ entity_type: entityType,
157
+ contains_sensitive_data: true
158
+ }) + [
159
+ `# Entity: ${address}`,
160
+ "",
161
+ `Address: ${address}`,
162
+ `Type: ${entityType}`,
163
+ "",
164
+ "## Cases",
165
+ "",
166
+ `- [[cases/${caseId}/Case|${caseId}]]`,
167
+ ""
168
+ ].join("\n");
169
+ }
170
+ function renderVaultHome() {
171
+ return frontmatter({
172
+ type: "chain-insights-vault-home",
173
+ product: "Chain Insights",
174
+ contains_sensitive_data: true
175
+ }) + [
176
+ "# Chain Insights Vault",
177
+ "",
178
+ "Chain Insights is an AML investigation CLI and MCP proxy layered on GraphRAG MCP.",
179
+ "",
180
+ "## Start Here",
181
+ "",
182
+ "- [[Cases]]",
183
+ "- [[Entities]]",
184
+ "- [[Evidence]]",
185
+ "- [[Graphs]]",
186
+ "- [[Agent Console]]",
187
+ ""
188
+ ].join("\n");
189
+ }
190
+ function renderRootIndex(title, type, links) {
191
+ return frontmatter({
192
+ type,
193
+ product: "Chain Insights",
194
+ contains_sensitive_data: true
195
+ }) + [
196
+ `# ${title}`,
197
+ "",
198
+ ...links.map((link) => `- [[${link}]]`),
199
+ ""
200
+ ].join("\n");
201
+ }
202
+ function renderRootAgentConsole() {
203
+ return frontmatter({
204
+ type: "chain-insights-agent-console",
205
+ product: "Chain Insights",
206
+ contains_sensitive_data: true
207
+ }) + [
208
+ "# Agent Console",
209
+ "",
210
+ "Use Chain Insights case evidence as canonical local state and GraphRAG MCP for fresh graph facts.",
211
+ "",
212
+ "## Reading Order",
213
+ "",
214
+ "1. [[Home]]",
215
+ "2. [[Cases]]",
216
+ "3. [[Entities]]",
217
+ "4. [[Evidence]]",
218
+ "5. [[Graphs]]",
219
+ ""
220
+ ].join("\n");
221
+ }
222
+ function renderObsidianAppConfig() {
223
+ return JSON.stringify({
224
+ useMarkdownLinks: false,
225
+ newLinkFormat: "shortest",
226
+ alwaysUpdateLinks: true
227
+ }, null, 2) + "\n";
228
+ }
229
+ function renderObsidianGraphConfig() {
230
+ return JSON.stringify({
231
+ "collapse-filter": true,
232
+ search: "",
233
+ showTags: true,
234
+ showAttachments: true,
235
+ hideUnresolved: false,
236
+ showOrphans: true
237
+ }, null, 2) + "\n";
238
+ }
239
+ function renderObsidianTemplatesConfig() {
240
+ return JSON.stringify({
241
+ folder: "",
242
+ dateFormat: "YYYY-MM-DD",
243
+ timeFormat: "HH:mm"
244
+ }, null, 2) + "\n";
245
+ }
246
+ function renderVaultGitignore() {
247
+ return [
248
+ "# Chain Insights local runtime state",
249
+ ".chain-insights/runtime/",
250
+ "",
251
+ "# Obsidian local UI state",
252
+ ".obsidian/workspace.json",
253
+ ".obsidian/workspace-mobile.json",
254
+ ".obsidian/workspaces.json",
255
+ "",
256
+ "# Private export bundles are local by default",
257
+ "published/",
258
+ ""
259
+ ].join("\n");
260
+ }
261
+ //#endregion
262
+ //#region src/vault/index.ts
263
+ const VAULT_FILES = [
264
+ {
265
+ path: ".obsidian/app.json",
266
+ content: renderObsidianAppConfig()
267
+ },
268
+ {
269
+ path: ".obsidian/graph.json",
270
+ content: renderObsidianGraphConfig()
271
+ },
272
+ {
273
+ path: ".obsidian/templates.json",
274
+ content: renderObsidianTemplatesConfig()
275
+ },
276
+ {
277
+ path: ".gitignore",
278
+ content: renderVaultGitignore()
279
+ },
280
+ {
281
+ path: "Home.md",
282
+ content: renderVaultHome()
283
+ },
284
+ {
285
+ path: "Cases.md",
286
+ content: renderRootIndex("Cases", "chain-insights-vault-cases-index", ["Home", "Agent Console"])
287
+ },
288
+ {
289
+ path: "Entities.md",
290
+ content: renderRootIndex("Entities", "chain-insights-vault-entities-index", [
291
+ "Home",
292
+ "Cases",
293
+ "Evidence"
294
+ ])
295
+ },
296
+ {
297
+ path: "Evidence.md",
298
+ content: renderRootIndex("Evidence", "chain-insights-vault-evidence-index", [
299
+ "Home",
300
+ "Cases",
301
+ "Entities"
302
+ ])
303
+ },
304
+ {
305
+ path: "Graphs.md",
306
+ content: renderRootIndex("Graphs", "chain-insights-vault-graphs-index", [
307
+ "Home",
308
+ "Cases",
309
+ "Entities",
310
+ "Evidence"
311
+ ])
312
+ },
313
+ {
314
+ path: "Agent Console.md",
315
+ content: renderRootAgentConsole()
316
+ },
317
+ {
318
+ path: "Canvases/README.md",
319
+ content: renderRootIndex("Canvases", "chain-insights-vault-canvases-readme", ["Home", "Graphs"])
320
+ },
321
+ {
322
+ path: "Entities/README.md",
323
+ content: renderRootIndex("Entities Folder", "chain-insights-vault-entities-readme", ["Entities", "Cases"])
324
+ },
325
+ {
326
+ path: "Evidence/README.md",
327
+ content: renderRootIndex("Evidence Folder", "chain-insights-vault-evidence-readme", ["Evidence", "Cases"])
328
+ }
329
+ ];
330
+ async function scaffoldVault(options) {
331
+ const workspaceRoot = resolve(options.workspaceRoot);
332
+ const force = options.force === true;
333
+ if (!force) await assertNoVaultFileCollisions(workspaceRoot);
334
+ for (const dir of VAULT_DIRS) await mkdir(join(workspaceRoot, dir), { recursive: true });
335
+ const filesWritten = [];
336
+ for (const file of VAULT_FILES) {
337
+ await writeVaultFile(workspaceRoot, file, force);
338
+ filesWritten.push(file.path);
339
+ }
340
+ return {
341
+ workspaceRoot,
342
+ filesWritten
343
+ };
344
+ }
345
+ async function refreshCaseVault(options) {
346
+ const workspace = workspaceOutputPaths();
347
+ const force = options.force === true;
348
+ const [caseInfo, evidenceVerification, evidence, dossiers, graph] = await Promise.all([
349
+ CaseStore.get(options.caseId),
350
+ EvidenceStore.verifyManifest(options.caseId),
351
+ readCaseEvidence(options.caseId),
352
+ DossierStore.listSummaries(options.caseId),
353
+ loadLiveCaseGraph(options.caseId)
354
+ ]);
355
+ const caseSummary = {
356
+ id: caseInfo.id,
357
+ name: caseInfo.name,
358
+ status: caseInfo.status,
359
+ tags: caseInfo.tags,
360
+ description: caseInfo.description,
361
+ evidenceCount: evidenceVerification.count,
362
+ evidenceVerified: evidenceVerification.ok,
363
+ entityCount: dossiers.length
364
+ };
365
+ const canvasGraph = {
366
+ ...graph,
367
+ nodes: mergeDossierNodes(graph.nodes, dossiers)
368
+ };
369
+ const canvas = graphToCaseVaultCanvas(graphToCanvas(canvasGraph), caseInfo.id, canvasGraph.nodes);
370
+ const evidenceSummaries = evidence.map((evidenceDoc) => ({
371
+ ...evidenceDoc,
372
+ notePath: `Evidence/${safeFilename(`${evidenceDoc.filename.replace(/\.md$/, "")}-${caseInfo.id}`)}`
373
+ }));
374
+ const entityFiles = entityFilesForCase(caseInfo.id, canvasGraph.nodes, dossiers);
375
+ const entitySummaries = [...entityFiles.values()].map((entry) => entry.summary).sort((left, right) => left.label.localeCompare(right.label));
376
+ const files = [
377
+ {
378
+ path: `cases/${caseInfo.id}/Case.md`,
379
+ content: renderLiveCaseNote(caseSummary)
380
+ },
381
+ {
382
+ path: `cases/${caseInfo.id}/Agent Console.md`,
383
+ content: renderCaseAgentConsole(caseSummary)
384
+ },
385
+ {
386
+ path: `cases/${caseInfo.id}/Evidence.md`,
387
+ content: renderCaseEvidenceIndex(caseSummary, evidenceSummaries)
388
+ },
389
+ {
390
+ path: `cases/${caseInfo.id}/Entities.md`,
391
+ content: renderCaseEntityIndex(caseSummary, entitySummaries)
392
+ },
393
+ {
394
+ path: `cases/${caseInfo.id}/Graph.canvas`,
395
+ content: JSON.stringify(canvas, null, 2) + "\n"
396
+ },
397
+ ...evidenceSummaries.map((evidenceDoc) => ({
398
+ path: evidenceDoc.notePath,
399
+ content: renderEvidenceNote(evidenceDoc, caseInfo.id)
400
+ })),
401
+ ...[...entityFiles.values()].map((entry) => ({
402
+ path: entry.summary.notePath,
403
+ content: entry.content
404
+ }))
405
+ ];
406
+ if (!force) await assertNoFileCollisions(workspace.root, files);
407
+ const filesWritten = [];
408
+ for (const file of files) {
409
+ await writeVaultFile(workspace.root, file, force);
410
+ filesWritten.push(file.path);
411
+ }
412
+ return {
413
+ caseId: caseInfo.id,
414
+ filesWritten,
415
+ nextFile: `cases/${caseInfo.id}/Case.md`
416
+ };
417
+ }
418
+ async function assertNoVaultFileCollisions(workspaceRoot) {
419
+ await assertNoFileCollisions(workspaceRoot, VAULT_FILES);
420
+ }
421
+ async function assertNoFileCollisions(workspaceRoot, files) {
422
+ for (const file of files) try {
423
+ await access(join(workspaceRoot, file.path));
424
+ throw new Error(`Refusing to overwrite existing vault file: ${file.path}`);
425
+ } catch (error) {
426
+ if (isNotFoundError(error)) continue;
427
+ throw error;
428
+ }
429
+ }
430
+ async function writeVaultFile(workspaceRoot, file, force) {
431
+ try {
432
+ const filePath = join(workspaceRoot, file.path);
433
+ await mkdir(dirname(filePath), { recursive: true });
434
+ await writeFile(filePath, file.content, {
435
+ encoding: "utf8",
436
+ flag: force ? "w" : "wx"
437
+ });
438
+ } catch (error) {
439
+ if (!force && isFileExistsError(error)) throw new Error(`Refusing to overwrite existing vault file: ${file.path}`);
440
+ throw error;
441
+ }
442
+ }
443
+ function isFileExistsError(error) {
444
+ return error instanceof Error && "code" in error && error.code === "EEXIST";
445
+ }
446
+ function isNotFoundError(error) {
447
+ return error instanceof Error && "code" in error && error.code === "ENOENT";
448
+ }
449
+ function mergeDossierNodes(graphNodes, dossiers) {
450
+ const nodesById = /* @__PURE__ */ new Map();
451
+ const aliases = /* @__PURE__ */ new Map();
452
+ graphNodes.forEach((node, index) => {
453
+ const id = String(node["id"] ?? node["address"] ?? `node-${index + 1}`);
454
+ nodesById.set(id, node);
455
+ aliases.set(id, id);
456
+ if (typeof node["address"] === "string") aliases.set(node["address"], id);
457
+ });
458
+ for (const dossier of dossiers) {
459
+ const existingId = aliases.get(dossier.address);
460
+ if (existingId) {
461
+ const existing = nodesById.get(existingId);
462
+ if (existing) nodesById.set(existingId, enrichDossierNode(existing, dossier.type));
463
+ } else nodesById.set(dossier.address, {
464
+ id: dossier.address,
465
+ address: dossier.address,
466
+ node_type: dossier.type,
467
+ roles: [dossier.type]
468
+ });
469
+ }
470
+ return [...nodesById.values()];
471
+ }
472
+ async function readCaseEvidence(caseId) {
473
+ const evidenceDir = join(workspaceOutputPaths().casesRoot, caseId, "evidence");
474
+ const files = await readdir(evidenceDir).catch(() => []);
475
+ const docs = [];
476
+ for (const filename of files.filter((file) => file.endsWith(".md")).sort()) {
477
+ const { frontmatter, body } = parseFrontmatter(await readFile(join(evidenceDir, filename), "utf8"));
478
+ docs.push({
479
+ id: frontmatter["id"] || filename.replace(/\.md$/, ""),
480
+ filename,
481
+ source: frontmatter["source"] || "unknown",
482
+ timestamp: frontmatter["timestamp"] || "",
483
+ queryParams: frontmatter["queryParams"] || "",
484
+ body
485
+ });
486
+ }
487
+ return docs;
488
+ }
489
+ function entityFilesForCase(caseId, graphNodes, dossiers) {
490
+ const files = /* @__PURE__ */ new Map();
491
+ for (const [index, node] of graphNodes.entries()) {
492
+ const label = entityLabelForGraphNode(node, index);
493
+ const entityType = String(node["entityType"] ?? node["node_type"] ?? node["nodeType"] ?? "unknown");
494
+ const notePath = `Entities/${safeFilename(label)}`;
495
+ files.set(notePath, {
496
+ summary: {
497
+ label,
498
+ notePath,
499
+ entityType
500
+ },
501
+ content: renderEntityNote(label, caseId, entityType)
502
+ });
503
+ }
504
+ for (const dossier of dossiers) {
505
+ const notePath = `Entities/${safeFilename(dossier.address)}`;
506
+ files.set(notePath, {
507
+ summary: {
508
+ label: dossier.address,
509
+ notePath,
510
+ entityType: dossier.type
511
+ },
512
+ content: renderEntityNote(dossier.address, caseId, dossier.type)
513
+ });
514
+ }
515
+ return files;
516
+ }
517
+ function entityLabelForGraphNode(node, index) {
518
+ return String(node["address"] ?? node["id"] ?? `node-${index + 1}`);
519
+ }
520
+ function graphToCaseVaultCanvas(canvas, caseId, graphNodes) {
521
+ return {
522
+ nodes: canvas.nodes.map((node) => {
523
+ if (node.id === "case" && node.type === "file") return {
524
+ ...node,
525
+ file: `cases/${caseId}/Case.md`
526
+ };
527
+ const entityIndex = /^entity-(\d+)$/.exec(node.id)?.[1];
528
+ if (node.type === "file" && entityIndex) {
529
+ const graphNode = graphNodes[Number(entityIndex) - 1];
530
+ if (graphNode) return {
531
+ ...node,
532
+ file: `Entities/${safeFilename(entityLabelForGraphNode(graphNode, Number(entityIndex) - 1))}`
533
+ };
534
+ }
535
+ return node;
536
+ }),
537
+ edges: canvas.edges
538
+ };
539
+ }
540
+ async function loadLiveCaseGraph(caseId) {
541
+ const graph = await extractGraphFromCase(caseId);
542
+ return normalizeGraphPayload({
543
+ schema: "chain-insights.graph.v1",
544
+ nodes: graph.nodes,
545
+ edges: graph.edges,
546
+ flows: [],
547
+ edge_anchors: [],
548
+ metadata: graph.metadata
549
+ });
550
+ }
551
+ function enrichDossierNode(node, dossierType) {
552
+ const enriched = { ...node };
553
+ if (typeof enriched["node_type"] !== "string" || enriched["node_type"] === "unknown") enriched["node_type"] = dossierType;
554
+ if (!Array.isArray(enriched["roles"]) || enriched["roles"].length === 0) enriched["roles"] = [dossierType];
555
+ return enriched;
556
+ }
557
+ //#endregion
558
+ export { assertNoVaultFileCollisions, refreshCaseVault, scaffoldVault };
559
+
560
+ //# sourceMappingURL=vault-z35Dohdq.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"vault-z35Dohdq.mjs","names":[],"sources":["../src/vault/schema.ts","../src/vault/markdown.ts","../src/vault/index.ts"],"sourcesContent":["export type VaultScaffoldOptions = {\n workspaceRoot: string\n force?: boolean\n}\n\nexport type VaultScaffoldResult = {\n workspaceRoot: string\n filesWritten: string[]\n}\n\nexport type CaseVaultRefreshOptions = {\n caseId: string\n force?: boolean\n}\n\nexport type CaseVaultRefreshResult = {\n caseId: string\n filesWritten: string[]\n nextFile: string\n}\n\nexport const VAULT_DIRS = ['.obsidian', 'Canvases', 'Entities', 'Evidence', 'published'] as const\n","export function yamlString(value: string): string {\n return JSON.stringify(value)\n}\n\nexport function frontmatter(values: Record<string, string | boolean | string[]>): string {\n const lines = ['---']\n for (const [key, value] of Object.entries(values)) {\n if (Array.isArray(value)) {\n lines.push(`${key}:`)\n for (const item of value) lines.push(` - ${yamlString(item)}`)\n } else {\n lines.push(`${key}: ${typeof value === 'boolean' ? String(value) : yamlString(value)}`)\n }\n }\n lines.push('---', '')\n return lines.join('\\n')\n}\n\nexport type VaultCaseSummary = {\n id: string\n name: string\n status: string\n tags: string[]\n description: string\n evidenceCount: number\n evidenceVerified: boolean\n entityCount: number\n}\n\nexport type VaultEvidenceSummary = {\n id: string\n filename: string\n source: string\n timestamp: string\n queryParams: string\n notePath: string\n body: string\n}\n\nexport type VaultEntitySummary = {\n label: string\n notePath: string\n entityType: string\n}\n\nexport function renderLiveCaseNote(input: VaultCaseSummary): string {\n return frontmatter({\n type: 'chain-insights-case',\n case_id: input.id,\n status: input.status,\n tags: input.tags,\n contains_sensitive_data: true,\n source_of_truth: `cases/${input.id}/`,\n }) + [\n `# ${input.name}`,\n '',\n input.description,\n '',\n '## Live Workspace',\n '',\n `Status: ${input.status}`,\n `Evidence files: ${input.evidenceCount}`,\n `Evidence manifest verified: ${input.evidenceVerified ? 'yes' : 'no'}`,\n `Entities: ${input.entityCount}`,\n '',\n '## Navigation',\n '',\n '- [[Agent Console]]',\n '- [[Graph.canvas]]',\n '- [[Cases]]',\n `- [[cases/${input.id}/Evidence|Evidence]]`,\n `- [[cases/${input.id}/Entities|Entities]]`,\n '- [[Graphs]]',\n '',\n ].join('\\n')\n}\n\nexport function renderCaseAgentConsole(input: VaultCaseSummary): string {\n return frontmatter({\n type: 'chain-insights-case-agent-console',\n case_id: input.id,\n contains_sensitive_data: true,\n }) + [\n `# Agent Console: ${input.name}`,\n '',\n `Canonical case state: \\`cases/${input.id}/\\``,\n '',\n '## Case Files',\n '',\n '- [[Case]]',\n '- [[Graph.canvas]]',\n `- [[cases/${input.id}/Evidence|Evidence]]`,\n `- [[cases/${input.id}/Entities|Entities]]`,\n '',\n '## Current Counts',\n '',\n `- Evidence files: ${input.evidenceCount}`,\n `- Entities: ${input.entityCount}`,\n `- Manifest verified: ${input.evidenceVerified ? 'yes' : 'no'}`,\n '',\n ].join('\\n')\n}\n\nexport function renderCaseEvidenceIndex(input: VaultCaseSummary, evidence: VaultEvidenceSummary[]): string {\n return frontmatter({\n type: 'chain-insights-case-evidence-index',\n case_id: input.id,\n contains_sensitive_data: true,\n }) + [\n `# Evidence: ${input.name}`,\n '',\n `Canonical evidence directory: \\`cases/${input.id}/evidence/\\``,\n `Evidence files: ${input.evidenceCount}`,\n `Manifest verified: ${input.evidenceVerified ? 'yes' : 'no'}`,\n '',\n '## Evidence Notes',\n '',\n ...(evidence.length > 0\n ? evidence.map(item => `- [[${item.notePath.replace(/\\.md$/, '')}|${item.id}]] (${item.source})`)\n : ['No evidence files recorded yet.']),\n '',\n ].join('\\n')\n}\n\nexport function renderEvidenceNote(input: VaultEvidenceSummary, caseId: string): string {\n return frontmatter({\n type: 'chain-insights-evidence',\n case_id: caseId,\n evidence_id: input.id,\n source: input.source,\n source_file: `cases/${caseId}/evidence/${input.filename}`,\n contains_sensitive_data: true,\n }) + [\n `# Evidence: ${input.source}`,\n '',\n `Evidence ID: \\`${input.id}\\``,\n `Source file: \\`cases/${caseId}/evidence/${input.filename}\\``,\n `Captured: ${input.timestamp || 'unknown'}`,\n `Query params: ${input.queryParams || 'none'}`,\n '',\n '## Case',\n '',\n `- [[cases/${caseId}/Case|${caseId}]]`,\n '',\n '## Body',\n '',\n input.body.trim() || 'No evidence body recorded.',\n '',\n ].join('\\n')\n}\n\nexport function renderCaseEntityIndex(input: VaultCaseSummary, entities: VaultEntitySummary[]): string {\n return frontmatter({\n type: 'chain-insights-case-entity-index',\n case_id: input.id,\n contains_sensitive_data: true,\n }) + [\n `# Entities: ${input.name}`,\n '',\n `Canonical dossier directory: \\`cases/${input.id}/dossiers/\\``,\n `Entities: ${entities.length}`,\n '',\n '## Entity Notes',\n '',\n ...(entities.length > 0\n ? entities.map(item => `- [[${item.notePath.replace(/\\.md$/, '')}|${item.label}]] (${item.entityType})`)\n : ['No entities recorded yet.']),\n '',\n ].join('\\n')\n}\n\nexport function renderEntityNote(address: string, caseId: string, entityType: string): string {\n return frontmatter({\n type: 'chain-insights-entity',\n case_id: caseId,\n address,\n entity_type: entityType,\n contains_sensitive_data: true,\n }) + [\n `# Entity: ${address}`,\n '',\n `Address: ${address}`,\n `Type: ${entityType}`,\n '',\n '## Cases',\n '',\n `- [[cases/${caseId}/Case|${caseId}]]`,\n '',\n ].join('\\n')\n}\n\nexport function renderVaultHome(): string {\n return frontmatter({\n type: 'chain-insights-vault-home',\n product: 'Chain Insights',\n contains_sensitive_data: true,\n }) + [\n '# Chain Insights Vault',\n '',\n 'Chain Insights is an AML investigation CLI and MCP proxy layered on GraphRAG MCP.',\n '',\n '## Start Here',\n '',\n '- [[Cases]]',\n '- [[Entities]]',\n '- [[Evidence]]',\n '- [[Graphs]]',\n '- [[Agent Console]]',\n '',\n ].join('\\n')\n}\n\nexport function renderRootIndex(title: string, type: string, links: string[]): string {\n return frontmatter({\n type,\n product: 'Chain Insights',\n contains_sensitive_data: true,\n }) + [\n `# ${title}`,\n '',\n ...links.map((link) => `- [[${link}]]`),\n '',\n ].join('\\n')\n}\n\nexport function renderRootAgentConsole(): string {\n return frontmatter({\n type: 'chain-insights-agent-console',\n product: 'Chain Insights',\n contains_sensitive_data: true,\n }) + [\n '# Agent Console',\n '',\n 'Use Chain Insights case evidence as canonical local state and GraphRAG MCP for fresh graph facts.',\n '',\n '## Reading Order',\n '',\n '1. [[Home]]',\n '2. [[Cases]]',\n '3. [[Entities]]',\n '4. [[Evidence]]',\n '5. [[Graphs]]',\n '',\n ].join('\\n')\n}\n\nexport function renderObsidianAppConfig(): string {\n return JSON.stringify(\n {\n useMarkdownLinks: false,\n newLinkFormat: 'shortest',\n alwaysUpdateLinks: true,\n },\n null,\n 2,\n ) + '\\n'\n}\n\nexport function renderObsidianGraphConfig(): string {\n return JSON.stringify(\n {\n 'collapse-filter': true,\n search: '',\n showTags: true,\n showAttachments: true,\n hideUnresolved: false,\n showOrphans: true,\n },\n null,\n 2,\n ) + '\\n'\n}\n\nexport function renderObsidianTemplatesConfig(): string {\n return JSON.stringify(\n {\n folder: '',\n dateFormat: 'YYYY-MM-DD',\n timeFormat: 'HH:mm',\n },\n null,\n 2,\n ) + '\\n'\n}\n\nexport function renderVaultGitignore(): string {\n return [\n '# Chain Insights local runtime state',\n '.chain-insights/runtime/',\n '',\n '# Obsidian local UI state',\n '.obsidian/workspace.json',\n '.obsidian/workspace-mobile.json',\n '.obsidian/workspaces.json',\n '',\n '# Private export bundles are local by default',\n 'published/',\n '',\n ].join('\\n')\n}\n","import { access, mkdir, readFile, readdir, writeFile } from 'node:fs/promises'\nimport { dirname, resolve, join } from 'node:path'\nimport { CaseStore, DossierStore, EvidenceStore, parseFrontmatter } from '../cases/index.js'\nimport { graphToCanvas } from '../export/canvas.js'\nimport { safeFilename } from '../export/paths.js'\nimport type { JsonCanvas } from '../export/schema.js'\nimport { extractGraphFromCase } from '../viz/data-extractor.js'\nimport { normalizeGraphPayload } from '../viz/graph-normalizer.js'\nimport { workspaceOutputPaths } from '../workspace/output-root.js'\nimport type { CaseVaultRefreshOptions, CaseVaultRefreshResult, VaultScaffoldOptions, VaultScaffoldResult } from './schema.js'\nimport { VAULT_DIRS } from './schema.js'\nimport {\n renderCaseEntityIndex,\n renderCaseEvidenceIndex,\n renderCaseAgentConsole,\n renderEntityNote,\n renderEvidenceNote,\n renderLiveCaseNote,\n renderObsidianAppConfig,\n renderObsidianGraphConfig,\n renderObsidianTemplatesConfig,\n renderRootAgentConsole,\n renderRootIndex,\n renderVaultGitignore,\n renderVaultHome,\n type VaultEntitySummary,\n type VaultEvidenceSummary,\n} from './markdown.js'\n\ntype VaultFile = {\n path: string\n content: string\n}\n\nconst VAULT_FILES: VaultFile[] = [\n { path: '.obsidian/app.json', content: renderObsidianAppConfig() },\n { path: '.obsidian/graph.json', content: renderObsidianGraphConfig() },\n { path: '.obsidian/templates.json', content: renderObsidianTemplatesConfig() },\n { path: '.gitignore', content: renderVaultGitignore() },\n { path: 'Home.md', content: renderVaultHome() },\n {\n path: 'Cases.md',\n content: renderRootIndex('Cases', 'chain-insights-vault-cases-index', ['Home', 'Agent Console']),\n },\n {\n path: 'Entities.md',\n content: renderRootIndex('Entities', 'chain-insights-vault-entities-index', ['Home', 'Cases', 'Evidence']),\n },\n {\n path: 'Evidence.md',\n content: renderRootIndex('Evidence', 'chain-insights-vault-evidence-index', ['Home', 'Cases', 'Entities']),\n },\n {\n path: 'Graphs.md',\n content: renderRootIndex('Graphs', 'chain-insights-vault-graphs-index', ['Home', 'Cases', 'Entities', 'Evidence']),\n },\n { path: 'Agent Console.md', content: renderRootAgentConsole() },\n {\n path: 'Canvases/README.md',\n content: renderRootIndex('Canvases', 'chain-insights-vault-canvases-readme', ['Home', 'Graphs']),\n },\n {\n path: 'Entities/README.md',\n content: renderRootIndex('Entities Folder', 'chain-insights-vault-entities-readme', ['Entities', 'Cases']),\n },\n {\n path: 'Evidence/README.md',\n content: renderRootIndex('Evidence Folder', 'chain-insights-vault-evidence-readme', ['Evidence', 'Cases']),\n },\n]\n\nexport type {\n CaseVaultRefreshOptions,\n CaseVaultRefreshResult,\n VaultScaffoldOptions,\n VaultScaffoldResult,\n} from './schema.js'\nexport { VAULT_DIRS } from './schema.js'\n\nexport async function scaffoldVault(options: VaultScaffoldOptions): Promise<VaultScaffoldResult> {\n const workspaceRoot = resolve(options.workspaceRoot)\n const force = options.force === true\n\n if (!force) {\n await assertNoVaultFileCollisions(workspaceRoot)\n }\n\n for (const dir of VAULT_DIRS) {\n await mkdir(join(workspaceRoot, dir), { recursive: true })\n }\n\n const filesWritten: string[] = []\n for (const file of VAULT_FILES) {\n await writeVaultFile(workspaceRoot, file, force)\n filesWritten.push(file.path)\n }\n\n return { workspaceRoot, filesWritten }\n}\n\nexport async function refreshCaseVault(options: CaseVaultRefreshOptions): Promise<CaseVaultRefreshResult> {\n const workspace = workspaceOutputPaths()\n const force = options.force === true\n const [caseInfo, evidenceVerification, evidence, dossiers, graph] = await Promise.all([\n CaseStore.get(options.caseId),\n EvidenceStore.verifyManifest(options.caseId),\n readCaseEvidence(options.caseId),\n DossierStore.listSummaries(options.caseId),\n loadLiveCaseGraph(options.caseId),\n ])\n\n const caseSummary = {\n id: caseInfo.id,\n name: caseInfo.name,\n status: caseInfo.status,\n tags: caseInfo.tags,\n description: caseInfo.description,\n evidenceCount: evidenceVerification.count,\n evidenceVerified: evidenceVerification.ok,\n entityCount: dossiers.length,\n }\n const canvasGraph = {\n ...graph,\n nodes: mergeDossierNodes(graph.nodes, dossiers),\n }\n const canvas = graphToCaseVaultCanvas(graphToCanvas(canvasGraph), caseInfo.id, canvasGraph.nodes)\n const evidenceSummaries = evidence.map(evidenceDoc => ({\n ...evidenceDoc,\n notePath: `Evidence/${safeFilename(`${evidenceDoc.filename.replace(/\\.md$/, '')}-${caseInfo.id}`)}`,\n }))\n const entityFiles = entityFilesForCase(caseInfo.id, canvasGraph.nodes, dossiers)\n const entitySummaries = [...entityFiles.values()]\n .map(entry => entry.summary)\n .sort((left, right) => left.label.localeCompare(right.label))\n\n const files: VaultFile[] = [\n { path: `cases/${caseInfo.id}/Case.md`, content: renderLiveCaseNote(caseSummary) },\n { path: `cases/${caseInfo.id}/Agent Console.md`, content: renderCaseAgentConsole(caseSummary) },\n { path: `cases/${caseInfo.id}/Evidence.md`, content: renderCaseEvidenceIndex(caseSummary, evidenceSummaries) },\n { path: `cases/${caseInfo.id}/Entities.md`, content: renderCaseEntityIndex(caseSummary, entitySummaries) },\n { path: `cases/${caseInfo.id}/Graph.canvas`, content: JSON.stringify(canvas, null, 2) + '\\n' },\n ...evidenceSummaries.map(evidenceDoc => ({\n path: evidenceDoc.notePath,\n content: renderEvidenceNote(evidenceDoc, caseInfo.id),\n })),\n ...[...entityFiles.values()].map(entry => ({\n path: entry.summary.notePath,\n content: entry.content,\n })),\n ]\n\n if (!force) {\n await assertNoFileCollisions(workspace.root, files)\n }\n\n const filesWritten: string[] = []\n for (const file of files) {\n await writeVaultFile(workspace.root, file, force)\n filesWritten.push(file.path)\n }\n\n return {\n caseId: caseInfo.id,\n filesWritten,\n nextFile: `cases/${caseInfo.id}/Case.md`,\n }\n}\n\nexport async function assertNoVaultFileCollisions(workspaceRoot: string): Promise<void> {\n await assertNoFileCollisions(workspaceRoot, VAULT_FILES)\n}\n\nasync function assertNoFileCollisions(workspaceRoot: string, files: VaultFile[]): Promise<void> {\n for (const file of files) {\n try {\n await access(join(workspaceRoot, file.path))\n throw new Error(`Refusing to overwrite existing vault file: ${file.path}`)\n } catch (error) {\n if (isNotFoundError(error)) continue\n throw error\n }\n }\n}\n\nasync function writeVaultFile(workspaceRoot: string, file: VaultFile, force: boolean): Promise<void> {\n try {\n const filePath = join(workspaceRoot, file.path)\n await mkdir(dirname(filePath), { recursive: true })\n await writeFile(filePath, file.content, { encoding: 'utf8', flag: force ? 'w' : 'wx' })\n } catch (error) {\n if (!force && isFileExistsError(error)) {\n throw new Error(`Refusing to overwrite existing vault file: ${file.path}`)\n }\n throw error\n }\n}\n\nfunction isFileExistsError(error: unknown): boolean {\n return error instanceof Error && 'code' in error && error.code === 'EEXIST'\n}\n\nfunction isNotFoundError(error: unknown): boolean {\n return error instanceof Error && 'code' in error && error.code === 'ENOENT'\n}\n\nfunction mergeDossierNodes(\n graphNodes: Record<string, unknown>[],\n dossiers: Array<{ address: string; type: string }>,\n): Record<string, unknown>[] {\n const nodesById = new Map<string, Record<string, unknown>>()\n const aliases = new Map<string, string>()\n graphNodes.forEach((node, index) => {\n const id = String(node['id'] ?? node['address'] ?? `node-${index + 1}`)\n nodesById.set(id, node)\n aliases.set(id, id)\n if (typeof node['address'] === 'string') aliases.set(node['address'], id)\n })\n\n for (const dossier of dossiers) {\n const existingId = aliases.get(dossier.address)\n if (existingId) {\n const existing = nodesById.get(existingId)\n if (existing) {\n nodesById.set(existingId, enrichDossierNode(existing, dossier.type))\n }\n } else {\n nodesById.set(dossier.address, {\n id: dossier.address,\n address: dossier.address,\n node_type: dossier.type,\n roles: [dossier.type],\n })\n }\n }\n return [...nodesById.values()]\n}\n\ntype EvidenceDoc = Omit<VaultEvidenceSummary, 'notePath'>\n\nasync function readCaseEvidence(caseId: string): Promise<EvidenceDoc[]> {\n const workspace = workspaceOutputPaths()\n const evidenceDir = join(workspace.casesRoot, caseId, 'evidence')\n const files = await readdir(evidenceDir).catch(() => [])\n const docs: EvidenceDoc[] = []\n for (const filename of files.filter(file => file.endsWith('.md')).sort()) {\n const raw = await readFile(join(evidenceDir, filename), 'utf8')\n const { frontmatter, body } = parseFrontmatter(raw)\n docs.push({\n id: frontmatter['id'] || filename.replace(/\\.md$/, ''),\n filename,\n source: frontmatter['source'] || 'unknown',\n timestamp: frontmatter['timestamp'] || '',\n queryParams: frontmatter['queryParams'] || '',\n body,\n })\n }\n return docs\n}\n\nfunction entityFilesForCase(\n caseId: string,\n graphNodes: Record<string, unknown>[],\n dossiers: Array<{ address: string; type: string }>,\n): Map<string, { summary: VaultEntitySummary; content: string }> {\n const files = new Map<string, { summary: VaultEntitySummary; content: string }>()\n\n for (const [index, node] of graphNodes.entries()) {\n const label = entityLabelForGraphNode(node, index)\n const entityType = String(node['entityType'] ?? node['node_type'] ?? node['nodeType'] ?? 'unknown')\n const notePath = `Entities/${safeFilename(label)}`\n files.set(notePath, {\n summary: { label, notePath, entityType },\n content: renderEntityNote(label, caseId, entityType),\n })\n }\n\n for (const dossier of dossiers) {\n const notePath = `Entities/${safeFilename(dossier.address)}`\n files.set(notePath, {\n summary: { label: dossier.address, notePath, entityType: dossier.type },\n content: renderEntityNote(dossier.address, caseId, dossier.type),\n })\n }\n\n return files\n}\n\nfunction entityLabelForGraphNode(node: Record<string, unknown>, index: number): string {\n return String(node['address'] ?? node['id'] ?? `node-${index + 1}`)\n}\n\nfunction graphToCaseVaultCanvas(canvas: JsonCanvas, caseId: string, graphNodes: Record<string, unknown>[]): JsonCanvas {\n return {\n nodes: canvas.nodes.map(node => {\n if (node.id === 'case' && node.type === 'file') {\n return { ...node, file: `cases/${caseId}/Case.md` }\n }\n const entityIndex = /^entity-(\\d+)$/.exec(node.id)?.[1]\n if (node.type === 'file' && entityIndex) {\n const graphNode = graphNodes[Number(entityIndex) - 1]\n if (graphNode) return { ...node, file: `Entities/${safeFilename(entityLabelForGraphNode(graphNode, Number(entityIndex) - 1))}` }\n }\n return node\n }),\n edges: canvas.edges,\n }\n}\n\nasync function loadLiveCaseGraph(caseId: string): Promise<{ nodes: Record<string, unknown>[]; edges: Record<string, unknown>[] }> {\n const graph = await extractGraphFromCase(caseId)\n return normalizeGraphPayload({\n schema: 'chain-insights.graph.v1',\n nodes: graph.nodes,\n edges: graph.edges,\n flows: [],\n edge_anchors: [],\n metadata: graph.metadata,\n })\n}\n\nfunction enrichDossierNode(node: Record<string, unknown>, dossierType: string): Record<string, unknown> {\n const enriched = { ...node }\n if (typeof enriched['node_type'] !== 'string' || enriched['node_type'] === 'unknown') {\n enriched['node_type'] = dossierType\n }\n if (!Array.isArray(enriched['roles']) || enriched['roles'].length === 0) {\n enriched['roles'] = [dossierType]\n }\n return enriched\n}\n"],"mappings":"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"}
@@ -1,5 +1,5 @@
1
1
  const require_chunk = require("./chunk-DakpK96I.cjs");
2
- const require_data_extractor = require("./data-extractor-Cavd7wHk.cjs");
2
+ const require_data_extractor = require("./data-extractor-DS4rzy3M.cjs");
3
3
  const require_html_generator = require("./html-generator-Bx3UcLTB.cjs");
4
4
  let node_fs_promises = require("node:fs/promises");
5
5
  //#region src/viz/index.ts
@@ -14,10 +14,10 @@ async function generateVisualization(opts) {
14
14
  } catch {
15
15
  throw new Error("Invalid transaction data. The input file must contain a JSON array of transaction objects with `from`, `to`, and `value` fields.");
16
16
  }
17
- const { extractGraphFromJson } = await Promise.resolve().then(() => require("./data-extractor-Cavd7wHk.cjs")).then((n) => n.data_extractor_exports);
17
+ const { extractGraphFromJson } = await Promise.resolve().then(() => require("./data-extractor-DS4rzy3M.cjs")).then((n) => n.data_extractor_exports);
18
18
  rawData = extractGraphFromJson(parsed);
19
19
  } else if (opts.caseId) {
20
- const { extractGraphFromCase } = await Promise.resolve().then(() => require("./data-extractor-Cavd7wHk.cjs")).then((n) => n.data_extractor_exports);
20
+ const { extractGraphFromCase } = await Promise.resolve().then(() => require("./data-extractor-DS4rzy3M.cjs")).then((n) => n.data_extractor_exports);
21
21
  const extracted = await extractGraphFromCase(opts.caseId);
22
22
  if (extracted.nodes.length === 0) throw new Error("No Transaction Data. This case has no evidence with transaction data. Add evidence using `chain-insights evidence add` or provide a JSON file with `chain-insights viz --data <file.json>`.");
23
23
  rawData = extracted;
@@ -1,5 +1,5 @@
1
1
  import { t as __exportAll } from "./rolldown-runtime-D7D4PA-g.mjs";
2
- import { r as truncateGraph } from "./data-extractor-DZUJu1Bz.mjs";
2
+ import { r as truncateGraph } from "./data-extractor-B4nHw1wZ.mjs";
3
3
  import { r as writeVizHtml, t as generateHtml } from "./html-generator-AowOmzyi.mjs";
4
4
  import { readFile } from "node:fs/promises";
5
5
  //#region src/viz/index.ts
@@ -14,10 +14,10 @@ async function generateVisualization(opts) {
14
14
  } catch {
15
15
  throw new Error("Invalid transaction data. The input file must contain a JSON array of transaction objects with `from`, `to`, and `value` fields.");
16
16
  }
17
- const { extractGraphFromJson } = await import("./data-extractor-DZUJu1Bz.mjs").then((n) => n.t);
17
+ const { extractGraphFromJson } = await import("./data-extractor-B4nHw1wZ.mjs").then((n) => n.t);
18
18
  rawData = extractGraphFromJson(parsed);
19
19
  } else if (opts.caseId) {
20
- const { extractGraphFromCase } = await import("./data-extractor-DZUJu1Bz.mjs").then((n) => n.t);
20
+ const { extractGraphFromCase } = await import("./data-extractor-B4nHw1wZ.mjs").then((n) => n.t);
21
21
  const extracted = await extractGraphFromCase(opts.caseId);
22
22
  if (extracted.nodes.length === 0) throw new Error("No Transaction Data. This case has no evidence with transaction data. Add evidence using `chain-insights evidence add` or provide a JSON file with `chain-insights viz --data <file.json>`.");
23
23
  rawData = extracted;
@@ -32,4 +32,4 @@ async function generateVisualization(opts) {
32
32
  //#endregion
33
33
  export { viz_exports as n, generateVisualization as t };
34
34
 
35
- //# sourceMappingURL=viz-5y24S5X1.mjs.map
35
+ //# sourceMappingURL=viz-DB5XFG1z.mjs.map