hippo-memory 1.71.0 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (625) hide show
  1. package/README.md +7 -5
  2. package/dist/agent-memories/apply.d.ts +0 -11
  3. package/dist/agent-memories/apply.js +11 -26
  4. package/dist/agent-memories/claude-code.js +1 -1
  5. package/dist/agent-memories/codex.js +1 -1
  6. package/dist/agent-memories/copilot.d.ts +1 -3
  7. package/dist/agent-memories/copilot.js +1 -17
  8. package/dist/agent-memories/project-folds.d.ts +10 -0
  9. package/dist/agent-memories/project-folds.js +34 -0
  10. package/dist/agent-memories/sync.js +8 -6
  11. package/dist/api/assemble.js +3 -2
  12. package/dist/api/audit.d.ts +30 -2
  13. package/dist/api/audit.js +48 -7
  14. package/dist/api/auth.d.ts +11 -9
  15. package/dist/api/auth.js +39 -40
  16. package/dist/api/auto-sleep.d.ts +5 -2
  17. package/dist/api/auto-sleep.js +7 -3
  18. package/dist/api/availability.js +2 -3
  19. package/dist/api/cards.d.ts +42 -0
  20. package/dist/api/cards.js +52 -0
  21. package/dist/api/conflicts.d.ts +28 -0
  22. package/dist/api/conflicts.js +61 -0
  23. package/dist/api/context-auto.js +4 -2
  24. package/dist/api/context-render.js +4 -3
  25. package/dist/api/context-select.js +15 -29
  26. package/dist/api/context.js +29 -18
  27. package/dist/api/continuity.d.ts +47 -0
  28. package/dist/api/continuity.js +66 -0
  29. package/dist/api/dormant.js +4 -2
  30. package/dist/api/drill-down.js +3 -2
  31. package/dist/api/embeddings.d.ts +17 -0
  32. package/dist/api/embeddings.js +28 -0
  33. package/dist/api/error-reply.d.ts +8 -0
  34. package/dist/api/error-reply.js +21 -0
  35. package/dist/api/forget.d.ts +7 -3
  36. package/dist/api/forget.js +24 -14
  37. package/dist/api/goals.d.ts +1 -1
  38. package/dist/api/goals.js +5 -9
  39. package/dist/api/graph.js +2 -1
  40. package/dist/api/index.d.ts +4 -2
  41. package/dist/api/index.js +4 -2
  42. package/dist/api/instruction-detect.js +5 -1
  43. package/dist/api/learn.d.ts +5 -1
  44. package/dist/api/learn.js +71 -44
  45. package/dist/api/ledger-db.d.ts +2 -6
  46. package/dist/api/ledger-db.js +4 -36
  47. package/dist/api/memories.d.ts +21 -1
  48. package/dist/api/memories.js +51 -1
  49. package/dist/api/objects.d.ts +1 -1
  50. package/dist/api/objects.js +2 -1
  51. package/dist/api/outcome.d.ts +5 -5
  52. package/dist/api/outcome.js +17 -16
  53. package/dist/api/pilot-arm.d.ts +1 -11
  54. package/dist/api/pilot-arm.js +5 -45
  55. package/dist/api/predictions.d.ts +3 -1
  56. package/dist/api/predictions.js +8 -1
  57. package/dist/api/projects.d.ts +21 -0
  58. package/dist/api/projects.js +24 -0
  59. package/dist/api/promote.d.ts +3 -3
  60. package/dist/api/promote.js +26 -28
  61. package/dist/api/prompt-hook.d.ts +17 -2
  62. package/dist/api/prompt-hook.js +45 -4
  63. package/dist/api/quarantine.js +2 -1
  64. package/dist/api/recall-cli.d.ts +3 -0
  65. package/dist/api/recall-cli.js +13 -4
  66. package/dist/api/recall-core.js +10 -5
  67. package/dist/api/recall-pipeline.js +23 -24
  68. package/dist/api/recall-request.js +1 -1
  69. package/dist/api/recall-types.d.ts +3 -1
  70. package/dist/api/recall.d.ts +0 -3
  71. package/dist/api/recall.js +51 -73
  72. package/dist/api/remember-local.d.ts +5 -2
  73. package/dist/api/remember-local.js +15 -7
  74. package/dist/api/remember.d.ts +7 -3
  75. package/dist/api/remember.js +19 -16
  76. package/dist/api/session-end.d.ts +46 -0
  77. package/dist/api/session-end.js +131 -0
  78. package/dist/api/sleep-run.d.ts +1 -1
  79. package/dist/api/sleep-run.js +16 -11
  80. package/dist/api/sleep.js +4 -3
  81. package/dist/api/status.d.ts +24 -0
  82. package/dist/api/status.js +40 -0
  83. package/dist/api/store-init.d.ts +4 -0
  84. package/dist/api/store-init.js +9 -0
  85. package/dist/api/tokens.js +2 -2
  86. package/dist/api/types.d.ts +3 -7
  87. package/dist/api/types.js +6 -1
  88. package/dist/capture/caller-session.d.ts +0 -3
  89. package/dist/capture/caller-session.js +1 -12
  90. package/dist/capture/capture-error.d.ts +2 -2
  91. package/dist/capture/capture-error.js +23 -18
  92. package/dist/capture/codex-patch.js +3 -1
  93. package/dist/capture/command.js +36 -95
  94. package/dist/capture/compact.js +10 -5
  95. package/dist/capture/compaction-items-caller.js +11 -20
  96. package/dist/capture/compaction-record.d.ts +7 -93
  97. package/dist/capture/compaction-record.js +29 -426
  98. package/dist/capture/compaction-spool.d.ts +7 -7
  99. package/dist/capture/compaction-spool.js +60 -51
  100. package/dist/capture/copilot-transcript.d.ts +2 -1
  101. package/dist/capture/copilot-transcript.js +2 -1
  102. package/dist/capture/extract.d.ts +5 -2
  103. package/dist/capture/extract.js +4 -3
  104. package/dist/capture/failure-caller.d.ts +1 -1
  105. package/dist/capture/failure-caller.js +21 -16
  106. package/dist/capture/failure-reading.d.ts +2 -1
  107. package/dist/capture/failure-reading.js +7 -9
  108. package/dist/capture/pre-compact-caller.js +5 -4
  109. package/dist/capture/session-digest.js +4 -3
  110. package/dist/capture/session-end-caller.js +3 -2
  111. package/dist/capture/session-worker.js +22 -10
  112. package/dist/capture/transcript.d.ts +2 -1
  113. package/dist/capture/transcript.js +6 -3
  114. package/dist/capture/working-state.d.ts +4 -2
  115. package/dist/capture/working-state.js +4 -2
  116. package/dist/cli/audit-prune.d.ts +0 -25
  117. package/dist/cli/audit-prune.js +1 -27
  118. package/dist/cli/audit.js +20 -20
  119. package/dist/cli/auth.d.ts +1 -1
  120. package/dist/cli/auth.js +16 -17
  121. package/dist/cli/briefs.d.ts +1 -4
  122. package/dist/cli/briefs.js +37 -292
  123. package/dist/cli/card.js +41 -33
  124. package/dist/cli/client.d.ts +6 -2
  125. package/dist/cli/client.js +37 -21
  126. package/dist/cli/compact-resume-payload.js +1 -1
  127. package/dist/cli/context.d.ts +1 -1
  128. package/dist/cli/context.js +13 -13
  129. package/dist/cli/continuity.d.ts +1 -1
  130. package/dist/cli/continuity.js +36 -39
  131. package/dist/cli/curate.d.ts +2 -2
  132. package/dist/cli/curate.js +32 -36
  133. package/dist/cli/dag.d.ts +1 -1
  134. package/dist/cli/dag.js +23 -8
  135. package/dist/cli/decisions.d.ts +0 -2
  136. package/dist/cli/decisions.js +7 -285
  137. package/dist/cli/eval.d.ts +1 -1
  138. package/dist/cli/eval.js +12 -13
  139. package/dist/cli/explain.d.ts +1 -1
  140. package/dist/cli/explain.js +21 -25
  141. package/dist/cli/flag-values.js +16 -6
  142. package/dist/cli/flags.d.ts +0 -289
  143. package/dist/cli/flags.js +3 -138
  144. package/dist/cli/graph.d.ts +3 -0
  145. package/dist/cli/graph.js +83 -0
  146. package/dist/cli/hook-runtime.d.ts +6 -6
  147. package/dist/cli/hook-runtime.js +9 -36
  148. package/dist/cli/incidents.d.ts +3 -0
  149. package/dist/cli/incidents.js +112 -0
  150. package/dist/cli/init.d.ts +1 -1
  151. package/dist/cli/init.js +28 -19
  152. package/dist/cli/install-steps.d.ts +2 -1
  153. package/dist/cli/install-steps.js +11 -3
  154. package/dist/cli/last-sleep.js +1 -1
  155. package/dist/cli/maintenance.d.ts +3 -3
  156. package/dist/cli/maintenance.js +29 -30
  157. package/dist/cli/notes.d.ts +2 -0
  158. package/dist/cli/notes.js +41 -0
  159. package/dist/cli/object-verbs.d.ts +2 -2
  160. package/dist/cli/object-verbs.js +4 -4
  161. package/dist/cli/open-browser.d.ts +14 -0
  162. package/dist/cli/open-browser.js +26 -0
  163. package/dist/cli/playbooks.d.ts +3 -4
  164. package/dist/cli/playbooks.js +126 -290
  165. package/dist/cli/predictions.d.ts +3 -0
  166. package/dist/cli/predictions.js +174 -0
  167. package/dist/cli/print.js +2 -1
  168. package/dist/cli/projects.js +30 -22
  169. package/dist/cli/quality-repair-once.d.ts +1 -1
  170. package/dist/cli/quality-repair-once.js +6 -5
  171. package/dist/cli/recall.js +13 -7
  172. package/dist/cli/refine-llm.js +18 -17
  173. package/dist/cli/remember.js +17 -17
  174. package/dist/cli/scheduler.js +2 -1
  175. package/dist/cli/serve.js +11 -6
  176. package/dist/cli/session-hooks.d.ts +1 -5
  177. package/dist/cli/session-hooks.js +89 -168
  178. package/dist/cli/setup.d.ts +1 -1
  179. package/dist/cli/setup.js +17 -10
  180. package/dist/cli/shared.d.ts +2 -6
  181. package/dist/cli/shared.js +9 -29
  182. package/dist/cli/sleep-render.js +6 -3
  183. package/dist/cli/sleep.js +6 -37
  184. package/dist/cli/status.d.ts +3 -3
  185. package/dist/cli/status.js +32 -35
  186. package/dist/cli/transfer.d.ts +3 -3
  187. package/dist/cli/transfer.js +64 -43
  188. package/dist/cli/usage.d.ts +1 -80
  189. package/dist/cli/usage.js +2 -696
  190. package/dist/cli/verb-row.d.ts +34 -0
  191. package/dist/cli/verb-row.js +6 -0
  192. package/dist/cli/verbs/health.d.ts +27 -0
  193. package/dist/cli/verbs/health.js +234 -0
  194. package/dist/cli/verbs/memory.d.ts +16 -0
  195. package/dist/cli/verbs/memory.js +236 -0
  196. package/dist/cli/verbs/objects.d.ts +20 -0
  197. package/dist/cli/verbs/objects.js +257 -0
  198. package/dist/cli/verbs/sessions.d.ts +31 -0
  199. package/dist/cli/verbs/sessions.js +314 -0
  200. package/dist/cli/verbs.d.ts +81 -0
  201. package/dist/cli/verbs.js +7 -0
  202. package/dist/cli/versioned-verbs.d.ts +51 -0
  203. package/dist/cli/versioned-verbs.js +79 -0
  204. package/dist/cli.d.ts +1 -272
  205. package/dist/cli.js +24 -315
  206. package/dist/connectors/dlq.d.ts +39 -3
  207. package/dist/connectors/dlq.js +39 -4
  208. package/dist/connectors/github/backfill.js +12 -3
  209. package/dist/connectors/github/deletion.js +2 -1
  210. package/dist/connectors/github/dlq.js +31 -73
  211. package/dist/connectors/github/ingest.d.ts +2 -6
  212. package/dist/connectors/github/ingest.js +5 -29
  213. package/dist/connectors/github/tenant-routing.js +2 -1
  214. package/dist/connectors/github/webhook.d.ts +2 -1
  215. package/dist/connectors/github/webhook.js +35 -2
  216. package/dist/connectors/ingest.d.ts +10 -0
  217. package/dist/connectors/ingest.js +29 -0
  218. package/dist/connectors/slack/deletion.js +2 -1
  219. package/dist/connectors/slack/dlq.js +49 -71
  220. package/dist/connectors/slack/ingest.d.ts +2 -6
  221. package/dist/connectors/slack/ingest.js +4 -28
  222. package/dist/connectors/slack/tenant-routing.js +2 -1
  223. package/dist/connectors/slack/webhook.d.ts +2 -1
  224. package/dist/connectors/slack/webhook.js +2 -1
  225. package/dist/consolidate/conflicts.js +2 -2
  226. package/dist/consolidate/dag.js +29 -18
  227. package/dist/consolidate/dedupe.d.ts +7 -0
  228. package/dist/consolidate/dedupe.js +6 -4
  229. package/dist/consolidate/llm-passes.js +45 -19
  230. package/dist/consolidate/memory-value.js +3 -2
  231. package/dist/consolidate/merge.js +8 -8
  232. package/dist/consolidate/physics-pass.d.ts +6 -1
  233. package/dist/consolidate/physics-pass.js +26 -6
  234. package/dist/consolidate/replay.js +11 -4
  235. package/dist/consolidate/sleep.js +9 -6
  236. package/dist/consolidate/traces.js +5 -5
  237. package/dist/core/ablation.d.ts +10 -0
  238. package/dist/core/ablation.js +12 -0
  239. package/dist/{sharing/scope.d.ts → core/active-scope.d.ts} +1 -1
  240. package/dist/{sharing/scope.js → core/active-scope.js} +1 -1
  241. package/dist/core/ambient.d.ts +4 -0
  242. package/dist/core/ambient.js +39 -18
  243. package/dist/core/api-errors.d.ts +16 -0
  244. package/dist/core/api-errors.js +20 -0
  245. package/dist/core/card.js +3 -1
  246. package/dist/core/compaction-timing.d.ts +7 -0
  247. package/dist/core/compaction-timing.js +9 -0
  248. package/dist/core/config.d.ts +1 -1
  249. package/dist/core/config.js +22 -18
  250. package/dist/core/cosine.d.ts +3 -0
  251. package/dist/core/cosine.js +19 -0
  252. package/dist/{store → core}/markdown.d.ts +1 -1
  253. package/dist/{store → core}/markdown.js +4 -4
  254. package/dist/core/memory-audit.d.ts +17 -0
  255. package/dist/core/memory-audit.js +54 -0
  256. package/dist/core/memory.d.ts +14 -8
  257. package/dist/core/memory.js +35 -23
  258. package/dist/{consolidate → core}/merged-row.d.ts +1 -1
  259. package/dist/{consolidate → core}/merged-row.js +1 -1
  260. package/dist/core/physics.d.ts +3 -1
  261. package/dist/core/physics.js +23 -18
  262. package/dist/core/prediction.d.ts +3 -0
  263. package/dist/core/prediction.js +6 -0
  264. package/dist/core/project-identity.d.ts +3 -0
  265. package/dist/core/project-identity.js +12 -2
  266. package/dist/{store → core}/recall-scope.d.ts +1 -10
  267. package/dist/{store → core}/recall-scope.js +2 -19
  268. package/dist/core/search-types.d.ts +1 -1
  269. package/dist/dashboard/dashboard-actions.d.ts +2 -2
  270. package/dist/dashboard/dashboard-actions.js +5 -5
  271. package/dist/dashboard/dashboard-queries.js +2 -7
  272. package/dist/dashboard/dashboard-snapshot.js +1 -3
  273. package/dist/dashboard/dashboard.js +16 -5
  274. package/dist/db/busy.d.ts +2 -7
  275. package/dist/db/busy.js +21 -26
  276. package/dist/db/connect.d.ts +2 -2
  277. package/dist/db/connect.js +7 -7
  278. package/dist/db/index.d.ts +3 -3
  279. package/dist/db/index.js +3 -3
  280. package/dist/db/migrate.js +14 -7
  281. package/dist/db/migrations/index.d.ts +1 -1
  282. package/dist/db/migrations/index.js +3 -1
  283. package/dist/db/migrations/v11.js +1 -0
  284. package/dist/db/migrations/v14.js +1 -0
  285. package/dist/db/migrations/v55.d.ts +3 -0
  286. package/dist/db/migrations/v55.js +17 -0
  287. package/dist/db/open.d.ts +0 -2
  288. package/dist/db/open.js +6 -10
  289. package/dist/db/physics-state.d.ts +0 -4
  290. package/dist/db/physics-state.js +7 -33
  291. package/dist/db/request-stores.d.ts +1 -0
  292. package/dist/db/request-stores.js +2 -1
  293. package/dist/db/tables.d.ts +2 -0
  294. package/dist/db/tables.js +6 -2
  295. package/dist/db/vector-store.js +19 -5
  296. package/dist/db/wal-checkpointer.js +2 -1
  297. package/dist/doctor.d.ts +3 -0
  298. package/dist/doctor.js +18 -15
  299. package/dist/embeddings/local.d.ts +62 -0
  300. package/dist/embeddings/local.js +146 -0
  301. package/dist/{store/embeddings → embeddings}/provider.d.ts +5 -2
  302. package/dist/{store/embeddings → embeddings}/provider.js +19 -25
  303. package/dist/embeddings/transformers.d.ts +26 -0
  304. package/dist/embeddings/transformers.js +89 -0
  305. package/dist/entry/session-text.d.ts +1 -1
  306. package/dist/entry/session-text.js +1 -1
  307. package/dist/entry/store-kit.d.ts +37 -0
  308. package/dist/entry/store-kit.js +25 -0
  309. package/dist/entry/testing.d.ts +6 -0
  310. package/dist/entry/testing.js +7 -0
  311. package/dist/eval/eval-suite.js +17 -11
  312. package/dist/eval/eval.js +1 -1
  313. package/dist/eval/judgment.js +12 -5
  314. package/dist/graph/extract.js +3 -3
  315. package/dist/graph/recall.js +1 -1
  316. package/dist/graph/view.js +13 -5
  317. package/dist/graph/write.d.ts +1 -1
  318. package/dist/graph/write.js +9 -9
  319. package/dist/hooks/codex-session.js +3 -2
  320. package/dist/hooks/codex-wrapper.js +2 -1
  321. package/dist/hooks/json-hooks.js +10 -4
  322. package/dist/hooks/opencode.js +8 -5
  323. package/dist/hooks/shared.d.ts +0 -6
  324. package/dist/hooks/shared.js +4 -15
  325. package/dist/importers/core.js +4 -4
  326. package/dist/importers/sources.js +5 -4
  327. package/dist/importers/vault.d.ts +1 -1
  328. package/dist/importers/vault.js +25 -23
  329. package/dist/index.d.ts +5 -4
  330. package/dist/index.js +4 -3
  331. package/dist/learn/autolearn.d.ts +15 -3
  332. package/dist/learn/autolearn.js +38 -16
  333. package/dist/learn/churn-git.js +13 -4
  334. package/dist/learn/extract.d.ts +3 -2
  335. package/dist/learn/extract.js +7 -5
  336. package/dist/learn/forward-claim-detector.js +4 -2
  337. package/dist/learn/invalidation.d.ts +2 -1
  338. package/dist/learn/invalidation.js +18 -9
  339. package/dist/mcp/admin-tools.d.ts +2 -2
  340. package/dist/mcp/admin-tools.js +27 -48
  341. package/dist/mcp/format.js +3 -2
  342. package/dist/mcp/framing.d.ts +1 -0
  343. package/dist/mcp/framing.js +1 -1
  344. package/dist/mcp/memory-tools.d.ts +1 -1
  345. package/dist/mcp/memory-tools.js +8 -9
  346. package/dist/mcp/protocol.d.ts +11 -7
  347. package/dist/mcp/protocol.js +25 -12
  348. package/dist/mcp/recall-tools.js +12 -9
  349. package/dist/mcp/request.js +22 -20
  350. package/dist/mcp/stdio.js +37 -16
  351. package/dist/mcp/tool-args.js +2 -1
  352. package/dist/mcp/tools.js +44 -21
  353. package/dist/objects/customer-notes.d.ts +2 -2
  354. package/dist/objects/decisions.d.ts +2 -2
  355. package/dist/objects/descriptor.d.ts +1 -1
  356. package/dist/objects/incidents.d.ts +2 -2
  357. package/dist/objects/lifecycle.d.ts +1 -1
  358. package/dist/objects/lifecycle.js +2 -1
  359. package/dist/objects/policies.d.ts +2 -2
  360. package/dist/objects/policies.js +2 -1
  361. package/dist/objects/processes.d.ts +2 -2
  362. package/dist/objects/project-briefs.d.ts +2 -2
  363. package/dist/objects/project-briefs.js +2 -3
  364. package/dist/objects/skills.d.ts +2 -2
  365. package/dist/postinstall.js +1 -1
  366. package/dist/rerankers/clef.js +3 -6
  367. package/dist/rerankers/cross-encoder.d.ts +31 -2
  368. package/dist/rerankers/cross-encoder.js +71 -98
  369. package/dist/rerankers/index.js +5 -4
  370. package/dist/rerankers/jev.js +2 -4
  371. package/dist/rerankers/outage-warning.d.ts +3 -1
  372. package/dist/rerankers/outage-warning.js +5 -3
  373. package/dist/search/bm25-search.js +1 -1
  374. package/dist/search/boosts.js +1 -1
  375. package/dist/search/embed-memories.d.ts +12 -0
  376. package/dist/search/embed-memories.js +389 -0
  377. package/dist/search/engine.d.ts +8 -0
  378. package/dist/search/engine.js +10 -0
  379. package/dist/search/goal-boost.d.ts +1 -1
  380. package/dist/search/goal-boost.js +6 -3
  381. package/dist/search/hybrid.d.ts +9 -2
  382. package/dist/search/hybrid.js +9 -4
  383. package/dist/search/physics-search.d.ts +6 -3
  384. package/dist/search/physics-search.js +22 -15
  385. package/dist/search/rerank.js +1 -1
  386. package/dist/search/vector.d.ts +8 -6
  387. package/dist/search/vector.js +14 -17
  388. package/dist/server/auth.d.ts +3 -1
  389. package/dist/server/auth.js +24 -15
  390. package/dist/server/boot.d.ts +2 -1
  391. package/dist/server/boot.js +34 -84
  392. package/dist/server/client-ip.d.ts +9 -6
  393. package/dist/server/client-ip.js +36 -17
  394. package/dist/server/deadline.d.ts +0 -2
  395. package/dist/server/deadline.js +1 -7
  396. package/dist/server/defaults.d.ts +1 -0
  397. package/dist/server/defaults.js +1 -0
  398. package/dist/server/mcp-http.js +16 -11
  399. package/dist/server/request.js +7 -2
  400. package/dist/server/route-checks.d.ts +7 -0
  401. package/dist/server/route-checks.js +42 -0
  402. package/dist/server/route-table.d.ts +9 -8
  403. package/dist/server/route-table.js +127 -133
  404. package/dist/server/routes/admin.d.ts +8 -8
  405. package/dist/server/routes/admin.js +13 -21
  406. package/dist/server/routes/customer-notes.d.ts +6 -6
  407. package/dist/server/routes/customer-notes.js +1 -2
  408. package/dist/server/routes/decisions.d.ts +6 -6
  409. package/dist/server/routes/decisions.js +2 -4
  410. package/dist/server/routes/incidents.d.ts +6 -6
  411. package/dist/server/routes/incidents.js +2 -5
  412. package/dist/server/routes/memories.d.ts +9 -9
  413. package/dist/server/routes/memories.js +19 -40
  414. package/dist/server/routes/object-routes.d.ts +6 -6
  415. package/dist/server/routes/object-routes.js +4 -7
  416. package/dist/server/routes/policies.d.ts +7 -7
  417. package/dist/server/routes/policies.js +2 -4
  418. package/dist/server/routes/predictions.d.ts +6 -6
  419. package/dist/server/routes/predictions.js +9 -13
  420. package/dist/server/routes/processes.d.ts +6 -6
  421. package/dist/server/routes/processes.js +1 -2
  422. package/dist/server/routes/project-briefs.d.ts +7 -7
  423. package/dist/server/routes/project-briefs.js +2 -4
  424. package/dist/server/routes/recall.d.ts +5 -5
  425. package/dist/server/routes/recall.js +6 -10
  426. package/dist/server/routes/skills.d.ts +7 -7
  427. package/dist/server/routes/skills.js +2 -4
  428. package/dist/server/server-detect.d.ts +7 -1
  429. package/dist/server/server-detect.js +36 -11
  430. package/dist/server/sleep-child.js +26 -7
  431. package/dist/server/sleep-offload.d.ts +11 -5
  432. package/dist/server/sleep-offload.js +17 -11
  433. package/dist/server/tls.d.ts +7 -2
  434. package/dist/server/tls.js +17 -5
  435. package/dist/server/types.d.ts +29 -12
  436. package/dist/server/validation.d.ts +1 -2
  437. package/dist/server/validation.js +6 -11
  438. package/dist/server.d.ts +4 -40
  439. package/dist/server.js +3 -29
  440. package/dist/sharing/global-store.d.ts +4 -5
  441. package/dist/sharing/global-store.js +8 -13
  442. package/dist/sharing/global-sync.js +38 -45
  443. package/dist/sharing/project-merge.d.ts +7 -14
  444. package/dist/sharing/project-merge.js +57 -121
  445. package/dist/sharing/search-both.js +10 -3
  446. package/dist/sharing/share.d.ts +2 -0
  447. package/dist/sharing/share.js +39 -38
  448. package/dist/store/ambient.js +7 -7
  449. package/dist/store/audit-event.d.ts +1 -1
  450. package/dist/store/audit.d.ts +0 -16
  451. package/dist/store/audit.js +4 -55
  452. package/dist/store/auth.d.ts +4 -2
  453. package/dist/store/auth.js +7 -3
  454. package/dist/store/candidates.d.ts +3 -2
  455. package/dist/store/candidates.js +59 -30
  456. package/dist/store/capture-write.d.ts +17 -0
  457. package/dist/store/capture-write.js +35 -0
  458. package/dist/store/cards.js +6 -5
  459. package/dist/store/compaction-caller.d.ts +18 -0
  460. package/dist/store/compaction-caller.js +29 -0
  461. package/dist/store/compactions-record.d.ts +115 -0
  462. package/dist/store/compactions-record.js +418 -0
  463. package/dist/store/compactions.js +6 -4
  464. package/dist/store/conflicts.d.ts +7 -1
  465. package/dist/store/conflicts.js +13 -9
  466. package/dist/store/connectors/dlq.d.ts +10 -0
  467. package/dist/store/connectors/dlq.js +33 -0
  468. package/dist/store/connectors/event-log.d.ts +13 -0
  469. package/dist/store/connectors/event-log.js +24 -0
  470. package/dist/store/connectors/github.d.ts +7 -9
  471. package/dist/store/connectors/github.js +35 -60
  472. package/dist/store/connectors/slack.d.ts +2 -11
  473. package/dist/store/connectors/slack.js +24 -57
  474. package/dist/store/dashboard-reads.js +8 -6
  475. package/dist/store/delete-and-batch.d.ts +6 -0
  476. package/dist/store/delete-and-batch.js +40 -6
  477. package/dist/store/delivery-recorder.d.ts +12 -5
  478. package/dist/store/delivery-recorder.js +13 -11
  479. package/dist/store/descendant-page.js +8 -4
  480. package/dist/store/dormant.d.ts +1 -1
  481. package/dist/store/dormant.js +10 -4
  482. package/dist/store/embeddings/index.d.ts +2 -12
  483. package/dist/store/embeddings/index.js +5 -374
  484. package/dist/store/entry-reads.d.ts +35 -4
  485. package/dist/store/entry-reads.js +86 -19
  486. package/dist/store/entry-row.js +9 -2
  487. package/dist/store/entry-writes.d.ts +15 -12
  488. package/dist/store/entry-writes.js +54 -22
  489. package/dist/store/failure-log-at.d.ts +8 -0
  490. package/dist/store/failure-log-at.js +16 -0
  491. package/dist/store/failure-log.d.ts +2 -2
  492. package/dist/store/failure-log.js +5 -3
  493. package/dist/{trust → store}/gated-write.d.ts +3 -1
  494. package/dist/{trust → store}/gated-write.js +7 -5
  495. package/dist/store/goals.js +22 -19
  496. package/dist/store/graph-reads.js +9 -6
  497. package/dist/store/graph-view-rows.js +2 -1
  498. package/dist/store/graph-writes.d.ts +6 -6
  499. package/dist/store/graph-writes.js +48 -71
  500. package/dist/store/half-life.js +2 -2
  501. package/dist/store/handoffs.d.ts +10 -4
  502. package/dist/store/handoffs.js +10 -9
  503. package/dist/store/index-and-stats.js +2 -2
  504. package/dist/store/index.d.ts +2 -2
  505. package/dist/store/index.js +1 -1
  506. package/dist/store/key-writes.js +1 -1
  507. package/dist/store/ledger-turn.d.ts +9 -0
  508. package/dist/store/ledger-turn.js +38 -0
  509. package/dist/store/mirrors.js +19 -10
  510. package/dist/store/open.d.ts +2 -5
  511. package/dist/store/open.js +42 -54
  512. package/dist/store/pilot-arm.d.ts +12 -0
  513. package/dist/store/pilot-arm.js +42 -0
  514. package/dist/store/port.d.ts +68 -6
  515. package/dist/store/port.js +8 -0
  516. package/dist/store/predictions.d.ts +1 -2
  517. package/dist/store/predictions.js +3 -6
  518. package/dist/store/project-tags.d.ts +62 -0
  519. package/dist/store/project-tags.js +67 -0
  520. package/dist/store/quality-repair.js +1 -1
  521. package/dist/store/quarantine.js +2 -1
  522. package/dist/store/recall-trace.d.ts +2 -0
  523. package/dist/store/recall-trace.js +20 -3
  524. package/dist/store/rejected-values.js +16 -10
  525. package/dist/store/rejection-probe.d.ts +4 -0
  526. package/dist/store/rejection-probe.js +19 -0
  527. package/dist/store/rejection.d.ts +0 -17
  528. package/dist/store/rejection.js +1 -21
  529. package/dist/store/rows.js +2 -2
  530. package/dist/store/rule-sql.d.ts +11 -0
  531. package/dist/store/rule-sql.js +31 -6
  532. package/dist/store/search-rows.d.ts +5 -5
  533. package/dist/store/search-rows.js +18 -16
  534. package/dist/store/sessions.js +4 -2
  535. package/dist/store/set-aside.d.ts +14 -0
  536. package/dist/store/set-aside.js +23 -0
  537. package/dist/store/sqlite/busy.d.ts +3 -0
  538. package/dist/store/sqlite/busy.js +8 -0
  539. package/dist/store/sqlite/connector-events-group.js +4 -7
  540. package/dist/store/sqlite/connector-writes-group.js +6 -4
  541. package/dist/store/sqlite/entry-writes-group.d.ts +3 -3
  542. package/dist/store/sqlite/entry-writes-group.js +3 -3
  543. package/dist/store/sqlite/error-codec.js +4 -3
  544. package/dist/store/sqlite/executor.js +10 -4
  545. package/dist/store/sqlite/graph-reads-group.js +1 -1
  546. package/dist/store/sqlite/held-connection.d.ts +11 -0
  547. package/dist/store/sqlite/held-connection.js +41 -0
  548. package/dist/store/sqlite/last-recall-group.d.ts +13 -0
  549. package/dist/store/sqlite/last-recall-group.js +57 -0
  550. package/dist/store/sqlite/local.d.ts +0 -17
  551. package/dist/store/sqlite/local.js +0 -31
  552. package/dist/store/sqlite/maintenance-groups.d.ts +6 -0
  553. package/dist/store/sqlite/maintenance-groups.js +60 -0
  554. package/dist/store/sqlite/object-rows.d.ts +1 -1
  555. package/dist/store/sqlite/objects-group.d.ts +1 -1
  556. package/dist/store/sqlite/objects-group.js +15 -7
  557. package/dist/store/sqlite/store.d.ts +1 -8
  558. package/dist/store/sqlite/store.js +13 -22
  559. package/dist/store/summaries.d.ts +10 -3
  560. package/dist/store/summaries.js +54 -11
  561. package/dist/store/token-ledger-rows.js +3 -2
  562. package/dist/store/token-ledger.d.ts +0 -7
  563. package/dist/store/token-ledger.js +0 -35
  564. package/dist/store/vector-index.js +8 -4
  565. package/dist/support-bundle.js +2 -3
  566. package/dist/trust/reject-flow.js +2 -2
  567. package/dist/util/agent-homes.d.ts +15 -0
  568. package/dist/util/agent-homes.js +34 -0
  569. package/dist/util/anthropic-messages.d.ts +6 -1
  570. package/dist/util/anthropic-messages.js +26 -7
  571. package/dist/util/atomic-write.d.ts +5 -2
  572. package/dist/util/atomic-write.js +12 -8
  573. package/dist/util/chunked.d.ts +3 -0
  574. package/dist/util/chunked.js +10 -0
  575. package/dist/util/ellipsize.d.ts +3 -0
  576. package/dist/util/ellipsize.js +5 -0
  577. package/dist/util/env.d.ts +12 -2
  578. package/dist/util/env.js +12 -2
  579. package/dist/util/format.d.ts +5 -0
  580. package/dist/util/format.js +10 -0
  581. package/dist/util/hook-payload.d.ts +8 -0
  582. package/dist/util/hook-payload.js +37 -0
  583. package/dist/util/http-retry.d.ts +6 -0
  584. package/dist/util/http-retry.js +43 -5
  585. package/dist/util/http-util.d.ts +0 -8
  586. package/dist/util/http-util.js +10 -21
  587. package/dist/util/limits.d.ts +7 -0
  588. package/dist/util/limits.js +14 -0
  589. package/dist/util/log.d.ts +4 -0
  590. package/dist/util/log.js +9 -0
  591. package/dist/util/request-scope.d.ts +9 -3
  592. package/dist/util/request-scope.js +18 -9
  593. package/dist/util/secret-detect.js +6 -1
  594. package/dist/util/spawn-argv.d.ts +9 -0
  595. package/dist/util/spawn-argv.js +57 -0
  596. package/dist/util/sql.d.ts +3 -0
  597. package/dist/util/sql.js +6 -0
  598. package/dist/util/sqlite-blocked.d.ts +2 -0
  599. package/dist/util/sqlite-blocked.js +5 -0
  600. package/dist/util/stream-tee.d.ts +3 -0
  601. package/dist/util/stream-tee.js +35 -0
  602. package/dist/util/time.d.ts +4 -0
  603. package/dist/util/time.js +4 -0
  604. package/dist/util/vector-codec.d.ts +4 -0
  605. package/dist/util/vector-codec.js +15 -0
  606. package/dist/util/version.d.ts +1 -1
  607. package/dist/util/version.js +1 -1
  608. package/extensions/openclaw-plugin/openclaw.plugin.json +1 -1
  609. package/extensions/openclaw-plugin/package.json +1 -1
  610. package/openclaw.plugin.json +1 -1
  611. package/package.json +4 -2
  612. package/dist/api/on-store.d.ts +0 -16
  613. package/dist/api/on-store.js +0 -38
  614. package/dist/store/embeddings/local.d.ts +0 -15
  615. package/dist/store/embeddings/local.js +0 -175
  616. /package/dist/{cli → api}/correction-latency.d.ts +0 -0
  617. /package/dist/{cli → api}/correction-latency.js +0 -0
  618. /package/dist/{cli → api}/provenance-coverage.d.ts +0 -0
  619. /package/dist/{cli → api}/provenance-coverage.js +0 -0
  620. /package/dist/{store → core}/object-types.d.ts +0 -0
  621. /package/dist/{store → core}/object-types.js +0 -0
  622. /package/dist/{capture → util}/compaction-items.d.ts +0 -0
  623. /package/dist/{capture → util}/compaction-items.js +0 -0
  624. /package/dist/{store → util}/yaml.d.ts +0 -0
  625. /package/dist/{store → util}/yaml.js +0 -0
