hippo-memory 1.60.0 → 1.61.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 +1 -1
- package/dist/ablation.js +9 -27
- package/dist/agent-memories/apply.js +4 -1
- package/dist/agent-memories/claude-code.js +1 -1
- package/dist/agent-memories/codex.js +1 -1
- package/dist/agent-memories/gemini.js +1 -1
- package/dist/agent-memories/legacy.js +1 -1
- package/dist/agent-memories/source.js +1 -1
- package/dist/agent-memories/sync.js +8 -3
- package/dist/ambient-store.d.ts +14 -0
- package/dist/ambient-store.js +90 -0
- package/dist/ambient.d.ts +23 -0
- package/dist/ambient.js +72 -50
- package/dist/api/assemble.d.ts +93 -0
- package/dist/api/assemble.js +152 -0
- package/dist/api/audit.d.ts +17 -0
- package/dist/api/audit.js +23 -0
- package/dist/api/auth.d.ts +79 -0
- package/dist/api/auth.js +178 -0
- package/dist/api/context-types.d.ts +105 -0
- package/dist/api/context-types.js +3 -0
- package/dist/api/context.d.ts +31 -0
- package/dist/api/context.js +705 -0
- package/dist/api/dormant.d.ts +30 -0
- package/dist/api/dormant.js +140 -0
- package/dist/api/drill-down.d.ts +84 -0
- package/dist/api/drill-down.js +123 -0
- package/dist/api/forget.d.ts +57 -0
- package/dist/api/forget.js +87 -0
- package/dist/api/goals.d.ts +18 -0
- package/dist/api/goals.js +33 -0
- package/dist/api/learn.d.ts +31 -0
- package/dist/api/learn.js +88 -0
- package/dist/api/outcome.d.ts +61 -0
- package/dist/api/outcome.js +66 -0
- package/dist/api/promote.d.ts +54 -0
- package/dist/api/promote.js +203 -0
- package/dist/api/quarantine.d.ts +24 -0
- package/dist/api/quarantine.js +121 -0
- package/dist/api/recall-types.d.ts +390 -0
- package/dist/api/recall-types.js +3 -0
- package/dist/api/recall.d.ts +36 -0
- package/dist/api/recall.js +634 -0
- package/dist/api/remember.d.ts +35 -0
- package/dist/api/remember.js +43 -0
- package/dist/api/sleep.d.ts +136 -0
- package/dist/api/sleep.js +271 -0
- package/dist/api/tokens.d.ts +26 -0
- package/dist/api/tokens.js +60 -0
- package/dist/api/types.d.ts +56 -0
- package/dist/api/types.js +38 -0
- package/dist/api.d.ts +20 -1262
- package/dist/api.js +25 -2727
- package/dist/audit.d.ts +3 -0
- package/dist/audit.js +6 -3
- package/dist/auth.d.ts +45 -4
- package/dist/auth.js +125 -48
- package/dist/autolearn.js +2 -2
- package/dist/capture/command.d.ts +33 -0
- package/dist/capture/command.js +264 -0
- package/dist/capture/compact.d.ts +44 -0
- package/dist/capture/compact.js +354 -0
- package/dist/capture/extract.d.ts +21 -0
- package/dist/capture/extract.js +464 -0
- package/dist/capture/transcript.d.ts +40 -0
- package/dist/capture/transcript.js +193 -0
- package/dist/capture-error.js +2 -1
- package/dist/churn-git.js +4 -2
- package/dist/cli/audit.d.ts +3 -0
- package/dist/cli/audit.js +159 -0
- package/dist/cli/auth.d.ts +2 -0
- package/dist/cli/auth.js +171 -0
- package/dist/cli/briefs.d.ts +4 -0
- package/dist/cli/briefs.js +435 -0
- package/dist/cli/card.d.ts +3 -0
- package/dist/cli/card.js +333 -0
- package/dist/cli/context.d.ts +15 -0
- package/dist/cli/context.js +366 -0
- package/dist/cli/continuity.d.ts +6 -0
- package/dist/cli/continuity.js +445 -0
- package/dist/cli/curate.d.ts +19 -0
- package/dist/cli/curate.js +555 -0
- package/dist/cli/dag.d.ts +5 -0
- package/dist/cli/dag.js +177 -0
- package/dist/cli/decisions.d.ts +4 -0
- package/dist/cli/decisions.js +528 -0
- package/dist/cli/eval.d.ts +5 -0
- package/dist/cli/eval.js +213 -0
- package/dist/cli/explain.d.ts +4 -0
- package/dist/cli/explain.js +150 -0
- package/dist/cli/goals.d.ts +2 -0
- package/dist/cli/goals.js +196 -0
- package/dist/cli/hook-blocks.d.ts +18 -0
- package/dist/cli/hook-blocks.js +233 -0
- package/dist/cli/init.d.ts +2 -0
- package/dist/cli/init.js +305 -0
- package/dist/cli/maintenance.d.ts +4 -0
- package/dist/cli/maintenance.js +179 -0
- package/dist/cli/playbooks.d.ts +4 -0
- package/dist/cli/playbooks.js +556 -0
- package/dist/cli/projects.js +1 -1
- package/dist/cli/recall.d.ts +7 -0
- package/dist/cli/recall.js +597 -0
- package/dist/cli/remember.d.ts +5 -0
- package/dist/cli/remember.js +442 -0
- package/dist/cli/serve.d.ts +5 -0
- package/dist/cli/serve.js +40 -0
- package/dist/cli/session-hooks.d.ts +29 -0
- package/dist/cli/session-hooks.js +637 -0
- package/dist/cli/setup.d.ts +4 -0
- package/dist/cli/setup.js +376 -0
- package/dist/cli/shared.d.ts +15 -19
- package/dist/cli/shared.js +50 -341
- package/dist/cli/slack.d.ts +2 -0
- package/dist/cli/slack.js +171 -0
- package/dist/cli/status.d.ts +18 -0
- package/dist/cli/status.js +400 -0
- package/dist/cli/transfer.d.ts +10 -0
- package/dist/cli/transfer.js +438 -0
- package/dist/cli/usage.d.ts +85 -0
- package/dist/cli/usage.js +741 -0
- package/dist/cli.d.ts +71 -120
- package/dist/cli.js +170 -8469
- package/dist/client.js +15 -8
- package/dist/compaction-record.js +6 -4
- package/dist/connectors/github/backfill.js +94 -87
- package/dist/connectors/github/cli-impl.js +4 -3
- package/dist/connectors/github/dlq.js +67 -54
- package/dist/connectors/github/ingest.js +34 -35
- package/dist/connectors/github/tenant-routing.js +3 -2
- package/dist/connectors/github/webhook.js +135 -216
- package/dist/connectors/slack/dlq.js +49 -61
- package/dist/connectors/slack/ingest.js +55 -48
- package/dist/connectors/slack/tenant-routing.js +4 -3
- package/dist/connectors/slack/webhook.js +72 -74
- package/dist/consolidate/conflicts.d.ts +10 -0
- package/dist/consolidate/conflicts.js +178 -0
- package/dist/consolidate/decay.d.ts +12 -0
- package/dist/consolidate/decay.js +145 -0
- package/dist/consolidate/llm-passes.d.ts +3 -0
- package/dist/consolidate/llm-passes.js +141 -0
- package/dist/consolidate/merge.d.ts +7 -0
- package/dist/consolidate/merge.js +251 -0
- package/dist/consolidate/physics-pass.d.ts +3 -0
- package/dist/consolidate/physics-pass.js +60 -0
- package/dist/consolidate/run.d.ts +69 -0
- package/dist/consolidate/run.js +76 -0
- package/dist/consolidate/sleep.d.ts +18 -0
- package/dist/consolidate/sleep.js +209 -0
- package/dist/consolidate/traces.d.ts +4 -0
- package/dist/consolidate/traces.js +178 -0
- package/dist/context-auto.js +7 -11
- package/dist/context-render.d.ts +1 -1
- package/dist/context-render.js +1 -1
- package/dist/customer-notes.d.ts +3 -0
- package/dist/customer-notes.js +6 -4
- package/dist/dag.js +6 -5
- package/dist/dashboard-actions.d.ts +20 -0
- package/dist/dashboard-actions.js +88 -0
- package/dist/dashboard-params.d.ts +45 -0
- package/dist/dashboard-params.js +127 -0
- package/dist/dashboard-queries.d.ts +15 -0
- package/dist/dashboard-queries.js +355 -0
- package/dist/dashboard-snapshot.d.ts +138 -0
- package/dist/dashboard-snapshot.js +308 -0
- package/dist/dashboard-types.d.ts +163 -0
- package/dist/dashboard-types.js +3 -0
- package/dist/dashboard.d.ts +6 -7
- package/dist/dashboard.js +228 -202
- package/dist/db/busy.d.ts +5 -0
- package/dist/db/busy.js +24 -0
- package/dist/db/continuity.d.ts +5 -0
- package/dist/db/continuity.js +145 -0
- package/dist/db/meta.d.ts +8 -0
- package/dist/db/meta.js +35 -0
- package/dist/db/migrate.d.ts +9 -0
- package/dist/db/migrate.js +138 -0
- package/dist/db/migrations/index.d.ts +5 -0
- package/dist/db/migrations/index.js +109 -0
- package/dist/db/migrations/types.d.ts +14 -0
- package/dist/db/migrations/types.js +2 -0
- package/dist/db/migrations/v01.d.ts +3 -0
- package/dist/db/migrations/v01.js +38 -0
- package/dist/db/migrations/v02.d.ts +3 -0
- package/dist/db/migrations/v02.js +21 -0
- package/dist/db/migrations/v03.d.ts +3 -0
- package/dist/db/migrations/v03.js +22 -0
- package/dist/db/migrations/v04.d.ts +3 -0
- package/dist/db/migrations/v04.js +28 -0
- package/dist/db/migrations/v05.d.ts +3 -0
- package/dist/db/migrations/v05.js +21 -0
- package/dist/db/migrations/v06.d.ts +3 -0
- package/dist/db/migrations/v06.js +25 -0
- package/dist/db/migrations/v07.d.ts +3 -0
- package/dist/db/migrations/v07.js +13 -0
- package/dist/db/migrations/v08.d.ts +3 -0
- package/dist/db/migrations/v08.js +8 -0
- package/dist/db/migrations/v09.d.ts +3 -0
- package/dist/db/migrations/v09.js +13 -0
- package/dist/db/migrations/v10.d.ts +3 -0
- package/dist/db/migrations/v10.js +17 -0
- package/dist/db/migrations/v11.d.ts +3 -0
- package/dist/db/migrations/v11.js +15 -0
- package/dist/db/migrations/v12.d.ts +3 -0
- package/dist/db/migrations/v12.js +11 -0
- package/dist/db/migrations/v13.d.ts +3 -0
- package/dist/db/migrations/v13.js +15 -0
- package/dist/db/migrations/v14.d.ts +3 -0
- package/dist/db/migrations/v14.js +66 -0
- package/dist/db/migrations/v15.d.ts +3 -0
- package/dist/db/migrations/v15.js +42 -0
- package/dist/db/migrations/v16.d.ts +3 -0
- package/dist/db/migrations/v16.js +61 -0
- package/dist/db/migrations/v17.d.ts +3 -0
- package/dist/db/migrations/v17.js +46 -0
- package/dist/db/migrations/v18.d.ts +3 -0
- package/dist/db/migrations/v18.js +60 -0
- package/dist/db/migrations/v19.d.ts +3 -0
- package/dist/db/migrations/v19.js +28 -0
- package/dist/db/migrations/v20.d.ts +3 -0
- package/dist/db/migrations/v20.js +42 -0
- package/dist/db/migrations/v21.d.ts +3 -0
- package/dist/db/migrations/v21.js +16 -0
- package/dist/db/migrations/v22.d.ts +3 -0
- package/dist/db/migrations/v22.js +82 -0
- package/dist/db/migrations/v23.d.ts +3 -0
- package/dist/db/migrations/v23.js +48 -0
- package/dist/db/migrations/v24.d.ts +3 -0
- package/dist/db/migrations/v24.js +72 -0
- package/dist/db/migrations/v25.d.ts +3 -0
- package/dist/db/migrations/v25.js +46 -0
- package/dist/db/migrations/v26.d.ts +3 -0
- package/dist/db/migrations/v26.js +23 -0
- package/dist/db/migrations/v27.d.ts +3 -0
- package/dist/db/migrations/v27.js +57 -0
- package/dist/db/migrations/v28.d.ts +3 -0
- package/dist/db/migrations/v28.js +38 -0
- package/dist/db/migrations/v29.d.ts +3 -0
- package/dist/db/migrations/v29.js +78 -0
- package/dist/db/migrations/v30.d.ts +3 -0
- package/dist/db/migrations/v30.js +92 -0
- package/dist/db/migrations/v31.d.ts +3 -0
- package/dist/db/migrations/v31.js +74 -0
- package/dist/db/migrations/v32.d.ts +3 -0
- package/dist/db/migrations/v32.js +102 -0
- package/dist/db/migrations/v33.d.ts +3 -0
- package/dist/db/migrations/v33.js +104 -0
- package/dist/db/migrations/v34.d.ts +3 -0
- package/dist/db/migrations/v34.js +93 -0
- package/dist/db/migrations/v35.d.ts +3 -0
- package/dist/db/migrations/v35.js +98 -0
- package/dist/db/migrations/v36.d.ts +3 -0
- package/dist/db/migrations/v36.js +98 -0
- package/dist/db/migrations/v37.d.ts +3 -0
- package/dist/db/migrations/v37.js +219 -0
- package/dist/db/migrations/v38.d.ts +3 -0
- package/dist/db/migrations/v38.js +277 -0
- package/dist/db/migrations/v39.d.ts +3 -0
- package/dist/db/migrations/v39.js +59 -0
- package/dist/db/migrations/v40.d.ts +3 -0
- package/dist/db/migrations/v40.js +74 -0
- package/dist/db/migrations/v41.d.ts +3 -0
- package/dist/db/migrations/v41.js +43 -0
- package/dist/db/migrations/v42.d.ts +3 -0
- package/dist/db/migrations/v42.js +41 -0
- package/dist/db/migrations/v43.d.ts +3 -0
- package/dist/db/migrations/v43.js +67 -0
- package/dist/db/migrations/v44.d.ts +3 -0
- package/dist/db/migrations/v44.js +28 -0
- package/dist/db/migrations/v45.d.ts +3 -0
- package/dist/db/migrations/v45.js +30 -0
- package/dist/db/migrations/v46.d.ts +3 -0
- package/dist/db/migrations/v46.js +25 -0
- package/dist/db/migrations/v47.d.ts +3 -0
- package/dist/db/migrations/v47.js +17 -0
- package/dist/db/migrations/v48.d.ts +3 -0
- package/dist/db/migrations/v48.js +10 -0
- package/dist/db/migrations/v49.d.ts +3 -0
- package/dist/db/migrations/v49.js +31 -0
- package/dist/db/migrations/v50.d.ts +3 -0
- package/dist/db/migrations/v50.js +67 -0
- package/dist/db/migrations/v51.d.ts +3 -0
- package/dist/db/migrations/v51.js +14 -0
- package/dist/db/migrations/v52.d.ts +3 -0
- package/dist/db/migrations/v52.js +7 -0
- package/dist/db/open.d.ts +23 -0
- package/dist/db/open.js +146 -0
- package/dist/db/sqlite.d.ts +21 -0
- package/dist/db/sqlite.js +8 -0
- package/dist/db/tables.d.ts +7 -0
- package/dist/db/tables.js +38 -0
- package/dist/db.d.ts +6 -46
- package/dist/db.js +5 -3049
- package/dist/decisions.d.ts +4 -1
- package/dist/decisions.js +9 -7
- package/dist/dedupe.js +3 -2
- package/dist/delivery-recorder.js +4 -1
- package/dist/doctor.js +3 -3
- package/dist/embedding-provider.d.ts +1 -1
- package/dist/embedding-provider.js +4 -3
- package/dist/embeddings.d.ts +9 -52
- package/dist/embeddings.js +43 -297
- package/dist/env.d.ts +75 -0
- package/dist/env.js +119 -0
- package/dist/eval-suite.js +1 -1
- package/dist/eval.js +2 -2
- package/dist/extract.js +1 -1
- package/dist/gated-write.js +3 -1
- package/dist/goals.d.ts +3 -1
- package/dist/goals.js +18 -0
- package/dist/graph/read.d.ts +73 -0
- package/dist/graph/read.js +325 -0
- package/dist/graph/rows.d.ts +45 -0
- package/dist/graph/rows.js +51 -0
- package/dist/graph/types.d.ts +83 -0
- package/dist/graph/types.js +11 -0
- package/dist/graph/write.d.ts +93 -0
- package/dist/{graph.js → graph/write.js} +6 -384
- package/dist/graph-extract.js +2 -1
- package/dist/graph-recall.d.ts +1 -1
- package/dist/graph-recall.js +2 -2
- package/dist/graph-stream.js +1 -1
- package/dist/graph-view.d.ts +1 -1
- package/dist/graph-view.js +1 -1
- package/dist/half-life-migration.d.ts +1 -1
- package/dist/half-life-migration.js +2 -1
- package/dist/hooks/codex-session.d.ts +8 -0
- package/dist/hooks/codex-session.js +76 -0
- package/dist/hooks/codex-wrapper.d.ts +55 -0
- package/dist/hooks/codex-wrapper.js +288 -0
- package/dist/hooks/json-hooks.d.ts +63 -0
- package/dist/hooks/json-hooks.js +356 -0
- package/dist/hooks/opencode.d.ts +50 -0
- package/dist/hooks/opencode.js +202 -0
- package/dist/hooks/shared.d.ts +54 -0
- package/dist/hooks/shared.js +77 -0
- package/dist/http-retry.d.ts +2 -0
- package/dist/http-retry.js +4 -3
- package/dist/http-util.d.ts +3 -0
- package/dist/http-util.js +10 -0
- package/dist/{importers.d.ts → importers/core.d.ts} +13 -17
- package/dist/importers/core.js +141 -0
- package/dist/importers/markdown-parse.d.ts +41 -0
- package/dist/importers/markdown-parse.js +132 -0
- package/dist/importers/markdown.d.ts +3 -0
- package/dist/importers/markdown.js +92 -0
- package/dist/importers/sources.d.ts +7 -0
- package/dist/importers/sources.js +229 -0
- package/dist/importers/vault.d.ts +11 -0
- package/dist/importers/vault.js +352 -0
- package/dist/incidents.d.ts +3 -0
- package/dist/incidents.js +7 -5
- package/dist/index.d.ts +25 -6
- package/dist/index.js +23 -6
- package/dist/invalidation.js +2 -1
- package/dist/judgment.js +2 -1
- package/dist/keyset.d.ts +13 -0
- package/dist/keyset.js +8 -0
- package/dist/local-embedding.d.ts +13 -0
- package/dist/local-embedding.js +165 -0
- package/dist/log.d.ts +7 -0
- package/dist/log.js +19 -1
- package/dist/mcp/admin-tools.d.ts +8 -0
- package/dist/mcp/admin-tools.js +116 -0
- package/dist/mcp/format.d.ts +27 -0
- package/dist/mcp/format.js +135 -0
- package/dist/mcp/memory-tools.d.ts +5 -0
- package/dist/mcp/memory-tools.js +83 -0
- package/dist/mcp/protocol.d.ts +83 -0
- package/dist/mcp/protocol.js +55 -0
- package/dist/mcp/recall-tools.d.ts +6 -0
- package/dist/mcp/recall-tools.js +320 -0
- package/dist/mcp/request.d.ts +10 -0
- package/dist/mcp/request.js +163 -0
- package/dist/mcp/server.d.ts +4 -75
- package/dist/mcp/server.js +7 -1190
- package/dist/mcp/session-state.d.ts +11 -0
- package/dist/mcp/session-state.js +28 -0
- package/dist/mcp/stdio.d.ts +8 -0
- package/dist/mcp/stdio.js +79 -0
- package/dist/mcp/tools.d.ts +11 -0
- package/dist/mcp/tools.js +247 -0
- package/dist/memory.d.ts +3 -0
- package/dist/memory.js +27 -1
- package/dist/multihop.d.ts +1 -1
- package/dist/multihop.js +2 -1
- package/dist/owner-validation.js +2 -1
- package/dist/physics-state.js +10 -7
- package/dist/policies.d.ts +3 -0
- package/dist/policies.js +8 -6
- package/dist/postinstall.js +3 -2
- package/dist/predictions/planning-fallacy.d.ts +100 -0
- package/dist/predictions/planning-fallacy.js +190 -0
- package/dist/{predictions.d.ts → predictions/store.d.ts} +7 -102
- package/dist/predictions/store.js +434 -0
- package/dist/processes.d.ts +3 -0
- package/dist/processes.js +7 -5
- package/dist/project-briefs.d.ts +3 -0
- package/dist/project-briefs.js +7 -5
- package/dist/project-identity.js +3 -2
- package/dist/project-merge.js +3 -1
- package/dist/quarantine.d.ts +2 -1
- package/dist/quarantine.js +8 -5
- package/dist/raw-archive.js +1 -1
- package/dist/recall-history.js +3 -2
- package/dist/recall-pipeline.d.ts +2 -2
- package/dist/recall-pipeline.js +16 -8
- package/dist/recall-scope.js +1 -1
- package/dist/recall-trace.d.ts +1 -1
- package/dist/refine-llm.js +2 -1
- package/dist/reject-flow.js +6 -1
- package/dist/rerankers/clef.js +6 -5
- package/dist/rerankers/jev.d.ts +1 -1
- package/dist/rerankers/jev.js +4 -4
- package/dist/rerankers/llm.d.ts +4 -2
- package/dist/rerankers/llm.js +58 -38
- package/dist/rerankers/types.d.ts +1 -1
- package/dist/salience.js +1 -1
- package/dist/scheduler.d.ts +1 -0
- package/dist/scheduler.js +26 -4
- package/dist/scope.js +4 -3
- package/dist/search/as-of.d.ts +10 -0
- package/dist/search/as-of.js +22 -0
- package/dist/search/bm25-search.d.ts +14 -0
- package/dist/search/bm25-search.js +43 -0
- package/dist/search/bm25.d.ts +15 -0
- package/dist/search/bm25.js +54 -0
- package/dist/search/boosts.d.ts +54 -0
- package/dist/search/boosts.js +94 -0
- package/dist/search/breakdown.d.ts +7 -0
- package/dist/search/breakdown.js +20 -0
- package/dist/search/explain.d.ts +25 -0
- package/dist/search/explain.js +31 -0
- package/dist/search/finalize.d.ts +8 -0
- package/dist/search/finalize.js +52 -0
- package/dist/search/fusion.d.ts +27 -0
- package/dist/search/fusion.js +42 -0
- package/dist/search/hybrid-score.d.ts +20 -0
- package/dist/search/hybrid-score.js +73 -0
- package/dist/search/hybrid.d.ts +46 -0
- package/dist/search/hybrid.js +64 -0
- package/dist/search/physics-search.d.ts +29 -0
- package/dist/search/physics-search.js +162 -0
- package/dist/search/rerank.d.ts +10 -0
- package/dist/search/rerank.js +72 -0
- package/dist/search/temporal.d.ts +15 -0
- package/dist/search/temporal.js +45 -0
- package/dist/search/types.d.ts +91 -0
- package/dist/search/types.js +2 -0
- package/dist/search/vector.d.ts +30 -0
- package/dist/search/vector.js +71 -0
- package/dist/secret-detect.d.ts +2 -0
- package/dist/secret-detect.js +2 -1
- package/dist/server/auth.d.ts +52 -0
- package/dist/server/auth.js +221 -0
- package/dist/server/client-ip.d.ts +25 -0
- package/dist/server/client-ip.js +92 -0
- package/dist/server/cursor.d.ts +23 -0
- package/dist/server/cursor.js +58 -0
- package/dist/server/lifecycle.d.ts +7 -0
- package/dist/server/lifecycle.js +29 -0
- package/dist/server/mcp-http.d.ts +5 -0
- package/dist/server/mcp-http.js +199 -0
- package/dist/server/request.d.ts +33 -0
- package/dist/server/request.js +103 -0
- package/dist/server/routes/admin.d.ts +9 -0
- package/dist/server/routes/admin.js +158 -0
- package/dist/server/routes/customer-notes.d.ts +7 -0
- package/dist/server/routes/customer-notes.js +112 -0
- package/dist/server/routes/decisions.d.ts +7 -0
- package/dist/server/routes/decisions.js +133 -0
- package/dist/server/routes/incidents.d.ts +7 -0
- package/dist/server/routes/incidents.js +126 -0
- package/dist/server/routes/memories.d.ts +10 -0
- package/dist/server/routes/memories.js +179 -0
- package/dist/server/routes/policies.d.ts +8 -0
- package/dist/server/routes/policies.js +151 -0
- package/dist/server/routes/predictions.d.ts +7 -0
- package/dist/server/routes/predictions.js +164 -0
- package/dist/server/routes/processes.d.ts +7 -0
- package/dist/server/routes/processes.js +161 -0
- package/dist/server/routes/project-briefs.d.ts +8 -0
- package/dist/server/routes/project-briefs.js +136 -0
- package/dist/server/routes/recall.d.ts +8 -0
- package/dist/server/routes/recall.js +340 -0
- package/dist/server/routes/skills.d.ts +8 -0
- package/dist/server/routes/skills.js +150 -0
- package/dist/server/types.d.ts +56 -0
- package/dist/server/types.js +2 -0
- package/dist/server/validation.d.ts +14 -0
- package/dist/server/validation.js +91 -0
- package/dist/server.d.ts +7 -61
- package/dist/server.js +69 -2362
- package/dist/session-digest.d.ts +1 -1
- package/dist/session-digest.js +9 -2
- package/dist/shared.d.ts +3 -1
- package/dist/shared.js +26 -22
- package/dist/skills.d.ts +3 -0
- package/dist/skills.js +7 -5
- package/dist/stdin.js +2 -2
- package/dist/store/audit-event.d.ts +19 -0
- package/dist/store/audit-event.js +33 -0
- package/dist/store/candidates.d.ts +42 -0
- package/dist/store/candidates.js +152 -0
- package/dist/store/conflicts.d.ts +44 -0
- package/dist/store/conflicts.js +444 -0
- package/dist/store/delete-and-batch.d.ts +63 -0
- package/dist/store/delete-and-batch.js +310 -0
- package/dist/store/entry-reads.d.ts +92 -0
- package/dist/store/entry-reads.js +255 -0
- package/dist/store/entry-row.d.ts +67 -0
- package/dist/store/entry-row.js +208 -0
- package/dist/store/entry-writes.d.ts +46 -0
- package/dist/store/entry-writes.js +148 -0
- package/dist/store/handoffs.d.ts +26 -0
- package/dist/store/handoffs.js +184 -0
- package/dist/store/index-and-stats.d.ts +52 -0
- package/dist/store/index-and-stats.js +214 -0
- package/dist/store/markdown.d.ts +10 -0
- package/dist/store/markdown.js +108 -0
- package/dist/store/mirrors.d.ts +49 -0
- package/dist/store/mirrors.js +312 -0
- package/dist/store/open.d.ts +15 -0
- package/dist/store/open.js +223 -0
- package/dist/store/rows.d.ts +178 -0
- package/dist/store/rows.js +158 -0
- package/dist/store/search-rows.d.ts +86 -0
- package/dist/store/search-rows.js +254 -0
- package/dist/store/sessions.d.ts +83 -0
- package/dist/store/sessions.js +272 -0
- package/dist/store/summaries.d.ts +94 -0
- package/dist/store/summaries.js +377 -0
- package/dist/store/tenant-lookup.d.ts +12 -0
- package/dist/store/tenant-lookup.js +16 -0
- package/dist/store-cards.js +2 -1
- package/dist/summary-dirty.d.ts +4 -0
- package/dist/summary-dirty.js +32 -0
- package/dist/support-bundle.js +4 -3
- package/dist/tenant.js +2 -2
- package/dist/tokenize.d.ts +2 -0
- package/dist/tokenize.js +16 -0
- package/dist/transcript-tail.d.ts +7 -0
- package/dist/transcript-tail.js +48 -0
- package/dist/vector-store.d.ts +27 -0
- package/dist/vector-store.js +210 -0
- package/dist/version.d.ts +2 -2
- package/dist/version.js +2 -2
- package/dist/working-memory.js +1 -1
- package/dist/yaml.js +36 -11
- package/dist-ui/assets/ibm-plex-mono-latin-400-normal-CvHOgSBP.woff +0 -0
- package/dist-ui/assets/ibm-plex-mono-latin-400-normal-DMJ8VG8y.woff2 +0 -0
- package/dist-ui/assets/ibm-plex-mono-latin-500-normal-CB9ihrfo.woff +0 -0
- package/dist-ui/assets/ibm-plex-mono-latin-500-normal-DSY6xOcd.woff2 +0 -0
- package/dist-ui/assets/ibm-plex-mono-latin-600-normal-BgSNZQsw.woff2 +0 -0
- package/dist-ui/assets/ibm-plex-mono-latin-600-normal-DWFSQ4vo.woff +0 -0
- package/dist-ui/assets/ibm-plex-sans-latin-400-normal-CDDApCn2.woff2 +0 -0
- package/dist-ui/assets/ibm-plex-sans-latin-400-normal-CYLoc0-x.woff +0 -0
- package/dist-ui/assets/ibm-plex-sans-latin-500-normal-6ng42L7E.woff2 +0 -0
- package/dist-ui/assets/ibm-plex-sans-latin-500-normal-BgVn5rGT.woff +0 -0
- package/dist-ui/assets/ibm-plex-sans-latin-600-normal-Cu4Hd6ag.woff +0 -0
- package/dist-ui/assets/ibm-plex-sans-latin-600-normal-CuJfVYMP.woff2 +0 -0
- package/dist-ui/assets/index-DPN7cP19.js +33 -0
- package/dist-ui/assets/index-dFloKRVr.css +1 -0
- package/dist-ui/index.html +3 -25
- 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 +1 -1
- package/dist/capture.d.ts +0 -155
- package/dist/capture.js +0 -1295
- package/dist/consolidate.d.ts +0 -58
- package/dist/consolidate.js +0 -1124
- package/dist/graph.d.ts +0 -245
- package/dist/hooks.d.ts +0 -208
- package/dist/hooks.js +0 -1076
- package/dist/importers.js +0 -900
- package/dist/predictions.js +0 -620
- package/dist/search.d.ts +0 -320
- package/dist/search.js +0 -970
- package/dist/store.d.ts +0 -776
- package/dist/store.js +0 -3473
- package/dist-ui/assets/d3-BiWEKnn4.js +0 -1
- package/dist-ui/assets/index-BhT8RvO6.js +0 -61
- package/dist-ui/assets/index-RoXXJ5dq.css +0 -1
- package/dist-ui/assets/three-BDgTxR1l.js +0 -4112
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
import { closeHippoDb, openHippoDb } from '../db.js';
|
|
2
|
+
import { rowToSessionHandoff, isHandoffOutcome, } from '../handoff.js';
|
|
3
|
+
import { RECALL_DEFAULT_DENY_SCOPES } from '../recall-scope.js';
|
|
4
|
+
import { assertTenantId } from '../tenant.js';
|
|
5
|
+
import { openStore } from './open.js';
|
|
6
|
+
import { loadActiveTaskSnapshot } from './sessions.js';
|
|
7
|
+
// W1: the nine-column SELECT was cloned four times (plan rule 8); one
|
|
8
|
+
// definition so a sixth caller can't drift from the other five.
|
|
9
|
+
/** Column list shared by every session_handoffs SELECT; store-cards.ts reuses it for the card handoff lookup. */
|
|
10
|
+
export const HANDOFF_COLUMNS = 'id, session_id, repo_root, task_id, summary, next_action, artifacts_json, scope, created_at, constraints_json, evidence_json, outcome, target_runtime, card_id';
|
|
11
|
+
/**
|
|
12
|
+
* Save a session handoff record. Returns the persisted handoff.
|
|
13
|
+
*/
|
|
14
|
+
export function saveSessionHandoff(hippoRoot, tenantId, handoff) {
|
|
15
|
+
assertTenantId('saveSessionHandoff', tenantId);
|
|
16
|
+
const db = openStore(hippoRoot);
|
|
17
|
+
const now = new Date().toISOString();
|
|
18
|
+
// v1.2: scope is wired through. Read-side default-deny in api.recall +
|
|
19
|
+
// cmdRecall continuity excludes slack:private:* and 'unknown:legacy'.
|
|
20
|
+
try {
|
|
21
|
+
const result = db.prepare(`
|
|
22
|
+
INSERT INTO session_handoffs(session_id, repo_root, task_id, summary, next_action, artifacts_json, scope, tenant_id, created_at, constraints_json, evidence_json, outcome, target_runtime, card_id)
|
|
23
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
24
|
+
`).run(handoff.sessionId, handoff.repoRoot ?? null, handoff.taskId ?? null, handoff.summary, handoff.nextAction ?? null, JSON.stringify(handoff.artifacts ?? []), handoff.scope ?? null, tenantId, now, JSON.stringify(handoff.constraints ?? []), handoff.evidence ? JSON.stringify(handoff.evidence) : null, handoff.outcome ?? null, handoff.targetRuntime ?? null, handoff.cardId ?? null);
|
|
25
|
+
const id = Number(result.lastInsertRowid ?? 0);
|
|
26
|
+
// SAFETY: row's shape matches HANDOFF_COLUMNS.
|
|
27
|
+
const row = db.prepare(`
|
|
28
|
+
SELECT ${HANDOFF_COLUMNS}
|
|
29
|
+
FROM session_handoffs
|
|
30
|
+
WHERE id = ?
|
|
31
|
+
`).get(id);
|
|
32
|
+
if (!row) {
|
|
33
|
+
throw new Error('Failed to reload saved session handoff');
|
|
34
|
+
}
|
|
35
|
+
return rowToSessionHandoff(row);
|
|
36
|
+
}
|
|
37
|
+
finally {
|
|
38
|
+
closeHippoDb(db);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
/** Load the most recent handoff, optionally filtered by session ID. */
|
|
42
|
+
export function loadLatestHandoff(hippoRoot, tenantId, sessionId, opts = {}) {
|
|
43
|
+
assertTenantId('loadLatestHandoff', tenantId);
|
|
44
|
+
const db = openStore(hippoRoot);
|
|
45
|
+
try {
|
|
46
|
+
const conditions = ['tenant_id = ?'];
|
|
47
|
+
const params = [tenantId];
|
|
48
|
+
if (sessionId) {
|
|
49
|
+
conditions.push('session_id = ?');
|
|
50
|
+
params.push(sessionId);
|
|
51
|
+
}
|
|
52
|
+
if (opts.excludeSessionId) {
|
|
53
|
+
conditions.push('session_id != ?');
|
|
54
|
+
params.push(opts.excludeSessionId);
|
|
55
|
+
}
|
|
56
|
+
if (opts.unfinishedOnly) {
|
|
57
|
+
// codex P2: restrict to each session's newest revision first — stampHandoffOutcome
|
|
58
|
+
// only stamps the newest row, so an older null-outcome revision must not resurrect.
|
|
59
|
+
conditions.push(`id IN (SELECT MAX(id) FROM session_handoffs WHERE tenant_id = ? GROUP BY session_id)`);
|
|
60
|
+
params.push(tenantId);
|
|
61
|
+
conditions.push(`(outcome IS NULL OR outcome IN ('partial','failure'))`);
|
|
62
|
+
}
|
|
63
|
+
if (opts.maxAgeMs != null) {
|
|
64
|
+
conditions.push('created_at >= ?');
|
|
65
|
+
params.push(new Date(Date.now() - opts.maxAgeMs).toISOString());
|
|
66
|
+
}
|
|
67
|
+
if (opts.scopeFilter === 'default-deny') {
|
|
68
|
+
// codex P2: admit scope before LIMIT 1, else a newer denied row hides an older eligible one.
|
|
69
|
+
const placeholders = RECALL_DEFAULT_DENY_SCOPES.map(() => '?').join(', ');
|
|
70
|
+
conditions.push(`(scope IS NULL OR (scope NOT IN (${placeholders}) AND scope NOT LIKE '%:private:%'))`);
|
|
71
|
+
params.push(...RECALL_DEFAULT_DENY_SCOPES);
|
|
72
|
+
}
|
|
73
|
+
// SAFETY: row's shape matches HANDOFF_COLUMNS.
|
|
74
|
+
const row = db.prepare(`
|
|
75
|
+
SELECT ${HANDOFF_COLUMNS}
|
|
76
|
+
FROM session_handoffs
|
|
77
|
+
WHERE ${conditions.join(' AND ')}
|
|
78
|
+
ORDER BY created_at DESC, id DESC
|
|
79
|
+
LIMIT 1
|
|
80
|
+
`).get(...params);
|
|
81
|
+
return row ? rowToSessionHandoff(row) : null;
|
|
82
|
+
}
|
|
83
|
+
finally {
|
|
84
|
+
closeHippoDb(db);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Load a specific handoff by its row ID.
|
|
89
|
+
*/
|
|
90
|
+
export function loadHandoffById(hippoRoot, tenantId, id) {
|
|
91
|
+
assertTenantId('loadHandoffById', tenantId);
|
|
92
|
+
const db = openStore(hippoRoot);
|
|
93
|
+
try {
|
|
94
|
+
// SAFETY: row's shape matches HANDOFF_COLUMNS.
|
|
95
|
+
const row = db.prepare(`
|
|
96
|
+
SELECT ${HANDOFF_COLUMNS}
|
|
97
|
+
FROM session_handoffs
|
|
98
|
+
WHERE id = ? AND tenant_id = ?
|
|
99
|
+
`).get(id, tenantId);
|
|
100
|
+
return row ? rowToSessionHandoff(row) : null;
|
|
101
|
+
}
|
|
102
|
+
finally {
|
|
103
|
+
closeHippoDb(db);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
/** Stamp the outcome on a session's newest handoff, only if it has none yet. Returns rows changed. */
|
|
107
|
+
export function stampHandoffOutcome(hippoRoot, tenantId, sessionId, outcome) {
|
|
108
|
+
assertTenantId('stampHandoffOutcome', tenantId);
|
|
109
|
+
const db = openStore(hippoRoot);
|
|
110
|
+
try {
|
|
111
|
+
const result = db.prepare(`
|
|
112
|
+
UPDATE session_handoffs SET outcome = ?
|
|
113
|
+
WHERE tenant_id = ? AND session_id = ? AND outcome IS NULL
|
|
114
|
+
AND id = (
|
|
115
|
+
SELECT id FROM session_handoffs
|
|
116
|
+
WHERE tenant_id = ? AND session_id = ?
|
|
117
|
+
ORDER BY created_at DESC, id DESC LIMIT 1
|
|
118
|
+
)
|
|
119
|
+
`).run(outcome, tenantId, sessionId, tenantId, sessionId);
|
|
120
|
+
return Number(result.changes ?? 0);
|
|
121
|
+
}
|
|
122
|
+
finally {
|
|
123
|
+
closeHippoDb(db);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
/** Auto-write a handoff at session-end (DF1 T3) from the session's active snapshot, else from `derived`, its transcript state.
|
|
127
|
+
* @param evidence best-effort git state; outcome comes from the newest session_complete event.
|
|
128
|
+
* @returns null when neither source is the session's, a newer handoff covers the snapshot, or the session's latest handoff was not read off its transcript. */
|
|
129
|
+
export function writeSessionEndHandoff(hippoRoot, tenantId, sessionId, evidence, derived = null) {
|
|
130
|
+
assertTenantId('writeSessionEndHandoff', tenantId);
|
|
131
|
+
const active = loadActiveTaskSnapshot(hippoRoot, tenantId);
|
|
132
|
+
const existing = loadLatestHandoff(hippoRoot, tenantId, sessionId);
|
|
133
|
+
let snapshot;
|
|
134
|
+
let handoffEvidence = evidence;
|
|
135
|
+
if (active && active.session_id === sessionId) {
|
|
136
|
+
// Strict '>': a same-millisecond tie must not swallow the session's only write (test 6e).
|
|
137
|
+
if (existing && existing.updatedAt > active.updated_at)
|
|
138
|
+
return null;
|
|
139
|
+
snapshot = active;
|
|
140
|
+
}
|
|
141
|
+
else {
|
|
142
|
+
// Only an earlier transcript read gives way; `hippo handoff create` and unmarked older handoffs keep winning.
|
|
143
|
+
if (!derived || (existing && existing.evidence?.derivedFrom !== 'transcript'))
|
|
144
|
+
return null;
|
|
145
|
+
snapshot = { ...derived, scope: null };
|
|
146
|
+
handoffEvidence = { ...evidence, derivedFrom: 'transcript' };
|
|
147
|
+
}
|
|
148
|
+
const db = openHippoDb(hippoRoot);
|
|
149
|
+
let outcome = null;
|
|
150
|
+
try {
|
|
151
|
+
// SAFETY: row's shape matches the single `content` column below.
|
|
152
|
+
const completeEvent = db.prepare(`
|
|
153
|
+
SELECT content FROM session_events
|
|
154
|
+
WHERE tenant_id = ? AND session_id = ? AND event_type = 'session_complete'
|
|
155
|
+
ORDER BY created_at DESC, id DESC LIMIT 1
|
|
156
|
+
`).get(tenantId, sessionId);
|
|
157
|
+
if (isHandoffOutcome(completeEvent?.content))
|
|
158
|
+
outcome = completeEvent.content;
|
|
159
|
+
}
|
|
160
|
+
finally {
|
|
161
|
+
closeHippoDb(db);
|
|
162
|
+
}
|
|
163
|
+
// codex P2: same-task refresh carries forward envelope fields nobody cleared,
|
|
164
|
+
// rather than dropping them when the snapshot rewrite has no opinion on them.
|
|
165
|
+
// codex P1: a scope mismatch must not leak private metadata into an unscoped envelope.
|
|
166
|
+
const carryForward = existing != null && existing.taskId === snapshot.task
|
|
167
|
+
&& (existing.scope ?? null) === (snapshot.scope ?? null);
|
|
168
|
+
return saveSessionHandoff(hippoRoot, tenantId, {
|
|
169
|
+
version: 1,
|
|
170
|
+
sessionId,
|
|
171
|
+
repoRoot: carryForward ? existing.repoRoot : undefined,
|
|
172
|
+
taskId: snapshot.task,
|
|
173
|
+
summary: snapshot.summary,
|
|
174
|
+
nextAction: snapshot.next_step,
|
|
175
|
+
artifacts: carryForward ? existing.artifacts : [],
|
|
176
|
+
scope: snapshot.scope,
|
|
177
|
+
evidence: handoffEvidence,
|
|
178
|
+
outcome,
|
|
179
|
+
constraints: carryForward ? existing.constraints : undefined,
|
|
180
|
+
targetRuntime: carryForward ? existing.targetRuntime : undefined,
|
|
181
|
+
cardId: carryForward ? existing.cardId : undefined,
|
|
182
|
+
});
|
|
183
|
+
}
|
|
184
|
+
//# sourceMappingURL=handoffs.js.map
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import type { HippoIndex, LegacyStats } from './rows.js';
|
|
2
|
+
/** Load the derived index from SQLite. Read-only: index.json is only ever written by `rebuildIndex`. */
|
|
3
|
+
export declare function loadIndex(hippoRoot: string): HippoIndex;
|
|
4
|
+
/**
|
|
5
|
+
* Persist mutable index metadata. Entry rows themselves are derived from SQLite.
|
|
6
|
+
*
|
|
7
|
+
* LC1 F1(c) structural fix: `last_retrieval_ids` and `last_trace_id` must
|
|
8
|
+
* land atomically — callers (getContext, cmdRecall) fold a freshly-written
|
|
9
|
+
* trace id into `index.last_trace_id` before calling this, relying on BOTH
|
|
10
|
+
* meta keys committing together. Wrapped in BEGIN/COMMIT so a crash or a
|
|
11
|
+
* mid-write failure can never advance one key without the other. index.json
|
|
12
|
+
* is left untouched; only `rebuildIndex` writes it.
|
|
13
|
+
*/
|
|
14
|
+
export declare function saveIndex(hippoRoot: string, index: HippoIndex): void;
|
|
15
|
+
/**
|
|
16
|
+
* Rebuild mirrors from SQLite, importing any legacy markdown files not already present.
|
|
17
|
+
*/
|
|
18
|
+
export declare function rebuildIndex(hippoRoot: string): HippoIndex;
|
|
19
|
+
export declare function updateStats(hippoRoot: string, delta: {
|
|
20
|
+
remembered?: number;
|
|
21
|
+
recalled?: number;
|
|
22
|
+
forgotten?: number;
|
|
23
|
+
}): void;
|
|
24
|
+
export declare function updateStatsUnlessBusy(hippoRoot: string, delta: Parameters<typeof updateStats>[1], committed: string): void;
|
|
25
|
+
export declare function loadStats(hippoRoot: string): LegacyStats;
|
|
26
|
+
export declare function appendConsolidationRun(hippoRoot: string, run: {
|
|
27
|
+
timestamp: string;
|
|
28
|
+
decayed: number;
|
|
29
|
+
merged: number;
|
|
30
|
+
removed: number;
|
|
31
|
+
}): void;
|
|
32
|
+
/** Rows a tenant created since the last sleep (runs are host-wide), looking back at most 24 hours. */
|
|
33
|
+
export declare function countCreatedSinceLastSleep(hippoRoot: string, tenantId: string, now?: Date): number;
|
|
34
|
+
/**
|
|
35
|
+
* Session decay context: provides the data needed for session-based and adaptive decay.
|
|
36
|
+
*/
|
|
37
|
+
export interface SessionDecayContext {
|
|
38
|
+
/** Total number of sleep (consolidation) cycles completed. */
|
|
39
|
+
sleepCount: number;
|
|
40
|
+
/** Average interval between recent sleep cycles, in days. 0 if < 2 cycles. */
|
|
41
|
+
avgSessionIntervalDays: number;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Load the session decay context from the store.
|
|
45
|
+
* Uses consolidation_runs timestamps to compute session intervals.
|
|
46
|
+
*/
|
|
47
|
+
export declare function loadSessionDecayContext(hippoRoot: string): SessionDecayContext;
|
|
48
|
+
/**
|
|
49
|
+
* Increment the sleep counter. Called after each consolidation run.
|
|
50
|
+
*/
|
|
51
|
+
export declare function incrementSleepCount(hippoRoot: string): void;
|
|
52
|
+
//# sourceMappingURL=index-and-stats.d.ts.map
|
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
import { closeHippoDb, setMeta, isSqliteBusy, pruneConsolidationRuns, getMeta } from '../db.js';
|
|
2
|
+
import { RejectedValueError } from '../rejection.js';
|
|
3
|
+
import { log } from '../log.js';
|
|
4
|
+
import { audit } from './audit-event.js';
|
|
5
|
+
import { stampOriginProjectForImport, upsertEntryRow } from './entry-row.js';
|
|
6
|
+
import { buildIndexFromDb, syncMirrorFiles, writeIndexMirror, writeStatsMirror, buildStatsFromDb } from './mirrors.js';
|
|
7
|
+
import { openStore, loadLegacyEntriesFromMarkdown } from './open.js';
|
|
8
|
+
/** Load the derived index from SQLite. Read-only: index.json is only ever written by `rebuildIndex`. */
|
|
9
|
+
export function loadIndex(hippoRoot) {
|
|
10
|
+
const db = openStore(hippoRoot);
|
|
11
|
+
try {
|
|
12
|
+
return buildIndexFromDb(db);
|
|
13
|
+
}
|
|
14
|
+
finally {
|
|
15
|
+
closeHippoDb(db);
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Persist mutable index metadata. Entry rows themselves are derived from SQLite.
|
|
20
|
+
*
|
|
21
|
+
* LC1 F1(c) structural fix: `last_retrieval_ids` and `last_trace_id` must
|
|
22
|
+
* land atomically — callers (getContext, cmdRecall) fold a freshly-written
|
|
23
|
+
* trace id into `index.last_trace_id` before calling this, relying on BOTH
|
|
24
|
+
* meta keys committing together. Wrapped in BEGIN/COMMIT so a crash or a
|
|
25
|
+
* mid-write failure can never advance one key without the other. index.json
|
|
26
|
+
* is left untouched; only `rebuildIndex` writes it.
|
|
27
|
+
*/
|
|
28
|
+
export function saveIndex(hippoRoot, index) {
|
|
29
|
+
const db = openStore(hippoRoot);
|
|
30
|
+
try {
|
|
31
|
+
db.exec('BEGIN');
|
|
32
|
+
try {
|
|
33
|
+
setMeta(db, 'last_retrieval_ids', JSON.stringify(index.last_retrieval_ids ?? []));
|
|
34
|
+
setMeta(db, 'last_trace_id', index.last_trace_id ?? '');
|
|
35
|
+
db.exec('COMMIT');
|
|
36
|
+
}
|
|
37
|
+
catch (error) {
|
|
38
|
+
try {
|
|
39
|
+
db.exec('ROLLBACK');
|
|
40
|
+
}
|
|
41
|
+
catch { /* already rolled back; keep the original error */ }
|
|
42
|
+
throw error;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
finally {
|
|
46
|
+
closeHippoDb(db);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Rebuild mirrors from SQLite, importing any legacy markdown files not already present.
|
|
51
|
+
*/
|
|
52
|
+
export function rebuildIndex(hippoRoot) {
|
|
53
|
+
const db = openStore(hippoRoot);
|
|
54
|
+
try {
|
|
55
|
+
// SAFETY: rows' shape matches the single `id` column selected above.
|
|
56
|
+
const existingIds = new Set(db.prepare(`SELECT id FROM memories`).all().map((row) => row.id));
|
|
57
|
+
const legacyEntries = loadLegacyEntriesFromMarkdown(hippoRoot).filter((entry) => !existingIds.has(entry.id));
|
|
58
|
+
if (legacyEntries.length > 0) {
|
|
59
|
+
db.exec('BEGIN');
|
|
60
|
+
try {
|
|
61
|
+
// AT1 (plan §3, round-3 redesign): same guard-with-per-row-skip as
|
|
62
|
+
// bootstrapLegacyStore — rebuildIndex is the other channel through
|
|
63
|
+
// which a stale markdown mirror could resurrect a rejected value.
|
|
64
|
+
// Refusal audit written INLINE (nothing rolls back on a skip).
|
|
65
|
+
let rejectedCount = 0;
|
|
66
|
+
for (const entry of legacyEntries) {
|
|
67
|
+
// v39: same store-derived origin stamp as bootstrapLegacyStore.
|
|
68
|
+
const stamped = stampOriginProjectForImport(hippoRoot, entry);
|
|
69
|
+
try {
|
|
70
|
+
upsertEntryRow(db, stamped);
|
|
71
|
+
}
|
|
72
|
+
catch (err) {
|
|
73
|
+
if (err instanceof RejectedValueError) {
|
|
74
|
+
rejectedCount++;
|
|
75
|
+
audit(db, 'reject_refusal', err.entryId, { digest: err.digest, reason: err.reason }, 'cli', err.tenantId);
|
|
76
|
+
continue;
|
|
77
|
+
}
|
|
78
|
+
throw err;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
if (rejectedCount > 0) {
|
|
82
|
+
log.warn(`rebuildIndex: skipped ${rejectedCount} rejected value(s) found in legacy mirrors`);
|
|
83
|
+
}
|
|
84
|
+
db.exec('COMMIT');
|
|
85
|
+
}
|
|
86
|
+
catch (err) {
|
|
87
|
+
try {
|
|
88
|
+
db.exec('ROLLBACK');
|
|
89
|
+
}
|
|
90
|
+
catch { /* ignore if no active txn */ }
|
|
91
|
+
throw err;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
syncMirrorFiles(hippoRoot, db);
|
|
95
|
+
const index = buildIndexFromDb(db);
|
|
96
|
+
writeIndexMirror(hippoRoot, index);
|
|
97
|
+
return index;
|
|
98
|
+
}
|
|
99
|
+
finally {
|
|
100
|
+
closeHippoDb(db);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
export function updateStats(hippoRoot, delta) {
|
|
104
|
+
const db = openStore(hippoRoot);
|
|
105
|
+
try {
|
|
106
|
+
// One atomic statement per counter, and only for counters the caller
|
|
107
|
+
// named: the read-modify-write this replaces both lost increments to a
|
|
108
|
+
// concurrent writer and stamped stale values over the untouched two.
|
|
109
|
+
const increments = [
|
|
110
|
+
['total_remembered', delta.remembered ?? 0],
|
|
111
|
+
['total_recalled', delta.recalled ?? 0],
|
|
112
|
+
['total_forgotten', delta.forgotten ?? 0],
|
|
113
|
+
];
|
|
114
|
+
for (const [key, amount] of increments) {
|
|
115
|
+
if (amount === 0)
|
|
116
|
+
continue;
|
|
117
|
+
// Both binds are the same string: node:sqlite binds a JS number as REAL,
|
|
118
|
+
// which would store "1.0" into this TEXT column instead of "1".
|
|
119
|
+
db.prepare(`
|
|
120
|
+
INSERT INTO meta(key, value) VALUES(?, ?)
|
|
121
|
+
ON CONFLICT(key) DO UPDATE SET value = CAST(meta.value AS INTEGER) + CAST(? AS INTEGER)
|
|
122
|
+
`).run(key, String(amount), String(amount));
|
|
123
|
+
}
|
|
124
|
+
writeStatsMirror(hippoRoot, buildStatsFromDb(db));
|
|
125
|
+
}
|
|
126
|
+
finally {
|
|
127
|
+
closeHippoDb(db);
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
export function updateStatsUnlessBusy(hippoRoot, delta, committed) {
|
|
131
|
+
try {
|
|
132
|
+
updateStats(hippoRoot, delta);
|
|
133
|
+
}
|
|
134
|
+
catch (err) {
|
|
135
|
+
if (!isSqliteBusy(err))
|
|
136
|
+
throw err;
|
|
137
|
+
log.warnThenDebug('stats-busy', `${committed}, but the store was busy, so the stats counters were not updated`);
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
export function loadStats(hippoRoot) {
|
|
141
|
+
const db = openStore(hippoRoot);
|
|
142
|
+
try {
|
|
143
|
+
return buildStatsFromDb(db);
|
|
144
|
+
}
|
|
145
|
+
finally {
|
|
146
|
+
closeHippoDb(db);
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
export function appendConsolidationRun(hippoRoot, run) {
|
|
150
|
+
const db = openStore(hippoRoot);
|
|
151
|
+
try {
|
|
152
|
+
db.prepare(`INSERT INTO consolidation_runs(timestamp, decayed, merged, removed) VALUES (?, ?, ?, ?)`).run(run.timestamp, run.decayed, run.merged, run.removed);
|
|
153
|
+
pruneConsolidationRuns(db, 50);
|
|
154
|
+
writeStatsMirror(hippoRoot, buildStatsFromDb(db));
|
|
155
|
+
}
|
|
156
|
+
finally {
|
|
157
|
+
closeHippoDb(db);
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
/** Rows a tenant created since the last sleep (runs are host-wide), looking back at most 24 hours. */
|
|
161
|
+
export function countCreatedSinceLastSleep(hippoRoot, tenantId, now = new Date()) {
|
|
162
|
+
const db = openStore(hippoRoot);
|
|
163
|
+
try {
|
|
164
|
+
const dayAgo = new Date(now.getTime() - 86_400_000).toISOString();
|
|
165
|
+
const row = db.prepare(`SELECT COUNT(*) AS n FROM memories WHERE tenant_id = ?
|
|
166
|
+
AND created > MAX(?, COALESCE((SELECT MAX(timestamp) FROM consolidation_runs), ''))`).get(tenantId, dayAgo);
|
|
167
|
+
return row.n;
|
|
168
|
+
}
|
|
169
|
+
finally {
|
|
170
|
+
closeHippoDb(db);
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
/**
|
|
174
|
+
* Load the session decay context from the store.
|
|
175
|
+
* Uses consolidation_runs timestamps to compute session intervals.
|
|
176
|
+
*/
|
|
177
|
+
export function loadSessionDecayContext(hippoRoot) {
|
|
178
|
+
const db = openStore(hippoRoot);
|
|
179
|
+
try {
|
|
180
|
+
// Get recent consolidation timestamps (last 20)
|
|
181
|
+
// SAFETY: rows' shape matches the single `timestamp` column above.
|
|
182
|
+
const rows = db.prepare(`SELECT timestamp FROM consolidation_runs ORDER BY timestamp DESC, id DESC LIMIT 20`).all();
|
|
183
|
+
const sleepCount = Number(getMeta(db, 'sleep_count', '0')) || rows.length;
|
|
184
|
+
if (rows.length < 2) {
|
|
185
|
+
return { sleepCount, avgSessionIntervalDays: 0 };
|
|
186
|
+
}
|
|
187
|
+
// Compute average interval between consecutive sessions
|
|
188
|
+
const timestamps = rows.map((r) => new Date(r.timestamp).getTime()).reverse();
|
|
189
|
+
let totalInterval = 0;
|
|
190
|
+
for (let i = 1; i < timestamps.length; i++) {
|
|
191
|
+
totalInterval += timestamps[i] - timestamps[i - 1];
|
|
192
|
+
}
|
|
193
|
+
const avgMs = totalInterval / (timestamps.length - 1);
|
|
194
|
+
const avgDays = avgMs / (1000 * 60 * 60 * 24);
|
|
195
|
+
return { sleepCount, avgSessionIntervalDays: Math.max(0, avgDays) };
|
|
196
|
+
}
|
|
197
|
+
finally {
|
|
198
|
+
closeHippoDb(db);
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
/**
|
|
202
|
+
* Increment the sleep counter. Called after each consolidation run.
|
|
203
|
+
*/
|
|
204
|
+
export function incrementSleepCount(hippoRoot) {
|
|
205
|
+
const db = openStore(hippoRoot);
|
|
206
|
+
try {
|
|
207
|
+
const current = Number(getMeta(db, 'sleep_count', '0')) || 0;
|
|
208
|
+
setMeta(db, 'sleep_count', String(current + 1));
|
|
209
|
+
}
|
|
210
|
+
finally {
|
|
211
|
+
closeHippoDb(db);
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
//# sourceMappingURL=index-and-stats.js.map
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { type MemoryEntry } from '../memory.js';
|
|
2
|
+
/**
|
|
3
|
+
* Serialize a MemoryEntry to markdown with YAML frontmatter.
|
|
4
|
+
*/
|
|
5
|
+
export declare function serializeEntry(entry: MemoryEntry): string;
|
|
6
|
+
/**
|
|
7
|
+
* Deserialize a markdown file to a MemoryEntry.
|
|
8
|
+
*/
|
|
9
|
+
export declare function deserializeEntry(raw: string): MemoryEntry | null;
|
|
10
|
+
//# sourceMappingURL=markdown.d.ts.map
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import { dumpFrontmatter, parseFrontmatter } from '../yaml.js';
|
|
2
|
+
/**
|
|
3
|
+
* Serialize a MemoryEntry to markdown with YAML frontmatter.
|
|
4
|
+
*/
|
|
5
|
+
export function serializeEntry(entry) {
|
|
6
|
+
const frontmatter = {
|
|
7
|
+
id: entry.id,
|
|
8
|
+
created: entry.created,
|
|
9
|
+
last_retrieved: entry.last_retrieved,
|
|
10
|
+
retrieval_count: entry.retrieval_count,
|
|
11
|
+
strength: Math.round(entry.strength * 10000) / 10000,
|
|
12
|
+
half_life_days: entry.half_life_days,
|
|
13
|
+
layer: entry.layer,
|
|
14
|
+
tags: entry.tags,
|
|
15
|
+
emotional_valence: entry.emotional_valence,
|
|
16
|
+
schema_fit: entry.schema_fit,
|
|
17
|
+
source: entry.source,
|
|
18
|
+
outcome_score: entry.outcome_score,
|
|
19
|
+
outcome_positive: entry.outcome_positive,
|
|
20
|
+
outcome_negative: entry.outcome_negative,
|
|
21
|
+
conflicts_with: entry.conflicts_with,
|
|
22
|
+
pinned: entry.pinned,
|
|
23
|
+
confidence: entry.confidence ?? 'observed',
|
|
24
|
+
parents: entry.parents ?? [],
|
|
25
|
+
starred: entry.starred ?? false,
|
|
26
|
+
trace_outcome: entry.trace_outcome ?? null,
|
|
27
|
+
source_session_id: entry.source_session_id ?? null,
|
|
28
|
+
kind: entry.kind ?? 'distilled',
|
|
29
|
+
scope: entry.scope ?? null,
|
|
30
|
+
owner: entry.owner ?? null,
|
|
31
|
+
artifact_ref: entry.artifact_ref ?? null,
|
|
32
|
+
};
|
|
33
|
+
// Emit tenant_id only when not 'default' to keep diffs clean for the dominant
|
|
34
|
+
// single-tenant case (mirrors the plan's task 7 guidance).
|
|
35
|
+
const tenantId = entry.tenantId ?? 'default';
|
|
36
|
+
if (tenantId !== 'default') {
|
|
37
|
+
frontmatter['tenant_id'] = tenantId;
|
|
38
|
+
}
|
|
39
|
+
// v39: '' (user-global) and null (unknown, hidden by default) must both round-trip;
|
|
40
|
+
// only undefined (unstamped) is omitted, so a rebuild stamps nothing it can read.
|
|
41
|
+
if (entry.origin_project !== undefined) {
|
|
42
|
+
frontmatter['origin_project'] = entry.origin_project;
|
|
43
|
+
}
|
|
44
|
+
// Spread into a fresh object literal: dumpFrontmatter's Record<string,
|
|
45
|
+
// YamlValue> parameter needs an index signature, which a named interface
|
|
46
|
+
// reference (EntryFrontmatterFields) doesn't structurally provide even
|
|
47
|
+
// though every property's value type already matches.
|
|
48
|
+
const fm = dumpFrontmatter({ ...frontmatter });
|
|
49
|
+
return `${fm}\n\n${entry.content}\n`;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Deserialize a markdown file to a MemoryEntry.
|
|
53
|
+
*/
|
|
54
|
+
export function deserializeEntry(raw) {
|
|
55
|
+
const { data, content } = parseFrontmatter(raw);
|
|
56
|
+
if (!data['id'] || !data['layer'])
|
|
57
|
+
return null;
|
|
58
|
+
// SAFETY: every `as X` below narrows a raw YAML frontmatter field to an
|
|
59
|
+
// enum/union member of MemoryEntry; frontmatter is only ever written by
|
|
60
|
+
// serializeEntry (whose own fields are typed), so out-of-range values here
|
|
61
|
+
// would indicate hand-edited files, which this parser is not required to
|
|
62
|
+
// reject — matches the pre-existing permissive-parse behavior.
|
|
63
|
+
return {
|
|
64
|
+
id: String(data['id']),
|
|
65
|
+
created: String(data['created'] ?? new Date().toISOString()),
|
|
66
|
+
last_retrieved: String(data['last_retrieved'] ?? new Date().toISOString()),
|
|
67
|
+
retrieval_count: Number(data['retrieval_count'] ?? 0),
|
|
68
|
+
strength: Number(data['strength'] ?? 1.0),
|
|
69
|
+
half_life_days: Number(data['half_life_days'] ?? 7),
|
|
70
|
+
layer: data['layer'],
|
|
71
|
+
tags: normalizeStringArray(data['tags']),
|
|
72
|
+
emotional_valence: data['emotional_valence'] ?? 'neutral',
|
|
73
|
+
schema_fit: Number(data['schema_fit'] ?? 0.5),
|
|
74
|
+
source: String(data['source'] ?? 'cli'),
|
|
75
|
+
outcome_score: data['outcome_score'] === null || data['outcome_score'] === undefined ? null : Number(data['outcome_score']),
|
|
76
|
+
outcome_positive: Number(data['outcome_positive'] ?? 0),
|
|
77
|
+
outcome_negative: Number(data['outcome_negative'] ?? 0),
|
|
78
|
+
conflicts_with: normalizeStringArray(data['conflicts_with']),
|
|
79
|
+
pinned: Boolean(data['pinned'] ?? false),
|
|
80
|
+
confidence: data['confidence'] ?? 'observed',
|
|
81
|
+
content: content.trim(),
|
|
82
|
+
parents: normalizeStringArray(data['parents']),
|
|
83
|
+
starred: Boolean(data['starred'] ?? false),
|
|
84
|
+
trace_outcome: data['trace_outcome'] ?? null,
|
|
85
|
+
source_session_id: data['source_session_id'] === null || data['source_session_id'] === undefined
|
|
86
|
+
? null
|
|
87
|
+
: String(data['source_session_id']),
|
|
88
|
+
valid_from: data['valid_from'] ? String(data['valid_from']) : String(data['created'] ?? new Date().toISOString()),
|
|
89
|
+
superseded_by: data['superseded_by'] === null || data['superseded_by'] === undefined
|
|
90
|
+
? null
|
|
91
|
+
: String(data['superseded_by']),
|
|
92
|
+
extracted_from: data['extracted_from'] ?? null,
|
|
93
|
+
dag_level: Number(data['dag_level'] ?? 0),
|
|
94
|
+
dag_parent_id: data['dag_parent_id'] ?? null,
|
|
95
|
+
kind: (data['kind'] ?? 'distilled'),
|
|
96
|
+
scope: data['scope'] === null || data['scope'] === undefined ? null : String(data['scope']),
|
|
97
|
+
owner: data['owner'] === null || data['owner'] === undefined ? null : String(data['owner']),
|
|
98
|
+
artifact_ref: data['artifact_ref'] === null || data['artifact_ref'] === undefined ? null : String(data['artifact_ref']),
|
|
99
|
+
tenantId: data['tenant_id'] === null || data['tenant_id'] === undefined ? 'default' : String(data['tenant_id']),
|
|
100
|
+
origin_project: !('origin_project' in data) ? undefined : data['origin_project'] === null ? null : String(data['origin_project']),
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
function normalizeStringArray(value) {
|
|
104
|
+
if (!Array.isArray(value))
|
|
105
|
+
return [];
|
|
106
|
+
return value.map((item) => String(item));
|
|
107
|
+
}
|
|
108
|
+
//# sourceMappingURL=markdown.js.map
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { Layer, type MemoryEntry } from '../memory.js';
|
|
2
|
+
import { openHippoDb } from '../db.js';
|
|
3
|
+
import { type TaskSnapshot, type SessionEvent, type HippoIndex, type LegacyStats } from './rows.js';
|
|
4
|
+
export declare function layerDir(root: string, layer: Layer): string;
|
|
5
|
+
export declare function ensureMirrorDirectories(hippoRoot: string): void;
|
|
6
|
+
export declare function writeActiveTaskMirror(hippoRoot: string, tenantId: string, snapshot: TaskSnapshot): void;
|
|
7
|
+
export declare function removeActiveTaskMirror(hippoRoot: string, tenantId: string): void;
|
|
8
|
+
export declare function writeRecentSessionMirror(hippoRoot: string, tenantId: string, events: SessionEvent[]): void;
|
|
9
|
+
export declare function writeMarkdownMirror(hippoRoot: string, entry: MemoryEntry): void;
|
|
10
|
+
export declare function removeEntryMirrors(hippoRoot: string, id: string): void;
|
|
11
|
+
/**
|
|
12
|
+
* AT1 mirror-purge honesty fix (docs/plans/2026-08-15-at1-rejected-value-tombstone.md):
|
|
13
|
+
* the candidate markdown mirror paths still on disk for `id`, computed the
|
|
14
|
+
* same way `removeEntryMirrors` walks them (one per layer: buffer/episodic/
|
|
15
|
+
* semantic), filtered to the ones that still `fs.existsSync`. Used to report
|
|
16
|
+
* an EXPLICIT path when a best-effort purge fails and no reaper exists to
|
|
17
|
+
* retry it — plain `removeEntryMirrors` returns void, giving no way to name
|
|
18
|
+
* which file is stuck.
|
|
19
|
+
*/
|
|
20
|
+
export declare function getExistingEntryMirrorPaths(hippoRoot: string, id: string): string[];
|
|
21
|
+
/**
|
|
22
|
+
* AT1 fix: best-effort markdown-mirror purge shared by `reject-flow.ts`'s
|
|
23
|
+
* `rejectValue` and `resolveConflict`'s post-commit purge. Both used to log
|
|
24
|
+
* "will retry via reaper on next open" for EVERY failure, but the reaper
|
|
25
|
+
* (`cleanupArchivedMirrors`, raw-archive-mirror-cleanup.ts) only scans
|
|
26
|
+
* `raw_archive` — that message was false for a non-raw id, which has no
|
|
27
|
+
* reaper at all.
|
|
28
|
+
*
|
|
29
|
+
* Retries the unlink once synchronously (the common real-world failure is a
|
|
30
|
+
* transient lock/AV-scanner false positive, not a permanent one). On a
|
|
31
|
+
* second failure: raw ids still get the honest reaper message (true); non-raw
|
|
32
|
+
* ids get the EXPLICIT leftover file path(s) and a manual-delete instruction,
|
|
33
|
+
* since nothing will ever retry them automatically.
|
|
34
|
+
*
|
|
35
|
+
* Returns true if the mirror ended up purged (first or second attempt).
|
|
36
|
+
*/
|
|
37
|
+
export declare function purgeMirrorBestEffort(hippoRoot: string, id: string, isRaw: boolean, logPrefix: string): boolean;
|
|
38
|
+
/** Derive the current `HippoIndex` from SQLite. Exported for `rebuildIndex`
|
|
39
|
+
* (the only index.json writer) and the longmemeval benchmark. */
|
|
40
|
+
export declare function buildIndexFromDb(db: ReturnType<typeof openHippoDb>): HippoIndex;
|
|
41
|
+
export declare function buildStatsFromDb(db: ReturnType<typeof openHippoDb>): LegacyStats;
|
|
42
|
+
/** Write the `index.json` mirror file for an already-derived index. Exported for
|
|
43
|
+
* `rebuildIndex` (the only index.json writer) and the longmemeval benchmark. */
|
|
44
|
+
export declare function writeIndexMirror(hippoRoot: string, index: HippoIndex): void;
|
|
45
|
+
export declare function writeStatsMirror(hippoRoot: string, stats: LegacyStats): void;
|
|
46
|
+
/** Mirrors are derived from SQLite and written after COMMIT, so a failed write warns instead of failing a committed change. */
|
|
47
|
+
export declare function mirrorBestEffort(what: string, write: () => void): void;
|
|
48
|
+
export declare function syncMirrorFiles(hippoRoot: string, db: ReturnType<typeof openHippoDb>): void;
|
|
49
|
+
//# sourceMappingURL=mirrors.d.ts.map
|