hippo-memory 1.60.0 → 1.62.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 (593) hide show
  1. package/README.md +29 -54
  2. package/dist/ablation.js +9 -27
  3. package/dist/agent-memories/apply.d.ts +1 -1
  4. package/dist/agent-memories/apply.js +4 -1
  5. package/dist/agent-memories/claude-code.d.ts +3 -1
  6. package/dist/agent-memories/claude-code.js +54 -10
  7. package/dist/agent-memories/codex.js +1 -1
  8. package/dist/agent-memories/gemini.js +1 -1
  9. package/dist/agent-memories/legacy.js +1 -1
  10. package/dist/agent-memories/source.js +1 -1
  11. package/dist/agent-memories/sync.d.ts +3 -3
  12. package/dist/agent-memories/sync.js +22 -9
  13. package/dist/agent-memories/types.d.ts +0 -2
  14. package/dist/ambient-store.d.ts +14 -0
  15. package/dist/ambient-store.js +90 -0
  16. package/dist/ambient.d.ts +23 -0
  17. package/dist/ambient.js +72 -50
  18. package/dist/api/assemble.d.ts +93 -0
  19. package/dist/api/assemble.js +153 -0
  20. package/dist/api/audit.d.ts +17 -0
  21. package/dist/api/audit.js +23 -0
  22. package/dist/api/auth.d.ts +79 -0
  23. package/dist/api/auth.js +178 -0
  24. package/dist/api/context-select.d.ts +49 -0
  25. package/dist/api/context-select.js +344 -0
  26. package/dist/api/context-types.d.ts +105 -0
  27. package/dist/api/context-types.js +3 -0
  28. package/dist/api/context.d.ts +31 -0
  29. package/dist/api/context.js +378 -0
  30. package/dist/api/dormant.d.ts +30 -0
  31. package/dist/api/dormant.js +140 -0
  32. package/dist/api/drill-down.d.ts +84 -0
  33. package/dist/api/drill-down.js +126 -0
  34. package/dist/api/forget.d.ts +57 -0
  35. package/dist/api/forget.js +87 -0
  36. package/dist/api/goals.d.ts +18 -0
  37. package/dist/api/goals.js +33 -0
  38. package/dist/api/learn.d.ts +31 -0
  39. package/dist/api/learn.js +88 -0
  40. package/dist/api/outcome.d.ts +61 -0
  41. package/dist/api/outcome.js +66 -0
  42. package/dist/api/promote.d.ts +54 -0
  43. package/dist/api/promote.js +192 -0
  44. package/dist/api/quarantine.d.ts +24 -0
  45. package/dist/api/quarantine.js +121 -0
  46. package/dist/api/recall-types.d.ts +390 -0
  47. package/dist/api/recall-types.js +3 -0
  48. package/dist/api/recall.d.ts +36 -0
  49. package/dist/api/recall.js +499 -0
  50. package/dist/api/remember.d.ts +35 -0
  51. package/dist/api/remember.js +43 -0
  52. package/dist/api/sleep.d.ts +136 -0
  53. package/dist/api/sleep.js +256 -0
  54. package/dist/api/tokens.d.ts +26 -0
  55. package/dist/api/tokens.js +60 -0
  56. package/dist/api/types.d.ts +56 -0
  57. package/dist/api/types.js +38 -0
  58. package/dist/api.d.ts +20 -1262
  59. package/dist/api.js +25 -2727
  60. package/dist/audit.d.ts +3 -0
  61. package/dist/audit.js +6 -3
  62. package/dist/auth.d.ts +45 -4
  63. package/dist/auth.js +125 -48
  64. package/dist/autolearn.js +2 -2
  65. package/dist/capture/command.d.ts +33 -0
  66. package/dist/capture/command.js +264 -0
  67. package/dist/capture/compact.d.ts +44 -0
  68. package/dist/capture/compact.js +354 -0
  69. package/dist/capture/extract.d.ts +21 -0
  70. package/dist/capture/extract.js +464 -0
  71. package/dist/capture/transcript.d.ts +40 -0
  72. package/dist/capture/transcript.js +193 -0
  73. package/dist/capture-error.js +2 -1
  74. package/dist/churn-git.js +4 -2
  75. package/dist/cli/audit.d.ts +3 -0
  76. package/dist/cli/audit.js +159 -0
  77. package/dist/cli/auth.d.ts +2 -0
  78. package/dist/cli/auth.js +171 -0
  79. package/dist/cli/briefs.d.ts +4 -0
  80. package/dist/cli/briefs.js +453 -0
  81. package/dist/cli/card.d.ts +3 -0
  82. package/dist/cli/card.js +333 -0
  83. package/dist/cli/context.d.ts +15 -0
  84. package/dist/cli/context.js +376 -0
  85. package/dist/cli/continuity.d.ts +6 -0
  86. package/dist/cli/continuity.js +457 -0
  87. package/dist/cli/curate.d.ts +19 -0
  88. package/dist/cli/curate.js +556 -0
  89. package/dist/cli/dag.d.ts +5 -0
  90. package/dist/cli/dag.js +177 -0
  91. package/dist/cli/decisions.d.ts +4 -0
  92. package/dist/cli/decisions.js +528 -0
  93. package/dist/cli/eval.d.ts +5 -0
  94. package/dist/cli/eval.js +213 -0
  95. package/dist/cli/explain.d.ts +4 -0
  96. package/dist/cli/explain.js +156 -0
  97. package/dist/cli/goals.d.ts +2 -0
  98. package/dist/cli/goals.js +196 -0
  99. package/dist/cli/hook-blocks.d.ts +18 -0
  100. package/dist/cli/hook-blocks.js +233 -0
  101. package/dist/cli/init.d.ts +2 -0
  102. package/dist/cli/init.js +305 -0
  103. package/dist/cli/maintenance.d.ts +4 -0
  104. package/dist/cli/maintenance.js +190 -0
  105. package/dist/cli/playbooks.d.ts +4 -0
  106. package/dist/cli/playbooks.js +573 -0
  107. package/dist/cli/projects.js +9 -6
  108. package/dist/cli/recall.d.ts +7 -0
  109. package/dist/cli/recall.js +582 -0
  110. package/dist/cli/remember.d.ts +5 -0
  111. package/dist/cli/remember.js +485 -0
  112. package/dist/cli/serve.d.ts +5 -0
  113. package/dist/cli/serve.js +40 -0
  114. package/dist/cli/session-hooks.d.ts +29 -0
  115. package/dist/cli/session-hooks.js +647 -0
  116. package/dist/cli/setup.d.ts +4 -0
  117. package/dist/cli/setup.js +397 -0
  118. package/dist/cli/shared.d.ts +15 -19
  119. package/dist/cli/shared.js +50 -341
  120. package/dist/cli/slack.d.ts +2 -0
  121. package/dist/cli/slack.js +171 -0
  122. package/dist/cli/status.d.ts +18 -0
  123. package/dist/cli/status.js +409 -0
  124. package/dist/cli/transfer.d.ts +10 -0
  125. package/dist/cli/transfer.js +424 -0
  126. package/dist/cli/usage.d.ts +85 -0
  127. package/dist/cli/usage.js +741 -0
  128. package/dist/cli.d.ts +71 -120
  129. package/dist/cli.js +170 -8469
  130. package/dist/client.js +15 -8
  131. package/dist/compaction-record.d.ts +0 -2
  132. package/dist/compaction-record.js +7 -5
  133. package/dist/connectors/github/backfill.js +94 -87
  134. package/dist/connectors/github/cli-impl.js +4 -3
  135. package/dist/connectors/github/dlq.js +67 -54
  136. package/dist/connectors/github/ingest.js +34 -35
  137. package/dist/connectors/github/tenant-routing.js +3 -2
  138. package/dist/connectors/github/webhook.js +135 -216
  139. package/dist/connectors/slack/dlq.js +49 -61
  140. package/dist/connectors/slack/ingest.js +55 -48
  141. package/dist/connectors/slack/tenant-routing.js +4 -3
  142. package/dist/connectors/slack/webhook.js +72 -74
  143. package/dist/consolidate/conflicts.d.ts +10 -0
  144. package/dist/consolidate/conflicts.js +178 -0
  145. package/dist/consolidate/decay.d.ts +12 -0
  146. package/dist/consolidate/decay.js +145 -0
  147. package/dist/consolidate/llm-passes.d.ts +3 -0
  148. package/dist/consolidate/llm-passes.js +141 -0
  149. package/dist/consolidate/merge.d.ts +7 -0
  150. package/dist/consolidate/merge.js +251 -0
  151. package/dist/consolidate/physics-pass.d.ts +3 -0
  152. package/dist/consolidate/physics-pass.js +60 -0
  153. package/dist/consolidate/run.d.ts +69 -0
  154. package/dist/consolidate/run.js +76 -0
  155. package/dist/consolidate/sleep.d.ts +18 -0
  156. package/dist/consolidate/sleep.js +209 -0
  157. package/dist/consolidate/traces.d.ts +4 -0
  158. package/dist/consolidate/traces.js +178 -0
  159. package/dist/context-auto.js +7 -11
  160. package/dist/context-render.d.ts +1 -1
  161. package/dist/context-render.js +1 -1
  162. package/dist/customer-notes.d.ts +3 -0
  163. package/dist/customer-notes.js +83 -72
  164. package/dist/dag.js +225 -188
  165. package/dist/dashboard-actions.d.ts +20 -0
  166. package/dist/dashboard-actions.js +88 -0
  167. package/dist/dashboard-params.d.ts +45 -0
  168. package/dist/dashboard-params.js +127 -0
  169. package/dist/dashboard-queries.d.ts +15 -0
  170. package/dist/dashboard-queries.js +355 -0
  171. package/dist/dashboard-snapshot.d.ts +138 -0
  172. package/dist/dashboard-snapshot.js +308 -0
  173. package/dist/dashboard-types.d.ts +163 -0
  174. package/dist/dashboard-types.js +3 -0
  175. package/dist/dashboard.d.ts +6 -7
  176. package/dist/dashboard.js +228 -202
  177. package/dist/db/busy.d.ts +5 -0
  178. package/dist/db/busy.js +24 -0
  179. package/dist/db/continuity.d.ts +5 -0
  180. package/dist/db/continuity.js +145 -0
  181. package/dist/db/meta.d.ts +8 -0
  182. package/dist/db/meta.js +35 -0
  183. package/dist/db/migrate.d.ts +9 -0
  184. package/dist/db/migrate.js +138 -0
  185. package/dist/db/migrations/index.d.ts +5 -0
  186. package/dist/db/migrations/index.js +109 -0
  187. package/dist/db/migrations/types.d.ts +14 -0
  188. package/dist/db/migrations/types.js +2 -0
  189. package/dist/db/migrations/v01.d.ts +3 -0
  190. package/dist/db/migrations/v01.js +38 -0
  191. package/dist/db/migrations/v02.d.ts +3 -0
  192. package/dist/db/migrations/v02.js +21 -0
  193. package/dist/db/migrations/v03.d.ts +3 -0
  194. package/dist/db/migrations/v03.js +22 -0
  195. package/dist/db/migrations/v04.d.ts +3 -0
  196. package/dist/db/migrations/v04.js +28 -0
  197. package/dist/db/migrations/v05.d.ts +3 -0
  198. package/dist/db/migrations/v05.js +21 -0
  199. package/dist/db/migrations/v06.d.ts +3 -0
  200. package/dist/db/migrations/v06.js +25 -0
  201. package/dist/db/migrations/v07.d.ts +3 -0
  202. package/dist/db/migrations/v07.js +13 -0
  203. package/dist/db/migrations/v08.d.ts +3 -0
  204. package/dist/db/migrations/v08.js +8 -0
  205. package/dist/db/migrations/v09.d.ts +3 -0
  206. package/dist/db/migrations/v09.js +13 -0
  207. package/dist/db/migrations/v10.d.ts +3 -0
  208. package/dist/db/migrations/v10.js +17 -0
  209. package/dist/db/migrations/v11.d.ts +3 -0
  210. package/dist/db/migrations/v11.js +15 -0
  211. package/dist/db/migrations/v12.d.ts +3 -0
  212. package/dist/db/migrations/v12.js +11 -0
  213. package/dist/db/migrations/v13.d.ts +3 -0
  214. package/dist/db/migrations/v13.js +15 -0
  215. package/dist/db/migrations/v14.d.ts +3 -0
  216. package/dist/db/migrations/v14.js +66 -0
  217. package/dist/db/migrations/v15.d.ts +3 -0
  218. package/dist/db/migrations/v15.js +42 -0
  219. package/dist/db/migrations/v16.d.ts +3 -0
  220. package/dist/db/migrations/v16.js +61 -0
  221. package/dist/db/migrations/v17.d.ts +3 -0
  222. package/dist/db/migrations/v17.js +46 -0
  223. package/dist/db/migrations/v18.d.ts +3 -0
  224. package/dist/db/migrations/v18.js +60 -0
  225. package/dist/db/migrations/v19.d.ts +3 -0
  226. package/dist/db/migrations/v19.js +28 -0
  227. package/dist/db/migrations/v20.d.ts +3 -0
  228. package/dist/db/migrations/v20.js +42 -0
  229. package/dist/db/migrations/v21.d.ts +3 -0
  230. package/dist/db/migrations/v21.js +16 -0
  231. package/dist/db/migrations/v22.d.ts +3 -0
  232. package/dist/db/migrations/v22.js +82 -0
  233. package/dist/db/migrations/v23.d.ts +3 -0
  234. package/dist/db/migrations/v23.js +48 -0
  235. package/dist/db/migrations/v24.d.ts +3 -0
  236. package/dist/db/migrations/v24.js +72 -0
  237. package/dist/db/migrations/v25.d.ts +3 -0
  238. package/dist/db/migrations/v25.js +46 -0
  239. package/dist/db/migrations/v26.d.ts +3 -0
  240. package/dist/db/migrations/v26.js +23 -0
  241. package/dist/db/migrations/v27.d.ts +3 -0
  242. package/dist/db/migrations/v27.js +57 -0
  243. package/dist/db/migrations/v28.d.ts +3 -0
  244. package/dist/db/migrations/v28.js +38 -0
  245. package/dist/db/migrations/v29.d.ts +3 -0
  246. package/dist/db/migrations/v29.js +78 -0
  247. package/dist/db/migrations/v30.d.ts +3 -0
  248. package/dist/db/migrations/v30.js +92 -0
  249. package/dist/db/migrations/v31.d.ts +3 -0
  250. package/dist/db/migrations/v31.js +74 -0
  251. package/dist/db/migrations/v32.d.ts +3 -0
  252. package/dist/db/migrations/v32.js +102 -0
  253. package/dist/db/migrations/v33.d.ts +3 -0
  254. package/dist/db/migrations/v33.js +104 -0
  255. package/dist/db/migrations/v34.d.ts +3 -0
  256. package/dist/db/migrations/v34.js +93 -0
  257. package/dist/db/migrations/v35.d.ts +3 -0
  258. package/dist/db/migrations/v35.js +98 -0
  259. package/dist/db/migrations/v36.d.ts +3 -0
  260. package/dist/db/migrations/v36.js +98 -0
  261. package/dist/db/migrations/v37.d.ts +3 -0
  262. package/dist/db/migrations/v37.js +219 -0
  263. package/dist/db/migrations/v38.d.ts +3 -0
  264. package/dist/db/migrations/v38.js +277 -0
  265. package/dist/db/migrations/v39.d.ts +3 -0
  266. package/dist/db/migrations/v39.js +59 -0
  267. package/dist/db/migrations/v40.d.ts +3 -0
  268. package/dist/db/migrations/v40.js +74 -0
  269. package/dist/db/migrations/v41.d.ts +3 -0
  270. package/dist/db/migrations/v41.js +43 -0
  271. package/dist/db/migrations/v42.d.ts +3 -0
  272. package/dist/db/migrations/v42.js +41 -0
  273. package/dist/db/migrations/v43.d.ts +3 -0
  274. package/dist/db/migrations/v43.js +67 -0
  275. package/dist/db/migrations/v44.d.ts +3 -0
  276. package/dist/db/migrations/v44.js +28 -0
  277. package/dist/db/migrations/v45.d.ts +3 -0
  278. package/dist/db/migrations/v45.js +30 -0
  279. package/dist/db/migrations/v46.d.ts +3 -0
  280. package/dist/db/migrations/v46.js +25 -0
  281. package/dist/db/migrations/v47.d.ts +3 -0
  282. package/dist/db/migrations/v47.js +17 -0
  283. package/dist/db/migrations/v48.d.ts +3 -0
  284. package/dist/db/migrations/v48.js +10 -0
  285. package/dist/db/migrations/v49.d.ts +3 -0
  286. package/dist/db/migrations/v49.js +31 -0
  287. package/dist/db/migrations/v50.d.ts +3 -0
  288. package/dist/db/migrations/v50.js +67 -0
  289. package/dist/db/migrations/v51.d.ts +3 -0
  290. package/dist/db/migrations/v51.js +14 -0
  291. package/dist/db/migrations/v52.d.ts +3 -0
  292. package/dist/db/migrations/v52.js +7 -0
  293. package/dist/db/open.d.ts +23 -0
  294. package/dist/db/open.js +146 -0
  295. package/dist/db/sqlite.d.ts +21 -0
  296. package/dist/db/sqlite.js +8 -0
  297. package/dist/db/tables.d.ts +7 -0
  298. package/dist/db/tables.js +38 -0
  299. package/dist/db.d.ts +6 -46
  300. package/dist/db.js +5 -3049
  301. package/dist/decisions.d.ts +4 -1
  302. package/dist/decisions.js +102 -83
  303. package/dist/dedupe.js +3 -2
  304. package/dist/delivery-recorder.js +4 -1
  305. package/dist/doctor.js +14 -10
  306. package/dist/embedding-provider.d.ts +1 -1
  307. package/dist/embedding-provider.js +4 -3
  308. package/dist/embeddings.d.ts +9 -52
  309. package/dist/embeddings.js +43 -297
  310. package/dist/env.d.ts +75 -0
  311. package/dist/env.js +119 -0
  312. package/dist/eval-suite.js +1 -1
  313. package/dist/eval.js +2 -2
  314. package/dist/extract.js +1 -1
  315. package/dist/gated-write.js +3 -1
  316. package/dist/goals.d.ts +3 -1
  317. package/dist/goals.js +117 -86
  318. package/dist/graph/read.d.ts +73 -0
  319. package/dist/graph/read.js +325 -0
  320. package/dist/graph/rows.d.ts +45 -0
  321. package/dist/graph/rows.js +51 -0
  322. package/dist/graph/types.d.ts +83 -0
  323. package/dist/graph/types.js +11 -0
  324. package/dist/graph/write.d.ts +93 -0
  325. package/dist/{graph.js → graph/write.js} +6 -384
  326. package/dist/graph-extract.js +2 -1
  327. package/dist/graph-recall.d.ts +1 -1
  328. package/dist/graph-recall.js +2 -2
  329. package/dist/graph-stream.js +1 -1
  330. package/dist/graph-view.d.ts +1 -1
  331. package/dist/graph-view.js +1 -1
  332. package/dist/half-life-migration.d.ts +1 -1
  333. package/dist/half-life-migration.js +2 -1
  334. package/dist/hooks/codex-session.d.ts +8 -0
  335. package/dist/hooks/codex-session.js +76 -0
  336. package/dist/hooks/codex-wrapper.d.ts +55 -0
  337. package/dist/hooks/codex-wrapper.js +288 -0
  338. package/dist/hooks/json-hooks.d.ts +63 -0
  339. package/dist/hooks/json-hooks.js +356 -0
  340. package/dist/hooks/opencode.d.ts +50 -0
  341. package/dist/hooks/opencode.js +202 -0
  342. package/dist/hooks/shared.d.ts +54 -0
  343. package/dist/hooks/shared.js +77 -0
  344. package/dist/http-retry.d.ts +2 -0
  345. package/dist/http-retry.js +4 -3
  346. package/dist/http-util.d.ts +3 -0
  347. package/dist/http-util.js +10 -0
  348. package/dist/{importers.d.ts → importers/core.d.ts} +13 -17
  349. package/dist/importers/core.js +141 -0
  350. package/dist/importers/markdown-parse.d.ts +41 -0
  351. package/dist/importers/markdown-parse.js +132 -0
  352. package/dist/importers/markdown.d.ts +3 -0
  353. package/dist/importers/markdown.js +92 -0
  354. package/dist/importers/sources.d.ts +7 -0
  355. package/dist/importers/sources.js +229 -0
  356. package/dist/importers/vault.d.ts +11 -0
  357. package/dist/importers/vault.js +352 -0
  358. package/dist/incidents.d.ts +3 -0
  359. package/dist/incidents.js +52 -43
  360. package/dist/index.d.ts +25 -6
  361. package/dist/index.js +23 -6
  362. package/dist/invalidation.js +2 -1
  363. package/dist/judgment.js +2 -1
  364. package/dist/keyset.d.ts +13 -0
  365. package/dist/keyset.js +8 -0
  366. package/dist/local-embedding.d.ts +13 -0
  367. package/dist/local-embedding.js +165 -0
  368. package/dist/log.d.ts +7 -0
  369. package/dist/log.js +19 -1
  370. package/dist/mcp/admin-tools.d.ts +8 -0
  371. package/dist/mcp/admin-tools.js +116 -0
  372. package/dist/mcp/format.d.ts +27 -0
  373. package/dist/mcp/format.js +135 -0
  374. package/dist/mcp/memory-tools.d.ts +5 -0
  375. package/dist/mcp/memory-tools.js +83 -0
  376. package/dist/mcp/protocol.d.ts +83 -0
  377. package/dist/mcp/protocol.js +55 -0
  378. package/dist/mcp/recall-tools.d.ts +6 -0
  379. package/dist/mcp/recall-tools.js +320 -0
  380. package/dist/mcp/request.d.ts +10 -0
  381. package/dist/mcp/request.js +163 -0
  382. package/dist/mcp/server.d.ts +4 -75
  383. package/dist/mcp/server.js +7 -1190
  384. package/dist/mcp/session-state.d.ts +11 -0
  385. package/dist/mcp/session-state.js +28 -0
  386. package/dist/mcp/stdio.d.ts +8 -0
  387. package/dist/mcp/stdio.js +79 -0
  388. package/dist/mcp/tools.d.ts +11 -0
  389. package/dist/mcp/tools.js +247 -0
  390. package/dist/memory.d.ts +3 -0
  391. package/dist/memory.js +27 -1
  392. package/dist/multihop.d.ts +1 -1
  393. package/dist/multihop.js +2 -1
  394. package/dist/owner-validation.js +2 -1
  395. package/dist/physics-state.js +10 -7
  396. package/dist/policies.d.ts +3 -0
  397. package/dist/policies.js +93 -74
  398. package/dist/postinstall.js +3 -2
  399. package/dist/predictions/planning-fallacy.d.ts +100 -0
  400. package/dist/predictions/planning-fallacy.js +190 -0
  401. package/dist/{predictions.d.ts → predictions/store.d.ts} +7 -102
  402. package/dist/predictions/store.js +434 -0
  403. package/dist/processes.d.ts +3 -0
  404. package/dist/processes.js +94 -76
  405. package/dist/project-briefs.d.ts +3 -0
  406. package/dist/project-briefs.js +142 -113
  407. package/dist/project-identity.js +3 -2
  408. package/dist/project-merge.d.ts +12 -4
  409. package/dist/project-merge.js +132 -45
  410. package/dist/quarantine.d.ts +2 -1
  411. package/dist/quarantine.js +8 -5
  412. package/dist/raw-archive.js +1 -1
  413. package/dist/recall-history.js +3 -2
  414. package/dist/recall-pipeline.d.ts +2 -2
  415. package/dist/recall-pipeline.js +16 -8
  416. package/dist/recall-scope.js +1 -1
  417. package/dist/recall-trace.d.ts +1 -1
  418. package/dist/refine-llm.js +2 -1
  419. package/dist/reject-flow.js +6 -1
  420. package/dist/rerankers/clef.js +6 -5
  421. package/dist/rerankers/jev.d.ts +1 -1
  422. package/dist/rerankers/jev.js +4 -4
  423. package/dist/rerankers/llm.d.ts +4 -2
  424. package/dist/rerankers/llm.js +58 -38
  425. package/dist/rerankers/types.d.ts +1 -1
  426. package/dist/salience.js +1 -1
  427. package/dist/scheduler.d.ts +1 -0
  428. package/dist/scheduler.js +26 -4
  429. package/dist/scope.js +4 -3
  430. package/dist/search/as-of.d.ts +10 -0
  431. package/dist/search/as-of.js +22 -0
  432. package/dist/search/bm25-search.d.ts +14 -0
  433. package/dist/search/bm25-search.js +43 -0
  434. package/dist/search/bm25.d.ts +15 -0
  435. package/dist/search/bm25.js +54 -0
  436. package/dist/search/boosts.d.ts +54 -0
  437. package/dist/search/boosts.js +94 -0
  438. package/dist/search/breakdown.d.ts +7 -0
  439. package/dist/search/breakdown.js +20 -0
  440. package/dist/search/explain.d.ts +25 -0
  441. package/dist/search/explain.js +31 -0
  442. package/dist/search/finalize.d.ts +8 -0
  443. package/dist/search/finalize.js +52 -0
  444. package/dist/search/fusion.d.ts +27 -0
  445. package/dist/search/fusion.js +42 -0
  446. package/dist/search/hybrid-score.d.ts +20 -0
  447. package/dist/search/hybrid-score.js +73 -0
  448. package/dist/search/hybrid.d.ts +46 -0
  449. package/dist/search/hybrid.js +64 -0
  450. package/dist/search/physics-search.d.ts +29 -0
  451. package/dist/search/physics-search.js +162 -0
  452. package/dist/search/rerank.d.ts +10 -0
  453. package/dist/search/rerank.js +72 -0
  454. package/dist/search/temporal.d.ts +15 -0
  455. package/dist/search/temporal.js +45 -0
  456. package/dist/search/types.d.ts +91 -0
  457. package/dist/search/types.js +2 -0
  458. package/dist/search/vector.d.ts +30 -0
  459. package/dist/search/vector.js +71 -0
  460. package/dist/secret-detect.d.ts +2 -0
  461. package/dist/secret-detect.js +2 -1
  462. package/dist/server/auth.d.ts +52 -0
  463. package/dist/server/auth.js +221 -0
  464. package/dist/server/client-ip.d.ts +25 -0
  465. package/dist/server/client-ip.js +92 -0
  466. package/dist/server/cursor.d.ts +23 -0
  467. package/dist/server/cursor.js +58 -0
  468. package/dist/server/lifecycle.d.ts +7 -0
  469. package/dist/server/lifecycle.js +29 -0
  470. package/dist/server/mcp-http.d.ts +5 -0
  471. package/dist/server/mcp-http.js +199 -0
  472. package/dist/server/request.d.ts +33 -0
  473. package/dist/server/request.js +103 -0
  474. package/dist/server/routes/admin.d.ts +9 -0
  475. package/dist/server/routes/admin.js +158 -0
  476. package/dist/server/routes/customer-notes.d.ts +7 -0
  477. package/dist/server/routes/customer-notes.js +112 -0
  478. package/dist/server/routes/decisions.d.ts +7 -0
  479. package/dist/server/routes/decisions.js +133 -0
  480. package/dist/server/routes/incidents.d.ts +7 -0
  481. package/dist/server/routes/incidents.js +126 -0
  482. package/dist/server/routes/memories.d.ts +10 -0
  483. package/dist/server/routes/memories.js +179 -0
  484. package/dist/server/routes/policies.d.ts +8 -0
  485. package/dist/server/routes/policies.js +151 -0
  486. package/dist/server/routes/predictions.d.ts +7 -0
  487. package/dist/server/routes/predictions.js +164 -0
  488. package/dist/server/routes/processes.d.ts +7 -0
  489. package/dist/server/routes/processes.js +161 -0
  490. package/dist/server/routes/project-briefs.d.ts +8 -0
  491. package/dist/server/routes/project-briefs.js +136 -0
  492. package/dist/server/routes/recall.d.ts +8 -0
  493. package/dist/server/routes/recall.js +340 -0
  494. package/dist/server/routes/skills.d.ts +8 -0
  495. package/dist/server/routes/skills.js +150 -0
  496. package/dist/server/types.d.ts +56 -0
  497. package/dist/server/types.js +2 -0
  498. package/dist/server/validation.d.ts +14 -0
  499. package/dist/server/validation.js +91 -0
  500. package/dist/server.d.ts +7 -61
  501. package/dist/server.js +69 -2362
  502. package/dist/session-digest.d.ts +1 -1
  503. package/dist/session-digest.js +9 -2
  504. package/dist/shared.d.ts +12 -1
  505. package/dist/shared.js +33 -27
  506. package/dist/skills.d.ts +3 -0
  507. package/dist/skills.js +88 -70
  508. package/dist/stdin.js +2 -2
  509. package/dist/store/audit-event.d.ts +19 -0
  510. package/dist/store/audit-event.js +33 -0
  511. package/dist/store/candidates.d.ts +42 -0
  512. package/dist/store/candidates.js +152 -0
  513. package/dist/store/conflicts.d.ts +44 -0
  514. package/dist/store/conflicts.js +444 -0
  515. package/dist/store/delete-and-batch.d.ts +63 -0
  516. package/dist/store/delete-and-batch.js +310 -0
  517. package/dist/store/entry-reads.d.ts +92 -0
  518. package/dist/store/entry-reads.js +255 -0
  519. package/dist/store/entry-row.d.ts +67 -0
  520. package/dist/store/entry-row.js +208 -0
  521. package/dist/store/entry-writes.d.ts +46 -0
  522. package/dist/store/entry-writes.js +148 -0
  523. package/dist/store/handoffs.d.ts +26 -0
  524. package/dist/store/handoffs.js +184 -0
  525. package/dist/store/index-and-stats.d.ts +52 -0
  526. package/dist/store/index-and-stats.js +214 -0
  527. package/dist/store/markdown.d.ts +10 -0
  528. package/dist/store/markdown.js +108 -0
  529. package/dist/store/mirrors.d.ts +49 -0
  530. package/dist/store/mirrors.js +312 -0
  531. package/dist/store/open.d.ts +15 -0
  532. package/dist/store/open.js +223 -0
  533. package/dist/store/rows.d.ts +178 -0
  534. package/dist/store/rows.js +158 -0
  535. package/dist/store/search-rows.d.ts +86 -0
  536. package/dist/store/search-rows.js +260 -0
  537. package/dist/store/sessions.d.ts +83 -0
  538. package/dist/store/sessions.js +272 -0
  539. package/dist/store/summaries.d.ts +94 -0
  540. package/dist/store/summaries.js +377 -0
  541. package/dist/store/tenant-lookup.d.ts +12 -0
  542. package/dist/store/tenant-lookup.js +16 -0
  543. package/dist/store-cards.js +2 -1
  544. package/dist/summary-dirty.d.ts +4 -0
  545. package/dist/summary-dirty.js +32 -0
  546. package/dist/support-bundle.js +4 -3
  547. package/dist/tenant.js +2 -2
  548. package/dist/tokenize.d.ts +2 -0
  549. package/dist/tokenize.js +16 -0
  550. package/dist/transcript-tail.d.ts +7 -0
  551. package/dist/transcript-tail.js +48 -0
  552. package/dist/vector-store.d.ts +27 -0
  553. package/dist/vector-store.js +210 -0
  554. package/dist/version.d.ts +2 -2
  555. package/dist/version.js +2 -2
  556. package/dist/working-memory.js +1 -1
  557. package/dist/yaml.js +36 -11
  558. package/dist-ui/assets/ibm-plex-mono-latin-400-normal-CvHOgSBP.woff +0 -0
  559. package/dist-ui/assets/ibm-plex-mono-latin-400-normal-DMJ8VG8y.woff2 +0 -0
  560. package/dist-ui/assets/ibm-plex-mono-latin-500-normal-CB9ihrfo.woff +0 -0
  561. package/dist-ui/assets/ibm-plex-mono-latin-500-normal-DSY6xOcd.woff2 +0 -0
  562. package/dist-ui/assets/ibm-plex-mono-latin-600-normal-BgSNZQsw.woff2 +0 -0
  563. package/dist-ui/assets/ibm-plex-mono-latin-600-normal-DWFSQ4vo.woff +0 -0
  564. package/dist-ui/assets/ibm-plex-sans-latin-400-normal-CDDApCn2.woff2 +0 -0
  565. package/dist-ui/assets/ibm-plex-sans-latin-400-normal-CYLoc0-x.woff +0 -0
  566. package/dist-ui/assets/ibm-plex-sans-latin-500-normal-6ng42L7E.woff2 +0 -0
  567. package/dist-ui/assets/ibm-plex-sans-latin-500-normal-BgVn5rGT.woff +0 -0
  568. package/dist-ui/assets/ibm-plex-sans-latin-600-normal-Cu4Hd6ag.woff +0 -0
  569. package/dist-ui/assets/ibm-plex-sans-latin-600-normal-CuJfVYMP.woff2 +0 -0
  570. package/dist-ui/assets/index-DPN7cP19.js +33 -0
  571. package/dist-ui/assets/index-dFloKRVr.css +1 -0
  572. package/dist-ui/index.html +3 -25
  573. package/extensions/openclaw-plugin/openclaw.plugin.json +1 -1
  574. package/extensions/openclaw-plugin/package.json +1 -1
  575. package/openclaw.plugin.json +1 -1
  576. package/package.json +1 -1
  577. package/dist/capture.d.ts +0 -155
  578. package/dist/capture.js +0 -1295
  579. package/dist/consolidate.d.ts +0 -58
  580. package/dist/consolidate.js +0 -1124
  581. package/dist/graph.d.ts +0 -245
  582. package/dist/hooks.d.ts +0 -208
  583. package/dist/hooks.js +0 -1076
  584. package/dist/importers.js +0 -900
  585. package/dist/predictions.js +0 -620
  586. package/dist/search.d.ts +0 -320
  587. package/dist/search.js +0 -970
  588. package/dist/store.d.ts +0 -776
  589. package/dist/store.js +0 -3473
  590. package/dist-ui/assets/d3-BiWEKnn4.js +0 -1
  591. package/dist-ui/assets/index-BhT8RvO6.js +0 -61
  592. package/dist-ui/assets/index-RoXXJ5dq.css +0 -1
  593. package/dist-ui/assets/three-BDgTxR1l.js +0 -4112
