hippo-memory 1.60.0 → 1.62.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 +29 -54
- package/dist/ablation.js +9 -27
- package/dist/agent-memories/apply.d.ts +1 -1
- package/dist/agent-memories/apply.js +4 -1
- package/dist/agent-memories/claude-code.d.ts +3 -1
- package/dist/agent-memories/claude-code.js +54 -10
- 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.d.ts +3 -3
- package/dist/agent-memories/sync.js +22 -9
- package/dist/agent-memories/types.d.ts +0 -2
- 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 +153 -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-select.d.ts +49 -0
- package/dist/api/context-select.js +344 -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 +378 -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 +126 -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 +192 -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 +499 -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 +256 -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 +453 -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 +376 -0
- package/dist/cli/continuity.d.ts +6 -0
- package/dist/cli/continuity.js +457 -0
- package/dist/cli/curate.d.ts +19 -0
- package/dist/cli/curate.js +556 -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 +156 -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 +190 -0
- package/dist/cli/playbooks.d.ts +4 -0
- package/dist/cli/playbooks.js +573 -0
- package/dist/cli/projects.js +9 -6
- package/dist/cli/recall.d.ts +7 -0
- package/dist/cli/recall.js +582 -0
- package/dist/cli/remember.d.ts +5 -0
- package/dist/cli/remember.js +485 -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 +647 -0
- package/dist/cli/setup.d.ts +4 -0
- package/dist/cli/setup.js +397 -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 +409 -0
- package/dist/cli/transfer.d.ts +10 -0
- package/dist/cli/transfer.js +424 -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.d.ts +0 -2
- package/dist/compaction-record.js +7 -5
- 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 +83 -72
- package/dist/dag.js +225 -188
- 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 +102 -83
- package/dist/dedupe.js +3 -2
- package/dist/delivery-recorder.js +4 -1
- package/dist/doctor.js +14 -10
- 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 +117 -86
- 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 +52 -43
- 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 +93 -74
- 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 +94 -76
- package/dist/project-briefs.d.ts +3 -0
- package/dist/project-briefs.js +142 -113
- package/dist/project-identity.js +3 -2
- package/dist/project-merge.d.ts +12 -4
- package/dist/project-merge.js +132 -45
- 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 +12 -1
- package/dist/shared.js +33 -27
- package/dist/skills.d.ts +3 -0
- package/dist/skills.js +88 -70
- 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 +260 -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,192 @@
|
|
|
1
|
+
// Promote to the global store, supersede with a successor, and archive raw memories.
|
|
2
|
+
import { openHippoDb, closeHippoDb, isSqliteBusy } from '../db.js';
|
|
3
|
+
import { ConflictError, NotFoundError } from '../api-errors.js';
|
|
4
|
+
import { auditRejectionRefusal } from '../store/audit-event.js';
|
|
5
|
+
import { stampOriginProject } from '../store/entry-row.js';
|
|
6
|
+
import { removeEntryMirrors } from '../store/mirrors.js';
|
|
7
|
+
import { writeEntryDbOnly, writeEntryMirrors } from '../store/entry-writes.js';
|
|
8
|
+
import { readEntry } from '../store/entry-reads.js';
|
|
9
|
+
import { updateStatsUnlessBusy } from '../store/index-and-stats.js';
|
|
10
|
+
import { markSummaryDirtyInTx } from '../summary-dirty.js';
|
|
11
|
+
import { RejectedValueError } from '../rejection.js';
|
|
12
|
+
import { log } from '../log.js';
|
|
13
|
+
import { createSuccessor } from '../memory.js';
|
|
14
|
+
import { appendAuditEvent } from '../audit.js';
|
|
15
|
+
import { promoteToGlobal } from '../shared.js';
|
|
16
|
+
import { archiveRawMemory } from '../raw-archive.js';
|
|
17
|
+
import { loadConfig } from '../config.js';
|
|
18
|
+
import { selectMemoryTenant } from '../store/tenant-lookup.js';
|
|
19
|
+
export function promote(ctx, id) {
|
|
20
|
+
// Tenant scope: promoteToGlobal reads the entry from the local root via
|
|
21
|
+
// readEntry without a tenant filter, so a Bearer for tenant A could
|
|
22
|
+
// promote tenant B's row by guessing or leaking the id. Pre-check the
|
|
23
|
+
// row's tenant_id and deny cross-tenant access with the same not-found
|
|
24
|
+
// wording archiveRaw uses (no info leak about whether the id exists in
|
|
25
|
+
// another tenant).
|
|
26
|
+
const ownerDb = openHippoDb(ctx.hippoRoot);
|
|
27
|
+
try {
|
|
28
|
+
if (selectMemoryTenant(ownerDb, id) !== ctx.tenantId) {
|
|
29
|
+
throw new NotFoundError(`memory not found: ${id}`);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
finally {
|
|
33
|
+
closeHippoDb(ownerDb);
|
|
34
|
+
}
|
|
35
|
+
// The 'promote' row commits with the global copy, so no write follows the commit and a busy store fails the whole promote.
|
|
36
|
+
const globalEntry = promoteToGlobal(ctx.hippoRoot, id, {
|
|
37
|
+
actor: ctx.actor.subject,
|
|
38
|
+
tenantId: ctx.tenantId,
|
|
39
|
+
afterWrite: (db, globalId) => appendAuditEvent(db, {
|
|
40
|
+
tenantId: ctx.tenantId,
|
|
41
|
+
actor: ctx.actor.subject,
|
|
42
|
+
op: 'promote',
|
|
43
|
+
targetId: globalId,
|
|
44
|
+
metadata: { sourceId: id },
|
|
45
|
+
}),
|
|
46
|
+
});
|
|
47
|
+
return { ok: true, sourceId: id, globalId: globalEntry.id };
|
|
48
|
+
}
|
|
49
|
+
export function supersede(ctx, oldId, newContent) {
|
|
50
|
+
const old = readSupersedable(ctx, oldId);
|
|
51
|
+
const newEntry = createSuccessor(old, newContent, {
|
|
52
|
+
tenantId: ctx.tenantId,
|
|
53
|
+
baseHalfLifeDays: loadConfig(ctx.hippoRoot).defaultHalfLifeDays,
|
|
54
|
+
});
|
|
55
|
+
// Race-safe transition: open a fresh db handle, BEGIN IMMEDIATE, run all
|
|
56
|
+
// three steps (CAS on old + writeEntryDbOnly(new) + supersede audit row)
|
|
57
|
+
// inside the same transaction. Two concurrent supersedes: exactly one CAS
|
|
58
|
+
// wins (changes=1), the other gets changes=0 and throws CONFLICT. No
|
|
59
|
+
// dangling-pointer window: the new memory's row commits atomically with
|
|
60
|
+
// the old.superseded_by pointer.
|
|
61
|
+
const db = openHippoDb(ctx.hippoRoot);
|
|
62
|
+
try {
|
|
63
|
+
commitSupersede(db, ctx, oldId, old, newEntry);
|
|
64
|
+
// Mirrors after COMMIT, while the db handle is still open. Same
|
|
65
|
+
// invariant as the original writeEntry: a mirror failure leaves disk
|
|
66
|
+
// MISSING the markdown for the new memory (rebuildIndex rewrites every
|
|
67
|
+
// markdown mirror from the DB) but DOES NOT desync the DB or
|
|
68
|
+
// roll back the supersede. Logged + swallowed, non-fatal.
|
|
69
|
+
try {
|
|
70
|
+
writeEntryMirrors(ctx.hippoRoot, newEntry);
|
|
71
|
+
}
|
|
72
|
+
catch (mirrorErr) {
|
|
73
|
+
log.error(`supersede: mirror write failed (non-fatal, will self-heal): ${mirrorErr instanceof Error ? mirrorErr.message : String(mirrorErr)}`);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
finally {
|
|
77
|
+
closeHippoDb(db);
|
|
78
|
+
}
|
|
79
|
+
return { ok: true, oldId, newId: newEntry.id };
|
|
80
|
+
}
|
|
81
|
+
/** The tenant-scoped row to supersede; readEntry's tenant filter makes another tenant's id read as not found. */
|
|
82
|
+
function readSupersedable(ctx, oldId) {
|
|
83
|
+
const old = readEntry(ctx.hippoRoot, oldId, ctx.tenantId);
|
|
84
|
+
if (!old) {
|
|
85
|
+
throw new NotFoundError(`Memory not found: ${oldId}`);
|
|
86
|
+
}
|
|
87
|
+
// The CAS UPDATE closes the race; this check only gives a clearer error in the common single-writer case.
|
|
88
|
+
if (old.superseded_by) {
|
|
89
|
+
throw new ConflictError(`Memory ${oldId} is already superseded by ${old.superseded_by}. Supersede that one instead.`);
|
|
90
|
+
}
|
|
91
|
+
return old;
|
|
92
|
+
}
|
|
93
|
+
/** CAS on the old row, the successor's insert and the 'supersede' audit row, in one BEGIN IMMEDIATE transaction. */
|
|
94
|
+
function commitSupersede(db, ctx, oldId, old, newEntry) {
|
|
95
|
+
db.exec('BEGIN IMMEDIATE');
|
|
96
|
+
try {
|
|
97
|
+
// The tenant filter repeats readEntry's check at no cost, closing an ownership change between read and update.
|
|
98
|
+
const result = db.prepare(`
|
|
99
|
+
UPDATE memories
|
|
100
|
+
SET superseded_by = ?
|
|
101
|
+
WHERE id = ? AND tenant_id = ? AND superseded_by IS NULL
|
|
102
|
+
`).run(newEntry.id, oldId, ctx.tenantId);
|
|
103
|
+
if ((result.changes ?? 0) === 0) {
|
|
104
|
+
db.exec('ROLLBACK');
|
|
105
|
+
throw new ConflictError(`Memory ${oldId} already superseded by another writer`);
|
|
106
|
+
}
|
|
107
|
+
// After the CAS guard, so a lost race throws before the old parent is marked for rebuild.
|
|
108
|
+
if (old.dag_parent_id) {
|
|
109
|
+
markSummaryDirtyInTx(db, old.dag_parent_id, ctx.tenantId, ctx.actor.subject);
|
|
110
|
+
}
|
|
111
|
+
// Emits its own 'remember' audit row inside the same transaction.
|
|
112
|
+
writeEntryDbOnly(db, stampOriginProject(ctx.hippoRoot, newEntry), { actor: ctx.actor.subject });
|
|
113
|
+
appendAuditEvent(db, {
|
|
114
|
+
tenantId: ctx.tenantId,
|
|
115
|
+
actor: ctx.actor.subject,
|
|
116
|
+
op: 'supersede',
|
|
117
|
+
targetId: oldId,
|
|
118
|
+
metadata: { newId: newEntry.id },
|
|
119
|
+
});
|
|
120
|
+
db.exec('COMMIT');
|
|
121
|
+
}
|
|
122
|
+
catch (err) {
|
|
123
|
+
try {
|
|
124
|
+
db.exec('ROLLBACK');
|
|
125
|
+
}
|
|
126
|
+
catch { /* already rolled back */ }
|
|
127
|
+
// The refusal audit lands after ROLLBACK, in a fresh implicit transaction the aborted one cannot undo.
|
|
128
|
+
if (err instanceof RejectedValueError) {
|
|
129
|
+
auditRejectionRefusal(db, err, ctx.actor.subject);
|
|
130
|
+
}
|
|
131
|
+
throw err;
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
export function archiveRaw(ctx, id, reason, opts = {}) {
|
|
135
|
+
const db = openHippoDb(ctx.hippoRoot);
|
|
136
|
+
let mirrorOk = false;
|
|
137
|
+
try {
|
|
138
|
+
// Tenant scope: archiveRawMemory looks up the row by id alone, so a
|
|
139
|
+
// Bearer for tenant A could archive tenant B's raw row without this
|
|
140
|
+
// pre-check. Deny cross-tenant access with the same not-found message
|
|
141
|
+
// archiveRawMemory itself would throw on a missing row, so we don't
|
|
142
|
+
// leak whether the id exists in another tenant.
|
|
143
|
+
if (selectMemoryTenant(db, id) !== ctx.tenantId) {
|
|
144
|
+
throw new NotFoundError(`memory not found: ${id}`);
|
|
145
|
+
}
|
|
146
|
+
archiveRawMemory(db, id, {
|
|
147
|
+
reason,
|
|
148
|
+
who: ctx.actor.subject,
|
|
149
|
+
afterArchive: opts.afterArchive,
|
|
150
|
+
});
|
|
151
|
+
// archiveRawMemory deletes the memories row but leaves any legacy markdown
|
|
152
|
+
// mirror in <root>/{buffer,episodic,semantic}/<id>.md untouched. If we left
|
|
153
|
+
// the mirror in place, a subsequent initStore() on an empty memories table
|
|
154
|
+
// would silently re-import the row via bootstrapLegacyStore — defeating the
|
|
155
|
+
// archive (and the GDPR right-to-be-forgotten promise on raw rows). Mirror
|
|
156
|
+
// forget() at src/store.ts:1046, which uses the same removeEntryMirrors call.
|
|
157
|
+
// The DB transaction has already committed; if filesystem unlink fails here
|
|
158
|
+
// we log and continue. The mirror reaper in openHippoDb will catch it on
|
|
159
|
+
// next DB open: raw_archive.mirror_cleaned_at stays NULL until every layer
|
|
160
|
+
// mirror for this id is gone, so the reaper genuinely retries.
|
|
161
|
+
try {
|
|
162
|
+
removeEntryMirrors(ctx.hippoRoot, id);
|
|
163
|
+
mirrorOk = true;
|
|
164
|
+
}
|
|
165
|
+
catch (mirrorErr) {
|
|
166
|
+
log.error(`archiveRaw: mirror cleanup failed for ${id} (will retry via reaper on next openHippoDb): ${mirrorErr instanceof Error ? mirrorErr.message : String(mirrorErr)}`);
|
|
167
|
+
}
|
|
168
|
+
if (mirrorOk) {
|
|
169
|
+
// Stamp mirror_cleaned_at now so the next openHippoDb reaper SELECT
|
|
170
|
+
// returns empty for this row. NULL stays untouched on failure -> retry.
|
|
171
|
+
try {
|
|
172
|
+
db.prepare(`UPDATE raw_archive SET mirror_cleaned_at = ? WHERE memory_id = ?`).run(new Date().toISOString(), id);
|
|
173
|
+
}
|
|
174
|
+
catch (err) {
|
|
175
|
+
if (!isSqliteBusy(err))
|
|
176
|
+
throw err;
|
|
177
|
+
log.warnThenDebug('archive-mirror-stamp-busy', `archived ${id}; the store was busy, so the mirror reaper will re-check it on the next open`);
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
finally {
|
|
182
|
+
closeHippoDb(db);
|
|
183
|
+
}
|
|
184
|
+
// Counted here rather than in the CLI: the HTTP archive route calls this too,
|
|
185
|
+
// so a routed archive would otherwise never reach the forgotten counter.
|
|
186
|
+
updateStatsUnlessBusy(ctx.hippoRoot, { forgotten: 1 }, `removed ${id}`);
|
|
187
|
+
// archiveRawMemory does not return the archive_at timestamp it wrote. We
|
|
188
|
+
// emit a fresh ISO timestamp here for the API response. Within a millisecond
|
|
189
|
+
// of the actual write, fine for a server response shape.
|
|
190
|
+
return { ok: true, archivedAt: new Date().toISOString() };
|
|
191
|
+
}
|
|
192
|
+
//# sourceMappingURL=promote.js.map
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { type QuarantineStatus } from '../quarantine.js';
|
|
2
|
+
import type { KeysetPosition } from '../keyset.js';
|
|
3
|
+
import type { Context } from './types.js';
|
|
4
|
+
export interface QuarantineListItem {
|
|
5
|
+
id: string;
|
|
6
|
+
originalScope: string | null;
|
|
7
|
+
reason: string;
|
|
8
|
+
status: QuarantineStatus;
|
|
9
|
+
quarantinedAt: string;
|
|
10
|
+
decidedAt: string | null;
|
|
11
|
+
decidedBy: string | null;
|
|
12
|
+
contentPreview: string;
|
|
13
|
+
}
|
|
14
|
+
/** A tenant's quarantined memories, newest first. Default `status` is 'pending' (the review queue). */
|
|
15
|
+
export declare function quarantineList(ctx: Context, opts?: {
|
|
16
|
+
status?: QuarantineStatus | 'all';
|
|
17
|
+
limit?: number;
|
|
18
|
+
after?: KeysetPosition;
|
|
19
|
+
}): QuarantineListItem[];
|
|
20
|
+
/** Release a quarantined memory to its original scope. Admin only; the scope guard refuses a row moved since (mirrors restoreDormant). */
|
|
21
|
+
export declare function quarantineApprove(ctx: Context, id: string): void;
|
|
22
|
+
/** Keep a quarantined memory hidden for good. Admin only; the raw row is untouched (append-only). */
|
|
23
|
+
export declare function quarantineReject(ctx: Context, id: string): void;
|
|
24
|
+
//# sourceMappingURL=quarantine.d.ts.map
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
// Quarantine review: list, approve and reject held memories.
|
|
2
|
+
import { openHippoDb, closeHippoDb } from '../db.js';
|
|
3
|
+
import { ConflictError, ForbiddenError, NotFoundError } from '../api-errors.js';
|
|
4
|
+
import { writeEntryMirrors } from '../store/entry-writes.js';
|
|
5
|
+
import { readEntry } from '../store/entry-reads.js';
|
|
6
|
+
import { quarantineScopeFor, getQuarantineRow, listQuarantineRows, approveQuarantineRow, rejectQuarantineRow, } from '../quarantine.js';
|
|
7
|
+
import { log } from '../log.js';
|
|
8
|
+
import { appendAuditEvent } from '../audit.js';
|
|
9
|
+
const QUARANTINE_PREVIEW_CHARS = 200;
|
|
10
|
+
/** A tenant's quarantined memories, newest first. Default `status` is 'pending' (the review queue). */
|
|
11
|
+
export function quarantineList(ctx, opts = {}) {
|
|
12
|
+
const db = openHippoDb(ctx.hippoRoot);
|
|
13
|
+
try {
|
|
14
|
+
const rows = listQuarantineRows(db, ctx.tenantId, opts.status ?? 'pending', opts.limit, opts.after);
|
|
15
|
+
return rows.map((row) => {
|
|
16
|
+
const entry = readEntry(ctx.hippoRoot, row.memoryId, ctx.tenantId);
|
|
17
|
+
return {
|
|
18
|
+
id: row.memoryId,
|
|
19
|
+
originalScope: row.originalScope,
|
|
20
|
+
reason: row.reason,
|
|
21
|
+
status: row.status,
|
|
22
|
+
quarantinedAt: row.quarantinedAt,
|
|
23
|
+
decidedAt: row.decidedAt,
|
|
24
|
+
decidedBy: row.decidedBy,
|
|
25
|
+
contentPreview: entry ? entry.content.slice(0, QUARANTINE_PREVIEW_CHARS) : '',
|
|
26
|
+
};
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
finally {
|
|
30
|
+
closeHippoDb(db);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
function loadPendingQuarantineRow(db, tenantId, id) {
|
|
34
|
+
const row = getQuarantineRow(db, tenantId, id);
|
|
35
|
+
if (!row)
|
|
36
|
+
throw new NotFoundError(`not quarantined: ${id}`);
|
|
37
|
+
if (row.status !== 'pending')
|
|
38
|
+
throw new ConflictError(`${id} is already ${row.status}`);
|
|
39
|
+
return row;
|
|
40
|
+
}
|
|
41
|
+
/** Release a quarantined memory to its original scope. Admin only; the scope guard refuses a row moved since (mirrors restoreDormant). */
|
|
42
|
+
export function quarantineApprove(ctx, id) {
|
|
43
|
+
if (ctx.actor.role !== 'admin') {
|
|
44
|
+
throw new ForbiddenError('Only an admin key can approve a quarantined memory');
|
|
45
|
+
}
|
|
46
|
+
const db = openHippoDb(ctx.hippoRoot);
|
|
47
|
+
try {
|
|
48
|
+
db.exec('BEGIN IMMEDIATE');
|
|
49
|
+
try {
|
|
50
|
+
const row = loadPendingQuarantineRow(db, ctx.tenantId, id);
|
|
51
|
+
const quarantineScope = quarantineScopeFor(row.originalScope);
|
|
52
|
+
const updated = db
|
|
53
|
+
.prepare(`UPDATE memories SET scope = ? WHERE id = ? AND tenant_id = ? AND scope = ?`)
|
|
54
|
+
.run(row.originalScope, id, ctx.tenantId, quarantineScope);
|
|
55
|
+
if (Number(updated.changes ?? 0) !== 1) {
|
|
56
|
+
throw new ConflictError(`memory ${id} scope changed since quarantine; refusing to approve`);
|
|
57
|
+
}
|
|
58
|
+
approveQuarantineRow(db, ctx.tenantId, id, ctx.actor.subject);
|
|
59
|
+
appendAuditEvent(db, {
|
|
60
|
+
tenantId: ctx.tenantId,
|
|
61
|
+
actor: ctx.actor.subject,
|
|
62
|
+
op: 'quarantine_approve',
|
|
63
|
+
targetId: id,
|
|
64
|
+
metadata: { originalScope: row.originalScope },
|
|
65
|
+
});
|
|
66
|
+
db.exec('COMMIT');
|
|
67
|
+
}
|
|
68
|
+
catch (err) {
|
|
69
|
+
try {
|
|
70
|
+
db.exec('ROLLBACK');
|
|
71
|
+
}
|
|
72
|
+
catch { /* already rolled back */ }
|
|
73
|
+
throw err;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
finally {
|
|
77
|
+
closeHippoDb(db);
|
|
78
|
+
}
|
|
79
|
+
// Post-commit, best-effort: a failed rewrite leaves the mirror showing the quarantine scope (fail-closed).
|
|
80
|
+
try {
|
|
81
|
+
const restored = readEntry(ctx.hippoRoot, id, ctx.tenantId);
|
|
82
|
+
if (restored)
|
|
83
|
+
writeEntryMirrors(ctx.hippoRoot, restored);
|
|
84
|
+
}
|
|
85
|
+
catch (err) {
|
|
86
|
+
log.error(`quarantine: mirror rewrite failed for ${id}: ${err instanceof Error ? err.message : String(err)}`);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
/** Keep a quarantined memory hidden for good. Admin only; the raw row is untouched (append-only). */
|
|
90
|
+
export function quarantineReject(ctx, id) {
|
|
91
|
+
if (ctx.actor.role !== 'admin') {
|
|
92
|
+
throw new ForbiddenError('Only an admin key can reject a quarantined memory');
|
|
93
|
+
}
|
|
94
|
+
const db = openHippoDb(ctx.hippoRoot);
|
|
95
|
+
try {
|
|
96
|
+
db.exec('BEGIN IMMEDIATE');
|
|
97
|
+
try {
|
|
98
|
+
loadPendingQuarantineRow(db, ctx.tenantId, id);
|
|
99
|
+
rejectQuarantineRow(db, ctx.tenantId, id, ctx.actor.subject);
|
|
100
|
+
appendAuditEvent(db, {
|
|
101
|
+
tenantId: ctx.tenantId,
|
|
102
|
+
actor: ctx.actor.subject,
|
|
103
|
+
op: 'quarantine_reject',
|
|
104
|
+
targetId: id,
|
|
105
|
+
metadata: {},
|
|
106
|
+
});
|
|
107
|
+
db.exec('COMMIT');
|
|
108
|
+
}
|
|
109
|
+
catch (err) {
|
|
110
|
+
try {
|
|
111
|
+
db.exec('ROLLBACK');
|
|
112
|
+
}
|
|
113
|
+
catch { /* already rolled back */ }
|
|
114
|
+
throw err;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
finally {
|
|
118
|
+
closeHippoDb(db);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
//# sourceMappingURL=quarantine.js.map
|