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/rejection.js
CHANGED
|
@@ -1,43 +1,19 @@
|
|
|
1
|
-
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
4
|
-
* Exact-normalized-value semantics: a human who rejects a fact can refuse
|
|
5
|
-
* byte-stable re-ingestion of the same value across remember/capture/import/
|
|
6
|
-
* sync surfaces. Paraphrase/semantic matching is explicitly out of scope
|
|
7
|
-
* (documented limitation, plan "Design").
|
|
8
|
-
*
|
|
9
|
-
* Kept db-agnostic (helpers take a `DatabaseSyncLike` handle) and does NOT
|
|
10
|
-
* import from store.ts — store.ts imports from here, and the reverse would
|
|
11
|
-
* be a cycle.
|
|
12
|
-
*/
|
|
1
|
+
/** Rejected-value tombstone: a human can refuse byte-stable re-ingestion of a rejected fact (exact normalized value); paraphrase matching is out of scope.
|
|
2
|
+
* db-agnostic (helpers take a `DatabaseSyncLike`) and imports nothing from the store layer above it, which imports this (the reverse is a cycle). */
|
|
13
3
|
import { createHash } from 'node:crypto';
|
|
14
4
|
import { BadRequestError } from '../core/api-errors.js';
|
|
15
5
|
import { DIGEST_DISPLAY_CHARS } from '../util/token-text.js';
|
|
16
|
-
/**
|
|
17
|
-
*
|
|
18
|
-
* lowercase → collapse whitespace runs to a single space → trim. No
|
|
19
|
-
* punctuation stripping — over-normalization creates false refusals, which
|
|
20
|
-
* are worse than misses (plan §1).
|
|
21
|
-
*/
|
|
6
|
+
/** Normalize content for rejection digests: NFC, lowercase, collapse whitespace runs, trim. No punctuation stripping: over-normalizing causes false
|
|
7
|
+
* refusals, worse than misses. */
|
|
22
8
|
export function normalizeValueForRejection(content) {
|
|
23
9
|
return content.normalize('NFC').toLowerCase().replace(/\s+/g, ' ').trim();
|
|
24
10
|
}
|
|
25
|
-
/**
|
|
26
|
-
* Full sha256 hex (64 chars) of the normalized content. Reuses the strong-
|
|
27
|
-
* identity convention (importers.ts:814 content-hash tag), NOT the privacy-
|
|
28
|
-
* lossy 16-char convention (recall-trace query hashing) — a tombstone lookup
|
|
29
|
-
* key needs collision resistance, not redaction (plan §1).
|
|
30
|
-
*/
|
|
11
|
+
/** Full 64-char sha256 hex of the normalized content: a tombstone key needs collision resistance, not the 16-char redaction hash used for query hashing. */
|
|
31
12
|
export function rejectionDigest(content) {
|
|
32
13
|
return createHash('sha256').update(normalizeValueForRejection(content)).digest('hex');
|
|
33
14
|
}
|
|
34
|
-
/**
|
|
35
|
-
*
|
|
36
|
-
* upsertEntryRow) when an incoming write would introduce a value matching a
|
|
37
|
-
* tombstoned digest. Carries enough context for the transaction-owner catch
|
|
38
|
-
* blocks (writeEntry, api.supersede) to write a post-rollback
|
|
39
|
-
* `reject_refusal` audit row via `auditRejectionRefusal` (plan §3).
|
|
40
|
-
*/
|
|
15
|
+
/** Thrown by the write-path guard (checkRejectionGuard, via upsertEntryRow) when a write would introduce a tombstoned value; carries what the
|
|
16
|
+
* transaction-owner catch blocks (writeEntry, api.supersede) need to write the post-rollback `reject_refusal` audit row via `auditRejectionRefusal`. */
|
|
41
17
|
export class RejectedValueError extends BadRequestError {
|
|
42
18
|
digest;
|
|
43
19
|
tenantId;
|
|
@@ -66,10 +42,7 @@ function rowToRejectedValue(row) {
|
|
|
66
42
|
normalizedChars: row.normalized_chars,
|
|
67
43
|
};
|
|
68
44
|
}
|
|
69
|
-
/**
|
|
70
|
-
* Look up a tombstone by tenant + digest. One indexed point query — the
|
|
71
|
-
* guard's common-case cost, a miss ends the guard (plan §3).
|
|
72
|
-
*/
|
|
45
|
+
/** Look up a tombstone by tenant + digest: one indexed point query, the guard's common-case cost; a miss ends the guard. */
|
|
73
46
|
export function findRejectedValue(db, tenantId, digest) {
|
|
74
47
|
// SAFETY: row's shape matches the columns named in the SELECT above.
|
|
75
48
|
const row = db
|
|
@@ -78,10 +51,7 @@ export function findRejectedValue(db, tenantId, digest) {
|
|
|
78
51
|
.get(tenantId, digest);
|
|
79
52
|
return row ? rowToRejectedValue(row) : null;
|
|
80
53
|
}
|
|
81
|
-
/**
|
|
82
|
-
* Insert (or refresh) a tombstone row. Caller owns the transaction — used by
|
|
83
|
-
* the `reject` verb and `resolveConflict`'s `rejectLoserValue` path.
|
|
84
|
-
*/
|
|
54
|
+
/** Insert (or refresh) a tombstone row; the caller owns the transaction (used by the `reject` verb and `resolveConflict`'s `rejectLoserValue`). */
|
|
85
55
|
export function insertRejectedValue(db, opts) {
|
|
86
56
|
db.prepare(`INSERT INTO rejected_values(tenant_id, digest, reason, rejected_by, rejected_at, source_memory_id, normalized_chars)
|
|
87
57
|
VALUES (?, ?, ?, ?, ?, ?, ?)
|
|
@@ -92,10 +62,7 @@ export function insertRejectedValue(db, opts) {
|
|
|
92
62
|
source_memory_id = excluded.source_memory_id,
|
|
93
63
|
normalized_chars = excluded.normalized_chars`).run(opts.tenantId, opts.digest, opts.reason, opts.rejectedBy, opts.rejectedAt, opts.sourceMemoryId ?? null, opts.normalizedChars);
|
|
94
64
|
}
|
|
95
|
-
/**
|
|
96
|
-
* Delete a tombstone by tenant + exact digest: the `unreject` verb, the
|
|
97
|
-
* only escape hatch.
|
|
98
|
-
*/
|
|
65
|
+
/** Delete a tombstone by tenant + exact digest: the `unreject` verb, the only escape hatch. */
|
|
99
66
|
export function deleteRejectedValue(db, tenantId, digest) {
|
|
100
67
|
const result = db.prepare(`DELETE FROM rejected_values WHERE tenant_id = ? AND digest = ?`).run(tenantId, digest);
|
|
101
68
|
return (result.changes ?? 0) > 0;
|
|
@@ -109,33 +76,14 @@ export function listRejectedValues(db, tenantId) {
|
|
|
109
76
|
.all(tenantId);
|
|
110
77
|
return rows.map(rowToRejectedValue);
|
|
111
78
|
}
|
|
112
|
-
/**
|
|
113
|
-
*
|
|
114
|
-
* (store.ts). Fires when the incoming content's digest matches a tombstone
|
|
115
|
-
* AND the write *introduces* that content: the row is new, OR the stored
|
|
116
|
-
* row's content digest differs from the incoming one — an UPSERT editing a
|
|
117
|
-
* same-id row TO a rejected value is a content introduction and must be
|
|
118
|
-
* refused. Unchanged same-id re-persists (recall boost, decay, star toggle)
|
|
119
|
-
* are exempt by construction (plan §3).
|
|
120
|
-
*
|
|
121
|
-
* Ordering minimizes queries on the common (miss) path: (a) caller has
|
|
122
|
-
* already computed nothing yet — this does the digest + point lookup first;
|
|
123
|
-
* (b) a miss returns immediately (ONE indexed point query); (c) only on a
|
|
124
|
-
* tombstone hit does it SELECT the stored row's content to classify
|
|
125
|
-
* new-row vs content-introduction (+1 query, rare path).
|
|
126
|
-
*/
|
|
79
|
+
/** Write-path guard check: fires when the digest matches a tombstone AND the write introduces that content (a new row, or a same-id UPSERT changing it).
|
|
80
|
+
* Unchanged same-id re-persists (recall boost, decay, star toggle) are exempt. A miss costs ONE indexed point query; only a hit SELECTs the stored row. */
|
|
127
81
|
export function checkRejectionGuard(db, tenantId, entryId, content) {
|
|
128
82
|
const incomingDigest = rejectionDigest(content);
|
|
129
83
|
const tombstone = findRejectedValue(db, tenantId, incomingDigest);
|
|
130
84
|
if (!tombstone)
|
|
131
85
|
return; // miss ends the guard — the overwhelmingly common case
|
|
132
|
-
//
|
|
133
|
-
// ULIDs, this lookup only classifies new-row vs same-id re-persist for the
|
|
134
|
-
// id the caller is already writing, and the tombstone lookup above is the
|
|
135
|
-
// tenant-scoped decision. Matches deleteEntry's own by-id SELECT.
|
|
136
|
-
//
|
|
137
|
-
// Also read tenant_id: a same-id upsert that only changes tenantId introduces the
|
|
138
|
-
// content into the destination tenant, exactly as if the row were new there.
|
|
86
|
+
// Id-only on purpose (ids are global ULIDs; the tombstone lookup is tenant-scoped); tenant_id is read as a tenantId-only upsert introduces content there.
|
|
139
87
|
// SAFETY: storedRow's shape matches the two columns named in the SELECT above.
|
|
140
88
|
const storedRow = db.prepare(`SELECT content, tenant_id FROM memories WHERE id = ?`).get(entryId);
|
|
141
89
|
const isNewRow = storedRow === undefined;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { MemoryEntry } from '../core/memory.js';
|
|
2
|
+
/** Every superseded row, the row that replaced it and that row's extraction source, in loadAllEntries' order: all a correction-latency report reads. */
|
|
3
|
+
export declare function loadCorrectionEntries(hippoRoot: string): MemoryEntry[];
|
|
4
|
+
/** The kind='raw' rows in loadAllEntries' order: all a provenance-coverage report reads. */
|
|
5
|
+
export declare function loadRawEntries(hippoRoot: string): MemoryEntry[];
|
|
6
|
+
//# sourceMappingURL=report-reads.d.ts.map
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { MEMORY_SELECT_COLUMNS, rowToEntry } from './rows.js';
|
|
2
|
+
import { onHandle, openStore } from './open.js';
|
|
3
|
+
/** Every superseded row, the row that replaced it and that row's extraction source, in loadAllEntries' order: all a correction-latency report reads. */
|
|
4
|
+
export function loadCorrectionEntries(hippoRoot) {
|
|
5
|
+
return onHandle(hippoRoot, (db) => {
|
|
6
|
+
const superseded = `superseded_by IS NOT NULL AND superseded_by != ''`;
|
|
7
|
+
// SAFETY: selects exactly MEMORY_SELECT_COLUMNS, matching MemoryRow's field set.
|
|
8
|
+
const rows = db.prepare(`
|
|
9
|
+
SELECT ${MEMORY_SELECT_COLUMNS} FROM memories
|
|
10
|
+
WHERE (${superseded})
|
|
11
|
+
OR id IN (SELECT superseded_by FROM memories WHERE ${superseded})
|
|
12
|
+
OR id IN (
|
|
13
|
+
SELECT extracted_from FROM memories
|
|
14
|
+
WHERE extracted_from IS NOT NULL AND id IN (SELECT superseded_by FROM memories WHERE ${superseded})
|
|
15
|
+
)
|
|
16
|
+
ORDER BY created ASC, id ASC
|
|
17
|
+
`).all();
|
|
18
|
+
return rows.map(rowToEntry);
|
|
19
|
+
}, openStore);
|
|
20
|
+
}
|
|
21
|
+
/** The kind='raw' rows in loadAllEntries' order: all a provenance-coverage report reads. */
|
|
22
|
+
export function loadRawEntries(hippoRoot) {
|
|
23
|
+
return onHandle(hippoRoot, (db) => {
|
|
24
|
+
// SAFETY: selects exactly MEMORY_SELECT_COLUMNS, matching MemoryRow's field set.
|
|
25
|
+
const rows = db.prepare(`SELECT ${MEMORY_SELECT_COLUMNS} FROM memories WHERE kind = 'raw' ORDER BY created ASC, id ASC`).all();
|
|
26
|
+
return rows.map(rowToEntry);
|
|
27
|
+
}, openStore);
|
|
28
|
+
}
|
|
29
|
+
//# sourceMappingURL=report-reads.js.map
|
package/dist/store/rows.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { Layer, type MemoryEntry, type ConfidenceLevel } from '../core/memory.js';
|
|
2
2
|
import { type JsonValue } from '../util/json.js';
|
|
3
|
+
import { type StoredJsonSite } from '../util/stored-json.js';
|
|
3
4
|
export interface IndexEntry {
|
|
4
5
|
id: string;
|
|
5
6
|
file: string;
|
|
@@ -134,27 +135,16 @@ export interface SessionEvent {
|
|
|
134
135
|
created_at: string;
|
|
135
136
|
}
|
|
136
137
|
export declare const INDEX_VERSION = 3;
|
|
137
|
-
export declare const MEMORY_SELECT_COLUMNS
|
|
138
|
-
export declare const MEMORY_SEARCH_COLUMNS
|
|
139
|
-
/**
|
|
140
|
-
*
|
|
141
|
-
* `limit === undefined`. Single source of truth; `api.recall` imports
|
|
142
|
-
* this for `RecallResult.windowSize` reporting so the two cannot drift.
|
|
143
|
-
*/
|
|
138
|
+
export declare const MEMORY_SELECT_COLUMNS: string;
|
|
139
|
+
export declare const MEMORY_SEARCH_COLUMNS: string;
|
|
140
|
+
/** Default candidate-pool size for `loadSearchEntries` when `limit` is undefined; `api.recall` imports it for `RecallResult.windowSize` so the two cannot
|
|
141
|
+
* drift. */
|
|
144
142
|
export declare const DEFAULT_SEARCH_CANDIDATE_LIMIT = 200;
|
|
145
143
|
export declare function rowToEntry(row: MemoryRow): MemoryEntry;
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
*
|
|
150
|
-
* usable-looking 0/NaN — a consumer INSERTing recall_trace_outcomes with
|
|
151
|
-
* trace_id=0 would hit a masked FK violation (row id 0 never exists).
|
|
152
|
-
* Require a clean positive integer string; anything else is treated as
|
|
153
|
-
* unset. This is the ONE place that decides "clean" — every consumer of
|
|
154
|
-
* `HippoIndex.last_trace_id` (outcomeForLastRecall, tests) reads the
|
|
155
|
-
* already-validated value out of `buildIndexFromDb`'s result and never
|
|
156
|
-
* re-parses the raw meta string itself.
|
|
157
|
-
*/
|
|
144
|
+
/** A column that is not JSON reads as empty. With `site` the row is named at warn once; without it no row is known and the line stays at debug. */
|
|
145
|
+
export declare function parseJsonArray(raw: string | null | undefined, site?: StoredJsonSite): string[];
|
|
146
|
+
/** Strict parse for `last_trace_id`: Number(raw) turns '' or garbage into 0/NaN (a masked FK violation); require a clean positive integer string, else unset.
|
|
147
|
+
* The ONE place that decides 'clean'; consumers read the validated value from `buildIndexFromDb`'s result and never re-parse. */
|
|
158
148
|
export declare function parseLastTraceId(raw: string | null | undefined): string | null;
|
|
159
149
|
export declare function rowToTaskSnapshot(row: TaskSnapshotRow): TaskSnapshot;
|
|
160
150
|
export declare function rowToMemoryConflict(row: MemoryConflictRow): MemoryConflict;
|
package/dist/store/rows.js
CHANGED
|
@@ -1,22 +1,29 @@
|
|
|
1
|
+
import { DEFAULT_TENANT_ID } from '../util/env.js';
|
|
1
2
|
import { FALLBACK_HALF_LIFE_DAYS, DEFAULT_SCHEMA_FIT } from '../core/memory.js';
|
|
2
3
|
import { errorMessage, log } from '../util/log.js';
|
|
3
4
|
import { isJsonObject } from '../util/json.js';
|
|
5
|
+
import { warnDamagedColumn } from '../util/stored-json.js';
|
|
4
6
|
export const INDEX_VERSION = 3;
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
7
|
+
const MEMORY_COLUMN_NAMES = [
|
|
8
|
+
'id', 'created', 'last_retrieved', 'retrieval_count', 'strength', 'half_life_days', 'layer', 'tags_json',
|
|
9
|
+
'emotional_valence', 'schema_fit', 'source', 'outcome_score', 'outcome_positive', 'outcome_negative',
|
|
10
|
+
'conflicts_with_json', 'pinned', 'confidence', 'content', 'parents_json', 'starred', 'trace_outcome',
|
|
11
|
+
'source_session_id', 'valid_from', 'superseded_by', 'extracted_from', 'dag_level', 'dag_parent_id', 'kind', 'scope',
|
|
12
|
+
'owner', 'artifact_ref', 'tenant_id', 'origin_project', 'descendant_count', 'earliest_at', 'latest_at',
|
|
13
|
+
'summary_dirty', 'last_rebuilt_at', 'rebuild_count', 'dag_level_3_built_at',
|
|
14
|
+
];
|
|
15
|
+
// FTS-join columns for loadSearchRows: `m.<col> AS <col>` keeps rowToEntry's unqualified reads working.
|
|
16
|
+
export const MEMORY_SELECT_COLUMNS = MEMORY_COLUMN_NAMES.join(', ');
|
|
17
|
+
export const MEMORY_SEARCH_COLUMNS = [
|
|
18
|
+
...MEMORY_COLUMN_NAMES.map((c) => `m.${c} AS ${c}`),
|
|
19
|
+
'bm25(memories_fts) AS bm25_score',
|
|
20
|
+
].join(', ');
|
|
21
|
+
/** Default candidate-pool size for `loadSearchEntries` when `limit` is undefined; `api.recall` imports it for `RecallResult.windowSize` so the two cannot
|
|
22
|
+
* drift. */
|
|
14
23
|
export const DEFAULT_SEARCH_CANDIDATE_LIMIT = 200;
|
|
15
24
|
function rowToRetrievalFields(row) {
|
|
16
|
-
// SAFETY: every `as X`
|
|
17
|
-
//
|
|
18
|
-
// / MEMORY_SEARCH_COLUMNS, which are the only queries producing MemoryRow,
|
|
19
|
-
// and the DB layer only ever writes these columns from the same enums.
|
|
25
|
+
// SAFETY: every `as X` narrows a SQLite column to a MemoryEntry enum/union member; `row` comes from MEMORY_SELECT_COLUMNS / MEMORY_SEARCH_COLUMNS,
|
|
26
|
+
// the only queries producing MemoryRow, and the DB layer writes these columns only from the same enums.
|
|
20
27
|
return {
|
|
21
28
|
id: row.id,
|
|
22
29
|
created: row.created,
|
|
@@ -25,18 +32,18 @@ function rowToRetrievalFields(row) {
|
|
|
25
32
|
strength: Number(row.strength ?? 1),
|
|
26
33
|
half_life_days: Number(row.half_life_days ?? FALLBACK_HALF_LIFE_DAYS),
|
|
27
34
|
layer: row.layer,
|
|
28
|
-
tags: parseJsonArray(row.tags_json),
|
|
35
|
+
tags: parseJsonArray(row.tags_json, { table: 'memories', id: row.id, column: 'tags_json' }),
|
|
29
36
|
emotional_valence: row.emotional_valence ?? 'neutral',
|
|
30
37
|
schema_fit: Number(row.schema_fit ?? DEFAULT_SCHEMA_FIT),
|
|
31
38
|
source: row.source ?? 'cli',
|
|
32
39
|
outcome_score: row.outcome_score === null || row.outcome_score === undefined ? null : Number(row.outcome_score),
|
|
33
40
|
outcome_positive: Number(row.outcome_positive ?? 0),
|
|
34
41
|
outcome_negative: Number(row.outcome_negative ?? 0),
|
|
35
|
-
conflicts_with: parseJsonArray(row.conflicts_with_json),
|
|
42
|
+
conflicts_with: parseJsonArray(row.conflicts_with_json, { table: 'memories', id: row.id, column: 'conflicts_with_json' }),
|
|
36
43
|
pinned: Boolean(row.pinned),
|
|
37
44
|
confidence: row.confidence ?? 'observed',
|
|
38
45
|
content: row.content,
|
|
39
|
-
parents: parseJsonArray(row.parents_json),
|
|
46
|
+
parents: parseJsonArray(row.parents_json, { table: 'memories', id: row.id, column: 'parents_json' }),
|
|
40
47
|
starred: Boolean(row.starred),
|
|
41
48
|
trace_outcome: row.trace_outcome ?? null,
|
|
42
49
|
};
|
|
@@ -54,7 +61,7 @@ function rowToPlacementFields(row) {
|
|
|
54
61
|
scope: row.scope ?? null,
|
|
55
62
|
owner: row.owner ?? null,
|
|
56
63
|
artifact_ref: row.artifact_ref ?? null,
|
|
57
|
-
tenantId: row.tenant_id ??
|
|
64
|
+
tenantId: row.tenant_id ?? DEFAULT_TENANT_ID,
|
|
58
65
|
origin_project: row.origin_project ?? null,
|
|
59
66
|
descendant_count: Number(row.descendant_count ?? 0),
|
|
60
67
|
earliest_at: row.earliest_at ?? null,
|
|
@@ -74,7 +81,8 @@ export function rowToEntry(row) {
|
|
|
74
81
|
}
|
|
75
82
|
return entry;
|
|
76
83
|
}
|
|
77
|
-
|
|
84
|
+
/** A column that is not JSON reads as empty. With `site` the row is named at warn once; without it no row is known and the line stays at debug. */
|
|
85
|
+
export function parseJsonArray(raw, site) {
|
|
78
86
|
if (!raw)
|
|
79
87
|
return [];
|
|
80
88
|
try {
|
|
@@ -82,28 +90,22 @@ export function parseJsonArray(raw) {
|
|
|
82
90
|
return Array.isArray(parsed) ? parsed.map((item) => String(item)) : [];
|
|
83
91
|
}
|
|
84
92
|
catch (err) {
|
|
85
|
-
|
|
93
|
+
if (site)
|
|
94
|
+
warnDamagedColumn(site, 'not valid JSON');
|
|
95
|
+
else
|
|
96
|
+
log.debug(`store: corrupt JSON array column read as empty: ${errorMessage(err)}`);
|
|
86
97
|
return [];
|
|
87
98
|
}
|
|
88
99
|
}
|
|
89
|
-
/**
|
|
90
|
-
*
|
|
91
|
-
* A bare Number(raw) would turn '', whitespace, or garbage into a
|
|
92
|
-
* usable-looking 0/NaN — a consumer INSERTing recall_trace_outcomes with
|
|
93
|
-
* trace_id=0 would hit a masked FK violation (row id 0 never exists).
|
|
94
|
-
* Require a clean positive integer string; anything else is treated as
|
|
95
|
-
* unset. This is the ONE place that decides "clean" — every consumer of
|
|
96
|
-
* `HippoIndex.last_trace_id` (outcomeForLastRecall, tests) reads the
|
|
97
|
-
* already-validated value out of `buildIndexFromDb`'s result and never
|
|
98
|
-
* re-parses the raw meta string itself.
|
|
99
|
-
*/
|
|
100
|
+
/** Strict parse for `last_trace_id`: Number(raw) turns '' or garbage into 0/NaN (a masked FK violation); require a clean positive integer string, else unset.
|
|
101
|
+
* The ONE place that decides 'clean'; consumers read the validated value from `buildIndexFromDb`'s result and never re-parse. */
|
|
100
102
|
export function parseLastTraceId(raw) {
|
|
101
103
|
const trimmed = (raw ?? '').trim();
|
|
102
104
|
if (!/^\d+$/.test(trimmed) || Number(trimmed) <= 0)
|
|
103
105
|
return null;
|
|
104
106
|
return trimmed;
|
|
105
107
|
}
|
|
106
|
-
function parseJsonObject(raw) {
|
|
108
|
+
function parseJsonObject(raw, site) {
|
|
107
109
|
if (!raw)
|
|
108
110
|
return {};
|
|
109
111
|
try {
|
|
@@ -113,8 +115,8 @@ function parseJsonObject(raw) {
|
|
|
113
115
|
}
|
|
114
116
|
return {};
|
|
115
117
|
}
|
|
116
|
-
catch
|
|
117
|
-
|
|
118
|
+
catch {
|
|
119
|
+
warnDamagedColumn(site, 'not valid JSON');
|
|
118
120
|
return {};
|
|
119
121
|
}
|
|
120
122
|
}
|
|
@@ -153,7 +155,7 @@ export function rowToSessionEvent(row) {
|
|
|
153
155
|
content: row.content,
|
|
154
156
|
source: row.source,
|
|
155
157
|
scope: row.scope ?? null,
|
|
156
|
-
metadata: parseJsonObject(row.metadata_json),
|
|
158
|
+
metadata: parseJsonObject(row.metadata_json, { table: 'session_events', id: row.id, column: 'metadata_json' }),
|
|
157
159
|
created_at: row.created_at,
|
|
158
160
|
};
|
|
159
161
|
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
/** calculateStrength's clock-basis formula as SQL over `memories` columns, flags and multipliers baked in; keep in step.
|
|
2
|
+
* An unparseable date scores NULL here and 0 in JS, so sums agree. */
|
|
3
|
+
export declare function strengthSql(now: Date): string;
|
|
4
|
+
export declare const AUTO_DELETABLE_SQL: string;
|
|
5
|
+
//# sourceMappingURL=rule-sql.d.ts.map
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
// The SQL twins of the model's strength and keep rules (src/core/memory.ts); keep in step with calculateStrength and canAutoDelete.
|
|
2
|
+
import { DAY_MS } from '../util/time.js';
|
|
3
|
+
import { isDecayAblated, isOutcomeSlowAblated, isRecallBoostAblated } from '../core/ablation.js';
|
|
4
|
+
import { DECAY_BASE, EMOTIONAL_MULTIPLIERS, FALLBACK_HALF_LIFE_DAYS, KEEP_PAIRS, MAX_WRONG_HALVINGS, RETRIEVAL_BOOST_SLOPE, REWARD_SLOPE, applyLossAversionRatio, } from '../core/memory.js';
|
|
5
|
+
const UNIX_EPOCH_JULIAN_DAY = 2440587.5;
|
|
6
|
+
/** calculateStrength's clock-basis formula as SQL over `memories` columns, flags and multipliers baked in; keep in step.
|
|
7
|
+
* An unparseable date scores NULL here and 0 in JS, so sums agree. */
|
|
8
|
+
export function strengthSql(now) {
|
|
9
|
+
const num = (n) => (Number.isInteger(n) ? n.toFixed(1) : String(n));
|
|
10
|
+
const pos = 'COALESCE(outcome_positive, 0)';
|
|
11
|
+
const neg = 'COALESCE(outcome_negative, 0)';
|
|
12
|
+
const wrong = isOutcomeSlowAblated() || isDecayAblated() ? '0' : `MAX(0, ${neg} - ${pos})`;
|
|
13
|
+
const reward = isOutcomeSlowAblated()
|
|
14
|
+
? '1.0'
|
|
15
|
+
: `(CASE WHEN ${pos} = 0 AND ${neg} = 0 THEN 1.0 ELSE 1.0 + ${REWARD_SLOPE} * (${pos} - ${neg}) / (${pos} + ${neg} + 1.0) END)`;
|
|
16
|
+
const halfLife = `(COALESCE(half_life_days, ${FALLBACK_HALF_LIFE_DAYS}) * ${reward})`;
|
|
17
|
+
const anchor = isRecallBoostAblated() ? 'created' : 'last_retrieved';
|
|
18
|
+
const nowJulian = num(now.getTime() / DAY_MS + UNIX_EPOCH_JULIAN_DAY);
|
|
19
|
+
const decay = isDecayAblated() ? '1.0' : `pow(${DECAY_BASE}, (${nowJulian} - julianday(${anchor})) / ${halfLife})`;
|
|
20
|
+
const boost = isRecallBoostAblated()
|
|
21
|
+
? '1.0'
|
|
22
|
+
: `(CASE WHEN ${wrong} > 0 THEN 1.0 ELSE 1.0 + ${RETRIEVAL_BOOST_SLOPE} * log2(COALESCE(retrieval_count, 0) + 1) END)`;
|
|
23
|
+
const valences = /* SAFETY: a Record keyed by EmotionalValence */ Object.keys(EMOTIONAL_MULTIPLIERS);
|
|
24
|
+
const emotion = `(CASE COALESCE(emotional_valence, 'neutral') ${valences
|
|
25
|
+
.map((v) => `WHEN '${v}' THEN ${num(applyLossAversionRatio(v, EMOTIONAL_MULTIPLIERS[v]))}`)
|
|
26
|
+
.join(' ')} ELSE 1.0 END)`;
|
|
27
|
+
const penalty = `pow(${DECAY_BASE}, MIN(${wrong}, ${MAX_WRONG_HALVINGS}))`;
|
|
28
|
+
return `(CASE WHEN pinned THEN ${penalty} WHEN ${halfLife} <= 0 THEN 0.0
|
|
29
|
+
ELSE MIN(1.0, MAX(0.0, ${decay} * ${boost} * ${emotion})) * ${penalty} END)`;
|
|
30
|
+
}
|
|
31
|
+
const sqlText = (s) => `'${s.replace(/'/g, "''")}'`;
|
|
32
|
+
// json_each matches the tag as a whole element; substr, not LIKE, keeps the prefix case-sensitive like startsWith.
|
|
33
|
+
const keepPairSql = (p) => `(COALESCE(superseded_by, '') = '' AND EXISTS (SELECT 1 FROM json_each(CASE WHEN json_valid(tags_json) THEN tags_json ELSE '[]' END) WHERE value = ${sqlText(p.tag)}) AND substr(source, 1, ${p.sourcePrefix.length}) = ${sqlText(p.sourcePrefix)})`;
|
|
34
|
+
// Pinned and kept rows stay (a superseded row is not kept: its successor carries the tag and
|
|
35
|
+
// source); raw rows leave only through archiveRawMemory. The SQL twin guards the DELETE itself.
|
|
36
|
+
export const AUTO_DELETABLE_SQL = `pinned = 0 AND kind != 'raw'${KEEP_PAIRS.map((p) => ` AND NOT ${keepPairSql(p)}`).join('')}`;
|
|
37
|
+
//# sourceMappingURL=rule-sql.js.map
|
|
@@ -1,18 +1,7 @@
|
|
|
1
1
|
import type { MemoryEntry } from '../core/memory.js';
|
|
2
2
|
import { type DatabaseSyncLike } from '../db/index.js';
|
|
3
|
-
/**
|
|
4
|
-
*
|
|
5
|
-
* - 'default-deny': exclude scopes in `RECALL_DEFAULT_DENY_SCOPES`.
|
|
6
|
-
* - 'exact': exact match on `m.scope = value` (api.recall's explicit-scope request semantics).
|
|
7
|
-
* - 'default-deny-or-exact': the default-admitted set PLUS rows whose scope equals `value` (CLI `--scope`).
|
|
8
|
-
* The flag began as a tag-boost hint, so narrowing would return zero rows for tag-scoped workflows.
|
|
9
|
-
*
|
|
10
|
-
* Background pipelines (`consolidate`, `embeddings`, `refine-llm`, ...) call
|
|
11
|
-
* `loadSearchEntries` (no scopeFilter arg) and see all rows including
|
|
12
|
-
* quarantine.
|
|
13
|
-
*/
|
|
14
|
-
/** @internal Internal SQL-builder shape; not on the public API
|
|
15
|
-
* surface (not re-exported from `src/index.ts`). Subject to change. */
|
|
3
|
+
/** Recall scope filter: 'default-deny' (exclude RECALL_DEFAULT_DENY_SCOPES), 'exact' (m.scope = value), 'default-deny-or-exact' (both; CLI `--scope`).
|
|
4
|
+
* @internal Internal SQL-builder shape; not re-exported from `src/index.ts`. Subject to change. */
|
|
16
5
|
export type RecallScopeFilter = {
|
|
17
6
|
mode: 'default-deny';
|
|
18
7
|
ownScope?: string;
|
|
@@ -26,35 +15,15 @@ export type RecallScopeFilter = {
|
|
|
26
15
|
};
|
|
27
16
|
/** One project name, or every name a project's rows carry. */
|
|
28
17
|
export type OriginFilter = string | readonly string[];
|
|
29
|
-
/** Scope rule for recall: none requested is default-deny; 'exact' narrows to the request; 'additive' adds it to the default set, unless it is personal,
|
|
18
|
+
/** Scope rule for recall: none requested is default-deny; 'exact' narrows to the request; 'additive' adds it to the default set, unless it is personal,
|
|
19
|
+
* which only `ownScope` opens. */
|
|
30
20
|
export declare function recallScopeFilter(requestedScope: string | undefined, mode: 'exact' | 'additive', ownScope?: string): RecallScopeFilter;
|
|
31
21
|
/** Sends term queries down the LIKE path on a build that has FTS. Only tests call it. */
|
|
32
22
|
export declare function _forceLikePathForTests(on: boolean): void;
|
|
33
|
-
/**
|
|
34
|
-
* Load likely search candidates directly from SQLite.
|
|
35
|
-
* Uses FTS5 when available, falls back to LIKE matching, then full-store fallback.
|
|
36
|
-
*
|
|
37
|
-
* When `tenantId` is provided, every SELECT (FTS join, LIKE, fallback) filters
|
|
38
|
-
* by tenant_id. Cross-tenant memories never surface. Omitted = no filter.
|
|
39
|
-
*/
|
|
23
|
+
/** Load likely search candidates: FTS5 when available, else LIKE, then full-store fallback. With `tenantId` every SELECT filters by it; omitted = no filter. */
|
|
40
24
|
export declare function loadSearchEntries(hippoRoot: string, query: string, limit?: number, tenantId?: string): MemoryEntry[];
|
|
41
|
-
/**
|
|
42
|
-
*
|
|
43
|
-
* `unknown:legacy` cannot leak via any consumer that hasn't remembered to re-filter.
|
|
44
|
-
*
|
|
45
|
-
* - `requestedScope` undefined / '': default-deny on `unknown:legacy`, admitting `ownScope`, the caller's personal scope.
|
|
46
|
-
* - `requestedScope` non-empty string: exact match on `m.scope = requestedScope`.
|
|
47
|
-
*
|
|
48
|
-
* Private scopes: SQL applies a conservative `NOT LIKE '%:private:%'` before the LIMIT window so private
|
|
49
|
-
* rows cannot starve admitted ones; `passesScopeFilterForRecall` stays the exact JS post-filter.
|
|
50
|
-
*
|
|
51
|
-
* Consumers: `api.recall`, `cmdRecall`/`cmdExplain` direct CLI paths
|
|
52
|
-
* and `searchBothHybrid` recall mode. Background pipelines
|
|
53
|
-
* (`consolidate`, `embeddings`, `refine-llm`, ...) keep using
|
|
54
|
-
* `loadSearchEntries` so they can see quarantined rows when needed.
|
|
55
|
-
*
|
|
56
|
-
* `tenantId` is optional because searchBothHybrid's is; undefined means no tenant filter.
|
|
57
|
-
*/
|
|
25
|
+
/** Recall-mode loader: scope predicate in SQL so `unknown:legacy` cannot leak. Empty `requestedScope` default-denies (admits `ownScope`); else exact match.
|
|
26
|
+
* SQL `NOT LIKE '%:private:%'` runs before the LIMIT so private rows cannot starve admitted ones; `passesScopeFilterForRecall` is the exact post-filter. */
|
|
58
27
|
export declare function loadRecallSearchEntries(hippoRoot: string, query: string, limit?: number, tenantId?: string, requestedScope?: string, explicitScopeMode?: 'exact' | 'additive', includeSuperseded?: boolean, originProjects?: OriginFilter, ownScope?: string): MemoryEntry[];
|
|
59
28
|
export interface RecallSearchEntriesOptions {
|
|
60
29
|
readonly limit?: number;
|
|
@@ -6,7 +6,7 @@ import { errorMessage, log } from '../util/log.js';
|
|
|
6
6
|
import { originInSql } from '../core/project-identity.js';
|
|
7
7
|
import { topVectorMatches } from '../db/vector-store.js';
|
|
8
8
|
import { MEMORY_SELECT_COLUMNS, MEMORY_SEARCH_COLUMNS, DEFAULT_SEARCH_CANDIDATE_LIMIT, rowToEntry, } from './rows.js';
|
|
9
|
-
import { openStore } from './open.js';
|
|
9
|
+
import { onHandle, openStore } from './open.js';
|
|
10
10
|
import { escapeLike } from '../util/escape.js';
|
|
11
11
|
/** The recall scope rule for a table column prefix (`m.` or none); `passesScopeFilterForRecall` in recall-scope.ts is its JS twin. */
|
|
12
12
|
function recallScopeClause(col, scopeFilter) {
|
|
@@ -28,7 +28,8 @@ function withProject(scope, col, origin) {
|
|
|
28
28
|
const originProjects = [origin].flat();
|
|
29
29
|
return { sql: `${scope.sql} AND (${col}origin_project = '' OR ${originInSql(originProjects, `${col}origin_project`)})`, params: [...scope.params, ...originProjects] };
|
|
30
30
|
}
|
|
31
|
-
/** Scope rule for recall: none requested is default-deny; 'exact' narrows to the request; 'additive' adds it to the default set, unless it is personal,
|
|
31
|
+
/** Scope rule for recall: none requested is default-deny; 'exact' narrows to the request; 'additive' adds it to the default set, unless it is personal,
|
|
32
|
+
* which only `ownScope` opens. */
|
|
32
33
|
export function recallScopeFilter(requestedScope, mode, ownScope) {
|
|
33
34
|
if (!requestedScope || (mode === 'additive' && isPersonalScope(requestedScope)))
|
|
34
35
|
return { mode: 'default-deny', ownScope };
|
|
@@ -62,19 +63,14 @@ function loadSearchRows(db, query, limit, tenantId, options = {}) {
|
|
|
62
63
|
return selectAllCandidates(db, p, limit);
|
|
63
64
|
}
|
|
64
65
|
function searchPredicates(tenantId, scopeFilter, includeSuperseded, originProjects) {
|
|
65
|
-
// tenantId undefined = no tenant filter (legacy callers / cross-deployment
|
|
66
|
-
// helpers). tenantId set = strict tenant isolation, leveraging the composite
|
|
67
|
-
// idx_memories_tenant_created (leading column tenant_id, O(log n) lookup).
|
|
66
|
+
// tenantId undefined = no tenant filter (legacy callers / cross-deployment helpers); set = strict isolation via the composite idx_memories_tenant_created.
|
|
68
67
|
const tenantPredicate = tenantId !== undefined ? ` AND m.tenant_id = ?` : '';
|
|
69
68
|
const tenantOnlyPredicate = tenantId !== undefined ? ` WHERE tenant_id = ?` : '';
|
|
70
69
|
const tenantParams = tenantId !== undefined ? [tenantId] : [];
|
|
71
70
|
// Defensive: kind='archived' is a transient sentinel inside archiveRawMemory's SAVEPOINT, so this only
|
|
72
71
|
// guards against a dropped SAVEPOINT, a persisted 'archived' state, or direct-SQL writes.
|
|
73
72
|
const archivedClauseAlias = ` AND m.kind != 'archived'`;
|
|
74
|
-
//
|
|
75
|
-
// so prepend WHERE; if tenant set, append AND. handled in each call site
|
|
76
|
-
// by always joining `tenantOnlyPredicate + archivedClauseTenantOnly` where
|
|
77
|
-
// the latter switches between " AND" and " WHERE" based on caller context.
|
|
73
|
+
// Tenant-only path: with no tenant `tenantOnlyPredicate` is '', so the archived clause switches between ' AND' and ' WHERE' by caller context.
|
|
78
74
|
const archivedClauseTenantOnly = tenantId !== undefined ? ` AND kind != 'archived'` : ` WHERE kind != 'archived'`;
|
|
79
75
|
const aliasScope = withProject(recallScopeClause('m.', scopeFilter), 'm.', originProjects);
|
|
80
76
|
const plainScope = withProject(recallScopeClause('', scopeFilter), '', originProjects);
|
|
@@ -98,11 +94,8 @@ function selectAllCandidates(db, p, limit) {
|
|
|
98
94
|
function selectFtsCandidates(db, terms, p, limit) {
|
|
99
95
|
try {
|
|
100
96
|
const ftsQuery = terms.map((t) => `"${t.replace(/"/g, '""')}"`).join(' OR ');
|
|
101
|
-
// memories_fts
|
|
102
|
-
//
|
|
103
|
-
// on tenant_id).
|
|
104
|
-
// SAFETY: MEMORY_SEARCH_COLUMNS aliases every column to the same name
|
|
105
|
-
// MEMORY_SELECT_COLUMNS uses (plus bm25_score), matching MemoryRow.
|
|
97
|
+
// memories_fts has no tenant_id column; filter via the joined memories row (cheap with idx_memories_tenant_created).
|
|
98
|
+
// SAFETY: MEMORY_SEARCH_COLUMNS aliases every column like MEMORY_SELECT_COLUMNS (plus bm25_score), matching MemoryRow.
|
|
106
99
|
return db.prepare(`
|
|
107
100
|
SELECT ${MEMORY_SEARCH_COLUMNS}
|
|
108
101
|
FROM memories m
|
|
@@ -146,47 +139,18 @@ function selectLikeCandidates(db, terms, p, limit) {
|
|
|
146
139
|
LIMIT ?
|
|
147
140
|
`).all(...p.tenantParams, ...p.scopeParams, Math.max(limit, LIKE_WINDOW_ROWS), ...params, limit);
|
|
148
141
|
}
|
|
149
|
-
/**
|
|
150
|
-
* Load likely search candidates directly from SQLite.
|
|
151
|
-
* Uses FTS5 when available, falls back to LIKE matching, then full-store fallback.
|
|
152
|
-
*
|
|
153
|
-
* When `tenantId` is provided, every SELECT (FTS join, LIKE, fallback) filters
|
|
154
|
-
* by tenant_id. Cross-tenant memories never surface. Omitted = no filter.
|
|
155
|
-
*/
|
|
142
|
+
/** Load likely search candidates: FTS5 when available, else LIKE, then full-store fallback. With `tenantId` every SELECT filters by it; omitted = no filter. */
|
|
156
143
|
export function loadSearchEntries(hippoRoot, query, limit = DEFAULT_SEARCH_CANDIDATE_LIMIT, tenantId) {
|
|
157
|
-
|
|
158
|
-
try {
|
|
144
|
+
return onHandle(hippoRoot, (db) => {
|
|
159
145
|
return loadSearchRows(db, query, limit, tenantId).map(rowToEntry);
|
|
160
|
-
}
|
|
161
|
-
finally {
|
|
162
|
-
closeHippoDb(db);
|
|
163
|
-
}
|
|
146
|
+
}, openStore);
|
|
164
147
|
}
|
|
165
|
-
/**
|
|
166
|
-
*
|
|
167
|
-
* `unknown:legacy` cannot leak via any consumer that hasn't remembered to re-filter.
|
|
168
|
-
*
|
|
169
|
-
* - `requestedScope` undefined / '': default-deny on `unknown:legacy`, admitting `ownScope`, the caller's personal scope.
|
|
170
|
-
* - `requestedScope` non-empty string: exact match on `m.scope = requestedScope`.
|
|
171
|
-
*
|
|
172
|
-
* Private scopes: SQL applies a conservative `NOT LIKE '%:private:%'` before the LIMIT window so private
|
|
173
|
-
* rows cannot starve admitted ones; `passesScopeFilterForRecall` stays the exact JS post-filter.
|
|
174
|
-
*
|
|
175
|
-
* Consumers: `api.recall`, `cmdRecall`/`cmdExplain` direct CLI paths
|
|
176
|
-
* and `searchBothHybrid` recall mode. Background pipelines
|
|
177
|
-
* (`consolidate`, `embeddings`, `refine-llm`, ...) keep using
|
|
178
|
-
* `loadSearchEntries` so they can see quarantined rows when needed.
|
|
179
|
-
*
|
|
180
|
-
* `tenantId` is optional because searchBothHybrid's is; undefined means no tenant filter.
|
|
181
|
-
*/
|
|
148
|
+
/** Recall-mode loader: scope predicate in SQL so `unknown:legacy` cannot leak. Empty `requestedScope` default-denies (admits `ownScope`); else exact match.
|
|
149
|
+
* SQL `NOT LIKE '%:private:%'` runs before the LIMIT so private rows cannot starve admitted ones; `passesScopeFilterForRecall` is the exact post-filter. */
|
|
182
150
|
export function loadRecallSearchEntries(hippoRoot, query, limit = DEFAULT_SEARCH_CANDIDATE_LIMIT, tenantId, requestedScope, explicitScopeMode = 'exact', includeSuperseded = true, originProjects, ownScope) {
|
|
183
|
-
|
|
184
|
-
try {
|
|
151
|
+
return onHandle(hippoRoot, (db) => {
|
|
185
152
|
return loadRecallSearchEntriesFromDb(db, query, { limit, tenantId, requestedScope, explicitScopeMode, includeSuperseded, originProjects, ownScope });
|
|
186
|
-
}
|
|
187
|
-
finally {
|
|
188
|
-
closeHippoDb(db);
|
|
189
|
-
}
|
|
153
|
+
}, openStore);
|
|
190
154
|
}
|
|
191
155
|
// Split out so callers with an already-open db (the prompt-recall path) skip
|
|
192
156
|
// the initStore+open/close cycle per store per call.
|