chain-insights 0.3.9 → 0.3.18

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 (137) hide show
  1. package/README.md +49 -52
  2. package/dist/{active-ByNgjuAg.mjs → active-BQopLul8.mjs} +6 -8
  3. package/dist/active-BQopLul8.mjs.map +1 -0
  4. package/dist/{active-BVr55kvW.cjs → active-XWv72R1X.cjs} +4 -12
  5. package/dist/{app-BxojXjtB.cjs → app-DBrqk_iP.cjs} +12 -28
  6. package/dist/{app-CRd39JJ8.mjs → app-DXwILI_a.mjs} +13 -28
  7. package/dist/app-DXwILI_a.mjs.map +1 -0
  8. package/dist/{artifact-server-CP6LXQ9d.mjs → artifact-server-CcmLBv1j.mjs} +2 -2
  9. package/dist/{artifact-server-CP6LXQ9d.mjs.map → artifact-server-CcmLBv1j.mjs.map} +1 -1
  10. package/dist/{artifact-server-XbN16DwU.cjs → artifact-server-v0WgTPFT.cjs} +1 -1
  11. package/dist/{capabilities-BCvkTkIu.mjs → capabilities-CM72SErE.mjs} +2 -2
  12. package/dist/{capabilities-BCvkTkIu.mjs.map → capabilities-CM72SErE.mjs.map} +1 -1
  13. package/dist/{capabilities-DOa6EFO-.cjs → capabilities-DGeF-oHc.cjs} +1 -1
  14. package/dist/cli.cjs +149 -405
  15. package/dist/cli.mjs +149 -405
  16. package/dist/cli.mjs.map +1 -1
  17. package/dist/{client-Y_zqKqJT.cjs → client-BY-56ojr.cjs} +0 -17
  18. package/dist/{client-BgmHjBHQ.mjs → client-ytTO0mcZ.mjs} +2 -13
  19. package/dist/{client-BgmHjBHQ.mjs.map → client-ytTO0mcZ.mjs.map} +1 -1
  20. package/dist/{config-Drgc2HuF.mjs → config-C6zM8Xir.mjs} +3 -3
  21. package/dist/{config-Drgc2HuF.mjs.map → config-C6zM8Xir.mjs.map} +1 -1
  22. package/dist/{config-BwVx19Og.cjs → config-CkW404Cs.cjs} +2 -2
  23. package/dist/{graph-reports-BDELxmpi.mjs → graph-reports-CEq-Mvx0.mjs} +2 -2
  24. package/dist/{graph-reports-BDELxmpi.mjs.map → graph-reports-CEq-Mvx0.mjs.map} +1 -1
  25. package/dist/{graph-reports-B3mkLP8Z.cjs → graph-reports-CkglRtg4.cjs} +1 -1
  26. package/dist/{html-generator-Bx3UcLTB.cjs → html-generator-BFKafL8y.cjs} +5 -6
  27. package/dist/{html-generator-AowOmzyi.mjs → html-generator-D4fX71hI.mjs} +6 -6
  28. package/dist/html-generator-D4fX71hI.mjs.map +1 -0
  29. package/dist/index.cjs +5 -5
  30. package/dist/index.d.cts +1 -2
  31. package/dist/index.d.cts.map +1 -1
  32. package/dist/index.d.mts +1 -2
  33. package/dist/index.d.mts.map +1 -1
  34. package/dist/index.mjs +5 -5
  35. package/dist/{init-CKQ6F07J.mjs → init-BGDvGreX.mjs} +52 -55
  36. package/dist/init-BGDvGreX.mjs.map +1 -0
  37. package/dist/{init-Dhw8F23z.cjs → init-Cuw9TznI.cjs} +51 -54
  38. package/dist/{mcp-endpoint-DHs1cRFH.mjs → mcp-endpoint-QQ5Lbqc2.mjs} +5 -2
  39. package/dist/mcp-endpoint-QQ5Lbqc2.mjs.map +1 -0
  40. package/dist/{mcp-endpoint-BaV8h_lq.cjs → mcp-endpoint-cQIZSjkK.cjs} +4 -1
  41. package/dist/mcp-proxy.cjs +650 -771
  42. package/dist/mcp-proxy.d.cts.map +1 -1
  43. package/dist/mcp-proxy.d.mts.map +1 -1
  44. package/dist/mcp-proxy.mjs +651 -772
  45. package/dist/mcp-proxy.mjs.map +1 -1
  46. package/dist/{output-root-BRhzhhXZ.mjs → output-root-BK4pdjyz.mjs} +6 -3
  47. package/dist/output-root-BK4pdjyz.mjs.map +1 -0
  48. package/dist/{output-root-YIbl6PwF.cjs → output-root-DI0tzA0X.cjs} +5 -2
  49. package/dist/{public-tools-BY3PTw6x.cjs → public-tools-BREojpU7.cjs} +1244 -426
  50. package/dist/{public-tools-CvlZcysd.mjs → public-tools-brHmHGYm.mjs} +1240 -428
  51. package/dist/public-tools-brHmHGYm.mjs.map +1 -0
  52. package/dist/{schema-BFEWhzg7.mjs → schema-D_qwaQA5.mjs} +2 -2
  53. package/dist/{schema-BFEWhzg7.mjs.map → schema-D_qwaQA5.mjs.map} +1 -1
  54. package/dist/{schema-Vl9yuOFO.cjs → schema-Dr6JXSOF.cjs} +1 -1
  55. package/dist/{server-BXLX2j_A.mjs → server-BK4bfOiv.mjs} +2 -2
  56. package/dist/{server-BXLX2j_A.mjs.map → server-BK4bfOiv.mjs.map} +1 -1
  57. package/dist/{server-BqVdWath.cjs → server-ColyTG1t.cjs} +1 -1
  58. package/dist/templates/graph.html +1 -1
  59. package/dist/{tool-visibility-Buq7YdUZ.cjs → tool-visibility--QPgrRE5.cjs} +5 -1
  60. package/dist/{tool-visibility-BpyZHRBi.mjs → tool-visibility-nr6XqO1F.mjs} +6 -2
  61. package/dist/tool-visibility-nr6XqO1F.mjs.map +1 -0
  62. package/dist/viz-BBvY-wXz.cjs +210 -0
  63. package/dist/viz-D8umSF-t.mjs +199 -0
  64. package/dist/viz-D8umSF-t.mjs.map +1 -0
  65. package/docs/architecture.md +4 -3
  66. package/docs/contributing.md +12 -6
  67. package/docs/graph-tools.md +93 -68
  68. package/docs/investigation-workspaces.md +38 -124
  69. package/docs/mcp-proxy.md +23 -34
  70. package/package.json +2 -2
  71. package/skills/chain-insights-address-risk/SKILL.md +92 -0
  72. package/skills/chain-insights-bittensor-cypher/SKILL.md +2 -22
  73. package/skills/chain-insights-developer-experience/SKILL.md +8 -28
  74. package/skills/chain-insights-exposure-analysis/SKILL.md +83 -0
  75. package/skills/chain-insights-investigation/SKILL.md +59 -211
  76. package/skills/chain-insights-investigation/agents/openai.yaml +1 -1
  77. package/skills/chain-insights-investigation/scripts/run-target-uat.sh +37 -55
  78. package/skills/chain-insights-trace-funds/SKILL.md +14 -14
  79. package/skills/ci-status/SKILL.md +9 -15
  80. package/skills/test-chain-insights-graphrag-mcp/SKILL.md +5 -4
  81. package/skills/test-chain-insights-graphrag-mcp/scripts/run-uat.sh +272 -18
  82. package/dist/active-ByNgjuAg.mjs.map +0 -1
  83. package/dist/app-CRd39JJ8.mjs.map +0 -1
  84. package/dist/canvas-Cn-maEIh.mjs +0 -203
  85. package/dist/canvas-Cn-maEIh.mjs.map +0 -1
  86. package/dist/canvas-p-oKCMjc.cjs +0 -251
  87. package/dist/cases-Bz_9XKEw.cjs +0 -19
  88. package/dist/cases-TVcAifxu.mjs +0 -16
  89. package/dist/cases-TVcAifxu.mjs.map +0 -1
  90. package/dist/data-extractor-B4nHw1wZ.mjs +0 -336
  91. package/dist/data-extractor-B4nHw1wZ.mjs.map +0 -1
  92. package/dist/data-extractor-DS4rzy3M.cjs +0 -353
  93. package/dist/dossier-BXy57V4-.cjs +0 -88
  94. package/dist/dossier-Bjpcbcxa.mjs +0 -78
  95. package/dist/dossier-Bjpcbcxa.mjs.map +0 -1
  96. package/dist/evidence-CvEesemA.cjs +0 -200
  97. package/dist/evidence-D96PTzOQ.mjs +0 -195
  98. package/dist/evidence-D96PTzOQ.mjs.map +0 -1
  99. package/dist/export-CBhcJuZ6.mjs +0 -394
  100. package/dist/export-CBhcJuZ6.mjs.map +0 -1
  101. package/dist/export-D4v4-6F4.cjs +0 -394
  102. package/dist/frontmatter-D0ccQnUM.mjs +0 -26
  103. package/dist/frontmatter-D0ccQnUM.mjs.map +0 -1
  104. package/dist/frontmatter-Dvqa5HX6.cjs +0 -35
  105. package/dist/html-generator-AowOmzyi.mjs.map +0 -1
  106. package/dist/init-CKQ6F07J.mjs.map +0 -1
  107. package/dist/mcp-endpoint-DHs1cRFH.mjs.map +0 -1
  108. package/dist/output-root-BRhzhhXZ.mjs.map +0 -1
  109. package/dist/parser-BXLAHYnZ.cjs +0 -182
  110. package/dist/parser-CJfMsOl6.mjs +0 -182
  111. package/dist/parser-CJfMsOl6.mjs.map +0 -1
  112. package/dist/public-tools-CvlZcysd.mjs.map +0 -1
  113. package/dist/resolver-2jXNtWQO.mjs +0 -184
  114. package/dist/resolver-2jXNtWQO.mjs.map +0 -1
  115. package/dist/resolver-CZdQwKvh.cjs +0 -186
  116. package/dist/runner-CVnjpqc-.mjs +0 -149
  117. package/dist/runner-CVnjpqc-.mjs.map +0 -1
  118. package/dist/runner-bLy0pTr_.cjs +0 -147
  119. package/dist/selector-BvXM9jbe.mjs +0 -12
  120. package/dist/selector-BvXM9jbe.mjs.map +0 -1
  121. package/dist/selector-Dps_ZFxq.cjs +0 -10
  122. package/dist/session-BT7VpbAd.cjs +0 -127
  123. package/dist/session-DROyhebe.mjs +0 -117
  124. package/dist/session-DROyhebe.mjs.map +0 -1
  125. package/dist/store-C2B_AssI.mjs +0 -231
  126. package/dist/store-C2B_AssI.mjs.map +0 -1
  127. package/dist/store-CQhU8dz8.cjs +0 -242
  128. package/dist/tool-visibility-BpyZHRBi.mjs.map +0 -1
  129. package/dist/vault-B2y78Ypu.cjs +0 -560
  130. package/dist/vault-z35Dohdq.mjs +0 -560
  131. package/dist/vault-z35Dohdq.mjs.map +0 -1
  132. package/dist/viz-D1620cBX.cjs +0 -44
  133. package/dist/viz-DB5XFG1z.mjs +0 -35
  134. package/dist/viz-DB5XFG1z.mjs.map +0 -1
  135. package/docs/knowledge-exports.md +0 -204
  136. package/docs/obsidian-vault.md +0 -130
  137. package/skills/ci-case/SKILL.md +0 -43
