hippo-memory 1.60.0 → 1.61.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (585) 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 -1262
  53. package/dist/api.js +25 -2727
  54. package/dist/audit.d.ts +3 -0
  55. package/dist/audit.js +6 -3
  56. package/dist/auth.d.ts +45 -4
  57. package/dist/auth.js +125 -48
  58. package/dist/autolearn.js +2 -2
  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 +71 -120
  123. package/dist/cli.js +170 -8469
  124. package/dist/client.js +15 -8
  125. package/dist/compaction-record.js +6 -4
  126. package/dist/connectors/github/backfill.js +94 -87
  127. package/dist/connectors/github/cli-impl.js +4 -3
  128. package/dist/connectors/github/dlq.js +67 -54
  129. package/dist/connectors/github/ingest.js +34 -35
  130. package/dist/connectors/github/tenant-routing.js +3 -2
  131. package/dist/connectors/github/webhook.js +135 -216
  132. package/dist/connectors/slack/dlq.js +49 -61
  133. package/dist/connectors/slack/ingest.js +55 -48
  134. package/dist/connectors/slack/tenant-routing.js +4 -3
  135. package/dist/connectors/slack/webhook.js +72 -74
  136. package/dist/consolidate/conflicts.d.ts +10 -0
  137. package/dist/consolidate/conflicts.js +178 -0
  138. package/dist/consolidate/decay.d.ts +12 -0
  139. package/dist/consolidate/decay.js +145 -0
  140. package/dist/consolidate/llm-passes.d.ts +3 -0
  141. package/dist/consolidate/llm-passes.js +141 -0
  142. package/dist/consolidate/merge.d.ts +7 -0
  143. package/dist/consolidate/merge.js +251 -0
  144. package/dist/consolidate/physics-pass.d.ts +3 -0
  145. package/dist/consolidate/physics-pass.js +60 -0
  146. package/dist/consolidate/run.d.ts +69 -0
  147. package/dist/consolidate/run.js +76 -0
  148. package/dist/consolidate/sleep.d.ts +18 -0
  149. package/dist/consolidate/sleep.js +209 -0
  150. package/dist/consolidate/traces.d.ts +4 -0
  151. package/dist/consolidate/traces.js +178 -0
  152. package/dist/context-auto.js +7 -11
  153. package/dist/context-render.d.ts +1 -1
  154. package/dist/context-render.js +1 -1
  155. package/dist/customer-notes.d.ts +3 -0
  156. package/dist/customer-notes.js +6 -4
  157. package/dist/dag.js +6 -5
  158. package/dist/dashboard-actions.d.ts +20 -0
  159. package/dist/dashboard-actions.js +88 -0
  160. package/dist/dashboard-params.d.ts +45 -0
  161. package/dist/dashboard-params.js +127 -0
  162. package/dist/dashboard-queries.d.ts +15 -0
  163. package/dist/dashboard-queries.js +355 -0
  164. package/dist/dashboard-snapshot.d.ts +138 -0
  165. package/dist/dashboard-snapshot.js +308 -0
  166. package/dist/dashboard-types.d.ts +163 -0
  167. package/dist/dashboard-types.js +3 -0
  168. package/dist/dashboard.d.ts +6 -7
  169. package/dist/dashboard.js +228 -202
  170. package/dist/db/busy.d.ts +5 -0
  171. package/dist/db/busy.js +24 -0
  172. package/dist/db/continuity.d.ts +5 -0
  173. package/dist/db/continuity.js +145 -0
  174. package/dist/db/meta.d.ts +8 -0
  175. package/dist/db/meta.js +35 -0
  176. package/dist/db/migrate.d.ts +9 -0
  177. package/dist/db/migrate.js +138 -0
  178. package/dist/db/migrations/index.d.ts +5 -0
  179. package/dist/db/migrations/index.js +109 -0
  180. package/dist/db/migrations/types.d.ts +14 -0
  181. package/dist/db/migrations/types.js +2 -0
  182. package/dist/db/migrations/v01.d.ts +3 -0
  183. package/dist/db/migrations/v01.js +38 -0
  184. package/dist/db/migrations/v02.d.ts +3 -0
  185. package/dist/db/migrations/v02.js +21 -0
  186. package/dist/db/migrations/v03.d.ts +3 -0
  187. package/dist/db/migrations/v03.js +22 -0
  188. package/dist/db/migrations/v04.d.ts +3 -0
  189. package/dist/db/migrations/v04.js +28 -0
  190. package/dist/db/migrations/v05.d.ts +3 -0
  191. package/dist/db/migrations/v05.js +21 -0
  192. package/dist/db/migrations/v06.d.ts +3 -0
  193. package/dist/db/migrations/v06.js +25 -0
  194. package/dist/db/migrations/v07.d.ts +3 -0
  195. package/dist/db/migrations/v07.js +13 -0
  196. package/dist/db/migrations/v08.d.ts +3 -0
  197. package/dist/db/migrations/v08.js +8 -0
  198. package/dist/db/migrations/v09.d.ts +3 -0
  199. package/dist/db/migrations/v09.js +13 -0
  200. package/dist/db/migrations/v10.d.ts +3 -0
  201. package/dist/db/migrations/v10.js +17 -0
  202. package/dist/db/migrations/v11.d.ts +3 -0
  203. package/dist/db/migrations/v11.js +15 -0
  204. package/dist/db/migrations/v12.d.ts +3 -0
  205. package/dist/db/migrations/v12.js +11 -0
  206. package/dist/db/migrations/v13.d.ts +3 -0
  207. package/dist/db/migrations/v13.js +15 -0
  208. package/dist/db/migrations/v14.d.ts +3 -0
  209. package/dist/db/migrations/v14.js +66 -0
  210. package/dist/db/migrations/v15.d.ts +3 -0
  211. package/dist/db/migrations/v15.js +42 -0
  212. package/dist/db/migrations/v16.d.ts +3 -0
  213. package/dist/db/migrations/v16.js +61 -0
  214. package/dist/db/migrations/v17.d.ts +3 -0
  215. package/dist/db/migrations/v17.js +46 -0
  216. package/dist/db/migrations/v18.d.ts +3 -0
  217. package/dist/db/migrations/v18.js +60 -0
  218. package/dist/db/migrations/v19.d.ts +3 -0
  219. package/dist/db/migrations/v19.js +28 -0
  220. package/dist/db/migrations/v20.d.ts +3 -0
  221. package/dist/db/migrations/v20.js +42 -0
  222. package/dist/db/migrations/v21.d.ts +3 -0
  223. package/dist/db/migrations/v21.js +16 -0
  224. package/dist/db/migrations/v22.d.ts +3 -0
  225. package/dist/db/migrations/v22.js +82 -0
  226. package/dist/db/migrations/v23.d.ts +3 -0
  227. package/dist/db/migrations/v23.js +48 -0
  228. package/dist/db/migrations/v24.d.ts +3 -0
  229. package/dist/db/migrations/v24.js +72 -0
  230. package/dist/db/migrations/v25.d.ts +3 -0
  231. package/dist/db/migrations/v25.js +46 -0
  232. package/dist/db/migrations/v26.d.ts +3 -0
  233. package/dist/db/migrations/v26.js +23 -0
  234. package/dist/db/migrations/v27.d.ts +3 -0
  235. package/dist/db/migrations/v27.js +57 -0
  236. package/dist/db/migrations/v28.d.ts +3 -0
  237. package/dist/db/migrations/v28.js +38 -0
  238. package/dist/db/migrations/v29.d.ts +3 -0
  239. package/dist/db/migrations/v29.js +78 -0
  240. package/dist/db/migrations/v30.d.ts +3 -0
  241. package/dist/db/migrations/v30.js +92 -0
  242. package/dist/db/migrations/v31.d.ts +3 -0
  243. package/dist/db/migrations/v31.js +74 -0
  244. package/dist/db/migrations/v32.d.ts +3 -0
  245. package/dist/db/migrations/v32.js +102 -0
  246. package/dist/db/migrations/v33.d.ts +3 -0
  247. package/dist/db/migrations/v33.js +104 -0
  248. package/dist/db/migrations/v34.d.ts +3 -0
  249. package/dist/db/migrations/v34.js +93 -0
  250. package/dist/db/migrations/v35.d.ts +3 -0
  251. package/dist/db/migrations/v35.js +98 -0
  252. package/dist/db/migrations/v36.d.ts +3 -0
  253. package/dist/db/migrations/v36.js +98 -0
  254. package/dist/db/migrations/v37.d.ts +3 -0
  255. package/dist/db/migrations/v37.js +219 -0
  256. package/dist/db/migrations/v38.d.ts +3 -0
  257. package/dist/db/migrations/v38.js +277 -0
  258. package/dist/db/migrations/v39.d.ts +3 -0
  259. package/dist/db/migrations/v39.js +59 -0
  260. package/dist/db/migrations/v40.d.ts +3 -0
  261. package/dist/db/migrations/v40.js +74 -0
  262. package/dist/db/migrations/v41.d.ts +3 -0
  263. package/dist/db/migrations/v41.js +43 -0
  264. package/dist/db/migrations/v42.d.ts +3 -0
  265. package/dist/db/migrations/v42.js +41 -0
  266. package/dist/db/migrations/v43.d.ts +3 -0
  267. package/dist/db/migrations/v43.js +67 -0
  268. package/dist/db/migrations/v44.d.ts +3 -0
  269. package/dist/db/migrations/v44.js +28 -0
  270. package/dist/db/migrations/v45.d.ts +3 -0
  271. package/dist/db/migrations/v45.js +30 -0
  272. package/dist/db/migrations/v46.d.ts +3 -0
  273. package/dist/db/migrations/v46.js +25 -0
  274. package/dist/db/migrations/v47.d.ts +3 -0
  275. package/dist/db/migrations/v47.js +17 -0
  276. package/dist/db/migrations/v48.d.ts +3 -0
  277. package/dist/db/migrations/v48.js +10 -0
  278. package/dist/db/migrations/v49.d.ts +3 -0
  279. package/dist/db/migrations/v49.js +31 -0
  280. package/dist/db/migrations/v50.d.ts +3 -0
  281. package/dist/db/migrations/v50.js +67 -0
  282. package/dist/db/migrations/v51.d.ts +3 -0
  283. package/dist/db/migrations/v51.js +14 -0
  284. package/dist/db/migrations/v52.d.ts +3 -0
  285. package/dist/db/migrations/v52.js +7 -0
  286. package/dist/db/open.d.ts +23 -0
  287. package/dist/db/open.js +146 -0
  288. package/dist/db/sqlite.d.ts +21 -0
  289. package/dist/db/sqlite.js +8 -0
  290. package/dist/db/tables.d.ts +7 -0
  291. package/dist/db/tables.js +38 -0
  292. package/dist/db.d.ts +6 -46
  293. package/dist/db.js +5 -3049
  294. package/dist/decisions.d.ts +4 -1
  295. package/dist/decisions.js +9 -7
  296. package/dist/dedupe.js +3 -2
  297. package/dist/delivery-recorder.js +4 -1
  298. package/dist/doctor.js +3 -3
  299. package/dist/embedding-provider.d.ts +1 -1
  300. package/dist/embedding-provider.js +4 -3
  301. package/dist/embeddings.d.ts +9 -52
  302. package/dist/embeddings.js +43 -297
  303. package/dist/env.d.ts +75 -0
  304. package/dist/env.js +119 -0
  305. package/dist/eval-suite.js +1 -1
  306. package/dist/eval.js +2 -2
  307. package/dist/extract.js +1 -1
  308. package/dist/gated-write.js +3 -1
  309. package/dist/goals.d.ts +3 -1
  310. package/dist/goals.js +18 -0
  311. package/dist/graph/read.d.ts +73 -0
  312. package/dist/graph/read.js +325 -0
  313. package/dist/graph/rows.d.ts +45 -0
  314. package/dist/graph/rows.js +51 -0
  315. package/dist/graph/types.d.ts +83 -0
  316. package/dist/graph/types.js +11 -0
  317. package/dist/graph/write.d.ts +93 -0
  318. package/dist/{graph.js → graph/write.js} +6 -384
  319. package/dist/graph-extract.js +2 -1
  320. package/dist/graph-recall.d.ts +1 -1
  321. package/dist/graph-recall.js +2 -2
  322. package/dist/graph-stream.js +1 -1
  323. package/dist/graph-view.d.ts +1 -1
  324. package/dist/graph-view.js +1 -1
  325. package/dist/half-life-migration.d.ts +1 -1
  326. package/dist/half-life-migration.js +2 -1
  327. package/dist/hooks/codex-session.d.ts +8 -0
  328. package/dist/hooks/codex-session.js +76 -0
  329. package/dist/hooks/codex-wrapper.d.ts +55 -0
  330. package/dist/hooks/codex-wrapper.js +288 -0
  331. package/dist/hooks/json-hooks.d.ts +63 -0
  332. package/dist/hooks/json-hooks.js +356 -0
  333. package/dist/hooks/opencode.d.ts +50 -0
  334. package/dist/hooks/opencode.js +202 -0
  335. package/dist/hooks/shared.d.ts +54 -0
  336. package/dist/hooks/shared.js +77 -0
  337. package/dist/http-retry.d.ts +2 -0
  338. package/dist/http-retry.js +4 -3
  339. package/dist/http-util.d.ts +3 -0
  340. package/dist/http-util.js +10 -0
  341. package/dist/{importers.d.ts → importers/core.d.ts} +13 -17
  342. package/dist/importers/core.js +141 -0
  343. package/dist/importers/markdown-parse.d.ts +41 -0
  344. package/dist/importers/markdown-parse.js +132 -0
  345. package/dist/importers/markdown.d.ts +3 -0
  346. package/dist/importers/markdown.js +92 -0
  347. package/dist/importers/sources.d.ts +7 -0
  348. package/dist/importers/sources.js +229 -0
  349. package/dist/importers/vault.d.ts +11 -0
  350. package/dist/importers/vault.js +352 -0
  351. package/dist/incidents.d.ts +3 -0
  352. package/dist/incidents.js +7 -5
  353. package/dist/index.d.ts +25 -6
  354. package/dist/index.js +23 -6
  355. package/dist/invalidation.js +2 -1
  356. package/dist/judgment.js +2 -1
  357. package/dist/keyset.d.ts +13 -0
  358. package/dist/keyset.js +8 -0
  359. package/dist/local-embedding.d.ts +13 -0
  360. package/dist/local-embedding.js +165 -0
  361. package/dist/log.d.ts +7 -0
  362. package/dist/log.js +19 -1
  363. package/dist/mcp/admin-tools.d.ts +8 -0
  364. package/dist/mcp/admin-tools.js +116 -0
  365. package/dist/mcp/format.d.ts +27 -0
  366. package/dist/mcp/format.js +135 -0
  367. package/dist/mcp/memory-tools.d.ts +5 -0
  368. package/dist/mcp/memory-tools.js +83 -0
  369. package/dist/mcp/protocol.d.ts +83 -0
  370. package/dist/mcp/protocol.js +55 -0
  371. package/dist/mcp/recall-tools.d.ts +6 -0
  372. package/dist/mcp/recall-tools.js +320 -0
  373. package/dist/mcp/request.d.ts +10 -0
  374. package/dist/mcp/request.js +163 -0
  375. package/dist/mcp/server.d.ts +4 -75
  376. package/dist/mcp/server.js +7 -1190
  377. package/dist/mcp/session-state.d.ts +11 -0
  378. package/dist/mcp/session-state.js +28 -0
  379. package/dist/mcp/stdio.d.ts +8 -0
  380. package/dist/mcp/stdio.js +79 -0
  381. package/dist/mcp/tools.d.ts +11 -0
  382. package/dist/mcp/tools.js +247 -0
  383. package/dist/memory.d.ts +3 -0
  384. package/dist/memory.js +27 -1
  385. package/dist/multihop.d.ts +1 -1
  386. package/dist/multihop.js +2 -1
  387. package/dist/owner-validation.js +2 -1
  388. package/dist/physics-state.js +10 -7
  389. package/dist/policies.d.ts +3 -0
  390. package/dist/policies.js +8 -6
  391. package/dist/postinstall.js +3 -2
  392. package/dist/predictions/planning-fallacy.d.ts +100 -0
  393. package/dist/predictions/planning-fallacy.js +190 -0
  394. package/dist/{predictions.d.ts → predictions/store.d.ts} +7 -102
  395. package/dist/predictions/store.js +434 -0
  396. package/dist/processes.d.ts +3 -0
  397. package/dist/processes.js +7 -5
  398. package/dist/project-briefs.d.ts +3 -0
  399. package/dist/project-briefs.js +7 -5
  400. package/dist/project-identity.js +3 -2
  401. package/dist/project-merge.js +3 -1
  402. package/dist/quarantine.d.ts +2 -1
  403. package/dist/quarantine.js +8 -5
  404. package/dist/raw-archive.js +1 -1
  405. package/dist/recall-history.js +3 -2
  406. package/dist/recall-pipeline.d.ts +2 -2
  407. package/dist/recall-pipeline.js +16 -8
  408. package/dist/recall-scope.js +1 -1
  409. package/dist/recall-trace.d.ts +1 -1
  410. package/dist/refine-llm.js +2 -1
  411. package/dist/reject-flow.js +6 -1
  412. package/dist/rerankers/clef.js +6 -5
  413. package/dist/rerankers/jev.d.ts +1 -1
  414. package/dist/rerankers/jev.js +4 -4
  415. package/dist/rerankers/llm.d.ts +4 -2
  416. package/dist/rerankers/llm.js +58 -38
  417. package/dist/rerankers/types.d.ts +1 -1
  418. package/dist/salience.js +1 -1
  419. package/dist/scheduler.d.ts +1 -0
  420. package/dist/scheduler.js +26 -4
  421. package/dist/scope.js +4 -3
  422. package/dist/search/as-of.d.ts +10 -0
  423. package/dist/search/as-of.js +22 -0
  424. package/dist/search/bm25-search.d.ts +14 -0
  425. package/dist/search/bm25-search.js +43 -0
  426. package/dist/search/bm25.d.ts +15 -0
  427. package/dist/search/bm25.js +54 -0
  428. package/dist/search/boosts.d.ts +54 -0
  429. package/dist/search/boosts.js +94 -0
  430. package/dist/search/breakdown.d.ts +7 -0
  431. package/dist/search/breakdown.js +20 -0
  432. package/dist/search/explain.d.ts +25 -0
  433. package/dist/search/explain.js +31 -0
  434. package/dist/search/finalize.d.ts +8 -0
  435. package/dist/search/finalize.js +52 -0
  436. package/dist/search/fusion.d.ts +27 -0
  437. package/dist/search/fusion.js +42 -0
  438. package/dist/search/hybrid-score.d.ts +20 -0
  439. package/dist/search/hybrid-score.js +73 -0
  440. package/dist/search/hybrid.d.ts +46 -0
  441. package/dist/search/hybrid.js +64 -0
  442. package/dist/search/physics-search.d.ts +29 -0
  443. package/dist/search/physics-search.js +162 -0
  444. package/dist/search/rerank.d.ts +10 -0
  445. package/dist/search/rerank.js +72 -0
  446. package/dist/search/temporal.d.ts +15 -0
  447. package/dist/search/temporal.js +45 -0
  448. package/dist/search/types.d.ts +91 -0
  449. package/dist/search/types.js +2 -0
  450. package/dist/search/vector.d.ts +30 -0
  451. package/dist/search/vector.js +71 -0
  452. package/dist/secret-detect.d.ts +2 -0
  453. package/dist/secret-detect.js +2 -1
  454. package/dist/server/auth.d.ts +52 -0
  455. package/dist/server/auth.js +221 -0
  456. package/dist/server/client-ip.d.ts +25 -0
  457. package/dist/server/client-ip.js +92 -0
  458. package/dist/server/cursor.d.ts +23 -0
  459. package/dist/server/cursor.js +58 -0
  460. package/dist/server/lifecycle.d.ts +7 -0
  461. package/dist/server/lifecycle.js +29 -0
  462. package/dist/server/mcp-http.d.ts +5 -0
  463. package/dist/server/mcp-http.js +199 -0
  464. package/dist/server/request.d.ts +33 -0
  465. package/dist/server/request.js +103 -0
  466. package/dist/server/routes/admin.d.ts +9 -0
  467. package/dist/server/routes/admin.js +158 -0
  468. package/dist/server/routes/customer-notes.d.ts +7 -0
  469. package/dist/server/routes/customer-notes.js +112 -0
  470. package/dist/server/routes/decisions.d.ts +7 -0
  471. package/dist/server/routes/decisions.js +133 -0
  472. package/dist/server/routes/incidents.d.ts +7 -0
  473. package/dist/server/routes/incidents.js +126 -0
  474. package/dist/server/routes/memories.d.ts +10 -0
  475. package/dist/server/routes/memories.js +179 -0
  476. package/dist/server/routes/policies.d.ts +8 -0
  477. package/dist/server/routes/policies.js +151 -0
  478. package/dist/server/routes/predictions.d.ts +7 -0
  479. package/dist/server/routes/predictions.js +164 -0
  480. package/dist/server/routes/processes.d.ts +7 -0
  481. package/dist/server/routes/processes.js +161 -0
  482. package/dist/server/routes/project-briefs.d.ts +8 -0
  483. package/dist/server/routes/project-briefs.js +136 -0
  484. package/dist/server/routes/recall.d.ts +8 -0
  485. package/dist/server/routes/recall.js +340 -0
  486. package/dist/server/routes/skills.d.ts +8 -0
  487. package/dist/server/routes/skills.js +150 -0
  488. package/dist/server/types.d.ts +56 -0
  489. package/dist/server/types.js +2 -0
  490. package/dist/server/validation.d.ts +14 -0
  491. package/dist/server/validation.js +91 -0
  492. package/dist/server.d.ts +7 -61
  493. package/dist/server.js +69 -2362
  494. package/dist/session-digest.d.ts +1 -1
  495. package/dist/session-digest.js +9 -2
  496. package/dist/shared.d.ts +3 -1
  497. package/dist/shared.js +26 -22
  498. package/dist/skills.d.ts +3 -0
  499. package/dist/skills.js +7 -5
  500. package/dist/stdin.js +2 -2
  501. package/dist/store/audit-event.d.ts +19 -0
  502. package/dist/store/audit-event.js +33 -0
  503. package/dist/store/candidates.d.ts +42 -0
  504. package/dist/store/candidates.js +152 -0
  505. package/dist/store/conflicts.d.ts +44 -0
  506. package/dist/store/conflicts.js +444 -0
  507. package/dist/store/delete-and-batch.d.ts +63 -0
  508. package/dist/store/delete-and-batch.js +310 -0
  509. package/dist/store/entry-reads.d.ts +92 -0
  510. package/dist/store/entry-reads.js +255 -0
  511. package/dist/store/entry-row.d.ts +67 -0
  512. package/dist/store/entry-row.js +208 -0
  513. package/dist/store/entry-writes.d.ts +46 -0
  514. package/dist/store/entry-writes.js +148 -0
  515. package/dist/store/handoffs.d.ts +26 -0
  516. package/dist/store/handoffs.js +184 -0
  517. package/dist/store/index-and-stats.d.ts +52 -0
  518. package/dist/store/index-and-stats.js +214 -0
  519. package/dist/store/markdown.d.ts +10 -0
  520. package/dist/store/markdown.js +108 -0
  521. package/dist/store/mirrors.d.ts +49 -0
  522. package/dist/store/mirrors.js +312 -0
  523. package/dist/store/open.d.ts +15 -0
  524. package/dist/store/open.js +223 -0
  525. package/dist/store/rows.d.ts +178 -0
  526. package/dist/store/rows.js +158 -0
  527. package/dist/store/search-rows.d.ts +86 -0
  528. package/dist/store/search-rows.js +254 -0
  529. package/dist/store/sessions.d.ts +83 -0
  530. package/dist/store/sessions.js +272 -0
  531. package/dist/store/summaries.d.ts +94 -0
  532. package/dist/store/summaries.js +377 -0
  533. package/dist/store/tenant-lookup.d.ts +12 -0
  534. package/dist/store/tenant-lookup.js +16 -0
  535. package/dist/store-cards.js +2 -1
  536. package/dist/summary-dirty.d.ts +4 -0
  537. package/dist/summary-dirty.js +32 -0
  538. package/dist/support-bundle.js +4 -3
  539. package/dist/tenant.js +2 -2
  540. package/dist/tokenize.d.ts +2 -0
  541. package/dist/tokenize.js +16 -0
  542. package/dist/transcript-tail.d.ts +7 -0
  543. package/dist/transcript-tail.js +48 -0
  544. package/dist/vector-store.d.ts +27 -0
  545. package/dist/vector-store.js +210 -0
  546. package/dist/version.d.ts +2 -2
  547. package/dist/version.js +2 -2
  548. package/dist/working-memory.js +1 -1
  549. package/dist/yaml.js +36 -11
  550. package/dist-ui/assets/ibm-plex-mono-latin-400-normal-CvHOgSBP.woff +0 -0
  551. package/dist-ui/assets/ibm-plex-mono-latin-400-normal-DMJ8VG8y.woff2 +0 -0
  552. package/dist-ui/assets/ibm-plex-mono-latin-500-normal-CB9ihrfo.woff +0 -0
  553. package/dist-ui/assets/ibm-plex-mono-latin-500-normal-DSY6xOcd.woff2 +0 -0
  554. package/dist-ui/assets/ibm-plex-mono-latin-600-normal-BgSNZQsw.woff2 +0 -0
  555. package/dist-ui/assets/ibm-plex-mono-latin-600-normal-DWFSQ4vo.woff +0 -0
  556. package/dist-ui/assets/ibm-plex-sans-latin-400-normal-CDDApCn2.woff2 +0 -0
  557. package/dist-ui/assets/ibm-plex-sans-latin-400-normal-CYLoc0-x.woff +0 -0
  558. package/dist-ui/assets/ibm-plex-sans-latin-500-normal-6ng42L7E.woff2 +0 -0
  559. package/dist-ui/assets/ibm-plex-sans-latin-500-normal-BgVn5rGT.woff +0 -0
  560. package/dist-ui/assets/ibm-plex-sans-latin-600-normal-Cu4Hd6ag.woff +0 -0
  561. package/dist-ui/assets/ibm-plex-sans-latin-600-normal-CuJfVYMP.woff2 +0 -0
  562. package/dist-ui/assets/index-DPN7cP19.js +33 -0
  563. package/dist-ui/assets/index-dFloKRVr.css +1 -0
  564. package/dist-ui/index.html +3 -25
  565. package/extensions/openclaw-plugin/openclaw.plugin.json +1 -1
  566. package/extensions/openclaw-plugin/package.json +1 -1
  567. package/openclaw.plugin.json +1 -1
  568. package/package.json +1 -1
  569. package/dist/capture.d.ts +0 -155
  570. package/dist/capture.js +0 -1295
  571. package/dist/consolidate.d.ts +0 -58
  572. package/dist/consolidate.js +0 -1124
  573. package/dist/graph.d.ts +0 -245
  574. package/dist/hooks.d.ts +0 -208
  575. package/dist/hooks.js +0 -1076
  576. package/dist/importers.js +0 -900
  577. package/dist/predictions.js +0 -620
  578. package/dist/search.d.ts +0 -320
  579. package/dist/search.js +0 -970
  580. package/dist/store.d.ts +0 -776
  581. package/dist/store.js +0 -3473
  582. package/dist-ui/assets/d3-BiWEKnn4.js +0 -1
  583. package/dist-ui/assets/index-BhT8RvO6.js +0 -61
  584. package/dist-ui/assets/index-RoXXJ5dq.css +0 -1
  585. package/dist-ui/assets/three-BDgTxR1l.js +0 -4112
