hippo-memory 1.70.0 → 1.71.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/agent-memories/claude-code.d.ts +4 -2
- package/dist/agent-memories/claude-code.js +14 -5
- package/dist/agent-memories/files.js +23 -12
- package/dist/agent-memories/markdown.d.ts +1 -3
- package/dist/agent-memories/markdown.js +1 -3
- package/dist/agent-memories/report.js +2 -1
- package/dist/agent-memories/sync.d.ts +4 -2
- package/dist/agent-memories/sync.js +10 -5
- package/dist/api/assemble.d.ts +7 -44
- package/dist/api/assemble.js +2 -22
- package/dist/api/audit.d.ts +5 -1
- package/dist/api/audit.js +9 -1
- package/dist/api/auth.d.ts +13 -22
- package/dist/api/auth.js +34 -24
- package/dist/api/auto-sleep.js +2 -2
- package/dist/api/availability.d.ts +2 -15
- package/dist/api/availability.js +2 -15
- package/dist/api/context-select.js +3 -4
- package/dist/api/context-types.d.ts +10 -35
- package/dist/api/context.d.ts +5 -22
- package/dist/api/context.js +21 -38
- package/dist/api/dormant.d.ts +5 -21
- package/dist/api/dormant.js +7 -26
- package/dist/api/drill-down.d.ts +7 -46
- package/dist/api/drill-down.js +5 -26
- package/dist/api/forget.d.ts +5 -24
- package/dist/api/forget.js +5 -28
- package/dist/api/graph.d.ts +8 -0
- package/dist/api/graph.js +7 -0
- package/dist/api/index.d.ts +2 -0
- package/dist/api/index.js +2 -0
- package/dist/api/instruction-detect.js +16 -5
- package/dist/api/ledger-db.d.ts +2 -1
- package/dist/api/ledger-db.js +5 -3
- package/dist/api/memories.d.ts +5 -0
- package/dist/api/memories.js +7 -0
- package/dist/api/objects.d.ts +9 -0
- package/dist/api/objects.js +11 -0
- package/dist/api/on-store.js +5 -3
- package/dist/api/predictions.d.ts +9 -0
- package/dist/api/predictions.js +18 -0
- package/dist/api/promote.d.ts +13 -17
- package/dist/api/promote.js +11 -19
- package/dist/api/prompt-hook.d.ts +4 -4
- package/dist/api/prompt-hook.js +10 -9
- package/dist/api/recall-cli.d.ts +55 -0
- package/dist/api/recall-cli.js +94 -0
- package/dist/api/recall-core.js +14 -6
- package/dist/api/recall-finish.d.ts +53 -0
- package/dist/api/recall-finish.js +30 -0
- package/dist/api/recall-history.d.ts +17 -84
- package/dist/api/recall-history.js +15 -88
- package/dist/api/recall-pipeline.d.ts +2 -3
- package/dist/api/recall-pipeline.js +16 -9
- package/dist/api/recall-types.d.ts +64 -304
- package/dist/api/recall.d.ts +5 -33
- package/dist/api/recall.js +59 -60
- package/dist/api/refine.d.ts +7 -0
- package/dist/api/refine.js +10 -0
- package/dist/api/remember-local.d.ts +57 -0
- package/dist/api/remember-local.js +90 -0
- package/dist/api/remember.d.ts +18 -1
- package/dist/api/remember.js +13 -1
- package/dist/api/sleep-run.d.ts +1 -3
- package/dist/api/sleep-run.js +17 -21
- package/dist/api/sleep.d.ts +9 -28
- package/dist/api/tokens.d.ts +3 -10
- package/dist/api/tokens.js +3 -10
- package/dist/api/types.d.ts +6 -29
- package/dist/api/types.js +4 -22
- package/dist/capture/command.d.ts +4 -12
- package/dist/capture/command.js +6 -22
- package/dist/capture/compact.d.ts +4 -15
- package/dist/capture/compact.js +16 -25
- package/dist/capture/compaction-record.js +101 -69
- package/dist/capture/compaction-spool.d.ts +1 -1
- package/dist/capture/compaction-spool.js +1 -1
- package/dist/capture/session-digest.d.ts +1 -1
- package/dist/capture/session-digest.js +13 -7
- package/dist/capture/transcript.d.ts +2 -10
- package/dist/capture/transcript.js +4 -18
- package/dist/cli/api-context.d.ts +3 -0
- package/dist/cli/api-context.js +6 -0
- package/dist/cli/audit-prune.d.ts +6 -39
- package/dist/cli/audit-prune.js +6 -39
- package/dist/cli/audit.d.ts +1 -1
- package/dist/cli/audit.js +33 -34
- package/dist/cli/auth.d.ts +2 -2
- package/dist/cli/auth.js +57 -39
- package/dist/cli/briefs.d.ts +4 -4
- package/dist/cli/briefs.js +18 -22
- package/dist/cli/card.d.ts +2 -2
- package/dist/cli/card.js +31 -32
- package/dist/cli/client.d.ts +7 -27
- package/dist/cli/client.js +24 -43
- package/dist/cli/compact-resume-payload.js +3 -2
- package/dist/cli/context.d.ts +1 -2
- package/dist/cli/context.js +12 -8
- package/dist/cli/continuity.d.ts +6 -6
- package/dist/cli/continuity.js +62 -64
- package/dist/cli/correction-latency.d.ts +2 -14
- package/dist/cli/correction-latency.js +2 -14
- package/dist/cli/curate.d.ts +13 -17
- package/dist/cli/curate.js +68 -92
- package/dist/cli/dag.d.ts +4 -4
- package/dist/cli/dag.js +33 -27
- package/dist/cli/decisions.d.ts +4 -4
- package/dist/cli/decisions.js +33 -47
- package/dist/cli/eval.js +15 -13
- package/dist/cli/exit.d.ts +6 -0
- package/dist/cli/exit.js +11 -0
- package/dist/cli/explain.d.ts +1 -2
- package/dist/cli/explain.js +6 -4
- package/dist/cli/flag-values.d.ts +6 -1
- package/dist/cli/flag-values.js +27 -10
- package/dist/cli/flags.d.ts +1 -0
- package/dist/cli/flags.js +1 -1
- package/dist/cli/github.d.ts +14 -0
- package/dist/{connectors/github/cli-impl.js → cli/github.js} +43 -71
- package/dist/cli/goals.d.ts +2 -2
- package/dist/cli/goals.js +46 -50
- package/dist/cli/hook-runtime.d.ts +9 -27
- package/dist/cli/hook-runtime.js +15 -31
- package/dist/cli/init.d.ts +2 -2
- package/dist/cli/init.js +6 -12
- package/dist/cli/install-steps.js +3 -12
- package/dist/cli/last-sleep.d.ts +2 -1
- package/dist/cli/last-sleep.js +3 -0
- package/dist/cli/maintenance.d.ts +4 -4
- package/dist/cli/maintenance.js +14 -19
- package/dist/cli/object-verbs.js +4 -3
- package/dist/cli/owner-validation.d.ts +5 -28
- package/dist/cli/owner-validation.js +5 -28
- package/dist/cli/playbooks.d.ts +4 -4
- package/dist/cli/playbooks.js +23 -28
- package/dist/cli/print.d.ts +2 -5
- package/dist/cli/print.js +1 -4
- package/dist/cli/projects.d.ts +2 -2
- package/dist/cli/projects.js +1 -3
- package/dist/cli/provenance-coverage.d.ts +2 -6
- package/dist/cli/provenance-coverage.js +2 -6
- package/dist/cli/quality-repair-once.js +2 -2
- package/dist/cli/recall.d.ts +2 -4
- package/dist/cli/recall.js +55 -131
- package/dist/cli/refine-llm.d.ts +5 -31
- package/dist/cli/refine-llm.js +9 -36
- package/dist/cli/remember.d.ts +3 -3
- package/dist/cli/remember.js +122 -180
- package/dist/cli/scheduler.d.ts +2 -17
- package/dist/cli/scheduler.js +12 -18
- package/dist/cli/serve.js +21 -12
- package/dist/cli/session-hooks.d.ts +10 -18
- package/dist/cli/session-hooks.js +112 -113
- package/dist/cli/setup.d.ts +4 -4
- package/dist/cli/setup.js +19 -21
- package/dist/cli/shared.d.ts +9 -23
- package/dist/cli/shared.js +9 -32
- package/dist/cli/slack.d.ts +2 -2
- package/dist/cli/slack.js +19 -23
- package/dist/cli/sleep.d.ts +3 -2
- package/dist/cli/sleep.js +15 -16
- package/dist/cli/status.d.ts +9 -12
- package/dist/cli/status.js +55 -98
- package/dist/cli/stdin.d.ts +4 -6
- package/dist/cli/stdin.js +2 -3
- package/dist/cli/transfer.d.ts +9 -9
- package/dist/cli/transfer.js +66 -89
- package/dist/cli/usage.js +11 -5
- package/dist/cli.d.ts +66 -448
- package/dist/cli.js +87 -263
- package/dist/connectors/github/backfill.d.ts +5 -25
- package/dist/connectors/github/backfill.js +14 -49
- package/dist/connectors/github/deletion.d.ts +4 -18
- package/dist/connectors/github/deletion.js +2 -15
- package/dist/connectors/github/dlq.d.ts +8 -33
- package/dist/connectors/github/dlq.js +12 -29
- package/dist/connectors/github/ingest.d.ts +2 -6
- package/dist/connectors/github/ingest.js +4 -10
- package/dist/connectors/github/octokit-client.d.ts +4 -16
- package/dist/connectors/github/octokit-client.js +27 -24
- package/dist/connectors/github/ratelimit.d.ts +3 -14
- package/dist/connectors/github/ratelimit.js +3 -14
- package/dist/connectors/github/scope.d.ts +3 -5
- package/dist/connectors/github/scope.js +3 -5
- package/dist/connectors/github/signature.d.ts +4 -26
- package/dist/connectors/github/signature.js +4 -26
- package/dist/connectors/github/tenant-routing.d.ts +2 -24
- package/dist/connectors/github/tenant-routing.js +4 -26
- package/dist/connectors/github/transform.js +2 -16
- package/dist/connectors/github/types.d.ts +3 -15
- package/dist/connectors/github/types.js +2 -9
- package/dist/connectors/github/webhook.d.ts +2 -16
- package/dist/connectors/github/webhook.js +6 -22
- package/dist/connectors/slack/backfill.d.ts +4 -17
- package/dist/connectors/slack/backfill.js +4 -13
- package/dist/connectors/slack/dlq.d.ts +2 -19
- package/dist/connectors/slack/dlq.js +2 -19
- package/dist/connectors/slack/ingest.d.ts +2 -3
- package/dist/connectors/slack/ingest.js +2 -3
- package/dist/connectors/slack/scope.d.ts +2 -8
- package/dist/connectors/slack/scope.js +2 -8
- package/dist/connectors/slack/signature.d.ts +1 -6
- package/dist/connectors/slack/tenant-routing.d.ts +2 -19
- package/dist/connectors/slack/tenant-routing.js +2 -21
- package/dist/connectors/slack/transform.d.ts +2 -18
- package/dist/connectors/slack/transform.js +2 -18
- package/dist/connectors/slack/types.d.ts +3 -9
- package/dist/connectors/slack/types.js +2 -4
- package/dist/connectors/slack/web-client.js +33 -27
- package/dist/connectors/slack/webhook.d.ts +2 -19
- package/dist/connectors/slack/webhook.js +5 -26
- package/dist/connectors/slack/workspaces.d.ts +4 -24
- package/dist/connectors/slack/workspaces.js +4 -24
- package/dist/consolidate/conflicts.js +6 -14
- package/dist/consolidate/dag-summary.d.ts +8 -0
- package/dist/consolidate/dag-summary.js +41 -0
- package/dist/consolidate/dag.d.ts +5 -28
- package/dist/consolidate/dag.js +14 -75
- package/dist/consolidate/decay.js +7 -19
- package/dist/consolidate/dedupe.d.ts +6 -52
- package/dist/consolidate/dedupe.js +13 -71
- package/dist/consolidate/flush-units.d.ts +3 -4
- package/dist/consolidate/flush-units.js +3 -3
- package/dist/consolidate/half-life-migration.d.ts +3 -26
- package/dist/consolidate/half-life-migration.js +11 -28
- package/dist/consolidate/llm-passes.js +4 -21
- package/dist/consolidate/memory-value-weights.d.ts +2 -13
- package/dist/consolidate/memory-value-weights.js +2 -13
- package/dist/consolidate/memory-value.d.ts +11 -84
- package/dist/consolidate/memory-value.js +16 -104
- package/dist/consolidate/merge.js +10 -31
- package/dist/consolidate/merged-row.js +2 -1
- package/dist/consolidate/physics-pass.js +1 -3
- package/dist/consolidate/replay.d.ts +6 -38
- package/dist/consolidate/replay.js +14 -52
- package/dist/consolidate/run.js +1 -1
- package/dist/consolidate/sleep.d.ts +1 -8
- package/dist/consolidate/sleep.js +5 -17
- package/dist/consolidate/trace.d.ts +3 -18
- package/dist/consolidate/trace.js +3 -18
- package/dist/consolidate/traces.js +6 -22
- package/dist/core/ablation.d.ts +4 -91
- package/dist/core/ablation.js +4 -91
- package/dist/core/ambient.d.ts +1 -8
- package/dist/core/ambient.js +1 -8
- package/dist/core/capture-contract.d.ts +4 -2
- package/dist/core/capture-contract.js +4 -2
- package/dist/core/card.d.ts +4 -1
- package/dist/core/card.js +8 -0
- package/dist/core/compare.d.ts +11 -67
- package/dist/core/compare.js +9 -63
- package/dist/core/config.d.ts +10 -24
- package/dist/core/config.js +13 -14
- package/dist/core/handoff.d.ts +1 -7
- package/dist/core/handoff.js +1 -7
- package/dist/core/memory-quality.js +1 -1
- package/dist/core/memory.d.ts +41 -164
- package/dist/core/memory.js +51 -221
- package/dist/core/package-root.d.ts +3 -0
- package/dist/core/package-root.js +5 -0
- package/dist/core/physics-config.d.ts +1 -4
- package/dist/core/physics-config.js +3 -8
- package/dist/core/physics.d.ts +15 -61
- package/dist/core/physics.js +59 -122
- package/dist/core/project-identity.d.ts +17 -58
- package/dist/core/project-identity.js +17 -38
- package/dist/core/project-remote.js +13 -2
- package/dist/core/raw-append-only.d.ts +5 -0
- package/dist/core/raw-append-only.js +7 -0
- package/dist/core/salience.d.ts +1 -7
- package/dist/core/salience.js +1 -7
- package/dist/dashboard/dashboard-actions.js +2 -2
- package/dist/dashboard/dashboard-snapshot.d.ts +2 -1
- package/dist/dashboard/dashboard-snapshot.js +11 -2
- package/dist/dashboard/dashboard-types.d.ts +2 -1
- package/dist/dashboard/dashboard.d.ts +1 -0
- package/dist/dashboard/dashboard.js +50 -4
- package/dist/db/busy.d.ts +1 -1
- package/dist/db/busy.js +17 -8
- package/dist/db/connect.d.ts +1 -0
- package/dist/db/connect.js +3 -3
- package/dist/db/migrate.js +3 -3
- package/dist/db/migrations/types.d.ts +2 -5
- package/dist/db/migrations/v14.js +2 -3
- package/dist/db/migrations/v15.js +2 -8
- package/dist/db/migrations/v16.js +2 -3
- package/dist/db/migrations/v17.js +2 -3
- package/dist/db/migrations/v19.js +2 -5
- package/dist/db/migrations/v20.js +2 -7
- package/dist/db/migrations/v22.js +4 -17
- package/dist/db/migrations/v23.js +3 -14
- package/dist/db/migrations/v24.js +2 -4
- package/dist/db/migrations/v25.js +3 -8
- package/dist/db/migrations/v26.js +2 -13
- package/dist/db/migrations/v27.js +3 -11
- package/dist/db/migrations/v28.js +2 -14
- package/dist/db/migrations/v29.js +4 -18
- package/dist/db/migrations/v30.js +4 -16
- package/dist/db/migrations/v31.js +2 -15
- package/dist/db/migrations/v32.js +4 -22
- package/dist/db/migrations/v33.js +2 -15
- package/dist/db/migrations/v34.js +2 -11
- package/dist/db/migrations/v35.js +2 -11
- package/dist/db/migrations/v36.js +2 -11
- package/dist/db/migrations/v37.js +8 -33
- package/dist/db/migrations/v38.js +5 -38
- package/dist/db/migrations/v39.js +9 -20
- package/dist/db/migrations/v40.js +2 -9
- package/dist/db/migrations/v41.js +2 -24
- package/dist/db/migrations/v43.js +1 -1
- package/dist/db/migrations/v44.js +2 -8
- package/dist/db/migrations/v45.js +2 -7
- package/dist/db/migrations/v47.js +2 -3
- package/dist/db/migrations/v51.js +1 -1
- package/dist/db/open.d.ts +2 -0
- package/dist/db/open.js +17 -1
- package/dist/db/physics-state.d.ts +6 -22
- package/dist/db/physics-state.js +25 -36
- package/dist/db/raw-archive-mirror-cleanup.d.ts +2 -17
- package/dist/db/raw-archive-mirror-cleanup.js +2 -17
- package/dist/db/vector-store.d.ts +2 -0
- package/dist/db/vector-store.js +8 -1
- package/dist/doctor.js +74 -19
- package/dist/entry/session-text.js +2 -1
- package/dist/eval/eval-stats.d.ts +15 -53
- package/dist/eval/eval-stats.js +12 -42
- package/dist/eval/eval-suite.d.ts +2 -13
- package/dist/eval/eval-suite.js +74 -34
- package/dist/eval/eval.d.ts +6 -24
- package/dist/eval/eval.js +7 -34
- package/dist/eval/judgment.d.ts +0 -3
- package/dist/eval/judgment.js +19 -11
- package/dist/extensions/openclaw-plugin/index.js +1 -1
- package/dist/graph/extract.d.ts +5 -27
- package/dist/graph/extract.js +7 -33
- package/dist/graph/recall.d.ts +7 -20
- package/dist/graph/recall.js +14 -76
- package/dist/graph/stream.d.ts +7 -39
- package/dist/graph/stream.js +11 -34
- package/dist/graph/view.d.ts +9 -35
- package/dist/graph/view.js +11 -39
- package/dist/hooks/codex-wrapper.js +2 -2
- package/dist/hooks/copilot.js +2 -1
- package/dist/hooks/hook-blocks.d.ts +6 -2
- package/dist/hooks/hook-blocks.js +37 -124
- package/dist/hooks/json-hooks.d.ts +4 -36
- package/dist/hooks/json-hooks.js +18 -57
- package/dist/hooks/opencode.d.ts +0 -38
- package/dist/hooks/opencode.js +9 -76
- package/dist/hooks/shared.d.ts +8 -17
- package/dist/hooks/shared.js +29 -20
- package/dist/importers/core.d.ts +12 -37
- package/dist/importers/core.js +9 -27
- package/dist/importers/markdown-parse.d.ts +8 -22
- package/dist/importers/markdown-parse.js +8 -25
- package/dist/importers/markdown.js +3 -12
- package/dist/importers/sources.js +7 -35
- package/dist/importers/vault.d.ts +2 -8
- package/dist/importers/vault.js +25 -81
- package/dist/index.d.ts +6 -2
- package/dist/index.js +6 -2
- package/dist/learn/autolearn.d.ts +14 -41
- package/dist/learn/autolearn.js +14 -41
- package/dist/learn/extract.js +2 -4
- package/dist/learn/forward-claim-detector.d.ts +6 -30
- package/dist/learn/forward-claim-detector.js +14 -66
- package/dist/learn/invalidation.d.ts +6 -18
- package/dist/learn/invalidation.js +9 -26
- package/dist/mcp/admin-tools.js +3 -5
- package/dist/mcp/memory-tools.js +4 -9
- package/dist/mcp/protocol.d.ts +8 -26
- package/dist/mcp/protocol.js +3 -6
- package/dist/mcp/recall-tools.js +3 -3
- package/dist/mcp/request.d.ts +3 -11
- package/dist/mcp/request.js +10 -26
- package/dist/mcp/server.d.ts +3 -9
- package/dist/mcp/server.js +5 -16
- package/dist/mcp/session-state.d.ts +1 -1
- package/dist/mcp/session-state.js +5 -11
- package/dist/mcp/stdio.d.ts +2 -6
- package/dist/mcp/stdio.js +48 -12
- package/dist/mcp/tools.js +5 -3
- package/dist/objects/customer-notes.d.ts +7 -42
- package/dist/objects/customer-notes.js +7 -48
- package/dist/objects/decisions.d.ts +12 -50
- package/dist/objects/decisions.js +15 -53
- package/dist/objects/incidents.d.ts +7 -38
- package/dist/objects/incidents.js +7 -41
- package/dist/objects/policies.d.ts +11 -89
- package/dist/objects/policies.js +11 -98
- package/dist/objects/processes.d.ts +7 -52
- package/dist/objects/processes.js +7 -61
- package/dist/objects/project-briefs.d.ts +11 -55
- package/dist/objects/project-briefs.js +14 -75
- package/dist/objects/skills.d.ts +7 -42
- package/dist/objects/skills.js +8 -54
- package/dist/postinstall.js +6 -19
- package/dist/predictions/planning-fallacy.d.ts +11 -34
- package/dist/rerankers/clef.js +3 -31
- package/dist/rerankers/cross-encoder.js +4 -6
- package/dist/rerankers/jev.js +9 -6
- package/dist/rerankers/llm.d.ts +2 -11
- package/dist/rerankers/llm.js +14 -14
- package/dist/rerankers/outage-warning.d.ts +2 -1
- package/dist/rerankers/outage-warning.js +2 -1
- package/dist/rerankers/remote.d.ts +1 -0
- package/dist/rerankers/remote.js +2 -0
- package/dist/rerankers/types.d.ts +2 -14
- package/dist/search/boosts.d.ts +0 -2
- package/dist/search/boosts.js +2 -2
- package/dist/search/goal-boost.d.ts +23 -0
- package/dist/search/goal-boost.js +90 -0
- package/dist/search/hybrid.d.ts +2 -0
- package/dist/search/multihop.js +2 -3
- package/dist/search/path-context.d.ts +5 -18
- package/dist/search/path-context.js +5 -18
- package/dist/search/physics-search.js +11 -8
- package/dist/search/rrf.d.ts +7 -35
- package/dist/search/rrf.js +5 -30
- package/dist/search/vector.d.ts +7 -0
- package/dist/search/vector.js +35 -5
- package/dist/server/auth.d.ts +9 -28
- package/dist/server/auth.js +32 -25
- package/dist/server/boot.d.ts +2 -21
- package/dist/server/boot.js +63 -96
- package/dist/server/client-ip.d.ts +3 -19
- package/dist/server/client-ip.js +5 -28
- package/dist/server/defaults.d.ts +3 -0
- package/dist/server/defaults.js +4 -0
- package/dist/server/key-check-bounds.d.ts +2 -1
- package/dist/server/lifecycle.d.ts +5 -4
- package/dist/server/lifecycle.js +19 -4
- package/dist/server/mcp-http.js +10 -44
- package/dist/server/rate-limit.d.ts +5 -18
- package/dist/server/rate-limit.js +4 -13
- package/dist/server/request.d.ts +4 -8
- package/dist/server/request.js +9 -17
- package/dist/server/route-table.js +42 -49
- package/dist/server/routes/admin.js +22 -28
- package/dist/server/routes/customer-notes.js +7 -12
- package/dist/server/routes/decisions.js +10 -17
- package/dist/server/routes/incidents.js +12 -20
- package/dist/server/routes/memories.js +12 -32
- package/dist/server/routes/object-routes.d.ts +0 -5
- package/dist/server/routes/object-routes.js +7 -15
- package/dist/server/routes/policies.js +10 -18
- package/dist/server/routes/predictions.js +13 -25
- package/dist/server/routes/processes.js +16 -26
- package/dist/server/routes/project-briefs.js +9 -16
- package/dist/server/routes/recall.js +10 -35
- package/dist/server/routes/skills.js +8 -18
- package/dist/server/server-detect.d.ts +9 -53
- package/dist/server/server-detect.js +24 -90
- package/dist/server/sleep-offload.js +4 -1
- package/dist/server/types.d.ts +12 -10
- package/dist/server/validation.d.ts +3 -1
- package/dist/server/validation.js +10 -23
- package/dist/server.d.ts +2 -2
- package/dist/server.js +3 -2
- package/dist/sharing/global-store.d.ts +19 -0
- package/dist/sharing/global-store.js +75 -0
- package/dist/sharing/global-sync.d.ts +6 -0
- package/dist/sharing/global-sync.js +80 -0
- package/dist/sharing/project-merge.d.ts +4 -5
- package/dist/sharing/project-merge.js +9 -7
- package/dist/sharing/scope.d.ts +4 -11
- package/dist/sharing/scope.js +4 -11
- package/dist/sharing/search-both.d.ts +60 -0
- package/dist/sharing/search-both.js +138 -0
- package/dist/sharing/share.d.ts +38 -0
- package/dist/sharing/share.js +226 -0
- package/dist/store/ambient.js +4 -9
- package/dist/store/audit-event.d.ts +4 -12
- package/dist/store/audit-event.js +4 -12
- package/dist/store/audit.d.ts +2 -5
- package/dist/store/audit.js +4 -12
- package/dist/store/auth.d.ts +6 -6
- package/dist/store/auth.js +10 -9
- package/dist/store/candidates.d.ts +20 -3
- package/dist/store/candidates.js +77 -48
- package/dist/store/card-detail.d.ts +2 -1
- package/dist/store/card-detail.js +2 -1
- package/dist/store/cards.d.ts +14 -9
- package/dist/store/cards.js +72 -126
- package/dist/store/conflicts.d.ts +4 -21
- package/dist/store/conflicts.js +71 -150
- package/dist/store/connectors/github.d.ts +10 -10
- package/dist/store/connectors/github.js +10 -10
- package/dist/store/dashboard-reads.js +4 -8
- package/dist/store/delete-and-batch.d.ts +11 -31
- package/dist/store/delete-and-batch.js +48 -64
- package/dist/store/delivery-recorder.d.ts +8 -4
- package/dist/store/delivery-recorder.js +25 -15
- package/dist/store/diagnostics.js +6 -13
- package/dist/store/dormant.d.ts +7 -29
- package/dist/store/dormant.js +15 -56
- package/dist/store/embeddings/index.d.ts +11 -80
- package/dist/store/embeddings/index.js +71 -207
- package/dist/store/embeddings/local.js +15 -32
- package/dist/store/embeddings/provider.d.ts +16 -53
- package/dist/store/embeddings/provider.js +41 -69
- package/dist/store/entry-reads.d.ts +21 -57
- package/dist/store/entry-reads.js +65 -126
- package/dist/store/entry-row.d.ts +6 -35
- package/dist/store/entry-row.js +9 -37
- package/dist/store/entry-writes.d.ts +10 -16
- package/dist/store/entry-writes.js +17 -35
- package/dist/store/goals.d.ts +3 -40
- package/dist/store/goals.js +21 -160
- package/dist/store/graph-queue.d.ts +6 -22
- package/dist/store/graph-queue.js +14 -45
- package/dist/store/graph-reads.d.ts +11 -35
- package/dist/store/graph-reads.js +20 -58
- package/dist/store/graph-rows.d.ts +3 -6
- package/dist/store/graph-rows.js +6 -9
- package/dist/store/graph-view-rows.d.ts +2 -1
- package/dist/store/graph-view-rows.js +2 -1
- package/dist/store/graph-writes.d.ts +6 -31
- package/dist/store/graph-writes.js +13 -37
- package/dist/store/half-life.d.ts +2 -1
- package/dist/store/half-life.js +14 -16
- package/dist/store/handoffs.d.ts +5 -11
- package/dist/store/handoffs.js +16 -34
- package/dist/store/index-and-stats.d.ts +6 -19
- package/dist/store/index-and-stats.js +34 -82
- package/dist/store/markdown.d.ts +2 -6
- package/dist/store/markdown.js +21 -20
- package/dist/store/mirrors.d.ts +2 -6
- package/dist/store/mirrors.js +14 -23
- package/dist/store/open.js +6 -13
- package/dist/store/planning-fallacy-evidence.d.ts +2 -30
- package/dist/store/planning-fallacy-evidence.js +8 -37
- package/dist/store/port.d.ts +82 -79
- package/dist/store/predictions.d.ts +11 -51
- package/dist/store/predictions.js +38 -119
- package/dist/{cli → store}/quality-repair.js +15 -31
- package/dist/store/raw-archive.d.ts +4 -16
- package/dist/store/raw-archive.js +14 -29
- package/dist/store/recall-scope.d.ts +19 -79
- package/dist/store/recall-scope.js +21 -82
- package/dist/store/recall-trace.d.ts +10 -77
- package/dist/store/recall-trace.js +19 -95
- package/dist/store/rejected-values.js +7 -19
- package/dist/store/rejection.d.ts +12 -58
- package/dist/store/rejection.js +13 -65
- package/dist/store/report-reads.d.ts +6 -0
- package/dist/store/report-reads.js +29 -0
- package/dist/store/rows.d.ts +9 -19
- package/dist/store/rows.js +36 -34
- package/dist/store/rule-sql.d.ts +5 -0
- package/dist/store/rule-sql.js +37 -0
- package/dist/store/search-rows.d.ts +7 -38
- package/dist/store/search-rows.js +14 -50
- package/dist/store/sessions.d.ts +10 -47
- package/dist/store/sessions.js +17 -73
- package/dist/store/sqlite/connector-events-group.js +2 -2
- package/dist/store/sqlite/entry-writes-group.js +2 -2
- package/dist/store/sqlite/error-codec.js +4 -2
- package/dist/store/sqlite/executor.d.ts +2 -1
- package/dist/store/sqlite/executor.js +2 -1
- package/dist/store/sqlite/local.d.ts +3 -3
- package/dist/store/sqlite/local.js +1 -0
- package/dist/store/sqlite/object-rows.js +6 -3
- package/dist/store/sqlite/objects-group.js +4 -2
- package/dist/store/sqlite/quarantine-group.js +2 -2
- package/dist/store/sqlite/store.d.ts +1 -4
- package/dist/store/sqlite/store.js +2 -3
- package/dist/store/sqlite/vector-reads-group.js +2 -2
- package/dist/store/sqlite/worker-jobs.js +1 -1
- package/dist/store/sqlite/worker-ops.d.ts +13 -2
- package/dist/store/sqlite/worker-ops.js +13 -2
- package/dist/store/sqlite/worker-store.js +5 -2
- package/dist/store/summaries.d.ts +10 -62
- package/dist/store/summaries.js +34 -146
- package/dist/store/summary-dirty.js +1 -1
- package/dist/store/tenant-lookup.d.ts +6 -1
- package/dist/store/tenant-lookup.js +7 -0
- package/dist/store/tenant.d.ts +2 -16
- package/dist/store/tenant.js +4 -19
- package/dist/store/token-ledger.d.ts +13 -43
- package/dist/store/token-ledger.js +19 -50
- package/dist/store/usage-reports.js +5 -13
- package/dist/store/vector-index.d.ts +46 -0
- package/dist/store/vector-index.js +170 -0
- package/dist/store/working-memory.d.ts +6 -25
- package/dist/store/working-memory.js +18 -52
- package/dist/store/yaml.d.ts +1 -5
- package/dist/store/yaml.js +2 -6
- package/dist/support-bundle.js +7 -5
- package/dist/trust/reject-flow.js +1 -3
- package/dist/util/anthropic-messages.js +14 -2
- package/dist/util/atomic-write.d.ts +2 -1
- package/dist/util/atomic-write.js +35 -4
- package/dist/util/capped-json.d.ts +6 -0
- package/dist/util/capped-json.js +46 -0
- package/dist/util/crash-handlers.d.ts +8 -1
- package/dist/util/crash-handlers.js +52 -10
- package/dist/util/env.d.ts +13 -6
- package/dist/util/env.js +14 -7
- package/dist/util/home-path.d.ts +2 -1
- package/dist/util/home-path.js +4 -2
- package/dist/util/http-retry.d.ts +3 -1
- package/dist/util/http-retry.js +26 -5
- package/dist/util/log.d.ts +3 -2
- package/dist/util/log.js +25 -9
- package/dist/util/request-scope.d.ts +2 -1
- package/dist/util/request-scope.js +2 -1
- package/dist/util/secret-detect.d.ts +5 -30
- package/dist/util/secret-detect.js +13 -39
- package/dist/util/stored-json.d.ts +1 -1
- package/dist/util/stored-json.js +1 -1
- package/dist/util/token-text.d.ts +1 -4
- package/dist/util/token-text.js +1 -4
- package/dist/util/transcript-tail.d.ts +2 -0
- package/dist/util/transcript-tail.js +24 -23
- package/dist/util/version.d.ts +5 -20
- package/dist/util/version.js +5 -20
- package/extensions/openclaw-plugin/index.ts +1 -1
- 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/connectors/github/cli-impl.d.ts +0 -25
- package/dist/sharing/shared.d.ts +0 -187
- package/dist/sharing/shared.js +0 -563
- package/dist/store/vector-writes.d.ts +0 -13
- package/dist/store/vector-writes.js +0 -89
- /package/dist/{cli → store}/quality-repair.d.ts +0 -0
package/dist/store/conflicts.js
CHANGED
|
@@ -1,30 +1,30 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { DEFAULT_TENANT_ID } from '../util/env.js';
|
|
2
|
+
import { closeHippoDb, withWriteScope } from '../db/index.js';
|
|
2
3
|
import { rejectionDigest, insertRejectedValue, normalizeValueForRejection } from './rejection.js';
|
|
3
4
|
import { archiveRawMemory } from './raw-archive.js';
|
|
4
5
|
import { rowToMemoryConflict } from './rows.js';
|
|
5
6
|
import { audit } from './audit-event.js';
|
|
6
7
|
import { syncChangedMirrors, purgeMirrorBestEffort } from './mirrors.js';
|
|
7
|
-
import { selectEntriesByIds } from './entry-reads.js';
|
|
8
|
-
import { openStore } from './open.js';
|
|
8
|
+
import { chunked, selectEntriesByIds } from './entry-reads.js';
|
|
9
|
+
import { onHandle, openStore } from './open.js';
|
|
9
10
|
import { deleteEntryCore } from './delete-and-batch.js';
|
|
10
11
|
import { BadRequestError } from '../core/api-errors.js';
|
|
11
12
|
import { canTouchScope, isPersonalScope } from './recall-scope.js';
|
|
12
13
|
import { selectMemoryReach } from './tenant-lookup.js';
|
|
14
|
+
// The one place MemoryConflictRow's columns are listed; CONFLICT_COLS_MC is the same list under the `mc` alias.
|
|
15
|
+
const CONFLICT_COLS = 'id, memory_a_id, memory_b_id, reason, score, status, detected_at, updated_at';
|
|
16
|
+
const CONFLICT_COLS_MC = CONFLICT_COLS.split(', ').map((c) => `mc.${c}`).join(', ');
|
|
13
17
|
function canonicalConflictPair(aId, bId) {
|
|
14
18
|
return aId < bId
|
|
15
19
|
? { memory_a_id: aId, memory_b_id: bId }
|
|
16
20
|
: { memory_a_id: bId, memory_b_id: aId };
|
|
17
21
|
}
|
|
18
22
|
function selectConflictRowsInTenant(db, status, allStatuses, tenantId) {
|
|
19
|
-
// Tenanted query
|
|
20
|
-
//
|
|
21
|
-
// pre-fix row surfaces (consistent with resolveConflict).
|
|
22
|
-
// SAFETY: both branches select the same eight mc.* columns (aliased
|
|
23
|
-
// to MemoryConflictRow's field names) from memory_conflicts.
|
|
23
|
+
// Tenanted query: JOIN memories on both members and require each in-tenant, so no cross-tenant or stale pre-fix pair surfaces.
|
|
24
|
+
// SAFETY: both branches select CONFLICT_COLS_MC, MemoryConflictRow's columns.
|
|
24
25
|
return allStatuses
|
|
25
26
|
? db.prepare(`
|
|
26
|
-
SELECT
|
|
27
|
-
mc.status, mc.detected_at, mc.updated_at
|
|
27
|
+
SELECT ${CONFLICT_COLS_MC}
|
|
28
28
|
FROM memory_conflicts mc
|
|
29
29
|
JOIN memories ma ON ma.id = mc.memory_a_id
|
|
30
30
|
JOIN memories mb ON mb.id = mc.memory_b_id
|
|
@@ -32,8 +32,7 @@ function selectConflictRowsInTenant(db, status, allStatuses, tenantId) {
|
|
|
32
32
|
ORDER BY mc.updated_at DESC, mc.id DESC
|
|
33
33
|
`).all(tenantId, tenantId)
|
|
34
34
|
: db.prepare(`
|
|
35
|
-
SELECT
|
|
36
|
-
mc.status, mc.detected_at, mc.updated_at
|
|
35
|
+
SELECT ${CONFLICT_COLS_MC}
|
|
37
36
|
FROM memory_conflicts mc
|
|
38
37
|
JOIN memories ma ON ma.id = mc.memory_a_id
|
|
39
38
|
JOIN memories mb ON mb.id = mc.memory_b_id
|
|
@@ -43,37 +42,29 @@ function selectConflictRowsInTenant(db, status, allStatuses, tenantId) {
|
|
|
43
42
|
}
|
|
44
43
|
function selectConflictRowsUnscoped(db, status, allStatuses) {
|
|
45
44
|
// Unscoped query — legacy direct-mode (CLI, tests, consolidate).
|
|
46
|
-
// SAFETY: both branches select
|
|
47
|
-
// MemoryConflictRow's field set.
|
|
45
|
+
// SAFETY: both branches select CONFLICT_COLS, MemoryConflictRow's columns.
|
|
48
46
|
return allStatuses
|
|
49
47
|
? db.prepare(`
|
|
50
|
-
SELECT
|
|
48
|
+
SELECT ${CONFLICT_COLS}
|
|
51
49
|
FROM memory_conflicts
|
|
52
50
|
ORDER BY updated_at DESC, id DESC
|
|
53
51
|
`).all()
|
|
54
52
|
: db.prepare(`
|
|
55
|
-
SELECT
|
|
53
|
+
SELECT ${CONFLICT_COLS}
|
|
56
54
|
FROM memory_conflicts
|
|
57
55
|
WHERE status = ?
|
|
58
56
|
ORDER BY updated_at DESC, id DESC
|
|
59
57
|
`).all(status);
|
|
60
58
|
}
|
|
61
59
|
export function listMemoryConflicts(hippoRoot, status = 'open', tenantId) {
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
// v0.28 — '*' is a sentinel meaning "no status filter, return all rows".
|
|
65
|
-
// Pre-v0.28 callers (cli/mcp/dashboard) always passed 'open' or default,
|
|
66
|
-
// so this sentinel is purely additive. The 4 SQL branches below cover
|
|
67
|
-
// {tenanted | unscoped} × {all-statuses | specific-status}.
|
|
60
|
+
return onHandle(hippoRoot, (db) => {
|
|
61
|
+
// '*' is a sentinel for no status filter; the 4 SQL branches below cover {tenanted | unscoped} x {all-statuses | specific-status}.
|
|
68
62
|
const allStatuses = status === '*';
|
|
69
63
|
const rows = tenantId !== undefined
|
|
70
64
|
? selectConflictRowsInTenant(db, status, allStatuses, tenantId)
|
|
71
65
|
: selectConflictRowsUnscoped(db, status, allStatuses);
|
|
72
66
|
return rows.map(rowToMemoryConflict);
|
|
73
|
-
}
|
|
74
|
-
finally {
|
|
75
|
-
closeHippoDb(db);
|
|
76
|
-
}
|
|
67
|
+
}, openStore);
|
|
77
68
|
}
|
|
78
69
|
// listMemoryConflicts' tenanted open set: both members in the tenant.
|
|
79
70
|
const OPEN_IN_TENANT = `FROM memory_conflicts mc
|
|
@@ -82,22 +73,17 @@ const OPEN_IN_TENANT = `FROM memory_conflicts mc
|
|
|
82
73
|
WHERE mc.status = 'open' AND ma.tenant_id = ? AND mb.tenant_id = ?`;
|
|
83
74
|
/** How many open conflicts listMemoryConflicts returns for a tenant, without loading one. */
|
|
84
75
|
export function countOpenConflicts(hippoRoot, tenantId) {
|
|
85
|
-
|
|
86
|
-
try {
|
|
76
|
+
return onHandle(hippoRoot, (db) => {
|
|
87
77
|
// SAFETY: one row with the single aliased count column.
|
|
88
78
|
const row = db.prepare(`SELECT COUNT(*) AS n ${OPEN_IN_TENANT}`).get(tenantId, tenantId);
|
|
89
79
|
return Number(row.n);
|
|
90
|
-
}
|
|
91
|
-
finally {
|
|
92
|
-
closeHippoDb(db);
|
|
93
|
-
}
|
|
80
|
+
}, openStore);
|
|
94
81
|
}
|
|
95
82
|
/** A tenant's open conflicts naming `memoryId`, in listMemoryConflicts' order, each with its other member read in one batch. */
|
|
96
83
|
export function loadOpenConflictsOf(hippoRoot, tenantId, memoryId) {
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
const rows = db.prepare(`SELECT mc.id, mc.memory_a_id, mc.memory_b_id, mc.reason, mc.score, mc.status, mc.detected_at, mc.updated_at
|
|
84
|
+
return onHandle(hippoRoot, (db) => {
|
|
85
|
+
// SAFETY: selects CONFLICT_COLS_MC, MemoryConflictRow's columns.
|
|
86
|
+
const rows = db.prepare(`SELECT ${CONFLICT_COLS_MC}
|
|
101
87
|
${OPEN_IN_TENANT} AND (mc.memory_a_id = ? OR mc.memory_b_id = ?)
|
|
102
88
|
ORDER BY mc.updated_at DESC, mc.id DESC`).all(tenantId, tenantId, memoryId, memoryId);
|
|
103
89
|
const conflicts = rows.map(rowToMemoryConflict);
|
|
@@ -110,44 +96,47 @@ export function loadOpenConflictsOf(hippoRoot, tenantId, memoryId) {
|
|
|
110
96
|
out.push({ conflict, other });
|
|
111
97
|
}
|
|
112
98
|
return out;
|
|
113
|
-
}
|
|
114
|
-
finally {
|
|
115
|
-
closeHippoDb(db);
|
|
116
|
-
}
|
|
99
|
+
}, openStore);
|
|
117
100
|
}
|
|
118
101
|
/** Conflicts whose two rows `actor` may both touch; someone else's personal row hides its whole pair. */
|
|
119
102
|
export function listTouchableConflicts(hippoRoot, status, tenantId, actor) {
|
|
120
103
|
const conflicts = listMemoryConflicts(hippoRoot, status, tenantId);
|
|
121
|
-
|
|
122
|
-
try {
|
|
104
|
+
return onHandle(hippoRoot, (db) => {
|
|
123
105
|
return conflicts.filter((c) => [c.memory_a_id, c.memory_b_id].every((id) => canTouchScope(actor, selectMemoryReach(db, id)?.scope ?? null)));
|
|
124
|
-
}
|
|
125
|
-
finally {
|
|
126
|
-
closeHippoDb(db);
|
|
127
|
-
}
|
|
106
|
+
});
|
|
128
107
|
}
|
|
129
108
|
export function replaceDetectedConflicts(hippoRoot, detected, detectedAt = new Date().toISOString()) {
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
const changedIds = writeConflictRefresh(db, readConflictRefresh(db), detected, detectedAt);
|
|
109
|
+
onHandle(hippoRoot, (db) => {
|
|
110
|
+
const changedIds = writeConflictRefresh(db, readConflictRefresh(db, detected), detected, detectedAt);
|
|
133
111
|
syncChangedMirrors(hippoRoot, db, [...selectEntriesByIds(db, changedIds).values()]);
|
|
134
|
-
}
|
|
135
|
-
finally {
|
|
136
|
-
closeHippoDb(db);
|
|
137
|
-
}
|
|
112
|
+
}, openStore);
|
|
138
113
|
}
|
|
139
|
-
/** The refresh's
|
|
140
|
-
function readConflictRefresh(db) {
|
|
114
|
+
/** The refresh's reads, kept out of the write lock; only rows holding refs, in an open conflict or in `detected` are loaded, not the whole table. */
|
|
115
|
+
function readConflictRefresh(db, detected) {
|
|
141
116
|
// Tenant guard (E2): a conflict is meaningful only within one tenant, so cross-tenant pairs are
|
|
142
117
|
// skipped on insert and on rebuild, and a stale cross-tenant row can neither persist nor leak a foreign id.
|
|
143
118
|
const tenantById = new Map();
|
|
144
119
|
const storedRefs = new Map();
|
|
145
120
|
// SAFETY: rows' shape matches the three columns named in the SELECT.
|
|
146
|
-
|
|
121
|
+
const rows = db.prepare(`
|
|
122
|
+
SELECT id, tenant_id, conflicts_with_json FROM memories
|
|
123
|
+
WHERE conflicts_with_json != '[]'
|
|
124
|
+
OR id IN (SELECT memory_a_id FROM memory_conflicts WHERE status = 'open')
|
|
125
|
+
OR id IN (SELECT memory_b_id FROM memory_conflicts WHERE status = 'open')
|
|
126
|
+
`).all();
|
|
127
|
+
for (const r of rows) {
|
|
147
128
|
tenantById.set(r.id, r.tenant_id);
|
|
148
129
|
if (r.conflicts_with_json !== '[]')
|
|
149
130
|
storedRefs.set(r.id, r.conflicts_with_json);
|
|
150
131
|
}
|
|
132
|
+
const given = [...new Set(detected.flatMap((c) => [c.memory_a_id, c.memory_b_id]))].filter((id) => !tenantById.has(id));
|
|
133
|
+
for (const ids of chunked(given)) {
|
|
134
|
+
const marks = ids.map(() => '?').join(',');
|
|
135
|
+
// SAFETY: rows' shape matches the two columns named in the SELECT.
|
|
136
|
+
const found = db.prepare(`SELECT id, tenant_id FROM memories WHERE id IN (${marks})`).all(...ids);
|
|
137
|
+
for (const r of found)
|
|
138
|
+
tenantById.set(r.id, r.tenant_id);
|
|
139
|
+
}
|
|
151
140
|
const sameTenant = (a, b) => {
|
|
152
141
|
const ta = tenantById.get(a);
|
|
153
142
|
const tb = tenantById.get(b);
|
|
@@ -170,10 +159,9 @@ function writeConflictRefresh(db, reads, detected, detectedAt) {
|
|
|
170
159
|
}
|
|
171
160
|
function resolveStaleOpenConflicts(db, canonicalDetected, sameTenant, detectedAt) {
|
|
172
161
|
const detectedKeys = new Set(canonicalDetected.map((conflict) => `${conflict.memory_a_id}::${conflict.memory_b_id}`));
|
|
173
|
-
// SAFETY: openRows' shape matches the
|
|
174
|
-
// above.
|
|
162
|
+
// SAFETY: openRows' shape matches the columns named in CONFLICT_COLS.
|
|
175
163
|
const openRows = db.prepare(`
|
|
176
|
-
SELECT
|
|
164
|
+
SELECT ${CONFLICT_COLS}
|
|
177
165
|
FROM memory_conflicts
|
|
178
166
|
WHERE status = 'open'
|
|
179
167
|
`).all();
|
|
@@ -181,11 +169,7 @@ function resolveStaleOpenConflicts(db, canonicalDetected, sameTenant, detectedAt
|
|
|
181
169
|
for (const row of openRows) {
|
|
182
170
|
const key = `${row.memory_a_id}::${row.memory_b_id}`;
|
|
183
171
|
const stale = !detectedKeys.has(key);
|
|
184
|
-
//
|
|
185
|
-
// loop in upsertDetectedConflicts and the refMap rebuild skip
|
|
186
|
-
// cross-tenant pairs, but the resolve-stale loop previously left
|
|
187
|
-
// re-detected cross-tenant rows lingering status='open'. The
|
|
188
|
-
// sameTenant() helper is already built one block up; no extra query.
|
|
172
|
+
// Auto-resolve any open cross-tenant row: the insert loop and refMap rebuild skip those pairs, so re-detected ones would linger as 'open'.
|
|
189
173
|
const crossTenant = !sameTenant(row.memory_a_id, row.memory_b_id);
|
|
190
174
|
if (stale || crossTenant)
|
|
191
175
|
resolve.run(detectedAt, row.id);
|
|
@@ -242,10 +226,8 @@ function rebuildConflictsWithJson(db, { sameTenant, storedRefs }) {
|
|
|
242
226
|
}
|
|
243
227
|
return changedIds;
|
|
244
228
|
}
|
|
245
|
-
//
|
|
246
|
-
//
|
|
247
|
-
// then returns null, indistinguishable from a bad id. Omitted tenantId =
|
|
248
|
-
// legacy unscoped behaviour (CLI direct mode, tests, consolidate.ts).
|
|
229
|
+
// With tenantId, both members must be in-tenant and every memories mutation carries AND tenant_id = ?; a cross-tenant probe returns null like a bad id.
|
|
230
|
+
// Omitted tenantId = unscoped (CLI direct mode, tests).
|
|
249
231
|
function conflictMemScope(tenantId) {
|
|
250
232
|
return {
|
|
251
233
|
memScope: tenantId !== undefined ? ' AND tenant_id = ?' : '',
|
|
@@ -268,21 +250,8 @@ function findResolvableConflict(db, conflictId, keepId, tenantId) {
|
|
|
268
250
|
return null;
|
|
269
251
|
return { conflict, loserId };
|
|
270
252
|
}
|
|
271
|
-
/**
|
|
272
|
-
*
|
|
273
|
-
* Sets conflict status to 'resolved' and halves the loser's half-life.
|
|
274
|
-
* If --forget is used, the loser is removed entirely (kind-aware: raw rows
|
|
275
|
-
* are archived via archiveRawMemory, others deleted via deleteEntryCore —
|
|
276
|
-
* AT1 fix for the pre-existing crash where a raw loser aborted the whole
|
|
277
|
-
* resolve transaction against the append-only trigger). `opts.rejectLoserValue`
|
|
278
|
-
* additionally tombstones the loser's normalized digest so it cannot be
|
|
279
|
-
* re-asserted later.
|
|
280
|
-
*
|
|
281
|
-
* Every resolution path (weaken / forget / reject) emits a `conflict_resolve`
|
|
282
|
-
* audit row (AT1 — previously resolveConflict wrote zero audit rows on any path).
|
|
283
|
-
*
|
|
284
|
-
* Returns the resolved conflict, or null if not found.
|
|
285
|
-
*/
|
|
253
|
+
/** Resolve a conflict by keeping one memory and halving the loser's half-life; `--forget` removes the loser, `opts.rejectLoserValue` also tombstones its
|
|
254
|
+
* digest. Every path emits a `conflict_resolve` audit row. Returns the resolved conflict, or null if not found. */
|
|
286
255
|
export function resolveConflict(hippoRoot, conflictId, keepId, forgetLoser = false, tenantId, opts) {
|
|
287
256
|
const db = openStore(hippoRoot);
|
|
288
257
|
const scope = conflictMemScope(tenantId);
|
|
@@ -312,19 +281,17 @@ export function resolveConflict(hippoRoot, conflictId, keepId, forgetLoser = fal
|
|
|
312
281
|
}
|
|
313
282
|
}
|
|
314
283
|
function selectConflictRow(db, conflictId, tenantId) {
|
|
315
|
-
// SAFETY:
|
|
316
|
-
// tenanted branch) matching MemoryConflictRow's field set.
|
|
284
|
+
// SAFETY: the branches select CONFLICT_COLS_MC and CONFLICT_COLS, MemoryConflictRow's columns.
|
|
317
285
|
return (tenantId !== undefined
|
|
318
286
|
? db.prepare(`
|
|
319
|
-
SELECT
|
|
320
|
-
mc.status, mc.detected_at, mc.updated_at
|
|
287
|
+
SELECT ${CONFLICT_COLS_MC}
|
|
321
288
|
FROM memory_conflicts mc
|
|
322
289
|
JOIN memories ma ON ma.id = mc.memory_a_id
|
|
323
290
|
JOIN memories mb ON mb.id = mc.memory_b_id
|
|
324
291
|
WHERE mc.id = ? AND ma.tenant_id = ? AND mb.tenant_id = ?
|
|
325
292
|
`).get(conflictId, tenantId, tenantId)
|
|
326
293
|
: db.prepare(`
|
|
327
|
-
SELECT
|
|
294
|
+
SELECT ${CONFLICT_COLS}
|
|
328
295
|
FROM memory_conflicts WHERE id = ?
|
|
329
296
|
`).get(conflictId));
|
|
330
297
|
}
|
|
@@ -335,21 +302,13 @@ function weakenConflictLoser(db, t) {
|
|
|
335
302
|
return { loserRemoved: false, loserWasRaw: false, rejectedDigest: undefined, extraRemovedIds: [], extraRemovedRawIds: [] };
|
|
336
303
|
}
|
|
337
304
|
function removeConflictLoser(db, t) {
|
|
338
|
-
//
|
|
339
|
-
//
|
|
340
|
-
// `DELETE FROM memories WHERE id = ?` aborted the whole transaction when
|
|
341
|
-
// the loser was kind='raw' (append-only trigger fires); route through
|
|
342
|
-
// the same helpers the reject verb uses (both db-scoped, both compose
|
|
343
|
-
// inside this BEGIN/COMMIT). loserRemoved / loserWasRaw drive both the
|
|
344
|
-
// conflicts_with_json skip below and the post-commit mirror purge.
|
|
305
|
+
// Removal is kind-aware: a bare DELETE on a raw loser fires the append-only trigger, so use the same helpers as the reject verb.
|
|
306
|
+
// loserRemoved / loserWasRaw drive the conflicts_with_json skip below and the post-commit mirror purge.
|
|
345
307
|
const removal = {
|
|
346
308
|
loserRemoved: false,
|
|
347
309
|
loserWasRaw: false,
|
|
348
310
|
rejectedDigest: undefined,
|
|
349
|
-
//
|
|
350
|
-
// rejectLoserValue also removes (see below) — separate from loserId so
|
|
351
|
-
// the audit + post-commit mirror purge can cover ALL of them, not just
|
|
352
|
-
// loserId.
|
|
311
|
+
// Same-tenant duplicates of the loser's content that rejectLoserValue also removes; kept apart from loserId so audit and mirror purge cover all of them.
|
|
353
312
|
extraRemovedIds: [],
|
|
354
313
|
extraRemovedRawIds: [],
|
|
355
314
|
};
|
|
@@ -380,7 +339,7 @@ function removeConflictLoser(db, t) {
|
|
|
380
339
|
}
|
|
381
340
|
function recordRejectedLoserValue(db, t, loserRow, digest, who) {
|
|
382
341
|
insertRejectedValue(db, {
|
|
383
|
-
tenantId: loserRow.tenant_id ??
|
|
342
|
+
tenantId: loserRow.tenant_id ?? DEFAULT_TENANT_ID,
|
|
384
343
|
digest,
|
|
385
344
|
reason: who.reason,
|
|
386
345
|
rejectedBy: who.actor,
|
|
@@ -397,19 +356,9 @@ function tombstoneLoserValue(db, t, loserRow, who, removal) {
|
|
|
397
356
|
const { actor, reason } = who;
|
|
398
357
|
const rejectedDigest = rejectionDigest(loserRow.content);
|
|
399
358
|
recordRejectedLoserValue(db, t, loserRow, rejectedDigest, who);
|
|
400
|
-
//
|
|
401
|
-
//
|
|
402
|
-
|
|
403
|
-
// leaving same-TENANT duplicates live while their shared content
|
|
404
|
-
// was tombstoned. Same O(N) scan pattern as reject-flow.ts (human-
|
|
405
|
-
// triggered command, tenant's row count is human-scale). CRITICAL
|
|
406
|
-
// BOUNDARY: tenant-scoped ONLY — tombstones are tenant-scoped by
|
|
407
|
-
// design, so a same-content row in ANOTHER tenant is legitimately
|
|
408
|
-
// live and must NOT be touched here. `keepId` is excluded even if
|
|
409
|
-
// its content coincidentally matches: the human explicitly chose
|
|
410
|
-
// to keep it in this same resolution, and this branch must not
|
|
411
|
-
// undo that choice in the same transaction.
|
|
412
|
-
const loserTenantId = loserRow.tenant_id ?? 'default';
|
|
359
|
+
// Remove ALL live same-tenant rows whose digest matches (as reject-flow.ts rejectValue does), not just loserId; the O(N) scan is human-scale.
|
|
360
|
+
// Tenant-scoped ONLY, since tombstones are; `keepId` is excluded even if its content matches, because the human chose to keep it.
|
|
361
|
+
const loserTenantId = loserRow.tenant_id ?? DEFAULT_TENANT_ID;
|
|
413
362
|
// SAFETY: dupRows' shape matches the four columns named in the SELECT above.
|
|
414
363
|
const dupRows = db
|
|
415
364
|
.prepare(`SELECT id, kind, content, scope FROM memories WHERE tenant_id = ? AND id != ? AND id != ?`)
|
|
@@ -434,9 +383,8 @@ function tombstoneLoserValue(db, t, loserRow, who, removal) {
|
|
|
434
383
|
function stripConflictRefs(db, t, loserRemoved) {
|
|
435
384
|
const { memScope, memArgs } = t.scope;
|
|
436
385
|
const { keepId, loserId } = t;
|
|
437
|
-
// Clean up conflicts_with references
|
|
438
|
-
// SAFETY: keepRow's shape matches the single `conflicts_with_json`
|
|
439
|
-
// column selected above.
|
|
386
|
+
// Clean up conflicts_with references.
|
|
387
|
+
// SAFETY: keepRow's shape matches the single `conflicts_with_json` column selected above.
|
|
440
388
|
const keepRow = db.prepare(`SELECT conflicts_with_json FROM memories WHERE id = ?${memScope}`).get(keepId, ...memArgs);
|
|
441
389
|
if (keepRow) {
|
|
442
390
|
const refs = JSON.parse(keepRow.conflicts_with_json || '[]');
|
|
@@ -458,56 +406,29 @@ function stripConflictRefs(db, t, loserRemoved) {
|
|
|
458
406
|
}
|
|
459
407
|
function auditConflictResolve(db, t, removal, tenantId) {
|
|
460
408
|
const { loserRemoved, loserWasRaw, rejectedDigest, extraRemovedIds } = removal;
|
|
461
|
-
//
|
|
462
|
-
// rows on any path before this). Every path — weaken, forget, reject —
|
|
463
|
-
// lands exactly one conflict_resolve row.
|
|
409
|
+
// Every path (weaken, forget, reject) lands exactly one conflict_resolve audit row.
|
|
464
410
|
const conflictResolveMeta = {
|
|
465
411
|
conflictId: t.conflictId,
|
|
466
412
|
keepId: t.keepId,
|
|
467
413
|
loserId: t.loserId,
|
|
468
414
|
disposition: loserRemoved ? (loserWasRaw ? 'archived_raw' : 'deleted') : 'weakened',
|
|
469
415
|
rejected: Boolean(t.opts?.rejectLoserValue),
|
|
470
|
-
//
|
|
471
|
-
// same-tenant duplicate sweep above (extraRemovedIds) needs an
|
|
472
|
-
// audit trail too.
|
|
416
|
+
// Every row this call removed, not just loserId, so the duplicate sweep (extraRemovedIds) is audited too.
|
|
473
417
|
removedIds: loserRemoved ? [t.loserId, ...extraRemovedIds] : [],
|
|
474
418
|
};
|
|
475
419
|
// Assigned only when present so the serialized audit payload keeps
|
|
476
420
|
// omitting the key, exactly as the pre-migration object literal did.
|
|
477
421
|
if (rejectedDigest !== undefined)
|
|
478
422
|
conflictResolveMeta.rejectedDigest = rejectedDigest;
|
|
479
|
-
// Fresh spread literal: ConflictResolveMeta is a closed interface (
|
|
480
|
-
// index signature) and isn't directly assignable to audit()'s
|
|
481
|
-
// Record<string, JsonValue> metadata param; a spread into a fresh
|
|
482
|
-
// object literal satisfies it without widening the declared type above.
|
|
423
|
+
// Fresh spread literal: ConflictResolveMeta is a closed interface, not assignable to audit()'s Record<string, JsonValue> metadata otherwise.
|
|
483
424
|
audit(db, 'conflict_resolve', { targetId: t.keepId, metadata: { ...conflictResolveMeta }, actor: t.opts?.rejectedBy ?? 'cli', tenantId });
|
|
484
425
|
}
|
|
485
426
|
function purgeRemovedLoserMirrors(hippoRoot, db, loserId, removal) {
|
|
486
|
-
//
|
|
487
|
-
//
|
|
488
|
-
// a raw loser crashed outright (bare DELETE FROM memories hit the
|
|
489
|
-
// append-only trigger) — there is no legacy "successful forget, no
|
|
490
|
-
// purge" behavior to preserve for that case. Post-AT1's kind-aware
|
|
491
|
-
// removal (archiveRawMemory / deleteEntryCore above) makes plain
|
|
492
|
-
// --forget succeed on every kind, but until this fix the mirror was
|
|
493
|
-
// only purged when rejectLoserValue was ALSO set: a plain raw --forget
|
|
494
|
-
// left its markdown mirror orphaned (the reaper still catches it
|
|
495
|
-
// eventually, since archiveRawMemory's own raw_archive insert leaves
|
|
496
|
-
// mirror_cleaned_at NULL) and a plain non-raw --forget left its mirror
|
|
497
|
-
// orphaned FOREVER (no reaper exists for non-raw rows). Same post-commit
|
|
498
|
-
// purge+reaper pattern as the reject verb (src/trust/reject-flow.ts) and
|
|
499
|
-
// api.archiveRaw — reusing removeEntryMirrors + raw_archive bookkeeping.
|
|
500
|
-
// AT1 P1 fix: loop over loserId AND every same-tenant duplicate the
|
|
501
|
-
// rejectLoserValue sweep above removed (extraRemovedIds) — previously
|
|
502
|
-
// only loserId's mirror was purged, leaving duplicate mirrors orphaned
|
|
503
|
-
// despite their rows being gone.
|
|
427
|
+
// Mirror purge and reaper stamp for EVERY removed loser (loserId and each extraRemovedIds duplicate), post-commit like the reject verb.
|
|
428
|
+
// A non-raw mirror has no reaper, so skipping the purge would orphan it forever.
|
|
504
429
|
for (const removedId of [loserId, ...removal.extraRemovedIds]) {
|
|
505
430
|
const isRaw = removedId === loserId ? removal.loserWasRaw : removal.extraRemovedRawIds.includes(removedId);
|
|
506
|
-
//
|
|
507
|
-
// which cleanupArchivedMirrors' reaper never scans — reports the
|
|
508
|
-
// EXPLICIT leftover path(s) instead of the false "will retry via
|
|
509
|
-
// reaper" claim. See its own doc comment (store.ts, near
|
|
510
|
-
// removeEntryMirrors) for the full rationale.
|
|
431
|
+
// purgeMirrorBestEffort retries once, then reports the explicit leftover paths for non-raw ids, which the cleanupArchivedMirrors reaper never scans.
|
|
511
432
|
const mirrorOk = purgeMirrorBestEffort(hippoRoot, removedId, isRaw, 'resolveConflict');
|
|
512
433
|
if (mirrorOk && isRaw) {
|
|
513
434
|
db.prepare(`UPDATE raw_archive SET mirror_cleaned_at = ? WHERE memory_id = ?`).run(new Date().toISOString(), removedId);
|
|
@@ -516,7 +437,7 @@ function purgeRemovedLoserMirrors(hippoRoot, db, loserId, removal) {
|
|
|
516
437
|
}
|
|
517
438
|
/** The conflict and loser ids every conflict_resolve audit row names. */
|
|
518
439
|
export function conflictResolveAuditsAt(db) {
|
|
519
|
-
// SAFETY: SELECT of two fields every conflict_resolve audit row carries (ConflictResolveMeta
|
|
440
|
+
// SAFETY: SELECT of two fields every conflict_resolve audit row carries (ConflictResolveMeta above).
|
|
520
441
|
return db.prepare(`SELECT json_extract(metadata_json, '$.conflictId') AS conflictId, json_extract(metadata_json, '$.loserId') AS loserId FROM audit_log WHERE op = 'conflict_resolve'`).all();
|
|
521
442
|
}
|
|
522
443
|
/** Every resolved conflict with both sides. */
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { type DatabaseSyncLike } from '../../db/index.js';
|
|
2
2
|
/** One github_event_log row to write; `memoryId` is null for an event that produced no memory. */
|
|
3
|
-
export interface
|
|
3
|
+
export interface GitHubEventLogEntry {
|
|
4
4
|
idempotencyKey: string;
|
|
5
5
|
deliveryId: string;
|
|
6
6
|
eventName: string;
|
|
@@ -9,12 +9,12 @@ export interface GithubEventLogEntry {
|
|
|
9
9
|
export declare function eventSeenAt(db: DatabaseSyncLike, idempotencyKey: string): boolean;
|
|
10
10
|
export declare function eventMemoryAt(db: DatabaseSyncLike, idempotencyKey: string): string | null;
|
|
11
11
|
/** False when the key was already logged, so a caller inside a write scope can roll its own row back. */
|
|
12
|
-
export declare function logEventAt(db: DatabaseSyncLike, entry:
|
|
12
|
+
export declare function logEventAt(db: DatabaseSyncLike, entry: GitHubEventLogEntry): boolean;
|
|
13
13
|
/** The memory an already-seen key points at, or null when the key is new. */
|
|
14
14
|
export declare function seenEvent(hippoRoot: string, idempotencyKey: string): {
|
|
15
15
|
memoryId: string | null;
|
|
16
16
|
} | null;
|
|
17
|
-
export declare function logEvent(hippoRoot: string, entry:
|
|
17
|
+
export declare function logEvent(hippoRoot: string, entry: GitHubEventLogEntry): void;
|
|
18
18
|
export interface ArtifactDeletion {
|
|
19
19
|
tenantId: string;
|
|
20
20
|
artifactRef: string;
|
|
@@ -46,7 +46,7 @@ export interface DlqItem {
|
|
|
46
46
|
bucket: DlqBucket | string;
|
|
47
47
|
}
|
|
48
48
|
/** One github_dlq row to write, already redacted by the caller; the four GitHub-only columns are stored NULL when left out. */
|
|
49
|
-
export interface
|
|
49
|
+
export interface GitHubDlqInsert {
|
|
50
50
|
tenantId: string;
|
|
51
51
|
rawPayload: string;
|
|
52
52
|
error: string;
|
|
@@ -57,12 +57,12 @@ export interface GithubDlqWrite {
|
|
|
57
57
|
repoFullName?: string | null;
|
|
58
58
|
bucket: DlqBucket;
|
|
59
59
|
}
|
|
60
|
-
export declare function
|
|
61
|
-
export declare function
|
|
62
|
-
export declare function
|
|
63
|
-
export declare function
|
|
60
|
+
export declare function insertGitHubDlq(hippoRoot: string, row: GitHubDlqInsert): number;
|
|
61
|
+
export declare function listGitHubDlq(hippoRoot: string, tenantId: string, limit: number): DlqItem[];
|
|
62
|
+
export declare function githubDlqEntry(hippoRoot: string, id: number): DlqItem | null;
|
|
63
|
+
export declare function bumpGitHubDlqRetryCount(hippoRoot: string, id: number): void;
|
|
64
64
|
/** What the routing tables say about one webhook; `tenant` is the installation match, or the repo match when no installation was sent. */
|
|
65
|
-
export interface
|
|
65
|
+
export interface GitHubRouting {
|
|
66
66
|
installations: number;
|
|
67
67
|
repositories: number;
|
|
68
68
|
tenant: string | null;
|
|
@@ -70,7 +70,7 @@ export interface GithubRouting {
|
|
|
70
70
|
export declare function githubRouting(hippoRoot: string, args: {
|
|
71
71
|
installationId?: string | null;
|
|
72
72
|
repoFullName?: string | null;
|
|
73
|
-
}):
|
|
73
|
+
}): GitHubRouting;
|
|
74
74
|
export type HwmColumn = 'issues_hwm' | 'issue_comments_hwm' | 'pr_review_comments_hwm';
|
|
75
75
|
export interface StoredCursors {
|
|
76
76
|
issues: string | null;
|
|
@@ -47,7 +47,7 @@ export function archiveDeletedArtifact(hippoRoot, del) {
|
|
|
47
47
|
return { duplicate: false, archived: memoryIds.length };
|
|
48
48
|
});
|
|
49
49
|
}
|
|
50
|
-
function
|
|
50
|
+
function insertGitHubDlqAt(db, row) {
|
|
51
51
|
const result = db
|
|
52
52
|
.prepare(`INSERT INTO github_dlq
|
|
53
53
|
(tenant_id, raw_payload, error, event_name, delivery_id, signature,
|
|
@@ -56,8 +56,8 @@ function insertDlqAt(db, row) {
|
|
|
56
56
|
.run(row.tenantId, row.rawPayload, row.error, row.eventName ?? null, row.deliveryId ?? null, row.signature, row.installationId ?? null, row.repoFullName ?? null, new Date().toISOString(), row.bucket);
|
|
57
57
|
return Number(result.lastInsertRowid);
|
|
58
58
|
}
|
|
59
|
-
export function
|
|
60
|
-
return onHandle(hippoRoot, (db) =>
|
|
59
|
+
export function insertGitHubDlq(hippoRoot, row) {
|
|
60
|
+
return onHandle(hippoRoot, (db) => insertGitHubDlqAt(db, row));
|
|
61
61
|
}
|
|
62
62
|
const SELECT_COLUMNS = `id, tenant_id, raw_payload, error, event_name, delivery_id,
|
|
63
63
|
signature, installation_id, repo_full_name, retry_count,
|
|
@@ -79,7 +79,7 @@ function rowToItem(r) {
|
|
|
79
79
|
bucket: r.bucket == null ? 'parse_error' : String(r.bucket),
|
|
80
80
|
};
|
|
81
81
|
}
|
|
82
|
-
function
|
|
82
|
+
function listGitHubDlqAt(db, tenantId, limit) {
|
|
83
83
|
// SAFETY: SELECT_COLUMNS projects exactly DlqRawRow's fields.
|
|
84
84
|
const rows = db
|
|
85
85
|
.prepare(`SELECT ${SELECT_COLUMNS}
|
|
@@ -90,10 +90,10 @@ function listDlqAt(db, tenantId, limit) {
|
|
|
90
90
|
.all(tenantId, limit);
|
|
91
91
|
return rows.map(rowToItem);
|
|
92
92
|
}
|
|
93
|
-
export function
|
|
94
|
-
return onHandle(hippoRoot, (db) =>
|
|
93
|
+
export function listGitHubDlq(hippoRoot, tenantId, limit) {
|
|
94
|
+
return onHandle(hippoRoot, (db) => listGitHubDlqAt(db, tenantId, limit));
|
|
95
95
|
}
|
|
96
|
-
function
|
|
96
|
+
function githubDlqEntryAt(db, id) {
|
|
97
97
|
// SAFETY: SELECT_COLUMNS projects exactly DlqRawRow's fields.
|
|
98
98
|
const row = db
|
|
99
99
|
.prepare(`SELECT ${SELECT_COLUMNS}
|
|
@@ -104,10 +104,10 @@ function dlqEntryAt(db, id) {
|
|
|
104
104
|
return null;
|
|
105
105
|
return rowToItem(row);
|
|
106
106
|
}
|
|
107
|
-
export function
|
|
108
|
-
return onHandle(hippoRoot, (db) =>
|
|
107
|
+
export function githubDlqEntry(hippoRoot, id) {
|
|
108
|
+
return onHandle(hippoRoot, (db) => githubDlqEntryAt(db, id));
|
|
109
109
|
}
|
|
110
|
-
export function
|
|
110
|
+
export function bumpGitHubDlqRetryCount(hippoRoot, id) {
|
|
111
111
|
onHandle(hippoRoot, (db) => {
|
|
112
112
|
db.prepare(`UPDATE github_dlq
|
|
113
113
|
SET retry_count = retry_count + 1,
|
|
@@ -5,7 +5,7 @@ import { withReadSnapshot } from '../db/busy.js';
|
|
|
5
5
|
import { pragmaDataVersion } from '../db/meta.js';
|
|
6
6
|
import { tableExists } from '../db/tables.js';
|
|
7
7
|
import { storedVectorIds } from '../db/vector-store.js';
|
|
8
|
-
import { openStore } from './open.js';
|
|
8
|
+
import { onHandle, openStore } from './open.js';
|
|
9
9
|
import { QUARANTINE_SCOPE_PREFIX } from './quarantine.js';
|
|
10
10
|
import { parseJsonArray } from './rows.js';
|
|
11
11
|
const LIVE_COLUMNS = 'id, created, last_retrieved, retrieval_count, half_life_days, layer, tags_json, emotional_valence, outcome_positive, outcome_negative, pinned, confidence, content, superseded_by, kind, scope, origin_project';
|
|
@@ -24,7 +24,7 @@ function toDashboardRow(row) {
|
|
|
24
24
|
retrieval_count: Number(row.retrieval_count ?? 0),
|
|
25
25
|
half_life_days: Number(row.half_life_days ?? 7),
|
|
26
26
|
layer: row.layer,
|
|
27
|
-
tags: parseJsonArray(row.tags_json),
|
|
27
|
+
tags: parseJsonArray(row.tags_json, { table: 'memories', id: row.id, column: 'tags_json' }),
|
|
28
28
|
emotional_valence: row.emotional_valence ?? 'neutral',
|
|
29
29
|
outcome_positive: Number(row.outcome_positive ?? 0),
|
|
30
30
|
outcome_negative: Number(row.outcome_negative ?? 0),
|
|
@@ -39,8 +39,7 @@ function toDashboardRow(row) {
|
|
|
39
39
|
}
|
|
40
40
|
/** One tenant's live rows and the counts of the rest, read in one transaction so the two agree. */
|
|
41
41
|
export function loadDashboardRows(hippoRoot, tenantId) {
|
|
42
|
-
|
|
43
|
-
try {
|
|
42
|
+
return onHandle(hippoRoot, (db) => {
|
|
44
43
|
return withReadSnapshot(db, () => {
|
|
45
44
|
// SAFETY: the SELECT names exactly LiveRow's columns.
|
|
46
45
|
const live = db.prepare(`SELECT ${LIVE_COLUMNS} FROM memories WHERE tenant_id = ? AND ${LIVE} ORDER BY created ASC, id ASC`).all(tenantId);
|
|
@@ -56,10 +55,7 @@ export function loadDashboardRows(hippoRoot, tenantId) {
|
|
|
56
55
|
excluded[why] = Number(n);
|
|
57
56
|
return { live: live.map(toDashboardRow), excluded };
|
|
58
57
|
});
|
|
59
|
-
}
|
|
60
|
-
finally {
|
|
61
|
-
closeHippoDb(db);
|
|
62
|
-
}
|
|
58
|
+
}, openStore);
|
|
63
59
|
}
|
|
64
60
|
/** The dashboard's one read-only connection, kept across refreshes for the commit signal; it opens on the first read that finds a database. */
|
|
65
61
|
export class DashboardConnection {
|
|
@@ -8,16 +8,8 @@ export declare const MEMORY_BACKED_TABLES: readonly ["predictions", "decisions",
|
|
|
8
8
|
export declare function memoriesBackingObjects(hippoRoot: string): Set<string>;
|
|
9
9
|
/** memoriesBackingObjects on the caller's handle. */
|
|
10
10
|
export declare function memoriesBackingObjectsOn(db: DatabaseSyncLike): Set<string>;
|
|
11
|
-
/**
|
|
12
|
-
*
|
|
13
|
-
* NO filesystem I/O: the caller's transaction may still roll back, and mirrors are written post-commit.
|
|
14
|
-
*
|
|
15
|
-
* `opts.suppressForgetAudit` (default false): `rejectValue` and `resolveConflict` set it because each
|
|
16
|
-
* writes its own aggregate audit row, so a removed row must not ALSO emit a `forget` row.
|
|
17
|
-
*
|
|
18
|
-
* Returns `{tenantId, dagParentId}` for the removed row, or `null` if no row with `id`
|
|
19
|
-
* existed or `automatic` refused it (pinned, raw, kept for good or backing an object at DELETE time, so a late pin wins).
|
|
20
|
-
*/
|
|
11
|
+
/** db-scoped delete core, composable inside a caller's transaction; NO filesystem I/O, mirrors are written post-commit. `suppressForgetAudit` is set by
|
|
12
|
+
* rejectValue and resolveConflict (own audit row). Returns `{tenantId, dagParentId}`, or null if absent or `automatic` refused it. */
|
|
21
13
|
export declare function deleteEntryCore(db: ReturnType<typeof openHippoDb>, id: string, opts?: {
|
|
22
14
|
actor?: string;
|
|
23
15
|
suppressForgetAudit?: boolean;
|
|
@@ -27,29 +19,17 @@ export declare function deleteEntryCore(db: ReturnType<typeof openHippoDb>, id:
|
|
|
27
19
|
tenantId: string;
|
|
28
20
|
dagParentId: string | null;
|
|
29
21
|
} | null;
|
|
30
|
-
/**
|
|
31
|
-
*
|
|
32
|
-
*
|
|
33
|
-
* `opts.actor` defaults to 'cli'. The api.* layer threads `ctx.actor` so HTTP
|
|
34
|
-
* callers land with `api_key:<key_id>` in the audit log without a duplicate
|
|
35
|
-
* emit from the api wrapper.
|
|
36
|
-
*
|
|
37
|
-
* Thin wrapper over `deleteEntryCore` (open → core → mirrors → close);
|
|
38
|
-
* behavior is byte-identical to the pre-split implementation for every
|
|
39
|
-
* existing caller.
|
|
40
|
-
*/
|
|
22
|
+
/** Delete an entry from SQLite and mirrors; thin wrapper over `deleteEntryCore` (open, core, mirrors, close).
|
|
23
|
+
* `opts.actor` defaults to 'cli'; the api layer threads `ctx.actor` so HTTP callers land as `api_key:<key_id>` in the audit log. */
|
|
41
24
|
export declare function deleteEntry(hippoRoot: string, id: string, opts?: {
|
|
42
25
|
actor?: string;
|
|
43
26
|
reason?: string;
|
|
44
27
|
automatic?: boolean;
|
|
45
28
|
}): boolean;
|
|
46
|
-
/**
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
*
|
|
50
|
-
* leaves exactly like a delete (FTS row, DAG parent dirty-mark, mirrors), in the same transaction, so a memory
|
|
51
|
-
* is never in both places or in neither. Deletes and moves both skip rows that are no longer auto-deletable
|
|
52
|
-
* (pinned, raw, kept for good or backing an object since the caller decided). Returns the ids that left `memories`, deleted or moved. */
|
|
29
|
+
/** Each row as the caller loaded it, by id; a `ReadonlyMap` fits. */
|
|
30
|
+
export type LoadedRows = Pick<ReadonlyMap<string, MemoryEntry>, 'get'>;
|
|
31
|
+
/** Writes, deletes and dormant moves in one transaction. With `snapshot`, a write keeps only the fields the caller changed and never resurrects a gone row.
|
|
32
|
+
* Dormant moves (src/store/dormant.ts) leave `memories` like a delete; both skip rows no longer auto-deletable. Returns ids that left `memories`. */
|
|
53
33
|
export declare function batchWriteAndDelete(hippoRoot: string, toWrite: MemoryEntry[], toDeleteIds: string[], opts?: {
|
|
54
34
|
snapshot?: ReadonlyMap<string, MemoryEntry>;
|
|
55
35
|
dormant?: DormantMove[];
|
|
@@ -70,10 +50,10 @@ export declare function deleteEntriesOneByOne(hippoRoot: string, targets: readon
|
|
|
70
50
|
actor?: string;
|
|
71
51
|
automatic?: boolean;
|
|
72
52
|
}): boolean[];
|
|
73
|
-
/** Commits whole components in transactions of about `budget.holdMs
|
|
74
|
-
*
|
|
53
|
+
/** Commits whole components in transactions of about `budget.holdMs`, letting other writers in between; returns the ids that left `memories`.
|
|
54
|
+
* The snapshot keeps what other writers changed after the caller loaded its rows. */
|
|
75
55
|
export declare function commitInChunks(hippoRoot: string, components: readonly FlushComponent[], opts: {
|
|
76
|
-
snapshot:
|
|
56
|
+
snapshot: LoadedRows;
|
|
77
57
|
budget: WriteBudget;
|
|
78
58
|
busyWaitMs: number;
|
|
79
59
|
}): Promise<string[]>;
|