hippo-memory 1.59.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.
Files changed (596) hide show
  1. package/README.md +1 -1
  2. package/dist/ablation.js +9 -27
  3. package/dist/agent-memories/apply.js +4 -1
  4. package/dist/agent-memories/claude-code.js +1 -1
  5. package/dist/agent-memories/codex.js +1 -1
  6. package/dist/agent-memories/gemini.js +1 -1
  7. package/dist/agent-memories/legacy.js +1 -1
  8. package/dist/agent-memories/source.js +1 -1
  9. package/dist/agent-memories/sync.js +8 -3
  10. package/dist/ambient-store.d.ts +14 -0
  11. package/dist/ambient-store.js +90 -0
  12. package/dist/ambient.d.ts +23 -0
  13. package/dist/ambient.js +72 -50
  14. package/dist/api/assemble.d.ts +93 -0
  15. package/dist/api/assemble.js +152 -0
  16. package/dist/api/audit.d.ts +17 -0
  17. package/dist/api/audit.js +23 -0
  18. package/dist/api/auth.d.ts +79 -0
  19. package/dist/api/auth.js +178 -0
  20. package/dist/api/context-types.d.ts +105 -0
  21. package/dist/api/context-types.js +3 -0
  22. package/dist/api/context.d.ts +31 -0
  23. package/dist/api/context.js +705 -0
  24. package/dist/api/dormant.d.ts +30 -0
  25. package/dist/api/dormant.js +140 -0
  26. package/dist/api/drill-down.d.ts +84 -0
  27. package/dist/api/drill-down.js +123 -0
  28. package/dist/api/forget.d.ts +57 -0
  29. package/dist/api/forget.js +87 -0
  30. package/dist/api/goals.d.ts +18 -0
  31. package/dist/api/goals.js +33 -0
  32. package/dist/api/learn.d.ts +31 -0
  33. package/dist/api/learn.js +88 -0
  34. package/dist/api/outcome.d.ts +61 -0
  35. package/dist/api/outcome.js +66 -0
  36. package/dist/api/promote.d.ts +54 -0
  37. package/dist/api/promote.js +203 -0
  38. package/dist/api/quarantine.d.ts +24 -0
  39. package/dist/api/quarantine.js +121 -0
  40. package/dist/api/recall-types.d.ts +390 -0
  41. package/dist/api/recall-types.js +3 -0
  42. package/dist/api/recall.d.ts +36 -0
  43. package/dist/api/recall.js +634 -0
  44. package/dist/api/remember.d.ts +35 -0
  45. package/dist/api/remember.js +43 -0
  46. package/dist/api/sleep.d.ts +136 -0
  47. package/dist/api/sleep.js +271 -0
  48. package/dist/api/tokens.d.ts +26 -0
  49. package/dist/api/tokens.js +60 -0
  50. package/dist/api/types.d.ts +56 -0
  51. package/dist/api/types.js +38 -0
  52. package/dist/api.d.ts +20 -1260
  53. package/dist/api.js +25 -2711
  54. package/dist/audit.d.ts +3 -0
  55. package/dist/audit.js +7 -3
  56. package/dist/auth.d.ts +45 -4
  57. package/dist/auth.js +125 -48
  58. package/dist/autolearn.js +7 -4
  59. package/dist/capture/command.d.ts +33 -0
  60. package/dist/capture/command.js +264 -0
  61. package/dist/capture/compact.d.ts +44 -0
  62. package/dist/capture/compact.js +354 -0
  63. package/dist/capture/extract.d.ts +21 -0
  64. package/dist/capture/extract.js +464 -0
  65. package/dist/capture/transcript.d.ts +40 -0
  66. package/dist/capture/transcript.js +193 -0
  67. package/dist/capture-error.js +2 -1
  68. package/dist/churn-git.js +4 -2
  69. package/dist/cli/audit.d.ts +3 -0
  70. package/dist/cli/audit.js +159 -0
  71. package/dist/cli/auth.d.ts +2 -0
  72. package/dist/cli/auth.js +171 -0
  73. package/dist/cli/briefs.d.ts +4 -0
  74. package/dist/cli/briefs.js +435 -0
  75. package/dist/cli/card.d.ts +3 -0
  76. package/dist/cli/card.js +333 -0
  77. package/dist/cli/context.d.ts +15 -0
  78. package/dist/cli/context.js +366 -0
  79. package/dist/cli/continuity.d.ts +6 -0
  80. package/dist/cli/continuity.js +445 -0
  81. package/dist/cli/curate.d.ts +19 -0
  82. package/dist/cli/curate.js +555 -0
  83. package/dist/cli/dag.d.ts +5 -0
  84. package/dist/cli/dag.js +177 -0
  85. package/dist/cli/decisions.d.ts +4 -0
  86. package/dist/cli/decisions.js +528 -0
  87. package/dist/cli/eval.d.ts +5 -0
  88. package/dist/cli/eval.js +213 -0
  89. package/dist/cli/explain.d.ts +4 -0
  90. package/dist/cli/explain.js +150 -0
  91. package/dist/cli/goals.d.ts +2 -0
  92. package/dist/cli/goals.js +196 -0
  93. package/dist/cli/hook-blocks.d.ts +18 -0
  94. package/dist/cli/hook-blocks.js +233 -0
  95. package/dist/cli/init.d.ts +2 -0
  96. package/dist/cli/init.js +305 -0
  97. package/dist/cli/maintenance.d.ts +4 -0
  98. package/dist/cli/maintenance.js +179 -0
  99. package/dist/cli/playbooks.d.ts +4 -0
  100. package/dist/cli/playbooks.js +556 -0
  101. package/dist/cli/projects.js +1 -1
  102. package/dist/cli/recall.d.ts +7 -0
  103. package/dist/cli/recall.js +597 -0
  104. package/dist/cli/remember.d.ts +5 -0
  105. package/dist/cli/remember.js +442 -0
  106. package/dist/cli/serve.d.ts +5 -0
  107. package/dist/cli/serve.js +40 -0
  108. package/dist/cli/session-hooks.d.ts +29 -0
  109. package/dist/cli/session-hooks.js +637 -0
  110. package/dist/cli/setup.d.ts +4 -0
  111. package/dist/cli/setup.js +376 -0
  112. package/dist/cli/shared.d.ts +15 -19
  113. package/dist/cli/shared.js +50 -341
  114. package/dist/cli/slack.d.ts +2 -0
  115. package/dist/cli/slack.js +171 -0
  116. package/dist/cli/status.d.ts +18 -0
  117. package/dist/cli/status.js +400 -0
  118. package/dist/cli/transfer.d.ts +10 -0
  119. package/dist/cli/transfer.js +438 -0
  120. package/dist/cli/usage.d.ts +85 -0
  121. package/dist/cli/usage.js +741 -0
  122. package/dist/cli.d.ts +319 -13
  123. package/dist/cli.js +436 -8580
  124. package/dist/client.js +15 -8
  125. package/dist/compaction-record.js +12 -9
  126. package/dist/config.js +12 -11
  127. package/dist/connectors/github/backfill.js +94 -87
  128. package/dist/connectors/github/cli-impl.js +5 -3
  129. package/dist/connectors/github/dlq.js +67 -54
  130. package/dist/connectors/github/ingest.js +34 -35
  131. package/dist/connectors/github/tenant-routing.js +3 -2
  132. package/dist/connectors/github/webhook.js +135 -216
  133. package/dist/connectors/slack/dlq.js +49 -61
  134. package/dist/connectors/slack/ingest.js +55 -48
  135. package/dist/connectors/slack/tenant-routing.js +4 -3
  136. package/dist/connectors/slack/webhook.js +72 -74
  137. package/dist/consolidate/conflicts.d.ts +10 -0
  138. package/dist/consolidate/conflicts.js +178 -0
  139. package/dist/consolidate/decay.d.ts +12 -0
  140. package/dist/consolidate/decay.js +145 -0
  141. package/dist/consolidate/llm-passes.d.ts +3 -0
  142. package/dist/consolidate/llm-passes.js +141 -0
  143. package/dist/consolidate/merge.d.ts +7 -0
  144. package/dist/consolidate/merge.js +251 -0
  145. package/dist/consolidate/physics-pass.d.ts +3 -0
  146. package/dist/consolidate/physics-pass.js +60 -0
  147. package/dist/consolidate/run.d.ts +69 -0
  148. package/dist/consolidate/run.js +76 -0
  149. package/dist/consolidate/sleep.d.ts +18 -0
  150. package/dist/consolidate/sleep.js +209 -0
  151. package/dist/consolidate/traces.d.ts +4 -0
  152. package/dist/consolidate/traces.js +178 -0
  153. package/dist/context-auto.js +7 -11
  154. package/dist/context-render.d.ts +1 -1
  155. package/dist/context-render.js +1 -1
  156. package/dist/customer-notes.d.ts +3 -0
  157. package/dist/customer-notes.js +6 -4
  158. package/dist/dag.js +13 -12
  159. package/dist/dashboard-actions.d.ts +20 -0
  160. package/dist/dashboard-actions.js +88 -0
  161. package/dist/dashboard-params.d.ts +45 -0
  162. package/dist/dashboard-params.js +127 -0
  163. package/dist/dashboard-queries.d.ts +15 -0
  164. package/dist/dashboard-queries.js +355 -0
  165. package/dist/dashboard-snapshot.d.ts +138 -0
  166. package/dist/dashboard-snapshot.js +308 -0
  167. package/dist/dashboard-types.d.ts +163 -0
  168. package/dist/dashboard-types.js +3 -0
  169. package/dist/dashboard.d.ts +6 -7
  170. package/dist/dashboard.js +231 -203
  171. package/dist/db/busy.d.ts +5 -0
  172. package/dist/db/busy.js +24 -0
  173. package/dist/db/continuity.d.ts +5 -0
  174. package/dist/db/continuity.js +145 -0
  175. package/dist/db/meta.d.ts +8 -0
  176. package/dist/db/meta.js +35 -0
  177. package/dist/db/migrate.d.ts +9 -0
  178. package/dist/db/migrate.js +138 -0
  179. package/dist/db/migrations/index.d.ts +5 -0
  180. package/dist/db/migrations/index.js +109 -0
  181. package/dist/db/migrations/types.d.ts +14 -0
  182. package/dist/db/migrations/types.js +2 -0
  183. package/dist/db/migrations/v01.d.ts +3 -0
  184. package/dist/db/migrations/v01.js +38 -0
  185. package/dist/db/migrations/v02.d.ts +3 -0
  186. package/dist/db/migrations/v02.js +21 -0
  187. package/dist/db/migrations/v03.d.ts +3 -0
  188. package/dist/db/migrations/v03.js +22 -0
  189. package/dist/db/migrations/v04.d.ts +3 -0
  190. package/dist/db/migrations/v04.js +28 -0
  191. package/dist/db/migrations/v05.d.ts +3 -0
  192. package/dist/db/migrations/v05.js +21 -0
  193. package/dist/db/migrations/v06.d.ts +3 -0
  194. package/dist/db/migrations/v06.js +25 -0
  195. package/dist/db/migrations/v07.d.ts +3 -0
  196. package/dist/db/migrations/v07.js +13 -0
  197. package/dist/db/migrations/v08.d.ts +3 -0
  198. package/dist/db/migrations/v08.js +8 -0
  199. package/dist/db/migrations/v09.d.ts +3 -0
  200. package/dist/db/migrations/v09.js +13 -0
  201. package/dist/db/migrations/v10.d.ts +3 -0
  202. package/dist/db/migrations/v10.js +17 -0
  203. package/dist/db/migrations/v11.d.ts +3 -0
  204. package/dist/db/migrations/v11.js +15 -0
  205. package/dist/db/migrations/v12.d.ts +3 -0
  206. package/dist/db/migrations/v12.js +11 -0
  207. package/dist/db/migrations/v13.d.ts +3 -0
  208. package/dist/db/migrations/v13.js +15 -0
  209. package/dist/db/migrations/v14.d.ts +3 -0
  210. package/dist/db/migrations/v14.js +66 -0
  211. package/dist/db/migrations/v15.d.ts +3 -0
  212. package/dist/db/migrations/v15.js +42 -0
  213. package/dist/db/migrations/v16.d.ts +3 -0
  214. package/dist/db/migrations/v16.js +61 -0
  215. package/dist/db/migrations/v17.d.ts +3 -0
  216. package/dist/db/migrations/v17.js +46 -0
  217. package/dist/db/migrations/v18.d.ts +3 -0
  218. package/dist/db/migrations/v18.js +60 -0
  219. package/dist/db/migrations/v19.d.ts +3 -0
  220. package/dist/db/migrations/v19.js +28 -0
  221. package/dist/db/migrations/v20.d.ts +3 -0
  222. package/dist/db/migrations/v20.js +42 -0
  223. package/dist/db/migrations/v21.d.ts +3 -0
  224. package/dist/db/migrations/v21.js +16 -0
  225. package/dist/db/migrations/v22.d.ts +3 -0
  226. package/dist/db/migrations/v22.js +82 -0
  227. package/dist/db/migrations/v23.d.ts +3 -0
  228. package/dist/db/migrations/v23.js +48 -0
  229. package/dist/db/migrations/v24.d.ts +3 -0
  230. package/dist/db/migrations/v24.js +72 -0
  231. package/dist/db/migrations/v25.d.ts +3 -0
  232. package/dist/db/migrations/v25.js +46 -0
  233. package/dist/db/migrations/v26.d.ts +3 -0
  234. package/dist/db/migrations/v26.js +23 -0
  235. package/dist/db/migrations/v27.d.ts +3 -0
  236. package/dist/db/migrations/v27.js +57 -0
  237. package/dist/db/migrations/v28.d.ts +3 -0
  238. package/dist/db/migrations/v28.js +38 -0
  239. package/dist/db/migrations/v29.d.ts +3 -0
  240. package/dist/db/migrations/v29.js +78 -0
  241. package/dist/db/migrations/v30.d.ts +3 -0
  242. package/dist/db/migrations/v30.js +92 -0
  243. package/dist/db/migrations/v31.d.ts +3 -0
  244. package/dist/db/migrations/v31.js +74 -0
  245. package/dist/db/migrations/v32.d.ts +3 -0
  246. package/dist/db/migrations/v32.js +102 -0
  247. package/dist/db/migrations/v33.d.ts +3 -0
  248. package/dist/db/migrations/v33.js +104 -0
  249. package/dist/db/migrations/v34.d.ts +3 -0
  250. package/dist/db/migrations/v34.js +93 -0
  251. package/dist/db/migrations/v35.d.ts +3 -0
  252. package/dist/db/migrations/v35.js +98 -0
  253. package/dist/db/migrations/v36.d.ts +3 -0
  254. package/dist/db/migrations/v36.js +98 -0
  255. package/dist/db/migrations/v37.d.ts +3 -0
  256. package/dist/db/migrations/v37.js +219 -0
  257. package/dist/db/migrations/v38.d.ts +3 -0
  258. package/dist/db/migrations/v38.js +277 -0
  259. package/dist/db/migrations/v39.d.ts +3 -0
  260. package/dist/db/migrations/v39.js +59 -0
  261. package/dist/db/migrations/v40.d.ts +3 -0
  262. package/dist/db/migrations/v40.js +74 -0
  263. package/dist/db/migrations/v41.d.ts +3 -0
  264. package/dist/db/migrations/v41.js +43 -0
  265. package/dist/db/migrations/v42.d.ts +3 -0
  266. package/dist/db/migrations/v42.js +41 -0
  267. package/dist/db/migrations/v43.d.ts +3 -0
  268. package/dist/db/migrations/v43.js +67 -0
  269. package/dist/db/migrations/v44.d.ts +3 -0
  270. package/dist/db/migrations/v44.js +28 -0
  271. package/dist/db/migrations/v45.d.ts +3 -0
  272. package/dist/db/migrations/v45.js +30 -0
  273. package/dist/db/migrations/v46.d.ts +3 -0
  274. package/dist/db/migrations/v46.js +25 -0
  275. package/dist/db/migrations/v47.d.ts +3 -0
  276. package/dist/db/migrations/v47.js +17 -0
  277. package/dist/db/migrations/v48.d.ts +3 -0
  278. package/dist/db/migrations/v48.js +10 -0
  279. package/dist/db/migrations/v49.d.ts +3 -0
  280. package/dist/db/migrations/v49.js +31 -0
  281. package/dist/db/migrations/v50.d.ts +3 -0
  282. package/dist/db/migrations/v50.js +67 -0
  283. package/dist/db/migrations/v51.d.ts +3 -0
  284. package/dist/db/migrations/v51.js +14 -0
  285. package/dist/db/migrations/v52.d.ts +3 -0
  286. package/dist/db/migrations/v52.js +7 -0
  287. package/dist/db/open.d.ts +23 -0
  288. package/dist/db/open.js +146 -0
  289. package/dist/db/sqlite.d.ts +21 -0
  290. package/dist/db/sqlite.js +8 -0
  291. package/dist/db/tables.d.ts +7 -0
  292. package/dist/db/tables.js +38 -0
  293. package/dist/db.d.ts +6 -46
  294. package/dist/db.js +5 -3036
  295. package/dist/decisions.d.ts +4 -1
  296. package/dist/decisions.js +9 -7
  297. package/dist/dedupe.js +3 -2
  298. package/dist/delivery-recorder.js +5 -1
  299. package/dist/doctor.js +4 -3
  300. package/dist/dormant.js +1 -0
  301. package/dist/embedding-provider.d.ts +1 -1
  302. package/dist/embedding-provider.js +7 -5
  303. package/dist/embeddings.d.ts +9 -52
  304. package/dist/embeddings.js +47 -298
  305. package/dist/env.d.ts +75 -0
  306. package/dist/env.js +119 -0
  307. package/dist/eval-suite.js +1 -1
  308. package/dist/eval.js +2 -2
  309. package/dist/extract.js +5 -4
  310. package/dist/gated-write.js +3 -1
  311. package/dist/goals.d.ts +3 -1
  312. package/dist/goals.js +18 -0
  313. package/dist/graph/read.d.ts +73 -0
  314. package/dist/graph/read.js +325 -0
  315. package/dist/graph/rows.d.ts +45 -0
  316. package/dist/graph/rows.js +51 -0
  317. package/dist/graph/types.d.ts +83 -0
  318. package/dist/graph/types.js +11 -0
  319. package/dist/graph/write.d.ts +93 -0
  320. package/dist/{graph.js → graph/write.js} +8 -391
  321. package/dist/graph-extract.js +2 -1
  322. package/dist/graph-recall.d.ts +1 -1
  323. package/dist/graph-recall.js +2 -2
  324. package/dist/graph-stream.js +1 -1
  325. package/dist/graph-view.d.ts +1 -1
  326. package/dist/graph-view.js +1 -1
  327. package/dist/half-life-migration.d.ts +1 -1
  328. package/dist/half-life-migration.js +2 -1
  329. package/dist/handoff.js +3 -0
  330. package/dist/hooks/codex-session.d.ts +8 -0
  331. package/dist/hooks/codex-session.js +76 -0
  332. package/dist/hooks/codex-wrapper.d.ts +55 -0
  333. package/dist/hooks/codex-wrapper.js +288 -0
  334. package/dist/hooks/json-hooks.d.ts +63 -0
  335. package/dist/hooks/json-hooks.js +356 -0
  336. package/dist/hooks/opencode.d.ts +50 -0
  337. package/dist/hooks/opencode.js +202 -0
  338. package/dist/hooks/shared.d.ts +54 -0
  339. package/dist/hooks/shared.js +77 -0
  340. package/dist/http-retry.d.ts +2 -0
  341. package/dist/http-retry.js +4 -3
  342. package/dist/http-util.d.ts +3 -0
  343. package/dist/http-util.js +10 -0
  344. package/dist/{importers.d.ts → importers/core.d.ts} +13 -17
  345. package/dist/importers/core.js +141 -0
  346. package/dist/importers/markdown-parse.d.ts +41 -0
  347. package/dist/importers/markdown-parse.js +132 -0
  348. package/dist/importers/markdown.d.ts +3 -0
  349. package/dist/importers/markdown.js +92 -0
  350. package/dist/importers/sources.d.ts +7 -0
  351. package/dist/importers/sources.js +229 -0
  352. package/dist/importers/vault.d.ts +11 -0
  353. package/dist/importers/vault.js +352 -0
  354. package/dist/incidents.d.ts +3 -0
  355. package/dist/incidents.js +8 -5
  356. package/dist/index.d.ts +25 -6
  357. package/dist/index.js +23 -6
  358. package/dist/invalidation.js +2 -1
  359. package/dist/judgment.js +7 -3
  360. package/dist/keyset.d.ts +13 -0
  361. package/dist/keyset.js +8 -0
  362. package/dist/local-embedding.d.ts +13 -0
  363. package/dist/local-embedding.js +165 -0
  364. package/dist/log.d.ts +7 -0
  365. package/dist/log.js +19 -1
  366. package/dist/mcp/admin-tools.d.ts +8 -0
  367. package/dist/mcp/admin-tools.js +116 -0
  368. package/dist/mcp/format.d.ts +27 -0
  369. package/dist/mcp/format.js +135 -0
  370. package/dist/mcp/memory-tools.d.ts +5 -0
  371. package/dist/mcp/memory-tools.js +83 -0
  372. package/dist/mcp/protocol.d.ts +83 -0
  373. package/dist/mcp/protocol.js +55 -0
  374. package/dist/mcp/recall-tools.d.ts +6 -0
  375. package/dist/mcp/recall-tools.js +320 -0
  376. package/dist/mcp/request.d.ts +10 -0
  377. package/dist/mcp/request.js +163 -0
  378. package/dist/mcp/server.d.ts +4 -70
  379. package/dist/mcp/server.js +8 -1172
  380. package/dist/mcp/session-state.d.ts +11 -0
  381. package/dist/mcp/session-state.js +28 -0
  382. package/dist/mcp/stdio.d.ts +8 -0
  383. package/dist/mcp/stdio.js +79 -0
  384. package/dist/mcp/tools.d.ts +11 -0
  385. package/dist/mcp/tools.js +247 -0
  386. package/dist/memory.d.ts +8 -3
  387. package/dist/memory.js +27 -1
  388. package/dist/multihop.d.ts +1 -1
  389. package/dist/multihop.js +2 -1
  390. package/dist/owner-validation.js +2 -1
  391. package/dist/physics-state.js +10 -7
  392. package/dist/policies.d.ts +3 -0
  393. package/dist/policies.js +8 -6
  394. package/dist/postinstall.js +3 -2
  395. package/dist/predictions/planning-fallacy.d.ts +100 -0
  396. package/dist/predictions/planning-fallacy.js +190 -0
  397. package/dist/{predictions.d.ts → predictions/store.d.ts} +7 -102
  398. package/dist/predictions/store.js +434 -0
  399. package/dist/processes.d.ts +3 -0
  400. package/dist/processes.js +8 -5
  401. package/dist/project-briefs.d.ts +3 -0
  402. package/dist/project-briefs.js +7 -5
  403. package/dist/project-identity.d.ts +1 -1
  404. package/dist/project-identity.js +12 -6
  405. package/dist/project-merge.js +3 -1
  406. package/dist/quarantine.d.ts +2 -1
  407. package/dist/quarantine.js +8 -5
  408. package/dist/raw-archive-mirror-cleanup.js +2 -1
  409. package/dist/raw-archive.js +1 -1
  410. package/dist/recall-history.js +3 -2
  411. package/dist/recall-pipeline.d.ts +2 -2
  412. package/dist/recall-pipeline.js +16 -8
  413. package/dist/recall-scope.js +1 -1
  414. package/dist/recall-trace.d.ts +3 -3
  415. package/dist/recall-trace.js +10 -14
  416. package/dist/refine-llm.js +20 -11
  417. package/dist/reject-flow.js +6 -1
  418. package/dist/rerankers/clef.d.ts +2 -2
  419. package/dist/rerankers/clef.js +72 -30
  420. package/dist/rerankers/cross-encoder.js +6 -4
  421. package/dist/rerankers/jev.d.ts +4 -2
  422. package/dist/rerankers/jev.js +24 -19
  423. package/dist/rerankers/llm.d.ts +4 -2
  424. package/dist/rerankers/llm.js +61 -41
  425. package/dist/rerankers/types.d.ts +1 -1
  426. package/dist/salience.js +1 -1
  427. package/dist/same-text.d.ts +2 -0
  428. package/dist/same-text.js +4 -0
  429. package/dist/scheduler.d.ts +1 -0
  430. package/dist/scheduler.js +26 -3
  431. package/dist/scope.js +4 -3
  432. package/dist/search/as-of.d.ts +10 -0
  433. package/dist/search/as-of.js +22 -0
  434. package/dist/search/bm25-search.d.ts +14 -0
  435. package/dist/search/bm25-search.js +43 -0
  436. package/dist/search/bm25.d.ts +15 -0
  437. package/dist/search/bm25.js +54 -0
  438. package/dist/search/boosts.d.ts +54 -0
  439. package/dist/search/boosts.js +94 -0
  440. package/dist/search/breakdown.d.ts +7 -0
  441. package/dist/search/breakdown.js +20 -0
  442. package/dist/search/explain.d.ts +25 -0
  443. package/dist/search/explain.js +31 -0
  444. package/dist/search/finalize.d.ts +8 -0
  445. package/dist/search/finalize.js +52 -0
  446. package/dist/search/fusion.d.ts +27 -0
  447. package/dist/search/fusion.js +42 -0
  448. package/dist/search/hybrid-score.d.ts +20 -0
  449. package/dist/search/hybrid-score.js +73 -0
  450. package/dist/search/hybrid.d.ts +46 -0
  451. package/dist/search/hybrid.js +64 -0
  452. package/dist/search/physics-search.d.ts +29 -0
  453. package/dist/search/physics-search.js +162 -0
  454. package/dist/search/rerank.d.ts +10 -0
  455. package/dist/search/rerank.js +72 -0
  456. package/dist/search/temporal.d.ts +15 -0
  457. package/dist/search/temporal.js +45 -0
  458. package/dist/search/types.d.ts +91 -0
  459. package/dist/search/types.js +2 -0
  460. package/dist/search/vector.d.ts +30 -0
  461. package/dist/search/vector.js +71 -0
  462. package/dist/secret-detect.d.ts +2 -0
  463. package/dist/secret-detect.js +3 -1
  464. package/dist/server/auth.d.ts +52 -0
  465. package/dist/server/auth.js +221 -0
  466. package/dist/server/client-ip.d.ts +25 -0
  467. package/dist/server/client-ip.js +92 -0
  468. package/dist/server/cursor.d.ts +23 -0
  469. package/dist/server/cursor.js +58 -0
  470. package/dist/server/lifecycle.d.ts +7 -0
  471. package/dist/server/lifecycle.js +29 -0
  472. package/dist/server/mcp-http.d.ts +5 -0
  473. package/dist/server/mcp-http.js +199 -0
  474. package/dist/server/request.d.ts +33 -0
  475. package/dist/server/request.js +103 -0
  476. package/dist/server/routes/admin.d.ts +9 -0
  477. package/dist/server/routes/admin.js +158 -0
  478. package/dist/server/routes/customer-notes.d.ts +7 -0
  479. package/dist/server/routes/customer-notes.js +112 -0
  480. package/dist/server/routes/decisions.d.ts +7 -0
  481. package/dist/server/routes/decisions.js +133 -0
  482. package/dist/server/routes/incidents.d.ts +7 -0
  483. package/dist/server/routes/incidents.js +126 -0
  484. package/dist/server/routes/memories.d.ts +10 -0
  485. package/dist/server/routes/memories.js +179 -0
  486. package/dist/server/routes/policies.d.ts +8 -0
  487. package/dist/server/routes/policies.js +151 -0
  488. package/dist/server/routes/predictions.d.ts +7 -0
  489. package/dist/server/routes/predictions.js +164 -0
  490. package/dist/server/routes/processes.d.ts +7 -0
  491. package/dist/server/routes/processes.js +161 -0
  492. package/dist/server/routes/project-briefs.d.ts +8 -0
  493. package/dist/server/routes/project-briefs.js +136 -0
  494. package/dist/server/routes/recall.d.ts +8 -0
  495. package/dist/server/routes/recall.js +340 -0
  496. package/dist/server/routes/skills.d.ts +8 -0
  497. package/dist/server/routes/skills.js +150 -0
  498. package/dist/server/types.d.ts +56 -0
  499. package/dist/server/types.js +2 -0
  500. package/dist/server/validation.d.ts +14 -0
  501. package/dist/server/validation.js +91 -0
  502. package/dist/server.d.ts +7 -61
  503. package/dist/server.js +92 -2368
  504. package/dist/session-digest.d.ts +1 -1
  505. package/dist/session-digest.js +9 -2
  506. package/dist/shared.d.ts +3 -1
  507. package/dist/shared.js +46 -40
  508. package/dist/skills.d.ts +3 -0
  509. package/dist/skills.js +7 -5
  510. package/dist/stdin.js +3 -2
  511. package/dist/store/audit-event.d.ts +19 -0
  512. package/dist/store/audit-event.js +33 -0
  513. package/dist/store/candidates.d.ts +42 -0
  514. package/dist/store/candidates.js +152 -0
  515. package/dist/store/conflicts.d.ts +44 -0
  516. package/dist/store/conflicts.js +444 -0
  517. package/dist/store/delete-and-batch.d.ts +63 -0
  518. package/dist/store/delete-and-batch.js +310 -0
  519. package/dist/store/entry-reads.d.ts +92 -0
  520. package/dist/store/entry-reads.js +255 -0
  521. package/dist/store/entry-row.d.ts +67 -0
  522. package/dist/store/entry-row.js +208 -0
  523. package/dist/store/entry-writes.d.ts +46 -0
  524. package/dist/store/entry-writes.js +148 -0
  525. package/dist/store/handoffs.d.ts +26 -0
  526. package/dist/store/handoffs.js +184 -0
  527. package/dist/store/index-and-stats.d.ts +52 -0
  528. package/dist/store/index-and-stats.js +214 -0
  529. package/dist/store/markdown.d.ts +10 -0
  530. package/dist/store/markdown.js +108 -0
  531. package/dist/store/mirrors.d.ts +49 -0
  532. package/dist/store/mirrors.js +312 -0
  533. package/dist/store/open.d.ts +15 -0
  534. package/dist/store/open.js +223 -0
  535. package/dist/store/rows.d.ts +178 -0
  536. package/dist/store/rows.js +158 -0
  537. package/dist/store/search-rows.d.ts +86 -0
  538. package/dist/store/search-rows.js +254 -0
  539. package/dist/store/sessions.d.ts +83 -0
  540. package/dist/store/sessions.js +272 -0
  541. package/dist/store/summaries.d.ts +94 -0
  542. package/dist/store/summaries.js +377 -0
  543. package/dist/store/tenant-lookup.d.ts +12 -0
  544. package/dist/store/tenant-lookup.js +16 -0
  545. package/dist/store-cards.js +2 -1
  546. package/dist/summary-dirty.d.ts +4 -0
  547. package/dist/summary-dirty.js +32 -0
  548. package/dist/support-bundle.js +4 -3
  549. package/dist/tenant.js +2 -2
  550. package/dist/token-ledger.js +1 -0
  551. package/dist/tokenize.d.ts +2 -0
  552. package/dist/tokenize.js +16 -0
  553. package/dist/transcript-tail.d.ts +7 -0
  554. package/dist/transcript-tail.js +48 -0
  555. package/dist/vector-store.d.ts +27 -0
  556. package/dist/vector-store.js +210 -0
  557. package/dist/version.d.ts +2 -2
  558. package/dist/version.js +2 -2
  559. package/dist/working-memory.js +1 -1
  560. package/dist/yaml.js +36 -11
  561. package/dist-ui/assets/ibm-plex-mono-latin-400-normal-CvHOgSBP.woff +0 -0
  562. package/dist-ui/assets/ibm-plex-mono-latin-400-normal-DMJ8VG8y.woff2 +0 -0
  563. package/dist-ui/assets/ibm-plex-mono-latin-500-normal-CB9ihrfo.woff +0 -0
  564. package/dist-ui/assets/ibm-plex-mono-latin-500-normal-DSY6xOcd.woff2 +0 -0
  565. package/dist-ui/assets/ibm-plex-mono-latin-600-normal-BgSNZQsw.woff2 +0 -0
  566. package/dist-ui/assets/ibm-plex-mono-latin-600-normal-DWFSQ4vo.woff +0 -0
  567. package/dist-ui/assets/ibm-plex-sans-latin-400-normal-CDDApCn2.woff2 +0 -0
  568. package/dist-ui/assets/ibm-plex-sans-latin-400-normal-CYLoc0-x.woff +0 -0
  569. package/dist-ui/assets/ibm-plex-sans-latin-500-normal-6ng42L7E.woff2 +0 -0
  570. package/dist-ui/assets/ibm-plex-sans-latin-500-normal-BgVn5rGT.woff +0 -0
  571. package/dist-ui/assets/ibm-plex-sans-latin-600-normal-Cu4Hd6ag.woff +0 -0
  572. package/dist-ui/assets/ibm-plex-sans-latin-600-normal-CuJfVYMP.woff2 +0 -0
  573. package/dist-ui/assets/index-DPN7cP19.js +33 -0
  574. package/dist-ui/assets/index-dFloKRVr.css +1 -0
  575. package/dist-ui/index.html +3 -25
  576. package/extensions/openclaw-plugin/openclaw.plugin.json +1 -1
  577. package/extensions/openclaw-plugin/package.json +1 -1
  578. package/openclaw.plugin.json +1 -1
  579. package/package.json +2 -1
  580. package/dist/capture.d.ts +0 -155
  581. package/dist/capture.js +0 -1293
  582. package/dist/consolidate.d.ts +0 -58
  583. package/dist/consolidate.js +0 -1123
  584. package/dist/graph.d.ts +0 -245
  585. package/dist/hooks.d.ts +0 -208
  586. package/dist/hooks.js +0 -1073
  587. package/dist/importers.js +0 -897
  588. package/dist/predictions.js +0 -620
  589. package/dist/search.d.ts +0 -320
  590. package/dist/search.js +0 -968
  591. package/dist/store.d.ts +0 -744
  592. package/dist/store.js +0 -3372
  593. package/dist-ui/assets/d3-BiWEKnn4.js +0 -1
  594. package/dist-ui/assets/index-BhT8RvO6.js +0 -61
  595. package/dist-ui/assets/index-RoXXJ5dq.css +0 -1
  596. package/dist-ui/assets/three-BDgTxR1l.js +0 -4112
