@ashlr/hub 2.2.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/CHANGELOG.md +1158 -0
- package/LICENSE +21 -0
- package/README.md +833 -0
- package/bin/ashlr +8 -0
- package/dist/api/core.d.ts +28 -0
- package/dist/api/core.js +42 -0
- package/dist/api/core.js.map +1 -0
- package/dist/api/index.d.ts +9 -0
- package/dist/api/index.js +9 -0
- package/dist/api/index.js.map +1 -0
- package/dist/api/plugin.d.ts +12 -0
- package/dist/api/plugin.js +13 -0
- package/dist/api/plugin.js.map +1 -0
- package/dist/api/types.d.ts +9 -0
- package/dist/api/types.js +9 -0
- package/dist/api/types.js.map +1 -0
- package/dist/cli/args.d.ts +20 -0
- package/dist/cli/args.js +23 -0
- package/dist/cli/args.js.map +1 -0
- package/dist/cli/ask.d.ts +22 -0
- package/dist/cli/ask.js +240 -0
- package/dist/cli/ask.js.map +1 -0
- package/dist/cli/audit.d.ts +26 -0
- package/dist/cli/audit.js +199 -0
- package/dist/cli/audit.js.map +1 -0
- package/dist/cli/backlog.d.ts +26 -0
- package/dist/cli/backlog.js +322 -0
- package/dist/cli/backlog.js.map +1 -0
- package/dist/cli/completions.d.ts +18 -0
- package/dist/cli/completions.js +156 -0
- package/dist/cli/completions.js.map +1 -0
- package/dist/cli/daemon.d.ts +31 -0
- package/dist/cli/daemon.js +334 -0
- package/dist/cli/daemon.js.map +1 -0
- package/dist/cli/demo-sandbox.d.ts +78 -0
- package/dist/cli/demo-sandbox.js +227 -0
- package/dist/cli/demo-sandbox.js.map +1 -0
- package/dist/cli/demo.d.ts +76 -0
- package/dist/cli/demo.js +285 -0
- package/dist/cli/demo.js.map +1 -0
- package/dist/cli/digest.d.ts +46 -0
- package/dist/cli/digest.js +352 -0
- package/dist/cli/digest.js.map +1 -0
- package/dist/cli/doctor-init.d.ts +28 -0
- package/dist/cli/doctor-init.js +335 -0
- package/dist/cli/doctor-init.js.map +1 -0
- package/dist/cli/genome.d.ts +62 -0
- package/dist/cli/genome.js +1061 -0
- package/dist/cli/genome.js.map +1 -0
- package/dist/cli/gh.d.ts +27 -0
- package/dist/cli/gh.js +322 -0
- package/dist/cli/gh.js.map +1 -0
- package/dist/cli/goals.d.ts +55 -0
- package/dist/cli/goals.js +667 -0
- package/dist/cli/goals.js.map +1 -0
- package/dist/cli/health.d.ts +56 -0
- package/dist/cli/health.js +407 -0
- package/dist/cli/health.js.map +1 -0
- package/dist/cli/help.d.ts +51 -0
- package/dist/cli/help.js +436 -0
- package/dist/cli/help.js.map +1 -0
- package/dist/cli/inbox.d.ts +28 -0
- package/dist/cli/inbox.js +589 -0
- package/dist/cli/inbox.js.map +1 -0
- package/dist/cli/index.d.ts +41 -0
- package/dist/cli/index.js +1208 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/knowledge.d.ts +33 -0
- package/dist/cli/knowledge.js +575 -0
- package/dist/cli/knowledge.js.map +1 -0
- package/dist/cli/mcp.d.ts +26 -0
- package/dist/cli/mcp.js +487 -0
- package/dist/cli/mcp.js.map +1 -0
- package/dist/cli/models.d.ts +26 -0
- package/dist/cli/models.js +435 -0
- package/dist/cli/models.js.map +1 -0
- package/dist/cli/new.d.ts +32 -0
- package/dist/cli/new.js +565 -0
- package/dist/cli/new.js.map +1 -0
- package/dist/cli/notify.d.ts +20 -0
- package/dist/cli/notify.js +188 -0
- package/dist/cli/notify.js.map +1 -0
- package/dist/cli/onboard.d.ts +85 -0
- package/dist/cli/onboard.js +305 -0
- package/dist/cli/onboard.js.map +1 -0
- package/dist/cli/open.d.ts +38 -0
- package/dist/cli/open.js +86 -0
- package/dist/cli/open.js.map +1 -0
- package/dist/cli/orient.d.ts +14 -0
- package/dist/cli/orient.js +110 -0
- package/dist/cli/orient.js.map +1 -0
- package/dist/cli/picker.d.ts +21 -0
- package/dist/cli/picker.js +177 -0
- package/dist/cli/picker.js.map +1 -0
- package/dist/cli/plugins.d.ts +21 -0
- package/dist/cli/plugins.js +394 -0
- package/dist/cli/plugins.js.map +1 -0
- package/dist/cli/preflight.d.ts +29 -0
- package/dist/cli/preflight.js +131 -0
- package/dist/cli/preflight.js.map +1 -0
- package/dist/cli/pulse.d.ts +26 -0
- package/dist/cli/pulse.js +482 -0
- package/dist/cli/pulse.js.map +1 -0
- package/dist/cli/reflect.d.ts +42 -0
- package/dist/cli/reflect.js +381 -0
- package/dist/cli/reflect.js.map +1 -0
- package/dist/cli/run.d.ts +29 -0
- package/dist/cli/run.js +687 -0
- package/dist/cli/run.js.map +1 -0
- package/dist/cli/sandbox.d.ts +20 -0
- package/dist/cli/sandbox.js +345 -0
- package/dist/cli/sandbox.js.map +1 -0
- package/dist/cli/seams.d.ts +41 -0
- package/dist/cli/seams.js +167 -0
- package/dist/cli/seams.js.map +1 -0
- package/dist/cli/serve.d.ts +25 -0
- package/dist/cli/serve.js +249 -0
- package/dist/cli/serve.js.map +1 -0
- package/dist/cli/ship.d.ts +33 -0
- package/dist/cli/ship.js +433 -0
- package/dist/cli/ship.js.map +1 -0
- package/dist/cli/spec.d.ts +19 -0
- package/dist/cli/spec.js +478 -0
- package/dist/cli/spec.js.map +1 -0
- package/dist/cli/swarm.d.ts +42 -0
- package/dist/cli/swarm.js +1365 -0
- package/dist/cli/swarm.js.map +1 -0
- package/dist/cli/telemetry.d.ts +26 -0
- package/dist/cli/telemetry.js +364 -0
- package/dist/cli/telemetry.js.map +1 -0
- package/dist/cli/tui.d.ts +17 -0
- package/dist/cli/tui.js +52 -0
- package/dist/cli/tui.js.map +1 -0
- package/dist/cli/ui.d.ts +53 -0
- package/dist/cli/ui.js +66 -0
- package/dist/cli/ui.js.map +1 -0
- package/dist/cli/update.d.ts +38 -0
- package/dist/cli/update.js +682 -0
- package/dist/cli/update.js.map +1 -0
- package/dist/cli/vercel.d.ts +20 -0
- package/dist/cli/vercel.js +193 -0
- package/dist/cli/vercel.js.map +1 -0
- package/dist/cli/verify-safety.d.ts +96 -0
- package/dist/cli/verify-safety.js +509 -0
- package/dist/cli/verify-safety.js.map +1 -0
- package/dist/cli/wire.d.ts +22 -0
- package/dist/cli/wire.js +205 -0
- package/dist/cli/wire.js.map +1 -0
- package/dist/core/classify.d.ts +51 -0
- package/dist/core/classify.js +450 -0
- package/dist/core/classify.js.map +1 -0
- package/dist/core/config.d.ts +63 -0
- package/dist/core/config.js +474 -0
- package/dist/core/config.js.map +1 -0
- package/dist/core/daemon/loop.d.ts +74 -0
- package/dist/core/daemon/loop.js +618 -0
- package/dist/core/daemon/loop.js.map +1 -0
- package/dist/core/daemon/state.d.ts +66 -0
- package/dist/core/daemon/state.js +197 -0
- package/dist/core/daemon/state.js.map +1 -0
- package/dist/core/dashboard.d.ts +40 -0
- package/dist/core/dashboard.js +463 -0
- package/dist/core/dashboard.js.map +1 -0
- package/dist/core/digest/build.d.ts +51 -0
- package/dist/core/digest/build.js +230 -0
- package/dist/core/digest/build.js.map +1 -0
- package/dist/core/digest/deliver.d.ts +47 -0
- package/dist/core/digest/deliver.js +230 -0
- package/dist/core/digest/deliver.js.map +1 -0
- package/dist/core/digest/store.d.ts +57 -0
- package/dist/core/digest/store.js +223 -0
- package/dist/core/digest/store.js.map +1 -0
- package/dist/core/doctor-fix.d.ts +21 -0
- package/dist/core/doctor-fix.js +440 -0
- package/dist/core/doctor-fix.js.map +1 -0
- package/dist/core/doctor.d.ts +18 -0
- package/dist/core/doctor.js +806 -0
- package/dist/core/doctor.js.map +1 -0
- package/dist/core/env-bridge.d.ts +64 -0
- package/dist/core/env-bridge.js +103 -0
- package/dist/core/env-bridge.js.map +1 -0
- package/dist/core/genome/capture.d.ts +49 -0
- package/dist/core/genome/capture.js +352 -0
- package/dist/core/genome/capture.js.map +1 -0
- package/dist/core/genome/consolidate.d.ts +38 -0
- package/dist/core/genome/consolidate.js +426 -0
- package/dist/core/genome/consolidate.js.map +1 -0
- package/dist/core/genome/export.d.ts +29 -0
- package/dist/core/genome/export.js +102 -0
- package/dist/core/genome/export.js.map +1 -0
- package/dist/core/genome/playbook.d.ts +33 -0
- package/dist/core/genome/playbook.js +320 -0
- package/dist/core/genome/playbook.js.map +1 -0
- package/dist/core/genome/recall.d.ts +45 -0
- package/dist/core/genome/recall.js +293 -0
- package/dist/core/genome/recall.js.map +1 -0
- package/dist/core/genome/store.d.ts +62 -0
- package/dist/core/genome/store.js +711 -0
- package/dist/core/genome/store.js.map +1 -0
- package/dist/core/git.d.ts +34 -0
- package/dist/core/git.js +115 -0
- package/dist/core/git.js.map +1 -0
- package/dist/core/goals/advance.d.ts +82 -0
- package/dist/core/goals/advance.js +263 -0
- package/dist/core/goals/advance.js.map +1 -0
- package/dist/core/goals/planner.d.ts +58 -0
- package/dist/core/goals/planner.js +233 -0
- package/dist/core/goals/planner.js.map +1 -0
- package/dist/core/goals/store.d.ts +128 -0
- package/dist/core/goals/store.js +442 -0
- package/dist/core/goals/store.js.map +1 -0
- package/dist/core/inbox/apply.d.ts +36 -0
- package/dist/core/inbox/apply.js +407 -0
- package/dist/core/inbox/apply.js.map +1 -0
- package/dist/core/inbox/notify-proposal.d.ts +13 -0
- package/dist/core/inbox/notify-proposal.js +21 -0
- package/dist/core/inbox/notify-proposal.js.map +1 -0
- package/dist/core/inbox/store.d.ts +67 -0
- package/dist/core/inbox/store.js +258 -0
- package/dist/core/inbox/store.js.map +1 -0
- package/dist/core/index-engine.d.ts +62 -0
- package/dist/core/index-engine.js +486 -0
- package/dist/core/index-engine.js.map +1 -0
- package/dist/core/integrations/desktop-notify.d.ts +18 -0
- package/dist/core/integrations/desktop-notify.js +42 -0
- package/dist/core/integrations/desktop-notify.js.map +1 -0
- package/dist/core/integrations/editors.d.ts +50 -0
- package/dist/core/integrations/editors.js +216 -0
- package/dist/core/integrations/editors.js.map +1 -0
- package/dist/core/integrations/github.d.ts +66 -0
- package/dist/core/integrations/github.js +332 -0
- package/dist/core/integrations/github.js.map +1 -0
- package/dist/core/integrations/identity.d.ts +29 -0
- package/dist/core/integrations/identity.js +359 -0
- package/dist/core/integrations/identity.js.map +1 -0
- package/dist/core/integrations/notify.d.ts +23 -0
- package/dist/core/integrations/notify.js +96 -0
- package/dist/core/integrations/notify.js.map +1 -0
- package/dist/core/integrations/vercel.d.ts +37 -0
- package/dist/core/integrations/vercel.js +192 -0
- package/dist/core/integrations/vercel.js.map +1 -0
- package/dist/core/knowledge/ask.d.ts +34 -0
- package/dist/core/knowledge/ask.js +325 -0
- package/dist/core/knowledge/ask.js.map +1 -0
- package/dist/core/knowledge/graph.d.ts +51 -0
- package/dist/core/knowledge/graph.js +564 -0
- package/dist/core/knowledge/graph.js.map +1 -0
- package/dist/core/knowledge/index.d.ts +74 -0
- package/dist/core/knowledge/index.js +586 -0
- package/dist/core/knowledge/index.js.map +1 -0
- package/dist/core/learn/playbooks.d.ts +84 -0
- package/dist/core/learn/playbooks.js +241 -0
- package/dist/core/learn/playbooks.js.map +1 -0
- package/dist/core/learn/reflect.d.ts +87 -0
- package/dist/core/learn/reflect.js +435 -0
- package/dist/core/learn/reflect.js.map +1 -0
- package/dist/core/learn/store.d.ts +51 -0
- package/dist/core/learn/store.js +165 -0
- package/dist/core/learn/store.js.map +1 -0
- package/dist/core/learn/tuning.d.ts +48 -0
- package/dist/core/learn/tuning.js +201 -0
- package/dist/core/learn/tuning.js.map +1 -0
- package/dist/core/lifecycle/scaffold.d.ts +43 -0
- package/dist/core/lifecycle/scaffold.js +260 -0
- package/dist/core/lifecycle/scaffold.js.map +1 -0
- package/dist/core/lifecycle/ship.d.ts +48 -0
- package/dist/core/lifecycle/ship.js +513 -0
- package/dist/core/lifecycle/ship.js.map +1 -0
- package/dist/core/lifecycle/templates.d.ts +20 -0
- package/dist/core/lifecycle/templates.js +605 -0
- package/dist/core/lifecycle/templates.js.map +1 -0
- package/dist/core/mcp-gateway.d.ts +59 -0
- package/dist/core/mcp-gateway.js +385 -0
- package/dist/core/mcp-gateway.js.map +1 -0
- package/dist/core/mcp-native.d.ts +53 -0
- package/dist/core/mcp-native.js +507 -0
- package/dist/core/mcp-native.js.map +1 -0
- package/dist/core/mcp-registry.d.ts +36 -0
- package/dist/core/mcp-registry.js +180 -0
- package/dist/core/mcp-registry.js.map +1 -0
- package/dist/core/observability/budget-alert.d.ts +18 -0
- package/dist/core/observability/budget-alert.js +90 -0
- package/dist/core/observability/budget-alert.js.map +1 -0
- package/dist/core/observability/estimate.d.ts +27 -0
- package/dist/core/observability/estimate.js +188 -0
- package/dist/core/observability/estimate.js.map +1 -0
- package/dist/core/observability/forecast.d.ts +19 -0
- package/dist/core/observability/forecast.js +101 -0
- package/dist/core/observability/forecast.js.map +1 -0
- package/dist/core/observability/governance.d.ts +28 -0
- package/dist/core/observability/governance.js +101 -0
- package/dist/core/observability/governance.js.map +1 -0
- package/dist/core/observability/otlp.d.ts +88 -0
- package/dist/core/observability/otlp.js +217 -0
- package/dist/core/observability/otlp.js.map +1 -0
- package/dist/core/observability/rollup.d.ts +35 -0
- package/dist/core/observability/rollup.js +311 -0
- package/dist/core/observability/rollup.js.map +1 -0
- package/dist/core/observability/telemetry-sink.d.ts +63 -0
- package/dist/core/observability/telemetry-sink.js +350 -0
- package/dist/core/observability/telemetry-sink.js.map +1 -0
- package/dist/core/observability/usage-source.d.ts +60 -0
- package/dist/core/observability/usage-source.js +347 -0
- package/dist/core/observability/usage-source.js.map +1 -0
- package/dist/core/onboard.d.ts +27 -0
- package/dist/core/onboard.js +288 -0
- package/dist/core/onboard.js.map +1 -0
- package/dist/core/orient.d.ts +23 -0
- package/dist/core/orient.js +135 -0
- package/dist/core/orient.js.map +1 -0
- package/dist/core/phantom.d.ts +23 -0
- package/dist/core/phantom.js +279 -0
- package/dist/core/phantom.js.map +1 -0
- package/dist/core/plugins/host-api.d.ts +29 -0
- package/dist/core/plugins/host-api.js +113 -0
- package/dist/core/plugins/host-api.js.map +1 -0
- package/dist/core/plugins/integrity.d.ts +36 -0
- package/dist/core/plugins/integrity.js +73 -0
- package/dist/core/plugins/integrity.js.map +1 -0
- package/dist/core/plugins/manifest.d.ts +31 -0
- package/dist/core/plugins/manifest.js +316 -0
- package/dist/core/plugins/manifest.js.map +1 -0
- package/dist/core/plugins/registry.d.ts +87 -0
- package/dist/core/plugins/registry.js +415 -0
- package/dist/core/plugins/registry.js.map +1 -0
- package/dist/core/plugins/types.d.ts +182 -0
- package/dist/core/plugins/types.js +40 -0
- package/dist/core/plugins/types.js.map +1 -0
- package/dist/core/plugins/wrappers.d.ts +40 -0
- package/dist/core/plugins/wrappers.js +229 -0
- package/dist/core/plugins/wrappers.js.map +1 -0
- package/dist/core/portfolio/backlog.d.ts +40 -0
- package/dist/core/portfolio/backlog.js +177 -0
- package/dist/core/portfolio/backlog.js.map +1 -0
- package/dist/core/portfolio/scanners.d.ts +21 -0
- package/dist/core/portfolio/scanners.js +600 -0
- package/dist/core/portfolio/scanners.js.map +1 -0
- package/dist/core/providers.d.ts +34 -0
- package/dist/core/providers.js +250 -0
- package/dist/core/providers.js.map +1 -0
- package/dist/core/quality/conventions.d.ts +35 -0
- package/dist/core/quality/conventions.js +267 -0
- package/dist/core/quality/conventions.js.map +1 -0
- package/dist/core/quality/fixes.d.ts +56 -0
- package/dist/core/quality/fixes.js +209 -0
- package/dist/core/quality/fixes.js.map +1 -0
- package/dist/core/quality/health.d.ts +69 -0
- package/dist/core/quality/health.js +350 -0
- package/dist/core/quality/health.js.map +1 -0
- package/dist/core/quality/store.d.ts +56 -0
- package/dist/core/quality/store.js +195 -0
- package/dist/core/quality/store.js.map +1 -0
- package/dist/core/readiness.d.ts +112 -0
- package/dist/core/readiness.js +431 -0
- package/dist/core/readiness.js.map +1 -0
- package/dist/core/run/agent-loop.d.ts +40 -0
- package/dist/core/run/agent-loop.js +291 -0
- package/dist/core/run/agent-loop.js.map +1 -0
- package/dist/core/run/budget.d.ts +47 -0
- package/dist/core/run/budget.js +113 -0
- package/dist/core/run/budget.js.map +1 -0
- package/dist/core/run/engines.d.ts +75 -0
- package/dist/core/run/engines.js +199 -0
- package/dist/core/run/engines.js.map +1 -0
- package/dist/core/run/model-manager.d.ts +64 -0
- package/dist/core/run/model-manager.js +339 -0
- package/dist/core/run/model-manager.js.map +1 -0
- package/dist/core/run/orchestrator.d.ts +100 -0
- package/dist/core/run/orchestrator.js +1515 -0
- package/dist/core/run/orchestrator.js.map +1 -0
- package/dist/core/run/provider-client.d.ts +46 -0
- package/dist/core/run/provider-client.js +796 -0
- package/dist/core/run/provider-client.js.map +1 -0
- package/dist/core/run/retry.d.ts +19 -0
- package/dist/core/run/retry.js +68 -0
- package/dist/core/run/retry.js.map +1 -0
- package/dist/core/run/router.d.ts +50 -0
- package/dist/core/run/router.js +257 -0
- package/dist/core/run/router.js.map +1 -0
- package/dist/core/run/self-heal.d.ts +52 -0
- package/dist/core/run/self-heal.js +181 -0
- package/dist/core/run/self-heal.js.map +1 -0
- package/dist/core/run/streaming.d.ts +31 -0
- package/dist/core/run/streaming.js +122 -0
- package/dist/core/run/streaming.js.map +1 -0
- package/dist/core/run/verify.d.ts +30 -0
- package/dist/core/run/verify.js +204 -0
- package/dist/core/run/verify.js.map +1 -0
- package/dist/core/sandbox/audit.d.ts +31 -0
- package/dist/core/sandbox/audit.js +169 -0
- package/dist/core/sandbox/audit.js.map +1 -0
- package/dist/core/sandbox/policy.d.ts +61 -0
- package/dist/core/sandbox/policy.js +211 -0
- package/dist/core/sandbox/policy.js.map +1 -0
- package/dist/core/sandbox/worktree.d.ts +175 -0
- package/dist/core/sandbox/worktree.js +673 -0
- package/dist/core/sandbox/worktree.js.map +1 -0
- package/dist/core/seams/backlog.d.ts +47 -0
- package/dist/core/seams/backlog.js +47 -0
- package/dist/core/seams/backlog.js.map +1 -0
- package/dist/core/seams/daemon-coordinator.d.ts +72 -0
- package/dist/core/seams/daemon-coordinator.js +76 -0
- package/dist/core/seams/daemon-coordinator.js.map +1 -0
- package/dist/core/seams/genome.d.ts +45 -0
- package/dist/core/seams/genome.js +53 -0
- package/dist/core/seams/genome.js.map +1 -0
- package/dist/core/seams/identity.d.ts +40 -0
- package/dist/core/seams/identity.js +44 -0
- package/dist/core/seams/identity.js.map +1 -0
- package/dist/core/seams/inbox.d.ts +60 -0
- package/dist/core/seams/inbox.js +66 -0
- package/dist/core/seams/inbox.js.map +1 -0
- package/dist/core/seams/index.d.ts +20 -0
- package/dist/core/seams/index.js +21 -0
- package/dist/core/seams/index.js.map +1 -0
- package/dist/core/seams/portfolio.d.ts +50 -0
- package/dist/core/seams/portfolio.js +61 -0
- package/dist/core/seams/portfolio.js.map +1 -0
- package/dist/core/seams/registry.d.ts +42 -0
- package/dist/core/seams/registry.js +128 -0
- package/dist/core/seams/registry.js.map +1 -0
- package/dist/core/seams/run-swarm.d.ts +66 -0
- package/dist/core/seams/run-swarm.js +74 -0
- package/dist/core/seams/run-swarm.js.map +1 -0
- package/dist/core/seams/types.d.ts +123 -0
- package/dist/core/seams/types.js +35 -0
- package/dist/core/seams/types.js.map +1 -0
- package/dist/core/spec/spec-store.d.ts +62 -0
- package/dist/core/spec/spec-store.js +359 -0
- package/dist/core/spec/spec-store.js.map +1 -0
- package/dist/core/swarm/gate.d.ts +45 -0
- package/dist/core/swarm/gate.js +114 -0
- package/dist/core/swarm/gate.js.map +1 -0
- package/dist/core/swarm/planner.d.ts +32 -0
- package/dist/core/swarm/planner.js +293 -0
- package/dist/core/swarm/planner.js.map +1 -0
- package/dist/core/swarm/rollback.d.ts +56 -0
- package/dist/core/swarm/rollback.js +266 -0
- package/dist/core/swarm/rollback.js.map +1 -0
- package/dist/core/swarm/runner.d.ts +62 -0
- package/dist/core/swarm/runner.js +1263 -0
- package/dist/core/swarm/runner.js.map +1 -0
- package/dist/core/swarm/sign.d.ts +71 -0
- package/dist/core/swarm/sign.js +362 -0
- package/dist/core/swarm/sign.js.map +1 -0
- package/dist/core/swarm/store.d.ts +52 -0
- package/dist/core/swarm/store.js +195 -0
- package/dist/core/swarm/store.js.map +1 -0
- package/dist/core/tidy.d.ts +32 -0
- package/dist/core/tidy.js +354 -0
- package/dist/core/tidy.js.map +1 -0
- package/dist/core/tools-registry.d.ts +16 -0
- package/dist/core/tools-registry.js +308 -0
- package/dist/core/tools-registry.js.map +1 -0
- package/dist/core/types.d.ts +2545 -0
- package/dist/core/types.js +9 -0
- package/dist/core/types.js.map +1 -0
- package/dist/core/web/api.d.ts +53 -0
- package/dist/core/web/api.js +698 -0
- package/dist/core/web/api.js.map +1 -0
- package/dist/core/web/public/app.js +1906 -0
- package/dist/core/web/public/index.html +721 -0
- package/dist/core/web/public/styles.css +2007 -0
- package/dist/core/web/server.d.ts +18 -0
- package/dist/core/web/server.js +122 -0
- package/dist/core/web/server.js.map +1 -0
- package/dist/core/web/static.d.ts +18 -0
- package/dist/core/web/static.js +122 -0
- package/dist/core/web/static.js.map +1 -0
- package/dist/tui/app.d.ts +33 -0
- package/dist/tui/app.js +350 -0
- package/dist/tui/app.js.map +1 -0
- package/dist/tui/render.d.ts +20 -0
- package/dist/tui/render.js +558 -0
- package/dist/tui/render.js.map +1 -0
- package/package.json +80 -0
- package/schema/config.schema.json +223 -0
|
@@ -0,0 +1,586 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* knowledge/index.ts — Portfolio Knowledge Index (M25)
|
|
3
|
+
*
|
|
4
|
+
* INVARIANTS (non-negotiable):
|
|
5
|
+
* 1. LOCAL-ONLY: embeddings run against local Ollama only. Never send chunks
|
|
6
|
+
* to a cloud endpoint — this file has no allowCloud path at all.
|
|
7
|
+
* 2. READ-ONLY: never mutates any enrolled repo. Writes go to knowledgeDir()
|
|
8
|
+
* only (~/.ashlr/knowledge/<repo-hash>/).
|
|
9
|
+
* 3. ENROLLMENT-SCOPED: default repo set is listEnrolled() (DEFAULT EMPTY →
|
|
10
|
+
* returns {repos:0, chunks:0}; never scans arbitrary paths).
|
|
11
|
+
* 4. BOUNDED: caps file count, total bytes read, and wall-clock time per repo;
|
|
12
|
+
* skips node_modules / .git / dist / build / binaries / lockfiles.
|
|
13
|
+
* 5. NO SECRETS: skips .env* / *.pem / *.key / *.p12 files outright; scrubs
|
|
14
|
+
* secret-shaped tokens from chunk text before storing or embedding.
|
|
15
|
+
* 6. INCREMENTAL: re-indexes only files whose mtime > last index timestamp.
|
|
16
|
+
* Never throws — all errors are silently swallowed per the contract.
|
|
17
|
+
*/
|
|
18
|
+
import fs from 'node:fs';
|
|
19
|
+
import path from 'node:path';
|
|
20
|
+
import crypto from 'node:crypto';
|
|
21
|
+
import { homedir } from 'node:os';
|
|
22
|
+
import { listEnrolled, isEnrolled } from '../sandbox/policy.js';
|
|
23
|
+
// ---------------------------------------------------------------------------
|
|
24
|
+
// Constants — bounds to keep indexing fast and private
|
|
25
|
+
// ---------------------------------------------------------------------------
|
|
26
|
+
/** Max source files to index per repo per run. */
|
|
27
|
+
const MAX_FILES_PER_REPO = 500;
|
|
28
|
+
/** Max bytes to read from a single file (512 KB). */
|
|
29
|
+
const MAX_FILE_BYTES = 512 * 1024;
|
|
30
|
+
/** Max total bytes read across all files in one repo (32 MB). */
|
|
31
|
+
const MAX_REPO_BYTES = 32 * 1024 * 1024;
|
|
32
|
+
/** Wall-clock budget per repo in ms (60 s). */
|
|
33
|
+
const REPO_BUDGET_MS = 60_000;
|
|
34
|
+
/** Lines per chunk (target: 80–120). */
|
|
35
|
+
const CHUNK_LINES = 100;
|
|
36
|
+
/** Max text length sent to Ollama for embedding (chars). */
|
|
37
|
+
const EMBED_TEXT_LIMIT = 2000;
|
|
38
|
+
/** Timeout for a single Ollama embedding request (ms). */
|
|
39
|
+
const EMBED_TIMEOUT_MS = 10_000;
|
|
40
|
+
// ---------------------------------------------------------------------------
|
|
41
|
+
// Skip lists
|
|
42
|
+
// ---------------------------------------------------------------------------
|
|
43
|
+
/** Directory names to never descend into. */
|
|
44
|
+
const SKIP_DIRS = new Set([
|
|
45
|
+
'node_modules', '.git', 'dist', 'build', '.next', '.turbo',
|
|
46
|
+
'coverage', '__pycache__', '.cache', 'vendor', 'out', '.output',
|
|
47
|
+
'.vercel', '.serverless', 'target', 'pkg', '.yarn',
|
|
48
|
+
]);
|
|
49
|
+
/** File extensions treated as binary / non-text. */
|
|
50
|
+
const BINARY_EXTS = new Set([
|
|
51
|
+
'.png', '.jpg', '.jpeg', '.gif', '.webp', '.svg', '.ico',
|
|
52
|
+
'.mp4', '.mp3', '.wav', '.ogg', '.mov', '.avi',
|
|
53
|
+
'.pdf', '.zip', '.tar', '.gz', '.bz2', '.7z', '.rar',
|
|
54
|
+
'.wasm', '.exe', '.dylib', '.so', '.dll', '.a', '.o',
|
|
55
|
+
'.ttf', '.otf', '.woff', '.woff2', '.eot',
|
|
56
|
+
'.db', '.sqlite', '.sqlite3',
|
|
57
|
+
'.bin', '.dat',
|
|
58
|
+
]);
|
|
59
|
+
/** Filenames / patterns that always contain secrets — skip entirely. */
|
|
60
|
+
const SECRET_FILENAME_RE = /^\.env(\.|$)|\.pem$|\.key$|\.p12$|\.pfx$|\.crt$|id_rsa|id_ed25519|\.tfvars$/i;
|
|
61
|
+
/**
|
|
62
|
+
* Secret-bearing basenames to skip outright. Mirrors graph.ts SECRET_FILES so
|
|
63
|
+
* the index (which STORES + EMBEDS chunk text) never reads structured/low-entropy
|
|
64
|
+
* secrets that token-shaped scrubbing would miss (e.g. {"password":"hunter2"},
|
|
65
|
+
* .npmrc _authToken=…, service-account.json). Kept in sync with graph.ts.
|
|
66
|
+
*/
|
|
67
|
+
const SECRET_FILES = new Set([
|
|
68
|
+
'.env', '.env.local', '.env.production', '.env.development', '.env.test',
|
|
69
|
+
'.env.staging', '.envrc',
|
|
70
|
+
'credentials.json', 'secrets.json', 'secret.json',
|
|
71
|
+
'id_rsa', 'id_ed25519', 'id_ecdsa', 'id_dsa',
|
|
72
|
+
'.npmrc', '.netrc',
|
|
73
|
+
'service-account.json', 'serviceaccount.json',
|
|
74
|
+
]);
|
|
75
|
+
/** Lockfile basenames — skip (large + not useful for RAG). */
|
|
76
|
+
const LOCKFILE_NAMES = new Set([
|
|
77
|
+
'package-lock.json', 'yarn.lock', 'pnpm-lock.yaml',
|
|
78
|
+
'Cargo.lock', 'Gemfile.lock', 'poetry.lock', 'go.sum',
|
|
79
|
+
'composer.lock', 'mix.lock',
|
|
80
|
+
]);
|
|
81
|
+
// ---------------------------------------------------------------------------
|
|
82
|
+
// Secret scrubbing
|
|
83
|
+
// ---------------------------------------------------------------------------
|
|
84
|
+
/**
|
|
85
|
+
* Patterns for secret-shaped tokens: API keys, JWTs, long hex/base64 strings.
|
|
86
|
+
* Applied to chunk text before storing or embedding.
|
|
87
|
+
*
|
|
88
|
+
* EXPORTED (read-only) so the `ashlr verify-safety` self-check (H4) can run the
|
|
89
|
+
* REAL pattern set against a synthesized secret rather than a drifting private
|
|
90
|
+
* copy. Treat as a frozen constant — callers must never mutate it.
|
|
91
|
+
*/
|
|
92
|
+
export const SECRET_PATTERNS = [
|
|
93
|
+
// Generic "key = <value>" assignments with high-entropy values
|
|
94
|
+
/\b(api[_-]?key|secret[_-]?key|access[_-]?token|auth[_-]?token|private[_-]?key|client[_-]?secret)\s*[:=]\s*["']?[A-Za-z0-9+/=_-]{20,}["']?/gi,
|
|
95
|
+
// password / passwd / pwd / connection-string / _authToken assignments
|
|
96
|
+
// (covers structured/low-entropy secrets the high-entropy patterns miss)
|
|
97
|
+
/\b(password|passwd|pwd|connection[_-]?string|conn[_-]?str|_?auth[_-]?token)\s*[:=]\s*["']?[^\s"']{6,}["']?/gi,
|
|
98
|
+
// AWS-style access keys
|
|
99
|
+
/\b(AKIA|ASIA|AROA)[A-Z0-9]{16}\b/g,
|
|
100
|
+
// JWTs (three base64url segments separated by dots)
|
|
101
|
+
/\beyJ[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+\b/g,
|
|
102
|
+
// Long hex strings (≥32 chars) — likely tokens/hashes used as secrets
|
|
103
|
+
/\b[0-9a-f]{32,}\b/gi,
|
|
104
|
+
// Long base64 strings (≥40 chars, not in comments/imports)
|
|
105
|
+
/(?<![/\w])[A-Za-z0-9+/]{40,}={0,2}(?![/\w])/g,
|
|
106
|
+
// H6 (PART B.2): bare Stripe secret keys (sk_live_… / sk_test_…). The
|
|
107
|
+
// underscores in `sk_live_…` break the base64 char class + the \w boundary
|
|
108
|
+
// of the high-entropy patterns above, so this shape was MISSED before H6
|
|
109
|
+
// (the H4 finding). This grows the array 6 -> 7; verify-safety pins
|
|
110
|
+
// length >= 6, so it stays GREEN. See docs/contracts/CONTRACT-H6.md §B.2 + the deliberate H4
|
|
111
|
+
// assertion flip §B.4.
|
|
112
|
+
/\bsk_(live|test)_[A-Za-z0-9_]{16,}\b/g,
|
|
113
|
+
];
|
|
114
|
+
/**
|
|
115
|
+
* Scrub secret-shaped tokens from a chunk of text. Returns sanitized text.
|
|
116
|
+
*
|
|
117
|
+
* EXPORTED (pure, read-only) so the H4 `ashlr verify-safety` self-check can
|
|
118
|
+
* invoke the REAL redaction function — not a copy — against a synthesized
|
|
119
|
+
* secret, so any weakening of the function body (or its pattern set) is caught.
|
|
120
|
+
*/
|
|
121
|
+
export function scrubSecrets(text) {
|
|
122
|
+
let out = text;
|
|
123
|
+
for (const pattern of SECRET_PATTERNS) {
|
|
124
|
+
out = out.replace(pattern, '[REDACTED]');
|
|
125
|
+
}
|
|
126
|
+
return out;
|
|
127
|
+
}
|
|
128
|
+
// ---------------------------------------------------------------------------
|
|
129
|
+
// Path helpers
|
|
130
|
+
// ---------------------------------------------------------------------------
|
|
131
|
+
/** Root on-disk directory for the knowledge index: ~/.ashlr/knowledge */
|
|
132
|
+
export function knowledgeDir() {
|
|
133
|
+
return path.join(homedir(), '.ashlr', 'knowledge');
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* Derive a stable short hash for a repo path.
|
|
137
|
+
* Normalizes to an absolute path first so the write path (listEnrolled()
|
|
138
|
+
* absolute paths) and the read path (`loadChunks('./app')`, trailing slash, etc.)
|
|
139
|
+
* always hash to the same directory.
|
|
140
|
+
* Used as the sub-directory name under knowledgeDir().
|
|
141
|
+
*/
|
|
142
|
+
function repoHash(repoPath) {
|
|
143
|
+
const abs = path.resolve(repoPath);
|
|
144
|
+
return crypto.createHash('sha1').update(abs).digest('hex').slice(0, 16);
|
|
145
|
+
}
|
|
146
|
+
/** Path to the JSONL chunks file for a given repo. */
|
|
147
|
+
function chunksFile(repoPath) {
|
|
148
|
+
return path.join(knowledgeDir(), repoHash(repoPath), 'chunks.jsonl');
|
|
149
|
+
}
|
|
150
|
+
/** Path to the metadata file for a given repo (stores last index timestamp). */
|
|
151
|
+
function metaFile(repoPath) {
|
|
152
|
+
return path.join(knowledgeDir(), repoHash(repoPath), 'meta.json');
|
|
153
|
+
}
|
|
154
|
+
function readMeta(repoPath) {
|
|
155
|
+
try {
|
|
156
|
+
const raw = fs.readFileSync(metaFile(repoPath), 'utf8');
|
|
157
|
+
const parsed = JSON.parse(raw);
|
|
158
|
+
if (typeof parsed === 'object' &&
|
|
159
|
+
parsed !== null &&
|
|
160
|
+
typeof parsed['lastIndexedAt'] === 'number') {
|
|
161
|
+
return parsed;
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
catch {
|
|
165
|
+
// absent or malformed
|
|
166
|
+
}
|
|
167
|
+
return null;
|
|
168
|
+
}
|
|
169
|
+
function writeMeta(repoPath, meta) {
|
|
170
|
+
try {
|
|
171
|
+
const dir = path.dirname(metaFile(repoPath));
|
|
172
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
173
|
+
fs.writeFileSync(metaFile(repoPath), JSON.stringify(meta, null, 2), 'utf8');
|
|
174
|
+
}
|
|
175
|
+
catch {
|
|
176
|
+
// best-effort
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
// ---------------------------------------------------------------------------
|
|
180
|
+
// File walk
|
|
181
|
+
// ---------------------------------------------------------------------------
|
|
182
|
+
/**
|
|
183
|
+
* Collect all indexable source file paths under a repo directory.
|
|
184
|
+
* Bounded by MAX_FILES_PER_REPO. Read-only — never modifies anything.
|
|
185
|
+
*/
|
|
186
|
+
function collectFiles(repoPath) {
|
|
187
|
+
const results = [];
|
|
188
|
+
function walk(dir) {
|
|
189
|
+
if (results.length >= MAX_FILES_PER_REPO)
|
|
190
|
+
return;
|
|
191
|
+
let entries;
|
|
192
|
+
try {
|
|
193
|
+
entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
194
|
+
}
|
|
195
|
+
catch {
|
|
196
|
+
return;
|
|
197
|
+
}
|
|
198
|
+
for (const entry of entries) {
|
|
199
|
+
if (results.length >= MAX_FILES_PER_REPO)
|
|
200
|
+
break;
|
|
201
|
+
const name = entry.name;
|
|
202
|
+
// Skip symlinks entirely (files + dirs) so the walk can never escape the
|
|
203
|
+
// enrolled repo boundary via a symlink to ~, /etc, or another repo.
|
|
204
|
+
if (entry.isSymbolicLink())
|
|
205
|
+
continue;
|
|
206
|
+
// Skip hidden directories and known skip dirs
|
|
207
|
+
if (entry.isDirectory()) {
|
|
208
|
+
if (SKIP_DIRS.has(name) || name.startsWith('.'))
|
|
209
|
+
continue;
|
|
210
|
+
walk(path.join(dir, name));
|
|
211
|
+
continue;
|
|
212
|
+
}
|
|
213
|
+
if (!entry.isFile())
|
|
214
|
+
continue;
|
|
215
|
+
// Skip lockfiles
|
|
216
|
+
if (LOCKFILE_NAMES.has(name))
|
|
217
|
+
continue;
|
|
218
|
+
// Skip secret-named files (pattern + explicit basename set)
|
|
219
|
+
if (SECRET_FILENAME_RE.test(name))
|
|
220
|
+
continue;
|
|
221
|
+
if (SECRET_FILES.has(name))
|
|
222
|
+
continue;
|
|
223
|
+
// Skip binaries by extension
|
|
224
|
+
const ext = path.extname(name).toLowerCase();
|
|
225
|
+
if (BINARY_EXTS.has(ext))
|
|
226
|
+
continue;
|
|
227
|
+
results.push(path.join(dir, name));
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
walk(repoPath);
|
|
231
|
+
return results;
|
|
232
|
+
}
|
|
233
|
+
// ---------------------------------------------------------------------------
|
|
234
|
+
// Chunking
|
|
235
|
+
// ---------------------------------------------------------------------------
|
|
236
|
+
/**
|
|
237
|
+
* Split file text into chunks of ~CHUNK_LINES lines each.
|
|
238
|
+
* Returns an array of {startLine, endLine, text} objects (1-based lines).
|
|
239
|
+
*/
|
|
240
|
+
function chunkText(text) {
|
|
241
|
+
const lines = text.split('\n');
|
|
242
|
+
const chunks = [];
|
|
243
|
+
for (let i = 0; i < lines.length; i += CHUNK_LINES) {
|
|
244
|
+
const startLine = i + 1; // 1-based
|
|
245
|
+
const slice = lines.slice(i, i + CHUNK_LINES);
|
|
246
|
+
const endLine = startLine + slice.length - 1;
|
|
247
|
+
const chunkText = slice.join('\n').trim();
|
|
248
|
+
if (chunkText.length > 0) {
|
|
249
|
+
chunks.push({ startLine, endLine, text: chunkText });
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
return chunks;
|
|
253
|
+
}
|
|
254
|
+
// ---------------------------------------------------------------------------
|
|
255
|
+
// Local Ollama embedding (best-effort — never throws, never cloud)
|
|
256
|
+
// ---------------------------------------------------------------------------
|
|
257
|
+
/**
|
|
258
|
+
* Detect an embedding-capable model at the local Ollama base URL.
|
|
259
|
+
* Mirrors the approach in genome/recall.ts. Never throws.
|
|
260
|
+
*/
|
|
261
|
+
async function detectEmbeddingModel(ollamaBase) {
|
|
262
|
+
const controller = new AbortController();
|
|
263
|
+
const timer = setTimeout(() => controller.abort(), 3000);
|
|
264
|
+
try {
|
|
265
|
+
const res = await fetch(`${ollamaBase.replace(/\/+$/, '')}/api/tags`, {
|
|
266
|
+
signal: controller.signal,
|
|
267
|
+
headers: { Accept: 'application/json' },
|
|
268
|
+
});
|
|
269
|
+
if (!res.ok)
|
|
270
|
+
return { available: false };
|
|
271
|
+
const body = (await res.json());
|
|
272
|
+
if (typeof body !== 'object' ||
|
|
273
|
+
body === null ||
|
|
274
|
+
!Array.isArray(body['models'])) {
|
|
275
|
+
return { available: false };
|
|
276
|
+
}
|
|
277
|
+
const models = body.models;
|
|
278
|
+
const EMBED_HINTS = ['bge', 'nomic-embed', 'mxbai-embed', 'all-minilm', 'embed'];
|
|
279
|
+
for (const hint of EMBED_HINTS) {
|
|
280
|
+
const found = models.find((m) => m.name.toLowerCase().includes(hint));
|
|
281
|
+
if (found)
|
|
282
|
+
return { available: true, model: found.name };
|
|
283
|
+
}
|
|
284
|
+
return { available: false };
|
|
285
|
+
}
|
|
286
|
+
catch {
|
|
287
|
+
return { available: false };
|
|
288
|
+
}
|
|
289
|
+
finally {
|
|
290
|
+
clearTimeout(timer);
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
/**
|
|
294
|
+
* Fetch an embedding for `text` from local Ollama.
|
|
295
|
+
* Returns null on any error (network, model unavailable, timeout).
|
|
296
|
+
* NEVER sends to a cloud endpoint — only ever hits ollamaBase (localhost).
|
|
297
|
+
*/
|
|
298
|
+
async function fetchEmbedding(ollamaBase, model, text) {
|
|
299
|
+
const controller = new AbortController();
|
|
300
|
+
const timer = setTimeout(() => controller.abort(), EMBED_TIMEOUT_MS);
|
|
301
|
+
try {
|
|
302
|
+
const res = await fetch(`${ollamaBase.replace(/\/+$/, '')}/api/embeddings`, {
|
|
303
|
+
method: 'POST',
|
|
304
|
+
signal: controller.signal,
|
|
305
|
+
headers: { 'Content-Type': 'application/json' },
|
|
306
|
+
body: JSON.stringify({ model, prompt: text.slice(0, EMBED_TEXT_LIMIT) }),
|
|
307
|
+
});
|
|
308
|
+
if (!res.ok)
|
|
309
|
+
return null;
|
|
310
|
+
const body = (await res.json());
|
|
311
|
+
if (typeof body !== 'object' ||
|
|
312
|
+
body === null ||
|
|
313
|
+
!Array.isArray(body['embedding'])) {
|
|
314
|
+
return null;
|
|
315
|
+
}
|
|
316
|
+
const embedding = body.embedding;
|
|
317
|
+
if (!embedding.every((v) => typeof v === 'number'))
|
|
318
|
+
return null;
|
|
319
|
+
return embedding;
|
|
320
|
+
}
|
|
321
|
+
catch {
|
|
322
|
+
return null;
|
|
323
|
+
}
|
|
324
|
+
finally {
|
|
325
|
+
clearTimeout(timer);
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
// ---------------------------------------------------------------------------
|
|
329
|
+
// JSONL persistence
|
|
330
|
+
// ---------------------------------------------------------------------------
|
|
331
|
+
/** Overwrite the repo's JSONL file with the provided chunks. */
|
|
332
|
+
function writeChunks(repoPath, chunks) {
|
|
333
|
+
try {
|
|
334
|
+
const file = chunksFile(repoPath);
|
|
335
|
+
const dir = path.dirname(file);
|
|
336
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
337
|
+
if (chunks.length === 0) {
|
|
338
|
+
fs.writeFileSync(file, '', 'utf8');
|
|
339
|
+
return;
|
|
340
|
+
}
|
|
341
|
+
const lines = chunks.map((c) => JSON.stringify(c)).join('\n') + '\n';
|
|
342
|
+
fs.writeFileSync(file, lines, 'utf8');
|
|
343
|
+
}
|
|
344
|
+
catch {
|
|
345
|
+
// best-effort
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
// ---------------------------------------------------------------------------
|
|
349
|
+
// loadChunks — public API
|
|
350
|
+
// ---------------------------------------------------------------------------
|
|
351
|
+
/**
|
|
352
|
+
* Load persisted knowledge chunks, optionally scoped to one repo (absolute path).
|
|
353
|
+
* Returns [] when nothing is indexed or on any read error.
|
|
354
|
+
* NEVER scans repo source — reads only the persisted index under knowledgeDir().
|
|
355
|
+
*/
|
|
356
|
+
export function loadChunks(repo) {
|
|
357
|
+
const results = [];
|
|
358
|
+
if (repo !== undefined) {
|
|
359
|
+
// Scoped to a single repo
|
|
360
|
+
const file = chunksFile(repo);
|
|
361
|
+
return readChunksFile(file);
|
|
362
|
+
}
|
|
363
|
+
// All repos: enumerate sub-directories under knowledgeDir()
|
|
364
|
+
const root = knowledgeDir();
|
|
365
|
+
let entries;
|
|
366
|
+
try {
|
|
367
|
+
entries = fs.readdirSync(root, { withFileTypes: true });
|
|
368
|
+
}
|
|
369
|
+
catch {
|
|
370
|
+
return [];
|
|
371
|
+
}
|
|
372
|
+
for (const entry of entries) {
|
|
373
|
+
if (!entry.isDirectory())
|
|
374
|
+
continue;
|
|
375
|
+
const file = path.join(root, entry.name, 'chunks.jsonl');
|
|
376
|
+
const chunks = readChunksFile(file);
|
|
377
|
+
results.push(...chunks);
|
|
378
|
+
}
|
|
379
|
+
return results;
|
|
380
|
+
}
|
|
381
|
+
/** Parse a single JSONL chunks file. Returns [] on any error. */
|
|
382
|
+
function readChunksFile(file) {
|
|
383
|
+
const chunks = [];
|
|
384
|
+
try {
|
|
385
|
+
const raw = fs.readFileSync(file, 'utf8');
|
|
386
|
+
for (const line of raw.split('\n')) {
|
|
387
|
+
const trimmed = line.trim();
|
|
388
|
+
if (!trimmed)
|
|
389
|
+
continue;
|
|
390
|
+
try {
|
|
391
|
+
const parsed = JSON.parse(trimmed);
|
|
392
|
+
if (isKnowledgeChunk(parsed)) {
|
|
393
|
+
chunks.push(parsed);
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
catch {
|
|
397
|
+
// skip malformed lines
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
catch {
|
|
402
|
+
// file absent or unreadable
|
|
403
|
+
}
|
|
404
|
+
return chunks;
|
|
405
|
+
}
|
|
406
|
+
/** Type guard for KnowledgeChunk. */
|
|
407
|
+
function isKnowledgeChunk(v) {
|
|
408
|
+
if (typeof v !== 'object' || v === null)
|
|
409
|
+
return false;
|
|
410
|
+
const obj = v;
|
|
411
|
+
return (typeof obj['repo'] === 'string' &&
|
|
412
|
+
typeof obj['file'] === 'string' &&
|
|
413
|
+
typeof obj['startLine'] === 'number' &&
|
|
414
|
+
typeof obj['endLine'] === 'number' &&
|
|
415
|
+
typeof obj['text'] === 'string');
|
|
416
|
+
}
|
|
417
|
+
// ---------------------------------------------------------------------------
|
|
418
|
+
// Index a single file — returns new chunks (may have vectors)
|
|
419
|
+
// ---------------------------------------------------------------------------
|
|
420
|
+
async function indexFile(repoPath, filePath, embedModel, ollamaBase) {
|
|
421
|
+
// Read file with byte cap
|
|
422
|
+
let raw;
|
|
423
|
+
try {
|
|
424
|
+
const stat = fs.statSync(filePath);
|
|
425
|
+
if (stat.size > MAX_FILE_BYTES)
|
|
426
|
+
return [];
|
|
427
|
+
raw = fs.readFileSync(filePath, 'utf8');
|
|
428
|
+
}
|
|
429
|
+
catch {
|
|
430
|
+
return [];
|
|
431
|
+
}
|
|
432
|
+
// Repo-relative path for citation
|
|
433
|
+
const relFile = path.relative(repoPath, filePath);
|
|
434
|
+
const textChunks = chunkText(raw);
|
|
435
|
+
const result = [];
|
|
436
|
+
for (const tc of textChunks) {
|
|
437
|
+
const scrubbedText = scrubSecrets(tc.text);
|
|
438
|
+
let vector;
|
|
439
|
+
if (embedModel.available) {
|
|
440
|
+
const vec = await fetchEmbedding(ollamaBase, embedModel.model, scrubbedText);
|
|
441
|
+
if (vec !== null)
|
|
442
|
+
vector = vec;
|
|
443
|
+
}
|
|
444
|
+
const chunk = {
|
|
445
|
+
repo: repoPath,
|
|
446
|
+
file: relFile,
|
|
447
|
+
startLine: tc.startLine,
|
|
448
|
+
endLine: tc.endLine,
|
|
449
|
+
text: scrubbedText,
|
|
450
|
+
...(vector !== undefined ? { vector } : {}),
|
|
451
|
+
};
|
|
452
|
+
result.push(chunk);
|
|
453
|
+
}
|
|
454
|
+
return result;
|
|
455
|
+
}
|
|
456
|
+
export async function buildKnowledge(opts) {
|
|
457
|
+
// ENROLLMENT-SCOPED (docs/contracts/CONTRACT-M25.md invariant 3): listEnrolled() is already
|
|
458
|
+
// enrollment-scoped, but an explicit opts.repos list (forwarded from the CLI's
|
|
459
|
+
// --repo / positional args) must be validated against isEnrolled() so a caller
|
|
460
|
+
// can NEVER index an arbitrary, non-enrolled directory. Resolve to absolute
|
|
461
|
+
// first (listEnrolled() stores resolved paths) and drop any non-enrolled path.
|
|
462
|
+
const repos = (opts?.repos ?? listEnrolled()).filter((r) => isEnrolled(r));
|
|
463
|
+
// Default-empty enrollment (or all paths non-enrolled) → nothing to do
|
|
464
|
+
if (repos.length === 0) {
|
|
465
|
+
return { repos: 0, chunks: 0 };
|
|
466
|
+
}
|
|
467
|
+
// Detect local Ollama embedding model once (shared across repos)
|
|
468
|
+
const ollamaBase = 'http://localhost:11434';
|
|
469
|
+
let embedModel;
|
|
470
|
+
try {
|
|
471
|
+
embedModel = await detectEmbeddingModel(ollamaBase);
|
|
472
|
+
}
|
|
473
|
+
catch {
|
|
474
|
+
embedModel = { available: false };
|
|
475
|
+
}
|
|
476
|
+
let totalChunks = 0;
|
|
477
|
+
let indexedRepos = 0;
|
|
478
|
+
for (let i = 0; i < repos.length; i++) {
|
|
479
|
+
const repoPath = repos[i];
|
|
480
|
+
let repoChunks = 0;
|
|
481
|
+
try {
|
|
482
|
+
repoChunks = await indexRepo(repoPath, embedModel, ollamaBase);
|
|
483
|
+
totalChunks += repoChunks;
|
|
484
|
+
if (repoChunks >= 0)
|
|
485
|
+
indexedRepos++;
|
|
486
|
+
}
|
|
487
|
+
catch {
|
|
488
|
+
// one bad repo never crashes the whole run
|
|
489
|
+
}
|
|
490
|
+
try {
|
|
491
|
+
opts?.onProgress?.({ repo: repoPath, repoIndex: i + 1, repoCount: repos.length, newChunks: repoChunks });
|
|
492
|
+
}
|
|
493
|
+
catch {
|
|
494
|
+
// progress is best-effort — a throwing callback never breaks the build
|
|
495
|
+
}
|
|
496
|
+
}
|
|
497
|
+
return { repos: indexedRepos, chunks: totalChunks };
|
|
498
|
+
}
|
|
499
|
+
/**
|
|
500
|
+
* Index a single enrolled repo. Returns the number of NEW chunks added.
|
|
501
|
+
* Never throws.
|
|
502
|
+
*/
|
|
503
|
+
async function indexRepo(repoPath, embedModel, ollamaBase) {
|
|
504
|
+
const deadline = Date.now() + REPO_BUDGET_MS;
|
|
505
|
+
// Load incremental metadata
|
|
506
|
+
const meta = readMeta(repoPath);
|
|
507
|
+
const lastIndexedAt = meta?.lastIndexedAt ?? 0;
|
|
508
|
+
// Collect all eligible files
|
|
509
|
+
const allFiles = collectFiles(repoPath);
|
|
510
|
+
// Filter to only files modified since last index (incremental)
|
|
511
|
+
const changedFiles = allFiles.filter((f) => {
|
|
512
|
+
try {
|
|
513
|
+
const st = fs.statSync(f);
|
|
514
|
+
return st.mtimeMs > lastIndexedAt;
|
|
515
|
+
}
|
|
516
|
+
catch {
|
|
517
|
+
return true; // include if we can't stat
|
|
518
|
+
}
|
|
519
|
+
});
|
|
520
|
+
if (changedFiles.length === 0) {
|
|
521
|
+
// Nothing changed — repo counts as indexed but adds 0 chunks
|
|
522
|
+
return 0;
|
|
523
|
+
}
|
|
524
|
+
// Load existing chunks (for files not being re-indexed)
|
|
525
|
+
const existingChunks = loadChunks(repoPath);
|
|
526
|
+
const reindexedFiles = new Set(changedFiles.map((f) => path.relative(repoPath, f)));
|
|
527
|
+
// Live (currently-existing) repo-relative files, for deletion pruning.
|
|
528
|
+
const liveFiles = new Set(allFiles.map((f) => path.relative(repoPath, f)));
|
|
529
|
+
// Keep chunks from files that are NOT being re-indexed AND still exist on disk.
|
|
530
|
+
// (A deleted file is absent from collectFiles → not in reindexedFiles → would
|
|
531
|
+
// otherwise leave permanently-stale chunks that ask/graph cite forever.)
|
|
532
|
+
const keptChunks = existingChunks.filter((c) => !reindexedFiles.has(c.file) && liveFiles.has(c.file));
|
|
533
|
+
let newChunks = [];
|
|
534
|
+
let totalRepoBytesRead = 0;
|
|
535
|
+
// Track files we did NOT process this run (budget/time truncation) so we can
|
|
536
|
+
// avoid advancing lastIndexedAt past them — otherwise a skipped changed file
|
|
537
|
+
// would never be re-indexed and would silently vanish from the index.
|
|
538
|
+
let truncated = false;
|
|
539
|
+
const skippedMtimes = [];
|
|
540
|
+
for (let fi = 0; fi < changedFiles.length; fi++) {
|
|
541
|
+
const filePath = changedFiles[fi];
|
|
542
|
+
// Wall-clock budget check — every remaining file is unprocessed.
|
|
543
|
+
if (Date.now() >= deadline) {
|
|
544
|
+
truncated = true;
|
|
545
|
+
for (let j = fi; j < changedFiles.length; j++) {
|
|
546
|
+
try {
|
|
547
|
+
skippedMtimes.push(fs.statSync(changedFiles[j]).mtimeMs);
|
|
548
|
+
}
|
|
549
|
+
catch { /* ignore */ }
|
|
550
|
+
}
|
|
551
|
+
break;
|
|
552
|
+
}
|
|
553
|
+
// Byte budget check — this file is skipped but later ones may still fit.
|
|
554
|
+
let size;
|
|
555
|
+
try {
|
|
556
|
+
size = fs.statSync(filePath).size;
|
|
557
|
+
}
|
|
558
|
+
catch {
|
|
559
|
+
continue;
|
|
560
|
+
}
|
|
561
|
+
if (totalRepoBytesRead + size > MAX_REPO_BYTES) {
|
|
562
|
+
truncated = true;
|
|
563
|
+
try {
|
|
564
|
+
skippedMtimes.push(fs.statSync(filePath).mtimeMs);
|
|
565
|
+
}
|
|
566
|
+
catch { /* ignore */ }
|
|
567
|
+
continue;
|
|
568
|
+
}
|
|
569
|
+
totalRepoBytesRead += size;
|
|
570
|
+
const fileChunks = await indexFile(repoPath, filePath, embedModel, ollamaBase);
|
|
571
|
+
newChunks = newChunks.concat(fileChunks);
|
|
572
|
+
}
|
|
573
|
+
// Write all chunks (kept + new) back atomically
|
|
574
|
+
const allChunks = [...keptChunks, ...newChunks];
|
|
575
|
+
writeChunks(repoPath, allChunks);
|
|
576
|
+
// Update metadata. On truncation, hold lastIndexedAt just below the oldest
|
|
577
|
+
// un-processed changed file so it is retried on the next run (don't strand it).
|
|
578
|
+
let nextIndexedAt = Date.now();
|
|
579
|
+
if (truncated && skippedMtimes.length > 0) {
|
|
580
|
+
const oldestSkipped = Math.min(...skippedMtimes);
|
|
581
|
+
nextIndexedAt = Math.min(nextIndexedAt, oldestSkipped - 1);
|
|
582
|
+
}
|
|
583
|
+
writeMeta(repoPath, { repo: repoPath, lastIndexedAt: nextIndexedAt });
|
|
584
|
+
return newChunks.length;
|
|
585
|
+
}
|
|
586
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/core/knowledge/index.ts"],"names":[],"mappings":"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"}
|