chain-insights 0.3.7 → 0.3.11

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 (56) hide show
  1. package/README.md +5 -0
  2. package/dist/{app-BxojXjtB.cjs → app-DjJn3irw.cjs} +1 -1
  3. package/dist/{app-CRd39JJ8.mjs → app-norpwdou.mjs} +2 -2
  4. package/dist/{app-CRd39JJ8.mjs.map → app-norpwdou.mjs.map} +1 -1
  5. package/dist/{artifact-server-XbN16DwU.cjs → artifact-server-C6_gtIql.cjs} +1 -1
  6. package/dist/{artifact-server-CP6LXQ9d.mjs → artifact-server-DHPM0lxS.mjs} +2 -2
  7. package/dist/{artifact-server-CP6LXQ9d.mjs.map → artifact-server-DHPM0lxS.mjs.map} +1 -1
  8. package/dist/{capabilities-BC3Y5EOi.mjs → capabilities-BCvkTkIu.mjs} +3 -6
  9. package/dist/capabilities-BCvkTkIu.mjs.map +1 -0
  10. package/dist/{capabilities-D5PSx9Hj.cjs → capabilities-DOa6EFO-.cjs} +2 -5
  11. package/dist/cli.cjs +58 -31
  12. package/dist/cli.mjs +58 -31
  13. package/dist/cli.mjs.map +1 -1
  14. package/dist/{client-D4JE7fFF.mjs → client-BgmHjBHQ.mjs} +15 -7
  15. package/dist/client-BgmHjBHQ.mjs.map +1 -0
  16. package/dist/{client-Db6IV1tv.cjs → client-Y_zqKqJT.cjs} +19 -5
  17. package/dist/{config-Drgc2HuF.mjs → config-C6zM8Xir.mjs} +3 -3
  18. package/dist/{config-Drgc2HuF.mjs.map → config-C6zM8Xir.mjs.map} +1 -1
  19. package/dist/{config-BwVx19Og.cjs → config-CkW404Cs.cjs} +2 -2
  20. package/dist/index.cjs +4 -4
  21. package/dist/index.d.cts.map +1 -1
  22. package/dist/index.d.mts.map +1 -1
  23. package/dist/index.mjs +4 -4
  24. package/dist/{init-CKQ6F07J.mjs → init-uAmPfio2.mjs} +2 -2
  25. package/dist/{init-CKQ6F07J.mjs.map → init-uAmPfio2.mjs.map} +1 -1
  26. package/dist/{init-Dhw8F23z.cjs → init-vj2v5PMP.cjs} +1 -1
  27. package/dist/{mcp-endpoint-DHs1cRFH.mjs → mcp-endpoint-QQ5Lbqc2.mjs} +5 -2
  28. package/dist/mcp-endpoint-QQ5Lbqc2.mjs.map +1 -0
  29. package/dist/{mcp-endpoint-BaV8h_lq.cjs → mcp-endpoint-cQIZSjkK.cjs} +4 -1
  30. package/dist/mcp-proxy.cjs +444 -410
  31. package/dist/mcp-proxy.d.cts +3 -1
  32. package/dist/mcp-proxy.d.cts.map +1 -1
  33. package/dist/mcp-proxy.d.mts +3 -1
  34. package/dist/mcp-proxy.d.mts.map +1 -1
  35. package/dist/mcp-proxy.mjs +444 -411
  36. package/dist/mcp-proxy.mjs.map +1 -1
  37. package/dist/{public-tools-xfVNz9NE.cjs → public-tools-BY3PTw6x.cjs} +59 -31
  38. package/dist/{public-tools-CyUZEz9B.mjs → public-tools-CvlZcysd.mjs} +60 -32
  39. package/dist/public-tools-CvlZcysd.mjs.map +1 -0
  40. package/dist/{runner-DWuSy1Se.mjs → runner-B9fXAP0t.mjs} +3 -3
  41. package/dist/{runner-DWuSy1Se.mjs.map → runner-B9fXAP0t.mjs.map} +1 -1
  42. package/dist/{runner-CVo41fjz.cjs → runner-CcZCrrkn.cjs} +2 -2
  43. package/dist/{schema-BFEWhzg7.mjs → schema-D_qwaQA5.mjs} +2 -2
  44. package/dist/{schema-BFEWhzg7.mjs.map → schema-D_qwaQA5.mjs.map} +1 -1
  45. package/dist/{schema-Vl9yuOFO.cjs → schema-Dr6JXSOF.cjs} +1 -1
  46. package/dist/{server-BXLX2j_A.mjs → server-86dyCsJO.mjs} +2 -2
  47. package/dist/{server-BXLX2j_A.mjs.map → server-86dyCsJO.mjs.map} +1 -1
  48. package/dist/{server-BqVdWath.cjs → server-B2NFmnCM.cjs} +1 -1
  49. package/dist/update-BJoXYucO.cjs +145 -0
  50. package/dist/update-CJUfGCxs.mjs +145 -0
  51. package/dist/update-CJUfGCxs.mjs.map +1 -0
  52. package/package.json +1 -1
  53. package/dist/capabilities-BC3Y5EOi.mjs.map +0 -1
  54. package/dist/client-D4JE7fFF.mjs.map +0 -1
  55. package/dist/mcp-endpoint-DHs1cRFH.mjs.map +0 -1
  56. package/dist/public-tools-CyUZEz9B.mjs.map +0 -1
@@ -1,6 +1,6 @@
1
1
  import { t as __exportAll } from "./rolldown-runtime-D7D4PA-g.mjs";
2
- import { r as graphMcpEndpointEnvOverride } from "./mcp-endpoint-DHs1cRFH.mjs";
3
- import { n as parseInvestigatorConfig, t as DEFAULT_CONFIG } from "./schema-BFEWhzg7.mjs";
2
+ import { r as graphMcpEndpointEnvOverride } from "./mcp-endpoint-QQ5Lbqc2.mjs";
3
+ import { n as parseInvestigatorConfig, t as DEFAULT_CONFIG } from "./schema-D_qwaQA5.mjs";
4
4
  import path from "node:path";
5
5
  import { mkdir, readFile, writeFile } from "node:fs/promises";
6
6
  import os from "node:os";