@@ -1,5 +1,6 @@
1
1
  /** Quarantine tier (CD5, AT3): pending/approved/rejected record for a memory `remember` flagged as untrusted. */
2
2
  import { appendAuditEvent } from './audit.js';
3
+ import { keysetAfter } from './keyset.js';
3
4
  export const QUARANTINE_SCOPE_PREFIX = 'quarantine:private:';
4
5
  /** Scope a quarantined memory is stored under; matches PRIVATE_SCOPE_RE so every default-deny site hides it. */
5
6
  export function quarantineScopeFor(original) {
@@ -39,16 +40,18 @@ export function getQuarantineRow(db, tenantId, memoryId) {
39
40
  .get(tenantId, memoryId);
40
41
  return row ? fromDbRow(row) : null;
41
42
  }
42
- export function listQuarantineRows(db, tenantId, status = 'pending', limit = 100) {
43
+ export function listQuarantineRows(db, tenantId, status = 'pending', limit = 100, afterRow) {
43
44
  // A pending row whose memory was deleted (e.g. Slack message_deleted) is dead; keep its history, drop it from the queue.
44
45
  const live = status === 'pending'
45
46
  ? ' AND EXISTS (SELECT 1 FROM memories m WHERE m.id = memory_quarantine.memory_id AND m.tenant_id = memory_quarantine.tenant_id)'
46
47
  : '';
48
+ const after = keysetAfter('quarantined_at', 'memory_id', afterRow);
49
+ const order = 'ORDER BY quarantined_at DESC, memory_id DESC LIMIT ?';
47
50
  const rows = status === 'all'
48
- ? db.prepare(`SELECT ${SELECT_COLUMNS} FROM memory_quarantine WHERE tenant_id = ? ORDER BY quarantined_at DESC LIMIT ?`)
49
- .all(tenantId, limit)
50
- : db.prepare(`SELECT ${SELECT_COLUMNS} FROM memory_quarantine WHERE tenant_id = ? AND status = ?${live} ORDER BY quarantined_at DESC LIMIT ?`)
51
- .all(tenantId, status, limit);
51
+ ? db.prepare(`SELECT ${SELECT_COLUMNS} FROM memory_quarantine WHERE tenant_id = ?${after.sql} ${order}`)
52
+ .all(tenantId, ...after.params, limit)
53
+ : db.prepare(`SELECT ${SELECT_COLUMNS} FROM memory_quarantine WHERE tenant_id = ? AND status = ?${live}${after.sql} ${order}`)
54
+ .all(tenantId, status, ...after.params, limit);
52
55
  // SAFETY: both branches select SELECT_COLUMNS, matching QuarantineDbRow's field set.
53
56
  return rows.map(fromDbRow);
54
57
  }
@@ -1,5 +1,6 @@
1
1
  import * as fs from 'fs';
2
2
  import * as path from 'path';
3
+ import { log } from './log.js';
3
4
  const LAYERS = ['episodic', 'buffer', 'semantic'];
4
5
  const MAX_WARN_LOGS = 5;
5
6
  /**
@@ -42,7 +43,7 @@ export function cleanupArchivedMirrors(hippoRoot, db) {
42
43
  catch (err) {
43
44
  allOk = false;
44
45
  if (warnCount < MAX_WARN_LOGS) {
45
- console.warn(`cleanupArchivedMirrors: unlink failed for ${filePath} (will retry on next DB open):`, err);
46
+ log.warn(`cleanupArchivedMirrors: unlink failed for ${filePath} (will retry on next DB open): ${err instanceof Error ? err.message : String(err)}`);
46
47
  warnCount += 1;
47
48
  }
48
49
  }
@@ -1,7 +1,7 @@
1
1
  import { BadRequestError, NotFoundError } from './api-errors.js';
2
2
  import { isFtsAvailable } from './db.js';
3
3
  import { appendAuditEvent, reportAuditWriteFailure } from './audit.js';
4
- import { markSummaryDirtyInTx } from './store.js';
4
+ import { markSummaryDirtyInTx } from './summary-dirty.js';
5
5
  export function archiveRawMemory(db, id, opts) {
6
6
  // SAFETY: SELECT * FROM memories returns every column of the memories table; only
7
7
  // kind, tenant_id, and dag_parent_id are read below, all guaranteed present (possibly
@@ -18,6 +18,7 @@
18
18
  * Composes with J3.2: AnchoringHint + PlanningFallacyHint are independent
19
19
  * signals; both can fire on the same recall.
20
20
  */
21
+ import { envAnchoringOff, envAvailabilityOff } from './env.js';
21
22
  const DEFAULT_MIN_DOMINANCE = 3;
22
23
  const DEFAULT_RECENT_REPEAT_WINDOW = 5;
23
24
  const DEFAULT_COOLDOWN = 3;
@@ -238,7 +239,7 @@ export function snapshotRing(ring) {
238
239
  */
239
240
  export function biasHintEnabled(kind) {
240
241
  return kind === 'anchoring'
241
- ? process.env.HIPPO_ANCHORING !== 'off'
242
- : process.env.HIPPO_AVAILABILITY !== 'off';
242
+ ? !envAnchoringOff()
243
+ : !envAvailabilityOff();
243
244
  }
244
245
  //# sourceMappingURL=recall-history.js.map
@@ -2,7 +2,7 @@ import { type GoalRecallLogRow } from './goals.js';
2
2
  import { type MemoryEntry } from './memory.js';
3
3
  import type { PhysicsConfig } from './physics-config.js';
4
4
  import type { RerankerFn } from './rerankers/types.js';
5
- import { type ResultCost, type SearchResult } from './search.js';
5
+ import type { ResultCost, SearchResult } from './search/types.js';
6
6
  /** Stores rankRecall reads and where it sends operator notes. */
7
7
  export interface RankRecallCtx {
8
8
  hippoRoot: string;
@@ -23,7 +23,7 @@ export interface RecallSearchOpts {
23
23
  mmrLambda: number;
24
24
  localBump: number;
25
25
  minResults?: number;
26
- /** Score breakdowns for `hippo explain`; explain's physics call also leaves out the bi-temporal flags. */
26
+ /** Score breakdowns for `hippo explain`; explain's physics call also leaves out minResults and includeSuperseded. */
27
27
  explain: boolean;
28
28
  }
29
29
  /** `--graph-hops` and `--graph-seeds`. */
@@ -4,17 +4,18 @@ import { evalNow } from './ablation.js';
4
4
  import { oneCopyPerMemory } from './api.js';
5
5
  import { compareEntryIdentity } from './compare.js';
6
6
  import { closeHippoDb, openHippoDb } from './db.js';
7
- import { isEmbeddingAvailable } from './embeddings.js';
7
+ import { isEmbeddingAvailable } from './local-embedding.js';
8
8
  import { computeGoalStackBoost } from './goals.js';
9
9
  import { graphExpandRecall } from './graph-recall.js';
10
10
  import { DEFAULT_GRAPH_STREAM_WEIGHT } from './graph-stream.js';
11
11
  import { Layer } from './memory.js';
12
12
  import { multihopSearch } from './multihop.js';
13
13
  import { passesCliRecallScopeFilter } from './recall-scope.js';
14
- import { hybridSearch, physicsSearch, textOverlap } from './search.js';
14
+ import { hybridSearch } from './search/hybrid.js';
15
+ import { physicsSearch } from './search/physics-search.js';
15
16
  import { searchBothHybrid } from './shared.js';
16
- import { loadRecallSearchEntries } from './store.js';
17
- import { tokenize as tokenizeQuery } from './tokenize.js';
17
+ import { loadRecallSearchEntries, recallScopeFilter } from './store/search-rows.js';
18
+ import { textOverlap, tokenize as tokenizeQuery } from './tokenize.js';
18
19
  /** Ranks memories for a query as `hippo recall` does, through the `limit` slice. Reads stores, embeddings and
19
20
  * physics state; writes nothing and prints nothing (notes go to `ctx.note`). The caller supplies the cost
20
21
  * function and reranker in `opts`, and persists the returned goal-log rows. */
@@ -124,10 +125,17 @@ async function searchPool(ctx, opts, pool) {
124
125
  const allEntries = oneCopyPerMemory(pool.local, pool.global, evalNow()).flat();
125
126
  return multihopSearch(query, allEntries, { budget, cost, hippoRoot: ctx.hippoRoot, minResults, includeSuperseded, asOf });
126
127
  }
128
+ const requested = opts.explicitScope || undefined;
129
+ const vectorCandidates = {
130
+ tenantId: ctx.tenantId,
131
+ scope: recallScopeFilter(requested, 'additive'),
132
+ includeSuperseded: includeSuperseded || Boolean(asOf),
133
+ admit: (e) => passesCliRecallScopeFilter(e.scope ?? null, requested),
134
+ };
127
135
  if (search.usePhysics && !globalRoot) {
128
- // Explain has never passed the bi-temporal flags to physics; keeping that holds its output steady.
129
- const temporal = explain ? {} : { minResults, includeSuperseded, asOf };
130
- return physicsSearch(query, pool.local, { budget, cost, hippoRoot: ctx.hippoRoot, physicsConfig: search.physicsConfig, scope, explain, ...temporal });
136
+ // Explain leaves minResults and includeSuperseded out to hold its output steady; asOf must reach physics or later rows leak.
137
+ const temporal = explain ? { asOf } : { minResults, includeSuperseded, asOf };
138
+ return physicsSearch(query, pool.local, { budget, cost, hippoRoot: ctx.hippoRoot, physicsConfig: search.physicsConfig, scope, explain, vectorCandidates, ...temporal });
131
139
  }
132
140
  if (globalRoot) {
133
141
  // searchBothHybrid reloads candidates itself, so the scope rule is passed in rather than inherited from the pool.
@@ -137,7 +145,7 @@ async function searchPool(ctx, opts, pool) {
137
145
  recallScope: opts.explicitScope ? { requested: opts.explicitScope, additive: true } : {},
138
146
  });
139
147
  }
140
- return hybridSearch(query, pool.local, { budget, cost, hippoRoot: ctx.hippoRoot, explain, mmr, mmrLambda, minResults, scope, includeSuperseded, asOf });
148
+ return hybridSearch(query, pool.local, { budget, cost, hippoRoot: ctx.hippoRoot, explain, mmr, mmrLambda, minResults, scope, includeSuperseded, asOf, vectorCandidates });
141
149
  }
142
150
  /** Adds memories reached by walking the entity graph out from the lexical seeds. */
143
151
  function expandGraph(ctx, opts, graph, state) {
@@ -124,7 +124,7 @@ export function isRestrictedScope(scope) {
124
124
  return false;
125
125
  // SAFETY: RECALL_DEFAULT_DENY_SCOPES is a readonly tuple of string
126
126
  // literals; widening the array (not the input) lets .includes() take any scope.
127
- // `:private:` anywhere, any case, matches the store's SQL default-deny (store.ts:894) so JS never admits what SQL hides.
127
+ // `:private:` anywhere, any case, matches the store's SQL default-deny (store/search-rows.ts) so JS never admits what SQL hides.
128
128
  return isPrivateScope(scope) || /:private:/i.test(scope) || RECALL_DEFAULT_DENY_SCOPES.includes(scope);
129
129
  }
130
130
  /** True when `actor` may read `scope`: admin always; member needs an exact grant on a restricted scope. */
@@ -16,7 +16,7 @@
16
16
  * new debug env var).
17
17
  */
18
18
  import { type DatabaseSyncLike } from './db.js';
19
- import type { RerankStep } from './search.js';
19
+ import type { RerankStep } from './search/types.js';
20
20
  import { type DeliveryEventInput } from './delivery-recorder.js';
21
21
  /** One ranked result to persist alongside its trace row. */
22
22
  export interface RecallTraceResultInput {
@@ -102,8 +102,8 @@ export interface RecordTraceOutcomeInput {
102
102
  * this function from caller-side state (`last_trace_id` / applied outcome
103
103
  * ids) that can go stale relative to the trace it names — a forgotten
104
104
  * memory, a tenant switch mid-session, or a race between two callers. Two
105
- * checks run before the insert, both skip silently (console.error one
106
- * line) rather than throw:
105
+ * checks run before the insert, both skip with one log.warn line
106
+ * rather than throw:
107
107
  * 1. The named trace must exist and belong to `input.tenantId` — a
108
108
  * tenant mismatch or a dangling id (deleted trace) skips.
109
109
  * 2. `input.memoryIds` is intersected against the trace's OWN
@@ -18,6 +18,7 @@
18
18
  import { createHash } from 'node:crypto';
19
19
  import { openHippoDb, closeHippoDb } from './db.js';
20
20
  import { DELIVERY_LEDGER_VERSION } from './delivery-recorder.js';
21
+ import { log } from './log.js';
21
22
  /**
22
23
  * Strip a RerankStep down to {stage, multiplier, scoreBefore, scoreAfter}
23
24
  * before persisting (F3 privacy fix, codex cross-model finding). `note` is
@@ -76,8 +77,7 @@ export function writeRecallTrace(db, input) {
76
77
  }
77
78
  }
78
79
  catch (error) {
79
- // eslint-disable-next-line no-console
80
- console.error(`[hippo] recall trace write failed: ${error instanceof Error ? error.message : String(error)}`);
80
+ log.error(`recall trace write failed: ${error instanceof Error ? error.message : String(error)}`);
81
81
  return null;
82
82
  }
83
83
  }
@@ -113,8 +113,7 @@ export function writeRecallTraceAtRoot(root, input) {
113
113
  db = openHippoDb(root);
114
114
  }
115
115
  catch (error) {
116
- // eslint-disable-next-line no-console
117
- console.error(`[hippo] recall trace connection failed: ${error instanceof Error ? error.message : String(error)}`);
116
+ log.error(`recall trace connection failed: ${error instanceof Error ? error.message : String(error)}`);
118
117
  return null;
119
118
  }
120
119
  try {
@@ -140,8 +139,8 @@ export function writeRecallTraceAtRoot(root, input) {
140
139
  * this function from caller-side state (`last_trace_id` / applied outcome
141
140
  * ids) that can go stale relative to the trace it names — a forgotten
142
141
  * memory, a tenant switch mid-session, or a race between two callers. Two
143
- * checks run before the insert, both skip silently (console.error one
144
- * line) rather than throw:
142
+ * checks run before the insert, both skip with one log.warn line
143
+ * rather than throw:
145
144
  * 1. The named trace must exist and belong to `input.tenantId` — a
146
145
  * tenant mismatch or a dangling id (deleted trace) skips.
147
146
  * 2. `input.memoryIds` is intersected against the trace's OWN
@@ -158,8 +157,7 @@ export function recordTraceOutcome(db, input) {
158
157
  // SELECT above; sqlite returns undefined when no row matches.
159
158
  const trace = db.prepare(`SELECT tenant_id FROM recall_traces WHERE id = ?`).get(input.traceId);
160
159
  if (!trace || trace.tenant_id !== input.tenantId) {
161
- // eslint-disable-next-line no-console
162
- console.error(`[hippo] recall trace outcome skipped: trace ${input.traceId} missing or tenant mismatch`);
160
+ log.warn(`recall trace outcome skipped: trace ${input.traceId} missing or tenant mismatch`);
163
161
  return;
164
162
  }
165
163
  // SAFETY: row shape matches the single `memory_id` column named in the
@@ -170,8 +168,7 @@ export function recordTraceOutcome(db, input) {
170
168
  const members = new Set(memberRows.map((r) => r.memory_id));
171
169
  const credited = input.memoryIds.filter((id) => members.has(id));
172
170
  if (credited.length === 0) {
173
- // eslint-disable-next-line no-console
174
- console.error(`[hippo] recall trace outcome skipped: no credited ids intersect trace ${input.traceId}'s results`);
171
+ log.warn(`recall trace outcome skipped: no credited ids intersect trace ${input.traceId}'s results`);
175
172
  return;
176
173
  }
177
174
  db.prepare(`
@@ -180,8 +177,7 @@ export function recordTraceOutcome(db, input) {
180
177
  `).run(input.traceId, new Date().toISOString(), input.tenantId, input.outcome, JSON.stringify(credited));
181
178
  }
182
179
  catch (error) {
183
- // eslint-disable-next-line no-console
184
- console.error(`[hippo] recall trace outcome write failed: ${error instanceof Error ? error.message : String(error)}`);
180
+ log.error(`recall trace outcome write failed: ${error instanceof Error ? error.message : String(error)}`);
185
181
  }
186
182
  }
187
183
  /** Pruned on write, counted back from the event's ts capped at the real clock, so a far-future fake time spares real rows. */
@@ -270,7 +266,7 @@ export function writeDeliveryEvent(db, input) {
270
266
  }
271
267
  }
272
268
  catch (error) {
273
- // eslint-disable-next-line no-console
269
+ // The prompt hook's stderr shows this exact `[hippo] delivery ledger` line, so it stays off the logger's format.
274
270
  console.error(`[hippo] delivery ledger write failed: ${error instanceof Error ? error.message : String(error)}`);
275
271
  return null;
276
272
  }
@@ -282,7 +278,7 @@ export function writeDeliveryEventAtRoot(root, input) {
282
278
  db = openHippoDb(root, { busyWaitMs: DELIVERY_LEDGER_WAIT_MS });
283
279
  }
284
280
  catch (error) {
285
- // eslint-disable-next-line no-console
281
+ // Same hook stderr line as writeDeliveryEvent above.
286
282
  console.error(`[hippo] delivery ledger write failed: ${error instanceof Error ? error.message : String(error)}`);
287
283
  return null;
288
284
  }
@@ -13,9 +13,11 @@
13
13
  * - On failure (API error, bad response), the original memory is untouched.
14
14
  */
15
15
  import { Layer } from './memory.js';
16
- import { loadAllEntries, readEntry, writeEntry } from './store.js';
17
- import { redactSecrets } from './secret-detect.js';
16
+ import { writeEntry } from './store/entry-writes.js';
17
+ import { loadAllEntries, readEntry } from './store/entry-reads.js';
18
+ import { redactSecretsStrict } from './secret-detect.js';
18
19
  import { fetchWithRetry, llmTimeoutMs } from './http-retry.js';
20
+ import { log } from './log.js';
19
21
  const REFINED_TAG = 'llm-refined';
20
22
  const CONSOLIDATED_MARKERS = [
21
23
  '[Consolidated from',
@@ -31,7 +33,7 @@ export async function refineSemanticMemory(merged, sources, opts) {
31
33
  const fetchFn = opts.fetcher ?? fetch;
32
34
  const sourceBlock = sources
33
35
  .slice(0, 8)
34
- .map((s, i) => `[source ${i + 1}] ${redactSecrets(s.content).slice(0, 400)}`)
36
+ .map((s, i) => `[source ${i + 1}] ${redactSecretsStrict(s.content).slice(0, 400)}`)
35
37
  .join('\n\n');
36
38
  const prompt = `You are refining a semantic memory in an agent's memory store. The rule-based consolidator merged several related episodic memories into one, but the output is clumsy. Produce a single coherent semantic memory that captures the underlying principle.
37
39
 
@@ -43,7 +45,7 @@ Rules:
43
45
  - Do NOT include the "[Consolidated from N ...]" marker.
44
46
 
45
47
  Current merged content:
46
- ${redactSecrets(merged)}
48
+ ${redactSecretsStrict(merged)}
47
49
 
48
50
  Source memories (up to 8 shown):
49
51
  ${sourceBlock}`;
@@ -63,24 +65,31 @@ ${sourceBlock}`;
63
65
  }),
64
66
  }, { timeoutMs: llmTimeoutMs(), fetchFn });
65
67
  }
66
- catch {
68
+ catch (err) {
69
+ log.warn(`refine: request failed: ${err instanceof Error ? err.message : String(err)}`);
67
70
  return null;
68
71
  }
69
- if (!res.ok)
72
+ if (!res.ok) {
73
+ log.warn(`refine: API answered HTTP ${res.status}`);
70
74
  return null;
75
+ }
76
+ let text;
71
77
  try {
72
78
  // SAFETY: data is the Anthropic Messages API response body; the
73
79
  // documented response shape is `{ content: [{ type, text, ... }] }`
74
80
  // for a text-generating request like this one.
75
81
  const data = await res.json();
76
- const text = data.content?.[0]?.text?.trim() ?? '';
77
- if (text.length < 10)
78
- return null;
79
- return text;
82
+ text = data.content?.[0]?.text?.trim() ?? '';
83
+ }
84
+ catch (err) {
85
+ log.warn(`refine: unreadable response: ${err instanceof Error ? err.message : String(err)}`);
86
+ return null;
80
87
  }
81
- catch {
88
+ if (text.length < 10) {
89
+ log.warn('refine: response was empty or too short to use');
82
90
  return null;
83
91
  }
92
+ return text;
84
93
  }
85
94
  function isConsolidated(entry) {
86
95
  if (entry.layer !== Layer.Semantic)
@@ -15,7 +15,12 @@ import { closeHippoDb } from './db.js';
15
15
  import { appendAuditEvent, reportAuditWriteFailure } from './audit.js';
16
16
  import { archiveRawMemory } from './raw-archive.js';
17
17
  import { deleteDormantRow, listDormantSnapshots, purgeDormantByDigest, replaceDormantEntry } from './dormant.js';
18
- import { openStore, deleteEntryCore, purgeMirrorBestEffort, selectAllEntries, stampOriginProject, writeEntryDbOnly, writeEntryMirrors, } from './store.js';
18
+ import { stampOriginProject } from './store/entry-row.js';
19
+ import { purgeMirrorBestEffort } from './store/mirrors.js';
20
+ import { openStore } from './store/open.js';
21
+ import { writeEntryDbOnly, writeEntryMirrors } from './store/entry-writes.js';
22
+ import { selectAllEntries } from './store/entry-reads.js';
23
+ import { deleteEntryCore } from './store/delete-and-batch.js';
19
24
  import { heldTexts } from './same-text.js';
20
25
  import { mergedSuccessor } from './merged-row.js';
21
26
  import { rejectionDigest, normalizeValueForRejection, insertRejectedValue, deleteRejectedValue, listRejectedValues, } from './rejection.js';
@@ -1,4 +1,4 @@
1
- import type { RerankerFn } from './types.js';
1
+ import type { RerankerFn, RerankProvenance } from './types.js';
2
2
  import { type JsonValue } from '../http-util.js';
3
3
  /** The two pretrained CLEF decision models served by Cloudflare Workers AI. */
4
4
  export type ClefModel = 'clef-flash' | 'clef';
@@ -7,7 +7,7 @@ export declare function isClefModel(name: string): name is ClefModel;
7
7
  interface ClefRoute {
8
8
  url: string;
9
9
  token: string | undefined;
10
- backend: 'cloudflare' | 'private-endpoint';
10
+ backend: Exclude<RerankProvenance['backend'], 'native'>;
11
11
  }
12
12
  interface ClefScores {
13
13
  scores: number[];
@@ -1,7 +1,12 @@
1
- import { buildRelevanceRequest, JEV_DEFAULT_TOP_K } from './jev.js';
1
+ import { envClefEndpoint, envClefEndpointToken, envClefTimeoutMs, envCloudflareAccountId, envCloudflareApiToken } from '../env.js';
2
+ import { buildRelevanceRequest, JEV_DEFAULT_TOP_K, rankByScores } from './jev.js';
2
3
  import { isJsonObjectRecord } from '../http-util.js';
4
+ import { log } from '../log.js';
3
5
  const CLEF_MODELS = ['clef-flash', 'clef'];
4
6
  const DEFAULT_TIMEOUT_MS = 15_000;
7
+ const MAX_TIMEOUT_MS = 120_000;
8
+ // 64 answers fit in a few KB; 1 MiB leaves room for a verbose envelope.
9
+ const MAX_REPLY_BYTES = 1024 * 1024;
5
10
  // Workers AI rejects a request with more than 64 questions, one per candidate here.
6
11
  const MAX_CANDIDATES = 64;
7
12
  const ACCOUNT_ID = /^[0-9a-f]{32}$/i;
@@ -9,6 +14,10 @@ const ACCOUNT_ID = /^[0-9a-f]{32}$/i;
9
14
  export function isClefModel(name) {
10
15
  return CLEF_MODELS.some((m) => m === name);
11
16
  }
17
+ // Plain http would put the token and the memory text on the wire, so only the local machine may use it.
18
+ function isLoopback(hostname) {
19
+ return hostname === 'localhost' || hostname === '[::1]' || /^127(\.\d{1,3}){3}$/.test(hostname);
20
+ }
12
21
  function isNumber(v) {
13
22
  return Number.isFinite(v);
14
23
  }
@@ -16,11 +25,16 @@ function isString(v) {
16
25
  return v !== undefined && v !== null && v.constructor === String;
17
26
  }
18
27
  function isRejection(v) {
19
- return typeof v === 'string';
28
+ return v.constructor === String;
29
+ }
30
+ // fetch quotes a rejected header value in its error, so a token it would reject must never reach it.
31
+ function checkHeaderSafe(name, token) {
32
+ if (!/^[\x21-\x7e]+$/.test(token))
33
+ throw new Error(`${name} has characters a header cannot carry`);
20
34
  }
21
35
  /** Transport from trusted local env, never call arguments: HIPPO_CLEF_ENDPOINT wins over hosted Workers AI. */
22
36
  export function resolveClefRoute(model) {
23
- const endpoint = process.env.HIPPO_CLEF_ENDPOINT?.trim();
37
+ const endpoint = envClefEndpoint();
24
38
  if (endpoint) {
25
39
  let parsed;
26
40
  try {
@@ -32,14 +46,25 @@ export function resolveClefRoute(model) {
32
46
  if (parsed.protocol !== 'https:' && parsed.protocol !== 'http:') {
33
47
  throw new Error('HIPPO_CLEF_ENDPOINT must be an http or https URL');
34
48
  }
35
- return { url: parsed.href, token: process.env.HIPPO_CLEF_ENDPOINT_TOKEN?.trim() || undefined, backend: 'private-endpoint' };
49
+ // fetch echoes a URL with credentials in its error text, which reaches stderr.
50
+ if (parsed.username || parsed.password) {
51
+ throw new Error('HIPPO_CLEF_ENDPOINT must not embed credentials; set HIPPO_CLEF_ENDPOINT_TOKEN');
52
+ }
53
+ if (parsed.protocol === 'http:' && !isLoopback(parsed.hostname)) {
54
+ throw new Error('HIPPO_CLEF_ENDPOINT must use https unless it is on this machine');
55
+ }
56
+ const endpointToken = envClefEndpointToken();
57
+ if (endpointToken)
58
+ checkHeaderSafe('HIPPO_CLEF_ENDPOINT_TOKEN', endpointToken);
59
+ return { url: parsed.href, token: endpointToken, backend: 'private-endpoint' };
36
60
  }
37
- const account = process.env.CLOUDFLARE_ACCOUNT_ID?.trim() ?? '';
38
- const token = process.env.CLOUDFLARE_API_TOKEN?.trim() ?? '';
61
+ const account = envCloudflareAccountId();
62
+ const token = envCloudflareApiToken();
39
63
  if (!account || !token)
40
64
  throw new Error('CLOUDFLARE_ACCOUNT_ID and CLOUDFLARE_API_TOKEN not set');
41
65
  if (!ACCOUNT_ID.test(account))
42
66
  throw new Error('CLOUDFLARE_ACCOUNT_ID is not a 32-character hex id');
67
+ checkHeaderSafe('CLOUDFLARE_API_TOKEN', token);
43
68
  return {
44
69
  url: `https://api.cloudflare.com/client/v4/accounts/${account}/ai/run/@cf/cloudflare/${model}`,
45
70
  token,
@@ -83,15 +108,43 @@ export function parseClefReply(body, n, model, requireModel) {
83
108
  outputTokens: isNumber(usage.output_tokens) ? usage.output_tokens : undefined,
84
109
  };
85
110
  }
111
+ // The timeout bounds time, not bytes: a hostile endpoint could stream a huge 2xx body into memory.
112
+ async function readCappedJson(resp) {
113
+ if (!resp.body)
114
+ throw new Error('reply has no body');
115
+ const reader = resp.body.getReader();
116
+ const decoder = new TextDecoder();
117
+ let raw = '';
118
+ let received = 0;
119
+ for (;;) {
120
+ const { done, value } = await reader.read();
121
+ if (done)
122
+ break;
123
+ received += value.byteLength;
124
+ if (received > MAX_REPLY_BYTES) {
125
+ await reader.cancel();
126
+ throw new Error(`reply over ${MAX_REPLY_BYTES} bytes`);
127
+ }
128
+ raw += decoder.decode(value, { stream: true });
129
+ }
130
+ raw += decoder.decode();
131
+ try {
132
+ return JSON.parse(raw);
133
+ }
134
+ catch {
135
+ throw new Error('reply is not JSON');
136
+ }
137
+ }
86
138
  async function requestScores(model, query, head, route) {
87
139
  const { state, questions } = buildRelevanceRequest(query, head);
88
- const parsedTimeout = Number.parseInt(process.env.HIPPO_CLEF_TIMEOUT_MS ?? '', 10);
89
- const timeoutMs = parsedTimeout > 0 ? parsedTimeout : DEFAULT_TIMEOUT_MS;
90
- const controller = new AbortController();
91
- const timer = setTimeout(() => controller.abort(), timeoutMs);
140
+ // Strict parse: parseInt would read "15s" as 15 ms, and Node clamps a delay past 2^31-1 to 1 ms.
141
+ const requested = Number(envClefTimeoutMs());
142
+ const timeoutMs = Number.isInteger(requested) && requested > 0 && requested <= MAX_TIMEOUT_MS ? requested : DEFAULT_TIMEOUT_MS;
92
143
  const headers = new Headers({ 'content-type': 'application/json' });
93
144
  if (route.token)
94
145
  headers.set('authorization', `Bearer ${route.token}`);
146
+ const controller = new AbortController();
147
+ const timer = setTimeout(() => controller.abort(), timeoutMs);
95
148
  try {
96
149
  const resp = await fetch(route.url, {
97
150
  method: 'POST',
@@ -105,7 +158,7 @@ async function requestScores(model, query, head, route) {
105
158
  await resp.body?.cancel();
106
159
  throw new Error(`HTTP ${resp.status}${ray ? `, ray ${ray}` : ''}`);
107
160
  }
108
- const body = await resp.json();
161
+ const body = await readCappedJson(resp);
109
162
  const parsed = parseClefReply(body, head.length, model, route.backend === 'cloudflare');
110
163
  if (isRejection(parsed))
111
164
  throw new Error(parsed);
@@ -127,7 +180,8 @@ function nativeOrder(head, provenance) {
127
180
  rerankScore: r.score,
128
181
  preRerankRank: r.preRerankRank ?? i + 1,
129
182
  postRerankRank: i + 1,
130
- rerankProvenance: provenance,
183
+ // A copy per row, so a caller editing one result cannot change another's provenance.
184
+ rerankProvenance: { ...provenance },
131
185
  }));
132
186
  }
133
187
  /** A CLEF reranker for one model: Jev's request shape and pool; any failure keeps the native order (never paid Jev), warning once. */
@@ -137,42 +191,30 @@ export function createClefReranker(model) {
137
191
  const head = results.slice(0, options?.topK ?? JEV_DEFAULT_TOP_K);
138
192
  if (head.length === 0)
139
193
  return [];
140
- let backend = 'native';
194
+ let route;
141
195
  let got;
142
196
  try {
143
197
  if (head.length > MAX_CANDIDATES)
144
198
  throw new Error(`more than ${MAX_CANDIDATES} candidates`);
145
- const route = resolveClefRoute(model);
146
- backend = route.backend;
199
+ route = resolveClefRoute(model);
147
200
  got = await requestScores(model, query, head, route);
148
201
  }
149
202
  catch (err) {
150
203
  const reason = err instanceof Error ? err.message : 'unknown error';
151
204
  if (!warned) {
152
205
  warned = true;
153
- // eslint-disable-next-line no-console
154
- console.warn(`[hippo] ${model} reranker unavailable (${reason}); keeping the native order. Subsequent calls will not repeat this warning.`);
206
+ log.warn(`${model} reranker unavailable (${reason}); keeping the native order. Subsequent calls will not repeat this warning.`);
155
207
  }
156
208
  return nativeOrder(head, { backend: 'native', requestedModel: model, fallbackReason: reason });
157
209
  }
158
- const provenance = {
159
- backend,
210
+ const rerankProvenance = {
211
+ backend: route.backend,
160
212
  requestedModel: model,
161
213
  actualModel: got.actualModel,
162
214
  inputTokens: got.inputTokens,
163
215
  outputTokens: got.outputTokens,
164
216
  };
165
- const scored = head.map((r, i) => ({
166
- ...r,
167
- rerankScore: got.scores[i],
168
- preRerankRank: r.preRerankRank ?? i + 1,
169
- postRerankRank: 0,
170
- rerankProvenance: provenance,
171
- }));
172
- // Stable sort: ties fall back to the prior relevance order.
173
- scored.sort((a, b) => b.rerankScore - a.rerankScore);
174
- scored.forEach((r, i) => (r.postRerankRank = i + 1));
175
- return scored;
217
+ return rankByScores(head, got.scores).map((r) => ({ ...r, rerankProvenance: { ...rerankProvenance } }));
176
218
  };
177
219
  }
178
220
  /** Opt-in CLEF-flash reranker (Cloudflare Workers AI or HIPPO_CLEF_ENDPOINT); off unless named, so defaults stay native. */
@@ -1,5 +1,6 @@
1
1
  import { createRequire } from 'node:module';
2
2
  import { pathToFileURL } from 'node:url';
3
+ import { log } from '../log.js';
3
4
  const MODEL_NAME = 'Xenova/ms-marco-MiniLM-L-6-v2';
4
5
  const _require = createRequire(import.meta.url);
5
6
  const TRANSFORMERS_PACKAGES = ['@huggingface/transformers', '@xenova/transformers'];
@@ -36,7 +37,8 @@ async function loadTransformersModule() {
36
37
  const seq = mod.AutoModelForSequenceClassification ?? mod.default?.AutoModelForSequenceClassification;
37
38
  return tok && seq ? { AutoTokenizer: tok, AutoModelForSequenceClassification: seq } : null;
38
39
  }
39
- catch {
40
+ catch (err) {
41
+ log.debug(`cross-encoder: transformers import failed: ${err instanceof Error ? err.message : String(err)}`);
40
42
  return null;
41
43
  }
42
44
  }
@@ -78,7 +80,8 @@ async function buildPipeline() {
78
80
  return score;
79
81
  };
80
82
  }
81
- catch {
83
+ catch (err) {
84
+ log.debug(`cross-encoder: model load failed: ${err instanceof Error ? err.message : String(err)}`);
82
85
  return null;
83
86
  }
84
87
  }
@@ -102,8 +105,7 @@ export const crossEncoderReranker = async (query, results, options) => {
102
105
  // working reranker.
103
106
  if (!warnedOnFallback) {
104
107
  warnedOnFallback = true;
105
- // eslint-disable-next-line no-console
106
- console.warn('[hippo] cross-encoder reranker unavailable (no Transformers.js backend, or model fetch blocked); falling back to identity ordering. Subsequent calls will not repeat this warning.');
108
+ log.warn('cross-encoder reranker unavailable (no Transformers.js backend, or model fetch blocked); falling back to identity ordering. Subsequent calls will not repeat this warning.');
107
109
  }
108
110
  return head.map((r, i) => ({
109
111
  ...r,
@@ -1,5 +1,5 @@
1
- import type { RerankerFn } from './types.js';
2
- import type { SearchResult } from '../search.js';
1
+ import type { RerankerFn, RerankResult } from './types.js';
2
+ import type { SearchResult } from '../search/types.js';
3
3
  export declare const JEV_DEFAULT_TOP_K = 40;
4
4
  /** The System One `state` and one `noul` question per candidate (`c1`..`cN`). */
5
5
  export interface RelevanceRequest {
@@ -13,6 +13,8 @@ export interface RelevanceRequest {
13
13
  export declare function buildRelevanceRequest(query: string, head: readonly SearchResult[]): RelevanceRequest;
14
14
  /** Builds a Jev reranker around the reranker it degrades to. Exported so a test can pass a stand-in. */
15
15
  export declare function createJevReranker(localFallback: RerankerFn): RerankerFn;
16
+ /** Orders `head` by `scores[i]`, keeping any upstream pre-rerank rank. Shared with CLEF. */
17
+ export declare function rankByScores(head: readonly SearchResult[], scores: readonly number[]): RerankResult[];
16
18
  /** Track 4 reranker: hosted TypeSafe Jev, opt-in and paid (TYPESAFE_API_KEY), one batched call per recall.
17
19
  * Any failure warns once and delegates to the local cross-encoder. Scores are not bit-stable run to run.
18
20
  * Cost, env vars, evidence and limits: docs/evals/2026-09-19-jev-reranker.md. */