package/dist/cli.cjs CHANGED
@@ -29,34 +29,6 @@ if (rawArgs[0] === "mcp" && [
29
29
  console.error(`error: unknown command '${rawArgs[1]}'`);
30
30
  process.exit(1);
31
31
  }
32
- async function resolveCaseSelector(input) {
33
- const { resolveCaseSelector } = await Promise.resolve().then(() => require("./selector-Dps_ZFxq.cjs"));
34
- return resolveCaseSelector(input);
35
- }
36
- async function scopeCasesToInvocationDir() {
37
- if (process.env["CHAIN_INSIGHTS_CASES_ROOT"]?.trim()) return;
38
- const { activeCasesRoot } = await Promise.resolve().then(() => require("./active-BVr55kvW.cjs")).then((n) => n.active_exports);
39
- process.env["CHAIN_INSIGHTS_CASES_ROOT"] = activeCasesRoot();
40
- }
41
- async function showCaseContext(caseSelector) {
42
- const { CaseStore } = await Promise.resolve().then(() => require("./cases-Bz_9XKEw.cjs")).then((n) => n.cases_exports);
43
- const caseId = await resolveCaseSelector(caseSelector);
44
- const ctx = await CaseStore.loadContext(caseId);
45
- console.log(`\n=== Case: ${ctx.case.id} ===`);
46
- console.log(`Name: ${ctx.case.name}`);
47
- console.log(`Status: ${ctx.case.status}`);
48
- console.log(`Tags: ${ctx.case.tags.join(", ") || "none"}`);
49
- console.log(`Evidence files: ${ctx.evidenceCount}`);
50
- console.log(`Dossiers: ${ctx.dossierSummaries.length}`);
51
- if (ctx.lastSession) {
52
- console.log(`\n--- Last Session (${ctx.lastSession.sessionId}) ---`);
53
- console.log(ctx.lastSession.body.slice(0, 500));
54
- } else console.log("\nNo previous sessions.");
55
- if (ctx.dossierSummaries.length > 0) {
56
- console.log("\n--- Entity Dossiers ---");
57
- for (const d of ctx.dossierSummaries) console.log(` ${d.address} [${d.type}] tags: ${d.riskTags || "none"}`);
58
- }
59
- }
60
32
  function optionalNumber(value) {
61
33
  if (value === void 0) return void 0;
62
34
  const parsed = Number(value);
@@ -70,9 +42,9 @@ function optionalNumberArg(value, name) {
70
42
  throw new Error(`Invalid number for ${name}: ${String(value)}`);
71
43
  }
72
44
  async function withGraphMcpClient(name, fn) {
73
- const { loadConfig } = await Promise.resolve().then(() => require("./config-BwVx19Og.cjs")).then((n) => n.config_exports);
45
+ const { loadConfig } = await Promise.resolve().then(() => require("./config-CkW404Cs.cjs")).then((n) => n.config_exports);
74
46
  const config = await loadConfig();
75
- const { createConfiguredGraphMcpFetch, resolveGraphMcpEndpoint } = await Promise.resolve().then(() => require("./client-Y_zqKqJT.cjs")).then((n) => n.client_exports);
47
+ const { createConfiguredGraphMcpFetch, resolveGraphMcpEndpoint } = await Promise.resolve().then(() => require("./client-BY-56ojr.cjs")).then((n) => n.client_exports);
76
48
  const paymentFetch = await createConfiguredGraphMcpFetch(config);
77
49
  const { Client } = await import("@modelcontextprotocol/sdk/client/index.js");
78
50
  const { StreamableHTTPClientTransport } = await import("@modelcontextprotocol/sdk/client/streamableHttp.js");
@@ -90,9 +62,51 @@ async function withGraphMcpClient(name, fn) {
90
62
  function printMcpTextContent(result) {
91
63
  for (const item of result.content ?? []) if (item.type === "text") console.log(item.text);
92
64
  }
65
+ function addExposureSubjectOptions(command) {
66
+ return command.requiredOption("--network <network>", "Network to query. Run `cia mcp networks` for supported networks.").option("--account <address>", "Account address to inspect").option("--owner <address>", "Owner address to inspect").option("--counterparty <address>", "Counterparty address to inspect").option("--venue <name>", "Optional venue filter, for example Bittensor or Hyperliquid").option("--instrument <id>", "Optional instrument filter, for example a subnet lifecycle id or BTC-PERP").option("--instrument-type <type>", "Optional instrument type filter, for example subnet, perp, spot, vault, or staking").option("--start-timestamp-ms <milliseconds>", "Optional inclusive lower activity timestamp bound").option("--end-timestamp-ms <milliseconds>", "Optional inclusive upper activity timestamp bound").option("--limit <number>", "Maximum exposure rows, default 100, max 500");
67
+ }
68
+ function addExposureMarketOptions(command, requiredInstrument, includeNetwork = true) {
69
+ let configured = command.option("--venue <name>", "Optional venue filter, for example Bittensor or Hyperliquid").option("--market <id>", "Alias for --instrument when using market language").option("--instrument-type <type>", "Optional instrument type filter, for example subnet, perp, spot, vault, or staking").option("--start-timestamp-ms <milliseconds>", "Optional inclusive lower activity timestamp bound").option("--end-timestamp-ms <milliseconds>", "Optional inclusive upper activity timestamp bound").option("--limit <number>", "Maximum exposure rows, default 100, max 500");
70
+ if (includeNetwork) configured = configured.requiredOption("--network <network>", "Network to query. Run `cia mcp networks` for supported networks.");
71
+ return requiredInstrument ? configured.requiredOption("--instrument <id>", "Instrument, market, subnet, hotkey, vault, or durable exposure target identifier to inspect") : configured.option("--instrument <id>", "Instrument, market, subnet, hotkey, vault, or durable exposure target identifier to inspect");
72
+ }
73
+ function buildExposureInsightCommand(name, tool, description) {
74
+ const command = new commander.Command(name).description(description);
75
+ const configured = tool === "exposure_crowding" ? addExposureMarketOptions(command, true) : tool === "exposure_exit_pressure" ? addExposureSubjectOptions(command).option("--market <id>", "Alias for --instrument when using market language") : addExposureSubjectOptions(command);
76
+ if (tool === "exposure_correlation") configured.option("--candidate-accounts <addresses>", "Comma-separated candidate accounts to compare against");
77
+ if (tool === "exposure_explain") configured.option("--market <id>", "Alias for --instrument when using market language").option("--position-id <id>", "Optional venue-native position, trade, stake, rotation, or lifecycle identifier");
78
+ return configured.action(async (opts) => {
79
+ try {
80
+ await withGraphMcpClient(`chain-insights-cli-${name}`, async (client) => {
81
+ const { exposureCarry, exposureCorrelation, exposureCrowding, exposureExitPressure, exposureExplain, exposureQuality } = await Promise.resolve().then(() => require("./public-tools-BREojpU7.cjs"));
82
+ const args = {
83
+ network: opts.network,
84
+ account: opts.account,
85
+ owner: opts.owner,
86
+ counterparty: opts.counterparty,
87
+ venue: opts.venue,
88
+ instrument: opts.instrument,
89
+ market: opts.market,
90
+ instrumentType: opts.instrumentType,
91
+ startTimestampMs: optionalNumber(opts.startTimestampMs),
92
+ endTimestampMs: optionalNumber(opts.endTimestampMs),
93
+ limit: optionalNumber(opts.limit),
94
+ candidateAccounts: opts.candidateAccounts,
95
+ positionId: opts.positionId
96
+ };
97
+ const result = tool === "exposure_quality" ? await exposureQuality(client, args) : tool === "exposure_carry" ? await exposureCarry(client, args) : tool === "exposure_crowding" ? await exposureCrowding(client, args) : tool === "exposure_exit_pressure" ? await exposureExitPressure(client, args) : tool === "exposure_correlation" ? await exposureCorrelation(client, args) : await exposureExplain(client, args);
98
+ console.log(result.summaryText);
99
+ console.log(JSON.stringify(result.structuredContent, null, 2));
100
+ });
101
+ } catch (err) {
102
+ console.error(err.message);
103
+ process.exit(1);
104
+ }
105
+ });
106
+ }
93
107
  async function printNetworkCapabilities(opts) {
94
- const { loadConfig } = await Promise.resolve().then(() => require("./config-BwVx19Og.cjs")).then((n) => n.config_exports);
95
- const { fetchNetworkCapabilities, formatNetworkCapabilities } = await Promise.resolve().then(() => require("./capabilities-DOa6EFO-.cjs"));
108
+ const { loadConfig } = await Promise.resolve().then(() => require("./config-CkW404Cs.cjs")).then((n) => n.config_exports);
109
+ const { fetchNetworkCapabilities, formatNetworkCapabilities } = await Promise.resolve().then(() => require("./capabilities-DGeF-oHc.cjs"));
96
110
  const document = await fetchNetworkCapabilities(await loadConfig());
97
111
  if (opts.json) console.log(JSON.stringify(document, null, 2));
98
112
  else console.log(formatNetworkCapabilities(document));
@@ -107,9 +121,9 @@ program.command("networks").alias("network").description("List supported graph n
107
121
  });
108
122
  program.command("serve").description("Start local visualization server").option("-p, --port <number>", "Port to bind (default: 4321)", "4321").action(async (opts) => {
109
123
  try {
110
- const { requireWorkspaceRoot } = await Promise.resolve().then(() => require("./output-root-YIbl6PwF.cjs")).then((n) => n.output_root_exports);
124
+ const { requireWorkspaceRoot } = await Promise.resolve().then(() => require("./output-root-DI0tzA0X.cjs")).then((n) => n.output_root_exports);
111
125
  const workspaceRoot = requireWorkspaceRoot();
112
- const { startServer } = await Promise.resolve().then(() => require("./server-BqVdWath.cjs")).then((n) => n.server_exports);
126
+ const { startServer } = await Promise.resolve().then(() => require("./server-ColyTG1t.cjs")).then((n) => n.server_exports);
113
127
  console.log(`Workspace: ${workspaceRoot}`);
114
128
  startServer(parseInt(opts.port, 10));
115
129
  } catch (err) {
@@ -118,8 +132,8 @@ program.command("serve").description("Start local visualization server").option(
118
132
  }
119
133
  });
120
134
  program.command("status").description("Show toolkit status and configuration").action(async () => {
121
- const { loadConfig } = await Promise.resolve().then(() => require("./config-BwVx19Og.cjs")).then((n) => n.config_exports);
122
- const { findActiveWorkspace, activeDataDir } = await Promise.resolve().then(() => require("./active-BVr55kvW.cjs")).then((n) => n.active_exports);
135
+ const { loadConfig } = await Promise.resolve().then(() => require("./config-CkW404Cs.cjs")).then((n) => n.config_exports);
136
+ const { findActiveWorkspace, activeDataDir } = await Promise.resolve().then(() => require("./active-XWv72R1X.cjs")).then((n) => n.active_exports);
123
137
  const config = await loadConfig();
124
138
  const workspace = findActiveWorkspace();
125
139
  const graphMcpStatus = config.graphMcpMode === "debug" && config.graphMcpAuthToken?.trim() ? "bearer access mode" : `${config.graphMcpMode} mode`;
@@ -154,28 +168,9 @@ program.command("update").description("Check npmjs for a newer Chain Insights re
154
168
  process.exit(1);
155
169
  }
156
170
  });
157
- program.command("obsidian").description("Manage the local Obsidian investigation vault").addCommand(new commander.Command("open").description("Open the current Chain Insights vault in Obsidian").argument("[path]", "Workspace path to open as an Obsidian vault").action(async (workspacePath) => {
158
- try {
159
- const { findActiveWorkspace } = await Promise.resolve().then(() => require("./active-BVr55kvW.cjs")).then((n) => n.active_exports);
160
- const workspace = workspacePath ? node_path.default.resolve(workspacePath) : findActiveWorkspace()?.root;
161
- if (!workspace) {
162
- console.error("No Chain Insights workspace found. Run: cia init .");
163
- process.exit(1);
164
- }
165
- const open = (await import("open")).default;
166
- await open(workspace, {
167
- app: { name: "obsidian" },
168
- wait: false
169
- });
170
- } catch (err) {
171
- console.error(err.message);
172
- console.error("Open Obsidian manually and choose \"Open folder as vault\" for this workspace.");
173
- process.exit(1);
174
- }
175
- }));
176
171
  program.command("debug").description("Configure Graph MCP debug mode").addCommand(new commander.Command("on").description("Enable Graph MCP debug mode without x402 payments").requiredOption("--token <token>", "Debug bearer token").option("--endpoint <url>", "Graph MCP endpoint").action(async (opts) => {
177
172
  try {
178
- const { saveConfig } = await Promise.resolve().then(() => require("./config-BwVx19Og.cjs")).then((n) => n.config_exports);
173
+ const { saveConfig } = await Promise.resolve().then(() => require("./config-CkW404Cs.cjs")).then((n) => n.config_exports);
179
174
  await saveConfig({
180
175
  graphMcpMode: "debug",
181
176
  graphMcpAuthToken: opts.token,
@@ -190,7 +185,7 @@ program.command("debug").description("Configure Graph MCP debug mode").addComman
190
185
  }
191
186
  })).addCommand(new commander.Command("off").description("Disable Graph MCP debug mode and use paid x402 calls").action(async () => {
192
187
  try {
193
- const { saveConfig } = await Promise.resolve().then(() => require("./config-BwVx19Og.cjs")).then((n) => n.config_exports);
188
+ const { saveConfig } = await Promise.resolve().then(() => require("./config-CkW404Cs.cjs")).then((n) => n.config_exports);
194
189
  await saveConfig({
195
190
  graphMcpMode: "paid",
196
191
  graphMcpAuthToken: ""
@@ -203,7 +198,7 @@ program.command("debug").description("Configure Graph MCP debug mode").addComman
203
198
  }
204
199
  })).addCommand(new commander.Command("status").description("Show Graph MCP payment/debug mode").action(async () => {
205
200
  try {
206
- const { loadConfig } = await Promise.resolve().then(() => require("./config-BwVx19Og.cjs")).then((n) => n.config_exports);
201
+ const { loadConfig } = await Promise.resolve().then(() => require("./config-CkW404Cs.cjs")).then((n) => n.config_exports);
207
202
  const config = await loadConfig();
208
203
  console.log(`Graph MCP mode: ${config.graphMcpMode}`);
209
204
  console.log(`Graph endpoint: ${config.graphMcpEndpoint}`);
@@ -218,7 +213,7 @@ program.command("access-key").description("Configure Graph MCP test access key m
218
213
  try {
219
214
  const normalizedKey = key.trim();
220
215
  if (!normalizedKey) throw new Error("Test access key is required");
221
- const { saveConfig } = await Promise.resolve().then(() => require("./config-BwVx19Og.cjs")).then((n) => n.config_exports);
216
+ const { saveConfig } = await Promise.resolve().then(() => require("./config-CkW404Cs.cjs")).then((n) => n.config_exports);
222
217
  await saveConfig({
223
218
  graphMcpMode: "debug",
224
219
  graphMcpAuthToken: normalizedKey,
@@ -233,7 +228,7 @@ program.command("access-key").description("Configure Graph MCP test access key m
233
228
  }
234
229
  })).addCommand(new commander.Command("clear").description("Remove the Graph MCP test access key and use paid x402 calls").action(async () => {
235
230
  try {
236
- const { saveConfig } = await Promise.resolve().then(() => require("./config-BwVx19Og.cjs")).then((n) => n.config_exports);
231
+ const { saveConfig } = await Promise.resolve().then(() => require("./config-CkW404Cs.cjs")).then((n) => n.config_exports);
237
232
  await saveConfig({
238
233
  graphMcpMode: "paid",
239
234
  graphMcpAuthToken: ""
@@ -246,7 +241,7 @@ program.command("access-key").description("Configure Graph MCP test access key m
246
241
  }
247
242
  })).addCommand(new commander.Command("status").description("Show Graph MCP test access key status").action(async () => {
248
243
  try {
249
- const { loadConfig } = await Promise.resolve().then(() => require("./config-BwVx19Og.cjs")).then((n) => n.config_exports);
244
+ const { loadConfig } = await Promise.resolve().then(() => require("./config-CkW404Cs.cjs")).then((n) => n.config_exports);
250
245
  const config = await loadConfig();
251
246
  console.log(`Graph endpoint: ${config.graphMcpEndpoint}`);
252
247
  console.log(`Access key: ${config.graphMcpAuthToken?.trim() ? "configured" : "not configured"}`);
@@ -258,7 +253,7 @@ program.command("access-key").description("Configure Graph MCP test access key m
258
253
  }));
259
254
  program.command("init").description("Initialize an investigation workspace").argument("[dir]", "Workspace directory to initialize", ".").option("--force", "Overwrite existing workspace files").action(async (dir, opts) => {
260
255
  try {
261
- const { initWorkspace } = await Promise.resolve().then(() => require("./init-Dhw8F23z.cjs"));
256
+ const { initWorkspace } = await Promise.resolve().then(() => require("./init-Cuw9TznI.cjs"));
262
257
  const result = await initWorkspace({
263
258
  targetDir: dir,
264
259
  force: opts.force
@@ -295,8 +290,8 @@ program.command("setup").description("Configure external MCP clients").addComman
295
290
  }
296
291
  }));
297
292
  program.command("config").description("Read or write configuration values").addCommand(new commander.Command("get").argument("<key>", "Config key to read").action(async (key) => {
298
- const { loadConfig } = await Promise.resolve().then(() => require("./config-BwVx19Og.cjs")).then((n) => n.config_exports);
299
- const { CONFIG_KEYS } = await Promise.resolve().then(() => require("./schema-Vl9yuOFO.cjs")).then((n) => n.schema_exports);
293
+ const { loadConfig } = await Promise.resolve().then(() => require("./config-CkW404Cs.cjs")).then((n) => n.config_exports);
294
+ const { CONFIG_KEYS } = await Promise.resolve().then(() => require("./schema-Dr6JXSOF.cjs")).then((n) => n.schema_exports);
300
295
  if (!CONFIG_KEYS.includes(key)) {
301
296
  console.error(`Unknown config key: ${key}`);
302
297
  process.exit(1);
@@ -316,8 +311,8 @@ program.command("config").description("Read or write configuration values").addC
316
311
  }
317
312
  return;
318
313
  }
319
- const { loadConfig, saveConfig } = await Promise.resolve().then(() => require("./config-BwVx19Og.cjs")).then((n) => n.config_exports);
320
- const { CONFIG_KEYS, DEFAULT_CONFIG } = await Promise.resolve().then(() => require("./schema-Vl9yuOFO.cjs")).then((n) => n.schema_exports);
314
+ const { loadConfig, saveConfig } = await Promise.resolve().then(() => require("./config-CkW404Cs.cjs")).then((n) => n.config_exports);
315
+ const { CONFIG_KEYS, DEFAULT_CONFIG } = await Promise.resolve().then(() => require("./schema-Dr6JXSOF.cjs")).then((n) => n.schema_exports);
321
316
  const current = await loadConfig();
322
317
  if (!CONFIG_KEYS.includes(key)) {
323
318
  console.error(`Unknown config key: ${key}`);
@@ -408,9 +403,9 @@ program.command("mcp").description("Interact with the Chain Insights MCP endpoin
408
403
  try {
409
404
  const { loadSchema, saveSchema } = await Promise.resolve().then(() => require("./schema-cache-CJk1EL3L.cjs"));
410
405
  const { formatToolsTable } = await Promise.resolve().then(() => require("./format-9NLBykEL.cjs"));
411
- const { visibleRemoteTools } = await Promise.resolve().then(() => require("./tool-visibility-Buq7YdUZ.cjs")).then((n) => n.tool_visibility_exports);
412
- const { loadConfig } = await Promise.resolve().then(() => require("./config-BwVx19Og.cjs")).then((n) => n.config_exports);
413
- const { createConfiguredGraphMcpFetch, resolveGraphMcpEndpoint } = await Promise.resolve().then(() => require("./client-Y_zqKqJT.cjs")).then((n) => n.client_exports);
406
+ const { visibleRemoteTools } = await Promise.resolve().then(() => require("./tool-visibility--QPgrRE5.cjs")).then((n) => n.tool_visibility_exports);
407
+ const { loadConfig } = await Promise.resolve().then(() => require("./config-CkW404Cs.cjs")).then((n) => n.config_exports);
408
+ const { createConfiguredGraphMcpFetch, resolveGraphMcpEndpoint } = await Promise.resolve().then(() => require("./client-BY-56ojr.cjs")).then((n) => n.client_exports);
414
409
  const config = await loadConfig();
415
410
  const graphMcpEndpoint = resolveGraphMcpEndpoint(config);
416
411
  let tools = opts.refresh ? null : await loadSchema(graphMcpEndpoint);
@@ -435,12 +430,12 @@ program.command("mcp").description("Interact with the Chain Insights MCP endpoin
435
430
  console.error(err.message);
436
431
  process.exit(1);
437
432
  }
438
- })).addCommand(new commander.Command("address-risk").description("Screen an address for risk, exchange behavior, and optional compare_address connection risk").requiredOption("--address <address>", "Full blockchain address to screen").requiredOption("--network <network>", "Network to query. Run `cia mcp networks` for supported networks.").option("--compare-address <address>", "Optional second address for connection-risk compare mode").option("--remote", "Force remote MCP tool call instead of local Chain Insights recipe").action(async (opts) => {
433
+ })).addCommand(new commander.Command("aml-address-risk").description("Screen an address for risk, exchange behavior, and optional compare_address connection risk").requiredOption("--address <address>", "Full blockchain address to screen").requiredOption("--network <network>", "Network to query. Run `cia mcp networks` for supported networks.").option("--compare-address <address>", "Optional second address for connection-risk compare mode").option("--remote", "Force remote MCP tool call instead of local Chain Insights recipe").action(async (opts) => {
439
434
  try {
440
- await withGraphMcpClient("chain-insights-cli-address-risk", async (client) => {
435
+ await withGraphMcpClient("chain-insights-cli-aml-address-risk", async (client) => {
441
436
  if (opts.remote) {
442
437
  printMcpTextContent(await client.callTool({
443
- name: "address_risk",
438
+ name: "aml_address_risk",
444
439
  arguments: {
445
440
  address: opts.address,
446
441
  network: opts.network,
@@ -449,7 +444,7 @@ program.command("mcp").description("Interact with the Chain Insights MCP endpoin
449
444
  }));
450
445
  return;
451
446
  }
452
- const { addressRisk } = await Promise.resolve().then(() => require("./public-tools-BY3PTw6x.cjs"));
447
+ const { addressRisk } = await Promise.resolve().then(() => require("./public-tools-BREojpU7.cjs"));
453
448
  const result = await addressRisk(client, {
454
449
  address: opts.address,
455
450
  network: opts.network,
@@ -461,14 +456,14 @@ program.command("mcp").description("Interact with the Chain Insights MCP endpoin
461
456
  console.error(err.message);
462
457
  process.exit(1);
463
458
  }
464
- })).addCommand(new commander.Command("trace-victim-funds").description("Trace victim/source addresses forward to exchange deposit candidates").requiredOption("--victim-addresses <addresses>", "Comma-separated full victim/source addresses, max 5").requiredOption("--network <network>", "Network to query. Run `cia mcp networks` for supported networks.").option("--known-suspect-addresses <addresses>", "Optional known suspect addresses for context only, max 5").option("--case <id>", "Case ID to attach compact evidence pointers").option("--incident-timestamp-ms <milliseconds>", "Optional incident timestamp in milliseconds").option("--max-hops <number>", "Maximum trace hops, 1-5").option("--per-address-limit <number>", "Maximum exchange paths/results per address, 1-10").option("--min-amount-sum <number>", "Minimum r.amount_sum for traced edges").option("--remote", "Force remote MCP tool call instead of local Chain Insights recipe").action(async (opts) => {
459
+ })).addCommand(new commander.Command("aml-trace-victim-funds").description("Trace victim/source addresses forward to exchange deposit candidates").requiredOption("--victim-addresses <addresses>", "Comma-separated full victim/source addresses, max 5").requiredOption("--network <network>", "Network to query. Run `cia mcp networks` for supported networks.").option("--known-suspect-addresses <addresses>", "Optional known suspect addresses for context only, max 5").option("--incident-timestamp-ms <milliseconds>", "Optional incident timestamp in milliseconds").option("--max-hops <number>", "Maximum trace hops, 1-5").option("--per-address-limit <number>", "Maximum exchange paths/results per address, 1-10").option("--min-amount-sum <number>", "Minimum r.amount_sum for traced edges").option("--remote", "Force remote MCP tool call instead of local Chain Insights recipe").action(async (opts) => {
465
460
  try {
466
- const { requireWorkspaceRoot } = await Promise.resolve().then(() => require("./output-root-YIbl6PwF.cjs")).then((n) => n.output_root_exports);
461
+ const { requireWorkspaceRoot } = await Promise.resolve().then(() => require("./output-root-DI0tzA0X.cjs")).then((n) => n.output_root_exports);
467
462
  requireWorkspaceRoot();
468
- await withGraphMcpClient("chain-insights-cli-trace-victim-funds", async (client, config) => {
463
+ await withGraphMcpClient("chain-insights-cli-aml-trace-victim-funds", async (client, config) => {
469
464
  if (opts.remote) {
470
465
  printMcpTextContent(await client.callTool({
471
- name: "trace_victim_funds",
466
+ name: "aml_trace_victim_funds",
472
467
  arguments: {
473
468
  victim_addresses: opts.victimAddresses,
474
469
  network: opts.network,
@@ -477,13 +472,11 @@ program.command("mcp").description("Interact with the Chain Insights MCP endpoin
477
472
  }));
478
473
  return;
479
474
  }
480
- const { traceVictimFunds } = await Promise.resolve().then(() => require("./public-tools-BY3PTw6x.cjs"));
481
- const caseId = opts.case ? await resolveCaseSelector(opts.case) : void 0;
475
+ const { traceVictimFunds } = await Promise.resolve().then(() => require("./public-tools-BREojpU7.cjs"));
482
476
  const result = await traceVictimFunds(client, config, {
483
477
  victimAddresses: opts.victimAddresses,
484
478
  knownSuspectAddresses: opts.knownSuspectAddresses,
485
479
  network: opts.network,
486
- caseId,
487
480
  incidentTimestampMs: optionalNumber(opts.incidentTimestampMs),
488
481
  maxHops: optionalNumber(opts.maxHops),
489
482
  perAddressLimit: optionalNumber(opts.perAddressLimit),
@@ -496,21 +489,19 @@ program.command("mcp").description("Interact with the Chain Insights MCP endpoin
496
489
  console.error(err.message);
497
490
  process.exit(1);
498
491
  }
499
- })).addCommand(new commander.Command("trace-suspect-funds").description("Trace suspected scammer, mule, operator, or laundering-ring addresses forward to cashout topology").requiredOption("--network <network>", "Network to query. Run `cia mcp networks` for supported networks.").requiredOption("--suspect-addresses <addresses>", "Comma-separated full suspect-controlled addresses, max 5").option("--incident-timestamp-ms <milliseconds>", "Optional incident timestamp in milliseconds").option("--max-hops <number>", "Maximum trace hops, default 3, max 5").option("--per-address-limit <number>", "Maximum exchange paths/results per address, 1-10").option("--min-amount-sum <number>", "Minimum r.amount_sum for traced edges").option("--case <id>", "Case ID to attach compact evidence pointers").action(async (opts) => {
492
+ })).addCommand(new commander.Command("aml-trace-suspect-funds").description("Trace suspected scammer, mule, operator, or laundering-ring addresses forward to cashout topology").requiredOption("--network <network>", "Network to query. Run `cia mcp networks` for supported networks.").requiredOption("--suspect-addresses <addresses>", "Comma-separated full suspect-controlled addresses, max 5").option("--incident-timestamp-ms <milliseconds>", "Optional incident timestamp in milliseconds").option("--max-hops <number>", "Maximum trace hops, default 3, max 5").option("--per-address-limit <number>", "Maximum exchange paths/results per address, 1-10").option("--min-amount-sum <number>", "Minimum r.amount_sum for traced edges").action(async (opts) => {
500
493
  try {
501
- const { requireWorkspaceRoot } = await Promise.resolve().then(() => require("./output-root-YIbl6PwF.cjs")).then((n) => n.output_root_exports);
494
+ const { requireWorkspaceRoot } = await Promise.resolve().then(() => require("./output-root-DI0tzA0X.cjs")).then((n) => n.output_root_exports);
502
495
  requireWorkspaceRoot();
503
- await withGraphMcpClient("chain-insights-cli-trace-suspect-funds", async (client, config) => {
504
- const { traceSuspectFunds } = await Promise.resolve().then(() => require("./public-tools-BY3PTw6x.cjs"));
505
- const caseId = opts.case ? await resolveCaseSelector(opts.case) : void 0;
496
+ await withGraphMcpClient("chain-insights-cli-aml-trace-suspect-funds", async (client, config) => {
497
+ const { traceSuspectFunds } = await Promise.resolve().then(() => require("./public-tools-BREojpU7.cjs"));
506
498
  const result = await traceSuspectFunds(client, config, {
507
499
  suspectAddresses: opts.suspectAddresses,
508
500
  network: opts.network,
509
501
  maxHops: optionalNumber(opts.maxHops),
510
502
  perAddressLimit: optionalNumber(opts.perAddressLimit),
511
503
  minAmountSum: optionalNumber(opts.minAmountSum),
512
- incidentTimestampMs: optionalNumber(opts.incidentTimestampMs),
513
- caseId
504
+ incidentTimestampMs: optionalNumber(opts.incidentTimestampMs)
514
505
  });
515
506
  console.log(result.summaryText);
516
507
  console.log(JSON.stringify(result.structuredContent, null, 2));
@@ -519,18 +510,16 @@ program.command("mcp").description("Interact with the Chain Insights MCP endpoin
519
510
  console.error(err.message);
520
511
  process.exit(1);
521
512
  }
522
- })).addCommand(new commander.Command("trace-deposit-sources").description("Trace backward from suspected deposit/cashout addresses to upstream sources and convergence").requiredOption("--network <network>", "Network to query. Run `cia mcp networks` for supported networks.").requiredOption("--deposit-addresses <addresses>", "Comma-separated full suspected deposit/cashout addresses, max 5").option("--max-hops <number>", "Maximum reverse traceback hops, default 2, max 5").option("--case <id>", "Case ID to attach compact evidence pointers").action(async (opts) => {
513
+ })).addCommand(new commander.Command("aml-trace-deposit-sources").description("Trace backward from suspected deposit/cashout addresses to upstream sources and convergence").requiredOption("--network <network>", "Network to query. Run `cia mcp networks` for supported networks.").requiredOption("--deposit-addresses <addresses>", "Comma-separated full suspected deposit/cashout addresses, max 5").option("--max-hops <number>", "Maximum reverse traceback hops, default 2, max 5").action(async (opts) => {
523
514
  try {
524
- const { requireWorkspaceRoot } = await Promise.resolve().then(() => require("./output-root-YIbl6PwF.cjs")).then((n) => n.output_root_exports);
515
+ const { requireWorkspaceRoot } = await Promise.resolve().then(() => require("./output-root-DI0tzA0X.cjs")).then((n) => n.output_root_exports);
525
516
  requireWorkspaceRoot();
526
- await withGraphMcpClient("chain-insights-cli-trace-deposit-sources", async (client, config) => {
527
- const { traceDepositSources } = await Promise.resolve().then(() => require("./public-tools-BY3PTw6x.cjs"));
528
- const caseId = opts.case ? await resolveCaseSelector(opts.case) : void 0;
517
+ await withGraphMcpClient("chain-insights-cli-aml-trace-deposit-sources", async (client, config) => {
518
+ const { traceDepositSources } = await Promise.resolve().then(() => require("./public-tools-BREojpU7.cjs"));
529
519
  const result = await traceDepositSources(client, config, {
530
520
  depositAddresses: opts.depositAddresses,
531
521
  network: opts.network,
532
- maxHops: optionalNumber(opts.maxHops),
533
- caseId
522
+ maxHops: optionalNumber(opts.maxHops)
534
523
  });
535
524
  console.log(result.summaryText);
536
525
  console.log(JSON.stringify(result.structuredContent, null, 2));
@@ -539,21 +528,21 @@ program.command("mcp").description("Interact with the Chain Insights MCP endpoin
539
528
  console.error(err.message);
540
529
  process.exit(1);
541
530
  }
542
- })).addCommand(new commander.Command("stake-insights").description("Explain Bittensor staking behavior around an address, coldkey, or hotkey").requiredOption("--network <network>", "Network to query. Run `cia mcp networks` for supported networks.").option("--address <address>", "Full Bittensor address to inspect as either coldkey or hotkey").option("--coldkey <address>", "Full Bittensor coldkey address to inspect").option("--hotkey <address>", "Full Bittensor hotkey address to inspect").option("--netuid <number>", "Optional subnet netuid filter").option("--start-timestamp-ms <milliseconds>", "Optional inclusive lower activity timestamp bound").option("--end-timestamp-ms <milliseconds>", "Optional inclusive upper activity timestamp bound").option("--start-block <number>", "Optional start block. Current stake graph parity may require timestamp windows instead.").option("--end-block <number>", "Optional end block. Current stake graph parity may require timestamp windows instead.").option("--depth <number>", "Optional expansion depth limit, default 1, max 3").action(async (opts) => {
531
+ })).addCommand(new commander.Command("exposure-profile").description("Explain staking or trading exposure around one account, owner, or counterparty").requiredOption("--network <network>", "Network to query. Run `cia mcp networks` for supported networks.").option("--account <address>", "Account address to inspect").option("--owner <address>", "Owner address to inspect").option("--counterparty <address>", "Counterparty address to inspect").option("--venue <name>", "Optional venue filter, for example Bittensor or Hyperliquid").option("--instrument <id>", "Optional instrument filter, for example a subnet lifecycle id or BTC-PERP").option("--instrument-type <type>", "Optional instrument type filter, for example subnet, perp, spot, vault, or staking").option("--start-timestamp-ms <milliseconds>", "Optional inclusive lower activity timestamp bound").option("--end-timestamp-ms <milliseconds>", "Optional inclusive upper activity timestamp bound").option("--limit <number>", "Maximum exposure rows, default 100, max 500").action(async (opts) => {
543
532
  try {
544
- await withGraphMcpClient("chain-insights-cli-stake-insights", async (client) => {
545
- const { stakeInsights } = await Promise.resolve().then(() => require("./public-tools-BY3PTw6x.cjs"));
546
- const result = await stakeInsights(client, {
533
+ await withGraphMcpClient("chain-insights-cli-exposure-profile", async (client) => {
534
+ const { exposureProfile } = await Promise.resolve().then(() => require("./public-tools-BREojpU7.cjs"));
535
+ const result = await exposureProfile(client, {
547
536
  network: opts.network,
548
- address: opts.address,
549
- coldkey: opts.coldkey,
550
- hotkey: opts.hotkey,
551
- netuid: optionalNumber(opts.netuid),
537
+ account: opts.account,
538
+ owner: opts.owner,
539
+ counterparty: opts.counterparty,
540
+ venue: opts.venue,
541
+ instrument: opts.instrument,
542
+ instrumentType: opts.instrumentType,
552
543
  startTimestampMs: optionalNumber(opts.startTimestampMs),
553
544
  endTimestampMs: optionalNumber(opts.endTimestampMs),
554
- startBlock: optionalNumber(opts.startBlock),
555
- endBlock: optionalNumber(opts.endBlock),
556
- depth: optionalNumber(opts.depth)
545
+ limit: optionalNumber(opts.limit)
557
546
  });
558
547
  console.log(result.summaryText);
559
548
  console.log(JSON.stringify(result.structuredContent, null, 2));
@@ -562,15 +551,15 @@ program.command("mcp").description("Interact with the Chain Insights MCP endpoin
562
551
  console.error(err.message);
563
552
  process.exit(1);
564
553
  }
565
- })).addCommand(new commander.Command("call").description("Call an MCP tool directly (debug)").argument("<tool>", "Tool name to call").argument("[args...]", "Key=value arguments (e.g. address=0x1234 chain=ethereum)").action(async (tool, rawArgs) => {
554
+ })).addCommand(buildExposureInsightCommand("exposure-quality", "exposure_quality", "Score whether exposure behavior looks disciplined, fragile, lucky, or noisy")).addCommand(buildExposureInsightCommand("exposure-carry", "exposure_carry", "Explain carry earned or paid by staking, trading, funding, fees, emissions, or dividends")).addCommand(buildExposureInsightCommand("exposure-crowding", "exposure_crowding", "Measure crowding and side concentration for a market, subnet, hotkey, vault, or strategy")).addCommand(buildExposureInsightCommand("exposure-exit-pressure", "exposure_exit_pressure", "Explain liquidation, slippage, funding pain, unstake, or other exit pressure")).addCommand(buildExposureInsightCommand("exposure-correlation", "exposure_correlation", "Compare accounts for possible copy, overlap, or strategy-cluster exposure behavior")).addCommand(buildExposureInsightCommand("exposure-explain", "exposure_explain", "Explain a specific exposure lifecycle, trade, position, stake, rotation, or incident")).addCommand(new commander.Command("call").description("Call an MCP tool directly (debug)").argument("<tool>", "Tool name to call").argument("[args...]", "Key=value arguments (e.g. address=0x1234 chain=ethereum)").action(async (tool, rawArgs) => {
566
555
  try {
567
556
  const { parseMcpCallArgs } = await Promise.resolve().then(() => require("./call-args-CcUV6gFS.cjs"));
568
- const { assertPublicMcpToolName } = await Promise.resolve().then(() => require("./tool-visibility-Buq7YdUZ.cjs")).then((n) => n.tool_visibility_exports);
557
+ const { assertPublicMcpToolName } = await Promise.resolve().then(() => require("./tool-visibility--QPgrRE5.cjs")).then((n) => n.tool_visibility_exports);
569
558
  const args = parseMcpCallArgs(rawArgs);
570
559
  assertPublicMcpToolName(tool);
571
560
  await withGraphMcpClient("chain-insights-cli-call", async (client, config) => {
572
- if (tool === "address_risk") {
573
- const { addressRisk } = await Promise.resolve().then(() => require("./public-tools-BY3PTw6x.cjs"));
561
+ if (tool === "aml_address_risk") {
562
+ const { addressRisk } = await Promise.resolve().then(() => require("./public-tools-BREojpU7.cjs"));
574
563
  const result = await addressRisk(client, {
575
564
  address: String(args["address"] ?? ""),
576
565
  network: String(args["network"] ?? ""),
@@ -579,13 +568,12 @@ program.command("mcp").description("Interact with the Chain Insights MCP endpoin
579
568
  console.log(result.summaryText);
580
569
  return;
581
570
  }
582
- if (tool === "trace_victim_funds") {
583
- const { traceVictimFunds } = await Promise.resolve().then(() => require("./public-tools-BY3PTw6x.cjs"));
571
+ if (tool === "aml_trace_victim_funds") {
572
+ const { traceVictimFunds } = await Promise.resolve().then(() => require("./public-tools-BREojpU7.cjs"));
584
573
  const result = await traceVictimFunds(client, config, {
585
574
  victimAddresses: args["victim_addresses"] ?? "",
586
575
  knownSuspectAddresses: args["known_suspect_addresses"],
587
576
  network: String(args["network"] ?? ""),
588
- caseId: args["case_id"] === void 0 ? void 0 : String(args["case_id"]),
589
577
  incidentTimestampMs: optionalNumberArg(args["incident_timestamp_ms"], "incident_timestamp_ms"),
590
578
  maxHops: typeof args["max_hops"] === "number" ? args["max_hops"] : void 0,
591
579
  perAddressLimit: typeof args["per_address_limit"] === "number" ? args["per_address_limit"] : void 0,
@@ -595,12 +583,11 @@ program.command("mcp").description("Interact with the Chain Insights MCP endpoin
595
583
  console.log(JSON.stringify(result.structuredContent, null, 2));
596
584
  return;
597
585
  }
598
- if (tool === "trace_suspect_funds") {
599
- const { traceSuspectFunds } = await Promise.resolve().then(() => require("./public-tools-BY3PTw6x.cjs"));
586
+ if (tool === "aml_trace_suspect_funds") {
587
+ const { traceSuspectFunds } = await Promise.resolve().then(() => require("./public-tools-BREojpU7.cjs"));
600
588
  const result = await traceSuspectFunds(client, config, {
601
589
  suspectAddresses: args["suspect_addresses"] ?? "",
602
590
  network: String(args["network"] ?? ""),
603
- caseId: args["case_id"] === void 0 ? void 0 : String(args["case_id"]),
604
591
  maxHops: typeof args["max_hops"] === "number" ? args["max_hops"] : void 0,
605
592
  perAddressLimit: typeof args["per_address_limit"] === "number" ? args["per_address_limit"] : void 0,
606
593
  minAmountSum: typeof args["min_amount_sum"] === "number" ? args["min_amount_sum"] : void 0,
@@ -610,36 +597,64 @@ program.command("mcp").description("Interact with the Chain Insights MCP endpoin
610
597
  console.log(JSON.stringify(result.structuredContent, null, 2));
611
598
  return;
612
599
  }
613
- if (tool === "trace_deposit_sources") {
614
- const { traceDepositSources } = await Promise.resolve().then(() => require("./public-tools-BY3PTw6x.cjs"));
600
+ if (tool === "aml_trace_deposit_sources") {
601
+ const { traceDepositSources } = await Promise.resolve().then(() => require("./public-tools-BREojpU7.cjs"));
615
602
  const result = await traceDepositSources(client, config, {
616
603
  depositAddresses: args["deposit_addresses"] ?? "",
617
604
  network: String(args["network"] ?? ""),
618
- caseId: args["case_id"] === void 0 ? void 0 : String(args["case_id"]),
619
605
  maxHops: typeof args["max_hops"] === "number" ? args["max_hops"] : void 0
620
606
  });
621
607
  console.log(result.summaryText);
622
608
  console.log(JSON.stringify(result.structuredContent, null, 2));
623
609
  return;
624
610
  }
625
- if (tool === "stake_insights") {
626
- const { stakeInsights } = await Promise.resolve().then(() => require("./public-tools-BY3PTw6x.cjs"));
627
- const result = await stakeInsights(client, {
611
+ if (tool === "exposure_profile") {
612
+ const { exposureProfile } = await Promise.resolve().then(() => require("./public-tools-BREojpU7.cjs"));
613
+ const result = await exposureProfile(client, {
628
614
  network: String(args["network"] ?? ""),
629
- address: args["address"] === void 0 ? void 0 : String(args["address"]),
630
- coldkey: args["coldkey"] === void 0 ? void 0 : String(args["coldkey"]),
631
- hotkey: args["hotkey"] === void 0 ? void 0 : String(args["hotkey"]),
632
- netuid: optionalNumberArg(args["netuid"], "netuid"),
615
+ account: args["account"] === void 0 ? void 0 : String(args["account"]),
616
+ owner: args["owner"] === void 0 ? void 0 : String(args["owner"]),
617
+ counterparty: args["counterparty"] === void 0 ? void 0 : String(args["counterparty"]),
618
+ venue: args["venue"] === void 0 ? void 0 : String(args["venue"]),
619
+ instrument: args["instrument"] === void 0 ? void 0 : String(args["instrument"]),
620
+ instrumentType: args["instrument_type"] === void 0 ? void 0 : String(args["instrument_type"]),
633
621
  startTimestampMs: optionalNumberArg(args["start_timestamp_ms"], "start_timestamp_ms"),
634
622
  endTimestampMs: optionalNumberArg(args["end_timestamp_ms"], "end_timestamp_ms"),
635
- startBlock: optionalNumberArg(args["start_block"], "start_block"),
636
- endBlock: optionalNumberArg(args["end_block"], "end_block"),
637
- depth: optionalNumberArg(args["depth"] ?? args["max_hops"], "depth")
623
+ limit: optionalNumberArg(args["limit"], "limit")
638
624
  });
639
625
  console.log(result.summaryText);
640
626
  console.log(JSON.stringify(result.structuredContent, null, 2));
641
627
  return;
642
628
  }
629
+ if ([
630
+ "exposure_quality",
631
+ "exposure_carry",
632
+ "exposure_crowding",
633
+ "exposure_exit_pressure",
634
+ "exposure_correlation",
635
+ "exposure_explain"
636
+ ].includes(tool)) {
637
+ const { exposureCarry, exposureCorrelation, exposureCrowding, exposureExitPressure, exposureExplain, exposureQuality } = await Promise.resolve().then(() => require("./public-tools-BREojpU7.cjs"));
638
+ const exposureArgs = {
639
+ network: String(args["network"] ?? ""),
640
+ account: args["account"] === void 0 ? void 0 : String(args["account"]),
641
+ owner: args["owner"] === void 0 ? void 0 : String(args["owner"]),
642
+ counterparty: args["counterparty"] === void 0 ? void 0 : String(args["counterparty"]),
643
+ venue: args["venue"] === void 0 ? void 0 : String(args["venue"]),
644
+ instrument: args["instrument"] === void 0 ? void 0 : String(args["instrument"]),
645
+ market: args["market"] === void 0 ? void 0 : String(args["market"]),
646
+ instrumentType: args["instrument_type"] === void 0 ? void 0 : String(args["instrument_type"]),
647
+ startTimestampMs: optionalNumberArg(args["start_timestamp_ms"], "start_timestamp_ms"),
648
+ endTimestampMs: optionalNumberArg(args["end_timestamp_ms"], "end_timestamp_ms"),
649
+ limit: optionalNumberArg(args["limit"], "limit"),
650
+ candidateAccounts: args["candidate_accounts"],
651
+ positionId: args["position_id"] === void 0 ? void 0 : String(args["position_id"])
652
+ };
653
+ const result = tool === "exposure_quality" ? await exposureQuality(client, exposureArgs) : tool === "exposure_carry" ? await exposureCarry(client, exposureArgs) : tool === "exposure_crowding" ? await exposureCrowding(client, exposureArgs) : tool === "exposure_exit_pressure" ? await exposureExitPressure(client, exposureArgs) : tool === "exposure_correlation" ? await exposureCorrelation(client, exposureArgs) : await exposureExplain(client, exposureArgs);
654
+ console.log(result.summaryText);
655
+ console.log(JSON.stringify(result.structuredContent, null, 2));
656
+ return;
657
+ }
643
658
  printMcpTextContent(await client.callTool({
644
659
  name: tool,
645
660
  arguments: args
@@ -650,289 +665,18 @@ program.command("mcp").description("Interact with the Chain Insights MCP endpoin
650
665
  process.exit(1);
651
666
  }
652
667
  }));
653
- const caseCommand = new commander.Command("case").description("Manage investigation cases").hook("preAction", async () => {
654
- await scopeCasesToInvocationDir();
655
- }).addCommand(new commander.Command("open").description("Open a new investigation case").argument("<name>", "Case name (e.g. \"Tornado Mixer Investigation\")").option("--tags <tags>", "Comma-separated tags (e.g. aml,mixer,defi)", "").option("--description <desc>", "Brief description of the investigation", "").action(async (name, opts) => {
656
- try {
657
- if (/^[1-9]\d*$/.test(name.trim())) throw new Error("Numeric case names look like list selectors. Use a descriptive case name, e.g. `cia case open \"Tracking stolen funds from <address>\"`.");
658
- const { CaseStore } = await Promise.resolve().then(() => require("./cases-Bz_9XKEw.cjs")).then((n) => n.cases_exports);
659
- const tags = opts.tags ? opts.tags.split(",").map((t) => t.trim()).filter(Boolean) : [];
660
- const c = await CaseStore.create({
661
- name,
662
- tags,
663
- description: opts.description
664
- });
665
- const { casesRoot } = await Promise.resolve().then(() => require("./store-CQhU8dz8.cjs")).then((n) => n.store_exports);
666
- console.log(`Case opened: ${c.id}`);
667
- console.log(`Directory: ${node_path.default.join(casesRoot(), c.id)}/`);
668
- console.log(`Status: ${c.status}`);
669
- const { findActiveWorkspace } = await Promise.resolve().then(() => require("./active-BVr55kvW.cjs")).then((n) => n.active_exports);
670
- if (findActiveWorkspace()) try {
671
- const { refreshCaseVault } = await Promise.resolve().then(() => require("./vault-B2y78Ypu.cjs"));
672
- const result = await refreshCaseVault({
673
- caseId: c.id,
674
- force: true
675
- });
676
- console.log(`Open first: ${result.nextFile}`);
677
- } catch (refreshErr) {
678
- console.error(`Warning: live vault refresh failed: ${refreshErr.message}`);
679
- console.error(`Run: cia case vault refresh ${c.id} --force`);
680
- }
681
- } catch (err) {
682
- console.error(err.message);
683
- process.exit(1);
684
- }
685
- })).addCommand(new commander.Command("activate").description("Activate a case (set status to active)").argument("<case-id>", "Case ID to activate").action(async (caseSelector) => {
686
- try {
687
- const { CaseStore } = await Promise.resolve().then(() => require("./cases-Bz_9XKEw.cjs")).then((n) => n.cases_exports);
688
- const caseId = await resolveCaseSelector(caseSelector);
689
- const c = await CaseStore.setStatus(caseId, "active");
690
- console.log(`Case ${c.id} is now: active`);
691
- } catch (err) {
692
- console.error(err.message);
693
- process.exit(1);
694
- }
695
- })).addCommand(new commander.Command("suspend").description("Suspend a case (set status to suspended)").argument("<case-id>", "Case ID to suspend").action(async (caseSelector) => {
696
- try {
697
- const { CaseStore } = await Promise.resolve().then(() => require("./cases-Bz_9XKEw.cjs")).then((n) => n.cases_exports);
698
- const caseId = await resolveCaseSelector(caseSelector);
699
- const c = await CaseStore.setStatus(caseId, "suspended");
700
- console.log(`Case ${c.id} is now: suspended`);
701
- } catch (err) {
702
- console.error(err.message);
703
- process.exit(1);
704
- }
705
- })).addCommand(new commander.Command("close").description("Close a case permanently").argument("<case-id>", "Case ID to close").action(async (caseSelector) => {
706
- try {
707
- const { CaseStore } = await Promise.resolve().then(() => require("./cases-Bz_9XKEw.cjs")).then((n) => n.cases_exports);
708
- const caseId = await resolveCaseSelector(caseSelector);
709
- const c = await CaseStore.setStatus(caseId, "closed");
710
- console.log(`Case ${c.id} is now: closed`);
711
- } catch (err) {
712
- console.error(err.message);
713
- process.exit(1);
714
- }
715
- })).addCommand(new commander.Command("list").description("List all investigation cases").option("--status <status>", "Filter by status (open|active|suspended|closed)").action(async (opts) => {
716
- try {
717
- const { CaseStore } = await Promise.resolve().then(() => require("./cases-Bz_9XKEw.cjs")).then((n) => n.cases_exports);
718
- const cases = await CaseStore.list();
719
- const filtered = opts.status ? cases.filter((c) => c.status === opts.status) : cases;
720
- if (filtered.length === 0) {
721
- console.log("No cases found.");
722
- return;
723
- }
724
- for (const [index, c] of filtered.entries()) console.log(`${index + 1}. ${c.id} [${c.status}] ${c.name}`);
725
- } catch (err) {
726
- console.error(err.message);
727
- process.exit(1);
728
- }
729
- })).addCommand(new commander.Command("evidence").description("Manage case evidence").addCommand(new commander.Command("add").description("Add evidence to a case from an MCP query result").argument("<case-id>", "Case ID to add evidence to").option("--source <tool>", "MCP tool name that produced this evidence", "manual").option("--content <text>", "Evidence content (MCP response or notes)", "").option("--query-params <params>", "Query parameters used (e.g. address=0x1234)", "").action(async (caseSelector, opts) => {
730
- try {
731
- const { EvidenceStore } = await Promise.resolve().then(() => require("./cases-Bz_9XKEw.cjs")).then((n) => n.cases_exports);
732
- const caseId = await resolveCaseSelector(caseSelector);
733
- const result = await EvidenceStore.append(caseId, {
734
- source: opts.source,
735
- content: opts.content,
736
- queryParams: opts.queryParams
737
- });
738
- console.log(`Evidence saved: ${result.filename}`);
739
- console.log(`SHA-256: ${result.sha256}`);
740
- } catch (err) {
741
- console.error(err.message);
742
- process.exit(1);
743
- }
744
- })).addCommand(new commander.Command("verify").description("Verify evidence manifest integrity for a case").argument("<case-id>", "Case ID to verify").action(async (caseSelector) => {
745
- try {
746
- const { EvidenceStore } = await Promise.resolve().then(() => require("./cases-Bz_9XKEw.cjs")).then((n) => n.cases_exports);
747
- const caseId = await resolveCaseSelector(caseSelector);
748
- const result = await EvidenceStore.verifyManifest(caseId);
749
- if (result.ok) console.log(`Manifest OK — ${result.count} evidence file(s) verified`);
750
- else {
751
- console.error(`Manifest FAILED — tampered files: ${(result.tampered ?? []).join(", ")}`);
752
- process.exit(1);
753
- }
754
- } catch (err) {
755
- console.error(err.message);
756
- process.exit(1);
757
- }
758
- }))).addCommand(new commander.Command("dossier").description("Manage entity dossiers for a case").addCommand(new commander.Command("update").description("Append a finding to an entity dossier").argument("<case-id>", "Case ID").argument("<address>", "Entity address or identifier").option("--finding <text>", "Finding to append to the dossier", "").option("--type <type>", "Entity type (eoa|contract|exchange|mixer|unknown)", "unknown").action(async (caseSelector, address, opts) => {
759
- try {
760
- const { DossierStore } = await Promise.resolve().then(() => require("./cases-Bz_9XKEw.cjs")).then((n) => n.cases_exports);
761
- const caseId = await resolveCaseSelector(caseSelector);
762
- const entityType = [
763
- "eoa",
764
- "contract",
765
- "exchange",
766
- "mixer",
767
- "unknown"
768
- ].includes(opts.type) ? opts.type : "unknown";
769
- await DossierStore.appendFinding(caseId, address, opts.finding, entityType);
770
- console.log(`Dossier updated for ${address}`);
771
- } catch (err) {
772
- console.error(err.message);
773
- process.exit(1);
774
- }
775
- }))).addCommand(new commander.Command("session").description("Manage investigation sessions").addCommand(new commander.Command("start").description("Start a new investigation session for a case").argument("<case-id>", "Case ID").argument("[title...]", "Optional session title").action(async (caseSelector, titleParts) => {
776
- try {
777
- const { SessionStore } = await Promise.resolve().then(() => require("./cases-Bz_9XKEw.cjs")).then((n) => n.cases_exports);
778
- const caseId = await resolveCaseSelector(caseSelector);
779
- const title = titleParts.join(" ").trim();
780
- const s = await SessionStore.start(caseId, title ? { title } : {});
781
- console.log(`Session started: ${s.sessionId}`);
782
- } catch (err) {
783
- console.error(err.message);
784
- process.exit(1);
785
- }
786
- })).addCommand(new commander.Command("end").description("End the current session with findings and next steps").argument("<case-id>", "Case ID").option("--findings <text>", "Key findings from this session", "").option("--next-steps <text>", "Next steps for the investigation", "").action(async (caseSelector, opts) => {
787
- try {
788
- const { SessionStore } = await Promise.resolve().then(() => require("./cases-Bz_9XKEw.cjs")).then((n) => n.cases_exports);
789
- const caseId = await resolveCaseSelector(caseSelector);
790
- await SessionStore.end(caseId, {
791
- findings: opts.findings,
792
- nextSteps: opts.nextSteps
793
- });
794
- await SessionStore.archiveOldSessions(caseId);
795
- console.log(`Session ended for case ${caseId}`);
796
- } catch (err) {
797
- console.error(err.message);
798
- process.exit(1);
799
- }
800
- }))).addCommand(new commander.Command("vault").description("Manage live Obsidian case vault notes").addCommand(new commander.Command("refresh").description("Refresh Obsidian vault notes for a case").argument("<case-id-or-selector>", "Case ID or case list number to refresh").option("--force", "Overwrite existing generated case vault files").action(async (caseSelector, opts) => {
801
- try {
802
- const caseId = await resolveCaseSelector(caseSelector);
803
- const { refreshCaseVault } = await Promise.resolve().then(() => require("./vault-B2y78Ypu.cjs"));
804
- const result = await refreshCaseVault({
805
- caseId,
806
- force: opts.force === true
807
- });
808
- console.log(`Case vault refreshed: ${caseId}`);
809
- console.log(`Files: ${result.filesWritten.length}`);
810
- console.log(`Open first: ${result.nextFile}`);
811
- } catch (err) {
812
- console.error(err.message);
813
- process.exit(1);
814
- }
815
- }))).addCommand(new commander.Command("export").description("Export a case for Obsidian, LLM Wiki, and agents").argument("<case-id>", "Case ID or case list number to export").option("--target <target>", "Export target: obsidian-llmwiki", "obsidian-llmwiki").option("--mode <mode>", "Redaction mode: private|partner|public", "private").option("--out <directory>", "Output directory. Defaults to published/<case-slug>").action(async (caseSelector, opts) => {
816
- try {
817
- const target = opts.target === "obsidian-llmwiki" ? opts.target : void 0;
818
- const mode = [
819
- "private",
820
- "partner",
821
- "public"
822
- ].includes(opts.mode) ? opts.mode : void 0;
823
- if (!target) throw new Error(`Unsupported export target: ${opts.target}`);
824
- if (!mode) throw new Error(`Unsupported export mode: ${opts.mode}`);
825
- const caseId = await resolveCaseSelector(caseSelector);
826
- const { exportCase } = await Promise.resolve().then(() => require("./export-D4v4-6F4.cjs"));
827
- const result = await exportCase({
828
- caseId,
829
- target,
830
- mode,
831
- outputDir: opts.out
832
- });
833
- console.log(`Case exported: ${result.outputDir}`);
834
- console.log(`Manifest: ${result.manifestPath}`);
835
- console.log(`Files: ${result.fileCount}`);
836
- console.log(`Open first: ${result.nextFile}`);
837
- for (const warning of result.warnings) console.warn(`Warning: ${warning}`);
838
- } catch (err) {
839
- console.error(err.message);
840
- process.exit(1);
841
- }
842
- })).addCommand(new commander.Command("show").description("Show saved case context").argument("<case-id>", "Case ID or case list number to show").action(async (caseSelector) => {
843
- try {
844
- await showCaseContext(caseSelector);
845
- } catch (err) {
846
- console.error(err.message);
847
- process.exit(1);
848
- }
849
- }));
850
- program.addCommand(caseCommand);
851
- program.command("playbook").description("Run and manage investigation playbooks").addCommand(new commander.Command("run").description("Execute a playbook by name").argument("<name>", "Playbook name (e.g. trace-funds, risk-check, entity-profile)").option("--case <id>", "Case ID to attach evidence to (auto-created if omitted)").option("--from <n>", "Resume from step N (1-based)", "1").option("--dry-run", "Show steps without executing").option("-p, --param <kv...>", "Parameters as key=value pairs (repeatable, e.g. -p address=0x1 -p hops=3)").action(async (name, opts) => {
852
- try {
853
- const resolvedParams = {};
854
- for (const kv of opts.param ?? []) {
855
- const eq = kv.indexOf("=");
856
- if (eq === -1) {
857
- console.error(`Invalid param format: "${kv}". Use key=value`);
858
- process.exit(1);
859
- }
860
- const key = kv.slice(0, eq);
861
- if (!key) {
862
- console.error(`Invalid param format: "${kv}". Key must be non-empty`);
863
- process.exit(1);
864
- }
865
- resolvedParams[key] = kv.slice(eq + 1);
866
- }
867
- const { resolvePlaybookContent } = await Promise.resolve().then(() => require("./resolver-CZdQwKvh.cjs"));
868
- const markdown = await resolvePlaybookContent(name);
869
- const { PlaybookParser } = await Promise.resolve().then(() => require("./parser-BXLAHYnZ.cjs"));
870
- const definition = PlaybookParser.parse(markdown, resolvedParams);
871
- for (const spec of definition.params) if (spec.required && !resolvedParams[spec.name] && !spec.default) {
872
- console.error(`Missing required param: ${spec.name}. Pass with: -p ${spec.name}=<value>`);
873
- process.exit(1);
874
- }
875
- const fromN = parseInt(opts.from, 10);
876
- if (isNaN(fromN) || fromN < 1) {
877
- console.error(`Invalid --from value: "${opts.from}". Must be a positive integer.`);
878
- process.exit(1);
879
- }
880
- const { PlaybookRunner } = await Promise.resolve().then(() => require("./runner-bLy0pTr_.cjs"));
881
- await PlaybookRunner.run(definition, {
882
- caseId: opts.case,
883
- from: fromN,
884
- dryRun: opts.dryRun,
885
- params: resolvedParams
886
- });
887
- } catch (err) {
888
- console.error(err.message);
889
- process.exit(1);
890
- }
891
- })).addCommand(new commander.Command("list").description("List available playbooks (built-in and user-defined)").action(async () => {
892
- try {
893
- const { listPlaybooks } = await Promise.resolve().then(() => require("./resolver-CZdQwKvh.cjs"));
894
- const playbooks = await listPlaybooks();
895
- if (playbooks.length === 0) {
896
- console.log("No playbooks found.");
897
- return;
898
- }
899
- for (const p of playbooks) console.log(` ${p.name.padEnd(20)} [${p.source}]`);
900
- } catch (err) {
901
- console.error(err.message);
902
- process.exit(1);
903
- }
904
- })).addCommand(new commander.Command("show").description("Show steps for a playbook without executing").argument("<name>", "Playbook name").action(async (name) => {
905
- try {
906
- const { resolvePlaybookContent } = await Promise.resolve().then(() => require("./resolver-CZdQwKvh.cjs"));
907
- const { PlaybookParser } = await Promise.resolve().then(() => require("./parser-BXLAHYnZ.cjs"));
908
- const markdown = await resolvePlaybookContent(name);
909
- const definition = PlaybookParser.parse(markdown, {});
910
- console.log(`Playbook: ${definition.name} v${definition.version}`);
911
- console.log(`${definition.description}\n`);
912
- console.log(`Parameters:`);
913
- for (const p of definition.params) {
914
- const req = p.required ? "(required)" : `(optional, default: ${p.default ?? "none"})`;
915
- console.log(` ${p.name}: ${p.type} ${req}`);
916
- }
917
- console.log(`\nSteps:`);
918
- for (const step of definition.steps) console.log(` ${step.index}. ${step.label} → tool: ${step.tool}`);
919
- } catch (err) {
920
- console.error(err.message);
921
- process.exit(1);
922
- }
923
- }));
924
- program.command("viz").description("Generate money flow visualization").argument("[case-id]", "Case ID to visualize").option("--data <file>", "Raw transaction JSON file for ad-hoc visualization").option("-p, --port <number>", "Server port", "4321").action(async (caseId, opts) => {
668
+ program.command("viz").description("Generate a workspace visualization").argument("[source-id]", "Workspace graph report ID to render").option("--data <file>", "Raw transaction JSON file for ad-hoc visualization").option("-p, --port <number>", "Server port", "4321").action(async (sourceId, opts) => {
925
669
  try {
926
- if (!caseId && !opts.data) {
927
- console.error("Provide either a case ID or --data <file.json>");
670
+ if (!sourceId && !opts.data) {
671
+ console.error("Provide either a visualization source ID or --data <file.json>");
928
672
  process.exit(1);
929
673
  }
930
- const { generateVisualization } = await Promise.resolve().then(() => require("./viz-D1620cBX.cjs")).then((n) => n.viz_exports);
674
+ const { generateVisualization } = await Promise.resolve().then(() => require("./viz-BBvY-wXz.cjs")).then((n) => n.viz_exports);
931
675
  const result = await generateVisualization({
932
- caseId,
676
+ sourceId,
933
677
  dataFile: opts.data
934
678
  });
935
- const { startServer } = await Promise.resolve().then(() => require("./server-BqVdWath.cjs")).then((n) => n.server_exports);
679
+ const { startServer } = await Promise.resolve().then(() => require("./server-ColyTG1t.cjs")).then((n) => n.server_exports);
936
680
  const port = parseInt(opts.port, 10);
937
681
  startServer(port);
938
682
  const url = `http://127.0.0.1:${port}/viz/${result.vizId}`;