hippo-memory 1.70.0 → 1.71.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/agent-memories/claude-code.d.ts +4 -2
- package/dist/agent-memories/claude-code.js +14 -5
- package/dist/agent-memories/files.js +23 -12
- package/dist/agent-memories/markdown.d.ts +1 -3
- package/dist/agent-memories/markdown.js +1 -3
- package/dist/agent-memories/report.js +2 -1
- package/dist/agent-memories/sync.d.ts +4 -2
- package/dist/agent-memories/sync.js +10 -5
- package/dist/api/assemble.d.ts +7 -44
- package/dist/api/assemble.js +2 -22
- package/dist/api/audit.d.ts +5 -1
- package/dist/api/audit.js +9 -1
- package/dist/api/auth.d.ts +13 -22
- package/dist/api/auth.js +34 -24
- package/dist/api/auto-sleep.js +2 -2
- package/dist/api/availability.d.ts +2 -15
- package/dist/api/availability.js +2 -15
- package/dist/api/context-select.js +3 -4
- package/dist/api/context-types.d.ts +10 -35
- package/dist/api/context.d.ts +5 -22
- package/dist/api/context.js +21 -38
- package/dist/api/dormant.d.ts +5 -21
- package/dist/api/dormant.js +7 -26
- package/dist/api/drill-down.d.ts +7 -46
- package/dist/api/drill-down.js +5 -26
- package/dist/api/forget.d.ts +5 -24
- package/dist/api/forget.js +5 -28
- package/dist/api/graph.d.ts +8 -0
- package/dist/api/graph.js +7 -0
- package/dist/api/index.d.ts +2 -0
- package/dist/api/index.js +2 -0
- package/dist/api/instruction-detect.js +16 -5
- package/dist/api/ledger-db.d.ts +2 -1
- package/dist/api/ledger-db.js +5 -3
- package/dist/api/memories.d.ts +5 -0
- package/dist/api/memories.js +7 -0
- package/dist/api/objects.d.ts +9 -0
- package/dist/api/objects.js +11 -0
- package/dist/api/on-store.js +5 -3
- package/dist/api/predictions.d.ts +9 -0
- package/dist/api/predictions.js +18 -0
- package/dist/api/promote.d.ts +13 -17
- package/dist/api/promote.js +11 -19
- package/dist/api/prompt-hook.d.ts +4 -4
- package/dist/api/prompt-hook.js +10 -9
- package/dist/api/recall-cli.d.ts +55 -0
- package/dist/api/recall-cli.js +94 -0
- package/dist/api/recall-core.js +14 -6
- package/dist/api/recall-finish.d.ts +53 -0
- package/dist/api/recall-finish.js +30 -0
- package/dist/api/recall-history.d.ts +17 -84
- package/dist/api/recall-history.js +15 -88
- package/dist/api/recall-pipeline.d.ts +2 -3
- package/dist/api/recall-pipeline.js +16 -9
- package/dist/api/recall-types.d.ts +64 -304
- package/dist/api/recall.d.ts +5 -33
- package/dist/api/recall.js +59 -60
- package/dist/api/refine.d.ts +7 -0
- package/dist/api/refine.js +10 -0
- package/dist/api/remember-local.d.ts +57 -0
- package/dist/api/remember-local.js +90 -0
- package/dist/api/remember.d.ts +18 -1
- package/dist/api/remember.js +13 -1
- package/dist/api/sleep-run.d.ts +1 -3
- package/dist/api/sleep-run.js +17 -21
- package/dist/api/sleep.d.ts +9 -28
- package/dist/api/tokens.d.ts +3 -10
- package/dist/api/tokens.js +3 -10
- package/dist/api/types.d.ts +6 -29
- package/dist/api/types.js +4 -22
- package/dist/capture/command.d.ts +4 -12
- package/dist/capture/command.js +6 -22
- package/dist/capture/compact.d.ts +4 -15
- package/dist/capture/compact.js +16 -25
- package/dist/capture/compaction-record.js +101 -69
- package/dist/capture/compaction-spool.d.ts +1 -1
- package/dist/capture/compaction-spool.js +1 -1
- package/dist/capture/session-digest.d.ts +1 -1
- package/dist/capture/session-digest.js +13 -7
- package/dist/capture/transcript.d.ts +2 -10
- package/dist/capture/transcript.js +4 -18
- package/dist/cli/api-context.d.ts +3 -0
- package/dist/cli/api-context.js +6 -0
- package/dist/cli/audit-prune.d.ts +6 -39
- package/dist/cli/audit-prune.js +6 -39
- package/dist/cli/audit.d.ts +1 -1
- package/dist/cli/audit.js +33 -34
- package/dist/cli/auth.d.ts +2 -2
- package/dist/cli/auth.js +57 -39
- package/dist/cli/briefs.d.ts +4 -4
- package/dist/cli/briefs.js +18 -22
- package/dist/cli/card.d.ts +2 -2
- package/dist/cli/card.js +31 -32
- package/dist/cli/client.d.ts +7 -27
- package/dist/cli/client.js +24 -43
- package/dist/cli/compact-resume-payload.js +3 -2
- package/dist/cli/context.d.ts +1 -2
- package/dist/cli/context.js +12 -8
- package/dist/cli/continuity.d.ts +6 -6
- package/dist/cli/continuity.js +62 -64
- package/dist/cli/correction-latency.d.ts +2 -14
- package/dist/cli/correction-latency.js +2 -14
- package/dist/cli/curate.d.ts +13 -17
- package/dist/cli/curate.js +68 -92
- package/dist/cli/dag.d.ts +4 -4
- package/dist/cli/dag.js +33 -27
- package/dist/cli/decisions.d.ts +4 -4
- package/dist/cli/decisions.js +33 -47
- package/dist/cli/eval.js +15 -13
- package/dist/cli/exit.d.ts +6 -0
- package/dist/cli/exit.js +11 -0
- package/dist/cli/explain.d.ts +1 -2
- package/dist/cli/explain.js +6 -4
- package/dist/cli/flag-values.d.ts +6 -1
- package/dist/cli/flag-values.js +27 -10
- package/dist/cli/flags.d.ts +1 -0
- package/dist/cli/flags.js +1 -1
- package/dist/cli/github.d.ts +14 -0
- package/dist/{connectors/github/cli-impl.js → cli/github.js} +43 -71
- package/dist/cli/goals.d.ts +2 -2
- package/dist/cli/goals.js +46 -50
- package/dist/cli/hook-runtime.d.ts +9 -27
- package/dist/cli/hook-runtime.js +15 -31
- package/dist/cli/init.d.ts +2 -2
- package/dist/cli/init.js +6 -12
- package/dist/cli/install-steps.js +3 -12
- package/dist/cli/last-sleep.d.ts +2 -1
- package/dist/cli/last-sleep.js +3 -0
- package/dist/cli/maintenance.d.ts +4 -4
- package/dist/cli/maintenance.js +14 -19
- package/dist/cli/object-verbs.js +4 -3
- package/dist/cli/owner-validation.d.ts +5 -28
- package/dist/cli/owner-validation.js +5 -28
- package/dist/cli/playbooks.d.ts +4 -4
- package/dist/cli/playbooks.js +23 -28
- package/dist/cli/print.d.ts +2 -5
- package/dist/cli/print.js +1 -4
- package/dist/cli/projects.d.ts +2 -2
- package/dist/cli/projects.js +1 -3
- package/dist/cli/provenance-coverage.d.ts +2 -6
- package/dist/cli/provenance-coverage.js +2 -6
- package/dist/cli/quality-repair-once.js +2 -2
- package/dist/cli/recall.d.ts +2 -4
- package/dist/cli/recall.js +55 -131
- package/dist/cli/refine-llm.d.ts +5 -31
- package/dist/cli/refine-llm.js +9 -36
- package/dist/cli/remember.d.ts +3 -3
- package/dist/cli/remember.js +122 -180
- package/dist/cli/scheduler.d.ts +2 -17
- package/dist/cli/scheduler.js +12 -18
- package/dist/cli/serve.js +21 -12
- package/dist/cli/session-hooks.d.ts +10 -18
- package/dist/cli/session-hooks.js +112 -113
- package/dist/cli/setup.d.ts +4 -4
- package/dist/cli/setup.js +19 -21
- package/dist/cli/shared.d.ts +9 -23
- package/dist/cli/shared.js +9 -32
- package/dist/cli/slack.d.ts +2 -2
- package/dist/cli/slack.js +19 -23
- package/dist/cli/sleep.d.ts +3 -2
- package/dist/cli/sleep.js +15 -16
- package/dist/cli/status.d.ts +9 -12
- package/dist/cli/status.js +55 -98
- package/dist/cli/stdin.d.ts +4 -6
- package/dist/cli/stdin.js +2 -3
- package/dist/cli/transfer.d.ts +9 -9
- package/dist/cli/transfer.js +66 -89
- package/dist/cli/usage.js +11 -5
- package/dist/cli.d.ts +66 -448
- package/dist/cli.js +87 -263
- package/dist/connectors/github/backfill.d.ts +5 -25
- package/dist/connectors/github/backfill.js +14 -49
- package/dist/connectors/github/deletion.d.ts +4 -18
- package/dist/connectors/github/deletion.js +2 -15
- package/dist/connectors/github/dlq.d.ts +8 -33
- package/dist/connectors/github/dlq.js +12 -29
- package/dist/connectors/github/ingest.d.ts +2 -6
- package/dist/connectors/github/ingest.js +4 -10
- package/dist/connectors/github/octokit-client.d.ts +4 -16
- package/dist/connectors/github/octokit-client.js +27 -24
- package/dist/connectors/github/ratelimit.d.ts +3 -14
- package/dist/connectors/github/ratelimit.js +3 -14
- package/dist/connectors/github/scope.d.ts +3 -5
- package/dist/connectors/github/scope.js +3 -5
- package/dist/connectors/github/signature.d.ts +4 -26
- package/dist/connectors/github/signature.js +4 -26
- package/dist/connectors/github/tenant-routing.d.ts +2 -24
- package/dist/connectors/github/tenant-routing.js +4 -26
- package/dist/connectors/github/transform.js +2 -16
- package/dist/connectors/github/types.d.ts +3 -15
- package/dist/connectors/github/types.js +2 -9
- package/dist/connectors/github/webhook.d.ts +2 -16
- package/dist/connectors/github/webhook.js +6 -22
- package/dist/connectors/slack/backfill.d.ts +4 -17
- package/dist/connectors/slack/backfill.js +4 -13
- package/dist/connectors/slack/dlq.d.ts +2 -19
- package/dist/connectors/slack/dlq.js +2 -19
- package/dist/connectors/slack/ingest.d.ts +2 -3
- package/dist/connectors/slack/ingest.js +2 -3
- package/dist/connectors/slack/scope.d.ts +2 -8
- package/dist/connectors/slack/scope.js +2 -8
- package/dist/connectors/slack/signature.d.ts +1 -6
- package/dist/connectors/slack/tenant-routing.d.ts +2 -19
- package/dist/connectors/slack/tenant-routing.js +2 -21
- package/dist/connectors/slack/transform.d.ts +2 -18
- package/dist/connectors/slack/transform.js +2 -18
- package/dist/connectors/slack/types.d.ts +3 -9
- package/dist/connectors/slack/types.js +2 -4
- package/dist/connectors/slack/web-client.js +33 -27
- package/dist/connectors/slack/webhook.d.ts +2 -19
- package/dist/connectors/slack/webhook.js +5 -26
- package/dist/connectors/slack/workspaces.d.ts +4 -24
- package/dist/connectors/slack/workspaces.js +4 -24
- package/dist/consolidate/conflicts.js +6 -14
- package/dist/consolidate/dag-summary.d.ts +8 -0
- package/dist/consolidate/dag-summary.js +41 -0
- package/dist/consolidate/dag.d.ts +5 -28
- package/dist/consolidate/dag.js +14 -75
- package/dist/consolidate/decay.js +7 -19
- package/dist/consolidate/dedupe.d.ts +6 -52
- package/dist/consolidate/dedupe.js +13 -71
- package/dist/consolidate/flush-units.d.ts +3 -4
- package/dist/consolidate/flush-units.js +3 -3
- package/dist/consolidate/half-life-migration.d.ts +3 -26
- package/dist/consolidate/half-life-migration.js +11 -28
- package/dist/consolidate/llm-passes.js +4 -21
- package/dist/consolidate/memory-value-weights.d.ts +2 -13
- package/dist/consolidate/memory-value-weights.js +2 -13
- package/dist/consolidate/memory-value.d.ts +11 -84
- package/dist/consolidate/memory-value.js +16 -104
- package/dist/consolidate/merge.js +10 -31
- package/dist/consolidate/merged-row.js +2 -1
- package/dist/consolidate/physics-pass.js +1 -3
- package/dist/consolidate/replay.d.ts +6 -38
- package/dist/consolidate/replay.js +14 -52
- package/dist/consolidate/run.js +1 -1
- package/dist/consolidate/sleep.d.ts +1 -8
- package/dist/consolidate/sleep.js +5 -17
- package/dist/consolidate/trace.d.ts +3 -18
- package/dist/consolidate/trace.js +3 -18
- package/dist/consolidate/traces.js +6 -22
- package/dist/core/ablation.d.ts +4 -91
- package/dist/core/ablation.js +4 -91
- package/dist/core/ambient.d.ts +1 -8
- package/dist/core/ambient.js +1 -8
- package/dist/core/capture-contract.d.ts +4 -2
- package/dist/core/capture-contract.js +4 -2
- package/dist/core/card.d.ts +4 -1
- package/dist/core/card.js +8 -0
- package/dist/core/compare.d.ts +11 -67
- package/dist/core/compare.js +9 -63
- package/dist/core/config.d.ts +10 -24
- package/dist/core/config.js +13 -14
- package/dist/core/handoff.d.ts +1 -7
- package/dist/core/handoff.js +1 -7
- package/dist/core/memory-quality.js +1 -1
- package/dist/core/memory.d.ts +41 -164
- package/dist/core/memory.js +51 -221
- package/dist/core/package-root.d.ts +3 -0
- package/dist/core/package-root.js +5 -0
- package/dist/core/physics-config.d.ts +1 -4
- package/dist/core/physics-config.js +3 -8
- package/dist/core/physics.d.ts +15 -61
- package/dist/core/physics.js +59 -122
- package/dist/core/project-identity.d.ts +17 -58
- package/dist/core/project-identity.js +17 -38
- package/dist/core/project-remote.js +13 -2
- package/dist/core/raw-append-only.d.ts +5 -0
- package/dist/core/raw-append-only.js +7 -0
- package/dist/core/salience.d.ts +1 -7
- package/dist/core/salience.js +1 -7
- package/dist/dashboard/dashboard-actions.js +2 -2
- package/dist/dashboard/dashboard-snapshot.d.ts +2 -1
- package/dist/dashboard/dashboard-snapshot.js +11 -2
- package/dist/dashboard/dashboard-types.d.ts +2 -1
- package/dist/dashboard/dashboard.d.ts +1 -0
- package/dist/dashboard/dashboard.js +50 -4
- package/dist/db/busy.d.ts +1 -1
- package/dist/db/busy.js +17 -8
- package/dist/db/connect.d.ts +1 -0
- package/dist/db/connect.js +3 -3
- package/dist/db/migrate.js +3 -3
- package/dist/db/migrations/types.d.ts +2 -5
- package/dist/db/migrations/v14.js +2 -3
- package/dist/db/migrations/v15.js +2 -8
- package/dist/db/migrations/v16.js +2 -3
- package/dist/db/migrations/v17.js +2 -3
- package/dist/db/migrations/v19.js +2 -5
- package/dist/db/migrations/v20.js +2 -7
- package/dist/db/migrations/v22.js +4 -17
- package/dist/db/migrations/v23.js +3 -14
- package/dist/db/migrations/v24.js +2 -4
- package/dist/db/migrations/v25.js +3 -8
- package/dist/db/migrations/v26.js +2 -13
- package/dist/db/migrations/v27.js +3 -11
- package/dist/db/migrations/v28.js +2 -14
- package/dist/db/migrations/v29.js +4 -18
- package/dist/db/migrations/v30.js +4 -16
- package/dist/db/migrations/v31.js +2 -15
- package/dist/db/migrations/v32.js +4 -22
- package/dist/db/migrations/v33.js +2 -15
- package/dist/db/migrations/v34.js +2 -11
- package/dist/db/migrations/v35.js +2 -11
- package/dist/db/migrations/v36.js +2 -11
- package/dist/db/migrations/v37.js +8 -33
- package/dist/db/migrations/v38.js +5 -38
- package/dist/db/migrations/v39.js +9 -20
- package/dist/db/migrations/v40.js +2 -9
- package/dist/db/migrations/v41.js +2 -24
- package/dist/db/migrations/v43.js +1 -1
- package/dist/db/migrations/v44.js +2 -8
- package/dist/db/migrations/v45.js +2 -7
- package/dist/db/migrations/v47.js +2 -3
- package/dist/db/migrations/v51.js +1 -1
- package/dist/db/open.d.ts +2 -0
- package/dist/db/open.js +17 -1
- package/dist/db/physics-state.d.ts +6 -22
- package/dist/db/physics-state.js +25 -36
- package/dist/db/raw-archive-mirror-cleanup.d.ts +2 -17
- package/dist/db/raw-archive-mirror-cleanup.js +2 -17
- package/dist/db/vector-store.d.ts +2 -0
- package/dist/db/vector-store.js +8 -1
- package/dist/doctor.js +74 -19
- package/dist/entry/session-text.js +2 -1
- package/dist/eval/eval-stats.d.ts +15 -53
- package/dist/eval/eval-stats.js +12 -42
- package/dist/eval/eval-suite.d.ts +2 -13
- package/dist/eval/eval-suite.js +74 -34
- package/dist/eval/eval.d.ts +6 -24
- package/dist/eval/eval.js +7 -34
- package/dist/eval/judgment.d.ts +0 -3
- package/dist/eval/judgment.js +19 -11
- package/dist/extensions/openclaw-plugin/index.js +1 -1
- package/dist/graph/extract.d.ts +5 -27
- package/dist/graph/extract.js +7 -33
- package/dist/graph/recall.d.ts +7 -20
- package/dist/graph/recall.js +14 -76
- package/dist/graph/stream.d.ts +7 -39
- package/dist/graph/stream.js +11 -34
- package/dist/graph/view.d.ts +9 -35
- package/dist/graph/view.js +11 -39
- package/dist/hooks/codex-wrapper.js +2 -2
- package/dist/hooks/copilot.js +2 -1
- package/dist/hooks/hook-blocks.d.ts +6 -2
- package/dist/hooks/hook-blocks.js +37 -124
- package/dist/hooks/json-hooks.d.ts +4 -36
- package/dist/hooks/json-hooks.js +18 -57
- package/dist/hooks/opencode.d.ts +0 -38
- package/dist/hooks/opencode.js +9 -76
- package/dist/hooks/shared.d.ts +8 -17
- package/dist/hooks/shared.js +29 -20
- package/dist/importers/core.d.ts +12 -37
- package/dist/importers/core.js +9 -27
- package/dist/importers/markdown-parse.d.ts +8 -22
- package/dist/importers/markdown-parse.js +8 -25
- package/dist/importers/markdown.js +3 -12
- package/dist/importers/sources.js +7 -35
- package/dist/importers/vault.d.ts +2 -8
- package/dist/importers/vault.js +25 -81
- package/dist/index.d.ts +6 -2
- package/dist/index.js +6 -2
- package/dist/learn/autolearn.d.ts +14 -41
- package/dist/learn/autolearn.js +14 -41
- package/dist/learn/extract.js +2 -4
- package/dist/learn/forward-claim-detector.d.ts +6 -30
- package/dist/learn/forward-claim-detector.js +14 -66
- package/dist/learn/invalidation.d.ts +6 -18
- package/dist/learn/invalidation.js +9 -26
- package/dist/mcp/admin-tools.js +3 -5
- package/dist/mcp/memory-tools.js +4 -9
- package/dist/mcp/protocol.d.ts +8 -26
- package/dist/mcp/protocol.js +3 -6
- package/dist/mcp/recall-tools.js +3 -3
- package/dist/mcp/request.d.ts +3 -11
- package/dist/mcp/request.js +10 -26
- package/dist/mcp/server.d.ts +3 -9
- package/dist/mcp/server.js +5 -16
- package/dist/mcp/session-state.d.ts +1 -1
- package/dist/mcp/session-state.js +5 -11
- package/dist/mcp/stdio.d.ts +2 -6
- package/dist/mcp/stdio.js +48 -12
- package/dist/mcp/tools.js +5 -3
- package/dist/objects/customer-notes.d.ts +7 -42
- package/dist/objects/customer-notes.js +7 -48
- package/dist/objects/decisions.d.ts +12 -50
- package/dist/objects/decisions.js +15 -53
- package/dist/objects/incidents.d.ts +7 -38
- package/dist/objects/incidents.js +7 -41
- package/dist/objects/policies.d.ts +11 -89
- package/dist/objects/policies.js +11 -98
- package/dist/objects/processes.d.ts +7 -52
- package/dist/objects/processes.js +7 -61
- package/dist/objects/project-briefs.d.ts +11 -55
- package/dist/objects/project-briefs.js +14 -75
- package/dist/objects/skills.d.ts +7 -42
- package/dist/objects/skills.js +8 -54
- package/dist/postinstall.js +6 -19
- package/dist/predictions/planning-fallacy.d.ts +11 -34
- package/dist/rerankers/clef.js +3 -31
- package/dist/rerankers/cross-encoder.js +4 -6
- package/dist/rerankers/jev.js +9 -6
- package/dist/rerankers/llm.d.ts +2 -11
- package/dist/rerankers/llm.js +14 -14
- package/dist/rerankers/outage-warning.d.ts +2 -1
- package/dist/rerankers/outage-warning.js +2 -1
- package/dist/rerankers/remote.d.ts +1 -0
- package/dist/rerankers/remote.js +2 -0
- package/dist/rerankers/types.d.ts +2 -14
- package/dist/search/boosts.d.ts +0 -2
- package/dist/search/boosts.js +2 -2
- package/dist/search/goal-boost.d.ts +23 -0
- package/dist/search/goal-boost.js +90 -0
- package/dist/search/hybrid.d.ts +2 -0
- package/dist/search/multihop.js +2 -3
- package/dist/search/path-context.d.ts +5 -18
- package/dist/search/path-context.js +5 -18
- package/dist/search/physics-search.js +11 -8
- package/dist/search/rrf.d.ts +7 -35
- package/dist/search/rrf.js +5 -30
- package/dist/search/vector.d.ts +7 -0
- package/dist/search/vector.js +35 -5
- package/dist/server/auth.d.ts +9 -28
- package/dist/server/auth.js +32 -25
- package/dist/server/boot.d.ts +2 -21
- package/dist/server/boot.js +63 -96
- package/dist/server/client-ip.d.ts +3 -19
- package/dist/server/client-ip.js +5 -28
- package/dist/server/defaults.d.ts +3 -0
- package/dist/server/defaults.js +4 -0
- package/dist/server/key-check-bounds.d.ts +2 -1
- package/dist/server/lifecycle.d.ts +5 -4
- package/dist/server/lifecycle.js +19 -4
- package/dist/server/mcp-http.js +10 -44
- package/dist/server/rate-limit.d.ts +5 -18
- package/dist/server/rate-limit.js +4 -13
- package/dist/server/request.d.ts +4 -8
- package/dist/server/request.js +9 -17
- package/dist/server/route-table.js +42 -49
- package/dist/server/routes/admin.js +22 -28
- package/dist/server/routes/customer-notes.js +7 -12
- package/dist/server/routes/decisions.js +10 -17
- package/dist/server/routes/incidents.js +12 -20
- package/dist/server/routes/memories.js +12 -32
- package/dist/server/routes/object-routes.d.ts +0 -5
- package/dist/server/routes/object-routes.js +7 -15
- package/dist/server/routes/policies.js +10 -18
- package/dist/server/routes/predictions.js +13 -25
- package/dist/server/routes/processes.js +16 -26
- package/dist/server/routes/project-briefs.js +9 -16
- package/dist/server/routes/recall.js +10 -35
- package/dist/server/routes/skills.js +8 -18
- package/dist/server/server-detect.d.ts +9 -53
- package/dist/server/server-detect.js +24 -90
- package/dist/server/sleep-offload.js +4 -1
- package/dist/server/types.d.ts +12 -10
- package/dist/server/validation.d.ts +3 -1
- package/dist/server/validation.js +10 -23
- package/dist/server.d.ts +2 -2
- package/dist/server.js +3 -2
- package/dist/sharing/global-store.d.ts +19 -0
- package/dist/sharing/global-store.js +75 -0
- package/dist/sharing/global-sync.d.ts +6 -0
- package/dist/sharing/global-sync.js +80 -0
- package/dist/sharing/project-merge.d.ts +4 -5
- package/dist/sharing/project-merge.js +9 -7
- package/dist/sharing/scope.d.ts +4 -11
- package/dist/sharing/scope.js +4 -11
- package/dist/sharing/search-both.d.ts +60 -0
- package/dist/sharing/search-both.js +138 -0
- package/dist/sharing/share.d.ts +38 -0
- package/dist/sharing/share.js +226 -0
- package/dist/store/ambient.js +4 -9
- package/dist/store/audit-event.d.ts +4 -12
- package/dist/store/audit-event.js +4 -12
- package/dist/store/audit.d.ts +2 -5
- package/dist/store/audit.js +4 -12
- package/dist/store/auth.d.ts +6 -6
- package/dist/store/auth.js +10 -9
- package/dist/store/candidates.d.ts +20 -3
- package/dist/store/candidates.js +77 -48
- package/dist/store/card-detail.d.ts +2 -1
- package/dist/store/card-detail.js +2 -1
- package/dist/store/cards.d.ts +14 -9
- package/dist/store/cards.js +72 -126
- package/dist/store/conflicts.d.ts +4 -21
- package/dist/store/conflicts.js +71 -150
- package/dist/store/connectors/github.d.ts +10 -10
- package/dist/store/connectors/github.js +10 -10
- package/dist/store/dashboard-reads.js +4 -8
- package/dist/store/delete-and-batch.d.ts +11 -31
- package/dist/store/delete-and-batch.js +48 -64
- package/dist/store/delivery-recorder.d.ts +8 -4
- package/dist/store/delivery-recorder.js +25 -15
- package/dist/store/diagnostics.js +6 -13
- package/dist/store/dormant.d.ts +7 -29
- package/dist/store/dormant.js +15 -56
- package/dist/store/embeddings/index.d.ts +11 -80
- package/dist/store/embeddings/index.js +71 -207
- package/dist/store/embeddings/local.js +15 -32
- package/dist/store/embeddings/provider.d.ts +16 -53
- package/dist/store/embeddings/provider.js +41 -69
- package/dist/store/entry-reads.d.ts +21 -57
- package/dist/store/entry-reads.js +65 -126
- package/dist/store/entry-row.d.ts +6 -35
- package/dist/store/entry-row.js +9 -37
- package/dist/store/entry-writes.d.ts +10 -16
- package/dist/store/entry-writes.js +17 -35
- package/dist/store/goals.d.ts +3 -40
- package/dist/store/goals.js +21 -160
- package/dist/store/graph-queue.d.ts +6 -22
- package/dist/store/graph-queue.js +14 -45
- package/dist/store/graph-reads.d.ts +11 -35
- package/dist/store/graph-reads.js +20 -58
- package/dist/store/graph-rows.d.ts +3 -6
- package/dist/store/graph-rows.js +6 -9
- package/dist/store/graph-view-rows.d.ts +2 -1
- package/dist/store/graph-view-rows.js +2 -1
- package/dist/store/graph-writes.d.ts +6 -31
- package/dist/store/graph-writes.js +13 -37
- package/dist/store/half-life.d.ts +2 -1
- package/dist/store/half-life.js +14 -16
- package/dist/store/handoffs.d.ts +5 -11
- package/dist/store/handoffs.js +16 -34
- package/dist/store/index-and-stats.d.ts +6 -19
- package/dist/store/index-and-stats.js +34 -82
- package/dist/store/markdown.d.ts +2 -6
- package/dist/store/markdown.js +21 -20
- package/dist/store/mirrors.d.ts +2 -6
- package/dist/store/mirrors.js +14 -23
- package/dist/store/open.js +6 -13
- package/dist/store/planning-fallacy-evidence.d.ts +2 -30
- package/dist/store/planning-fallacy-evidence.js +8 -37
- package/dist/store/port.d.ts +82 -79
- package/dist/store/predictions.d.ts +11 -51
- package/dist/store/predictions.js +38 -119
- package/dist/{cli → store}/quality-repair.js +15 -31
- package/dist/store/raw-archive.d.ts +4 -16
- package/dist/store/raw-archive.js +14 -29
- package/dist/store/recall-scope.d.ts +19 -79
- package/dist/store/recall-scope.js +21 -82
- package/dist/store/recall-trace.d.ts +10 -77
- package/dist/store/recall-trace.js +19 -95
- package/dist/store/rejected-values.js +7 -19
- package/dist/store/rejection.d.ts +12 -58
- package/dist/store/rejection.js +13 -65
- package/dist/store/report-reads.d.ts +6 -0
- package/dist/store/report-reads.js +29 -0
- package/dist/store/rows.d.ts +9 -19
- package/dist/store/rows.js +36 -34
- package/dist/store/rule-sql.d.ts +5 -0
- package/dist/store/rule-sql.js +37 -0
- package/dist/store/search-rows.d.ts +7 -38
- package/dist/store/search-rows.js +14 -50
- package/dist/store/sessions.d.ts +10 -47
- package/dist/store/sessions.js +17 -73
- package/dist/store/sqlite/connector-events-group.js +2 -2
- package/dist/store/sqlite/entry-writes-group.js +2 -2
- package/dist/store/sqlite/error-codec.js +4 -2
- package/dist/store/sqlite/executor.d.ts +2 -1
- package/dist/store/sqlite/executor.js +2 -1
- package/dist/store/sqlite/local.d.ts +3 -3
- package/dist/store/sqlite/local.js +1 -0
- package/dist/store/sqlite/object-rows.js +6 -3
- package/dist/store/sqlite/objects-group.js +4 -2
- package/dist/store/sqlite/quarantine-group.js +2 -2
- package/dist/store/sqlite/store.d.ts +1 -4
- package/dist/store/sqlite/store.js +2 -3
- package/dist/store/sqlite/vector-reads-group.js +2 -2
- package/dist/store/sqlite/worker-jobs.js +1 -1
- package/dist/store/sqlite/worker-ops.d.ts +13 -2
- package/dist/store/sqlite/worker-ops.js +13 -2
- package/dist/store/sqlite/worker-store.js +5 -2
- package/dist/store/summaries.d.ts +10 -62
- package/dist/store/summaries.js +34 -146
- package/dist/store/summary-dirty.js +1 -1
- package/dist/store/tenant-lookup.d.ts +6 -1
- package/dist/store/tenant-lookup.js +7 -0
- package/dist/store/tenant.d.ts +2 -16
- package/dist/store/tenant.js +4 -19
- package/dist/store/token-ledger.d.ts +13 -43
- package/dist/store/token-ledger.js +19 -50
- package/dist/store/usage-reports.js +5 -13
- package/dist/store/vector-index.d.ts +46 -0
- package/dist/store/vector-index.js +170 -0
- package/dist/store/working-memory.d.ts +6 -25
- package/dist/store/working-memory.js +18 -52
- package/dist/store/yaml.d.ts +1 -5
- package/dist/store/yaml.js +2 -6
- package/dist/support-bundle.js +7 -5
- package/dist/trust/reject-flow.js +1 -3
- package/dist/util/anthropic-messages.js +14 -2
- package/dist/util/atomic-write.d.ts +2 -1
- package/dist/util/atomic-write.js +35 -4
- package/dist/util/capped-json.d.ts +6 -0
- package/dist/util/capped-json.js +46 -0
- package/dist/util/crash-handlers.d.ts +8 -1
- package/dist/util/crash-handlers.js +52 -10
- package/dist/util/env.d.ts +13 -6
- package/dist/util/env.js +14 -7
- package/dist/util/home-path.d.ts +2 -1
- package/dist/util/home-path.js +4 -2
- package/dist/util/http-retry.d.ts +3 -1
- package/dist/util/http-retry.js +26 -5
- package/dist/util/log.d.ts +3 -2
- package/dist/util/log.js +25 -9
- package/dist/util/request-scope.d.ts +2 -1
- package/dist/util/request-scope.js +2 -1
- package/dist/util/secret-detect.d.ts +5 -30
- package/dist/util/secret-detect.js +13 -39
- package/dist/util/stored-json.d.ts +1 -1
- package/dist/util/stored-json.js +1 -1
- package/dist/util/token-text.d.ts +1 -4
- package/dist/util/token-text.js +1 -4
- package/dist/util/transcript-tail.d.ts +2 -0
- package/dist/util/transcript-tail.js +24 -23
- package/dist/util/version.d.ts +5 -20
- package/dist/util/version.js +5 -20
- package/extensions/openclaw-plugin/index.ts +1 -1
- package/extensions/openclaw-plugin/openclaw.plugin.json +1 -1
- package/extensions/openclaw-plugin/package.json +1 -1
- package/openclaw.plugin.json +1 -1
- package/package.json +1 -1
- package/dist/connectors/github/cli-impl.d.ts +0 -25
- package/dist/sharing/shared.d.ts +0 -187
- package/dist/sharing/shared.js +0 -563
- package/dist/store/vector-writes.d.ts +0 -13
- package/dist/store/vector-writes.js +0 -89
- /package/dist/{cli → store}/quality-repair.d.ts +0 -0
package/dist/sharing/scope.d.ts
CHANGED
|
@@ -1,14 +1,7 @@
|
|
|
1
|
-
/**
|
|
2
|
-
*
|
|
3
|
-
* Returns a scope name string (no prefix), or null if no scope detected.
|
|
4
|
-
* Priority: HIPPO_SCOPE > GSTACK_SKILL > OPENCLAW_SKILL.
|
|
5
|
-
*
|
|
6
|
-
* Pure env var reads: no I/O, safe to call from hot paths (e.g. UserPromptSubmit hook).
|
|
7
|
-
*/
|
|
1
|
+
/** Detect the current operational scope from env (HIPPO_SCOPE > GSTACK_SKILL > OPENCLAW_SKILL); returns the name without prefix, or null.
|
|
2
|
+
* Pure env reads, no I/O, so it is safe on hot paths such as the UserPromptSubmit hook. */
|
|
8
3
|
export declare function detectScope(): string | null;
|
|
9
|
-
/**
|
|
10
|
-
*
|
|
11
|
-
* Returns: 1 if matching scope, -1 if mismatching scope, 0 if neutral (no scope on either side).
|
|
12
|
-
*/
|
|
4
|
+
/** Compute scope match between a memory's scope tags and the active scope.
|
|
5
|
+
* Returns: 1 if matching scope, -1 if mismatching scope, 0 if neutral (no scope on either side). */
|
|
13
6
|
export declare function scopeMatch(memoryTags: string[], activeScope: string | null): -1 | 0 | 1;
|
|
14
7
|
//# sourceMappingURL=scope.d.ts.map
|
package/dist/sharing/scope.js
CHANGED
|
@@ -1,11 +1,6 @@
|
|
|
1
1
|
import { envGstackSkill, envOpenclawSkill, envScope } from '../util/env.js';
|
|
2
|
-
/**
|
|
3
|
-
*
|
|
4
|
-
* Returns a scope name string (no prefix), or null if no scope detected.
|
|
5
|
-
* Priority: HIPPO_SCOPE > GSTACK_SKILL > OPENCLAW_SKILL.
|
|
6
|
-
*
|
|
7
|
-
* Pure env var reads: no I/O, safe to call from hot paths (e.g. UserPromptSubmit hook).
|
|
8
|
-
*/
|
|
2
|
+
/** Detect the current operational scope from env (HIPPO_SCOPE > GSTACK_SKILL > OPENCLAW_SKILL); returns the name without prefix, or null.
|
|
3
|
+
* Pure env reads, no I/O, so it is safe on hot paths such as the UserPromptSubmit hook. */
|
|
9
4
|
export function detectScope() {
|
|
10
5
|
const explicit = envScope();
|
|
11
6
|
if (explicit && explicit.trim())
|
|
@@ -18,10 +13,8 @@ export function detectScope() {
|
|
|
18
13
|
return openclawSkill.trim();
|
|
19
14
|
return null;
|
|
20
15
|
}
|
|
21
|
-
/**
|
|
22
|
-
*
|
|
23
|
-
* Returns: 1 if matching scope, -1 if mismatching scope, 0 if neutral (no scope on either side).
|
|
24
|
-
*/
|
|
16
|
+
/** Compute scope match between a memory's scope tags and the active scope.
|
|
17
|
+
* Returns: 1 if matching scope, -1 if mismatching scope, 0 if neutral (no scope on either side). */
|
|
25
18
|
export function scopeMatch(memoryTags, activeScope) {
|
|
26
19
|
const scopeTags = memoryTags.filter(t => t.startsWith('scope:'));
|
|
27
20
|
if (scopeTags.length === 0)
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { MemoryEntry } from '../core/memory.js';
|
|
2
|
+
import { type SearchResult, type ResultCost } from '../core/search-types.js';
|
|
3
|
+
import { type HybridVectorCandidates } from '../search/vector.js';
|
|
4
|
+
export declare function logEmbedAllFailure<E>(caller: string, err: E): void;
|
|
5
|
+
export interface SearchOptions {
|
|
6
|
+
budget?: number;
|
|
7
|
+
now?: Date;
|
|
8
|
+
minResults?: number;
|
|
9
|
+
/** Tenant scope for both stores. Undefined = no filter (legacy single-tenant). */
|
|
10
|
+
tenantId?: string;
|
|
11
|
+
}
|
|
12
|
+
/** Search both local and global stores and merge: local results are boosted 1.2x to prefer project context.
|
|
13
|
+
* Returns results sorted by adjusted score within the combined token budget. */
|
|
14
|
+
export declare function searchBoth(query: string, localRoot: string, globalRoot: string, options?: SearchOptions): SearchResult[];
|
|
15
|
+
export interface HybridSearchOptions extends SearchOptions {
|
|
16
|
+
embeddingWeight?: number;
|
|
17
|
+
explain?: boolean;
|
|
18
|
+
mmr?: boolean;
|
|
19
|
+
mmrLambda?: number;
|
|
20
|
+
/** Multiplier applied to local-store scores when merging with global.
|
|
21
|
+
* Defaults to 1.2. Use 1.0 to remove the local bias for eval comparisons. */
|
|
22
|
+
localBump?: number;
|
|
23
|
+
/** Active scope for scope-boost scoring. Auto-detected if not provided. */
|
|
24
|
+
scope?: string | null;
|
|
25
|
+
/** Include superseded memories in results. Default false. */
|
|
26
|
+
includeSuperseded?: boolean;
|
|
27
|
+
/** Filter to memories current at this ISO date string. */
|
|
28
|
+
asOf?: string;
|
|
29
|
+
/** Budget cost per result, spent the same way in each store and in the merged list. */
|
|
30
|
+
cost?: ResultCost;
|
|
31
|
+
/** Propagated to underlying hybridSearch calls.
|
|
32
|
+
* Per-call > env HIPPO_SUMMARY_DEBOOST > 0.85 default. */
|
|
33
|
+
summaryDeboost?: number;
|
|
34
|
+
/** Propagated. Default true (1.05 boost if rebuilt within 7d). */
|
|
35
|
+
summaryFreshness?: boolean;
|
|
36
|
+
/** Optional admission predicate applied to the loaded candidates of BOTH stores before ranking, cross-store dedupe and budgeting,
|
|
37
|
+
* so an excluded row cannot shadow its admitted duplicate or saturate the budget. Undefined (recall paths never set it) means no filter. */
|
|
38
|
+
entryFilter?: (entry: MemoryEntry) => boolean;
|
|
39
|
+
/** Recall scope filter for `searchBothHybrid`: absent is the only unfiltered mode; present uses `loadRecallSearchEntries` plus a JS post-filter.
|
|
40
|
+
* `{}` = default-deny (legacy and `<source>:private:*` excluded); `{ requested: 'X' }` = exact; `{ requested: 'X', additive: true }` = default plus X.
|
|
41
|
+
* An object, not `string | null`, because the sibling `scope` option already gives null a different meaning.
|
|
42
|
+
* Do not pass `{}` casually from non-recall paths. */
|
|
43
|
+
recallScope?: {
|
|
44
|
+
requested?: string;
|
|
45
|
+
additive?: boolean;
|
|
46
|
+
ownScope?: string;
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
/** Hybrid search across both local and global stores, using embeddings when available.
|
|
50
|
+
* Async version of searchBoth that calls hybridSearch instead of search. */
|
|
51
|
+
export declare function searchBothHybrid(query: string, localRoot: string, globalRoot: string, options?: HybridSearchOptions): Promise<SearchResult[]>;
|
|
52
|
+
/** Hybrid ranking of rows already loaded from each store: the local bump, one copy per text, then the shared budget. */
|
|
53
|
+
export declare function rankBothStores(query: string, roots: {
|
|
54
|
+
local: string;
|
|
55
|
+
global: string;
|
|
56
|
+
}, entries: {
|
|
57
|
+
local: MemoryEntry[];
|
|
58
|
+
global: MemoryEntry[];
|
|
59
|
+
}, vectorCandidates: HybridVectorCandidates, options?: HybridSearchOptions): Promise<SearchResult[]>;
|
|
60
|
+
//# sourceMappingURL=search-both.d.ts.map
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
// Search across the local and global stores, merged into one ranked, budgeted list.
|
|
2
|
+
import { compareScoresDesc } from '../core/compare.js';
|
|
3
|
+
import * as fs from 'fs';
|
|
4
|
+
import { loadSearchEntries, loadRecallSearchEntries, recallScopeFilter } from '../store/search-rows.js';
|
|
5
|
+
import { passesScopeFilterForRecall, passesCliRecallScopeFilter } from '../store/recall-scope.js';
|
|
6
|
+
import { search } from '../search/bm25-search.js';
|
|
7
|
+
import { hybridSearch } from '../search/hybrid.js';
|
|
8
|
+
import { fitBudget } from '../search/finalize.js';
|
|
9
|
+
import { DEFAULT_LOCAL_BUMP, DEFAULT_RECALL_BUDGET } from '../core/search-types.js';
|
|
10
|
+
import { startQueryEmbedDeadline } from '../search/vector.js';
|
|
11
|
+
import { evalNow } from '../core/ablation.js';
|
|
12
|
+
import { duplicateKey } from '../util/same-text.js';
|
|
13
|
+
import { errorMessage, log } from '../util/log.js';
|
|
14
|
+
// The rows are already copied; a failed background embed only delays vectors, so it warns instead of throwing.
|
|
15
|
+
export function logEmbedAllFailure(caller, err) {
|
|
16
|
+
log.warn(`${caller}: background embed failed (${errorMessage(err)}); run 'hippo embed' to backfill`);
|
|
17
|
+
}
|
|
18
|
+
/** Search both local and global stores and merge: local results are boosted 1.2x to prefer project context.
|
|
19
|
+
* Returns results sorted by adjusted score within the combined token budget. */
|
|
20
|
+
export function searchBoth(query, localRoot, globalRoot, options = {}) {
|
|
21
|
+
const { budget = DEFAULT_RECALL_BUDGET, now = evalNow(), minResults, tenantId } = options;
|
|
22
|
+
const effectiveMin = minResults ?? 1;
|
|
23
|
+
const localEntries = fs.existsSync(localRoot) ? loadSearchEntries(localRoot, query, undefined, tenantId) : [];
|
|
24
|
+
const globalEntries = fs.existsSync(globalRoot) ? loadSearchEntries(globalRoot, query, undefined, tenantId) : [];
|
|
25
|
+
if (localEntries.length === 0 && globalEntries.length === 0)
|
|
26
|
+
return [];
|
|
27
|
+
// Search each store with full budget, then blend
|
|
28
|
+
const localResults = search(query, localEntries, { budget, now, minResults });
|
|
29
|
+
const globalResults = search(query, globalEntries, { budget, now, minResults });
|
|
30
|
+
const deduped = dedupeByContent(tagLocalAndGlobal(localResults, globalResults));
|
|
31
|
+
// PLAIN stable score sort on purpose: both inputs are deterministically ordered,
|
|
32
|
+
// and an exact tie keeps the LOCAL result ahead of the global one (concat order).
|
|
33
|
+
deduped.sort((a, b) => compareScoresDesc(a.score, b.score));
|
|
34
|
+
// Apply combined token budget (guarantee at least minResults items)
|
|
35
|
+
const results = [];
|
|
36
|
+
let usedTokens = 0;
|
|
37
|
+
for (let i = 0; i < deduped.length; i++) {
|
|
38
|
+
if (results.length >= effectiveMin && usedTokens + deduped[i].tokens > budget)
|
|
39
|
+
continue;
|
|
40
|
+
usedTokens += deduped[i].tokens;
|
|
41
|
+
results.push(deduped[i]);
|
|
42
|
+
}
|
|
43
|
+
return results;
|
|
44
|
+
}
|
|
45
|
+
function tagLocalAndGlobal(localResults, globalResults) {
|
|
46
|
+
// Tag global results. Local memories get a configurable priority bump.
|
|
47
|
+
return [
|
|
48
|
+
...localResults.map((r) => ({
|
|
49
|
+
...r,
|
|
50
|
+
isGlobal: false,
|
|
51
|
+
score: r.score * DEFAULT_LOCAL_BUMP,
|
|
52
|
+
breakdown: r.breakdown
|
|
53
|
+
? { ...r.breakdown, sourceBump: DEFAULT_LOCAL_BUMP, final: r.breakdown.final * DEFAULT_LOCAL_BUMP }
|
|
54
|
+
: undefined,
|
|
55
|
+
})),
|
|
56
|
+
...globalResults.map((r) => ({ ...r, isGlobal: true })),
|
|
57
|
+
];
|
|
58
|
+
}
|
|
59
|
+
function dedupeByContent(tagged) {
|
|
60
|
+
// Remove duplicates by content (local/global IDs differ after promote/share)
|
|
61
|
+
const seen = new Set();
|
|
62
|
+
return tagged.filter((r) => {
|
|
63
|
+
const key = duplicateKey(r.entry.content);
|
|
64
|
+
if (seen.has(key))
|
|
65
|
+
return false;
|
|
66
|
+
seen.add(key);
|
|
67
|
+
return true;
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
/** Hybrid search across both local and global stores, using embeddings when available.
|
|
71
|
+
* Async version of searchBoth that calls hybridSearch instead of search. */
|
|
72
|
+
export async function searchBothHybrid(query, localRoot, globalRoot, options = {}) {
|
|
73
|
+
const { includeSuperseded, asOf, tenantId, entryFilter, recallScope } = options;
|
|
74
|
+
// With an admission filter, lift the per-store candidate cap (default 200) to a bounded 5000: excluded rows could otherwise fill the window first.
|
|
75
|
+
const searchWindow = entryFilter ? 5000 : undefined;
|
|
76
|
+
// Recall mode: push the scope predicate into SQL like api.recall, so quarantine/private rows never enter the candidates, shadow duplicates or use budget.
|
|
77
|
+
// The JS post-filter below is the regex-only `<source>:private:*` half plus defense in depth on exact match.
|
|
78
|
+
const loadEntries = (root) => {
|
|
79
|
+
if (!fs.existsSync(root))
|
|
80
|
+
return [];
|
|
81
|
+
return recallScope
|
|
82
|
+
? loadRecallSearchEntries(root, query, searchWindow, tenantId, recallScope.requested, recallScope.additive ? 'additive' : 'exact', Boolean(includeSuperseded) || Boolean(asOf), undefined, recallScope.ownScope)
|
|
83
|
+
: loadSearchEntries(root, query, searchWindow, tenantId);
|
|
84
|
+
};
|
|
85
|
+
const passesScope = (e) => !recallScope || (recallScope.additive
|
|
86
|
+
? passesCliRecallScopeFilter(e.scope ?? null, recallScope.requested) || passesScopeFilterForRecall(e.scope ?? null, undefined, recallScope.ownScope)
|
|
87
|
+
: passesScopeFilterForRecall(e.scope ?? null, recallScope.requested, recallScope.ownScope));
|
|
88
|
+
const admit = (e) => passesScope(e) && (!entryFilter || entryFilter(e));
|
|
89
|
+
const localEntries = loadEntries(localRoot).filter(admit);
|
|
90
|
+
const globalEntries = loadEntries(globalRoot).filter(admit);
|
|
91
|
+
// The vector arm loads under the same SQL rules as loadEntries, then the same JS admission.
|
|
92
|
+
const vectorCandidates = {
|
|
93
|
+
tenantId,
|
|
94
|
+
scope: recallScope ? recallScopeFilter(recallScope.requested, recallScope.additive ? 'additive' : 'exact', recallScope.ownScope) : undefined,
|
|
95
|
+
includeSuperseded: !recallScope || Boolean(includeSuperseded) || Boolean(asOf),
|
|
96
|
+
admit,
|
|
97
|
+
};
|
|
98
|
+
return rankBothStores(query, { local: localRoot, global: globalRoot }, { local: localEntries, global: globalEntries }, vectorCandidates, options);
|
|
99
|
+
}
|
|
100
|
+
/** Hybrid ranking of rows already loaded from each store: the local bump, one copy per text, then the shared budget. */
|
|
101
|
+
export async function rankBothStores(query, roots, entries, vectorCandidates, options = {}) {
|
|
102
|
+
const { budget = DEFAULT_RECALL_BUDGET, now = evalNow(), embeddingWeight, explain, mmr, mmrLambda, localBump = DEFAULT_LOCAL_BUMP, minResults, cost, scope, includeSuperseded, asOf, summaryDeboost, summaryFreshness } = options;
|
|
103
|
+
if (entries.local.length === 0 && entries.global.length === 0)
|
|
104
|
+
return [];
|
|
105
|
+
// One deadline for both stores, so a provider that stalls on the first is not waited on again for the second.
|
|
106
|
+
const shared = {
|
|
107
|
+
budget, now, embeddingWeight, explain, mmr, mmrLambda, minResults, cost, scope, includeSuperseded, asOf, summaryDeboost, summaryFreshness,
|
|
108
|
+
vectorCandidates, queryEmbedDeadline: startQueryEmbedDeadline(),
|
|
109
|
+
};
|
|
110
|
+
const localResults = await hybridSearch(query, entries.local, { ...shared, hippoRoot: roots.local });
|
|
111
|
+
const globalResults = await hybridSearch(query, entries.global, { ...shared, hippoRoot: roots.global });
|
|
112
|
+
// Tag global results. Local memories get a configurable priority bump.
|
|
113
|
+
const tagged = [
|
|
114
|
+
...localResults.map((r) => ({
|
|
115
|
+
...r,
|
|
116
|
+
isGlobal: false,
|
|
117
|
+
score: r.score * localBump,
|
|
118
|
+
breakdown: r.breakdown
|
|
119
|
+
? { ...r.breakdown, sourceBump: localBump, final: r.breakdown.final * localBump }
|
|
120
|
+
: undefined,
|
|
121
|
+
})),
|
|
122
|
+
...globalResults.map((r) => ({ ...r, isGlobal: true })),
|
|
123
|
+
];
|
|
124
|
+
// Remove duplicates by content (local/global IDs differ after promote/share)
|
|
125
|
+
const seen = new Set();
|
|
126
|
+
const deduped = tagged.filter((r) => {
|
|
127
|
+
const key = duplicateKey(r.entry.content);
|
|
128
|
+
if (seen.has(key))
|
|
129
|
+
return false;
|
|
130
|
+
seen.add(key);
|
|
131
|
+
return true;
|
|
132
|
+
});
|
|
133
|
+
// PLAIN stable score sort on purpose -- see searchBoth above;
|
|
134
|
+
// same rationale (deterministic inputs + stability; local-first on ties).
|
|
135
|
+
deduped.sort((a, b) => compareScoresDesc(a.score, b.score));
|
|
136
|
+
return fitBudget(deduped, budget, minResults ?? 1, cost);
|
|
137
|
+
}
|
|
138
|
+
//# sourceMappingURL=search-both.js.map
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { MemoryEntry } from '../core/memory.js';
|
|
2
|
+
/** Tags whose rows only a hand-run share or promote may copy to the global store; derived rows inherit them. */
|
|
3
|
+
export declare const NEVER_AUTO_SHARE_TAGS: ReadonlySet<string>;
|
|
4
|
+
export declare function neverAutoShareTags(sources: readonly MemoryEntry[]): string[];
|
|
5
|
+
/** Tags whose rows sleep keeps as written: never merged, never sent to LLM extraction. Conflict detection keeps its own list. */
|
|
6
|
+
export declare const NO_MERGE_TAGS: ReadonlySet<string>;
|
|
7
|
+
/** Estimate how well a memory would transfer to other projects.
|
|
8
|
+
* Returns 0..1 where >0.5 = good candidate for sharing. */
|
|
9
|
+
export declare function transferScore(entry: MemoryEntry): number;
|
|
10
|
+
/** Share a memory to the global store with attribution (source enriched with project path and timestamp).
|
|
11
|
+
* Returns the new entry, or null if the transfer score is too low. */
|
|
12
|
+
export declare function shareMemory(localRoot: string, id: string, options?: {
|
|
13
|
+
force?: boolean;
|
|
14
|
+
tenantId?: string;
|
|
15
|
+
skipEmbed?: boolean;
|
|
16
|
+
}): MemoryEntry | null;
|
|
17
|
+
/** List all projects that contributed memories to the global store, parsed from 'shared:<project>:' or 'promoted:<path>' sources.
|
|
18
|
+
* `tenantId` filters to one tenant; undefined is host-wide (legacy callers: CLI standalone, dashboard). */
|
|
19
|
+
export declare function listPeers(globalRoot?: string, tenantId?: string): Array<{
|
|
20
|
+
project: string;
|
|
21
|
+
count: number;
|
|
22
|
+
latest: string;
|
|
23
|
+
}>;
|
|
24
|
+
type AutoShareStats = {
|
|
25
|
+
secretSkipped: number;
|
|
26
|
+
rejectedSkipped?: number;
|
|
27
|
+
neverAutoShareSkipped?: number;
|
|
28
|
+
};
|
|
29
|
+
/** 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.
|
|
30
|
+
* `options.stats` is an opt-in out-param: `secretSkipped` counts shares the secret veto prevented, `rejectedSkipped` rejection refusals (0 under `dryRun`). */
|
|
31
|
+
export declare function autoShare(localRoot: string, options?: {
|
|
32
|
+
minScore?: number;
|
|
33
|
+
dryRun?: boolean;
|
|
34
|
+
tenantId?: string;
|
|
35
|
+
stats?: AutoShareStats;
|
|
36
|
+
}): MemoryEntry[];
|
|
37
|
+
export {};
|
|
38
|
+
//# sourceMappingURL=share.d.ts.map
|
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
// Sharing local memories to the global store: transfer scoring, share, peers and auto-share.
|
|
2
|
+
import { BadRequestError, NotFoundError } from '../core/api-errors.js';
|
|
3
|
+
import * as fs from 'fs';
|
|
4
|
+
import * as path from 'path';
|
|
5
|
+
import { generateId, COMPACTION_MEMORY_TAG } from '../core/memory.js';
|
|
6
|
+
import { AGENT_MEMORY_SOURCE_PREFIX, AGENT_MEMORY_TAGS } from '../core/agent-memory-tools.js';
|
|
7
|
+
import { writeEntry } from '../store/entry-writes.js';
|
|
8
|
+
import { loadAllEntries, readEntry } from '../store/entry-reads.js';
|
|
9
|
+
import { tallySources } from '../store/candidates.js';
|
|
10
|
+
import { isPersonalScope } from '../store/recall-scope.js';
|
|
11
|
+
import { fallbackOrigin } from '../core/project-identity.js';
|
|
12
|
+
import { detectSecret } from '../util/secret-detect.js';
|
|
13
|
+
import { isQuarantineScope } from '../trust/quarantine.js';
|
|
14
|
+
import { RejectedValueError } from '../store/rejection.js';
|
|
15
|
+
import { embedMemory, embedAll } from '../store/embeddings/index.js';
|
|
16
|
+
import { duplicateKey, storedTextKeys } from '../util/same-text.js';
|
|
17
|
+
import { isReusable } from '../core/memory-quality.js';
|
|
18
|
+
import { log } from '../util/log.js';
|
|
19
|
+
import { getGlobalRoot, initGlobal } from './global-store.js';
|
|
20
|
+
import { logEmbedAllFailure } from './search-both.js';
|
|
21
|
+
/** Tags that indicate project-specific memories (poor transfer candidates) */
|
|
22
|
+
const PROJECT_SPECIFIC_TAGS = new Set([
|
|
23
|
+
'file-path', 'config', 'deploy', 'cron', 'url', 'auth',
|
|
24
|
+
'field-names', 'column-names', 'api-key', 'endpoint',
|
|
25
|
+
]);
|
|
26
|
+
/** Tags that indicate transferable memories (good transfer candidates) */
|
|
27
|
+
const TRANSFERABLE_TAGS = new Set([
|
|
28
|
+
'error', 'platform', 'windows', 'encoding', 'python', 'shell',
|
|
29
|
+
'powershell', 'quant', 'backtest', 'pattern', 'rule', 'gotcha',
|
|
30
|
+
'sub-agent', 'review', 'best-practice',
|
|
31
|
+
]);
|
|
32
|
+
/** Tags whose rows only a hand-run share or promote may copy to the global store; derived rows inherit them. */
|
|
33
|
+
export const NEVER_AUTO_SHARE_TAGS = new Set([
|
|
34
|
+
'git-learned',
|
|
35
|
+
'session-digest',
|
|
36
|
+
...AGENT_MEMORY_TAGS,
|
|
37
|
+
]);
|
|
38
|
+
export function neverAutoShareTags(sources) {
|
|
39
|
+
return [...NEVER_AUTO_SHARE_TAGS].filter((tag) => sources.some((s) => s.tags.includes(tag)));
|
|
40
|
+
}
|
|
41
|
+
/** Tags whose rows sleep keeps as written: never merged, never sent to LLM extraction. Conflict detection keeps its own list. */
|
|
42
|
+
export const NO_MERGE_TAGS = new Set([
|
|
43
|
+
'extracted',
|
|
44
|
+
'session-digest',
|
|
45
|
+
COMPACTION_MEMORY_TAG,
|
|
46
|
+
...AGENT_MEMORY_TAGS,
|
|
47
|
+
]);
|
|
48
|
+
/** Estimate how well a memory would transfer to other projects.
|
|
49
|
+
* Returns 0..1 where >0.5 = good candidate for sharing. */
|
|
50
|
+
export function transferScore(entry) {
|
|
51
|
+
let score = 0.5; // neutral default
|
|
52
|
+
// Boost for transferable tags
|
|
53
|
+
const transferableCount = entry.tags.filter((t) => TRANSFERABLE_TAGS.has(t)).length;
|
|
54
|
+
score += transferableCount * 0.1;
|
|
55
|
+
// Penalize for project-specific tags
|
|
56
|
+
const specificCount = entry.tags.filter((t) => PROJECT_SPECIFIC_TAGS.has(t)).length;
|
|
57
|
+
score -= specificCount * 0.15;
|
|
58
|
+
// High-retrieval memories are more likely to be universally useful
|
|
59
|
+
if (entry.retrieval_count >= 3)
|
|
60
|
+
score += 0.1;
|
|
61
|
+
// Pinned memories are important to their owner
|
|
62
|
+
if (entry.pinned)
|
|
63
|
+
score += 0.1;
|
|
64
|
+
// Error-tagged memories often encode universal lessons
|
|
65
|
+
if (entry.emotional_valence === 'negative' || entry.emotional_valence === 'critical')
|
|
66
|
+
score += 0.05;
|
|
67
|
+
return Math.min(1, Math.max(0, score));
|
|
68
|
+
}
|
|
69
|
+
/** Share a memory to the global store with attribution (source enriched with project path and timestamp).
|
|
70
|
+
* Returns the new entry, or null if the transfer score is too low. */
|
|
71
|
+
export function shareMemory(localRoot, id, options = {}) {
|
|
72
|
+
// tenantId is optional for single-tenant callers (autoShare passes only `{ force: true }`); MCP/REST hosts MUST pass it so tenant A cannot share
|
|
73
|
+
// tenant B's memory to global (readEntry returns null on a cross-tenant lookup).
|
|
74
|
+
const entry = readEntry(localRoot, id, options.tenantId);
|
|
75
|
+
if (!entry)
|
|
76
|
+
throw new NotFoundError(`Memory not found: ${id}`);
|
|
77
|
+
assertShareable(entry, id);
|
|
78
|
+
const score = transferScore(entry);
|
|
79
|
+
if (score < 0.3 && !options.force)
|
|
80
|
+
return null;
|
|
81
|
+
initGlobal();
|
|
82
|
+
const globalRoot = getGlobalRoot();
|
|
83
|
+
// The label keeps the folder name for a user-global row; a NULL row gets `shared::`, which originFromSource reads as no project.
|
|
84
|
+
const fallbackName = path.basename(path.resolve(localRoot, '..'));
|
|
85
|
+
const originName = entry.origin_project ?? fallbackOrigin(localRoot);
|
|
86
|
+
const label = originName === '' ? fallbackName : (originName ?? '');
|
|
87
|
+
const globalEntry = {
|
|
88
|
+
...entry,
|
|
89
|
+
id: generateId('g'),
|
|
90
|
+
source: `shared:${label}:${new Date().toISOString()}`,
|
|
91
|
+
origin_project: originName,
|
|
92
|
+
};
|
|
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
|
+
}
|
|
100
|
+
function assertShareable(entry, id) {
|
|
101
|
+
// 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.
|
|
102
|
+
const secret = detectSecret(entry);
|
|
103
|
+
if (secret.flagged) {
|
|
104
|
+
throw new BadRequestError(`Refusing to share ${id} to the global store: content matches secret material (${secret.reason}). ` +
|
|
105
|
+
`Secrets stay in their owning project's store.`);
|
|
106
|
+
}
|
|
107
|
+
// A quarantined row is unreviewed input, not a lesson; sharing it would spread poison globally.
|
|
108
|
+
if (isQuarantineScope(entry.scope)) {
|
|
109
|
+
throw new BadRequestError(`Refusing to share ${id}: it is quarantined pending review. Approve it first via 'hippo quarantine approve ${id}'.`);
|
|
110
|
+
}
|
|
111
|
+
if (isPersonalScope(entry.scope ?? null)) {
|
|
112
|
+
throw new BadRequestError(`Refusing to share ${id}: it is a personal memory and stays with its owner on this server.`);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
/** List all projects that contributed memories to the global store, parsed from 'shared:<project>:' or 'promoted:<path>' sources.
|
|
116
|
+
* `tenantId` filters to one tenant; undefined is host-wide (legacy callers: CLI standalone, dashboard). */
|
|
117
|
+
export function listPeers(globalRoot, tenantId) {
|
|
118
|
+
const root = globalRoot ?? getGlobalRoot();
|
|
119
|
+
if (!fs.existsSync(root))
|
|
120
|
+
return [];
|
|
121
|
+
// Tenant-scoped by default when tenantId provided. Host-wide when
|
|
122
|
+
// undefined (preserves back-compat).
|
|
123
|
+
const tallies = tallySources(root, tenantId).sort((a, b) => (a.first < b.first ? -1 : a.first > b.first ? 1 : 0));
|
|
124
|
+
const peerMap = new Map();
|
|
125
|
+
for (const tally of tallies) {
|
|
126
|
+
let project = 'unknown';
|
|
127
|
+
if (tally.source.startsWith('shared:')) {
|
|
128
|
+
const parts = tally.source.split(':');
|
|
129
|
+
project = parts[1] || 'unknown';
|
|
130
|
+
}
|
|
131
|
+
else if (tally.source.startsWith('promoted:')) {
|
|
132
|
+
const promotedPath = tally.source.slice('promoted:'.length);
|
|
133
|
+
project = path.basename(path.resolve(promotedPath, '..'));
|
|
134
|
+
}
|
|
135
|
+
else if (tally.source === 'cli-global') {
|
|
136
|
+
project = 'global-cli';
|
|
137
|
+
}
|
|
138
|
+
const existing = peerMap.get(project);
|
|
139
|
+
if (!existing) {
|
|
140
|
+
peerMap.set(project, { count: tally.count, latest: tally.latest });
|
|
141
|
+
}
|
|
142
|
+
else {
|
|
143
|
+
existing.count += tally.count;
|
|
144
|
+
if (tally.latest > existing.latest)
|
|
145
|
+
existing.latest = tally.latest;
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
return Array.from(peerMap.entries())
|
|
149
|
+
.map(([project, data]) => ({ project, ...data }))
|
|
150
|
+
.sort((a, b) => b.count - a.count);
|
|
151
|
+
}
|
|
152
|
+
function isAutoShareCandidate(entry, globalContentSet, minScore, stats) {
|
|
153
|
+
// shareMemory refuses quarantined and personal rows; filtering here keeps sleep from aborting on one.
|
|
154
|
+
if (isQuarantineScope(entry.scope ?? null) || isPersonalScope(entry.scope ?? null) || !isReusable(entry))
|
|
155
|
+
return false;
|
|
156
|
+
// Before the score: these rows describe one project only, and a git seed's 'error' tag clears the bar.
|
|
157
|
+
if (entry.tags.some((t) => NEVER_AUTO_SHARE_TAGS.has(t)) || entry.source.startsWith(AGENT_MEMORY_SOURCE_PREFIX)) {
|
|
158
|
+
if (stats)
|
|
159
|
+
stats.neverAutoShareSkipped = (stats.neverAutoShareSkipped ?? 0) + 1;
|
|
160
|
+
return false;
|
|
161
|
+
}
|
|
162
|
+
const score = transferScore(entry);
|
|
163
|
+
if (score < minScore)
|
|
164
|
+
return false;
|
|
165
|
+
// Skip if already shared (same text apart from spacing)
|
|
166
|
+
if (globalContentSet.has(duplicateKey(entry.content)))
|
|
167
|
+
return false;
|
|
168
|
+
// Secret veto, checked LAST so the stats counter only counts rows it withheld (a row failing the score or dedupe gate was never going to share).
|
|
169
|
+
// shareMemory would throw here; filtering keeps the sleep pipeline fail-safe.
|
|
170
|
+
if (detectSecret(entry).flagged) {
|
|
171
|
+
if (stats)
|
|
172
|
+
stats.secretSkipped++;
|
|
173
|
+
return false;
|
|
174
|
+
}
|
|
175
|
+
return true;
|
|
176
|
+
}
|
|
177
|
+
// Rejection containment: shareMemory -> writeEntry can throw RejectedValueError against the GLOBAL store tombstones and abort the autoShare sleep phase.
|
|
178
|
+
// Catch per item like syncGlobalToLocal; writeEntry already audits reject_refusal before rethrowing, so count and continue.
|
|
179
|
+
function shareCandidates(localRoot, candidates, stats) {
|
|
180
|
+
const shared = [];
|
|
181
|
+
let rejectedSkipped = 0;
|
|
182
|
+
for (const entry of candidates) {
|
|
183
|
+
try {
|
|
184
|
+
// skipEmbed: batching invariant, this is a batch producer, so it embeds
|
|
185
|
+
// once via embedAll() below rather than once per row inside shareMemory.
|
|
186
|
+
const result = shareMemory(localRoot, entry.id, { force: true, skipEmbed: true });
|
|
187
|
+
if (result)
|
|
188
|
+
shared.push(result);
|
|
189
|
+
}
|
|
190
|
+
catch (err) {
|
|
191
|
+
if (err instanceof RejectedValueError) {
|
|
192
|
+
rejectedSkipped++;
|
|
193
|
+
if (stats)
|
|
194
|
+
stats.rejectedSkipped = (stats.rejectedSkipped ?? 0) + 1;
|
|
195
|
+
continue;
|
|
196
|
+
}
|
|
197
|
+
throw err;
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
if (rejectedSkipped > 0) {
|
|
201
|
+
log.warn(`autoShare: skipped ${rejectedSkipped} candidate(s) refused by the global store's rejection tombstone`);
|
|
202
|
+
}
|
|
203
|
+
return shared;
|
|
204
|
+
}
|
|
205
|
+
/** 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
|
+
* `options.stats` is an opt-in out-param: `secretSkipped` counts shares the secret veto prevented, `rejectedSkipped` rejection refusals (0 under `dryRun`). */
|
|
207
|
+
export function autoShare(localRoot, options = {}) {
|
|
208
|
+
const { minScore = 0.6, dryRun = false } = options;
|
|
209
|
+
const localEntries = loadAllEntries(localRoot, options.tenantId);
|
|
210
|
+
initGlobal();
|
|
211
|
+
const globalRoot = getGlobalRoot();
|
|
212
|
+
// Host-wide read. The global store IS the union across all tenants;
|
|
213
|
+
// per-tenant filtering on the global root would defeat the purpose.
|
|
214
|
+
const globalEntries = loadAllEntries(globalRoot);
|
|
215
|
+
// Build set of global content hashes to avoid duplicates
|
|
216
|
+
const globalContentSet = storedTextKeys(globalEntries);
|
|
217
|
+
const candidates = localEntries.filter((entry) => isAutoShareCandidate(entry, globalContentSet, minScore, options.stats));
|
|
218
|
+
if (dryRun)
|
|
219
|
+
return candidates;
|
|
220
|
+
const shared = shareCandidates(localRoot, candidates, options.stats);
|
|
221
|
+
if (shared.length > 0) {
|
|
222
|
+
void embedAll(globalRoot).catch((err) => logEmbedAllFailure('autoShare', err));
|
|
223
|
+
}
|
|
224
|
+
return shared;
|
|
225
|
+
}
|
|
226
|
+
//# sourceMappingURL=share.js.map
|
package/dist/store/ambient.js
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { strengthSql } from '../core/memory.js';
|
|
1
|
+
import { strengthSql } from './rule-sql.js';
|
|
3
2
|
import { scopeAdmitSql } from './recall-scope.js';
|
|
4
3
|
import { SECRET_TAGS } from '../util/secret-detect.js';
|
|
5
|
-
import { openStore } from './open.js';
|
|
4
|
+
import { onHandle, openStore } from './open.js';
|
|
6
5
|
import { jsonList } from './candidates.js';
|
|
7
6
|
import { originInSql } from '../core/project-identity.js';
|
|
8
7
|
import { isErrorTagged } from '../core/ambient.js';
|
|
@@ -41,8 +40,7 @@ export function loadAmbientTallies(hippoRoot, tenantId, filter) {
|
|
|
41
40
|
const { where, params } = contextRowsWhere(tenantId, filter);
|
|
42
41
|
const secret = secretTaggedSql();
|
|
43
42
|
const sevenDaysAgo = new Date(filter.now.getTime() - 7 * DAY_MS).toISOString();
|
|
44
|
-
|
|
45
|
-
try {
|
|
43
|
+
return onHandle(hippoRoot, (db) => {
|
|
46
44
|
// SAFETY: one aggregate row whose columns are the aliases named below. Tag lists come back as one JSON array of
|
|
47
45
|
// arrays and are counted in JS, which maps items through String() as parseJsonArray does.
|
|
48
46
|
const row = db.prepare(`SELECT
|
|
@@ -84,9 +82,6 @@ export function loadAmbientTallies(hippoRoot, tenantId, filter) {
|
|
|
84
82
|
maxDagLevel: Number(row.maxDagLevel),
|
|
85
83
|
tagCounts,
|
|
86
84
|
};
|
|
87
|
-
}
|
|
88
|
-
finally {
|
|
89
|
-
closeHippoDb(db);
|
|
90
|
-
}
|
|
85
|
+
}, openStore);
|
|
91
86
|
}
|
|
92
87
|
//# sourceMappingURL=ambient.js.map
|
|
@@ -8,18 +8,10 @@ export interface AuditOptions {
|
|
|
8
8
|
readonly actor?: string;
|
|
9
9
|
readonly tenantId?: string;
|
|
10
10
|
}
|
|
11
|
-
/**
|
|
12
|
-
*
|
|
13
|
-
* log can never crash the surrounding mutation — the SQLite store is still the
|
|
14
|
-
* source of truth and audit failures are diagnosable from the missing rows.
|
|
15
|
-
*/
|
|
11
|
+
/** Emit an audit event for a mutation. Never throws: the SQLite store stays the source of truth,
|
|
12
|
+
* and a failed audit write shows up as missing rows. */
|
|
16
13
|
export declare function audit(db: ReturnType<typeof openHippoDb>, op: AuditOp, options?: AuditOptions): void;
|
|
17
|
-
/**
|
|
18
|
-
*
|
|
19
|
-
* transaction OWNER post-rollback — writeEntry's catch (no outer tx exists
|
|
20
|
-
* there, so this lands in a fresh implicit transaction) and commitSupersede's
|
|
21
|
-
* catch (after its own ROLLBACK) — never inside a scope the caller's own
|
|
22
|
-
* rollback could claw back. Best-effort `audit()` semantics: never throws.
|
|
23
|
-
*/
|
|
14
|
+
/** Refusal audit for the rejected-value guard, written by the transaction owner after rollback so the caller's own rollback cannot claw it back.
|
|
15
|
+
* Best-effort like `audit()`: never throws. */
|
|
24
16
|
export declare function auditRejectionRefusal(db: ReturnType<typeof openHippoDb>, err: RejectedValueError, actor: string): void;
|
|
25
17
|
//# sourceMappingURL=audit-event.d.ts.map
|
|
@@ -1,10 +1,7 @@
|
|
|
1
1
|
import { resolveTenantId } from './tenant.js';
|
|
2
2
|
import { appendAuditEvent, reportAuditWriteFailure } from './audit.js';
|
|
3
|
-
/**
|
|
4
|
-
*
|
|
5
|
-
* log can never crash the surrounding mutation — the SQLite store is still the
|
|
6
|
-
* source of truth and audit failures are diagnosable from the missing rows.
|
|
7
|
-
*/
|
|
3
|
+
/** Emit an audit event for a mutation. Never throws: the SQLite store stays the source of truth,
|
|
4
|
+
* and a failed audit write shows up as missing rows. */
|
|
8
5
|
export function audit(db, op, options = {}) {
|
|
9
6
|
const { targetId, metadata, actor = 'cli', tenantId } = options;
|
|
10
7
|
try {
|
|
@@ -21,13 +18,8 @@ export function audit(db, op, options = {}) {
|
|
|
21
18
|
reportAuditWriteFailure(op, String(error), targetId);
|
|
22
19
|
}
|
|
23
20
|
}
|
|
24
|
-
/**
|
|
25
|
-
*
|
|
26
|
-
* transaction OWNER post-rollback — writeEntry's catch (no outer tx exists
|
|
27
|
-
* there, so this lands in a fresh implicit transaction) and commitSupersede's
|
|
28
|
-
* catch (after its own ROLLBACK) — never inside a scope the caller's own
|
|
29
|
-
* rollback could claw back. Best-effort `audit()` semantics: never throws.
|
|
30
|
-
*/
|
|
21
|
+
/** Refusal audit for the rejected-value guard, written by the transaction owner after rollback so the caller's own rollback cannot claw it back.
|
|
22
|
+
* Best-effort like `audit()`: never throws. */
|
|
31
23
|
export function auditRejectionRefusal(db, err, actor) {
|
|
32
24
|
audit(db, 'reject_refusal', { targetId: err.entryId, metadata: { digest: err.digest, reason: err.reason }, actor, tenantId: err.tenantId });
|
|
33
25
|
}
|
package/dist/store/audit.d.ts
CHANGED
|
@@ -66,11 +66,8 @@ export interface ListAuditAfterOpts {
|
|
|
66
66
|
/** Omit for every tenant (deployment-wide export). */
|
|
67
67
|
tenantId?: string;
|
|
68
68
|
}
|
|
69
|
-
/**
|
|
70
|
-
*
|
|
71
|
-
* and never reused, but deletes (retention prune) leave gaps, so resume from
|
|
72
|
-
* the last id returned, never from a count.
|
|
73
|
-
*/
|
|
69
|
+
/** Cursor read: events with id > afterId, ascending. Retention prune leaves gaps in the ids,
|
|
70
|
+
* so resume from the last id returned, never from a count. */
|
|
74
71
|
export declare function listAuditEventsAfter(db: DatabaseSyncLike, opts: ListAuditAfterOpts): AuditEvent[];
|
|
75
72
|
/** Latest time each target got a good outcome, from the audit rows, read on a handle of its own; unlike queryAuditEvents it has no row cap. */
|
|
76
73
|
export declare function confirmedOutcomeTimes(hippoRoot: string, tenantId: string): Map<string, string>;
|
package/dist/store/audit.js
CHANGED
|
@@ -55,9 +55,6 @@ export function auditMemories(entries, backing) {
|
|
|
55
55
|
clean: entries.length - issues.length,
|
|
56
56
|
};
|
|
57
57
|
}
|
|
58
|
-
// ---------------------------------------------------------------------------
|
|
59
|
-
// Audit log primitives (append-only mutation trail)
|
|
60
|
-
// ---------------------------------------------------------------------------
|
|
61
58
|
// The one list of audit ops: the AuditOp type, `hippo audit list --op` and GET /v1/audit?op= all read it.
|
|
62
59
|
export const AUDIT_OPS = [
|
|
63
60
|
'remember',
|
|
@@ -182,11 +179,8 @@ export function queryAuditEvents(db, opts) {
|
|
|
182
179
|
.all(...params, ...after.params, limit);
|
|
183
180
|
return rows.map(rowToAuditEvent);
|
|
184
181
|
}
|
|
185
|
-
/**
|
|
186
|
-
*
|
|
187
|
-
* and never reused, but deletes (retention prune) leave gaps, so resume from
|
|
188
|
-
* the last id returned, never from a count.
|
|
189
|
-
*/
|
|
182
|
+
/** Cursor read: events with id > afterId, ascending. Retention prune leaves gaps in the ids,
|
|
183
|
+
* so resume from the last id returned, never from a count. */
|
|
190
184
|
export function listAuditEventsAfter(db, opts) {
|
|
191
185
|
if (!Number.isInteger(opts.afterId) || opts.afterId < 0) {
|
|
192
186
|
throw new RangeError('afterId must be a non-negative integer');
|
|
@@ -255,10 +249,8 @@ function rowToAuditEvent(r) {
|
|
|
255
249
|
function safeJsonParse(raw, id) {
|
|
256
250
|
try {
|
|
257
251
|
const v = JSON.parse(raw);
|
|
258
|
-
// SAFETY: JSON.parse
|
|
259
|
-
//
|
|
260
|
-
// (both are valid JsonObject shapes for our purposes), matching the prior
|
|
261
|
-
// `typeof v === 'object' && v !== null` check without using typeof.
|
|
252
|
+
// SAFETY: JSON.parse returns only an object, array or primitive; `instanceof Object` is true for the first two,
|
|
253
|
+
// both valid JsonObject shapes here.
|
|
262
254
|
return v instanceof Object ? v : {};
|
|
263
255
|
}
|
|
264
256
|
catch {
|