hippo-memory 1.71.0 → 1.72.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/agent-memories/apply.d.ts +0 -11
- package/dist/agent-memories/apply.js +6 -21
- package/dist/agent-memories/claude-code.js +1 -1
- package/dist/agent-memories/codex.js +1 -1
- package/dist/agent-memories/copilot.d.ts +1 -3
- package/dist/agent-memories/copilot.js +1 -17
- package/dist/agent-memories/project-folds.d.ts +10 -0
- package/dist/agent-memories/project-folds.js +34 -0
- package/dist/agent-memories/sync.js +8 -6
- package/dist/api/assemble.js +1 -1
- package/dist/api/audit.d.ts +29 -1
- package/dist/api/audit.js +44 -5
- package/dist/api/auth.d.ts +7 -4
- package/dist/api/auth.js +12 -8
- package/dist/api/auto-sleep.d.ts +5 -2
- package/dist/api/auto-sleep.js +7 -3
- package/dist/api/availability.js +2 -3
- package/dist/api/cards.d.ts +42 -0
- package/dist/api/cards.js +52 -0
- package/dist/api/conflicts.d.ts +28 -0
- package/dist/api/conflicts.js +61 -0
- package/dist/api/context-render.js +4 -3
- package/dist/api/context-select.js +9 -11
- package/dist/api/context.js +17 -8
- package/dist/api/continuity.d.ts +47 -0
- package/dist/api/continuity.js +66 -0
- package/dist/api/dormant.js +4 -2
- package/dist/api/drill-down.js +1 -1
- package/dist/api/embeddings.d.ts +17 -0
- package/dist/api/embeddings.js +28 -0
- package/dist/api/error-reply.d.ts +8 -0
- package/dist/api/error-reply.js +21 -0
- package/dist/api/forget.d.ts +6 -2
- package/dist/api/forget.js +18 -7
- package/dist/api/goals.d.ts +1 -1
- package/dist/api/goals.js +5 -9
- package/dist/api/index.d.ts +4 -2
- package/dist/api/index.js +4 -2
- package/dist/api/instruction-detect.js +5 -1
- package/dist/api/learn.d.ts +4 -0
- package/dist/api/learn.js +53 -27
- package/dist/api/ledger-db.d.ts +2 -6
- package/dist/api/ledger-db.js +4 -36
- package/dist/api/memories.d.ts +19 -1
- package/dist/api/memories.js +39 -0
- package/dist/api/objects.d.ts +1 -1
- package/dist/api/outcome.js +1 -1
- package/dist/api/pilot-arm.d.ts +1 -11
- package/dist/api/pilot-arm.js +5 -45
- package/dist/api/predictions.d.ts +3 -1
- package/dist/api/predictions.js +6 -0
- package/dist/api/projects.d.ts +21 -0
- package/dist/api/projects.js +24 -0
- package/dist/api/promote.js +1 -1
- package/dist/api/prompt-hook.d.ts +15 -2
- package/dist/api/prompt-hook.js +44 -4
- package/dist/api/recall-cli.d.ts +3 -0
- package/dist/api/recall-cli.js +13 -4
- package/dist/api/recall-core.js +3 -3
- package/dist/api/recall-pipeline.js +6 -7
- package/dist/api/recall-request.js +1 -1
- package/dist/api/recall.d.ts +0 -3
- package/dist/api/recall.js +19 -44
- package/dist/api/remember-local.js +1 -1
- package/dist/api/remember.d.ts +2 -1
- package/dist/api/remember.js +3 -2
- package/dist/api/session-end.d.ts +22 -0
- package/dist/api/session-end.js +101 -0
- package/dist/api/sleep-run.d.ts +1 -1
- package/dist/api/sleep-run.js +13 -9
- package/dist/api/status.d.ts +24 -0
- package/dist/api/status.js +40 -0
- package/dist/api/store-init.d.ts +4 -0
- package/dist/api/store-init.js +9 -0
- package/dist/api/tokens.js +1 -1
- package/dist/api/types.d.ts +2 -0
- package/dist/api/types.js +6 -1
- package/dist/capture/caller-session.d.ts +0 -3
- package/dist/capture/caller-session.js +1 -12
- package/dist/capture/capture-error.d.ts +2 -2
- package/dist/capture/capture-error.js +23 -18
- package/dist/capture/codex-patch.js +3 -1
- package/dist/capture/command.js +36 -95
- package/dist/capture/compact.js +10 -5
- package/dist/capture/compaction-items-caller.js +11 -20
- package/dist/capture/compaction-record.d.ts +7 -93
- package/dist/capture/compaction-record.js +29 -426
- package/dist/capture/compaction-spool.d.ts +4 -2
- package/dist/capture/compaction-spool.js +20 -6
- package/dist/capture/copilot-transcript.d.ts +2 -1
- package/dist/capture/copilot-transcript.js +2 -1
- package/dist/capture/extract.d.ts +5 -2
- package/dist/capture/extract.js +4 -3
- package/dist/capture/failure-caller.d.ts +1 -1
- package/dist/capture/failure-caller.js +21 -16
- package/dist/capture/failure-reading.d.ts +2 -1
- package/dist/capture/failure-reading.js +7 -9
- package/dist/capture/pre-compact-caller.js +5 -4
- package/dist/capture/session-digest.js +4 -3
- package/dist/capture/session-end-caller.js +2 -1
- package/dist/capture/session-worker.js +3 -4
- package/dist/capture/transcript.d.ts +2 -1
- package/dist/capture/transcript.js +6 -3
- package/dist/capture/working-state.d.ts +4 -2
- package/dist/capture/working-state.js +4 -2
- package/dist/cli/audit-prune.d.ts +0 -25
- package/dist/cli/audit-prune.js +1 -27
- package/dist/cli/audit.js +13 -13
- package/dist/cli/auth.d.ts +1 -1
- package/dist/cli/auth.js +12 -13
- package/dist/cli/briefs.d.ts +1 -4
- package/dist/cli/briefs.js +37 -292
- package/dist/cli/card.js +41 -33
- package/dist/cli/client.d.ts +5 -0
- package/dist/cli/client.js +24 -8
- package/dist/cli/compact-resume-payload.js +1 -1
- package/dist/cli/context.d.ts +1 -1
- package/dist/cli/context.js +12 -12
- package/dist/cli/continuity.d.ts +1 -1
- package/dist/cli/continuity.js +36 -39
- package/dist/cli/curate.d.ts +1 -1
- package/dist/cli/curate.js +23 -27
- package/dist/cli/dag.d.ts +1 -1
- package/dist/cli/dag.js +23 -8
- package/dist/cli/decisions.d.ts +0 -2
- package/dist/cli/decisions.js +4 -281
- package/dist/cli/eval.d.ts +1 -1
- package/dist/cli/eval.js +12 -13
- package/dist/cli/explain.d.ts +1 -1
- package/dist/cli/explain.js +21 -25
- package/dist/cli/flag-values.js +16 -6
- package/dist/cli/flags.d.ts +0 -289
- package/dist/cli/flags.js +3 -138
- package/dist/cli/graph.d.ts +3 -0
- package/dist/cli/graph.js +83 -0
- package/dist/cli/hook-runtime.d.ts +3 -5
- package/dist/cli/hook-runtime.js +7 -34
- package/dist/cli/incidents.d.ts +3 -0
- package/dist/cli/incidents.js +112 -0
- package/dist/cli/init.d.ts +1 -1
- package/dist/cli/init.js +28 -19
- package/dist/cli/install-steps.d.ts +2 -1
- package/dist/cli/install-steps.js +11 -3
- package/dist/cli/last-sleep.js +1 -1
- package/dist/cli/lenient-id.d.ts +2 -0
- package/dist/cli/lenient-id.js +13 -0
- package/dist/cli/maintenance.d.ts +3 -3
- package/dist/cli/maintenance.js +29 -30
- package/dist/cli/notes.d.ts +2 -0
- package/dist/cli/notes.js +41 -0
- package/dist/cli/open-browser.d.ts +14 -0
- package/dist/cli/open-browser.js +26 -0
- package/dist/cli/playbooks.d.ts +3 -4
- package/dist/cli/playbooks.js +126 -290
- package/dist/cli/predictions.d.ts +3 -0
- package/dist/cli/predictions.js +175 -0
- package/dist/cli/print.js +2 -1
- package/dist/cli/projects.js +30 -22
- package/dist/cli/quality-repair-once.d.ts +1 -1
- package/dist/cli/quality-repair-once.js +6 -5
- package/dist/cli/recall.js +13 -7
- package/dist/cli/refine-llm.js +17 -17
- package/dist/cli/remember.js +12 -12
- package/dist/cli/scheduler.js +2 -1
- package/dist/cli/serve.js +3 -3
- package/dist/cli/session-hooks.d.ts +1 -1
- package/dist/cli/session-hooks.js +45 -115
- package/dist/cli/setup.d.ts +1 -1
- package/dist/cli/setup.js +17 -10
- package/dist/cli/shared.d.ts +2 -6
- package/dist/cli/shared.js +9 -29
- package/dist/cli/sleep-render.js +6 -3
- package/dist/cli/sleep.js +6 -37
- package/dist/cli/status.d.ts +3 -3
- package/dist/cli/status.js +32 -35
- package/dist/cli/transfer.d.ts +1 -1
- package/dist/cli/transfer.js +33 -31
- package/dist/cli/usage.d.ts +0 -79
- package/dist/cli/usage.js +1 -695
- package/dist/cli/verb-row.d.ts +32 -0
- package/dist/cli/verb-row.js +6 -0
- package/dist/cli/verbs/health.d.ts +27 -0
- package/dist/cli/verbs/health.js +232 -0
- package/dist/cli/verbs/memory.d.ts +16 -0
- package/dist/cli/verbs/memory.js +244 -0
- package/dist/cli/verbs/objects.d.ts +20 -0
- package/dist/cli/verbs/objects.js +254 -0
- package/dist/cli/verbs/sessions.d.ts +31 -0
- package/dist/cli/verbs/sessions.js +312 -0
- package/dist/cli/verbs.d.ts +81 -0
- package/dist/cli/verbs.js +7 -0
- package/dist/cli/versioned-verbs.d.ts +51 -0
- package/dist/cli/versioned-verbs.js +79 -0
- package/dist/cli.d.ts +1 -272
- package/dist/cli.js +23 -313
- package/dist/connectors/dlq.d.ts +39 -3
- package/dist/connectors/dlq.js +37 -3
- package/dist/connectors/github/backfill.js +12 -3
- package/dist/connectors/github/dlq.js +31 -73
- package/dist/connectors/github/ingest.d.ts +2 -6
- package/dist/connectors/github/ingest.js +3 -28
- package/dist/connectors/github/webhook.d.ts +2 -1
- package/dist/connectors/github/webhook.js +33 -2
- package/dist/connectors/ingest.d.ts +10 -0
- package/dist/connectors/ingest.js +28 -0
- package/dist/connectors/slack/dlq.js +49 -71
- package/dist/connectors/slack/ingest.d.ts +2 -6
- package/dist/connectors/slack/ingest.js +2 -27
- package/dist/connectors/slack/webhook.d.ts +2 -1
- package/dist/connectors/slack/webhook.js +2 -1
- package/dist/consolidate/conflicts.js +1 -1
- package/dist/consolidate/dag.js +15 -9
- package/dist/consolidate/dedupe.d.ts +7 -0
- package/dist/consolidate/dedupe.js +5 -3
- package/dist/consolidate/llm-passes.js +45 -19
- package/dist/consolidate/memory-value.js +2 -1
- package/dist/consolidate/merge.js +2 -2
- package/dist/consolidate/physics-pass.d.ts +6 -1
- package/dist/consolidate/physics-pass.js +26 -6
- package/dist/consolidate/replay.js +11 -4
- package/dist/consolidate/sleep.js +8 -5
- package/dist/consolidate/traces.js +3 -3
- package/dist/core/ablation.d.ts +10 -0
- package/dist/core/ablation.js +12 -0
- package/dist/{sharing/scope.d.ts → core/active-scope.d.ts} +1 -1
- package/dist/{sharing/scope.js → core/active-scope.js} +1 -1
- package/dist/core/ambient.d.ts +4 -0
- package/dist/core/ambient.js +39 -18
- package/dist/core/api-errors.d.ts +16 -0
- package/dist/core/api-errors.js +20 -0
- package/dist/core/card.js +3 -1
- package/dist/core/compaction-timing.d.ts +7 -0
- package/dist/core/compaction-timing.js +9 -0
- package/dist/core/config.d.ts +1 -1
- package/dist/core/config.js +7 -2
- package/dist/core/cosine.d.ts +3 -0
- package/dist/core/cosine.js +19 -0
- package/dist/{store → core}/markdown.d.ts +1 -1
- package/dist/{store → core}/markdown.js +2 -2
- package/dist/core/memory-audit.d.ts +17 -0
- package/dist/core/memory-audit.js +54 -0
- package/dist/core/memory.d.ts +10 -4
- package/dist/core/memory.js +25 -18
- package/dist/{consolidate → core}/merged-row.d.ts +1 -1
- package/dist/{consolidate → core}/merged-row.js +1 -1
- package/dist/core/physics.js +6 -16
- package/dist/core/prediction.d.ts +3 -0
- package/dist/core/prediction.js +6 -0
- package/dist/core/project-identity.d.ts +3 -0
- package/dist/core/project-identity.js +10 -1
- package/dist/{store → core}/recall-scope.d.ts +1 -10
- package/dist/{store → core}/recall-scope.js +2 -19
- package/dist/db/busy.d.ts +2 -7
- package/dist/db/busy.js +21 -26
- package/dist/db/connect.d.ts +0 -1
- package/dist/db/connect.js +5 -6
- package/dist/db/index.d.ts +3 -3
- package/dist/db/index.js +3 -3
- package/dist/db/migrations/index.d.ts +1 -1
- package/dist/db/migrations/index.js +3 -1
- package/dist/db/migrations/v55.d.ts +3 -0
- package/dist/db/migrations/v55.js +17 -0
- package/dist/db/open.d.ts +0 -2
- package/dist/db/open.js +6 -10
- package/dist/db/physics-state.js +3 -3
- package/dist/db/tables.d.ts +2 -0
- package/dist/db/tables.js +6 -2
- package/dist/db/vector-store.js +17 -4
- package/dist/db/wal-checkpointer.js +2 -1
- package/dist/doctor.js +11 -8
- package/dist/embeddings/local.d.ts +62 -0
- package/dist/embeddings/local.js +146 -0
- package/dist/{store/embeddings → embeddings}/provider.d.ts +5 -2
- package/dist/{store/embeddings → embeddings}/provider.js +18 -15
- package/dist/embeddings/transformers.d.ts +26 -0
- package/dist/embeddings/transformers.js +89 -0
- package/dist/entry/session-text.d.ts +1 -1
- package/dist/entry/session-text.js +1 -1
- package/dist/eval/eval-suite.js +17 -11
- package/dist/eval/eval.js +1 -1
- package/dist/eval/judgment.js +11 -4
- package/dist/graph/extract.js +3 -3
- package/dist/graph/recall.js +1 -1
- package/dist/graph/view.js +13 -5
- package/dist/graph/write.d.ts +1 -1
- package/dist/graph/write.js +9 -9
- package/dist/hooks/codex-session.js +3 -2
- package/dist/hooks/codex-wrapper.js +2 -1
- package/dist/hooks/json-hooks.js +4 -2
- package/dist/hooks/opencode.js +8 -5
- package/dist/hooks/shared.d.ts +0 -6
- package/dist/hooks/shared.js +4 -15
- package/dist/importers/core.js +1 -1
- package/dist/importers/sources.js +5 -4
- package/dist/importers/vault.js +7 -5
- package/dist/index.d.ts +3 -2
- package/dist/index.js +3 -2
- package/dist/learn/autolearn.d.ts +10 -2
- package/dist/learn/autolearn.js +32 -12
- package/dist/learn/churn-git.js +13 -4
- package/dist/learn/extract.d.ts +3 -2
- package/dist/learn/extract.js +6 -4
- package/dist/learn/forward-claim-detector.js +4 -2
- package/dist/learn/invalidation.js +10 -6
- package/dist/mcp/admin-tools.d.ts +2 -2
- package/dist/mcp/admin-tools.js +27 -48
- package/dist/mcp/format.js +3 -2
- package/dist/mcp/framing.d.ts +1 -0
- package/dist/mcp/framing.js +1 -1
- package/dist/mcp/memory-tools.js +3 -1
- package/dist/mcp/protocol.d.ts +11 -7
- package/dist/mcp/protocol.js +25 -12
- package/dist/mcp/recall-tools.js +12 -9
- package/dist/mcp/request.js +2 -1
- package/dist/mcp/stdio.js +24 -8
- package/dist/mcp/tool-args.js +2 -1
- package/dist/mcp/tools.js +44 -21
- package/dist/objects/customer-notes.d.ts +2 -2
- package/dist/objects/decisions.d.ts +2 -2
- package/dist/objects/descriptor.d.ts +1 -1
- package/dist/objects/incidents.d.ts +2 -2
- package/dist/objects/lifecycle.d.ts +1 -1
- package/dist/objects/lifecycle.js +2 -1
- package/dist/objects/policies.d.ts +2 -2
- package/dist/objects/policies.js +2 -1
- package/dist/objects/processes.d.ts +2 -2
- package/dist/objects/project-briefs.d.ts +2 -2
- package/dist/objects/project-briefs.js +2 -3
- package/dist/objects/skills.d.ts +2 -2
- package/dist/postinstall.js +1 -1
- package/dist/rerankers/clef.js +3 -6
- package/dist/rerankers/cross-encoder.d.ts +31 -2
- package/dist/rerankers/cross-encoder.js +63 -97
- package/dist/rerankers/index.js +5 -4
- package/dist/rerankers/jev.js +2 -4
- package/dist/rerankers/outage-warning.d.ts +3 -1
- package/dist/rerankers/outage-warning.js +5 -3
- package/dist/search/bm25-search.js +1 -1
- package/dist/search/boosts.js +1 -1
- package/dist/search/embed-memories.d.ts +9 -0
- package/dist/search/embed-memories.js +377 -0
- package/dist/search/goal-boost.d.ts +1 -1
- package/dist/search/goal-boost.js +6 -3
- package/dist/search/hybrid.d.ts +9 -2
- package/dist/search/hybrid.js +9 -4
- package/dist/search/physics-search.d.ts +6 -3
- package/dist/search/physics-search.js +22 -15
- package/dist/search/rerank.js +1 -1
- package/dist/search/vector.d.ts +8 -6
- package/dist/search/vector.js +10 -13
- package/dist/server/auth.d.ts +2 -0
- package/dist/server/auth.js +17 -7
- package/dist/server/boot.js +7 -66
- package/dist/server/client-ip.d.ts +0 -2
- package/dist/server/client-ip.js +3 -2
- package/dist/server/deadline.d.ts +0 -2
- package/dist/server/deadline.js +1 -7
- package/dist/server/defaults.d.ts +1 -0
- package/dist/server/defaults.js +1 -0
- package/dist/server/mcp-http.js +16 -11
- package/dist/server/request.js +7 -2
- package/dist/server/route-checks.d.ts +7 -0
- package/dist/server/route-checks.js +42 -0
- package/dist/server/route-table.d.ts +9 -8
- package/dist/server/route-table.js +127 -132
- package/dist/server/routes/admin.d.ts +8 -8
- package/dist/server/routes/admin.js +13 -21
- package/dist/server/routes/customer-notes.d.ts +6 -6
- package/dist/server/routes/customer-notes.js +1 -2
- package/dist/server/routes/decisions.d.ts +6 -6
- package/dist/server/routes/decisions.js +2 -4
- package/dist/server/routes/incidents.d.ts +6 -6
- package/dist/server/routes/incidents.js +2 -5
- package/dist/server/routes/memories.d.ts +9 -9
- package/dist/server/routes/memories.js +15 -38
- package/dist/server/routes/object-routes.d.ts +6 -6
- package/dist/server/routes/object-routes.js +4 -7
- package/dist/server/routes/policies.d.ts +7 -7
- package/dist/server/routes/policies.js +2 -4
- package/dist/server/routes/predictions.d.ts +6 -6
- package/dist/server/routes/predictions.js +9 -13
- package/dist/server/routes/processes.d.ts +6 -6
- package/dist/server/routes/processes.js +1 -2
- package/dist/server/routes/project-briefs.d.ts +7 -7
- package/dist/server/routes/project-briefs.js +2 -4
- package/dist/server/routes/recall.d.ts +5 -5
- package/dist/server/routes/recall.js +6 -10
- package/dist/server/routes/skills.d.ts +7 -7
- package/dist/server/routes/skills.js +2 -4
- package/dist/server/server-detect.d.ts +7 -1
- package/dist/server/server-detect.js +36 -11
- package/dist/server/sleep-child.js +26 -7
- package/dist/server/sleep-offload.d.ts +11 -5
- package/dist/server/sleep-offload.js +17 -11
- package/dist/server/types.d.ts +22 -10
- package/dist/server/validation.d.ts +1 -2
- package/dist/server/validation.js +6 -11
- package/dist/server.d.ts +5 -4
- package/dist/server.js +5 -4
- package/dist/sharing/global-store.js +2 -2
- package/dist/sharing/global-sync.js +38 -45
- package/dist/sharing/project-merge.d.ts +7 -14
- package/dist/sharing/project-merge.js +57 -121
- package/dist/sharing/search-both.js +1 -1
- package/dist/sharing/share.d.ts +2 -0
- package/dist/sharing/share.js +37 -34
- package/dist/store/ambient.js +5 -6
- package/dist/store/audit-event.d.ts +1 -1
- package/dist/store/audit.d.ts +0 -16
- package/dist/store/audit.js +4 -55
- package/dist/store/auth.d.ts +4 -2
- package/dist/store/auth.js +7 -3
- package/dist/store/candidates.d.ts +3 -2
- package/dist/store/candidates.js +42 -23
- package/dist/store/capture-write.d.ts +17 -0
- package/dist/store/capture-write.js +35 -0
- package/dist/store/cards.js +1 -1
- package/dist/store/compaction-caller.d.ts +18 -0
- package/dist/store/compaction-caller.js +29 -0
- package/dist/store/compactions-record.d.ts +115 -0
- package/dist/store/compactions-record.js +417 -0
- package/dist/store/compactions.js +6 -4
- package/dist/store/conflicts.js +7 -4
- package/dist/store/connectors/dlq.d.ts +10 -0
- package/dist/store/connectors/dlq.js +32 -0
- package/dist/store/connectors/github.d.ts +7 -9
- package/dist/store/connectors/github.js +30 -53
- package/dist/store/connectors/slack.d.ts +2 -11
- package/dist/store/connectors/slack.js +18 -47
- package/dist/store/dashboard-reads.js +7 -6
- package/dist/store/delete-and-batch.d.ts +6 -0
- package/dist/store/delete-and-batch.js +36 -3
- package/dist/store/delivery-recorder.d.ts +10 -3
- package/dist/store/delivery-recorder.js +12 -5
- package/dist/store/descendant-page.js +6 -3
- package/dist/store/dormant.d.ts +1 -1
- package/dist/store/dormant.js +3 -1
- package/dist/store/embeddings/index.d.ts +2 -12
- package/dist/store/embeddings/index.js +5 -374
- package/dist/store/entry-reads.d.ts +13 -4
- package/dist/store/entry-reads.js +47 -11
- package/dist/store/entry-writes.d.ts +5 -5
- package/dist/store/entry-writes.js +32 -12
- package/dist/store/failure-log-at.d.ts +8 -0
- package/dist/store/failure-log-at.js +16 -0
- package/dist/store/failure-log.d.ts +2 -2
- package/dist/store/failure-log.js +5 -3
- package/dist/{trust → store}/gated-write.d.ts +3 -1
- package/dist/{trust → store}/gated-write.js +7 -5
- package/dist/store/goals.js +20 -18
- package/dist/store/graph-reads.js +4 -2
- package/dist/store/graph-writes.d.ts +6 -6
- package/dist/store/graph-writes.js +48 -71
- package/dist/store/handoffs.d.ts +1 -1
- package/dist/store/handoffs.js +6 -6
- package/dist/store/index-and-stats.js +2 -2
- package/dist/store/key-writes.js +1 -1
- package/dist/store/ledger-turn.d.ts +9 -0
- package/dist/store/ledger-turn.js +38 -0
- package/dist/store/mirrors.js +10 -6
- package/dist/store/open.d.ts +0 -4
- package/dist/store/open.js +40 -53
- package/dist/store/pilot-arm.d.ts +12 -0
- package/dist/store/pilot-arm.js +42 -0
- package/dist/store/port.d.ts +9 -3
- package/dist/store/port.js +8 -0
- package/dist/store/predictions.d.ts +1 -2
- package/dist/store/predictions.js +3 -6
- package/dist/store/project-tags.d.ts +62 -0
- package/dist/store/project-tags.js +67 -0
- package/dist/store/quarantine.js +2 -1
- package/dist/store/recall-trace.d.ts +2 -0
- package/dist/store/recall-trace.js +18 -2
- package/dist/store/rejected-values.js +2 -1
- package/dist/store/rejection-probe.d.ts +4 -0
- package/dist/store/rejection-probe.js +19 -0
- package/dist/store/rejection.d.ts +0 -17
- package/dist/store/rejection.js +1 -21
- package/dist/store/rule-sql.d.ts +9 -0
- package/dist/store/rule-sql.js +21 -2
- package/dist/store/search-rows.js +9 -4
- package/dist/store/sessions.js +4 -2
- package/dist/store/set-aside.d.ts +14 -0
- package/dist/store/set-aside.js +23 -0
- package/dist/store/sqlite/busy.d.ts +3 -0
- package/dist/store/sqlite/busy.js +8 -0
- package/dist/store/sqlite/connector-events-group.js +4 -7
- package/dist/store/sqlite/connector-writes-group.js +3 -3
- package/dist/store/sqlite/entry-writes-group.js +2 -2
- package/dist/store/sqlite/error-codec.js +4 -3
- package/dist/store/sqlite/executor.js +10 -4
- package/dist/store/sqlite/graph-reads-group.js +1 -1
- package/dist/store/sqlite/held-connection.d.ts +9 -0
- package/dist/store/sqlite/held-connection.js +41 -0
- package/dist/store/sqlite/object-rows.d.ts +1 -1
- package/dist/store/sqlite/objects-group.d.ts +1 -1
- package/dist/store/sqlite/objects-group.js +1 -1
- package/dist/store/sqlite/store.js +14 -12
- package/dist/store/summaries.d.ts +3 -3
- package/dist/store/summaries.js +5 -4
- package/dist/store/token-ledger.d.ts +0 -7
- package/dist/store/token-ledger.js +0 -35
- package/dist/store/vector-index.js +3 -2
- package/dist/support-bundle.js +2 -3
- package/dist/trust/reject-flow.js +2 -2
- package/dist/util/agent-homes.d.ts +15 -0
- package/dist/util/agent-homes.js +34 -0
- package/dist/util/anthropic-messages.d.ts +3 -0
- package/dist/util/anthropic-messages.js +22 -5
- package/dist/util/chunked.d.ts +3 -0
- package/dist/util/chunked.js +10 -0
- package/dist/util/ellipsize.d.ts +3 -0
- package/dist/util/ellipsize.js +5 -0
- package/dist/util/env.d.ts +2 -1
- package/dist/util/env.js +2 -1
- package/dist/util/format.d.ts +3 -0
- package/dist/util/format.js +6 -0
- package/dist/util/hook-payload.d.ts +8 -0
- package/dist/util/hook-payload.js +37 -0
- package/dist/util/http-retry.d.ts +6 -0
- package/dist/util/http-retry.js +43 -5
- package/dist/util/http-util.d.ts +0 -8
- package/dist/util/http-util.js +10 -21
- package/dist/util/limits.d.ts +7 -0
- package/dist/util/limits.js +14 -0
- package/dist/util/log.d.ts +4 -0
- package/dist/util/log.js +9 -0
- package/dist/util/request-scope.d.ts +3 -1
- package/dist/util/request-scope.js +11 -6
- package/dist/util/secret-detect.js +6 -1
- package/dist/util/sqlite-blocked.d.ts +2 -0
- package/dist/util/sqlite-blocked.js +5 -0
- package/dist/util/stream-tee.d.ts +3 -0
- package/dist/util/stream-tee.js +35 -0
- package/dist/util/time.d.ts +4 -0
- package/dist/util/time.js +4 -0
- package/dist/util/version.d.ts +1 -1
- package/dist/util/version.js +1 -1
- package/extensions/openclaw-plugin/openclaw.plugin.json +1 -1
- package/extensions/openclaw-plugin/package.json +1 -1
- package/openclaw.plugin.json +1 -1
- package/package.json +2 -2
- package/dist/store/embeddings/local.d.ts +0 -15
- package/dist/store/embeddings/local.js +0 -175
- /package/dist/{cli → api}/correction-latency.d.ts +0 -0
- /package/dist/{cli → api}/correction-latency.js +0 -0
- /package/dist/{cli → api}/provenance-coverage.d.ts +0 -0
- /package/dist/{cli → api}/provenance-coverage.js +0 -0
- /package/dist/{store → core}/object-types.d.ts +0 -0
- /package/dist/{store → core}/object-types.js +0 -0
- /package/dist/{capture → util}/compaction-items.d.ts +0 -0
- /package/dist/{capture → util}/compaction-items.js +0 -0
- /package/dist/{store → util}/yaml.d.ts +0 -0
- /package/dist/{store → util}/yaml.js +0 -0
|
@@ -1,26 +1,14 @@
|
|
|
1
1
|
// `hippo projects`: list the project names a store holds, fold one into another, and repair old tags in one reversible pass.
|
|
2
2
|
import * as fs from 'node:fs';
|
|
3
3
|
import * as path from 'node:path';
|
|
4
|
-
import { setAsideRow } from '../agent-memories/apply.js';
|
|
5
4
|
import { transcriptNotesProject } from '../agent-memories/claude-code.js';
|
|
6
5
|
import { containerId, containerPrefix } from '../agent-memories/source.js';
|
|
6
|
+
import { foldEdges, foldedInto } from '../agent-memories/project-folds.js';
|
|
7
7
|
import { AGENT_MEMORY_SOURCE_PREFIX, AGENT_MEMORY_TOOLS, toolSourcePrefix } from '../core/agent-memory-tools.js';
|
|
8
|
-
import { appendAuditEvent, queryAuditEvents } from '../store/audit.js';
|
|
9
8
|
import { isSharedStore } from '../core/config.js';
|
|
10
|
-
import { withTrialScope, withWriteScope } from '../db/index.js';
|
|
11
|
-
import { withBackup } from '../db/backup.js';
|
|
12
|
-
import { getMeta, setMeta } from '../db/meta.js';
|
|
13
|
-
import { insertDormantRow, listDormantSnapshots, replaceDormantEntry } from '../store/dormant.js';
|
|
14
9
|
import { processEnv } from '../util/env.js';
|
|
15
|
-
import { calculateStrength } from '../core/memory.js';
|
|
16
|
-
import { isObjectLike, isStringValue } from '../core/capture-contract.js';
|
|
17
10
|
import { isGlobalStoreRoot, projectNames, resolveProjectIdentity } from '../core/project-identity.js';
|
|
18
11
|
import { duplicateKey } from '../util/same-text.js';
|
|
19
|
-
import { compactionOriginsWithCwd, compactionTranscripts, holdsOrigin, restampCompactionOrigin } from '../store/compactions.js';
|
|
20
|
-
import { removeEntryMirrors } from '../store/mirrors.js';
|
|
21
|
-
import { deleteEntryRowInTx, restampOriginProjectAt, stampOriginProjectsAt, writeEntryMirrors } from '../store/entry-writes.js';
|
|
22
|
-
import { selectAllEntries, selectLiveEntriesBySourcePrefix } from '../store/entry-reads.js';
|
|
23
|
-
const ACTOR = 'cli';
|
|
24
12
|
function isImport(entry) {
|
|
25
13
|
return entry.source.startsWith(AGENT_MEMORY_SOURCE_PREFIX);
|
|
26
14
|
}
|
|
@@ -29,8 +17,8 @@ function toolTag(source) {
|
|
|
29
17
|
return AGENT_MEMORY_TOOLS.find((t) => t.id === id)?.tag ?? null;
|
|
30
18
|
}
|
|
31
19
|
/** Live rows per project name, newest write first, with how many of its imported notes are copies held elsewhere. */
|
|
32
|
-
export function listProjects(
|
|
33
|
-
const live =
|
|
20
|
+
export function listProjects(store) {
|
|
21
|
+
const live = store.entries().filter((e) => !e.superseded_by);
|
|
34
22
|
const byOrigin = new Map();
|
|
35
23
|
const holders = new Map();
|
|
36
24
|
for (const e of live) {
|
|
@@ -51,9 +39,6 @@ export function listProjects(db, tenantId) {
|
|
|
51
39
|
};
|
|
52
40
|
}).sort((a, b) => b.newest.localeCompare(a.newest));
|
|
53
41
|
}
|
|
54
|
-
function inTransaction(db, dryRun, body) {
|
|
55
|
-
return dryRun ? withTrialScope(db, 'merge_projects', body) : withWriteScope(db, 'merge_projects', body);
|
|
56
|
-
}
|
|
57
42
|
/** Refuses user-global and unknown: they are not projects, and folding them would leak or hide every row. */
|
|
58
43
|
export function validateMergeNames(from, into) {
|
|
59
44
|
if (from.trim() === '' || into.trim() === '')
|
|
@@ -63,23 +48,19 @@ export function validateMergeNames(from, into) {
|
|
|
63
48
|
return null;
|
|
64
49
|
}
|
|
65
50
|
/** Folds project `from` into `into` for one tenant in one transaction; a dry run rolls back and writes nothing, mirrors included. */
|
|
66
|
-
export function mergeProjects(
|
|
51
|
+
export function mergeProjects(store, opts) {
|
|
67
52
|
const refusal = validateMergeNames(opts.from, opts.into);
|
|
68
53
|
if (refusal)
|
|
69
54
|
throw new Error(refusal);
|
|
70
|
-
const {
|
|
71
|
-
|
|
72
|
-
const folded = foldInTx(
|
|
73
|
-
|
|
74
|
-
return { from, into, ...folded, backup };
|
|
55
|
+
const { from, into, dryRun } = opts;
|
|
56
|
+
return store.rewrite({ dryRun, backupLabel: 'before-merge' }, (tx, backup) => {
|
|
57
|
+
const folded = foldInTx(tx, from, into);
|
|
58
|
+
tx.audit('project_merge', { from, into, backup, ...folded });
|
|
59
|
+
return { result: { from, into, ...folded, backup }, rewrite: folded.restamped, purge: folded.setAside };
|
|
75
60
|
});
|
|
76
|
-
const result = dryRun ? fold(null) : withBackup(db, hippoRoot, 'before-merge', fold);
|
|
77
|
-
if (!dryRun)
|
|
78
|
-
refreshMirrors(db, hippoRoot, tenantId, result.restamped, result.setAside);
|
|
79
|
-
return result;
|
|
80
61
|
}
|
|
81
|
-
function foldInTx(
|
|
82
|
-
const all =
|
|
62
|
+
function foldInTx(tx, from, into) {
|
|
63
|
+
const all = tx.entries();
|
|
83
64
|
const rows = all.filter((e) => e.origin_project === from);
|
|
84
65
|
// The sync renames the rest to `into`'s prefix and keeps their ids; only a note `into` already holds would show twice.
|
|
85
66
|
const held = new Set(all.filter((e) => e.origin_project === into && !e.superseded_by && isImport(e)).map(noteKey));
|
|
@@ -88,20 +69,20 @@ function foldInTx(db, tenantId, from, into) {
|
|
|
88
69
|
const tag = toolTag(row.source);
|
|
89
70
|
if (!isImport(row) || row.superseded_by || row.kind === 'raw' || tag === null || !held.has(noteKey(row)))
|
|
90
71
|
continue;
|
|
91
|
-
if (
|
|
72
|
+
if (tx.setAside(tag, { ...row, origin_project: into }, 'project-merge').kind === 'dormant')
|
|
92
73
|
setAside.push(row.id);
|
|
93
74
|
}
|
|
94
75
|
const gone = new Set(setAside);
|
|
95
76
|
const restamped = rows.filter((e) => !gone.has(e.id)).map((e) => e.id);
|
|
96
|
-
|
|
77
|
+
tx.restampOrigin(from, into);
|
|
97
78
|
const dormantRestamped = [];
|
|
98
|
-
for (const snap of
|
|
79
|
+
for (const snap of tx.dormant()) {
|
|
99
80
|
if (snap.entry.origin_project !== from || gone.has(snap.entry.id))
|
|
100
81
|
continue;
|
|
101
|
-
|
|
82
|
+
tx.replaceDormant(snap.entry.id, { ...snap.entry, origin_project: into });
|
|
102
83
|
dormantRestamped.push(snap.entry.id);
|
|
103
84
|
}
|
|
104
|
-
const compactions =
|
|
85
|
+
const compactions = tx.restampCompactions(from, into);
|
|
105
86
|
return { setAside, restamped, dormantRestamped, compactions };
|
|
106
87
|
}
|
|
107
88
|
/** Tool, note key and hash of an import, without the container, whose id hashes the project name. */
|
|
@@ -110,20 +91,20 @@ function noteKey(entry) {
|
|
|
110
91
|
return `${rest.split(':')[0]}:${rest.slice(rest.indexOf('/') + 1)}`;
|
|
111
92
|
}
|
|
112
93
|
/** Live imports under a project name whose exact text a user-global import holds: a session folder's notes stamped with the folder it ended in. */
|
|
113
|
-
function importCopies(
|
|
114
|
-
const live =
|
|
94
|
+
function importCopies(store) {
|
|
95
|
+
const live = store.entries().filter((e) => !e.superseded_by && isImport(e));
|
|
115
96
|
const userGlobal = new Set(live.filter((e) => e.origin_project === '').map((e) => duplicateKey(e.content)));
|
|
116
97
|
return live.filter((e) => e.origin_project && e.kind !== 'raw' && !e.pinned && toolTag(e.source) !== null && userGlobal.has(duplicateKey(e.content)));
|
|
117
98
|
}
|
|
118
99
|
/** Imports to set aside. The global store also checks each Claude session folder a compaction recorded: its
|
|
119
100
|
* notes under any other project are misfiled, edited or not, and a text copy in the right folder is kept. */
|
|
120
|
-
function strayImports(
|
|
121
|
-
const copies = importCopies(
|
|
101
|
+
function strayImports(store, hippoRoot) {
|
|
102
|
+
const copies = importCopies(store);
|
|
122
103
|
if (!isGlobalStoreRoot(hippoRoot))
|
|
123
104
|
return copies;
|
|
124
105
|
const machine = { platform: process.platform, env: processEnv() };
|
|
125
106
|
const { platform } = machine;
|
|
126
|
-
const sessions = compactionTranscripts(
|
|
107
|
+
const sessions = store.compactionTranscripts();
|
|
127
108
|
const owners = new Map();
|
|
128
109
|
for (const { transcript, cwd } of sessions) {
|
|
129
110
|
const project = transcriptNotesProject(transcript, cwd, machine);
|
|
@@ -134,9 +115,9 @@ function strayImports(db, hippoRoot, tenantId) {
|
|
|
134
115
|
owners.set(dir, ids.set(project.name, [...new Set([...(ids.get(project.name) ?? []), ...projectNames(project)])]));
|
|
135
116
|
}
|
|
136
117
|
const tool = toolSourcePrefix('claude-code');
|
|
137
|
-
const live =
|
|
118
|
+
const live = store.liveEntriesBySourcePrefix(tool).filter((e) => e.kind !== 'raw' && !e.pinned);
|
|
138
119
|
const origins = new Set(live.map((e) => e.origin_project ?? ''));
|
|
139
|
-
const edges = foldEdges(
|
|
120
|
+
const edges = foldEdges(store);
|
|
140
121
|
const right = new Set();
|
|
141
122
|
const wrong = new Set();
|
|
142
123
|
for (const [dir, ids] of owners) {
|
|
@@ -154,12 +135,12 @@ function strayImports(db, hippoRoot, tenantId) {
|
|
|
154
135
|
return [...misfiled, ...copies.filter((e) => !seen.has(e.id) && !right.has(prefix(e)))];
|
|
155
136
|
}
|
|
156
137
|
/** The global store reads each name's recorded session folders, where a compaction's name came from its cwd; a project store folds only its own folder name. */
|
|
157
|
-
function planFolds(
|
|
138
|
+
function planFolds(store, hippoRoot, globalFolds) {
|
|
158
139
|
// A name someone merged into by hand stays: undoing their choice would rest on the resolver alone.
|
|
159
|
-
const chosen = new Set(
|
|
140
|
+
const chosen = new Set(store.auditEvents('project_merge').map((e) => e.metadata.into));
|
|
160
141
|
if (!isGlobalStoreRoot(hippoRoot))
|
|
161
|
-
return { folds: ownLegacyFold(
|
|
162
|
-
const rows = compactionOriginsWithCwd(
|
|
142
|
+
return { folds: ownLegacyFold(store, hippoRoot).filter((f) => !chosen.has(f.from)), collisions: [] };
|
|
143
|
+
const rows = store.compactionOriginsWithCwd();
|
|
163
144
|
const today = new Map();
|
|
164
145
|
for (const { origin, cwd } of rows) {
|
|
165
146
|
if (fs.existsSync(cwd))
|
|
@@ -181,60 +162,29 @@ function planFolds(db, hippoRoot, tenantId, globalFolds) {
|
|
|
181
162
|
return { folds: globalFolds ? folds.filter((f) => !sources.has(f.into)) : [], collisions };
|
|
182
163
|
}
|
|
183
164
|
/** A project store's rows, dormant snapshots and compaction records written before its id existed carry its folder name. */
|
|
184
|
-
function ownLegacyFold(
|
|
165
|
+
function ownLegacyFold(store, hippoRoot) {
|
|
185
166
|
// A shared store's rows carry their callers' names, so one matching its folder's is a member's project, not a legacy tag.
|
|
186
167
|
if (isSharedStore(hippoRoot))
|
|
187
168
|
return [];
|
|
188
169
|
const { name, legacyName } = resolveProjectIdentity(path.dirname(path.resolve(hippoRoot)));
|
|
189
170
|
if (legacyName === '' || legacyName === name)
|
|
190
171
|
return [];
|
|
191
|
-
const held = holdsOrigin(
|
|
192
|
-
|| holdsOrigin(
|
|
193
|
-
||
|
|
172
|
+
const held = store.holdsOrigin('memories', legacyName)
|
|
173
|
+
|| store.holdsOrigin('compactions', legacyName)
|
|
174
|
+
|| store.dormant().some((s) => s.entry.origin_project === legacyName);
|
|
194
175
|
return held ? [{ from: legacyName, into: name }] : [];
|
|
195
176
|
}
|
|
196
|
-
function foldOf(value) {
|
|
197
|
-
if (!isObjectLike(value) || Array.isArray(value))
|
|
198
|
-
return [];
|
|
199
|
-
const { from, into } = value;
|
|
200
|
-
return isStringValue(from) && isStringValue(into) ? [{ from, into }] : [];
|
|
201
|
-
}
|
|
202
|
-
function foldEdges(db, tenantId) {
|
|
203
|
-
return [
|
|
204
|
-
...queryAuditEvents(db, { tenantId, op: 'project_merge', limit: 10000 }).flatMap((e) => foldOf(e.metadata)),
|
|
205
|
-
...queryAuditEvents(db, { tenantId, op: 'project_repair', limit: 10000 })
|
|
206
|
-
.flatMap((e) => (Array.isArray(e.metadata.folds) ? e.metadata.folds.flatMap(foldOf) : [])),
|
|
207
|
-
];
|
|
208
|
-
}
|
|
209
|
-
function foldedInto(edges, names) {
|
|
210
|
-
const seen = new Set(names);
|
|
211
|
-
let grew = true;
|
|
212
|
-
while (grew) {
|
|
213
|
-
grew = false;
|
|
214
|
-
for (const { from, into } of edges) {
|
|
215
|
-
if (!seen.has(into) || seen.has(from))
|
|
216
|
-
continue;
|
|
217
|
-
seen.add(from);
|
|
218
|
-
grew = true;
|
|
219
|
-
}
|
|
220
|
-
}
|
|
221
|
-
return [...seen].filter((n) => !names.includes(n));
|
|
222
|
-
}
|
|
223
|
-
/** Names folded, directly or through others, into one of `names`; the sync moves imports still filed under them. */
|
|
224
|
-
export function namesFoldedInto(db, tenantId, names) {
|
|
225
|
-
return foldedInto(foldEdges(db, tenantId), names);
|
|
226
|
-
}
|
|
227
177
|
/** Reads only, so doctor and a dry run take no write lock; merged rows are planned before any fold, so a few may re-tag differently once folds apply. */
|
|
228
|
-
export function planProjectRepair(
|
|
229
|
-
const { folds, collisions } = planFolds(
|
|
230
|
-
return { copies: strayImports(
|
|
178
|
+
export function planProjectRepair(store, hippoRoot, globalFolds = true) {
|
|
179
|
+
const { folds, collisions } = planFolds(store, hippoRoot, globalFolds);
|
|
180
|
+
return { copies: strayImports(store, hippoRoot).map((e) => e.id), folds, collisions, ...planUserGlobalRepair(store, folds) };
|
|
231
181
|
}
|
|
232
182
|
/** Parents read with `folds` already applied, so a plan matches what apply does after folding. */
|
|
233
|
-
function planUserGlobalRepair(
|
|
234
|
-
const all =
|
|
183
|
+
function planUserGlobalRepair(store, folds) {
|
|
184
|
+
const all = store.entries();
|
|
235
185
|
const renamed = new Map(folds.map((f) => [f.from, f.into]));
|
|
236
186
|
const after = (origin) => (origin ? renamed.get(origin) ?? origin : origin ?? null);
|
|
237
|
-
const origins = new Map(
|
|
187
|
+
const origins = new Map(store.dormant().map((s) => [s.entry.id, after(s.entry.origin_project)]));
|
|
238
188
|
for (const e of all)
|
|
239
189
|
origins.set(e.id, after(e.origin_project));
|
|
240
190
|
const toProject = [];
|
|
@@ -258,59 +208,45 @@ function planUserGlobalRepair(db, tenantId, folds) {
|
|
|
258
208
|
}
|
|
259
209
|
/** Sets aside stray imports, folds the names the resolver now maps elsewhere, then
|
|
260
210
|
* re-tags sleep's user-global merges by their parents; a dry run only plans. */
|
|
261
|
-
export function repairProjects(
|
|
262
|
-
const {
|
|
211
|
+
export function repairProjects(store, opts) {
|
|
212
|
+
const { dryRun, globalFolds = true } = opts;
|
|
213
|
+
const { hippoRoot } = store;
|
|
263
214
|
if (dryRun)
|
|
264
|
-
return { ...planProjectRepair(
|
|
265
|
-
|
|
215
|
+
return { ...planProjectRepair(store, hippoRoot, globalFolds), backup: null };
|
|
216
|
+
return store.rewrite({ dryRun: false, backupLabel: 'before-repair' }, (tx, backup) => {
|
|
266
217
|
const copies = [];
|
|
267
|
-
for (const row of strayImports(
|
|
218
|
+
for (const row of strayImports(tx, hippoRoot)) {
|
|
268
219
|
const tag = toolTag(row.source);
|
|
269
|
-
if (tag !== null &&
|
|
220
|
+
if (tag !== null && tx.setAside(tag, row, 'project-repair').kind === 'dormant')
|
|
270
221
|
copies.push(row.id);
|
|
271
222
|
}
|
|
272
|
-
const { folds, collisions } = planFolds(
|
|
273
|
-
const folded = folds.map((f) => foldInTx(
|
|
274
|
-
const plan = planUserGlobalRepair(
|
|
275
|
-
|
|
276
|
-
const aside = new Set(plan.setAside);
|
|
223
|
+
const { folds, collisions } = planFolds(tx, hippoRoot, globalFolds);
|
|
224
|
+
const folded = folds.map((f) => foldInTx(tx, f.from, f.into));
|
|
225
|
+
const plan = planUserGlobalRepair(tx, []);
|
|
226
|
+
tx.stampOrigins(plan.toProject);
|
|
277
227
|
const now = new Date();
|
|
278
|
-
for (const row of
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
}
|
|
282
|
-
appendAuditEvent(db, { tenantId, actor: ACTOR, op: 'project_repair', metadata: { backup, copies, folds, folded, ...plan } });
|
|
228
|
+
for (const row of tx.entriesByIds(plan.setAside).values())
|
|
229
|
+
tx.retire(row, 'project-repair', now);
|
|
230
|
+
tx.audit('project_repair', { backup, copies, folds, folded, ...plan });
|
|
283
231
|
return {
|
|
284
232
|
result: { copies, folds, collisions, ...plan, backup },
|
|
285
233
|
rewrite: [...plan.toProject.map((r) => r.id), ...folded.flatMap((f) => f.restamped)],
|
|
286
234
|
purge: [...copies, ...plan.setAside, ...folded.flatMap((f) => f.setAside)],
|
|
287
235
|
};
|
|
288
|
-
})
|
|
289
|
-
refreshMirrors(db, hippoRoot, tenantId, rewrite, purge);
|
|
290
|
-
return result;
|
|
236
|
+
});
|
|
291
237
|
}
|
|
292
|
-
const AUTO_REPAIR_META_KEY = 'project_repair_auto';
|
|
293
238
|
/** True when a repair would change nothing. */
|
|
294
239
|
function repairIsEmpty(r) {
|
|
295
240
|
return r.copies.length + r.folds.length + r.toProject.length + r.setAside.length === 0;
|
|
296
241
|
}
|
|
297
242
|
/** Sleep runs repair once per store, so an upgrade needs no command. Global-store folds stay
|
|
298
243
|
* with `hippo projects repair`: their evidence is compaction folders, blind to a same-named repo that never compacted. */
|
|
299
|
-
export function repairOnceOnSleep(
|
|
300
|
-
if (
|
|
244
|
+
export function repairOnceOnSleep(store) {
|
|
245
|
+
if (store.repairedOnce())
|
|
301
246
|
return null;
|
|
302
|
-
const plan = planProjectRepair(
|
|
303
|
-
const result = repairIsEmpty(plan) ? null : repairProjects(
|
|
304
|
-
|
|
247
|
+
const plan = planProjectRepair(store, store.hippoRoot, false);
|
|
248
|
+
const result = repairIsEmpty(plan) ? null : repairProjects(store, { dryRun: false, globalFolds: false });
|
|
249
|
+
store.markRepairedOnce();
|
|
305
250
|
return result;
|
|
306
251
|
}
|
|
307
|
-
/** After commit, as the agent memory sync does: a stale mirror would bring the old tag back on the next rebuild. */
|
|
308
|
-
function refreshMirrors(db, hippoRoot, tenantId, rewrite, purge) {
|
|
309
|
-
const ids = new Set(rewrite);
|
|
310
|
-
for (const entry of selectAllEntries(db, tenantId))
|
|
311
|
-
if (ids.has(entry.id))
|
|
312
|
-
writeEntryMirrors(hippoRoot, entry);
|
|
313
|
-
for (const id of purge)
|
|
314
|
-
removeEntryMirrors(hippoRoot, id);
|
|
315
|
-
}
|
|
316
252
|
//# sourceMappingURL=project-merge.js.map
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import { compareScoresDesc } from '../core/compare.js';
|
|
3
3
|
import * as fs from 'fs';
|
|
4
4
|
import { loadSearchEntries, loadRecallSearchEntries, recallScopeFilter } from '../store/search-rows.js';
|
|
5
|
-
import { passesScopeFilterForRecall, passesCliRecallScopeFilter } from '../
|
|
5
|
+
import { passesScopeFilterForRecall, passesCliRecallScopeFilter } from '../core/recall-scope.js';
|
|
6
6
|
import { search } from '../search/bm25-search.js';
|
|
7
7
|
import { hybridSearch } from '../search/hybrid.js';
|
|
8
8
|
import { fitBudget } from '../search/finalize.js';
|
package/dist/sharing/share.d.ts
CHANGED
|
@@ -4,6 +4,8 @@ export declare const NEVER_AUTO_SHARE_TAGS: ReadonlySet<string>;
|
|
|
4
4
|
export declare function neverAutoShareTags(sources: readonly MemoryEntry[]): string[];
|
|
5
5
|
/** Tags whose rows sleep keeps as written: never merged, never sent to LLM extraction. Conflict detection keeps its own list. */
|
|
6
6
|
export declare const NO_MERGE_TAGS: ReadonlySet<string>;
|
|
7
|
+
/** The transfer score a memory needs before sleep or `hippo share --auto` copies it to the global store. */
|
|
8
|
+
export declare const AUTO_SHARE_MIN_SCORE = 0.6;
|
|
7
9
|
/** Estimate how well a memory would transfer to other projects.
|
|
8
10
|
* Returns 0..1 where >0.5 = good candidate for sharing. */
|
|
9
11
|
export declare function transferScore(entry: MemoryEntry): number;
|
package/dist/sharing/share.js
CHANGED
|
@@ -4,15 +4,14 @@ import * as fs from 'fs';
|
|
|
4
4
|
import * as path from 'path';
|
|
5
5
|
import { generateId, COMPACTION_MEMORY_TAG } from '../core/memory.js';
|
|
6
6
|
import { AGENT_MEMORY_SOURCE_PREFIX, AGENT_MEMORY_TAGS } from '../core/agent-memory-tools.js';
|
|
7
|
-
import { writeEntry } from '../store/entry-writes.js';
|
|
7
|
+
import { writeEntriesSkippingRejected, writeEntry } from '../store/entry-writes.js';
|
|
8
8
|
import { loadAllEntries, readEntry } from '../store/entry-reads.js';
|
|
9
9
|
import { tallySources } from '../store/candidates.js';
|
|
10
|
-
import { isPersonalScope } from '../
|
|
10
|
+
import { isPersonalScope } from '../core/recall-scope.js';
|
|
11
11
|
import { fallbackOrigin } from '../core/project-identity.js';
|
|
12
12
|
import { detectSecret } from '../util/secret-detect.js';
|
|
13
13
|
import { isQuarantineScope } from '../trust/quarantine.js';
|
|
14
|
-
import {
|
|
15
|
-
import { embedMemory, embedAll } from '../store/embeddings/index.js';
|
|
14
|
+
import { embedMemory, embedAll } from '../search/embed-memories.js';
|
|
16
15
|
import { duplicateKey, storedTextKeys } from '../util/same-text.js';
|
|
17
16
|
import { isReusable } from '../core/memory-quality.js';
|
|
18
17
|
import { log } from '../util/log.js';
|
|
@@ -45,6 +44,8 @@ export const NO_MERGE_TAGS = new Set([
|
|
|
45
44
|
COMPACTION_MEMORY_TAG,
|
|
46
45
|
...AGENT_MEMORY_TAGS,
|
|
47
46
|
]);
|
|
47
|
+
/** The transfer score a memory needs before sleep or `hippo share --auto` copies it to the global store. */
|
|
48
|
+
export const AUTO_SHARE_MIN_SCORE = 0.6;
|
|
48
49
|
/** Estimate how well a memory would transfer to other projects.
|
|
49
50
|
* Returns 0..1 where >0.5 = good candidate for sharing. */
|
|
50
51
|
export function transferScore(entry) {
|
|
@@ -74,28 +75,34 @@ export function shareMemory(localRoot, id, options = {}) {
|
|
|
74
75
|
const entry = readEntry(localRoot, id, options.tenantId);
|
|
75
76
|
if (!entry)
|
|
76
77
|
throw new NotFoundError(`Memory not found: ${id}`);
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
if (score < 0.3 && !options.force)
|
|
78
|
+
const globalEntry = toGlobalEntry(localRoot, entry, options.force === true);
|
|
79
|
+
if (!globalEntry)
|
|
80
80
|
return null;
|
|
81
81
|
initGlobal();
|
|
82
82
|
const globalRoot = getGlobalRoot();
|
|
83
|
+
writeEntry(globalRoot, globalEntry);
|
|
84
|
+
// Embed here unless the caller opts out: autoShare sets skipEmbed to batch one embedAll(), since embedMemory rewrites the whole index per call.
|
|
85
|
+
if (!options.skipEmbed) {
|
|
86
|
+
void embedMemory(globalRoot, globalEntry);
|
|
87
|
+
}
|
|
88
|
+
return globalEntry;
|
|
89
|
+
}
|
|
90
|
+
/** The global copy of a local row, or null when its transfer score is too low and `force` is off; throws when the row may not be shared. */
|
|
91
|
+
function toGlobalEntry(localRoot, entry, force) {
|
|
92
|
+
assertShareable(entry, entry.id);
|
|
93
|
+
const score = transferScore(entry);
|
|
94
|
+
if (score < 0.3 && !force)
|
|
95
|
+
return null;
|
|
83
96
|
// The label keeps the folder name for a user-global row; a NULL row gets `shared::`, which originFromSource reads as no project.
|
|
84
97
|
const fallbackName = path.basename(path.resolve(localRoot, '..'));
|
|
85
98
|
const originName = entry.origin_project ?? fallbackOrigin(localRoot);
|
|
86
99
|
const label = originName === '' ? fallbackName : (originName ?? '');
|
|
87
|
-
|
|
100
|
+
return {
|
|
88
101
|
...entry,
|
|
89
102
|
id: generateId('g'),
|
|
90
103
|
source: `shared:${label}:${new Date().toISOString()}`,
|
|
91
104
|
origin_project: originName,
|
|
92
105
|
};
|
|
93
|
-
writeEntry(globalRoot, globalEntry);
|
|
94
|
-
// Embed here unless the caller opts out: autoShare sets skipEmbed to batch one embedAll(), since embedMemory rewrites the whole index per call.
|
|
95
|
-
if (!options.skipEmbed) {
|
|
96
|
-
void embedMemory(globalRoot, globalEntry);
|
|
97
|
-
}
|
|
98
|
-
return globalEntry;
|
|
99
106
|
}
|
|
100
107
|
function assertShareable(entry, id) {
|
|
101
108
|
// Secret veto: secrets never reach the global store, even with --force; throw loudly, since a silent null reads as "low transfer score" and invites retries.
|
|
@@ -174,29 +181,25 @@ function isAutoShareCandidate(entry, globalContentSet, minScore, stats) {
|
|
|
174
181
|
}
|
|
175
182
|
return true;
|
|
176
183
|
}
|
|
177
|
-
//
|
|
178
|
-
//
|
|
179
|
-
function shareCandidates(localRoot, candidates, stats) {
|
|
184
|
+
// A row the GLOBAL store's rejection tombstones refuse is audited and skipped, so it cannot abort the autoShare sleep phase.
|
|
185
|
+
// The candidates are rows already held, written in one transaction; the caller embeds once via embedAll() afterwards.
|
|
186
|
+
function shareCandidates(localRoot, globalRoot, candidates, stats) {
|
|
180
187
|
const shared = [];
|
|
181
188
|
let rejectedSkipped = 0;
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
if (
|
|
188
|
-
shared.push(
|
|
189
|
-
}
|
|
190
|
-
catch (err) {
|
|
191
|
-
if (err instanceof RejectedValueError) {
|
|
192
|
-
rejectedSkipped++;
|
|
193
|
-
if (stats)
|
|
194
|
-
stats.rejectedSkipped = (stats.rejectedSkipped ?? 0) + 1;
|
|
189
|
+
writeEntriesSkippingRejected(globalRoot, (put) => {
|
|
190
|
+
for (const entry of candidates) {
|
|
191
|
+
const globalEntry = toGlobalEntry(localRoot, entry, true);
|
|
192
|
+
if (!globalEntry)
|
|
193
|
+
continue;
|
|
194
|
+
if (put(globalEntry)) {
|
|
195
|
+
shared.push(globalEntry);
|
|
195
196
|
continue;
|
|
196
197
|
}
|
|
197
|
-
|
|
198
|
+
rejectedSkipped++;
|
|
199
|
+
if (stats)
|
|
200
|
+
stats.rejectedSkipped = (stats.rejectedSkipped ?? 0) + 1;
|
|
198
201
|
}
|
|
199
|
-
}
|
|
202
|
+
});
|
|
200
203
|
if (rejectedSkipped > 0) {
|
|
201
204
|
log.warn(`autoShare: skipped ${rejectedSkipped} candidate(s) refused by the global store's rejection tombstone`);
|
|
202
205
|
}
|
|
@@ -205,7 +208,7 @@ function shareCandidates(localRoot, candidates, stats) {
|
|
|
205
208
|
/** Auto-share local memories with high transfer scores, not already global and without a NEVER_AUTO_SHARE_TAGS tag; `options.tenantId` scopes the LOCAL read.
|
|
206
209
|
* `options.stats` is an opt-in out-param: `secretSkipped` counts shares the secret veto prevented, `rejectedSkipped` rejection refusals (0 under `dryRun`). */
|
|
207
210
|
export function autoShare(localRoot, options = {}) {
|
|
208
|
-
const { minScore =
|
|
211
|
+
const { minScore = AUTO_SHARE_MIN_SCORE, dryRun = false } = options;
|
|
209
212
|
const localEntries = loadAllEntries(localRoot, options.tenantId);
|
|
210
213
|
initGlobal();
|
|
211
214
|
const globalRoot = getGlobalRoot();
|
|
@@ -217,7 +220,7 @@ export function autoShare(localRoot, options = {}) {
|
|
|
217
220
|
const candidates = localEntries.filter((entry) => isAutoShareCandidate(entry, globalContentSet, minScore, options.stats));
|
|
218
221
|
if (dryRun)
|
|
219
222
|
return candidates;
|
|
220
|
-
const shared = shareCandidates(localRoot, candidates, options.stats);
|
|
223
|
+
const shared = shareCandidates(localRoot, globalRoot, candidates, options.stats);
|
|
221
224
|
if (shared.length > 0) {
|
|
222
225
|
void embedAll(globalRoot).catch((err) => logEmbedAllFailure('autoShare', err));
|
|
223
226
|
}
|
package/dist/store/ambient.js
CHANGED
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
import { strengthSql } from './rule-sql.js';
|
|
2
|
-
import { scopeAdmitSql } from './
|
|
2
|
+
import { scopeAdmitSql } from './rule-sql.js';
|
|
3
3
|
import { SECRET_TAGS } from '../util/secret-detect.js';
|
|
4
4
|
import { onHandle, openStore } from './open.js';
|
|
5
5
|
import { jsonList } from './candidates.js';
|
|
6
6
|
import { originInSql } from '../core/project-identity.js';
|
|
7
|
-
import { isErrorTagged } from '../core/ambient.js';
|
|
8
|
-
import { DAY_MS } from '../util/time.js';
|
|
7
|
+
import { AMBIENT_FRESH_WINDOW_MS, HIGH_SCHEMA_FIT_ABOVE, isErrorTagged } from '../core/ambient.js';
|
|
9
8
|
// SHORTCUT: mirrors loadContextCandidates' WHERE (request-path snapshots pin the match); share it once store.ts is split.
|
|
10
9
|
function contextRowsWhere(tenantId, filter) {
|
|
11
10
|
const where = ['tenant_id = ?', `COALESCE(superseded_by, '') = ''`, `COALESCE(kind, '') != 'archived'`];
|
|
@@ -39,7 +38,7 @@ function secretTaggedSql() {
|
|
|
39
38
|
export function loadAmbientTallies(hippoRoot, tenantId, filter) {
|
|
40
39
|
const { where, params } = contextRowsWhere(tenantId, filter);
|
|
41
40
|
const secret = secretTaggedSql();
|
|
42
|
-
const
|
|
41
|
+
const freshAfter = new Date(filter.now.getTime() - AMBIENT_FRESH_WINDOW_MS).toISOString();
|
|
43
42
|
return onHandle(hippoRoot, (db) => {
|
|
44
43
|
// SAFETY: one aggregate row whose columns are the aliases named below. Tag lists come back as one JSON array of
|
|
45
44
|
// arrays and are counted in JS, which maps items through String() as parseJsonArray does.
|
|
@@ -48,7 +47,7 @@ export function loadAmbientTallies(hippoRoot, tenantId, filter) {
|
|
|
48
47
|
COALESCE(SUM(${strengthSql(filter.now)}), 0) AS strengthSum,
|
|
49
48
|
COALESCE(SUM(julianday(created) > julianday(?)), 0) AS fresh,
|
|
50
49
|
COALESCE(SUM(emotional_valence IN ('negative', 'critical')), 0) AS negative,
|
|
51
|
-
COALESCE(SUM(COALESCE(schema_fit, 0.5) >
|
|
50
|
+
COALESCE(SUM(COALESCE(schema_fit, 0.5) > ?), 0) AS highSchemaFit,
|
|
52
51
|
COALESCE(SUM(layer = 'semantic'), 0) AS semantic,
|
|
53
52
|
COALESCE(SUM(layer = 'episodic'), 0) AS episodic,
|
|
54
53
|
COALESCE(SUM(json_array_length(${jsonList('conflicts_with_json')})), 0) AS conflicts,
|
|
@@ -57,7 +56,7 @@ export function loadAmbientTallies(hippoRoot, tenantId, filter) {
|
|
|
57
56
|
'[' || COALESCE(group_concat(${jsonList('tags_json')}, ','), '') || ']' AS tagLists
|
|
58
57
|
FROM memories
|
|
59
58
|
WHERE ${where.join(' AND ')}
|
|
60
|
-
AND ((${originInSql(filter.currentProject)} AND origin_project != '') OR NOT ${secret.sql})`).get(
|
|
59
|
+
AND ((${originInSql(filter.currentProject)} AND origin_project != '') OR NOT ${secret.sql})`).get(freshAfter, HIGH_SCHEMA_FIT_ABOVE, ...params, ...filter.currentProject, ...secret.params);
|
|
61
60
|
const tagCounts = new Map();
|
|
62
61
|
let errors = 0;
|
|
63
62
|
const lists = /* SAFETY: jsonList yields an array per row, joined into one array */ JSON.parse(row.tagLists);
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { openHippoDb } from '../db/index.js';
|
|
2
2
|
import { type AuditOp } from './audit.js';
|
|
3
|
-
import { RejectedValueError } from '
|
|
3
|
+
import { RejectedValueError } from '../core/api-errors.js';
|
|
4
4
|
import type { JsonValue } from '../util/json.js';
|
|
5
5
|
export interface AuditOptions {
|
|
6
6
|
readonly targetId?: string;
|
package/dist/store/audit.d.ts
CHANGED
|
@@ -1,22 +1,6 @@
|
|
|
1
|
-
import { type MemoryEntry } from '../core/memory.js';
|
|
2
1
|
import { type DatabaseSyncLike } from '../db/index.js';
|
|
3
2
|
import type { JsonObject } from './working-memory.js';
|
|
4
3
|
import { type KeysetPosition } from '../util/keyset.js';
|
|
5
|
-
export type AuditSeverity = 'warning' | 'error';
|
|
6
|
-
export interface AuditIssue {
|
|
7
|
-
memoryId: string;
|
|
8
|
-
content: string;
|
|
9
|
-
severity: AuditSeverity;
|
|
10
|
-
reason: string;
|
|
11
|
-
}
|
|
12
|
-
export interface AuditResult {
|
|
13
|
-
total: number;
|
|
14
|
-
issues: AuditIssue[];
|
|
15
|
-
clean: number;
|
|
16
|
-
}
|
|
17
|
-
export declare function auditMemory(entry: MemoryEntry, backsObject?: boolean): AuditIssue | null;
|
|
18
|
-
/** `backing`: ids of memories that back an object (store.memoriesBackingObjects). */
|
|
19
|
-
export declare function auditMemories(entries: MemoryEntry[], backing: ReadonlySet<string>): AuditResult;
|
|
20
4
|
export declare const AUDIT_OPS: readonly ["remember", "recall", "promote", "supersede", "forget", "archive_raw", "auth_revoke", "auth_create", "outcome", "consolidate", "audit_prune", "summary_marked_dirty", "summary_marked_clean", "summary_rebuilt", "predict_create", "predict_close", "predict_baserate", "recall_autodebias_hint", "recall_autodebias_hint_no_class_match", "recall_autodebias_hint_tiebreak", "recall_anchor_detected_query_repeat", "recall_anchor_detected_memory_dominance", "recall_anchor_skipped_no_session", "recall_availability_detected", "decision_create", "decision_supersede", "decision_close", "incident_open", "incident_resolve", "incident_close", "process_create", "process_supersede", "process_close", "policy_create", "policy_supersede", "policy_close", "skill_create", "skill_supersede", "skill_close", "project_brief_create", "project_brief_supersede", "project_brief_close", "customer_note_create", "customer_note_supersede", "customer_note_close", "mv_rescue", "reject_value", "reject_refusal", "unreject_value", "conflict_resolve", "half_life_migrate", "dormant_restore", "auth_grant", "auth_ungrant", "quarantine", "quarantine_approve", "quarantine_reject", "agent_memory_restore", "agent_memory_set_aside", "project_merge", "project_repair", "quality_repair"];
|
|
21
5
|
export type AuditOp = (typeof AUDIT_OPS)[number];
|
|
22
6
|
export interface AppendAuditOpts {
|
package/dist/store/audit.js
CHANGED
|
@@ -1,60 +1,9 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { canAutoDelete } from '../core/memory.js';
|
|
1
|
+
import { DEFAULT_LIST_LIMIT } from '../util/limits.js';
|
|
3
2
|
import { closeHippoDb, openHippoDb, withWriteScope } from '../db/index.js';
|
|
4
3
|
import { log } from '../util/log.js';
|
|
4
|
+
import { blockHash } from '../util/token-text.js';
|
|
5
5
|
import { keysetAfter } from '../util/keyset.js';
|
|
6
6
|
import { warnDamagedColumn } from '../util/stored-json.js';
|
|
7
|
-
import { automaticDefect, hasNoSpecificity, isFragment, isReleaseCommitNoise, substantiveWordCount, } from '../core/memory-quality.js';
|
|
8
|
-
export function auditMemory(entry, backsObject = false) {
|
|
9
|
-
const issue = classifyMemory(entry);
|
|
10
|
-
// Error means "auto-remove"; a pinned, raw, kept-for-good or object-backing row is never auto-removed, so it can only warn.
|
|
11
|
-
if (issue?.severity === 'error' && (!canAutoDelete(entry) || backsObject)) {
|
|
12
|
-
const why = entry.pinned ? 'pinned' : entry.kind === 'raw' ? 'raw' : backsObject ? 'backs an object' : 'keep rule';
|
|
13
|
-
return { ...issue, severity: 'warning', reason: `${issue.reason} (${why}, kept)` };
|
|
14
|
-
}
|
|
15
|
-
return issue;
|
|
16
|
-
}
|
|
17
|
-
function classifyMemory(entry) {
|
|
18
|
-
const content = entry.content.trim();
|
|
19
|
-
if (content.length < 3) {
|
|
20
|
-
return { memoryId: entry.id, content, severity: 'error', reason: 'too short (< 3 chars)' };
|
|
21
|
-
}
|
|
22
|
-
if (content.length < 10) {
|
|
23
|
-
return { memoryId: entry.id, content, severity: 'error', reason: 'too short (< 10 chars)' };
|
|
24
|
-
}
|
|
25
|
-
if (isReleaseCommitNoise(content)) {
|
|
26
|
-
return { memoryId: entry.id, content, severity: 'error', reason: 'release/commit noise, not a useful memory' };
|
|
27
|
-
}
|
|
28
|
-
if (isFragment(content)) {
|
|
29
|
-
return { memoryId: entry.id, content, severity: 'warning', reason: 'sentence fragment — lacks context' };
|
|
30
|
-
}
|
|
31
|
-
const substantive = substantiveWordCount(content);
|
|
32
|
-
if (substantive < 2) {
|
|
33
|
-
return { memoryId: entry.id, content, severity: 'warning', reason: `only ${substantive} substantive word(s) — too vague` };
|
|
34
|
-
}
|
|
35
|
-
if (content.length < 40 && hasNoSpecificity(content)) {
|
|
36
|
-
return { memoryId: entry.id, content, severity: 'warning', reason: 'no specific details (names, paths, numbers, code)' };
|
|
37
|
-
}
|
|
38
|
-
const reason = automaticDefect(entry);
|
|
39
|
-
if (reason !== null) {
|
|
40
|
-
return { memoryId: entry.id, content, severity: 'warning', reason: `automatic memory defect: ${reason}` };
|
|
41
|
-
}
|
|
42
|
-
return null;
|
|
43
|
-
}
|
|
44
|
-
/** `backing`: ids of memories that back an object (store.memoriesBackingObjects). */
|
|
45
|
-
export function auditMemories(entries, backing) {
|
|
46
|
-
const issues = [];
|
|
47
|
-
for (const entry of entries) {
|
|
48
|
-
const issue = auditMemory(entry, backing.has(entry.id));
|
|
49
|
-
if (issue)
|
|
50
|
-
issues.push(issue);
|
|
51
|
-
}
|
|
52
|
-
return {
|
|
53
|
-
total: entries.length,
|
|
54
|
-
issues,
|
|
55
|
-
clean: entries.length - issues.length,
|
|
56
|
-
};
|
|
57
|
-
}
|
|
58
7
|
// The one list of audit ops: the AuditOp type, `hippo audit list --op` and GET /v1/audit?op= all read it.
|
|
59
8
|
export const AUDIT_OPS = [
|
|
60
9
|
'remember',
|
|
@@ -128,7 +77,7 @@ function bigintSafeReplacer(_key, value) {
|
|
|
128
77
|
}
|
|
129
78
|
export function auditQueryFields(query) {
|
|
130
79
|
return {
|
|
131
|
-
query_hash:
|
|
80
|
+
query_hash: blockHash(query),
|
|
132
81
|
query_length: query.length,
|
|
133
82
|
};
|
|
134
83
|
}
|
|
@@ -172,7 +121,7 @@ export function queryAuditEvents(db, opts) {
|
|
|
172
121
|
}
|
|
173
122
|
const after = keysetAfter('ts', 'id', opts.after);
|
|
174
123
|
// One past the route's 10000 cap: GET /v1/audit reads a row ahead to tell whether another page exists.
|
|
175
|
-
const limit = Math.max(1, Math.min(opts.limit ??
|
|
124
|
+
const limit = Math.max(1, Math.min(opts.limit ?? DEFAULT_LIST_LIMIT, 10001));
|
|
176
125
|
// SAFETY: AUDIT_COLUMNS names exactly the AuditRow columns, in this order.
|
|
177
126
|
const rows = db
|
|
178
127
|
.prepare(`SELECT ${AUDIT_COLUMNS} FROM audit_log WHERE ${where.join(' AND ')}${after.sql} ORDER BY ts DESC, id DESC LIMIT ?`)
|