@@ -1,13 +1,14 @@
1
1
  import { createClefReranker } from './clef.js';
2
- import { crossEncoderReranker } from './cross-encoder.js';
2
+ import { createCrossEncoderReranker } from './cross-encoder.js';
3
3
  import { createJevReranker } from './jev.js';
4
4
  import { createLlmReranker } from './llm.js';
5
- // Each hosted reranker is built once here, so its outage warning lasts the process.
5
+ // Each reranker is built once here, so its outage warning lasts the process; jev falls back to the same cross-encoder, so one model loads.
6
+ const crossEncoder = createCrossEncoderReranker();
6
7
  const REGISTRY = {
7
8
  clef: createClefReranker('clef'),
8
9
  'clef-flash': createClefReranker('clef-flash'),
9
- 'cross-encoder': crossEncoderReranker,
10
- jev: createJevReranker(crossEncoderReranker),
10
+ 'cross-encoder': crossEncoder,
11
+ jev: createJevReranker(crossEncoder),
11
12
  llm: createLlmReranker(),
12
13
  };
13
14
  function isRegisteredRerankerName(name) {
@@ -1,3 +1,4 @@
1
+ import { truncateWithEllipsis } from '../util/ellipsize.js';
1
2
  import { envJevModel, envJevTimeoutMs, envTypesafeApiKey } from '../util/env.js';
2
3
  import { redactSecretsStrict } from '../util/secret-detect.js';
3
4
  import { createOutageWarning } from './outage-warning.js';
@@ -15,9 +16,6 @@ const TRUNCATE_CHARS = 1200;
15
16
  const DEFAULT_MODEL = 'jev-1.13.0';
16
17
  // The pool size the eval numbers were measured at.
17
18
  export const JEV_DEFAULT_TOP_K = 40;
18
- function truncate(s, n) {
19
- return s.length <= n ? s : `${s.slice(0, n)}...`;
20
- }
21
19
  // Number.isFinite rejects a string or null without coercing it, which the
22
20
  // declared type cannot promise about a third-party payload.
23
21
  function isProbability(v) {
@@ -40,7 +38,7 @@ function parseScores(body, n) {
40
38
  /** Redacted query plus numbered, redacted, truncated candidates. Shared with CLEF so both arms see matched input. */
41
39
  export function buildRelevanceRequest(query, head) {
42
40
  // Strict: this text leaves the machine, so Bearer, Basic-auth and JWT shapes go too.
43
- const lines = head.map((r, i) => `[${i + 1}] ${truncate(redactSecretsStrict(r.entry.content), TRUNCATE_CHARS)}`);
41
+ const lines = head.map((r, i) => `[${i + 1}] ${truncateWithEllipsis(redactSecretsStrict(r.entry.content), TRUNCATE_CHARS)}`);
44
42
  const state = `Query: ${redactSecretsStrict(query)}\n\nNumbered candidate memories from an AI coding agent's project store:\n\n${lines.join('\n\n')}`;
45
43
  const questions = {};
46
44
  for (let i = 1; i <= head.length; i++) {
@@ -1,5 +1,7 @@
1
+ import { type LogFields } from '../util/log.js';
1
2
  export interface OutageWarning {
2
- failed(reason: string): void;
3
+ /** `fields` carries the error's class and stack onto the warning line. */
4
+ failed(reason: string, fields?: LogFields): void;
3
5
  answered(): void;
4
6
  }
5
7
  /** Warns when `name` starts failing, at most every five minutes while it keeps failing,
@@ -1,6 +1,7 @@
1
1
  // One way for a reranker to report that it stopped working, without a line per recall.
2
+ import { MINUTE_MS } from '../util/time.js';
2
3
  import { log } from '../util/log.js';
3
- const REPEAT_MS = 5 * 60_000;
4
+ const REPEAT_MS = 5 * MINUTE_MS;
4
5
  /** Warns when `name` starts failing, at most every five minutes while it keeps failing,
5
6
  * and once when it answers again. `fallback` says what recall does meanwhile. */
6
7
  export function createOutageWarning(name, fallback) {
@@ -8,14 +9,15 @@ export function createOutageWarning(name, fallback) {
8
9
  let unreported = 0;
9
10
  let warnedAt = 0;
10
11
  return {
11
- failed(reason) {
12
+ failed(reason, fields) {
12
13
  failures++;
13
14
  if (failures > 1 && Date.now() - warnedAt < REPEAT_MS) {
14
15
  unreported++;
15
16
  return;
16
17
  }
17
18
  const skipped = unreported > 0 ? ` ${unreported} more calls failed since the last warning.` : '';
18
- log.warn(`${name} reranker unavailable (${reason}); ${fallback}.${skipped} While it fails this repeats at most every ${REPEAT_MS / 60_000} minutes.`);
19
+ const repeat = `While it fails this repeats at most every ${REPEAT_MS / MINUTE_MS} minutes.`;
20
+ log.warn(`${name} reranker unavailable (${reason}); ${fallback}.${skipped} ${repeat}`, fields);
19
21
  warnedAt = Date.now();
20
22
  unreported = 0;
21
23
  },
@@ -2,7 +2,7 @@ import { estimateTokens } from '../util/token-text.js';
2
2
  import { tokenize } from '../util/tokenize.js';
3
3
  import { evalNow } from '../core/ablation.js';
4
4
  import { extractPathTags } from './path-context.js';
5
- import { detectScope } from '../sharing/scope.js';
5
+ import { detectScope } from '../core/active-scope.js';
6
6
  import { compareScoredResults } from '../core/compare.js';
7
7
  import { bm25Score, buildCorpus, entryText } from './bm25.js';
8
8
  import { currentEntries } from './as-of.js';
@@ -2,7 +2,7 @@ import { envSummaryDeboost } from '../util/env.js';
2
2
  import { calculateStrength, CHURN_STALE_TAG } from '../core/memory.js';
3
3
  import { isOutcomeFastAblated, isRecencyAblated, evalRecencyScaleDays } from '../core/ablation.js';
4
4
  import { pathBoostMultiplier } from './path-context.js';
5
- import { scopeMatch } from '../sharing/scope.js';
5
+ import { scopeMatch } from '../core/active-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.
@@ -0,0 +1,12 @@
1
+ import type { MemoryEntry } from '../core/memory.js';
2
+ import { type EmbeddingProvider } from '../embeddings/provider.js';
3
+ import { type HippoStore } from '../store/port.js';
4
+ /** `off` is a provider that is disabled or not installed, which is a choice; `failed` is a memory that stays out of the vector index. */
5
+ export type EmbedOutcome = 'indexed' | 'off' | 'failed';
6
+ /** Embed a single memory entry and cache the result in the embedding index; with `store`, through its vectorWrites, never opening hippo.db.
7
+ * Resolves whatever fails, so a caller that fires and forgets stays safe; the outcome says whether the memory reached the index. */
8
+ export declare function embedMemory(hippoRoot: string, entry: MemoryEntry, model?: string, store?: HippoStore): Promise<EmbedOutcome>;
9
+ /** Embeds every entry with no cached vector, prunes vectors of deleted memories, and returns how many it embedded; `provider` defaults to the
10
+ * configured one. With `store`, every tenant's memories with no vector for the provider's model go through its `vectorWrites`, never hippo.db. */
11
+ export declare function embedAll(hippoRoot: string, model?: string, provider?: EmbeddingProvider, store?: HippoStore): Promise<number>;
12
+ //# sourceMappingURL=embed-memories.d.ts.map
@@ -0,0 +1,389 @@
1
+ // Embeds memories into the vector index: picks the configured provider, computes each vector and hands it to the store,
2
+ // which only keeps it (src/store/port.ts VectorWrites).
3
+ import * as fs from 'fs';
4
+ import * as path from 'path';
5
+ import { randomUUID } from 'crypto';
6
+ import { loadConfig } from '../core/config.js';
7
+ import { initializeParticle } from '../core/physics.js';
8
+ import { resolveEmbeddingProvider } from '../embeddings/provider.js';
9
+ import { embeddingIndexIdentity, embeddingInputText, embeddingModelRequiresReindex, indexNeedsRebuild, saveStoredEmbeddingModel, } from '../store/embeddings/index.js';
10
+ import { loadAllEntryIds, loadEntriesByIds } from '../store/entry-reads.js';
11
+ import { requireGroup, } from '../store/port.js';
12
+ import { indexedModel, pruneStoredVectors, replacesIndex, resetStoredParticles, saveEmbeddingIndex, saveStoredVectors, seedStoredParticle, } from '../store/vector-index.js';
13
+ import { chunked } from '../util/chunked.js';
14
+ import { envByName } from '../util/env.js';
15
+ import { errorCode, errorMessage, log } from '../util/log.js';
16
+ import { redactSecretsStrict } from '../util/secret-detect.js';
17
+ const STORE_PAGE = 64;
18
+ /** The rows for `ids`, a page at a time and in that order; an id deleted since it was listed is skipped. */
19
+ function* entryPages(hippoRoot, ids) {
20
+ for (const page of chunked(ids, STORE_PAGE)) {
21
+ const byId = new Map(loadEntriesByIds(hippoRoot, page).map((e) => [e.id, e]));
22
+ const entries = page.flatMap((id) => byId.get(id) ?? []);
23
+ if (entries.length > 0)
24
+ yield entries;
25
+ }
26
+ }
27
+ async function rebuildEmbeddingIndex(hippoRoot, ids, provider) {
28
+ const rebuilt = {};
29
+ for (const entries of entryPages(hippoRoot, ids)) {
30
+ // On a hard transport/auth failure provider.embed throws, so the caller aborts WITHOUT saving
31
+ // a partial index (atomic reindex: the old index + stored identity are preserved).
32
+ const vectors = await provider.embed(entries.map((e) => embeddingInputText(e)), 'passage');
33
+ for (let i = 0; i < entries.length; i++) {
34
+ const vec = vectors[i];
35
+ if (vec && vec.length > 0) {
36
+ rebuilt[entries[i].id] = vec;
37
+ }
38
+ else {
39
+ noteSkippedEmbedding(entries[i].id);
40
+ }
41
+ }
42
+ }
43
+ return rebuilt;
44
+ }
45
+ function resetPhysicsFromIndex(hippoRoot, ids, index) {
46
+ try {
47
+ resetStoredParticles(hippoRoot, ids, index);
48
+ }
49
+ catch (err) {
50
+ // Best effort: retrieval still falls back without physics state.
51
+ log.warn(`physics reset after reindex failed: ${errorMessage(err)}`);
52
+ }
53
+ }
54
+ /** A provider's `[]` row is a swallowed per-item failure; name the memory so the gap can be traced. */
55
+ function noteSkippedEmbedding(id) {
56
+ log.warn('memory not embedded; the next embed run retries it', { id });
57
+ }
58
+ const EMBED_LOCK_FILE = 'embeddings.lock';
59
+ const EMBED_LOCK_WAIT_MS = 10_000;
60
+ const EMBED_LOCK_OWNER = `${process.pid}:${randomUUID()}`;
61
+ // In-process mutex plus an O_EXCL "<pid>:<token>" lock file: our token is a lock we leaked; our PID
62
+ // with another token is a live worker thread, unless the lock predates this process (a reused PID).
63
+ let _embedWriteLock = Promise.resolve();
64
+ function embedLockHolderAlive(lockPath) {
65
+ let raw;
66
+ try {
67
+ raw = fs.readFileSync(lockPath, 'utf8');
68
+ }
69
+ catch (err) {
70
+ return !(err instanceof Error && 'code' in err && err.code === 'ENOENT');
71
+ }
72
+ const mtimeMs = fs.statSync(lockPath, { throwIfNoEntry: false })?.mtimeMs ?? 0;
73
+ const pid = Number(raw.split(':')[0]);
74
+ // An empty lock is a holder between create and write; after 5 s it is a crashed one.
75
+ if (!Number.isInteger(pid) || pid <= 0)
76
+ return Date.now() - mtimeMs < 5_000;
77
+ if (raw === EMBED_LOCK_OWNER)
78
+ return false;
79
+ if (pid === process.pid)
80
+ return mtimeMs >= Date.now() - process.uptime() * 1000;
81
+ try {
82
+ process.kill(pid, 0);
83
+ return true;
84
+ }
85
+ catch (err) {
86
+ return err instanceof Error && 'code' in err && err.code === 'EPERM';
87
+ }
88
+ }
89
+ // After the double-break race below the file can be another writer's lock, so remove only our own.
90
+ function releaseEmbedFileLock(lockPath) {
91
+ let raw;
92
+ try {
93
+ raw = fs.readFileSync(lockPath, 'utf8');
94
+ }
95
+ catch (err) {
96
+ if (err instanceof Error && 'code' in err && err.code === 'ENOENT')
97
+ return;
98
+ throw err;
99
+ }
100
+ if (raw === EMBED_LOCK_OWNER)
101
+ fs.rmSync(lockPath, { force: true });
102
+ }
103
+ async function acquireEmbedFileLock(hippoRoot) {
104
+ const lockPath = path.join(hippoRoot, EMBED_LOCK_FILE);
105
+ const deadline = Date.now() + EMBED_LOCK_WAIT_MS;
106
+ for (;;) {
107
+ try {
108
+ fs.writeFileSync(lockPath, EMBED_LOCK_OWNER, { flag: 'wx' });
109
+ return () => releaseEmbedFileLock(lockPath);
110
+ }
111
+ catch (err) {
112
+ if (!(err instanceof Error && 'code' in err && err.code === 'EEXIST'))
113
+ throw err;
114
+ }
115
+ // SHORTCUT: two waiters can both break one dead holder's lock; a vector lost that way is backfilled by the next `hippo embed`.
116
+ if (!embedLockHolderAlive(lockPath)) {
117
+ fs.rmSync(lockPath, { force: true });
118
+ continue;
119
+ }
120
+ if (Date.now() >= deadline)
121
+ throw new Error(`the embedding index is busy: another hippo process holds ${lockPath}`);
122
+ await new Promise((r) => setTimeout(r, 50));
123
+ }
124
+ }
125
+ async function withEmbedLock(hippoRoot, fn) {
126
+ return withProcessEmbedLock(async () => {
127
+ const release = await acquireEmbedFileLock(hippoRoot);
128
+ try {
129
+ return await fn();
130
+ }
131
+ finally {
132
+ release();
133
+ }
134
+ });
135
+ }
136
+ // A store keeps each write whole in its own transaction, and a lock file in hippoRoot would not reach a worker on another host.
137
+ async function withProcessEmbedLock(fn) {
138
+ let resolve;
139
+ const next = new Promise(r => { resolve = r; });
140
+ const prev = _embedWriteLock;
141
+ _embedWriteLock = next;
142
+ await prev;
143
+ try {
144
+ return await fn();
145
+ }
146
+ finally {
147
+ resolve();
148
+ }
149
+ }
150
+ // A bad key fails every write; one full warning per distinct failure tells the user, and a count of the repeats follows at most once per interval.
151
+ const EMBED_WARN_KEY_CAP = 64;
152
+ const EMBED_SUPPRESSED_SUMMARY_INTERVAL_MS = 60_000;
153
+ const embedFailureSeen = new Map();
154
+ function embedFailureKey(source, cause) {
155
+ const kind = errorCode(cause) || (cause instanceof Error ? cause.constructor.name : 'NonError');
156
+ return `${source}:${kind}`;
157
+ }
158
+ function warnEmbedFailureOnce(source, rawMessage, cause) {
159
+ const key = embedFailureKey(source, cause);
160
+ const now = Date.now();
161
+ const seen = embedFailureSeen.get(key);
162
+ if (seen) {
163
+ seen.suppressed += 1;
164
+ if (now - seen.lastNoticeAt >= EMBED_SUPPRESSED_SUMMARY_INTERVAL_MS) {
165
+ log.warn(`${seen.suppressed} more embedding errors from ${source} since the last notice; memories are still stored without embeddings.`);
166
+ seen.suppressed = 0;
167
+ seen.lastNoticeAt = now;
168
+ }
169
+ return;
170
+ }
171
+ // Oldest key out, so a full map still lets a new failure warn.
172
+ if (embedFailureSeen.size >= EMBED_WARN_KEY_CAP) {
173
+ for (const oldest of embedFailureSeen.keys()) {
174
+ embedFailureSeen.delete(oldest);
175
+ break;
176
+ }
177
+ }
178
+ embedFailureSeen.set(key, { lastNoticeAt: now, suppressed: 0 });
179
+ // Strict scrub: this line can land in a hook log file, and an API may echo the key back in its error body.
180
+ const message = redactSecretsStrict(rawMessage).replace(/\s+/g, ' ').replace(/\.+$/, '');
181
+ log.warn(`embedding failed (${source}): ${message}. Memories are stored without embeddings until this is fixed.`);
182
+ }
183
+ function vectorGroups(store) {
184
+ return [requireGroup(store, 'vectors'), requireGroup(store, 'vectorWrites')];
185
+ }
186
+ /** Writes one page's vectors, one writeVectors per tenant, and stops at the first refused write; `withParticles` seeds each memory's particle. */
187
+ async function writeVectorPage(writes, write, page, vectors, withParticles) {
188
+ const byTenant = new Map();
189
+ page.forEach((entry, i) => {
190
+ const vector = vectors[i];
191
+ if (!vector || vector.length === 0)
192
+ return noteSkippedEmbedding(entry.id);
193
+ const row = withParticles ? { memoryId: entry.id, vector, particle: initializeParticle(entry, vector) } : { memoryId: entry.id, vector };
194
+ byTenant.set(entry.tenant_id, [...(byTenant.get(entry.tenant_id) ?? []), row]);
195
+ });
196
+ let written = 0;
197
+ for (const [tenantId, rows] of byTenant) {
198
+ const result = await writes.writeVectors({ ...write, tenantId, rows });
199
+ if (result.modelMismatch)
200
+ return { written, modelMismatch: true };
201
+ written += result.written;
202
+ }
203
+ return { written, modelMismatch: false };
204
+ }
205
+ const OTHER_MODEL_INDEX = "the vector index was built by another embedding model; run 'hippo embed' to rebuild it";
206
+ /** Embeds every memory with no vector under `model`, page by page, so a provider failure keeps the pages written; a rebuild reseeds the particles it drops. */
207
+ async function backfillInStore(writes, provider, model, rebuild) {
208
+ let count = 0;
209
+ let afterId;
210
+ for (;;) {
211
+ const page = await writes.entriesWithoutVector({ model, afterId, limit: STORE_PAGE });
212
+ if (page.length === 0)
213
+ return count;
214
+ afterId = page[page.length - 1].id;
215
+ const vectors = await provider.embed(page.map((e) => embeddingInputText(e)), 'passage');
216
+ const result = await writeVectorPage(writes, { model, replaceIndex: rebuild }, page, vectors, rebuild);
217
+ // Another process rebuilt the index mid-run; every later page would be refused too, after paying the provider for it.
218
+ if (result.modelMismatch)
219
+ throw new Error(OTHER_MODEL_INDEX);
220
+ count += result.written;
221
+ }
222
+ }
223
+ /** embedAll on a store: a model change re-embeds every memory, and the first page written drops the old index. */
224
+ async function embedAllInStore(store, provider) {
225
+ const [reads, writes] = vectorGroups(store);
226
+ const rebuild = indexNeedsRebuild(indexedModel(await reads.embeddingIndexState()), provider.id);
227
+ return backfillInStore(writes, provider, embeddingIndexIdentity(provider.id), rebuild);
228
+ }
229
+ /** embedMemory on a store; like the hippo.db path it resolves whatever fails. Unlike it, it leaves a model change to embedAll, so a stale
230
+ * read here never drops another process's rebuild; the read only saves a paid embed call, as the write refuses another model itself. */
231
+ function embedMemoryInStore(store, provider, entry) {
232
+ return withProcessEmbedLock(async () => {
233
+ const [reads, writes] = vectorGroups(store);
234
+ const model = embeddingIndexIdentity(provider.id);
235
+ try {
236
+ const refused = replacesIndex(await reads.embeddingIndexState(), model)
237
+ || (await writeVectorPage(writes, { model, replaceIndex: false }, [entry], await provider.embed([embeddingInputText(entry)], 'passage'), true)).modelMismatch;
238
+ if (refused)
239
+ warnEmbedFailureOnce('index', OTHER_MODEL_INDEX);
240
+ return refused ? 'failed' : 'indexed';
241
+ }
242
+ catch (err) {
243
+ warnEmbedFailureOnce(provider.kind, errorMessage(err), err);
244
+ return 'failed';
245
+ }
246
+ }).catch((err) => {
247
+ log.warn(`skipped embedding ${entry.id} (${errorMessage(err)})`);
248
+ return 'failed';
249
+ });
250
+ }
251
+ const INLINE_REINDEX_MAX_ROWS = 256;
252
+ /** Embed a single memory entry and cache the result in the embedding index; with `store`, through its vectorWrites, never opening hippo.db.
253
+ * Resolves whatever fails, so a caller that fires and forgets stays safe; the outcome says whether the memory reached the index. */
254
+ export async function embedMemory(hippoRoot, entry, model, store) {
255
+ let provider;
256
+ try {
257
+ provider = resolveEmbeddingProvider(hippoRoot, { model });
258
+ }
259
+ catch (err) {
260
+ // Callers fire and forget, so this must resolve: a bad config warns once instead of rejecting.
261
+ warnEmbedFailureOnce('config', errorMessage(err), err);
262
+ return 'failed';
263
+ }
264
+ if (!provider.isAvailable())
265
+ return 'off';
266
+ if (store)
267
+ return embedMemoryInStore(store, provider, entry);
268
+ return withEmbedLock(hippoRoot, () => embedMemoryLocked(hippoRoot, provider, entry)).catch((err) => {
269
+ log.warn(`skipped embedding ${entry.id} (${errorMessage(err)}); run 'hippo embed' to backfill`);
270
+ return 'failed';
271
+ });
272
+ }
273
+ /** Best-effort: an embedding failure (API down, bad key, 5xx) must not reject the caller's write; the existing index is left as-is.
274
+ * Failures surface on the explicit `hippo embed` / `embedAll` path. */
275
+ async function embedMemoryLocked(hippoRoot, provider, entry) {
276
+ try {
277
+ const identity = provider.id;
278
+ if (embeddingModelRequiresReindex(hippoRoot, identity)) {
279
+ // A fire-and-forget write heals a small index inline; a large one is left to `hippo embed`, so no write holds the lock for a whole-store embed.
280
+ if (loadAllEntryIds(hippoRoot).length > INLINE_REINDEX_MAX_ROWS) {
281
+ warnEmbedFailureOnce('index', OTHER_MODEL_INDEX);
282
+ return 'failed';
283
+ }
284
+ await rebuildIndexForProvider(hippoRoot, provider);
285
+ return 'indexed';
286
+ }
287
+ const [vector] = await provider.embed([embeddingInputText(entry)], 'passage');
288
+ if (!vector || vector.length === 0)
289
+ return 'failed';
290
+ saveStoredVectors(hippoRoot, [[entry.id, vector]], embeddingIndexIdentity(identity));
291
+ saveStoredEmbeddingModel(hippoRoot, identity);
292
+ initializePhysicsIfMissing(hippoRoot, entry, vector);
293
+ return 'indexed';
294
+ }
295
+ catch (err) {
296
+ // Provider failure (API down / bad key). Best-effort: leave the index as-is, but say so once.
297
+ warnEmbedFailureOnce(provider.kind, errorMessage(err), err);
298
+ return 'failed';
299
+ }
300
+ }
301
+ // Every page is embedded before one transaction replaces the index, and the identity is saved only after that: a provider failure or a crash
302
+ // at any earlier point leaves the old identity, so embeddingModelRequiresReindex has the next run rebuild from the start.
303
+ async function rebuildIndexForProvider(hippoRoot, provider) {
304
+ const identity = provider.id;
305
+ // Host-wide rebuild: one embedding index per hippoRoot, keyed by tenant-scoped entry.id; per-tenant indices would be a larger architecture change.
306
+ const ids = loadAllEntryIds(hippoRoot);
307
+ const rebuiltIndex = await rebuildEmbeddingIndex(hippoRoot, ids, provider);
308
+ saveEmbeddingIndex(hippoRoot, rebuiltIndex, embeddingIndexIdentity(identity));
309
+ saveStoredEmbeddingModel(hippoRoot, identity);
310
+ resetPhysicsFromIndex(hippoRoot, ids, rebuiltIndex);
311
+ return Object.keys(rebuiltIndex).length;
312
+ }
313
+ function initializePhysicsIfMissing(hippoRoot, entry, vector) {
314
+ try {
315
+ seedStoredParticle(hippoRoot, entry, vector);
316
+ }
317
+ catch (err) {
318
+ // Physics init is best-effort and must not fail the embedding that just landed.
319
+ log.debug(`physics state not initialised for ${entry.id}: ${errorMessage(err)}`);
320
+ }
321
+ }
322
+ /** Throws when an unavailable provider is a misconfiguration rather than an intentional no-op. */
323
+ function throwIfProviderKeyMissing(hippoRoot, provider) {
324
+ // A configured API provider with a missing key is a misconfiguration: surface it so callers of the exported embedAll() learn nothing was written.
325
+ // Local-not-installed and an explicit enabled=false stay silent no-ops.
326
+ const cfg = loadConfig(hippoRoot).embeddings;
327
+ if (provider.kind !== 'local' &&
328
+ cfg.enabled !== false &&
329
+ provider.keyEnv &&
330
+ !envByName(provider.keyEnv)?.trim()) {
331
+ throw new Error(`Embedding provider '${provider.kind}' is configured but ${provider.keyEnv} is not set.`);
332
+ }
333
+ }
334
+ // Embeds entries without a cached vector in save-checkpointed chunks; a `[]` row means that item could not be embedded and is retried next run.
335
+ // On a hard provider failure mid-backfill the chunks already embedded are persisted (paid progress), then it stops and resumes next run.
336
+ async function backfillPending(hippoRoot, provider, pending, model) {
337
+ let count = 0;
338
+ // Initialized to `undefined` so it stays a plain `unknown` binding for the arbitrary caught value; falsy either way.
339
+ let backfillError = undefined;
340
+ for (const chunk of entryPages(hippoRoot, pending)) {
341
+ let vectors;
342
+ try {
343
+ vectors = await provider.embed(chunk.map((e) => embeddingInputText(e)), 'passage');
344
+ }
345
+ catch (err) {
346
+ // Preserve the chunks already saved this run, then surface the failure
347
+ // below so the explicit `hippo embed` path never reports a false success.
348
+ backfillError = err;
349
+ break;
350
+ }
351
+ const rows = [];
352
+ for (let j = 0; j < chunk.length; j++) {
353
+ const vec = vectors[j];
354
+ if (vec && vec.length > 0)
355
+ rows.push([chunk[j].id, vec]);
356
+ else
357
+ noteSkippedEmbedding(chunk[j].id);
358
+ }
359
+ count += saveStoredVectors(hippoRoot, rows, model);
360
+ }
361
+ return { count, backfillError };
362
+ }
363
+ /** Embeds every entry with no cached vector, prunes vectors of deleted memories, and returns how many it embedded; `provider` defaults to the
364
+ * configured one. With `store`, every tenant's memories with no vector for the provider's model go through its `vectorWrites`, never hippo.db. */
365
+ export async function embedAll(hippoRoot, model, provider = resolveEmbeddingProvider(hippoRoot, { model }), store) {
366
+ if (!provider.isAvailable()) {
367
+ throwIfProviderKeyMissing(hippoRoot, provider);
368
+ return 0;
369
+ }
370
+ if (store)
371
+ return withProcessEmbedLock(() => embedAllInStore(store, provider));
372
+ return withEmbedLock(hippoRoot, async () => {
373
+ const identity = provider.id;
374
+ if (embeddingModelRequiresReindex(hippoRoot, identity))
375
+ return rebuildIndexForProvider(hippoRoot, provider);
376
+ // Host-wide by design: embedAll backfills all tenants' entries into the per-host index; per-tenant filtering would produce partial indices and break
377
+ // recall.
378
+ const embedded = pruneStoredVectors(hippoRoot);
379
+ const pending = loadAllEntryIds(hippoRoot).filter((id) => !embedded.has(id));
380
+ const { count, backfillError } = await backfillPending(hippoRoot, provider, pending, embeddingIndexIdentity(identity));
381
+ saveStoredEmbeddingModel(hippoRoot, identity);
382
+ // Partial progress is now persisted; surface a hard backfill failure so the
383
+ // explicit embed path reports it (best-effort callers go via embedMemory).
384
+ if (backfillError)
385
+ throw backfillError;
386
+ return count;
387
+ });
388
+ }
389
+ //# sourceMappingURL=embed-memories.js.map
@@ -0,0 +1,8 @@
1
+ import type { MemoryEntry } from '../core/memory.js';
2
+ import type { PhysicsConfig } from '../core/physics-config.js';
3
+ import type { SearchResult } from '../core/search-types.js';
4
+ import { type HybridSearchOptions } from './hybrid.js';
5
+ import type { VectorSource } from './vector.js';
6
+ /** Physics scoring when `physics` holds its config, hybrid otherwise, both on the store `source` names; each caller keeps its own options. */
7
+ export declare function searchByEngine(source: VectorSource, query: string, pool: MemoryEntry[], physics: PhysicsConfig | null, options: Omit<HybridSearchOptions, 'hippoRoot' | 'store'>): Promise<SearchResult[]>;
8
+ //# sourceMappingURL=engine.d.ts.map
@@ -0,0 +1,10 @@
1
+ // The one search-engine choice every ranker over a candidate pool makes: recall's band, MCP's wide list, the CLI core and context.
2
+ import { hybridSearch } from './hybrid.js';
3
+ import { physicsSearchIn } from './physics-search.js';
4
+ /** Physics scoring when `physics` holds its config, hybrid otherwise, both on the store `source` names; each caller keeps its own options. */
5
+ export function searchByEngine(source, query, pool, physics, options) {
6
+ return physics
7
+ ? physicsSearchIn(source, query, pool, { ...options, physicsConfig: physics })
8
+ : hybridSearch(query, pool, { ...options, hippoRoot: source.root, store: source.store });
9
+ }
10
+ //# sourceMappingURL=engine.js.map
@@ -1,4 +1,4 @@
1
- import type { MemoryEntry } from '../core/memory.js';
1
+ import { type MemoryEntry } from '../core/memory.js';
2
2
  import type { RerankStep } from '../core/search-types.js';
3
3
  import type { ActiveGoals, GoalRecallLogRow } from '../store/goals.js';
4
4
  /** Options of {@link boostByGoals}. */
@@ -1,10 +1,13 @@
1
1
  // src/search/goal-boost.ts: the goal-stack boost over goals already read; it ranks rows and touches no store.
2
2
  import { compareScoresDesc } from '../core/compare.js';
3
+ import { DEFAULT_SCHEMA_FIT } from '../core/memory.js';
3
4
  const MAX_FINAL_MULTIPLIER = 3.0;
5
+ const FIRST_MATCH_BOOST = 2.0;
6
+ const EXTRA_MATCH_BOOST = 0.5;
4
7
  /** The capped boost for one row whose tags match `matches` active goals. */
5
8
  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);
9
+ // First match boosts by FIRST_MATCH_BOOST, each further one adds EXTRA_MATCH_BOOST, capped at MAX_FINAL_MULTIPLIER.
10
+ let multiplier = Math.min(FIRST_MATCH_BOOST + EXTRA_MATCH_BOOST * (matches.length - 1), MAX_FINAL_MULTIPLIER);
8
11
  // Compose per-policy multipliers per matched tag.
9
12
  for (const tag of matches) {
10
13
  const goal = goalsByTag.get(tag);
@@ -20,7 +23,7 @@ function goalBoostMultiplier(entry, tags, matches, goalsByTag, policiesByGoalId)
20
23
  multiplier *=
21
24
  1.0 +
22
25
  Math.max(0, policy.weightSchemaFit - 1.0) *
23
- (entry.schema_fit ?? 0.5);
26
+ (entry.schema_fit ?? DEFAULT_SCHEMA_FIT);
24
27
  }
25
28
  else if (policy.policyType === 'recency-first') {
26
29
  multiplier *= policy.weightRecency;
@@ -1,10 +1,10 @@
1
1
  import type { MemoryEntry } from '../core/memory.js';
2
2
  import type { RerankerFn, RerankerOptions } from '../rerankers/types.js';
3
3
  import { type BM25Corpus } from './bm25.js';
4
- import { type HybridVectorCandidates } from './vector.js';
4
+ import { type HybridVectorCandidates, type VectorSource } from './vector.js';
5
5
  import { type GraphStreamOptions } from './fusion.js';
6
6
  import { type ResultCost, type SearchResult } from '../core/search-types.js';
7
- import type { HippoStore } from '../store/index.js';
7
+ import { type HippoStore } from '../store/index.js';
8
8
  export interface HybridSearchOptions {
9
9
  budget?: number;
10
10
  now?: Date;
@@ -46,6 +46,13 @@ export interface HybridSearchOptions {
46
46
  /** The deadline a caller already started for this recall's query embedding; a fresh budget when unset. */
47
47
  queryEmbedDeadline?: AbortSignal;
48
48
  }
49
+ export declare const DEFAULT_EMBEDDING_WEIGHT = 0.6;
50
+ export declare const DEFAULT_MMR_LAMBDA = 0.7;
49
51
  /** BM25 blended with cosine similarity when stored vectors and a provider are available, BM25 * strength * recency otherwise. */
50
52
  export declare function hybridSearch(query: string, entries: MemoryEntry[], options?: HybridSearchOptions): Promise<SearchResult[]>;
53
+ /** hippo.db under `hippoRoot` when the caller passed no store: the default lives on this exported entry, never inside the vector arm. */
54
+ export declare function vectorSourceOf({ hippoRoot, store }: {
55
+ hippoRoot?: string;
56
+ store?: HippoStore;
57
+ }): VectorSource | undefined;
51
58
  //# sourceMappingURL=hybrid.d.ts.map
@@ -1,7 +1,7 @@
1
1
  import { tokenize } from '../util/tokenize.js';
2
2
  import { evalNow } from '../core/ablation.js';
3
3
  import { extractPathTags } from './path-context.js';
4
- import { detectScope } from '../sharing/scope.js';
4
+ import { detectScope } from '../core/active-scope.js';
5
5
  import { compareScoredResults } from '../core/compare.js';
6
6
  import { bm25Score, buildCorpus, entryText } from './bm25.js';
7
7
  import { currentEntries } from './as-of.js';
@@ -13,9 +13,10 @@ import { scoreHybridPool } from './hybrid-score.js';
13
13
  import { applyMmrWindow, applyReranker } from './rerank.js';
14
14
  import { dedupeExtracted, fitBudget, withDagChildren } from './finalize.js';
15
15
  import { DEFAULT_RECALL_BUDGET } from '../core/search-types.js';
16
+ import { sqliteStore } from '../store/index.js';
16
17
  // Share of the blended score that cosine takes, and the relevance side of the MMR relevance-versus-diversity trade.
17
- const DEFAULT_EMBEDDING_WEIGHT = 0.6;
18
- const DEFAULT_MMR_LAMBDA = 0.7;
18
+ export const DEFAULT_EMBEDDING_WEIGHT = 0.6;
19
+ export const DEFAULT_MMR_LAMBDA = 0.7;
19
20
  /** BM25 blended with cosine similarity when stored vectors and a provider are available, BM25 * strength * recency otherwise. */
20
21
  export async function hybridSearch(query, entries, options = {}) {
21
22
  const now = options.now ?? evalNow(); // honors HIPPO_FAKE_NOW (eval-only; see ablation.ts)
@@ -26,7 +27,7 @@ export async function hybridSearch(query, entries, options = {}) {
26
27
  const queryTerms = tokenize(query);
27
28
  if (queryTerms.length === 0)
28
29
  return [];
29
- const arm = await resolveVectorArm(query, pool, options);
30
+ const arm = await resolveVectorArm(query, pool, vectorSourceOf(options), options);
30
31
  // A prepared corpus covers the caller's entries only, so rows the vector arm added force a rebuild.
31
32
  const corpus = (arm.addedRows ? undefined : options.preparedCorpus) ?? buildCorpus(arm.entries.map(entryText));
32
33
  const bm25Scores = arm.entries.map((_, i) => bm25Score(corpus, i, queryTerms));
@@ -48,6 +49,10 @@ export async function hybridSearch(query, entries, options = {}) {
48
49
  const ordered = await orderHybrid(query, withDagChildren(dedupeExtracted(scored), arm.entries), arm, options);
49
50
  return fitBudget(ordered, options.budget ?? DEFAULT_RECALL_BUDGET, options.minResults ?? 1, options.cost);
50
51
  }
52
+ /** hippo.db under `hippoRoot` when the caller passed no store: the default lives on this exported entry, never inside the vector arm. */
53
+ export function vectorSourceOf({ hippoRoot, store }) {
54
+ return hippoRoot ? { root: hippoRoot, store: store ?? sqliteStore(hippoRoot) } : undefined;
55
+ }
51
56
  function hybridBoostContext(query, pool, now, options) {
52
57
  return {
53
58
  now,
@@ -1,7 +1,7 @@
1
1
  import { type MemoryEntry } from '../core/memory.js';
2
2
  import { type PhysicsConfig } from '../core/physics-config.js';
3
- import { type HippoStore } from '../store/index.js';
4
- import { type HybridVectorCandidates } from './vector.js';
3
+ import type { HippoStore } from '../store/index.js';
4
+ import { type HybridVectorCandidates, type VectorSource } from './vector.js';
5
5
  import { type ResultCost, type SearchResult } from '../core/search-types.js';
6
6
  export interface PhysicsSearchOptions {
7
7
  budget?: number;
@@ -27,6 +27,9 @@ export interface PhysicsSearchOptions {
27
27
  /** Where vectors and particles are read; hippo.db under `hippoRoot` when unset. */
28
28
  store?: HippoStore;
29
29
  }
30
- /** Scores memories by gravity, momentum and cluster amplification; rows without physics state rank through hybridSearch. */
30
+ /** Scores memories by gravity, momentum and cluster amplification; rows without physics state rank through hybridSearch.
31
+ * Reads hippo.db under `hippoRoot` when no store is passed. */
31
32
  export declare function physicsSearch(query: string, entries: MemoryEntry[], options?: PhysicsSearchOptions): Promise<SearchResult[]>;
33
+ /** physicsSearch on the store the caller names, so a caller holding its request's store never falls back to hippo.db. */
34
+ export declare function physicsSearchIn(source: VectorSource, query: string, entries: MemoryEntry[], options?: PhysicsSearchOptions): Promise<SearchResult[]>;
32
35
  //# sourceMappingURL=physics-search.d.ts.map