@@ -0,0 +1,178 @@
1
+ // API key management: create, list, revoke, and grant or ungrant restricted scopes.
2
+ import { openHippoDb, closeHippoDb } from '../db.js';
3
+ import { BadRequestError, ConflictError, ForbiddenError, NotFoundError } from '../api-errors.js';
4
+ import { appendAuditEvent, reportAuditWriteFailure } from '../audit.js';
5
+ import { createApiKey, listApiKeyRows, revokeApiKey, grantScope, ungrantScope } from '../auth.js';
6
+ import { isRestrictedScope } from '../recall-scope.js';
7
+ import { selectApiKeyOwner } from '../store/tenant-lookup.js';
8
+ /**
9
+ * Mint a new API key. The new key is ALWAYS bound to `ctx.tenantId`. Callers
10
+ * cannot override the tenant via the opts bag — a previous `tenantId` field
11
+ * was removed because the HTTP layer would happily forward `body.tenantId`,
12
+ * letting tenant A mint a key for tenant B. The HTTP route handler at
13
+ * `src/server.ts` POST /v1/auth/keys mirrors this: it ignores any body
14
+ * `tenantId` and uses the resolved Bearer's tenant exclusively.
15
+ *
16
+ * Only an admin actor can mint (ForbiddenError otherwise), and a key never
17
+ * outranks its minter: a resolver admin is tenant-only, so it mints members.
18
+ */
19
+ export function authCreate(ctx, opts) {
20
+ if (ctx.actor.role !== 'admin') {
21
+ throw new ForbiddenError('Only an admin key can create API keys');
22
+ }
23
+ if (ctx.actor.viaAuthResolver && opts.role === 'admin') {
24
+ throw new ForbiddenError('A key minted through the auth resolver can only be a member key');
25
+ }
26
+ const db = openHippoDb(ctx.hippoRoot);
27
+ try {
28
+ const role = opts.role ?? (ctx.actor.viaAuthResolver ? 'member' : 'admin');
29
+ const result = createApiKey(db, { tenantId: ctx.tenantId, label: opts.label, role });
30
+ // v1.12.4: audit emit (closes the gap v1.12.3 CHANGELOG flagged as deferred).
31
+ // Mirrors the auth_revoke pattern at authRevoke — same try/catch so audit
32
+ // failure can't crash a successful mint. The plaintext is NEVER logged;
33
+ // metadata carries label + role + the keyId (which is non-secret).
34
+ try {
35
+ appendAuditEvent(db, {
36
+ tenantId: ctx.tenantId,
37
+ actor: ctx.actor.subject,
38
+ op: 'auth_create',
39
+ targetId: result.keyId,
40
+ metadata: {
41
+ label: opts.label ?? null,
42
+ role,
43
+ },
44
+ });
45
+ }
46
+ catch (error) {
47
+ // Audit must not crash a successful mint.
48
+ reportAuditWriteFailure('auth_create', String(error), result.keyId);
49
+ }
50
+ return { keyId: result.keyId, plaintext: result.plaintext, tenantId: ctx.tenantId, role };
51
+ }
52
+ finally {
53
+ closeHippoDb(db);
54
+ }
55
+ }
56
+ /**
57
+ * List API keys visible to the calling tenant.
58
+ *
59
+ * Divergence from `cmdAuthList` in src/cli.ts: the CLI today returns ALL keys
60
+ * regardless of tenant (single-tenant deployments). The API surface is tenant-
61
+ * scoped because future multi-tenant deployments will share a hippoRoot, and
62
+ * tenant A must not see tenant B's keys. Read-only — no audit emit (matches A5).
63
+ */
64
+ export function authList(ctx, opts) {
65
+ return authListRows(ctx, opts).map((r) => r.key);
66
+ }
67
+ /** One page of the caller's tenant's keys, newest first, with the row ids a next-page cursor is built from. */
68
+ export function authListRows(ctx, opts) {
69
+ const db = openHippoDb(ctx.hippoRoot);
70
+ try {
71
+ return listApiKeyRows(db, { ...opts, tenantId: ctx.tenantId });
72
+ }
73
+ finally {
74
+ closeHippoDb(db);
75
+ }
76
+ }
77
+ export function authRevoke(ctx, keyId) {
78
+ if (ctx.actor.role !== 'admin' && ctx.actor.subject !== `api_key:${keyId}`) {
79
+ throw new ForbiddenError('A member key can revoke only itself');
80
+ }
81
+ const db = openHippoDb(ctx.hippoRoot);
82
+ try {
83
+ const row = selectApiKeyOwner(db, keyId);
84
+ // Cross-tenant access denied: same message as missing key, no info leak.
85
+ if (!row || row.tenantId !== ctx.tenantId) {
86
+ throw new NotFoundError(`Unknown key_id: ${keyId}`);
87
+ }
88
+ if (ctx.actor.viaAuthResolver && row.role === 'admin') {
89
+ throw new ForbiddenError('An auth resolver admin cannot revoke an admin key, which outranks it');
90
+ }
91
+ let revokedAt;
92
+ let alreadyRevoked = false;
93
+ if (row.revokedAt) {
94
+ alreadyRevoked = true;
95
+ revokedAt = row.revokedAt;
96
+ }
97
+ else {
98
+ revokeApiKey(db, keyId);
99
+ revokedAt = selectApiKeyOwner(db, keyId)?.revokedAt ?? new Date().toISOString();
100
+ }
101
+ if (!alreadyRevoked) {
102
+ try {
103
+ appendAuditEvent(db, {
104
+ tenantId: row.tenantId, // M1: KEY's tenant, not ctx.tenantId.
105
+ actor: ctx.actor.subject,
106
+ op: 'auth_revoke',
107
+ targetId: keyId,
108
+ });
109
+ }
110
+ catch (error) {
111
+ // Audit must not crash a successful revoke.
112
+ reportAuditWriteFailure('auth_revoke', String(error), keyId);
113
+ }
114
+ }
115
+ return { ok: true, revokedAt };
116
+ }
117
+ finally {
118
+ closeHippoDb(db);
119
+ }
120
+ }
121
+ /**
122
+ * The tenant that owns `keyId`, or undefined for an unknown key. Host admin only: it reads across tenants,
123
+ * so the local CLI can run revoke and grant in the key's own tenant.
124
+ */
125
+ export function authKeyTenant(ctx, keyId) {
126
+ if (!ctx.actor.hostAdmin) {
127
+ throw new ForbiddenError('Only the host admin can look up a key across tenants');
128
+ }
129
+ const db = openHippoDb(ctx.hippoRoot);
130
+ try {
131
+ return selectApiKeyOwner(db, keyId)?.tenantId;
132
+ }
133
+ finally {
134
+ closeHippoDb(db);
135
+ }
136
+ }
137
+ /** Grant `keyId` read access to one restricted `scope` (ROADMAP Part VIII EI2). Admin only. */
138
+ export function authGrant(ctx, keyId, scope) {
139
+ return changeScopeGrant(ctx, keyId, scope, 'auth_grant');
140
+ }
141
+ /** Revoke `keyId`'s grant on `scope`. Same authorization and lookup rules as authGrant. */
142
+ export function authUngrant(ctx, keyId, scope) {
143
+ return changeScopeGrant(ctx, keyId, scope, 'auth_ungrant');
144
+ }
145
+ function changeScopeGrant(ctx, keyId, scope, op) {
146
+ if (ctx.actor.role !== 'admin') {
147
+ throw new ForbiddenError('Only an admin key can change scope grants');
148
+ }
149
+ const db = openHippoDb(ctx.hippoRoot);
150
+ try {
151
+ const row = selectApiKeyOwner(db, keyId);
152
+ if (!row || row.tenantId !== ctx.tenantId) {
153
+ throw new NotFoundError(`Unknown key_id: ${keyId}`);
154
+ }
155
+ if (op === 'auth_grant' && row.revokedAt) {
156
+ throw new ConflictError(`${keyId} is revoked; a grant on it would never apply`);
157
+ }
158
+ if (!isRestrictedScope(scope)) {
159
+ throw new BadRequestError(`${scope} is not a restricted scope; it is already readable by default`);
160
+ }
161
+ if (op === 'auth_grant')
162
+ grantScope(db, keyId, scope);
163
+ else
164
+ ungrantScope(db, keyId, scope);
165
+ try {
166
+ appendAuditEvent(db, { tenantId: ctx.tenantId, actor: ctx.actor.subject, op, targetId: keyId, metadata: { scope } });
167
+ }
168
+ catch (err) {
169
+ // Audit must not undo a grant change that already committed; surface it instead.
170
+ reportAuditWriteFailure(op, String(err), keyId);
171
+ }
172
+ return { ok: true };
173
+ }
174
+ finally {
175
+ closeHippoDb(db);
176
+ }
177
+ }
178
+ //# sourceMappingURL=auth.js.map
@@ -0,0 +1,49 @@
1
+ import type { AmbientLoadResult } from '../store/candidates.js';
2
+ import { type MemoryEntry } from '../memory.js';
3
+ import { type HippoConfig } from '../config.js';
4
+ import type { DeliveryObserver } from '../delivery-recorder.js';
5
+ import type { ContextCost, ContextOpts, ContextResultEntry } from './context-types.js';
6
+ import type { Context } from './types.js';
7
+ /** What getContext resolved from opts and config before it read a row. */
8
+ export interface ContextPlan {
9
+ pinnedOnly: boolean;
10
+ limit: number;
11
+ includeRecent: number;
12
+ activeScope: string;
13
+ exactScope: string | undefined;
14
+ query: string;
15
+ hasLocal: boolean;
16
+ hasGlobal: boolean;
17
+ globalRoot: string;
18
+ primaryIsGlobal: boolean;
19
+ hasLocalTaskState: boolean;
20
+ config: HippoConfig;
21
+ currentProjectName: string;
22
+ includeCrossProject: boolean;
23
+ originProject: string | undefined;
24
+ promptRecallPending: boolean;
25
+ cost: ContextCost | undefined;
26
+ price: (entry: MemoryEntry, isGlobal: boolean, promptRecall?: boolean) => number;
27
+ obs: DeliveryObserver | undefined;
28
+ }
29
+ /** The ambient admit rules; `digestHidden` is read late because a prompt-recall eligibility check can still set it. */
30
+ export interface ContextAdmission {
31
+ ambientAdmit: (e: MemoryEntry) => boolean;
32
+ admit: (e: MemoryEntry) => boolean;
33
+ /** What the two-store search admits: `admit` without the own-session compaction rule. */
34
+ bothStoresAdmit: (e: MemoryEntry) => boolean;
35
+ digestHidden: () => boolean;
36
+ }
37
+ export interface ContextPools {
38
+ local: AmbientLoadResult;
39
+ global: AmbientLoadResult;
40
+ }
41
+ export declare function oneCopyPerMemory(local: readonly MemoryEntry[], global: readonly MemoryEntry[], now: Date): [MemoryEntry[], MemoryEntry[]];
42
+ export declare const finiteOr: (v: number, dflt: number, min: number) => number;
43
+ /** Pins plus the prompt-recall or recent-N backfill; null means the block is empty. */
44
+ export declare function selectPinned(ctx: Context, opts: ContextOpts, plan: ContextPlan, left: number, pools: ContextPools, admission: ContextAdmission): ContextResultEntry[] | null;
45
+ /** No query: the strongest memories by strength, up to budget. */
46
+ export declare function selectStrongest(plan: ContextPlan, left: number, pools: ContextPools): ContextResultEntry[];
47
+ /** Real query: hybrid search over both stores, or physics/hybrid over the local rows; emits the 'recall' audit row. */
48
+ export declare function selectBySearch(ctx: Context, plan: ContextPlan, left: number, pools: ContextPools, admission: ContextAdmission): Promise<ContextResultEntry[]>;
49
+ //# sourceMappingURL=context-select.d.ts.map
@@ -0,0 +1,344 @@
1
+ // getContext's selection stages: the pinned-only branch, the strongest-first branch and the search branch.
2
+ import { openHippoDb, closeHippoDb } from '../db.js';
3
+ import { recallScopeFilter } from '../store/search-rows.js';
4
+ import { loadIndex } from '../store/index-and-stats.js';
5
+ import { calculateStrength } from '../memory.js';
6
+ import { appendAuditEvent, auditQueryFields, isContentWorthStoring } from '../audit.js';
7
+ import { rankBothStores } from '../shared.js';
8
+ import { evalNow } from '../ablation.js';
9
+ import { hybridSearch } from '../search/hybrid.js';
10
+ import { physicsSearch } from '../search/physics-search.js';
11
+ import { compareScoredResults } from '../compare.js';
12
+ import { scopeMatch } from '../scope.js';
13
+ import { loadConfig } from '../config.js';
14
+ import { promptTokens, contentTokens, gatePromptRecall, } from '../prompt-recall.js';
15
+ // Share and promote copy a memory to the global store under a new id, so equal content is the only link.
16
+ // A pinned copy wins, then the stronger one after the ranking's own global discount; a tie keeps the local copy.
17
+ export function oneCopyPerMemory(local, global, now) {
18
+ const score = (e, isGlobal) => calculateStrength(e, now) * (isGlobal ? 1 / 1.2 : 1);
19
+ const best = new Map();
20
+ const offer = (entry, isGlobal) => {
21
+ const held = best.get(entry.content);
22
+ const wins = !held || (held.entry.pinned !== entry.pinned
23
+ ? entry.pinned
24
+ : score(entry, isGlobal) > score(held.entry, held.isGlobal));
25
+ if (wins)
26
+ best.set(entry.content, { entry, isGlobal });
27
+ };
28
+ for (const e of local)
29
+ offer(e, false);
30
+ for (const e of global)
31
+ offer(e, true);
32
+ const kept = new Set([...best.values()].map((b) => b.entry));
33
+ return [local.filter((e) => kept.has(e)), global.filter((e) => kept.has(e))];
34
+ }
35
+ export const finiteOr = (v, dflt, min) => Number.isFinite(v) && v >= min ? v : dflt;
36
+ /** Pins plus the prompt-recall or recent-N backfill; null means the block is empty. */
37
+ export function selectPinned(ctx, opts, plan, left, pools, admission) {
38
+ const { obs, primaryIsGlobal } = plan;
39
+ // loadConfig is safe even when local isn't initialised — returns defaults.
40
+ const pinnedCfg = loadConfig(ctx.hippoRoot);
41
+ if (!pinnedCfg.pinnedInject.enabled) {
42
+ return null;
43
+ }
44
+ // Effective budget: explicit opts.budget wins over config, less what the sections took.
45
+ const effBudget = left;
46
+ const nowP = evalNow(); // honors HIPPO_FAKE_NOW (eval-only; see ablation.ts)
47
+ const localEntries = pools.local.entries;
48
+ const globalEntries = pools.global.entries;
49
+ obs?.offer(localEntries, primaryIsGlobal);
50
+ obs?.offer(globalEntries, true);
51
+ const [localPool, globalPool] = oneCopyPerMemory(localEntries, globalEntries, nowP);
52
+ obs?.dropMissing([...localEntries, ...globalEntries], [...localPool, ...globalPool], 'load', 'duplicate');
53
+ const picked = { items: [], ids: new Set(), used: 0 };
54
+ // Pinned entries are explicit user intent, the recent-N list an automatic
55
+ // backfill. Both loops share ONE budget and the recent loop runs first, so
56
+ // pins are ranked here and reserve their share before it can spend.
57
+ const pinnedLocal = localPool.filter((e) => e.pinned);
58
+ const pinnedGlobal = globalPool.filter((e) => e.pinned);
59
+ const rankedPinned = rankPinned(plan, pinnedLocal, pinnedGlobal, nowP);
60
+ const recentBudget = Math.max(0, effBudget - reservePinned(rankedPinned, effBudget));
61
+ // Prompt recall gates the backfill on the prompt instead of recency.
62
+ if (plan.promptRecallPending) {
63
+ const candidates = () => promptRecallCandidates(plan, pools, admission.admit, rankedPinned, nowP);
64
+ backfillFromPrompt(opts, plan, pinnedCfg, candidates, picked, recentBudget);
65
+ }
66
+ else if (plan.includeRecent > 0) {
67
+ backfillRecent(plan, localPool, globalPool, picked, recentBudget, nowP);
68
+ }
69
+ if (pinnedLocal.length === 0 &&
70
+ pinnedGlobal.length === 0 &&
71
+ picked.items.length === 0 &&
72
+ !admission.digestHidden()) {
73
+ return null;
74
+ }
75
+ admitWithinBudget(rankedPinned, picked, effBudget, obs);
76
+ return picked.items;
77
+ }
78
+ function rankPinned(plan, pinnedLocal, pinnedGlobal, nowP) {
79
+ return [
80
+ ...pinnedLocal.map((e) => ({ entry: e, isGlobal: plan.primaryIsGlobal })),
81
+ ...pinnedGlobal.map((e) => ({ entry: e, isGlobal: true })),
82
+ ]
83
+ .map(({ entry, isGlobal }) => {
84
+ const scopeSig = scopeMatch(entry.tags, plan.activeScope);
85
+ const sBst = scopeSig === 1 ? 1.5 : scopeSig === -1 ? 0.5 : 1.0;
86
+ return {
87
+ entry,
88
+ score: calculateStrength(entry, nowP) * (isGlobal ? 1 / 1.2 : 1) * sBst,
89
+ tokens: plan.price(entry, isGlobal),
90
+ isGlobal,
91
+ };
92
+ })
93
+ .sort(compareScoredResults);
94
+ }
95
+ // Mirrors the pin loop's continue-not-break so a big pin cannot block smaller ones from reserving, and dedupes by id
96
+ // because a synced pin sits in both stores. A pin also in the recent slice is counted twice: recents under-fill, safely.
97
+ function reservePinned(rankedPinned, effBudget) {
98
+ let pinnedReserve = 0;
99
+ const reservedIds = new Set();
100
+ for (const r of rankedPinned) {
101
+ if (reservedIds.has(r.entry.id))
102
+ continue;
103
+ if (pinnedReserve + r.tokens <= effBudget) {
104
+ pinnedReserve += r.tokens;
105
+ reservedIds.add(r.entry.id);
106
+ }
107
+ }
108
+ return pinnedReserve;
109
+ }
110
+ /** Skips ids already picked and rows past the budget, so a large row never blocks smaller ones behind it. */
111
+ function admitWithinBudget(rows, picked, budget, obs) {
112
+ for (const r of rows) {
113
+ if (picked.ids.has(r.entry.id))
114
+ continue;
115
+ if (picked.used + r.tokens > budget) {
116
+ obs?.reject(r.entry, 'budget', 'budget', r.score, r.tokens);
117
+ continue;
118
+ }
119
+ picked.items.push(r);
120
+ picked.ids.add(r.entry.id);
121
+ picked.used += r.tokens;
122
+ }
123
+ }
124
+ function backfillFromPrompt(opts, plan, pinnedCfg, candidates, picked, recentBudget) {
125
+ const rawMetric = pinnedCfg.pinnedInject.promptRecallMetric;
126
+ const metric = rawMetric === 'cosine' ? 'cosine' : 'jaccard';
127
+ const gate = {
128
+ metric,
129
+ threshold: finiteOr(pinnedCfg.pinnedInject.promptRecallThreshold, 0.04, 0),
130
+ minShared: finiteOr(pinnedCfg.pinnedInject.promptRecallMinShared, 2, 0),
131
+ maxItems: finiteOr(pinnedCfg.pinnedInject.promptRecallMaxItems, 5, 1),
132
+ };
133
+ const p = promptTokens(opts.prompt ?? '');
134
+ if (p.size === 0)
135
+ return;
136
+ const candidateItems = candidates();
137
+ const gated = gatePromptRecall(p, candidateItems, gate);
138
+ plan.obs?.gated(p, candidateItems, gate, gated);
139
+ for (const g of gated) {
140
+ if (picked.ids.has(g.item.id))
141
+ continue;
142
+ const tokens = plan.price(g.item.entry, g.item.isGlobal, true);
143
+ if (picked.used + tokens > recentBudget) {
144
+ plan.obs?.reject(g.item.entry, 'budget', 'budget', g.score, tokens);
145
+ continue;
146
+ }
147
+ picked.items.push({ entry: g.item.entry, score: g.score, tokens, isGlobal: g.item.isGlobal, promptRecall: true });
148
+ picked.ids.add(g.item.id);
149
+ picked.used += tokens;
150
+ }
151
+ }
152
+ // Candidates came off the ambient load's own connection (the recall request), not a fresh open.
153
+ function promptRecallCandidates(plan, pools, admit, rankedPinned, nowP) {
154
+ const { obs, primaryIsGlobal } = plan;
155
+ // A candidate carrying a pin's text would inject that memory a second time.
156
+ const pinnedText = new Set(rankedPinned.map((r) => r.entry.content));
157
+ const ineligibleReason = (e) => !admit(e) ? 'scope'
158
+ : e.pinned ? 'pinned'
159
+ : !isContentWorthStoring(e.content) ? 'quality'
160
+ : pinnedText.has(e.content) ? 'duplicate'
161
+ : null;
162
+ const eligible = (e) => {
163
+ const why = ineligibleReason(e);
164
+ if (why !== null && why !== 'pinned')
165
+ obs?.reject(e, 'eligible', why);
166
+ return why === null;
167
+ };
168
+ obs?.offer(pools.local.recall ?? [], primaryIsGlobal, 'prompt-recall');
169
+ obs?.offer(pools.global.recall ?? [], true, 'prompt-recall');
170
+ const localEligible = (pools.local.recall ?? []).filter(eligible);
171
+ const globalEligible = (pools.global.recall ?? []).filter(eligible);
172
+ const [localCandidates, globalCandidates] = oneCopyPerMemory(localEligible, globalEligible, nowP);
173
+ obs?.dropMissing([...localEligible, ...globalEligible], [...localCandidates, ...globalCandidates], 'eligible', 'duplicate');
174
+ const seenCandidateIds = new Set();
175
+ const candidateItems = [];
176
+ // Local wins the id collision (a global row synced into the local store).
177
+ for (const e of localCandidates) {
178
+ if (seenCandidateIds.has(e.id))
179
+ continue;
180
+ seenCandidateIds.add(e.id);
181
+ candidateItems.push({ id: e.id, tokens: contentTokens(e.content), entry: e, isGlobal: primaryIsGlobal });
182
+ }
183
+ for (const e of globalCandidates) {
184
+ if (seenCandidateIds.has(e.id))
185
+ continue;
186
+ seenCandidateIds.add(e.id);
187
+ candidateItems.push({ id: e.id, tokens: contentTokens(e.content), entry: e, isGlobal: true });
188
+ }
189
+ return candidateItems;
190
+ }
191
+ function backfillRecent(plan, localPool, globalPool, picked, recentBudget, nowP) {
192
+ const recent = [
193
+ ...localPool.map((entry) => ({ entry, isGlobal: plan.primaryIsGlobal })),
194
+ ...globalPool.map((entry) => ({ entry, isGlobal: true })),
195
+ ]
196
+ // Newest first, then id: stable within one store, but same-millisecond rows fall to random ids across ingests.
197
+ .sort((a, b) => {
198
+ const byCreated = Date.parse(b.entry.created) - Date.parse(a.entry.created);
199
+ return byCreated !== 0 ? byCreated : b.entry.id.localeCompare(a.entry.id);
200
+ })
201
+ // Filter before slice so a junk row is backfilled past, not counted against N. Pins bypass the floor: a dropped
202
+ // pin's share of the shared budget would go to a backfilled row, and the pin loop could not win it back.
203
+ .filter(({ entry }) => entry.pinned || isContentWorthStoring(entry.content))
204
+ .slice(0, plan.includeRecent)
205
+ .map(({ entry, isGlobal }) => ({
206
+ entry,
207
+ score: calculateStrength(entry, nowP) * (isGlobal ? 1 / 1.2 : 1),
208
+ tokens: plan.price(entry, isGlobal),
209
+ isGlobal,
210
+ }));
211
+ admitWithinBudget(recent, picked, recentBudget, plan.obs);
212
+ }
213
+ /** No query: the strongest memories by strength, up to budget. */
214
+ export function selectStrongest(plan, left, pools) {
215
+ const now = evalNow(); // honors HIPPO_FAKE_NOW (eval-only; see ablation.ts)
216
+ const [localPool, globalPool] = oneCopyPerMemory(pools.local.entries, pools.global.entries, now);
217
+ const localRanked = localPool
218
+ .map((e) => ({
219
+ entry: e,
220
+ score: calculateStrength(e, now),
221
+ tokens: plan.price(e, plan.primaryIsGlobal),
222
+ isGlobal: plan.primaryIsGlobal,
223
+ }))
224
+ .sort(compareScoredResults);
225
+ const globalRanked = globalPool
226
+ .map((e) => ({
227
+ entry: e,
228
+ score: calculateStrength(e, now) * (1 / 1.2),
229
+ tokens: plan.price(e, true),
230
+ isGlobal: true,
231
+ }))
232
+ .sort(compareScoredResults);
233
+ const combined = [...localRanked, ...globalRanked].sort(compareScoredResults);
234
+ const selected = [];
235
+ let used = 0;
236
+ for (const r of combined) {
237
+ if (used + r.tokens > left)
238
+ continue;
239
+ selected.push(r);
240
+ used += r.tokens;
241
+ }
242
+ return selected;
243
+ }
244
+ /** Real query: hybrid search over both stores, or physics/hybrid over the local rows; emits the 'recall' audit row. */
245
+ export async function selectBySearch(ctx, plan, left, pools, admission) {
246
+ const minResults = plan.cost ? 0 : undefined; // a priced block skips an oversize top hit too, so the budget bounds it
247
+ const results = plan.hasGlobal && !plan.primaryIsGlobal
248
+ ? await searchBothStores(ctx, plan, left, minResults, pools, admission.bothStoresAdmit)
249
+ : await searchLocalRows(ctx, plan, left, minResults, pools.local.entries, admission.admit);
250
+ auditContextRecall(ctx, plan, results.length);
251
+ return results;
252
+ }
253
+ // The pools were admitted at load, before ranking, dedupe and budget: a post-filter would let an excluded row fill the
254
+ // budget or shadow its admitted duplicate.
255
+ async function searchBothStores(ctx, plan, left, minResults, pools, admit) {
256
+ const { cost, price } = plan;
257
+ const localIndex = loadIndex(ctx.hippoRoot);
258
+ const isGlobalHit = (e) => !localIndex.entries[e.id];
259
+ const roots = { local: ctx.hippoRoot, global: plan.globalRoot };
260
+ const merged = await rankBothStores(plan.query, roots, { local: pools.local.entries, global: pools.global.entries }, contextVectorSpec(ctx, plan, admit), {
261
+ budget: left,
262
+ minResults,
263
+ cost: cost && ((r) => price(r.entry, isGlobalHit(r.entry))),
264
+ scope: plan.activeScope,
265
+ });
266
+ return merged.map((r) => ({
267
+ entry: r.entry,
268
+ score: r.score,
269
+ tokens: price(r.entry, isGlobalHit(r.entry)),
270
+ isGlobal: isGlobalHit(r.entry),
271
+ }));
272
+ }
273
+ /** The vector arm under the lexical window's own tenant, scope and current-row rules. */
274
+ function contextVectorSpec(ctx, plan, admit) {
275
+ return { tenantId: ctx.tenantId, scope: recallScopeFilter(plan.exactScope, 'exact'), includeSuperseded: false, admit };
276
+ }
277
+ async function searchLocalRows(ctx, plan, left, minResults, localEntries, admit) {
278
+ const { cost, price, primaryIsGlobal, query } = plan;
279
+ const ctxConfig = loadConfig(ctx.hippoRoot);
280
+ const usePhysicsCtx = ctxConfig.physics?.enabled !== false;
281
+ const localCost = cost && ((r) => price(r.entry, primaryIsGlobal));
282
+ const vectorCandidates = contextVectorSpec(ctx, plan, admit);
283
+ const ctxResults = usePhysicsCtx
284
+ ? await physicsSearch(query, localEntries, {
285
+ budget: left,
286
+ minResults,
287
+ cost: localCost,
288
+ hippoRoot: ctx.hippoRoot,
289
+ physicsConfig: ctxConfig.physics,
290
+ scope: plan.activeScope,
291
+ vectorCandidates,
292
+ })
293
+ : await hybridSearch(query, localEntries, {
294
+ budget: left,
295
+ minResults,
296
+ cost: localCost,
297
+ hippoRoot: ctx.hippoRoot,
298
+ scope: plan.activeScope,
299
+ vectorCandidates,
300
+ });
301
+ return ctxResults.map((r) => ({
302
+ entry: r.entry,
303
+ score: r.score,
304
+ tokens: price(r.entry, primaryIsGlobal),
305
+ isGlobal: primaryIsGlobal,
306
+ }));
307
+ }
308
+ // Same 'recall' op api.recall emits; the pinned-only and no-query branches never search, so they never emit.
309
+ function auditContextRecall(ctx, plan, resultCount) {
310
+ const ctxRecallMetadata = {
311
+ ...auditQueryFields(plan.query),
312
+ results: resultCount,
313
+ mode: 'context',
314
+ };
315
+ if (plan.hasLocal) {
316
+ const localDb = openHippoDb(ctx.hippoRoot);
317
+ try {
318
+ appendAuditEvent(localDb, {
319
+ tenantId: ctx.tenantId,
320
+ actor: ctx.actor.subject,
321
+ op: 'recall',
322
+ metadata: ctxRecallMetadata,
323
+ });
324
+ }
325
+ finally {
326
+ closeHippoDb(localDb);
327
+ }
328
+ }
329
+ if (plan.hasGlobal && !plan.primaryIsGlobal) {
330
+ const globalDb = openHippoDb(plan.globalRoot);
331
+ try {
332
+ appendAuditEvent(globalDb, {
333
+ tenantId: ctx.tenantId,
334
+ actor: ctx.actor.subject,
335
+ op: 'recall',
336
+ metadata: ctxRecallMetadata,
337
+ });
338
+ }
339
+ finally {
340
+ closeHippoDb(globalDb);
341
+ }
342
+ }
343
+ }
344
+ //# sourceMappingURL=context-select.js.map
@@ -0,0 +1,105 @@
1
+ import type { TaskSnapshot, SessionEvent } from '../store/rows.js';
2
+ import type { SessionHandoff } from '../handoff.js';
3
+ import type { MemoryEntry } from '../memory.js';
4
+ import type { DeliveryObserver } from '../delivery-recorder.js';
5
+ import type { AmbientState } from '../ambient.js';
6
+ /**
7
+ * Options for `getContext` — assemble a budget-bounded context bundle
8
+ * (recalled memories + active task snapshot + handoff + recent events).
9
+ * Extracted from `cmdContext` in `cli.ts` in Episode A of the api.ts refactor.
10
+ *
11
+ * Named `getContext` (not `context`) to avoid collision with the `Context`
12
+ * interface above and the ubiquitous `ctx: Context` convention. Follows the
13
+ * existing `getEntry` naming pattern in store.ts.
14
+ *
15
+ * Scope narrow (T5 execute decision): rendering opts (`format`, `framing`,
16
+ * `rendered`) and host-side opts (`auto`) are NOT included here. The print
17
+ * helpers (`printContextMarkdown`, `printActiveTaskSnapshot`, `printHandoff`,
18
+ * `printSessionEvents`) are shared with `cmdRecall` / `cmdSnapshot` /
19
+ * `cmdHandoffShow` — moving them into api.ts would expand T5 to also rewire
20
+ * those commands. CLI handles rendering + auto-resolution. Episode B can add
21
+ * `api.renderContext` once a shared rendering need actually materializes.
22
+ */
23
+ export interface ContextOpts {
24
+ q?: string;
25
+ /** Default 1500 tokens. */
26
+ budget?: number;
27
+ limit?: number;
28
+ pinnedOnly?: boolean;
29
+ scope?: string;
30
+ /** Envelope scope to match exactly, as in `recall`: admits that scope even when private, after the actor's scope check. */
31
+ exactScope?: string;
32
+ /** With `pinnedOnly`, also inject the N most recent writes that pass the
33
+ * quality floor (`isContentWorthStoring`, DF3). Filtering happens BEFORE
34
+ * the take-N, so a caller asking for 5 gets 5 qualifying entries rather
35
+ * than 5-minus-junk; pinned entries bypass the floor. Entries are only
36
+ * skipped for this read, never mutated or deleted. Ignored when
37
+ * `pinnedOnly` is false — no other path reads it. */
38
+ includeRecent?: number;
39
+ /** v39 memory scope isolation: re-include other-project memories that the
40
+ * origin partition excludes by default. They come back tagged
41
+ * `category: 'cross-project'` so renderers can demarcate them. */
42
+ crossProject?: boolean;
43
+ /** The active project name for the origin partition ('' = not in a
44
+ * project). Defaults to `resolveProjectIdentity(process.cwd()).name`;
45
+ * surfaces whose process cwd is not the caller's project (HTTP server)
46
+ * should pass it explicitly. */
47
+ currentProject?: string;
48
+ /** DF1 (docs/plans/2026-08-23-df1-snapshot-lifecycle.md, T2): the calling
49
+ * session's id. Stamped on this call's recall trace, and the owner-match input to
50
+ * `loadFreshActiveTaskSnapshot` — when it strictly equals the active
51
+ * snapshot's `session_id`, the read is unbounded (same-session
52
+ * continuity); otherwise the snapshot must pass the freshness bound to
53
+ * surface. Absent (undefined/null/'') never short-circuits as a match;
54
+ * it just means every snapshot goes through the age check. Host-resolved
55
+ * (stdin payload, HIPPO_SESSION_ID, else the host's session var) so this stays host-agnostic. */
56
+ currentSessionId?: string | null;
57
+ /** Z1: raw hook-payload prompt; only the pinned-only branch reads it, gated on `pinnedInject.promptRecall`. */
58
+ prompt?: string;
59
+ /** What the budget pays for, from the caller that renders the block. Absent = the memory text alone. */
60
+ cost?: ContextCost;
61
+ /** @internal The CLI's delivery-ledger observer; it only reads, so selection is the same with or without it. */
62
+ deliveryObserver?: DeliveryObserver;
63
+ }
64
+ /** Budget prices in the text a caller prints, so the budget bounds what reaches the model. */
65
+ export interface ContextCost {
66
+ /** Tokens of one entry as printed. */
67
+ entry: (item: Pick<ContextResultEntry, 'entry' | 'isGlobal' | 'promptRecall' | 'origin' | 'category'>) => number;
68
+ /** Tokens of the headers and footer the block can print at this budget, reserved before any entry. */
69
+ fixed: (budget: number, can: {
70
+ cross: boolean;
71
+ promptRecall: boolean;
72
+ ambient: boolean;
73
+ }) => number;
74
+ /** Tokens of the sections printed ahead of the memories, each as printed. */
75
+ snapshot: (s: TaskSnapshot) => number;
76
+ handoff: (h: SessionHandoff) => number;
77
+ trail: (events: SessionEvent[]) => number;
78
+ }
79
+ export interface ContextResultEntry {
80
+ entry: MemoryEntry;
81
+ score: number;
82
+ /** What this entry cost the budget: its printed line under `ContextOpts.cost`, else its memory text. */
83
+ tokens: number;
84
+ isGlobal?: boolean;
85
+ isFreshTail?: boolean;
86
+ /** Z1: admitted by the prompt-recall gate, not the recent-N backfill or a pin. */
87
+ promptRecall?: boolean;
88
+ /** v39: the entry's owning project ('' = user-global, null = legacy row). */
89
+ origin?: string | null;
90
+ /** v39: how the origin relates to the active project. 'cross-project'
91
+ * entries only appear when ContextOpts.crossProject was set (or isolation
92
+ * is disabled). */
93
+ category?: 'project' | 'user-global' | 'cross-project';
94
+ }
95
+ export interface ContextResult {
96
+ entries: ContextResultEntry[];
97
+ tokens: number;
98
+ activeSnapshot?: TaskSnapshot | null;
99
+ sessionHandoff?: SessionHandoff | null;
100
+ recentEvents?: SessionEvent[];
101
+ /** The ambient landscape summary over every live row the read may see in the local and global stores,
102
+ * not just the rows loaded. Present only when ambient config is on, the caller is not pinned-only, and an entry was returned. */
103
+ ambientState?: AmbientState;
104
+ }
105
+ //# sourceMappingURL=context-types.d.ts.map
@@ -0,0 +1,3 @@
1
+ // Option and result shapes for getContext.
2
+ export {};
3
+ //# sourceMappingURL=context-types.js.map