@@ -74,4 +74,4 @@ async function resetConfigCache() {
74
74
  //#endregion
75
75
  export { saveConfig as i, loadConfig as n, resetConfigCache as r, config_exports as t };
76
76
 
77
- //# sourceMappingURL=config-Drgc2HuF.mjs.map
77
+ //# sourceMappingURL=config-C6zM8Xir.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"config-Drgc2HuF.mjs","names":[],"sources":["../src/config/index.ts"],"sourcesContent":["import { readFile, writeFile, mkdir } from 'node:fs/promises'\nimport path from 'node:path'\nimport os from 'node:os'\nimport { DEFAULT_CONFIG, parseInvestigatorConfig, type InvestigatorConfig } from './schema.js'\nimport { graphMcpEndpointEnvOverride } from './mcp-endpoint.js'\n\n// Config path derived from HOME at call time so tests can override HOME.\nfunction configPath(): string {\n return path.join(os.homedir(), '.chain-insights', 'config.json')\n}\n\nlet _cached: InvestigatorConfig | null = null\n\nfunction applyRuntimeEnvOverrides(config: InvestigatorConfig): InvestigatorConfig {\n let graphMcpEndpoint: string | undefined\n try {\n graphMcpEndpoint = graphMcpEndpointEnvOverride()\n } catch (err) {\n throw new Error(`Invalid configuration in environment: ${(err as Error).message}`)\n }\n return graphMcpEndpoint\n ? parseInvestigatorConfig({ ...config, graphMcpEndpoint })\n : config\n}\n\nasync function loadStoredConfig(): Promise<InvestigatorConfig> {\n const cfgPath = configPath()\n let raw: string\n try {\n raw = await readFile(cfgPath, 'utf8')\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code === 'ENOENT') {\n return DEFAULT_CONFIG\n }\n throw new Error(`Unable to read config ${cfgPath}: ${(err as Error).message}`)\n }\n\n let parsedJson: unknown\n try {\n parsedJson = JSON.parse(raw) as unknown\n } catch (err) {\n throw new Error(`Invalid JSON in ${cfgPath}: ${(err as Error).message}`)\n }\n\n try {\n return parseInvestigatorConfig(parsedJson)\n } catch (err) {\n throw new Error(`Invalid configuration in ${cfgPath}: ${(err as Error).message}`)\n }\n}\n\nexport async function loadConfig(): Promise<InvestigatorConfig> {\n if (_cached) return _cached\n _cached = applyRuntimeEnvOverrides(await loadStoredConfig())\n return _cached\n}\n\nexport async function saveConfig(updates: Partial<InvestigatorConfig>): Promise<void> {\n const current = await loadStoredConfig()\n let next: InvestigatorConfig\n try {\n next = parseInvestigatorConfig({ ...current, ...updates })\n } catch (err) {\n throw new Error(`Invalid configuration update: ${(err as Error).message}`)\n }\n const p = configPath()\n await mkdir(path.dirname(p), { recursive: true })\n await writeFile(p, JSON.stringify(next, null, 2) + '\\n', { mode: 0o600 })\n _cached = applyRuntimeEnvOverrides(next)\n}\n\nexport async function resetConfigCache(): Promise<void> {\n _cached = null\n}\n"],"mappings":";;;;;;;;;;;;AAOA,SAAS,aAAqB;CAC5B,OAAO,KAAK,KAAK,GAAG,QAAQ,GAAG,mBAAmB,aAAa;AACjE;AAEA,IAAI,UAAqC;AAEzC,SAAS,yBAAyB,QAAgD;CAChF,IAAI;CACJ,IAAI;EACF,mBAAmB,4BAA4B;CACjD,SAAS,KAAK;EACZ,MAAM,IAAI,MAAM,yCAA0C,IAAc,SAAS;CACnF;CACA,OAAO,mBACH,wBAAwB;EAAE,GAAG;EAAQ;CAAiB,CAAC,IACvD;AACN;AAEA,eAAe,mBAAgD;CAC7D,MAAM,UAAU,WAAW;CAC3B,IAAI;CACJ,IAAI;EACF,MAAM,MAAM,SAAS,SAAS,MAAM;CACtC,SAAS,KAAK;EACZ,IAAK,IAA8B,SAAS,UAC1C,OAAO;EAET,MAAM,IAAI,MAAM,yBAAyB,QAAQ,IAAK,IAAc,SAAS;CAC/E;CAEA,IAAI;CACJ,IAAI;EACF,aAAa,KAAK,MAAM,GAAG;CAC7B,SAAS,KAAK;EACZ,MAAM,IAAI,MAAM,mBAAmB,QAAQ,IAAK,IAAc,SAAS;CACzE;CAEA,IAAI;EACF,OAAO,wBAAwB,UAAU;CAC3C,SAAS,KAAK;EACZ,MAAM,IAAI,MAAM,4BAA4B,QAAQ,IAAK,IAAc,SAAS;CAClF;AACF;AAEA,eAAsB,aAA0C;CAC9D,IAAI,SAAS,OAAO;CACpB,UAAU,yBAAyB,MAAM,iBAAiB,CAAC;CAC3D,OAAO;AACT;AAEA,eAAsB,WAAW,SAAqD;CACpF,MAAM,UAAU,MAAM,iBAAiB;CACvC,IAAI;CACJ,IAAI;EACF,OAAO,wBAAwB;GAAE,GAAG;GAAS,GAAG;EAAQ,CAAC;CAC3D,SAAS,KAAK;EACZ,MAAM,IAAI,MAAM,iCAAkC,IAAc,SAAS;CAC3E;CACA,MAAM,IAAI,WAAW;CACrB,MAAM,MAAM,KAAK,QAAQ,CAAC,GAAG,EAAE,WAAW,KAAK,CAAC;CAChD,MAAM,UAAU,GAAG,KAAK,UAAU,MAAM,MAAM,CAAC,IAAI,MAAM,EAAE,MAAM,IAAM,CAAC;CACxE,UAAU,yBAAyB,IAAI;AACzC;AAEA,eAAsB,mBAAkC;CACtD,UAAU;AACZ"}
1
+ {"version":3,"file":"config-C6zM8Xir.mjs","names":[],"sources":["../src/config/index.ts"],"sourcesContent":["import { readFile, writeFile, mkdir } from 'node:fs/promises'\nimport path from 'node:path'\nimport os from 'node:os'\nimport { DEFAULT_CONFIG, parseInvestigatorConfig, type InvestigatorConfig } from './schema.js'\nimport { graphMcpEndpointEnvOverride } from './mcp-endpoint.js'\n\n// Config path derived from HOME at call time so tests can override HOME.\nfunction configPath(): string {\n return path.join(os.homedir(), '.chain-insights', 'config.json')\n}\n\nlet _cached: InvestigatorConfig | null = null\n\nfunction applyRuntimeEnvOverrides(config: InvestigatorConfig): InvestigatorConfig {\n let graphMcpEndpoint: string | undefined\n try {\n graphMcpEndpoint = graphMcpEndpointEnvOverride()\n } catch (err) {\n throw new Error(`Invalid configuration in environment: ${(err as Error).message}`)\n }\n return graphMcpEndpoint\n ? parseInvestigatorConfig({ ...config, graphMcpEndpoint })\n : config\n}\n\nasync function loadStoredConfig(): Promise<InvestigatorConfig> {\n const cfgPath = configPath()\n let raw: string\n try {\n raw = await readFile(cfgPath, 'utf8')\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code === 'ENOENT') {\n return DEFAULT_CONFIG\n }\n throw new Error(`Unable to read config ${cfgPath}: ${(err as Error).message}`)\n }\n\n let parsedJson: unknown\n try {\n parsedJson = JSON.parse(raw) as unknown\n } catch (err) {\n throw new Error(`Invalid JSON in ${cfgPath}: ${(err as Error).message}`)\n }\n\n try {\n return parseInvestigatorConfig(parsedJson)\n } catch (err) {\n throw new Error(`Invalid configuration in ${cfgPath}: ${(err as Error).message}`)\n }\n}\n\nexport async function loadConfig(): Promise<InvestigatorConfig> {\n if (_cached) return _cached\n _cached = applyRuntimeEnvOverrides(await loadStoredConfig())\n return _cached\n}\n\nexport async function saveConfig(updates: Partial<InvestigatorConfig>): Promise<void> {\n const current = await loadStoredConfig()\n let next: InvestigatorConfig\n try {\n next = parseInvestigatorConfig({ ...current, ...updates })\n } catch (err) {\n throw new Error(`Invalid configuration update: ${(err as Error).message}`)\n }\n const p = configPath()\n await mkdir(path.dirname(p), { recursive: true })\n await writeFile(p, JSON.stringify(next, null, 2) + '\\n', { mode: 0o600 })\n _cached = applyRuntimeEnvOverrides(next)\n}\n\nexport async function resetConfigCache(): Promise<void> {\n _cached = null\n}\n"],"mappings":";;;;;;;;;;;;AAOA,SAAS,aAAqB;CAC5B,OAAO,KAAK,KAAK,GAAG,QAAQ,GAAG,mBAAmB,aAAa;AACjE;AAEA,IAAI,UAAqC;AAEzC,SAAS,yBAAyB,QAAgD;CAChF,IAAI;CACJ,IAAI;EACF,mBAAmB,4BAA4B;CACjD,SAAS,KAAK;EACZ,MAAM,IAAI,MAAM,yCAA0C,IAAc,SAAS;CACnF;CACA,OAAO,mBACH,wBAAwB;EAAE,GAAG;EAAQ;CAAiB,CAAC,IACvD;AACN;AAEA,eAAe,mBAAgD;CAC7D,MAAM,UAAU,WAAW;CAC3B,IAAI;CACJ,IAAI;EACF,MAAM,MAAM,SAAS,SAAS,MAAM;CACtC,SAAS,KAAK;EACZ,IAAK,IAA8B,SAAS,UAC1C,OAAO;EAET,MAAM,IAAI,MAAM,yBAAyB,QAAQ,IAAK,IAAc,SAAS;CAC/E;CAEA,IAAI;CACJ,IAAI;EACF,aAAa,KAAK,MAAM,GAAG;CAC7B,SAAS,KAAK;EACZ,MAAM,IAAI,MAAM,mBAAmB,QAAQ,IAAK,IAAc,SAAS;CACzE;CAEA,IAAI;EACF,OAAO,wBAAwB,UAAU;CAC3C,SAAS,KAAK;EACZ,MAAM,IAAI,MAAM,4BAA4B,QAAQ,IAAK,IAAc,SAAS;CAClF;AACF;AAEA,eAAsB,aAA0C;CAC9D,IAAI,SAAS,OAAO;CACpB,UAAU,yBAAyB,MAAM,iBAAiB,CAAC;CAC3D,OAAO;AACT;AAEA,eAAsB,WAAW,SAAqD;CACpF,MAAM,UAAU,MAAM,iBAAiB;CACvC,IAAI;CACJ,IAAI;EACF,OAAO,wBAAwB;GAAE,GAAG;GAAS,GAAG;EAAQ,CAAC;CAC3D,SAAS,KAAK;EACZ,MAAM,IAAI,MAAM,iCAAkC,IAAc,SAAS;CAC3E;CACA,MAAM,IAAI,WAAW;CACrB,MAAM,MAAM,KAAK,QAAQ,CAAC,GAAG,EAAE,WAAW,KAAK,CAAC;CAChD,MAAM,UAAU,GAAG,KAAK,UAAU,MAAM,MAAM,CAAC,IAAI,MAAM,EAAE,MAAM,IAAM,CAAC;CACxE,UAAU,yBAAyB,IAAI;AACzC;AAEA,eAAsB,mBAAkC;CACtD,UAAU;AACZ"}
@@ -1,6 +1,6 @@
1
1
  const require_chunk = require("./chunk-DakpK96I.cjs");
2
- const require_mcp_endpoint = require("./mcp-endpoint-BaV8h_lq.cjs");
3
- const require_schema = require("./schema-Vl9yuOFO.cjs");
2
+ const require_mcp_endpoint = require("./mcp-endpoint-cQIZSjkK.cjs");
3
+ const require_schema = require("./schema-Dr6JXSOF.cjs");
4
4
  let node_path = require("node:path");
5
5
  node_path = require_chunk.__toESM(node_path, 1);
6
6
  let node_fs_promises = require("node:fs/promises");
package/dist/index.cjs CHANGED
@@ -1,11 +1,11 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
- const require_config = require("./config-BwVx19Og.cjs");
3
- const require_app = require("./app-BxojXjtB.cjs");
4
- const require_server = require("./server-BqVdWath.cjs");
2
+ const require_config = require("./config-CkW404Cs.cjs");
3
+ const require_app = require("./app-DjJn3irw.cjs");
4
+ const require_server = require("./server-B2NFmnCM.cjs");
5
5
  const require_wallet = require("./wallet-gC2jxh7j.cjs");
6
6
  const require_tools = require("./tools-BhTI3Lmg.cjs");
7
7
  const require_topup_server = require("./topup-server-DhYlOOBM.cjs");
8
- const require_client = require("./client-Db6IV1tv.cjs");
8
+ const require_client = require("./client-Y_zqKqJT.cjs");
9
9
  const require_viz = require("./viz-D1620cBX.cjs");
10
10
  exports.buildTopupInfo = require_tools.buildTopupInfo;
11
11
  exports.createApp = require_app.createApp;
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.cts","names":[],"sources":["../src/config/schema.ts","../src/config/index.ts","../src/server/app.ts","../src/server/index.ts","../src/wallet/index.ts","../src/wallet/tools.ts","../src/wallet/mcp-proxy/topup-server.ts","../src/wallet/topup-server.ts","../src/mcp/client.ts","../src/viz/graph-model.ts","../src/viz/index.ts"],"mappings":";;;;;cAmBa,YAAA,EAAY,CAAA,CAAA,SAAA;;;;;;;;;;;;;;KAYb,kBAAA,GAAqB,CAAA,CAAE,KAAK,QAAQ,YAAA;;;iBCoB1B,UAAA,CAAA,GAAc,OAAO,CAAC,kBAAA;AAAA,iBAMtB,UAAA,CAAW,OAAA,EAAS,OAAA,CAAQ,kBAAA,IAAsB,OAAA;AAAA,iBAclD,gBAAA,CAAA,GAAoB,OAAO;;;iBC4DjC,SAAA,CAAA,GAAa,IAAI;;;iBChIjB,WAAA,CAAY,IAAW;;;iBC0BvB,yBAAA,CAA0B,KAAA,WAAgB,GAAG;AAAA,iBAO7C,2BAAA,CAA4B,UAAA,WAAqB,OAAO;;AJjBxE;;;;;;iBI4BsB,UAAA,CAAW,UAAA,WAAqB,OAAO;AAAA,iBA2BvC,mBAAA,CAAoB,UAAA,WAAqB,OAAO,CAAC,OAAA;;;;;;;iBAajD,UAAA,CAAA,GAAc,OAAO;;;;;iBA2CrB,kBAAA,CAAA,GAAsB,OAAO;;;cC7HtC,aAAA;AAAA,cACA,YAAA;AAAA,UAyCI,oBAAA;EACf,OAAA,EAAS,OAAA;EACT,UAAA,EAAY,GAAG;AAAA;AAAA,UAGA,SAAA;EACf,cAAA;EACA,OAAA;EACA,QAAA,SAAiB,aAAA;EACjB,KAAA;EACA,cAAA,SAAuB,YAAY;EACnC,SAAA;AAAA;AAAA,iBAqCoB,gBAAA,CAAA,GAAoB,OAAO,CAAC,oBAAA;AAAA,iBAa5B,cAAA,CACpB,OAAA,EAAS,OAAA,WACT,MAAA,wBACC,OAAO;AAAA,iBAsBY,aAAA,CACpB,OAAA,EAAS,OAAA,WACT,MAAA,wBACC,OAAO;AAAA,iBA8OM,mBAAA,CAAoB,OAAA,UAAiB,WAAA,UAAqB,UAAA;AAAA,iBAUpD,oBAAA,CAAqB,OAAA,GAAU,oBAAA,GAAuB,OAAO;AAAA,iBASnE,cAAA,CAAe,OAAA,UAAiB,QAAA,YAAoB,SAAS;;;iBClR7D,oBAAA,CAAqB,kBAAA,UAA4B,QAAgB;;;iBClBjE,WAAA,CAAA;AAAA,iBAcM,gBAAA,CAAiB,OAAA,EAAS,oBAAA,YAAgC,OAAO;;;;;;;;;;;;;iBCwBvE,oBAAA,CAAqB,UAAA,iBAA2B,SAAA,mBAAkB,KAAA;;;cCnIrE,SAAA,EAAS,CAAA,CAAA,SAAA;;;;;;;;;;;;;;;;;;;;;;;KAWV,SAAA,GAAY,CAAA,CAAE,KAAK,QAAQ,SAAA;AAAA,cAE1B,SAAA,EAAS,CAAA,CAAA,SAAA;;;;;;;;KAQV,SAAA,GAAY,CAAA,CAAE,KAAK,QAAQ,SAAA;AAAA,cAE1B,SAAA,EAAS,CAAA,CAAA,SAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KAYV,SAAA,GAAY,CAAA,CAAE,KAAK,QAAQ,SAAA;;;iBClCjB,qBAAA,CAAsB,IAAA;EAC1C,MAAA;EACA,QAAA;AAAA,IACE,OAAO;EAAG,KAAA;EAAe,QAAA;AAAA"}
1
+ {"version":3,"file":"index.d.cts","names":[],"sources":["../src/config/schema.ts","../src/config/index.ts","../src/server/app.ts","../src/server/index.ts","../src/wallet/index.ts","../src/wallet/tools.ts","../src/wallet/mcp-proxy/topup-server.ts","../src/wallet/topup-server.ts","../src/mcp/client.ts","../src/viz/graph-model.ts","../src/viz/index.ts"],"mappings":";;;;;cAmBa,YAAA,EAAY,CAAA,CAAA,SAAA;;;;;;;;;;;;;;KAYb,kBAAA,GAAqB,CAAA,CAAE,KAAK,QAAQ,YAAA;;;iBCoB1B,UAAA,CAAA,GAAc,OAAO,CAAC,kBAAA;AAAA,iBAMtB,UAAA,CAAW,OAAA,EAAS,OAAA,CAAQ,kBAAA,IAAsB,OAAA;AAAA,iBAclD,gBAAA,CAAA,GAAoB,OAAO;;;iBC4DjC,SAAA,CAAA,GAAa,IAAI;;;iBChIjB,WAAA,CAAY,IAAW;;;iBC0BvB,yBAAA,CAA0B,KAAA,WAAgB,GAAG;AAAA,iBAO7C,2BAAA,CAA4B,UAAA,WAAqB,OAAO;;AJjBxE;;;;;;iBI4BsB,UAAA,CAAW,UAAA,WAAqB,OAAO;AAAA,iBA2BvC,mBAAA,CAAoB,UAAA,WAAqB,OAAO,CAAC,OAAA;;;;;;;iBAajD,UAAA,CAAA,GAAc,OAAO;;;;;iBA2CrB,kBAAA,CAAA,GAAsB,OAAO;;;cC7HtC,aAAA;AAAA,cACA,YAAA;AAAA,UAyCI,oBAAA;EACf,OAAA,EAAS,OAAA;EACT,UAAA,EAAY,GAAG;AAAA;AAAA,UAGA,SAAA;EACf,cAAA;EACA,OAAA;EACA,QAAA,SAAiB,aAAA;EACjB,KAAA;EACA,cAAA,SAAuB,YAAY;EACnC,SAAA;AAAA;AAAA,iBAqCoB,gBAAA,CAAA,GAAoB,OAAO,CAAC,oBAAA;AAAA,iBAa5B,cAAA,CACpB,OAAA,EAAS,OAAA,WACT,MAAA,wBACC,OAAO;AAAA,iBAsBY,aAAA,CACpB,OAAA,EAAS,OAAA,WACT,MAAA,wBACC,OAAO;AAAA,iBA8OM,mBAAA,CAAoB,OAAA,UAAiB,WAAA,UAAqB,UAAA;AAAA,iBAUpD,oBAAA,CAAqB,OAAA,GAAU,oBAAA,GAAuB,OAAO;AAAA,iBASnE,cAAA,CAAe,OAAA,UAAiB,QAAA,YAAoB,SAAS;;;iBClR7D,oBAAA,CAAqB,kBAAA,UAA4B,QAAgB;;;iBClBjE,WAAA,CAAA;AAAA,iBAcM,gBAAA,CAAiB,OAAA,EAAS,oBAAA,YAAgC,OAAO;;;;;;;;;;;;;iBC+BvE,oBAAA,CAAqB,UAAA,iBAA2B,SAAA,mBAAkB,KAAA;;;cC1IrE,SAAA,EAAS,CAAA,CAAA,SAAA;;;;;;;;;;;;;;;;;;;;;;;KAWV,SAAA,GAAY,CAAA,CAAE,KAAK,QAAQ,SAAA;AAAA,cAE1B,SAAA,EAAS,CAAA,CAAA,SAAA;;;;;;;;KAQV,SAAA,GAAY,CAAA,CAAE,KAAK,QAAQ,SAAA;AAAA,cAE1B,SAAA,EAAS,CAAA,CAAA,SAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KAYV,SAAA,GAAY,CAAA,CAAE,KAAK,QAAQ,SAAA;;;iBClCjB,qBAAA,CAAsB,IAAA;EAC1C,MAAA;EACA,QAAA;AAAA,IACE,OAAO;EAAG,KAAA;EAAe,QAAA;AAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.mts","names":[],"sources":["../src/config/schema.ts","../src/config/index.ts","../src/server/app.ts","../src/server/index.ts","../src/wallet/index.ts","../src/wallet/tools.ts","../src/wallet/mcp-proxy/topup-server.ts","../src/wallet/topup-server.ts","../src/mcp/client.ts","../src/viz/graph-model.ts","../src/viz/index.ts"],"mappings":";;;;;cAmBa,YAAA,EAAY,CAAA,CAAA,SAAA;;;;;;;;;;;;;;KAYb,kBAAA,GAAqB,CAAA,CAAE,KAAK,QAAQ,YAAA;;;iBCoB1B,UAAA,CAAA,GAAc,OAAO,CAAC,kBAAA;AAAA,iBAMtB,UAAA,CAAW,OAAA,EAAS,OAAA,CAAQ,kBAAA,IAAsB,OAAA;AAAA,iBAclD,gBAAA,CAAA,GAAoB,OAAO;;;iBC4DjC,SAAA,CAAA,GAAa,IAAI;;;iBChIjB,WAAA,CAAY,IAAW;;;iBC0BvB,yBAAA,CAA0B,KAAA,WAAgB,GAAG;AAAA,iBAO7C,2BAAA,CAA4B,UAAA,WAAqB,OAAO;;AJjBxE;;;;;;iBI4BsB,UAAA,CAAW,UAAA,WAAqB,OAAO;AAAA,iBA2BvC,mBAAA,CAAoB,UAAA,WAAqB,OAAO,CAAC,OAAA;;;;;;;iBAajD,UAAA,CAAA,GAAc,OAAO;;;;;iBA2CrB,kBAAA,CAAA,GAAsB,OAAO;;;cC7HtC,aAAA;AAAA,cACA,YAAA;AAAA,UAyCI,oBAAA;EACf,OAAA,EAAS,OAAA;EACT,UAAA,EAAY,GAAG;AAAA;AAAA,UAGA,SAAA;EACf,cAAA;EACA,OAAA;EACA,QAAA,SAAiB,aAAA;EACjB,KAAA;EACA,cAAA,SAAuB,YAAY;EACnC,SAAA;AAAA;AAAA,iBAqCoB,gBAAA,CAAA,GAAoB,OAAO,CAAC,oBAAA;AAAA,iBAa5B,cAAA,CACpB,OAAA,EAAS,OAAA,WACT,MAAA,wBACC,OAAO;AAAA,iBAsBY,aAAA,CACpB,OAAA,EAAS,OAAA,WACT,MAAA,wBACC,OAAO;AAAA,iBA8OM,mBAAA,CAAoB,OAAA,UAAiB,WAAA,UAAqB,UAAA;AAAA,iBAUpD,oBAAA,CAAqB,OAAA,GAAU,oBAAA,GAAuB,OAAO;AAAA,iBASnE,cAAA,CAAe,OAAA,UAAiB,QAAA,YAAoB,SAAS;;;iBClR7D,oBAAA,CAAqB,kBAAA,UAA4B,QAAgB;;;iBClBjE,WAAA,CAAA;AAAA,iBAcM,gBAAA,CAAiB,OAAA,EAAS,oBAAA,YAAgC,OAAO;;;;;;;;;;;;;iBCwBvE,oBAAA,CAAqB,UAAA,iBAA2B,SAAA,mBAAkB,KAAA;;;cCnIrE,SAAA,EAAS,CAAA,CAAA,SAAA;;;;;;;;;;;;;;;;;;;;;;;KAWV,SAAA,GAAY,CAAA,CAAE,KAAK,QAAQ,SAAA;AAAA,cAE1B,SAAA,EAAS,CAAA,CAAA,SAAA;;;;;;;;KAQV,SAAA,GAAY,CAAA,CAAE,KAAK,QAAQ,SAAA;AAAA,cAE1B,SAAA,EAAS,CAAA,CAAA,SAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KAYV,SAAA,GAAY,CAAA,CAAE,KAAK,QAAQ,SAAA;;;iBClCjB,qBAAA,CAAsB,IAAA;EAC1C,MAAA;EACA,QAAA;AAAA,IACE,OAAO;EAAG,KAAA;EAAe,QAAA;AAAA"}
1
+ {"version":3,"file":"index.d.mts","names":[],"sources":["../src/config/schema.ts","../src/config/index.ts","../src/server/app.ts","../src/server/index.ts","../src/wallet/index.ts","../src/wallet/tools.ts","../src/wallet/mcp-proxy/topup-server.ts","../src/wallet/topup-server.ts","../src/mcp/client.ts","../src/viz/graph-model.ts","../src/viz/index.ts"],"mappings":";;;;;cAmBa,YAAA,EAAY,CAAA,CAAA,SAAA;;;;;;;;;;;;;;KAYb,kBAAA,GAAqB,CAAA,CAAE,KAAK,QAAQ,YAAA;;;iBCoB1B,UAAA,CAAA,GAAc,OAAO,CAAC,kBAAA;AAAA,iBAMtB,UAAA,CAAW,OAAA,EAAS,OAAA,CAAQ,kBAAA,IAAsB,OAAA;AAAA,iBAclD,gBAAA,CAAA,GAAoB,OAAO;;;iBC4DjC,SAAA,CAAA,GAAa,IAAI;;;iBChIjB,WAAA,CAAY,IAAW;;;iBC0BvB,yBAAA,CAA0B,KAAA,WAAgB,GAAG;AAAA,iBAO7C,2BAAA,CAA4B,UAAA,WAAqB,OAAO;;AJjBxE;;;;;;iBI4BsB,UAAA,CAAW,UAAA,WAAqB,OAAO;AAAA,iBA2BvC,mBAAA,CAAoB,UAAA,WAAqB,OAAO,CAAC,OAAA;;;;;;;iBAajD,UAAA,CAAA,GAAc,OAAO;;;;;iBA2CrB,kBAAA,CAAA,GAAsB,OAAO;;;cC7HtC,aAAA;AAAA,cACA,YAAA;AAAA,UAyCI,oBAAA;EACf,OAAA,EAAS,OAAA;EACT,UAAA,EAAY,GAAG;AAAA;AAAA,UAGA,SAAA;EACf,cAAA;EACA,OAAA;EACA,QAAA,SAAiB,aAAA;EACjB,KAAA;EACA,cAAA,SAAuB,YAAY;EACnC,SAAA;AAAA;AAAA,iBAqCoB,gBAAA,CAAA,GAAoB,OAAO,CAAC,oBAAA;AAAA,iBAa5B,cAAA,CACpB,OAAA,EAAS,OAAA,WACT,MAAA,wBACC,OAAO;AAAA,iBAsBY,aAAA,CACpB,OAAA,EAAS,OAAA,WACT,MAAA,wBACC,OAAO;AAAA,iBA8OM,mBAAA,CAAoB,OAAA,UAAiB,WAAA,UAAqB,UAAA;AAAA,iBAUpD,oBAAA,CAAqB,OAAA,GAAU,oBAAA,GAAuB,OAAO;AAAA,iBASnE,cAAA,CAAe,OAAA,UAAiB,QAAA,YAAoB,SAAS;;;iBClR7D,oBAAA,CAAqB,kBAAA,UAA4B,QAAgB;;;iBClBjE,WAAA,CAAA;AAAA,iBAcM,gBAAA,CAAiB,OAAA,EAAS,oBAAA,YAAgC,OAAO;;;;;;;;;;;;;iBC+BvE,oBAAA,CAAqB,UAAA,iBAA2B,SAAA,mBAAkB,KAAA;;;cC1IrE,SAAA,EAAS,CAAA,CAAA,SAAA;;;;;;;;;;;;;;;;;;;;;;;KAWV,SAAA,GAAY,CAAA,CAAE,KAAK,QAAQ,SAAA;AAAA,cAE1B,SAAA,EAAS,CAAA,CAAA,SAAA;;;;;;;;KAQV,SAAA,GAAY,CAAA,CAAE,KAAK,QAAQ,SAAA;AAAA,cAE1B,SAAA,EAAS,CAAA,CAAA,SAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KAYV,SAAA,GAAY,CAAA,CAAE,KAAK,QAAQ,SAAA;;;iBClCjB,qBAAA,CAAsB,IAAA;EAC1C,MAAA;EACA,QAAA;AAAA,IACE,OAAO;EAAG,KAAA;EAAe,QAAA;AAAA"}
package/dist/index.mjs CHANGED
@@ -1,9 +1,9 @@
1
- import { i as saveConfig, n as loadConfig, r as resetConfigCache } from "./config-Drgc2HuF.mjs";
2
- import { t as createApp } from "./app-CRd39JJ8.mjs";
3
- import { n as startServer } from "./server-BXLX2j_A.mjs";
1
+ import { i as saveConfig, n as loadConfig, r as resetConfigCache } from "./config-C6zM8Xir.mjs";
2
+ import { t as createApp } from "./app-norpwdou.mjs";
3
+ import { n as startServer } from "./server-86dyCsJO.mjs";
4
4
  import { a as setWalletPrivateKey, i as normalizeWalletPrivateKey, n as encryptKey, o as walletAddressFromPrivateKey, r as isWalletConfigured, t as decryptKey } from "./wallet-BL0fJC29.mjs";
5
5
  import { a as getWalletAccount, i as getBalanceUsdc, n as formatWalletBalance, o as getWalletBalanceText, r as getBalanceEth, t as buildTopupInfo } from "./tools-v6kcdojg.mjs";
6
6
  import { i as generateArtifactHtml, n as startTopupServer, t as getTopupUrl } from "./topup-server-R3dNp-p8.mjs";
7
- import { i as createMcpFetchClient } from "./client-D4JE7fFF.mjs";
7
+ import { a as createMcpFetchClient } from "./client-BgmHjBHQ.mjs";
8
8
  import { t as generateVisualization } from "./viz-DB5XFG1z.mjs";
9
9
  export { buildTopupInfo, createApp, createMcpFetchClient, decryptKey, encryptKey, formatWalletBalance, generateArtifactHtml, generateVisualization, getBalanceEth, getBalanceUsdc, getTopupUrl, getWalletAccount, getWalletBalanceText, isWalletConfigured, loadConfig, normalizeWalletPrivateKey, resetConfigCache, saveConfig, setWalletPrivateKey, startServer, startTopupServer, walletAddressFromPrivateKey };
@@ -1,4 +1,4 @@
1
- import { t as LOCAL_GRAPH_MCP_ENDPOINT } from "./mcp-endpoint-DHs1cRFH.mjs";
1
+ import { t as LOCAL_GRAPH_MCP_ENDPOINT } from "./mcp-endpoint-QQ5Lbqc2.mjs";
2
2
  import { assertNoVaultFileCollisions, scaffoldVault } from "./vault-z35Dohdq.mjs";
3
3
  import path from "node:path";
4
4
  import { access, mkdir, writeFile } from "node:fs/promises";
@@ -272,4 +272,4 @@ async function initWorkspace(options) {
272
272
  //#endregion
273
273
  export { initWorkspace };
274
274
 
275
- //# sourceMappingURL=init-CKQ6F07J.mjs.map
275
+ //# sourceMappingURL=init-uAmPfio2.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"init-CKQ6F07J.mjs","names":[],"sources":["../src/workspace/init.ts"],"sourcesContent":["import { access, mkdir, writeFile } from 'node:fs/promises'\nimport path from 'node:path'\nimport { LOCAL_GRAPH_MCP_ENDPOINT } from '../config/mcp-endpoint.js'\nimport { assertNoVaultFileCollisions, scaffoldVault } from '../vault/index.js'\n\nexport interface InitWorkspaceOptions {\n targetDir: string\n force?: boolean\n}\n\nexport interface InitWorkspaceResult {\n workspaceRoot: string\n filesWritten: string[]\n}\n\nconst WORKSPACE_DIRS = [\n '.chain-insights',\n '.chain-insights/schema',\n '.chain-insights/runtime',\n '.chain-insights/runtime/logs',\n '.chain-insights/runtime-skill',\n 'cases',\n 'imports',\n 'reports',\n 'reports/graphs',\n 'reports/tables',\n 'templates',\n 'published',\n]\n\nfunction todayIso(): string {\n return new Date().toISOString().slice(0, 10)\n}\n\nfunction workspaceJson(workspaceRoot: string): string {\n return JSON.stringify({\n schema: 'chain-insights.workspace.v1',\n name: 'Chain Insights Investigations',\n workspace_root: workspaceRoot,\n default_network: 'bittensor',\n graph_mcp_endpoint: LOCAL_GRAPH_MCP_ENDPOINT,\n cases_dir: 'cases',\n imports_dir: 'imports',\n reports_dir: 'reports',\n templates_dir: 'templates',\n created_at: todayIso(),\n }, null, 2) + '\\n'\n}\n\nconst README = `# Chain Insights Investigation Vault\n\nThis is a Chain Insights AML investigation workspace and Obsidian-compatible vault.\nOpen this directory in Obsidian to review cases, entities, evidence, graphs, and\npublished investigation bundles alongside the Chain Insights runtime metadata.\n\n## Start\n\n\\`\\`\\`bash\nchain-insights mcp tools --refresh\nchain-insights wallet ready --check-only\n\\`\\`\\`\n\n## Layout\n\n\\`\\`\\`text\n.chain-insights/ Workspace metadata\ncases/ Case exports and notes\nimports/ External reports, CSVs, screenshots, raw notes\nreports/ Final or interim analyst reports\nreports/graphs/ Graph JSON for visualization\nreports/tables/ Compact tabular extracts\ntemplates/ Reusable case/report templates\npublished/ Obsidian-ready case exports and published bundles\n.chain-insights/schema/ Runtime graph schema captures\n.chain-insights/runtime/ Workspace-local runtime process state and debug logs\n.chain-insights/runtime-skill/ Workspace-specific agent schema notes\n.obsidian/ Obsidian vault configuration\nCanvases/ Obsidian canvases for graph review\nEntities/ Entity notes and indexes\nEvidence/ Evidence notes and indexes\n\\`\\`\\`\n`\n\nconst AGENTS = `# Agent Instructions\n\nYou are operating inside a Chain Insights investigation workspace.\n\n- Read README.md first.\n- If this directory is not initialized, run \\`cia init .\\` before investigation-producing commands.\n- Do not rerun init in an existing workspace unless replacing scaffolding with \\`--force\\`.\n- Read .chain-insights/runtime-skill/SKILL.md before graph queries.\n- Preserve full blockchain addresses exactly.\n- Do not guess the network for graph queries.\n- Capture or refresh graph schema before the first case query.\n- Save compact evidence with original graph field names.\n- Put canonical graph JSON in reports/graphs/ and analyst tables in reports/tables/.\n- Evidence files should summarize and point to graph/table outputs; do not paste large raw JSON blobs into evidence Markdown.\n- Investigation output must stay in this initialized workspace.\n- Never write cases, evidence, reports, graph JSON, HTML, schema captures, or logs to ~/.chain-insights.\n- Keep theories lightweight until evidence supports them.\n`\n\nconst CLAUDE = AGENTS\n\nconst CASE_BRIEF = `# Case Brief\n\n## Summary\n\nStatus:\nNetwork:\nCurrent Assessment:\n\n## Known Addresses\n\n## Claims To Validate\n\n## Evidence\n\n## Next Steps\n`\n\nconst IMPORTS_README = `# External Investigation Inputs\n\nPut user-provided or third-party investigation material here before turning it\ninto case evidence.\n\nExamples:\n\n- Exchange support exports\n- CSV extracts\n- Screenshots\n- Raw notes\n- Partner reports\n\nFiles in this directory are inputs, not verified evidence. When an import\nsupports a claim, summarize it into the case evidence manifest and reference\nthe original file path.\n`\n\nconst TEMPLATES_README = `# Reusable Workspace Templates\n\nStore local report, case, prompt, and evidence templates here.\n\nTemplates are optional workspace helpers. They are not evidence and should not\nbe treated as case state until copied into a case, evidence file, dossier, or\nreport.\n`\n\nconst RUNTIME_SKILL = `---\nname: chain-insights-runtime-schema\ndescription: Workspace-local Chain Insights runtime schema notes. Refresh this after connecting to a graph MCP endpoint.\n---\n\n# Runtime Graph Schema\n\nBefore the first investigation query, capture the live graph schema into:\n\n\\`\\`\\`text\n.chain-insights/schema/<network>.graph-schema.json\n\\`\\`\\`\n\nUse \\`graph_query_batch\\` for schema capture. Prefix current topology reads\nwith \\`USE live_topology\\`, historical topology reads with\n\\`USE archive_topology\\`, and fact reads with \\`USE facts\\`, for example:\n\n\\`\\`\\`bash\ncia mcp call graph_query_batch network=<network> 'queries=[{\"id\":\"node_labels\",\"query\":\"USE live_topology MATCH (n:Address) RETURN \\\"Address\\\" AS node_label, count(n) AS sample_count LIMIT 1\"},{\"id\":\"archive_flow_sample\",\"query\":\"USE archive_topology MATCH (:Address)-[f:FLOWS_TO]->(:Address) RETURN f.period_granularity AS granularity, f.amount_sum AS amount_sum LIMIT 20\"}]'\n\\`\\`\\`\n\nThen update this file with observed labels, relationship types, and allowed\nproperty names for the active network.\n\nRules:\n\n- Prefer \\`graph_query\\` and \\`graph_query_batch\\` for graph-language reads.\n- Use \\`USE live_topology\\` for recent topology, \\`USE archive_topology\\`\n for historical topology, and \\`USE facts\\` for labels, features,\n risk scores, assets, and enrichment. Address facts can be reached through\n relationships such as \\`(:Address)-[:HAS_FEATURE]->(:AddressFeature)\\`.\n Archived money-flow topology is exposed as\n \\`(:Address)-[:FLOWS_TO]->(:Address)\\` with \\`period_granularity\\`,\n \\`period_start_date\\`, and \\`period_end_date\\` on the relationship.\n- Preserve source schema field names in evidence and generated data files.\n- Do not rename, reinterpret, or add unit labels to graph fields unless the\n schema or query result explicitly supports that interpretation.\n- Keep evidence compact: select only the fields needed to support the claim.\n Avoid storing whole node or relationship property blobs in evidence unless\n the purpose of the query is schema discovery or debugging.\n- When using BFS, fixed-depth traversal fallbacks, or any manual \\`FLOWS_TO\\`\n traversal, treat exchange hot wallets as terminal endpoints only. Do not\n expand from, through, or classify exchange nodes as deposit, suspect, or\n intermediate candidates. In Cypher, require every non-terminal traversal node\n to satisfy \\`is_exchange IS NULL\\`; only the final exchange endpoint should\n satisfy \\`is_exchange IS NOT NULL\\`.\n- Keep analysis products separate from evidence: graph JSON belongs under\n \\`reports/graphs/\\`, tabular extracts under \\`reports/tables/\\`, and analyst\n narrative under \\`reports/\\`.\n- Evidence Markdown should be a short provenance record with key facts and\n pointers. Large JSON belongs in \\`reports/tables/\\`, not inline in evidence.\n\nTrace tool chaining:\n\n1. Use \\`trace_victim_funds\\` when the user gives victim/source addresses.\n2. Pass returned \\`continuation.candidate_deposit_addresses\\` to\n \\`trace_deposit_sources\\`; do not make victim tracing run deposit traceback\n internally.\n3. Pass high-confidence \\`continuation.candidate_suspect_addresses\\` from\n deposit traceback to \\`trace_suspect_funds\\`.\n4. Use \\`trace_suspect_funds\\` when the user gives suspected scammer, mule,\n operator, or laundering-ring addresses. \\`incident_timestamp_ms\\` is\n optional.\n5. Use \\`address_risk\\` for single-address enrichment, and\n \\`graph_query_batch\\` only when the role-specific tools do not answer the\n exact question.\n\nAll trace tools return \\`chain-insights.trace.v1\\`. Preserve full addresses in\n\\`input.addresses\\`, \\`addresses[].address\\`, \\`edges[].from_address\\`,\n\\`edges[].to_address\\`, \\`paths[].addresses\\`, \\`candidate_labels[].address\\`,\nand \\`continuation\\` address lists.\n`\n\nconst SCHEMA_README = `# Runtime Schema Captures\n\nStore graph schema captures here, for example:\n\n\\`\\`\\`text\nbittensor.graph-schema.json\n\\`\\`\\`\n\nSchema captures should be generated before the first case query in a fresh\nworkspace, then referenced by evidence, reports, and runtime skill notes.\n`\n\nfunction workspaceFiles(workspaceRoot: string): Array<[string, string]> {\n return [\n ['.chain-insights/workspace.json', workspaceJson(workspaceRoot)],\n ['README.md', README],\n ['AGENTS.md', AGENTS],\n ['CLAUDE.md', CLAUDE],\n ['imports/README.md', IMPORTS_README],\n ['templates/README.md', TEMPLATES_README],\n ['templates/case-brief.md', CASE_BRIEF],\n ['.chain-insights/runtime-skill/SKILL.md', RUNTIME_SKILL],\n ['.chain-insights/schema/README.md', SCHEMA_README],\n ['.chain-insights/runtime/.keep', ''],\n ['.chain-insights/runtime/logs/.keep', ''],\n ]\n}\n\nasync function assertNoFileCollisions(workspaceRoot: string): Promise<void> {\n for (const [relativePath] of workspaceFiles(workspaceRoot)) {\n const filePath = path.join(workspaceRoot, relativePath)\n try {\n await access(filePath)\n throw new Error(`Refusing to overwrite ${filePath}. Re-run with --force to replace workspace files.`)\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code === 'ENOENT') {\n continue\n }\n throw err\n }\n }\n}\n\nexport async function initWorkspace(options: InitWorkspaceOptions): Promise<InitWorkspaceResult> {\n const workspaceRoot = path.resolve(options.targetDir)\n if (!options.force) {\n await assertNoFileCollisions(workspaceRoot)\n await assertNoVaultFileCollisions(workspaceRoot)\n }\n\n for (const dir of WORKSPACE_DIRS) {\n await mkdir(path.join(workspaceRoot, dir), { recursive: true })\n }\n\n const filesWritten: string[] = []\n const flag = options.force ? 'w' : 'wx'\n for (const [relativePath, content] of workspaceFiles(workspaceRoot)) {\n const filePath = path.join(workspaceRoot, relativePath)\n try {\n await writeFile(filePath, content, { mode: 0o600, flag })\n filesWritten.push(relativePath)\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code === 'EEXIST') {\n throw new Error(`Refusing to overwrite ${filePath}. Re-run with --force to replace workspace files.`)\n }\n throw err\n }\n }\n\n const vault = await scaffoldVault({ workspaceRoot, force: options.force })\n filesWritten.push(...vault.filesWritten)\n\n return { workspaceRoot, filesWritten }\n}\n"],"mappings":";;;;;AAeA,MAAM,iBAAiB;CACrB;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;AACF;AAEA,SAAS,WAAmB;CAC1B,wBAAO,IAAI,KAAK,GAAE,YAAY,EAAE,MAAM,GAAG,EAAE;AAC7C;AAEA,SAAS,cAAc,eAA+B;CACpD,OAAO,KAAK,UAAU;EACpB,QAAQ;EACR,MAAM;EACN,gBAAgB;EAChB,iBAAiB;EACjB,oBAAoB;EACpB,WAAW;EACX,aAAa;EACb,aAAa;EACb,eAAe;EACf,YAAY,SAAS;CACvB,GAAG,MAAM,CAAC,IAAI;AAChB;AAEA,MAAM,SAAS;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAkCf,MAAM,SAAS;;;;;;;;;;;;;;;;;;AAmBf,MAAM,SAAS;AAEf,MAAM,aAAa;;;;;;;;;;;;;;;;AAiBnB,MAAM,iBAAiB;;;;;;;;;;;;;;;;;AAkBvB,MAAM,mBAAmB;;;;;;;;AASzB,MAAM,gBAAgB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAyEtB,MAAM,gBAAgB;;;;;;;;;;;AAYtB,SAAS,eAAe,eAAgD;CACtE,OAAO;EACL,CAAC,kCAAkC,cAAc,aAAa,CAAC;EAC/D,CAAC,aAAa,MAAM;EACpB,CAAC,aAAa,MAAM;EACpB,CAAC,aAAa,MAAM;EACpB,CAAC,qBAAqB,cAAc;EACpC,CAAC,uBAAuB,gBAAgB;EACxC,CAAC,2BAA2B,UAAU;EACtC,CAAC,0CAA0C,aAAa;EACxD,CAAC,oCAAoC,aAAa;EAClD,CAAC,iCAAiC,EAAE;EACpC,CAAC,sCAAsC,EAAE;CAC3C;AACF;AAEA,eAAe,uBAAuB,eAAsC;CAC1E,KAAK,MAAM,CAAC,iBAAiB,eAAe,aAAa,GAAG;EAC1D,MAAM,WAAW,KAAK,KAAK,eAAe,YAAY;EACtD,IAAI;GACF,MAAM,OAAO,QAAQ;GACrB,MAAM,IAAI,MAAM,yBAAyB,SAAS,kDAAkD;EACtG,SAAS,KAAK;GACZ,IAAK,IAA8B,SAAS,UAC1C;GAEF,MAAM;EACR;CACF;AACF;AAEA,eAAsB,cAAc,SAA6D;CAC/F,MAAM,gBAAgB,KAAK,QAAQ,QAAQ,SAAS;CACpD,IAAI,CAAC,QAAQ,OAAO;EAClB,MAAM,uBAAuB,aAAa;EAC1C,MAAM,4BAA4B,aAAa;CACjD;CAEA,KAAK,MAAM,OAAO,gBAChB,MAAM,MAAM,KAAK,KAAK,eAAe,GAAG,GAAG,EAAE,WAAW,KAAK,CAAC;CAGhE,MAAM,eAAyB,CAAC;CAChC,MAAM,OAAO,QAAQ,QAAQ,MAAM;CACnC,KAAK,MAAM,CAAC,cAAc,YAAY,eAAe,aAAa,GAAG;EACnE,MAAM,WAAW,KAAK,KAAK,eAAe,YAAY;EACtD,IAAI;GACF,MAAM,UAAU,UAAU,SAAS;IAAE,MAAM;IAAO;GAAK,CAAC;GACxD,aAAa,KAAK,YAAY;EAChC,SAAS,KAAK;GACZ,IAAK,IAA8B,SAAS,UAC1C,MAAM,IAAI,MAAM,yBAAyB,SAAS,kDAAkD;GAEtG,MAAM;EACR;CACF;CAEA,MAAM,QAAQ,MAAM,cAAc;EAAE;EAAe,OAAO,QAAQ;CAAM,CAAC;CACzE,aAAa,KAAK,GAAG,MAAM,YAAY;CAEvC,OAAO;EAAE;EAAe;CAAa;AACvC"}
1
+ {"version":3,"file":"init-uAmPfio2.mjs","names":[],"sources":["../src/workspace/init.ts"],"sourcesContent":["import { access, mkdir, writeFile } from 'node:fs/promises'\nimport path from 'node:path'\nimport { LOCAL_GRAPH_MCP_ENDPOINT } from '../config/mcp-endpoint.js'\nimport { assertNoVaultFileCollisions, scaffoldVault } from '../vault/index.js'\n\nexport interface InitWorkspaceOptions {\n targetDir: string\n force?: boolean\n}\n\nexport interface InitWorkspaceResult {\n workspaceRoot: string\n filesWritten: string[]\n}\n\nconst WORKSPACE_DIRS = [\n '.chain-insights',\n '.chain-insights/schema',\n '.chain-insights/runtime',\n '.chain-insights/runtime/logs',\n '.chain-insights/runtime-skill',\n 'cases',\n 'imports',\n 'reports',\n 'reports/graphs',\n 'reports/tables',\n 'templates',\n 'published',\n]\n\nfunction todayIso(): string {\n return new Date().toISOString().slice(0, 10)\n}\n\nfunction workspaceJson(workspaceRoot: string): string {\n return JSON.stringify({\n schema: 'chain-insights.workspace.v1',\n name: 'Chain Insights Investigations',\n workspace_root: workspaceRoot,\n default_network: 'bittensor',\n graph_mcp_endpoint: LOCAL_GRAPH_MCP_ENDPOINT,\n cases_dir: 'cases',\n imports_dir: 'imports',\n reports_dir: 'reports',\n templates_dir: 'templates',\n created_at: todayIso(),\n }, null, 2) + '\\n'\n}\n\nconst README = `# Chain Insights Investigation Vault\n\nThis is a Chain Insights AML investigation workspace and Obsidian-compatible vault.\nOpen this directory in Obsidian to review cases, entities, evidence, graphs, and\npublished investigation bundles alongside the Chain Insights runtime metadata.\n\n## Start\n\n\\`\\`\\`bash\nchain-insights mcp tools --refresh\nchain-insights wallet ready --check-only\n\\`\\`\\`\n\n## Layout\n\n\\`\\`\\`text\n.chain-insights/ Workspace metadata\ncases/ Case exports and notes\nimports/ External reports, CSVs, screenshots, raw notes\nreports/ Final or interim analyst reports\nreports/graphs/ Graph JSON for visualization\nreports/tables/ Compact tabular extracts\ntemplates/ Reusable case/report templates\npublished/ Obsidian-ready case exports and published bundles\n.chain-insights/schema/ Runtime graph schema captures\n.chain-insights/runtime/ Workspace-local runtime process state and debug logs\n.chain-insights/runtime-skill/ Workspace-specific agent schema notes\n.obsidian/ Obsidian vault configuration\nCanvases/ Obsidian canvases for graph review\nEntities/ Entity notes and indexes\nEvidence/ Evidence notes and indexes\n\\`\\`\\`\n`\n\nconst AGENTS = `# Agent Instructions\n\nYou are operating inside a Chain Insights investigation workspace.\n\n- Read README.md first.\n- If this directory is not initialized, run \\`cia init .\\` before investigation-producing commands.\n- Do not rerun init in an existing workspace unless replacing scaffolding with \\`--force\\`.\n- Read .chain-insights/runtime-skill/SKILL.md before graph queries.\n- Preserve full blockchain addresses exactly.\n- Do not guess the network for graph queries.\n- Capture or refresh graph schema before the first case query.\n- Save compact evidence with original graph field names.\n- Put canonical graph JSON in reports/graphs/ and analyst tables in reports/tables/.\n- Evidence files should summarize and point to graph/table outputs; do not paste large raw JSON blobs into evidence Markdown.\n- Investigation output must stay in this initialized workspace.\n- Never write cases, evidence, reports, graph JSON, HTML, schema captures, or logs to ~/.chain-insights.\n- Keep theories lightweight until evidence supports them.\n`\n\nconst CLAUDE = AGENTS\n\nconst CASE_BRIEF = `# Case Brief\n\n## Summary\n\nStatus:\nNetwork:\nCurrent Assessment:\n\n## Known Addresses\n\n## Claims To Validate\n\n## Evidence\n\n## Next Steps\n`\n\nconst IMPORTS_README = `# External Investigation Inputs\n\nPut user-provided or third-party investigation material here before turning it\ninto case evidence.\n\nExamples:\n\n- Exchange support exports\n- CSV extracts\n- Screenshots\n- Raw notes\n- Partner reports\n\nFiles in this directory are inputs, not verified evidence. When an import\nsupports a claim, summarize it into the case evidence manifest and reference\nthe original file path.\n`\n\nconst TEMPLATES_README = `# Reusable Workspace Templates\n\nStore local report, case, prompt, and evidence templates here.\n\nTemplates are optional workspace helpers. They are not evidence and should not\nbe treated as case state until copied into a case, evidence file, dossier, or\nreport.\n`\n\nconst RUNTIME_SKILL = `---\nname: chain-insights-runtime-schema\ndescription: Workspace-local Chain Insights runtime schema notes. Refresh this after connecting to a graph MCP endpoint.\n---\n\n# Runtime Graph Schema\n\nBefore the first investigation query, capture the live graph schema into:\n\n\\`\\`\\`text\n.chain-insights/schema/<network>.graph-schema.json\n\\`\\`\\`\n\nUse \\`graph_query_batch\\` for schema capture. Prefix current topology reads\nwith \\`USE live_topology\\`, historical topology reads with\n\\`USE archive_topology\\`, and fact reads with \\`USE facts\\`, for example:\n\n\\`\\`\\`bash\ncia mcp call graph_query_batch network=<network> 'queries=[{\"id\":\"node_labels\",\"query\":\"USE live_topology MATCH (n:Address) RETURN \\\"Address\\\" AS node_label, count(n) AS sample_count LIMIT 1\"},{\"id\":\"archive_flow_sample\",\"query\":\"USE archive_topology MATCH (:Address)-[f:FLOWS_TO]->(:Address) RETURN f.period_granularity AS granularity, f.amount_sum AS amount_sum LIMIT 20\"}]'\n\\`\\`\\`\n\nThen update this file with observed labels, relationship types, and allowed\nproperty names for the active network.\n\nRules:\n\n- Prefer \\`graph_query\\` and \\`graph_query_batch\\` for graph-language reads.\n- Use \\`USE live_topology\\` for recent topology, \\`USE archive_topology\\`\n for historical topology, and \\`USE facts\\` for labels, features,\n risk scores, assets, and enrichment. Address facts can be reached through\n relationships such as \\`(:Address)-[:HAS_FEATURE]->(:AddressFeature)\\`.\n Archived money-flow topology is exposed as\n \\`(:Address)-[:FLOWS_TO]->(:Address)\\` with \\`period_granularity\\`,\n \\`period_start_date\\`, and \\`period_end_date\\` on the relationship.\n- Preserve source schema field names in evidence and generated data files.\n- Do not rename, reinterpret, or add unit labels to graph fields unless the\n schema or query result explicitly supports that interpretation.\n- Keep evidence compact: select only the fields needed to support the claim.\n Avoid storing whole node or relationship property blobs in evidence unless\n the purpose of the query is schema discovery or debugging.\n- When using BFS, fixed-depth traversal fallbacks, or any manual \\`FLOWS_TO\\`\n traversal, treat exchange hot wallets as terminal endpoints only. Do not\n expand from, through, or classify exchange nodes as deposit, suspect, or\n intermediate candidates. In Cypher, require every non-terminal traversal node\n to satisfy \\`is_exchange IS NULL\\`; only the final exchange endpoint should\n satisfy \\`is_exchange IS NOT NULL\\`.\n- Keep analysis products separate from evidence: graph JSON belongs under\n \\`reports/graphs/\\`, tabular extracts under \\`reports/tables/\\`, and analyst\n narrative under \\`reports/\\`.\n- Evidence Markdown should be a short provenance record with key facts and\n pointers. Large JSON belongs in \\`reports/tables/\\`, not inline in evidence.\n\nTrace tool chaining:\n\n1. Use \\`trace_victim_funds\\` when the user gives victim/source addresses.\n2. Pass returned \\`continuation.candidate_deposit_addresses\\` to\n \\`trace_deposit_sources\\`; do not make victim tracing run deposit traceback\n internally.\n3. Pass high-confidence \\`continuation.candidate_suspect_addresses\\` from\n deposit traceback to \\`trace_suspect_funds\\`.\n4. Use \\`trace_suspect_funds\\` when the user gives suspected scammer, mule,\n operator, or laundering-ring addresses. \\`incident_timestamp_ms\\` is\n optional.\n5. Use \\`address_risk\\` for single-address enrichment, and\n \\`graph_query_batch\\` only when the role-specific tools do not answer the\n exact question.\n\nAll trace tools return \\`chain-insights.trace.v1\\`. Preserve full addresses in\n\\`input.addresses\\`, \\`addresses[].address\\`, \\`edges[].from_address\\`,\n\\`edges[].to_address\\`, \\`paths[].addresses\\`, \\`candidate_labels[].address\\`,\nand \\`continuation\\` address lists.\n`\n\nconst SCHEMA_README = `# Runtime Schema Captures\n\nStore graph schema captures here, for example:\n\n\\`\\`\\`text\nbittensor.graph-schema.json\n\\`\\`\\`\n\nSchema captures should be generated before the first case query in a fresh\nworkspace, then referenced by evidence, reports, and runtime skill notes.\n`\n\nfunction workspaceFiles(workspaceRoot: string): Array<[string, string]> {\n return [\n ['.chain-insights/workspace.json', workspaceJson(workspaceRoot)],\n ['README.md', README],\n ['AGENTS.md', AGENTS],\n ['CLAUDE.md', CLAUDE],\n ['imports/README.md', IMPORTS_README],\n ['templates/README.md', TEMPLATES_README],\n ['templates/case-brief.md', CASE_BRIEF],\n ['.chain-insights/runtime-skill/SKILL.md', RUNTIME_SKILL],\n ['.chain-insights/schema/README.md', SCHEMA_README],\n ['.chain-insights/runtime/.keep', ''],\n ['.chain-insights/runtime/logs/.keep', ''],\n ]\n}\n\nasync function assertNoFileCollisions(workspaceRoot: string): Promise<void> {\n for (const [relativePath] of workspaceFiles(workspaceRoot)) {\n const filePath = path.join(workspaceRoot, relativePath)\n try {\n await access(filePath)\n throw new Error(`Refusing to overwrite ${filePath}. Re-run with --force to replace workspace files.`)\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code === 'ENOENT') {\n continue\n }\n throw err\n }\n }\n}\n\nexport async function initWorkspace(options: InitWorkspaceOptions): Promise<InitWorkspaceResult> {\n const workspaceRoot = path.resolve(options.targetDir)\n if (!options.force) {\n await assertNoFileCollisions(workspaceRoot)\n await assertNoVaultFileCollisions(workspaceRoot)\n }\n\n for (const dir of WORKSPACE_DIRS) {\n await mkdir(path.join(workspaceRoot, dir), { recursive: true })\n }\n\n const filesWritten: string[] = []\n const flag = options.force ? 'w' : 'wx'\n for (const [relativePath, content] of workspaceFiles(workspaceRoot)) {\n const filePath = path.join(workspaceRoot, relativePath)\n try {\n await writeFile(filePath, content, { mode: 0o600, flag })\n filesWritten.push(relativePath)\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code === 'EEXIST') {\n throw new Error(`Refusing to overwrite ${filePath}. Re-run with --force to replace workspace files.`)\n }\n throw err\n }\n }\n\n const vault = await scaffoldVault({ workspaceRoot, force: options.force })\n filesWritten.push(...vault.filesWritten)\n\n return { workspaceRoot, filesWritten }\n}\n"],"mappings":";;;;;AAeA,MAAM,iBAAiB;CACrB;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;AACF;AAEA,SAAS,WAAmB;CAC1B,wBAAO,IAAI,KAAK,GAAE,YAAY,EAAE,MAAM,GAAG,EAAE;AAC7C;AAEA,SAAS,cAAc,eAA+B;CACpD,OAAO,KAAK,UAAU;EACpB,QAAQ;EACR,MAAM;EACN,gBAAgB;EAChB,iBAAiB;EACjB,oBAAoB;EACpB,WAAW;EACX,aAAa;EACb,aAAa;EACb,eAAe;EACf,YAAY,SAAS;CACvB,GAAG,MAAM,CAAC,IAAI;AAChB;AAEA,MAAM,SAAS;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAkCf,MAAM,SAAS;;;;;;;;;;;;;;;;;;AAmBf,MAAM,SAAS;AAEf,MAAM,aAAa;;;;;;;;;;;;;;;;AAiBnB,MAAM,iBAAiB;;;;;;;;;;;;;;;;;AAkBvB,MAAM,mBAAmB;;;;;;;;AASzB,MAAM,gBAAgB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAyEtB,MAAM,gBAAgB;;;;;;;;;;;AAYtB,SAAS,eAAe,eAAgD;CACtE,OAAO;EACL,CAAC,kCAAkC,cAAc,aAAa,CAAC;EAC/D,CAAC,aAAa,MAAM;EACpB,CAAC,aAAa,MAAM;EACpB,CAAC,aAAa,MAAM;EACpB,CAAC,qBAAqB,cAAc;EACpC,CAAC,uBAAuB,gBAAgB;EACxC,CAAC,2BAA2B,UAAU;EACtC,CAAC,0CAA0C,aAAa;EACxD,CAAC,oCAAoC,aAAa;EAClD,CAAC,iCAAiC,EAAE;EACpC,CAAC,sCAAsC,EAAE;CAC3C;AACF;AAEA,eAAe,uBAAuB,eAAsC;CAC1E,KAAK,MAAM,CAAC,iBAAiB,eAAe,aAAa,GAAG;EAC1D,MAAM,WAAW,KAAK,KAAK,eAAe,YAAY;EACtD,IAAI;GACF,MAAM,OAAO,QAAQ;GACrB,MAAM,IAAI,MAAM,yBAAyB,SAAS,kDAAkD;EACtG,SAAS,KAAK;GACZ,IAAK,IAA8B,SAAS,UAC1C;GAEF,MAAM;EACR;CACF;AACF;AAEA,eAAsB,cAAc,SAA6D;CAC/F,MAAM,gBAAgB,KAAK,QAAQ,QAAQ,SAAS;CACpD,IAAI,CAAC,QAAQ,OAAO;EAClB,MAAM,uBAAuB,aAAa;EAC1C,MAAM,4BAA4B,aAAa;CACjD;CAEA,KAAK,MAAM,OAAO,gBAChB,MAAM,MAAM,KAAK,KAAK,eAAe,GAAG,GAAG,EAAE,WAAW,KAAK,CAAC;CAGhE,MAAM,eAAyB,CAAC;CAChC,MAAM,OAAO,QAAQ,QAAQ,MAAM;CACnC,KAAK,MAAM,CAAC,cAAc,YAAY,eAAe,aAAa,GAAG;EACnE,MAAM,WAAW,KAAK,KAAK,eAAe,YAAY;EACtD,IAAI;GACF,MAAM,UAAU,UAAU,SAAS;IAAE,MAAM;IAAO;GAAK,CAAC;GACxD,aAAa,KAAK,YAAY;EAChC,SAAS,KAAK;GACZ,IAAK,IAA8B,SAAS,UAC1C,MAAM,IAAI,MAAM,yBAAyB,SAAS,kDAAkD;GAEtG,MAAM;EACR;CACF;CAEA,MAAM,QAAQ,MAAM,cAAc;EAAE;EAAe,OAAO,QAAQ;CAAM,CAAC;CACzE,aAAa,KAAK,GAAG,MAAM,YAAY;CAEvC,OAAO;EAAE;EAAe;CAAa;AACvC"}
@@ -1,5 +1,5 @@
1
1
  const require_chunk = require("./chunk-DakpK96I.cjs");
2
- const require_mcp_endpoint = require("./mcp-endpoint-BaV8h_lq.cjs");
2
+ const require_mcp_endpoint = require("./mcp-endpoint-cQIZSjkK.cjs");
3
3
  const require_vault = require("./vault-B2y78Ypu.cjs");
4
4
  let node_path = require("node:path");
5
5
  node_path = require_chunk.__toESM(node_path, 1);
@@ -14,6 +14,9 @@ function isLoopbackHost(hostname) {
14
14
  if (isIP(normalized) !== 4) return false;
15
15
  return normalized.split(".")[0] === "127";
16
16
  }
17
+ function isKubernetesServiceHost(hostname) {
18
+ return hostname.toLowerCase().endsWith(".svc.cluster.local");
19
+ }
17
20
  function graphMcpEndpointEnvOverride() {
18
21
  const envEndpoint = process.env.CHAIN_INSIGHTS_GRAPH_MCP_ENDPOINT?.trim() || process.env.GRAPH_MCP_ENDPOINT?.trim();
19
22
  return envEndpoint ? validateMcpEndpoint(envEndpoint, "graphMcpEndpoint") : void 0;
@@ -30,10 +33,10 @@ function validateMcpEndpoint(value, key) {
30
33
  if (parsed.username || parsed.password) throw new Error(`${key} must not include URL credentials.`);
31
34
  if (parsed.search || parsed.hash) throw new Error(`${key} must not include query parameters or URL fragments.`);
32
35
  if (parsed.protocol !== "https:" && parsed.protocol !== "http:") throw new Error(`${key} must use either https:// or http://.`);
33
- if (parsed.protocol === "http:" && !isLoopbackHost(parsed.hostname)) throw new Error(`${key} must use https:// for remote hosts. http:// is allowed only for localhost or loopback addresses.`);
36
+ if (parsed.protocol === "http:" && !isLoopbackHost(parsed.hostname) && !isKubernetesServiceHost(parsed.hostname)) throw new Error(`${key} must use https:// for remote hosts. http:// is allowed only for localhost, loopback addresses, or Kubernetes *.svc.cluster.local service DNS.`);
34
37
  return trimmed;
35
38
  }
36
39
  //#endregion
37
40
  export { validateMcpEndpoint as i, LOCAL_LEGACY_MCP_ENDPOINT as n, graphMcpEndpointEnvOverride as r, LOCAL_GRAPH_MCP_ENDPOINT as t };
38
41
 
39
- //# sourceMappingURL=mcp-endpoint-DHs1cRFH.mjs.map
42
+ //# sourceMappingURL=mcp-endpoint-QQ5Lbqc2.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mcp-endpoint-QQ5Lbqc2.mjs","names":[],"sources":["../src/config/mcp-endpoint.ts"],"sourcesContent":["import { isIP } from 'node:net'\n\nconst LOOPBACK_HOSTS = new Set(['localhost', '127.0.0.1', '::1', '[::1]'])\n\nexport const LOCAL_GRAPH_MCP_ENDPOINT = 'http://127.0.0.1:8012/mcp'\nexport const LOCAL_LEGACY_MCP_ENDPOINT = 'http://127.0.0.1:4000'\n\nfunction isLoopbackHost(hostname: string): boolean {\n const normalized = hostname.toLowerCase().replace(/^\\[(.*)\\]$/, '$1')\n if (LOOPBACK_HOSTS.has(normalized)) return true\n if (isIP(normalized) !== 4) return false\n return normalized.split('.')[0] === '127'\n}\n\nfunction isKubernetesServiceHost(hostname: string): boolean {\n return hostname.toLowerCase().endsWith('.svc.cluster.local')\n}\n\nexport function graphMcpEndpointEnvOverride(): string | undefined {\n const envEndpoint = process.env.CHAIN_INSIGHTS_GRAPH_MCP_ENDPOINT?.trim()\n || process.env.GRAPH_MCP_ENDPOINT?.trim()\n return envEndpoint ? validateMcpEndpoint(envEndpoint, 'graphMcpEndpoint') : undefined\n}\n\nexport function validateMcpEndpoint(value: string, key: string): string {\n const trimmed = value.trim()\n if (!trimmed) {\n throw new Error(`${key} must be a non-empty absolute URL.`)\n }\n\n let parsed: URL\n try {\n parsed = new URL(trimmed)\n } catch {\n throw new Error(\n `${key} must be an absolute URL (example: https://mcp.example.com/mcp or http://127.0.0.1:8012/mcp).`,\n )\n }\n\n if (parsed.username || parsed.password) {\n throw new Error(`${key} must not include URL credentials.`)\n }\n if (parsed.search || parsed.hash) {\n throw new Error(`${key} must not include query parameters or URL fragments.`)\n }\n if (parsed.protocol !== 'https:' && parsed.protocol !== 'http:') {\n throw new Error(`${key} must use either https:// or http://.`)\n }\n if (parsed.protocol === 'http:' && !isLoopbackHost(parsed.hostname) && !isKubernetesServiceHost(parsed.hostname)) {\n throw new Error(\n `${key} must use https:// for remote hosts. http:// is allowed only for localhost, loopback addresses, or Kubernetes *.svc.cluster.local service DNS.`,\n )\n }\n\n return trimmed\n}\n"],"mappings":";;AAEA,MAAM,iBAAiB,IAAI,IAAI;CAAC;CAAa;CAAa;CAAO;AAAO,CAAC;AAEzE,MAAa,2BAA2B;AACxC,MAAa,4BAA4B;AAEzC,SAAS,eAAe,UAA2B;CACjD,MAAM,aAAa,SAAS,YAAY,EAAE,QAAQ,cAAc,IAAI;CACpE,IAAI,eAAe,IAAI,UAAU,GAAG,OAAO;CAC3C,IAAI,KAAK,UAAU,MAAM,GAAG,OAAO;CACnC,OAAO,WAAW,MAAM,GAAG,EAAE,OAAO;AACtC;AAEA,SAAS,wBAAwB,UAA2B;CAC1D,OAAO,SAAS,YAAY,EAAE,SAAS,oBAAoB;AAC7D;AAEA,SAAgB,8BAAkD;CAChE,MAAM,cAAc,QAAQ,IAAI,mCAAmC,KAAK,KACnE,QAAQ,IAAI,oBAAoB,KAAK;CAC1C,OAAO,cAAc,oBAAoB,aAAa,kBAAkB,IAAI,KAAA;AAC9E;AAEA,SAAgB,oBAAoB,OAAe,KAAqB;CACtE,MAAM,UAAU,MAAM,KAAK;CAC3B,IAAI,CAAC,SACH,MAAM,IAAI,MAAM,GAAG,IAAI,mCAAmC;CAG5D,IAAI;CACJ,IAAI;EACF,SAAS,IAAI,IAAI,OAAO;CAC1B,QAAQ;EACN,MAAM,IAAI,MACR,GAAG,IAAI,8FACT;CACF;CAEA,IAAI,OAAO,YAAY,OAAO,UAC5B,MAAM,IAAI,MAAM,GAAG,IAAI,mCAAmC;CAE5D,IAAI,OAAO,UAAU,OAAO,MAC1B,MAAM,IAAI,MAAM,GAAG,IAAI,qDAAqD;CAE9E,IAAI,OAAO,aAAa,YAAY,OAAO,aAAa,SACtD,MAAM,IAAI,MAAM,GAAG,IAAI,sCAAsC;CAE/D,IAAI,OAAO,aAAa,WAAW,CAAC,eAAe,OAAO,QAAQ,KAAK,CAAC,wBAAwB,OAAO,QAAQ,GAC7G,MAAM,IAAI,MACR,GAAG,IAAI,+IACT;CAGF,OAAO;AACT"}
@@ -14,6 +14,9 @@ function isLoopbackHost(hostname) {
14
14
  if ((0, node_net.isIP)(normalized) !== 4) return false;
15
15
  return normalized.split(".")[0] === "127";
16
16
  }
17
+ function isKubernetesServiceHost(hostname) {
18
+ return hostname.toLowerCase().endsWith(".svc.cluster.local");
19
+ }
17
20
  function graphMcpEndpointEnvOverride() {
18
21
  const envEndpoint = process.env.CHAIN_INSIGHTS_GRAPH_MCP_ENDPOINT?.trim() || process.env.GRAPH_MCP_ENDPOINT?.trim();
19
22
  return envEndpoint ? validateMcpEndpoint(envEndpoint, "graphMcpEndpoint") : void 0;
@@ -30,7 +33,7 @@ function validateMcpEndpoint(value, key) {
30
33
  if (parsed.username || parsed.password) throw new Error(`${key} must not include URL credentials.`);
31
34
  if (parsed.search || parsed.hash) throw new Error(`${key} must not include query parameters or URL fragments.`);
32
35
  if (parsed.protocol !== "https:" && parsed.protocol !== "http:") throw new Error(`${key} must use either https:// or http://.`);
33
- if (parsed.protocol === "http:" && !isLoopbackHost(parsed.hostname)) throw new Error(`${key} must use https:// for remote hosts. http:// is allowed only for localhost or loopback addresses.`);
36
+ if (parsed.protocol === "http:" && !isLoopbackHost(parsed.hostname) && !isKubernetesServiceHost(parsed.hostname)) throw new Error(`${key} must use https:// for remote hosts. http:// is allowed only for localhost, loopback addresses, or Kubernetes *.svc.cluster.local service DNS.`);
34
37
  return trimmed;
35
38
  }
36
39
  //#endregion