hippo-memory 1.71.0 → 1.72.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/apply.d.ts +0 -11
- package/dist/agent-memories/apply.js +6 -21
- package/dist/agent-memories/claude-code.js +1 -1
- package/dist/agent-memories/codex.js +1 -1
- package/dist/agent-memories/copilot.d.ts +1 -3
- package/dist/agent-memories/copilot.js +1 -17
- package/dist/agent-memories/project-folds.d.ts +10 -0
- package/dist/agent-memories/project-folds.js +34 -0
- package/dist/agent-memories/sync.js +8 -6
- package/dist/api/assemble.js +1 -1
- package/dist/api/audit.d.ts +29 -1
- package/dist/api/audit.js +44 -5
- package/dist/api/auth.d.ts +7 -4
- package/dist/api/auth.js +12 -8
- package/dist/api/auto-sleep.d.ts +5 -2
- package/dist/api/auto-sleep.js +7 -3
- package/dist/api/availability.js +2 -3
- package/dist/api/cards.d.ts +42 -0
- package/dist/api/cards.js +52 -0
- package/dist/api/conflicts.d.ts +28 -0
- package/dist/api/conflicts.js +61 -0
- package/dist/api/context-render.js +4 -3
- package/dist/api/context-select.js +9 -11
- package/dist/api/context.js +17 -8
- package/dist/api/continuity.d.ts +47 -0
- package/dist/api/continuity.js +66 -0
- package/dist/api/dormant.js +4 -2
- package/dist/api/drill-down.js +1 -1
- package/dist/api/embeddings.d.ts +17 -0
- package/dist/api/embeddings.js +28 -0
- package/dist/api/error-reply.d.ts +8 -0
- package/dist/api/error-reply.js +21 -0
- package/dist/api/forget.d.ts +6 -2
- package/dist/api/forget.js +18 -7
- package/dist/api/goals.d.ts +1 -1
- package/dist/api/goals.js +5 -9
- package/dist/api/index.d.ts +4 -2
- package/dist/api/index.js +4 -2
- package/dist/api/instruction-detect.js +5 -1
- package/dist/api/learn.d.ts +4 -0
- package/dist/api/learn.js +53 -27
- package/dist/api/ledger-db.d.ts +2 -6
- package/dist/api/ledger-db.js +4 -36
- package/dist/api/memories.d.ts +19 -1
- package/dist/api/memories.js +39 -0
- package/dist/api/objects.d.ts +1 -1
- package/dist/api/outcome.js +1 -1
- package/dist/api/pilot-arm.d.ts +1 -11
- package/dist/api/pilot-arm.js +5 -45
- package/dist/api/predictions.d.ts +3 -1
- package/dist/api/predictions.js +6 -0
- package/dist/api/projects.d.ts +21 -0
- package/dist/api/projects.js +24 -0
- package/dist/api/promote.js +1 -1
- package/dist/api/prompt-hook.d.ts +15 -2
- package/dist/api/prompt-hook.js +44 -4
- package/dist/api/recall-cli.d.ts +3 -0
- package/dist/api/recall-cli.js +13 -4
- package/dist/api/recall-core.js +3 -3
- package/dist/api/recall-pipeline.js +6 -7
- package/dist/api/recall-request.js +1 -1
- package/dist/api/recall.d.ts +0 -3
- package/dist/api/recall.js +19 -44
- package/dist/api/remember-local.js +1 -1
- package/dist/api/remember.d.ts +2 -1
- package/dist/api/remember.js +3 -2
- package/dist/api/session-end.d.ts +22 -0
- package/dist/api/session-end.js +101 -0
- package/dist/api/sleep-run.d.ts +1 -1
- package/dist/api/sleep-run.js +13 -9
- package/dist/api/status.d.ts +24 -0
- package/dist/api/status.js +40 -0
- package/dist/api/store-init.d.ts +4 -0
- package/dist/api/store-init.js +9 -0
- package/dist/api/tokens.js +1 -1
- package/dist/api/types.d.ts +2 -0
- package/dist/api/types.js +6 -1
- package/dist/capture/caller-session.d.ts +0 -3
- package/dist/capture/caller-session.js +1 -12
- package/dist/capture/capture-error.d.ts +2 -2
- package/dist/capture/capture-error.js +23 -18
- package/dist/capture/codex-patch.js +3 -1
- package/dist/capture/command.js +36 -95
- package/dist/capture/compact.js +10 -5
- package/dist/capture/compaction-items-caller.js +11 -20
- package/dist/capture/compaction-record.d.ts +7 -93
- package/dist/capture/compaction-record.js +29 -426
- package/dist/capture/compaction-spool.d.ts +4 -2
- package/dist/capture/compaction-spool.js +20 -6
- package/dist/capture/copilot-transcript.d.ts +2 -1
- package/dist/capture/copilot-transcript.js +2 -1
- package/dist/capture/extract.d.ts +5 -2
- package/dist/capture/extract.js +4 -3
- package/dist/capture/failure-caller.d.ts +1 -1
- package/dist/capture/failure-caller.js +21 -16
- package/dist/capture/failure-reading.d.ts +2 -1
- package/dist/capture/failure-reading.js +7 -9
- package/dist/capture/pre-compact-caller.js +5 -4
- package/dist/capture/session-digest.js +4 -3
- package/dist/capture/session-end-caller.js +2 -1
- package/dist/capture/session-worker.js +3 -4
- package/dist/capture/transcript.d.ts +2 -1
- package/dist/capture/transcript.js +6 -3
- package/dist/capture/working-state.d.ts +4 -2
- package/dist/capture/working-state.js +4 -2
- package/dist/cli/audit-prune.d.ts +0 -25
- package/dist/cli/audit-prune.js +1 -27
- package/dist/cli/audit.js +13 -13
- package/dist/cli/auth.d.ts +1 -1
- package/dist/cli/auth.js +12 -13
- package/dist/cli/briefs.d.ts +1 -4
- package/dist/cli/briefs.js +37 -292
- package/dist/cli/card.js +41 -33
- package/dist/cli/client.d.ts +5 -0
- package/dist/cli/client.js +24 -8
- package/dist/cli/compact-resume-payload.js +1 -1
- package/dist/cli/context.d.ts +1 -1
- package/dist/cli/context.js +12 -12
- package/dist/cli/continuity.d.ts +1 -1
- package/dist/cli/continuity.js +36 -39
- package/dist/cli/curate.d.ts +1 -1
- package/dist/cli/curate.js +23 -27
- package/dist/cli/dag.d.ts +1 -1
- package/dist/cli/dag.js +23 -8
- package/dist/cli/decisions.d.ts +0 -2
- package/dist/cli/decisions.js +4 -281
- package/dist/cli/eval.d.ts +1 -1
- package/dist/cli/eval.js +12 -13
- package/dist/cli/explain.d.ts +1 -1
- package/dist/cli/explain.js +21 -25
- package/dist/cli/flag-values.js +16 -6
- package/dist/cli/flags.d.ts +0 -289
- package/dist/cli/flags.js +3 -138
- package/dist/cli/graph.d.ts +3 -0
- package/dist/cli/graph.js +83 -0
- package/dist/cli/hook-runtime.d.ts +3 -5
- package/dist/cli/hook-runtime.js +7 -34
- package/dist/cli/incidents.d.ts +3 -0
- package/dist/cli/incidents.js +112 -0
- package/dist/cli/init.d.ts +1 -1
- package/dist/cli/init.js +28 -19
- package/dist/cli/install-steps.d.ts +2 -1
- package/dist/cli/install-steps.js +11 -3
- package/dist/cli/last-sleep.js +1 -1
- package/dist/cli/lenient-id.d.ts +2 -0
- package/dist/cli/lenient-id.js +13 -0
- package/dist/cli/maintenance.d.ts +3 -3
- package/dist/cli/maintenance.js +29 -30
- package/dist/cli/notes.d.ts +2 -0
- package/dist/cli/notes.js +41 -0
- package/dist/cli/open-browser.d.ts +14 -0
- package/dist/cli/open-browser.js +26 -0
- package/dist/cli/playbooks.d.ts +3 -4
- package/dist/cli/playbooks.js +126 -290
- package/dist/cli/predictions.d.ts +3 -0
- package/dist/cli/predictions.js +175 -0
- package/dist/cli/print.js +2 -1
- package/dist/cli/projects.js +30 -22
- package/dist/cli/quality-repair-once.d.ts +1 -1
- package/dist/cli/quality-repair-once.js +6 -5
- package/dist/cli/recall.js +13 -7
- package/dist/cli/refine-llm.js +17 -17
- package/dist/cli/remember.js +12 -12
- package/dist/cli/scheduler.js +2 -1
- package/dist/cli/serve.js +3 -3
- package/dist/cli/session-hooks.d.ts +1 -1
- package/dist/cli/session-hooks.js +45 -115
- package/dist/cli/setup.d.ts +1 -1
- package/dist/cli/setup.js +17 -10
- package/dist/cli/shared.d.ts +2 -6
- package/dist/cli/shared.js +9 -29
- package/dist/cli/sleep-render.js +6 -3
- package/dist/cli/sleep.js +6 -37
- package/dist/cli/status.d.ts +3 -3
- package/dist/cli/status.js +32 -35
- package/dist/cli/transfer.d.ts +1 -1
- package/dist/cli/transfer.js +33 -31
- package/dist/cli/usage.d.ts +0 -79
- package/dist/cli/usage.js +1 -695
- package/dist/cli/verb-row.d.ts +32 -0
- package/dist/cli/verb-row.js +6 -0
- package/dist/cli/verbs/health.d.ts +27 -0
- package/dist/cli/verbs/health.js +232 -0
- package/dist/cli/verbs/memory.d.ts +16 -0
- package/dist/cli/verbs/memory.js +244 -0
- package/dist/cli/verbs/objects.d.ts +20 -0
- package/dist/cli/verbs/objects.js +254 -0
- package/dist/cli/verbs/sessions.d.ts +31 -0
- package/dist/cli/verbs/sessions.js +312 -0
- package/dist/cli/verbs.d.ts +81 -0
- package/dist/cli/verbs.js +7 -0
- package/dist/cli/versioned-verbs.d.ts +51 -0
- package/dist/cli/versioned-verbs.js +79 -0
- package/dist/cli.d.ts +1 -272
- package/dist/cli.js +23 -313
- package/dist/connectors/dlq.d.ts +39 -3
- package/dist/connectors/dlq.js +37 -3
- package/dist/connectors/github/backfill.js +12 -3
- package/dist/connectors/github/dlq.js +31 -73
- package/dist/connectors/github/ingest.d.ts +2 -6
- package/dist/connectors/github/ingest.js +3 -28
- package/dist/connectors/github/webhook.d.ts +2 -1
- package/dist/connectors/github/webhook.js +33 -2
- package/dist/connectors/ingest.d.ts +10 -0
- package/dist/connectors/ingest.js +28 -0
- package/dist/connectors/slack/dlq.js +49 -71
- package/dist/connectors/slack/ingest.d.ts +2 -6
- package/dist/connectors/slack/ingest.js +2 -27
- package/dist/connectors/slack/webhook.d.ts +2 -1
- package/dist/connectors/slack/webhook.js +2 -1
- package/dist/consolidate/conflicts.js +1 -1
- package/dist/consolidate/dag.js +15 -9
- package/dist/consolidate/dedupe.d.ts +7 -0
- package/dist/consolidate/dedupe.js +5 -3
- package/dist/consolidate/llm-passes.js +45 -19
- package/dist/consolidate/memory-value.js +2 -1
- package/dist/consolidate/merge.js +2 -2
- package/dist/consolidate/physics-pass.d.ts +6 -1
- package/dist/consolidate/physics-pass.js +26 -6
- package/dist/consolidate/replay.js +11 -4
- package/dist/consolidate/sleep.js +8 -5
- package/dist/consolidate/traces.js +3 -3
- package/dist/core/ablation.d.ts +10 -0
- package/dist/core/ablation.js +12 -0
- package/dist/{sharing/scope.d.ts → core/active-scope.d.ts} +1 -1
- package/dist/{sharing/scope.js → core/active-scope.js} +1 -1
- package/dist/core/ambient.d.ts +4 -0
- package/dist/core/ambient.js +39 -18
- package/dist/core/api-errors.d.ts +16 -0
- package/dist/core/api-errors.js +20 -0
- package/dist/core/card.js +3 -1
- package/dist/core/compaction-timing.d.ts +7 -0
- package/dist/core/compaction-timing.js +9 -0
- package/dist/core/config.d.ts +1 -1
- package/dist/core/config.js +7 -2
- package/dist/core/cosine.d.ts +3 -0
- package/dist/core/cosine.js +19 -0
- package/dist/{store → core}/markdown.d.ts +1 -1
- package/dist/{store → core}/markdown.js +2 -2
- package/dist/core/memory-audit.d.ts +17 -0
- package/dist/core/memory-audit.js +54 -0
- package/dist/core/memory.d.ts +10 -4
- package/dist/core/memory.js +25 -18
- package/dist/{consolidate → core}/merged-row.d.ts +1 -1
- package/dist/{consolidate → core}/merged-row.js +1 -1
- package/dist/core/physics.js +6 -16
- package/dist/core/prediction.d.ts +3 -0
- package/dist/core/prediction.js +6 -0
- package/dist/core/project-identity.d.ts +3 -0
- package/dist/core/project-identity.js +10 -1
- package/dist/{store → core}/recall-scope.d.ts +1 -10
- package/dist/{store → core}/recall-scope.js +2 -19
- package/dist/db/busy.d.ts +2 -7
- package/dist/db/busy.js +21 -26
- package/dist/db/connect.d.ts +0 -1
- package/dist/db/connect.js +5 -6
- package/dist/db/index.d.ts +3 -3
- package/dist/db/index.js +3 -3
- package/dist/db/migrations/index.d.ts +1 -1
- package/dist/db/migrations/index.js +3 -1
- package/dist/db/migrations/v55.d.ts +3 -0
- package/dist/db/migrations/v55.js +17 -0
- package/dist/db/open.d.ts +0 -2
- package/dist/db/open.js +6 -10
- package/dist/db/physics-state.js +3 -3
- package/dist/db/tables.d.ts +2 -0
- package/dist/db/tables.js +6 -2
- package/dist/db/vector-store.js +17 -4
- package/dist/db/wal-checkpointer.js +2 -1
- package/dist/doctor.js +11 -8
- package/dist/embeddings/local.d.ts +62 -0
- package/dist/embeddings/local.js +146 -0
- package/dist/{store/embeddings → embeddings}/provider.d.ts +5 -2
- package/dist/{store/embeddings → embeddings}/provider.js +18 -15
- package/dist/embeddings/transformers.d.ts +26 -0
- package/dist/embeddings/transformers.js +89 -0
- package/dist/entry/session-text.d.ts +1 -1
- package/dist/entry/session-text.js +1 -1
- package/dist/eval/eval-suite.js +17 -11
- package/dist/eval/eval.js +1 -1
- package/dist/eval/judgment.js +11 -4
- package/dist/graph/extract.js +3 -3
- package/dist/graph/recall.js +1 -1
- package/dist/graph/view.js +13 -5
- package/dist/graph/write.d.ts +1 -1
- package/dist/graph/write.js +9 -9
- package/dist/hooks/codex-session.js +3 -2
- package/dist/hooks/codex-wrapper.js +2 -1
- package/dist/hooks/json-hooks.js +4 -2
- package/dist/hooks/opencode.js +8 -5
- package/dist/hooks/shared.d.ts +0 -6
- package/dist/hooks/shared.js +4 -15
- package/dist/importers/core.js +1 -1
- package/dist/importers/sources.js +5 -4
- package/dist/importers/vault.js +7 -5
- package/dist/index.d.ts +3 -2
- package/dist/index.js +3 -2
- package/dist/learn/autolearn.d.ts +10 -2
- package/dist/learn/autolearn.js +32 -12
- package/dist/learn/churn-git.js +13 -4
- package/dist/learn/extract.d.ts +3 -2
- package/dist/learn/extract.js +6 -4
- package/dist/learn/forward-claim-detector.js +4 -2
- package/dist/learn/invalidation.js +10 -6
- package/dist/mcp/admin-tools.d.ts +2 -2
- package/dist/mcp/admin-tools.js +27 -48
- package/dist/mcp/format.js +3 -2
- package/dist/mcp/framing.d.ts +1 -0
- package/dist/mcp/framing.js +1 -1
- package/dist/mcp/memory-tools.js +3 -1
- package/dist/mcp/protocol.d.ts +11 -7
- package/dist/mcp/protocol.js +25 -12
- package/dist/mcp/recall-tools.js +12 -9
- package/dist/mcp/request.js +2 -1
- package/dist/mcp/stdio.js +24 -8
- package/dist/mcp/tool-args.js +2 -1
- package/dist/mcp/tools.js +44 -21
- package/dist/objects/customer-notes.d.ts +2 -2
- package/dist/objects/decisions.d.ts +2 -2
- package/dist/objects/descriptor.d.ts +1 -1
- package/dist/objects/incidents.d.ts +2 -2
- package/dist/objects/lifecycle.d.ts +1 -1
- package/dist/objects/lifecycle.js +2 -1
- package/dist/objects/policies.d.ts +2 -2
- package/dist/objects/policies.js +2 -1
- package/dist/objects/processes.d.ts +2 -2
- package/dist/objects/project-briefs.d.ts +2 -2
- package/dist/objects/project-briefs.js +2 -3
- package/dist/objects/skills.d.ts +2 -2
- package/dist/postinstall.js +1 -1
- package/dist/rerankers/clef.js +3 -6
- package/dist/rerankers/cross-encoder.d.ts +31 -2
- package/dist/rerankers/cross-encoder.js +63 -97
- package/dist/rerankers/index.js +5 -4
- package/dist/rerankers/jev.js +2 -4
- package/dist/rerankers/outage-warning.d.ts +3 -1
- package/dist/rerankers/outage-warning.js +5 -3
- package/dist/search/bm25-search.js +1 -1
- package/dist/search/boosts.js +1 -1
- package/dist/search/embed-memories.d.ts +9 -0
- package/dist/search/embed-memories.js +377 -0
- package/dist/search/goal-boost.d.ts +1 -1
- package/dist/search/goal-boost.js +6 -3
- package/dist/search/hybrid.d.ts +9 -2
- package/dist/search/hybrid.js +9 -4
- package/dist/search/physics-search.d.ts +6 -3
- package/dist/search/physics-search.js +22 -15
- package/dist/search/rerank.js +1 -1
- package/dist/search/vector.d.ts +8 -6
- package/dist/search/vector.js +10 -13
- package/dist/server/auth.d.ts +2 -0
- package/dist/server/auth.js +17 -7
- package/dist/server/boot.js +7 -66
- package/dist/server/client-ip.d.ts +0 -2
- package/dist/server/client-ip.js +3 -2
- package/dist/server/deadline.d.ts +0 -2
- package/dist/server/deadline.js +1 -7
- package/dist/server/defaults.d.ts +1 -0
- package/dist/server/defaults.js +1 -0
- package/dist/server/mcp-http.js +16 -11
- package/dist/server/request.js +7 -2
- package/dist/server/route-checks.d.ts +7 -0
- package/dist/server/route-checks.js +42 -0
- package/dist/server/route-table.d.ts +9 -8
- package/dist/server/route-table.js +127 -132
- package/dist/server/routes/admin.d.ts +8 -8
- package/dist/server/routes/admin.js +13 -21
- package/dist/server/routes/customer-notes.d.ts +6 -6
- package/dist/server/routes/customer-notes.js +1 -2
- package/dist/server/routes/decisions.d.ts +6 -6
- package/dist/server/routes/decisions.js +2 -4
- package/dist/server/routes/incidents.d.ts +6 -6
- package/dist/server/routes/incidents.js +2 -5
- package/dist/server/routes/memories.d.ts +9 -9
- package/dist/server/routes/memories.js +15 -38
- package/dist/server/routes/object-routes.d.ts +6 -6
- package/dist/server/routes/object-routes.js +4 -7
- package/dist/server/routes/policies.d.ts +7 -7
- package/dist/server/routes/policies.js +2 -4
- package/dist/server/routes/predictions.d.ts +6 -6
- package/dist/server/routes/predictions.js +9 -13
- package/dist/server/routes/processes.d.ts +6 -6
- package/dist/server/routes/processes.js +1 -2
- package/dist/server/routes/project-briefs.d.ts +7 -7
- package/dist/server/routes/project-briefs.js +2 -4
- package/dist/server/routes/recall.d.ts +5 -5
- package/dist/server/routes/recall.js +6 -10
- package/dist/server/routes/skills.d.ts +7 -7
- package/dist/server/routes/skills.js +2 -4
- package/dist/server/server-detect.d.ts +7 -1
- package/dist/server/server-detect.js +36 -11
- package/dist/server/sleep-child.js +26 -7
- package/dist/server/sleep-offload.d.ts +11 -5
- package/dist/server/sleep-offload.js +17 -11
- package/dist/server/types.d.ts +22 -10
- package/dist/server/validation.d.ts +1 -2
- package/dist/server/validation.js +6 -11
- package/dist/server.d.ts +5 -4
- package/dist/server.js +5 -4
- package/dist/sharing/global-store.js +2 -2
- package/dist/sharing/global-sync.js +38 -45
- package/dist/sharing/project-merge.d.ts +7 -14
- package/dist/sharing/project-merge.js +57 -121
- package/dist/sharing/search-both.js +1 -1
- package/dist/sharing/share.d.ts +2 -0
- package/dist/sharing/share.js +37 -34
- package/dist/store/ambient.js +5 -6
- package/dist/store/audit-event.d.ts +1 -1
- package/dist/store/audit.d.ts +0 -16
- package/dist/store/audit.js +4 -55
- package/dist/store/auth.d.ts +4 -2
- package/dist/store/auth.js +7 -3
- package/dist/store/candidates.d.ts +3 -2
- package/dist/store/candidates.js +42 -23
- package/dist/store/capture-write.d.ts +17 -0
- package/dist/store/capture-write.js +35 -0
- package/dist/store/cards.js +1 -1
- package/dist/store/compaction-caller.d.ts +18 -0
- package/dist/store/compaction-caller.js +29 -0
- package/dist/store/compactions-record.d.ts +115 -0
- package/dist/store/compactions-record.js +417 -0
- package/dist/store/compactions.js +6 -4
- package/dist/store/conflicts.js +7 -4
- package/dist/store/connectors/dlq.d.ts +10 -0
- package/dist/store/connectors/dlq.js +32 -0
- package/dist/store/connectors/github.d.ts +7 -9
- package/dist/store/connectors/github.js +30 -53
- package/dist/store/connectors/slack.d.ts +2 -11
- package/dist/store/connectors/slack.js +18 -47
- package/dist/store/dashboard-reads.js +7 -6
- package/dist/store/delete-and-batch.d.ts +6 -0
- package/dist/store/delete-and-batch.js +36 -3
- package/dist/store/delivery-recorder.d.ts +10 -3
- package/dist/store/delivery-recorder.js +12 -5
- package/dist/store/descendant-page.js +6 -3
- package/dist/store/dormant.d.ts +1 -1
- package/dist/store/dormant.js +3 -1
- package/dist/store/embeddings/index.d.ts +2 -12
- package/dist/store/embeddings/index.js +5 -374
- package/dist/store/entry-reads.d.ts +13 -4
- package/dist/store/entry-reads.js +47 -11
- package/dist/store/entry-writes.d.ts +5 -5
- package/dist/store/entry-writes.js +32 -12
- package/dist/store/failure-log-at.d.ts +8 -0
- package/dist/store/failure-log-at.js +16 -0
- package/dist/store/failure-log.d.ts +2 -2
- package/dist/store/failure-log.js +5 -3
- package/dist/{trust → store}/gated-write.d.ts +3 -1
- package/dist/{trust → store}/gated-write.js +7 -5
- package/dist/store/goals.js +20 -18
- package/dist/store/graph-reads.js +4 -2
- package/dist/store/graph-writes.d.ts +6 -6
- package/dist/store/graph-writes.js +48 -71
- package/dist/store/handoffs.d.ts +1 -1
- package/dist/store/handoffs.js +6 -6
- package/dist/store/index-and-stats.js +2 -2
- package/dist/store/key-writes.js +1 -1
- package/dist/store/ledger-turn.d.ts +9 -0
- package/dist/store/ledger-turn.js +38 -0
- package/dist/store/mirrors.js +10 -6
- package/dist/store/open.d.ts +0 -4
- package/dist/store/open.js +40 -53
- package/dist/store/pilot-arm.d.ts +12 -0
- package/dist/store/pilot-arm.js +42 -0
- package/dist/store/port.d.ts +9 -3
- package/dist/store/port.js +8 -0
- package/dist/store/predictions.d.ts +1 -2
- package/dist/store/predictions.js +3 -6
- package/dist/store/project-tags.d.ts +62 -0
- package/dist/store/project-tags.js +67 -0
- package/dist/store/quarantine.js +2 -1
- package/dist/store/recall-trace.d.ts +2 -0
- package/dist/store/recall-trace.js +18 -2
- package/dist/store/rejected-values.js +2 -1
- package/dist/store/rejection-probe.d.ts +4 -0
- package/dist/store/rejection-probe.js +19 -0
- package/dist/store/rejection.d.ts +0 -17
- package/dist/store/rejection.js +1 -21
- package/dist/store/rule-sql.d.ts +9 -0
- package/dist/store/rule-sql.js +21 -2
- package/dist/store/search-rows.js +9 -4
- package/dist/store/sessions.js +4 -2
- package/dist/store/set-aside.d.ts +14 -0
- package/dist/store/set-aside.js +23 -0
- package/dist/store/sqlite/busy.d.ts +3 -0
- package/dist/store/sqlite/busy.js +8 -0
- package/dist/store/sqlite/connector-events-group.js +4 -7
- package/dist/store/sqlite/connector-writes-group.js +3 -3
- package/dist/store/sqlite/entry-writes-group.js +2 -2
- package/dist/store/sqlite/error-codec.js +4 -3
- package/dist/store/sqlite/executor.js +10 -4
- package/dist/store/sqlite/graph-reads-group.js +1 -1
- package/dist/store/sqlite/held-connection.d.ts +9 -0
- package/dist/store/sqlite/held-connection.js +41 -0
- package/dist/store/sqlite/object-rows.d.ts +1 -1
- package/dist/store/sqlite/objects-group.d.ts +1 -1
- package/dist/store/sqlite/objects-group.js +1 -1
- package/dist/store/sqlite/store.js +14 -12
- package/dist/store/summaries.d.ts +3 -3
- package/dist/store/summaries.js +5 -4
- package/dist/store/token-ledger.d.ts +0 -7
- package/dist/store/token-ledger.js +0 -35
- package/dist/store/vector-index.js +3 -2
- package/dist/support-bundle.js +2 -3
- package/dist/trust/reject-flow.js +2 -2
- package/dist/util/agent-homes.d.ts +15 -0
- package/dist/util/agent-homes.js +34 -0
- package/dist/util/anthropic-messages.d.ts +3 -0
- package/dist/util/anthropic-messages.js +22 -5
- package/dist/util/chunked.d.ts +3 -0
- package/dist/util/chunked.js +10 -0
- package/dist/util/ellipsize.d.ts +3 -0
- package/dist/util/ellipsize.js +5 -0
- package/dist/util/env.d.ts +2 -1
- package/dist/util/env.js +2 -1
- package/dist/util/format.d.ts +3 -0
- package/dist/util/format.js +6 -0
- package/dist/util/hook-payload.d.ts +8 -0
- package/dist/util/hook-payload.js +37 -0
- package/dist/util/http-retry.d.ts +6 -0
- package/dist/util/http-retry.js +43 -5
- package/dist/util/http-util.d.ts +0 -8
- package/dist/util/http-util.js +10 -21
- package/dist/util/limits.d.ts +7 -0
- package/dist/util/limits.js +14 -0
- package/dist/util/log.d.ts +4 -0
- package/dist/util/log.js +9 -0
- package/dist/util/request-scope.d.ts +3 -1
- package/dist/util/request-scope.js +11 -6
- package/dist/util/secret-detect.js +6 -1
- package/dist/util/sqlite-blocked.d.ts +2 -0
- package/dist/util/sqlite-blocked.js +5 -0
- package/dist/util/stream-tee.d.ts +3 -0
- package/dist/util/stream-tee.js +35 -0
- package/dist/util/time.d.ts +4 -0
- package/dist/util/time.js +4 -0
- package/dist/util/version.d.ts +1 -1
- package/dist/util/version.js +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 +2 -2
- package/dist/store/embeddings/local.d.ts +0 -15
- package/dist/store/embeddings/local.js +0 -175
- /package/dist/{cli → api}/correction-latency.d.ts +0 -0
- /package/dist/{cli → api}/correction-latency.js +0 -0
- /package/dist/{cli → api}/provenance-coverage.d.ts +0 -0
- /package/dist/{cli → api}/provenance-coverage.js +0 -0
- /package/dist/{store → core}/object-types.d.ts +0 -0
- /package/dist/{store → core}/object-types.js +0 -0
- /package/dist/{capture → util}/compaction-items.d.ts +0 -0
- /package/dist/{capture → util}/compaction-items.js +0 -0
- /package/dist/{store → util}/yaml.d.ts +0 -0
- /package/dist/{store → util}/yaml.js +0 -0
package/dist/store/open.js
CHANGED
|
@@ -2,26 +2,15 @@
|
|
|
2
2
|
import * as fs from 'fs';
|
|
3
3
|
import * as path from 'path';
|
|
4
4
|
import { DEFAULT_HALF_LIFE_DAYS, Layer } from '../core/memory.js';
|
|
5
|
-
import { closeHippoDb, currentRequestStores, openHippoDb, getMeta, setMeta, withWriteScope } from '../db/index.js';
|
|
5
|
+
import { closeHippoDb, currentRequestStores, openHippoDb, getMeta, setMeta, withWriteScope, pruneConsolidationRuns, } from '../db/index.js';
|
|
6
6
|
import { openHippoDbWithFacts } from '../db/open.js';
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import { RejectedValueError } from './rejection.js';
|
|
10
|
-
import { errorMessage, log } from '../util/log.js';
|
|
7
|
+
import { RejectedValueError } from '../core/api-errors.js';
|
|
8
|
+
import { errorFields, errorMessage, log } from '../util/log.js';
|
|
11
9
|
import { audit } from './audit-event.js';
|
|
12
|
-
import { deserializeEntry } from '
|
|
10
|
+
import { deserializeEntry } from '../core/markdown.js';
|
|
13
11
|
import { stampOriginProjectForImport, upsertEntryRow } from './entry-row.js';
|
|
14
12
|
import { ensureMirrorDirectories, syncMirrorFiles, layerDir } from './mirrors.js';
|
|
15
13
|
import { isJsonObject } from '../util/json.js';
|
|
16
|
-
/** Nearest ancestor store like git; the strict join is the fallback so `hippo init` still creates `<cwd>/.hippo`. */
|
|
17
|
-
export function getHippoRoot(cwd = process.cwd(), opts) {
|
|
18
|
-
return findHippoStoreDir(cwd, opts) ?? path.join(realpathOrResolve(cwd), '.hippo');
|
|
19
|
-
}
|
|
20
|
-
export function isInitialized(hippoRoot) {
|
|
21
|
-
// autoInstallHooks / setupDailySchedule can create a bare .hippo with no hippo.db; counting
|
|
22
|
-
// that as initialized makes `hippo init` skip initStore, so only hippo.db counts.
|
|
23
|
-
return fs.existsSync(path.join(hippoRoot, 'hippo.db'));
|
|
24
|
-
}
|
|
25
14
|
export function initStore(hippoRoot) {
|
|
26
15
|
closeHippoDb(openStore(hippoRoot));
|
|
27
16
|
}
|
|
@@ -48,8 +37,9 @@ export function openStore(hippoRoot, opts) {
|
|
|
48
37
|
try {
|
|
49
38
|
closeHippoDb(db);
|
|
50
39
|
}
|
|
51
|
-
catch {
|
|
52
|
-
//
|
|
40
|
+
catch (closeErr) {
|
|
41
|
+
// The init error is the one thrown; the close failure is only logged.
|
|
42
|
+
log.error(`openStore: closing the handle after a failed init failed: ${errorMessage(closeErr)}`, errorFields(closeErr));
|
|
53
43
|
}
|
|
54
44
|
throw error;
|
|
55
45
|
}
|
|
@@ -142,6 +132,8 @@ function importLegacyIndexAndStats(db, hippoRoot) {
|
|
|
142
132
|
const row = run;
|
|
143
133
|
insertRun.run(String(row.timestamp ?? new Date().toISOString()), Number(row.decayed ?? 0), Number(row.merged ?? 0), Number(row.removed ?? 0));
|
|
144
134
|
}
|
|
135
|
+
// Same cap as every later sleep, so stats.json and the table agree from the first open.
|
|
136
|
+
pruneConsolidationRuns(db);
|
|
145
137
|
}
|
|
146
138
|
export function loadLegacyEntriesFromMarkdown(hippoRoot) {
|
|
147
139
|
const entries = [];
|
|
@@ -152,52 +144,47 @@ export function loadLegacyEntriesFromMarkdown(hippoRoot) {
|
|
|
152
144
|
for (const file of fs.readdirSync(dir)) {
|
|
153
145
|
if (!file.endsWith('.md'))
|
|
154
146
|
continue;
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
147
|
+
try {
|
|
148
|
+
const entry = deserializeEntry(fs.readFileSync(path.join(dir, file), 'utf8'));
|
|
149
|
+
if (entry)
|
|
150
|
+
entries.push(entry);
|
|
151
|
+
}
|
|
152
|
+
catch (err) {
|
|
153
|
+
log.warn(`store: skipped unreadable legacy file ${file}: ${errorMessage(err)}`);
|
|
154
|
+
}
|
|
159
155
|
}
|
|
160
156
|
}
|
|
161
157
|
return entries;
|
|
162
158
|
}
|
|
163
|
-
function
|
|
164
|
-
|
|
165
|
-
if (!fs.existsSync(indexPath)) {
|
|
166
|
-
return { version: 1, entries: {}, last_retrieval_ids: [], last_trace_id: null };
|
|
167
|
-
}
|
|
159
|
+
function readLegacyJsonObject(file) {
|
|
160
|
+
let parsed;
|
|
168
161
|
try {
|
|
169
|
-
|
|
170
|
-
// a hand-edited file that violates the shape falls through to the catch block's fallback.
|
|
171
|
-
return JSON.parse(fs.readFileSync(indexPath, 'utf8'));
|
|
162
|
+
parsed = JSON.parse(fs.readFileSync(file, 'utf8'));
|
|
172
163
|
}
|
|
173
164
|
catch (err) {
|
|
174
|
-
log.
|
|
175
|
-
return
|
|
165
|
+
log.warn(`store: unreadable ${path.basename(file)} read as empty: ${errorMessage(err)}`);
|
|
166
|
+
return null;
|
|
167
|
+
}
|
|
168
|
+
if (!isJsonObject(parsed)) {
|
|
169
|
+
log.warn(`store: ${path.basename(file)} is not a JSON object, read as empty`);
|
|
170
|
+
return null;
|
|
176
171
|
}
|
|
172
|
+
return parsed;
|
|
173
|
+
}
|
|
174
|
+
function loadLegacyIndexFile(hippoRoot) {
|
|
175
|
+
const indexPath = path.join(hippoRoot, 'index.json');
|
|
176
|
+
const empty = { version: 1, entries: {}, last_retrieval_ids: [], last_trace_id: null };
|
|
177
|
+
if (!fs.existsSync(indexPath))
|
|
178
|
+
return empty;
|
|
179
|
+
// SAFETY: index.json is written by writeIndexMirror as a HippoIndex; readers default every field, so only the object shape is checked.
|
|
180
|
+
return readLegacyJsonObject(indexPath) ?? empty;
|
|
177
181
|
}
|
|
178
182
|
function loadLegacyStatsFile(hippoRoot) {
|
|
179
183
|
const statsPath = path.join(hippoRoot, 'stats.json');
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
consolidation_runs: [],
|
|
186
|
-
};
|
|
187
|
-
}
|
|
188
|
-
try {
|
|
189
|
-
// SAFETY: stats.json is only written by writeStatsMirror below with exactly these four fields; callers also guard every read with `?? 0` / `Array.isArray`,
|
|
190
|
-
// so a hand-edited file is tolerated even if this cast is wrong.
|
|
191
|
-
return JSON.parse(fs.readFileSync(statsPath, 'utf8'));
|
|
192
|
-
}
|
|
193
|
-
catch (err) {
|
|
194
|
-
log.debug(`store: unreadable stats.json read as zero: ${errorMessage(err)}`);
|
|
195
|
-
return {
|
|
196
|
-
total_remembered: 0,
|
|
197
|
-
total_recalled: 0,
|
|
198
|
-
total_forgotten: 0,
|
|
199
|
-
consolidation_runs: [],
|
|
200
|
-
};
|
|
201
|
-
}
|
|
184
|
+
const empty = { total_remembered: 0, total_recalled: 0, total_forgotten: 0, consolidation_runs: [] };
|
|
185
|
+
if (!fs.existsSync(statsPath))
|
|
186
|
+
return empty;
|
|
187
|
+
// SAFETY: callers guard every field read with `?? 0` / `Array.isArray`, so only the object shape is checked.
|
|
188
|
+
return readLegacyJsonObject(statsPath) ?? empty;
|
|
202
189
|
}
|
|
203
190
|
//# sourceMappingURL=open.js.map
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { type DatabaseSyncLike } from '../db/index.js';
|
|
2
|
+
export type PilotArm = 'hippo' | 'holdout';
|
|
3
|
+
/** Deterministic split: the same session and rate always land in the same arm. */
|
|
4
|
+
export declare function hashArm(sessionId: string, rateBp: number): PilotArm;
|
|
5
|
+
/** The session's first stored arm, or null; never writes. Without `tenantId` any tenant's row counts, since on one machine a session has one arm. */
|
|
6
|
+
export declare function readPilotArm(db: DatabaseSyncLike, sessionId: string, tenantId?: string): PilotArm | null;
|
|
7
|
+
/** The stored arm, else the hash arm written once; on any error the hash arm comes back unrecorded. */
|
|
8
|
+
export declare function ensurePilotArm(db: DatabaseSyncLike, tenantId: string, sessionId: string, rateBp: number, opts?: {
|
|
9
|
+
ownTenantOnly?: boolean;
|
|
10
|
+
now?: string;
|
|
11
|
+
}): PilotArm;
|
|
12
|
+
//# sourceMappingURL=pilot-arm.d.ts.map
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
// Pilot arm: one token_ledger row per session names its arm, `hippo` or `holdout`, so a pilot can compare them.
|
|
2
|
+
// `items` holds the holdout rate in basis points; readers outside this repo depend on these rows, so their shape is fixed.
|
|
3
|
+
import { createHash } from 'node:crypto';
|
|
4
|
+
import { HOOK_DB_WAIT_MS, scopedBusyWait, withWriteScope } from '../db/index.js';
|
|
5
|
+
import { errorMessage, log } from '../util/log.js';
|
|
6
|
+
import { firstPilotArmHash } from './token-ledger-rows.js';
|
|
7
|
+
import { recordTokenUse } from './token-ledger.js';
|
|
8
|
+
/** Deterministic split: the same session and rate always land in the same arm. */
|
|
9
|
+
export function hashArm(sessionId, rateBp) {
|
|
10
|
+
const bucket = parseInt(createHash('sha256').update(sessionId).digest('hex').slice(0, 8), 16) % 10000;
|
|
11
|
+
return bucket < rateBp ? 'holdout' : 'hippo';
|
|
12
|
+
}
|
|
13
|
+
/** The session's first stored arm, or null; never writes. Without `tenantId` any tenant's row counts, since on one machine a session has one arm. */
|
|
14
|
+
export function readPilotArm(db, sessionId, tenantId) {
|
|
15
|
+
const row = firstPilotArmHash(db, sessionId, tenantId);
|
|
16
|
+
return row?.block_hash === 'holdout' || row?.block_hash === 'hippo' ? row.block_hash : null;
|
|
17
|
+
}
|
|
18
|
+
/** The stored arm, else the hash arm written once; on any error the hash arm comes back unrecorded. */
|
|
19
|
+
// The wait is the caller's lock-wait scope (a hook's 1 s, a server request's 250 ms); it holds on a handle opened in that scope.
|
|
20
|
+
export function ensurePilotArm(db, tenantId, sessionId, rateBp, opts = {}) {
|
|
21
|
+
const hashed = hashArm(sessionId, rateBp);
|
|
22
|
+
const readTenant = opts.ownTenantOnly ? tenantId : undefined;
|
|
23
|
+
try {
|
|
24
|
+
// A stored row is the common case after the first prompt, so it must not take the write lock.
|
|
25
|
+
const existing = readPilotArm(db, sessionId, readTenant);
|
|
26
|
+
if (existing !== null)
|
|
27
|
+
return existing;
|
|
28
|
+
return withWriteScope(db, 'pilot_arm', () => {
|
|
29
|
+
const stored = readPilotArm(db, sessionId, readTenant);
|
|
30
|
+
if (stored === null) {
|
|
31
|
+
recordTokenUse(db, { tenantId, sessionId, surface: 'pilot', event: 'arm', items: rateBp, tokens: 0, hash: hashed, now: opts.now });
|
|
32
|
+
}
|
|
33
|
+
return stored ?? hashed;
|
|
34
|
+
}, { busyWaitMs: scopedBusyWait() ?? HOOK_DB_WAIT_MS });
|
|
35
|
+
}
|
|
36
|
+
catch (err) {
|
|
37
|
+
// A prompt hook must not fail on pilot bookkeeping; concurrent callers still agree on the hash arm.
|
|
38
|
+
log.debug(`pilot arm not stored, using the hash arm: ${errorMessage(err)}`);
|
|
39
|
+
return hashed;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
//# sourceMappingURL=pilot-arm.js.map
|
package/dist/store/port.d.ts
CHANGED
|
@@ -10,11 +10,12 @@ import type { JsonValue } from '../util/json.js';
|
|
|
10
10
|
import type { KeysetPosition } from '../util/keyset.js';
|
|
11
11
|
import type { MemoryEntry } from '../core/memory.js';
|
|
12
12
|
import type { PhysicsParticle } from '../core/physics.js';
|
|
13
|
-
import type { BriefReceipt, Incident, IncidentFields, ObjectByKind, ObjectFields, ObjectKind, Policy, SavableKind, Skill } from '
|
|
13
|
+
import type { BriefReceipt, Incident, IncidentFields, ObjectByKind, ObjectFields, ObjectKind, Policy, SavableKind, Skill } from '../core/object-types.js';
|
|
14
14
|
import type { PlanningFallacyEvidence } from './planning-fallacy-evidence.js';
|
|
15
|
-
import type {
|
|
15
|
+
import type { Prediction, PredictionBaserate, SavePredictionOpts } from './predictions.js';
|
|
16
|
+
import type { ClosureState } from '../core/prediction.js';
|
|
16
17
|
import type { QuarantineRow, QuarantineStatus } from './quarantine.js';
|
|
17
|
-
import type { ScopeActor } from '
|
|
18
|
+
import type { ScopeActor } from '../core/recall-scope.js';
|
|
18
19
|
import type { RecallTraceInput } from './recall-trace.js';
|
|
19
20
|
import type { AmbientLoadResult, AmbientRecallRequest, ContextCandidateFilter, RecentOrigins } from './candidates.js';
|
|
20
21
|
import type { GitHubDlqInsert, GitHubRouting } from './connectors/github.js';
|
|
@@ -603,6 +604,11 @@ export type StoreGroup = 'base' | keyof StoreGroups;
|
|
|
603
604
|
export declare function hasGroup(store: HippoStore, group: StoreGroup): boolean;
|
|
604
605
|
/** The group's methods; a store without them throws StoreNotPortedError, which answers 501 as any unported path does. */
|
|
605
606
|
export declare function requireGroup<G extends keyof StoreGroups>(store: HippoStore, group: G): StoreGroups[G];
|
|
607
|
+
export declare const STORE_BUSY_MESSAGE = "store busy (another hippo process holds the write lock); retry shortly";
|
|
608
|
+
/** A store behind the port throws this when its lock wait runs out, so the server answers 503 as it does for a busy hippo.db. */
|
|
609
|
+
export declare class StoreBusyError extends Error {
|
|
610
|
+
constructor(message?: string, options?: ErrorOptions);
|
|
611
|
+
}
|
|
606
612
|
/** What `serve()` reads and writes through. Each method is atomic and no transaction spans an
|
|
607
613
|
* await, since SQLite's lock wait blocks the event loop; a lock timeout throws `StoreBusyError`. */
|
|
608
614
|
export interface HippoStore extends Partial<StoreGroups> {
|
package/dist/store/port.js
CHANGED
|
@@ -14,4 +14,12 @@ export function requireGroup(store, group) {
|
|
|
14
14
|
throw new StoreNotPortedError(store.kind, group);
|
|
15
15
|
return methods;
|
|
16
16
|
}
|
|
17
|
+
export const STORE_BUSY_MESSAGE = 'store busy (another hippo process holds the write lock); retry shortly';
|
|
18
|
+
/** A store behind the port throws this when its lock wait runs out, so the server answers 503 as it does for a busy hippo.db. */
|
|
19
|
+
export class StoreBusyError extends Error {
|
|
20
|
+
constructor(message = STORE_BUSY_MESSAGE, options) {
|
|
21
|
+
super(message, options);
|
|
22
|
+
this.name = 'StoreBusyError';
|
|
23
|
+
}
|
|
24
|
+
}
|
|
17
25
|
//# sourceMappingURL=port.js.map
|
|
@@ -4,8 +4,7 @@
|
|
|
4
4
|
import { type MemoryEntry } from '../core/memory.js';
|
|
5
5
|
import { type KeysetPosition } from '../util/keyset.js';
|
|
6
6
|
import type { PredictionSave } from './port.js';
|
|
7
|
-
|
|
8
|
-
export declare const VALID_CLOSURE_STATES: ReadonlySet<ClosureState>;
|
|
7
|
+
import { type ClosureState } from '../core/prediction.js';
|
|
9
8
|
export interface Prediction {
|
|
10
9
|
id: number;
|
|
11
10
|
/** Nullable: ON DELETE SET NULL allows memory deletion (forget /
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
/** First-class prediction: an ex-ante claim closed against an outcome. The `predictions` table is the source of truth; the memory row only mirrors the claim.
|
|
2
2
|
* Every helper requires tenantId; `trg_predictions_tenant_match_*` triggers enforce the prediction's tenant matches the referenced memory's.
|
|
3
3
|
* `savePrediction` writes memory and prediction inside `writeEntry`'s SAVEPOINT (via afterWrite), so a failure in either rolls back both. */
|
|
4
|
+
import { DEFAULT_LIST_LIMIT } from '../util/limits.js';
|
|
4
5
|
import { BadRequestError, NotFoundError } from '../core/api-errors.js';
|
|
5
6
|
import { withWriteScope } from '../db/index.js';
|
|
6
7
|
import { onHandle } from './open.js';
|
|
@@ -10,15 +11,11 @@ import { createMemory, Layer } from '../core/memory.js';
|
|
|
10
11
|
import { appendAuditEvent } from './audit.js';
|
|
11
12
|
import { loadConfig } from '../core/config.js';
|
|
12
13
|
import { keysetAfter } from '../util/keyset.js';
|
|
13
|
-
|
|
14
|
+
import { VALID_CLOSURE_STATES } from '../core/prediction.js';
|
|
15
|
+
const DEFAULT_PREDICTION_PAGE_SIZE = DEFAULT_LIST_LIMIT;
|
|
14
16
|
const SELECT_COLUMNS = `id, memory_id, tenant_id, class_tag, claim_text,
|
|
15
17
|
estimate_value, estimate_unit, target_date,
|
|
16
18
|
actual_value, closure_state, closed_at, closure_note, created_at`;
|
|
17
|
-
export const VALID_CLOSURE_STATES = new Set([
|
|
18
|
-
'open',
|
|
19
|
-
'closed',
|
|
20
|
-
'closed-unknown',
|
|
21
|
-
]);
|
|
22
19
|
function rowToPrediction(row) {
|
|
23
20
|
return {
|
|
24
21
|
id: row.id,
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { type DatabaseSyncLike } from '../db/index.js';
|
|
2
|
+
import { type MemoryEntry } from '../core/memory.js';
|
|
3
|
+
import { type AppendAuditOpts, type AuditEvent } from './audit.js';
|
|
4
|
+
import { type DormantReason, type DormantSnapshot } from './dormant.js';
|
|
5
|
+
import { type SetAsideResult, type SetAsideWhy } from './set-aside.js';
|
|
6
|
+
export type ProjectTagOp = 'project_merge' | 'project_repair';
|
|
7
|
+
export interface ProjectTagReads {
|
|
8
|
+
entries(): MemoryEntry[];
|
|
9
|
+
liveEntriesBySourcePrefix(prefix: string): MemoryEntry[];
|
|
10
|
+
entriesByIds(ids: readonly string[]): Map<string, MemoryEntry>;
|
|
11
|
+
dormant(): DormantSnapshot[];
|
|
12
|
+
auditEvents(op: ProjectTagOp): AuditEvent[];
|
|
13
|
+
compactionTranscripts(): Array<{
|
|
14
|
+
transcript: string;
|
|
15
|
+
cwd: string | null;
|
|
16
|
+
}>;
|
|
17
|
+
compactionOriginsWithCwd(): Array<{
|
|
18
|
+
origin: string;
|
|
19
|
+
cwd: string;
|
|
20
|
+
}>;
|
|
21
|
+
holdsOrigin(table: 'memories' | 'compactions', name: string): boolean;
|
|
22
|
+
}
|
|
23
|
+
export interface ProjectTagWrites extends ProjectTagReads {
|
|
24
|
+
setAside(tag: string, row: MemoryEntry, why: SetAsideWhy): SetAsideResult;
|
|
25
|
+
restampOrigin(from: string, into: string): void;
|
|
26
|
+
restampCompactions(from: string, into: string): number;
|
|
27
|
+
replaceDormant(id: string, entry: MemoryEntry): void;
|
|
28
|
+
stampOrigins(rows: ReadonlyArray<{
|
|
29
|
+
readonly id: string;
|
|
30
|
+
readonly origin: string;
|
|
31
|
+
}>): void;
|
|
32
|
+
/** A live row to dormant storage, restorable, as sleep's dormant move does. */
|
|
33
|
+
retire(row: MemoryEntry, reason: DormantReason, now: Date): void;
|
|
34
|
+
audit(op: ProjectTagOp, metadata: AppendAuditOpts['metadata']): void;
|
|
35
|
+
}
|
|
36
|
+
/** A rewrite's answer plus the ids whose mirrors are rewritten, and those whose mirrors go, once it commits. */
|
|
37
|
+
export interface TagRewrite<T> {
|
|
38
|
+
readonly result: T;
|
|
39
|
+
readonly rewrite: readonly string[];
|
|
40
|
+
readonly purge: readonly string[];
|
|
41
|
+
}
|
|
42
|
+
export interface ProjectTagStore extends ProjectTagReads {
|
|
43
|
+
readonly hippoRoot: string;
|
|
44
|
+
/** One transaction; a dry run rolls back with no backup, else the store is backed up first and mirrors follow the commit. */
|
|
45
|
+
rewrite<T>(opts: {
|
|
46
|
+
readonly dryRun: boolean;
|
|
47
|
+
readonly backupLabel: string;
|
|
48
|
+
}, body: (tx: ProjectTagWrites, backup: string | null) => TagRewrite<T>): T;
|
|
49
|
+
repairedOnce(): boolean;
|
|
50
|
+
markRepairedOnce(): void;
|
|
51
|
+
}
|
|
52
|
+
export interface ProjectTagScope {
|
|
53
|
+
readonly hippoRoot: string;
|
|
54
|
+
readonly tenantId: string;
|
|
55
|
+
/** Who the audit rows name. */
|
|
56
|
+
readonly actor: string;
|
|
57
|
+
}
|
|
58
|
+
/** Reads on a handle the caller opened and closes, for doctor's read-only check and the note sync. */
|
|
59
|
+
export declare function projectTagReads(db: DatabaseSyncLike, tenantId: string): ProjectTagReads;
|
|
60
|
+
/** Runs `fn` on hippo.db under `scope.hippoRoot`, opened for this call and closed after. */
|
|
61
|
+
export declare function onProjectTags<T>(scope: ProjectTagScope, fn: (store: ProjectTagStore) => T): T;
|
|
62
|
+
//# sourceMappingURL=project-tags.d.ts.map
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
// The rows `hippo projects` and sleep's tag repair read and write, bound to one hippo.db handle and tenant,
|
|
2
|
+
// so the merge and repair rules in src/sharing/project-merge.ts decide without holding the handle.
|
|
3
|
+
import { getMeta, setMeta, withTrialScope, withWriteScope } from '../db/index.js';
|
|
4
|
+
import { withBackup } from '../db/backup.js';
|
|
5
|
+
import { calculateStrength } from '../core/memory.js';
|
|
6
|
+
import { appendAuditEvent, queryAuditEvents } from './audit.js';
|
|
7
|
+
import { compactionOriginsWithCwd, compactionTranscripts, holdsOrigin, restampCompactionOrigin } from './compactions.js';
|
|
8
|
+
import { insertDormantRow, listDormantSnapshots, replaceDormantEntry } from './dormant.js';
|
|
9
|
+
import { selectAllEntries, selectEntriesByIds, selectLiveEntriesBySourcePrefix } from './entry-reads.js';
|
|
10
|
+
import { deleteEntryRowInTx, restampOriginProjectAt, stampOriginProjectsAt, writeEntryMirrors } from './entry-writes.js';
|
|
11
|
+
import { removeEntryMirrors } from './mirrors.js';
|
|
12
|
+
import { onHandle } from './open.js';
|
|
13
|
+
import { setAsideRow } from './set-aside.js';
|
|
14
|
+
const AUDIT_READ_CAP = 10000;
|
|
15
|
+
const TX_LABEL = 'merge_projects';
|
|
16
|
+
const AUTO_REPAIR_META_KEY = 'project_repair_auto';
|
|
17
|
+
/** Reads on a handle the caller opened and closes, for doctor's read-only check and the note sync. */
|
|
18
|
+
export function projectTagReads(db, tenantId) {
|
|
19
|
+
return {
|
|
20
|
+
entries: () => selectAllEntries(db, tenantId),
|
|
21
|
+
liveEntriesBySourcePrefix: (prefix) => selectLiveEntriesBySourcePrefix(db, tenantId, prefix),
|
|
22
|
+
entriesByIds: (ids) => selectEntriesByIds(db, ids, tenantId),
|
|
23
|
+
dormant: () => listDormantSnapshots(db, tenantId),
|
|
24
|
+
auditEvents: (op) => queryAuditEvents(db, { tenantId, op, limit: AUDIT_READ_CAP }),
|
|
25
|
+
compactionTranscripts: () => compactionTranscripts(db, tenantId),
|
|
26
|
+
compactionOriginsWithCwd: () => compactionOriginsWithCwd(db, tenantId),
|
|
27
|
+
holdsOrigin: (table, name) => holdsOrigin(db, table, tenantId, name),
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
function projectTagWrites(db, { tenantId, actor }) {
|
|
31
|
+
return {
|
|
32
|
+
...projectTagReads(db, tenantId),
|
|
33
|
+
setAside: (tag, row, why) => setAsideRow(db, tag, row, why),
|
|
34
|
+
restampOrigin: (from, into) => restampOriginProjectAt(db, tenantId, from, into),
|
|
35
|
+
restampCompactions: (from, into) => restampCompactionOrigin(db, tenantId, from, into),
|
|
36
|
+
replaceDormant: (id, entry) => replaceDormantEntry(db, tenantId, id, entry),
|
|
37
|
+
stampOrigins: (rows) => stampOriginProjectsAt(db, tenantId, rows),
|
|
38
|
+
retire: (row, reason, now) => {
|
|
39
|
+
insertDormantRow(db, { entry: row, strength: calculateStrength(row, now), reason, dormantAt: now.toISOString() });
|
|
40
|
+
deleteEntryRowInTx(db, row, actor);
|
|
41
|
+
},
|
|
42
|
+
audit: (op, metadata) => appendAuditEvent(db, { tenantId, actor, op, metadata }),
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
function rewriteOn(db, scope, opts, body) {
|
|
46
|
+
const tx = projectTagWrites(db, scope);
|
|
47
|
+
if (opts.dryRun)
|
|
48
|
+
return withTrialScope(db, TX_LABEL, () => body(tx, null)).result;
|
|
49
|
+
const done = withBackup(db, scope.hippoRoot, opts.backupLabel, (backup) => withWriteScope(db, TX_LABEL, () => body(tx, backup)));
|
|
50
|
+
// After commit, as the agent memory sync does: a stale mirror would bring the old tag back on the next rebuild.
|
|
51
|
+
for (const entry of selectEntriesByIds(db, done.rewrite, scope.tenantId).values())
|
|
52
|
+
writeEntryMirrors(scope.hippoRoot, entry);
|
|
53
|
+
for (const id of done.purge)
|
|
54
|
+
removeEntryMirrors(scope.hippoRoot, id);
|
|
55
|
+
return done.result;
|
|
56
|
+
}
|
|
57
|
+
/** Runs `fn` on hippo.db under `scope.hippoRoot`, opened for this call and closed after. */
|
|
58
|
+
export function onProjectTags(scope, fn) {
|
|
59
|
+
return onHandle(scope.hippoRoot, (db) => fn({
|
|
60
|
+
...projectTagReads(db, scope.tenantId),
|
|
61
|
+
hippoRoot: scope.hippoRoot,
|
|
62
|
+
rewrite: (opts, body) => rewriteOn(db, scope, opts, body),
|
|
63
|
+
repairedOnce: () => getMeta(db, AUTO_REPAIR_META_KEY) === '1',
|
|
64
|
+
markRepairedOnce: () => setMeta(db, AUTO_REPAIR_META_KEY, '1'),
|
|
65
|
+
}));
|
|
66
|
+
}
|
|
67
|
+
//# sourceMappingURL=project-tags.js.map
|
package/dist/store/quarantine.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
// The memory_quarantine table: the review queue's rows, and the approve and reject writes with their audit rows.
|
|
2
|
+
import { DEFAULT_LIST_LIMIT } from '../util/limits.js';
|
|
2
3
|
import { appendAuditEvent } from './audit.js';
|
|
3
4
|
import { withWriteScopeOr } from '../db/index.js';
|
|
4
5
|
import { keysetAfter } from '../util/keyset.js';
|
|
@@ -27,7 +28,7 @@ function getQuarantineRow(db, tenantId, memoryId) {
|
|
|
27
28
|
.get(tenantId, memoryId);
|
|
28
29
|
return row ? fromDbRow(row) : null;
|
|
29
30
|
}
|
|
30
|
-
function listQuarantineRows(db, tenantId, status = 'pending', limit =
|
|
31
|
+
function listQuarantineRows(db, tenantId, status = 'pending', limit = DEFAULT_LIST_LIMIT, afterRow) {
|
|
31
32
|
// A pending row whose memory was deleted (e.g. Slack message_deleted) is dead; keep its history, drop it from the queue.
|
|
32
33
|
const live = status === 'pending'
|
|
33
34
|
? ' AND EXISTS (SELECT 1 FROM memories m WHERE m.id = memory_quarantine.memory_id AND m.tenant_id = memory_quarantine.tenant_id)'
|
|
@@ -101,6 +101,8 @@ export interface DeliveryEventRow {
|
|
|
101
101
|
recall_hash: string | null;
|
|
102
102
|
emitted_hash: string | null;
|
|
103
103
|
elapsed_ms: number;
|
|
104
|
+
tool_use_id: string | null;
|
|
105
|
+
failure_id: number | null;
|
|
104
106
|
candidates: DeliveryCandidateRow[];
|
|
105
107
|
}
|
|
106
108
|
/** One event plus its candidates in one write transaction, then prune; fail-soft. The caller must not hold a transaction on `db`. */
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
/** Retrieval-trace persistence: the single producer for `recall_traces`, `recall_trace_results` and `recall_trace_outcomes`.
|
|
2
2
|
* One trace row per recall on api.recall, api.getContext and CLI cmdRecall: the (query, shown, outcome) triple the learned components train on.
|
|
3
3
|
* All writes are fail-soft: a failed trace write is logged to stderr and swallowed, never breaking the surrounding call. */
|
|
4
|
-
import { openHippoDb, closeHippoDb,
|
|
4
|
+
import { openHippoDb, closeHippoDb, withWriteScope } from '../db/index.js';
|
|
5
|
+
import { rethrowIfSqliteBlocked } from '../util/sqlite-blocked.js';
|
|
5
6
|
import { DELIVERY_LEDGER_VERSION, isBoundaryEvent } from './delivery-recorder.js';
|
|
6
7
|
import { errorFields, errorMessage, log } from '../util/log.js';
|
|
7
8
|
import { DAY_MS } from '../util/time.js';
|
|
@@ -105,7 +106,7 @@ const DELIVERY_EVENT_COLUMNS = [
|
|
|
105
106
|
'session_id', 'session_state', 'host_turn_id', 'turn_seq', 'duplicate_of', 'prompt_hash', 'prompt_length', 'query_hash',
|
|
106
107
|
'recall_trace_id', 'block_state', 'prompt_recall', 'considered_count', 'filtered_count', 'selected_count', 'emitted_count',
|
|
107
108
|
'rejected_count', 'rejected_unlisted', 'sections_shown', 'sections_dropped', 'budget_tokens', 'selected_tokens',
|
|
108
|
-
'injected_tokens', 'static_hash', 'recall_hash', 'emitted_hash', 'elapsed_ms',
|
|
109
|
+
'injected_tokens', 'static_hash', 'recall_hash', 'emitted_hash', 'elapsed_ms', 'tool_use_id', 'failure_id',
|
|
109
110
|
];
|
|
110
111
|
function findDuplicateBoundary(db, input) {
|
|
111
112
|
// SAFETY: rows carry exactly the `id` and `ts` columns selected.
|
|
@@ -117,7 +118,21 @@ function findDuplicateBoundary(db, input) {
|
|
|
117
118
|
const at = Date.parse(input.ts);
|
|
118
119
|
return rows.find((r) => Math.abs(Date.parse(r.ts) - at) <= DELIVERY_DUPLICATE_WINDOW_MS)?.id ?? null;
|
|
119
120
|
}
|
|
121
|
+
function findDuplicateToolFailure(db, input) {
|
|
122
|
+
// Without a call id a time window would merge parallel failures, so two such fires stay two rows.
|
|
123
|
+
if (input.toolUseId === undefined || input.toolUseId === null)
|
|
124
|
+
return null;
|
|
125
|
+
// SAFETY: a single `id` column, undefined when no row matches.
|
|
126
|
+
const row = db.prepare(`
|
|
127
|
+
SELECT id FROM delivery_events
|
|
128
|
+
WHERE tenant_id = ? AND session_id = ? AND event_type = ? AND tool_use_id = ? AND turn_seq IS NOT NULL
|
|
129
|
+
ORDER BY id LIMIT 1
|
|
130
|
+
`).get(input.tenantId, input.sessionId, input.eventType, input.toolUseId);
|
|
131
|
+
return row?.id ?? null;
|
|
132
|
+
}
|
|
120
133
|
function findDuplicateTurn(db, input) {
|
|
134
|
+
if (input.eventType === 'tool-failure')
|
|
135
|
+
return findDuplicateToolFailure(db, input);
|
|
121
136
|
// A boundary has no prompt, and two compactions of one session never start within the window, so time alone decides.
|
|
122
137
|
if (isBoundaryEvent(input.eventType))
|
|
123
138
|
return findDuplicateBoundary(db, input);
|
|
@@ -165,6 +180,7 @@ export function writeDeliveryEvent(db, input) {
|
|
|
165
180
|
input.consideredCount, input.filteredCount, input.selectedCount, input.emittedCount, input.rejectedCount,
|
|
166
181
|
input.rejectedUnlisted, input.sectionsShown, input.sectionsDropped, input.budgetTokens, input.selectedTokens,
|
|
167
182
|
input.injectedTokens, input.staticHash, input.recallHash, input.emittedHash, Math.round(input.elapsedMs),
|
|
183
|
+
input.toolUseId ?? null, input.failureId ?? null,
|
|
168
184
|
];
|
|
169
185
|
const eventId = Number(db.prepare(`
|
|
170
186
|
INSERT INTO delivery_events (${DELIVERY_EVENT_COLUMNS.join(', ')})
|
|
@@ -11,7 +11,8 @@ import { writeEntryDbOnly, writeEntryMirrors } from './entry-writes.js';
|
|
|
11
11
|
import { purgeMirrorBestEffort } from './mirrors.js';
|
|
12
12
|
import { onHandle, openStore } from './open.js';
|
|
13
13
|
import { archiveRawMemory, markMirrorCleaned } from './raw-archive.js';
|
|
14
|
-
import {
|
|
14
|
+
import { checkRejectionGuard, deleteRejectedValue, insertRejectedValue, listRejectedValues, normalizeValueForRejection, rejectionDigest, } from './rejection.js';
|
|
15
|
+
import { RejectedValueError } from '../core/api-errors.js';
|
|
15
16
|
function removeLiveRows(db, hippoRoot, rejection, holdsValue, removal) {
|
|
16
17
|
const { tenantId, actor, reason } = rejection;
|
|
17
18
|
const { removedIds, removedRawIds, successors } = removal;
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export type RejectionProbe = (tenantId: string, entryId: string, content: string) => boolean;
|
|
2
|
+
/** Runs `fn` with a probe that says whether the write guard would refuse the content; the handle closes after. */
|
|
3
|
+
export declare function withRejectionProbe<T>(hippoRoot: string, fn: (wouldReject: RejectionProbe) => T): T;
|
|
4
|
+
//# sourceMappingURL=rejection-probe.d.ts.map
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
// A rejected-value check for a dry run, on a handle the caller never sees.
|
|
2
|
+
import { onHandle } from './open.js';
|
|
3
|
+
import { checkRejectionGuard } from './rejection.js';
|
|
4
|
+
import { RejectedValueError } from '../core/api-errors.js';
|
|
5
|
+
/** Runs `fn` with a probe that says whether the write guard would refuse the content; the handle closes after. */
|
|
6
|
+
export function withRejectionProbe(hippoRoot, fn) {
|
|
7
|
+
return onHandle(hippoRoot, (db) => fn((tenantId, entryId, content) => {
|
|
8
|
+
try {
|
|
9
|
+
checkRejectionGuard(db, tenantId, entryId, content);
|
|
10
|
+
return false;
|
|
11
|
+
}
|
|
12
|
+
catch (err) {
|
|
13
|
+
if (err instanceof RejectedValueError)
|
|
14
|
+
return true;
|
|
15
|
+
throw err;
|
|
16
|
+
}
|
|
17
|
+
}));
|
|
18
|
+
}
|
|
19
|
+
//# sourceMappingURL=rejection-probe.js.map
|
|
@@ -1,28 +1,11 @@
|
|
|
1
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
2
|
* db-agnostic (helpers take a `DatabaseSyncLike`) and imports nothing from the store layer above it, which imports this (the reverse is a cycle). */
|
|
3
3
|
import type { DatabaseSyncLike } from '../db/index.js';
|
|
4
|
-
import { BadRequestError } from '../core/api-errors.js';
|
|
5
4
|
/** Normalize content for rejection digests: NFC, lowercase, collapse whitespace runs, trim. No punctuation stripping: over-normalizing causes false
|
|
6
5
|
* refusals, worse than misses. */
|
|
7
6
|
export declare function normalizeValueForRejection(content: string): string;
|
|
8
7
|
/** 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. */
|
|
9
8
|
export declare function rejectionDigest(content: string): string;
|
|
10
|
-
/** Thrown by the write-path guard (checkRejectionGuard, via upsertEntryRow) when a write would introduce a tombstoned value; carries what the
|
|
11
|
-
* transaction-owner catch blocks (writeEntry, api.supersede) need to write the post-rollback `reject_refusal` audit row via `auditRejectionRefusal`. */
|
|
12
|
-
export declare class RejectedValueError extends BadRequestError {
|
|
13
|
-
readonly digest: string;
|
|
14
|
-
readonly tenantId: string;
|
|
15
|
-
readonly entryId: string;
|
|
16
|
-
readonly reason: string | null;
|
|
17
|
-
readonly rejectedAt: string;
|
|
18
|
-
constructor(opts: {
|
|
19
|
-
digest: string;
|
|
20
|
-
tenantId: string;
|
|
21
|
-
entryId: string;
|
|
22
|
-
reason: string | null;
|
|
23
|
-
rejectedAt: string;
|
|
24
|
-
});
|
|
25
|
-
}
|
|
26
9
|
export interface RejectedValueRow {
|
|
27
10
|
tenantId: string;
|
|
28
11
|
digest: string;
|
package/dist/store/rejection.js
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
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
2
|
* db-agnostic (helpers take a `DatabaseSyncLike`) and imports nothing from the store layer above it, which imports this (the reverse is a cycle). */
|
|
3
3
|
import { createHash } from 'node:crypto';
|
|
4
|
-
import {
|
|
5
|
-
import { DIGEST_DISPLAY_CHARS } from '../util/token-text.js';
|
|
4
|
+
import { RejectedValueError } from '../core/api-errors.js';
|
|
6
5
|
/** Normalize content for rejection digests: NFC, lowercase, collapse whitespace runs, trim. No punctuation stripping: over-normalizing causes false
|
|
7
6
|
* refusals, worse than misses. */
|
|
8
7
|
export function normalizeValueForRejection(content) {
|
|
@@ -12,25 +11,6 @@ export function normalizeValueForRejection(content) {
|
|
|
12
11
|
export function rejectionDigest(content) {
|
|
13
12
|
return createHash('sha256').update(normalizeValueForRejection(content)).digest('hex');
|
|
14
13
|
}
|
|
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`. */
|
|
17
|
-
export class RejectedValueError extends BadRequestError {
|
|
18
|
-
digest;
|
|
19
|
-
tenantId;
|
|
20
|
-
entryId;
|
|
21
|
-
reason;
|
|
22
|
-
rejectedAt;
|
|
23
|
-
constructor(opts) {
|
|
24
|
-
super(`Memory value refused: matches a rejected value (digest ${opts.digest.slice(0, DIGEST_DISPLAY_CHARS)}..., ` +
|
|
25
|
-
`reason: ${opts.reason ?? 'none given'}). Run "hippo unreject" to allow it again.`);
|
|
26
|
-
this.name = 'RejectedValueError';
|
|
27
|
-
this.digest = opts.digest;
|
|
28
|
-
this.tenantId = opts.tenantId;
|
|
29
|
-
this.entryId = opts.entryId;
|
|
30
|
-
this.reason = opts.reason;
|
|
31
|
-
this.rejectedAt = opts.rejectedAt;
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
14
|
function rowToRejectedValue(row) {
|
|
35
15
|
return {
|
|
36
16
|
tenantId: row.tenant_id,
|
package/dist/store/rule-sql.d.ts
CHANGED
|
@@ -2,4 +2,13 @@
|
|
|
2
2
|
* An unparseable date scores NULL here and 0 in JS, so sums agree. */
|
|
3
3
|
export declare function strengthSql(now: Date): string;
|
|
4
4
|
export declare const AUTO_DELETABLE_SQL: string;
|
|
5
|
+
export interface SqlFragment {
|
|
6
|
+
sql: string;
|
|
7
|
+
params: string[];
|
|
8
|
+
}
|
|
9
|
+
/** SQL twin of the no-request arm of passesScopeFilterForRecall; `ownScope` is bound and compared with `=`, so `%` or `_` in an owner match nothing extra. */
|
|
10
|
+
export declare function scopeAdmitSql(col: '' | 'm.', ownScope?: string | null): SqlFragment;
|
|
11
|
+
/** SQL twin of canTouchScope, which is also canReadScope for an admin: every row but
|
|
12
|
+
* another person's personal one. LIKE folds ASCII case as isPersonalScope's /i does. */
|
|
13
|
+
export declare function touchableScopeSql(col: '' | 'm.', ownScope?: string | null): SqlFragment;
|
|
5
14
|
//# sourceMappingURL=rule-sql.d.ts.map
|
package/dist/store/rule-sql.js
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
// The SQL twins of the model's strength and keep
|
|
1
|
+
// The SQL twins of the model's rules in src/core: strength and keep (memory.ts), recall scope (recall-scope.ts); keep each in step with its JS half.
|
|
2
2
|
import { DAY_MS } from '../util/time.js';
|
|
3
3
|
import { isDecayAblated, isOutcomeSlowAblated, isRecallBoostAblated } from '../core/ablation.js';
|
|
4
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
|
+
import { PERSONAL_SCOPE_PREFIX, RECALL_DEFAULT_DENY_SCOPES } from '../core/recall-scope.js';
|
|
5
6
|
const UNIX_EPOCH_JULIAN_DAY = 2440587.5;
|
|
6
7
|
/** calculateStrength's clock-basis formula as SQL over `memories` columns, flags and multipliers baked in; keep in step.
|
|
7
8
|
* An unparseable date scores NULL here and 0 in JS, so sums agree. */
|
|
@@ -30,8 +31,26 @@ export function strengthSql(now) {
|
|
|
30
31
|
}
|
|
31
32
|
const sqlText = (s) => `'${s.replace(/'/g, "''")}'`;
|
|
32
33
|
// 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)
|
|
34
|
+
const keepPairSql = (p) => `(COALESCE(superseded_by, '') = '' AND EXISTS (SELECT 1 FROM json_each(CASE WHEN json_valid(tags_json) THEN tags_json ELSE '[]' END) ` +
|
|
35
|
+
`WHERE value = ${sqlText(p.tag)}) AND substr(source, 1, ${p.sourcePrefix.length}) = ${sqlText(p.sourcePrefix)})`;
|
|
34
36
|
// Pinned and kept rows stay (a superseded row is not kept: its successor carries the tag and
|
|
35
37
|
// source); raw rows leave only through archiveRawMemory. The SQL twin guards the DELETE itself.
|
|
36
38
|
export const AUTO_DELETABLE_SQL = `pinned = 0 AND kind != 'raw'${KEEP_PAIRS.map((p) => ` AND NOT ${keepPairSql(p)}`).join('')}`;
|
|
39
|
+
/** SQL twin of the no-request arm of passesScopeFilterForRecall; `ownScope` is bound and compared with `=`, so `%` or `_` in an owner match nothing extra. */
|
|
40
|
+
export function scopeAdmitSql(col, ownScope) {
|
|
41
|
+
const placeholders = RECALL_DEFAULT_DENY_SCOPES.map(() => '?').join(', ');
|
|
42
|
+
const admitted = `${col}scope IS NULL OR (${col}scope NOT IN (${placeholders}) AND ${col}scope NOT LIKE '%:private:%')`;
|
|
43
|
+
if (ownScope == null)
|
|
44
|
+
return { sql: `(${admitted})`, params: [...RECALL_DEFAULT_DENY_SCOPES] };
|
|
45
|
+
// The own arm sits inside the outer parentheses so a caller's `AND ${sql}` cannot split it off.
|
|
46
|
+
return { sql: `(${admitted} OR ${col}scope = ?)`, params: [...RECALL_DEFAULT_DENY_SCOPES, ownScope] };
|
|
47
|
+
}
|
|
48
|
+
/** SQL twin of canTouchScope, which is also canReadScope for an admin: every row but
|
|
49
|
+
* another person's personal one. LIKE folds ASCII case as isPersonalScope's /i does. */
|
|
50
|
+
export function touchableScopeSql(col, ownScope) {
|
|
51
|
+
const notPersonal = `${col}scope IS NULL OR ${col}scope NOT LIKE '${PERSONAL_SCOPE_PREFIX}%'`;
|
|
52
|
+
if (ownScope == null)
|
|
53
|
+
return { sql: `(${notPersonal})`, params: [] };
|
|
54
|
+
return { sql: `(${notPersonal} OR ${col}scope = ?)`, params: [ownScope] };
|
|
55
|
+
}
|
|
37
56
|
//# sourceMappingURL=rule-sql.js.map
|