@@ -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 {
@@ -13,7 +13,8 @@
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';
16
+ import { writeEntry } from './store/entry-writes.js';
17
+ import { loadAllEntries, readEntry } from './store/entry-reads.js';
17
18
  import { redactSecretsStrict } from './secret-detect.js';
18
19
  import { fetchWithRetry, llmTimeoutMs } from './http-retry.js';
19
20
  import { log } from './log.js';
@@ -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,3 +1,4 @@
1
+ import { envClefEndpoint, envClefEndpointToken, envClefTimeoutMs, envCloudflareAccountId, envCloudflareApiToken } from '../env.js';
1
2
  import { buildRelevanceRequest, JEV_DEFAULT_TOP_K, rankByScores } from './jev.js';
2
3
  import { isJsonObjectRecord } from '../http-util.js';
3
4
  import { log } from '../log.js';
@@ -33,7 +34,7 @@ function checkHeaderSafe(name, token) {
33
34
  }
34
35
  /** Transport from trusted local env, never call arguments: HIPPO_CLEF_ENDPOINT wins over hosted Workers AI. */
35
36
  export function resolveClefRoute(model) {
36
- const endpoint = process.env.HIPPO_CLEF_ENDPOINT?.trim();
37
+ const endpoint = envClefEndpoint();
37
38
  if (endpoint) {
38
39
  let parsed;
39
40
  try {
@@ -52,13 +53,13 @@ export function resolveClefRoute(model) {
52
53
  if (parsed.protocol === 'http:' && !isLoopback(parsed.hostname)) {
53
54
  throw new Error('HIPPO_CLEF_ENDPOINT must use https unless it is on this machine');
54
55
  }
55
- const endpointToken = process.env.HIPPO_CLEF_ENDPOINT_TOKEN?.trim() || undefined;
56
+ const endpointToken = envClefEndpointToken();
56
57
  if (endpointToken)
57
58
  checkHeaderSafe('HIPPO_CLEF_ENDPOINT_TOKEN', endpointToken);
58
59
  return { url: parsed.href, token: endpointToken, backend: 'private-endpoint' };
59
60
  }
60
- const account = process.env.CLOUDFLARE_ACCOUNT_ID?.trim() ?? '';
61
- const token = process.env.CLOUDFLARE_API_TOKEN?.trim() ?? '';
61
+ const account = envCloudflareAccountId();
62
+ const token = envCloudflareApiToken();
62
63
  if (!account || !token)
63
64
  throw new Error('CLOUDFLARE_ACCOUNT_ID and CLOUDFLARE_API_TOKEN not set');
64
65
  if (!ACCOUNT_ID.test(account))
@@ -137,7 +138,7 @@ async function readCappedJson(resp) {
137
138
  async function requestScores(model, query, head, route) {
138
139
  const { state, questions } = buildRelevanceRequest(query, head);
139
140
  // Strict parse: parseInt would read "15s" as 15 ms, and Node clamps a delay past 2^31-1 to 1 ms.
140
- const requested = Number(process.env.HIPPO_CLEF_TIMEOUT_MS);
141
+ const requested = Number(envClefTimeoutMs());
141
142
  const timeoutMs = Number.isInteger(requested) && requested > 0 && requested <= MAX_TIMEOUT_MS ? requested : DEFAULT_TIMEOUT_MS;
142
143
  const headers = new Headers({ 'content-type': 'application/json' });
143
144
  if (route.token)
@@ -1,5 +1,5 @@
1
1
  import type { RerankerFn, RerankResult } from './types.js';
2
- import type { SearchResult } from '../search.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 {
@@ -1,3 +1,4 @@
1
+ import { envJevModel, envJevTimeoutMs, envTypesafeApiKey } from '../env.js';
1
2
  import { crossEncoderReranker } from './cross-encoder.js';
2
3
  import { redactSecretsStrict } from '../secret-detect.js';
3
4
  import { log } from '../log.js';
@@ -45,12 +46,11 @@ export function buildRelevanceRequest(query, head) {
45
46
  }
46
47
  /** One batched request for the whole candidate list. Rejects with the reason when there are no usable scores. */
47
48
  async function requestScores(query, head) {
48
- const key = process.env.TYPESAFE_API_KEY;
49
+ const key = envTypesafeApiKey();
49
50
  if (!key)
50
51
  throw new Error('TYPESAFE_API_KEY not set');
51
52
  const { state, questions } = buildRelevanceRequest(query, head);
52
- const parsed = Number.parseInt(process.env.HIPPO_JEV_TIMEOUT_MS ?? '', 10);
53
- const timeoutMs = parsed > 0 ? parsed : DEFAULT_TIMEOUT_MS;
53
+ const timeoutMs = envJevTimeoutMs() ?? DEFAULT_TIMEOUT_MS;
54
54
  const controller = new AbortController();
55
55
  const timer = setTimeout(() => controller.abort(), timeoutMs);
56
56
  try {
@@ -59,7 +59,7 @@ async function requestScores(query, head) {
59
59
  headers: { 'content-type': 'application/json', authorization: `Bearer ${key}` },
60
60
  body: JSON.stringify({
61
61
  state,
62
- model: process.env.HIPPO_JEV_MODEL ?? DEFAULT_MODEL,
62
+ model: envJevModel() ?? DEFAULT_MODEL,
63
63
  questions,
64
64
  }),
65
65
  signal: controller.signal,
@@ -8,8 +8,10 @@ import type { RerankerFn } from './types.js';
8
8
  * Full characterisation deferred to a follow-on plan.
9
9
  *
10
10
  * Timeout: defaults to 30s; overridable via HIPPO_LLM_RERANKER_TIMEOUT_MS.
11
- * On timeout or any fetch failure, the reranker silently falls back to
12
- * identity ordering — recall must not hang on a wedged endpoint.
11
+ * On timeout or any fetch failure, the reranker warns once per process and
12
+ * falls back to identity ordering; recall must not hang on a wedged endpoint.
13
13
  */
14
+ export declare function createLlmReranker(): RerankerFn;
15
+ /** The instance the reranker registry serves; its warn-once flag lasts the process. */
14
16
  export declare const llmReranker: RerankerFn;
15
17
  //# sourceMappingURL=llm.d.ts.map
@@ -1,4 +1,6 @@
1
+ import { envLlmRerankerKey, envLlmRerankerModel, envLlmRerankerTimeoutMs, envLlmRerankerUrl } from '../env.js';
1
2
  import { redactSecretsStrict } from '../secret-detect.js';
3
+ import { log } from '../log.js';
2
4
  const DEFAULT_TIMEOUT_MS = 30_000;
3
5
  /**
4
6
  * Track 3 reranker: listwise LLM rerank. Uses a customer-supplied
@@ -9,24 +11,50 @@ const DEFAULT_TIMEOUT_MS = 30_000;
9
11
  * Full characterisation deferred to a follow-on plan.
10
12
  *
11
13
  * Timeout: defaults to 30s; overridable via HIPPO_LLM_RERANKER_TIMEOUT_MS.
12
- * On timeout or any fetch failure, the reranker silently falls back to
13
- * identity ordering — recall must not hang on a wedged endpoint.
14
+ * On timeout or any fetch failure, the reranker warns once per process and
15
+ * falls back to identity ordering; recall must not hang on a wedged endpoint.
14
16
  */
15
- export const llmReranker = async (query, results, options) => {
16
- const url = process.env.HIPPO_LLM_RERANKER_URL;
17
- const key = process.env.HIPPO_LLM_RERANKER_KEY;
18
- if (!url) {
19
- throw new Error('HIPPO_LLM_RERANKER_URL not set; refusing to run LLM reranker.');
20
- }
21
- const topK = options?.topK ?? 20;
22
- const head = results.slice(0, topK);
17
+ export function createLlmReranker() {
18
+ let warned = false;
19
+ return async (query, results, options) => {
20
+ const url = envLlmRerankerUrl();
21
+ if (!url) {
22
+ throw new Error('HIPPO_LLM_RERANKER_URL not set; refusing to run LLM reranker.');
23
+ }
24
+ const head = results.slice(0, options?.topK ?? 20);
25
+ let permutation = null;
26
+ try {
27
+ permutation = await requestPermutation(url, query, head);
28
+ }
29
+ catch (err) {
30
+ // A read path never throws, and never hands back the unranked order without saying so.
31
+ if (!warned) {
32
+ warned = true;
33
+ const reason = err instanceof Error ? err.message : 'unknown error';
34
+ log.warn(`llm reranker unavailable (${reason}); keeping the input order. Subsequent calls will not repeat this warning.`);
35
+ }
36
+ }
37
+ const ordered = permutation ? permutation.map((idx) => head[idx]) : head;
38
+ return ordered.map((r, i) => ({
39
+ ...r,
40
+ rerankScore: ordered.length - i,
41
+ preRerankRank: r.preRerankRank ?? i + 1,
42
+ postRerankRank: i + 1,
43
+ }));
44
+ };
45
+ }
46
+ /** The instance the reranker registry serves; its warn-once flag lasts the process. */
47
+ export const llmReranker = createLlmReranker();
48
+ /** One chat-completions call; rejects with the reason when the reply holds no usable permutation. */
49
+ async function requestPermutation(url, query, head) {
50
+ const key = envLlmRerankerKey();
23
51
  const prompt = [
24
52
  `Rerank the candidates below by relevance to the query. Output a JSON array of indices (zero-indexed) in best-first order.`,
25
53
  `Query: ${redactSecretsStrict(query)}`,
26
54
  ...head.map((r, i) => `[${i}] ${redactSecretsStrict(r.entry.content)}`),
27
55
  `Output format: [<int>, <int>, ...] with all ${head.length} indices.`,
28
56
  ].join('\n');
29
- const timeoutMs = Number.parseInt(process.env.HIPPO_LLM_RERANKER_TIMEOUT_MS ?? '', 10) || DEFAULT_TIMEOUT_MS;
57
+ const timeoutMs = envLlmRerankerTimeoutMs() ?? DEFAULT_TIMEOUT_MS;
30
58
  const controller = new AbortController();
31
59
  const timer = setTimeout(() => controller.abort(), timeoutMs);
32
60
  const headers = {
@@ -35,47 +63,39 @@ export const llmReranker = async (query, results, options) => {
35
63
  if (key) {
36
64
  headers.authorization = `Bearer ${key}`;
37
65
  }
38
- let permutation = null;
39
66
  try {
40
67
  const resp = await fetch(`${url.replace(/\/$/, '')}/chat/completions`, {
41
68
  method: 'POST',
42
69
  headers: { ...headers },
43
70
  body: JSON.stringify({
44
- model: process.env.HIPPO_LLM_RERANKER_MODEL ?? 'gpt-4o-mini',
71
+ model: envLlmRerankerModel() ?? 'gpt-4o-mini',
45
72
  messages: [{ role: 'user', content: prompt }],
46
73
  temperature: 0,
47
74
  }),
48
75
  signal: controller.signal,
49
76
  });
50
- if (resp.ok) {
51
- const j = await resp.json();
52
- const txt = j.choices?.[0]?.message?.content ?? '';
53
- const m = txt.match(/\[\s*(\d+(?:\s*,\s*\d+)*)\s*\]/);
54
- if (m) {
55
- const parsed = m[1].split(',').map((s) => parseInt(s.trim(), 10));
56
- if (parsed.length === head.length &&
57
- parsed.every((n) => Number.isInteger(n) && n >= 0 && n < head.length) &&
58
- new Set(parsed).size === head.length) {
59
- permutation = parsed;
60
- }
61
- }
77
+ if (!resp.ok) {
78
+ await resp.body?.cancel();
79
+ throw new Error(`HTTP ${resp.status}`);
62
80
  }
81
+ const j = await resp.json();
82
+ const txt = j.choices?.[0]?.message?.content ?? '';
83
+ const m = txt.match(/\[\s*(\d+(?:\s*,\s*\d+)*)\s*\]/);
84
+ const parsed = m ? m[1].split(',').map((s) => parseInt(s.trim(), 10)) : [];
85
+ const isPermutation = parsed.length === head.length &&
86
+ parsed.every((n) => Number.isInteger(n) && n >= 0 && n < head.length) &&
87
+ new Set(parsed).size === head.length;
88
+ if (!isPermutation)
89
+ throw new Error('reply is not a permutation of the candidates');
90
+ return parsed;
63
91
  }
64
- catch {
65
- // Fall through to identity. Includes AbortError on timeout — see
66
- // DEFAULT_TIMEOUT_MS / HIPPO_LLM_RERANKER_TIMEOUT_MS above.
92
+ catch (err) {
93
+ if (err instanceof Error && err.name === 'AbortError')
94
+ throw new Error(`no answer within ${timeoutMs} ms`);
95
+ throw err;
67
96
  }
68
97
  finally {
69
98
  clearTimeout(timer);
70
99
  }
71
- const ordered = permutation
72
- ? permutation.map((idx) => head[idx])
73
- : head;
74
- return ordered.map((r, i) => ({
75
- ...r,
76
- rerankScore: ordered.length - i,
77
- preRerankRank: r.preRerankRank ?? i + 1,
78
- postRerankRank: i + 1,
79
- }));
80
- };
100
+ }
81
101
  //# sourceMappingURL=llm.js.map
@@ -1,4 +1,4 @@
1
- import type { SearchResult } from '../search.js';
1
+ import type { SearchResult } from '../search/types.js';
2
2
  /**
3
3
  * A reranker reorders (and optionally rescales) the candidate set produced
4
4
  * by hybridSearch's BM25 + cosine + MMR pipeline. Rerankers run AFTER MMR
package/dist/salience.js CHANGED
@@ -5,7 +5,7 @@
5
5
  * Inspired by the biological salience network (anterior insula + dACC):
6
6
  * not everything that enters working memory deserves long-term storage.
7
7
  */
8
- import { textOverlap } from './search.js';
8
+ import { textOverlap } from './tokenize.js';
9
9
  import { duplicateKey, heldTextKeys } from './same-text.js';
10
10
  const DEFAULTS = {
11
11
  recentWindow: 20,
@@ -16,6 +16,7 @@ export interface SchedulerFsDeps {
16
16
  readFileSync: typeof fs.readFileSync;
17
17
  mkdirSync: typeof fs.mkdirSync;
18
18
  writeFileSync: typeof fs.writeFileSync;
19
+ renameSync: typeof fs.renameSync;
19
20
  }
20
21
  /** Test-only override. Not part of this module's public API surface. */
21
22
  export declare function __setSchedulerFsDeps(overrides: Partial<SchedulerFsDeps>): void;
package/dist/scheduler.js CHANGED
@@ -1,11 +1,13 @@
1
1
  import * as fs from 'fs';
2
2
  import * as path from 'path';
3
+ import { log } from './log.js';
3
4
  export const DAILY_TASK_NAME = 'hippo-daily-runner';
4
5
  let fsDeps = {
5
6
  existsSync: fs.existsSync,
6
7
  readFileSync: fs.readFileSync,
7
8
  mkdirSync: fs.mkdirSync,
8
9
  writeFileSync: fs.writeFileSync,
10
+ renameSync: fs.renameSync,
9
11
  };
10
12
  /** Test-only override. Not part of this module's public API surface. */
11
13
  export function __setSchedulerFsDeps(overrides) {
@@ -27,8 +29,16 @@ export function loadWorkspaceRegistry(globalRoot) {
27
29
  const registryPath = workspaceRegistryPath(globalRoot);
28
30
  if (!fsDeps.existsSync(registryPath))
29
31
  return defaultRegistry();
32
+ let text;
30
33
  try {
31
- const parsed = JSON.parse(fsDeps.readFileSync(registryPath, 'utf8'));
34
+ text = fsDeps.readFileSync(registryPath, 'utf8');
35
+ }
36
+ catch (err) {
37
+ log.warn(`workspace registry ${registryPath} could not be read (${err instanceof Error ? err.message : String(err)}); starting with no workspaces`);
38
+ return defaultRegistry();
39
+ }
40
+ try {
41
+ const parsed = JSON.parse(text);
32
42
  const workspaces = Array.isArray(parsed.workspaces)
33
43
  ? [...new Set(parsed.workspaces.map((entry) => normalizeWorkspace(String(entry))).filter(Boolean))].sort()
34
44
  : [];
@@ -37,13 +47,25 @@ export function loadWorkspaceRegistry(globalRoot) {
37
47
  workspaces,
38
48
  };
39
49
  }
40
- catch {
41
- // A missing or corrupt registry starts empty; the next registration rewrites it.
50
+ catch (err) {
51
+ // The next registration rewrites the file, so keep the bad copy for the user to recover entries from.
52
+ setAsideCorruptRegistry(registryPath, err);
42
53
  return defaultRegistry();
43
54
  }
44
55
  }
56
+ function setAsideCorruptRegistry(registryPath, err) {
57
+ const reason = err instanceof Error ? err.message : String(err);
58
+ const aside = `${registryPath}.corrupt-${new Date().toISOString().replace(/[:.]/g, '-')}`;
59
+ try {
60
+ fsDeps.renameSync(registryPath, aside);
61
+ log.warn(`workspace registry ${registryPath} is corrupt (${reason}); moved it to ${aside} and starting with no workspaces`);
62
+ }
63
+ catch (renameErr) {
64
+ log.warn(`workspace registry ${registryPath} is corrupt (${reason}) and could not be moved aside (${renameErr instanceof Error ? renameErr.message : String(renameErr)}); starting with no workspaces`);
65
+ }
66
+ }
45
67
  export function saveWorkspaceRegistry(globalRoot, registry) {
46
- fsDeps.mkdirSync(globalRoot, { recursive: true });
68
+ fsDeps.mkdirSync(globalRoot, { recursive: true, mode: 0o700 });
47
69
  fsDeps.writeFileSync(workspaceRegistryPath(globalRoot), JSON.stringify({
48
70
  version: 1,
49
71
  workspaces: [...new Set(registry.workspaces.map(normalizeWorkspace))].sort(),
package/dist/scope.js CHANGED
@@ -1,3 +1,4 @@
1
+ import { envGstackSkill, envOpenclawSkill, envScope } from './env.js';
1
2
  /**
2
3
  * Detect the current operational scope from environment signals.
3
4
  * Returns a scope name string (no prefix), or null if no scope detected.
@@ -6,13 +7,13 @@
6
7
  * Pure env var reads: no I/O, safe to call from hot paths (e.g. UserPromptSubmit hook).
7
8
  */
8
9
  export function detectScope() {
9
- const explicit = process.env['HIPPO_SCOPE'];
10
+ const explicit = envScope();
10
11
  if (explicit && explicit.trim())
11
12
  return explicit.trim();
12
- const gstackSkill = process.env['GSTACK_SKILL'];
13
+ const gstackSkill = envGstackSkill();
13
14
  if (gstackSkill && gstackSkill.trim())
14
15
  return gstackSkill.trim();
15
- const openclawSkill = process.env['OPENCLAW_SKILL'];
16
+ const openclawSkill = envOpenclawSkill();
16
17
  if (openclawSkill && openclawSkill.trim())
17
18
  return openclawSkill.trim();
18
19
  return null;
@@ -0,0 +1,10 @@
1
+ import type { MemoryEntry } from '../memory.js';
2
+ export interface CurrentnessOptions {
3
+ /** Keep only rows current at this ISO date string. */
4
+ asOf?: string;
5
+ /** Keep superseded rows when no `asOf` is given. */
6
+ includeSuperseded?: boolean;
7
+ }
8
+ /** Rows current at `asOf`, or rows not superseded unless `includeSuperseded`. */
9
+ export declare function currentEntries(entries: MemoryEntry[], options: CurrentnessOptions): MemoryEntry[];
10
+ //# sourceMappingURL=as-of.d.ts.map
@@ -0,0 +1,22 @@
1
+ /** Rows current at `asOf`, or rows not superseded unless `includeSuperseded`. */
2
+ export function currentEntries(entries, options) {
3
+ if (options.asOf)
4
+ return entriesAsOf(entries, new Date(options.asOf));
5
+ return options.includeSuperseded ? entries : entries.filter((e) => !e.superseded_by);
6
+ }
7
+ function entriesAsOf(entries, asOfDate) {
8
+ // A merged pool can repeat an id; the first row wins, as a scan from the front would pick.
9
+ const byId = new Map();
10
+ for (const e of entries)
11
+ if (!byId.has(e.id))
12
+ byId.set(e.id, e);
13
+ return entries.filter((e) => {
14
+ if (new Date(e.valid_from) > asOfDate)
15
+ return false;
16
+ if (!e.superseded_by)
17
+ return true;
18
+ const successor = byId.get(e.superseded_by);
19
+ return successor?.valid_from ? new Date(successor.valid_from) > asOfDate : true;
20
+ });
21
+ }
22
+ //# sourceMappingURL=as-of.js.map
@@ -0,0 +1,14 @@
1
+ import type { MemoryEntry } from '../memory.js';
2
+ import type { ResultCost, SearchResult } from './types.js';
3
+ export interface SearchOptions {
4
+ budget?: number;
5
+ now?: Date;
6
+ hippoRoot?: string;
7
+ minResults?: number;
8
+ cost?: ResultCost;
9
+ includeSuperseded?: boolean;
10
+ asOf?: string;
11
+ }
12
+ /** Synchronous BM25 search: relevance * strength * recency and the rank boosts, without embeddings or the outcome nudge. */
13
+ export declare function search(query: string, entries: MemoryEntry[], options?: SearchOptions): SearchResult[];
14
+ //# sourceMappingURL=bm25-search.d.ts.map
@@ -0,0 +1,43 @@
1
+ import { estimateTokens } from '../token-ledger.js';
2
+ import { tokenize } from '../tokenize.js';
3
+ import { evalNow } from '../ablation.js';
4
+ import { extractPathTags } from '../path-context.js';
5
+ import { detectScope } from '../scope.js';
6
+ import { compareScoredResults } from '../compare.js';
7
+ import { bm25Score, buildCorpus, entryText } from './bm25.js';
8
+ import { currentEntries } from './as-of.js';
9
+ import { applyRankBoosts, strengthRecencyMultipliers, NO_SUMMARY_SCORING } from './boosts.js';
10
+ import { temporalContext } from './temporal.js';
11
+ import { dedupeExtracted, fitBudget, withDagChildren } from './finalize.js';
12
+ /** Synchronous BM25 search: relevance * strength * recency and the rank boosts, without embeddings or the outcome nudge. */
13
+ export function search(query, entries, options = {}) {
14
+ const now = options.now ?? evalNow(); // honors HIPPO_FAKE_NOW (eval-only; see ablation.ts)
15
+ const pool = currentEntries(entries, options);
16
+ if (pool.length === 0)
17
+ return [];
18
+ const queryTerms = tokenize(query);
19
+ if (queryTerms.length === 0)
20
+ return [];
21
+ const corpus = buildCorpus(pool.map(entryText));
22
+ const ctx = {
23
+ now,
24
+ pathTags: extractPathTags(process.cwd()),
25
+ scope: detectScope(),
26
+ temporal: temporalContext(query, pool),
27
+ outcome: false,
28
+ summary: NO_SUMMARY_SCORING,
29
+ };
30
+ const scored = [];
31
+ for (let i = 0; i < pool.length; i++) {
32
+ const bm25 = bm25Score(corpus, i, queryTerms);
33
+ if (bm25 <= 0)
34
+ continue;
35
+ const { strength, recency } = strengthRecencyMultipliers(pool[i], now);
36
+ const normBm25 = bm25 / queryTerms.length;
37
+ const score = applyRankBoosts(normBm25 * strength * recency, pool[i], ctx).score;
38
+ scored.push({ entry: pool[i], score, bm25, cosine: 0, tokens: estimateTokens(pool[i].content) });
39
+ }
40
+ scored.sort(compareScoredResults);
41
+ return fitBudget(withDagChildren(dedupeExtracted(scored), pool), options.budget ?? 4000, options.minResults ?? 1, options.cost);
42
+ }
43
+ //# sourceMappingURL=bm25-search.js.map
@@ -0,0 +1,15 @@
1
+ import type { MemoryEntry } from '../memory.js';
2
+ /** Tokenized BM25 corpus; build it once with `buildCorpus` and reuse it across queries on the same entry set. */
3
+ export interface BM25Corpus {
4
+ docs: string[][];
5
+ avgLen: number;
6
+ df: Map<string, number>;
7
+ N: number;
8
+ }
9
+ /** The text BM25 indexes for an entry: its content followed by its tags. */
10
+ export declare function entryText(entry: MemoryEntry): string;
11
+ export declare function buildCorpus(texts: string[]): BM25Corpus;
12
+ export declare function bm25Score(corpus: BM25Corpus, docIdx: number, queryTerms: string[]): number;
13
+ /** Query terms that appear in the entry's indexed text, in query order. */
14
+ export declare function matchedQueryTerms(queryTerms: Iterable<string>, entry: MemoryEntry): string[];
15
+ //# sourceMappingURL=bm25.d.ts.map
@@ -0,0 +1,54 @@
1
+ import { tokenize } from '../tokenize.js';
2
+ const BM25_K1 = 1.5;
3
+ const BM25_B = 0.75;
4
+ /** The text BM25 indexes for an entry: its content followed by its tags. */
5
+ export function entryText(entry) {
6
+ return `${entry.content} ${entry.tags.join(' ')}`;
7
+ }
8
+ export function buildCorpus(texts) {
9
+ const docs = texts.map(tokenize);
10
+ const N = docs.length;
11
+ const df = new Map();
12
+ let totalLen = 0;
13
+ for (const doc of docs) {
14
+ totalLen += doc.length;
15
+ const seen = new Set();
16
+ for (const term of doc) {
17
+ if (!seen.has(term)) {
18
+ df.set(term, (df.get(term) ?? 0) + 1);
19
+ seen.add(term);
20
+ }
21
+ }
22
+ }
23
+ const avgLen = N > 0 ? totalLen / N : 1;
24
+ return { docs, avgLen, df, N };
25
+ }
26
+ export function bm25Score(corpus, docIdx, queryTerms) {
27
+ const doc = corpus.docs[docIdx];
28
+ const docLen = doc.length;
29
+ let score = 0;
30
+ const tf = new Map();
31
+ for (const t of doc)
32
+ tf.set(t, (tf.get(t) ?? 0) + 1);
33
+ for (const term of queryTerms) {
34
+ const f = tf.get(term) ?? 0;
35
+ if (f === 0)
36
+ continue;
37
+ const df = corpus.df.get(term) ?? 0;
38
+ const idf = Math.log((corpus.N - df + 0.5) / (df + 0.5) + 1);
39
+ const numerator = f * (BM25_K1 + 1);
40
+ const denominator = f + BM25_K1 * (1 - BM25_B + BM25_B * (docLen / corpus.avgLen));
41
+ score += idf * (numerator / denominator);
42
+ }
43
+ return score;
44
+ }
45
+ /** Query terms that appear in the entry's indexed text, in query order. */
46
+ export function matchedQueryTerms(queryTerms, entry) {
47
+ const docTerms = new Set(tokenize(entryText(entry)));
48
+ const matched = [];
49
+ for (const t of queryTerms)
50
+ if (docTerms.has(t))
51
+ matched.push(t);
52
+ return matched;
53
+ }
54
+ //# sourceMappingURL=bm25.js.map