@astragenie/astramemory-local 0.7.2
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 +341 -0
- package/README.md +419 -0
- package/dist/backup/retention.d.ts +15 -0
- package/dist/backup/retention.js +62 -0
- package/dist/backup/retention.js.map +1 -0
- package/dist/backup/snapshot.d.ts +21 -0
- package/dist/backup/snapshot.js +55 -0
- package/dist/backup/snapshot.js.map +1 -0
- package/dist/backup/verify.d.ts +23 -0
- package/dist/backup/verify.js +77 -0
- package/dist/backup/verify.js.map +1 -0
- package/dist/budget/tracker.d.ts +58 -0
- package/dist/budget/tracker.js +102 -0
- package/dist/budget/tracker.js.map +1 -0
- package/dist/capture/codex.d.ts +63 -0
- package/dist/capture/codex.js +0 -0
- package/dist/capture/codex.js.map +1 -0
- package/dist/cli/backup.d.ts +1 -0
- package/dist/cli/backup.js +112 -0
- package/dist/cli/backup.js.map +1 -0
- package/dist/cli/budget.d.ts +7 -0
- package/dist/cli/budget.js +44 -0
- package/dist/cli/budget.js.map +1 -0
- package/dist/cli/capture.d.ts +10 -0
- package/dist/cli/capture.js +113 -0
- package/dist/cli/capture.js.map +1 -0
- package/dist/cli/consolidate.d.ts +16 -0
- package/dist/cli/consolidate.js +146 -0
- package/dist/cli/consolidate.js.map +1 -0
- package/dist/cli/doctor.d.ts +1 -0
- package/dist/cli/doctor.js +54 -0
- package/dist/cli/doctor.js.map +1 -0
- package/dist/cli/entity-backfill.d.ts +10 -0
- package/dist/cli/entity-backfill.js +46 -0
- package/dist/cli/entity-backfill.js.map +1 -0
- package/dist/cli/hook-install.d.ts +45 -0
- package/dist/cli/hook-install.js +77 -0
- package/dist/cli/hook-install.js.map +1 -0
- package/dist/cli/index.d.ts +2 -0
- package/dist/cli/index.js +312 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/init.d.ts +16 -0
- package/dist/cli/init.js +431 -0
- package/dist/cli/init.js.map +1 -0
- package/dist/cli/mcp-stdio.d.ts +18 -0
- package/dist/cli/mcp-stdio.js +67 -0
- package/dist/cli/mcp-stdio.js.map +1 -0
- package/dist/cli/memory.d.ts +15 -0
- package/dist/cli/memory.js +52 -0
- package/dist/cli/memory.js.map +1 -0
- package/dist/cli/open-runtime-db.d.ts +15 -0
- package/dist/cli/open-runtime-db.js +37 -0
- package/dist/cli/open-runtime-db.js.map +1 -0
- package/dist/cli/pair.d.ts +29 -0
- package/dist/cli/pair.js +64 -0
- package/dist/cli/pair.js.map +1 -0
- package/dist/cli/providers.d.ts +10 -0
- package/dist/cli/providers.js +97 -0
- package/dist/cli/providers.js.map +1 -0
- package/dist/cli/queue-purge.d.ts +5 -0
- package/dist/cli/queue-purge.js +92 -0
- package/dist/cli/queue-purge.js.map +1 -0
- package/dist/cli/queue.d.ts +29 -0
- package/dist/cli/queue.js +73 -0
- package/dist/cli/queue.js.map +1 -0
- package/dist/cli/rebuild.d.ts +15 -0
- package/dist/cli/rebuild.js +70 -0
- package/dist/cli/rebuild.js.map +1 -0
- package/dist/cli/reembed-dim.d.ts +21 -0
- package/dist/cli/reembed-dim.js +199 -0
- package/dist/cli/reembed-dim.js.map +1 -0
- package/dist/cli/reinstall.d.ts +1 -0
- package/dist/cli/reinstall.js +205 -0
- package/dist/cli/reinstall.js.map +1 -0
- package/dist/cli/restore.d.ts +1 -0
- package/dist/cli/restore.js +167 -0
- package/dist/cli/restore.js.map +1 -0
- package/dist/cli/retag.d.ts +14 -0
- package/dist/cli/retag.js +62 -0
- package/dist/cli/retag.js.map +1 -0
- package/dist/cli/search.d.ts +66 -0
- package/dist/cli/search.js +174 -0
- package/dist/cli/search.js.map +1 -0
- package/dist/cli/serve.d.ts +9 -0
- package/dist/cli/serve.js +364 -0
- package/dist/cli/serve.js.map +1 -0
- package/dist/cli/service.d.ts +1 -0
- package/dist/cli/service.js +121 -0
- package/dist/cli/service.js.map +1 -0
- package/dist/cli/sync.d.ts +15 -0
- package/dist/cli/sync.js +61 -0
- package/dist/cli/sync.js.map +1 -0
- package/dist/cli/token.d.ts +24 -0
- package/dist/cli/token.js +77 -0
- package/dist/cli/token.js.map +1 -0
- package/dist/cli/wait-health.d.ts +4 -0
- package/dist/cli/wait-health.js +23 -0
- package/dist/cli/wait-health.js.map +1 -0
- package/dist/config/config.d.ts +127 -0
- package/dist/config/config.js +38 -0
- package/dist/config/config.js.map +1 -0
- package/dist/config/datadir.d.ts +30 -0
- package/dist/config/datadir.js +65 -0
- package/dist/config/datadir.js.map +1 -0
- package/dist/config/loader.d.ts +23 -0
- package/dist/config/loader.js +102 -0
- package/dist/config/loader.js.map +1 -0
- package/dist/config/migrate-dirs.d.ts +36 -0
- package/dist/config/migrate-dirs.js +132 -0
- package/dist/config/migrate-dirs.js.map +1 -0
- package/dist/config/persist-envs.d.ts +23 -0
- package/dist/config/persist-envs.js +119 -0
- package/dist/config/persist-envs.js.map +1 -0
- package/dist/config/resolve-runtime.d.ts +19 -0
- package/dist/config/resolve-runtime.js +53 -0
- package/dist/config/resolve-runtime.js.map +1 -0
- package/dist/config/secrets.d.ts +28 -0
- package/dist/config/secrets.js +38 -0
- package/dist/config/secrets.js.map +1 -0
- package/dist/config/sync-settings.d.ts +16 -0
- package/dist/config/sync-settings.js +34 -0
- package/dist/config/sync-settings.js.map +1 -0
- package/dist/config/writer.d.ts +19 -0
- package/dist/config/writer.js +121 -0
- package/dist/config/writer.js.map +1 -0
- package/dist/consolidate/consolidate.d.ts +80 -0
- package/dist/consolidate/consolidate.js +0 -0
- package/dist/consolidate/consolidate.js.map +1 -0
- package/dist/consolidate/proposals.d.ts +35 -0
- package/dist/consolidate/proposals.js +66 -0
- package/dist/consolidate/proposals.js.map +1 -0
- package/dist/contracts/atom-wire.d.ts +48 -0
- package/dist/contracts/atom-wire.js +55 -0
- package/dist/contracts/atom-wire.js.map +1 -0
- package/dist/contracts/embed.d.ts +41 -0
- package/dist/contracts/embed.js +20 -0
- package/dist/contracts/embed.js.map +1 -0
- package/dist/contracts/index.d.ts +5 -0
- package/dist/contracts/index.js +6 -0
- package/dist/contracts/index.js.map +1 -0
- package/dist/contracts/job.d.ts +113 -0
- package/dist/contracts/job.js +32 -0
- package/dist/contracts/job.js.map +1 -0
- package/dist/contracts/llm.d.ts +30 -0
- package/dist/contracts/llm.js +2 -0
- package/dist/contracts/llm.js.map +1 -0
- package/dist/contracts/memory.d.ts +47 -0
- package/dist/contracts/memory.js +5 -0
- package/dist/contracts/memory.js.map +1 -0
- package/dist/contracts/vector.d.ts +29 -0
- package/dist/contracts/vector.js +2 -0
- package/dist/contracts/vector.js.map +1 -0
- package/dist/distill/flatten-turns.d.ts +1 -0
- package/dist/distill/flatten-turns.js +50 -0
- package/dist/distill/flatten-turns.js.map +1 -0
- package/dist/distill/pipeline.d.ts +45 -0
- package/dist/distill/pipeline.js +113 -0
- package/dist/distill/pipeline.js.map +1 -0
- package/dist/distill/prompts/extract.d.ts +122 -0
- package/dist/distill/prompts/extract.js +67 -0
- package/dist/distill/prompts/extract.js.map +1 -0
- package/dist/distill/stages/01-cleanup.d.ts +9 -0
- package/dist/distill/stages/01-cleanup.js +67 -0
- package/dist/distill/stages/01-cleanup.js.map +1 -0
- package/dist/distill/stages/02-normalize.d.ts +9 -0
- package/dist/distill/stages/02-normalize.js +76 -0
- package/dist/distill/stages/02-normalize.js.map +1 -0
- package/dist/distill/stages/03-chunk.d.ts +22 -0
- package/dist/distill/stages/03-chunk.js +138 -0
- package/dist/distill/stages/03-chunk.js.map +1 -0
- package/dist/distill/stages/04-compact.d.ts +28 -0
- package/dist/distill/stages/04-compact.js +69 -0
- package/dist/distill/stages/04-compact.js.map +1 -0
- package/dist/distill/stages/05-extract.d.ts +35 -0
- package/dist/distill/stages/05-extract.js +101 -0
- package/dist/distill/stages/05-extract.js.map +1 -0
- package/dist/distill/stages/06-reduce.d.ts +16 -0
- package/dist/distill/stages/06-reduce.js +30 -0
- package/dist/distill/stages/06-reduce.js.map +1 -0
- package/dist/distill/stages/07-memory-normalize.d.ts +27 -0
- package/dist/distill/stages/07-memory-normalize.js +65 -0
- package/dist/distill/stages/07-memory-normalize.js.map +1 -0
- package/dist/distill/stages/08-embed-index.d.ts +31 -0
- package/dist/distill/stages/08-embed-index.js +82 -0
- package/dist/distill/stages/08-embed-index.js.map +1 -0
- package/dist/doctor/checks.d.ts +77 -0
- package/dist/doctor/checks.js +626 -0
- package/dist/doctor/checks.js.map +1 -0
- package/dist/doctor/hardening-checks.d.ts +9 -0
- package/dist/doctor/hardening-checks.js +182 -0
- package/dist/doctor/hardening-checks.js.map +1 -0
- package/dist/doctor/probes/embed-probe.d.ts +19 -0
- package/dist/doctor/probes/embed-probe.js +47 -0
- package/dist/doctor/probes/embed-probe.js.map +1 -0
- package/dist/doctor/probes/llm-chat-probe.d.ts +11 -0
- package/dist/doctor/probes/llm-chat-probe.js +41 -0
- package/dist/doctor/probes/llm-chat-probe.js.map +1 -0
- package/dist/doctor/probes/plugin-coexistence.d.ts +14 -0
- package/dist/doctor/probes/plugin-coexistence.js +60 -0
- package/dist/doctor/probes/plugin-coexistence.js.map +1 -0
- package/dist/doctor/runner.d.ts +17 -0
- package/dist/doctor/runner.js +53 -0
- package/dist/doctor/runner.js.map +1 -0
- package/dist/doctor/types.d.ts +12 -0
- package/dist/doctor/types.js +2 -0
- package/dist/doctor/types.js.map +1 -0
- package/dist/entity/backfill.d.ts +30 -0
- package/dist/entity/backfill.js +55 -0
- package/dist/entity/backfill.js.map +1 -0
- package/dist/entity/extract-entities.d.ts +27 -0
- package/dist/entity/extract-entities.js +86 -0
- package/dist/entity/extract-entities.js.map +1 -0
- package/dist/entity/normalize.d.ts +17 -0
- package/dist/entity/normalize.js +20 -0
- package/dist/entity/normalize.js.map +1 -0
- package/dist/eval/harness.d.ts +96 -0
- package/dist/eval/harness.js +119 -0
- package/dist/eval/harness.js.map +1 -0
- package/dist/eval/metrics.d.ts +23 -0
- package/dist/eval/metrics.js +44 -0
- package/dist/eval/metrics.js.map +1 -0
- package/dist/log/correlation.d.ts +24 -0
- package/dist/log/correlation.js +33 -0
- package/dist/log/correlation.js.map +1 -0
- package/dist/log/logger.d.ts +38 -0
- package/dist/log/logger.js +129 -0
- package/dist/log/logger.js.map +1 -0
- package/dist/log/scrub.d.ts +33 -0
- package/dist/log/scrub.js +91 -0
- package/dist/log/scrub.js.map +1 -0
- package/dist/mcp/server.d.ts +36 -0
- package/dist/mcp/server.js +553 -0
- package/dist/mcp/server.js.map +1 -0
- package/dist/memory-tool/adapter.d.ts +73 -0
- package/dist/memory-tool/adapter.js +269 -0
- package/dist/memory-tool/adapter.js.map +1 -0
- package/dist/pipeline/errors.d.ts +21 -0
- package/dist/pipeline/errors.js +34 -0
- package/dist/pipeline/errors.js.map +1 -0
- package/dist/pipeline/failure-classifier.d.ts +13 -0
- package/dist/pipeline/failure-classifier.js +72 -0
- package/dist/pipeline/failure-classifier.js.map +1 -0
- package/dist/pipeline/handler-ctx-ext.d.ts +23 -0
- package/dist/pipeline/handler-ctx-ext.js +19 -0
- package/dist/pipeline/handler-ctx-ext.js.map +1 -0
- package/dist/pipeline/handler.d.ts +20 -0
- package/dist/pipeline/handler.js +2 -0
- package/dist/pipeline/handler.js.map +1 -0
- package/dist/pipeline/handlers/cleanup.d.ts +14 -0
- package/dist/pipeline/handlers/cleanup.js +47 -0
- package/dist/pipeline/handlers/cleanup.js.map +1 -0
- package/dist/pipeline/handlers/consolidate.d.ts +8 -0
- package/dist/pipeline/handlers/consolidate.js +23 -0
- package/dist/pipeline/handlers/consolidate.js.map +1 -0
- package/dist/pipeline/handlers/distill-events.d.ts +15 -0
- package/dist/pipeline/handlers/distill-events.js +134 -0
- package/dist/pipeline/handlers/distill-events.js.map +1 -0
- package/dist/pipeline/handlers/distill.d.ts +17 -0
- package/dist/pipeline/handlers/distill.js +110 -0
- package/dist/pipeline/handlers/distill.js.map +1 -0
- package/dist/pipeline/handlers/reembed.d.ts +10 -0
- package/dist/pipeline/handlers/reembed.js +34 -0
- package/dist/pipeline/handlers/reembed.js.map +1 -0
- package/dist/pipeline/job-repo.d.ts +86 -0
- package/dist/pipeline/job-repo.js +168 -0
- package/dist/pipeline/job-repo.js.map +1 -0
- package/dist/pipeline/mock-providers.d.ts +49 -0
- package/dist/pipeline/mock-providers.js +175 -0
- package/dist/pipeline/mock-providers.js.map +1 -0
- package/dist/pipeline/registry.d.ts +15 -0
- package/dist/pipeline/registry.js +20 -0
- package/dist/pipeline/registry.js.map +1 -0
- package/dist/pipeline/worker.d.ts +41 -0
- package/dist/pipeline/worker.js +167 -0
- package/dist/pipeline/worker.js.map +1 -0
- package/dist/providers/embed/azure-openai.d.ts +25 -0
- package/dist/providers/embed/azure-openai.js +138 -0
- package/dist/providers/embed/azure-openai.js.map +1 -0
- package/dist/providers/embed/ollama.d.ts +17 -0
- package/dist/providers/embed/ollama.js +106 -0
- package/dist/providers/embed/ollama.js.map +1 -0
- package/dist/providers/index.d.ts +19 -0
- package/dist/providers/index.js +72 -0
- package/dist/providers/index.js.map +1 -0
- package/dist/providers/llm/azure-openai.d.ts +20 -0
- package/dist/providers/llm/azure-openai.js +135 -0
- package/dist/providers/llm/azure-openai.js.map +1 -0
- package/dist/providers/llm/ollama.d.ts +13 -0
- package/dist/providers/llm/ollama.js +113 -0
- package/dist/providers/llm/ollama.js.map +1 -0
- package/dist/providers/llm/pricing.d.ts +21 -0
- package/dist/providers/llm/pricing.js +22 -0
- package/dist/providers/llm/pricing.js.map +1 -0
- package/dist/recall/pack.d.ts +32 -0
- package/dist/recall/pack.js +90 -0
- package/dist/recall/pack.js.map +1 -0
- package/dist/recall/policy.d.ts +39 -0
- package/dist/recall/policy.js +96 -0
- package/dist/recall/policy.js.map +1 -0
- package/dist/redact/detectors.d.ts +20 -0
- package/dist/redact/detectors.js +85 -0
- package/dist/redact/detectors.js.map +1 -0
- package/dist/redact/entropy.d.ts +24 -0
- package/dist/redact/entropy.js +77 -0
- package/dist/redact/entropy.js.map +1 -0
- package/dist/redact/index.d.ts +47 -0
- package/dist/redact/index.js +165 -0
- package/dist/redact/index.js.map +1 -0
- package/dist/search/fuse.d.ts +108 -0
- package/dist/search/fuse.js +135 -0
- package/dist/search/fuse.js.map +1 -0
- package/dist/search/query.d.ts +28 -0
- package/dist/search/query.js +70 -0
- package/dist/search/query.js.map +1 -0
- package/dist/search/search.d.ts +164 -0
- package/dist/search/search.js +310 -0
- package/dist/search/search.js.map +1 -0
- package/dist/server/app.d.ts +17 -0
- package/dist/server/app.js +133 -0
- package/dist/server/app.js.map +1 -0
- package/dist/server/health-state.d.ts +29 -0
- package/dist/server/health-state.js +28 -0
- package/dist/server/health-state.js.map +1 -0
- package/dist/server/lib/network.d.ts +12 -0
- package/dist/server/lib/network.js +16 -0
- package/dist/server/lib/network.js.map +1 -0
- package/dist/server/lib/score-contract.d.ts +36 -0
- package/dist/server/lib/score-contract.js +54 -0
- package/dist/server/lib/score-contract.js.map +1 -0
- package/dist/server/lib/stable-stringify.d.ts +10 -0
- package/dist/server/lib/stable-stringify.js +27 -0
- package/dist/server/lib/stable-stringify.js.map +1 -0
- package/dist/server/lib/wire-meta.d.ts +7 -0
- package/dist/server/lib/wire-meta.js +29 -0
- package/dist/server/lib/wire-meta.js.map +1 -0
- package/dist/server/queries/dashboard.d.ts +142 -0
- package/dist/server/queries/dashboard.js +166 -0
- package/dist/server/queries/dashboard.js.map +1 -0
- package/dist/server/routes/consolidation.d.ts +14 -0
- package/dist/server/routes/consolidation.js +67 -0
- package/dist/server/routes/consolidation.js.map +1 -0
- package/dist/server/routes/dashboard-api-html.d.ts +15 -0
- package/dist/server/routes/dashboard-api-html.js +144 -0
- package/dist/server/routes/dashboard-api-html.js.map +1 -0
- package/dist/server/routes/dashboard-consolidation-html.d.ts +26 -0
- package/dist/server/routes/dashboard-consolidation-html.js +202 -0
- package/dist/server/routes/dashboard-consolidation-html.js.map +1 -0
- package/dist/server/routes/dashboard-html.d.ts +15 -0
- package/dist/server/routes/dashboard-html.js +365 -0
- package/dist/server/routes/dashboard-html.js.map +1 -0
- package/dist/server/routes/dashboard-jobs-html.d.ts +18 -0
- package/dist/server/routes/dashboard-jobs-html.js +186 -0
- package/dist/server/routes/dashboard-jobs-html.js.map +1 -0
- package/dist/server/routes/dashboard-search-html.d.ts +18 -0
- package/dist/server/routes/dashboard-search-html.js +189 -0
- package/dist/server/routes/dashboard-search-html.js.map +1 -0
- package/dist/server/routes/dashboard.d.ts +19 -0
- package/dist/server/routes/dashboard.js +68 -0
- package/dist/server/routes/dashboard.js.map +1 -0
- package/dist/server/routes/digest.d.ts +9 -0
- package/dist/server/routes/digest.js +37 -0
- package/dist/server/routes/digest.js.map +1 -0
- package/dist/server/routes/entities.d.ts +12 -0
- package/dist/server/routes/entities.js +46 -0
- package/dist/server/routes/entities.js.map +1 -0
- package/dist/server/routes/health.d.ts +14 -0
- package/dist/server/routes/health.js +100 -0
- package/dist/server/routes/health.js.map +1 -0
- package/dist/server/routes/ingest.d.ts +209 -0
- package/dist/server/routes/ingest.js +454 -0
- package/dist/server/routes/ingest.js.map +1 -0
- package/dist/server/routes/lifecycle.d.ts +21 -0
- package/dist/server/routes/lifecycle.js +132 -0
- package/dist/server/routes/lifecycle.js.map +1 -0
- package/dist/server/routes/mcp.d.ts +15 -0
- package/dist/server/routes/mcp.js +36 -0
- package/dist/server/routes/mcp.js.map +1 -0
- package/dist/server/routes/memory-tool.d.ts +14 -0
- package/dist/server/routes/memory-tool.js +28 -0
- package/dist/server/routes/memory-tool.js.map +1 -0
- package/dist/server/routes/memory.d.ts +7 -0
- package/dist/server/routes/memory.js +19 -0
- package/dist/server/routes/memory.js.map +1 -0
- package/dist/server/routes/recall.d.ts +15 -0
- package/dist/server/routes/recall.js +74 -0
- package/dist/server/routes/recall.js.map +1 -0
- package/dist/server/routes/search.d.ts +12 -0
- package/dist/server/routes/search.js +203 -0
- package/dist/server/routes/search.js.map +1 -0
- package/dist/server/routes/version.d.ts +2 -0
- package/dist/server/routes/version.js +11 -0
- package/dist/server/routes/version.js.map +1 -0
- package/dist/server/routes/why.d.ts +9 -0
- package/dist/server/routes/why.js +38 -0
- package/dist/server/routes/why.js.map +1 -0
- package/dist/service/index.d.ts +10 -0
- package/dist/service/index.js +25 -0
- package/dist/service/index.js.map +1 -0
- package/dist/service/install-flow.d.ts +18 -0
- package/dist/service/install-flow.js +47 -0
- package/dist/service/install-flow.js.map +1 -0
- package/dist/service/instance-lock.d.ts +26 -0
- package/dist/service/instance-lock.js +150 -0
- package/dist/service/instance-lock.js.map +1 -0
- package/dist/service/launchd.d.ts +11 -0
- package/dist/service/launchd.js +196 -0
- package/dist/service/launchd.js.map +1 -0
- package/dist/service/schtasks.d.ts +31 -0
- package/dist/service/schtasks.js +274 -0
- package/dist/service/schtasks.js.map +1 -0
- package/dist/service/shim.d.ts +21 -0
- package/dist/service/shim.js +80 -0
- package/dist/service/shim.js.map +1 -0
- package/dist/service/systemd.d.ts +11 -0
- package/dist/service/systemd.js +150 -0
- package/dist/service/systemd.js.map +1 -0
- package/dist/service/task-xml.d.ts +36 -0
- package/dist/service/task-xml.js +91 -0
- package/dist/service/task-xml.js.map +1 -0
- package/dist/service/types.d.ts +47 -0
- package/dist/service/types.js +2 -0
- package/dist/service/types.js.map +1 -0
- package/dist/storage/archival.d.ts +29 -0
- package/dist/storage/archival.js +47 -0
- package/dist/storage/archival.js.map +1 -0
- package/dist/storage/bearer-keystore.d.ts +34 -0
- package/dist/storage/bearer-keystore.js +75 -0
- package/dist/storage/bearer-keystore.js.map +1 -0
- package/dist/storage/db.d.ts +37 -0
- package/dist/storage/db.js +92 -0
- package/dist/storage/db.js.map +1 -0
- package/dist/storage/entities.d.ts +71 -0
- package/dist/storage/entities.js +141 -0
- package/dist/storage/entities.js.map +1 -0
- package/dist/storage/ingest-idempotency.d.ts +26 -0
- package/dist/storage/ingest-idempotency.js +29 -0
- package/dist/storage/ingest-idempotency.js.map +1 -0
- package/dist/storage/keystore.d.ts +64 -0
- package/dist/storage/keystore.js +194 -0
- package/dist/storage/keystore.js.map +1 -0
- package/dist/storage/memories.d.ts +51 -0
- package/dist/storage/memories.js +67 -0
- package/dist/storage/memories.js.map +1 -0
- package/dist/storage/memory-events.d.ts +145 -0
- package/dist/storage/memory-events.js +287 -0
- package/dist/storage/memory-events.js.map +1 -0
- package/dist/storage/migrate-encrypt.d.ts +16 -0
- package/dist/storage/migrate-encrypt.js +121 -0
- package/dist/storage/migrate-encrypt.js.map +1 -0
- package/dist/storage/migrate.d.ts +27 -0
- package/dist/storage/migrate.js +105 -0
- package/dist/storage/migrate.js.map +1 -0
- package/dist/storage/redaction-log.d.ts +18 -0
- package/dist/storage/redaction-log.js +27 -0
- package/dist/storage/redaction-log.js.map +1 -0
- package/dist/storage/usefulness.d.ts +115 -0
- package/dist/storage/usefulness.js +203 -0
- package/dist/storage/usefulness.js.map +1 -0
- package/dist/sync/conflict-resolve.d.ts +26 -0
- package/dist/sync/conflict-resolve.js +139 -0
- package/dist/sync/conflict-resolve.js.map +1 -0
- package/dist/sync/puller.d.ts +115 -0
- package/dist/sync/puller.js +173 -0
- package/dist/sync/puller.js.map +1 -0
- package/dist/sync/shipper.d.ts +112 -0
- package/dist/sync/shipper.js +189 -0
- package/dist/sync/shipper.js.map +1 -0
- package/dist/tag-hygiene/backfill.d.ts +50 -0
- package/dist/tag-hygiene/backfill.js +117 -0
- package/dist/tag-hygiene/backfill.js.map +1 -0
- package/dist/tag-hygiene/derive-repo.d.ts +9 -0
- package/dist/tag-hygiene/derive-repo.js +19 -0
- package/dist/tag-hygiene/derive-repo.js.map +1 -0
- package/dist/tag-hygiene/tier2-infer.d.ts +28 -0
- package/dist/tag-hygiene/tier2-infer.js +72 -0
- package/dist/tag-hygiene/tier2-infer.js.map +1 -0
- package/dist/vector/sqlite-vec.d.ts +16 -0
- package/dist/vector/sqlite-vec.js +49 -0
- package/dist/vector/sqlite-vec.js.map +1 -0
- package/migrations/001-init.sql +117 -0
- package/migrations/002-wire-v1.sql +16 -0
- package/migrations/003-expand-memory-types.sql +81 -0
- package/migrations/004-provenance.sql +4 -0
- package/migrations/005-security.sql +12 -0
- package/migrations/006-atom-v3.sql +28 -0
- package/migrations/007-memory-events.sql +30 -0
- package/migrations/008-consolidation.sql +31 -0
- package/migrations/009-tag-hygiene.sql +13 -0
- package/migrations/010-sync-pull.sql +53 -0
- package/migrations/011-embed-dim-migration.sql +28 -0
- package/migrations/012-entities.sql +36 -0
- package/migrations/013-archival.sql +50 -0
- package/package.json +50 -0
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* hardening-checks.ts — doctor checks matching `reinstall`'s assertions (W1.3).
|
|
3
|
+
*
|
|
4
|
+
* Doctor must be able to see everything reinstall warns about, so a user who
|
|
5
|
+
* only runs doctor still learns about: stranded legacy databases, lingering
|
|
6
|
+
* plaintext encryption backups, a service serving a different build than the
|
|
7
|
+
* repo, zombie instance locks, and accumulating poison jobs.
|
|
8
|
+
*/
|
|
9
|
+
import { existsSync, statSync } from 'node:fs';
|
|
10
|
+
import { join } from 'node:path';
|
|
11
|
+
import { legacyDataDir } from '../config/datadir.js';
|
|
12
|
+
import { readLockInfo } from '../service/instance-lock.js';
|
|
13
|
+
import { PKG_VERSION } from '../server/lib/wire-meta.js';
|
|
14
|
+
export function getHardeningChecks(opts) {
|
|
15
|
+
return [
|
|
16
|
+
checkStrandedLegacyDb(opts.dataDir),
|
|
17
|
+
checkPreEncryptionBak(opts.dataDir),
|
|
18
|
+
checkServedVersion(opts.port),
|
|
19
|
+
checkZombieLock(opts.dataDir),
|
|
20
|
+
checkPoisonJobs(opts.openDbReadonly),
|
|
21
|
+
checkPendingProposals(opts.openDbReadonly),
|
|
22
|
+
];
|
|
23
|
+
}
|
|
24
|
+
/** Consolidation proposals waiting for review — silent pile-up is the failure
|
|
25
|
+
* mode of a scheduled consolidation cadence with no reviewer. */
|
|
26
|
+
function checkPendingProposals(openDbReadonly) {
|
|
27
|
+
return {
|
|
28
|
+
name: 'Consolidation proposals reviewed',
|
|
29
|
+
async run() {
|
|
30
|
+
let db = null;
|
|
31
|
+
try {
|
|
32
|
+
db = await openDbReadonly();
|
|
33
|
+
const row = db.prepare(`SELECT COUNT(*) AS n FROM consolidation_proposals WHERE status = 'pending'`).get();
|
|
34
|
+
if (row.n === 0)
|
|
35
|
+
return { ok: true, message: 'no pending consolidation proposals' };
|
|
36
|
+
return {
|
|
37
|
+
ok: false,
|
|
38
|
+
message: `${row.n} consolidation proposal(s) awaiting review (borderline near-duplicates, 0.94-0.97 similarity)`,
|
|
39
|
+
fix: "Review with 'astramem-local consolidate proposals' then accept/reject",
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
catch (err) {
|
|
43
|
+
return { ok: true, message: `proposal check skipped: ${err instanceof Error ? err.message : String(err)}` };
|
|
44
|
+
}
|
|
45
|
+
finally {
|
|
46
|
+
try {
|
|
47
|
+
db?.close();
|
|
48
|
+
}
|
|
49
|
+
catch { /* ignore */ }
|
|
50
|
+
}
|
|
51
|
+
},
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
/** Legacy data dir still holds a database that is NOT the one being served. */
|
|
55
|
+
function checkStrandedLegacyDb(dataDir) {
|
|
56
|
+
return {
|
|
57
|
+
name: 'No stranded legacy database',
|
|
58
|
+
async run() {
|
|
59
|
+
const legacy = legacyDataDir();
|
|
60
|
+
const legacyDb = join(legacy, 'memory.sqlite');
|
|
61
|
+
if (legacy === dataDir || !existsSync(legacyDb)) {
|
|
62
|
+
return { ok: true, message: 'no legacy database present' };
|
|
63
|
+
}
|
|
64
|
+
const st = statSync(legacyDb);
|
|
65
|
+
const kb = Math.round(st.size / 1024);
|
|
66
|
+
return {
|
|
67
|
+
ok: false,
|
|
68
|
+
message: `legacy dir still holds a ${kb}KB database: ${legacyDb} (mtime ${st.mtime.toISOString()})`,
|
|
69
|
+
fix: `Verify the served DB at ${join(dataDir, 'memory.sqlite')} contains your real data, then delete the legacy dir`,
|
|
70
|
+
};
|
|
71
|
+
},
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
/** Plaintext pre-encryption backup lingering next to the encrypted DB. */
|
|
75
|
+
function checkPreEncryptionBak(dataDir) {
|
|
76
|
+
return {
|
|
77
|
+
name: 'No plaintext pre-encryption backup',
|
|
78
|
+
async run() {
|
|
79
|
+
const bak = join(dataDir, 'memory.sqlite.pre-encryption.bak');
|
|
80
|
+
if (!existsSync(bak))
|
|
81
|
+
return { ok: true, message: 'no pre-encryption backup present' };
|
|
82
|
+
const ageDays = (Date.now() - statSync(bak).mtimeMs) / (24 * 60 * 60 * 1000);
|
|
83
|
+
return {
|
|
84
|
+
ok: false,
|
|
85
|
+
message: `PLAINTEXT copy of the database still on disk (${ageDays.toFixed(1)}d old): ${bak}`,
|
|
86
|
+
fix: 'serve auto-deletes it after 7 days; delete manually once the encrypted DB is verified',
|
|
87
|
+
};
|
|
88
|
+
},
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
/** Daemon serves a different build than the one running doctor. */
|
|
92
|
+
function checkServedVersion(port) {
|
|
93
|
+
return {
|
|
94
|
+
name: 'Served version matches this build',
|
|
95
|
+
async run() {
|
|
96
|
+
let body;
|
|
97
|
+
try {
|
|
98
|
+
const res = await fetch(`http://127.0.0.1:${port}/version`, { signal: AbortSignal.timeout(2000) });
|
|
99
|
+
body = (await res.json());
|
|
100
|
+
}
|
|
101
|
+
catch {
|
|
102
|
+
return { ok: true, message: 'daemon not reachable — version check skipped' };
|
|
103
|
+
}
|
|
104
|
+
if (body.version === PKG_VERSION) {
|
|
105
|
+
return { ok: true, message: `daemon serving v${body.version} (matches build)` };
|
|
106
|
+
}
|
|
107
|
+
return {
|
|
108
|
+
ok: false,
|
|
109
|
+
message: `daemon serves v${body.version} but this build is v${PKG_VERSION} — a different install is running`,
|
|
110
|
+
fix: "Run 'astramem-local reinstall' from the build you want (stale global installs shadow the repo build)",
|
|
111
|
+
};
|
|
112
|
+
},
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
/** daemon.lock held by a dead or unresponsive process. */
|
|
116
|
+
function checkZombieLock(dataDir) {
|
|
117
|
+
return {
|
|
118
|
+
name: 'Instance lock healthy',
|
|
119
|
+
async run() {
|
|
120
|
+
const holder = readLockInfo(dataDir);
|
|
121
|
+
if (!holder)
|
|
122
|
+
return { ok: true, message: 'no daemon.lock (daemon not running)' };
|
|
123
|
+
let alive = true;
|
|
124
|
+
try {
|
|
125
|
+
process.kill(holder.pid, 0);
|
|
126
|
+
}
|
|
127
|
+
catch {
|
|
128
|
+
alive = false;
|
|
129
|
+
}
|
|
130
|
+
if (!alive) {
|
|
131
|
+
return {
|
|
132
|
+
ok: false,
|
|
133
|
+
message: `daemon.lock held by dead pid ${holder.pid} — stale (self-heals on next serve)`,
|
|
134
|
+
fix: "Start the daemon ('astramem-local service start' or 'reinstall'); the stale lock is stolen automatically",
|
|
135
|
+
};
|
|
136
|
+
}
|
|
137
|
+
try {
|
|
138
|
+
const res = await fetch(`http://127.0.0.1:${holder.port}/health`, { signal: AbortSignal.timeout(2000) });
|
|
139
|
+
if (res.ok)
|
|
140
|
+
return { ok: true, message: `lock held by pid ${holder.pid}, daemon healthy on :${holder.port}` };
|
|
141
|
+
}
|
|
142
|
+
catch {
|
|
143
|
+
/* fall through */
|
|
144
|
+
}
|
|
145
|
+
return {
|
|
146
|
+
ok: false,
|
|
147
|
+
message: `daemon.lock pid ${holder.pid} is alive but /health on :${holder.port} is unresponsive (zombie)`,
|
|
148
|
+
fix: `Kill pid ${holder.pid} and restart the service`,
|
|
149
|
+
};
|
|
150
|
+
},
|
|
151
|
+
};
|
|
152
|
+
}
|
|
153
|
+
/** Poisoned jobs accumulating in the queue. */
|
|
154
|
+
function checkPoisonJobs(openDbReadonly) {
|
|
155
|
+
return {
|
|
156
|
+
name: 'No poisoned jobs',
|
|
157
|
+
async run() {
|
|
158
|
+
let db = null;
|
|
159
|
+
try {
|
|
160
|
+
db = await openDbReadonly();
|
|
161
|
+
const row = db.prepare(`SELECT COUNT(*) AS n FROM jobs WHERE state = 'poison'`).get();
|
|
162
|
+
if (row.n === 0)
|
|
163
|
+
return { ok: true, message: 'no poisoned jobs' };
|
|
164
|
+
return {
|
|
165
|
+
ok: false,
|
|
166
|
+
message: `${row.n} poisoned job(s) in the queue (retries exhausted or deterministic failure)`,
|
|
167
|
+
fix: "Inspect with 'astramem-local queue'; purged automatically after 30 days",
|
|
168
|
+
};
|
|
169
|
+
}
|
|
170
|
+
catch (err) {
|
|
171
|
+
return { ok: true, message: `poison check skipped: ${err instanceof Error ? err.message : String(err)}` };
|
|
172
|
+
}
|
|
173
|
+
finally {
|
|
174
|
+
try {
|
|
175
|
+
db?.close();
|
|
176
|
+
}
|
|
177
|
+
catch { /* ignore */ }
|
|
178
|
+
}
|
|
179
|
+
},
|
|
180
|
+
};
|
|
181
|
+
}
|
|
182
|
+
//# sourceMappingURL=hardening-checks.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hardening-checks.js","sourceRoot":"","sources":["../../src/doctor/hardening-checks.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAC/C,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAGjC,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAC3D,OAAO,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAC;AASzD,MAAM,UAAU,kBAAkB,CAAC,IAAwB;IACzD,OAAO;QACL,qBAAqB,CAAC,IAAI,CAAC,OAAO,CAAC;QACnC,qBAAqB,CAAC,IAAI,CAAC,OAAO,CAAC;QACnC,kBAAkB,CAAC,IAAI,CAAC,IAAI,CAAC;QAC7B,eAAe,CAAC,IAAI,CAAC,OAAO,CAAC;QAC7B,eAAe,CAAC,IAAI,CAAC,cAAc,CAAC;QACpC,qBAAqB,CAAC,IAAI,CAAC,cAAc,CAAC;KAC3C,CAAC;AACJ,CAAC;AAED;kEACkE;AAClE,SAAS,qBAAqB,CAAC,cAAiC;IAC9D,OAAO;QACL,IAAI,EAAE,kCAAkC;QACxC,KAAK,CAAC,GAAG;YACP,IAAI,EAAE,GAAc,IAAI,CAAC;YACzB,IAAI,CAAC;gBACH,EAAE,GAAG,MAAM,cAAc,EAAE,CAAC;gBAC5B,MAAM,GAAG,GAAG,EAAE,CAAC,OAAO,CACpB,4EAA4E,CAC7E,CAAC,GAAG,EAAmB,CAAC;gBACzB,IAAI,GAAG,CAAC,CAAC,KAAK,CAAC;oBAAE,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,oCAAoC,EAAE,CAAC;gBACpF,OAAO;oBACL,EAAE,EAAE,KAAK;oBACT,OAAO,EAAE,GAAG,GAAG,CAAC,CAAC,+FAA+F;oBAChH,GAAG,EAAE,uEAAuE;iBAC7E,CAAC;YACJ,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,2BAA2B,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;YAC9G,CAAC;oBAAS,CAAC;gBACT,IAAI,CAAC;oBAAC,EAAE,EAAE,KAAK,EAAE,CAAC;gBAAC,CAAC;gBAAC,MAAM,CAAC,CAAC,YAAY,CAAC,CAAC;YAC7C,CAAC;QACH,CAAC;KACF,CAAC;AACJ,CAAC;AAED,+EAA+E;AAC/E,SAAS,qBAAqB,CAAC,OAAe;IAC5C,OAAO;QACL,IAAI,EAAE,6BAA6B;QACnC,KAAK,CAAC,GAAG;YACP,MAAM,MAAM,GAAG,aAAa,EAAE,CAAC;YAC/B,MAAM,QAAQ,GAAG,IAAI,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC;YAC/C,IAAI,MAAM,KAAK,OAAO,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;gBAChD,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,4BAA4B,EAAE,CAAC;YAC7D,CAAC;YACD,MAAM,EAAE,GAAG,QAAQ,CAAC,QAAQ,CAAC,CAAC;YAC9B,MAAM,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,IAAI,GAAG,IAAI,CAAC,CAAC;YACtC,OAAO;gBACL,EAAE,EAAE,KAAK;gBACT,OAAO,EAAE,4BAA4B,EAAE,gBAAgB,QAAQ,WAAW,EAAE,CAAC,KAAK,CAAC,WAAW,EAAE,GAAG;gBACnG,GAAG,EAAE,2BAA2B,IAAI,CAAC,OAAO,EAAE,eAAe,CAAC,sDAAsD;aACrH,CAAC;QACJ,CAAC;KACF,CAAC;AACJ,CAAC;AAED,0EAA0E;AAC1E,SAAS,qBAAqB,CAAC,OAAe;IAC5C,OAAO;QACL,IAAI,EAAE,oCAAoC;QAC1C,KAAK,CAAC,GAAG;YACP,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,EAAE,kCAAkC,CAAC,CAAC;YAC9D,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC;gBAAE,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,kCAAkC,EAAE,CAAC;YACvF,MAAM,OAAO,GAAG,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC;YAC7E,OAAO;gBACL,EAAE,EAAE,KAAK;gBACT,OAAO,EAAE,iDAAiD,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,WAAW,GAAG,EAAE;gBAC5F,GAAG,EAAE,uFAAuF;aAC7F,CAAC;QACJ,CAAC;KACF,CAAC;AACJ,CAAC;AAED,mEAAmE;AACnE,SAAS,kBAAkB,CAAC,IAAY;IACtC,OAAO;QACL,IAAI,EAAE,mCAAmC;QACzC,KAAK,CAAC,GAAG;YACP,IAAI,IAA0B,CAAC;YAC/B,IAAI,CAAC;gBACH,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,oBAAoB,IAAI,UAAU,EAAE,EAAE,MAAM,EAAE,WAAW,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;gBACnG,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAAyB,CAAC;YACpD,CAAC;YAAC,MAAM,CAAC;gBACP,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,8CAA8C,EAAE,CAAC;YAC/E,CAAC;YACD,IAAI,IAAI,CAAC,OAAO,KAAK,WAAW,EAAE,CAAC;gBACjC,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,mBAAmB,IAAI,CAAC,OAAO,kBAAkB,EAAE,CAAC;YAClF,CAAC;YACD,OAAO;gBACL,EAAE,EAAE,KAAK;gBACT,OAAO,EAAE,kBAAkB,IAAI,CAAC,OAAO,uBAAuB,WAAW,mCAAmC;gBAC5G,GAAG,EAAE,sGAAsG;aAC5G,CAAC;QACJ,CAAC;KACF,CAAC;AACJ,CAAC;AAED,0DAA0D;AAC1D,SAAS,eAAe,CAAC,OAAe;IACtC,OAAO;QACL,IAAI,EAAE,uBAAuB;QAC7B,KAAK,CAAC,GAAG;YACP,MAAM,MAAM,GAAG,YAAY,CAAC,OAAO,CAAC,CAAC;YACrC,IAAI,CAAC,MAAM;gBAAE,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,qCAAqC,EAAE,CAAC;YACjF,IAAI,KAAK,GAAG,IAAI,CAAC;YACjB,IAAI,CAAC;gBACH,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;YAC9B,CAAC;YAAC,MAAM,CAAC;gBACP,KAAK,GAAG,KAAK,CAAC;YAChB,CAAC;YACD,IAAI,CAAC,KAAK,EAAE,CAAC;gBACX,OAAO;oBACL,EAAE,EAAE,KAAK;oBACT,OAAO,EAAE,gCAAgC,MAAM,CAAC,GAAG,qCAAqC;oBACxF,GAAG,EAAE,0GAA0G;iBAChH,CAAC;YACJ,CAAC;YACD,IAAI,CAAC;gBACH,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,oBAAoB,MAAM,CAAC,IAAI,SAAS,EAAE,EAAE,MAAM,EAAE,WAAW,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;gBACzG,IAAI,GAAG,CAAC,EAAE;oBAAE,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,oBAAoB,MAAM,CAAC,GAAG,wBAAwB,MAAM,CAAC,IAAI,EAAE,EAAE,CAAC;YAChH,CAAC;YAAC,MAAM,CAAC;gBACP,kBAAkB;YACpB,CAAC;YACD,OAAO;gBACL,EAAE,EAAE,KAAK;gBACT,OAAO,EAAE,mBAAmB,MAAM,CAAC,GAAG,6BAA6B,MAAM,CAAC,IAAI,2BAA2B;gBACzG,GAAG,EAAE,YAAY,MAAM,CAAC,GAAG,0BAA0B;aACtD,CAAC;QACJ,CAAC;KACF,CAAC;AACJ,CAAC;AAED,+CAA+C;AAC/C,SAAS,eAAe,CAAC,cAAiC;IACxD,OAAO;QACL,IAAI,EAAE,kBAAkB;QACxB,KAAK,CAAC,GAAG;YACP,IAAI,EAAE,GAAc,IAAI,CAAC;YACzB,IAAI,CAAC;gBACH,EAAE,GAAG,MAAM,cAAc,EAAE,CAAC;gBAC5B,MAAM,GAAG,GAAG,EAAE,CAAC,OAAO,CAAC,uDAAuD,CAAC,CAAC,GAAG,EAAmB,CAAC;gBACvG,IAAI,GAAG,CAAC,CAAC,KAAK,CAAC;oBAAE,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,kBAAkB,EAAE,CAAC;gBAClE,OAAO;oBACL,EAAE,EAAE,KAAK;oBACT,OAAO,EAAE,GAAG,GAAG,CAAC,CAAC,4EAA4E;oBAC7F,GAAG,EAAE,yEAAyE;iBAC/E,CAAC;YACJ,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,yBAAyB,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;YAC5G,CAAC;oBAAS,CAAC;gBACT,IAAI,CAAC;oBAAC,EAAE,EAAE,KAAK,EAAE,CAAC;gBAAC,CAAC;gBAAC,MAAM,CAAC,CAAC,YAAY,CAAC,CAAC;YAC7C,CAAC;QACH,CAAC;KACF,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { EmbedProvider } from '../../contracts/embed.js';
|
|
2
|
+
import type { CheckResult } from '../types.js';
|
|
3
|
+
/**
|
|
4
|
+
* Embed probe: sends a real embedding call to the configured provider.
|
|
5
|
+
*
|
|
6
|
+
* Validates that the provider is reachable, the model is loaded, and the
|
|
7
|
+
* returned vector matches the expected dim. A dim mismatch indicates a
|
|
8
|
+
* provider misconfiguration (wrong model, wrong dimensions parameter for
|
|
9
|
+
* Azure, or a stale config after an un-migrated `embedding.dim` edit)
|
|
10
|
+
* before it silently corrupts vector search.
|
|
11
|
+
*
|
|
12
|
+
* FEAT-409: `expectedDim` defaults to `provider.dim` — the provider was
|
|
13
|
+
* itself constructed from config.embedding.dim (providers/index.ts), so
|
|
14
|
+
* this stays config-derived without every caller needing to thread it
|
|
15
|
+
* through explicitly. Pass it explicitly to check against a DIFFERENT
|
|
16
|
+
* expectation (e.g. the schema dim of a DB the provider hasn't been
|
|
17
|
+
* pointed at yet).
|
|
18
|
+
*/
|
|
19
|
+
export declare function embedProbe(provider: EmbedProvider, timeoutMs?: number, expectedDim?: number): Promise<CheckResult>;
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Embed probe: sends a real embedding call to the configured provider.
|
|
3
|
+
*
|
|
4
|
+
* Validates that the provider is reachable, the model is loaded, and the
|
|
5
|
+
* returned vector matches the expected dim. A dim mismatch indicates a
|
|
6
|
+
* provider misconfiguration (wrong model, wrong dimensions parameter for
|
|
7
|
+
* Azure, or a stale config after an un-migrated `embedding.dim` edit)
|
|
8
|
+
* before it silently corrupts vector search.
|
|
9
|
+
*
|
|
10
|
+
* FEAT-409: `expectedDim` defaults to `provider.dim` — the provider was
|
|
11
|
+
* itself constructed from config.embedding.dim (providers/index.ts), so
|
|
12
|
+
* this stays config-derived without every caller needing to thread it
|
|
13
|
+
* through explicitly. Pass it explicitly to check against a DIFFERENT
|
|
14
|
+
* expectation (e.g. the schema dim of a DB the provider hasn't been
|
|
15
|
+
* pointed at yet).
|
|
16
|
+
*/
|
|
17
|
+
export async function embedProbe(provider, timeoutMs = 5000, expectedDim = provider.dim) {
|
|
18
|
+
try {
|
|
19
|
+
const start = Date.now();
|
|
20
|
+
const vecs = await Promise.race([
|
|
21
|
+
provider.embed(['ping']),
|
|
22
|
+
new Promise((_, rej) => setTimeout(() => rej(new Error('timeout')), timeoutMs)),
|
|
23
|
+
]);
|
|
24
|
+
const latency = Date.now() - start;
|
|
25
|
+
const vec = vecs[0];
|
|
26
|
+
if (!vec || vec.length !== expectedDim) {
|
|
27
|
+
return {
|
|
28
|
+
ok: false,
|
|
29
|
+
message: `${provider.name}: dim ${vec?.length ?? 0}, expected ${expectedDim}`,
|
|
30
|
+
fix: 'Misconfigured embed provider — check model and dimensions setting',
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
return {
|
|
34
|
+
ok: true,
|
|
35
|
+
message: `${provider.name}/${provider.model} returned ${expectedDim}-dim in ${latency}ms`,
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
catch (err) {
|
|
39
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
40
|
+
return {
|
|
41
|
+
ok: false,
|
|
42
|
+
message: `${provider.name}: ${msg}`,
|
|
43
|
+
fix: 'Check provider config + model',
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
//# sourceMappingURL=embed-probe.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"embed-probe.js","sourceRoot":"","sources":["../../../src/doctor/probes/embed-probe.ts"],"names":[],"mappings":"AAGA;;;;;;;;;;;;;;;GAeG;AACH,MAAM,CAAC,KAAK,UAAU,UAAU,CAC9B,QAAuB,EACvB,SAAS,GAAG,IAAI,EAChB,cAAsB,QAAQ,CAAC,GAAG;IAElC,IAAI,CAAC;QACH,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QACzB,MAAM,IAAI,GAAG,MAAM,OAAO,CAAC,IAAI,CAAC;YAC9B,QAAQ,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,CAAC;YACxB,IAAI,OAAO,CAAQ,CAAC,CAAC,EAAE,GAAG,EAAE,EAAE,CAC5B,UAAU,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,IAAI,KAAK,CAAC,SAAS,CAAC,CAAC,EAAE,SAAS,CAAC,CACvD;SACF,CAAC,CAAC;QACH,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK,CAAC;QAEnC,MAAM,GAAG,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;QACpB,IAAI,CAAC,GAAG,IAAI,GAAG,CAAC,MAAM,KAAK,WAAW,EAAE,CAAC;YACvC,OAAO;gBACL,EAAE,EAAE,KAAK;gBACT,OAAO,EAAE,GAAG,QAAQ,CAAC,IAAI,SAAS,GAAG,EAAE,MAAM,IAAI,CAAC,cAAc,WAAW,EAAE;gBAC7E,GAAG,EAAE,mEAAmE;aACzE,CAAC;QACJ,CAAC;QAED,OAAO;YACL,EAAE,EAAE,IAAI;YACR,OAAO,EAAE,GAAG,QAAQ,CAAC,IAAI,IAAI,QAAQ,CAAC,KAAK,aAAa,WAAW,WAAW,OAAO,IAAI;SAC1F,CAAC;IACJ,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,GAAG,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QAC7D,OAAO;YACL,EAAE,EAAE,KAAK;YACT,OAAO,EAAE,GAAG,QAAQ,CAAC,IAAI,KAAK,GAAG,EAAE;YACnC,GAAG,EAAE,+BAA+B;SACrC,CAAC;IACJ,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { LLMProvider } from '../../contracts/llm.js';
|
|
2
|
+
import type { CheckResult } from '../types.js';
|
|
3
|
+
/**
|
|
4
|
+
* LLM chat probe: sends a real 1-token chat request to the configured provider.
|
|
5
|
+
*
|
|
6
|
+
* This replaces surface-only `/api/tags` checks — the model may be listed but
|
|
7
|
+
* unloaded, or the name may mismatch (qwen2.5-coder vs qwen2.5-coder:7b).
|
|
8
|
+
* A real chat call exercises the full path: model loaded, prompt handled,
|
|
9
|
+
* response non-empty.
|
|
10
|
+
*/
|
|
11
|
+
export declare function llmChatProbe(provider: LLMProvider, timeoutMs?: number): Promise<CheckResult>;
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* LLM chat probe: sends a real 1-token chat request to the configured provider.
|
|
3
|
+
*
|
|
4
|
+
* This replaces surface-only `/api/tags` checks — the model may be listed but
|
|
5
|
+
* unloaded, or the name may mismatch (qwen2.5-coder vs qwen2.5-coder:7b).
|
|
6
|
+
* A real chat call exercises the full path: model loaded, prompt handled,
|
|
7
|
+
* response non-empty.
|
|
8
|
+
*/
|
|
9
|
+
export async function llmChatProbe(provider, timeoutMs = 5000) {
|
|
10
|
+
try {
|
|
11
|
+
const start = Date.now();
|
|
12
|
+
const result = await Promise.race([
|
|
13
|
+
provider.chat([{ role: 'user', content: '1' }], {
|
|
14
|
+
maxTokens: 1,
|
|
15
|
+
temperature: 0,
|
|
16
|
+
}),
|
|
17
|
+
new Promise((_, rej) => setTimeout(() => rej(new Error('timeout')), timeoutMs)),
|
|
18
|
+
]);
|
|
19
|
+
const latency = Date.now() - start;
|
|
20
|
+
if (!result.text || result.text.trim().length === 0) {
|
|
21
|
+
return {
|
|
22
|
+
ok: false,
|
|
23
|
+
message: `${provider.name}/${provider.model}: empty response`,
|
|
24
|
+
fix: 'Check model is loaded (ollama run <model>) and responding',
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
return {
|
|
28
|
+
ok: true,
|
|
29
|
+
message: `${provider.name}/${provider.model} responded in ${latency}ms`,
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
catch (err) {
|
|
33
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
34
|
+
return {
|
|
35
|
+
ok: false,
|
|
36
|
+
message: `${provider.name}/${provider.model}: ${msg}`,
|
|
37
|
+
fix: 'Check provider config and model availability',
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
//# sourceMappingURL=llm-chat-probe.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"llm-chat-probe.js","sourceRoot":"","sources":["../../../src/doctor/probes/llm-chat-probe.ts"],"names":[],"mappings":"AAGA;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY,CAChC,QAAqB,EACrB,SAAS,GAAG,IAAI;IAEhB,IAAI,CAAC;QACH,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QACzB,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,IAAI,CAAC;YAChC,QAAQ,CAAC,IAAI,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC,EAAE;gBAC9C,SAAS,EAAE,CAAC;gBACZ,WAAW,EAAE,CAAC;aACf,CAAC;YACF,IAAI,OAAO,CAAQ,CAAC,CAAC,EAAE,GAAG,EAAE,EAAE,CAC5B,UAAU,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,IAAI,KAAK,CAAC,SAAS,CAAC,CAAC,EAAE,SAAS,CAAC,CACvD;SACF,CAAC,CAAC;QACH,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK,CAAC;QAEnC,IAAI,CAAC,MAAM,CAAC,IAAI,IAAI,MAAM,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACpD,OAAO;gBACL,EAAE,EAAE,KAAK;gBACT,OAAO,EAAE,GAAG,QAAQ,CAAC,IAAI,IAAI,QAAQ,CAAC,KAAK,kBAAkB;gBAC7D,GAAG,EAAE,2DAA2D;aACjE,CAAC;QACJ,CAAC;QAED,OAAO;YACL,EAAE,EAAE,IAAI;YACR,OAAO,EAAE,GAAG,QAAQ,CAAC,IAAI,IAAI,QAAQ,CAAC,KAAK,iBAAiB,OAAO,IAAI;SACxE,CAAC;IACJ,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,GAAG,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QAC7D,OAAO;YACL,EAAE,EAAE,KAAK;YACT,OAAO,EAAE,GAAG,QAAQ,CAAC,IAAI,IAAI,QAAQ,CAAC,KAAK,KAAK,GAAG,EAAE;YACrD,GAAG,EAAE,8CAA8C;SACpD,CAAC;IACJ,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { CheckResult } from '../types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Plugin coexistence probe: detects silent URL mismatches between the running
|
|
4
|
+
* daemon and any plugin config that might route traffic elsewhere.
|
|
5
|
+
*
|
|
6
|
+
* Checks:
|
|
7
|
+
* 1. MEMORY_API_URL env — if set, must point at this daemon's loopback:port.
|
|
8
|
+
* 2. Common .mcp.json locations — if found, the mcpServers.memory.url must
|
|
9
|
+
* point at this daemon's port, not a SaaS endpoint or different port.
|
|
10
|
+
*
|
|
11
|
+
* Risk addressed: spec risk #4 — user with both SaaS and local plugin config
|
|
12
|
+
* gets silent ambiguity about which backend their queries hit.
|
|
13
|
+
*/
|
|
14
|
+
export declare function pluginCoexistenceProbe(daemonPort: number): Promise<CheckResult>;
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { existsSync, readFileSync } from 'node:fs';
|
|
2
|
+
import { join } from 'node:path';
|
|
3
|
+
import { homedir } from 'node:os';
|
|
4
|
+
/**
|
|
5
|
+
* Plugin coexistence probe: detects silent URL mismatches between the running
|
|
6
|
+
* daemon and any plugin config that might route traffic elsewhere.
|
|
7
|
+
*
|
|
8
|
+
* Checks:
|
|
9
|
+
* 1. MEMORY_API_URL env — if set, must point at this daemon's loopback:port.
|
|
10
|
+
* 2. Common .mcp.json locations — if found, the mcpServers.memory.url must
|
|
11
|
+
* point at this daemon's port, not a SaaS endpoint or different port.
|
|
12
|
+
*
|
|
13
|
+
* Risk addressed: spec risk #4 — user with both SaaS and local plugin config
|
|
14
|
+
* gets silent ambiguity about which backend their queries hit.
|
|
15
|
+
*/
|
|
16
|
+
export async function pluginCoexistenceProbe(daemonPort) {
|
|
17
|
+
const indicators = [];
|
|
18
|
+
// ── 1. MEMORY_API_URL env ──────────────────────────────────────────────────
|
|
19
|
+
const envUrl = process.env.MEMORY_API_URL;
|
|
20
|
+
if (envUrl) {
|
|
21
|
+
const pointsHere = envUrl.includes(`127.0.0.1:${daemonPort}`) ||
|
|
22
|
+
envUrl.includes(`localhost:${daemonPort}`);
|
|
23
|
+
if (!pointsHere) {
|
|
24
|
+
indicators.push(`MEMORY_API_URL=${envUrl} (not pointing at this daemon at :${daemonPort})`);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
// ── 2. Scan likely .mcp.json locations ────────────────────────────────────
|
|
28
|
+
const candidates = [
|
|
29
|
+
join(homedir(), '.claude', 'plugins', 'memory-plugin', '.mcp.json'),
|
|
30
|
+
join(process.cwd(), '.mcp.json'),
|
|
31
|
+
join(homedir(), 'mega', 'astramemory-plugin', '.mcp.json'),
|
|
32
|
+
];
|
|
33
|
+
for (const candidate of candidates) {
|
|
34
|
+
if (existsSync(candidate)) {
|
|
35
|
+
try {
|
|
36
|
+
const raw = readFileSync(candidate, 'utf8');
|
|
37
|
+
const content = JSON.parse(raw);
|
|
38
|
+
const memUrl = content.mcpServers?.['memory']?.url;
|
|
39
|
+
if (memUrl &&
|
|
40
|
+
!memUrl.includes(`127.0.0.1:${daemonPort}`) &&
|
|
41
|
+
!memUrl.includes(`localhost:${daemonPort}`)) {
|
|
42
|
+
indicators.push(`Plugin .mcp.json at ${candidate} points at ${memUrl}, not this daemon`);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
catch {
|
|
46
|
+
// JSON parse errors are non-fatal — file may be from another plugin
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
// ── Result ────────────────────────────────────────────────────────────────
|
|
51
|
+
if (indicators.length > 0) {
|
|
52
|
+
return {
|
|
53
|
+
ok: false,
|
|
54
|
+
message: `Plugin config does not point at this daemon: ${indicators.join('; ')}`,
|
|
55
|
+
fix: `Set MEMORY_API_URL=http://127.0.0.1:${daemonPort} and update plugin .mcp.json`,
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
return { ok: true, message: 'Plugin config aligned with daemon port' };
|
|
59
|
+
}
|
|
60
|
+
//# sourceMappingURL=plugin-coexistence.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plugin-coexistence.js","sourceRoot":"","sources":["../../../src/doctor/probes/plugin-coexistence.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACnD,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAOlC;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,KAAK,UAAU,sBAAsB,CAC1C,UAAkB;IAElB,MAAM,UAAU,GAAa,EAAE,CAAC;IAEhC,8EAA8E;IAC9E,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC;IAC1C,IAAI,MAAM,EAAE,CAAC;QACX,MAAM,UAAU,GACd,MAAM,CAAC,QAAQ,CAAC,aAAa,UAAU,EAAE,CAAC;YAC1C,MAAM,CAAC,QAAQ,CAAC,aAAa,UAAU,EAAE,CAAC,CAAC;QAC7C,IAAI,CAAC,UAAU,EAAE,CAAC;YAChB,UAAU,CAAC,IAAI,CACb,kBAAkB,MAAM,qCAAqC,UAAU,GAAG,CAC3E,CAAC;QACJ,CAAC;IACH,CAAC;IAED,6EAA6E;IAC7E,MAAM,UAAU,GAAG;QACjB,IAAI,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,SAAS,EAAE,eAAe,EAAE,WAAW,CAAC;QACnE,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,WAAW,CAAC;QAChC,IAAI,CAAC,OAAO,EAAE,EAAE,MAAM,EAAE,oBAAoB,EAAE,WAAW,CAAC;KAC3D,CAAC;IAEF,KAAK,MAAM,SAAS,IAAI,UAAU,EAAE,CAAC;QACnC,IAAI,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;YAC1B,IAAI,CAAC;gBACH,MAAM,GAAG,GAAG,YAAY,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC;gBAC5C,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAY,CAAC;gBAC3C,MAAM,MAAM,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC,QAAQ,CAAC,EAAE,GAAG,CAAC;gBACnD,IACE,MAAM;oBACN,CAAC,MAAM,CAAC,QAAQ,CAAC,aAAa,UAAU,EAAE,CAAC;oBAC3C,CAAC,MAAM,CAAC,QAAQ,CAAC,aAAa,UAAU,EAAE,CAAC,EAC3C,CAAC;oBACD,UAAU,CAAC,IAAI,CACb,uBAAuB,SAAS,cAAc,MAAM,mBAAmB,CACxE,CAAC;gBACJ,CAAC;YACH,CAAC;YAAC,MAAM,CAAC;gBACP,oEAAoE;YACtE,CAAC;QACH,CAAC;IACH,CAAC;IAED,6EAA6E;IAC7E,IAAI,UAAU,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC1B,OAAO;YACL,EAAE,EAAE,KAAK;YACT,OAAO,EAAE,gDAAgD,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE;YAChF,GAAG,EACD,uCAAuC,UAAU,8BAA8B;SAClF,CAAC;IACJ,CAAC;IAED,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,wCAAwC,EAAE,CAAC;AACzE,CAAC"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { Check, CheckResult } from './types.js';
|
|
2
|
+
export interface CheckResultWithName extends CheckResult {
|
|
3
|
+
name: string;
|
|
4
|
+
}
|
|
5
|
+
/**
|
|
6
|
+
* Run all checks, catching any unexpected errors and surfacing them as failures.
|
|
7
|
+
*/
|
|
8
|
+
export declare function runChecks(checks: Check[]): Promise<CheckResultWithName[]>;
|
|
9
|
+
/**
|
|
10
|
+
* Format results as a human-readable table for terminal output.
|
|
11
|
+
*/
|
|
12
|
+
export declare function formatTable(results: CheckResultWithName[]): string;
|
|
13
|
+
/**
|
|
14
|
+
* Format results as machine-readable JSON.
|
|
15
|
+
* Shape: { checks: [{name, ok, message, fix?}], summary: {ok: N, fail: M} }
|
|
16
|
+
*/
|
|
17
|
+
export declare function formatJson(results: CheckResultWithName[]): string;
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Run all checks, catching any unexpected errors and surfacing them as failures.
|
|
3
|
+
*/
|
|
4
|
+
export async function runChecks(checks) {
|
|
5
|
+
const results = [];
|
|
6
|
+
for (const check of checks) {
|
|
7
|
+
try {
|
|
8
|
+
const result = await check.run();
|
|
9
|
+
results.push({ name: check.name, ...result });
|
|
10
|
+
}
|
|
11
|
+
catch (err) {
|
|
12
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
13
|
+
results.push({ name: check.name, ok: false, message: `Error: ${message}` });
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
return results;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Format results as a human-readable table for terminal output.
|
|
20
|
+
*/
|
|
21
|
+
export function formatTable(results) {
|
|
22
|
+
const lines = [];
|
|
23
|
+
for (const r of results) {
|
|
24
|
+
const icon = r.ok ? '✓' : '✗';
|
|
25
|
+
lines.push(` ${icon} ${r.name}: ${r.message}`);
|
|
26
|
+
if (!r.ok && r.fix) {
|
|
27
|
+
lines.push(` fix: ${r.fix}`);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
return lines.join('\n');
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Format results as machine-readable JSON.
|
|
34
|
+
* Shape: { checks: [{name, ok, message, fix?}], summary: {ok: N, fail: M} }
|
|
35
|
+
*/
|
|
36
|
+
export function formatJson(results) {
|
|
37
|
+
const checks = results.map(r => {
|
|
38
|
+
const entry = {
|
|
39
|
+
name: r.name,
|
|
40
|
+
ok: r.ok,
|
|
41
|
+
message: r.message,
|
|
42
|
+
};
|
|
43
|
+
if (r.fix !== undefined)
|
|
44
|
+
entry.fix = r.fix;
|
|
45
|
+
return entry;
|
|
46
|
+
});
|
|
47
|
+
const summary = {
|
|
48
|
+
ok: results.filter(r => r.ok).length,
|
|
49
|
+
fail: results.filter(r => !r.ok).length,
|
|
50
|
+
};
|
|
51
|
+
return JSON.stringify({ checks, summary }, null, 2);
|
|
52
|
+
}
|
|
53
|
+
//# sourceMappingURL=runner.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runner.js","sourceRoot":"","sources":["../../src/doctor/runner.ts"],"names":[],"mappings":"AAMA;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,MAAe;IAC7C,MAAM,OAAO,GAA0B,EAAE,CAAC;IAC1C,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;QAC3B,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE,CAAC;YACjC,OAAO,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,GAAG,MAAM,EAAE,CAAC,CAAC;QAChD,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,OAAO,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YACjE,OAAO,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,UAAU,OAAO,EAAE,EAAE,CAAC,CAAC;QAC9E,CAAC;IACH,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,WAAW,CAAC,OAA8B;IACxD,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,KAAK,MAAM,CAAC,IAAI,OAAO,EAAE,CAAC;QACxB,MAAM,IAAI,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC;QAC9B,KAAK,CAAC,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC;QAChD,IAAI,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,GAAG,EAAE,CAAC;YACnB,KAAK,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC;QACpC,CAAC;IACH,CAAC;IACD,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1B,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,UAAU,CAAC,OAA8B;IACvD,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE;QAC7B,MAAM,KAAK,GAA4B;YACrC,IAAI,EAAE,CAAC,CAAC,IAAI;YACZ,EAAE,EAAE,CAAC,CAAC,EAAE;YACR,OAAO,EAAE,CAAC,CAAC,OAAO;SACnB,CAAC;QACF,IAAI,CAAC,CAAC,GAAG,KAAK,SAAS;YAAE,KAAK,CAAC,GAAG,GAAG,CAAC,CAAC,GAAG,CAAC;QAC3C,OAAO,KAAK,CAAC;IACf,CAAC,CAAC,CAAC;IACH,MAAM,OAAO,GAAG;QACd,EAAE,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,MAAM;QACpC,IAAI,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,MAAM;KACxC,CAAC;IACF,OAAO,IAAI,CAAC,SAAS,CAAC,EAAE,MAAM,EAAE,OAAO,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;AACtD,CAAC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export interface CheckResult {
|
|
2
|
+
ok: boolean;
|
|
3
|
+
message: string;
|
|
4
|
+
/** Optional shell command / instruction to fix the issue */
|
|
5
|
+
fix?: string;
|
|
6
|
+
}
|
|
7
|
+
export interface Check {
|
|
8
|
+
/** Short unique identifier used in output table and JSON */
|
|
9
|
+
name: string;
|
|
10
|
+
/** Execute the check and return a result */
|
|
11
|
+
run(): Promise<CheckResult>;
|
|
12
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/doctor/types.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* runEntityBackfill — FEAT-402 AC-7. One-shot pass that extracts + links
|
|
3
|
+
* entities for the pre-existing corpus WITHOUT re-distilling memory text:
|
|
4
|
+
* memories.text/normalized_text/hash are never touched, only entities +
|
|
5
|
+
* memory_entities rows are written.
|
|
6
|
+
*
|
|
7
|
+
* Candidate selection (`memories NOT IN memory_entities`) makes this
|
|
8
|
+
* idempotent by construction, same shape as the tag-hygiene backfill
|
|
9
|
+
* (src/tag-hygiene/backfill.ts): a memory that already has at least one
|
|
10
|
+
* entity link is never re-selected, so re-running on a fully-linked corpus
|
|
11
|
+
* is a pure no-op scan. A memory whose extraction genuinely found nothing
|
|
12
|
+
* (or failed/was budget-skipped) stays a candidate for the next run since it
|
|
13
|
+
* never received a link — no separate "tried and found nothing" state is
|
|
14
|
+
* needed for slice 1.
|
|
15
|
+
*/
|
|
16
|
+
import type { DB } from '../storage/db.js';
|
|
17
|
+
import type { LLMProvider } from '../contracts/index.js';
|
|
18
|
+
export interface EntityBackfillOptions {
|
|
19
|
+
dryRun: boolean;
|
|
20
|
+
limit?: number;
|
|
21
|
+
capUsd: number;
|
|
22
|
+
}
|
|
23
|
+
export interface EntityBackfillResult {
|
|
24
|
+
scanned: number;
|
|
25
|
+
linked: number;
|
|
26
|
+
entitiesLinked: number;
|
|
27
|
+
skipped: number;
|
|
28
|
+
dryRun: boolean;
|
|
29
|
+
}
|
|
30
|
+
export declare function runEntityBackfill(db: DB, provider: LLMProvider, opts: EntityBackfillOptions): Promise<EntityBackfillResult>;
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* runEntityBackfill — FEAT-402 AC-7. One-shot pass that extracts + links
|
|
3
|
+
* entities for the pre-existing corpus WITHOUT re-distilling memory text:
|
|
4
|
+
* memories.text/normalized_text/hash are never touched, only entities +
|
|
5
|
+
* memory_entities rows are written.
|
|
6
|
+
*
|
|
7
|
+
* Candidate selection (`memories NOT IN memory_entities`) makes this
|
|
8
|
+
* idempotent by construction, same shape as the tag-hygiene backfill
|
|
9
|
+
* (src/tag-hygiene/backfill.ts): a memory that already has at least one
|
|
10
|
+
* entity link is never re-selected, so re-running on a fully-linked corpus
|
|
11
|
+
* is a pure no-op scan. A memory whose extraction genuinely found nothing
|
|
12
|
+
* (or failed/was budget-skipped) stays a candidate for the next run since it
|
|
13
|
+
* never received a link — no separate "tried and found nothing" state is
|
|
14
|
+
* needed for slice 1.
|
|
15
|
+
*/
|
|
16
|
+
import { BudgetTracker } from '../budget/tracker.js';
|
|
17
|
+
import { EntityRepo } from '../storage/entities.js';
|
|
18
|
+
import { extractEntitiesForText } from './extract-entities.js';
|
|
19
|
+
export async function runEntityBackfill(db, provider, opts) {
|
|
20
|
+
const limitClause = opts.limit !== undefined ? ` LIMIT ${Math.max(1, opts.limit)}` : '';
|
|
21
|
+
const rows = db
|
|
22
|
+
.prepare(`
|
|
23
|
+
SELECT m.id, m.text
|
|
24
|
+
FROM memories m
|
|
25
|
+
LEFT JOIN memory_entities me ON me.memory_id = m.id
|
|
26
|
+
WHERE me.memory_id IS NULL
|
|
27
|
+
ORDER BY m.created_at ASC${limitClause}
|
|
28
|
+
`)
|
|
29
|
+
.all();
|
|
30
|
+
const budget = new BudgetTracker(db);
|
|
31
|
+
const entityRepo = new EntityRepo(db);
|
|
32
|
+
let linked = 0;
|
|
33
|
+
let entitiesLinked = 0;
|
|
34
|
+
let skipped = 0;
|
|
35
|
+
for (const row of rows) {
|
|
36
|
+
const entities = await extractEntitiesForText(row.text, provider, budget, opts.capUsd);
|
|
37
|
+
if (entities.length === 0) {
|
|
38
|
+
skipped++;
|
|
39
|
+
continue;
|
|
40
|
+
}
|
|
41
|
+
if (!opts.dryRun) {
|
|
42
|
+
entityRepo.linkEntitiesForMemory(row.id, entities);
|
|
43
|
+
}
|
|
44
|
+
linked++;
|
|
45
|
+
entitiesLinked += entities.length;
|
|
46
|
+
}
|
|
47
|
+
return {
|
|
48
|
+
scanned: rows.length,
|
|
49
|
+
linked,
|
|
50
|
+
entitiesLinked,
|
|
51
|
+
skipped,
|
|
52
|
+
dryRun: opts.dryRun,
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
//# sourceMappingURL=backfill.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"backfill.js","sourceRoot":"","sources":["../../src/entity/backfill.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAIH,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AACpD,OAAO,EAAE,sBAAsB,EAAE,MAAM,uBAAuB,CAAC;AAqB/D,MAAM,CAAC,KAAK,UAAU,iBAAiB,CACrC,EAAM,EACN,QAAqB,EACrB,IAA2B;IAE3B,MAAM,WAAW,GAAG,IAAI,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,UAAU,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;IACxF,MAAM,IAAI,GAAG,EAAE;SACZ,OAAO,CAAC;;;;;iCAKoB,WAAW;KACvC,CAAC;SACD,GAAG,EAAiB,CAAC;IAExB,MAAM,MAAM,GAAG,IAAI,aAAa,CAAC,EAAE,CAAC,CAAC;IACrC,MAAM,UAAU,GAAG,IAAI,UAAU,CAAC,EAAE,CAAC,CAAC;IAEtC,IAAI,MAAM,GAAG,CAAC,CAAC;IACf,IAAI,cAAc,GAAG,CAAC,CAAC;IACvB,IAAI,OAAO,GAAG,CAAC,CAAC;IAEhB,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;QACvB,MAAM,QAAQ,GAAG,MAAM,sBAAsB,CAAC,GAAG,CAAC,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC;QACvF,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC1B,OAAO,EAAE,CAAC;YACV,SAAS;QACX,CAAC;QACD,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC;YACjB,UAAU,CAAC,qBAAqB,CAAC,GAAG,CAAC,EAAE,EAAE,QAAQ,CAAC,CAAC;QACrD,CAAC;QACD,MAAM,EAAE,CAAC;QACT,cAAc,IAAI,QAAQ,CAAC,MAAM,CAAC;IACpC,CAAC;IAED,OAAO;QACL,OAAO,EAAE,IAAI,CAAC,MAAM;QACpB,MAAM;QACN,cAAc;QACd,OAAO;QACP,MAAM,EAAE,IAAI,CAAC,MAAM;KACpB,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Entity-only LLM extraction (FEAT-402 AC-7) — used by the `entity-backfill`
|
|
3
|
+
* command to extract entities from ALREADY-DISTILLED memory text, without
|
|
4
|
+
* re-running the full 8-stage distill pipeline (no re-chunking, no atom
|
|
5
|
+
* re-extraction, memory text and hash untouched). Distill-time extraction
|
|
6
|
+
* (stage 5, src/distill/stages/05-extract.ts) instead emits entities inline
|
|
7
|
+
* on each atom in the SAME LLM call — this module exists only for the
|
|
8
|
+
* backfill's one-shot pass over pre-existing rows that predate that stage.
|
|
9
|
+
*
|
|
10
|
+
* Deliberately lenient: unlike stage 5's extractChunk (which throws
|
|
11
|
+
* DeterministicError on parse failure and poisons the job), a bad response
|
|
12
|
+
* here just returns [] and lets the caller log + move on. The corpus is
|
|
13
|
+
* scanned by "not yet linked" (src/entity/backfill.ts), so a memory that got
|
|
14
|
+
* an empty/failed extraction this run remains a valid candidate on the next
|
|
15
|
+
* run — the backfill is naturally resumable without a checkpoint table.
|
|
16
|
+
*/
|
|
17
|
+
import type { LLMProvider } from '../contracts/index.js';
|
|
18
|
+
import { type AtomEntity } from '../distill/prompts/extract.js';
|
|
19
|
+
import { BudgetTracker } from '../budget/tracker.js';
|
|
20
|
+
export declare const ENTITY_ONLY_SYSTEM_PROMPT = "You identify named things mentioned in a short piece of durable knowledge extracted from an AI coding agent transcript.\n\nOutput STRICT JSON matching:\n{\n \"entities\": [\n { \"name\": \"<named thing mentioned>\", \"kind\": \"product\" | \"tech\" | \"person\" | \"org\" | \"repo\" | \"concept\" }\n ]\n}\n\nkind is one of:\n- product: a named product or app (e.g. \"AstraMemory\", \"GitHub Copilot\")\n- tech: a language/framework/library/tool/protocol (e.g. \"Postgres\", \"TypeScript\", \"sqlite-vec\")\n- person: a named individual\n- org: a company or organization\n- repo: a named git repository or codebase\n- concept: a named pattern, architecture, or idea (e.g. \"bitemporal model\", \"CRDT\")\n\nList every specific named thing the text is ABOUT \u2014 not every word. If nothing specific is named, return {\"entities\": []}.";
|
|
21
|
+
/**
|
|
22
|
+
* Extract entities from one piece of already-distilled memory text.
|
|
23
|
+
* Returns [] (never throws) on budget-exceeded, transport, or parse failure
|
|
24
|
+
* — callers decide whether/how to surface that (the backfill CLI counts it
|
|
25
|
+
* as "skipped", not "failed").
|
|
26
|
+
*/
|
|
27
|
+
export declare function extractEntitiesForText(text: string, provider: LLMProvider, budget: BudgetTracker, capUsd: number): Promise<AtomEntity[]>;
|