hippo-memory 1.44.0 → 1.46.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/README.md +68 -24
- package/bin/hippo.js +3 -1
- package/dist/ablation.d.ts +10 -1
- package/dist/ablation.js +17 -1
- package/dist/api.d.ts +81 -22
- package/dist/api.js +258 -49
- package/dist/audit.d.ts +2 -2
- package/dist/audit.js +9 -0
- package/dist/autolearn.d.ts +1 -1
- package/dist/autolearn.js +2 -1
- package/dist/capture-error.d.ts +20 -0
- package/dist/capture-error.js +82 -0
- package/dist/capture.d.ts +25 -8
- package/dist/capture.js +100 -5
- package/dist/cli.d.ts +9 -1
- package/dist/cli.js +531 -119
- package/dist/client.d.ts +4 -21
- package/dist/client.js +3 -112
- package/dist/config.d.ts +20 -0
- package/dist/config.js +37 -1
- package/dist/consolidate.d.ts +9 -0
- package/dist/consolidate.js +133 -46
- package/dist/dag.d.ts +1 -0
- package/dist/dag.js +10 -5
- package/dist/dashboard.js +7 -3
- package/dist/db.js +69 -24
- package/dist/dedupe.d.ts +1 -0
- package/dist/dedupe.js +4 -7
- package/dist/doctor.d.ts +34 -0
- package/dist/doctor.js +174 -0
- package/dist/dormant.d.ts +91 -0
- package/dist/dormant.js +121 -0
- package/dist/embedding-provider.js +2 -1
- package/dist/embeddings.js +81 -8
- package/dist/eval-stats.d.ts +123 -0
- package/dist/eval-stats.js +187 -0
- package/dist/extract.d.ts +2 -0
- package/dist/extract.js +9 -4
- package/dist/half-life-migration.d.ts +55 -0
- package/dist/half-life-migration.js +111 -0
- package/dist/hooks.d.ts +4 -0
- package/dist/hooks.js +47 -0
- package/dist/mcp/server.d.ts +6 -0
- package/dist/mcp/server.js +90 -48
- package/dist/memory.d.ts +18 -1
- package/dist/memory.js +33 -5
- package/dist/physics-config.js +5 -1
- package/dist/recall-scope.d.ts +24 -0
- package/dist/recall-scope.js +41 -0
- package/dist/refine-llm.js +3 -2
- package/dist/reject-flow.d.ts +3 -3
- package/dist/reject-flow.js +10 -3
- package/dist/rerankers/jev.js +3 -2
- package/dist/rerankers/llm.js +3 -2
- package/dist/search.d.ts +4 -4
- package/dist/search.js +26 -21
- package/dist/server.d.ts +5 -0
- package/dist/server.js +49 -29
- package/dist/shared.js +1 -1
- package/dist/store.d.ts +29 -11
- package/dist/store.js +197 -70
- package/dist/token-ledger.d.ts +119 -0
- package/dist/token-ledger.js +181 -0
- package/dist/version.d.ts +4 -6
- package/dist/version.js +4 -7
- package/extensions/openclaw-plugin/openclaw.plugin.json +1 -1
- package/extensions/openclaw-plugin/package.json +1 -1
- package/openclaw.plugin.json +1 -1
- package/package.json +7 -3
- package/dist/ablation.d.ts.map +0 -1
- package/dist/ablation.js.map +0 -1
- package/dist/ambient.d.ts.map +0 -1
- package/dist/ambient.js.map +0 -1
- package/dist/api.d.ts.map +0 -1
- package/dist/api.js.map +0 -1
- package/dist/audit-prune.d.ts.map +0 -1
- package/dist/audit-prune.js.map +0 -1
- package/dist/audit.d.ts.map +0 -1
- package/dist/audit.js.map +0 -1
- package/dist/auth.d.ts.map +0 -1
- package/dist/auth.js.map +0 -1
- package/dist/autolearn.d.ts.map +0 -1
- package/dist/autolearn.js.map +0 -1
- package/dist/availability.d.ts.map +0 -1
- package/dist/availability.js.map +0 -1
- package/dist/benchmarks/e1.3/incident-recall-eval.js +0 -78
- package/dist/benchmarks/e1.3/incident-recall-eval.js.map +0 -1
- package/dist/benchmarks/e1.3/slack-1000-event-smoke.js +0 -103
- package/dist/benchmarks/e1.3/slack-1000-event-smoke.js.map +0 -1
- package/dist/capture.d.ts.map +0 -1
- package/dist/capture.js.map +0 -1
- package/dist/card-detail.d.ts.map +0 -1
- package/dist/card-detail.js.map +0 -1
- package/dist/card.d.ts.map +0 -1
- package/dist/card.js.map +0 -1
- package/dist/cli.d.ts.map +0 -1
- package/dist/cli.js.map +0 -1
- package/dist/client.d.ts.map +0 -1
- package/dist/client.js.map +0 -1
- package/dist/compare.d.ts.map +0 -1
- package/dist/compare.js.map +0 -1
- package/dist/config.d.ts.map +0 -1
- package/dist/config.js.map +0 -1
- package/dist/connectors/github/backfill.d.ts.map +0 -1
- package/dist/connectors/github/backfill.js.map +0 -1
- package/dist/connectors/github/cli-impl.d.ts.map +0 -1
- package/dist/connectors/github/cli-impl.js.map +0 -1
- package/dist/connectors/github/deletion.d.ts.map +0 -1
- package/dist/connectors/github/deletion.js.map +0 -1
- package/dist/connectors/github/dlq.d.ts.map +0 -1
- package/dist/connectors/github/dlq.js.map +0 -1
- package/dist/connectors/github/idempotency.d.ts.map +0 -1
- package/dist/connectors/github/idempotency.js.map +0 -1
- package/dist/connectors/github/ingest.d.ts.map +0 -1
- package/dist/connectors/github/ingest.js.map +0 -1
- package/dist/connectors/github/octokit-client.d.ts.map +0 -1
- package/dist/connectors/github/octokit-client.js.map +0 -1
- package/dist/connectors/github/ratelimit.d.ts.map +0 -1
- package/dist/connectors/github/ratelimit.js.map +0 -1
- package/dist/connectors/github/scope.d.ts.map +0 -1
- package/dist/connectors/github/scope.js.map +0 -1
- package/dist/connectors/github/signature.d.ts.map +0 -1
- package/dist/connectors/github/signature.js.map +0 -1
- package/dist/connectors/github/tenant-routing.d.ts.map +0 -1
- package/dist/connectors/github/tenant-routing.js.map +0 -1
- package/dist/connectors/github/transform.d.ts.map +0 -1
- package/dist/connectors/github/transform.js.map +0 -1
- package/dist/connectors/github/types.d.ts.map +0 -1
- package/dist/connectors/github/types.js.map +0 -1
- package/dist/connectors/slack/backfill.d.ts.map +0 -1
- package/dist/connectors/slack/backfill.js.map +0 -1
- package/dist/connectors/slack/deletion.d.ts.map +0 -1
- package/dist/connectors/slack/deletion.js.map +0 -1
- package/dist/connectors/slack/dlq.d.ts.map +0 -1
- package/dist/connectors/slack/dlq.js.map +0 -1
- package/dist/connectors/slack/idempotency.d.ts.map +0 -1
- package/dist/connectors/slack/idempotency.js.map +0 -1
- package/dist/connectors/slack/ingest.d.ts.map +0 -1
- package/dist/connectors/slack/ingest.js.map +0 -1
- package/dist/connectors/slack/ratelimit.d.ts.map +0 -1
- package/dist/connectors/slack/ratelimit.js.map +0 -1
- package/dist/connectors/slack/scope.d.ts.map +0 -1
- package/dist/connectors/slack/scope.js.map +0 -1
- package/dist/connectors/slack/signature.d.ts.map +0 -1
- package/dist/connectors/slack/signature.js.map +0 -1
- package/dist/connectors/slack/tenant-routing.d.ts.map +0 -1
- package/dist/connectors/slack/tenant-routing.js.map +0 -1
- package/dist/connectors/slack/transform.d.ts.map +0 -1
- package/dist/connectors/slack/transform.js.map +0 -1
- package/dist/connectors/slack/types.d.ts.map +0 -1
- package/dist/connectors/slack/types.js.map +0 -1
- package/dist/connectors/slack/web-client.d.ts.map +0 -1
- package/dist/connectors/slack/web-client.js.map +0 -1
- package/dist/connectors/slack/workspaces.d.ts.map +0 -1
- package/dist/connectors/slack/workspaces.js.map +0 -1
- package/dist/consolidate.d.ts.map +0 -1
- package/dist/consolidate.js.map +0 -1
- package/dist/correction-latency.d.ts.map +0 -1
- package/dist/correction-latency.js.map +0 -1
- package/dist/customer-notes.d.ts.map +0 -1
- package/dist/customer-notes.js.map +0 -1
- package/dist/dag.d.ts.map +0 -1
- package/dist/dag.js.map +0 -1
- package/dist/dashboard.d.ts.map +0 -1
- package/dist/dashboard.js.map +0 -1
- package/dist/db.d.ts.map +0 -1
- package/dist/db.js.map +0 -1
- package/dist/decisions.d.ts.map +0 -1
- package/dist/decisions.js.map +0 -1
- package/dist/dedupe.d.ts.map +0 -1
- package/dist/dedupe.js.map +0 -1
- package/dist/embedding-provider.d.ts.map +0 -1
- package/dist/embedding-provider.js.map +0 -1
- package/dist/embeddings.d.ts.map +0 -1
- package/dist/embeddings.js.map +0 -1
- package/dist/eval-suite.d.ts.map +0 -1
- package/dist/eval-suite.js.map +0 -1
- package/dist/eval.d.ts.map +0 -1
- package/dist/eval.js.map +0 -1
- package/dist/extensions/openclaw-plugin/index.js.map +0 -1
- package/dist/extract.d.ts.map +0 -1
- package/dist/extract.js.map +0 -1
- package/dist/forward-claim-detector.d.ts.map +0 -1
- package/dist/forward-claim-detector.js.map +0 -1
- package/dist/goals.d.ts.map +0 -1
- package/dist/goals.js.map +0 -1
- package/dist/graph-extract.d.ts.map +0 -1
- package/dist/graph-extract.js.map +0 -1
- package/dist/graph-recall.d.ts.map +0 -1
- package/dist/graph-recall.js.map +0 -1
- package/dist/graph-stream.d.ts.map +0 -1
- package/dist/graph-stream.js.map +0 -1
- package/dist/graph-view.d.ts.map +0 -1
- package/dist/graph-view.js.map +0 -1
- package/dist/graph.d.ts.map +0 -1
- package/dist/graph.js.map +0 -1
- package/dist/handoff.d.ts.map +0 -1
- package/dist/handoff.js.map +0 -1
- package/dist/hooks.d.ts.map +0 -1
- package/dist/hooks.js.map +0 -1
- package/dist/importers.d.ts.map +0 -1
- package/dist/importers.js.map +0 -1
- package/dist/incidents.d.ts.map +0 -1
- package/dist/incidents.js.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/invalidation.d.ts.map +0 -1
- package/dist/invalidation.js.map +0 -1
- package/dist/mcp/framing.d.ts.map +0 -1
- package/dist/mcp/framing.js.map +0 -1
- package/dist/mcp/server.d.ts.map +0 -1
- package/dist/mcp/server.js.map +0 -1
- package/dist/memory-value-weights.d.ts.map +0 -1
- package/dist/memory-value-weights.js.map +0 -1
- package/dist/memory-value.d.ts.map +0 -1
- package/dist/memory-value.js.map +0 -1
- package/dist/memory.d.ts.map +0 -1
- package/dist/memory.js.map +0 -1
- package/dist/multihop.d.ts.map +0 -1
- package/dist/multihop.js.map +0 -1
- package/dist/owner-validation.d.ts.map +0 -1
- package/dist/owner-validation.js.map +0 -1
- package/dist/path-context.d.ts.map +0 -1
- package/dist/path-context.js.map +0 -1
- package/dist/physics-config.d.ts.map +0 -1
- package/dist/physics-config.js.map +0 -1
- package/dist/physics-state.d.ts.map +0 -1
- package/dist/physics-state.js.map +0 -1
- package/dist/physics.d.ts.map +0 -1
- package/dist/physics.js.map +0 -1
- package/dist/policies.d.ts.map +0 -1
- package/dist/policies.js.map +0 -1
- package/dist/postinstall.d.ts.map +0 -1
- package/dist/postinstall.js.map +0 -1
- package/dist/predictions.d.ts.map +0 -1
- package/dist/predictions.js.map +0 -1
- package/dist/processes.d.ts.map +0 -1
- package/dist/processes.js.map +0 -1
- package/dist/project-briefs.d.ts.map +0 -1
- package/dist/project-briefs.js.map +0 -1
- package/dist/project-identity.d.ts.map +0 -1
- package/dist/project-identity.js.map +0 -1
- package/dist/provenance-coverage.d.ts.map +0 -1
- package/dist/provenance-coverage.js.map +0 -1
- package/dist/rate-limit.d.ts.map +0 -1
- package/dist/rate-limit.js.map +0 -1
- package/dist/raw-archive-mirror-cleanup.d.ts.map +0 -1
- package/dist/raw-archive-mirror-cleanup.js.map +0 -1
- package/dist/raw-archive.d.ts.map +0 -1
- package/dist/raw-archive.js.map +0 -1
- package/dist/recall-history.d.ts.map +0 -1
- package/dist/recall-history.js.map +0 -1
- package/dist/recall-scope.d.ts.map +0 -1
- package/dist/recall-scope.js.map +0 -1
- package/dist/recall-trace.d.ts.map +0 -1
- package/dist/recall-trace.js.map +0 -1
- package/dist/refine-llm.d.ts.map +0 -1
- package/dist/refine-llm.js.map +0 -1
- package/dist/reject-flow.d.ts.map +0 -1
- package/dist/reject-flow.js.map +0 -1
- package/dist/rejection.d.ts.map +0 -1
- package/dist/rejection.js.map +0 -1
- package/dist/replay.d.ts.map +0 -1
- package/dist/replay.js.map +0 -1
- package/dist/rerankers/cross-encoder.d.ts.map +0 -1
- package/dist/rerankers/cross-encoder.js.map +0 -1
- package/dist/rerankers/index.d.ts.map +0 -1
- package/dist/rerankers/index.js.map +0 -1
- package/dist/rerankers/jev.d.ts.map +0 -1
- package/dist/rerankers/jev.js.map +0 -1
- package/dist/rerankers/llm.d.ts.map +0 -1
- package/dist/rerankers/llm.js.map +0 -1
- package/dist/rerankers/types.d.ts.map +0 -1
- package/dist/rerankers/types.js.map +0 -1
- package/dist/rrf.d.ts.map +0 -1
- package/dist/rrf.js.map +0 -1
- package/dist/salience.d.ts.map +0 -1
- package/dist/salience.js.map +0 -1
- package/dist/scheduler.d.ts.map +0 -1
- package/dist/scheduler.js.map +0 -1
- package/dist/scope.d.ts.map +0 -1
- package/dist/scope.js.map +0 -1
- package/dist/search.d.ts.map +0 -1
- package/dist/search.js.map +0 -1
- package/dist/secret-detect.d.ts.map +0 -1
- package/dist/secret-detect.js.map +0 -1
- package/dist/server-detect.d.ts.map +0 -1
- package/dist/server-detect.js.map +0 -1
- package/dist/server.d.ts.map +0 -1
- package/dist/server.js.map +0 -1
- package/dist/shared.d.ts.map +0 -1
- package/dist/shared.js.map +0 -1
- package/dist/skills.d.ts.map +0 -1
- package/dist/skills.js.map +0 -1
- package/dist/sleep-redact.d.ts +0 -58
- package/dist/sleep-redact.d.ts.map +0 -1
- package/dist/sleep-redact.js +0 -80
- package/dist/sleep-redact.js.map +0 -1
- package/dist/src/ablation.js +0 -138
- package/dist/src/ablation.js.map +0 -1
- package/dist/src/ambient.js +0 -148
- package/dist/src/ambient.js.map +0 -1
- package/dist/src/api.js +0 -2109
- package/dist/src/api.js.map +0 -1
- package/dist/src/audit-prune.js +0 -109
- package/dist/src/audit-prune.js.map +0 -1
- package/dist/src/audit.js +0 -213
- package/dist/src/audit.js.map +0 -1
- package/dist/src/auth.js +0 -97
- package/dist/src/auth.js.map +0 -1
- package/dist/src/autolearn.js +0 -174
- package/dist/src/autolearn.js.map +0 -1
- package/dist/src/availability.js +0 -94
- package/dist/src/availability.js.map +0 -1
- package/dist/src/capture.js +0 -1346
- package/dist/src/capture.js.map +0 -1
- package/dist/src/card-detail.js +0 -15
- package/dist/src/card-detail.js.map +0 -1
- package/dist/src/card.js +0 -19
- package/dist/src/card.js.map +0 -1
- package/dist/src/cli.js +0 -9387
- package/dist/src/cli.js.map +0 -1
- package/dist/src/client.js +0 -237
- package/dist/src/client.js.map +0 -1
- package/dist/src/compare.js +0 -122
- package/dist/src/compare.js.map +0 -1
- package/dist/src/config.js +0 -135
- package/dist/src/config.js.map +0 -1
- package/dist/src/connectors/github/backfill.js +0 -281
- package/dist/src/connectors/github/backfill.js.map +0 -1
- package/dist/src/connectors/github/cli-impl.js +0 -234
- package/dist/src/connectors/github/cli-impl.js.map +0 -1
- package/dist/src/connectors/github/deletion.js +0 -85
- package/dist/src/connectors/github/deletion.js.map +0 -1
- package/dist/src/connectors/github/dlq.js +0 -190
- package/dist/src/connectors/github/dlq.js.map +0 -1
- package/dist/src/connectors/github/idempotency.js +0 -27
- package/dist/src/connectors/github/idempotency.js.map +0 -1
- package/dist/src/connectors/github/ingest.js +0 -156
- package/dist/src/connectors/github/ingest.js.map +0 -1
- package/dist/src/connectors/github/octokit-client.js +0 -70
- package/dist/src/connectors/github/octokit-client.js.map +0 -1
- package/dist/src/connectors/github/ratelimit.js +0 -31
- package/dist/src/connectors/github/ratelimit.js.map +0 -1
- package/dist/src/connectors/github/scope.js +0 -13
- package/dist/src/connectors/github/scope.js.map +0 -1
- package/dist/src/connectors/github/signature.js +0 -81
- package/dist/src/connectors/github/signature.js.map +0 -1
- package/dist/src/connectors/github/tenant-routing.js +0 -69
- package/dist/src/connectors/github/tenant-routing.js.map +0 -1
- package/dist/src/connectors/github/transform.js +0 -103
- package/dist/src/connectors/github/transform.js.map +0 -1
- package/dist/src/connectors/github/types.js +0 -100
- package/dist/src/connectors/github/types.js.map +0 -1
- package/dist/src/connectors/slack/backfill.js +0 -78
- package/dist/src/connectors/slack/backfill.js.map +0 -1
- package/dist/src/connectors/slack/deletion.js +0 -59
- package/dist/src/connectors/slack/deletion.js.map +0 -1
- package/dist/src/connectors/slack/dlq.js +0 -224
- package/dist/src/connectors/slack/dlq.js.map +0 -1
- package/dist/src/connectors/slack/idempotency.js +0 -31
- package/dist/src/connectors/slack/idempotency.js.map +0 -1
- package/dist/src/connectors/slack/ingest.js +0 -109
- package/dist/src/connectors/slack/ingest.js.map +0 -1
- package/dist/src/connectors/slack/ratelimit.js +0 -18
- package/dist/src/connectors/slack/ratelimit.js.map +0 -1
- package/dist/src/connectors/slack/scope.js +0 -13
- package/dist/src/connectors/slack/scope.js.map +0 -1
- package/dist/src/connectors/slack/signature.js +0 -27
- package/dist/src/connectors/slack/signature.js.map +0 -1
- package/dist/src/connectors/slack/tenant-routing.js +0 -41
- package/dist/src/connectors/slack/tenant-routing.js.map +0 -1
- package/dist/src/connectors/slack/transform.js +0 -47
- package/dist/src/connectors/slack/transform.js.map +0 -1
- package/dist/src/connectors/slack/types.js +0 -35
- package/dist/src/connectors/slack/types.js.map +0 -1
- package/dist/src/connectors/slack/web-client.js +0 -43
- package/dist/src/connectors/slack/web-client.js.map +0 -1
- package/dist/src/connectors/slack/workspaces.js +0 -62
- package/dist/src/connectors/slack/workspaces.js.map +0 -1
- package/dist/src/consolidate.js +0 -978
- package/dist/src/consolidate.js.map +0 -1
- package/dist/src/correction-latency.js +0 -74
- package/dist/src/correction-latency.js.map +0 -1
- package/dist/src/customer-notes.js +0 -325
- package/dist/src/customer-notes.js.map +0 -1
- package/dist/src/dag.js +0 -352
- package/dist/src/dag.js.map +0 -1
- package/dist/src/dashboard.js +0 -258
- package/dist/src/dashboard.js.map +0 -1
- package/dist/src/db.js +0 -2731
- package/dist/src/db.js.map +0 -1
- package/dist/src/decisions.js +0 -304
- package/dist/src/decisions.js.map +0 -1
- package/dist/src/dedupe.js +0 -141
- package/dist/src/dedupe.js.map +0 -1
- package/dist/src/embedding-provider.js +0 -314
- package/dist/src/embedding-provider.js.map +0 -1
- package/dist/src/embeddings.js +0 -543
- package/dist/src/embeddings.js.map +0 -1
- package/dist/src/eval-suite.js +0 -294
- package/dist/src/eval-suite.js.map +0 -1
- package/dist/src/eval.js +0 -187
- package/dist/src/eval.js.map +0 -1
- package/dist/src/extract.js +0 -117
- package/dist/src/extract.js.map +0 -1
- package/dist/src/forward-claim-detector.js +0 -117
- package/dist/src/forward-claim-detector.js.map +0 -1
- package/dist/src/goals.js +0 -399
- package/dist/src/goals.js.map +0 -1
- package/dist/src/graph-extract.js +0 -314
- package/dist/src/graph-extract.js.map +0 -1
- package/dist/src/graph-recall.js +0 -277
- package/dist/src/graph-recall.js.map +0 -1
- package/dist/src/graph-stream.js +0 -176
- package/dist/src/graph-stream.js.map +0 -1
- package/dist/src/graph-view.js +0 -310
- package/dist/src/graph-view.js.map +0 -1
- package/dist/src/graph.js +0 -762
- package/dist/src/graph.js.map +0 -1
- package/dist/src/handoff.js +0 -65
- package/dist/src/handoff.js.map +0 -1
- package/dist/src/hooks.js +0 -926
- package/dist/src/hooks.js.map +0 -1
- package/dist/src/importers.js +0 -881
- package/dist/src/importers.js.map +0 -1
- package/dist/src/incidents.js +0 -336
- package/dist/src/incidents.js.map +0 -1
- package/dist/src/index.js +0 -32
- package/dist/src/index.js.map +0 -1
- package/dist/src/invalidation.js +0 -129
- package/dist/src/invalidation.js.map +0 -1
- package/dist/src/mcp/framing.js +0 -45
- package/dist/src/mcp/framing.js.map +0 -1
- package/dist/src/mcp/server.js +0 -1298
- package/dist/src/mcp/server.js.map +0 -1
- package/dist/src/memory-value-weights.js +0 -31
- package/dist/src/memory-value-weights.js.map +0 -1
- package/dist/src/memory-value.js +0 -261
- package/dist/src/memory-value.js.map +0 -1
- package/dist/src/memory.js +0 -425
- package/dist/src/memory.js.map +0 -1
- package/dist/src/multihop.js +0 -35
- package/dist/src/multihop.js.map +0 -1
- package/dist/src/owner-validation.js +0 -56
- package/dist/src/owner-validation.js.map +0 -1
- package/dist/src/path-context.js +0 -48
- package/dist/src/path-context.js.map +0 -1
- package/dist/src/physics-config.js +0 -26
- package/dist/src/physics-config.js.map +0 -1
- package/dist/src/physics-state.js +0 -172
- package/dist/src/physics-state.js.map +0 -1
- package/dist/src/physics.js +0 -378
- package/dist/src/physics.js.map +0 -1
- package/dist/src/policies.js +0 -414
- package/dist/src/policies.js.map +0 -1
- package/dist/src/postinstall.js +0 -101
- package/dist/src/postinstall.js.map +0 -1
- package/dist/src/predictions.js +0 -629
- package/dist/src/predictions.js.map +0 -1
- package/dist/src/processes.js +0 -349
- package/dist/src/processes.js.map +0 -1
- package/dist/src/project-briefs.js +0 -492
- package/dist/src/project-briefs.js.map +0 -1
- package/dist/src/project-identity.js +0 -200
- package/dist/src/project-identity.js.map +0 -1
- package/dist/src/provenance-coverage.js +0 -23
- package/dist/src/provenance-coverage.js.map +0 -1
- package/dist/src/rate-limit.js +0 -60
- package/dist/src/rate-limit.js.map +0 -1
- package/dist/src/raw-archive-mirror-cleanup.js +0 -55
- package/dist/src/raw-archive-mirror-cleanup.js.map +0 -1
- package/dist/src/raw-archive.js +0 -91
- package/dist/src/raw-archive.js.map +0 -1
- package/dist/src/recall-history.js +0 -235
- package/dist/src/recall-history.js.map +0 -1
- package/dist/src/recall-scope.js +0 -89
- package/dist/src/recall-scope.js.map +0 -1
- package/dist/src/recall-trace.js +0 -186
- package/dist/src/recall-trace.js.map +0 -1
- package/dist/src/refine-llm.js +0 -156
- package/dist/src/refine-llm.js.map +0 -1
- package/dist/src/reject-flow.js +0 -209
- package/dist/src/reject-flow.js.map +0 -1
- package/dist/src/rejection.js +0 -160
- package/dist/src/rejection.js.map +0 -1
- package/dist/src/replay.js +0 -122
- package/dist/src/replay.js.map +0 -1
- package/dist/src/rerankers/cross-encoder.js +0 -137
- package/dist/src/rerankers/cross-encoder.js.map +0 -1
- package/dist/src/rerankers/index.js +0 -20
- package/dist/src/rerankers/index.js.map +0 -1
- package/dist/src/rerankers/jev.js +0 -119
- package/dist/src/rerankers/jev.js.map +0 -1
- package/dist/src/rerankers/llm.js +0 -80
- package/dist/src/rerankers/llm.js.map +0 -1
- package/dist/src/rerankers/types.js +0 -2
- package/dist/src/rerankers/types.js.map +0 -1
- package/dist/src/rrf.js +0 -61
- package/dist/src/rrf.js.map +0 -1
- package/dist/src/salience.js +0 -74
- package/dist/src/salience.js.map +0 -1
- package/dist/src/scheduler.js +0 -77
- package/dist/src/scheduler.js.map +0 -1
- package/dist/src/scope.js +0 -35
- package/dist/src/scope.js.map +0 -1
- package/dist/src/search.js +0 -1003
- package/dist/src/search.js.map +0 -1
- package/dist/src/secret-detect.js +0 -95
- package/dist/src/secret-detect.js.map +0 -1
- package/dist/src/server-detect.js +0 -231
- package/dist/src/server-detect.js.map +0 -1
- package/dist/src/server.js +0 -3255
- package/dist/src/server.js.map +0 -1
- package/dist/src/shared.js +0 -502
- package/dist/src/shared.js.map +0 -1
- package/dist/src/skills.js +0 -346
- package/dist/src/skills.js.map +0 -1
- package/dist/src/sleep-redact.js +0 -80
- package/dist/src/sleep-redact.js.map +0 -1
- package/dist/src/sso.js +0 -22
- package/dist/src/sso.js.map +0 -1
- package/dist/src/stdin.js +0 -41
- package/dist/src/stdin.js.map +0 -1
- package/dist/src/store.js +0 -3749
- package/dist/src/store.js.map +0 -1
- package/dist/src/tenant.js +0 -17
- package/dist/src/tenant.js.map +0 -1
- package/dist/src/trace.js +0 -72
- package/dist/src/trace.js.map +0 -1
- package/dist/src/version.js +0 -40
- package/dist/src/version.js.map +0 -1
- package/dist/src/working-memory.js +0 -157
- package/dist/src/working-memory.js.map +0 -1
- package/dist/src/yaml.js +0 -107
- package/dist/src/yaml.js.map +0 -1
- package/dist/sso.d.ts +0 -13
- package/dist/sso.d.ts.map +0 -1
- package/dist/sso.js +0 -22
- package/dist/sso.js.map +0 -1
- package/dist/stdin.d.ts.map +0 -1
- package/dist/stdin.js.map +0 -1
- package/dist/store.d.ts.map +0 -1
- package/dist/store.js.map +0 -1
- package/dist/tenant.d.ts.map +0 -1
- package/dist/tenant.js.map +0 -1
- package/dist/trace.d.ts.map +0 -1
- package/dist/trace.js.map +0 -1
- package/dist/version.d.ts.map +0 -1
- package/dist/version.js.map +0 -1
- package/dist/working-memory.d.ts.map +0 -1
- package/dist/working-memory.js.map +0 -1
- package/dist/yaml.d.ts.map +0 -1
- package/dist/yaml.js.map +0 -1
package/dist/consolidate.js
CHANGED
|
@@ -7,12 +7,14 @@
|
|
|
7
7
|
* 3. Stats tracking
|
|
8
8
|
*/
|
|
9
9
|
import { evalNow, isRecallBoostAblated } from './ablation.js';
|
|
10
|
-
import { Layer, calculateStrength, createMemory } from './memory.js';
|
|
10
|
+
import { Layer, calculateStrength, canAutoDelete, createMemory } from './memory.js';
|
|
11
11
|
import { loadAllEntries, batchWriteAndDelete, appendConsolidationRun, replaceDetectedConflicts, loadSessionDecayContext, incrementSleepCount, findPromotableSessions, traceExistsForSession, listSessionEvents, } from './store.js';
|
|
12
12
|
import { textOverlap, markRetrieved } from './search.js';
|
|
13
13
|
import { compareEntryIdentity } from './compare.js';
|
|
14
14
|
import { openHippoDb, closeHippoDb } from './db.js';
|
|
15
15
|
import { rejectionDigest, findRejectedValue } from './rejection.js';
|
|
16
|
+
import { countExpiredDormant, purgeExpiredDormant } from './dormant.js';
|
|
17
|
+
import { detectSecret } from './secret-detect.js';
|
|
16
18
|
import { loadPhysicsState, savePhysicsState, refreshParticleProperties } from './physics-state.js';
|
|
17
19
|
import { simulate } from './physics.js';
|
|
18
20
|
import { loadConfig } from './config.js';
|
|
@@ -22,6 +24,7 @@ import { resolveTenantId } from './tenant.js';
|
|
|
22
24
|
import { rescueSet, rankNonPinnedByTenant, validateWeights } from './memory-value.js';
|
|
23
25
|
import { MEMORY_VALUE_WEIGHTS, SOURCE_ARTIFACT_SHA256 } from './memory-value-weights.js';
|
|
24
26
|
import { appendAuditEvent } from './audit.js';
|
|
27
|
+
import { migrateDefaultHalfLife } from './half-life-migration.js';
|
|
25
28
|
const DECAY_THRESHOLD = 0.05;
|
|
26
29
|
const MERGE_OVERLAP_THRESHOLD = 0.35; // Jaccard similarity for "related"
|
|
27
30
|
const MERGE_MIN_CLUSTER = 2; // minimum cluster size to merge
|
|
@@ -59,6 +62,37 @@ const REPLAY_COUNT_DEFAULT = 5;
|
|
|
59
62
|
function isJsonString(value) {
|
|
60
63
|
return typeof value === 'string';
|
|
61
64
|
}
|
|
65
|
+
/** Tables whose rows keep a first-class object's backing memory in `memory_id` (ON DELETE SET NULL). */
|
|
66
|
+
const MEMORY_BACKED_TABLES = ['predictions', 'decisions', 'processes', 'policies', 'skills', 'project_briefs', 'customer_notes'];
|
|
67
|
+
/**
|
|
68
|
+
* Ids of memories that back a first-class object (a decision, prediction,
|
|
69
|
+
* process, policy, skill, project brief or customer note). Sleep never
|
|
70
|
+
* retires these: deleting or moving one to dormant storage fires the
|
|
71
|
+
* object's ON DELETE SET NULL and a restore cannot repair the link. Their
|
|
72
|
+
* lifecycle belongs to the object. A table missing from an older schema is
|
|
73
|
+
* skipped.
|
|
74
|
+
*/
|
|
75
|
+
function memoriesBackingObjects(hippoRoot) {
|
|
76
|
+
const ids = new Set();
|
|
77
|
+
const db = openHippoDb(hippoRoot);
|
|
78
|
+
try {
|
|
79
|
+
for (const table of MEMORY_BACKED_TABLES) {
|
|
80
|
+
try {
|
|
81
|
+
// SAFETY: SELECT of one nullable TEXT column, filtered to non-null.
|
|
82
|
+
const rows = db.prepare(`SELECT memory_id FROM ${table} WHERE memory_id IS NOT NULL`).all();
|
|
83
|
+
for (const r of rows)
|
|
84
|
+
ids.add(r.memory_id);
|
|
85
|
+
}
|
|
86
|
+
catch {
|
|
87
|
+
// Table not present in this schema version.
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
finally {
|
|
92
|
+
closeHippoDb(db);
|
|
93
|
+
}
|
|
94
|
+
return ids;
|
|
95
|
+
}
|
|
62
96
|
/**
|
|
63
97
|
* Run a full consolidation pass.
|
|
64
98
|
*/
|
|
@@ -68,6 +102,8 @@ export async function consolidate(hippoRoot, options = {}) {
|
|
|
68
102
|
const result = {
|
|
69
103
|
decayed: 0,
|
|
70
104
|
removed: 0,
|
|
105
|
+
dormant: 0,
|
|
106
|
+
dormantExpired: 0,
|
|
71
107
|
merged: 0,
|
|
72
108
|
semanticCreated: 0,
|
|
73
109
|
replayed: 0,
|
|
@@ -86,11 +122,24 @@ export async function consolidate(hippoRoot, options = {}) {
|
|
|
86
122
|
details: [],
|
|
87
123
|
physicsSimulated: 0,
|
|
88
124
|
};
|
|
125
|
+
// A changed default half-life moves memories still on the old base first,
|
|
126
|
+
// so this pass decays them at the new one (src/half-life-migration.ts).
|
|
127
|
+
const halfLife = migrateDefaultHalfLife(hippoRoot, loadConfig(hippoRoot).defaultHalfLifeDays, { dryRun });
|
|
128
|
+
if (halfLife.rescaled > 0) {
|
|
129
|
+
result.details.push(` ⏳ ${dryRun ? 'would move' : 'moved'} ${halfLife.rescaled} memories from the ${halfLife.from}-day to the ${halfLife.to}-day half-life`);
|
|
130
|
+
}
|
|
89
131
|
// L9: host-wide by design. Consolidation runs across all tenants in one
|
|
90
132
|
// pass — per-tenant filtering would create N consolidation runs per host
|
|
91
133
|
// with no cross-tenant dedup. The api.sleep audit row tags this with the
|
|
92
134
|
// admin synthetic actor; see api.ts:2050 for the rationale.
|
|
93
135
|
const all = loadAllEntries(hippoRoot);
|
|
136
|
+
if (dryRun)
|
|
137
|
+
for (const e of all)
|
|
138
|
+
e.half_life_days = halfLife.halfLives.get(e.id) ?? e.half_life_days;
|
|
139
|
+
const backingObjects = memoriesBackingObjects(hippoRoot);
|
|
140
|
+
// Retirable: auto-deletable (never pinned, never raw) and not backing a first-class object.
|
|
141
|
+
const retirable = (entry) => canAutoDelete(entry) && !backingObjects.has(entry.id);
|
|
142
|
+
const snapshot = new Map(structuredClone(all).map((e) => [e.id, e]));
|
|
94
143
|
// Load decay options from config + session context
|
|
95
144
|
const config = loadConfig(hippoRoot);
|
|
96
145
|
const sessionCtx = loadSessionDecayContext(hippoRoot);
|
|
@@ -102,6 +151,28 @@ export async function consolidate(hippoRoot, options = {}) {
|
|
|
102
151
|
// Collect all writes/deletes and batch them at the end
|
|
103
152
|
const pendingWrites = [];
|
|
104
153
|
const pendingDeletes = [];
|
|
154
|
+
const pendingDormant = [];
|
|
155
|
+
// A faded, unpinned, unrescued memory leaves active memory one of three
|
|
156
|
+
// ways. A raw receipt is append-only: trg_memories_raw_append_only aborts
|
|
157
|
+
// a DELETE, and with it this whole cycle's batch and every later sleep,
|
|
158
|
+
// so it stays where it is (stored strength refreshed) but sits out the
|
|
159
|
+
// rest of this cycle the way a deleted row would. Anything else goes
|
|
160
|
+
// dormant when config.dormant is on, and is deleted otherwise.
|
|
161
|
+
// Only called for rows `retirable` allows (never pinned, never raw, never backing a first-class object).
|
|
162
|
+
const retireFaded = (entry, strength) => {
|
|
163
|
+
const why = `(strength ${strength.toFixed(4)} < ${DECAY_THRESHOLD})`;
|
|
164
|
+
// A faded secret is deleted, never kept dormant: keeping it would hold a
|
|
165
|
+
// credential on disk that the user reasonably expects forgetting removed.
|
|
166
|
+
if (config.dormant.enabled && !detectSecret(entry).flagged) {
|
|
167
|
+
result.dormant++;
|
|
168
|
+
result.details.push(` 💤 dormant ${entry.id} ${why}`);
|
|
169
|
+
pendingDormant.push({ entry: { ...entry, strength }, strength, reason: 'decay', dormantAt: now.toISOString() });
|
|
170
|
+
return;
|
|
171
|
+
}
|
|
172
|
+
result.removed++;
|
|
173
|
+
result.details.push(` 🗑 removed ${entry.id} ${why}`);
|
|
174
|
+
pendingDeletes.push(entry.id);
|
|
175
|
+
};
|
|
105
176
|
// -------------------------------------------------------------------------
|
|
106
177
|
// 1. Decay pass
|
|
107
178
|
// -------------------------------------------------------------------------
|
|
@@ -131,12 +202,12 @@ export async function consolidate(hippoRoot, options = {}) {
|
|
|
131
202
|
for (const entry of all) {
|
|
132
203
|
const strength = calculateStrength(entry, now, decayOpts);
|
|
133
204
|
strengthById.set(entry.id, strength);
|
|
134
|
-
if (
|
|
205
|
+
if (retirable(entry) && strength < DECAY_THRESHOLD) {
|
|
135
206
|
condemned.push(entry);
|
|
136
207
|
}
|
|
137
208
|
}
|
|
138
209
|
// --- Phase 2a: rescue decision (pure compute) ---
|
|
139
|
-
// Runs under --dry-run too (only pendingDeletes
|
|
210
|
+
// Runs under --dry-run too (only the pendingDeletes flush and the audit write in
|
|
140
211
|
// "4. Log run" below stay !dryRun-gated), so the preview matches what a
|
|
141
212
|
// real run would decide.
|
|
142
213
|
const condemnedIds = new Set(condemned.map((e) => e.id));
|
|
@@ -173,7 +244,7 @@ export async function consolidate(hippoRoot, options = {}) {
|
|
|
173
244
|
// preserves flag-off's ordering semantics exactly.)
|
|
174
245
|
for (const entry of all) {
|
|
175
246
|
const strength = strengthById.get(entry.id);
|
|
176
|
-
if (
|
|
247
|
+
if (retirable(entry) && strength < DECAY_THRESHOLD) {
|
|
177
248
|
if (rescuedIds.has(entry.id)) {
|
|
178
249
|
// Rescued (D1): standard survivor stored-strength refresh (P2-1).
|
|
179
250
|
// Confidence is left alone here: it is an epistemic tier, not a
|
|
@@ -192,11 +263,7 @@ export async function consolidate(hippoRoot, options = {}) {
|
|
|
192
263
|
result.details.push(` 🛟 ${entry.id} (strength ${strength.toFixed(4)} < ${DECAY_THRESHOLD})${rankNote}`);
|
|
193
264
|
}
|
|
194
265
|
else {
|
|
195
|
-
|
|
196
|
-
result.details.push(` 🗑 removed ${entry.id} (strength ${strength.toFixed(4)} < ${DECAY_THRESHOLD})`);
|
|
197
|
-
if (!dryRun) {
|
|
198
|
-
pendingDeletes.push(entry.id);
|
|
199
|
-
}
|
|
266
|
+
retireFaded(entry, strength);
|
|
200
267
|
}
|
|
201
268
|
}
|
|
202
269
|
else {
|
|
@@ -212,12 +279,8 @@ export async function consolidate(hippoRoot, options = {}) {
|
|
|
212
279
|
else {
|
|
213
280
|
for (const entry of all) {
|
|
214
281
|
const strength = calculateStrength(entry, now, decayOpts);
|
|
215
|
-
if (
|
|
216
|
-
|
|
217
|
-
result.details.push(` 🗑 removed ${entry.id} (strength ${strength.toFixed(4)} < ${DECAY_THRESHOLD})`);
|
|
218
|
-
if (!dryRun) {
|
|
219
|
-
pendingDeletes.push(entry.id);
|
|
220
|
-
}
|
|
282
|
+
if (retirable(entry) && strength < DECAY_THRESHOLD) {
|
|
283
|
+
retireFaded(entry, strength);
|
|
221
284
|
}
|
|
222
285
|
else {
|
|
223
286
|
// Only strength is a cached computation; confidence stays as stored.
|
|
@@ -423,26 +486,34 @@ export async function consolidate(hippoRoot, options = {}) {
|
|
|
423
486
|
// 1.6. Batch extraction — extract facts from episodic memories missing them
|
|
424
487
|
// -------------------------------------------------------------------------
|
|
425
488
|
const extractedFromIds = new Set(survivors.filter((e) => e.extracted_from).map((e) => e.extracted_from));
|
|
426
|
-
const extractionCandidates = survivors.filter((e) => e.layer === Layer.Episodic && !extractedFromIds.has(e.id));
|
|
489
|
+
const extractionCandidates = survivors.filter((e) => e.layer === Layer.Episodic && !e.superseded_by && !extractedFromIds.has(e.id));
|
|
427
490
|
result.extractionCandidates = extractionCandidates.length;
|
|
428
|
-
|
|
491
|
+
// extraction.enabled=false is the opt-out for every LLM phase below, key or no key.
|
|
492
|
+
const apiKey = config.extraction.enabled !== false ? (process.env.ANTHROPIC_API_KEY ?? '') : '';
|
|
493
|
+
const llmErrorsSeen = new Set();
|
|
494
|
+
const llmError = (phase) => (msg) => {
|
|
495
|
+
const line = ` ⚠️ ${phase}: ${msg}`;
|
|
496
|
+
if (llmErrorsSeen.has(line))
|
|
497
|
+
return;
|
|
498
|
+
llmErrorsSeen.add(line);
|
|
499
|
+
result.details.push(line);
|
|
500
|
+
console.error(`consolidate ${phase}: ${msg}`);
|
|
501
|
+
};
|
|
502
|
+
const llmOpts = { apiKey, model: config.extraction.model, fetcher: options.fetcher };
|
|
429
503
|
if (apiKey && extractionCandidates.length > 0 && !dryRun) {
|
|
430
504
|
const { extractFacts, storeExtractedFacts } = await import('./extract.js');
|
|
431
505
|
const batchLimit = 20;
|
|
432
506
|
let extractedCount = 0;
|
|
433
507
|
for (const candidate of extractionCandidates.slice(0, batchLimit)) {
|
|
434
508
|
try {
|
|
435
|
-
const facts = await extractFacts(candidate.content, {
|
|
436
|
-
apiKey,
|
|
437
|
-
model: config.extraction.model,
|
|
438
|
-
});
|
|
509
|
+
const facts = await extractFacts(candidate.content, { ...llmOpts, onError: llmError('extraction') });
|
|
439
510
|
if (facts.length > 0) {
|
|
440
511
|
storeExtractedFacts(hippoRoot, candidate, facts);
|
|
441
512
|
extractedCount += facts.length;
|
|
442
513
|
}
|
|
443
514
|
}
|
|
444
|
-
catch {
|
|
445
|
-
|
|
515
|
+
catch (err) {
|
|
516
|
+
llmError('extraction')(String(err));
|
|
446
517
|
}
|
|
447
518
|
}
|
|
448
519
|
result.extracted = extractedCount;
|
|
@@ -450,22 +521,19 @@ export async function consolidate(hippoRoot, options = {}) {
|
|
|
450
521
|
// -------------------------------------------------------------------------
|
|
451
522
|
// 1.7. DAG summarization — cluster extracted facts and generate summaries
|
|
452
523
|
// -------------------------------------------------------------------------
|
|
453
|
-
const extractedFacts = survivors.filter((e) => e.tags.includes('extracted') && e.dag_level === 1);
|
|
524
|
+
const extractedFacts = survivors.filter((e) => e.tags.includes('extracted') && e.dag_level === 1 && !e.superseded_by);
|
|
454
525
|
if (apiKey && extractedFacts.length >= 3 && !dryRun) {
|
|
455
526
|
try {
|
|
456
527
|
const { buildDag } = await import('./dag.js');
|
|
457
|
-
const dagResult = await buildDag(hippoRoot, extractedFacts, {
|
|
458
|
-
apiKey,
|
|
459
|
-
model: config.extraction.model,
|
|
460
|
-
});
|
|
528
|
+
const dagResult = await buildDag(hippoRoot, extractedFacts, { ...llmOpts, onError: llmError('dag') });
|
|
461
529
|
result.dagCandidateClusters = dagResult.candidateClusters;
|
|
462
530
|
result.dagSummariesCreated = dagResult.summariesCreated;
|
|
463
531
|
if (dagResult.summariesCreated > 0) {
|
|
464
532
|
result.details.push(` 🌳 DAG: ${dagResult.summariesCreated} summaries created, ${dagResult.factsLinked} facts linked`);
|
|
465
533
|
}
|
|
466
534
|
}
|
|
467
|
-
catch {
|
|
468
|
-
|
|
535
|
+
catch (err) {
|
|
536
|
+
llmError('dag')(String(err));
|
|
469
537
|
}
|
|
470
538
|
}
|
|
471
539
|
// -------------------------------------------------------------------------
|
|
@@ -485,11 +553,7 @@ export async function consolidate(hippoRoot, options = {}) {
|
|
|
485
553
|
const cap = Number.isFinite(rawCap) && rawCap > 0
|
|
486
554
|
? Math.min(rawCap, 1000)
|
|
487
555
|
: 20;
|
|
488
|
-
const rebuildResult = await rebuildDirtySummaries(hippoRoot, {
|
|
489
|
-
apiKey,
|
|
490
|
-
model: config.extraction.model,
|
|
491
|
-
cap,
|
|
492
|
-
});
|
|
556
|
+
const rebuildResult = await rebuildDirtySummaries(hippoRoot, { ...llmOpts, onError: llmError('dag rebuild'), cap });
|
|
493
557
|
result.summariesRebuilt = rebuildResult.rebuilt;
|
|
494
558
|
result.summariesRebuildFailed = rebuildResult.failed;
|
|
495
559
|
result.summariesZeroChildSkipped = rebuildResult.zeroChildSkipped;
|
|
@@ -510,8 +574,8 @@ export async function consolidate(hippoRoot, options = {}) {
|
|
|
510
574
|
result.details.push(` 🌳 DAG rebuild: ${parts.join(', ')}`);
|
|
511
575
|
}
|
|
512
576
|
}
|
|
513
|
-
catch {
|
|
514
|
-
|
|
577
|
+
catch (err) {
|
|
578
|
+
llmError('dag rebuild')(String(err));
|
|
515
579
|
}
|
|
516
580
|
}
|
|
517
581
|
// -------------------------------------------------------------------------
|
|
@@ -529,18 +593,15 @@ export async function consolidate(hippoRoot, options = {}) {
|
|
|
529
593
|
const { loadAllL2Summaries } = await import('./store.js');
|
|
530
594
|
const l2Summaries = loadAllL2Summaries(hippoRoot);
|
|
531
595
|
if (l2Summaries.length >= 2) {
|
|
532
|
-
const profileResult = await buildEntityProfiles(hippoRoot, l2Summaries, {
|
|
533
|
-
apiKey,
|
|
534
|
-
model: config.extraction.model,
|
|
535
|
-
});
|
|
596
|
+
const profileResult = await buildEntityProfiles(hippoRoot, l2Summaries, { ...llmOpts, onError: llmError('dag profiles') });
|
|
536
597
|
result.entityProfilesCreated = profileResult.profilesCreated;
|
|
537
598
|
if (profileResult.profilesCreated > 0) {
|
|
538
599
|
result.details.push(` 🌲 DAG L3: ${profileResult.profilesCreated} entity profiles, ${profileResult.l2sLinked} L2s linked`);
|
|
539
600
|
}
|
|
540
601
|
}
|
|
541
602
|
}
|
|
542
|
-
catch {
|
|
543
|
-
|
|
603
|
+
catch (err) {
|
|
604
|
+
llmError('dag profiles')(String(err));
|
|
544
605
|
}
|
|
545
606
|
}
|
|
546
607
|
// -------------------------------------------------------------------------
|
|
@@ -599,7 +660,7 @@ export async function consolidate(hippoRoot, options = {}) {
|
|
|
599
660
|
// -------------------------------------------------------------------------
|
|
600
661
|
// 3. Merge pass - episodic entries only
|
|
601
662
|
// -------------------------------------------------------------------------
|
|
602
|
-
const mergeCandidates = survivors.filter((e) => e.layer === Layer.Episodic && !e.tags.includes('extracted'));
|
|
663
|
+
const mergeCandidates = survivors.filter((e) => e.layer === Layer.Episodic && !e.superseded_by && !e.tags.includes('extracted'));
|
|
603
664
|
const used = new Set();
|
|
604
665
|
// T1 fix (2026-08-15 hardening pass): partition by tenantId BEFORE the
|
|
605
666
|
// overlap loop so a cluster can never span tenants. Previously textOverlap
|
|
@@ -735,9 +796,35 @@ export async function consolidate(hippoRoot, options = {}) {
|
|
|
735
796
|
if (mergesSkippedRejected > 0) {
|
|
736
797
|
console.error(`consolidate: skipped ${mergesSkippedRejected} merge(s) whose content matches a rejected value`);
|
|
737
798
|
}
|
|
738
|
-
|
|
799
|
+
result.removedIds = pendingDeletes;
|
|
800
|
+
// One transaction; the snapshot keeps what the DAG passes and other writers changed while sleep ran.
|
|
801
|
+
// Dormant moves ride in the same transaction (src/dormant.ts).
|
|
739
802
|
if (!dryRun) {
|
|
740
|
-
batchWriteAndDelete(hippoRoot, pendingWrites, pendingDeletes);
|
|
803
|
+
const left = new Set(batchWriteAndDelete(hippoRoot, pendingWrites, pendingDeletes, { snapshot, dormant: pendingDormant }));
|
|
804
|
+
for (const id of [...pendingDeletes, ...pendingDormant.map((m) => m.entry.id)]) {
|
|
805
|
+
if (!left.has(id))
|
|
806
|
+
result.details.push(` ↩ ${id} not removed: pinned or already gone before sleep saved`);
|
|
807
|
+
}
|
|
808
|
+
result.removedIds = pendingDeletes.filter((id) => left.has(id));
|
|
809
|
+
result.removed = result.removedIds.length;
|
|
810
|
+
result.dormant = pendingDormant.filter((m) => left.has(m.entry.id)).length;
|
|
811
|
+
}
|
|
812
|
+
// Dormant retention: a dormant memory nobody restored within
|
|
813
|
+
// dormant.retentionDays is deleted for good (0 keeps them forever). Runs
|
|
814
|
+
// even when dormant.enabled is off, so turning it off still ages out what
|
|
815
|
+
// earlier sleeps kept.
|
|
816
|
+
if (config.dormant.retentionDays > 0) {
|
|
817
|
+
const cutoff = new Date(now.getTime() - config.dormant.retentionDays * 24 * 60 * 60 * 1000).toISOString();
|
|
818
|
+
const db = openHippoDb(hippoRoot);
|
|
819
|
+
try {
|
|
820
|
+
result.dormantExpired = dryRun ? countExpiredDormant(db, cutoff) : purgeExpiredDormant(db, cutoff);
|
|
821
|
+
}
|
|
822
|
+
finally {
|
|
823
|
+
closeHippoDb(db);
|
|
824
|
+
}
|
|
825
|
+
if (result.dormantExpired > 0) {
|
|
826
|
+
result.details.push(` ⌛ ${dryRun ? 'would expire' : 'expired'} ${result.dormantExpired} dormant memor${result.dormantExpired === 1 ? 'y' : 'ies'} older than ${config.dormant.retentionDays} days`);
|
|
827
|
+
}
|
|
741
828
|
}
|
|
742
829
|
// -------------------------------------------------------------------------
|
|
743
830
|
// 4. Log run
|
package/dist/dag.d.ts
CHANGED
|
@@ -9,6 +9,7 @@ export interface DagSummaryOptions {
|
|
|
9
9
|
apiKey: string;
|
|
10
10
|
model?: string;
|
|
11
11
|
fetcher?: typeof fetch;
|
|
12
|
+
onError?: (msg: string) => void;
|
|
12
13
|
}
|
|
13
14
|
export declare function generateDagSummary(label: string, factContents: string[], opts: DagSummaryOptions): Promise<string | null>;
|
|
14
15
|
export interface DagBuildResult {
|
package/dist/dag.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { createMemory, Layer } from './memory.js';
|
|
2
2
|
import { writeEntry, loadAllDirtySummaries, loadChildrenOfSummary, applyRebuildResult, clearSummaryDirtyAfterBuild, } from './store.js';
|
|
3
3
|
import { RejectedValueError } from './rejection.js';
|
|
4
|
+
import { redactSecrets } from './secret-detect.js';
|
|
4
5
|
export function clusterFacts(facts) {
|
|
5
6
|
if (facts.length === 0)
|
|
6
7
|
return [];
|
|
@@ -42,9 +43,9 @@ Write a single concise paragraph (2-4 sentences) that captures all the key infor
|
|
|
42
43
|
export async function generateDagSummary(label, factContents, opts) {
|
|
43
44
|
const model = opts.model ?? 'claude-sonnet-4-6';
|
|
44
45
|
const fetchFn = opts.fetcher ?? fetch;
|
|
45
|
-
const factsBlock = factContents.map((f, i) => `${i + 1}. ${f}`).join('\n');
|
|
46
|
+
const factsBlock = factContents.map((f, i) => `${i + 1}. ${redactSecrets(f)}`).join('\n');
|
|
46
47
|
const prompt = DAG_SUMMARY_PROMPT
|
|
47
|
-
.replace('{label}', label)
|
|
48
|
+
.replace('{label}', redactSecrets(label))
|
|
48
49
|
.replace('{facts}', factsBlock);
|
|
49
50
|
let res;
|
|
50
51
|
try {
|
|
@@ -62,17 +63,21 @@ export async function generateDagSummary(label, factContents, opts) {
|
|
|
62
63
|
}),
|
|
63
64
|
});
|
|
64
65
|
}
|
|
65
|
-
catch {
|
|
66
|
+
catch (err) {
|
|
67
|
+
opts.onError?.(`request failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
66
68
|
return null;
|
|
67
69
|
}
|
|
68
|
-
if (!res.ok)
|
|
70
|
+
if (!res.ok) {
|
|
71
|
+
opts.onError?.(`HTTP ${res.status}`);
|
|
69
72
|
return null;
|
|
73
|
+
}
|
|
70
74
|
try {
|
|
71
75
|
const data = await res.json();
|
|
72
76
|
const text = data.content?.[0]?.text?.trim() ?? '';
|
|
73
77
|
return text.length >= 20 ? text : null;
|
|
74
78
|
}
|
|
75
|
-
catch {
|
|
79
|
+
catch (err) {
|
|
80
|
+
opts.onError?.(`unparseable response: ${err instanceof Error ? err.message : String(err)}`);
|
|
76
81
|
return null;
|
|
77
82
|
}
|
|
78
83
|
}
|
package/dist/dashboard.js
CHANGED
|
@@ -14,6 +14,7 @@ import { listPeers } from './shared.js';
|
|
|
14
14
|
import { loadEmbeddingIndex } from './embeddings.js';
|
|
15
15
|
import { resolveTenantId } from './tenant.js';
|
|
16
16
|
import { loadCardDetail } from './card-detail.js';
|
|
17
|
+
import { isCrossSite, LOOPBACK_HOST_HEADER } from './server.js';
|
|
17
18
|
function buildDashboardData(hippoRoot) {
|
|
18
19
|
// A5: scope dashboard to active tenant. Without this, the UI surfaces every
|
|
19
20
|
// tenant's memories on a multi-tenant deployment.
|
|
@@ -122,8 +123,6 @@ const MIME_TYPES = {
|
|
|
122
123
|
'.ico': 'image/x-icon',
|
|
123
124
|
'.woff2': 'font/woff2',
|
|
124
125
|
};
|
|
125
|
-
// Binds 127.0.0.1 only; refusing other Hosts closes the DNS-rebinding route.
|
|
126
|
-
const LOOPBACK_HOST = /^(localhost|127\.0\.0\.1)(:\d+)?$/i;
|
|
127
126
|
function isStaticFileExtension(ext) {
|
|
128
127
|
return Object.hasOwn(MIME_TYPES, ext);
|
|
129
128
|
}
|
|
@@ -156,7 +155,7 @@ export function serveDashboard(hippoRoot, port = 3333) {
|
|
|
156
155
|
const hasDistUi = fs.existsSync(path.join(distUiDir, 'index.html'));
|
|
157
156
|
const handleRequest = (req, res) => {
|
|
158
157
|
const host = req.headers.host;
|
|
159
|
-
if (host !== undefined && !
|
|
158
|
+
if (host !== undefined && !LOOPBACK_HOST_HEADER.test(host)) {
|
|
160
159
|
res.writeHead(403, { 'Content-Type': 'text/plain' });
|
|
161
160
|
res.end('Forbidden');
|
|
162
161
|
return;
|
|
@@ -168,6 +167,11 @@ export function serveDashboard(hippoRoot, port = 3333) {
|
|
|
168
167
|
// POST /api/star/:id - toggle starred on a memory
|
|
169
168
|
const starMatch = pathname.match(/^\/api\/star\/([A-Za-z0-9_\-]+)$/);
|
|
170
169
|
if (starMatch && req.method === 'POST') {
|
|
170
|
+
if (isCrossSite(req)) {
|
|
171
|
+
res.writeHead(403, { 'Content-Type': 'text/plain' });
|
|
172
|
+
res.end('Forbidden');
|
|
173
|
+
return;
|
|
174
|
+
}
|
|
171
175
|
const id = starMatch[1];
|
|
172
176
|
const entry = readEntry(hippoRoot, id, resolveTenantId({}));
|
|
173
177
|
if (!entry)
|
package/dist/db.js
CHANGED
|
@@ -11,7 +11,7 @@ const require = createRequire(import.meta.url);
|
|
|
11
11
|
// runtime (Node's built-in synchronous SQLite module); there are no bundled
|
|
12
12
|
// types for it here, so this require + cast is the module's documented boundary.
|
|
13
13
|
const { DatabaseSync } = require('node:sqlite');
|
|
14
|
-
const CURRENT_SCHEMA_VERSION =
|
|
14
|
+
const CURRENT_SCHEMA_VERSION = 45;
|
|
15
15
|
const MIGRATIONS = [
|
|
16
16
|
{
|
|
17
17
|
version: 1,
|
|
@@ -2367,6 +2367,62 @@ const MIGRATIONS = [
|
|
|
2367
2367
|
`);
|
|
2368
2368
|
},
|
|
2369
2369
|
},
|
|
2370
|
+
{
|
|
2371
|
+
version: 44,
|
|
2372
|
+
up: (db) => {
|
|
2373
|
+
// Dormant memories (src/dormant.ts): with `dormant.enabled`, the sleep
|
|
2374
|
+
// decay pass moves a faded memory here instead of deleting it. The row
|
|
2375
|
+
// leaves `memories` in the same transaction, so recall, context and
|
|
2376
|
+
// every sleep pass stop seeing it; entry_json is the full MemoryEntry
|
|
2377
|
+
// snapshot `hippo dormant restore` writes back. No FK to memories (the
|
|
2378
|
+
// memories row is gone by design). Additive only, v41 precedent: no
|
|
2379
|
+
// min_compatible_binary bump. An older binary ignores the table and
|
|
2380
|
+
// keeps deleting faded memories as it always did.
|
|
2381
|
+
db.exec(`
|
|
2382
|
+
CREATE TABLE IF NOT EXISTS dormant_memories (
|
|
2383
|
+
tenant_id TEXT NOT NULL DEFAULT 'default',
|
|
2384
|
+
id TEXT NOT NULL,
|
|
2385
|
+
content TEXT NOT NULL,
|
|
2386
|
+
entry_json TEXT NOT NULL,
|
|
2387
|
+
reason TEXT NOT NULL,
|
|
2388
|
+
strength REAL NOT NULL,
|
|
2389
|
+
dormant_at TEXT NOT NULL,
|
|
2390
|
+
PRIMARY KEY (tenant_id, id)
|
|
2391
|
+
) WITHOUT ROWID;
|
|
2392
|
+
CREATE INDEX IF NOT EXISTS idx_dormant_memories_tenant_time
|
|
2393
|
+
ON dormant_memories(tenant_id, dormant_at DESC);
|
|
2394
|
+
`);
|
|
2395
|
+
},
|
|
2396
|
+
},
|
|
2397
|
+
{
|
|
2398
|
+
version: 45,
|
|
2399
|
+
up: (db) => {
|
|
2400
|
+
// Token ledger (src/token-ledger.ts, ROADMAP TE0): one row per block of
|
|
2401
|
+
// memory text hippo hands an agent (hook, CLI, MCP, HTTP). `event` is
|
|
2402
|
+
// 'inject' (sent), 'skip' (unchanged since the session's last inject,
|
|
2403
|
+
// not sent) or 'reset' (compaction dropped earlier injections, so the
|
|
2404
|
+
// next one must be sent). block_hash lets the per-prompt hook skip an
|
|
2405
|
+
// unchanged block. Rows older than the retention window are pruned on
|
|
2406
|
+
// write. Additive only: no min_compatible_binary bump.
|
|
2407
|
+
db.exec(`
|
|
2408
|
+
CREATE TABLE IF NOT EXISTS token_ledger (
|
|
2409
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
2410
|
+
ts TEXT NOT NULL,
|
|
2411
|
+
tenant_id TEXT NOT NULL DEFAULT 'default',
|
|
2412
|
+
session_id TEXT,
|
|
2413
|
+
surface TEXT NOT NULL,
|
|
2414
|
+
event TEXT NOT NULL,
|
|
2415
|
+
items INTEGER NOT NULL DEFAULT 0,
|
|
2416
|
+
tokens INTEGER NOT NULL DEFAULT 0,
|
|
2417
|
+
block_hash TEXT
|
|
2418
|
+
);
|
|
2419
|
+
CREATE INDEX IF NOT EXISTS idx_token_ledger_session
|
|
2420
|
+
ON token_ledger(tenant_id, session_id, surface, id DESC);
|
|
2421
|
+
CREATE INDEX IF NOT EXISTS idx_token_ledger_ts
|
|
2422
|
+
ON token_ledger(ts);
|
|
2423
|
+
`);
|
|
2424
|
+
},
|
|
2425
|
+
},
|
|
2370
2426
|
];
|
|
2371
2427
|
function tableHasColumn(db, tableName, columnName) {
|
|
2372
2428
|
if (!/^[a-z_]+$/i.test(tableName))
|
|
@@ -2389,16 +2445,12 @@ export function getHippoDbPath(hippoRoot) {
|
|
|
2389
2445
|
export function getCurrentSchemaVersion() {
|
|
2390
2446
|
return CURRENT_SCHEMA_VERSION;
|
|
2391
2447
|
}
|
|
2392
|
-
|
|
2393
|
-
|
|
2394
|
-
|
|
2395
|
-
|
|
2396
|
-
|
|
2397
|
-
|
|
2398
|
-
return row?.value ?? null;
|
|
2399
|
-
}
|
|
2400
|
-
catch {
|
|
2401
|
-
return null;
|
|
2448
|
+
/** Refuse a store stamped for a newer binary. Fails closed: runMigrations creates meta first, so a failed read is a real error. */
|
|
2449
|
+
function assertBinaryCompatible(db) {
|
|
2450
|
+
const minRequired = getMeta(db, 'min_compatible_binary');
|
|
2451
|
+
if (minRequired && compareSemver(minRequired, PACKAGE_VERSION) > 0) {
|
|
2452
|
+
throw new Error(`hippo-memory: this database requires hippo-memory >= ${minRequired}, but the running binary is ${PACKAGE_VERSION}. ` +
|
|
2453
|
+
`Upgrade hippo-memory to open it; an older binary does not know this schema and could expose private rows or damage the store.`);
|
|
2402
2454
|
}
|
|
2403
2455
|
}
|
|
2404
2456
|
function isSqliteBusy(error) {
|
|
@@ -2456,17 +2508,8 @@ export function openHippoDb(hippoRoot) {
|
|
|
2456
2508
|
}
|
|
2457
2509
|
function runMigrations(db, hippoRoot) {
|
|
2458
2510
|
ensureMetaTable(db);
|
|
2459
|
-
//
|
|
2460
|
-
|
|
2461
|
-
// leak github:private:* rows on no-scope recall. Refuse to open a DB stamped
|
|
2462
|
-
// with a min newer than this binary's version. Read BEFORE migrations so a
|
|
2463
|
-
// stale v1.2.0 binary cannot apply unknown future migrations either.
|
|
2464
|
-
const minRequired = readMinCompatibleBinary(db);
|
|
2465
|
-
if (minRequired && compareSemver(minRequired, PACKAGE_VERSION) > 0) {
|
|
2466
|
-
throw new Error(`hippo-memory: this database requires hippo-memory >= ${minRequired}, but the running binary is ${PACKAGE_VERSION}. ` +
|
|
2467
|
-
`Upgrade hippo-memory to open this database. Running an older binary against this DB would leak private rows that the ` +
|
|
2468
|
-
`older filter does not recognize.`);
|
|
2469
|
-
}
|
|
2511
|
+
// Before anything writes, so a stale binary never repairs or migrates a store it does not understand.
|
|
2512
|
+
assertBinaryCompatible(db);
|
|
2470
2513
|
let currentVersion = getSchemaVersion(db);
|
|
2471
2514
|
if (currentVersion > 0)
|
|
2472
2515
|
ensureContinuityTables(db);
|
|
@@ -2475,6 +2518,8 @@ function runMigrations(db, hippoRoot) {
|
|
|
2475
2518
|
continue;
|
|
2476
2519
|
execWithBusyRetry(db, 'BEGIN IMMEDIATE');
|
|
2477
2520
|
try {
|
|
2521
|
+
// A newer binary may have migrated and raised the minimum while we waited for the lock.
|
|
2522
|
+
assertBinaryCompatible(db);
|
|
2478
2523
|
// Re-read under the write lock: another process may have applied this
|
|
2479
2524
|
// migration while we waited, and re-running one is not idempotent.
|
|
2480
2525
|
const applied = getSchemaVersion(db);
|
|
@@ -2672,8 +2717,8 @@ function ensureOptionalFts(db) {
|
|
|
2672
2717
|
backfillFtsIndex(db);
|
|
2673
2718
|
available = true;
|
|
2674
2719
|
}
|
|
2675
|
-
catch {
|
|
2676
|
-
|
|
2720
|
+
catch (err) {
|
|
2721
|
+
console.error(`hippo: full-text index unavailable (${err instanceof Error ? err.message : String(err)}); search falls back to slower LIKE matching`);
|
|
2677
2722
|
}
|
|
2678
2723
|
// Read-first: only write when the flag actually changed, so a healthy
|
|
2679
2724
|
// store's open doesn't take a write lock for a same-value upsert.
|
package/dist/dedupe.d.ts
CHANGED
|
@@ -70,5 +70,6 @@ export declare function strengthBucket(strength: number | null | undefined): num
|
|
|
70
70
|
export declare function deduplicateStore(hippoRoot: string, options?: {
|
|
71
71
|
threshold?: number;
|
|
72
72
|
dryRun?: boolean;
|
|
73
|
+
actor?: string;
|
|
73
74
|
}): DedupResult;
|
|
74
75
|
//# sourceMappingURL=dedupe.d.ts.map
|
package/dist/dedupe.js
CHANGED
|
@@ -23,6 +23,7 @@
|
|
|
23
23
|
import { textOverlap } from './search.js';
|
|
24
24
|
import { loadAllEntries, deleteEntry } from './store.js';
|
|
25
25
|
import { compareEntryIdentity } from './compare.js';
|
|
26
|
+
import { canAutoDelete } from './memory.js';
|
|
26
27
|
/** Quantization step for strength-tie comparisons. The historical 0.01
|
|
27
28
|
* epsilon (see `strengthBucket` below) applied via rounding instead of a
|
|
28
29
|
* raw abs-diff threshold, so the tiebreak is transitive. */
|
|
@@ -111,7 +112,7 @@ export function deduplicateStore(hippoRoot, options = {}) {
|
|
|
111
112
|
if (removed.has(tenantEntries[i].id))
|
|
112
113
|
continue;
|
|
113
114
|
for (let j = i + 1; j < tenantEntries.length; j++) {
|
|
114
|
-
if (removed.has(tenantEntries[j].id))
|
|
115
|
+
if (removed.has(tenantEntries[j].id) || !canAutoDelete(tenantEntries[j]))
|
|
115
116
|
continue;
|
|
116
117
|
const similarity = textOverlap(tenantEntries[i].content, tenantEntries[j].content);
|
|
117
118
|
if (similarity <= threshold)
|
|
@@ -131,11 +132,7 @@ export function deduplicateStore(hippoRoot, options = {}) {
|
|
|
131
132
|
}
|
|
132
133
|
}
|
|
133
134
|
}
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
deleteEntry(hippoRoot, id);
|
|
137
|
-
}
|
|
138
|
-
}
|
|
139
|
-
return { removed: removed.size, pairs };
|
|
135
|
+
const done = dryRun ? pairs : pairs.filter((p) => deleteEntry(hippoRoot, p.removed, { actor: options.actor, reason: `dedup: duplicate of ${p.kept}`, automatic: true }));
|
|
136
|
+
return { removed: done.length, pairs: done };
|
|
140
137
|
}
|
|
141
138
|
//# sourceMappingURL=dedupe.js.map
|
package/dist/doctor.d.ts
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/** Outcome of one check. `fail` makes `hippo doctor` exit 1. */
|
|
2
|
+
export type DoctorStatus = 'pass' | 'warn' | 'fail' | 'info';
|
|
3
|
+
/** One check in a {@link DoctorReport}. */
|
|
4
|
+
export interface DoctorCheck {
|
|
5
|
+
id: string;
|
|
6
|
+
status: DoctorStatus;
|
|
7
|
+
detail: string;
|
|
8
|
+
/** Command or step that resolves a warn or fail. */
|
|
9
|
+
fix?: string;
|
|
10
|
+
}
|
|
11
|
+
/** Result of {@link runDoctor}. */
|
|
12
|
+
export interface DoctorReport {
|
|
13
|
+
ok: boolean;
|
|
14
|
+
version: string;
|
|
15
|
+
/** The store the checks ran against, or null when none exists. */
|
|
16
|
+
store: string | null;
|
|
17
|
+
checks: DoctorCheck[];
|
|
18
|
+
}
|
|
19
|
+
/** Inputs for {@link runDoctor}; defaults come from the process. */
|
|
20
|
+
export interface DoctorOpts {
|
|
21
|
+
cwd?: string;
|
|
22
|
+
/** Home directory used to find agent configuration (~/.claude). */
|
|
23
|
+
home?: string;
|
|
24
|
+
version: string;
|
|
25
|
+
nodeVersion?: string;
|
|
26
|
+
now?: Date;
|
|
27
|
+
}
|
|
28
|
+
/** Minimum Node.js version hippo supports (package.json engines). */
|
|
29
|
+
export declare const MIN_NODE = "22.16.0";
|
|
30
|
+
/** Run every check. Never throws for a broken install; broken parts become failed checks. */
|
|
31
|
+
export declare function runDoctor(opts: DoctorOpts): DoctorReport;
|
|
32
|
+
/** Human-readable rendering of a {@link DoctorReport}. */
|
|
33
|
+
export declare function formatDoctor(report: DoctorReport): string;
|
|
34
|
+
//# sourceMappingURL=doctor.d.ts.map
|