hippo-memory 1.60.0 → 1.61.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/ablation.js +9 -27
- package/dist/agent-memories/apply.js +4 -1
- package/dist/agent-memories/claude-code.js +1 -1
- package/dist/agent-memories/codex.js +1 -1
- package/dist/agent-memories/gemini.js +1 -1
- package/dist/agent-memories/legacy.js +1 -1
- package/dist/agent-memories/source.js +1 -1
- package/dist/agent-memories/sync.js +8 -3
- package/dist/ambient-store.d.ts +14 -0
- package/dist/ambient-store.js +90 -0
- package/dist/ambient.d.ts +23 -0
- package/dist/ambient.js +72 -50
- package/dist/api/assemble.d.ts +93 -0
- package/dist/api/assemble.js +152 -0
- package/dist/api/audit.d.ts +17 -0
- package/dist/api/audit.js +23 -0
- package/dist/api/auth.d.ts +79 -0
- package/dist/api/auth.js +178 -0
- package/dist/api/context-types.d.ts +105 -0
- package/dist/api/context-types.js +3 -0
- package/dist/api/context.d.ts +31 -0
- package/dist/api/context.js +705 -0
- package/dist/api/dormant.d.ts +30 -0
- package/dist/api/dormant.js +140 -0
- package/dist/api/drill-down.d.ts +84 -0
- package/dist/api/drill-down.js +123 -0
- package/dist/api/forget.d.ts +57 -0
- package/dist/api/forget.js +87 -0
- package/dist/api/goals.d.ts +18 -0
- package/dist/api/goals.js +33 -0
- package/dist/api/learn.d.ts +31 -0
- package/dist/api/learn.js +88 -0
- package/dist/api/outcome.d.ts +61 -0
- package/dist/api/outcome.js +66 -0
- package/dist/api/promote.d.ts +54 -0
- package/dist/api/promote.js +203 -0
- package/dist/api/quarantine.d.ts +24 -0
- package/dist/api/quarantine.js +121 -0
- package/dist/api/recall-types.d.ts +390 -0
- package/dist/api/recall-types.js +3 -0
- package/dist/api/recall.d.ts +36 -0
- package/dist/api/recall.js +634 -0
- package/dist/api/remember.d.ts +35 -0
- package/dist/api/remember.js +43 -0
- package/dist/api/sleep.d.ts +136 -0
- package/dist/api/sleep.js +271 -0
- package/dist/api/tokens.d.ts +26 -0
- package/dist/api/tokens.js +60 -0
- package/dist/api/types.d.ts +56 -0
- package/dist/api/types.js +38 -0
- package/dist/api.d.ts +20 -1262
- package/dist/api.js +25 -2727
- package/dist/audit.d.ts +3 -0
- package/dist/audit.js +6 -3
- package/dist/auth.d.ts +45 -4
- package/dist/auth.js +125 -48
- package/dist/autolearn.js +2 -2
- package/dist/capture/command.d.ts +33 -0
- package/dist/capture/command.js +264 -0
- package/dist/capture/compact.d.ts +44 -0
- package/dist/capture/compact.js +354 -0
- package/dist/capture/extract.d.ts +21 -0
- package/dist/capture/extract.js +464 -0
- package/dist/capture/transcript.d.ts +40 -0
- package/dist/capture/transcript.js +193 -0
- package/dist/capture-error.js +2 -1
- package/dist/churn-git.js +4 -2
- package/dist/cli/audit.d.ts +3 -0
- package/dist/cli/audit.js +159 -0
- package/dist/cli/auth.d.ts +2 -0
- package/dist/cli/auth.js +171 -0
- package/dist/cli/briefs.d.ts +4 -0
- package/dist/cli/briefs.js +435 -0
- package/dist/cli/card.d.ts +3 -0
- package/dist/cli/card.js +333 -0
- package/dist/cli/context.d.ts +15 -0
- package/dist/cli/context.js +366 -0
- package/dist/cli/continuity.d.ts +6 -0
- package/dist/cli/continuity.js +445 -0
- package/dist/cli/curate.d.ts +19 -0
- package/dist/cli/curate.js +555 -0
- package/dist/cli/dag.d.ts +5 -0
- package/dist/cli/dag.js +177 -0
- package/dist/cli/decisions.d.ts +4 -0
- package/dist/cli/decisions.js +528 -0
- package/dist/cli/eval.d.ts +5 -0
- package/dist/cli/eval.js +213 -0
- package/dist/cli/explain.d.ts +4 -0
- package/dist/cli/explain.js +150 -0
- package/dist/cli/goals.d.ts +2 -0
- package/dist/cli/goals.js +196 -0
- package/dist/cli/hook-blocks.d.ts +18 -0
- package/dist/cli/hook-blocks.js +233 -0
- package/dist/cli/init.d.ts +2 -0
- package/dist/cli/init.js +305 -0
- package/dist/cli/maintenance.d.ts +4 -0
- package/dist/cli/maintenance.js +179 -0
- package/dist/cli/playbooks.d.ts +4 -0
- package/dist/cli/playbooks.js +556 -0
- package/dist/cli/projects.js +1 -1
- package/dist/cli/recall.d.ts +7 -0
- package/dist/cli/recall.js +597 -0
- package/dist/cli/remember.d.ts +5 -0
- package/dist/cli/remember.js +442 -0
- package/dist/cli/serve.d.ts +5 -0
- package/dist/cli/serve.js +40 -0
- package/dist/cli/session-hooks.d.ts +29 -0
- package/dist/cli/session-hooks.js +637 -0
- package/dist/cli/setup.d.ts +4 -0
- package/dist/cli/setup.js +376 -0
- package/dist/cli/shared.d.ts +15 -19
- package/dist/cli/shared.js +50 -341
- package/dist/cli/slack.d.ts +2 -0
- package/dist/cli/slack.js +171 -0
- package/dist/cli/status.d.ts +18 -0
- package/dist/cli/status.js +400 -0
- package/dist/cli/transfer.d.ts +10 -0
- package/dist/cli/transfer.js +438 -0
- package/dist/cli/usage.d.ts +85 -0
- package/dist/cli/usage.js +741 -0
- package/dist/cli.d.ts +71 -120
- package/dist/cli.js +170 -8469
- package/dist/client.js +15 -8
- package/dist/compaction-record.js +6 -4
- package/dist/connectors/github/backfill.js +94 -87
- package/dist/connectors/github/cli-impl.js +4 -3
- package/dist/connectors/github/dlq.js +67 -54
- package/dist/connectors/github/ingest.js +34 -35
- package/dist/connectors/github/tenant-routing.js +3 -2
- package/dist/connectors/github/webhook.js +135 -216
- package/dist/connectors/slack/dlq.js +49 -61
- package/dist/connectors/slack/ingest.js +55 -48
- package/dist/connectors/slack/tenant-routing.js +4 -3
- package/dist/connectors/slack/webhook.js +72 -74
- package/dist/consolidate/conflicts.d.ts +10 -0
- package/dist/consolidate/conflicts.js +178 -0
- package/dist/consolidate/decay.d.ts +12 -0
- package/dist/consolidate/decay.js +145 -0
- package/dist/consolidate/llm-passes.d.ts +3 -0
- package/dist/consolidate/llm-passes.js +141 -0
- package/dist/consolidate/merge.d.ts +7 -0
- package/dist/consolidate/merge.js +251 -0
- package/dist/consolidate/physics-pass.d.ts +3 -0
- package/dist/consolidate/physics-pass.js +60 -0
- package/dist/consolidate/run.d.ts +69 -0
- package/dist/consolidate/run.js +76 -0
- package/dist/consolidate/sleep.d.ts +18 -0
- package/dist/consolidate/sleep.js +209 -0
- package/dist/consolidate/traces.d.ts +4 -0
- package/dist/consolidate/traces.js +178 -0
- package/dist/context-auto.js +7 -11
- package/dist/context-render.d.ts +1 -1
- package/dist/context-render.js +1 -1
- package/dist/customer-notes.d.ts +3 -0
- package/dist/customer-notes.js +6 -4
- package/dist/dag.js +6 -5
- package/dist/dashboard-actions.d.ts +20 -0
- package/dist/dashboard-actions.js +88 -0
- package/dist/dashboard-params.d.ts +45 -0
- package/dist/dashboard-params.js +127 -0
- package/dist/dashboard-queries.d.ts +15 -0
- package/dist/dashboard-queries.js +355 -0
- package/dist/dashboard-snapshot.d.ts +138 -0
- package/dist/dashboard-snapshot.js +308 -0
- package/dist/dashboard-types.d.ts +163 -0
- package/dist/dashboard-types.js +3 -0
- package/dist/dashboard.d.ts +6 -7
- package/dist/dashboard.js +228 -202
- package/dist/db/busy.d.ts +5 -0
- package/dist/db/busy.js +24 -0
- package/dist/db/continuity.d.ts +5 -0
- package/dist/db/continuity.js +145 -0
- package/dist/db/meta.d.ts +8 -0
- package/dist/db/meta.js +35 -0
- package/dist/db/migrate.d.ts +9 -0
- package/dist/db/migrate.js +138 -0
- package/dist/db/migrations/index.d.ts +5 -0
- package/dist/db/migrations/index.js +109 -0
- package/dist/db/migrations/types.d.ts +14 -0
- package/dist/db/migrations/types.js +2 -0
- package/dist/db/migrations/v01.d.ts +3 -0
- package/dist/db/migrations/v01.js +38 -0
- package/dist/db/migrations/v02.d.ts +3 -0
- package/dist/db/migrations/v02.js +21 -0
- package/dist/db/migrations/v03.d.ts +3 -0
- package/dist/db/migrations/v03.js +22 -0
- package/dist/db/migrations/v04.d.ts +3 -0
- package/dist/db/migrations/v04.js +28 -0
- package/dist/db/migrations/v05.d.ts +3 -0
- package/dist/db/migrations/v05.js +21 -0
- package/dist/db/migrations/v06.d.ts +3 -0
- package/dist/db/migrations/v06.js +25 -0
- package/dist/db/migrations/v07.d.ts +3 -0
- package/dist/db/migrations/v07.js +13 -0
- package/dist/db/migrations/v08.d.ts +3 -0
- package/dist/db/migrations/v08.js +8 -0
- package/dist/db/migrations/v09.d.ts +3 -0
- package/dist/db/migrations/v09.js +13 -0
- package/dist/db/migrations/v10.d.ts +3 -0
- package/dist/db/migrations/v10.js +17 -0
- package/dist/db/migrations/v11.d.ts +3 -0
- package/dist/db/migrations/v11.js +15 -0
- package/dist/db/migrations/v12.d.ts +3 -0
- package/dist/db/migrations/v12.js +11 -0
- package/dist/db/migrations/v13.d.ts +3 -0
- package/dist/db/migrations/v13.js +15 -0
- package/dist/db/migrations/v14.d.ts +3 -0
- package/dist/db/migrations/v14.js +66 -0
- package/dist/db/migrations/v15.d.ts +3 -0
- package/dist/db/migrations/v15.js +42 -0
- package/dist/db/migrations/v16.d.ts +3 -0
- package/dist/db/migrations/v16.js +61 -0
- package/dist/db/migrations/v17.d.ts +3 -0
- package/dist/db/migrations/v17.js +46 -0
- package/dist/db/migrations/v18.d.ts +3 -0
- package/dist/db/migrations/v18.js +60 -0
- package/dist/db/migrations/v19.d.ts +3 -0
- package/dist/db/migrations/v19.js +28 -0
- package/dist/db/migrations/v20.d.ts +3 -0
- package/dist/db/migrations/v20.js +42 -0
- package/dist/db/migrations/v21.d.ts +3 -0
- package/dist/db/migrations/v21.js +16 -0
- package/dist/db/migrations/v22.d.ts +3 -0
- package/dist/db/migrations/v22.js +82 -0
- package/dist/db/migrations/v23.d.ts +3 -0
- package/dist/db/migrations/v23.js +48 -0
- package/dist/db/migrations/v24.d.ts +3 -0
- package/dist/db/migrations/v24.js +72 -0
- package/dist/db/migrations/v25.d.ts +3 -0
- package/dist/db/migrations/v25.js +46 -0
- package/dist/db/migrations/v26.d.ts +3 -0
- package/dist/db/migrations/v26.js +23 -0
- package/dist/db/migrations/v27.d.ts +3 -0
- package/dist/db/migrations/v27.js +57 -0
- package/dist/db/migrations/v28.d.ts +3 -0
- package/dist/db/migrations/v28.js +38 -0
- package/dist/db/migrations/v29.d.ts +3 -0
- package/dist/db/migrations/v29.js +78 -0
- package/dist/db/migrations/v30.d.ts +3 -0
- package/dist/db/migrations/v30.js +92 -0
- package/dist/db/migrations/v31.d.ts +3 -0
- package/dist/db/migrations/v31.js +74 -0
- package/dist/db/migrations/v32.d.ts +3 -0
- package/dist/db/migrations/v32.js +102 -0
- package/dist/db/migrations/v33.d.ts +3 -0
- package/dist/db/migrations/v33.js +104 -0
- package/dist/db/migrations/v34.d.ts +3 -0
- package/dist/db/migrations/v34.js +93 -0
- package/dist/db/migrations/v35.d.ts +3 -0
- package/dist/db/migrations/v35.js +98 -0
- package/dist/db/migrations/v36.d.ts +3 -0
- package/dist/db/migrations/v36.js +98 -0
- package/dist/db/migrations/v37.d.ts +3 -0
- package/dist/db/migrations/v37.js +219 -0
- package/dist/db/migrations/v38.d.ts +3 -0
- package/dist/db/migrations/v38.js +277 -0
- package/dist/db/migrations/v39.d.ts +3 -0
- package/dist/db/migrations/v39.js +59 -0
- package/dist/db/migrations/v40.d.ts +3 -0
- package/dist/db/migrations/v40.js +74 -0
- package/dist/db/migrations/v41.d.ts +3 -0
- package/dist/db/migrations/v41.js +43 -0
- package/dist/db/migrations/v42.d.ts +3 -0
- package/dist/db/migrations/v42.js +41 -0
- package/dist/db/migrations/v43.d.ts +3 -0
- package/dist/db/migrations/v43.js +67 -0
- package/dist/db/migrations/v44.d.ts +3 -0
- package/dist/db/migrations/v44.js +28 -0
- package/dist/db/migrations/v45.d.ts +3 -0
- package/dist/db/migrations/v45.js +30 -0
- package/dist/db/migrations/v46.d.ts +3 -0
- package/dist/db/migrations/v46.js +25 -0
- package/dist/db/migrations/v47.d.ts +3 -0
- package/dist/db/migrations/v47.js +17 -0
- package/dist/db/migrations/v48.d.ts +3 -0
- package/dist/db/migrations/v48.js +10 -0
- package/dist/db/migrations/v49.d.ts +3 -0
- package/dist/db/migrations/v49.js +31 -0
- package/dist/db/migrations/v50.d.ts +3 -0
- package/dist/db/migrations/v50.js +67 -0
- package/dist/db/migrations/v51.d.ts +3 -0
- package/dist/db/migrations/v51.js +14 -0
- package/dist/db/migrations/v52.d.ts +3 -0
- package/dist/db/migrations/v52.js +7 -0
- package/dist/db/open.d.ts +23 -0
- package/dist/db/open.js +146 -0
- package/dist/db/sqlite.d.ts +21 -0
- package/dist/db/sqlite.js +8 -0
- package/dist/db/tables.d.ts +7 -0
- package/dist/db/tables.js +38 -0
- package/dist/db.d.ts +6 -46
- package/dist/db.js +5 -3049
- package/dist/decisions.d.ts +4 -1
- package/dist/decisions.js +9 -7
- package/dist/dedupe.js +3 -2
- package/dist/delivery-recorder.js +4 -1
- package/dist/doctor.js +3 -3
- package/dist/embedding-provider.d.ts +1 -1
- package/dist/embedding-provider.js +4 -3
- package/dist/embeddings.d.ts +9 -52
- package/dist/embeddings.js +43 -297
- package/dist/env.d.ts +75 -0
- package/dist/env.js +119 -0
- package/dist/eval-suite.js +1 -1
- package/dist/eval.js +2 -2
- package/dist/extract.js +1 -1
- package/dist/gated-write.js +3 -1
- package/dist/goals.d.ts +3 -1
- package/dist/goals.js +18 -0
- package/dist/graph/read.d.ts +73 -0
- package/dist/graph/read.js +325 -0
- package/dist/graph/rows.d.ts +45 -0
- package/dist/graph/rows.js +51 -0
- package/dist/graph/types.d.ts +83 -0
- package/dist/graph/types.js +11 -0
- package/dist/graph/write.d.ts +93 -0
- package/dist/{graph.js → graph/write.js} +6 -384
- package/dist/graph-extract.js +2 -1
- package/dist/graph-recall.d.ts +1 -1
- package/dist/graph-recall.js +2 -2
- package/dist/graph-stream.js +1 -1
- package/dist/graph-view.d.ts +1 -1
- package/dist/graph-view.js +1 -1
- package/dist/half-life-migration.d.ts +1 -1
- package/dist/half-life-migration.js +2 -1
- package/dist/hooks/codex-session.d.ts +8 -0
- package/dist/hooks/codex-session.js +76 -0
- package/dist/hooks/codex-wrapper.d.ts +55 -0
- package/dist/hooks/codex-wrapper.js +288 -0
- package/dist/hooks/json-hooks.d.ts +63 -0
- package/dist/hooks/json-hooks.js +356 -0
- package/dist/hooks/opencode.d.ts +50 -0
- package/dist/hooks/opencode.js +202 -0
- package/dist/hooks/shared.d.ts +54 -0
- package/dist/hooks/shared.js +77 -0
- package/dist/http-retry.d.ts +2 -0
- package/dist/http-retry.js +4 -3
- package/dist/http-util.d.ts +3 -0
- package/dist/http-util.js +10 -0
- package/dist/{importers.d.ts → importers/core.d.ts} +13 -17
- package/dist/importers/core.js +141 -0
- package/dist/importers/markdown-parse.d.ts +41 -0
- package/dist/importers/markdown-parse.js +132 -0
- package/dist/importers/markdown.d.ts +3 -0
- package/dist/importers/markdown.js +92 -0
- package/dist/importers/sources.d.ts +7 -0
- package/dist/importers/sources.js +229 -0
- package/dist/importers/vault.d.ts +11 -0
- package/dist/importers/vault.js +352 -0
- package/dist/incidents.d.ts +3 -0
- package/dist/incidents.js +7 -5
- package/dist/index.d.ts +25 -6
- package/dist/index.js +23 -6
- package/dist/invalidation.js +2 -1
- package/dist/judgment.js +2 -1
- package/dist/keyset.d.ts +13 -0
- package/dist/keyset.js +8 -0
- package/dist/local-embedding.d.ts +13 -0
- package/dist/local-embedding.js +165 -0
- package/dist/log.d.ts +7 -0
- package/dist/log.js +19 -1
- package/dist/mcp/admin-tools.d.ts +8 -0
- package/dist/mcp/admin-tools.js +116 -0
- package/dist/mcp/format.d.ts +27 -0
- package/dist/mcp/format.js +135 -0
- package/dist/mcp/memory-tools.d.ts +5 -0
- package/dist/mcp/memory-tools.js +83 -0
- package/dist/mcp/protocol.d.ts +83 -0
- package/dist/mcp/protocol.js +55 -0
- package/dist/mcp/recall-tools.d.ts +6 -0
- package/dist/mcp/recall-tools.js +320 -0
- package/dist/mcp/request.d.ts +10 -0
- package/dist/mcp/request.js +163 -0
- package/dist/mcp/server.d.ts +4 -75
- package/dist/mcp/server.js +7 -1190
- package/dist/mcp/session-state.d.ts +11 -0
- package/dist/mcp/session-state.js +28 -0
- package/dist/mcp/stdio.d.ts +8 -0
- package/dist/mcp/stdio.js +79 -0
- package/dist/mcp/tools.d.ts +11 -0
- package/dist/mcp/tools.js +247 -0
- package/dist/memory.d.ts +3 -0
- package/dist/memory.js +27 -1
- package/dist/multihop.d.ts +1 -1
- package/dist/multihop.js +2 -1
- package/dist/owner-validation.js +2 -1
- package/dist/physics-state.js +10 -7
- package/dist/policies.d.ts +3 -0
- package/dist/policies.js +8 -6
- package/dist/postinstall.js +3 -2
- package/dist/predictions/planning-fallacy.d.ts +100 -0
- package/dist/predictions/planning-fallacy.js +190 -0
- package/dist/{predictions.d.ts → predictions/store.d.ts} +7 -102
- package/dist/predictions/store.js +434 -0
- package/dist/processes.d.ts +3 -0
- package/dist/processes.js +7 -5
- package/dist/project-briefs.d.ts +3 -0
- package/dist/project-briefs.js +7 -5
- package/dist/project-identity.js +3 -2
- package/dist/project-merge.js +3 -1
- package/dist/quarantine.d.ts +2 -1
- package/dist/quarantine.js +8 -5
- package/dist/raw-archive.js +1 -1
- package/dist/recall-history.js +3 -2
- package/dist/recall-pipeline.d.ts +2 -2
- package/dist/recall-pipeline.js +16 -8
- package/dist/recall-scope.js +1 -1
- package/dist/recall-trace.d.ts +1 -1
- package/dist/refine-llm.js +2 -1
- package/dist/reject-flow.js +6 -1
- package/dist/rerankers/clef.js +6 -5
- package/dist/rerankers/jev.d.ts +1 -1
- package/dist/rerankers/jev.js +4 -4
- package/dist/rerankers/llm.d.ts +4 -2
- package/dist/rerankers/llm.js +58 -38
- package/dist/rerankers/types.d.ts +1 -1
- package/dist/salience.js +1 -1
- package/dist/scheduler.d.ts +1 -0
- package/dist/scheduler.js +26 -4
- package/dist/scope.js +4 -3
- package/dist/search/as-of.d.ts +10 -0
- package/dist/search/as-of.js +22 -0
- package/dist/search/bm25-search.d.ts +14 -0
- package/dist/search/bm25-search.js +43 -0
- package/dist/search/bm25.d.ts +15 -0
- package/dist/search/bm25.js +54 -0
- package/dist/search/boosts.d.ts +54 -0
- package/dist/search/boosts.js +94 -0
- package/dist/search/breakdown.d.ts +7 -0
- package/dist/search/breakdown.js +20 -0
- package/dist/search/explain.d.ts +25 -0
- package/dist/search/explain.js +31 -0
- package/dist/search/finalize.d.ts +8 -0
- package/dist/search/finalize.js +52 -0
- package/dist/search/fusion.d.ts +27 -0
- package/dist/search/fusion.js +42 -0
- package/dist/search/hybrid-score.d.ts +20 -0
- package/dist/search/hybrid-score.js +73 -0
- package/dist/search/hybrid.d.ts +46 -0
- package/dist/search/hybrid.js +64 -0
- package/dist/search/physics-search.d.ts +29 -0
- package/dist/search/physics-search.js +162 -0
- package/dist/search/rerank.d.ts +10 -0
- package/dist/search/rerank.js +72 -0
- package/dist/search/temporal.d.ts +15 -0
- package/dist/search/temporal.js +45 -0
- package/dist/search/types.d.ts +91 -0
- package/dist/search/types.js +2 -0
- package/dist/search/vector.d.ts +30 -0
- package/dist/search/vector.js +71 -0
- package/dist/secret-detect.d.ts +2 -0
- package/dist/secret-detect.js +2 -1
- package/dist/server/auth.d.ts +52 -0
- package/dist/server/auth.js +221 -0
- package/dist/server/client-ip.d.ts +25 -0
- package/dist/server/client-ip.js +92 -0
- package/dist/server/cursor.d.ts +23 -0
- package/dist/server/cursor.js +58 -0
- package/dist/server/lifecycle.d.ts +7 -0
- package/dist/server/lifecycle.js +29 -0
- package/dist/server/mcp-http.d.ts +5 -0
- package/dist/server/mcp-http.js +199 -0
- package/dist/server/request.d.ts +33 -0
- package/dist/server/request.js +103 -0
- package/dist/server/routes/admin.d.ts +9 -0
- package/dist/server/routes/admin.js +158 -0
- package/dist/server/routes/customer-notes.d.ts +7 -0
- package/dist/server/routes/customer-notes.js +112 -0
- package/dist/server/routes/decisions.d.ts +7 -0
- package/dist/server/routes/decisions.js +133 -0
- package/dist/server/routes/incidents.d.ts +7 -0
- package/dist/server/routes/incidents.js +126 -0
- package/dist/server/routes/memories.d.ts +10 -0
- package/dist/server/routes/memories.js +179 -0
- package/dist/server/routes/policies.d.ts +8 -0
- package/dist/server/routes/policies.js +151 -0
- package/dist/server/routes/predictions.d.ts +7 -0
- package/dist/server/routes/predictions.js +164 -0
- package/dist/server/routes/processes.d.ts +7 -0
- package/dist/server/routes/processes.js +161 -0
- package/dist/server/routes/project-briefs.d.ts +8 -0
- package/dist/server/routes/project-briefs.js +136 -0
- package/dist/server/routes/recall.d.ts +8 -0
- package/dist/server/routes/recall.js +340 -0
- package/dist/server/routes/skills.d.ts +8 -0
- package/dist/server/routes/skills.js +150 -0
- package/dist/server/types.d.ts +56 -0
- package/dist/server/types.js +2 -0
- package/dist/server/validation.d.ts +14 -0
- package/dist/server/validation.js +91 -0
- package/dist/server.d.ts +7 -61
- package/dist/server.js +69 -2362
- package/dist/session-digest.d.ts +1 -1
- package/dist/session-digest.js +9 -2
- package/dist/shared.d.ts +3 -1
- package/dist/shared.js +26 -22
- package/dist/skills.d.ts +3 -0
- package/dist/skills.js +7 -5
- package/dist/stdin.js +2 -2
- package/dist/store/audit-event.d.ts +19 -0
- package/dist/store/audit-event.js +33 -0
- package/dist/store/candidates.d.ts +42 -0
- package/dist/store/candidates.js +152 -0
- package/dist/store/conflicts.d.ts +44 -0
- package/dist/store/conflicts.js +444 -0
- package/dist/store/delete-and-batch.d.ts +63 -0
- package/dist/store/delete-and-batch.js +310 -0
- package/dist/store/entry-reads.d.ts +92 -0
- package/dist/store/entry-reads.js +255 -0
- package/dist/store/entry-row.d.ts +67 -0
- package/dist/store/entry-row.js +208 -0
- package/dist/store/entry-writes.d.ts +46 -0
- package/dist/store/entry-writes.js +148 -0
- package/dist/store/handoffs.d.ts +26 -0
- package/dist/store/handoffs.js +184 -0
- package/dist/store/index-and-stats.d.ts +52 -0
- package/dist/store/index-and-stats.js +214 -0
- package/dist/store/markdown.d.ts +10 -0
- package/dist/store/markdown.js +108 -0
- package/dist/store/mirrors.d.ts +49 -0
- package/dist/store/mirrors.js +312 -0
- package/dist/store/open.d.ts +15 -0
- package/dist/store/open.js +223 -0
- package/dist/store/rows.d.ts +178 -0
- package/dist/store/rows.js +158 -0
- package/dist/store/search-rows.d.ts +86 -0
- package/dist/store/search-rows.js +254 -0
- package/dist/store/sessions.d.ts +83 -0
- package/dist/store/sessions.js +272 -0
- package/dist/store/summaries.d.ts +94 -0
- package/dist/store/summaries.js +377 -0
- package/dist/store/tenant-lookup.d.ts +12 -0
- package/dist/store/tenant-lookup.js +16 -0
- package/dist/store-cards.js +2 -1
- package/dist/summary-dirty.d.ts +4 -0
- package/dist/summary-dirty.js +32 -0
- package/dist/support-bundle.js +4 -3
- package/dist/tenant.js +2 -2
- package/dist/tokenize.d.ts +2 -0
- package/dist/tokenize.js +16 -0
- package/dist/transcript-tail.d.ts +7 -0
- package/dist/transcript-tail.js +48 -0
- package/dist/vector-store.d.ts +27 -0
- package/dist/vector-store.js +210 -0
- package/dist/version.d.ts +2 -2
- package/dist/version.js +2 -2
- package/dist/working-memory.js +1 -1
- package/dist/yaml.js +36 -11
- package/dist-ui/assets/ibm-plex-mono-latin-400-normal-CvHOgSBP.woff +0 -0
- package/dist-ui/assets/ibm-plex-mono-latin-400-normal-DMJ8VG8y.woff2 +0 -0
- package/dist-ui/assets/ibm-plex-mono-latin-500-normal-CB9ihrfo.woff +0 -0
- package/dist-ui/assets/ibm-plex-mono-latin-500-normal-DSY6xOcd.woff2 +0 -0
- package/dist-ui/assets/ibm-plex-mono-latin-600-normal-BgSNZQsw.woff2 +0 -0
- package/dist-ui/assets/ibm-plex-mono-latin-600-normal-DWFSQ4vo.woff +0 -0
- package/dist-ui/assets/ibm-plex-sans-latin-400-normal-CDDApCn2.woff2 +0 -0
- package/dist-ui/assets/ibm-plex-sans-latin-400-normal-CYLoc0-x.woff +0 -0
- package/dist-ui/assets/ibm-plex-sans-latin-500-normal-6ng42L7E.woff2 +0 -0
- package/dist-ui/assets/ibm-plex-sans-latin-500-normal-BgVn5rGT.woff +0 -0
- package/dist-ui/assets/ibm-plex-sans-latin-600-normal-Cu4Hd6ag.woff +0 -0
- package/dist-ui/assets/ibm-plex-sans-latin-600-normal-CuJfVYMP.woff2 +0 -0
- package/dist-ui/assets/index-DPN7cP19.js +33 -0
- package/dist-ui/assets/index-dFloKRVr.css +1 -0
- package/dist-ui/index.html +3 -25
- 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/capture.d.ts +0 -155
- package/dist/capture.js +0 -1295
- package/dist/consolidate.d.ts +0 -58
- package/dist/consolidate.js +0 -1124
- package/dist/graph.d.ts +0 -245
- package/dist/hooks.d.ts +0 -208
- package/dist/hooks.js +0 -1076
- package/dist/importers.js +0 -900
- package/dist/predictions.js +0 -620
- package/dist/search.d.ts +0 -320
- package/dist/search.js +0 -970
- package/dist/store.d.ts +0 -776
- package/dist/store.js +0 -3473
- package/dist-ui/assets/d3-BiWEKnn4.js +0 -1
- package/dist-ui/assets/index-BhT8RvO6.js +0 -61
- package/dist-ui/assets/index-RoXXJ5dq.css +0 -1
- package/dist-ui/assets/three-BDgTxR1l.js +0 -4112
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
import { calculateStrength } from '../memory.js';
|
|
2
|
+
import { estimateTokens } from '../token-ledger.js';
|
|
3
|
+
import { evalNow, isRecallBoostAblated } from '../ablation.js';
|
|
4
|
+
import { embeddingModelRequiresReindex } from '../embeddings.js';
|
|
5
|
+
import { resolveEmbeddingProvider } from '../embedding-provider.js';
|
|
6
|
+
import { physicsScore as computePhysicsScores, computeMass } from '../physics.js';
|
|
7
|
+
import { DEFAULT_PHYSICS_CONFIG } from '../physics-config.js';
|
|
8
|
+
import { loadPhysicsState } from '../physics-state.js';
|
|
9
|
+
import { openHippoDb, closeHippoDb } from '../db.js';
|
|
10
|
+
import { compareScoredResults } from '../compare.js';
|
|
11
|
+
import { log } from '../log.js';
|
|
12
|
+
import { churnStaleFactor, summaryMultipliers, summaryScoring } from './boosts.js';
|
|
13
|
+
import { addDagFields, ageInDays } from './breakdown.js';
|
|
14
|
+
import { fitBudget } from './finalize.js';
|
|
15
|
+
import { hybridSearch } from './hybrid.js';
|
|
16
|
+
import { currentEntries } from './as-of.js';
|
|
17
|
+
import { vectorCandidatesOutside } from './vector.js';
|
|
18
|
+
/** Scores memories by gravity, momentum and cluster amplification; rows without physics state rank through hybridSearch. */
|
|
19
|
+
export async function physicsSearch(query, entries, options = {}) {
|
|
20
|
+
const now = options.now ?? evalNow(); // honors HIPPO_FAKE_NOW (eval-only; see ablation.ts)
|
|
21
|
+
const explain = options.explain ?? false;
|
|
22
|
+
const scoring = { now, explain, summary: summaryScoring(options) };
|
|
23
|
+
if (entries.length === 0 || !options.hippoRoot)
|
|
24
|
+
return [];
|
|
25
|
+
// memory_physics keeps only current positions and masses, so a past-dated query must rank without them.
|
|
26
|
+
if (options.asOf)
|
|
27
|
+
return hybridSearch(query, entries, options);
|
|
28
|
+
const root = options.hippoRoot;
|
|
29
|
+
const queryVector = await physicsQueryVector(query, root, options.queryEmbedding);
|
|
30
|
+
if (!queryVector)
|
|
31
|
+
return hybridSearch(query, entries, options);
|
|
32
|
+
const pool = currentEntries(withVectorCandidates(root, entries, queryVector, options.vectorCandidates), options);
|
|
33
|
+
const physicsMap = loadCandidateParticles(root, pool);
|
|
34
|
+
if (!physicsMap)
|
|
35
|
+
return hybridSearch(query, pool, options);
|
|
36
|
+
const pools = splitByParticle(pool, physicsMap, queryVector, now);
|
|
37
|
+
const config = options.physicsConfig ?? DEFAULT_PHYSICS_CONFIG;
|
|
38
|
+
const physicsResults = scorePhysicsPool(pools, queryVector, config, scoring);
|
|
39
|
+
const classicResults = pools.classic.length > 0
|
|
40
|
+
? await hybridSearch(query, pools.classic, { ...options, vectorCandidates: undefined, budget: Infinity, explain })
|
|
41
|
+
: [];
|
|
42
|
+
const merged = mergeScorePools(physicsResults, classicResults);
|
|
43
|
+
merged.sort(compareScoredResults);
|
|
44
|
+
return fitBudget(merged, options.budget ?? 4000, options.minResults ?? 1, options.cost);
|
|
45
|
+
}
|
|
46
|
+
/** The caller's vector, else the provider's; null sends the caller to hybridSearch. */
|
|
47
|
+
async function physicsQueryVector(query, root, given) {
|
|
48
|
+
if (given && given.length > 0)
|
|
49
|
+
return given;
|
|
50
|
+
// Physics scores against particle positions, not the stored vector index, so a pruned index must not block it.
|
|
51
|
+
try {
|
|
52
|
+
const provider = resolveEmbeddingProvider(root);
|
|
53
|
+
if (!provider.isAvailable() || embeddingModelRequiresReindex(root, provider.id))
|
|
54
|
+
return null;
|
|
55
|
+
const [vec] = await provider.embed([query], 'query');
|
|
56
|
+
return vec && vec.length > 0 ? vec : null;
|
|
57
|
+
}
|
|
58
|
+
catch (err) {
|
|
59
|
+
log.debug(`physics search: query embed failed, using hybrid: ${err instanceof Error ? err.message : String(err)}`);
|
|
60
|
+
return null;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
function withVectorCandidates(root, entries, queryVector, spec) {
|
|
64
|
+
if (!spec)
|
|
65
|
+
return entries;
|
|
66
|
+
try {
|
|
67
|
+
return [...entries, ...vectorCandidatesOutside(root, entries, queryVector, spec)];
|
|
68
|
+
}
|
|
69
|
+
catch (err) {
|
|
70
|
+
log.warn(`physics search ranked the lexical pool only; the vector lookup failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
71
|
+
return entries;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
/** Particles for the candidate rows only, so one tenant's search never reads every tenant's physics state. */
|
|
75
|
+
function loadCandidateParticles(root, pool) {
|
|
76
|
+
try {
|
|
77
|
+
const db = openHippoDb(root);
|
|
78
|
+
try {
|
|
79
|
+
return loadPhysicsState(db, pool.map((e) => e.id));
|
|
80
|
+
}
|
|
81
|
+
finally {
|
|
82
|
+
closeHippoDb(db);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
catch (err) {
|
|
86
|
+
log.debug(`physics search: state load failed, using hybrid: ${err instanceof Error ? err.message : String(err)}`);
|
|
87
|
+
return null;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
function splitByParticle(pool, physicsMap, queryVector, now) {
|
|
91
|
+
const pools = { entries: [], particles: [], classic: [] };
|
|
92
|
+
for (const entry of pool) {
|
|
93
|
+
const particle = physicsMap.get(entry.id);
|
|
94
|
+
const usable = particle
|
|
95
|
+
&& particle.position.length > 0
|
|
96
|
+
&& particle.position.length === queryVector.length
|
|
97
|
+
&& particle.velocity.length === queryVector.length;
|
|
98
|
+
if (!usable) {
|
|
99
|
+
pools.classic.push(entry);
|
|
100
|
+
continue;
|
|
101
|
+
}
|
|
102
|
+
pools.entries.push(entry);
|
|
103
|
+
// EVAL-ONLY ablation (see ablation.ts): persisted masses bake in recall history twice, so the flag recomputes mass live.
|
|
104
|
+
pools.particles.push(isRecallBoostAblated() ? { ...particle, mass: computeMass(calculateStrength(entry, now), entry.retrieval_count) } : particle);
|
|
105
|
+
}
|
|
106
|
+
return pools;
|
|
107
|
+
}
|
|
108
|
+
function scorePhysicsPool(pools, queryVector, config, scoring) {
|
|
109
|
+
if (pools.particles.length === 0)
|
|
110
|
+
return [];
|
|
111
|
+
const entryMap = new Map(pools.entries.map((e) => [e.id, e]));
|
|
112
|
+
// Content tie key: baseScore ties pick the cluster amplification set, so the order must hold across fresh ingests.
|
|
113
|
+
const scored = computePhysicsScores(pools.particles, queryVector, config, (id) => entryMap.get(id)?.content ?? id);
|
|
114
|
+
const results = [];
|
|
115
|
+
for (const s of scored) {
|
|
116
|
+
if (s.finalScore <= 0)
|
|
117
|
+
continue;
|
|
118
|
+
const entry = entryMap.get(s.memoryId);
|
|
119
|
+
if (!entry)
|
|
120
|
+
continue;
|
|
121
|
+
const summary = summaryMultipliers(entry, scoring.now, scoring.summary);
|
|
122
|
+
const churnStaleMultiplier = churnStaleFactor(entry);
|
|
123
|
+
const finalScore = s.finalScore * summary.deboost * summary.freshness * churnStaleMultiplier;
|
|
124
|
+
if (finalScore <= 0)
|
|
125
|
+
continue;
|
|
126
|
+
const result = { entry, score: finalScore, bm25: 0, cosine: s.baseScore, tokens: estimateTokens(entry.content) };
|
|
127
|
+
if (scoring.explain) {
|
|
128
|
+
result.breakdown = addDagFields(physicsBreakdown(entry, s.baseScore, finalScore, churnStaleMultiplier, scoring.now), entry, summary.deboost, summary.freshness);
|
|
129
|
+
}
|
|
130
|
+
results.push(result);
|
|
131
|
+
}
|
|
132
|
+
return results;
|
|
133
|
+
}
|
|
134
|
+
function physicsBreakdown(entry, baseScore, final, churnStaleMultiplier, now) {
|
|
135
|
+
return {
|
|
136
|
+
mode: 'physics',
|
|
137
|
+
normBm25: 0,
|
|
138
|
+
bm25Weight: 0,
|
|
139
|
+
embeddingWeight: 1,
|
|
140
|
+
cosine: baseScore,
|
|
141
|
+
base: baseScore,
|
|
142
|
+
strengthMultiplier: 1,
|
|
143
|
+
recencyMultiplier: 1,
|
|
144
|
+
decisionBoost: 1,
|
|
145
|
+
pathBoost: 1,
|
|
146
|
+
scopeBoost: 1,
|
|
147
|
+
sourceBump: 1,
|
|
148
|
+
outcomeBoost: 1,
|
|
149
|
+
churnStaleMultiplier,
|
|
150
|
+
matchedTerms: [],
|
|
151
|
+
final,
|
|
152
|
+
ageDays: ageInDays(entry, now),
|
|
153
|
+
};
|
|
154
|
+
}
|
|
155
|
+
/** Normalizes each pool to [0, 1] by its largest pre-churn score, then concatenates them. */
|
|
156
|
+
function mergeScorePools(poolA, poolB) {
|
|
157
|
+
const unpenalised = (r) => r.score / churnStaleFactor(r.entry);
|
|
158
|
+
const maxA = poolA.reduce((m, r) => Math.max(m, unpenalised(r)), 1e-9);
|
|
159
|
+
const maxB = poolB.reduce((m, r) => Math.max(m, unpenalised(r)), 1e-9);
|
|
160
|
+
return [...poolA.map((r) => ({ ...r, score: r.score / maxA })), ...poolB.map((r) => ({ ...r, score: r.score / maxB }))];
|
|
161
|
+
}
|
|
162
|
+
//# sourceMappingURL=physics-search.js.map
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { RerankerFn, RerankerOptions } from '../rerankers/types.js';
|
|
2
|
+
import type { SearchResult } from './types.js';
|
|
3
|
+
/** MMR: repeatedly picks the candidate maximising lambda * relevance - (1 - lambda) * max(cos(cand, picked)).
|
|
4
|
+
* Input must be sorted by relevance; strict `>` keeps ties first-wins, so a deterministic input stays deterministic. */
|
|
5
|
+
export declare function mmrRerank(scored: SearchResult[], embeddingIndex: Record<string, number[]>, lambda: number, explain: boolean): SearchResult[];
|
|
6
|
+
/** MMR over the top window only; the tail keeps its relevance order. */
|
|
7
|
+
export declare function applyMmrWindow(scored: SearchResult[], embeddingIndex: Record<string, number[]>, lambda: number, explain: boolean): SearchResult[];
|
|
8
|
+
/** Runs the reranker over the top `topK` (default 50) and stamps pre and post ranks; see src/rerankers/types.ts. */
|
|
9
|
+
export declare function applyReranker(query: string, ordered: SearchResult[], reranker: RerankerFn, rerankerOptions?: RerankerOptions): Promise<SearchResult[]>;
|
|
10
|
+
//# sourceMappingURL=rerank.d.ts.map
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { cosineSimilarity } from '../embeddings.js';
|
|
2
|
+
// MMR is O(K^2) cosine ops; candidates below this window never survive budget filtering anyway.
|
|
3
|
+
const MMR_CANDIDATE_CAP = 100;
|
|
4
|
+
/** MMR: repeatedly picks the candidate maximising lambda * relevance - (1 - lambda) * max(cos(cand, picked)).
|
|
5
|
+
* Input must be sorted by relevance; strict `>` keeps ties first-wins, so a deterministic input stays deterministic. */
|
|
6
|
+
export function mmrRerank(scored, embeddingIndex, lambda, explain) {
|
|
7
|
+
if (scored.length === 0)
|
|
8
|
+
return scored;
|
|
9
|
+
const maxScore = scored[0].score || 1;
|
|
10
|
+
const normScore = scored.map((r) => r.score / maxScore);
|
|
11
|
+
const vectors = scored.map((r) => embeddingIndex[r.entry.id] ?? null);
|
|
12
|
+
const picked = [];
|
|
13
|
+
const remaining = new Set(scored.map((_, i) => i));
|
|
14
|
+
while (remaining.size > 0) {
|
|
15
|
+
let bestIdx = -1;
|
|
16
|
+
let bestMmr = -Infinity;
|
|
17
|
+
for (const i of remaining) {
|
|
18
|
+
const maxSim = maxSimilarityToPicked(vectors[i], picked, embeddingIndex);
|
|
19
|
+
const mmr = lambda * normScore[i] - (1 - lambda) * maxSim;
|
|
20
|
+
if (mmr > bestMmr) {
|
|
21
|
+
bestMmr = mmr;
|
|
22
|
+
bestIdx = i;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
if (bestIdx === -1)
|
|
26
|
+
break;
|
|
27
|
+
remaining.delete(bestIdx);
|
|
28
|
+
picked.push(scored[bestIdx]);
|
|
29
|
+
}
|
|
30
|
+
if (explain)
|
|
31
|
+
attachMmrRanks(scored, picked);
|
|
32
|
+
return picked;
|
|
33
|
+
}
|
|
34
|
+
function maxSimilarityToPicked(vi, picked, embeddingIndex) {
|
|
35
|
+
let maxSim = 0;
|
|
36
|
+
if (!vi)
|
|
37
|
+
return maxSim;
|
|
38
|
+
for (const p of picked) {
|
|
39
|
+
const vp = embeddingIndex[p.entry.id];
|
|
40
|
+
if (!vp || vp.length !== vi.length)
|
|
41
|
+
continue;
|
|
42
|
+
const sim = Math.max(0, cosineSimilarity(vi, vp));
|
|
43
|
+
if (sim > maxSim)
|
|
44
|
+
maxSim = sim;
|
|
45
|
+
}
|
|
46
|
+
return maxSim;
|
|
47
|
+
}
|
|
48
|
+
function attachMmrRanks(scored, picked) {
|
|
49
|
+
const preRank = new Map();
|
|
50
|
+
scored.forEach((r, i) => preRank.set(r.entry.id, i + 1));
|
|
51
|
+
picked.forEach((r, i) => {
|
|
52
|
+
if (r.breakdown) {
|
|
53
|
+
r.breakdown.preMmrRank = preRank.get(r.entry.id);
|
|
54
|
+
r.breakdown.postMmrRank = i + 1;
|
|
55
|
+
}
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
/** MMR over the top window only; the tail keeps its relevance order. */
|
|
59
|
+
export function applyMmrWindow(scored, embeddingIndex, lambda, explain) {
|
|
60
|
+
const head = scored.slice(0, MMR_CANDIDATE_CAP);
|
|
61
|
+
const tail = scored.slice(MMR_CANDIDATE_CAP);
|
|
62
|
+
return [...mmrRerank(head, embeddingIndex, lambda, explain), ...tail];
|
|
63
|
+
}
|
|
64
|
+
/** Runs the reranker over the top `topK` (default 50) and stamps pre and post ranks; see src/rerankers/types.ts. */
|
|
65
|
+
export async function applyReranker(query, ordered, reranker, rerankerOptions) {
|
|
66
|
+
const topK = rerankerOptions?.topK ?? 50;
|
|
67
|
+
const head = ordered.slice(0, topK).map((r, i) => ({ ...r, preRerankRank: i + 1 }));
|
|
68
|
+
const tail = ordered.slice(topK);
|
|
69
|
+
const reranked = await reranker(query, head, { ...rerankerOptions, topK });
|
|
70
|
+
return [...reranked.map((r, i) => ({ ...r, postRerankRank: i + 1 })), ...tail];
|
|
71
|
+
}
|
|
72
|
+
//# sourceMappingURL=rerank.js.map
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { MemoryEntry } from '../memory.js';
|
|
2
|
+
export type TemporalDirection = 'recent' | 'oldest' | null;
|
|
3
|
+
export declare function detectTemporalDirection(query: string): TemporalDirection;
|
|
4
|
+
export interface TemporalRange {
|
|
5
|
+
minTime: number;
|
|
6
|
+
maxTime: number;
|
|
7
|
+
}
|
|
8
|
+
export declare function computeTemporalRange(entries: MemoryEntry[]): TemporalRange;
|
|
9
|
+
export declare function temporalBoost(entry: MemoryEntry, direction: TemporalDirection, range: TemporalRange): number;
|
|
10
|
+
/** The query's temporal cue and, only when there is one, the pool's time range. */
|
|
11
|
+
export declare function temporalContext(query: string, entries: MemoryEntry[]): {
|
|
12
|
+
direction: TemporalDirection;
|
|
13
|
+
range: TemporalRange;
|
|
14
|
+
};
|
|
15
|
+
//# sourceMappingURL=temporal.d.ts.map
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
const TEMPORAL_RECENT_CUES = new Set(['recently', 'latest', 'last', 'newest', 'current', 'today']);
|
|
2
|
+
const TEMPORAL_OLDEST_CUES = new Set(['first', 'earliest', 'oldest', 'initially', 'originally']);
|
|
3
|
+
export function detectTemporalDirection(query) {
|
|
4
|
+
const words = query.toLowerCase().split(/\s+/);
|
|
5
|
+
for (const w of words) {
|
|
6
|
+
if (TEMPORAL_RECENT_CUES.has(w))
|
|
7
|
+
return 'recent';
|
|
8
|
+
if (TEMPORAL_OLDEST_CUES.has(w))
|
|
9
|
+
return 'oldest';
|
|
10
|
+
}
|
|
11
|
+
return null;
|
|
12
|
+
}
|
|
13
|
+
export function computeTemporalRange(entries) {
|
|
14
|
+
let minTime = Infinity;
|
|
15
|
+
let maxTime = -Infinity;
|
|
16
|
+
for (const e of entries) {
|
|
17
|
+
const t = new Date(e.created).getTime();
|
|
18
|
+
if (t < minTime)
|
|
19
|
+
minTime = t;
|
|
20
|
+
if (t > maxTime)
|
|
21
|
+
maxTime = t;
|
|
22
|
+
}
|
|
23
|
+
return { minTime, maxTime };
|
|
24
|
+
}
|
|
25
|
+
export function temporalBoost(entry, direction, range) {
|
|
26
|
+
if (!direction)
|
|
27
|
+
return 1.0;
|
|
28
|
+
const span = range.maxTime - range.minTime;
|
|
29
|
+
if (span === 0)
|
|
30
|
+
return 1.0;
|
|
31
|
+
const entryTime = new Date(entry.created).getTime();
|
|
32
|
+
const normalized = (entryTime - range.minTime) / span;
|
|
33
|
+
if (direction === 'recent') {
|
|
34
|
+
return 0.8 + 0.4 * normalized;
|
|
35
|
+
}
|
|
36
|
+
else {
|
|
37
|
+
return 0.8 + 0.4 * (1 - normalized);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
/** The query's temporal cue and, only when there is one, the pool's time range. */
|
|
41
|
+
export function temporalContext(query, entries) {
|
|
42
|
+
const direction = detectTemporalDirection(query);
|
|
43
|
+
return { direction, range: direction ? computeTemporalRange(entries) : { minTime: 0, maxTime: 0 } };
|
|
44
|
+
}
|
|
45
|
+
//# sourceMappingURL=temporal.js.map
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import type { MemoryEntry } from '../memory.js';
|
|
2
|
+
/** One score mutation applied after candidate generation; allocated only under `recall --why` or `RecallOpts.explain`. */
|
|
3
|
+
export interface RerankStep {
|
|
4
|
+
/** One of: interference, value, utility, reranker, goal-boost, retrieval-count-downweight. */
|
|
5
|
+
stage: string;
|
|
6
|
+
/** The score multiplier applied at this stage, when the transform is a scalar multiply. */
|
|
7
|
+
multiplier?: number;
|
|
8
|
+
/** Score before this stage ran. */
|
|
9
|
+
scoreBefore: number;
|
|
10
|
+
/** Score after this stage ran. */
|
|
11
|
+
scoreAfter: number;
|
|
12
|
+
/** Optional human-readable detail (e.g. the matched goal tags). */
|
|
13
|
+
note?: string;
|
|
14
|
+
}
|
|
15
|
+
export interface SearchResult {
|
|
16
|
+
entry: MemoryEntry;
|
|
17
|
+
score: number;
|
|
18
|
+
bm25: number;
|
|
19
|
+
cosine: number;
|
|
20
|
+
tokens: number;
|
|
21
|
+
/** Populated when search is called with options.explain === true. */
|
|
22
|
+
breakdown?: ScoreBreakdown;
|
|
23
|
+
/** Ordered lifecycle re-ranking steps that mutated `score`; set only when `recall --why` asks for it. */
|
|
24
|
+
rerankTrace?: RerankStep[];
|
|
25
|
+
/** Set when a reranker ran; orders the results while `score` keeps the pre-rerank value. */
|
|
26
|
+
rerankScore?: number;
|
|
27
|
+
preRerankRank?: number;
|
|
28
|
+
postRerankRank?: number;
|
|
29
|
+
/** Set for results reached by graph traversal (`recall --hops N`): how the memory was reached from a lexical seed. */
|
|
30
|
+
graphVia?: {
|
|
31
|
+
hops: number;
|
|
32
|
+
relType: string;
|
|
33
|
+
direction: 'from' | 'to';
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
/** What a result costs against a budget: the tokens of the text it prints as. */
|
|
37
|
+
export type ResultCost = (r: SearchResult) => number;
|
|
38
|
+
export interface ScoreBreakdown {
|
|
39
|
+
/** `hybrid`: BM25 plus a cached doc vector; `hybrid-no-vec`: the query was embedded but this doc has no vector
|
|
40
|
+
* (run `hippo embed`); `bm25-only`: no usable embeddings; `physics`: scored by the physics engine. */
|
|
41
|
+
mode: 'hybrid' | 'hybrid-no-vec' | 'bm25-only' | 'physics';
|
|
42
|
+
/** BM25 score after normalization by max-in-corpus (0..1). */
|
|
43
|
+
normBm25: number;
|
|
44
|
+
/** Weight applied to BM25 in the hybrid blend. */
|
|
45
|
+
bm25Weight: number;
|
|
46
|
+
/** Weight applied to cosine in the hybrid blend. */
|
|
47
|
+
embeddingWeight: number;
|
|
48
|
+
/** Cosine similarity (0 when embeddings not used). */
|
|
49
|
+
cosine: number;
|
|
50
|
+
/** Blended base score before multipliers. */
|
|
51
|
+
base: number;
|
|
52
|
+
/** Multiplier from memory strength: 0.5 + 0.5*strength. */
|
|
53
|
+
strengthMultiplier: number;
|
|
54
|
+
/** Multiplier from age: 0.8 + 0.2*recencyBoost. */
|
|
55
|
+
recencyMultiplier: number;
|
|
56
|
+
/** 1.2 if tagged 'decision', else 1.0. */
|
|
57
|
+
decisionBoost: number;
|
|
58
|
+
/** 1.0..1.3 based on cwd path tag overlap. */
|
|
59
|
+
pathBoost: number;
|
|
60
|
+
/** 1.5 if scope matches, 0.5 if scope mismatches, 1.0 if neutral. */
|
|
61
|
+
scopeBoost: number;
|
|
62
|
+
/** Extra multiplier applied post-hybrid (e.g. 1.2x for local hits in a local+global merge); 1.0 otherwise. */
|
|
63
|
+
sourceBump: number;
|
|
64
|
+
/** Immediate outcome nudge, 1 + 0.15*tanh(pos - neg) clipped to [0.85, 1.15]; separate from the slow strength path. */
|
|
65
|
+
outcomeBoost: number;
|
|
66
|
+
/** CHURN_STALE_RANK_MULTIPLIER if tagged 'churn-stale', else 1.0. */
|
|
67
|
+
churnStaleMultiplier: number;
|
|
68
|
+
/** Pre-MMR rank (1-indexed). Only set when MMR re-ranking ran. */
|
|
69
|
+
preMmrRank?: number;
|
|
70
|
+
/** Post-MMR rank (1-indexed). Only set when MMR re-ranking ran. */
|
|
71
|
+
postMmrRank?: number;
|
|
72
|
+
/** Query terms that appeared verbatim in the doc. */
|
|
73
|
+
matchedTerms: string[];
|
|
74
|
+
/** Final composite score (= base * multipliers). */
|
|
75
|
+
final: number;
|
|
76
|
+
/** Age of the memory in whole days, at scoring time. */
|
|
77
|
+
ageDays: number;
|
|
78
|
+
/** entry.dag_level (0=raw, 1=extracted, 2=topic, 3=entity). */
|
|
79
|
+
dagLevel?: number;
|
|
80
|
+
/** descendant_count column, refreshed by the DAG rebuild. */
|
|
81
|
+
descendantCount?: number;
|
|
82
|
+
/** last_rebuilt_at ISO; null if never rebuilt. Summaries only. */
|
|
83
|
+
lastRebuiltAt?: string | null;
|
|
84
|
+
/** Cumulative rebuild_count. Summaries only. */
|
|
85
|
+
rebuildCount?: number;
|
|
86
|
+
/** Deboost applied (1.0 for non-summaries; default 0.85 for summaries). */
|
|
87
|
+
summaryDeboost?: number;
|
|
88
|
+
/** 1.05 if a summary was rebuilt within 7 days; 1.0 otherwise. */
|
|
89
|
+
summaryFreshnessBoost?: number;
|
|
90
|
+
}
|
|
91
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import type { MemoryEntry } from '../memory.js';
|
|
2
|
+
import { type VectorCandidateSpec } from '../store/search-rows.js';
|
|
3
|
+
import { type CurrentnessOptions } from './as-of.js';
|
|
4
|
+
/** hybridSearch's vector arm: which rows it may add, plus the caller's JS admission rules (exact private regex, entry filters). */
|
|
5
|
+
export type HybridVectorCandidates = VectorCandidateSpec & {
|
|
6
|
+
admit?: (entry: MemoryEntry) => boolean;
|
|
7
|
+
};
|
|
8
|
+
/** What the vector arm produced; fields fill in step by step, so a late failure keeps the rows already added. */
|
|
9
|
+
export interface VectorArm {
|
|
10
|
+
entries: MemoryEntry[];
|
|
11
|
+
addedRows: boolean;
|
|
12
|
+
useEmbeddings: boolean;
|
|
13
|
+
embeddingIndex: Record<string, number[]>;
|
|
14
|
+
queryVector: number[];
|
|
15
|
+
}
|
|
16
|
+
export interface VectorArmOptions extends CurrentnessOptions {
|
|
17
|
+
hippoRoot?: string;
|
|
18
|
+
vectorCandidates?: HybridVectorCandidates;
|
|
19
|
+
}
|
|
20
|
+
/** The nearest admitted rows not already in `entries`. */
|
|
21
|
+
export declare function vectorCandidatesOutside(hippoRoot: string, entries: readonly MemoryEntry[], queryVector: readonly number[], spec: HybridVectorCandidates): MemoryEntry[];
|
|
22
|
+
/** Embeds the query and loads stored vectors; any failure leaves BM25 to rank alone. */
|
|
23
|
+
export declare function resolveVectorArm(query: string, entries: MemoryEntry[], options: VectorArmOptions): Promise<VectorArm>;
|
|
24
|
+
export interface DenseScores {
|
|
25
|
+
cosine: number[];
|
|
26
|
+
/** Whether each entry had a cached doc vector to compare against. */
|
|
27
|
+
hadVec: boolean[];
|
|
28
|
+
}
|
|
29
|
+
export declare function denseScores(arm: VectorArm): DenseScores;
|
|
30
|
+
//# sourceMappingURL=vector.d.ts.map
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { cosineSimilarity, embeddingModelRequiresReindex, hasEmbeddings, loadStoredVectors } from '../embeddings.js';
|
|
2
|
+
import { loadVectorCandidateEntries } from '../store/search-rows.js';
|
|
3
|
+
import { resolveEmbeddingProvider } from '../embedding-provider.js';
|
|
4
|
+
import { log } from '../log.js';
|
|
5
|
+
import { redactSecretsStrict } from '../secret-detect.js';
|
|
6
|
+
import { currentEntries } from './as-of.js';
|
|
7
|
+
// Search runs on every hook prompt, so one line per reason per process says why vectors went unused without flooding stderr.
|
|
8
|
+
function warnBm25Fallback(reason, detail) {
|
|
9
|
+
log.once(`search.bm25-fallback.${reason}`, 'warn', `hybrid search fell back to BM25 only: ${redactSecretsStrict(detail)}`);
|
|
10
|
+
}
|
|
11
|
+
/** The nearest admitted rows not already in `entries`. */
|
|
12
|
+
export function vectorCandidatesOutside(hippoRoot, entries, queryVector, spec) {
|
|
13
|
+
const inPool = new Set(entries.map((e) => e.id));
|
|
14
|
+
return loadVectorCandidateEntries(hippoRoot, queryVector, spec).filter((e) => !inPool.has(e.id) && (spec.admit?.(e) ?? true));
|
|
15
|
+
}
|
|
16
|
+
/** Embeds the query and loads stored vectors; any failure leaves BM25 to rank alone. */
|
|
17
|
+
export async function resolveVectorArm(query, entries, options) {
|
|
18
|
+
const arm = { entries, addedRows: false, useEmbeddings: false, embeddingIndex: {}, queryVector: [] };
|
|
19
|
+
if (!options.hippoRoot)
|
|
20
|
+
return arm;
|
|
21
|
+
try {
|
|
22
|
+
await fillVectorArm(arm, query, options.hippoRoot, options);
|
|
23
|
+
}
|
|
24
|
+
catch (err) {
|
|
25
|
+
warnBm25Fallback('error', err instanceof Error ? err.message : String(err));
|
|
26
|
+
}
|
|
27
|
+
return arm;
|
|
28
|
+
}
|
|
29
|
+
async function fillVectorArm(arm, query, root, options) {
|
|
30
|
+
const provider = resolveEmbeddingProvider(root);
|
|
31
|
+
if (!provider.isAvailable())
|
|
32
|
+
return;
|
|
33
|
+
if (embeddingModelRequiresReindex(root, provider.id)) {
|
|
34
|
+
warnBm25Fallback('reindex', "the embedding index was built by another model or is being rebuilt; run 'hippo embed'");
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
const spec = options.vectorCandidates;
|
|
38
|
+
const vectors = loadStoredVectors(root, arm.entries.map((e) => e.id));
|
|
39
|
+
// Only spend a (possibly paid, off-box) query embedding when there is a stored vector this search can use.
|
|
40
|
+
if (vectors.size === 0 && !(spec !== undefined && hasEmbeddings(root)))
|
|
41
|
+
return;
|
|
42
|
+
const [vec] = await provider.embed([query], 'query');
|
|
43
|
+
arm.queryVector = vec ?? [];
|
|
44
|
+
if (arm.queryVector.length === 0) {
|
|
45
|
+
warnBm25Fallback('empty-query-vector', 'the embedding provider returned no vector for the query');
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
const added = spec ? vectorCandidatesOutside(root, arm.entries, arm.queryVector, spec) : [];
|
|
49
|
+
if (added.length > 0) {
|
|
50
|
+
arm.addedRows = true;
|
|
51
|
+
arm.entries = currentEntries([...arm.entries, ...added], options);
|
|
52
|
+
for (const [id, v] of loadStoredVectors(root, added.map((e) => e.id)))
|
|
53
|
+
vectors.set(id, v);
|
|
54
|
+
}
|
|
55
|
+
arm.embeddingIndex = Object.fromEntries(vectors);
|
|
56
|
+
arm.useEmbeddings = true;
|
|
57
|
+
}
|
|
58
|
+
export function denseScores(arm) {
|
|
59
|
+
const n = arm.entries.length;
|
|
60
|
+
const cosine = new Array(n).fill(0);
|
|
61
|
+
const hadVec = new Array(n).fill(false);
|
|
62
|
+
if (!arm.useEmbeddings)
|
|
63
|
+
return { cosine, hadVec };
|
|
64
|
+
for (let i = 0; i < n; i++) {
|
|
65
|
+
const cached = arm.embeddingIndex[arm.entries[i].id];
|
|
66
|
+
hadVec[i] = Boolean(cached && arm.queryVector.length > 0);
|
|
67
|
+
cosine[i] = hadVec[i] ? Math.max(0, cosineSimilarity(arm.queryVector, cached)) : 0;
|
|
68
|
+
}
|
|
69
|
+
return { cosine, hadVec };
|
|
70
|
+
}
|
|
71
|
+
//# sourceMappingURL=vector.js.map
|
package/dist/secret-detect.d.ts
CHANGED
|
@@ -23,6 +23,8 @@ export interface SecretDetection {
|
|
|
23
23
|
flagged: boolean;
|
|
24
24
|
reason: string | null;
|
|
25
25
|
}
|
|
26
|
+
/** Tags that flag a memory as secret, lower case; detectSecret folds a tag's case before the lookup. */
|
|
27
|
+
export declare const SECRET_TAGS: ReadonlySet<string>;
|
|
26
28
|
/**
|
|
27
29
|
* Scan a memory's tags + content for secret material.
|
|
28
30
|
* Pure and deterministic; no filesystem or store access.
|
package/dist/secret-detect.js
CHANGED
|
@@ -18,7 +18,8 @@
|
|
|
18
18
|
* Leaf module: keep free of imports from store/api/shared so all of them
|
|
19
19
|
* can import it without cycles.
|
|
20
20
|
*/
|
|
21
|
-
|
|
21
|
+
/** Tags that flag a memory as secret, lower case; detectSecret folds a tag's case before the lookup. */
|
|
22
|
+
export const SECRET_TAGS = new Set([
|
|
22
23
|
'secret', 'api-key', 'apikey', 'credential', 'credentials',
|
|
23
24
|
'token', 'password', 'private-key',
|
|
24
25
|
]);
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import type { IncomingMessage } from 'node:http';
|
|
2
|
+
import type { Context } from '../api.js';
|
|
3
|
+
import type { ServeOpts } from './types.js';
|
|
4
|
+
/**
|
|
5
|
+
* Recognise loopback remote addresses. Node reports IPv6-mapped IPv4 as
|
|
6
|
+
* '::ffff:127.0.0.1' on dual-stack sockets, so we accept that alongside
|
|
7
|
+
* the bare v4 and v6 loopbacks. Anything else is treated as remote.
|
|
8
|
+
*/
|
|
9
|
+
export declare function isLoopback(remoteAddress: string | undefined): boolean;
|
|
10
|
+
/**
|
|
11
|
+
* Read the Authorization header in a case-insensitive way and pull the
|
|
12
|
+
* bearer token out. Returns:
|
|
13
|
+
* - { kind: 'absent' } when no Authorization header is present
|
|
14
|
+
* - { kind: 'malformed' } when the header is set but not 'Bearer <token>'
|
|
15
|
+
* - { kind: 'bearer', token } when a non-empty bearer token is present
|
|
16
|
+
*
|
|
17
|
+
* The header NAME is case-insensitive (Node lowercases all header names on
|
|
18
|
+
* IncomingMessage.headers); the SCHEME ('Bearer') is also matched
|
|
19
|
+
* case-insensitively per RFC 6750.
|
|
20
|
+
*/
|
|
21
|
+
type AuthHeader = {
|
|
22
|
+
kind: 'absent';
|
|
23
|
+
} | {
|
|
24
|
+
kind: 'malformed';
|
|
25
|
+
} | {
|
|
26
|
+
kind: 'bearer';
|
|
27
|
+
token: string;
|
|
28
|
+
};
|
|
29
|
+
export declare function readAuthHeader(req: IncomingMessage): AuthHeader;
|
|
30
|
+
type AuthOpts = Pick<ServeOpts, 'hippoRoot' | 'authResolver' | 'authResolverTimeoutMs'>;
|
|
31
|
+
/** Add-ons call this to refuse a subject that would collide with a built-in actor. */
|
|
32
|
+
export declare function isReservedActor(subject: string): boolean;
|
|
33
|
+
/**
|
|
34
|
+
* Build a per-request Context from the Authorization header and remote
|
|
35
|
+
* address. Throws HttpError(401) for invalid / missing credentials. Opens
|
|
36
|
+
* the DB only for an API-key-shaped Bearer token (or any Bearer token when no
|
|
37
|
+
* auth resolver is registered), so loopback no-auth requests stay cheap.
|
|
38
|
+
*/
|
|
39
|
+
export declare function buildContextWithAuth(req: IncomingMessage, opts: AuthOpts): Promise<Context>;
|
|
40
|
+
/**
|
|
41
|
+
* Auth check for routes that do not need a tenant Context (e.g. MCP transport,
|
|
42
|
+
* which builds its own root resolution via findHippoRoot). Throws HttpError
|
|
43
|
+
* 401 the same way buildContextWithAuth does, but skips building the Context
|
|
44
|
+
* envelope. Loopback no-auth still passes.
|
|
45
|
+
*/
|
|
46
|
+
export declare function requireAuth(req: IncomingMessage, opts: AuthOpts): Promise<void>;
|
|
47
|
+
/** Never rejects: an outage (5xx) skips one heartbeat tick, only a definite 4xx denial closes the stream. */
|
|
48
|
+
export declare function heartbeatVerdict(req: IncomingMessage, opts: AuthOpts): Promise<'ok' | 'revoked' | 'unavailable'>;
|
|
49
|
+
/** Gate for any action beyond the caller's own tenant: a tenant's admin, by key or resolver, is never a host admin. */
|
|
50
|
+
export declare function assertCrossTenantAdmin(ctx: Context, what: string): void;
|
|
51
|
+
export {};
|
|
52
|
+
//# sourceMappingURL=auth.d.ts.map
|