chain-insights 0.3.4 → 0.3.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +28 -11
- package/dist/canvas-Cn-maEIh.mjs +203 -0
- package/dist/canvas-Cn-maEIh.mjs.map +1 -0
- package/dist/canvas-p-oKCMjc.cjs +251 -0
- package/dist/cases-Bz_9XKEw.cjs +19 -0
- package/dist/cases-TVcAifxu.mjs +16 -0
- package/dist/cases-TVcAifxu.mjs.map +1 -0
- package/dist/cli.cjs +74 -28
- package/dist/cli.mjs +74 -28
- package/dist/cli.mjs.map +1 -1
- package/dist/{data-extractor-DZUJu1Bz.mjs → data-extractor-B4nHw1wZ.mjs} +2 -2
- package/dist/{data-extractor-DZUJu1Bz.mjs.map → data-extractor-B4nHw1wZ.mjs.map} +1 -1
- package/dist/{data-extractor-Cavd7wHk.cjs → data-extractor-DS4rzy3M.cjs} +1 -1
- package/dist/{export-BqTCO9lP.mjs → export-CBhcJuZ6.mjs} +8 -205
- package/dist/export-CBhcJuZ6.mjs.map +1 -0
- package/dist/{export-DsXgtCwO.cjs → export-D4v4-6F4.cjs} +16 -214
- package/dist/index.cjs +1 -1
- package/dist/index.mjs +1 -1
- package/dist/{init-DLBL_nVG.mjs → init-CKQ6F07J.mjs} +22 -5
- package/dist/init-CKQ6F07J.mjs.map +1 -0
- package/dist/{init-zqbd7i-_.cjs → init-Dhw8F23z.cjs} +21 -4
- package/dist/mcp-proxy.cjs +20 -20
- package/dist/mcp-proxy.mjs +20 -20
- package/dist/mcp-proxy.mjs.map +1 -1
- package/dist/{public-tools-wJoAFDFa.mjs → public-tools-CyUZEz9B.mjs} +3 -3
- package/dist/{public-tools-wJoAFDFa.mjs.map → public-tools-CyUZEz9B.mjs.map} +1 -1
- package/dist/{public-tools-BvMb3H2P.cjs → public-tools-xfVNz9NE.cjs} +2 -2
- package/dist/{runner-BhZ4lnF1.cjs → runner-CVo41fjz.cjs} +2 -2
- package/dist/{runner-DIJSbkjc.mjs → runner-DWuSy1Se.mjs} +3 -3
- package/dist/{runner-DIJSbkjc.mjs.map → runner-DWuSy1Se.mjs.map} +1 -1
- package/dist/{selector-CF2o5gxN.mjs → selector-BvXM9jbe.mjs} +2 -2
- package/dist/{selector-CF2o5gxN.mjs.map → selector-BvXM9jbe.mjs.map} +1 -1
- package/dist/{selector-DfAMZEC9.cjs → selector-Dps_ZFxq.cjs} +1 -1
- package/dist/{store-CTtqQtaE.mjs → store-C2B_AssI.mjs} +2 -2
- package/dist/{store-CTtqQtaE.mjs.map → store-C2B_AssI.mjs.map} +1 -1
- package/dist/{store-CqPfs47P.cjs → store-CQhU8dz8.cjs} +0 -18
- package/dist/vault-B2y78Ypu.cjs +560 -0
- package/dist/vault-z35Dohdq.mjs +560 -0
- package/dist/vault-z35Dohdq.mjs.map +1 -0
- package/dist/{viz-Dqp3C5kb.cjs → viz-D1620cBX.cjs} +3 -3
- package/dist/{viz-5y24S5X1.mjs → viz-DB5XFG1z.mjs} +4 -4
- package/dist/{viz-5y24S5X1.mjs.map → viz-DB5XFG1z.mjs.map} +1 -1
- package/docs/graph-tools.md +24 -8
- package/docs/investigation-workspaces.md +36 -10
- package/docs/knowledge-exports.md +6 -2
- package/docs/mcp-proxy.md +29 -7
- package/docs/obsidian-vault.md +130 -0
- package/package.json +1 -1
- package/skills/chain-insights-developer-experience/SKILL.md +2 -2
- package/skills/chain-insights-investigation/SKILL.md +1 -1
- package/dist/cases-Cp9DUbEV.mjs +0 -6
- package/dist/cases-sTY5aXav.cjs +0 -9
- package/dist/export-BqTCO9lP.mjs.map +0 -1
- package/dist/init-DLBL_nVG.mjs.map +0 -1
|
@@ -882,7 +882,7 @@ async function runFundFlowProbe(remoteClient, _config, options) {
|
|
|
882
882
|
await (0, node_fs_promises.writeFile)(tableHtmlPath, buildTableHtml(seedAddress, network, flows, deposits, sourceMatches, reverseLeads), { mode: 384 });
|
|
883
883
|
await (0, node_fs_promises.writeFile)(reportPath, buildMarkdownReport(seedAddress, network, flows, deposits, sourceMatches, reverseLeads, aliases, graphPath, schemaResult.filePath), { mode: 384 });
|
|
884
884
|
if (options.caseId) {
|
|
885
|
-
const { EvidenceStore } = await Promise.resolve().then(() => require("./cases-
|
|
885
|
+
const { EvidenceStore } = await Promise.resolve().then(() => require("./cases-Bz_9XKEw.cjs")).then((n) => n.cases_exports);
|
|
886
886
|
await EvidenceStore.append(options.caseId, {
|
|
887
887
|
source: evidenceSource,
|
|
888
888
|
queryParams: `network=${network} seed_address=${seedAddress} max_hops=${maxHops} per_address_limit=${perAddressLimit} min_amount_sum=${minAmountSum}`,
|
|
@@ -2321,7 +2321,7 @@ async function traceDepositSources(remoteClient, _config, options) {
|
|
|
2321
2321
|
const artifacts = await writeTraceSourceArtifacts("trace_deposit_sources", network, graphData, rows, summaryText);
|
|
2322
2322
|
const evidence = artifactEvidence(artifacts);
|
|
2323
2323
|
if (options.caseId) {
|
|
2324
|
-
const { EvidenceStore } = await Promise.resolve().then(() => require("./cases-
|
|
2324
|
+
const { EvidenceStore } = await Promise.resolve().then(() => require("./cases-Bz_9XKEw.cjs")).then((n) => n.cases_exports);
|
|
2325
2325
|
await EvidenceStore.append(options.caseId, {
|
|
2326
2326
|
source: "trace_deposit_sources",
|
|
2327
2327
|
queryParams: `network=${network} deposit_addresses=${deposits.join(",")} max_hops=${maxHops}`,
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
const require_version = require("./version-CO9Or_YV.cjs");
|
|
2
2
|
const require_config = require("./config-BwVx19Og.cjs");
|
|
3
3
|
const require_client = require("./client-Db6IV1tv.cjs");
|
|
4
|
-
const require_viz = require("./viz-
|
|
5
|
-
const require_store = require("./store-
|
|
4
|
+
const require_viz = require("./viz-D1620cBX.cjs");
|
|
5
|
+
const require_store = require("./store-CQhU8dz8.cjs");
|
|
6
6
|
const require_evidence = require("./evidence-CvEesemA.cjs");
|
|
7
7
|
let _modelcontextprotocol_sdk_client_index_js = require("@modelcontextprotocol/sdk/client/index.js");
|
|
8
8
|
let _modelcontextprotocol_sdk_client_streamableHttp_js = require("@modelcontextprotocol/sdk/client/streamableHttp.js");
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { n as PACKAGE_VERSION } from "./version-BA3J8hu4.mjs";
|
|
2
2
|
import { n as loadConfig } from "./config-Drgc2HuF.mjs";
|
|
3
3
|
import { r as createConfiguredMcpFetch } from "./client-D4JE7fFF.mjs";
|
|
4
|
-
import { t as generateVisualization } from "./viz-
|
|
5
|
-
import { t as CaseStore } from "./store-
|
|
4
|
+
import { t as generateVisualization } from "./viz-DB5XFG1z.mjs";
|
|
5
|
+
import { t as CaseStore } from "./store-C2B_AssI.mjs";
|
|
6
6
|
import { t as EvidenceStore } from "./evidence-D96PTzOQ.mjs";
|
|
7
7
|
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
|
|
8
8
|
import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/streamableHttp.js";
|
|
@@ -146,4 +146,4 @@ async run(playbook, opts) {
|
|
|
146
146
|
//#endregion
|
|
147
147
|
export { PlaybookRunner };
|
|
148
148
|
|
|
149
|
-
//# sourceMappingURL=runner-
|
|
149
|
+
//# sourceMappingURL=runner-DWuSy1Se.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"runner-DIJSbkjc.mjs","names":[],"sources":["../src/playbooks/runner.ts"],"sourcesContent":["import { Client } from '@modelcontextprotocol/sdk/client/index.js'\nimport { StreamableHTTPClientTransport } from '@modelcontextprotocol/sdk/client/streamableHttp.js'\nimport { CaseStore } from '../cases/store.js'\nimport { EvidenceStore } from '../cases/evidence.js'\nimport { loadConfig } from '../config/index.js'\nimport { createConfiguredMcpFetch } from '../mcp/client.js'\nimport { generateVisualization } from '../viz/index.js'\nimport { PACKAGE_VERSION } from '../version.js'\nimport type { PlaybookDefinition } from './schema.js'\n\nexport interface RunnerOptions {\n caseId?: string // attach to existing case; omit for quick-case auto-creation\n from?: number // 1-based step to resume from (default: 1)\n dryRun?: boolean // print steps, no MCP calls\n params?: Record<string, string>\n}\n\n/** Sleep for ms milliseconds. */\nfunction sleep(ms: number): Promise<void> {\n return new Promise(resolve => setTimeout(resolve, ms))\n}\n\n/** Check if an error is a timeout/abort error. */\nfunction isTimeoutError(err: unknown): boolean {\n if (!(err instanceof Error)) return false\n return err.name === 'AbortError' || (err as NodeJS.ErrnoException).code === 'ECONNRESET'\n}\n\n/** Check if an error is a payment failure. */\nfunction isPaymentError(err: unknown): boolean {\n if (!(err instanceof Error)) return false\n const msg = err.message.toLowerCase()\n // Match HTTP 402 status more precisely, or x402-specific error signals\n return msg.includes('http 402') ||\n msg.includes('status 402') ||\n msg.includes('payment required') ||\n msg.includes('x402')\n}\n\n/**\n * Call an MCP tool with retry logic on timeout (up to 3 total attempts).\n * Returns the text result or throws on non-retryable error.\n */\nasync function callWithRetry(\n client: Client,\n toolName: string,\n params: Record<string, string>\n): Promise<string> {\n const MAX_ATTEMPTS = 3\n let lastErr: unknown\n\n for (let attempt = 1; attempt <= MAX_ATTEMPTS; attempt++) {\n try {\n const result = await client.callTool({ name: toolName, arguments: params })\n const content = result.content as Array<{ type: string; text?: string }>\n return content.filter(c => c.type === 'text').map(c => c.text ?? '').join('\\n')\n } catch (err) {\n if (isTimeoutError(err) && attempt < MAX_ATTEMPTS) {\n lastErr = err\n await sleep(1000)\n continue\n }\n throw err\n }\n }\n\n throw lastErr\n}\n\nasync function validateStepTools(client: Client, steps: PlaybookDefinition['steps']): Promise<void> {\n const result = await client.listTools()\n const available = new Set(result.tools.map(tool => tool.name))\n const missing = [...new Set(steps.map(step => step.tool).filter(tool => !available.has(tool)))]\n if (missing.length === 0) return\n\n const availableList = [...available].sort().join(', ') || 'none'\n throw new Error(\n `Unknown MCP tool(s) in playbook: ${missing.join(', ')}. ` +\n `Available tools: ${availableList}. Run \\`chain-insights mcp tools --refresh\\` to inspect the live MCP schema.`\n )\n}\n\nexport const PlaybookRunner = {\n /**\n * Execute a playbook definition step-by-step against the live MCP.\n *\n * @param playbook - Parsed and validated PlaybookDefinition\n * @param opts - Runner options (caseId, from, dryRun, params)\n */\n async run(playbook: PlaybookDefinition, opts: RunnerOptions): Promise<void> {\n const startIndex = (opts.from ?? 1) - 1 // convert 1-based to 0-based\n const stepsToRun = playbook.steps.slice(startIndex)\n const totalSteps = playbook.steps.length\n\n // --- DRY RUN ---\n if (opts.dryRun) {\n console.log(`Playbook: ${playbook.name} (dry run — no MCP calls)`)\n console.log(`Steps: ${totalSteps} total, starting from ${startIndex + 1}`)\n console.log('')\n for (const step of stepsToRun) {\n console.log(`Step ${step.index}/${totalSteps}: ${step.tool} (params: ${JSON.stringify(step.params)})`)\n }\n console.log('')\n console.log('Cost: unknown (MCP pricing not available without live connection)')\n return\n }\n\n // --- MCP AUTH CHECK (before case creation to avoid orphan cases) ---\n const config = await loadConfig()\n const mcpFetch = await createConfiguredMcpFetch(config)\n\n // --- CASE RESOLUTION ---\n let caseId: string\n if (opts.caseId) {\n const existingCase = await CaseStore.get(opts.caseId)\n caseId = existingCase.id\n } else {\n const newCase = await CaseStore.create({\n name: `quick-${playbook.name}-${Date.now()}`,\n tags: ['quick', 'playbook', playbook.name],\n description: `Auto-created for one-off playbook run: ${playbook.name}`,\n })\n caseId = newCase.id\n console.log(`Created quick case: ${caseId}`)\n }\n\n // --- MCP CONNECTION ---\n const client = new Client({ name: 'chain-insights-playbook', version: PACKAGE_VERSION })\n await client.connect(\n new StreamableHTTPClientTransport(new URL(config.mcpEndpoint), { fetch: mcpFetch })\n )\n\n let evidenceCount = 0\n\n try {\n await validateStepTools(client, stepsToRun)\n\n // --- STEP LOOP ---\n for (const step of stepsToRun) {\n console.log(`Step ${step.index}/${totalSteps}: ${step.label}...`)\n\n let result: string\n try {\n result = await callWithRetry(client, step.tool, step.params)\n } catch (err) {\n if (isPaymentError(err)) {\n if (process.stdin.isTTY) {\n // Interactive: prompt user\n const { createInterface } = await import('node:readline')\n const rl = createInterface({ input: process.stdin, output: process.stdout })\n const answer = await new Promise<string>(resolve => {\n rl.question(`Payment required for step ${step.index}. (retry/skip/abort): `, resolve)\n })\n rl.close()\n\n if (answer.trim().toLowerCase() === 'retry') {\n result = await callWithRetry(client, step.tool, step.params)\n } else if (answer.trim().toLowerCase() === 'skip') {\n console.log(`Step ${step.index} skipped.`)\n continue\n } else {\n throw new Error(`Aborted at step ${step.index} due to payment failure.`)\n }\n } else {\n // Non-TTY: abort\n throw new Error(\n `Payment required for step ${step.index} but no interactive terminal available. ` +\n `Configure wallet with \\`chain-insights wallet import <private-key>\\`, then run \\`chain-insights wallet ready\\`. Aborting.`\n )\n }\n } else {\n // Non-payment, non-timeout MCP error — stop and report\n const completedSteps = step.index - 1 - startIndex\n const completedMsg = completedSteps > 0\n ? `Completed: steps ${startIndex + 1}..${step.index - 1}.`\n : 'No steps completed before failure.'\n console.error(\n `Step ${step.index} failed: ${(err as Error).message}. ` +\n `${completedMsg} Run with --from ${step.index} to resume.`\n )\n throw err\n }\n }\n\n // --- STORE EVIDENCE ---\n await EvidenceStore.append(caseId, {\n source: step.tool,\n content: result,\n queryParams: JSON.stringify(step.params),\n })\n evidenceCount++\n console.log(` (${result.length} chars stored)`)\n }\n\n // --- AUTO-VIZ for trace-funds ---\n if (playbook.name === 'trace-funds') {\n try {\n const viz = await generateVisualization({ caseId })\n console.log(`Visualization generated: ${viz.htmlPath}`)\n } catch {\n console.log('No transaction data to visualize.')\n }\n }\n\n // --- FINAL SUMMARY ---\n console.log(`Playbook complete. Case: ${caseId}. Evidence: ${evidenceCount} entries.`)\n } finally {\n await client.close()\n }\n },\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"runner-DWuSy1Se.mjs","names":[],"sources":["../src/playbooks/runner.ts"],"sourcesContent":["import { Client } from '@modelcontextprotocol/sdk/client/index.js'\nimport { StreamableHTTPClientTransport } from '@modelcontextprotocol/sdk/client/streamableHttp.js'\nimport { CaseStore } from '../cases/store.js'\nimport { EvidenceStore } from '../cases/evidence.js'\nimport { loadConfig } from '../config/index.js'\nimport { createConfiguredMcpFetch } from '../mcp/client.js'\nimport { generateVisualization } from '../viz/index.js'\nimport { PACKAGE_VERSION } from '../version.js'\nimport type { PlaybookDefinition } from './schema.js'\n\nexport interface RunnerOptions {\n caseId?: string // attach to existing case; omit for quick-case auto-creation\n from?: number // 1-based step to resume from (default: 1)\n dryRun?: boolean // print steps, no MCP calls\n params?: Record<string, string>\n}\n\n/** Sleep for ms milliseconds. */\nfunction sleep(ms: number): Promise<void> {\n return new Promise(resolve => setTimeout(resolve, ms))\n}\n\n/** Check if an error is a timeout/abort error. */\nfunction isTimeoutError(err: unknown): boolean {\n if (!(err instanceof Error)) return false\n return err.name === 'AbortError' || (err as NodeJS.ErrnoException).code === 'ECONNRESET'\n}\n\n/** Check if an error is a payment failure. */\nfunction isPaymentError(err: unknown): boolean {\n if (!(err instanceof Error)) return false\n const msg = err.message.toLowerCase()\n // Match HTTP 402 status more precisely, or x402-specific error signals\n return msg.includes('http 402') ||\n msg.includes('status 402') ||\n msg.includes('payment required') ||\n msg.includes('x402')\n}\n\n/**\n * Call an MCP tool with retry logic on timeout (up to 3 total attempts).\n * Returns the text result or throws on non-retryable error.\n */\nasync function callWithRetry(\n client: Client,\n toolName: string,\n params: Record<string, string>\n): Promise<string> {\n const MAX_ATTEMPTS = 3\n let lastErr: unknown\n\n for (let attempt = 1; attempt <= MAX_ATTEMPTS; attempt++) {\n try {\n const result = await client.callTool({ name: toolName, arguments: params })\n const content = result.content as Array<{ type: string; text?: string }>\n return content.filter(c => c.type === 'text').map(c => c.text ?? '').join('\\n')\n } catch (err) {\n if (isTimeoutError(err) && attempt < MAX_ATTEMPTS) {\n lastErr = err\n await sleep(1000)\n continue\n }\n throw err\n }\n }\n\n throw lastErr\n}\n\nasync function validateStepTools(client: Client, steps: PlaybookDefinition['steps']): Promise<void> {\n const result = await client.listTools()\n const available = new Set(result.tools.map(tool => tool.name))\n const missing = [...new Set(steps.map(step => step.tool).filter(tool => !available.has(tool)))]\n if (missing.length === 0) return\n\n const availableList = [...available].sort().join(', ') || 'none'\n throw new Error(\n `Unknown MCP tool(s) in playbook: ${missing.join(', ')}. ` +\n `Available tools: ${availableList}. Run \\`chain-insights mcp tools --refresh\\` to inspect the live MCP schema.`\n )\n}\n\nexport const PlaybookRunner = {\n /**\n * Execute a playbook definition step-by-step against the live MCP.\n *\n * @param playbook - Parsed and validated PlaybookDefinition\n * @param opts - Runner options (caseId, from, dryRun, params)\n */\n async run(playbook: PlaybookDefinition, opts: RunnerOptions): Promise<void> {\n const startIndex = (opts.from ?? 1) - 1 // convert 1-based to 0-based\n const stepsToRun = playbook.steps.slice(startIndex)\n const totalSteps = playbook.steps.length\n\n // --- DRY RUN ---\n if (opts.dryRun) {\n console.log(`Playbook: ${playbook.name} (dry run — no MCP calls)`)\n console.log(`Steps: ${totalSteps} total, starting from ${startIndex + 1}`)\n console.log('')\n for (const step of stepsToRun) {\n console.log(`Step ${step.index}/${totalSteps}: ${step.tool} (params: ${JSON.stringify(step.params)})`)\n }\n console.log('')\n console.log('Cost: unknown (MCP pricing not available without live connection)')\n return\n }\n\n // --- MCP AUTH CHECK (before case creation to avoid orphan cases) ---\n const config = await loadConfig()\n const mcpFetch = await createConfiguredMcpFetch(config)\n\n // --- CASE RESOLUTION ---\n let caseId: string\n if (opts.caseId) {\n const existingCase = await CaseStore.get(opts.caseId)\n caseId = existingCase.id\n } else {\n const newCase = await CaseStore.create({\n name: `quick-${playbook.name}-${Date.now()}`,\n tags: ['quick', 'playbook', playbook.name],\n description: `Auto-created for one-off playbook run: ${playbook.name}`,\n })\n caseId = newCase.id\n console.log(`Created quick case: ${caseId}`)\n }\n\n // --- MCP CONNECTION ---\n const client = new Client({ name: 'chain-insights-playbook', version: PACKAGE_VERSION })\n await client.connect(\n new StreamableHTTPClientTransport(new URL(config.mcpEndpoint), { fetch: mcpFetch })\n )\n\n let evidenceCount = 0\n\n try {\n await validateStepTools(client, stepsToRun)\n\n // --- STEP LOOP ---\n for (const step of stepsToRun) {\n console.log(`Step ${step.index}/${totalSteps}: ${step.label}...`)\n\n let result: string\n try {\n result = await callWithRetry(client, step.tool, step.params)\n } catch (err) {\n if (isPaymentError(err)) {\n if (process.stdin.isTTY) {\n // Interactive: prompt user\n const { createInterface } = await import('node:readline')\n const rl = createInterface({ input: process.stdin, output: process.stdout })\n const answer = await new Promise<string>(resolve => {\n rl.question(`Payment required for step ${step.index}. (retry/skip/abort): `, resolve)\n })\n rl.close()\n\n if (answer.trim().toLowerCase() === 'retry') {\n result = await callWithRetry(client, step.tool, step.params)\n } else if (answer.trim().toLowerCase() === 'skip') {\n console.log(`Step ${step.index} skipped.`)\n continue\n } else {\n throw new Error(`Aborted at step ${step.index} due to payment failure.`)\n }\n } else {\n // Non-TTY: abort\n throw new Error(\n `Payment required for step ${step.index} but no interactive terminal available. ` +\n `Configure wallet with \\`chain-insights wallet import <private-key>\\`, then run \\`chain-insights wallet ready\\`. Aborting.`\n )\n }\n } else {\n // Non-payment, non-timeout MCP error — stop and report\n const completedSteps = step.index - 1 - startIndex\n const completedMsg = completedSteps > 0\n ? `Completed: steps ${startIndex + 1}..${step.index - 1}.`\n : 'No steps completed before failure.'\n console.error(\n `Step ${step.index} failed: ${(err as Error).message}. ` +\n `${completedMsg} Run with --from ${step.index} to resume.`\n )\n throw err\n }\n }\n\n // --- STORE EVIDENCE ---\n await EvidenceStore.append(caseId, {\n source: step.tool,\n content: result,\n queryParams: JSON.stringify(step.params),\n })\n evidenceCount++\n console.log(` (${result.length} chars stored)`)\n }\n\n // --- AUTO-VIZ for trace-funds ---\n if (playbook.name === 'trace-funds') {\n try {\n const viz = await generateVisualization({ caseId })\n console.log(`Visualization generated: ${viz.htmlPath}`)\n } catch {\n console.log('No transaction data to visualize.')\n }\n }\n\n // --- FINAL SUMMARY ---\n console.log(`Playbook complete. Case: ${caseId}. Evidence: ${evidenceCount} entries.`)\n } finally {\n await client.close()\n }\n },\n}\n"],"mappings":"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"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { t as CaseStore } from "./store-
|
|
1
|
+
import { t as CaseStore } from "./store-C2B_AssI.mjs";
|
|
2
2
|
//#region src/cases/selector.ts
|
|
3
3
|
async function resolveCaseSelector(input) {
|
|
4
4
|
if (!/^[1-9]\d*$/.test(input)) return input;
|
|
@@ -9,4 +9,4 @@ async function resolveCaseSelector(input) {
|
|
|
9
9
|
//#endregion
|
|
10
10
|
export { resolveCaseSelector };
|
|
11
11
|
|
|
12
|
-
//# sourceMappingURL=selector-
|
|
12
|
+
//# sourceMappingURL=selector-BvXM9jbe.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"selector-
|
|
1
|
+
{"version":3,"file":"selector-BvXM9jbe.mjs","names":[],"sources":["../src/cases/selector.ts"],"sourcesContent":["import { CaseStore } from './store.js'\n\nexport async function resolveCaseSelector(input: string): Promise<string> {\n if (!/^[1-9]\\d*$/.test(input)) return input\n\n const cases = await CaseStore.list()\n const index = Number(input) - 1\n const selected = cases[index]\n if (!selected) {\n throw new Error(`No case numbered ${input}. Run \\`cia case list\\` to see available cases.`)\n }\n return selected.id\n}\n"],"mappings":";;AAEA,eAAsB,oBAAoB,OAAgC;CACxE,IAAI,CAAC,aAAa,KAAK,KAAK,GAAG,OAAO;CAItC,MAAM,YAAW,MAFG,UAAU,KAAK,GACrB,OAAO,KAAK,IAAI;CAE9B,IAAI,CAAC,UACH,MAAM,IAAI,MAAM,oBAAoB,MAAM,gDAAgD;CAE5F,OAAO,SAAS;AAClB"}
|
|
@@ -226,6 +226,6 @@ const CaseStore = {
|
|
|
226
226
|
}
|
|
227
227
|
};
|
|
228
228
|
//#endregion
|
|
229
|
-
export {
|
|
229
|
+
export { store_exports as n, CaseStore as t };
|
|
230
230
|
|
|
231
|
-
//# sourceMappingURL=store-
|
|
231
|
+
//# sourceMappingURL=store-C2B_AssI.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"store-CTtqQtaE.mjs","names":["nodeErr"],"sources":["../src/cases/schema.ts","../src/cases/store.ts"],"sourcesContent":["import * as z from 'zod'\n\n// Case ID format: YYYYMMDD_NNN_slug (e.g. 20260511_001_tornado-mixer)\n// Regex rejects path traversal chars (../, shell chars) per T-03-01 threat model.\nconst caseIdRegex = /^\\d{8}_\\d{3}_[a-z0-9][a-z0-9-]*$/\n\nexport const CaseStatusEnum = z.enum(['open', 'active', 'suspended', 'closed'])\nexport type CaseStatus = z.infer<typeof CaseStatusEnum>\n\nexport const CaseSchema = z.object({\n id: z.string().regex(caseIdRegex, 'Invalid case ID format'),\n name: z.string().min(1).max(200),\n status: CaseStatusEnum.default('open'),\n created: z.string().datetime(),\n updated: z.string().datetime(),\n tags: z.array(z.string()).default([]),\n description: z.string().default(''),\n slug: z.string().optional(),\n})\nexport type Case = z.infer<typeof CaseSchema>\n\nexport const EvidenceSchema = z.object({\n id: z.string().min(1),\n caseId: z.string().regex(caseIdRegex),\n source: z.string().min(1),\n timestamp: z.string().datetime(),\n queryParams: z.string().default(''),\n})\nexport type Evidence = z.infer<typeof EvidenceSchema>\n\nexport const DossierSchema = z.object({\n address: z.string().min(1).max(100),\n type: z.enum(['eoa', 'contract', 'exchange', 'mixer', 'unknown']).default('unknown'),\n firstSeen: z.string().datetime(),\n lastSeen: z.string().datetime(),\n riskTags: z.string().default(''),\n})\nexport type Dossier = z.infer<typeof DossierSchema>\n\nexport const SessionSchema = z.object({\n sessionId: z.string().min(1),\n caseId: z.string().regex(caseIdRegex),\n startTime: z.string().datetime(),\n endTime: z.string().optional(),\n status: z.enum(['active', 'ended']).default('active'),\n})\nexport type Session = z.infer<typeof SessionSchema>\n","import { readFile, writeFile, mkdir, readdir } from 'node:fs/promises'\nimport path from 'node:path'\nimport { workspaceOutputPaths } from '../workspace/output-root.js'\nimport { parseFrontmatter, serializeFrontmatter } from './frontmatter.js'\nimport { CaseSchema, type Case, type CaseStatus } from './schema.js'\n\nexport const casesRoot = () => workspaceOutputPaths().casesRoot\n\nfunction caseDir(id: string): string {\n return path.join(casesRoot(), id)\n}\n\nexport function generateCaseId(name: string, existingIds: string[]): string {\n const date = new Date().toISOString().slice(0, 10).replace(/-/g, '')\n const slug = name.toLowerCase()\n .replace(/[^a-z0-9]+/g, '-')\n .replace(/(^-|-$)/g, '')\n .slice(0, 40)\n const todayNums = existingIds\n .filter(id => id.startsWith(date + '_'))\n .map(id => parseInt(id.split('_')[1] ?? '0', 10))\n .filter(n => !isNaN(n))\n const next = todayNums.length > 0 ? Math.max(...todayNums) + 1 : 1\n return `${date}_${String(next).padStart(3, '0')}_${slug}`\n}\n\nexport const CaseStore = {\n async create(input: { name: string; tags: string[]; description: string }): Promise<Case> {\n const root = casesRoot()\n await mkdir(root, { recursive: true })\n const existingIds = await readdir(root).catch(() => [])\n const id = generateCaseId(input.name, existingIds)\n const slug = id.split('_').slice(2).join('_')\n const now = new Date().toISOString()\n const tags = input.tags\n\n const dir = caseDir(id)\n await mkdir(path.join(dir, 'evidence'), { recursive: true })\n await mkdir(path.join(dir, 'dossiers'), { recursive: true })\n\n const fm: Record<string, string> = {\n id,\n name: input.name,\n status: 'open',\n created: now,\n updated: now,\n tags: tags.join(','),\n description: input.description,\n slug,\n }\n const body = [\n `# ${input.name}`,\n '',\n `Opened: ${now}`,\n `Status: open`,\n '',\n '## Question',\n '',\n input.description || 'TBD',\n '',\n '## Current Assessment',\n '',\n 'TBD',\n '',\n '## Top Findings',\n '',\n '| Finding | Confidence | Evidence |',\n '|---|---:|---|',\n '',\n '## Next Actions',\n '',\n '- TBD',\n '',\n '## Reports',\n '',\n ].join('\\n')\n await writeFile(path.join(dir, 'case.md'), serializeFrontmatter(fm, body), { mode: 0o600 })\n\n const manifest = JSON.stringify({ caseId: id, entries: [] }, null, 2) + '\\n'\n await writeFile(path.join(dir, 'manifest.json'), manifest, { mode: 0o600 })\n\n return CaseSchema.parse({ id, name: input.name, status: 'open', created: now, updated: now, tags, description: input.description, slug })\n },\n\n async setStatus(id: string, status: CaseStatus): Promise<Case> {\n const dir = caseDir(id)\n const filePath = path.join(dir, 'case.md')\n const raw = await readFile(filePath, 'utf8')\n const { frontmatter, body } = parseFrontmatter(raw)\n const now = new Date().toISOString()\n frontmatter['status'] = status\n frontmatter['updated'] = now\n await writeFile(filePath, serializeFrontmatter(frontmatter, body), { mode: 0o600 })\n\n const tags = (frontmatter['tags'] ?? '').split(',').filter(Boolean)\n return CaseSchema.parse({\n id,\n name: frontmatter['name'] ?? '',\n status,\n created: frontmatter['created'] ?? now,\n updated: now,\n tags,\n description: frontmatter['description'] ?? '',\n })\n },\n\n async list(): Promise<Array<{ id: string; name: string; status: string }>> {\n const root = casesRoot()\n try {\n const ids = await readdir(root)\n const cases: Array<{ id: string; name: string; status: string; created: string }> = []\n for (const id of ids) {\n try {\n const raw = await readFile(path.join(caseDir(id), 'case.md'), 'utf8')\n const { frontmatter } = parseFrontmatter(raw)\n cases.push({\n id,\n name: frontmatter['name'] ?? id,\n status: frontmatter['status'] ?? 'open',\n created: frontmatter['created'] ?? '',\n })\n } catch (err: unknown) {\n const nodeErr = err as NodeJS.ErrnoException\n if (nodeErr.code !== 'ENOENT' && nodeErr.code !== 'ENOTDIR') throw err\n }\n }\n return cases\n .sort((a, b) => b.created.localeCompare(a.created) || b.id.localeCompare(a.id))\n .map(({ id, name, status }) => ({ id, name, status }))\n } catch (err: unknown) {\n const nodeErr = err as NodeJS.ErrnoException\n if (nodeErr.code === 'ENOENT') return []\n throw err\n }\n },\n\n async get(id: string): Promise<Case> {\n const dir = caseDir(id)\n const raw = await readFile(path.join(dir, 'case.md'), 'utf8')\n const { frontmatter } = parseFrontmatter(raw)\n const tags = (frontmatter['tags'] ?? '').split(',').filter(Boolean)\n return CaseSchema.parse({\n id,\n name: frontmatter['name'] ?? '',\n status: frontmatter['status'] ?? 'open',\n created: frontmatter['created'] ?? new Date().toISOString(),\n updated: frontmatter['updated'] ?? new Date().toISOString(),\n tags,\n description: frontmatter['description'] ?? '',\n })\n },\n\n async loadContext(id: string): Promise<{\n case: { id: string; name: string; status: string; created: string; updated: string; tags: string[] };\n lastSession: { sessionId: string; startTime: string; endTime?: string; body: string } | null;\n dossierSummaries: Array<{ address: string; type: string; riskTags: string; firstSeen: string; lastSeen: string }>;\n evidenceCount: number;\n }> {\n const dir = caseDir(id)\n\n // Read case.md\n const raw = await readFile(path.join(dir, 'case.md'), 'utf8')\n const { frontmatter } = parseFrontmatter(raw)\n const tags = (frontmatter['tags'] ?? '').split(',').filter(Boolean)\n\n // Lazy imports to avoid circular deps\n const { SessionStore } = await import('./session.js')\n const { DossierStore } = await import('./dossier.js')\n\n const [latestSession, dossierSummaries, manifest] = await Promise.all([\n SessionStore.getLatest(id),\n DossierStore.listSummaries(id),\n readFile(path.join(dir, 'manifest.json'), 'utf8').catch(() => '{\"entries\":[]}'),\n ])\n\n const manifestData = JSON.parse(manifest) as { entries: unknown[] }\n const evidenceCount = manifestData.entries.length\n\n const lastSession = latestSession\n ? {\n sessionId: latestSession.frontmatter['sessionId'] ?? '',\n startTime: latestSession.frontmatter['startTime'] ?? '',\n endTime: latestSession.frontmatter['endTime'] || undefined,\n body: latestSession.body,\n }\n : null\n\n return {\n case: {\n id,\n name: frontmatter['name'] ?? '',\n status: frontmatter['status'] ?? 'open',\n created: frontmatter['created'] ?? '',\n updated: frontmatter['updated'] ?? '',\n tags,\n },\n lastSession,\n dossierSummaries,\n evidenceCount,\n }\n },\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"store-C2B_AssI.mjs","names":["nodeErr"],"sources":["../src/cases/schema.ts","../src/cases/store.ts"],"sourcesContent":["import * as z from 'zod'\n\n// Case ID format: YYYYMMDD_NNN_slug (e.g. 20260511_001_tornado-mixer)\n// Regex rejects path traversal chars (../, shell chars) per T-03-01 threat model.\nconst caseIdRegex = /^\\d{8}_\\d{3}_[a-z0-9][a-z0-9-]*$/\n\nexport const CaseStatusEnum = z.enum(['open', 'active', 'suspended', 'closed'])\nexport type CaseStatus = z.infer<typeof CaseStatusEnum>\n\nexport const CaseSchema = z.object({\n id: z.string().regex(caseIdRegex, 'Invalid case ID format'),\n name: z.string().min(1).max(200),\n status: CaseStatusEnum.default('open'),\n created: z.string().datetime(),\n updated: z.string().datetime(),\n tags: z.array(z.string()).default([]),\n description: z.string().default(''),\n slug: z.string().optional(),\n})\nexport type Case = z.infer<typeof CaseSchema>\n\nexport const EvidenceSchema = z.object({\n id: z.string().min(1),\n caseId: z.string().regex(caseIdRegex),\n source: z.string().min(1),\n timestamp: z.string().datetime(),\n queryParams: z.string().default(''),\n})\nexport type Evidence = z.infer<typeof EvidenceSchema>\n\nexport const DossierSchema = z.object({\n address: z.string().min(1).max(100),\n type: z.enum(['eoa', 'contract', 'exchange', 'mixer', 'unknown']).default('unknown'),\n firstSeen: z.string().datetime(),\n lastSeen: z.string().datetime(),\n riskTags: z.string().default(''),\n})\nexport type Dossier = z.infer<typeof DossierSchema>\n\nexport const SessionSchema = z.object({\n sessionId: z.string().min(1),\n caseId: z.string().regex(caseIdRegex),\n startTime: z.string().datetime(),\n endTime: z.string().optional(),\n status: z.enum(['active', 'ended']).default('active'),\n})\nexport type Session = z.infer<typeof SessionSchema>\n","import { readFile, writeFile, mkdir, readdir } from 'node:fs/promises'\nimport path from 'node:path'\nimport { workspaceOutputPaths } from '../workspace/output-root.js'\nimport { parseFrontmatter, serializeFrontmatter } from './frontmatter.js'\nimport { CaseSchema, type Case, type CaseStatus } from './schema.js'\n\nexport const casesRoot = () => workspaceOutputPaths().casesRoot\n\nfunction caseDir(id: string): string {\n return path.join(casesRoot(), id)\n}\n\nexport function generateCaseId(name: string, existingIds: string[]): string {\n const date = new Date().toISOString().slice(0, 10).replace(/-/g, '')\n const slug = name.toLowerCase()\n .replace(/[^a-z0-9]+/g, '-')\n .replace(/(^-|-$)/g, '')\n .slice(0, 40)\n const todayNums = existingIds\n .filter(id => id.startsWith(date + '_'))\n .map(id => parseInt(id.split('_')[1] ?? '0', 10))\n .filter(n => !isNaN(n))\n const next = todayNums.length > 0 ? Math.max(...todayNums) + 1 : 1\n return `${date}_${String(next).padStart(3, '0')}_${slug}`\n}\n\nexport const CaseStore = {\n async create(input: { name: string; tags: string[]; description: string }): Promise<Case> {\n const root = casesRoot()\n await mkdir(root, { recursive: true })\n const existingIds = await readdir(root).catch(() => [])\n const id = generateCaseId(input.name, existingIds)\n const slug = id.split('_').slice(2).join('_')\n const now = new Date().toISOString()\n const tags = input.tags\n\n const dir = caseDir(id)\n await mkdir(path.join(dir, 'evidence'), { recursive: true })\n await mkdir(path.join(dir, 'dossiers'), { recursive: true })\n\n const fm: Record<string, string> = {\n id,\n name: input.name,\n status: 'open',\n created: now,\n updated: now,\n tags: tags.join(','),\n description: input.description,\n slug,\n }\n const body = [\n `# ${input.name}`,\n '',\n `Opened: ${now}`,\n `Status: open`,\n '',\n '## Question',\n '',\n input.description || 'TBD',\n '',\n '## Current Assessment',\n '',\n 'TBD',\n '',\n '## Top Findings',\n '',\n '| Finding | Confidence | Evidence |',\n '|---|---:|---|',\n '',\n '## Next Actions',\n '',\n '- TBD',\n '',\n '## Reports',\n '',\n ].join('\\n')\n await writeFile(path.join(dir, 'case.md'), serializeFrontmatter(fm, body), { mode: 0o600 })\n\n const manifest = JSON.stringify({ caseId: id, entries: [] }, null, 2) + '\\n'\n await writeFile(path.join(dir, 'manifest.json'), manifest, { mode: 0o600 })\n\n return CaseSchema.parse({ id, name: input.name, status: 'open', created: now, updated: now, tags, description: input.description, slug })\n },\n\n async setStatus(id: string, status: CaseStatus): Promise<Case> {\n const dir = caseDir(id)\n const filePath = path.join(dir, 'case.md')\n const raw = await readFile(filePath, 'utf8')\n const { frontmatter, body } = parseFrontmatter(raw)\n const now = new Date().toISOString()\n frontmatter['status'] = status\n frontmatter['updated'] = now\n await writeFile(filePath, serializeFrontmatter(frontmatter, body), { mode: 0o600 })\n\n const tags = (frontmatter['tags'] ?? '').split(',').filter(Boolean)\n return CaseSchema.parse({\n id,\n name: frontmatter['name'] ?? '',\n status,\n created: frontmatter['created'] ?? now,\n updated: now,\n tags,\n description: frontmatter['description'] ?? '',\n })\n },\n\n async list(): Promise<Array<{ id: string; name: string; status: string }>> {\n const root = casesRoot()\n try {\n const ids = await readdir(root)\n const cases: Array<{ id: string; name: string; status: string; created: string }> = []\n for (const id of ids) {\n try {\n const raw = await readFile(path.join(caseDir(id), 'case.md'), 'utf8')\n const { frontmatter } = parseFrontmatter(raw)\n cases.push({\n id,\n name: frontmatter['name'] ?? id,\n status: frontmatter['status'] ?? 'open',\n created: frontmatter['created'] ?? '',\n })\n } catch (err: unknown) {\n const nodeErr = err as NodeJS.ErrnoException\n if (nodeErr.code !== 'ENOENT' && nodeErr.code !== 'ENOTDIR') throw err\n }\n }\n return cases\n .sort((a, b) => b.created.localeCompare(a.created) || b.id.localeCompare(a.id))\n .map(({ id, name, status }) => ({ id, name, status }))\n } catch (err: unknown) {\n const nodeErr = err as NodeJS.ErrnoException\n if (nodeErr.code === 'ENOENT') return []\n throw err\n }\n },\n\n async get(id: string): Promise<Case> {\n const dir = caseDir(id)\n const raw = await readFile(path.join(dir, 'case.md'), 'utf8')\n const { frontmatter } = parseFrontmatter(raw)\n const tags = (frontmatter['tags'] ?? '').split(',').filter(Boolean)\n return CaseSchema.parse({\n id,\n name: frontmatter['name'] ?? '',\n status: frontmatter['status'] ?? 'open',\n created: frontmatter['created'] ?? new Date().toISOString(),\n updated: frontmatter['updated'] ?? new Date().toISOString(),\n tags,\n description: frontmatter['description'] ?? '',\n })\n },\n\n async loadContext(id: string): Promise<{\n case: { id: string; name: string; status: string; created: string; updated: string; tags: string[] };\n lastSession: { sessionId: string; startTime: string; endTime?: string; body: string } | null;\n dossierSummaries: Array<{ address: string; type: string; riskTags: string; firstSeen: string; lastSeen: string }>;\n evidenceCount: number;\n }> {\n const dir = caseDir(id)\n\n // Read case.md\n const raw = await readFile(path.join(dir, 'case.md'), 'utf8')\n const { frontmatter } = parseFrontmatter(raw)\n const tags = (frontmatter['tags'] ?? '').split(',').filter(Boolean)\n\n // Lazy imports to avoid circular deps\n const { SessionStore } = await import('./session.js')\n const { DossierStore } = await import('./dossier.js')\n\n const [latestSession, dossierSummaries, manifest] = await Promise.all([\n SessionStore.getLatest(id),\n DossierStore.listSummaries(id),\n readFile(path.join(dir, 'manifest.json'), 'utf8').catch(() => '{\"entries\":[]}'),\n ])\n\n const manifestData = JSON.parse(manifest) as { entries: unknown[] }\n const evidenceCount = manifestData.entries.length\n\n const lastSession = latestSession\n ? {\n sessionId: latestSession.frontmatter['sessionId'] ?? '',\n startTime: latestSession.frontmatter['startTime'] ?? '',\n endTime: latestSession.frontmatter['endTime'] || undefined,\n body: latestSession.body,\n }\n : null\n\n return {\n case: {\n id,\n name: frontmatter['name'] ?? '',\n status: frontmatter['status'] ?? 'open',\n created: frontmatter['created'] ?? '',\n updated: frontmatter['updated'] ?? '',\n tags,\n },\n lastSession,\n dossierSummaries,\n evidenceCount,\n }\n },\n}\n"],"mappings":"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"}
|
|
@@ -228,30 +228,12 @@ const CaseStore = {
|
|
|
228
228
|
}
|
|
229
229
|
};
|
|
230
230
|
//#endregion
|
|
231
|
-
Object.defineProperty(exports, "CaseSchema", {
|
|
232
|
-
enumerable: true,
|
|
233
|
-
get: function() {
|
|
234
|
-
return CaseSchema;
|
|
235
|
-
}
|
|
236
|
-
});
|
|
237
|
-
Object.defineProperty(exports, "CaseStatusEnum", {
|
|
238
|
-
enumerable: true,
|
|
239
|
-
get: function() {
|
|
240
|
-
return CaseStatusEnum;
|
|
241
|
-
}
|
|
242
|
-
});
|
|
243
231
|
Object.defineProperty(exports, "CaseStore", {
|
|
244
232
|
enumerable: true,
|
|
245
233
|
get: function() {
|
|
246
234
|
return CaseStore;
|
|
247
235
|
}
|
|
248
236
|
});
|
|
249
|
-
Object.defineProperty(exports, "generateCaseId", {
|
|
250
|
-
enumerable: true,
|
|
251
|
-
get: function() {
|
|
252
|
-
return generateCaseId;
|
|
253
|
-
}
|
|
254
|
-
});
|
|
255
237
|
Object.defineProperty(exports, "store_exports", {
|
|
256
238
|
enumerable: true,
|
|
257
239
|
get: function() {
|