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/objects/skills.js
CHANGED
|
@@ -1,34 +1,11 @@
|
|
|
1
|
-
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
4
|
-
* A `skill` is a reusable, agent-followable capability: an `instructions` body
|
|
5
|
-
* plus an optional `trigger` ("when to apply"), evolving via the supersede delta
|
|
6
|
-
* lifecycle. "Executable" is scoped to an agent-followable INSTRUCTION that, once
|
|
7
|
-
* exported into the agent's in-force rules (AGENTS.md / CLAUDE.md) via
|
|
8
|
-
* `exportSkills`, is executed by the agent reading it. Literal code/command
|
|
9
|
-
* execution is deferred (security; a future sandbox). The distinguishing
|
|
10
|
-
* capability is therefore the EXPORT renderer, not a runtime.
|
|
11
|
-
*
|
|
12
|
-
* Reuses the process/decision supersede machinery verbatim (superseded_by self-FK
|
|
13
|
-
* + CAS + INSERT-preflight + server-derived version + change_summary + supersede
|
|
14
|
-
* tenant-match trigger). It DROPS process's `steps` (a skill's content is a single
|
|
15
|
-
* `instructions` body) and ADDS `trigger` (stored in the `trigger_text` column -
|
|
16
|
-
* `trigger` is a SQLite reserved keyword).
|
|
17
|
-
*
|
|
18
|
-
* The `skills` table is the source of truth (survives memory decay); the memory
|
|
19
|
-
* mirror is for recall. memory_id is NULLABLE with ON DELETE SET NULL.
|
|
20
|
-
*
|
|
21
|
-
* Lifecycle: active -> superseded (a newer version replaces it) or active ->
|
|
22
|
-
* closed (retired). Export renders ACTIVE skills only.
|
|
23
|
-
*/
|
|
1
|
+
/** Skill object: an agent-followable `instructions` body plus an optional `trigger`, evolving via supersession.
|
|
2
|
+
* `exportSkills` renders ACTIVE skills into AGENTS.md / CLAUDE.md rules; running code from a skill is deferred (security).
|
|
3
|
+
* `trigger` is stored in `trigger_text` because it is a SQLite reserved keyword. */
|
|
24
4
|
import { BadRequestError } from '../core/api-errors.js';
|
|
25
5
|
import { assertTenantId } from '../store/tenant.js';
|
|
26
6
|
import { checkText, requireLine } from './fields.js';
|
|
27
7
|
import { closeObjectAt, listObjectsAt, objectByIdAt, saveObjectAt } from './lifecycle.js';
|
|
28
8
|
import { sqliteObjects } from '../store/sqlite/objects-group.js';
|
|
29
|
-
// ---------------------------------------------------------------------------
|
|
30
|
-
// Domain types
|
|
31
|
-
// ---------------------------------------------------------------------------
|
|
32
9
|
export const VALID_SKILL_STATES = new Set([
|
|
33
10
|
'active',
|
|
34
11
|
'superseded',
|
|
@@ -42,9 +19,6 @@ export const MAX_SKILL_TRIGGER_LEN = 1024;
|
|
|
42
19
|
/** Aggregate bound on a single export render so the export body is never unbounded.
|
|
43
20
|
* Realistic active-skill counts are tens; 1000 is a generous bound. */
|
|
44
21
|
export const MAX_EXPORT_SKILLS = 1000;
|
|
45
|
-
// ---------------------------------------------------------------------------
|
|
46
|
-
// Validation
|
|
47
|
-
// ---------------------------------------------------------------------------
|
|
48
22
|
/** The trigger as stored, or null for none. One line, because a newline would forge a heading inside the exported **When:** line. */
|
|
49
23
|
function checkTrigger(trigger) {
|
|
50
24
|
if (trigger === undefined || trigger === null || trigger.trim().length === 0)
|
|
@@ -57,9 +31,7 @@ function checkTrigger(trigger) {
|
|
|
57
31
|
}
|
|
58
32
|
return trigger;
|
|
59
33
|
}
|
|
60
|
-
/** Recall-surface content for the memory mirror: name
|
|
61
|
-
* instructions. Named (mirrors buildProcessContent) so the recall surface is
|
|
62
|
-
* deterministic + unit-testable. */
|
|
34
|
+
/** Recall-surface content for the memory mirror: name, optional trigger, instructions. */
|
|
63
35
|
function buildSkillContent(skillName, instructions, trigger) {
|
|
64
36
|
let content = skillName;
|
|
65
37
|
if (trigger)
|
|
@@ -96,22 +68,11 @@ export const SKILL = {
|
|
|
96
68
|
};
|
|
97
69
|
},
|
|
98
70
|
};
|
|
99
|
-
|
|
100
|
-
// Public API
|
|
101
|
-
// ---------------------------------------------------------------------------
|
|
102
|
-
/**
|
|
103
|
-
* Create a skill (or a new version that supersedes an existing one). Writes the
|
|
104
|
-
* memory mirror + the skills row in the `objects` store group's one transaction. When
|
|
105
|
-
* supersedesSkillId is given, the referenced ACTIVE row is preflighted (status +
|
|
106
|
-
* version) BEFORE the INSERT, then CAS-UPDATEd -> superseded in the same transaction;
|
|
107
|
-
* the new version = predecessor.version + 1 (server-derived).
|
|
108
|
-
*/
|
|
71
|
+
/** Create a skill, or a new version superseding an existing one, in the `objects` store group's one transaction. */
|
|
109
72
|
export function saveSkill(hippoRoot, tenantId, opts, actor = 'cli') {
|
|
110
73
|
return saveObjectAt(SKILL, { hippoRoot, tenantId, actor }, opts);
|
|
111
74
|
}
|
|
112
|
-
/**
|
|
113
|
-
* Close (retire) an active skill. A superseded row is terminal.
|
|
114
|
-
*/
|
|
75
|
+
/** Close (retire) an active skill; a superseded row is terminal. */
|
|
115
76
|
export function closeSkill(hippoRoot, tenantId, id, actor = 'cli') {
|
|
116
77
|
return closeObjectAt(hippoRoot, SKILL, tenantId, id, actor);
|
|
117
78
|
}
|
|
@@ -124,15 +85,8 @@ export function loadSkills(hippoRoot, tenantId, opts = {}) {
|
|
|
124
85
|
export function loadActiveSkills(hippoRoot, tenantId, opts = {}) {
|
|
125
86
|
return loadSkills(hippoRoot, tenantId, { status: 'active', limit: opts.limit });
|
|
126
87
|
}
|
|
127
|
-
/**
|
|
128
|
-
*
|
|
129
|
-
* block (one H2 per skill, ordered by skill_name ASC for determinism), and RETURN
|
|
130
|
-
* the string. Does NOT write any file. Returns '' when there are no active skills.
|
|
131
|
-
*
|
|
132
|
-
* skill_name is single-line (validated on save) so it cannot break the H2 header;
|
|
133
|
-
* instructions are emitted verbatim (operator content). Bounded by MAX_EXPORT_SKILLS
|
|
134
|
-
* active rows; each field is capped on save, so the rendered string is bounded.
|
|
135
|
-
*/
|
|
88
|
+
/** Render the tenant's ACTIVE skills into one AGENTS.md / CLAUDE.md-style markdown block (H2 per skill, ordered by skill_name) and return it; writes no file.
|
|
89
|
+
* Bounded by MAX_EXPORT_SKILLS rows; instructions are emitted verbatim. */
|
|
136
90
|
export function exportSkills(hippoRoot, tenantId) {
|
|
137
91
|
assertTenantId('exportSkills', tenantId);
|
|
138
92
|
return skillsBlock(sqliteObjects(hippoRoot).activeSkillsByName(tenantId, MAX_EXPORT_SKILLS));
|
package/dist/postinstall.js
CHANGED
|
@@ -9,9 +9,8 @@ function main() {
|
|
|
9
9
|
if (envSkipPostinstall())
|
|
10
10
|
return;
|
|
11
11
|
try {
|
|
12
|
-
// Repair-only, for users who opted in (a Codex update can restore the real binary over our shim)
|
|
13
|
-
//
|
|
14
|
-
// hijacking, so first install is `hippo hook install codex` only.
|
|
12
|
+
// Repair-only, for users who opted in (a Codex update can restore the real binary over our shim): swapping the binary from postinstall
|
|
13
|
+
// is a consent violation that supply-chain scanners read as hijacking, so first install is `hippo hook install codex` only.
|
|
15
14
|
repairCodexWrapperIfInstalled();
|
|
16
15
|
}
|
|
17
16
|
catch (err) {
|
|
@@ -31,16 +30,8 @@ function main() {
|
|
|
31
30
|
// Never fail package install because the install hint could not be printed.
|
|
32
31
|
}
|
|
33
32
|
}
|
|
34
|
-
/**
|
|
35
|
-
*
|
|
36
|
-
* UserPromptSubmit hook is NOT yet installed, print a short message pointing
|
|
37
|
-
* the user at `hippo init`. No config writes. Silent otherwise.
|
|
38
|
-
*
|
|
39
|
-
* We avoid aggressively auto-patching ~/.claude/settings.json from a package
|
|
40
|
-
* postinstall — that's surprising, breaks the principle of least authority,
|
|
41
|
-
* and trips security scanners. A one-line visible prompt is the friendly
|
|
42
|
-
* middle ground.
|
|
43
|
-
*/
|
|
33
|
+
/** Read-only nudge: if Claude Code is detected and the Hippo UserPromptSubmit hook is not installed, point the user at `hippo init`.
|
|
34
|
+
* It never patches ~/.claude/settings.json from a package postinstall: surprising, against least authority, and trips security scanners. */
|
|
44
35
|
function printClaudeCodeNudge() {
|
|
45
36
|
const claudeDir = claudeConfigDir(os.homedir());
|
|
46
37
|
if (!fs.existsSync(claudeDir))
|
|
@@ -76,12 +67,8 @@ function printClaudeCodeNudge() {
|
|
|
76
67
|
line('To skip this message on future installs: export HIPPO_SKIP_POSTINSTALL=1');
|
|
77
68
|
line('');
|
|
78
69
|
}
|
|
79
|
-
/**
|
|
80
|
-
*
|
|
81
|
-
* wrapper is NOT installed, print the opt-in command. Mirrors the Claude Code
|
|
82
|
-
* nudge above — same least-authority reasoning: we tell the user what to run,
|
|
83
|
-
* we never swap their binary for them.
|
|
84
|
-
*/
|
|
70
|
+
/** Read-only nudge: if the Codex CLI is on PATH and the session-capture wrapper is not installed, print the opt-in command;
|
|
71
|
+
* same least-authority reasoning as the Claude Code nudge, we never swap the user's binary. */
|
|
85
72
|
function printCodexNudge() {
|
|
86
73
|
if (isCodexWrapperInstalled())
|
|
87
74
|
return;
|
|
@@ -1,15 +1,8 @@
|
|
|
1
1
|
import type { AppendAuditOpts } from '../store/audit.js';
|
|
2
2
|
import { type ForwardClaimMatch } from '../learn/forward-claim-detector.js';
|
|
3
3
|
import type { PlanningFallacyEvidence } from '../store/planning-fallacy-evidence.js';
|
|
4
|
-
/**
|
|
5
|
-
*
|
|
6
|
-
* agent's recall query carries a forward-prediction phrase AND the closest
|
|
7
|
-
* matching prediction class has closed historical data.
|
|
8
|
-
*
|
|
9
|
-
* The agent sees its track record at the moment of forecasting, anchoring
|
|
10
|
-
* on the outside view (Lovallo-Kahneman 2003) rather than the inside-view
|
|
11
|
-
* inside the planning fallacy.
|
|
12
|
-
*/
|
|
4
|
+
/** Surface delivered on `RecallResult.planningFallacyHint` when a recall query carries a forward-prediction phrase and the closest class has closed history,
|
|
5
|
+
* so the agent sees its own track record at the moment of forecasting. */
|
|
13
6
|
export interface PlanningFallacyHint {
|
|
14
7
|
classTag: string;
|
|
15
8
|
/** Verbatim PredictionBaserate.summary, e.g.
|
|
@@ -17,50 +10,34 @@ export interface PlanningFallacyHint {
|
|
|
17
10
|
baserateSummary: string;
|
|
18
11
|
/** Discriminator vs hypothetical future manual-override hints. */
|
|
19
12
|
source: 'j3.2-auto';
|
|
20
|
-
/** The regex match snippet that triggered detection
|
|
21
|
-
* see WHY the hint appeared and self-correct if detection misfires
|
|
22
|
-
* (e.g. "I wasn't predicting; ignore"). */
|
|
13
|
+
/** The regex match snippet that triggered detection, so the agent sees WHY the hint appeared and can self-correct if detection misfired. */
|
|
23
14
|
detectedPhrase: string;
|
|
24
15
|
nClosed: number;
|
|
25
16
|
/** Null only when every closed-row had estimate_value=0 (ratio undefined). */
|
|
26
17
|
meanRatio: number | null;
|
|
27
18
|
}
|
|
28
|
-
/**
|
|
29
|
-
*
|
|
30
|
-
* PlanningFallacyHint baserate was returned. Silence was the most common
|
|
31
|
-
* real-world failure: a natural-language query carries a
|
|
32
|
-
* forward-claim phrase but its non-stopword tokens don't overlap with
|
|
33
|
-
* any prediction class tag, so hippo emitted nothing despite
|
|
34
|
-
* the regex match. The watching variant surfaces the detection event
|
|
35
|
-
* + a one-line suggestion so the agent can either re-tag the prediction
|
|
36
|
-
* or pass the suggestion through to the user.
|
|
37
|
-
*/
|
|
19
|
+
/** "Watching" variant emitted when the forward-claim regex matched but no baserate hint was returned (no prediction class tag overlaps the query's tokens).
|
|
20
|
+
* It surfaces the detection plus a one-line suggestion so the agent can re-tag the prediction or pass the suggestion to the user. */
|
|
38
21
|
export interface PlanningFallacyWatching {
|
|
39
22
|
/** The forward-claim phrase the detector matched (verbatim regex match snippet). */
|
|
40
23
|
detectedPhrase: string;
|
|
41
|
-
/** Why hippo
|
|
42
|
-
*
|
|
43
|
-
* - 'tiebreak': >=2 classes tied at the same best score (silent on ambiguity). */
|
|
24
|
+
/** Why hippo could not produce a baserate hint despite the match: 'no_class_match' (no class scored >=1 on token overlap)
|
|
25
|
+
* or 'tiebreak' (>=2 classes tied at the best score; silent on ambiguity). */
|
|
44
26
|
reason: 'no_class_match' | 'tiebreak';
|
|
45
27
|
/** One-line agent-facing suggestion for how the user can give hippo
|
|
46
28
|
* enough signal to produce a baserate next time. */
|
|
47
29
|
suggestion: string;
|
|
48
30
|
}
|
|
49
|
-
/**
|
|
50
|
-
*
|
|
51
|
-
* available) OR `watching` (regex fired, no baserate), or NEITHER (mode=off,
|
|
52
|
-
* no queryText, no regex match, or nClosed=0 silent path). Never both.
|
|
53
|
-
*/
|
|
31
|
+
/** What `decidePlanningFallacy` hands to recall: EITHER `hint` (baserate available) OR `watching` (regex fired, no baserate), or NEITHER (mode=off,
|
|
32
|
+
* no queryText, no regex match, or nClosed=0). Never both. */
|
|
54
33
|
export interface PlanningFallacyOutput {
|
|
55
34
|
hint?: PlanningFallacyHint;
|
|
56
35
|
watching?: PlanningFallacyWatching;
|
|
57
36
|
}
|
|
58
37
|
export type AutodebiasMode = 'off' | 'regex';
|
|
59
38
|
export interface ComputePlanningFallacyHintOpts {
|
|
60
|
-
/** Override env
|
|
61
|
-
*
|
|
62
|
-
* reload). 'off' short-circuits to null BEFORE the regex gate so the
|
|
63
|
-
* AUTODEBIAS=off path pays zero work. */
|
|
39
|
+
/** Override env; undefined reads process.env.HIPPO_AUTODEBIAS per call (so tests can toggle it).
|
|
40
|
+
* 'off' short-circuits to null before the regex gate. */
|
|
64
41
|
mode?: AutodebiasMode;
|
|
65
42
|
}
|
|
66
43
|
/** The output a claim earns from its evidence, and the audit row that records the decision when there is one. */
|
package/dist/rerankers/clef.js
CHANGED
|
@@ -1,15 +1,14 @@
|
|
|
1
1
|
import { envClefEndpoint, envClefEndpointToken, envClefTimeoutMs, envCloudflareAccountId, envCloudflareApiToken } from '../util/env.js';
|
|
2
2
|
import { buildRelevanceRequest, JEV_DEFAULT_TOP_K, rankByScores } from './jev.js';
|
|
3
3
|
import { createOutageWarning } from './outage-warning.js';
|
|
4
|
-
import { rerankerPost } from './remote.js';
|
|
4
|
+
import { rerankerPost, RERANKER_MAX_REPLY_BYTES } from './remote.js';
|
|
5
|
+
import { readCappedJson } from '../util/capped-json.js';
|
|
5
6
|
import { isJsonObject } from '../util/json.js';
|
|
6
7
|
import { errorMessage } from '../util/log.js';
|
|
7
8
|
const RAY_ID_MAX_CHARS = 64;
|
|
8
9
|
const CLEF_MODELS = ['clef-flash', 'clef'];
|
|
9
10
|
const DEFAULT_TIMEOUT_MS = 15_000;
|
|
10
11
|
const MAX_TIMEOUT_MS = 120_000;
|
|
11
|
-
// 64 answers fit in a few KB; 1 MiB leaves room for a verbose envelope.
|
|
12
|
-
const MAX_REPLY_BYTES = 1024 * 1024;
|
|
13
12
|
// Workers AI rejects a request with more than 64 questions, one per candidate here.
|
|
14
13
|
const MAX_CANDIDATES = 64;
|
|
15
14
|
const ACCOUNT_ID = /^[0-9a-f]{32}$/i;
|
|
@@ -111,33 +110,6 @@ export function parseClefReply(body, n, model, requireModel) {
|
|
|
111
110
|
outputTokens: isNumber(usage.output_tokens) ? usage.output_tokens : undefined,
|
|
112
111
|
};
|
|
113
112
|
}
|
|
114
|
-
// The timeout bounds time, not bytes: a hostile endpoint could stream a huge 2xx body into memory.
|
|
115
|
-
async function readCappedJson(resp) {
|
|
116
|
-
if (!resp.body)
|
|
117
|
-
throw new Error('reply has no body');
|
|
118
|
-
const reader = resp.body.getReader();
|
|
119
|
-
const decoder = new TextDecoder();
|
|
120
|
-
let raw = '';
|
|
121
|
-
let received = 0;
|
|
122
|
-
for (;;) {
|
|
123
|
-
const { done, value } = await reader.read();
|
|
124
|
-
if (done)
|
|
125
|
-
break;
|
|
126
|
-
received += value.byteLength;
|
|
127
|
-
if (received > MAX_REPLY_BYTES) {
|
|
128
|
-
await reader.cancel();
|
|
129
|
-
throw new Error(`reply over ${MAX_REPLY_BYTES} bytes`);
|
|
130
|
-
}
|
|
131
|
-
raw += decoder.decode(value, { stream: true });
|
|
132
|
-
}
|
|
133
|
-
raw += decoder.decode();
|
|
134
|
-
try {
|
|
135
|
-
return JSON.parse(raw);
|
|
136
|
-
}
|
|
137
|
-
catch {
|
|
138
|
-
throw new Error('reply is not JSON');
|
|
139
|
-
}
|
|
140
|
-
}
|
|
141
113
|
async function requestScores(model, query, head, route) {
|
|
142
114
|
const { state, questions } = buildRelevanceRequest(query, head);
|
|
143
115
|
// Strict parse: parseInt would read "15s" as 15 ms, and Node clamps a delay past 2^31-1 to 1 ms.
|
|
@@ -153,7 +125,7 @@ async function requestScores(model, query, head, route) {
|
|
|
153
125
|
await resp.body?.cancel();
|
|
154
126
|
throw new Error(`HTTP ${resp.status}${ray ? `, ray ${ray}` : ''}`);
|
|
155
127
|
}
|
|
156
|
-
const body = await readCappedJson(resp);
|
|
128
|
+
const body = await readCappedJson(resp, RERANKER_MAX_REPLY_BYTES);
|
|
157
129
|
const parsed = parseClefReply(body, head.length, model, route.backend === 'cloudflare');
|
|
158
130
|
if (isRejection(parsed))
|
|
159
131
|
throw new Error(parsed);
|
|
@@ -7,9 +7,8 @@ const DEFAULT_CROSS_ENCODER_TOP_K = 50;
|
|
|
7
7
|
const MODEL_NAME = 'Xenova/ms-marco-MiniLM-L-6-v2';
|
|
8
8
|
const _require = createRequire(import.meta.url);
|
|
9
9
|
const TRANSFORMERS_PACKAGES = ['@huggingface/transformers', '@xenova/transformers'];
|
|
10
|
-
// Returns the ESM entry URL, the same build src/store/embeddings/index.ts imports
|
|
11
|
-
//
|
|
12
|
-
// the library, with its own ONNX sessions, in the process.
|
|
10
|
+
// Returns the ESM entry URL, the same build src/store/embeddings/index.ts imports; a require-style resolve picks the CommonJS build and
|
|
11
|
+
// puts a second copy of the library, with its own ONNX sessions, in the process.
|
|
13
12
|
function resolveTransformersPackage() {
|
|
14
13
|
for (const name of TRANSFORMERS_PACKAGES) {
|
|
15
14
|
try {
|
|
@@ -47,9 +46,8 @@ async function loadTransformersModule() {
|
|
|
47
46
|
}
|
|
48
47
|
let pipelineLoading = null;
|
|
49
48
|
const outage = createOutageWarning('cross-encoder', 'falling back to identity ordering');
|
|
50
|
-
// NOT the text-classification pipeline: this
|
|
51
|
-
//
|
|
52
|
-
// is identically 1.0 for every input. Read the logit, then squash it.
|
|
49
|
+
// NOT the text-classification pipeline: this is a num_labels=1 regression head and that pipeline softmaxes a length-1 logit vector (always 1.0).
|
|
50
|
+
// Read the logit, then squash it.
|
|
53
51
|
async function buildPipeline() {
|
|
54
52
|
try {
|
|
55
53
|
const mod = await loadTransformersModule();
|
package/dist/rerankers/jev.js
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import { envJevModel, envJevTimeoutMs, envTypesafeApiKey } from '../util/env.js';
|
|
2
2
|
import { redactSecretsStrict } from '../util/secret-detect.js';
|
|
3
3
|
import { createOutageWarning } from './outage-warning.js';
|
|
4
|
-
import { rerankerPost } from './remote.js';
|
|
4
|
+
import { rerankerPost, RERANKER_MAX_REPLY_BYTES } from './remote.js';
|
|
5
|
+
import { readCappedJson } from '../util/capped-json.js';
|
|
6
|
+
import { isJsonNumber, isJsonObject } from '../util/json.js';
|
|
5
7
|
import { compareScoresDesc } from '../core/compare.js';
|
|
6
8
|
import { errorMessage } from '../util/log.js';
|
|
7
9
|
const REQUEST_ID_MAX_CHARS = 64;
|
|
@@ -19,14 +21,16 @@ function truncate(s, n) {
|
|
|
19
21
|
// Number.isFinite rejects a string or null without coercing it, which the
|
|
20
22
|
// declared type cannot promise about a third-party payload.
|
|
21
23
|
function isProbability(v) {
|
|
22
|
-
return v
|
|
24
|
+
return isJsonNumber(v) && Number.isFinite(v) && v >= 0 && v <= 1;
|
|
23
25
|
}
|
|
24
26
|
// A half-scored list ranks worse than the order it would replace, so one bad
|
|
25
27
|
// answer voids the whole response.
|
|
26
|
-
function parseScores(
|
|
28
|
+
function parseScores(body, n) {
|
|
29
|
+
const answers = isJsonObject(body) ? body.answers : undefined;
|
|
27
30
|
const out = [];
|
|
28
31
|
for (let i = 1; i <= n; i++) {
|
|
29
|
-
const
|
|
32
|
+
const answer = isJsonObject(answers) ? answers[`c${i}`] : undefined;
|
|
33
|
+
const v = isJsonObject(answer) ? answer.noul : undefined;
|
|
30
34
|
if (!isProbability(v))
|
|
31
35
|
return null;
|
|
32
36
|
out.push(v);
|
|
@@ -67,8 +71,7 @@ async function requestScores(query, head) {
|
|
|
67
71
|
await resp.body?.cancel();
|
|
68
72
|
throw new Error(`HTTP ${resp.status}${requestId ? `, request ${requestId}` : ''}`);
|
|
69
73
|
}
|
|
70
|
-
const
|
|
71
|
-
const scores = parseScores(body.answers, head.length);
|
|
74
|
+
const scores = parseScores(await readCappedJson(resp, RERANKER_MAX_REPLY_BYTES), head.length);
|
|
72
75
|
if (!scores)
|
|
73
76
|
throw new Error('incomplete or out-of-range answers');
|
|
74
77
|
return scores;
|
package/dist/rerankers/llm.d.ts
CHANGED
|
@@ -1,14 +1,5 @@
|
|
|
1
1
|
import type { RerankerFn } from './types.js';
|
|
2
|
-
/**
|
|
3
|
-
*
|
|
4
|
-
* OpenAI-compatible endpoint. Gated on HIPPO_LLM_RERANKER_URL to prevent
|
|
5
|
-
* accidental cost.
|
|
6
|
-
*
|
|
7
|
-
* Skeleton only; full characterisation is deferred.
|
|
8
|
-
*
|
|
9
|
-
* Timeout: defaults to 30s for the whole call, retries included; overridable
|
|
10
|
-
* via HIPPO_LLM_RERANKER_TIMEOUT_MS. On timeout or any failure the reranker
|
|
11
|
-
* falls back to identity ordering; recall must not hang on a wedged endpoint.
|
|
12
|
-
*/
|
|
2
|
+
/** Track 3 reranker (skeleton): listwise LLM rerank on a customer-supplied OpenAI-compatible endpoint, gated on HIPPO_LLM_RERANKER_URL against accidental cost.
|
|
3
|
+
* Timeout is 30s for the whole call, retries included (HIPPO_LLM_RERANKER_TIMEOUT_MS); any failure falls back to identity ordering, so recall never hangs. */
|
|
13
4
|
export declare function createLlmReranker(): RerankerFn;
|
|
14
5
|
//# sourceMappingURL=llm.d.ts.map
|
package/dist/rerankers/llm.js
CHANGED
|
@@ -1,21 +1,14 @@
|
|
|
1
1
|
import { envLlmRerankerKey, envLlmRerankerModel, envLlmRerankerTimeoutMs, envLlmRerankerUrl } from '../util/env.js';
|
|
2
2
|
import { redactSecretsStrict } from '../util/secret-detect.js';
|
|
3
3
|
import { createOutageWarning } from './outage-warning.js';
|
|
4
|
-
import { rerankerPost } from './remote.js';
|
|
4
|
+
import { rerankerPost, RERANKER_MAX_REPLY_BYTES } from './remote.js';
|
|
5
|
+
import { readCappedJson } from '../util/capped-json.js';
|
|
6
|
+
import { isJsonObject, isJsonString } from '../util/json.js';
|
|
5
7
|
import { errorMessage } from '../util/log.js';
|
|
6
8
|
const DEFAULT_LLM_RERANK_TOP_K = 20;
|
|
7
9
|
const DEFAULT_TIMEOUT_MS = 30_000;
|
|
8
|
-
/**
|
|
9
|
-
*
|
|
10
|
-
* OpenAI-compatible endpoint. Gated on HIPPO_LLM_RERANKER_URL to prevent
|
|
11
|
-
* accidental cost.
|
|
12
|
-
*
|
|
13
|
-
* Skeleton only; full characterisation is deferred.
|
|
14
|
-
*
|
|
15
|
-
* Timeout: defaults to 30s for the whole call, retries included; overridable
|
|
16
|
-
* via HIPPO_LLM_RERANKER_TIMEOUT_MS. On timeout or any failure the reranker
|
|
17
|
-
* falls back to identity ordering; recall must not hang on a wedged endpoint.
|
|
18
|
-
*/
|
|
10
|
+
/** Track 3 reranker (skeleton): listwise LLM rerank on a customer-supplied OpenAI-compatible endpoint, gated on HIPPO_LLM_RERANKER_URL against accidental cost.
|
|
11
|
+
* Timeout is 30s for the whole call, retries included (HIPPO_LLM_RERANKER_TIMEOUT_MS); any failure falls back to identity ordering, so recall never hangs. */
|
|
19
12
|
export function createLlmReranker() {
|
|
20
13
|
const outage = createOutageWarning('llm', 'keeping the input order');
|
|
21
14
|
return async (query, results, options) => {
|
|
@@ -42,6 +35,14 @@ export function createLlmReranker() {
|
|
|
42
35
|
}));
|
|
43
36
|
};
|
|
44
37
|
}
|
|
38
|
+
/** The first choice's message text, or '' when the reply has none. */
|
|
39
|
+
function replyText(body) {
|
|
40
|
+
const choices = isJsonObject(body) ? body.choices : undefined;
|
|
41
|
+
const choice = Array.isArray(choices) ? choices[0] : undefined;
|
|
42
|
+
const message = isJsonObject(choice) ? choice.message : undefined;
|
|
43
|
+
const content = isJsonObject(message) ? message.content : undefined;
|
|
44
|
+
return isJsonString(content) ? content : '';
|
|
45
|
+
}
|
|
45
46
|
/** One chat-completions call; rejects with the reason when the reply holds no usable permutation. */
|
|
46
47
|
async function requestPermutation(url, query, head) {
|
|
47
48
|
const key = envLlmRerankerKey();
|
|
@@ -69,8 +70,7 @@ async function requestPermutation(url, query, head) {
|
|
|
69
70
|
await resp.body?.cancel();
|
|
70
71
|
throw new Error(`HTTP ${resp.status}`);
|
|
71
72
|
}
|
|
72
|
-
const
|
|
73
|
-
const txt = j.choices?.[0]?.message?.content ?? '';
|
|
73
|
+
const txt = replyText(await readCappedJson(resp, RERANKER_MAX_REPLY_BYTES));
|
|
74
74
|
const m = txt.match(/\[\s*(\d+(?:\s*,\s*\d+)*)\s*\]/);
|
|
75
75
|
const parsed = m ? m[1].split(',').map((s) => parseInt(s.trim(), 10)) : [];
|
|
76
76
|
const isPermutation = parsed.length === head.length &&
|
|
@@ -2,6 +2,7 @@ export interface OutageWarning {
|
|
|
2
2
|
failed(reason: string): void;
|
|
3
3
|
answered(): void;
|
|
4
4
|
}
|
|
5
|
-
/** Warns when `name` starts failing, at most every five minutes while it keeps failing,
|
|
5
|
+
/** Warns when `name` starts failing, at most every five minutes while it keeps failing,
|
|
6
|
+
* and once when it answers again. `fallback` says what recall does meanwhile. */
|
|
6
7
|
export declare function createOutageWarning(name: string, fallback: string): OutageWarning;
|
|
7
8
|
//# sourceMappingURL=outage-warning.d.ts.map
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
// One way for a reranker to report that it stopped working, without a line per recall.
|
|
2
2
|
import { log } from '../util/log.js';
|
|
3
3
|
const REPEAT_MS = 5 * 60_000;
|
|
4
|
-
/** Warns when `name` starts failing, at most every five minutes while it keeps failing,
|
|
4
|
+
/** Warns when `name` starts failing, at most every five minutes while it keeps failing,
|
|
5
|
+
* and once when it answers again. `fallback` says what recall does meanwhile. */
|
|
5
6
|
export function createOutageWarning(name, fallback) {
|
|
6
7
|
let failures = 0;
|
|
7
8
|
let unreported = 0;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
export declare const RERANKER_MAX_REPLY_BYTES: number;
|
|
1
2
|
/** POST a scoring request. A dropped connection, 429 or 5xx is retried, since scoring changes nothing on the far side. */
|
|
2
3
|
export declare function rerankerPost(url: string, init: RequestInit, budgetMs: number): Promise<Response>;
|
|
3
4
|
//# sourceMappingURL=remote.d.ts.map
|
package/dist/rerankers/remote.js
CHANGED
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
import { fetchWithRetry } from '../util/http-retry.js';
|
|
3
3
|
// A Retry-After longer than this would outlast most budgets, so the answer is handed back and the reranker falls back.
|
|
4
4
|
const RETRY_WAIT_CAP_MS = 2_000;
|
|
5
|
+
// Every reranker reads its reply through this cap; the largest honest reply is a few KB, and 1 MiB leaves room for a verbose envelope.
|
|
6
|
+
export const RERANKER_MAX_REPLY_BYTES = 1024 * 1024;
|
|
5
7
|
/** POST a scoring request. A dropped connection, 429 or 5xx is retried, since scoring changes nothing on the far side. */
|
|
6
8
|
export async function rerankerPost(url, init, budgetMs) {
|
|
7
9
|
// The budget bounds the whole call, retries included, so recall never waits past the configured timeout.
|
|
@@ -1,18 +1,6 @@
|
|
|
1
1
|
import type { SearchResult } from '../core/search-types.js';
|
|
2
|
-
/**
|
|
3
|
-
*
|
|
4
|
-
* by hybridSearch's BM25 + cosine + MMR pipeline. Rerankers run AFTER MMR
|
|
5
|
-
* de-duplication and BEFORE token-budget filtering, so the reranker sees
|
|
6
|
-
* the full diversity-balanced candidate pool but does not see candidates
|
|
7
|
-
* already filtered out by score-zero or supersession.
|
|
8
|
-
*
|
|
9
|
-
* Rerankers MUST be deterministic for a given (query, results) input
|
|
10
|
-
* unless explicitly documented as stochastic (the LLM track, and the
|
|
11
|
-
* hosted jev reranker, whose scores move slightly run to run).
|
|
12
|
-
* Determinism is required for paired A/B and for the workload-validity gate.
|
|
13
|
-
*
|
|
14
|
-
* @returns Reordered (and optionally rescaled) results.
|
|
15
|
-
*/
|
|
2
|
+
/** Reorders hybridSearch's candidates AFTER MMR de-duplication and BEFORE token-budget filtering, so it sees the full diverse pool.
|
|
3
|
+
* MUST be deterministic for a given (query, results) unless documented stochastic (LLM track, hosted jev): paired A/B and the validity gate need it. */
|
|
16
4
|
export type RerankerFn = (query: string, results: SearchResult[], options?: RerankerOptions) => Promise<RerankResult[]>;
|
|
17
5
|
/** JSON-serializable value. Per-track reranker config is opaque to the seam
|
|
18
6
|
* but must still be a concrete, serializable shape rather than `unknown`. */
|
package/dist/search/boosts.d.ts
CHANGED
|
@@ -1,10 +1,8 @@
|
|
|
1
1
|
import { type MemoryEntry } from '../core/memory.js';
|
|
2
2
|
import { type TemporalDirection, type TemporalRange } from './temporal.js';
|
|
3
|
-
export declare const CHURN_STALE_RANK_MULTIPLIER = 0.5;
|
|
4
3
|
export declare const STRENGTH_RANK_FLOOR = 0.5;
|
|
5
4
|
export declare const STRENGTH_RANK_SPAN = 0.5;
|
|
6
5
|
export declare function churnStaleFactor(entry: MemoryEntry): number;
|
|
7
|
-
export declare function recencyBoost(entry: MemoryEntry, now: Date): number;
|
|
8
6
|
/** Retrieval-time outcome nudge in [0.85, 1.15]; the bm25-outcome eval baseline ranks with it too. */
|
|
9
7
|
export declare function outcomeMultiplier(entry: MemoryEntry): number;
|
|
10
8
|
/** A DAG summary is a topic summary (level 2) or an entity profile (level 3); both take the same deboost. */
|
package/dist/search/boosts.js
CHANGED
|
@@ -5,7 +5,7 @@ import { pathBoostMultiplier } from './path-context.js';
|
|
|
5
5
|
import { scopeMatch } from '../sharing/scope.js';
|
|
6
6
|
import { temporalBoost } from './temporal.js';
|
|
7
7
|
import { DAY_MS } from '../util/time.js';
|
|
8
|
-
|
|
8
|
+
const CHURN_STALE_RANK_MULTIPLIER = 0.5; // SHORTCUT: untuned; measure on real recall before any default.
|
|
9
9
|
const DECISION_TAG_BOOST = 1.2;
|
|
10
10
|
// A memory tagged for the active scope outranks a neutral one; one tagged for another scope is demoted.
|
|
11
11
|
const SCOPE_MATCH_BOOST = 1.5;
|
|
@@ -27,7 +27,7 @@ const FRESHNESS_WINDOW_MS = 7 * DAY_MS;
|
|
|
27
27
|
export function churnStaleFactor(entry) {
|
|
28
28
|
return entry.tags.includes(CHURN_STALE_TAG) ? CHURN_STALE_RANK_MULTIPLIER : 1.0;
|
|
29
29
|
}
|
|
30
|
-
|
|
30
|
+
function recencyBoost(entry, now) {
|
|
31
31
|
if (isRecencyAblated())
|
|
32
32
|
return 1; // EVAL-ONLY ablation (see ablation.ts)
|
|
33
33
|
const created = new Date(entry.created);
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { MemoryEntry } from '../core/memory.js';
|
|
2
|
+
import type { RerankStep } from '../core/search-types.js';
|
|
3
|
+
import type { ActiveGoals, GoalRecallLogRow } from '../store/goals.js';
|
|
4
|
+
/** Options of {@link boostByGoals}. */
|
|
5
|
+
export interface GoalStackBoostOpts {
|
|
6
|
+
sessionId: string;
|
|
7
|
+
tenantId: string;
|
|
8
|
+
limit: number;
|
|
9
|
+
/** Side-channel: one goal-boost `RerankStep` per boosted row, keyed by `entry.id` (a map because the helper re-spreads rows); only populated when passed. */
|
|
10
|
+
trace?: Map<string, RerankStep>;
|
|
11
|
+
}
|
|
12
|
+
/** The boosted, re-sorted rows and the `goal_recall_log` rows they earn. */
|
|
13
|
+
export interface GoalStackBoost<R> {
|
|
14
|
+
results: R[];
|
|
15
|
+
log: GoalRecallLogRow[];
|
|
16
|
+
}
|
|
17
|
+
/** The goal-stack boost over goals already read, touching no store; a caller skips it under an explicit goal tag. Its log covers the top
|
|
18
|
+
* `limit` rows and keeps those whose memory is global, since only the store can tell them apart; {@link localGoalRecallRows} drops those before the write. */
|
|
19
|
+
export declare function boostByGoals<R extends {
|
|
20
|
+
entry: MemoryEntry;
|
|
21
|
+
score: number;
|
|
22
|
+
}>(results: R[], active: ActiveGoals, opts: GoalStackBoostOpts): GoalStackBoost<R>;
|
|
23
|
+
//# sourceMappingURL=goal-boost.d.ts.map
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
// src/search/goal-boost.ts: the goal-stack boost over goals already read; it ranks rows and touches no store.
|
|
2
|
+
import { compareScoresDesc } from '../core/compare.js';
|
|
3
|
+
const MAX_FINAL_MULTIPLIER = 3.0;
|
|
4
|
+
/** The capped boost for one row whose tags match `matches` active goals. */
|
|
5
|
+
function goalBoostMultiplier(entry, tags, matches, goalsByTag, policiesByGoalId) {
|
|
6
|
+
// Base 2.0x for first match, +0.5x per additional, capped at 3.0x.
|
|
7
|
+
let multiplier = Math.min(2.0 + 0.5 * (matches.length - 1), MAX_FINAL_MULTIPLIER);
|
|
8
|
+
// Compose per-policy multipliers per matched tag.
|
|
9
|
+
for (const tag of matches) {
|
|
10
|
+
const goal = goalsByTag.get(tag);
|
|
11
|
+
const policy = policiesByGoalId.get(goal.id);
|
|
12
|
+
if (!policy)
|
|
13
|
+
continue;
|
|
14
|
+
if (policy.policyType === 'error-prioritized' && tags.includes('error')) {
|
|
15
|
+
multiplier *= policy.errorPriority;
|
|
16
|
+
}
|
|
17
|
+
else if (policy.policyType === 'schema-fit-biased') {
|
|
18
|
+
// Linearly weight schema_fit in [0,1] up to (weightSchemaFit)x.
|
|
19
|
+
// Default 1.0 is a no-op.
|
|
20
|
+
multiplier *=
|
|
21
|
+
1.0 +
|
|
22
|
+
Math.max(0, policy.weightSchemaFit - 1.0) *
|
|
23
|
+
(entry.schema_fit ?? 0.5);
|
|
24
|
+
}
|
|
25
|
+
else if (policy.policyType === 'recency-first') {
|
|
26
|
+
multiplier *= policy.weightRecency;
|
|
27
|
+
}
|
|
28
|
+
else if (policy.policyType === 'hybrid') {
|
|
29
|
+
multiplier *= policy.weightOutcome;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
// Hard cap AFTER all composition.
|
|
33
|
+
return Math.min(multiplier, MAX_FINAL_MULTIPLIER);
|
|
34
|
+
}
|
|
35
|
+
/** Log rows for the top `limit` boosted rows, one per matched goal. */
|
|
36
|
+
function buildGoalRecallLog(boosted, matchesByEntryId, goalsByTag, opts) {
|
|
37
|
+
const { sessionId, tenantId, limit } = opts;
|
|
38
|
+
const recalledAt = new Date().toISOString();
|
|
39
|
+
const log = [];
|
|
40
|
+
for (const r of boosted.slice(0, limit)) {
|
|
41
|
+
const matches = matchesByEntryId.get(r.entry.id);
|
|
42
|
+
if (!matches || matches.length === 0)
|
|
43
|
+
continue;
|
|
44
|
+
for (const tag of matches) {
|
|
45
|
+
const goal = goalsByTag.get(tag);
|
|
46
|
+
if (!goal)
|
|
47
|
+
continue;
|
|
48
|
+
log.push({ goalId: goal.id, memoryId: r.entry.id, tenantId, sessionId, recalledAt, score: r.score });
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
return log;
|
|
52
|
+
}
|
|
53
|
+
/** The goal-stack boost over goals already read, touching no store; a caller skips it under an explicit goal tag. Its log covers the top
|
|
54
|
+
* `limit` rows and keeps those whose memory is global, since only the store can tell them apart; {@link localGoalRecallRows} drops those before the write. */
|
|
55
|
+
export function boostByGoals(results, active, opts) {
|
|
56
|
+
const { trace } = opts;
|
|
57
|
+
if (active.goals.length === 0)
|
|
58
|
+
return { results, log: [] };
|
|
59
|
+
const goalsByTag = new Map(active.goals.map((g) => [g.goalName, g]));
|
|
60
|
+
const policiesByGoalId = active.policies;
|
|
61
|
+
// Goal-tag matches per boosted row, keyed by entry id; a side table (not a spread-on marker property) so `boosted` stays exactly R[] with no cast-then-strip.
|
|
62
|
+
const matchesByEntryId = new Map();
|
|
63
|
+
const boosted = results
|
|
64
|
+
.map((r) => {
|
|
65
|
+
const tags = r.entry.tags ?? [];
|
|
66
|
+
const matches = tags.filter((t) => goalsByTag.has(t));
|
|
67
|
+
if (matches.length === 0)
|
|
68
|
+
return r;
|
|
69
|
+
const multiplier = goalBoostMultiplier(r.entry, tags, matches, goalsByTag, policiesByGoalId);
|
|
70
|
+
// Recall-trace side-channel: record the goal-boost step BEFORE the
|
|
71
|
+
// score is mutated, keyed by entry id; a pure read of r.score.
|
|
72
|
+
if (trace) {
|
|
73
|
+
trace.set(r.entry.id, {
|
|
74
|
+
stage: 'goal-boost',
|
|
75
|
+
multiplier,
|
|
76
|
+
scoreBefore: r.score,
|
|
77
|
+
scoreAfter: r.score * multiplier,
|
|
78
|
+
note: matches.join(', '),
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
matchesByEntryId.set(r.entry.id, matches);
|
|
82
|
+
// SAFETY: spreading a generic-constrained `r: R` widens to the spread's plain object type; only `score` changes, so the value still satisfies R.
|
|
83
|
+
return { ...r, score: r.score * multiplier };
|
|
84
|
+
})
|
|
85
|
+
// Deliberately a PLAIN stable score sort with no compareEntryIdentity tail: re-sorting an already deterministic ranking inherits its determinism via
|
|
86
|
+
// stability, and ties keep the prior (meaningful) rank instead of reordering by content.
|
|
87
|
+
.sort((a, b) => compareScoresDesc(a.score, b.score));
|
|
88
|
+
return { results: boosted, log: buildGoalRecallLog(boosted, matchesByEntryId, goalsByTag, opts) };
|
|
89
|
+
}
|
|
90
|
+
//# sourceMappingURL=goal-boost.js.map
|
package/dist/search/hybrid.d.ts
CHANGED
|
@@ -43,6 +43,8 @@ export interface HybridSearchOptions {
|
|
|
43
43
|
vectorCandidates?: HybridVectorCandidates;
|
|
44
44
|
/** Where vectors are read; hippo.db under `hippoRoot` when unset. */
|
|
45
45
|
store?: HippoStore;
|
|
46
|
+
/** The deadline a caller already started for this recall's query embedding; a fresh budget when unset. */
|
|
47
|
+
queryEmbedDeadline?: AbortSignal;
|
|
46
48
|
}
|
|
47
49
|
/** BM25 blended with cosine similarity when stored vectors and a provider are available, BM25 * strength * recency otherwise. */
|
|
48
50
|
export declare function hybridSearch(query: string, entries: MemoryEntry[], options?: HybridSearchOptions): Promise<SearchResult[]>;
|