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,7 @@
1
+ import { envJevModel, envJevTimeoutMs, envTypesafeApiKey } from '../env.js';
1
2
  import { crossEncoderReranker } from './cross-encoder.js';
2
- import { redactSecrets } from '../secret-detect.js';
3
+ import { redactSecretsStrict } from '../secret-detect.js';
4
+ import { log } from '../log.js';
3
5
  const ENDPOINT = 'https://api.typesafe.ai/v1/systemone';
4
6
  const DEFAULT_TIMEOUT_MS = 5_000;
5
7
  const TRUNCATE_CHARS = 1200;
@@ -30,8 +32,9 @@ function parseScores(answers, n) {
30
32
  }
31
33
  /** Redacted query plus numbered, redacted, truncated candidates. Shared with CLEF so both arms see matched input. */
32
34
  export function buildRelevanceRequest(query, head) {
33
- const lines = head.map((r, i) => `[${i + 1}] ${truncate(redactSecrets(r.entry.content), TRUNCATE_CHARS)}`);
34
- const state = `Query: ${redactSecrets(query)}\n\nNumbered candidate memories from an AI coding agent's project store:\n\n${lines.join('\n\n')}`;
35
+ // Strict: this text leaves the machine, so Bearer, Basic-auth and JWT shapes go too.
36
+ const lines = head.map((r, i) => `[${i + 1}] ${truncate(redactSecretsStrict(r.entry.content), TRUNCATE_CHARS)}`);
37
+ const state = `Query: ${redactSecretsStrict(query)}\n\nNumbered candidate memories from an AI coding agent's project store:\n\n${lines.join('\n\n')}`;
35
38
  const questions = {};
36
39
  for (let i = 1; i <= head.length; i++) {
37
40
  questions[`c${i}`] = {
@@ -43,12 +46,11 @@ export function buildRelevanceRequest(query, head) {
43
46
  }
44
47
  /** One batched request for the whole candidate list. Rejects with the reason when there are no usable scores. */
45
48
  async function requestScores(query, head) {
46
- const key = process.env.TYPESAFE_API_KEY;
49
+ const key = envTypesafeApiKey();
47
50
  if (!key)
48
51
  throw new Error('TYPESAFE_API_KEY not set');
49
52
  const { state, questions } = buildRelevanceRequest(query, head);
50
- const parsed = Number.parseInt(process.env.HIPPO_JEV_TIMEOUT_MS ?? '', 10);
51
- const timeoutMs = parsed > 0 ? parsed : DEFAULT_TIMEOUT_MS;
53
+ const timeoutMs = envJevTimeoutMs() ?? DEFAULT_TIMEOUT_MS;
52
54
  const controller = new AbortController();
53
55
  const timer = setTimeout(() => controller.abort(), timeoutMs);
54
56
  try {
@@ -57,7 +59,7 @@ async function requestScores(query, head) {
57
59
  headers: { 'content-type': 'application/json', authorization: `Bearer ${key}` },
58
60
  body: JSON.stringify({
59
61
  state,
60
- model: process.env.HIPPO_JEV_MODEL ?? DEFAULT_MODEL,
62
+ model: envJevModel() ?? DEFAULT_MODEL,
61
63
  questions,
62
64
  }),
63
65
  signal: controller.signal,
@@ -101,23 +103,26 @@ export function createJevReranker(localFallback) {
101
103
  if (!warned) {
102
104
  warned = true;
103
105
  const reason = err instanceof Error ? err.message : 'unknown error';
104
- // eslint-disable-next-line no-console
105
- console.warn(`[hippo] jev reranker unavailable (${reason}); falling back to the local cross-encoder. Subsequent calls will not repeat this warning.`);
106
+ log.warn(`jev reranker unavailable (${reason}); falling back to the local cross-encoder. Subsequent calls will not repeat this warning.`);
106
107
  }
107
108
  return localFallback(query, head, options);
108
109
  }
109
- const scored = head.map((r, i) => ({
110
- ...r,
111
- rerankScore: scores[i],
112
- preRerankRank: r.preRerankRank ?? i + 1,
113
- postRerankRank: 0,
114
- }));
115
- // Stable sort: ties fall back to the prior relevance order.
116
- scored.sort((a, b) => b.rerankScore - a.rerankScore);
117
- scored.forEach((r, i) => (r.postRerankRank = i + 1));
118
- return scored;
110
+ return rankByScores(head, scores);
119
111
  };
120
112
  }
113
+ /** Orders `head` by `scores[i]`, keeping any upstream pre-rerank rank. Shared with CLEF. */
114
+ export function rankByScores(head, scores) {
115
+ const scored = head.map((r, i) => ({
116
+ ...r,
117
+ rerankScore: scores[i],
118
+ preRerankRank: r.preRerankRank ?? i + 1,
119
+ postRerankRank: 0,
120
+ }));
121
+ // Stable sort: ties fall back to the prior relevance order.
122
+ scored.sort((a, b) => b.rerankScore - a.rerankScore);
123
+ scored.forEach((r, i) => (r.postRerankRank = i + 1));
124
+ return scored;
125
+ }
121
126
  /** Track 4 reranker: hosted TypeSafe Jev, opt-in and paid (TYPESAFE_API_KEY), one batched call per recall.
122
127
  * Any failure warns once and delegates to the local cross-encoder. Scores are not bit-stable run to run.
123
128
  * Cost, env vars, evidence and limits: docs/evals/2026-09-19-jev-reranker.md. */
@@ -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 { redactSecrets } from '../secret-detect.js';
1
+ import { envLlmRerankerKey, envLlmRerankerModel, envLlmRerankerTimeoutMs, envLlmRerankerUrl } from '../env.js';
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
- `Query: ${redactSecrets(query)}`,
26
- ...head.map((r, i) => `[${i}] ${redactSecrets(r.entry.content)}`),
53
+ `Query: ${redactSecretsStrict(query)}`,
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,
@@ -10,6 +10,8 @@ export declare function mergedText(header: string, texts: readonly string[]): st
10
10
  export declare function heldTexts(entry: Text): string[];
11
11
  /** Keys of every text a row holds word for word: its own, plus each source text inside a sleep-merged row. */
12
12
  export declare function heldTextKeys(entry: Text): string[];
13
+ /** The longest word of a text: every row holding the text word for word contains it, so a store lookup can filter on it. */
14
+ export declare function longestWord(text: string): string;
13
15
  export declare function storedTextKeys(entries: readonly Text[]): Set<string>;
14
16
  /** A final result list without copies: drops each unpinned row a sleep-merged row in the list holds word for word, and each later unpinned copy of a text. */
15
17
  export declare function dropHeldCopies<T>(rows: readonly T[], textOf: (row: T) => Text): T[];
package/dist/same-text.js CHANGED
@@ -19,6 +19,10 @@ export function heldTexts(entry) {
19
19
  export function heldTextKeys(entry) {
20
20
  return [duplicateKey(entry.content), ...heldTexts(entry).map(duplicateKey)];
21
21
  }
22
+ /** The longest word of a text: every row holding the text word for word contains it, so a store lookup can filter on it. */
23
+ export function longestWord(text) {
24
+ return duplicateKey(text).split(' ').reduce((best, w) => (w.length > best.length ? w : best), '');
25
+ }
22
26
  export function storedTextKeys(entries) {
23
27
  return new Set(entries.flatMap(heldTextKeys));
24
28
  }
@@ -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,12 +47,25 @@ export function loadWorkspaceRegistry(globalRoot) {
37
47
  workspaces,
38
48
  };
39
49
  }
40
- catch {
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);
41
53
  return defaultRegistry();
42
54
  }
43
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
+ }
44
67
  export function saveWorkspaceRegistry(globalRoot, registry) {
45
- fsDeps.mkdirSync(globalRoot, { recursive: true });
68
+ fsDeps.mkdirSync(globalRoot, { recursive: true, mode: 0o700 });
46
69
  fsDeps.writeFileSync(workspaceRegistryPath(globalRoot), JSON.stringify({
47
70
  version: 1,
48
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
@@ -0,0 +1,54 @@
1
+ import { type MemoryEntry } from '../memory.js';
2
+ import { type TemporalDirection, type TemporalRange } from './temporal.js';
3
+ export declare const CHURN_STALE_RANK_MULTIPLIER = 0.5;
4
+ export declare function churnStaleFactor(entry: MemoryEntry): number;
5
+ export declare function recencyBoost(entry: MemoryEntry, now: Date): number;
6
+ /** Retrieval-time outcome nudge in [0.85, 1.15]; the bm25-outcome eval baseline ranks with it too. */
7
+ export declare function outcomeMultiplier(entry: MemoryEntry): number;
8
+ /** A DAG summary is a topic summary (level 2) or an entity profile (level 3); both take the same deboost. */
9
+ export declare function isDagSummary(entry: MemoryEntry): boolean;
10
+ /** Summary deboost: per-call, then HIPPO_SUMMARY_DEBOOST, then 0.85; values outside (0, 1] fall through. */
11
+ export declare function resolveSummaryDeboost(perCall?: number): number;
12
+ export interface SummaryScoring {
13
+ deboost: number;
14
+ freshness: boolean;
15
+ }
16
+ /** The sync BM25 path applies no summary scoring; multiplying by exactly 1 keeps its scores bit-identical. */
17
+ export declare const NO_SUMMARY_SCORING: SummaryScoring;
18
+ export declare function summaryScoring(options: {
19
+ summaryDeboost?: number;
20
+ summaryFreshness?: boolean;
21
+ }): SummaryScoring;
22
+ export declare function summaryMultipliers(entry: MemoryEntry, now: Date, s: SummaryScoring): {
23
+ deboost: number;
24
+ freshness: number;
25
+ };
26
+ export declare function strengthRecencyMultipliers(entry: MemoryEntry, now: Date): {
27
+ strength: number;
28
+ recency: number;
29
+ };
30
+ export interface BoostContext {
31
+ now: Date;
32
+ pathTags: string[];
33
+ scope: string | null;
34
+ temporal: {
35
+ direction: TemporalDirection;
36
+ range: TemporalRange;
37
+ };
38
+ /** The sync BM25 path never applied the outcome nudge. */
39
+ outcome: boolean;
40
+ summary: SummaryScoring;
41
+ }
42
+ export interface AppliedBoosts {
43
+ score: number;
44
+ decisionBoost: number;
45
+ churnStaleMultiplier: number;
46
+ pathBoost: number;
47
+ outcomeBoost: number;
48
+ scopeBoost: number;
49
+ summaryDeboost: number;
50
+ summaryFreshnessBoost: number;
51
+ }
52
+ /** Applies every rank multiplier one at a time, in a fixed order, so float rounding matches across paths. */
53
+ export declare function applyRankBoosts(score: number, entry: MemoryEntry, ctx: BoostContext): AppliedBoosts;
54
+ //# sourceMappingURL=boosts.d.ts.map