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
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,13 +37,15 @@ 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
|
}
|
|
56
46
|
}
|
|
57
|
-
/** One call on a handle of its own, closed after
|
|
47
|
+
/** One call on a handle of its own, closed after (a request scope's handle stays open);
|
|
48
|
+
* pass openStore where the call also sets up mirror folders and legacy rows. */
|
|
58
49
|
export function onHandle(hippoRoot, fn, open = openHippoDb) {
|
|
59
50
|
const db = open(hippoRoot);
|
|
60
51
|
try {
|
|
@@ -142,6 +133,8 @@ function importLegacyIndexAndStats(db, hippoRoot) {
|
|
|
142
133
|
const row = run;
|
|
143
134
|
insertRun.run(String(row.timestamp ?? new Date().toISOString()), Number(row.decayed ?? 0), Number(row.merged ?? 0), Number(row.removed ?? 0));
|
|
144
135
|
}
|
|
136
|
+
// Same cap as every later sleep, so stats.json and the table agree from the first open.
|
|
137
|
+
pruneConsolidationRuns(db);
|
|
145
138
|
}
|
|
146
139
|
export function loadLegacyEntriesFromMarkdown(hippoRoot) {
|
|
147
140
|
const entries = [];
|
|
@@ -152,52 +145,47 @@ export function loadLegacyEntriesFromMarkdown(hippoRoot) {
|
|
|
152
145
|
for (const file of fs.readdirSync(dir)) {
|
|
153
146
|
if (!file.endsWith('.md'))
|
|
154
147
|
continue;
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
148
|
+
try {
|
|
149
|
+
const entry = deserializeEntry(fs.readFileSync(path.join(dir, file), 'utf8'));
|
|
150
|
+
if (entry)
|
|
151
|
+
entries.push(entry);
|
|
152
|
+
}
|
|
153
|
+
catch (err) {
|
|
154
|
+
log.warn(`store: skipped unreadable legacy file ${file}: ${errorMessage(err)}`);
|
|
155
|
+
}
|
|
159
156
|
}
|
|
160
157
|
}
|
|
161
158
|
return entries;
|
|
162
159
|
}
|
|
163
|
-
function
|
|
164
|
-
|
|
165
|
-
if (!fs.existsSync(indexPath)) {
|
|
166
|
-
return { version: 1, entries: {}, last_retrieval_ids: [], last_trace_id: null };
|
|
167
|
-
}
|
|
160
|
+
function readLegacyJsonObject(file) {
|
|
161
|
+
let parsed;
|
|
168
162
|
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'));
|
|
163
|
+
parsed = JSON.parse(fs.readFileSync(file, 'utf8'));
|
|
172
164
|
}
|
|
173
165
|
catch (err) {
|
|
174
|
-
log.
|
|
175
|
-
return
|
|
166
|
+
log.warn(`store: unreadable ${path.basename(file)} read as empty: ${errorMessage(err)}`);
|
|
167
|
+
return null;
|
|
168
|
+
}
|
|
169
|
+
if (!isJsonObject(parsed)) {
|
|
170
|
+
log.warn(`store: ${path.basename(file)} is not a JSON object, read as empty`);
|
|
171
|
+
return null;
|
|
176
172
|
}
|
|
173
|
+
return parsed;
|
|
174
|
+
}
|
|
175
|
+
function loadLegacyIndexFile(hippoRoot) {
|
|
176
|
+
const indexPath = path.join(hippoRoot, 'index.json');
|
|
177
|
+
const empty = { version: 1, entries: {}, last_retrieval_ids: [], last_trace_id: null };
|
|
178
|
+
if (!fs.existsSync(indexPath))
|
|
179
|
+
return empty;
|
|
180
|
+
// SAFETY: index.json is written by writeIndexMirror as a HippoIndex; readers default every field, so only the object shape is checked.
|
|
181
|
+
return readLegacyJsonObject(indexPath) ?? empty;
|
|
177
182
|
}
|
|
178
183
|
function loadLegacyStatsFile(hippoRoot) {
|
|
179
184
|
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
|
-
}
|
|
185
|
+
const empty = { total_remembered: 0, total_recalled: 0, total_forgotten: 0, consolidation_runs: [] };
|
|
186
|
+
if (!fs.existsSync(statsPath))
|
|
187
|
+
return empty;
|
|
188
|
+
// SAFETY: callers guard every field read with `?? 0` / `Array.isArray`, so only the object shape is checked.
|
|
189
|
+
return readLegacyJsonObject(statsPath) ?? empty;
|
|
202
190
|
}
|
|
203
191
|
//# 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
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import type { AmbientTallies } from '../core/ambient.js';
|
|
2
2
|
import type { AmbientStoreFilter } from './ambient.js';
|
|
3
3
|
import type { ApiKeyListRow, ApiKeyRecord, ListApiKeysOpts, NewApiKey } from './auth.js';
|
|
4
|
-
import type { AppendAuditOpts, AuditEvent, ListAuditAfterOpts, QueryAuditOpts } from './audit.js';
|
|
4
|
+
import type { AppendAuditOpts, AuditEvent, AuditPrune, ListAuditAfterOpts, QueryAuditOpts } from './audit.js';
|
|
5
|
+
import type { QualityRepairResult } from './quality-repair.js';
|
|
5
6
|
import type { EmbeddingIndexState } from './vector-index.js';
|
|
6
7
|
import type { Entity, Relation } from './graph-rows.js';
|
|
7
8
|
import type { ActiveGoals, GetActiveGoalsOpts, GoalRecallLogRow } from './goals.js';
|
|
@@ -10,13 +11,14 @@ import type { JsonValue } from '../util/json.js';
|
|
|
10
11
|
import type { KeysetPosition } from '../util/keyset.js';
|
|
11
12
|
import type { MemoryEntry } from '../core/memory.js';
|
|
12
13
|
import type { PhysicsParticle } from '../core/physics.js';
|
|
13
|
-
import type { BriefReceipt, Incident, IncidentFields, ObjectByKind, ObjectFields, ObjectKind, Policy, SavableKind, Skill } from '
|
|
14
|
+
import type { BriefReceipt, Incident, IncidentFields, ObjectByKind, ObjectFields, ObjectKind, Policy, SavableKind, Skill } from '../core/object-types.js';
|
|
14
15
|
import type { PlanningFallacyEvidence } from './planning-fallacy-evidence.js';
|
|
15
|
-
import type {
|
|
16
|
+
import type { Prediction, PredictionBaserate, SavePredictionOpts } from './predictions.js';
|
|
17
|
+
import type { ClosureState } from '../core/prediction.js';
|
|
16
18
|
import type { QuarantineRow, QuarantineStatus } from './quarantine.js';
|
|
17
|
-
import type { ScopeActor } from '
|
|
19
|
+
import type { ScopeActor } from '../core/recall-scope.js';
|
|
18
20
|
import type { RecallTraceInput } from './recall-trace.js';
|
|
19
|
-
import type { AmbientLoadResult, AmbientRecallRequest, ContextCandidateFilter, RecentOrigins } from './candidates.js';
|
|
21
|
+
import type { AmbientLoadResult, AmbientRecallRequest, ContextCandidateFilter, HeldText, RecentOrigins } from './candidates.js';
|
|
20
22
|
import type { GitHubDlqInsert, GitHubRouting } from './connectors/github.js';
|
|
21
23
|
import type { SlackDlqInsert, SlackTeamRoute } from './connectors/slack.js';
|
|
22
24
|
import type { StrengthenOptions } from './entry-writes.js';
|
|
@@ -410,6 +412,18 @@ export interface Readiness {
|
|
|
410
412
|
/** Resolves once one cheap read has answered; rejects with the store's own error when it cannot. */
|
|
411
413
|
ping(): Promise<void>;
|
|
412
414
|
}
|
|
415
|
+
/** A recall's writes when the store keeps it as its last one: `strengthen.ids` are the ids it returned. */
|
|
416
|
+
export type LastRecallWrites = RecallWrites & Required<Pick<RecallWrites, 'strengthen'>>;
|
|
417
|
+
/** The last recall a store keeps, so a later outcome can name it, and the outcome linked to a recall trace. */
|
|
418
|
+
export interface LastRecall {
|
|
419
|
+
/** entryWrites.applyOutcome, then a link from recall trace `traceId` to the ids applied; resolves to those ids. */
|
|
420
|
+
applyTracedOutcome(outcome: OutcomeWrite, traceId: number): Promise<string[]>;
|
|
421
|
+
/** applyTracedOutcome on the ids and trace of the last recall, read together so an outcome never pairs them with an older trace. */
|
|
422
|
+
applyOutcomeToLast(target: EntryTarget, good: boolean): Promise<string[]>;
|
|
423
|
+
/** finishRecall, then the ids this store lacks strengthened under `globalRoot`, then the ids and their trace saved as the last
|
|
424
|
+
* recall in one write; resolves to the trace id, null when none was asked or its write failed. */
|
|
425
|
+
finishRecall(writes: LastRecallWrites, globalRoot: string | undefined): Promise<number | null>;
|
|
426
|
+
}
|
|
413
427
|
/** Which of a tenant's quarantine records a list reads; `limit` is 100 when unset. */
|
|
414
428
|
export interface QuarantineListQuery {
|
|
415
429
|
readonly status: QuarantineStatus | 'all';
|
|
@@ -574,8 +588,49 @@ export interface VectorViews {
|
|
|
574
588
|
/** The same ids and values as `VectorReads.storedVectors`, each value a Float32 view. */
|
|
575
589
|
storedVectorViews(ids: readonly string[]): Promise<Map<string, Float32Array>>;
|
|
576
590
|
}
|
|
591
|
+
/** The store is hippo.db and its files under `hippoRoot`, so a path that reopens them by folder (sleep, its child process, the global store) may run. */
|
|
592
|
+
export interface LocalFiles {
|
|
593
|
+
readonly hippoRoot: string;
|
|
594
|
+
}
|
|
595
|
+
/** The reads and writes behind the memory-quality audit, its repair and audit-log retention. */
|
|
596
|
+
export interface AuditMaintenance {
|
|
597
|
+
/** Every memory of the tenant, in `loadAllEntries` order. */
|
|
598
|
+
tenantEntries(tenantId: string): Promise<MemoryEntry[]>;
|
|
599
|
+
/** The ids of every memory a typed object row names, in any tenant; an automatic pass never deletes one. */
|
|
600
|
+
objectBackedIds(): Promise<Set<string>>;
|
|
601
|
+
/** Deletes each removal's row with its own forget row, leaving a pinned, raw, kept or object-backing row; resolves to the ids deleted. */
|
|
602
|
+
deleteAutomatically(removals: readonly {
|
|
603
|
+
readonly id: string;
|
|
604
|
+
readonly reason: string;
|
|
605
|
+
}[], actor: string): Promise<string[]>;
|
|
606
|
+
/** Counts (dryRun) or deletes the tenant's audit rows before `cutoff`, then appends one audit_prune row; resolves to the count. */
|
|
607
|
+
pruneAuditRows(prune: AuditPrune): Promise<number>;
|
|
608
|
+
/** A preview, or with `apply` the moves of certain defects to dormant storage behind a backup. */
|
|
609
|
+
repairQuality(tenantId: string, apply: boolean): Promise<QualityRepairResult>;
|
|
610
|
+
/** repairQuality applied once per store; null once it ran there. */
|
|
611
|
+
repairQualityOnce(tenantId: string): Promise<QualityRepairResult | null>;
|
|
612
|
+
}
|
|
613
|
+
/** The reads and writes behind git auto-learn's batch. */
|
|
614
|
+
export interface LessonWrites {
|
|
615
|
+
/** Every memory of the tenant, in `loadAllEntries` order. */
|
|
616
|
+
tenantEntries(tenantId: string): Promise<MemoryEntry[]>;
|
|
617
|
+
/** Content, source and origin of the tenant's rows holding any of `words`, among the rows a team member or `ownScope`'s owner may touch. */
|
|
618
|
+
textsHoldingWords(tenantId: string, words: readonly string[], ownScope: string | null): Promise<HeldText[]>;
|
|
619
|
+
/** Writes each entry in one transaction; a rejected value writes its refusal row and is skipped. Resolves to the ids written. */
|
|
620
|
+
writeSkippingRejected(entries: readonly MemoryEntry[], actor: string): Promise<string[]>;
|
|
621
|
+
/** Rewrites each entry in one transaction, all or none. */
|
|
622
|
+
writeTogether(entries: readonly MemoryEntry[]): Promise<void>;
|
|
623
|
+
/** Adds `count` to the store-wide remembered counter. */
|
|
624
|
+
bumpRemembered(count: number): Promise<void>;
|
|
625
|
+
}
|
|
577
626
|
/** The optional groups: a store sets each one whole or leaves it unset, and a route or MCP tool names the one it needs. */
|
|
578
627
|
export interface StoreGroups {
|
|
628
|
+
/** Unset on any store but hippo.db; a request then runs fenced from hippo.db, and a route or tool that names no group answers 501. */
|
|
629
|
+
readonly localFiles: LocalFiles;
|
|
630
|
+
/** Unset on a store without it, where the quality audit, its repair and audit prune answer 501. */
|
|
631
|
+
readonly auditMaintenance: AuditMaintenance;
|
|
632
|
+
/** Unset on a store without it, where git learn answers 501. */
|
|
633
|
+
readonly lessonWrites: LessonWrites;
|
|
579
634
|
/** Unset on a store built before them, where hybrid and physics recall under an embedding provider answer 501. */
|
|
580
635
|
readonly vectors: VectorReads;
|
|
581
636
|
/** Unset on a store without them, where recall scores the number[] copies `vectors` returns, to the same ranking. */
|
|
@@ -598,15 +653,22 @@ export interface StoreGroups {
|
|
|
598
653
|
readonly objects: Objects;
|
|
599
654
|
/** Unset on a store built before it, where GET /ready answers 200 with `store: "unchecked"`. */
|
|
600
655
|
readonly readiness: Readiness;
|
|
656
|
+
/** Unset on a store that keeps no last recall, where outcomeForLastRecall and a traced outcome answer 501 and context writes no last recall. */
|
|
657
|
+
readonly lastRecall: LastRecall;
|
|
601
658
|
}
|
|
602
659
|
export type StoreGroup = 'base' | keyof StoreGroups;
|
|
603
660
|
export declare function hasGroup(store: HippoStore, group: StoreGroup): boolean;
|
|
604
661
|
/** The group's methods; a store without them throws StoreNotPortedError, which answers 501 as any unported path does. */
|
|
605
662
|
export declare function requireGroup<G extends keyof StoreGroups>(store: HippoStore, group: G): StoreGroups[G];
|
|
663
|
+
export declare const STORE_BUSY_MESSAGE = "store busy (another hippo process holds the write lock); retry shortly";
|
|
664
|
+
/** 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. */
|
|
665
|
+
export declare class StoreBusyError extends Error {
|
|
666
|
+
constructor(message?: string, options?: ErrorOptions);
|
|
667
|
+
}
|
|
606
668
|
/** What `serve()` reads and writes through. Each method is atomic and no transaction spans an
|
|
607
669
|
* await, since SQLite's lock wait blocks the event loop; a lock timeout throws `StoreBusyError`. */
|
|
608
670
|
export interface HippoStore extends Partial<StoreGroups> {
|
|
609
|
-
/**
|
|
671
|
+
/** A name for logs and errors; what a store can do is the groups it sets, `localFiles` above all. */
|
|
610
672
|
readonly kind: string;
|
|
611
673
|
/** The api_keys row for `keyId` with its scope grants, revoked or not; null when no row matches. */
|
|
612
674
|
findApiKey(keyId: string): Promise<ApiKeyRecord | null>;
|
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
|
|
@@ -133,7 +133,7 @@ function setAsideIssue(db, entry, reason, now, backup) {
|
|
|
133
133
|
if (getMeta(db, 'fts5_available', '0') === '1' && ftsRowExists(db, entry.id)) {
|
|
134
134
|
throw new Error(`Quality repair could not remove the full-text row for ${entry.id}`);
|
|
135
135
|
}
|
|
136
|
-
appendAuditEvent(db, { tenantId: entry.
|
|
136
|
+
appendAuditEvent(db, { tenantId: entry.tenant_id, actor, op: 'quality_repair', targetId: entry.id, metadata: { reason, backup } });
|
|
137
137
|
return true;
|
|
138
138
|
}
|
|
139
139
|
function applyPlan(db, root, tenantId, backup, doneKey) {
|
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,11 +1,13 @@
|
|
|
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';
|
|
8
9
|
import { blockHash } from '../util/token-text.js';
|
|
10
|
+
import { placeholders } from '../util/sql.js';
|
|
9
11
|
/** Strip a RerankStep to {stage, multiplier, scoreBefore, scoreAfter}: `note` is free-form (the CLI goal-boost step embeds goal tag text) and would leak
|
|
10
12
|
* user content into `rerank_json`; an allowlist, so any future free-form field is dropped too. */
|
|
11
13
|
function sanitizeRerankSteps(steps) {
|
|
@@ -105,7 +107,7 @@ const DELIVERY_EVENT_COLUMNS = [
|
|
|
105
107
|
'session_id', 'session_state', 'host_turn_id', 'turn_seq', 'duplicate_of', 'prompt_hash', 'prompt_length', 'query_hash',
|
|
106
108
|
'recall_trace_id', 'block_state', 'prompt_recall', 'considered_count', 'filtered_count', 'selected_count', 'emitted_count',
|
|
107
109
|
'rejected_count', 'rejected_unlisted', 'sections_shown', 'sections_dropped', 'budget_tokens', 'selected_tokens',
|
|
108
|
-
'injected_tokens', 'static_hash', 'recall_hash', 'emitted_hash', 'elapsed_ms',
|
|
110
|
+
'injected_tokens', 'static_hash', 'recall_hash', 'emitted_hash', 'elapsed_ms', 'tool_use_id', 'failure_id',
|
|
109
111
|
];
|
|
110
112
|
function findDuplicateBoundary(db, input) {
|
|
111
113
|
// SAFETY: rows carry exactly the `id` and `ts` columns selected.
|
|
@@ -117,7 +119,21 @@ function findDuplicateBoundary(db, input) {
|
|
|
117
119
|
const at = Date.parse(input.ts);
|
|
118
120
|
return rows.find((r) => Math.abs(Date.parse(r.ts) - at) <= DELIVERY_DUPLICATE_WINDOW_MS)?.id ?? null;
|
|
119
121
|
}
|
|
122
|
+
function findDuplicateToolFailure(db, input) {
|
|
123
|
+
// Without a call id a time window would merge parallel failures, so two such fires stay two rows.
|
|
124
|
+
if (input.toolUseId === undefined || input.toolUseId === null)
|
|
125
|
+
return null;
|
|
126
|
+
// SAFETY: a single `id` column, undefined when no row matches.
|
|
127
|
+
const row = db.prepare(`
|
|
128
|
+
SELECT id FROM delivery_events
|
|
129
|
+
WHERE tenant_id = ? AND session_id = ? AND event_type = ? AND tool_use_id = ? AND turn_seq IS NOT NULL
|
|
130
|
+
ORDER BY id LIMIT 1
|
|
131
|
+
`).get(input.tenantId, input.sessionId, input.eventType, input.toolUseId);
|
|
132
|
+
return row?.id ?? null;
|
|
133
|
+
}
|
|
120
134
|
function findDuplicateTurn(db, input) {
|
|
135
|
+
if (input.eventType === 'tool-failure')
|
|
136
|
+
return findDuplicateToolFailure(db, input);
|
|
121
137
|
// A boundary has no prompt, and two compactions of one session never start within the window, so time alone decides.
|
|
122
138
|
if (isBoundaryEvent(input.eventType))
|
|
123
139
|
return findDuplicateBoundary(db, input);
|
|
@@ -165,10 +181,11 @@ export function writeDeliveryEvent(db, input) {
|
|
|
165
181
|
input.consideredCount, input.filteredCount, input.selectedCount, input.emittedCount, input.rejectedCount,
|
|
166
182
|
input.rejectedUnlisted, input.sectionsShown, input.sectionsDropped, input.budgetTokens, input.selectedTokens,
|
|
167
183
|
input.injectedTokens, input.staticHash, input.recallHash, input.emittedHash, Math.round(input.elapsedMs),
|
|
184
|
+
input.toolUseId ?? null, input.failureId ?? null,
|
|
168
185
|
];
|
|
169
186
|
const eventId = Number(db.prepare(`
|
|
170
187
|
INSERT INTO delivery_events (${DELIVERY_EVENT_COLUMNS.join(', ')})
|
|
171
|
-
VALUES (${DELIVERY_EVENT_COLUMNS.
|
|
188
|
+
VALUES (${placeholders(DELIVERY_EVENT_COLUMNS.length)})
|
|
172
189
|
`).run(...values).lastInsertRowid);
|
|
173
190
|
const insertCandidate = db.prepare(`
|
|
174
191
|
INSERT INTO delivery_candidates (event_id, tenant_id, memory_id, source_store, pool, stage, outcome, reason, cand_rank, score, tokens)
|