@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,192 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* core/integrations/vercel.ts — Read-only Vercel project status via the
|
|
3
|
+
* `vercel` CLI.
|
|
4
|
+
*
|
|
5
|
+
* RULES:
|
|
6
|
+
* - READ-ONLY. Deploying stays in `ashlr ship` (already --confirm gated).
|
|
7
|
+
* - NEVER throws. Every exported function degrades gracefully on any
|
|
8
|
+
* failure (CLI absent, not authed, not linked, malformed output).
|
|
9
|
+
* - Uses the installed `vercel` CLI — no raw tokens are read, stored,
|
|
10
|
+
* logged, or printed.
|
|
11
|
+
* - spawnSync only (no shell prevents shell injection).
|
|
12
|
+
* - Bounded timeouts so a slow/hung CLI never blocks the caller.
|
|
13
|
+
*/
|
|
14
|
+
import { spawnSync } from 'node:child_process';
|
|
15
|
+
import { existsSync } from 'node:fs';
|
|
16
|
+
import { join } from 'node:path';
|
|
17
|
+
// ---------------------------------------------------------------------------
|
|
18
|
+
// Internal constants
|
|
19
|
+
// ---------------------------------------------------------------------------
|
|
20
|
+
const VERCEL_BIN = 'vercel';
|
|
21
|
+
const TIMEOUT_MS = 8_000; // ms — vercel ls can be slow on first run
|
|
22
|
+
const MAX_DEPLOYS = 10;
|
|
23
|
+
// ---------------------------------------------------------------------------
|
|
24
|
+
// Internal helpers
|
|
25
|
+
// ---------------------------------------------------------------------------
|
|
26
|
+
/**
|
|
27
|
+
* Run a vercel sub-command synchronously inside `cwd`.
|
|
28
|
+
* Returns trimmed stdout or null on any failure. Never throws.
|
|
29
|
+
*/
|
|
30
|
+
function runVercel(args, cwd) {
|
|
31
|
+
try {
|
|
32
|
+
const res = spawnSync(VERCEL_BIN, args, {
|
|
33
|
+
cwd,
|
|
34
|
+
timeout: TIMEOUT_MS,
|
|
35
|
+
stdio: 'pipe',
|
|
36
|
+
encoding: 'utf8',
|
|
37
|
+
env: {
|
|
38
|
+
...process.env,
|
|
39
|
+
// Suppress interactive prompts and update checks so the CLI
|
|
40
|
+
// is usable in a non-TTY context.
|
|
41
|
+
CI: '1',
|
|
42
|
+
FORCE_COLOR: '0',
|
|
43
|
+
},
|
|
44
|
+
});
|
|
45
|
+
// spawn error (e.g. ENOENT — vercel not on PATH) or non-zero exit → null.
|
|
46
|
+
if (res.error)
|
|
47
|
+
return null;
|
|
48
|
+
if (res.status !== 0)
|
|
49
|
+
return null;
|
|
50
|
+
return typeof res.stdout === 'string' ? res.stdout.trim() : null;
|
|
51
|
+
}
|
|
52
|
+
catch {
|
|
53
|
+
return null;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Returns true when a `.vercel/project.json` file exists in `cwd`, which
|
|
58
|
+
* indicates the directory has been linked to a Vercel project.
|
|
59
|
+
*/
|
|
60
|
+
function hasProjectJson(cwd) {
|
|
61
|
+
return existsSync(join(cwd, '.vercel', 'project.json'));
|
|
62
|
+
}
|
|
63
|
+
// ---------------------------------------------------------------------------
|
|
64
|
+
// JSON parsing helpers
|
|
65
|
+
// ---------------------------------------------------------------------------
|
|
66
|
+
/**
|
|
67
|
+
* Parse the JSON emitted by `vercel ls --format json`.
|
|
68
|
+
*
|
|
69
|
+
* The modern CLI emits `{ deployments: [...] }`; older shapes emit a bare
|
|
70
|
+
* array of deployment objects. Each relevant
|
|
71
|
+
* field is extracted defensively; unknown shapes produce an empty array.
|
|
72
|
+
*/
|
|
73
|
+
function parseDeployList(raw) {
|
|
74
|
+
const trimmed = raw.trim();
|
|
75
|
+
// vercel ls --format json wraps the array under a top-level key (or, on
|
|
76
|
+
// older CLI versions, emits a bare array).
|
|
77
|
+
let parsed;
|
|
78
|
+
try {
|
|
79
|
+
parsed = JSON.parse(trimmed);
|
|
80
|
+
}
|
|
81
|
+
catch {
|
|
82
|
+
return [];
|
|
83
|
+
}
|
|
84
|
+
// Accept a bare array OR { deployments: [...] } / { data: [...] } wrappers.
|
|
85
|
+
let items = null;
|
|
86
|
+
if (Array.isArray(parsed)) {
|
|
87
|
+
items = parsed;
|
|
88
|
+
}
|
|
89
|
+
else if (parsed !== null && typeof parsed === 'object') {
|
|
90
|
+
const obj = parsed;
|
|
91
|
+
for (const key of ['deployments', 'data', 'items']) {
|
|
92
|
+
if (Array.isArray(obj[key])) {
|
|
93
|
+
items = obj[key];
|
|
94
|
+
break;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
if (items === null)
|
|
99
|
+
return [];
|
|
100
|
+
const results = [];
|
|
101
|
+
for (const item of items) {
|
|
102
|
+
if (item === null || typeof item !== 'object')
|
|
103
|
+
continue;
|
|
104
|
+
const d = item;
|
|
105
|
+
// URL — vercel uses "url" or "alias" (first element).
|
|
106
|
+
let url = '';
|
|
107
|
+
if (typeof d['url'] === 'string' && d['url'].length > 0) {
|
|
108
|
+
url = d['url'];
|
|
109
|
+
}
|
|
110
|
+
else if (Array.isArray(d['alias']) && typeof d['alias'][0] === 'string') {
|
|
111
|
+
url = d['alias'][0];
|
|
112
|
+
}
|
|
113
|
+
if (!url)
|
|
114
|
+
continue; // skip entries without a URL
|
|
115
|
+
// State — various field names depending on vercel CLI version.
|
|
116
|
+
let state = 'UNKNOWN';
|
|
117
|
+
for (const key of ['state', 'readyState', 'status']) {
|
|
118
|
+
if (typeof d[key] === 'string' && d[key].length > 0) {
|
|
119
|
+
state = d[key].toUpperCase();
|
|
120
|
+
break;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
// Created timestamp.
|
|
124
|
+
let createdAt = null;
|
|
125
|
+
for (const key of ['createdAt', 'created', 'createdTime']) {
|
|
126
|
+
const val = d[key];
|
|
127
|
+
if (typeof val === 'string' && val.length > 0) {
|
|
128
|
+
createdAt = val;
|
|
129
|
+
break;
|
|
130
|
+
}
|
|
131
|
+
if (typeof val === 'number') {
|
|
132
|
+
createdAt = new Date(val).toISOString();
|
|
133
|
+
break;
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
// Target — "production" | "preview" | null.
|
|
137
|
+
let target = null;
|
|
138
|
+
for (const key of ['target', 'meta.githubCommitRef']) {
|
|
139
|
+
if (typeof d[key] === 'string' && d[key].length > 0) {
|
|
140
|
+
target = d[key];
|
|
141
|
+
break;
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
results.push({ url, state, createdAt, target });
|
|
145
|
+
if (results.length >= MAX_DEPLOYS)
|
|
146
|
+
break;
|
|
147
|
+
}
|
|
148
|
+
return results;
|
|
149
|
+
}
|
|
150
|
+
// ---------------------------------------------------------------------------
|
|
151
|
+
// Public API
|
|
152
|
+
// ---------------------------------------------------------------------------
|
|
153
|
+
/**
|
|
154
|
+
* Read-only linked-project snapshot via the `vercel` CLI.
|
|
155
|
+
* NEVER throws — degrades to `{ linked: false, latestState: null, url: null }`
|
|
156
|
+
* on any failure (CLI absent, not authed, not linked, scope prompt, timeout).
|
|
157
|
+
*/
|
|
158
|
+
export function vercelStatus(cwd) {
|
|
159
|
+
const unlinked = { linked: false, latestState: null, url: null };
|
|
160
|
+
// Fast-path: check for .vercel/project.json before spawning the CLI.
|
|
161
|
+
if (!hasProjectJson(cwd))
|
|
162
|
+
return unlinked;
|
|
163
|
+
// Attempt `vercel ls --format json` for a live deployment list — take the
|
|
164
|
+
// first (most recent) entry as the latest status. The modern Vercel CLI uses
|
|
165
|
+
// `-F, --format json`; the legacy `--json` flag errors with "unknown option".
|
|
166
|
+
const raw = runVercel(['ls', '--format', 'json'], cwd);
|
|
167
|
+
if (raw === null)
|
|
168
|
+
return unlinked;
|
|
169
|
+
const deploys = parseDeployList(raw);
|
|
170
|
+
if (deploys.length > 0) {
|
|
171
|
+
const latest = deploys[0];
|
|
172
|
+
return {
|
|
173
|
+
linked: true,
|
|
174
|
+
latestState: latest.state,
|
|
175
|
+
url: latest.url,
|
|
176
|
+
};
|
|
177
|
+
}
|
|
178
|
+
// `vercel ls` returned parseable JSON but no deployments — still linked.
|
|
179
|
+
return { linked: true, latestState: null, url: null };
|
|
180
|
+
}
|
|
181
|
+
/**
|
|
182
|
+
* List recent deployments for the Vercel project linked to `cwd`.
|
|
183
|
+
* NEVER throws — returns [] on any failure (CLI absent, not authed, not
|
|
184
|
+
* linked, malformed output, timeout).
|
|
185
|
+
*/
|
|
186
|
+
export function listDeploys(cwd) {
|
|
187
|
+
const raw = runVercel(['ls', '--format', 'json'], cwd);
|
|
188
|
+
if (raw === null)
|
|
189
|
+
return [];
|
|
190
|
+
return parseDeployList(raw);
|
|
191
|
+
}
|
|
192
|
+
//# sourceMappingURL=vercel.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"vercel.js","sourceRoot":"","sources":["../../../src/core/integrations/vercel.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ask.ts — Portfolio RAG: retrieve + synthesize answers from the knowledge index.
|
|
3
|
+
*
|
|
4
|
+
* INVARIANTS (non-negotiable):
|
|
5
|
+
* 1. LOCAL-ONLY BY DEFAULT — code/chunks are NEVER sent to a cloud model unless
|
|
6
|
+
* opts.allowCloud === true AND a cloud key exists. Any code-to-cloud on the
|
|
7
|
+
* default path is a contract violation.
|
|
8
|
+
* 2. READ-ONLY — this module never modifies any enrolled repo or any file
|
|
9
|
+
* outside knowledgeDir().
|
|
10
|
+
* 3. ENROLLMENT-SCOPED — retrieval is limited to loadChunks() output, which
|
|
11
|
+
* itself is scoped to the persisted index (enrolled repos only).
|
|
12
|
+
* 4. BOUNDED — top-K retrieval is capped; chunk text in the prompt is capped.
|
|
13
|
+
* 5. NO SECRETS — chunks stored in the index are already scrubbed; we do not
|
|
14
|
+
* re-expose them beyond the local synthesis prompt.
|
|
15
|
+
* 6. NEVER THROWS — degrades gracefully; returns a useful message on any failure.
|
|
16
|
+
*/
|
|
17
|
+
import type { AskResult } from '../types.js';
|
|
18
|
+
/**
|
|
19
|
+
* Answer `question` using a local RAG pipeline over the persisted knowledge index.
|
|
20
|
+
*
|
|
21
|
+
* Retrieval: embedding cosine similarity (local Ollama) when vectors are present,
|
|
22
|
+
* else keyword/TF-IDF. Synthesis: LOCAL model via getActiveClient (Ollama/LM Studio).
|
|
23
|
+
*
|
|
24
|
+
* PRIVACY GUARDRAIL: code chunks are only sent to the local synthesis model by
|
|
25
|
+
* default. They are sent to a cloud model ONLY when opts.allowCloud === true AND
|
|
26
|
+
* a cloud key exists (enforced by getActiveClient — it throws otherwise).
|
|
27
|
+
*
|
|
28
|
+
* Never throws. Degrades to an informational message when nothing is indexed
|
|
29
|
+
* or the local model is unreachable.
|
|
30
|
+
*/
|
|
31
|
+
export declare function ask(question: string, opts: {
|
|
32
|
+
repo?: string;
|
|
33
|
+
allowCloud: boolean;
|
|
34
|
+
}): Promise<AskResult>;
|
|
@@ -0,0 +1,325 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ask.ts — Portfolio RAG: retrieve + synthesize answers from the knowledge index.
|
|
3
|
+
*
|
|
4
|
+
* INVARIANTS (non-negotiable):
|
|
5
|
+
* 1. LOCAL-ONLY BY DEFAULT — code/chunks are NEVER sent to a cloud model unless
|
|
6
|
+
* opts.allowCloud === true AND a cloud key exists. Any code-to-cloud on the
|
|
7
|
+
* default path is a contract violation.
|
|
8
|
+
* 2. READ-ONLY — this module never modifies any enrolled repo or any file
|
|
9
|
+
* outside knowledgeDir().
|
|
10
|
+
* 3. ENROLLMENT-SCOPED — retrieval is limited to loadChunks() output, which
|
|
11
|
+
* itself is scoped to the persisted index (enrolled repos only).
|
|
12
|
+
* 4. BOUNDED — top-K retrieval is capped; chunk text in the prompt is capped.
|
|
13
|
+
* 5. NO SECRETS — chunks stored in the index are already scrubbed; we do not
|
|
14
|
+
* re-expose them beyond the local synthesis prompt.
|
|
15
|
+
* 6. NEVER THROWS — degrades gracefully; returns a useful message on any failure.
|
|
16
|
+
*/
|
|
17
|
+
import { loadChunks } from './index.js';
|
|
18
|
+
import { getActiveClient } from '../run/provider-client.js';
|
|
19
|
+
import { loadConfig } from '../config.js';
|
|
20
|
+
// ---------------------------------------------------------------------------
|
|
21
|
+
// Constants
|
|
22
|
+
// ---------------------------------------------------------------------------
|
|
23
|
+
/** Number of top chunks to retrieve for synthesis. */
|
|
24
|
+
const TOP_K = 8;
|
|
25
|
+
/** Max characters of a single chunk to include in the synthesis prompt. */
|
|
26
|
+
const CHUNK_TEXT_CAP = 600;
|
|
27
|
+
/** Max total characters of all chunk context in the synthesis prompt. */
|
|
28
|
+
const CONTEXT_TOTAL_CAP = 6000;
|
|
29
|
+
/** Timeout (ms) for the local Ollama /api/embeddings request. */
|
|
30
|
+
const EMBED_TIMEOUT_MS = 8000;
|
|
31
|
+
// ---------------------------------------------------------------------------
|
|
32
|
+
// Tokenisation (shared pattern with recall.ts — no import to avoid coupling)
|
|
33
|
+
// ---------------------------------------------------------------------------
|
|
34
|
+
function tokenize(text) {
|
|
35
|
+
return text
|
|
36
|
+
.toLowerCase()
|
|
37
|
+
.split(/[^a-z0-9]+/)
|
|
38
|
+
.filter((t) => t.length > 1); // drop single-char tokens
|
|
39
|
+
}
|
|
40
|
+
// ---------------------------------------------------------------------------
|
|
41
|
+
// Cosine similarity
|
|
42
|
+
// ---------------------------------------------------------------------------
|
|
43
|
+
function cosine(a, b) {
|
|
44
|
+
if (a.length === 0 || a.length !== b.length)
|
|
45
|
+
return 0;
|
|
46
|
+
let dot = 0, normA = 0, normB = 0;
|
|
47
|
+
for (let i = 0; i < a.length; i++) {
|
|
48
|
+
dot += a[i] * b[i];
|
|
49
|
+
normA += a[i] * a[i];
|
|
50
|
+
normB += b[i] * b[i];
|
|
51
|
+
}
|
|
52
|
+
const denom = Math.sqrt(normA) * Math.sqrt(normB);
|
|
53
|
+
return denom === 0 ? 0 : dot / denom;
|
|
54
|
+
}
|
|
55
|
+
// ---------------------------------------------------------------------------
|
|
56
|
+
// Keyword / TF-IDF scoring for a chunk
|
|
57
|
+
// ---------------------------------------------------------------------------
|
|
58
|
+
function keywordScoreChunk(query, chunk) {
|
|
59
|
+
const queryTerms = new Set(tokenize(query));
|
|
60
|
+
if (queryTerms.size === 0)
|
|
61
|
+
return 0;
|
|
62
|
+
// Weight file path tokens slightly (they indicate structural relevance)
|
|
63
|
+
const fileTokens = tokenize(chunk.file);
|
|
64
|
+
const textTokens = tokenize(chunk.text);
|
|
65
|
+
const weightedFreq = new Map();
|
|
66
|
+
for (const t of fileTokens) {
|
|
67
|
+
weightedFreq.set(t, (weightedFreq.get(t) ?? 0) + 2);
|
|
68
|
+
}
|
|
69
|
+
for (const t of textTokens) {
|
|
70
|
+
weightedFreq.set(t, (weightedFreq.get(t) ?? 0) + 1);
|
|
71
|
+
}
|
|
72
|
+
if (weightedFreq.size === 0)
|
|
73
|
+
return 0;
|
|
74
|
+
let hits = 0;
|
|
75
|
+
for (const term of queryTerms) {
|
|
76
|
+
hits += weightedFreq.get(term) ?? 0;
|
|
77
|
+
}
|
|
78
|
+
return hits === 0 ? 0 : hits / queryTerms.size;
|
|
79
|
+
}
|
|
80
|
+
// ---------------------------------------------------------------------------
|
|
81
|
+
// Local Ollama embedding helpers (best-effort; never throw)
|
|
82
|
+
// ---------------------------------------------------------------------------
|
|
83
|
+
async function detectEmbeddingModel(ollamaBase) {
|
|
84
|
+
const controller = new AbortController();
|
|
85
|
+
const timer = setTimeout(() => controller.abort(), 3000);
|
|
86
|
+
try {
|
|
87
|
+
const res = await fetch(`${ollamaBase.replace(/\/+$/, '')}/api/tags`, {
|
|
88
|
+
signal: controller.signal,
|
|
89
|
+
headers: { Accept: 'application/json' },
|
|
90
|
+
});
|
|
91
|
+
if (!res.ok)
|
|
92
|
+
return { available: false };
|
|
93
|
+
const body = (await res.json());
|
|
94
|
+
if (typeof body !== 'object' ||
|
|
95
|
+
body === null ||
|
|
96
|
+
!Array.isArray(body['models'])) {
|
|
97
|
+
return { available: false };
|
|
98
|
+
}
|
|
99
|
+
const models = body.models;
|
|
100
|
+
const EMBED_HINTS = ['bge', 'nomic-embed', 'mxbai-embed', 'all-minilm', 'embed'];
|
|
101
|
+
for (const hint of EMBED_HINTS) {
|
|
102
|
+
const found = models.find((m) => m.name.toLowerCase().includes(hint));
|
|
103
|
+
if (found)
|
|
104
|
+
return { available: true, model: found.name };
|
|
105
|
+
}
|
|
106
|
+
return { available: false };
|
|
107
|
+
}
|
|
108
|
+
catch {
|
|
109
|
+
return { available: false };
|
|
110
|
+
}
|
|
111
|
+
finally {
|
|
112
|
+
clearTimeout(timer);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
async function fetchEmbedding(ollamaBase, model, text) {
|
|
116
|
+
const controller = new AbortController();
|
|
117
|
+
const timer = setTimeout(() => controller.abort(), EMBED_TIMEOUT_MS);
|
|
118
|
+
try {
|
|
119
|
+
const res = await fetch(`${ollamaBase.replace(/\/+$/, '')}/api/embeddings`, {
|
|
120
|
+
method: 'POST',
|
|
121
|
+
signal: controller.signal,
|
|
122
|
+
headers: { 'Content-Type': 'application/json' },
|
|
123
|
+
body: JSON.stringify({ model, prompt: text.slice(0, 2000) }),
|
|
124
|
+
});
|
|
125
|
+
if (!res.ok)
|
|
126
|
+
return null;
|
|
127
|
+
const body = (await res.json());
|
|
128
|
+
if (typeof body !== 'object' ||
|
|
129
|
+
body === null ||
|
|
130
|
+
!Array.isArray(body['embedding'])) {
|
|
131
|
+
return null;
|
|
132
|
+
}
|
|
133
|
+
const embedding = body.embedding;
|
|
134
|
+
if (!embedding.every((v) => typeof v === 'number'))
|
|
135
|
+
return null;
|
|
136
|
+
return embedding;
|
|
137
|
+
}
|
|
138
|
+
catch {
|
|
139
|
+
return null;
|
|
140
|
+
}
|
|
141
|
+
finally {
|
|
142
|
+
clearTimeout(timer);
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* Retrieve the top-K most relevant chunks from the index for `question`.
|
|
147
|
+
* Tries embedding cosine similarity first (local Ollama); falls back to
|
|
148
|
+
* keyword/TF-IDF. Never throws; returns [] on any failure.
|
|
149
|
+
*/
|
|
150
|
+
async function retrieve(question, chunks, ollamaBase) {
|
|
151
|
+
if (chunks.length === 0)
|
|
152
|
+
return { hits: [], method: 'keyword' };
|
|
153
|
+
// --- Attempt embedding retrieval if any chunks have vectors ---
|
|
154
|
+
const chunksWithVectors = chunks.filter((c) => c.vector && c.vector.length > 0);
|
|
155
|
+
if (chunksWithVectors.length > 0) {
|
|
156
|
+
// Try to get a query embedding from local Ollama
|
|
157
|
+
try {
|
|
158
|
+
const modelProbe = await detectEmbeddingModel(ollamaBase);
|
|
159
|
+
if (modelProbe.available) {
|
|
160
|
+
const queryVec = await fetchEmbedding(ollamaBase, modelProbe.model, question);
|
|
161
|
+
if (queryVec !== null) {
|
|
162
|
+
// Score all chunks that have vectors by cosine; keyword score for the rest
|
|
163
|
+
const hits = chunks.map((chunk) => {
|
|
164
|
+
if (chunk.vector && chunk.vector.length > 0) {
|
|
165
|
+
return {
|
|
166
|
+
chunk,
|
|
167
|
+
score: cosine(queryVec, chunk.vector),
|
|
168
|
+
method: 'embedding',
|
|
169
|
+
};
|
|
170
|
+
}
|
|
171
|
+
return {
|
|
172
|
+
chunk,
|
|
173
|
+
score: keywordScoreChunk(question, chunk),
|
|
174
|
+
method: 'keyword',
|
|
175
|
+
};
|
|
176
|
+
});
|
|
177
|
+
hits.sort((a, b) => b.score - a.score);
|
|
178
|
+
return { hits: hits.slice(0, TOP_K), method: 'embedding' };
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
catch {
|
|
183
|
+
// Fall through to keyword
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
// --- Keyword / TF-IDF fallback ---
|
|
187
|
+
const hits = chunks.map((chunk) => ({
|
|
188
|
+
chunk,
|
|
189
|
+
score: keywordScoreChunk(question, chunk),
|
|
190
|
+
method: 'keyword',
|
|
191
|
+
}));
|
|
192
|
+
hits.sort((a, b) => b.score - a.score);
|
|
193
|
+
return { hits: hits.slice(0, TOP_K), method: 'keyword' };
|
|
194
|
+
}
|
|
195
|
+
// ---------------------------------------------------------------------------
|
|
196
|
+
// Prompt construction
|
|
197
|
+
// ---------------------------------------------------------------------------
|
|
198
|
+
function buildPrompt(question, hits) {
|
|
199
|
+
if (hits.length === 0) {
|
|
200
|
+
return `Answer the following question as best you can. No source context is available.\n\nQuestion: ${question}`;
|
|
201
|
+
}
|
|
202
|
+
const contextParts = [];
|
|
203
|
+
let totalChars = 0;
|
|
204
|
+
for (const hit of hits) {
|
|
205
|
+
const { chunk } = hit;
|
|
206
|
+
const header = `[${chunk.repo}] ${chunk.file}:${chunk.startLine}-${chunk.endLine}`;
|
|
207
|
+
const body = chunk.text.slice(0, CHUNK_TEXT_CAP);
|
|
208
|
+
const entry = `${header}\n${body}`;
|
|
209
|
+
if (totalChars + entry.length > CONTEXT_TOTAL_CAP)
|
|
210
|
+
break;
|
|
211
|
+
contextParts.push(entry);
|
|
212
|
+
totalChars += entry.length;
|
|
213
|
+
}
|
|
214
|
+
return [
|
|
215
|
+
'You are a software assistant with access to source code excerpts from an enrolled code portfolio.',
|
|
216
|
+
'Answer the question using only the provided context. Cite the source (repo, file, line) for each claim.',
|
|
217
|
+
'If the context does not contain enough information, say so clearly.',
|
|
218
|
+
'',
|
|
219
|
+
'--- SOURCE CONTEXT ---',
|
|
220
|
+
contextParts.join('\n\n---\n'),
|
|
221
|
+
'--- END CONTEXT ---',
|
|
222
|
+
'',
|
|
223
|
+
`Question: ${question}`,
|
|
224
|
+
].join('\n');
|
|
225
|
+
}
|
|
226
|
+
// ---------------------------------------------------------------------------
|
|
227
|
+
// Public API
|
|
228
|
+
// ---------------------------------------------------------------------------
|
|
229
|
+
/**
|
|
230
|
+
* Answer `question` using a local RAG pipeline over the persisted knowledge index.
|
|
231
|
+
*
|
|
232
|
+
* Retrieval: embedding cosine similarity (local Ollama) when vectors are present,
|
|
233
|
+
* else keyword/TF-IDF. Synthesis: LOCAL model via getActiveClient (Ollama/LM Studio).
|
|
234
|
+
*
|
|
235
|
+
* PRIVACY GUARDRAIL: code chunks are only sent to the local synthesis model by
|
|
236
|
+
* default. They are sent to a cloud model ONLY when opts.allowCloud === true AND
|
|
237
|
+
* a cloud key exists (enforced by getActiveClient — it throws otherwise).
|
|
238
|
+
*
|
|
239
|
+
* Never throws. Degrades to an informational message when nothing is indexed
|
|
240
|
+
* or the local model is unreachable.
|
|
241
|
+
*/
|
|
242
|
+
export async function ask(question, opts) {
|
|
243
|
+
const noKnowledge = (reason) => ({
|
|
244
|
+
question,
|
|
245
|
+
answer: reason,
|
|
246
|
+
sources: [],
|
|
247
|
+
method: 'keyword',
|
|
248
|
+
local: true,
|
|
249
|
+
});
|
|
250
|
+
// --- Load chunks from the persisted index ---
|
|
251
|
+
let chunks;
|
|
252
|
+
try {
|
|
253
|
+
chunks = loadChunks(opts.repo);
|
|
254
|
+
}
|
|
255
|
+
catch {
|
|
256
|
+
return noKnowledge('No knowledge indexed — run `ashlr knowledge build` to index enrolled repos.');
|
|
257
|
+
}
|
|
258
|
+
if (chunks.length === 0) {
|
|
259
|
+
const scope = opts.repo ? ` for repo ${opts.repo}` : '';
|
|
260
|
+
return noKnowledge(`No knowledge indexed${scope} — run \`ashlr knowledge build\` to index enrolled repos.`);
|
|
261
|
+
}
|
|
262
|
+
// --- Load config (synchronous) for Ollama base URL and provider client ---
|
|
263
|
+
let cfg;
|
|
264
|
+
try {
|
|
265
|
+
cfg = loadConfig();
|
|
266
|
+
}
|
|
267
|
+
catch {
|
|
268
|
+
return noKnowledge('Could not load ashlr config — run `ashlr` once to initialize.');
|
|
269
|
+
}
|
|
270
|
+
const ollamaBase = (cfg.models?.ollama ?? 'http://localhost:11434').replace(/\/+$/, '');
|
|
271
|
+
// --- Retrieve top-K relevant chunks ---
|
|
272
|
+
let hits;
|
|
273
|
+
let method;
|
|
274
|
+
try {
|
|
275
|
+
({ hits, method } = await retrieve(question, chunks, ollamaBase));
|
|
276
|
+
}
|
|
277
|
+
catch {
|
|
278
|
+
hits = [];
|
|
279
|
+
method = 'keyword';
|
|
280
|
+
}
|
|
281
|
+
// --- Build cited sources from retrieved hits ---
|
|
282
|
+
const sources = hits.map((h) => ({
|
|
283
|
+
repo: h.chunk.repo,
|
|
284
|
+
file: h.chunk.file,
|
|
285
|
+
line: h.chunk.startLine,
|
|
286
|
+
}));
|
|
287
|
+
// --- Synthesize answer via local model ---
|
|
288
|
+
// PRIVACY: getActiveClient enforces LOCAL-ONLY by default.
|
|
289
|
+
// allowCloud is forwarded verbatim — the client will throw if cloud is
|
|
290
|
+
// selected without --allow-cloud, providing a clear error message.
|
|
291
|
+
const prompt = buildPrompt(question, hits);
|
|
292
|
+
let answer;
|
|
293
|
+
let isLocal = true;
|
|
294
|
+
try {
|
|
295
|
+
const client = await getActiveClient(cfg, { allowCloud: opts.allowCloud });
|
|
296
|
+
// ALLOWLIST (not denylist): treat ONLY the known local providers as local.
|
|
297
|
+
// Any unknown/new provider id (e.g. a future 'bedrock'/'vertex') defaults to
|
|
298
|
+
// local:false (cloud) so it correctly triggers the cloud warning rather than
|
|
299
|
+
// being silently mislabeled as local.
|
|
300
|
+
isLocal = client.id === 'ollama' || client.id === 'lmstudio';
|
|
301
|
+
const result = await client.chat([
|
|
302
|
+
{ role: 'user', content: prompt },
|
|
303
|
+
]);
|
|
304
|
+
answer = result.content.trim();
|
|
305
|
+
if (!answer) {
|
|
306
|
+
answer = 'The local model returned an empty response. Ensure Ollama is running with a chat model loaded.';
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
catch (err) {
|
|
310
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
311
|
+
// Surface the local-first refusal clearly so the user knows what to do
|
|
312
|
+
answer = `Could not synthesize an answer: ${msg}`;
|
|
313
|
+
// If the error is a local-first refusal (no cloud without --allow-cloud),
|
|
314
|
+
// treat it as a local attempt (the synthesis just failed)
|
|
315
|
+
isLocal = true;
|
|
316
|
+
}
|
|
317
|
+
return {
|
|
318
|
+
question,
|
|
319
|
+
answer,
|
|
320
|
+
sources,
|
|
321
|
+
method,
|
|
322
|
+
local: isLocal,
|
|
323
|
+
};
|
|
324
|
+
}
|
|
325
|
+
//# sourceMappingURL=ask.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ask.js","sourceRoot":"","sources":["../../../src/core/knowledge/ask.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* graph.ts — Knowledge Graph + Impact analysis for enrolled repos.
|
|
3
|
+
*
|
|
4
|
+
* INVARIANTS (docs/contracts/CONTRACT-M25.md):
|
|
5
|
+
* 1. READ-ONLY: never modifies any enrolled repo; analysis only.
|
|
6
|
+
* 2. ENROLLMENT-SCOPED: default repos = listEnrolled() (DEFAULT EMPTY => empty graph).
|
|
7
|
+
* 3. BOUNDED: caps file walk depth, file count, and skips node_modules/.git/dist/binaries.
|
|
8
|
+
* 4. NEVER THROWS: all functions catch internally; callers get empty structures on error.
|
|
9
|
+
* 5. LOCAL-ONLY: no network calls; pure filesystem analysis.
|
|
10
|
+
* 6. NO SECRETS: skips .env/key files; does not emit secret-shaped content.
|
|
11
|
+
*
|
|
12
|
+
* buildGraph(repos?): construct KnowledgeGraph from persisted index + package.json manifests
|
|
13
|
+
* + import/require statements. Nodes: repos, key modules, shared deps.
|
|
14
|
+
* Edges: imports/depends/shared-dep. CrossRepo: same dep across repos, duplicated modules.
|
|
15
|
+
*
|
|
16
|
+
* impact(target, repos?): find all references to a file path or symbol across enrolled repos
|
|
17
|
+
* via the persisted index + grep-style scan. Returns ImpactResult with references + dependents.
|
|
18
|
+
*/
|
|
19
|
+
import type { KnowledgeGraph, ImpactResult } from '../types.js';
|
|
20
|
+
/**
|
|
21
|
+
* Build a KnowledgeGraph from enrolled repos (or the provided list).
|
|
22
|
+
*
|
|
23
|
+
* Nodes:
|
|
24
|
+
* - kind:'repo' — each enrolled repo
|
|
25
|
+
* - kind:'module' — key source files within a repo (those that import packages)
|
|
26
|
+
* - kind:'dep' — external dependencies (package names)
|
|
27
|
+
*
|
|
28
|
+
* Edges:
|
|
29
|
+
* - kind:'depends' — repo -> dep (from package.json)
|
|
30
|
+
* - kind:'imports' — module -> dep (from import statements)
|
|
31
|
+
* - kind:'shared-dep' — dep -> dep node (already in graph; used for cross-repo detection)
|
|
32
|
+
*
|
|
33
|
+
* CrossRepo:
|
|
34
|
+
* - kind:'shared-dep' when a dep appears in 2+ repos
|
|
35
|
+
* - kind:'duplicate-module' when the same relative module path exists in 2+ repos
|
|
36
|
+
*
|
|
37
|
+
* BOUNDED, READ-ONLY, NEVER THROWS.
|
|
38
|
+
*/
|
|
39
|
+
export declare function buildGraph(repos?: string[]): KnowledgeGraph;
|
|
40
|
+
/**
|
|
41
|
+
* Find all references to a file path or symbol across enrolled repos.
|
|
42
|
+
*
|
|
43
|
+
* For a file target: searches for import/require of that file (by basename and
|
|
44
|
+
* relative paths) and any text occurrence of the path.
|
|
45
|
+
* For a symbol target (no path separators, no extension): searches for usage
|
|
46
|
+
* occurrences in source files via text scan.
|
|
47
|
+
*
|
|
48
|
+
* Returns references (repo/file:line) and a list of dependent module names.
|
|
49
|
+
* BOUNDED (MAX_REFERENCES cap). READ-ONLY. NEVER THROWS.
|
|
50
|
+
*/
|
|
51
|
+
export declare function impact(target: string, repos?: string[]): ImpactResult;
|