chain-insights 0.37.3 → 0.42.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +31 -1
- package/bin/install.cjs +59 -2
- package/dist/{action-log-diTHyMbV.mjs → action-log-D49Par9P.mjs} +2 -2
- package/dist/{action-log-diTHyMbV.mjs.map → action-log-D49Par9P.mjs.map} +1 -1
- package/dist/{active-BQopLul8.mjs → active-Dkf8AB1R.mjs} +2 -2
- package/dist/{active-BQopLul8.mjs.map → active-Dkf8AB1R.mjs.map} +1 -1
- package/dist/apps/claude-view.html +117 -0
- package/dist/{capabilities-BbAQ4Tfa.cjs → capabilities-A8fsfP24.cjs} +4 -1
- package/dist/{capabilities-C8DQSfyW.mjs → capabilities-DfWL6n_g.mjs} +7 -4
- package/dist/capabilities-DfWL6n_g.mjs.map +1 -0
- package/dist/cli.cjs +84 -133
- package/dist/cli.mjs +102 -151
- package/dist/cli.mjs.map +1 -1
- package/dist/{client-CHYskPnG.mjs → client-gsLi528K.mjs} +4 -4
- package/dist/{client-CHYskPnG.mjs.map → client-gsLi528K.mjs.map} +1 -1
- package/dist/{config-DbbPiGk0.mjs → config-9MabJh5R.mjs} +36 -4
- package/dist/config-9MabJh5R.mjs.map +1 -0
- package/dist/{config-B542AM4w.cjs → config-BxtMoo9c.cjs} +33 -1
- package/dist/{create-C0buxEfU.mjs → create-CpfZq2fx.mjs} +2 -2
- package/dist/{create-C0buxEfU.mjs.map → create-CpfZq2fx.mjs.map} +1 -1
- package/dist/flows-BfUlyWvJ.mjs +344 -0
- package/dist/flows-BfUlyWvJ.mjs.map +1 -0
- package/dist/flows-CzsxUf35.cjs +394 -0
- package/dist/index.cjs +5 -4
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +7 -6
- package/dist/mcp-proxy.cjs +215 -45
- package/dist/mcp-proxy.d.cts +7 -0
- package/dist/mcp-proxy.d.cts.map +1 -1
- package/dist/mcp-proxy.d.mts +7 -0
- package/dist/mcp-proxy.d.mts.map +1 -1
- package/dist/mcp-proxy.mjs +219 -52
- package/dist/mcp-proxy.mjs.map +1 -1
- package/dist/print-result-BEA_PyNz.cjs +178 -0
- package/dist/print-result-k9kXVR2c.mjs +151 -0
- package/dist/print-result-k9kXVR2c.mjs.map +1 -0
- package/dist/{public-tools-DWONw7kZ.cjs → public-tools-3yTC17cA.cjs} +1 -6
- package/dist/{public-tools-CDpFHbZ8.mjs → public-tools-CZyeptJQ.mjs} +3 -8
- package/dist/public-tools-CZyeptJQ.mjs.map +1 -0
- package/dist/{rolldown-runtime-D7D4PA-g.mjs → rolldown-runtime-8H4AJuhK.mjs} +1 -0
- package/dist/{schema-B0OuHW_l.mjs → schema-KjZqCHbu.mjs} +3 -3
- package/dist/schema-KjZqCHbu.mjs.map +1 -0
- package/dist/schema-cache-DJdU4MIP.mjs.map +1 -1
- package/dist/{schema-CtFWYoJz.cjs → schema-tX0U0-VI.cjs} +1 -1
- package/dist/{subscription-status-MyeqOmbA.mjs → subscription-status-CJ-DaMW9.mjs} +2 -2
- package/dist/{subscription-status-MyeqOmbA.mjs.map → subscription-status-CJ-DaMW9.mjs.map} +1 -1
- package/dist/{tool-visibility-CyZqYnQA.cjs → tool-visibility-BdsE6vQB.cjs} +27 -4
- package/dist/{tool-visibility-CJV9HezW.mjs → tool-visibility-wW2vAaj9.mjs} +22 -6
- package/dist/tool-visibility-wW2vAaj9.mjs.map +1 -0
- package/dist/{tools-BRQAPF2R.mjs → tools-BnThuvE2.mjs} +3 -3
- package/dist/{tools-BRQAPF2R.mjs.map → tools-BnThuvE2.mjs.map} +1 -1
- package/dist/topup-server-BIbSfvX5.cjs +146 -0
- package/dist/{topup-server-YN3iHrHW.cjs → topup-server-Bh7MlzRt.cjs} +485 -239
- package/dist/{topup-server-BLdF1SFQ.mjs → topup-server-BrkPhqJG.mjs} +488 -242
- package/dist/topup-server-BrkPhqJG.mjs.map +1 -0
- package/dist/topup-server-DzeM_YAt.mjs +131 -0
- package/dist/topup-server-DzeM_YAt.mjs.map +1 -0
- package/dist/{transport-error-DmC9WLTW.cjs → transport-error-CenkuT7T.cjs} +5 -2
- package/dist/{transport-error-CSEb6sPr.mjs → transport-error-S0za4TCe.mjs} +6 -3
- package/dist/transport-error-S0za4TCe.mjs.map +1 -0
- package/dist/{update-MsoEFbhn.mjs → update-7TewxG_2.mjs} +2 -2
- package/dist/{update-MsoEFbhn.mjs.map → update-7TewxG_2.mjs.map} +1 -1
- package/dist/{update-RKd0UW90.cjs → update-Rn1RSqrb.cjs} +7 -7
- package/dist/{usage-status-CHiOPA-2.mjs → usage-status-CXOnrq-s.mjs} +2 -2
- package/dist/{usage-status-CHiOPA-2.mjs.map → usage-status-CXOnrq-s.mjs.map} +1 -1
- package/dist/{wallet-COcm4oIb.mjs → wallet-GNDl3FkR.mjs} +2 -2
- package/dist/{wallet-COcm4oIb.mjs.map → wallet-GNDl3FkR.mjs.map} +1 -1
- package/docs/graph-query-compatibility.md +33 -27
- package/docs/graph-tools.md +138 -39
- package/docs/mcp-proxy.md +39 -8
- package/docs/stability.md +2 -1
- package/package.json +5 -6
- package/skills/chain-insights-cypher/SKILL.md +249 -52
- package/skills/chain-insights-cypher/agents/openai.yaml +1 -1
- package/skills/chain-insights-schema-evm/SKILL.md +75 -47
- package/dist/capabilities-C8DQSfyW.mjs.map +0 -1
- package/dist/config-DbbPiGk0.mjs.map +0 -1
- package/dist/html-generator-BCDtYcGs.mjs +0 -16
- package/dist/html-generator-BCDtYcGs.mjs.map +0 -1
- package/dist/html-generator-DFwMRWN3.cjs +0 -16
- package/dist/public-tools-CDpFHbZ8.mjs.map +0 -1
- package/dist/schema-B0OuHW_l.mjs.map +0 -1
- package/dist/tool-visibility-CJV9HezW.mjs.map +0 -1
- package/dist/topup-server-BLdF1SFQ.mjs.map +0 -1
- package/dist/transport-error-CSEb6sPr.mjs.map +0 -1
- package/dist/version-BA3J8hu4.mjs +0 -8
- package/dist/version-BA3J8hu4.mjs.map +0 -1
- package/dist/version-CO9Or_YV.cjs +0 -17
package/README.md
CHANGED
|
@@ -39,7 +39,7 @@ cia mcp tools # list remote graph tools
|
|
|
39
39
|
Sixty seconds gets you the CLI, a network overview, a CIA workflow, and the
|
|
40
40
|
available remote graph tools for Robinhood.
|
|
41
41
|
To call the same tools from an agent, register the MCP proxy:
|
|
42
|
-
`cia setup claude-code` (or `codex` / `hermes`).
|
|
42
|
+
`cia setup claude-code` (or `claude-desktop` / `codex` / `hermes`).
|
|
43
43
|
|
|
44
44
|
CLI results are human-readable by default. Add `--json` when another tool or
|
|
45
45
|
script needs indented JSON:
|
|
@@ -55,6 +55,29 @@ cia workflow aml-address-risk --json \
|
|
|
55
55
|
The AML address-risk contract uses the latest version when `version` is
|
|
56
56
|
omitted. Pin the current contract with `--version v1` on the workflow command.
|
|
57
57
|
|
|
58
|
+
### Claude plugin
|
|
59
|
+
|
|
60
|
+
The `plugin/` folder is the Chain Insights plugin for Claude. It starts the
|
|
61
|
+
local Chain Insights MCP proxy on your computer over stdio
|
|
62
|
+
(`chain-insights-mcp-proxy` from the npm package, through `npx`), and brings the
|
|
63
|
+
`chain-insights-cypher` and `chain-insights-schema-evm` skills. The proxy
|
|
64
|
+
serves the money-flow, query-table and balance views itself, and reaches the
|
|
65
|
+
Chain Insights Graph for the data.
|
|
66
|
+
|
|
67
|
+
- **Runs in:** Claude Desktop, Cowork sessions on your computer, and Claude Code.
|
|
68
|
+
- **Cannot start it:** claude.ai on the web, the Claude mobile apps and Cowork
|
|
69
|
+
cloud sessions. They run no program on your computer.
|
|
70
|
+
|
|
71
|
+
The plugin needs Node.js 22 or newer. Add this repository as a plugin
|
|
72
|
+
marketplace, then install the `chain-insights` plugin from it.
|
|
73
|
+
|
|
74
|
+
Without the plugin, `npm install -g chain-insights` then
|
|
75
|
+
`cia setup claude-desktop` registers the installed proxy in Claude Desktop
|
|
76
|
+
directly. Restart Claude Desktop afterwards.
|
|
77
|
+
|
|
78
|
+
The plugin skills are copies of `skills/`. After editing a skill, run
|
|
79
|
+
`node scripts/sync-plugin-skills.mjs`; a test fails while the copies differ.
|
|
80
|
+
|
|
58
81
|
## Purpose And Ownership
|
|
59
82
|
|
|
60
83
|
One public npm package (`chain-insights`) providing the `cia` CLI and a
|
|
@@ -95,6 +118,7 @@ Never touches:
|
|
|
95
118
|
| `meta_usage_status` | Check the caller's daily free-tier graph query allowance |
|
|
96
119
|
| `meta_help` | Show Chain Insights tool and workflow guidance |
|
|
97
120
|
| `wallet_balance` | Show the local payment wallet amount |
|
|
121
|
+
| `wallet_topup` | Show the local payment wallet address and its QR code for a USDC top-up on Base |
|
|
98
122
|
|
|
99
123
|
## Dependencies
|
|
100
124
|
|
|
@@ -287,6 +311,12 @@ add `/mcp`.
|
|
|
287
311
|
cia config set graphMcpEndpoint https://mcp.chain-insights.ai/
|
|
288
312
|
```
|
|
289
313
|
|
|
314
|
+
To undo every local override at once, after an upgrade or a test setup:
|
|
315
|
+
|
|
316
|
+
```bash
|
|
317
|
+
cia config reset # production endpoint, paid mode, no test key; wallet kept; old file in config.json.bak
|
|
318
|
+
```
|
|
319
|
+
|
|
290
320
|
Optional one-shot override from the environment:
|
|
291
321
|
|
|
292
322
|
```bash
|
package/bin/install.cjs
CHANGED
|
@@ -22,12 +22,16 @@ const args = process.argv.slice(2)
|
|
|
22
22
|
const hasClaude = args.includes('--claude')
|
|
23
23
|
const hasCodex = args.includes('--codex')
|
|
24
24
|
const hasHermes = args.includes('--hermes')
|
|
25
|
+
const hasClaudeDesktop = args.includes('--claude-desktop')
|
|
25
26
|
const hasLocal = args.includes('--local')
|
|
26
27
|
|
|
27
|
-
if (!hasClaude && !hasCodex && !hasHermes && !hasLocal) {
|
|
28
|
+
if (!hasClaude && !hasCodex && !hasHermes && !hasClaudeDesktop && !hasLocal) {
|
|
28
29
|
console.log(`\n${bold}chain-insights installer${reset}`)
|
|
29
|
-
console.log(`\nUsage: node bin/install.cjs --claude | --codex | --hermes`)
|
|
30
|
+
console.log(`\nUsage: node bin/install.cjs --claude | --claude-desktop | --codex | --hermes`)
|
|
30
31
|
console.log(` ${cyan}--claude${reset} Install Claude Code skills globally to ~/.claude/skills/`)
|
|
32
|
+
console.log(
|
|
33
|
+
` ${cyan}--claude-desktop${reset} Register MCP in Claude Desktop (draws the money-flow views)`
|
|
34
|
+
)
|
|
31
35
|
console.log(
|
|
32
36
|
` ${cyan}--codex${reset} Install Codex skills globally to ~/.codex/skills/ and register MCP`
|
|
33
37
|
)
|
|
@@ -273,6 +277,59 @@ if (hasHermes) {
|
|
|
273
277
|
console.log(` ${cyan}Hermes MCP:${reset} registered in ${hermesConfig}`)
|
|
274
278
|
}
|
|
275
279
|
|
|
280
|
+
// Claude Desktop reads one JSON file per user. It is not a terminal program, so
|
|
281
|
+
// it does not see the PATH of a shell; the proxy is started with this Node's
|
|
282
|
+
// absolute path. Skills reach Claude Desktop through the plugin, not this file.
|
|
283
|
+
function claudeDesktopConfigPath() {
|
|
284
|
+
if (process.platform === 'darwin') {
|
|
285
|
+
return path.join(homeDir, 'Library', 'Application Support', 'Claude', 'claude_desktop_config.json')
|
|
286
|
+
}
|
|
287
|
+
if (process.platform === 'win32') {
|
|
288
|
+
const appData = process.env['APPDATA'] || path.join(homeDir, 'AppData', 'Roaming')
|
|
289
|
+
return path.join(appData, 'Claude', 'claude_desktop_config.json')
|
|
290
|
+
}
|
|
291
|
+
const configHome = process.env['XDG_CONFIG_HOME'] || path.join(homeDir, '.config')
|
|
292
|
+
return path.join(configHome, 'Claude', 'claude_desktop_config.json')
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
function installClaudeDesktopMcp(configFile, proxyPath) {
|
|
296
|
+
fs.mkdirSync(path.dirname(configFile), { recursive: true })
|
|
297
|
+
let config = {}
|
|
298
|
+
if (fs.existsSync(configFile)) {
|
|
299
|
+
const text = fs.readFileSync(configFile, 'utf8')
|
|
300
|
+
if (text.trim() !== '') {
|
|
301
|
+
try {
|
|
302
|
+
config = JSON.parse(text)
|
|
303
|
+
} catch {
|
|
304
|
+
throw new Error(`${configFile} is not valid JSON; fix it, then run the setup again`)
|
|
305
|
+
}
|
|
306
|
+
if (config === null || typeof config !== 'object' || Array.isArray(config)) {
|
|
307
|
+
throw new Error(`${configFile} does not hold a JSON object; fix it, then run the setup again`)
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
fs.copyFileSync(configFile, `${configFile}.bak`)
|
|
311
|
+
}
|
|
312
|
+
const servers =
|
|
313
|
+
config.mcpServers && typeof config.mcpServers === 'object' && !Array.isArray(config.mcpServers)
|
|
314
|
+
? config.mcpServers
|
|
315
|
+
: {}
|
|
316
|
+
servers['chain-insights'] = { command: process.execPath, args: [proxyPath] }
|
|
317
|
+
config.mcpServers = servers
|
|
318
|
+
fs.writeFileSync(configFile, `${JSON.stringify(config, null, 2)}\n`, 'utf8')
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
if (hasClaudeDesktop) {
|
|
322
|
+
const desktopConfig = claudeDesktopConfigPath()
|
|
323
|
+
try {
|
|
324
|
+
installClaudeDesktopMcp(desktopConfig, proxyBinPath)
|
|
325
|
+
console.log(` ${cyan}Claude Desktop MCP:${reset} registered in ${desktopConfig}`)
|
|
326
|
+
console.log(` ${dim}Restart Claude Desktop to load it.${reset}`)
|
|
327
|
+
} catch (err) {
|
|
328
|
+
console.error(` Claude Desktop MCP: ${err.message}`)
|
|
329
|
+
process.exit(1)
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
|
|
276
333
|
// ─── 5. Print installation summary ────────────────────────────────────────
|
|
277
334
|
|
|
278
335
|
console.log(`\n${bold}${green}Chain Insights installed${reset}`)
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { t as __exportAll } from "./rolldown-runtime-
|
|
1
|
+
import { t as __exportAll } from "./rolldown-runtime-8H4AJuhK.mjs";
|
|
2
2
|
import path from "node:path";
|
|
3
3
|
import { appendFile, mkdir } from "node:fs/promises";
|
|
4
4
|
//#region src/mcp/action-log.ts
|
|
@@ -90,4 +90,4 @@ function installActionLogging(client) {
|
|
|
90
90
|
//#endregion
|
|
91
91
|
export { action_log_exports as n, appendActionLog as r, actionLogSignalsFromResult as t };
|
|
92
92
|
|
|
93
|
-
//# sourceMappingURL=action-log-
|
|
93
|
+
//# sourceMappingURL=action-log-D49Par9P.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"action-log-
|
|
1
|
+
{"version":3,"file":"action-log-D49Par9P.mjs","names":[],"sources":["../src/mcp/action-log.ts"],"sourcesContent":["// src/mcp/action-log.ts\n// Optional append-only record of every MCP tool invocation, for operators\n// running cia unattended who need to audit what ran and why a result looked\n// the way it did. Off unless CIA_ACTION_LOG names a path.\n//\n// `warnings` and `search_limits` are captured deliberately: they are how a\n// reader tells \"found nothing\" from \"hit a cap\", which is invisible in the\n// result alone.\nimport { appendFile, mkdir } from 'node:fs/promises'\nimport path from 'node:path'\n\nexport interface ActionLogEntry {\n timestamp: number\n tool: string\n args: Record<string, unknown>\n outcome: 'ok' | 'error'\n duration_ms: number\n result_counts?: Record<string, number>\n warnings?: string[]\n search_limits?: Record<string, unknown>\n error?: string\n}\n\nexport function actionLogPath(): string | undefined {\n const configured = process.env.CIA_ACTION_LOG?.trim()\n return configured ? configured : undefined\n}\n\n// Some special filesystems (notably /proc) answer mkdir on a child with\n// ENOENT even though the parent visibly exists. Node's fs.mkdir(dir,\n// {recursive: true}) treats that as a transient race and retries with no\n// cap, which spins forever rather than rejecting — confirmed via strace\n// (an unbounded, rapid mkdir/statx loop; the event loop stays live and the\n// process never blocks, it just never stops). Walking the path ourselves,\n// one plain mkdir per component with no retry, makes every case settle in\n// a bounded number of syscalls: EEXIST is expected and skipped, anything\n// else (including that ENOENT-on-existing-parent case) fails once instead\n// of retrying.\nasync function ensureDir(dir: string): Promise<void> {\n const segments = dir.split(path.sep).filter(Boolean)\n let current = path.isAbsolute(dir) ? path.sep : ''\n for (const segment of segments) {\n current = current ? path.join(current, segment) : segment\n try {\n await mkdir(current)\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code === 'EEXIST') continue\n throw err\n }\n }\n}\n\n// A residual, undemonstrated risk remains distinct from the mkdir retry loop\n// above: a single mkdir/appendFile syscall genuinely wedged on a stalled\n// filesystem (e.g. a hung network mount) blocks like any normal blocking I/O\n// would. Node's fs promises do not support cancelling an in-flight mkdir, so\n// a bounded wait here only frees the *caller* — the wedged operation itself\n// keeps running in the background until the OS/filesystem gives up on its\n// own. That is an accepted, documented limitation, not a bug this module can\n// fix from userland; it is unrelated to (and much rarer than) the retry-loop\n// case ensureDir() eliminates above.\nconst WRITE_TIMEOUT_MS = 2000\n\nasync function writeEntry(file: string, entry: ActionLogEntry): Promise<void> {\n await ensureDir(path.dirname(file))\n await appendFile(file, JSON.stringify(entry) + '\\n', 'utf8')\n}\n\n// Never throws, and never hangs beyond WRITE_TIMEOUT_MS. A failure (or a\n// stall) recording an action must not fail (or stall) the action:\n// observability that can break the thing it observes is worse than none.\nexport async function appendActionLog(entry: ActionLogEntry): Promise<void> {\n const file = actionLogPath()\n if (!file) return\n try {\n await Promise.race([\n writeEntry(file, entry),\n new Promise<void>((resolve) => {\n const timer = setTimeout(resolve, WRITE_TIMEOUT_MS)\n timer.unref?.()\n }),\n ])\n } catch {\n // Intentionally swallowed.\n }\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value)\n}\n\n// Exported so BOTH client paths log identically: the MCP proxy's remote client\n// and the CLI's own client. They are separate clients, and wiring only one is how\n// an unattended instance ends up with an empty log while the mechanism 'works'.\nexport function actionLogSignalsFromResult(result: unknown): {\n warnings?: string[]\n search_limits?: Record<string, unknown>\n} {\n const structuredContent = isRecord(result) ? result['structuredContent'] : undefined\n if (!isRecord(structuredContent)) return {}\n const warnings = Array.isArray(structuredContent['warnings'])\n ? (structuredContent['warnings'] as string[])\n : undefined\n const input = structuredContent['input']\n const search_limits =\n isRecord(input) && isRecord(input['search_limits'])\n ? (input['search_limits'] as Record<string, unknown>)\n : undefined\n return { warnings, search_limits }\n}\n\ntype CallToolFn = (...args: never[]) => Promise<unknown>\n\n// Wrap a client's callTool so every invocation is recorded. Returns the client.\n// Idempotent-unsafe: call once per client.\nexport function installActionLogging<T extends { callTool: CallToolFn }>(client: T): T {\n const original = client.callTool.bind(client) as CallToolFn\n const wrapped = (async (...args: never[]) => {\n const startedAt = Date.now()\n const input = (args[0] ?? {}) as { name?: unknown; arguments?: Record<string, unknown> }\n const tool = String(input.name ?? 'unknown')\n const toolArgs = input.arguments ?? {}\n try {\n const result = await original(...args)\n const { warnings, search_limits } = actionLogSignalsFromResult(result)\n await appendActionLog({\n timestamp: startedAt,\n tool,\n args: toolArgs,\n outcome: 'ok',\n duration_ms: Date.now() - startedAt,\n warnings,\n search_limits,\n })\n return result\n } catch (err) {\n await appendActionLog({\n timestamp: startedAt,\n tool,\n args: toolArgs,\n outcome: 'error',\n duration_ms: Date.now() - startedAt,\n error: (err as Error).message,\n })\n throw err\n }\n }) as CallToolFn\n client.callTool = wrapped as T['callTool']\n return client\n}\n"],"mappings":";;;;;;;;;;AAuBA,SAAgB,gBAAoC;CAClD,MAAM,aAAa,QAAQ,IAAI,gBAAgB,KAAK;CACpD,OAAO,aAAa,aAAa,KAAA;AACnC;AAYA,eAAe,UAAU,KAA4B;CACnD,MAAM,WAAW,IAAI,MAAM,KAAK,GAAG,CAAC,CAAC,OAAO,OAAO;CACnD,IAAI,UAAU,KAAK,WAAW,GAAG,IAAI,KAAK,MAAM;CAChD,KAAK,MAAM,WAAW,UAAU;EAC9B,UAAU,UAAU,KAAK,KAAK,SAAS,OAAO,IAAI;EAClD,IAAI;GACF,MAAM,MAAM,OAAO;EACrB,SAAS,KAAK;GACZ,IAAK,IAA8B,SAAS,UAAU;GACtD,MAAM;EACR;CACF;AACF;AAWA,MAAM,mBAAmB;AAEzB,eAAe,WAAW,MAAc,OAAsC;CAC5E,MAAM,UAAU,KAAK,QAAQ,IAAI,CAAC;CAClC,MAAM,WAAW,MAAM,KAAK,UAAU,KAAK,IAAI,MAAM,MAAM;AAC7D;AAKA,eAAsB,gBAAgB,OAAsC;CAC1E,MAAM,OAAO,cAAc;CAC3B,IAAI,CAAC,MAAM;CACX,IAAI;EACF,MAAM,QAAQ,KAAK,CACjB,WAAW,MAAM,KAAK,GACtB,IAAI,SAAe,YAAY;GAE7B,WADyB,SAAS,gBAC9B,CAAC,CAAC,QAAQ;EAChB,CAAC,CACH,CAAC;CACH,QAAQ,CAER;AACF;AAEA,SAAS,SAAS,OAAkD;CAClE,OAAO,OAAO,UAAU,YAAY,UAAU,QAAQ,CAAC,MAAM,QAAQ,KAAK;AAC5E;AAKA,SAAgB,2BAA2B,QAGzC;CACA,MAAM,oBAAoB,SAAS,MAAM,IAAI,OAAO,uBAAuB,KAAA;CAC3E,IAAI,CAAC,SAAS,iBAAiB,GAAG,OAAO,CAAC;CAC1C,MAAM,WAAW,MAAM,QAAQ,kBAAkB,WAAW,IACvD,kBAAkB,cACnB,KAAA;CACJ,MAAM,QAAQ,kBAAkB;CAKhC,OAAO;EAAE;EAAU,eAHjB,SAAS,KAAK,KAAK,SAAS,MAAM,gBAAgB,IAC7C,MAAM,mBACP,KAAA;CAC2B;AACnC;AAMA,SAAgB,qBAAyD,QAAc;CACrF,MAAM,WAAW,OAAO,SAAS,KAAK,MAAM;CAC5C,MAAM,WAAW,OAAO,GAAG,SAAkB;EAC3C,MAAM,YAAY,KAAK,IAAI;EAC3B,MAAM,QAAS,KAAK,MAAM,CAAC;EAC3B,MAAM,OAAO,OAAO,MAAM,QAAQ,SAAS;EAC3C,MAAM,WAAW,MAAM,aAAa,CAAC;EACrC,IAAI;GACF,MAAM,SAAS,MAAM,SAAS,GAAG,IAAI;GACrC,MAAM,EAAE,UAAU,kBAAkB,2BAA2B,MAAM;GACrE,MAAM,gBAAgB;IACpB,WAAW;IACX;IACA,MAAM;IACN,SAAS;IACT,aAAa,KAAK,IAAI,IAAI;IAC1B;IACA;GACF,CAAC;GACD,OAAO;EACT,SAAS,KAAK;GACZ,MAAM,gBAAgB;IACpB,WAAW;IACX;IACA,MAAM;IACN,SAAS;IACT,aAAa,KAAK,IAAI,IAAI;IAC1B,OAAQ,IAAc;GACxB,CAAC;GACD,MAAM;EACR;CACF;CACA,OAAO,WAAW;CAClB,OAAO;AACT"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { t as __exportAll } from "./rolldown-runtime-
|
|
1
|
+
import { t as __exportAll } from "./rolldown-runtime-8H4AJuhK.mjs";
|
|
2
2
|
import path from "node:path";
|
|
3
3
|
import fs from "node:fs";
|
|
4
4
|
import os from "node:os";
|
|
@@ -45,4 +45,4 @@ function activeDataDir(fallbackDataDir) {
|
|
|
45
45
|
//#endregion
|
|
46
46
|
export { findActiveWorkspace as n, active_exports as t };
|
|
47
47
|
|
|
48
|
-
//# sourceMappingURL=active-
|
|
48
|
+
//# sourceMappingURL=active-Dkf8AB1R.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"active-
|
|
1
|
+
{"version":3,"file":"active-Dkf8AB1R.mjs","names":[],"sources":["../src/workspace/active.ts"],"sourcesContent":["import fs from 'node:fs'\nimport os from 'node:os'\nimport path from 'node:path'\n\ninterface WorkspaceConfig {\n schema?: string\n workspace_root?: string\n artifacts_dir?: string\n domain_hints?: unknown\n}\n\nexport interface ActiveWorkspace {\n root: string\n metadataDir: string\n artifactsRoot: string\n domainHints: string[]\n}\n\nfunction workspaceFromRoot(rootCandidate: string): ActiveWorkspace | null {\n const root = path.resolve(rootCandidate)\n const metadataDir = path.join(root, '.chain-insights')\n const markerPath = path.join(metadataDir, 'workspace.json')\n if (!fs.existsSync(markerPath)) return null\n\n const parsed = JSON.parse(fs.readFileSync(markerPath, 'utf8')) as WorkspaceConfig\n if (parsed.schema !== 'chain-insights.workspace.v1') return null\n\n const workspaceRoot = path.resolve(parsed.workspace_root ?? root)\n const artifactsDir = parsed.artifacts_dir ?? 'artifacts'\n const domainHints = Array.isArray(parsed.domain_hints)\n ? parsed.domain_hints.filter(\n (value): value is string => typeof value === 'string' && value.trim().length > 0\n )\n : []\n return {\n root: workspaceRoot,\n metadataDir: path.join(workspaceRoot, '.chain-insights'),\n artifactsRoot: path.resolve(workspaceRoot, artifactsDir),\n domainHints,\n }\n}\n\nexport function findActiveWorkspace(startDir = process.cwd()): ActiveWorkspace | null {\n const envWorkspace = process.env['CHAIN_INSIGHTS_WORKSPACE']?.trim()\n if (envWorkspace) {\n const active = workspaceFromRoot(envWorkspace)\n if (active) return active\n }\n\n let current = path.resolve(startDir)\n while (true) {\n const active = workspaceFromRoot(current)\n if (active) return active\n\n const parent = path.dirname(current)\n if (parent === current) return null\n current = parent\n }\n}\n\nexport function activeMetadataDir(): string {\n return findActiveWorkspace()?.metadataDir ?? path.join(os.homedir(), '.chain-insights')\n}\n\nexport function activeArtifactsRoot(): string {\n return (\n findActiveWorkspace()?.artifactsRoot ?? path.join(os.homedir(), '.chain-insights', 'artifacts')\n )\n}\n\nexport function activeDataDir(fallbackDataDir?: string): string {\n return (\n findActiveWorkspace()?.root ?? fallbackDataDir ?? path.join(os.homedir(), '.chain-insights')\n )\n}\n"],"mappings":";;;;;;;;;AAkBA,SAAS,kBAAkB,eAA+C;CACxE,MAAM,OAAO,KAAK,QAAQ,aAAa;CACvC,MAAM,cAAc,KAAK,KAAK,MAAM,iBAAiB;CACrD,MAAM,aAAa,KAAK,KAAK,aAAa,gBAAgB;CAC1D,IAAI,CAAC,GAAG,WAAW,UAAU,GAAG,OAAO;CAEvC,MAAM,SAAS,KAAK,MAAM,GAAG,aAAa,YAAY,MAAM,CAAC;CAC7D,IAAI,OAAO,WAAW,+BAA+B,OAAO;CAE5D,MAAM,gBAAgB,KAAK,QAAQ,OAAO,kBAAkB,IAAI;CAChE,MAAM,eAAe,OAAO,iBAAiB;CAC7C,MAAM,cAAc,MAAM,QAAQ,OAAO,YAAY,IACjD,OAAO,aAAa,QACjB,UAA2B,OAAO,UAAU,YAAY,MAAM,KAAK,CAAC,CAAC,SAAS,CACjF,IACA,CAAC;CACL,OAAO;EACL,MAAM;EACN,aAAa,KAAK,KAAK,eAAe,iBAAiB;EACvD,eAAe,KAAK,QAAQ,eAAe,YAAY;EACvD;CACF;AACF;AAEA,SAAgB,oBAAoB,WAAW,QAAQ,IAAI,GAA2B;CACpF,MAAM,eAAe,QAAQ,IAAI,2BAA2B,EAAE,KAAK;CACnE,IAAI,cAAc;EAChB,MAAM,SAAS,kBAAkB,YAAY;EAC7C,IAAI,QAAQ,OAAO;CACrB;CAEA,IAAI,UAAU,KAAK,QAAQ,QAAQ;CACnC,OAAO,MAAM;EACX,MAAM,SAAS,kBAAkB,OAAO;EACxC,IAAI,QAAQ,OAAO;EAEnB,MAAM,SAAS,KAAK,QAAQ,OAAO;EACnC,IAAI,WAAW,SAAS,OAAO;EAC/B,UAAU;CACZ;AACF;AAYA,SAAgB,cAAc,iBAAkC;CAC9D,OACE,oBAAoB,CAAC,EAAE,QAAQ,mBAAmB,KAAK,KAAK,GAAG,QAAQ,GAAG,iBAAiB;AAE/F"}
|