hippo-memory 1.71.0 → 2.0.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 +7 -5
- package/dist/agent-memories/apply.d.ts +0 -11
- package/dist/agent-memories/apply.js +11 -26
- 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 +3 -2
- package/dist/api/audit.d.ts +30 -2
- package/dist/api/audit.js +48 -7
- package/dist/api/auth.d.ts +11 -9
- package/dist/api/auth.js +39 -40
- 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-auto.js +4 -2
- package/dist/api/context-render.js +4 -3
- package/dist/api/context-select.js +15 -29
- package/dist/api/context.js +29 -18
- 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 +3 -2
- 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 +7 -3
- package/dist/api/forget.js +24 -14
- package/dist/api/goals.d.ts +1 -1
- package/dist/api/goals.js +5 -9
- package/dist/api/graph.js +2 -1
- 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 +5 -1
- package/dist/api/learn.js +71 -44
- package/dist/api/ledger-db.d.ts +2 -6
- package/dist/api/ledger-db.js +4 -36
- package/dist/api/memories.d.ts +21 -1
- package/dist/api/memories.js +51 -1
- package/dist/api/objects.d.ts +1 -1
- package/dist/api/objects.js +2 -1
- package/dist/api/outcome.d.ts +5 -5
- package/dist/api/outcome.js +17 -16
- 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 +8 -1
- package/dist/api/projects.d.ts +21 -0
- package/dist/api/projects.js +24 -0
- package/dist/api/promote.d.ts +3 -3
- package/dist/api/promote.js +26 -28
- package/dist/api/prompt-hook.d.ts +17 -2
- package/dist/api/prompt-hook.js +45 -4
- package/dist/api/quarantine.js +2 -1
- package/dist/api/recall-cli.d.ts +3 -0
- package/dist/api/recall-cli.js +13 -4
- package/dist/api/recall-core.js +10 -5
- package/dist/api/recall-pipeline.js +23 -24
- package/dist/api/recall-request.js +1 -1
- package/dist/api/recall-types.d.ts +3 -1
- package/dist/api/recall.d.ts +0 -3
- package/dist/api/recall.js +51 -73
- package/dist/api/remember-local.d.ts +5 -2
- package/dist/api/remember-local.js +15 -7
- package/dist/api/remember.d.ts +7 -3
- package/dist/api/remember.js +19 -16
- package/dist/api/session-end.d.ts +46 -0
- package/dist/api/session-end.js +131 -0
- package/dist/api/sleep-run.d.ts +1 -1
- package/dist/api/sleep-run.js +16 -11
- package/dist/api/sleep.js +4 -3
- 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 +2 -2
- package/dist/api/types.d.ts +3 -7
- 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 +7 -7
- package/dist/capture/compaction-spool.js +60 -51
- 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 +3 -2
- package/dist/capture/session-worker.js +22 -10
- 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 +20 -20
- package/dist/cli/auth.d.ts +1 -1
- package/dist/cli/auth.js +16 -17
- 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 +6 -2
- package/dist/cli/client.js +37 -21
- package/dist/cli/compact-resume-payload.js +1 -1
- package/dist/cli/context.d.ts +1 -1
- package/dist/cli/context.js +13 -13
- package/dist/cli/continuity.d.ts +1 -1
- package/dist/cli/continuity.js +36 -39
- package/dist/cli/curate.d.ts +2 -2
- package/dist/cli/curate.js +32 -36
- 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 +7 -285
- 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 +6 -6
- package/dist/cli/hook-runtime.js +9 -36
- 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/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/object-verbs.d.ts +2 -2
- package/dist/cli/object-verbs.js +4 -4
- 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 +174 -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 +18 -17
- package/dist/cli/remember.js +17 -17
- package/dist/cli/scheduler.js +2 -1
- package/dist/cli/serve.js +11 -6
- package/dist/cli/session-hooks.d.ts +1 -5
- package/dist/cli/session-hooks.js +89 -168
- 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 +3 -3
- package/dist/cli/transfer.js +64 -43
- package/dist/cli/usage.d.ts +1 -80
- package/dist/cli/usage.js +2 -696
- package/dist/cli/verb-row.d.ts +34 -0
- package/dist/cli/verb-row.js +6 -0
- package/dist/cli/verbs/health.d.ts +27 -0
- package/dist/cli/verbs/health.js +234 -0
- package/dist/cli/verbs/memory.d.ts +16 -0
- package/dist/cli/verbs/memory.js +236 -0
- package/dist/cli/verbs/objects.d.ts +20 -0
- package/dist/cli/verbs/objects.js +257 -0
- package/dist/cli/verbs/sessions.d.ts +31 -0
- package/dist/cli/verbs/sessions.js +314 -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 +24 -315
- package/dist/connectors/dlq.d.ts +39 -3
- package/dist/connectors/dlq.js +39 -4
- package/dist/connectors/github/backfill.js +12 -3
- package/dist/connectors/github/deletion.js +2 -1
- package/dist/connectors/github/dlq.js +31 -73
- package/dist/connectors/github/ingest.d.ts +2 -6
- package/dist/connectors/github/ingest.js +5 -29
- package/dist/connectors/github/tenant-routing.js +2 -1
- package/dist/connectors/github/webhook.d.ts +2 -1
- package/dist/connectors/github/webhook.js +35 -2
- package/dist/connectors/ingest.d.ts +10 -0
- package/dist/connectors/ingest.js +29 -0
- package/dist/connectors/slack/deletion.js +2 -1
- package/dist/connectors/slack/dlq.js +49 -71
- package/dist/connectors/slack/ingest.d.ts +2 -6
- package/dist/connectors/slack/ingest.js +4 -28
- package/dist/connectors/slack/tenant-routing.js +2 -1
- package/dist/connectors/slack/webhook.d.ts +2 -1
- package/dist/connectors/slack/webhook.js +2 -1
- package/dist/consolidate/conflicts.js +2 -2
- package/dist/consolidate/dag.js +29 -18
- package/dist/consolidate/dedupe.d.ts +7 -0
- package/dist/consolidate/dedupe.js +6 -4
- package/dist/consolidate/llm-passes.js +45 -19
- package/dist/consolidate/memory-value.js +3 -2
- package/dist/consolidate/merge.js +8 -8
- 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 +9 -6
- package/dist/consolidate/traces.js +5 -5
- 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 +22 -18
- 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 +4 -4
- package/dist/core/memory-audit.d.ts +17 -0
- package/dist/core/memory-audit.js +54 -0
- package/dist/core/memory.d.ts +14 -8
- package/dist/core/memory.js +35 -23
- package/dist/{consolidate → core}/merged-row.d.ts +1 -1
- package/dist/{consolidate → core}/merged-row.js +1 -1
- package/dist/core/physics.d.ts +3 -1
- package/dist/core/physics.js +23 -18
- 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 +12 -2
- package/dist/{store → core}/recall-scope.d.ts +1 -10
- package/dist/{store → core}/recall-scope.js +2 -19
- package/dist/core/search-types.d.ts +1 -1
- package/dist/dashboard/dashboard-actions.d.ts +2 -2
- package/dist/dashboard/dashboard-actions.js +5 -5
- package/dist/dashboard/dashboard-queries.js +2 -7
- package/dist/dashboard/dashboard-snapshot.js +1 -3
- package/dist/dashboard/dashboard.js +16 -5
- package/dist/db/busy.d.ts +2 -7
- package/dist/db/busy.js +21 -26
- package/dist/db/connect.d.ts +2 -2
- package/dist/db/connect.js +7 -7
- package/dist/db/index.d.ts +3 -3
- package/dist/db/index.js +3 -3
- package/dist/db/migrate.js +14 -7
- package/dist/db/migrations/index.d.ts +1 -1
- package/dist/db/migrations/index.js +3 -1
- package/dist/db/migrations/v11.js +1 -0
- package/dist/db/migrations/v14.js +1 -0
- 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.d.ts +0 -4
- package/dist/db/physics-state.js +7 -33
- package/dist/db/request-stores.d.ts +1 -0
- package/dist/db/request-stores.js +2 -1
- package/dist/db/tables.d.ts +2 -0
- package/dist/db/tables.js +6 -2
- package/dist/db/vector-store.js +19 -5
- package/dist/db/wal-checkpointer.js +2 -1
- package/dist/doctor.d.ts +3 -0
- package/dist/doctor.js +18 -15
- 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 +19 -25
- 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/entry/store-kit.d.ts +37 -0
- package/dist/entry/store-kit.js +25 -0
- package/dist/entry/testing.d.ts +6 -0
- package/dist/entry/testing.js +7 -0
- package/dist/eval/eval-suite.js +17 -11
- package/dist/eval/eval.js +1 -1
- package/dist/eval/judgment.js +12 -5
- 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 +10 -4
- 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 +4 -4
- package/dist/importers/sources.js +5 -4
- package/dist/importers/vault.d.ts +1 -1
- package/dist/importers/vault.js +25 -23
- package/dist/index.d.ts +5 -4
- package/dist/index.js +4 -3
- package/dist/learn/autolearn.d.ts +15 -3
- package/dist/learn/autolearn.js +38 -16
- package/dist/learn/churn-git.js +13 -4
- package/dist/learn/extract.d.ts +3 -2
- package/dist/learn/extract.js +7 -5
- package/dist/learn/forward-claim-detector.js +4 -2
- package/dist/learn/invalidation.d.ts +2 -1
- package/dist/learn/invalidation.js +18 -9
- 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.d.ts +1 -1
- package/dist/mcp/memory-tools.js +8 -9
- 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 +22 -20
- package/dist/mcp/stdio.js +37 -16
- 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 +71 -98
- 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 +12 -0
- package/dist/search/embed-memories.js +389 -0
- package/dist/search/engine.d.ts +8 -0
- package/dist/search/engine.js +10 -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 +14 -17
- package/dist/server/auth.d.ts +3 -1
- package/dist/server/auth.js +24 -15
- package/dist/server/boot.d.ts +2 -1
- package/dist/server/boot.js +34 -84
- package/dist/server/client-ip.d.ts +9 -6
- package/dist/server/client-ip.js +36 -17
- 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 -133
- 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 +19 -40
- 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/tls.d.ts +7 -2
- package/dist/server/tls.js +17 -5
- package/dist/server/types.d.ts +29 -12
- package/dist/server/validation.d.ts +1 -2
- package/dist/server/validation.js +6 -11
- package/dist/server.d.ts +4 -40
- package/dist/server.js +3 -29
- package/dist/sharing/global-store.d.ts +4 -5
- package/dist/sharing/global-store.js +8 -13
- 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 +10 -3
- package/dist/sharing/share.d.ts +2 -0
- package/dist/sharing/share.js +39 -38
- package/dist/store/ambient.js +7 -7
- 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 +59 -30
- package/dist/store/capture-write.d.ts +17 -0
- package/dist/store/capture-write.js +35 -0
- package/dist/store/cards.js +6 -5
- 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 +418 -0
- package/dist/store/compactions.js +6 -4
- package/dist/store/conflicts.d.ts +7 -1
- package/dist/store/conflicts.js +13 -9
- package/dist/store/connectors/dlq.d.ts +10 -0
- package/dist/store/connectors/dlq.js +33 -0
- package/dist/store/connectors/event-log.d.ts +13 -0
- package/dist/store/connectors/event-log.js +24 -0
- package/dist/store/connectors/github.d.ts +7 -9
- package/dist/store/connectors/github.js +35 -60
- package/dist/store/connectors/slack.d.ts +2 -11
- package/dist/store/connectors/slack.js +24 -57
- package/dist/store/dashboard-reads.js +8 -6
- package/dist/store/delete-and-batch.d.ts +6 -0
- package/dist/store/delete-and-batch.js +40 -6
- package/dist/store/delivery-recorder.d.ts +12 -5
- package/dist/store/delivery-recorder.js +13 -11
- package/dist/store/descendant-page.js +8 -4
- package/dist/store/dormant.d.ts +1 -1
- package/dist/store/dormant.js +10 -4
- package/dist/store/embeddings/index.d.ts +2 -12
- package/dist/store/embeddings/index.js +5 -374
- package/dist/store/entry-reads.d.ts +35 -4
- package/dist/store/entry-reads.js +86 -19
- package/dist/store/entry-row.js +9 -2
- package/dist/store/entry-writes.d.ts +15 -12
- package/dist/store/entry-writes.js +54 -22
- 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 +22 -19
- package/dist/store/graph-reads.js +9 -6
- package/dist/store/graph-view-rows.js +2 -1
- package/dist/store/graph-writes.d.ts +6 -6
- package/dist/store/graph-writes.js +48 -71
- package/dist/store/half-life.js +2 -2
- package/dist/store/handoffs.d.ts +10 -4
- package/dist/store/handoffs.js +10 -9
- package/dist/store/index-and-stats.js +2 -2
- package/dist/store/index.d.ts +2 -2
- package/dist/store/index.js +1 -1
- 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 +19 -10
- package/dist/store/open.d.ts +2 -5
- package/dist/store/open.js +42 -54
- package/dist/store/pilot-arm.d.ts +12 -0
- package/dist/store/pilot-arm.js +42 -0
- package/dist/store/port.d.ts +68 -6
- 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/quality-repair.js +1 -1
- package/dist/store/quarantine.js +2 -1
- package/dist/store/recall-trace.d.ts +2 -0
- package/dist/store/recall-trace.js +20 -3
- package/dist/store/rejected-values.js +16 -10
- 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/rows.js +2 -2
- package/dist/store/rule-sql.d.ts +11 -0
- package/dist/store/rule-sql.js +31 -6
- package/dist/store/search-rows.d.ts +5 -5
- package/dist/store/search-rows.js +18 -16
- 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 +6 -4
- package/dist/store/sqlite/entry-writes-group.d.ts +3 -3
- package/dist/store/sqlite/entry-writes-group.js +3 -3
- 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 +11 -0
- package/dist/store/sqlite/held-connection.js +41 -0
- package/dist/store/sqlite/last-recall-group.d.ts +13 -0
- package/dist/store/sqlite/last-recall-group.js +57 -0
- package/dist/store/sqlite/local.d.ts +0 -17
- package/dist/store/sqlite/local.js +0 -31
- package/dist/store/sqlite/maintenance-groups.d.ts +6 -0
- package/dist/store/sqlite/maintenance-groups.js +60 -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 +15 -7
- package/dist/store/sqlite/store.d.ts +1 -8
- package/dist/store/sqlite/store.js +13 -22
- package/dist/store/summaries.d.ts +10 -3
- package/dist/store/summaries.js +54 -11
- package/dist/store/token-ledger-rows.js +3 -2
- package/dist/store/token-ledger.d.ts +0 -7
- package/dist/store/token-ledger.js +0 -35
- package/dist/store/vector-index.js +8 -4
- 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 +6 -1
- package/dist/util/anthropic-messages.js +26 -7
- package/dist/util/atomic-write.d.ts +5 -2
- package/dist/util/atomic-write.js +12 -8
- 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 +12 -2
- package/dist/util/env.js +12 -2
- package/dist/util/format.d.ts +5 -0
- package/dist/util/format.js +10 -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 +9 -3
- package/dist/util/request-scope.js +18 -9
- package/dist/util/secret-detect.js +6 -1
- package/dist/util/spawn-argv.d.ts +9 -0
- package/dist/util/spawn-argv.js +57 -0
- package/dist/util/sql.d.ts +3 -0
- package/dist/util/sql.js +6 -0
- 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/vector-codec.d.ts +4 -0
- package/dist/util/vector-codec.js +15 -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 +4 -2
- package/dist/api/on-store.d.ts +0 -16
- package/dist/api/on-store.js +0 -38
- 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
|
@@ -5,25 +5,31 @@ import { heldTexts } from '../util/same-text.js';
|
|
|
5
5
|
import { audit } from './audit-event.js';
|
|
6
6
|
import { deleteEntryCore } from './delete-and-batch.js';
|
|
7
7
|
import { deleteDormantRow, listDormantSnapshots, purgeDormantByDigest, replaceDormantEntry } from './dormant.js';
|
|
8
|
-
import { entryRejectRowAt,
|
|
8
|
+
import { entryRejectRowAt, selectEntriesByIds, selectTenantTexts } from './entry-reads.js';
|
|
9
9
|
import { stampOriginProject } from './entry-row.js';
|
|
10
10
|
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;
|
|
18
|
-
|
|
19
|
-
|
|
19
|
+
// Text columns decide which rows hold the value; only those rows are read whole.
|
|
20
|
+
const directIds = [];
|
|
21
|
+
const mergedIds = [];
|
|
22
|
+
for (const row of selectTenantTexts(db, tenantId)) {
|
|
20
23
|
if (!rejection.inReach(row.scope))
|
|
21
24
|
continue;
|
|
22
|
-
if (
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
25
|
+
if (holdsValue(row.content))
|
|
26
|
+
directIds.push(row.id);
|
|
27
|
+
else if (heldTexts(row).some(holdsValue))
|
|
28
|
+
mergedIds.push(row.id);
|
|
29
|
+
}
|
|
30
|
+
const held = selectEntriesByIds(db, [...directIds, ...mergedIds], tenantId);
|
|
31
|
+
const merged = mergedIds.flatMap((id) => held.get(id) ?? []);
|
|
32
|
+
for (const row of directIds.flatMap((id) => held.get(id) ?? [])) {
|
|
27
33
|
if (row.kind === 'raw') {
|
|
28
34
|
// A raw row is append-only: archiving is its one removal path, and its savepoint nests in this write scope.
|
|
29
35
|
archiveRawMemory(db, row.id, { reason, who: actor });
|
|
@@ -96,7 +102,7 @@ export function applyRejection(hippoRoot, rejection) {
|
|
|
96
102
|
sourceMemoryId: memoryId ?? null,
|
|
97
103
|
normalizedChars: normalizeValueForRejection(content).length,
|
|
98
104
|
});
|
|
99
|
-
// SHORTCUT: scans
|
|
105
|
+
// SHORTCUT: scans the tenant's text columns, fine for a human-run command; a digest column needs a schema migration, held until approved.
|
|
100
106
|
const holdsValue = (text) => rejectionDigest(text) === digest;
|
|
101
107
|
removeLiveRows(db, hippoRoot, rejection, holdsValue, removal);
|
|
102
108
|
removeDormantCopies(db, rejection, digest, holdsValue, 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/rows.js
CHANGED
|
@@ -61,12 +61,12 @@ function rowToPlacementFields(row) {
|
|
|
61
61
|
scope: row.scope ?? null,
|
|
62
62
|
owner: row.owner ?? null,
|
|
63
63
|
artifact_ref: row.artifact_ref ?? null,
|
|
64
|
-
|
|
64
|
+
tenant_id: row.tenant_id ?? DEFAULT_TENANT_ID,
|
|
65
65
|
origin_project: row.origin_project ?? null,
|
|
66
66
|
descendant_count: Number(row.descendant_count ?? 0),
|
|
67
67
|
earliest_at: row.earliest_at ?? null,
|
|
68
68
|
latest_at: row.latest_at ?? null,
|
|
69
|
-
summary_dirty:
|
|
69
|
+
summary_dirty: Number(row.summary_dirty) === 1,
|
|
70
70
|
last_rebuilt_at: row.last_rebuilt_at ?? null,
|
|
71
71
|
rebuild_count: Number(row.rebuild_count ?? 0),
|
|
72
72
|
dag_level_3_built_at: row.dag_level_3_built_at ?? null,
|
package/dist/store/rule-sql.d.ts
CHANGED
|
@@ -1,5 +1,16 @@
|
|
|
1
|
+
/** calculateRewardFactor as SQL over `memories` columns; strengthSql and the context-candidate rank both build on it, so the slope has one source. */
|
|
2
|
+
export declare function rewardFactorSql(): string;
|
|
1
3
|
/** calculateStrength's clock-basis formula as SQL over `memories` columns, flags and multipliers baked in; keep in step.
|
|
2
4
|
* An unparseable date scores NULL here and 0 in JS, so sums agree. */
|
|
3
5
|
export declare function strengthSql(now: Date): string;
|
|
4
6
|
export declare const AUTO_DELETABLE_SQL: string;
|
|
7
|
+
export interface SqlFragment {
|
|
8
|
+
sql: string;
|
|
9
|
+
params: string[];
|
|
10
|
+
}
|
|
11
|
+
/** SQL twin of the no-request arm of passesScopeFilterForRecall; `ownScope` is bound and compared with `=`, so `%` or `_` in an owner match nothing extra. */
|
|
12
|
+
export declare function scopeAdmitSql(col: '' | 'm.', ownScope?: string | null): SqlFragment;
|
|
13
|
+
/** SQL twin of canTouchScope, which is also canReadScope for an admin: every row but
|
|
14
|
+
* another person's personal one. LIKE folds ASCII case as isPersonalScope's /i does. */
|
|
15
|
+
export declare function touchableScopeSql(col: '' | 'm.', ownScope?: string | null): SqlFragment;
|
|
5
16
|
//# sourceMappingURL=rule-sql.d.ts.map
|
package/dist/store/rule-sql.js
CHANGED
|
@@ -1,8 +1,18 @@
|
|
|
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';
|
|
6
|
+
import { placeholders } from '../util/sql.js';
|
|
5
7
|
const UNIX_EPOCH_JULIAN_DAY = 2440587.5;
|
|
8
|
+
/** calculateRewardFactor as SQL over `memories` columns; strengthSql and the context-candidate rank both build on it, so the slope has one source. */
|
|
9
|
+
export function rewardFactorSql() {
|
|
10
|
+
if (isOutcomeSlowAblated())
|
|
11
|
+
return '1.0';
|
|
12
|
+
const pos = 'COALESCE(outcome_positive, 0)';
|
|
13
|
+
const neg = 'COALESCE(outcome_negative, 0)';
|
|
14
|
+
return `(CASE WHEN ${pos} = 0 AND ${neg} = 0 THEN 1.0 ELSE 1.0 + ${REWARD_SLOPE} * (${pos} - ${neg}) / (${pos} + ${neg} + 1.0) END)`;
|
|
15
|
+
}
|
|
6
16
|
/** calculateStrength's clock-basis formula as SQL over `memories` columns, flags and multipliers baked in; keep in step.
|
|
7
17
|
* An unparseable date scores NULL here and 0 in JS, so sums agree. */
|
|
8
18
|
export function strengthSql(now) {
|
|
@@ -10,10 +20,7 @@ export function strengthSql(now) {
|
|
|
10
20
|
const pos = 'COALESCE(outcome_positive, 0)';
|
|
11
21
|
const neg = 'COALESCE(outcome_negative, 0)';
|
|
12
22
|
const wrong = isOutcomeSlowAblated() || isDecayAblated() ? '0' : `MAX(0, ${neg} - ${pos})`;
|
|
13
|
-
const
|
|
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})`;
|
|
23
|
+
const halfLife = `(COALESCE(half_life_days, ${FALLBACK_HALF_LIFE_DAYS}) * ${rewardFactorSql()})`;
|
|
17
24
|
const anchor = isRecallBoostAblated() ? 'created' : 'last_retrieved';
|
|
18
25
|
const nowJulian = num(now.getTime() / DAY_MS + UNIX_EPOCH_JULIAN_DAY);
|
|
19
26
|
const decay = isDecayAblated() ? '1.0' : `pow(${DECAY_BASE}, (${nowJulian} - julianday(${anchor})) / ${halfLife})`;
|
|
@@ -30,8 +37,26 @@ export function strengthSql(now) {
|
|
|
30
37
|
}
|
|
31
38
|
const sqlText = (s) => `'${s.replace(/'/g, "''")}'`;
|
|
32
39
|
// 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)
|
|
40
|
+
const keepPairSql = (p) => `(COALESCE(superseded_by, '') = '' AND EXISTS (SELECT 1 FROM json_each(CASE WHEN json_valid(tags_json) THEN tags_json ELSE '[]' END) ` +
|
|
41
|
+
`WHERE value = ${sqlText(p.tag)}) AND substr(source, 1, ${p.sourcePrefix.length}) = ${sqlText(p.sourcePrefix)})`;
|
|
34
42
|
// Pinned and kept rows stay (a superseded row is not kept: its successor carries the tag and
|
|
35
43
|
// source); raw rows leave only through archiveRawMemory. The SQL twin guards the DELETE itself.
|
|
36
44
|
export const AUTO_DELETABLE_SQL = `pinned = 0 AND kind != 'raw'${KEEP_PAIRS.map((p) => ` AND NOT ${keepPairSql(p)}`).join('')}`;
|
|
45
|
+
/** SQL twin of the no-request arm of passesScopeFilterForRecall; `ownScope` is bound and compared with `=`, so `%` or `_` in an owner match nothing extra. */
|
|
46
|
+
export function scopeAdmitSql(col, ownScope) {
|
|
47
|
+
const marks = placeholders(RECALL_DEFAULT_DENY_SCOPES.length);
|
|
48
|
+
const admitted = `${col}scope IS NULL OR (${col}scope NOT IN (${marks}) AND ${col}scope NOT LIKE '%:private:%')`;
|
|
49
|
+
if (ownScope == null)
|
|
50
|
+
return { sql: `(${admitted})`, params: [...RECALL_DEFAULT_DENY_SCOPES] };
|
|
51
|
+
// The own arm sits inside the outer parentheses so a caller's `AND ${sql}` cannot split it off.
|
|
52
|
+
return { sql: `(${admitted} OR ${col}scope = ?)`, params: [...RECALL_DEFAULT_DENY_SCOPES, ownScope] };
|
|
53
|
+
}
|
|
54
|
+
/** SQL twin of canTouchScope, which is also canReadScope for an admin: every row but
|
|
55
|
+
* another person's personal one. LIKE folds ASCII case as isPersonalScope's /i does. */
|
|
56
|
+
export function touchableScopeSql(col, ownScope) {
|
|
57
|
+
const notPersonal = `${col}scope IS NULL OR ${col}scope NOT LIKE '${PERSONAL_SCOPE_PREFIX}%'`;
|
|
58
|
+
if (ownScope == null)
|
|
59
|
+
return { sql: `(${notPersonal})`, params: [] };
|
|
60
|
+
return { sql: `(${notPersonal} OR ${col}scope = ?)`, params: [ownScope] };
|
|
61
|
+
}
|
|
37
62
|
//# sourceMappingURL=rule-sql.js.map
|
|
@@ -18,13 +18,8 @@ export type OriginFilter = string | readonly string[];
|
|
|
18
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
19
|
* which only `ownScope` opens. */
|
|
20
20
|
export declare function recallScopeFilter(requestedScope: string | undefined, mode: 'exact' | 'additive', ownScope?: string): RecallScopeFilter;
|
|
21
|
-
/** Sends term queries down the LIKE path on a build that has FTS. Only tests call it. */
|
|
22
|
-
export declare function _forceLikePathForTests(on: boolean): void;
|
|
23
21
|
/** Load likely search candidates: FTS5 when available, else LIKE, then full-store fallback. With `tenantId` every SELECT filters by it; omitted = no filter. */
|
|
24
22
|
export declare function loadSearchEntries(hippoRoot: string, query: string, limit?: number, tenantId?: string): MemoryEntry[];
|
|
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. */
|
|
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[];
|
|
28
23
|
export interface RecallSearchEntriesOptions {
|
|
29
24
|
readonly limit?: number;
|
|
30
25
|
readonly tenantId?: string;
|
|
@@ -34,6 +29,11 @@ export interface RecallSearchEntriesOptions {
|
|
|
34
29
|
readonly originProjects?: OriginFilter;
|
|
35
30
|
readonly ownScope?: string;
|
|
36
31
|
}
|
|
32
|
+
/** Recall-mode loader: scope predicate in SQL so `unknown:legacy` cannot leak. Empty `requestedScope` default-denies (admits `ownScope`); else exact match.
|
|
33
|
+
* SQL `NOT LIKE '%:private:%'` runs before the LIMIT so private rows cannot starve admitted ones; `passesScopeFilterForRecall` is the exact post-filter. */
|
|
34
|
+
export declare function loadRecallEntries(hippoRoot: string, query: string, options?: RecallSearchEntriesOptions): MemoryEntry[];
|
|
35
|
+
/** Positional form of `loadRecallEntries`, kept internal because the frozen q3b-ranker-floor benchmark imports it from dist. */
|
|
36
|
+
export declare function loadRecallSearchEntries(hippoRoot: string, query: string, limit?: number, tenantId?: string, requestedScope?: string, explicitScopeMode?: 'exact' | 'additive', includeSuperseded?: boolean, originProjects?: OriginFilter, ownScope?: string): MemoryEntry[];
|
|
37
37
|
export declare function loadRecallSearchEntriesFromDb(db: DatabaseSyncLike, query: string, options?: RecallSearchEntriesOptions): MemoryEntry[];
|
|
38
38
|
/** Which rows the vector arm of hybrid search may add: the same tenant, scope and superseded rules as the lexical load. */
|
|
39
39
|
export interface VectorCandidateSpec {
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { isFtsAvailable, closeHippoDb } from '../db/index.js';
|
|
2
2
|
import { tokenize } from '../util/tokenize.js';
|
|
3
|
-
import { isPersonalScope
|
|
3
|
+
import { isPersonalScope } from '../core/recall-scope.js';
|
|
4
|
+
import { scopeAdmitSql } from './rule-sql.js';
|
|
4
5
|
import { ftsTermParts, RAREST_TERM_COUNT, rarestFtsQuery } from '../core/prompt-recall.js';
|
|
5
6
|
import { errorMessage, log } from '../util/log.js';
|
|
6
7
|
import { originInSql } from '../core/project-identity.js';
|
|
@@ -8,6 +9,7 @@ import { topVectorMatches } from '../db/vector-store.js';
|
|
|
8
9
|
import { MEMORY_SELECT_COLUMNS, MEMORY_SEARCH_COLUMNS, DEFAULT_SEARCH_CANDIDATE_LIMIT, rowToEntry, } from './rows.js';
|
|
9
10
|
import { onHandle, openStore } from './open.js';
|
|
10
11
|
import { escapeLike } from '../util/escape.js';
|
|
12
|
+
import { placeholders } from '../util/sql.js';
|
|
11
13
|
/** The recall scope rule for a table column prefix (`m.` or none); `passesScopeFilterForRecall` in recall-scope.ts is its JS twin. */
|
|
12
14
|
function recallScopeClause(col, scopeFilter) {
|
|
13
15
|
if (scopeFilter === undefined)
|
|
@@ -26,7 +28,10 @@ function withProject(scope, col, origin) {
|
|
|
26
28
|
return scope;
|
|
27
29
|
// A string is the shape published callers passed before a project could carry several names.
|
|
28
30
|
const originProjects = [origin].flat();
|
|
29
|
-
return {
|
|
31
|
+
return {
|
|
32
|
+
sql: `${scope.sql} AND (${col}origin_project = '' OR ${originInSql(originProjects, `${col}origin_project`)})`,
|
|
33
|
+
params: [...scope.params, ...originProjects],
|
|
34
|
+
};
|
|
30
35
|
}
|
|
31
36
|
/** 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
37
|
* which only `ownScope` opens. */
|
|
@@ -36,11 +41,6 @@ export function recallScopeFilter(requestedScope, mode, ownScope) {
|
|
|
36
41
|
return mode === 'additive' ? { mode: 'default-deny-or-exact', value: requestedScope, ownScope } : { mode: 'exact', value: requestedScope };
|
|
37
42
|
}
|
|
38
43
|
const FTS_QUERY_SYNTAX_RE = /fts5: syntax error|unterminated string/i;
|
|
39
|
-
let forceLikePath = false;
|
|
40
|
-
/** Sends term queries down the LIKE path on a build that has FTS. Only tests call it. */
|
|
41
|
-
export function _forceLikePathForTests(on) {
|
|
42
|
-
forceLikePath = on;
|
|
43
|
-
}
|
|
44
44
|
function loadSearchRows(db, query, limit, tenantId, options = {}) {
|
|
45
45
|
const { scopeFilter, includeSuperseded = true, originProjects } = options;
|
|
46
46
|
const p = searchPredicates(tenantId, scopeFilter, includeSuperseded, originProjects);
|
|
@@ -49,8 +49,7 @@ function loadSearchRows(db, query, limit, tenantId, options = {}) {
|
|
|
49
49
|
// LIMIT here too, so every candidate path honours the caller's cap.
|
|
50
50
|
return selectAllCandidates(db, p, limit);
|
|
51
51
|
}
|
|
52
|
-
|
|
53
|
-
if (!forceLikePath && isFtsAvailable(db)) {
|
|
52
|
+
if (isFtsAvailable(db)) {
|
|
54
53
|
const rows = selectFtsCandidates(db, terms, p, limit);
|
|
55
54
|
if (rows.length > 0)
|
|
56
55
|
return rows;
|
|
@@ -85,7 +84,8 @@ function searchPredicates(tenantId, scopeFilter, includeSuperseded, originProjec
|
|
|
85
84
|
}
|
|
86
85
|
/** Every admitted row, oldest first; the no-terms path and the last-resort fallback share it. */
|
|
87
86
|
function selectAllCandidates(db, p, limit) {
|
|
88
|
-
const sql = `SELECT ${MEMORY_SELECT_COLUMNS} FROM memories${p.tenantOnlyPredicate}${p.archivedClauseTenantOnly}
|
|
87
|
+
const sql = `SELECT ${MEMORY_SELECT_COLUMNS} FROM memories${p.tenantOnlyPredicate}${p.archivedClauseTenantOnly}` +
|
|
88
|
+
`${p.plainScope.sql}${p.currentNoAlias} ORDER BY created ASC, id ASC LIMIT ?`;
|
|
89
89
|
// SAFETY: sql selects exactly MEMORY_SELECT_COLUMNS, whose column list
|
|
90
90
|
// matches MemoryRow's field set.
|
|
91
91
|
return db.prepare(sql).all(...p.tenantParams, ...p.scopeParams, limit);
|
|
@@ -147,15 +147,17 @@ export function loadSearchEntries(hippoRoot, query, limit = DEFAULT_SEARCH_CANDI
|
|
|
147
147
|
}
|
|
148
148
|
/** Recall-mode loader: scope predicate in SQL so `unknown:legacy` cannot leak. Empty `requestedScope` default-denies (admits `ownScope`); else exact match.
|
|
149
149
|
* SQL `NOT LIKE '%:private:%'` runs before the LIMIT so private rows cannot starve admitted ones; `passesScopeFilterForRecall` is the exact post-filter. */
|
|
150
|
+
export function loadRecallEntries(hippoRoot, query, options = {}) {
|
|
151
|
+
return onHandle(hippoRoot, (db) => loadRecallSearchEntriesFromDb(db, query, options), openStore);
|
|
152
|
+
}
|
|
153
|
+
/** Positional form of `loadRecallEntries`, kept internal because the frozen q3b-ranker-floor benchmark imports it from dist. */
|
|
150
154
|
export function loadRecallSearchEntries(hippoRoot, query, limit = DEFAULT_SEARCH_CANDIDATE_LIMIT, tenantId, requestedScope, explicitScopeMode = 'exact', includeSuperseded = true, originProjects, ownScope) {
|
|
151
|
-
return
|
|
152
|
-
return loadRecallSearchEntriesFromDb(db, query, { limit, tenantId, requestedScope, explicitScopeMode, includeSuperseded, originProjects, ownScope });
|
|
153
|
-
}, openStore);
|
|
155
|
+
return loadRecallEntries(hippoRoot, query, { limit, tenantId, requestedScope, explicitScopeMode, includeSuperseded, originProjects, ownScope });
|
|
154
156
|
}
|
|
155
157
|
// Split out so callers with an already-open db (the prompt-recall path) skip
|
|
156
158
|
// the initStore+open/close cycle per store per call.
|
|
157
159
|
export function loadRecallSearchEntriesFromDb(db, query, options = {}) {
|
|
158
|
-
const { limit = DEFAULT_SEARCH_CANDIDATE_LIMIT, tenantId, requestedScope, explicitScopeMode = 'exact', includeSuperseded = true, originProjects, ownScope } = options;
|
|
160
|
+
const { limit = DEFAULT_SEARCH_CANDIDATE_LIMIT, tenantId, requestedScope, explicitScopeMode = 'exact', includeSuperseded = true, originProjects, ownScope, } = options;
|
|
159
161
|
const scopeFilter = recallScopeFilter(requestedScope, explicitScopeMode, ownScope);
|
|
160
162
|
return loadSearchRows(db, query, limit, tenantId, { scopeFilter, includeSuperseded, originProjects }).map(rowToEntry);
|
|
161
163
|
}
|
|
@@ -171,7 +173,7 @@ export async function loadVectorCandidateEntries(hippoRoot, queryVector, spec) {
|
|
|
171
173
|
if (matches.length === 0)
|
|
172
174
|
return [];
|
|
173
175
|
// SAFETY: the SELECT names exactly MEMORY_SELECT_COLUMNS, matching MemoryRow's field set.
|
|
174
|
-
const rows = db.prepare(`SELECT ${MEMORY_SELECT_COLUMNS} FROM memories WHERE id IN (${matches.
|
|
176
|
+
const rows = db.prepare(`SELECT ${MEMORY_SELECT_COLUMNS} FROM memories WHERE id IN (${placeholders(matches.length)})`)
|
|
175
177
|
.all(...matches.map((m) => m.id));
|
|
176
178
|
const byId = new Map(rows.map((r) => [r.id, rowToEntry(r)]));
|
|
177
179
|
return matches.flatMap((m) => byId.get(m.id) ?? []);
|
|
@@ -192,7 +194,7 @@ export function pickRarestFtsQuery(db, terms, maxTerms = RAREST_TERM_COUNT) {
|
|
|
192
194
|
return '';
|
|
193
195
|
// SAFETY: rows' shape matches the two columns named in the SELECT.
|
|
194
196
|
const rows = db
|
|
195
|
-
.prepare(`SELECT term, doc FROM temp.z1_rarest_vocab WHERE term IN (${vocab.
|
|
197
|
+
.prepare(`SELECT term, doc FROM temp.z1_rarest_vocab WHERE term IN (${placeholders(vocab.length)})`)
|
|
196
198
|
.all(...vocab);
|
|
197
199
|
const counts = new Map(rows.map((r) => [r.term, r.doc]));
|
|
198
200
|
return rarestFtsQuery(terms, (part) => counts.get(part) ?? 0, maxTerms);
|
package/dist/store/sessions.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { HOUR_MS } from '../util/time.js';
|
|
1
2
|
import { isSharedStore } from '../core/config.js';
|
|
2
3
|
import { closeHippoDb, HOOK_DB_WAIT_MS, scopedBusyWait, withWriteScope } from '../db/index.js';
|
|
3
4
|
import { raiseMinBinary } from '../db/meta.js';
|
|
@@ -24,8 +25,9 @@ export function continuityStamp(key) {
|
|
|
24
25
|
}
|
|
25
26
|
// An unkeyed write acts on the tenant's newest or every active row, which on a shared store belong to other owners.
|
|
26
27
|
function assertKeyedOnSharedStore(fn, hippoRoot, key) {
|
|
27
|
-
if (!key && isSharedStore(hippoRoot))
|
|
28
|
+
if (!key && isSharedStore(hippoRoot)) {
|
|
28
29
|
throw new Error(`${fn}: a shared store keeps one task snapshot per owner and project, so this write needs their continuity key`);
|
|
30
|
+
}
|
|
29
31
|
}
|
|
30
32
|
function insertSnapshot(db, tenantId, snapshot, now, stamp) {
|
|
31
33
|
const result = db.prepare(`
|
|
@@ -95,7 +97,7 @@ export function loadActiveTaskSnapshot(hippoRoot, tenantId, key) {
|
|
|
95
97
|
}
|
|
96
98
|
/** Default freshness bound for AMBIENT active-task-snapshot reads: 72h rather than 48h so a Friday-evening orphan still offers continuity on Monday;
|
|
97
99
|
* override via `loadFreshActiveTaskSnapshot`'s `opts.maxAgeMs`; deliberately no env knob. */
|
|
98
|
-
export const SNAPSHOT_AMBIENT_MAX_AGE_MS = 72 *
|
|
100
|
+
export const SNAPSHOT_AMBIENT_MAX_AGE_MS = 72 * HOUR_MS;
|
|
99
101
|
/** A usable session id: non-null, non-empty string; named so the owner-match rule in `loadFreshActiveTaskSnapshot` states its contract once. */
|
|
100
102
|
function isNonEmptySessionId(value) {
|
|
101
103
|
return typeof value === 'string' && value.length > 0;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { DatabaseSyncLike } from '../db/index.js';
|
|
2
|
+
import { type MemoryEntry } from '../core/memory.js';
|
|
3
|
+
export declare const SYNC_ACTOR = "agent-memories";
|
|
4
|
+
export type SetAsideWhy = 'note-gone' | 'note-changed' | 'handover' | 'project-merge' | 'project-repair';
|
|
5
|
+
export type SetAsideResult = {
|
|
6
|
+
readonly kind: 'untagged';
|
|
7
|
+
readonly entry: MemoryEntry;
|
|
8
|
+
} | {
|
|
9
|
+
readonly kind: 'dormant';
|
|
10
|
+
readonly id: string;
|
|
11
|
+
};
|
|
12
|
+
/** Design 6's set-aside on the caller's transaction: a pinned row only loses the tag, any other goes dormant, restorable. */
|
|
13
|
+
export declare function setAsideRow(db: DatabaseSyncLike, tag: string, row: MemoryEntry, why: SetAsideWhy): SetAsideResult;
|
|
14
|
+
//# sourceMappingURL=set-aside.d.ts.map
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
// Takes an imported agent note out of recall on the caller's transaction; the note sync and the project repair both use it.
|
|
2
|
+
import { appendAuditEvent } from './audit.js';
|
|
3
|
+
import { insertDormantRow } from './dormant.js';
|
|
4
|
+
import { calculateStrength } from '../core/memory.js';
|
|
5
|
+
import { deleteEntryRowInTx, setEntryTagsInTx } from './entry-writes.js';
|
|
6
|
+
export const SYNC_ACTOR = 'agent-memories';
|
|
7
|
+
/** Design 6's set-aside on the caller's transaction: a pinned row only loses the tag, any other goes dormant, restorable. */
|
|
8
|
+
export function setAsideRow(db, tag, row, why) {
|
|
9
|
+
const untagged = { ...row, tags: row.tags.filter((t) => t !== tag) };
|
|
10
|
+
const audit = (metadata) => appendAuditEvent(db, { tenantId: row.tenant_id, actor: SYNC_ACTOR, op: 'agent_memory_set_aside', targetId: row.id, metadata });
|
|
11
|
+
if (row.pinned) {
|
|
12
|
+
setEntryTagsInTx(db, untagged);
|
|
13
|
+
audit({ why, untagged: true });
|
|
14
|
+
return { kind: 'untagged', entry: untagged };
|
|
15
|
+
}
|
|
16
|
+
const now = new Date();
|
|
17
|
+
// Sleep's dormant move skips kept rows, so the steps are written out here without its filter.
|
|
18
|
+
insertDormantRow(db, { entry: untagged, strength: calculateStrength(row, now), reason: 'source-deleted', dormantAt: now.toISOString() });
|
|
19
|
+
deleteEntryRowInTx(db, row, SYNC_ACTOR);
|
|
20
|
+
audit({ why });
|
|
21
|
+
return { kind: 'dormant', id: row.id };
|
|
22
|
+
}
|
|
23
|
+
//# sourceMappingURL=set-aside.js.map
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
// Busy detection lives with the adapter, so the port names no SQLite error code.
|
|
2
|
+
import { isSqliteBusy } from '../../db/busy.js';
|
|
3
|
+
import { StoreBusyError } from '../port.js';
|
|
4
|
+
/** A held lock in any store: SQLite's busy codes or a port's StoreBusyError. */
|
|
5
|
+
export function isStoreBusy(error) {
|
|
6
|
+
return error instanceof StoreBusyError || isSqliteBusy(error);
|
|
7
|
+
}
|
|
8
|
+
//# sourceMappingURL=busy.js.map
|
|
@@ -1,22 +1,19 @@
|
|
|
1
1
|
// hippo.db's half of the ConnectorEvents store group: each call on a handle of its own.
|
|
2
|
-
import { archiveDeletedArtifact,
|
|
2
|
+
import { archiveDeletedArtifact, githubEventRecord, githubEventSeenAt, githubRouting, insertGitHubDlq, markGitHubEventSeen } from '../connectors/github.js';
|
|
3
3
|
import { insertSlackDlq, markSlackEventSeen, rawMemoryIdForArtifactAt, slackEventRecord, slackEventSeenAt, slackTeamRoute } from '../connectors/slack.js';
|
|
4
4
|
import { onHandle } from '../open.js';
|
|
5
5
|
function eventRecord(hippoRoot, event) {
|
|
6
|
-
|
|
7
|
-
return slackEventRecord(hippoRoot, event.eventId);
|
|
8
|
-
const logged = seenEvent(hippoRoot, event.idempotencyKey);
|
|
9
|
-
return logged ? { seen: true, memoryId: logged.memoryId } : { seen: false };
|
|
6
|
+
return event.connector === 'slack' ? slackEventRecord(hippoRoot, event.eventId) : githubEventRecord(hippoRoot, event.idempotencyKey);
|
|
10
7
|
}
|
|
11
8
|
function markEventSeen(hippoRoot, event) {
|
|
12
9
|
if (event.connector === 'slack')
|
|
13
10
|
return markSlackEventSeen(hippoRoot, event.eventId, null);
|
|
14
11
|
const { idempotencyKey, deliveryId, eventName } = event;
|
|
15
|
-
|
|
12
|
+
markGitHubEventSeen(hippoRoot, { idempotencyKey, deliveryId, eventName, memoryId: null });
|
|
16
13
|
}
|
|
17
14
|
function deletionTarget(hippoRoot, { event, artifactRef, tenantId }) {
|
|
18
15
|
return onHandle(hippoRoot, (db) => {
|
|
19
|
-
const seen = event.connector === 'slack' ? slackEventSeenAt(db, event.eventId) :
|
|
16
|
+
const seen = event.connector === 'slack' ? slackEventSeenAt(db, event.eventId) : githubEventSeenAt(db, event.idempotencyKey);
|
|
20
17
|
return seen ? { seen: true } : { seen: false, memoryId: rawMemoryIdForArtifactAt(db, artifactRef, tenantId) };
|
|
21
18
|
});
|
|
22
19
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { githubEventMemoryAt, markGitHubEventSeenAt } from '../connectors/github.js';
|
|
2
2
|
import { markSlackEventSeenAt, slackEventMemoryAt } from '../connectors/slack.js';
|
|
3
3
|
import { stampOriginProject } from '../entry-row.js';
|
|
4
4
|
import { writeEntryMirrors } from '../entry-writes.js';
|
|
@@ -13,16 +13,18 @@ function logEvent(db, event, memoryId) {
|
|
|
13
13
|
if (event.connector === 'slack')
|
|
14
14
|
return markSlackEventSeenAt(db, event.eventId, memoryId);
|
|
15
15
|
const { idempotencyKey, deliveryId, eventName } = event;
|
|
16
|
-
return
|
|
16
|
+
return markGitHubEventSeenAt(db, { idempotencyKey, deliveryId, eventName, memoryId });
|
|
17
17
|
}
|
|
18
18
|
function loggedMemory(db, event) {
|
|
19
|
-
return event.connector === 'slack' ? slackEventMemoryAt(db, event.eventId) :
|
|
19
|
+
return event.connector === 'slack' ? slackEventMemoryAt(db, event.eventId) : githubEventMemoryAt(db, event.idempotencyKey);
|
|
20
20
|
}
|
|
21
21
|
/** The record, then the log row, go in after the memory row and ahead of its remember row, as a second store must order them. */
|
|
22
22
|
function writeWithCompanions(db, { entry, actor, event, quarantine }) {
|
|
23
23
|
writeInOwnTenant(db, entry, actor, (handle, memoryId) => {
|
|
24
24
|
if (quarantine)
|
|
25
|
-
recordQuarantine(handle, {
|
|
25
|
+
recordQuarantine(handle, {
|
|
26
|
+
tenantId: entry.tenant_id, memoryId, originalScope: quarantine.originalScope, reason: quarantine.reason, actor,
|
|
27
|
+
});
|
|
26
28
|
if (event && !logEvent(handle, event, memoryId))
|
|
27
29
|
throw new EventAlreadyLogged();
|
|
28
30
|
});
|
|
@@ -2,11 +2,11 @@ import { type DatabaseSyncLike } from '../../db/index.js';
|
|
|
2
2
|
import { type MemoryEntry } from '../../core/memory.js';
|
|
3
3
|
import { type ArchiveOpts } from '../raw-archive.js';
|
|
4
4
|
import type { EntryWrite, EntryWrites, OutcomeWrite, RawArchive, Sync } from '../port.js';
|
|
5
|
-
import { type
|
|
5
|
+
import { type WriteEntryInternalOptions } from '../entry-writes.js';
|
|
6
6
|
/** Each call on its own handle; mirrors and the forgotten counter follow the commit, so a rolled-back write leaves neither. */
|
|
7
7
|
export declare function sqliteEntryWrites(hippoRoot: string): Sync<EntryWrites>;
|
|
8
8
|
/** A store-side hook writes on the row's handle inside its write scope, so its throw undoes the row. */
|
|
9
|
-
export declare function writeEntryAt(hippoRoot: string, { entry, actor }: EntryWrite, afterWrite?:
|
|
9
|
+
export declare function writeEntryAt(hippoRoot: string, { entry, actor }: EntryWrite, afterWrite?: WriteEntryInternalOptions['afterWrite']): void;
|
|
10
10
|
/** A trace link follows the commit on the same handle and names only the ids applied, so a rolled-back outcome leaves none. */
|
|
11
11
|
export declare function applyOutcomeAt(hippoRoot: string, outcome: OutcomeWrite, traceId?: number): string[];
|
|
12
12
|
/** Reach is checked inside the archive's write scope. A store-side hook writes on the same handle inside that scope, so its throw undoes the archive. */
|
|
@@ -14,5 +14,5 @@ export declare function archiveRawAt(hippoRoot: string, archive: RawArchive, aft
|
|
|
14
14
|
/** The refusal row lands after `write` has rolled back, in a fresh implicit transaction the aborted one cannot undo. */
|
|
15
15
|
export declare function auditingRefusal<T>(db: DatabaseSyncLike, actor: string, write: () => T): T;
|
|
16
16
|
/** writeEntryAt on the caller's handle, so a sibling group can read on it after the scope has unwound. */
|
|
17
|
-
export declare function writeInOwnTenant(db: DatabaseSyncLike, entry: MemoryEntry, actor: string, afterWrite?:
|
|
17
|
+
export declare function writeInOwnTenant(db: DatabaseSyncLike, entry: MemoryEntry, actor: string, afterWrite?: WriteEntryInternalOptions['afterWrite']): void;
|
|
18
18
|
//# sourceMappingURL=entry-writes-group.d.ts.map
|
|
@@ -5,9 +5,9 @@ import { isSqliteBusy, withWriteScope } from '../../db/index.js';
|
|
|
5
5
|
import { errorFields, errorMessage, log } from '../../util/log.js';
|
|
6
6
|
import { entryAfterOutcome } from '../../core/memory.js';
|
|
7
7
|
import { archiveRawMemory } from '../raw-archive.js';
|
|
8
|
-
import { ownScopeTouches } from '
|
|
8
|
+
import { ownScopeTouches } from '../../core/recall-scope.js';
|
|
9
9
|
import { recordTraceOutcome } from '../recall-trace.js';
|
|
10
|
-
import { RejectedValueError } from '
|
|
10
|
+
import { RejectedValueError } from '../../core/api-errors.js';
|
|
11
11
|
import { markSummaryDirtyInTx } from '../summary-dirty.js';
|
|
12
12
|
import { auditRejectionRefusal } from '../audit-event.js';
|
|
13
13
|
import { deleteEntryCore } from '../delete-and-batch.js';
|
|
@@ -91,7 +91,7 @@ function assertInReach(db, target, id) {
|
|
|
91
91
|
/** hippo.db's upsert would move the row into the writer's tenant, so a store write refuses an id another tenant holds. */
|
|
92
92
|
function assertIdInTenant(db, entry) {
|
|
93
93
|
const holder = selectMemoryReach(db, entry.id)?.tenantId;
|
|
94
|
-
if (holder !== undefined && holder !== entry.
|
|
94
|
+
if (holder !== undefined && holder !== entry.tenant_id)
|
|
95
95
|
throw new ConflictError(`Memory ${entry.id} belongs to another tenant`);
|
|
96
96
|
}
|
|
97
97
|
/** The refusal row lands after `write` has rolled back, in a fresh implicit transaction the aborted one cannot undo. */
|
|
@@ -2,11 +2,12 @@
|
|
|
2
2
|
// of its class: the server's mappers test `instanceof`, `errcode` and fields.
|
|
3
3
|
import { BadRequestError, ConflictError, ForbiddenError, NotFoundError } from '../../core/api-errors.js';
|
|
4
4
|
import { RawAppendOnlyError } from '../../core/raw-append-only.js';
|
|
5
|
-
import { IncompatibleBinaryError
|
|
5
|
+
import { IncompatibleBinaryError } from '../../db/index.js';
|
|
6
|
+
import { StoreBusyError } from '../port.js';
|
|
6
7
|
import { BodyTimeoutError, BodyTooLargeError, HttpError } from '../../util/http-util.js';
|
|
7
8
|
import { errorMessage, log } from '../../util/log.js';
|
|
8
|
-
import { ScopeForbiddenError } from '
|
|
9
|
-
import { RejectedValueError } from '
|
|
9
|
+
import { ScopeForbiddenError } from '../../core/recall-scope.js';
|
|
10
|
+
import { RejectedValueError } from '../../core/api-errors.js';
|
|
10
11
|
import { OtherStoreFolderError, SqliteBlockedError, StoreNotPortedError } from '../../util/sqlite-blocked.js';
|
|
11
12
|
// Every class the server maps by, at or below the store layer. Abstract ApiError is absent: only its four subclasses are thrown.
|
|
12
13
|
const CLASSES = [
|
|
@@ -2,11 +2,12 @@
|
|
|
2
2
|
import { fileURLToPath } from 'node:url';
|
|
3
3
|
import { SHARE_ENV, Worker } from 'node:worker_threads';
|
|
4
4
|
import { addAuditWriteFailures } from '../audit.js';
|
|
5
|
-
import { getHippoDbPath, SERVER_DB_WAIT_MS
|
|
5
|
+
import { getHippoDbPath, SERVER_DB_WAIT_MS } from '../../db/index.js';
|
|
6
|
+
import { StoreBusyError } from '../port.js';
|
|
6
7
|
import { autoCheckpointPages } from '../../db/wal-checkpointer.js';
|
|
7
8
|
import { envStoreQueueMax } from '../../util/env.js';
|
|
8
9
|
import { DeadlineExceededError } from '../../util/http-util.js';
|
|
9
|
-
import { errorMessage, log } from '../../util/log.js';
|
|
10
|
+
import { errorFields, errorMessage, log } from '../../util/log.js';
|
|
10
11
|
import { requestScopes } from '../../util/request-scope.js';
|
|
11
12
|
import { decodeError } from './error-codec.js';
|
|
12
13
|
import { workerCounts } from './executor-counts.js';
|
|
@@ -27,6 +28,10 @@ const DEFAULT_WRITE_GRACE_MS = 2000;
|
|
|
27
28
|
function laneOf(mode) {
|
|
28
29
|
return { mode, queue: [], running: undefined, worker: undefined, stopping: undefined, commitFlag: undefined };
|
|
29
30
|
}
|
|
31
|
+
// A thread that will not stop leaves a live worker behind, so the rejection is logged rather than dropped.
|
|
32
|
+
function terminateLogged(worker) {
|
|
33
|
+
worker.terminate().catch((err) => log.warn('the store worker did not terminate cleanly', errorFields(err)));
|
|
34
|
+
}
|
|
30
35
|
/** Gives `pending`'s caller its one answer; a second call does nothing. */
|
|
31
36
|
function finish(pending, answer) {
|
|
32
37
|
if (pending.answered)
|
|
@@ -153,7 +158,7 @@ class WorkerPool {
|
|
|
153
158
|
#stopReader(lane, worker, pending) {
|
|
154
159
|
finish(pending, () => pending.fail(new DeadlineExceededError(READ_LATE)));
|
|
155
160
|
lane.stopping = worker;
|
|
156
|
-
|
|
161
|
+
terminateLogged(worker);
|
|
157
162
|
}
|
|
158
163
|
// Before its commit flag a stopped write is a known rollback; after it the thread is left to finish, since stopping it could not undo the write.
|
|
159
164
|
#stopWriter(lane, worker, pending) {
|
|
@@ -195,7 +200,8 @@ class WorkerPool {
|
|
|
195
200
|
return this.#exits.size;
|
|
196
201
|
}
|
|
197
202
|
terminateWriter() {
|
|
198
|
-
|
|
203
|
+
if (this.#writer.worker)
|
|
204
|
+
terminateLogged(this.#writer.worker);
|
|
199
205
|
}
|
|
200
206
|
#pump(lane) {
|
|
201
207
|
if (lane.running !== undefined)
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// hippo.db's half of the GraphReads store group: one read snapshot around the walk the CLI graph commands run.
|
|
2
|
-
import { canReadScope } from '
|
|
2
|
+
import { canReadScope } from '../../core/recall-scope.js';
|
|
3
3
|
import { withGraphReadSnapshot } from '../graph-reads.js';
|
|
4
4
|
import { graphViewRows } from '../graph-view-rows.js';
|
|
5
5
|
export function sqliteGraphReads(hippoRoot) {
|