nodedex 0.1.0
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/adapters/claude-code-watcher.mjs +336 -0
- package/adapters/hermes-statedb-watcher.mjs +234 -0
- package/adapters/nodedex-capture-core.mjs +129 -0
- package/adapters/nodedex-capture.mjs +169 -0
- package/dist/agent-protocol.d.ts +7 -0
- package/dist/agent-protocol.d.ts.map +1 -0
- package/dist/agent-protocol.js +38 -0
- package/dist/agent-protocol.js.map +1 -0
- package/dist/api-server.d.ts +5 -0
- package/dist/api-server.d.ts.map +1 -0
- package/dist/api-server.js +351 -0
- package/dist/api-server.js.map +1 -0
- package/dist/boot-env.d.ts +2 -0
- package/dist/boot-env.d.ts.map +1 -0
- package/dist/boot-env.js +12 -0
- package/dist/boot-env.js.map +1 -0
- package/dist/engine/__tests__/search-core.test.d.ts +2 -0
- package/dist/engine/__tests__/search-core.test.d.ts.map +1 -0
- package/dist/engine/__tests__/search-core.test.js +139 -0
- package/dist/engine/__tests__/search-core.test.js.map +1 -0
- package/dist/engine/ai-provider.d.ts +45 -0
- package/dist/engine/ai-provider.d.ts.map +1 -0
- package/dist/engine/ai-provider.js +5 -0
- package/dist/engine/ai-provider.js.map +1 -0
- package/dist/engine/embeddings.d.ts +51 -0
- package/dist/engine/embeddings.d.ts.map +1 -0
- package/dist/engine/embeddings.js +89 -0
- package/dist/engine/embeddings.js.map +1 -0
- package/dist/engine/providers/__tests__/failure-policy.test.d.ts +2 -0
- package/dist/engine/providers/__tests__/failure-policy.test.d.ts.map +1 -0
- package/dist/engine/providers/__tests__/failure-policy.test.js +134 -0
- package/dist/engine/providers/__tests__/failure-policy.test.js.map +1 -0
- package/dist/engine/providers/__tests__/model-caps.test.d.ts +2 -0
- package/dist/engine/providers/__tests__/model-caps.test.d.ts.map +1 -0
- package/dist/engine/providers/__tests__/model-caps.test.js +38 -0
- package/dist/engine/providers/__tests__/model-caps.test.js.map +1 -0
- package/dist/engine/providers/__tests__/openai-structured.test.d.ts +2 -0
- package/dist/engine/providers/__tests__/openai-structured.test.d.ts.map +1 -0
- package/dist/engine/providers/__tests__/openai-structured.test.js +73 -0
- package/dist/engine/providers/__tests__/openai-structured.test.js.map +1 -0
- package/dist/engine/providers/__tests__/usage-ledger.test.d.ts +2 -0
- package/dist/engine/providers/__tests__/usage-ledger.test.d.ts.map +1 -0
- package/dist/engine/providers/__tests__/usage-ledger.test.js +108 -0
- package/dist/engine/providers/__tests__/usage-ledger.test.js.map +1 -0
- package/dist/engine/providers/anthropic.d.ts +17 -0
- package/dist/engine/providers/anthropic.d.ts.map +1 -0
- package/dist/engine/providers/anthropic.js +125 -0
- package/dist/engine/providers/anthropic.js.map +1 -0
- package/dist/engine/providers/failure-policy.d.ts +56 -0
- package/dist/engine/providers/failure-policy.d.ts.map +1 -0
- package/dist/engine/providers/failure-policy.js +120 -0
- package/dist/engine/providers/failure-policy.js.map +1 -0
- package/dist/engine/providers/gemini.d.ts +22 -0
- package/dist/engine/providers/gemini.d.ts.map +1 -0
- package/dist/engine/providers/gemini.js +180 -0
- package/dist/engine/providers/gemini.js.map +1 -0
- package/dist/engine/providers/index.d.ts +8 -0
- package/dist/engine/providers/index.d.ts.map +1 -0
- package/dist/engine/providers/index.js +67 -0
- package/dist/engine/providers/index.js.map +1 -0
- package/dist/engine/providers/local.d.ts +12 -0
- package/dist/engine/providers/local.d.ts.map +1 -0
- package/dist/engine/providers/local.js +46 -0
- package/dist/engine/providers/local.js.map +1 -0
- package/dist/engine/providers/model-caps.d.ts +6 -0
- package/dist/engine/providers/model-caps.d.ts.map +1 -0
- package/dist/engine/providers/model-caps.js +49 -0
- package/dist/engine/providers/model-caps.js.map +1 -0
- package/dist/engine/providers/openai.d.ts +30 -0
- package/dist/engine/providers/openai.d.ts.map +1 -0
- package/dist/engine/providers/openai.js +309 -0
- package/dist/engine/providers/openai.js.map +1 -0
- package/dist/engine/providers/usage-ledger.d.ts +69 -0
- package/dist/engine/providers/usage-ledger.d.ts.map +1 -0
- package/dist/engine/providers/usage-ledger.js +209 -0
- package/dist/engine/providers/usage-ledger.js.map +1 -0
- package/dist/engine/search-core.d.ts +40 -0
- package/dist/engine/search-core.d.ts.map +1 -0
- package/dist/engine/search-core.js +109 -0
- package/dist/engine/search-core.js.map +1 -0
- package/dist/engine/vector-math.d.ts +5 -0
- package/dist/engine/vector-math.d.ts.map +1 -0
- package/dist/engine/vector-math.js +25 -0
- package/dist/engine/vector-math.js.map +1 -0
- package/dist/home-env.d.ts +26 -0
- package/dist/home-env.d.ts.map +1 -0
- package/dist/home-env.js +87 -0
- package/dist/home-env.js.map +1 -0
- package/dist/mcp-server.d.ts +13 -0
- package/dist/mcp-server.d.ts.map +1 -0
- package/dist/mcp-server.js +79 -0
- package/dist/mcp-server.js.map +1 -0
- package/dist/middleware/auth.d.ts +23 -0
- package/dist/middleware/auth.d.ts.map +1 -0
- package/dist/middleware/auth.js +104 -0
- package/dist/middleware/auth.js.map +1 -0
- package/dist/middleware/auto-recall.d.ts +7 -0
- package/dist/middleware/auto-recall.d.ts.map +1 -0
- package/dist/middleware/auto-recall.js +257 -0
- package/dist/middleware/auto-recall.js.map +1 -0
- package/dist/middleware/auto-reflect.d.ts +4 -0
- package/dist/middleware/auto-reflect.d.ts.map +1 -0
- package/dist/middleware/auto-reflect.js +5 -0
- package/dist/middleware/auto-reflect.js.map +1 -0
- package/dist/middleware/reflect/apply-flag-verdict.d.ts +27 -0
- package/dist/middleware/reflect/apply-flag-verdict.d.ts.map +1 -0
- package/dist/middleware/reflect/apply-flag-verdict.js +57 -0
- package/dist/middleware/reflect/apply-flag-verdict.js.map +1 -0
- package/dist/middleware/reflect/arc-entity-resolve.d.ts +29 -0
- package/dist/middleware/reflect/arc-entity-resolve.d.ts.map +1 -0
- package/dist/middleware/reflect/arc-entity-resolve.js +356 -0
- package/dist/middleware/reflect/arc-entity-resolve.js.map +1 -0
- package/dist/middleware/reflect/arc-inactivity-timer.d.ts +47 -0
- package/dist/middleware/reflect/arc-inactivity-timer.d.ts.map +1 -0
- package/dist/middleware/reflect/arc-inactivity-timer.js +175 -0
- package/dist/middleware/reflect/arc-inactivity-timer.js.map +1 -0
- package/dist/middleware/reflect/arc-pipeline.d.ts +33 -0
- package/dist/middleware/reflect/arc-pipeline.d.ts.map +1 -0
- package/dist/middleware/reflect/arc-pipeline.js +498 -0
- package/dist/middleware/reflect/arc-pipeline.js.map +1 -0
- package/dist/middleware/reflect/comprehend-pergroup.d.ts +100 -0
- package/dist/middleware/reflect/comprehend-pergroup.d.ts.map +1 -0
- package/dist/middleware/reflect/comprehend-pergroup.js +610 -0
- package/dist/middleware/reflect/comprehend-pergroup.js.map +1 -0
- package/dist/middleware/reflect/comprehend.d.ts +237 -0
- package/dist/middleware/reflect/comprehend.d.ts.map +1 -0
- package/dist/middleware/reflect/comprehend.js +706 -0
- package/dist/middleware/reflect/comprehend.js.map +1 -0
- package/dist/middleware/reflect/config.d.ts +34 -0
- package/dist/middleware/reflect/config.d.ts.map +1 -0
- package/dist/middleware/reflect/config.js +131 -0
- package/dist/middleware/reflect/config.js.map +1 -0
- package/dist/middleware/reflect/context.d.ts +138 -0
- package/dist/middleware/reflect/context.d.ts.map +1 -0
- package/dist/middleware/reflect/context.js +619 -0
- package/dist/middleware/reflect/context.js.map +1 -0
- package/dist/middleware/reflect/cost-breakdown.d.ts +69 -0
- package/dist/middleware/reflect/cost-breakdown.d.ts.map +1 -0
- package/dist/middleware/reflect/cost-breakdown.js +63 -0
- package/dist/middleware/reflect/cost-breakdown.js.map +1 -0
- package/dist/middleware/reflect/cost-guard.d.ts +102 -0
- package/dist/middleware/reflect/cost-guard.d.ts.map +1 -0
- package/dist/middleware/reflect/cost-guard.js +243 -0
- package/dist/middleware/reflect/cost-guard.js.map +1 -0
- package/dist/middleware/reflect/cost-pricing.d.ts +54 -0
- package/dist/middleware/reflect/cost-pricing.d.ts.map +1 -0
- package/dist/middleware/reflect/cost-pricing.js +148 -0
- package/dist/middleware/reflect/cost-pricing.js.map +1 -0
- package/dist/middleware/reflect/cross-group-link.d.ts +61 -0
- package/dist/middleware/reflect/cross-group-link.d.ts.map +1 -0
- package/dist/middleware/reflect/cross-group-link.js +212 -0
- package/dist/middleware/reflect/cross-group-link.js.map +1 -0
- package/dist/middleware/reflect/dedup-by-source-and-value.d.ts +70 -0
- package/dist/middleware/reflect/dedup-by-source-and-value.d.ts.map +1 -0
- package/dist/middleware/reflect/dedup-by-source-and-value.js +0 -0
- package/dist/middleware/reflect/dedup-by-source-and-value.js.map +1 -0
- package/dist/middleware/reflect/describe-roots.d.ts +58 -0
- package/dist/middleware/reflect/describe-roots.d.ts.map +1 -0
- package/dist/middleware/reflect/describe-roots.js +266 -0
- package/dist/middleware/reflect/describe-roots.js.map +1 -0
- package/dist/middleware/reflect/flag-reviewer-startup.d.ts +16 -0
- package/dist/middleware/reflect/flag-reviewer-startup.d.ts.map +1 -0
- package/dist/middleware/reflect/flag-reviewer-startup.js +107 -0
- package/dist/middleware/reflect/flag-reviewer-startup.js.map +1 -0
- package/dist/middleware/reflect/flag-reviewer.d.ts +69 -0
- package/dist/middleware/reflect/flag-reviewer.d.ts.map +1 -0
- package/dist/middleware/reflect/flag-reviewer.js +520 -0
- package/dist/middleware/reflect/flag-reviewer.js.map +1 -0
- package/dist/middleware/reflect/inline-dedup.d.ts +26 -0
- package/dist/middleware/reflect/inline-dedup.d.ts.map +1 -0
- package/dist/middleware/reflect/inline-dedup.js +131 -0
- package/dist/middleware/reflect/inline-dedup.js.map +1 -0
- package/dist/middleware/reflect/justify-decisions.d.ts +37 -0
- package/dist/middleware/reflect/justify-decisions.d.ts.map +1 -0
- package/dist/middleware/reflect/justify-decisions.js +159 -0
- package/dist/middleware/reflect/justify-decisions.js.map +1 -0
- package/dist/middleware/reflect/nl-accept.d.ts +35 -0
- package/dist/middleware/reflect/nl-accept.d.ts.map +1 -0
- package/dist/middleware/reflect/nl-accept.js +167 -0
- package/dist/middleware/reflect/nl-accept.js.map +1 -0
- package/dist/middleware/reflect/pass0.d.ts +20 -0
- package/dist/middleware/reflect/pass0.d.ts.map +1 -0
- package/dist/middleware/reflect/pass0.js +423 -0
- package/dist/middleware/reflect/pass0.js.map +1 -0
- package/dist/middleware/reflect/pass1.d.ts +17 -0
- package/dist/middleware/reflect/pass1.d.ts.map +1 -0
- package/dist/middleware/reflect/pass1.js +241 -0
- package/dist/middleware/reflect/pass1.js.map +1 -0
- package/dist/middleware/reflect/pass2-quarantine.d.ts +129 -0
- package/dist/middleware/reflect/pass2-quarantine.d.ts.map +1 -0
- package/dist/middleware/reflect/pass2-quarantine.js +272 -0
- package/dist/middleware/reflect/pass2-quarantine.js.map +1 -0
- package/dist/middleware/reflect/pass2-seams.d.ts +205 -0
- package/dist/middleware/reflect/pass2-seams.d.ts.map +1 -0
- package/dist/middleware/reflect/pass2-seams.js +279 -0
- package/dist/middleware/reflect/pass2-seams.js.map +1 -0
- package/dist/middleware/reflect/pass2-split-orchestrator.d.ts +37 -0
- package/dist/middleware/reflect/pass2-split-orchestrator.d.ts.map +1 -0
- package/dist/middleware/reflect/pass2-split-orchestrator.js +531 -0
- package/dist/middleware/reflect/pass2-split-orchestrator.js.map +1 -0
- package/dist/middleware/reflect/pass2.d.ts +17 -0
- package/dist/middleware/reflect/pass2.d.ts.map +1 -0
- package/dist/middleware/reflect/pass2.js +324 -0
- package/dist/middleware/reflect/pass2.js.map +1 -0
- package/dist/middleware/reflect/pass2a.d.ts +141 -0
- package/dist/middleware/reflect/pass2a.d.ts.map +1 -0
- package/dist/middleware/reflect/pass2a.js +404 -0
- package/dist/middleware/reflect/pass2a.js.map +1 -0
- package/dist/middleware/reflect/pass2b.d.ts +108 -0
- package/dist/middleware/reflect/pass2b.d.ts.map +1 -0
- package/dist/middleware/reflect/pass2b.js +480 -0
- package/dist/middleware/reflect/pass2b.js.map +1 -0
- package/dist/middleware/reflect/pass2c.d.ts +113 -0
- package/dist/middleware/reflect/pass2c.d.ts.map +1 -0
- package/dist/middleware/reflect/pass2c.js +360 -0
- package/dist/middleware/reflect/pass2c.js.map +1 -0
- package/dist/middleware/reflect/pass3-batch.d.ts +62 -0
- package/dist/middleware/reflect/pass3-batch.d.ts.map +1 -0
- package/dist/middleware/reflect/pass3-batch.js +139 -0
- package/dist/middleware/reflect/pass3-batch.js.map +1 -0
- package/dist/middleware/reflect/pass3.d.ts +23 -0
- package/dist/middleware/reflect/pass3.d.ts.map +1 -0
- package/dist/middleware/reflect/pass3.js +371 -0
- package/dist/middleware/reflect/pass3.js.map +1 -0
- package/dist/middleware/reflect/pass4-slice.d.ts +25 -0
- package/dist/middleware/reflect/pass4-slice.d.ts.map +1 -0
- package/dist/middleware/reflect/pass4-slice.js +315 -0
- package/dist/middleware/reflect/pass4-slice.js.map +1 -0
- package/dist/middleware/reflect/pass4.d.ts +30 -0
- package/dist/middleware/reflect/pass4.d.ts.map +1 -0
- package/dist/middleware/reflect/pass4.js +193 -0
- package/dist/middleware/reflect/pass4.js.map +1 -0
- package/dist/middleware/reflect/pass5.d.ts +22 -0
- package/dist/middleware/reflect/pass5.d.ts.map +1 -0
- package/dist/middleware/reflect/pass5.js +178 -0
- package/dist/middleware/reflect/pass5.js.map +1 -0
- package/dist/middleware/reflect/pass_judge.d.ts +44 -0
- package/dist/middleware/reflect/pass_judge.d.ts.map +1 -0
- package/dist/middleware/reflect/pass_judge.js +263 -0
- package/dist/middleware/reflect/pass_judge.js.map +1 -0
- package/dist/middleware/reflect/pipeline-flags.d.ts +140 -0
- package/dist/middleware/reflect/pipeline-flags.d.ts.map +1 -0
- package/dist/middleware/reflect/pipeline-flags.js +314 -0
- package/dist/middleware/reflect/pipeline-flags.js.map +1 -0
- package/dist/middleware/reflect/pipeline.d.ts +237 -0
- package/dist/middleware/reflect/pipeline.d.ts.map +1 -0
- package/dist/middleware/reflect/pipeline.js +3114 -0
- package/dist/middleware/reflect/pipeline.js.map +1 -0
- package/dist/middleware/reflect/promptOverride.d.ts +14 -0
- package/dist/middleware/reflect/promptOverride.d.ts.map +1 -0
- package/dist/middleware/reflect/promptOverride.js +28 -0
- package/dist/middleware/reflect/promptOverride.js.map +1 -0
- package/dist/middleware/reflect/provenance-check.d.ts +48 -0
- package/dist/middleware/reflect/provenance-check.d.ts.map +1 -0
- package/dist/middleware/reflect/provenance-check.js +180 -0
- package/dist/middleware/reflect/provenance-check.js.map +1 -0
- package/dist/middleware/reflect/provenance-reviewer.d.ts +52 -0
- package/dist/middleware/reflect/provenance-reviewer.d.ts.map +1 -0
- package/dist/middleware/reflect/provenance-reviewer.js +253 -0
- package/dist/middleware/reflect/provenance-reviewer.js.map +1 -0
- package/dist/middleware/reflect/prune-collapsed-types.d.ts +11 -0
- package/dist/middleware/reflect/prune-collapsed-types.d.ts.map +1 -0
- package/dist/middleware/reflect/prune-collapsed-types.js +32 -0
- package/dist/middleware/reflect/prune-collapsed-types.js.map +1 -0
- package/dist/middleware/reflect/recognize-root.d.ts +75 -0
- package/dist/middleware/reflect/recognize-root.d.ts.map +1 -0
- package/dist/middleware/reflect/recognize-root.js +204 -0
- package/dist/middleware/reflect/recognize-root.js.map +1 -0
- package/dist/middleware/reflect/render-agent-flag.d.ts +25 -0
- package/dist/middleware/reflect/render-agent-flag.d.ts.map +1 -0
- package/dist/middleware/reflect/render-agent-flag.js +39 -0
- package/dist/middleware/reflect/render-agent-flag.js.map +1 -0
- package/dist/middleware/reflect/retrieve-graph-slice.d.ts +54 -0
- package/dist/middleware/reflect/retrieve-graph-slice.d.ts.map +1 -0
- package/dist/middleware/reflect/retrieve-graph-slice.js +173 -0
- package/dist/middleware/reflect/retrieve-graph-slice.js.map +1 -0
- package/dist/middleware/reflect/root-relatedness.d.ts +31 -0
- package/dist/middleware/reflect/root-relatedness.d.ts.map +1 -0
- package/dist/middleware/reflect/root-relatedness.js +92 -0
- package/dist/middleware/reflect/root-relatedness.js.map +1 -0
- package/dist/middleware/reflect/schema-heal.d.ts +22 -0
- package/dist/middleware/reflect/schema-heal.d.ts.map +1 -0
- package/dist/middleware/reflect/schema-heal.js +119 -0
- package/dist/middleware/reflect/schema-heal.js.map +1 -0
- package/dist/middleware/reflect/schema-validator.d.ts +85 -0
- package/dist/middleware/reflect/schema-validator.d.ts.map +1 -0
- package/dist/middleware/reflect/schema-validator.js +196 -0
- package/dist/middleware/reflect/schema-validator.js.map +1 -0
- package/dist/middleware/reflect/stage-audit-graph.d.ts +115 -0
- package/dist/middleware/reflect/stage-audit-graph.d.ts.map +1 -0
- package/dist/middleware/reflect/stage-audit-graph.js +563 -0
- package/dist/middleware/reflect/stage-audit-graph.js.map +1 -0
- package/dist/middleware/reflect/stage-d-resolve-graph.d.ts +87 -0
- package/dist/middleware/reflect/stage-d-resolve-graph.d.ts.map +1 -0
- package/dist/middleware/reflect/stage-d-resolve-graph.js +256 -0
- package/dist/middleware/reflect/stage-d-resolve-graph.js.map +1 -0
- package/dist/middleware/reflect/synthesizeFromSceneCard.d.ts +15 -0
- package/dist/middleware/reflect/synthesizeFromSceneCard.d.ts.map +1 -0
- package/dist/middleware/reflect/synthesizeFromSceneCard.js +91 -0
- package/dist/middleware/reflect/synthesizeFromSceneCard.js.map +1 -0
- package/dist/middleware/reflect/types.d.ts +261 -0
- package/dist/middleware/reflect/types.d.ts.map +1 -0
- package/dist/middleware/reflect/types.js +3 -0
- package/dist/middleware/reflect/types.js.map +1 -0
- package/dist/middleware/reflect/v2-integrate.d.ts +120 -0
- package/dist/middleware/reflect/v2-integrate.d.ts.map +1 -0
- package/dist/middleware/reflect/v2-integrate.js +388 -0
- package/dist/middleware/reflect/v2-integrate.js.map +1 -0
- package/dist/middleware/reflect/v2-judge.d.ts +44 -0
- package/dist/middleware/reflect/v2-judge.d.ts.map +1 -0
- package/dist/middleware/reflect/v2-judge.js +191 -0
- package/dist/middleware/reflect/v2-judge.js.map +1 -0
- package/dist/relation-sets.d.ts +2 -0
- package/dist/relation-sets.d.ts.map +1 -0
- package/dist/relation-sets.js +35 -0
- package/dist/relation-sets.js.map +1 -0
- package/dist/routes/__tests__/flags.test.d.ts +2 -0
- package/dist/routes/__tests__/flags.test.d.ts.map +1 -0
- package/dist/routes/__tests__/flags.test.js +257 -0
- package/dist/routes/__tests__/flags.test.js.map +1 -0
- package/dist/routes/__tests__/models-catalog.test.d.ts +2 -0
- package/dist/routes/__tests__/models-catalog.test.d.ts.map +1 -0
- package/dist/routes/__tests__/models-catalog.test.js +130 -0
- package/dist/routes/__tests__/models-catalog.test.js.map +1 -0
- package/dist/routes/__tests__/reflect-pause-drain.test.d.ts +2 -0
- package/dist/routes/__tests__/reflect-pause-drain.test.d.ts.map +1 -0
- package/dist/routes/__tests__/reflect-pause-drain.test.js +38 -0
- package/dist/routes/__tests__/reflect-pause-drain.test.js.map +1 -0
- package/dist/routes/__tests__/spend-pause-drain.test.d.ts +2 -0
- package/dist/routes/__tests__/spend-pause-drain.test.d.ts.map +1 -0
- package/dist/routes/__tests__/spend-pause-drain.test.js +38 -0
- package/dist/routes/__tests__/spend-pause-drain.test.js.map +1 -0
- package/dist/routes/admin.d.ts +49 -0
- package/dist/routes/admin.d.ts.map +1 -0
- package/dist/routes/admin.js +471 -0
- package/dist/routes/admin.js.map +1 -0
- package/dist/routes/blocks.d.ts +4 -0
- package/dist/routes/blocks.d.ts.map +1 -0
- package/dist/routes/blocks.js +893 -0
- package/dist/routes/blocks.js.map +1 -0
- package/dist/routes/chat-proxy.d.ts +5 -0
- package/dist/routes/chat-proxy.d.ts.map +1 -0
- package/dist/routes/chat-proxy.js +225 -0
- package/dist/routes/chat-proxy.js.map +1 -0
- package/dist/routes/conversations.d.ts +4 -0
- package/dist/routes/conversations.d.ts.map +1 -0
- package/dist/routes/conversations.js +139 -0
- package/dist/routes/conversations.js.map +1 -0
- package/dist/routes/flags.d.ts +4 -0
- package/dist/routes/flags.d.ts.map +1 -0
- package/dist/routes/flags.js +151 -0
- package/dist/routes/flags.js.map +1 -0
- package/dist/routes/inject.d.ts +4 -0
- package/dist/routes/inject.d.ts.map +1 -0
- package/dist/routes/inject.js +183 -0
- package/dist/routes/inject.js.map +1 -0
- package/dist/routes/mcp-http.d.ts +5 -0
- package/dist/routes/mcp-http.d.ts.map +1 -0
- package/dist/routes/mcp-http.js +94 -0
- package/dist/routes/mcp-http.js.map +1 -0
- package/dist/routes/quarantine.d.ts +4 -0
- package/dist/routes/quarantine.d.ts.map +1 -0
- package/dist/routes/quarantine.js +66 -0
- package/dist/routes/quarantine.js.map +1 -0
- package/dist/routes/recall.d.ts +5 -0
- package/dist/routes/recall.d.ts.map +1 -0
- package/dist/routes/recall.js +573 -0
- package/dist/routes/recall.js.map +1 -0
- package/dist/routes/reflect.d.ts +5 -0
- package/dist/routes/reflect.d.ts.map +1 -0
- package/dist/routes/reflect.js +231 -0
- package/dist/routes/reflect.js.map +1 -0
- package/dist/routes/session.d.ts +4 -0
- package/dist/routes/session.d.ts.map +1 -0
- package/dist/routes/session.js +418 -0
- package/dist/routes/session.js.map +1 -0
- package/dist/routes/state.d.ts +116 -0
- package/dist/routes/state.d.ts.map +1 -0
- package/dist/routes/state.js +621 -0
- package/dist/routes/state.js.map +1 -0
- package/dist/routes/usage.d.ts +3 -0
- package/dist/routes/usage.d.ts.map +1 -0
- package/dist/routes/usage.js +141 -0
- package/dist/routes/usage.js.map +1 -0
- package/dist/routes/workspace.d.ts +5 -0
- package/dist/routes/workspace.d.ts.map +1 -0
- package/dist/routes/workspace.js +435 -0
- package/dist/routes/workspace.js.map +1 -0
- package/dist/server.d.ts +13 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +298 -0
- package/dist/server.js.map +1 -0
- package/dist/store/__tests__/backup.test.d.ts +2 -0
- package/dist/store/__tests__/backup.test.d.ts.map +1 -0
- package/dist/store/__tests__/backup.test.js +53 -0
- package/dist/store/__tests__/backup.test.js.map +1 -0
- package/dist/store/__tests__/quality.test.d.ts +2 -0
- package/dist/store/__tests__/quality.test.d.ts.map +1 -0
- package/dist/store/__tests__/quality.test.js +75 -0
- package/dist/store/__tests__/quality.test.js.map +1 -0
- package/dist/store/backup.d.ts +14 -0
- package/dist/store/backup.d.ts.map +1 -0
- package/dist/store/backup.js +95 -0
- package/dist/store/backup.js.map +1 -0
- package/dist/store/database.d.ts +407 -0
- package/dist/store/database.d.ts.map +1 -0
- package/dist/store/database.js +2004 -0
- package/dist/store/database.js.map +1 -0
- package/dist/store/quality.d.ts +25 -0
- package/dist/store/quality.d.ts.map +1 -0
- package/dist/store/quality.js +48 -0
- package/dist/store/quality.js.map +1 -0
- package/dist/tools/__tests__/assemble-block-chains.test.d.ts +2 -0
- package/dist/tools/__tests__/assemble-block-chains.test.d.ts.map +1 -0
- package/dist/tools/__tests__/assemble-block-chains.test.js +118 -0
- package/dist/tools/__tests__/assemble-block-chains.test.js.map +1 -0
- package/dist/tools/__tests__/filter-roots-by-concepts.test.d.ts +2 -0
- package/dist/tools/__tests__/filter-roots-by-concepts.test.d.ts.map +1 -0
- package/dist/tools/__tests__/filter-roots-by-concepts.test.js +68 -0
- package/dist/tools/__tests__/filter-roots-by-concepts.test.js.map +1 -0
- package/dist/tools/__tests__/flag-surface.test.d.ts +2 -0
- package/dist/tools/__tests__/flag-surface.test.d.ts.map +1 -0
- package/dist/tools/__tests__/flag-surface.test.js +130 -0
- package/dist/tools/__tests__/flag-surface.test.js.map +1 -0
- package/dist/tools/core.d.ts +5 -0
- package/dist/tools/core.d.ts.map +1 -0
- package/dist/tools/core.js +962 -0
- package/dist/tools/core.js.map +1 -0
- package/dist/tools/derive.d.ts +5 -0
- package/dist/tools/derive.d.ts.map +1 -0
- package/dist/tools/derive.js +182 -0
- package/dist/tools/derive.js.map +1 -0
- package/dist/tools/flag-surface.d.ts +26 -0
- package/dist/tools/flag-surface.d.ts.map +1 -0
- package/dist/tools/flag-surface.js +59 -0
- package/dist/tools/flag-surface.js.map +1 -0
- package/dist/tools/helpers.d.ts +99 -0
- package/dist/tools/helpers.d.ts.map +1 -0
- package/dist/tools/helpers.js +243 -0
- package/dist/tools/helpers.js.map +1 -0
- package/dist/tools/projects.d.ts +5 -0
- package/dist/tools/projects.d.ts.map +1 -0
- package/dist/tools/projects.js +175 -0
- package/dist/tools/projects.js.map +1 -0
- package/dist/tools/system.d.ts +5 -0
- package/dist/tools/system.d.ts.map +1 -0
- package/dist/tools/system.js +1361 -0
- package/dist/tools/system.js.map +1 -0
- package/dist/tools/tasks.d.ts +5 -0
- package/dist/tools/tasks.d.ts.map +1 -0
- package/dist/tools/tasks.js +289 -0
- package/dist/tools/tasks.js.map +1 -0
- package/package.json +69 -0
- package/scripts/nodedex-entry.mjs +396 -0
- package/tui-dist/App.js +185 -0
- package/tui-dist/api.js +197 -0
- package/tui-dist/cli.js +53 -0
- package/tui-dist/components.js +63 -0
- package/tui-dist/config.js +242 -0
- package/tui-dist/connect-snippets.js +98 -0
- package/tui-dist/feed.js +51 -0
- package/tui-dist/health.js +465 -0
- package/tui-dist/hooks.js +23 -0
- package/tui-dist/memory.js +220 -0
- package/tui-dist/onboarding.js +498 -0
- package/tui-dist/review.js +193 -0
- package/tui-dist/servers.js +556 -0
- package/tui-dist/smoke.js +15 -0
- package/tui-dist/theme.js +106 -0
|
@@ -0,0 +1,396 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* NodeDex CLI entry point.
|
|
4
|
+
*
|
|
5
|
+
* nodedex First run → the setup wizard; configured → the server
|
|
6
|
+
* nodedex run Start the MCP + API server (never the wizard)
|
|
7
|
+
* nodedex tui Launch the console / onboarding wizard
|
|
8
|
+
* nodedex setup Wizard, or headless with flags (see help)
|
|
9
|
+
* nodedex help Show usage
|
|
10
|
+
*
|
|
11
|
+
* Back-compat: `nodedex-server` (no args) ALWAYS starts the server (never interactive).
|
|
12
|
+
* In the repo, build first with `npm run build` in server/ (this loads ../dist/server.js);
|
|
13
|
+
* the published npm package ships dist/ + the compiled TUI (tui-dist/) ready to run.
|
|
14
|
+
*/
|
|
15
|
+
import { spawn } from "node:child_process";
|
|
16
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
17
|
+
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
18
|
+
import { dirname, resolve, join } from "node:path";
|
|
19
|
+
import { homedir } from "node:os";
|
|
20
|
+
|
|
21
|
+
const here = dirname(fileURLToPath(import.meta.url));
|
|
22
|
+
const args = process.argv.slice(2);
|
|
23
|
+
const cmd = (args[0] || "").toLowerCase();
|
|
24
|
+
|
|
25
|
+
const HELP = `nodedex — persistent knowledge-graph memory for AI agents
|
|
26
|
+
|
|
27
|
+
Usage:
|
|
28
|
+
nodedex run Start the MCP + API server (+ any enabled capture watchers)
|
|
29
|
+
nodedex connect Print the connection card: the RIGHT url per client location
|
|
30
|
+
(host / Docker / LAN), token rule, and copy-paste test commands.
|
|
31
|
+
--json for machine-readable (agents).
|
|
32
|
+
nodedex tui Launch the operator console
|
|
33
|
+
nodedex onboard Run the setup wizard (provider / model / port / db)
|
|
34
|
+
nodedex setup Same as onboard; with flags = HEADLESS setup (for agents/scripts):
|
|
35
|
+
--provider openrouter --key sk-or-... [--model google/gemini-2.5-flash-lite]
|
|
36
|
+
--provider local --base-url http://localhost:11434/v1 --model <id>
|
|
37
|
+
[--port 3001] [--db <name>] [--capture hermes,claude-code | none] [--dry-run]
|
|
38
|
+
nodedex uninstall Remove ALL local data + config (~/.nodedex) — asks first;
|
|
39
|
+
--yes skips the prompt (scripts). Does not remove the package.
|
|
40
|
+
nodedex help Show this message
|
|
41
|
+
|
|
42
|
+
Reconfigure = re-run \`nodedex onboard\` (wizard) or \`nodedex setup\` with flags
|
|
43
|
+
(headless — merges into the existing config, e.g. just --key or --model).
|
|
44
|
+
|
|
45
|
+
With no command: first run launches the setup wizard; once configured it starts
|
|
46
|
+
the server (same as \`nodedex run\`). \`nodedex-server\` always starts the server.
|
|
47
|
+
Headless example (what an agent runs after asking its user):
|
|
48
|
+
nodedex setup --provider openrouter --key sk-or-... --db memory --capture claude-code
|
|
49
|
+
nodedex run`;
|
|
50
|
+
|
|
51
|
+
// The server is env-only; the TUI normally injects provider/port/db env at launch
|
|
52
|
+
// (tui/src/config.ts: providerEnv + launchServer). `nodedex run` does the SAME
|
|
53
|
+
// translation here, from ~/.nodedex/config.json, so it works standalone — otherwise
|
|
54
|
+
// the bare server defaults to keyless gemini. Keep this mapping in sync with
|
|
55
|
+
// config.ts. Explicit env always wins (fill-if-unset).
|
|
56
|
+
const OPENROUTER_BASE_URL = "https://openrouter.ai/api/v1";
|
|
57
|
+
const OPENROUTER_DEFAULT_MODEL = "google/gemini-2.5-flash";
|
|
58
|
+
|
|
59
|
+
function applyConfigEnv() {
|
|
60
|
+
let c;
|
|
61
|
+
try {
|
|
62
|
+
c = JSON.parse(readFileSync(join(homedir(), ".nodedex", "config.json"), "utf8"));
|
|
63
|
+
} catch {
|
|
64
|
+
return; // no config yet — the server falls back to its own .env / defaults
|
|
65
|
+
}
|
|
66
|
+
const set = (k, v) => {
|
|
67
|
+
if (v != null && v !== "" && !process.env[k]) process.env[k] = String(v);
|
|
68
|
+
};
|
|
69
|
+
if (c.provider === "openrouter" && c.openrouter_key) {
|
|
70
|
+
set("AI_PROVIDER", "openai-compatible");
|
|
71
|
+
set("OPENAI_BASE_URL", OPENROUTER_BASE_URL);
|
|
72
|
+
set("OPENAI_API_KEY", c.openrouter_key);
|
|
73
|
+
set("AI_MODEL", c.model || OPENROUTER_DEFAULT_MODEL);
|
|
74
|
+
} else if (c.provider === "local" && c.base_url && c.model) {
|
|
75
|
+
set("AI_PROVIDER", "openai-compatible");
|
|
76
|
+
set("OPENAI_BASE_URL", c.base_url);
|
|
77
|
+
set("OPENAI_API_KEY", "local");
|
|
78
|
+
set("AI_MODEL", c.model);
|
|
79
|
+
}
|
|
80
|
+
set("PORT", c.port);
|
|
81
|
+
set("WORKSPACE_DB_PATH", c.dbPath);
|
|
82
|
+
// Arc mode ON, matching the TUI's launch env (servers.ts). Without this, watcher-fed
|
|
83
|
+
// turns (turn_number present) route to the retired per-turn v1 path and NO-OP — the
|
|
84
|
+
// whole capture story silently dead on a headless install. Found the hard way in the
|
|
85
|
+
// 2026-07-02 dogfood run: a bare `node dist/server.js` captured nothing.
|
|
86
|
+
set("NODEDEX_ARC_EXTRACTION", "1");
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
function startServer() {
|
|
90
|
+
applyConfigEnv();
|
|
91
|
+
const distServer = resolve(here, "../dist/server.js");
|
|
92
|
+
if (!existsSync(distServer)) {
|
|
93
|
+
console.error(
|
|
94
|
+
"[nodedex] dist/server.js not found — build the server first: `npm run build` (in server/)."
|
|
95
|
+
);
|
|
96
|
+
process.exit(1);
|
|
97
|
+
}
|
|
98
|
+
// On Windows a bare absolute path ("C:\\...") is rejected by the ESM loader;
|
|
99
|
+
// it must be a file:// URL.
|
|
100
|
+
import(pathToFileURL(distServer).href);
|
|
101
|
+
startEnabledWatchers();
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
// Headless path parity with the TUI: `nodedex run` also brings up whichever capture
|
|
105
|
+
// watchers the config enables (the TUI spawns its own when it runs; this covers
|
|
106
|
+
// server-only / agent-driven installs where no TUI is ever opened).
|
|
107
|
+
function startEnabledWatchers() {
|
|
108
|
+
let c = {};
|
|
109
|
+
try { c = JSON.parse(readFileSync(join(homedir(), ".nodedex", "config.json"), "utf8")); } catch { return; }
|
|
110
|
+
const defs = [
|
|
111
|
+
{ key: "hermesCapture", script: "hermes-statedb-watcher.mjs", name: "hermes" },
|
|
112
|
+
{ key: "claudeCapture", script: "claude-code-watcher.mjs", name: "claude-code" },
|
|
113
|
+
];
|
|
114
|
+
for (const d of defs) {
|
|
115
|
+
if (!c[d.key] || c[d.key].enabled === false) continue; // only spawn what setup/TUI explicitly enabled
|
|
116
|
+
const script = resolve(here, "../adapters", d.script);
|
|
117
|
+
if (!existsSync(script)) continue;
|
|
118
|
+
const child = spawn(process.execPath, [script], { cwd: resolve(here, ".."), stdio: ["ignore", "inherit", "inherit"] });
|
|
119
|
+
child.on("error", (e) => console.error(`[nodedex] ${d.name} watcher failed to start: ${e.message}`));
|
|
120
|
+
console.error(`[nodedex] ${d.name} capture watcher started (pid ${child.pid}).`);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
// ─── Headless setup (agent/script-driven — no TUI) ─────────────────────────────
|
|
125
|
+
// Writes the SAME ~/.nodedex/config.json the wizard writes, so `nodedex run`, the
|
|
126
|
+
// TUI, and the watchers all pick it up identically. Deterministic on purpose: an
|
|
127
|
+
// agent installing NodeDex for its user runs ONE command instead of improvising.
|
|
128
|
+
function flagValue(name) {
|
|
129
|
+
const i = args.indexOf(name);
|
|
130
|
+
return i >= 0 ? args[i + 1] : undefined;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
async function headlessSetup() {
|
|
134
|
+
const provider = (flagValue("--provider") || "").toLowerCase();
|
|
135
|
+
const dryRun = args.includes("--dry-run");
|
|
136
|
+
if (provider !== "openrouter" && provider !== "local") {
|
|
137
|
+
console.error("[nodedex setup] --provider must be 'openrouter' or 'local'. See `nodedex help`.");
|
|
138
|
+
process.exit(1);
|
|
139
|
+
}
|
|
140
|
+
const patch = { provider, onboarded: true };
|
|
141
|
+
|
|
142
|
+
if (provider === "openrouter") {
|
|
143
|
+
const key = flagValue("--key");
|
|
144
|
+
if (!key) { console.error("[nodedex setup] --key sk-or-... is required for --provider openrouter."); process.exit(1); }
|
|
145
|
+
// Same validation as the wizard: a typo fails HERE, not at first extraction.
|
|
146
|
+
try {
|
|
147
|
+
const r = await fetch(`${OPENROUTER_BASE_URL}/key`, { headers: { Authorization: `Bearer ${key}` }, signal: AbortSignal.timeout(8000) });
|
|
148
|
+
if (!r.ok) { console.error(`[nodedex setup] OpenRouter rejected the key (${r.status}).`); process.exit(1); }
|
|
149
|
+
} catch (e) {
|
|
150
|
+
console.error(`[nodedex setup] couldn't reach OpenRouter to validate the key (${e?.message ?? e}).`);
|
|
151
|
+
process.exit(1);
|
|
152
|
+
}
|
|
153
|
+
patch.openrouter_key = key;
|
|
154
|
+
patch.model = flagValue("--model") || "google/gemini-2.5-flash-lite";
|
|
155
|
+
} else {
|
|
156
|
+
const baseUrl = flagValue("--base-url");
|
|
157
|
+
const model = flagValue("--model");
|
|
158
|
+
if (!baseUrl || !model) { console.error("[nodedex setup] --base-url and --model are required for --provider local."); process.exit(1); }
|
|
159
|
+
patch.base_url = baseUrl;
|
|
160
|
+
patch.model = model;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
const port = Number(flagValue("--port"));
|
|
164
|
+
patch.port = Number.isInteger(port) && port > 0 ? port : 3001;
|
|
165
|
+
|
|
166
|
+
const db = flagValue("--db") || "workspace";
|
|
167
|
+
patch.dbPath = /[\\/]/.test(db)
|
|
168
|
+
? db // explicit path given
|
|
169
|
+
: join(homedir(), ".nodedex", `${db.trim().replace(/[^a-z0-9_-]/gi, "-").replace(/^-+|-+$/g, "") || "workspace"}.db`);
|
|
170
|
+
|
|
171
|
+
// Capture consent is EXPLICIT here (no checkbox screen): the caller — typically an
|
|
172
|
+
// agent that just asked its user — names the hosts. Default: none (read-only setup).
|
|
173
|
+
const capture = (flagValue("--capture") || "none").toLowerCase();
|
|
174
|
+
const hosts = new Set(capture === "none" ? [] : capture.split(",").map((s) => s.trim()).filter(Boolean));
|
|
175
|
+
patch.hermesCapture = { enabled: hosts.has("hermes") };
|
|
176
|
+
patch.claudeCapture = { enabled: hosts.has("claude-code") || hosts.has("claude") };
|
|
177
|
+
|
|
178
|
+
const configPath = join(homedir(), ".nodedex", "config.json");
|
|
179
|
+
let existing = {};
|
|
180
|
+
try { existing = JSON.parse(readFileSync(configPath, "utf8")); } catch { /* fresh install */ }
|
|
181
|
+
const merged = { ...existing, ...patch };
|
|
182
|
+
|
|
183
|
+
if (dryRun) {
|
|
184
|
+
const masked = { ...merged, openrouter_key: merged.openrouter_key ? merged.openrouter_key.slice(0, 8) + "…" : undefined };
|
|
185
|
+
console.log("[nodedex setup] DRY-RUN — would write to " + configPath + ":");
|
|
186
|
+
console.log(JSON.stringify(masked, null, 2));
|
|
187
|
+
return;
|
|
188
|
+
}
|
|
189
|
+
const { mkdirSync, writeFileSync } = await import("node:fs");
|
|
190
|
+
mkdirSync(join(homedir(), ".nodedex"), { recursive: true });
|
|
191
|
+
writeFileSync(configPath, JSON.stringify(merged, null, 2));
|
|
192
|
+
console.log(`[nodedex setup] config written → ${configPath}`);
|
|
193
|
+
console.log(` provider=${provider} model=${merged.model} port=${merged.port}`);
|
|
194
|
+
console.log(` db=${merged.dbPath}`);
|
|
195
|
+
console.log(` capture: hermes=${patch.hermesCapture.enabled} claude-code=${patch.claudeCapture.enabled}`);
|
|
196
|
+
console.log(`Next: \`nodedex run\` starts the server (+ enabled watchers).`);
|
|
197
|
+
console.log(`Connect your agent to http://127.0.0.1:${merged.port}/mcp — snippets: ~/.nodedex/connect-snippets.md (written by the TUI) or the README.`);
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
// Launch the TUI (operator console + first-run onboarding wizard). Two layouts:
|
|
201
|
+
// packaged (npx / npm install): the compiled TUI ships INSIDE this package at
|
|
202
|
+
// tui-dist/ and runs on plain node (its deps — ink/react — are package deps);
|
|
203
|
+
// repo/dev: the sibling tui/ package, run from source via tsx.
|
|
204
|
+
function launchTui(extraArgs = []) {
|
|
205
|
+
const packagedCli = resolve(here, "../tui-dist/cli.js");
|
|
206
|
+
const repoTuiDir = resolve(here, "../../tui");
|
|
207
|
+
let spawnArgs, cwd;
|
|
208
|
+
if (existsSync(packagedCli)) {
|
|
209
|
+
spawnArgs = [packagedCli, ...extraArgs];
|
|
210
|
+
cwd = resolve(here, "..");
|
|
211
|
+
} else if (existsSync(resolve(repoTuiDir, "src/cli.tsx"))) {
|
|
212
|
+
spawnArgs = ["--import", "tsx/esm", "src/cli.tsx", ...extraArgs];
|
|
213
|
+
cwd = repoTuiDir;
|
|
214
|
+
} else {
|
|
215
|
+
console.error("[nodedex] no TUI found (neither packaged tui-dist/ nor a repo tui/). Reinstall the package.");
|
|
216
|
+
process.exit(1);
|
|
217
|
+
}
|
|
218
|
+
const child = spawn(process.execPath, spawnArgs, { cwd, stdio: "inherit" });
|
|
219
|
+
child.on("error", (err) => {
|
|
220
|
+
console.error(`[nodedex] failed to launch the TUI: ${err.message}`);
|
|
221
|
+
process.exit(1);
|
|
222
|
+
});
|
|
223
|
+
child.on("exit", (code) => process.exit(code ?? 0));
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
// ─── `nodedex uninstall` — remove ~/.nodedex (data + config). DESTRUCTIVE. ─────
|
|
227
|
+
// Mirrors tui/scripts/uninstall.mjs so packaged (npx) installs have a way out too.
|
|
228
|
+
// Does NOT remove the package itself or the NodeDex entry in the agent host's MCP
|
|
229
|
+
// config. `--yes` skips the prompt (agent/script-driven).
|
|
230
|
+
async function uninstall() {
|
|
231
|
+
const { rmSync, readdirSync } = await import("node:fs");
|
|
232
|
+
const home = join(homedir(), ".nodedex");
|
|
233
|
+
if (!existsSync(home)) {
|
|
234
|
+
console.log(`Nothing to remove — ${home} doesn't exist.`);
|
|
235
|
+
return;
|
|
236
|
+
}
|
|
237
|
+
let dbs = [];
|
|
238
|
+
try { dbs = readdirSync(home).filter((f) => f.endsWith(".db")); } catch { /* unreadable */ }
|
|
239
|
+
console.log(`\nThis will permanently DELETE:\n ${home}\n`);
|
|
240
|
+
console.log("Including:");
|
|
241
|
+
console.log(" • your config + OpenRouter API key");
|
|
242
|
+
console.log(` • ${dbs.length} knowledge-graph database(s): ${dbs.join(", ") || "(none)"}`);
|
|
243
|
+
console.log(" • server logs + reflect-pause state");
|
|
244
|
+
console.log("\nThis cannot be undone. It does NOT remove the nodedex package, or the NodeDex");
|
|
245
|
+
console.log("entry in your agent host's MCP config — remove those yourself.\n");
|
|
246
|
+
|
|
247
|
+
if (!args.includes("--yes")) {
|
|
248
|
+
const readline = await import("node:readline/promises");
|
|
249
|
+
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
250
|
+
const ans = (await rl.question('Type "delete" to confirm: ')).trim().toLowerCase();
|
|
251
|
+
rl.close();
|
|
252
|
+
if (ans !== "delete") {
|
|
253
|
+
console.log("Aborted — nothing removed.");
|
|
254
|
+
return;
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
try {
|
|
258
|
+
rmSync(home, { recursive: true, force: true });
|
|
259
|
+
} catch (e) {
|
|
260
|
+
console.log(`\nFailed to remove ${home}: ${e?.message ?? e}`);
|
|
261
|
+
console.log("A server may still be holding a database file. Stop all NodeDex servers, then re-run.");
|
|
262
|
+
process.exit(1);
|
|
263
|
+
}
|
|
264
|
+
console.log(`\nRemoved ${home}.`);
|
|
265
|
+
console.log("Also remove the NodeDex MCP entry from your agent host's config.");
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
// First run? (mirrors tui/src/config.ts needsOnboarding, without importing it)
|
|
269
|
+
function isOnboarded() {
|
|
270
|
+
try {
|
|
271
|
+
const c = JSON.parse(readFileSync(join(homedir(), ".nodedex", "config.json"), "utf8"));
|
|
272
|
+
if (!c.onboarded) return false;
|
|
273
|
+
if (c.provider === "openrouter") return !!c.openrouter_key;
|
|
274
|
+
if (c.provider === "local") return !!(c.base_url && c.model);
|
|
275
|
+
return false;
|
|
276
|
+
} catch {
|
|
277
|
+
return false;
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
// ─── `nodedex connect` — the connection card ───────────────────────────────────
|
|
282
|
+
// THE fix for "connecting is messy": one command that reports ground truth instead
|
|
283
|
+
// of the user/agent guessing at ip × port × token. Reads the live server list
|
|
284
|
+
// (tui-session.json), probes health, and prints the RIGHT url for each client
|
|
285
|
+
// location + the exact test command to run from there. --json for agents.
|
|
286
|
+
async function connectCard() {
|
|
287
|
+
const asJson = args.includes("--json");
|
|
288
|
+
let session = {};
|
|
289
|
+
try { session = JSON.parse(readFileSync(join(homedir(), ".nodedex", "tui-session.json"), "utf8")); } catch { /* none */ }
|
|
290
|
+
let managed = Array.isArray(session?.managed) ? session.managed : [];
|
|
291
|
+
if (managed.length === 0) {
|
|
292
|
+
// No TUI-managed record — probe the config/default port directly (headless installs).
|
|
293
|
+
let port = 3001;
|
|
294
|
+
try { port = JSON.parse(readFileSync(join(homedir(), ".nodedex", "config.json"), "utf8"))?.port || 3001; } catch { /* default */ }
|
|
295
|
+
managed = [{ port, token: process.env.NODEDEX_API_TOKEN || "" }];
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
const servers = [];
|
|
299
|
+
for (const m of managed) {
|
|
300
|
+
if (!m?.port) continue;
|
|
301
|
+
let up = false, db = null;
|
|
302
|
+
try {
|
|
303
|
+
const r = await fetch(`http://127.0.0.1:${m.port}/api/health`, { signal: AbortSignal.timeout(2500) });
|
|
304
|
+
up = r.ok;
|
|
305
|
+
try { db = (await r.json())?.db ?? null; } catch { /* health may be bodyless */ }
|
|
306
|
+
} catch { /* down */ }
|
|
307
|
+
servers.push({ port: m.port, token: m.token || "", up, db });
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
// Best-effort LAN address (for a remote machine / LAN agent).
|
|
311
|
+
const { networkInterfaces } = await import("node:os");
|
|
312
|
+
let lanIp = null;
|
|
313
|
+
for (const ifaces of Object.values(networkInterfaces() || {})) {
|
|
314
|
+
for (const i of ifaces || []) {
|
|
315
|
+
if (i.family === "IPv4" && !i.internal && !String(i.address).startsWith("169.254.")) { lanIp = i.address; break; }
|
|
316
|
+
}
|
|
317
|
+
if (lanIp) break;
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
if (asJson) {
|
|
321
|
+
console.log(JSON.stringify({
|
|
322
|
+
token_rule: "same-machine connections NEVER need the token; Docker/remote ALWAYS do (unless NODEDEX_STRICT_TOKEN=1)",
|
|
323
|
+
servers: servers.map((s) => ({
|
|
324
|
+
up: s.up, port: s.port, db: s.db,
|
|
325
|
+
from_this_machine: { mcp: `http://127.0.0.1:${s.port}/mcp`, token_needed: false },
|
|
326
|
+
from_docker: { mcp: `http://host.docker.internal:${s.port}/mcp`, token_needed: !!s.token, token: s.token || null, linux_note: "add --add-host=host.docker.internal:host-gateway" },
|
|
327
|
+
from_lan: lanIp ? { mcp: `http://${lanIp}:${s.port}/mcp`, token_needed: !!s.token, token: s.token || null, note: "server must be started with NODEDEX_BIND_HOST=0.0.0.0" } : null,
|
|
328
|
+
})),
|
|
329
|
+
}, null, 2));
|
|
330
|
+
return;
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
if (servers.length === 0) { console.log("[nodedex connect] no server known — run `nodedex run` (or the TUI) first."); return; }
|
|
334
|
+
console.log("NodeDex connection card — the ONE token rule: same machine = no token; Docker/remote = token.\n");
|
|
335
|
+
for (const s of servers) {
|
|
336
|
+
console.log(`● port ${s.port} ${s.up ? "UP" : "DOWN — start it: nodedex run"}${s.db ? ` db=${s.db}` : ""}`);
|
|
337
|
+
console.log(` From THIS machine (Claude Code, local agents):`);
|
|
338
|
+
console.log(` http://127.0.0.1:${s.port}/mcp (no token, ever)`);
|
|
339
|
+
console.log(` test: curl http://127.0.0.1:${s.port}/api/health`);
|
|
340
|
+
console.log(` From INSIDE Docker (agent in a container):`);
|
|
341
|
+
console.log(` http://host.docker.internal:${s.port}/mcp${s.token ? ` + header Authorization: Bearer ${s.token}` : " (no token configured — set one for network exposure)"}`);
|
|
342
|
+
console.log(` test (run INSIDE the container): curl ${s.token ? `-H "Authorization: Bearer ${s.token}" ` : ""}http://host.docker.internal:${s.port}/api/health`);
|
|
343
|
+
console.log(` Linux: add --add-host=host.docker.internal:host-gateway to the container.`);
|
|
344
|
+
if (lanIp) console.log(` From ANOTHER machine on your network: http://${lanIp}:${s.port}/mcp (token required; server needs NODEDEX_BIND_HOST=0.0.0.0)`);
|
|
345
|
+
console.log("");
|
|
346
|
+
}
|
|
347
|
+
console.log(`If a Docker connect fails: (1) run the in-container curl above — if it hangs, it's networking
|
|
348
|
+
(host-gateway flag / Windows firewall "allow" prompt for node), not NodeDex; (2) 401 = missing/wrong
|
|
349
|
+
token header; (3) NEVER use "localhost" from a container (that's the container itself).`);
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
// Bare `npx nodedex` on a fresh machine = the setup wizard, not a keyless server.
|
|
353
|
+
// `nodedex run`/`start` (and the `nodedex-server` bin name) always mean the server —
|
|
354
|
+
// scripts and process managers must never be surprised by an interactive wizard.
|
|
355
|
+
const invokedAsServer = String(process.argv[1] || "").toLowerCase().includes("nodedex-server");
|
|
356
|
+
|
|
357
|
+
switch (cmd) {
|
|
358
|
+
case "":
|
|
359
|
+
if (!invokedAsServer && !isOnboarded()) {
|
|
360
|
+
console.error("[nodedex] first run — launching the setup wizard (use `nodedex run` to skip straight to the server).");
|
|
361
|
+
launchTui(["--onboard"]);
|
|
362
|
+
break;
|
|
363
|
+
}
|
|
364
|
+
startServer();
|
|
365
|
+
break;
|
|
366
|
+
case "run":
|
|
367
|
+
case "start":
|
|
368
|
+
startServer();
|
|
369
|
+
break;
|
|
370
|
+
case "connect":
|
|
371
|
+
case "doctor":
|
|
372
|
+
void connectCard();
|
|
373
|
+
break;
|
|
374
|
+
case "uninstall":
|
|
375
|
+
void uninstall();
|
|
376
|
+
break;
|
|
377
|
+
case "tui":
|
|
378
|
+
case "dashboard":
|
|
379
|
+
launchTui();
|
|
380
|
+
break;
|
|
381
|
+
case "onboard":
|
|
382
|
+
case "setup":
|
|
383
|
+
// Flags present → headless (agent/script-driven); bare → the interactive wizard.
|
|
384
|
+
if (args.some((a) => a.startsWith("--"))) void headlessSetup();
|
|
385
|
+
else launchTui(["--onboard"]);
|
|
386
|
+
break;
|
|
387
|
+
case "help":
|
|
388
|
+
case "-h":
|
|
389
|
+
case "--help":
|
|
390
|
+
console.log(HELP);
|
|
391
|
+
break;
|
|
392
|
+
default:
|
|
393
|
+
console.error(`[nodedex] unknown command: ${args[0]}\n`);
|
|
394
|
+
console.log(HELP);
|
|
395
|
+
process.exit(1);
|
|
396
|
+
}
|
package/tui-dist/App.js
ADDED
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
// App.tsx — shell v3: three views (memory · feed · health), one quiet chrome.
|
|
3
|
+
// Top line = brand + view bar; bottom line = the StatusLine (single home for
|
|
4
|
+
// connection/graph/pipeline/spend numbers). Two poll cadences: fast 2s over
|
|
5
|
+
// LOCAL endpoints, slow 30s for the OpenRouter balance. Input is guarded by
|
|
6
|
+
// isRawModeSupported so a non-TTY (piped) context still renders.
|
|
7
|
+
import { useCallback, useEffect, useRef, useState } from "react";
|
|
8
|
+
import { Box, Text, useApp, useInput, useStdin } from "ink";
|
|
9
|
+
import { Brand, ViewBar, StatusLine } from "./components.js";
|
|
10
|
+
import { MemoryTab } from "./memory.js";
|
|
11
|
+
import { FeedTab } from "./feed.js";
|
|
12
|
+
import { HealthTab } from "./health.js";
|
|
13
|
+
import { fetchDashboard, fetchBalance, getBase, setBase } from "./api.js";
|
|
14
|
+
import { killAllManaged, restoreSession, launchWatcher, isWatcherRunning } from "./servers.js";
|
|
15
|
+
import { loadHermesCapture, loadClaudeCapture } from "./config.js";
|
|
16
|
+
import { theme } from "./theme.js";
|
|
17
|
+
import { useTermSize } from "./hooks.js";
|
|
18
|
+
const VIEWS = ["memory", "feed", "health"];
|
|
19
|
+
const MEMORY = 0;
|
|
20
|
+
const FEED = 1;
|
|
21
|
+
const HEALTH = 2;
|
|
22
|
+
const VERSION = "0.3.0";
|
|
23
|
+
const FAST_MS = 2000;
|
|
24
|
+
const SLOW_MS = 30000;
|
|
25
|
+
export function App() {
|
|
26
|
+
const { exit } = useApp();
|
|
27
|
+
const { isRawModeSupported } = useStdin();
|
|
28
|
+
const { rows } = useTermSize();
|
|
29
|
+
const [dash, setDash] = useState(null);
|
|
30
|
+
const [balance, setBalance] = useState({ remaining: null, available: false });
|
|
31
|
+
const [active, setActive] = useState(MEMORY);
|
|
32
|
+
const [auto, setAuto] = useState(true);
|
|
33
|
+
// Restore the last server+db BEFORE the first poll so we land on the right one (a
|
|
34
|
+
// restart reconnects if it's up, else relaunches the managed server on the same
|
|
35
|
+
// port+db). Polling waits on this so the first frame isn't aimed at the default base.
|
|
36
|
+
const [booting, setBooting] = useState(true);
|
|
37
|
+
// A pane's free-text input mode (search, edit rows) owns the keyboard — while it
|
|
38
|
+
// captures, the shell must not act on q/esc/digits. Ref, not state, so the input
|
|
39
|
+
// handler sees the current value without re-subscribing.
|
|
40
|
+
const captureRef = useRef(false);
|
|
41
|
+
const onCapture = useCallback((v) => { captureRef.current = v; }, []);
|
|
42
|
+
const refresh = useCallback(async () => { setDash(await fetchDashboard()); }, []);
|
|
43
|
+
// Kill any servers the TUI launched before leaving — never leave a managed
|
|
44
|
+
// child (or a held port) behind. Belt-and-suspenders: also on process exit.
|
|
45
|
+
const doExit = useCallback(() => {
|
|
46
|
+
try {
|
|
47
|
+
killAllManaged();
|
|
48
|
+
}
|
|
49
|
+
catch { /* */ }
|
|
50
|
+
try {
|
|
51
|
+
exit();
|
|
52
|
+
}
|
|
53
|
+
catch { /* */ }
|
|
54
|
+
// Force the process down shortly after the soft unmount; pending handles (a
|
|
55
|
+
// managed server's pipes, scan timers) can keep the loop alive otherwise.
|
|
56
|
+
const t = setTimeout(() => process.exit(0), 120);
|
|
57
|
+
if (typeof t.unref === "function")
|
|
58
|
+
t.unref();
|
|
59
|
+
}, [exit]);
|
|
60
|
+
useEffect(() => {
|
|
61
|
+
const onProcExit = () => killAllManaged();
|
|
62
|
+
// SIGTERM/SIGHUP terminate WITHOUT running 'exit' handlers — handle explicitly.
|
|
63
|
+
const onSignal = () => { killAllManaged(); process.exit(0); };
|
|
64
|
+
process.on("exit", onProcExit);
|
|
65
|
+
process.on("SIGINT", onSignal);
|
|
66
|
+
process.on("SIGTERM", onSignal);
|
|
67
|
+
process.on("SIGHUP", onSignal);
|
|
68
|
+
return () => {
|
|
69
|
+
process.off("exit", onProcExit);
|
|
70
|
+
process.off("SIGINT", onSignal);
|
|
71
|
+
process.off("SIGTERM", onSignal);
|
|
72
|
+
process.off("SIGHUP", onSignal);
|
|
73
|
+
};
|
|
74
|
+
}, []);
|
|
75
|
+
// One-time startup restore: reconnect to (or relaunch) the last server+db, then
|
|
76
|
+
// release the boot gate so polling begins against the right base.
|
|
77
|
+
useEffect(() => {
|
|
78
|
+
let alive = true;
|
|
79
|
+
(async () => {
|
|
80
|
+
try {
|
|
81
|
+
const url = await restoreSession();
|
|
82
|
+
if (alive && url)
|
|
83
|
+
setBase(url);
|
|
84
|
+
}
|
|
85
|
+
catch { /* default base */ }
|
|
86
|
+
// Reconcile capture watchers: whatever the user left enabled comes back up with
|
|
87
|
+
// the servers (each watcher self-locates the live server, order doesn't matter).
|
|
88
|
+
try {
|
|
89
|
+
if (loadHermesCapture().enabled)
|
|
90
|
+
launchWatcher();
|
|
91
|
+
}
|
|
92
|
+
catch { /* best-effort */ }
|
|
93
|
+
try {
|
|
94
|
+
if (loadClaudeCapture().enabled)
|
|
95
|
+
launchWatcher("claude-code");
|
|
96
|
+
}
|
|
97
|
+
catch { /* best-effort */ }
|
|
98
|
+
if (alive)
|
|
99
|
+
setBooting(false);
|
|
100
|
+
})();
|
|
101
|
+
return () => { alive = false; };
|
|
102
|
+
}, []);
|
|
103
|
+
// Fast poll — local endpoints only. Held until boot restore picks the base.
|
|
104
|
+
useEffect(() => {
|
|
105
|
+
if (booting)
|
|
106
|
+
return;
|
|
107
|
+
let alive = true;
|
|
108
|
+
const run = async () => {
|
|
109
|
+
const d = await fetchDashboard();
|
|
110
|
+
if (alive)
|
|
111
|
+
setDash(d);
|
|
112
|
+
};
|
|
113
|
+
run();
|
|
114
|
+
if (!auto)
|
|
115
|
+
return () => { alive = false; };
|
|
116
|
+
const id = setInterval(run, FAST_MS);
|
|
117
|
+
return () => { alive = false; clearInterval(id); };
|
|
118
|
+
}, [auto, booting]);
|
|
119
|
+
// Slow poll — balance hits OpenRouter, keep it gentle. Also waits on boot.
|
|
120
|
+
useEffect(() => {
|
|
121
|
+
if (booting)
|
|
122
|
+
return;
|
|
123
|
+
let alive = true;
|
|
124
|
+
const run = async () => {
|
|
125
|
+
const b = await fetchBalance();
|
|
126
|
+
if (alive)
|
|
127
|
+
setBalance(b);
|
|
128
|
+
};
|
|
129
|
+
run();
|
|
130
|
+
const id = setInterval(run, SLOW_MS);
|
|
131
|
+
return () => { alive = false; clearInterval(id); };
|
|
132
|
+
}, [booting]);
|
|
133
|
+
useInput((input, key) => {
|
|
134
|
+
if (key.ctrl && input === "c") {
|
|
135
|
+
doExit();
|
|
136
|
+
return;
|
|
137
|
+
}
|
|
138
|
+
if (captureRef.current)
|
|
139
|
+
return; // a pane's input mode owns the keyboard
|
|
140
|
+
if (input === "q") {
|
|
141
|
+
doExit();
|
|
142
|
+
return;
|
|
143
|
+
}
|
|
144
|
+
if (key.tab) {
|
|
145
|
+
setActive((a) => (key.shift ? a - 1 + VIEWS.length : a + 1) % VIEWS.length);
|
|
146
|
+
return;
|
|
147
|
+
}
|
|
148
|
+
if (input >= "1" && input <= String(VIEWS.length)) {
|
|
149
|
+
setActive(Number(input) - 1);
|
|
150
|
+
return;
|
|
151
|
+
}
|
|
152
|
+
// r/j/k etc. belong to the views; only global leftovers here.
|
|
153
|
+
if (active === FEED && input === "r")
|
|
154
|
+
void refresh();
|
|
155
|
+
if (input === "a")
|
|
156
|
+
setAuto((v) => !v);
|
|
157
|
+
},
|
|
158
|
+
// Strict boolean: ink's useInput only skips raw mode when isActive === false.
|
|
159
|
+
{ isActive: isRawModeSupported === true });
|
|
160
|
+
const captureDots = [
|
|
161
|
+
{ name: "claude", on: isWatcherRunning("claude-code") },
|
|
162
|
+
{ name: "hermes", on: isWatcherRunning("hermes") },
|
|
163
|
+
];
|
|
164
|
+
let body;
|
|
165
|
+
if (active === HEALTH) {
|
|
166
|
+
// Health stays usable when the connection is down — that's where you fix it.
|
|
167
|
+
body = _jsx(HealthTab, { dash: dash, balance: balance, isActive: isRawModeSupported === true, onCapture: onCapture, onConnect: () => void refresh() });
|
|
168
|
+
}
|
|
169
|
+
else if (!dash) {
|
|
170
|
+
body = (_jsx(Box, { paddingY: 1, children: _jsx(Text, { color: theme.dim, children: `connecting to ${getBase()} …` }) }));
|
|
171
|
+
}
|
|
172
|
+
else if (!dash.ok) {
|
|
173
|
+
body = (_jsxs(Box, { flexDirection: "column", paddingY: 1, children: [_jsx(Text, { color: theme.danger, children: `● server unreachable at ${getBase()}` }), _jsx(Text, { color: theme.dim, children: "fix it in health [3] \u2014 switch server / db, or `nodedex run`" })] }));
|
|
174
|
+
}
|
|
175
|
+
else if (active === MEMORY) {
|
|
176
|
+
body = _jsx(MemoryTab, { isActive: isRawModeSupported === true, onCapture: onCapture });
|
|
177
|
+
}
|
|
178
|
+
else {
|
|
179
|
+
body = _jsx(FeedTab, { dash: dash, isActive: isRawModeSupported === true });
|
|
180
|
+
}
|
|
181
|
+
return (
|
|
182
|
+
// height-pinned to the terminal so the frame is a CONSTANT size across views —
|
|
183
|
+
// ink repaints in place instead of emitting a taller/shorter frame that scrolls.
|
|
184
|
+
_jsxs(Box, { flexDirection: "column", paddingX: 1, height: rows, overflow: "hidden", children: [_jsxs(Box, { flexShrink: 0, justifyContent: "space-between", marginBottom: 1, children: [_jsxs(Box, { children: [_jsx(Brand, {}), _jsx(Box, { marginLeft: 3, children: _jsx(ViewBar, { views: VIEWS, active: active }) })] }), _jsx(Text, { color: theme.dim, children: `v${VERSION}` })] }), _jsx(Box, { flexDirection: "column", flexGrow: 1, overflow: "hidden", children: body }), _jsx(Box, { flexShrink: 0, marginTop: 1, children: _jsx(StatusLine, { dash: dash, balance: balance, captureDots: captureDots }) })] }));
|
|
185
|
+
}
|