hippo-memory 1.60.0 → 1.61.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (585) hide show
  1. package/README.md +1 -1
  2. package/dist/ablation.js +9 -27
  3. package/dist/agent-memories/apply.js +4 -1
  4. package/dist/agent-memories/claude-code.js +1 -1
  5. package/dist/agent-memories/codex.js +1 -1
  6. package/dist/agent-memories/gemini.js +1 -1
  7. package/dist/agent-memories/legacy.js +1 -1
  8. package/dist/agent-memories/source.js +1 -1
  9. package/dist/agent-memories/sync.js +8 -3
  10. package/dist/ambient-store.d.ts +14 -0
  11. package/dist/ambient-store.js +90 -0
  12. package/dist/ambient.d.ts +23 -0
  13. package/dist/ambient.js +72 -50
  14. package/dist/api/assemble.d.ts +93 -0
  15. package/dist/api/assemble.js +152 -0
  16. package/dist/api/audit.d.ts +17 -0
  17. package/dist/api/audit.js +23 -0
  18. package/dist/api/auth.d.ts +79 -0
  19. package/dist/api/auth.js +178 -0
  20. package/dist/api/context-types.d.ts +105 -0
  21. package/dist/api/context-types.js +3 -0
  22. package/dist/api/context.d.ts +31 -0
  23. package/dist/api/context.js +705 -0
  24. package/dist/api/dormant.d.ts +30 -0
  25. package/dist/api/dormant.js +140 -0
  26. package/dist/api/drill-down.d.ts +84 -0
  27. package/dist/api/drill-down.js +123 -0
  28. package/dist/api/forget.d.ts +57 -0
  29. package/dist/api/forget.js +87 -0
  30. package/dist/api/goals.d.ts +18 -0
  31. package/dist/api/goals.js +33 -0
  32. package/dist/api/learn.d.ts +31 -0
  33. package/dist/api/learn.js +88 -0
  34. package/dist/api/outcome.d.ts +61 -0
  35. package/dist/api/outcome.js +66 -0
  36. package/dist/api/promote.d.ts +54 -0
  37. package/dist/api/promote.js +203 -0
  38. package/dist/api/quarantine.d.ts +24 -0
  39. package/dist/api/quarantine.js +121 -0
  40. package/dist/api/recall-types.d.ts +390 -0
  41. package/dist/api/recall-types.js +3 -0
  42. package/dist/api/recall.d.ts +36 -0
  43. package/dist/api/recall.js +634 -0
  44. package/dist/api/remember.d.ts +35 -0
  45. package/dist/api/remember.js +43 -0
  46. package/dist/api/sleep.d.ts +136 -0
  47. package/dist/api/sleep.js +271 -0
  48. package/dist/api/tokens.d.ts +26 -0
  49. package/dist/api/tokens.js +60 -0
  50. package/dist/api/types.d.ts +56 -0
  51. package/dist/api/types.js +38 -0
  52. package/dist/api.d.ts +20 -1262
  53. package/dist/api.js +25 -2727
  54. package/dist/audit.d.ts +3 -0
  55. package/dist/audit.js +6 -3
  56. package/dist/auth.d.ts +45 -4
  57. package/dist/auth.js +125 -48
  58. package/dist/autolearn.js +2 -2
  59. package/dist/capture/command.d.ts +33 -0
  60. package/dist/capture/command.js +264 -0
  61. package/dist/capture/compact.d.ts +44 -0
  62. package/dist/capture/compact.js +354 -0
  63. package/dist/capture/extract.d.ts +21 -0
  64. package/dist/capture/extract.js +464 -0
  65. package/dist/capture/transcript.d.ts +40 -0
  66. package/dist/capture/transcript.js +193 -0
  67. package/dist/capture-error.js +2 -1
  68. package/dist/churn-git.js +4 -2
  69. package/dist/cli/audit.d.ts +3 -0
  70. package/dist/cli/audit.js +159 -0
  71. package/dist/cli/auth.d.ts +2 -0
  72. package/dist/cli/auth.js +171 -0
  73. package/dist/cli/briefs.d.ts +4 -0
  74. package/dist/cli/briefs.js +435 -0
  75. package/dist/cli/card.d.ts +3 -0
  76. package/dist/cli/card.js +333 -0
  77. package/dist/cli/context.d.ts +15 -0
  78. package/dist/cli/context.js +366 -0
  79. package/dist/cli/continuity.d.ts +6 -0
  80. package/dist/cli/continuity.js +445 -0
  81. package/dist/cli/curate.d.ts +19 -0
  82. package/dist/cli/curate.js +555 -0
  83. package/dist/cli/dag.d.ts +5 -0
  84. package/dist/cli/dag.js +177 -0
  85. package/dist/cli/decisions.d.ts +4 -0
  86. package/dist/cli/decisions.js +528 -0
  87. package/dist/cli/eval.d.ts +5 -0
  88. package/dist/cli/eval.js +213 -0
  89. package/dist/cli/explain.d.ts +4 -0
  90. package/dist/cli/explain.js +150 -0
  91. package/dist/cli/goals.d.ts +2 -0
  92. package/dist/cli/goals.js +196 -0
  93. package/dist/cli/hook-blocks.d.ts +18 -0
  94. package/dist/cli/hook-blocks.js +233 -0
  95. package/dist/cli/init.d.ts +2 -0
  96. package/dist/cli/init.js +305 -0
  97. package/dist/cli/maintenance.d.ts +4 -0
  98. package/dist/cli/maintenance.js +179 -0
  99. package/dist/cli/playbooks.d.ts +4 -0
  100. package/dist/cli/playbooks.js +556 -0
  101. package/dist/cli/projects.js +1 -1
  102. package/dist/cli/recall.d.ts +7 -0
  103. package/dist/cli/recall.js +597 -0
  104. package/dist/cli/remember.d.ts +5 -0
  105. package/dist/cli/remember.js +442 -0
  106. package/dist/cli/serve.d.ts +5 -0
  107. package/dist/cli/serve.js +40 -0
  108. package/dist/cli/session-hooks.d.ts +29 -0
  109. package/dist/cli/session-hooks.js +637 -0
  110. package/dist/cli/setup.d.ts +4 -0
  111. package/dist/cli/setup.js +376 -0
  112. package/dist/cli/shared.d.ts +15 -19
  113. package/dist/cli/shared.js +50 -341
  114. package/dist/cli/slack.d.ts +2 -0
  115. package/dist/cli/slack.js +171 -0
  116. package/dist/cli/status.d.ts +18 -0
  117. package/dist/cli/status.js +400 -0
  118. package/dist/cli/transfer.d.ts +10 -0
  119. package/dist/cli/transfer.js +438 -0
  120. package/dist/cli/usage.d.ts +85 -0
  121. package/dist/cli/usage.js +741 -0
  122. package/dist/cli.d.ts +71 -120
  123. package/dist/cli.js +170 -8469
  124. package/dist/client.js +15 -8
  125. package/dist/compaction-record.js +6 -4
  126. package/dist/connectors/github/backfill.js +94 -87
  127. package/dist/connectors/github/cli-impl.js +4 -3
  128. package/dist/connectors/github/dlq.js +67 -54
  129. package/dist/connectors/github/ingest.js +34 -35
  130. package/dist/connectors/github/tenant-routing.js +3 -2
  131. package/dist/connectors/github/webhook.js +135 -216
  132. package/dist/connectors/slack/dlq.js +49 -61
  133. package/dist/connectors/slack/ingest.js +55 -48
  134. package/dist/connectors/slack/tenant-routing.js +4 -3
  135. package/dist/connectors/slack/webhook.js +72 -74
  136. package/dist/consolidate/conflicts.d.ts +10 -0
  137. package/dist/consolidate/conflicts.js +178 -0
  138. package/dist/consolidate/decay.d.ts +12 -0
  139. package/dist/consolidate/decay.js +145 -0
  140. package/dist/consolidate/llm-passes.d.ts +3 -0
  141. package/dist/consolidate/llm-passes.js +141 -0
  142. package/dist/consolidate/merge.d.ts +7 -0
  143. package/dist/consolidate/merge.js +251 -0
  144. package/dist/consolidate/physics-pass.d.ts +3 -0
  145. package/dist/consolidate/physics-pass.js +60 -0
  146. package/dist/consolidate/run.d.ts +69 -0
  147. package/dist/consolidate/run.js +76 -0
  148. package/dist/consolidate/sleep.d.ts +18 -0
  149. package/dist/consolidate/sleep.js +209 -0
  150. package/dist/consolidate/traces.d.ts +4 -0
  151. package/dist/consolidate/traces.js +178 -0
  152. package/dist/context-auto.js +7 -11
  153. package/dist/context-render.d.ts +1 -1
  154. package/dist/context-render.js +1 -1
  155. package/dist/customer-notes.d.ts +3 -0
  156. package/dist/customer-notes.js +6 -4
  157. package/dist/dag.js +6 -5
  158. package/dist/dashboard-actions.d.ts +20 -0
  159. package/dist/dashboard-actions.js +88 -0
  160. package/dist/dashboard-params.d.ts +45 -0
  161. package/dist/dashboard-params.js +127 -0
  162. package/dist/dashboard-queries.d.ts +15 -0
  163. package/dist/dashboard-queries.js +355 -0
  164. package/dist/dashboard-snapshot.d.ts +138 -0
  165. package/dist/dashboard-snapshot.js +308 -0
  166. package/dist/dashboard-types.d.ts +163 -0
  167. package/dist/dashboard-types.js +3 -0
  168. package/dist/dashboard.d.ts +6 -7
  169. package/dist/dashboard.js +228 -202
  170. package/dist/db/busy.d.ts +5 -0
  171. package/dist/db/busy.js +24 -0
  172. package/dist/db/continuity.d.ts +5 -0
  173. package/dist/db/continuity.js +145 -0
  174. package/dist/db/meta.d.ts +8 -0
  175. package/dist/db/meta.js +35 -0
  176. package/dist/db/migrate.d.ts +9 -0
  177. package/dist/db/migrate.js +138 -0
  178. package/dist/db/migrations/index.d.ts +5 -0
  179. package/dist/db/migrations/index.js +109 -0
  180. package/dist/db/migrations/types.d.ts +14 -0
  181. package/dist/db/migrations/types.js +2 -0
  182. package/dist/db/migrations/v01.d.ts +3 -0
  183. package/dist/db/migrations/v01.js +38 -0
  184. package/dist/db/migrations/v02.d.ts +3 -0
  185. package/dist/db/migrations/v02.js +21 -0
  186. package/dist/db/migrations/v03.d.ts +3 -0
  187. package/dist/db/migrations/v03.js +22 -0
  188. package/dist/db/migrations/v04.d.ts +3 -0
  189. package/dist/db/migrations/v04.js +28 -0
  190. package/dist/db/migrations/v05.d.ts +3 -0
  191. package/dist/db/migrations/v05.js +21 -0
  192. package/dist/db/migrations/v06.d.ts +3 -0
  193. package/dist/db/migrations/v06.js +25 -0
  194. package/dist/db/migrations/v07.d.ts +3 -0
  195. package/dist/db/migrations/v07.js +13 -0
  196. package/dist/db/migrations/v08.d.ts +3 -0
  197. package/dist/db/migrations/v08.js +8 -0
  198. package/dist/db/migrations/v09.d.ts +3 -0
  199. package/dist/db/migrations/v09.js +13 -0
  200. package/dist/db/migrations/v10.d.ts +3 -0
  201. package/dist/db/migrations/v10.js +17 -0
  202. package/dist/db/migrations/v11.d.ts +3 -0
  203. package/dist/db/migrations/v11.js +15 -0
  204. package/dist/db/migrations/v12.d.ts +3 -0
  205. package/dist/db/migrations/v12.js +11 -0
  206. package/dist/db/migrations/v13.d.ts +3 -0
  207. package/dist/db/migrations/v13.js +15 -0
  208. package/dist/db/migrations/v14.d.ts +3 -0
  209. package/dist/db/migrations/v14.js +66 -0
  210. package/dist/db/migrations/v15.d.ts +3 -0
  211. package/dist/db/migrations/v15.js +42 -0
  212. package/dist/db/migrations/v16.d.ts +3 -0
  213. package/dist/db/migrations/v16.js +61 -0
  214. package/dist/db/migrations/v17.d.ts +3 -0
  215. package/dist/db/migrations/v17.js +46 -0
  216. package/dist/db/migrations/v18.d.ts +3 -0
  217. package/dist/db/migrations/v18.js +60 -0
  218. package/dist/db/migrations/v19.d.ts +3 -0
  219. package/dist/db/migrations/v19.js +28 -0
  220. package/dist/db/migrations/v20.d.ts +3 -0
  221. package/dist/db/migrations/v20.js +42 -0
  222. package/dist/db/migrations/v21.d.ts +3 -0
  223. package/dist/db/migrations/v21.js +16 -0
  224. package/dist/db/migrations/v22.d.ts +3 -0
  225. package/dist/db/migrations/v22.js +82 -0
  226. package/dist/db/migrations/v23.d.ts +3 -0
  227. package/dist/db/migrations/v23.js +48 -0
  228. package/dist/db/migrations/v24.d.ts +3 -0
  229. package/dist/db/migrations/v24.js +72 -0
  230. package/dist/db/migrations/v25.d.ts +3 -0
  231. package/dist/db/migrations/v25.js +46 -0
  232. package/dist/db/migrations/v26.d.ts +3 -0
  233. package/dist/db/migrations/v26.js +23 -0
  234. package/dist/db/migrations/v27.d.ts +3 -0
  235. package/dist/db/migrations/v27.js +57 -0
  236. package/dist/db/migrations/v28.d.ts +3 -0
  237. package/dist/db/migrations/v28.js +38 -0
  238. package/dist/db/migrations/v29.d.ts +3 -0
  239. package/dist/db/migrations/v29.js +78 -0
  240. package/dist/db/migrations/v30.d.ts +3 -0
  241. package/dist/db/migrations/v30.js +92 -0
  242. package/dist/db/migrations/v31.d.ts +3 -0
  243. package/dist/db/migrations/v31.js +74 -0
  244. package/dist/db/migrations/v32.d.ts +3 -0
  245. package/dist/db/migrations/v32.js +102 -0
  246. package/dist/db/migrations/v33.d.ts +3 -0
  247. package/dist/db/migrations/v33.js +104 -0
  248. package/dist/db/migrations/v34.d.ts +3 -0
  249. package/dist/db/migrations/v34.js +93 -0
  250. package/dist/db/migrations/v35.d.ts +3 -0
  251. package/dist/db/migrations/v35.js +98 -0
  252. package/dist/db/migrations/v36.d.ts +3 -0
  253. package/dist/db/migrations/v36.js +98 -0
  254. package/dist/db/migrations/v37.d.ts +3 -0
  255. package/dist/db/migrations/v37.js +219 -0
  256. package/dist/db/migrations/v38.d.ts +3 -0
  257. package/dist/db/migrations/v38.js +277 -0
  258. package/dist/db/migrations/v39.d.ts +3 -0
  259. package/dist/db/migrations/v39.js +59 -0
  260. package/dist/db/migrations/v40.d.ts +3 -0
  261. package/dist/db/migrations/v40.js +74 -0
  262. package/dist/db/migrations/v41.d.ts +3 -0
  263. package/dist/db/migrations/v41.js +43 -0
  264. package/dist/db/migrations/v42.d.ts +3 -0
  265. package/dist/db/migrations/v42.js +41 -0
  266. package/dist/db/migrations/v43.d.ts +3 -0
  267. package/dist/db/migrations/v43.js +67 -0
  268. package/dist/db/migrations/v44.d.ts +3 -0
  269. package/dist/db/migrations/v44.js +28 -0
  270. package/dist/db/migrations/v45.d.ts +3 -0
  271. package/dist/db/migrations/v45.js +30 -0
  272. package/dist/db/migrations/v46.d.ts +3 -0
  273. package/dist/db/migrations/v46.js +25 -0
  274. package/dist/db/migrations/v47.d.ts +3 -0
  275. package/dist/db/migrations/v47.js +17 -0
  276. package/dist/db/migrations/v48.d.ts +3 -0
  277. package/dist/db/migrations/v48.js +10 -0
  278. package/dist/db/migrations/v49.d.ts +3 -0
  279. package/dist/db/migrations/v49.js +31 -0
  280. package/dist/db/migrations/v50.d.ts +3 -0
  281. package/dist/db/migrations/v50.js +67 -0
  282. package/dist/db/migrations/v51.d.ts +3 -0
  283. package/dist/db/migrations/v51.js +14 -0
  284. package/dist/db/migrations/v52.d.ts +3 -0
  285. package/dist/db/migrations/v52.js +7 -0
  286. package/dist/db/open.d.ts +23 -0
  287. package/dist/db/open.js +146 -0
  288. package/dist/db/sqlite.d.ts +21 -0
  289. package/dist/db/sqlite.js +8 -0
  290. package/dist/db/tables.d.ts +7 -0
  291. package/dist/db/tables.js +38 -0
  292. package/dist/db.d.ts +6 -46
  293. package/dist/db.js +5 -3049
  294. package/dist/decisions.d.ts +4 -1
  295. package/dist/decisions.js +9 -7
  296. package/dist/dedupe.js +3 -2
  297. package/dist/delivery-recorder.js +4 -1
  298. package/dist/doctor.js +3 -3
  299. package/dist/embedding-provider.d.ts +1 -1
  300. package/dist/embedding-provider.js +4 -3
  301. package/dist/embeddings.d.ts +9 -52
  302. package/dist/embeddings.js +43 -297
  303. package/dist/env.d.ts +75 -0
  304. package/dist/env.js +119 -0
  305. package/dist/eval-suite.js +1 -1
  306. package/dist/eval.js +2 -2
  307. package/dist/extract.js +1 -1
  308. package/dist/gated-write.js +3 -1
  309. package/dist/goals.d.ts +3 -1
  310. package/dist/goals.js +18 -0
  311. package/dist/graph/read.d.ts +73 -0
  312. package/dist/graph/read.js +325 -0
  313. package/dist/graph/rows.d.ts +45 -0
  314. package/dist/graph/rows.js +51 -0
  315. package/dist/graph/types.d.ts +83 -0
  316. package/dist/graph/types.js +11 -0
  317. package/dist/graph/write.d.ts +93 -0
  318. package/dist/{graph.js → graph/write.js} +6 -384
  319. package/dist/graph-extract.js +2 -1
  320. package/dist/graph-recall.d.ts +1 -1
  321. package/dist/graph-recall.js +2 -2
  322. package/dist/graph-stream.js +1 -1
  323. package/dist/graph-view.d.ts +1 -1
  324. package/dist/graph-view.js +1 -1
  325. package/dist/half-life-migration.d.ts +1 -1
  326. package/dist/half-life-migration.js +2 -1
  327. package/dist/hooks/codex-session.d.ts +8 -0
  328. package/dist/hooks/codex-session.js +76 -0
  329. package/dist/hooks/codex-wrapper.d.ts +55 -0
  330. package/dist/hooks/codex-wrapper.js +288 -0
  331. package/dist/hooks/json-hooks.d.ts +63 -0
  332. package/dist/hooks/json-hooks.js +356 -0
  333. package/dist/hooks/opencode.d.ts +50 -0
  334. package/dist/hooks/opencode.js +202 -0
  335. package/dist/hooks/shared.d.ts +54 -0
  336. package/dist/hooks/shared.js +77 -0
  337. package/dist/http-retry.d.ts +2 -0
  338. package/dist/http-retry.js +4 -3
  339. package/dist/http-util.d.ts +3 -0
  340. package/dist/http-util.js +10 -0
  341. package/dist/{importers.d.ts → importers/core.d.ts} +13 -17
  342. package/dist/importers/core.js +141 -0
  343. package/dist/importers/markdown-parse.d.ts +41 -0
  344. package/dist/importers/markdown-parse.js +132 -0
  345. package/dist/importers/markdown.d.ts +3 -0
  346. package/dist/importers/markdown.js +92 -0
  347. package/dist/importers/sources.d.ts +7 -0
  348. package/dist/importers/sources.js +229 -0
  349. package/dist/importers/vault.d.ts +11 -0
  350. package/dist/importers/vault.js +352 -0
  351. package/dist/incidents.d.ts +3 -0
  352. package/dist/incidents.js +7 -5
  353. package/dist/index.d.ts +25 -6
  354. package/dist/index.js +23 -6
  355. package/dist/invalidation.js +2 -1
  356. package/dist/judgment.js +2 -1
  357. package/dist/keyset.d.ts +13 -0
  358. package/dist/keyset.js +8 -0
  359. package/dist/local-embedding.d.ts +13 -0
  360. package/dist/local-embedding.js +165 -0
  361. package/dist/log.d.ts +7 -0
  362. package/dist/log.js +19 -1
  363. package/dist/mcp/admin-tools.d.ts +8 -0
  364. package/dist/mcp/admin-tools.js +116 -0
  365. package/dist/mcp/format.d.ts +27 -0
  366. package/dist/mcp/format.js +135 -0
  367. package/dist/mcp/memory-tools.d.ts +5 -0
  368. package/dist/mcp/memory-tools.js +83 -0
  369. package/dist/mcp/protocol.d.ts +83 -0
  370. package/dist/mcp/protocol.js +55 -0
  371. package/dist/mcp/recall-tools.d.ts +6 -0
  372. package/dist/mcp/recall-tools.js +320 -0
  373. package/dist/mcp/request.d.ts +10 -0
  374. package/dist/mcp/request.js +163 -0
  375. package/dist/mcp/server.d.ts +4 -75
  376. package/dist/mcp/server.js +7 -1190
  377. package/dist/mcp/session-state.d.ts +11 -0
  378. package/dist/mcp/session-state.js +28 -0
  379. package/dist/mcp/stdio.d.ts +8 -0
  380. package/dist/mcp/stdio.js +79 -0
  381. package/dist/mcp/tools.d.ts +11 -0
  382. package/dist/mcp/tools.js +247 -0
  383. package/dist/memory.d.ts +3 -0
  384. package/dist/memory.js +27 -1
  385. package/dist/multihop.d.ts +1 -1
  386. package/dist/multihop.js +2 -1
  387. package/dist/owner-validation.js +2 -1
  388. package/dist/physics-state.js +10 -7
  389. package/dist/policies.d.ts +3 -0
  390. package/dist/policies.js +8 -6
  391. package/dist/postinstall.js +3 -2
  392. package/dist/predictions/planning-fallacy.d.ts +100 -0
  393. package/dist/predictions/planning-fallacy.js +190 -0
  394. package/dist/{predictions.d.ts → predictions/store.d.ts} +7 -102
  395. package/dist/predictions/store.js +434 -0
  396. package/dist/processes.d.ts +3 -0
  397. package/dist/processes.js +7 -5
  398. package/dist/project-briefs.d.ts +3 -0
  399. package/dist/project-briefs.js +7 -5
  400. package/dist/project-identity.js +3 -2
  401. package/dist/project-merge.js +3 -1
  402. package/dist/quarantine.d.ts +2 -1
  403. package/dist/quarantine.js +8 -5
  404. package/dist/raw-archive.js +1 -1
  405. package/dist/recall-history.js +3 -2
  406. package/dist/recall-pipeline.d.ts +2 -2
  407. package/dist/recall-pipeline.js +16 -8
  408. package/dist/recall-scope.js +1 -1
  409. package/dist/recall-trace.d.ts +1 -1
  410. package/dist/refine-llm.js +2 -1
  411. package/dist/reject-flow.js +6 -1
  412. package/dist/rerankers/clef.js +6 -5
  413. package/dist/rerankers/jev.d.ts +1 -1
  414. package/dist/rerankers/jev.js +4 -4
  415. package/dist/rerankers/llm.d.ts +4 -2
  416. package/dist/rerankers/llm.js +58 -38
  417. package/dist/rerankers/types.d.ts +1 -1
  418. package/dist/salience.js +1 -1
  419. package/dist/scheduler.d.ts +1 -0
  420. package/dist/scheduler.js +26 -4
  421. package/dist/scope.js +4 -3
  422. package/dist/search/as-of.d.ts +10 -0
  423. package/dist/search/as-of.js +22 -0
  424. package/dist/search/bm25-search.d.ts +14 -0
  425. package/dist/search/bm25-search.js +43 -0
  426. package/dist/search/bm25.d.ts +15 -0
  427. package/dist/search/bm25.js +54 -0
  428. package/dist/search/boosts.d.ts +54 -0
  429. package/dist/search/boosts.js +94 -0
  430. package/dist/search/breakdown.d.ts +7 -0
  431. package/dist/search/breakdown.js +20 -0
  432. package/dist/search/explain.d.ts +25 -0
  433. package/dist/search/explain.js +31 -0
  434. package/dist/search/finalize.d.ts +8 -0
  435. package/dist/search/finalize.js +52 -0
  436. package/dist/search/fusion.d.ts +27 -0
  437. package/dist/search/fusion.js +42 -0
  438. package/dist/search/hybrid-score.d.ts +20 -0
  439. package/dist/search/hybrid-score.js +73 -0
  440. package/dist/search/hybrid.d.ts +46 -0
  441. package/dist/search/hybrid.js +64 -0
  442. package/dist/search/physics-search.d.ts +29 -0
  443. package/dist/search/physics-search.js +162 -0
  444. package/dist/search/rerank.d.ts +10 -0
  445. package/dist/search/rerank.js +72 -0
  446. package/dist/search/temporal.d.ts +15 -0
  447. package/dist/search/temporal.js +45 -0
  448. package/dist/search/types.d.ts +91 -0
  449. package/dist/search/types.js +2 -0
  450. package/dist/search/vector.d.ts +30 -0
  451. package/dist/search/vector.js +71 -0
  452. package/dist/secret-detect.d.ts +2 -0
  453. package/dist/secret-detect.js +2 -1
  454. package/dist/server/auth.d.ts +52 -0
  455. package/dist/server/auth.js +221 -0
  456. package/dist/server/client-ip.d.ts +25 -0
  457. package/dist/server/client-ip.js +92 -0
  458. package/dist/server/cursor.d.ts +23 -0
  459. package/dist/server/cursor.js +58 -0
  460. package/dist/server/lifecycle.d.ts +7 -0
  461. package/dist/server/lifecycle.js +29 -0
  462. package/dist/server/mcp-http.d.ts +5 -0
  463. package/dist/server/mcp-http.js +199 -0
  464. package/dist/server/request.d.ts +33 -0
  465. package/dist/server/request.js +103 -0
  466. package/dist/server/routes/admin.d.ts +9 -0
  467. package/dist/server/routes/admin.js +158 -0
  468. package/dist/server/routes/customer-notes.d.ts +7 -0
  469. package/dist/server/routes/customer-notes.js +112 -0
  470. package/dist/server/routes/decisions.d.ts +7 -0
  471. package/dist/server/routes/decisions.js +133 -0
  472. package/dist/server/routes/incidents.d.ts +7 -0
  473. package/dist/server/routes/incidents.js +126 -0
  474. package/dist/server/routes/memories.d.ts +10 -0
  475. package/dist/server/routes/memories.js +179 -0
  476. package/dist/server/routes/policies.d.ts +8 -0
  477. package/dist/server/routes/policies.js +151 -0
  478. package/dist/server/routes/predictions.d.ts +7 -0
  479. package/dist/server/routes/predictions.js +164 -0
  480. package/dist/server/routes/processes.d.ts +7 -0
  481. package/dist/server/routes/processes.js +161 -0
  482. package/dist/server/routes/project-briefs.d.ts +8 -0
  483. package/dist/server/routes/project-briefs.js +136 -0
  484. package/dist/server/routes/recall.d.ts +8 -0
  485. package/dist/server/routes/recall.js +340 -0
  486. package/dist/server/routes/skills.d.ts +8 -0
  487. package/dist/server/routes/skills.js +150 -0
  488. package/dist/server/types.d.ts +56 -0
  489. package/dist/server/types.js +2 -0
  490. package/dist/server/validation.d.ts +14 -0
  491. package/dist/server/validation.js +91 -0
  492. package/dist/server.d.ts +7 -61
  493. package/dist/server.js +69 -2362
  494. package/dist/session-digest.d.ts +1 -1
  495. package/dist/session-digest.js +9 -2
  496. package/dist/shared.d.ts +3 -1
  497. package/dist/shared.js +26 -22
  498. package/dist/skills.d.ts +3 -0
  499. package/dist/skills.js +7 -5
  500. package/dist/stdin.js +2 -2
  501. package/dist/store/audit-event.d.ts +19 -0
  502. package/dist/store/audit-event.js +33 -0
  503. package/dist/store/candidates.d.ts +42 -0
  504. package/dist/store/candidates.js +152 -0
  505. package/dist/store/conflicts.d.ts +44 -0
  506. package/dist/store/conflicts.js +444 -0
  507. package/dist/store/delete-and-batch.d.ts +63 -0
  508. package/dist/store/delete-and-batch.js +310 -0
  509. package/dist/store/entry-reads.d.ts +92 -0
  510. package/dist/store/entry-reads.js +255 -0
  511. package/dist/store/entry-row.d.ts +67 -0
  512. package/dist/store/entry-row.js +208 -0
  513. package/dist/store/entry-writes.d.ts +46 -0
  514. package/dist/store/entry-writes.js +148 -0
  515. package/dist/store/handoffs.d.ts +26 -0
  516. package/dist/store/handoffs.js +184 -0
  517. package/dist/store/index-and-stats.d.ts +52 -0
  518. package/dist/store/index-and-stats.js +214 -0
  519. package/dist/store/markdown.d.ts +10 -0
  520. package/dist/store/markdown.js +108 -0
  521. package/dist/store/mirrors.d.ts +49 -0
  522. package/dist/store/mirrors.js +312 -0
  523. package/dist/store/open.d.ts +15 -0
  524. package/dist/store/open.js +223 -0
  525. package/dist/store/rows.d.ts +178 -0
  526. package/dist/store/rows.js +158 -0
  527. package/dist/store/search-rows.d.ts +86 -0
  528. package/dist/store/search-rows.js +254 -0
  529. package/dist/store/sessions.d.ts +83 -0
  530. package/dist/store/sessions.js +272 -0
  531. package/dist/store/summaries.d.ts +94 -0
  532. package/dist/store/summaries.js +377 -0
  533. package/dist/store/tenant-lookup.d.ts +12 -0
  534. package/dist/store/tenant-lookup.js +16 -0
  535. package/dist/store-cards.js +2 -1
  536. package/dist/summary-dirty.d.ts +4 -0
  537. package/dist/summary-dirty.js +32 -0
  538. package/dist/support-bundle.js +4 -3
  539. package/dist/tenant.js +2 -2
  540. package/dist/tokenize.d.ts +2 -0
  541. package/dist/tokenize.js +16 -0
  542. package/dist/transcript-tail.d.ts +7 -0
  543. package/dist/transcript-tail.js +48 -0
  544. package/dist/vector-store.d.ts +27 -0
  545. package/dist/vector-store.js +210 -0
  546. package/dist/version.d.ts +2 -2
  547. package/dist/version.js +2 -2
  548. package/dist/working-memory.js +1 -1
  549. package/dist/yaml.js +36 -11
  550. package/dist-ui/assets/ibm-plex-mono-latin-400-normal-CvHOgSBP.woff +0 -0
  551. package/dist-ui/assets/ibm-plex-mono-latin-400-normal-DMJ8VG8y.woff2 +0 -0
  552. package/dist-ui/assets/ibm-plex-mono-latin-500-normal-CB9ihrfo.woff +0 -0
  553. package/dist-ui/assets/ibm-plex-mono-latin-500-normal-DSY6xOcd.woff2 +0 -0
  554. package/dist-ui/assets/ibm-plex-mono-latin-600-normal-BgSNZQsw.woff2 +0 -0
  555. package/dist-ui/assets/ibm-plex-mono-latin-600-normal-DWFSQ4vo.woff +0 -0
  556. package/dist-ui/assets/ibm-plex-sans-latin-400-normal-CDDApCn2.woff2 +0 -0
  557. package/dist-ui/assets/ibm-plex-sans-latin-400-normal-CYLoc0-x.woff +0 -0
  558. package/dist-ui/assets/ibm-plex-sans-latin-500-normal-6ng42L7E.woff2 +0 -0
  559. package/dist-ui/assets/ibm-plex-sans-latin-500-normal-BgVn5rGT.woff +0 -0
  560. package/dist-ui/assets/ibm-plex-sans-latin-600-normal-Cu4Hd6ag.woff +0 -0
  561. package/dist-ui/assets/ibm-plex-sans-latin-600-normal-CuJfVYMP.woff2 +0 -0
  562. package/dist-ui/assets/index-DPN7cP19.js +33 -0
  563. package/dist-ui/assets/index-dFloKRVr.css +1 -0
  564. package/dist-ui/index.html +3 -25
  565. package/extensions/openclaw-plugin/openclaw.plugin.json +1 -1
  566. package/extensions/openclaw-plugin/package.json +1 -1
  567. package/openclaw.plugin.json +1 -1
  568. package/package.json +1 -1
  569. package/dist/capture.d.ts +0 -155
  570. package/dist/capture.js +0 -1295
  571. package/dist/consolidate.d.ts +0 -58
  572. package/dist/consolidate.js +0 -1124
  573. package/dist/graph.d.ts +0 -245
  574. package/dist/hooks.d.ts +0 -208
  575. package/dist/hooks.js +0 -1076
  576. package/dist/importers.js +0 -900
  577. package/dist/predictions.js +0 -620
  578. package/dist/search.d.ts +0 -320
  579. package/dist/search.js +0 -970
  580. package/dist/store.d.ts +0 -776
  581. package/dist/store.js +0 -3473
  582. package/dist-ui/assets/d3-BiWEKnn4.js +0 -1
  583. package/dist-ui/assets/index-BhT8RvO6.js +0 -61
  584. package/dist-ui/assets/index-RoXXJ5dq.css +0 -1
  585. package/dist-ui/assets/three-BDgTxR1l.js +0 -4112
@@ -0,0 +1,637 @@
1
+ // Agent lifecycle hook verbs: session end, compaction, tool-failure capture and the Codex wrapper.
2
+ import * as path from 'path';
3
+ import * as fs from 'fs';
4
+ import { spawn } from 'child_process';
5
+ import { defaultSleepLogPath } from '../hooks/shared.js';
6
+ import { resolveCodexSessionTranscript } from '../hooks/codex-session.js';
7
+ import { resolveCodexWrapperPaths } from '../hooks/codex-wrapper.js';
8
+ import { isInitialized } from '../store/open.js';
9
+ import { loadActiveTaskSnapshot, loadFreshActiveTaskSnapshot, closeTaskSnapshotsForSession, listSessionEvents, } from '../store/sessions.js';
10
+ import { writeSessionEndHandoff } from '../store/handoffs.js';
11
+ import { readSessionScan, recordSessionDigest } from '../session-digest.js';
12
+ import { openHippoDb, closeHippoDb } from '../db.js';
13
+ import { captureToolFailure } from '../capture-error.js';
14
+ import { estimateTokens, isSubagentPayload, readApiCalls, recordRereads, recordTokenUse, } from '../token-ledger.js';
15
+ import { currentMachine, importAtCompaction } from '../agent-memories/sync.js';
16
+ import { summaryLine } from '../agent-memories/report.js';
17
+ import { deriveOriginProject } from '../project-identity.js';
18
+ import { getGlobalRoot } from '../shared.js';
19
+ import { cmdCapture } from '../capture/command.js';
20
+ import { cmdPreCompact, cmdPostCompact, transcriptWorkingState } from '../capture/compact.js';
21
+ import { resolveLastSessionTranscript } from '../capture/transcript.js';
22
+ import { truncateCodePointSafe } from '../transcript-tail.js';
23
+ import { COMPACTION_DB_WAIT_MS } from '../compaction-record.js';
24
+ import { readStdinBounded } from '../stdin.js';
25
+ import { resolveTenantId } from '../tenant.js';
26
+ import { log } from '../log.js';
27
+ import { printError } from './output.js';
28
+ import { collectHandoffEvidence, logSessionEndImport, appendSessionEndCloseLog, printActiveTaskSnapshot, printSessionEvents, resetHookInjection, captureConsole, hookStoreRoot, withLedgerDb, runHookWithStores, inPilotHoldout, } from './shared.js';
29
+ /** Prints the SessionEnd sleep log, then clears it. Stderr, because Claude Code adds
30
+ * SessionStart stdout to the model's context and this log is for the user. */
31
+ export function cmdLastSleep(flags) {
32
+ const logPath = typeof flags['path'] === 'string'
33
+ ? flags['path']
34
+ : defaultSleepLogPath();
35
+ if (!fs.existsSync(logPath))
36
+ return;
37
+ let content;
38
+ try {
39
+ content = fs.readFileSync(logPath, 'utf8');
40
+ }
41
+ catch {
42
+ // Removed or locked since the exists check: there is nothing to show this session.
43
+ return;
44
+ }
45
+ if (content.trim().length > 0) {
46
+ printError('=== Previous session hippo consolidation ===');
47
+ process.stderr.write(content);
48
+ if (!content.endsWith('\n'))
49
+ printError();
50
+ printError('===========================================');
51
+ }
52
+ if (!flags['keep']) {
53
+ try {
54
+ fs.unlinkSync(logPath);
55
+ }
56
+ catch { /* non-fatal */ }
57
+ }
58
+ }
59
+ /**
60
+ * SessionStart(compact) injector. Prints the active task snapshot + recent
61
+ * session trail so working state that would otherwise be lost to
62
+ * compaction summarisation survives into the new context window. No pinned
63
+ * memories here — the UserPromptSubmit hook already re-injects those every
64
+ * turn, so duplicating them here would double token cost for nothing.
65
+ *
66
+ * Same exit-0/crash-safety contract as `hippo pre-compact` (critic round
67
+ * 2): every path exits 0. A malformed payload or a store read failure
68
+ * degrades to empty stdout, never a thrown error — a failing SessionStart
69
+ * hook must not pollute session startup.
70
+ */
71
+ // X8: session-event content is capped at print time only — the shared
72
+ // printSessionEvents stays untouched for every other caller.
73
+ const COMPACT_RESUME_EVENT_CONTENT_CAP = 400;
74
+ // A snapshot older than this was not written for this compaction (pre-compact skipped), so restoring it is stale, not a resume.
75
+ const COMPACT_RESUME_MAX_AGE_MS = 15 * 60_000;
76
+ function cmdCompactResume(hippoRoot, stdinText, stdinTimedOut) {
77
+ try {
78
+ // X3: gate on the non-exiting isInitialized check before any
79
+ // store-opening call (loadActiveTaskSnapshot/listSessionEvents both
80
+ // call initStore internally, which would silently create a store in a
81
+ // project that never ran `hippo init` — this hook fires globally).
82
+ if (!isInitialized(hippoRoot)) {
83
+ process.exit(0);
84
+ }
85
+ // The matcher is an optimization, not a dependency: older Claude Code
86
+ // that ignores `matcher: 'compact'` would run this on every SessionStart,
87
+ // so we also gate on payload.source here. A payload that parses but
88
+ // carries a different source (e.g. 'startup') means the matcher-based
89
+ // gate failed to apply — stay silent rather than print stale state.
90
+ const nonEmptyStdin = !!stdinText && stdinText.trim() !== '';
91
+ // Without a payload session_id the X5 cross-restore guard below can
92
+ // never fire, so a timed-out empty read must not reach the print path.
93
+ let suppressOutput = stdinTimedOut && !nonEmptyStdin;
94
+ let payloadSessionId = null;
95
+ if (nonEmptyStdin) {
96
+ let payload = null;
97
+ try {
98
+ payload = JSON.parse(stdinText.trim());
99
+ }
100
+ catch {
101
+ // Malformed JSON is handled as a null payload by the fail-closed check below.
102
+ payload = null;
103
+ }
104
+ if (!payload || typeof payload !== 'object') {
105
+ // X13: fail closed on malformed non-empty stdin. The earlier
106
+ // "print on malformed" behavior survives only for TTY/no-stdin
107
+ // manual invocation (nonEmptyStdin is false there, this branch
108
+ // never runs).
109
+ suppressOutput = true;
110
+ }
111
+ else {
112
+ // Fail closed on structurally incomplete payloads too ({}, [],
113
+ // source missing/non-string): any parsed non-empty payload must say
114
+ // source === 'compact' to print. Real SessionStart payloads always
115
+ // carry source; only the TTY/no-stdin manual path prints without
116
+ // one (codex round 3).
117
+ // A sub-agent's payload carries its parent's session id, so X5 would pass and restore the parent's snapshot into it.
118
+ if (payload.source !== 'compact' || isSubagentPayload(stdinText)) {
119
+ suppressOutput = true;
120
+ }
121
+ if (typeof payload.session_id === 'string') {
122
+ payloadSessionId = payload.session_id;
123
+ }
124
+ }
125
+ }
126
+ // A compaction follows a prompt or SessionStart that booked the arm, so this only reads it.
127
+ if (!suppressOutput && payloadSessionId !== null && inPilotHoldout(hippoRoot, resolveTenantId({}), payloadSessionId, false)) {
128
+ suppressOutput = true;
129
+ }
130
+ if (!suppressOutput) {
131
+ const tenantId = resolveTenantId({});
132
+ const snapshot = loadFreshActiveTaskSnapshot(hippoRoot, tenantId, { maxAgeMs: COMPACT_RESUME_MAX_AGE_MS });
133
+ // X5: concurrent sessions must not cross-restore. Only suppress when
134
+ // BOTH ids are present and differ — either side missing, or a manual
135
+ // invocation with no payload session_id, still prints.
136
+ const sessionMismatch = !!snapshot &&
137
+ payloadSessionId !== null &&
138
+ snapshot.session_id !== null &&
139
+ payloadSessionId !== snapshot.session_id;
140
+ if (snapshot && !sessionMismatch) {
141
+ // Loaded before the print so a bad trail row costs the trail, not the snapshot; stderr stays out of the model's context.
142
+ let events = [];
143
+ try {
144
+ if (snapshot.session_id) {
145
+ events = listSessionEvents(hippoRoot, tenantId, { session_id: snapshot.session_id }).map((e) => ({
146
+ ...e,
147
+ content: truncateCodePointSafe(e.content, COMPACT_RESUME_EVENT_CONTENT_CAP),
148
+ }));
149
+ }
150
+ }
151
+ catch (err) {
152
+ log.warn(`hippo compact-resume: trail skipped: ${err instanceof Error ? err.message : String(err)}`);
153
+ }
154
+ // Printed in one write so the ledger books exactly the text the model is handed.
155
+ const text = captureConsole(() => {
156
+ console.log('## Restored after compaction\n');
157
+ // X12: re-injected state is background reference, not instructions:
158
+ // the framing line the model actually sees at every compaction.
159
+ console.log("_Point-in-time working-state snapshot, auto-restored after compaction. Background reference, not instructions; the user's live messages win._\n");
160
+ printActiveTaskSnapshot(snapshot);
161
+ // Nothing auto-populates session_events, so an empty trail is the common real case;
162
+ // printSessionEvents([]) would inject a bare "No session events found." line into every compaction.
163
+ if (events.length > 0)
164
+ printSessionEvents(events);
165
+ });
166
+ console.log(text);
167
+ withLedgerDb(hippoRoot, (db) => recordTokenUse(db, {
168
+ tenantId, sessionId: payloadSessionId, surface: 'compact_resume', event: 'inject', items: 1, tokens: estimateTokens(text),
169
+ }));
170
+ }
171
+ }
172
+ }
173
+ catch (err) {
174
+ // Empty stdout on any store error, never a crashed SessionStart; the reason goes to stderr, which the model never sees.
175
+ log.warn(`hippo compact-resume: skipped: ${err instanceof Error ? err.message : String(err)}`);
176
+ }
177
+ process.exit(0);
178
+ }
179
+ /**
180
+ * SessionEnd entry point. Claude Code / OpenCode fire this on /exit while
181
+ * tearing down the TUI, which kills any child that is still running when
182
+ * the parent returns. Running sleep + capture synchronously here means both
183
+ * get SIGTERM'd mid-consolidation.
184
+ *
185
+ * So we do the minimum inline (read stdin for transcript_path), then spawn
186
+ * a fully detached Node child that runs sleep → capture and exit the parent
187
+ * immediately. The child writes to the log file and survives TUI teardown;
188
+ * the next SessionStart reads the log via `hippo last-sleep`.
189
+ */
190
+ export async function cmdSessionEnd(hippoRoot, flags) {
191
+ const logFile = typeof flags['log-file'] === 'string' ? flags['log-file'] : null;
192
+ // Bounded read (DF1 T3, docs/plans/2026-08-23-df1-snapshot-lifecycle.md):
193
+ // extracts transcript_path + session_id for the detached worker's argv.
194
+ let sessionId = null;
195
+ const { text: stdinText } = await readStdinBounded();
196
+ try {
197
+ if (stdinText && stdinText.trim().startsWith('{')) {
198
+ const payload = JSON.parse(stdinText);
199
+ if (typeof payload.session_id === 'string') {
200
+ sessionId = payload.session_id;
201
+ }
202
+ }
203
+ }
204
+ catch {
205
+ // No stdin, not JSON, or read failure: the snapshot close below will no-op.
206
+ }
207
+ // Resolved here because only this process saw the payload; the worker captures just the path it is handed.
208
+ // Always a hook, so never scan: an empty stdin here is not a manual run.
209
+ const transcriptPath = resolveLastSessionTranscript(undefined, stdinText, { mayScan: false });
210
+ const workerArgs = [process.argv[1], '__session-end-worker'];
211
+ if (logFile)
212
+ workerArgs.push('--log-file', logFile);
213
+ if (transcriptPath)
214
+ workerArgs.push('--transcript', transcriptPath);
215
+ if (sessionId)
216
+ workerArgs.push('--session-id', sessionId);
217
+ try {
218
+ const child = spawn(process.execPath, workerArgs, {
219
+ detached: true,
220
+ stdio: 'ignore',
221
+ windowsHide: true,
222
+ });
223
+ child.unref();
224
+ }
225
+ catch (err) {
226
+ // If spawn fails, run inline as a last resort, handed what the child's argv would have carried.
227
+ if (transcriptPath)
228
+ flags['transcript'] = transcriptPath;
229
+ if (sessionId)
230
+ flags['session-id'] = sessionId;
231
+ await cmdSessionEndWorker(hippoRoot, flags);
232
+ return;
233
+ }
234
+ }
235
+ export async function cmdSessionEndWorker(hippoRoot, flags) {
236
+ const transcriptPath = typeof flags['transcript'] === 'string' ? flags['transcript'] : undefined;
237
+ const closeLogFile = typeof flags['log-file'] === 'string' ? flags['log-file'] : null;
238
+ const closeSessionId = typeof flags['session-id'] === 'string' ? flags['session-id'] : null;
239
+ const rereadLog = await bookSessionRereads(hippoRoot, transcriptPath, closeSessionId)
240
+ .catch((err) => [`re-read count failed: ${err instanceof Error ? err.message : String(err)}`]);
241
+ // Sleep starts the log file afresh, so the lines go in after it; on exit too, in case sleep exits the process.
242
+ const flushRereadLog = () => { for (const line of rereadLog.splice(0))
243
+ appendSessionEndCloseLog(closeLogFile, line); };
244
+ process.once('exit', flushRereadLog);
245
+ // Like the other hooks: project store, else global; a folder with neither must not get one made.
246
+ const store = hookStoreRoot(hippoRoot);
247
+ if (!isInitialized(store)) {
248
+ appendSessionEndCloseLog(closeLogFile, 'skip: no hippo store for this folder or globally', { startFresh: true });
249
+ flushRereadLog();
250
+ return;
251
+ }
252
+ // Sleeping the global store from here would learn this folder's git commits into it; it has its own daily sleep.
253
+ if (isInitialized(hippoRoot)) {
254
+ try {
255
+ await (await import('./sleep.js')).cmdSleep(hippoRoot, flags);
256
+ }
257
+ catch {
258
+ // sleep errors are already tee'd to the log file via cmdSleep's
259
+ // `[hippo] sleep failed: ...` line. Continue to capture regardless.
260
+ }
261
+ }
262
+ else {
263
+ appendSessionEndCloseLog(closeLogFile, 'skip sleep: this folder has no store of its own', { startFresh: true });
264
+ logSessionEndImport(closeLogFile, transcriptPath);
265
+ }
266
+ flushRereadLog();
267
+ const digestLog = (message) => appendSessionEndCloseLog(closeLogFile, message);
268
+ const scan = transcriptPath ? readSessionScan(transcriptPath, digestLog) : null;
269
+ try {
270
+ const logFile = typeof flags['log-file'] === 'string' ? flags['log-file'] : undefined;
271
+ // With no stdin of its own, capture would read this as a manual run and scan every project.
272
+ if (!transcriptPath) {
273
+ appendSessionEndCloseLog(logFile ?? null, 'skip capture: no transcript for this session');
274
+ }
275
+ else {
276
+ cmdCapture(store, {
277
+ source: 'last-session',
278
+ transcriptPath,
279
+ logFile,
280
+ dryRun: false,
281
+ global: false,
282
+ tenantId: resolveTenantId({}),
283
+ // In the global store, rows would otherwise read as user-global and show up in every project.
284
+ originProject: store === hippoRoot ? undefined : deriveOriginProject(process.cwd()),
285
+ sessionTurns: scan?.turns,
286
+ });
287
+ }
288
+ }
289
+ catch {
290
+ // Same treatment — the failure line is already in the log.
291
+ }
292
+ recordSessionDigest(hippoRoot, scan, {
293
+ key: closeSessionId || path.basename(transcriptPath ?? '', '.jsonl'),
294
+ tenantId: resolveTenantId({}),
295
+ log: digestLog,
296
+ });
297
+ // DF1 T3: close the ending session's own active task snapshot AFTER
298
+ // sleep+capture complete — neither producer (runPreCompact,
299
+ // `hippo snapshot save`) runs inside session-end, so this can never
300
+ // destroy same-run work. Scoped to `--session-id`: a concurrent session's
301
+ // active snapshot is untouched (closeTaskSnapshotsForSession's own WHERE
302
+ // clause). Absent session id -> no-op plus one log line; session-end is
303
+ // not guaranteed to fire at all (crash, kill -9), so the freshness bound
304
+ // in loadFreshActiveTaskSnapshot is the backstop layer, not this close.
305
+ // Handoff write happens BEFORE the snapshot close below, while the
306
+ // snapshot writeSessionEndHandoff reads is still active.
307
+ if (closeSessionId) {
308
+ try {
309
+ const tenantId = resolveTenantId({});
310
+ const ownSnapshot = loadActiveTaskSnapshot(store, tenantId)?.session_id === closeSessionId;
311
+ // A never-compacted session has no snapshot; read even when it has one, as another session's PreCompact can take the slot before the write.
312
+ const derived = transcriptPath
313
+ ? transcriptWorkingState(transcriptPath, (message) => appendSessionEndCloseLog(closeLogFile, message))
314
+ : null;
315
+ if (!ownSnapshot && !derived) {
316
+ appendSessionEndCloseLog(closeLogFile, 'skip: no snapshot or transcript for session');
317
+ }
318
+ else {
319
+ const evidence = collectHandoffEvidence(process.cwd(), 'unknown');
320
+ const handoff = writeSessionEndHandoff(store, tenantId, closeSessionId, evidence, derived);
321
+ appendSessionEndCloseLog(closeLogFile, handoff ? `wrote handoff for session ${closeSessionId}` : `skip: kept the existing handoff for session ${closeSessionId}`);
322
+ }
323
+ }
324
+ catch (err) {
325
+ // SAFETY: catch clauses bind unknown, but Node/V8 always throws an Error here.
326
+ appendSessionEndCloseLog(closeLogFile, `handoff write failed: ${err.message}`);
327
+ }
328
+ }
329
+ try {
330
+ if (closeSessionId) {
331
+ const closed = closeTaskSnapshotsForSession(store, resolveTenantId({}), closeSessionId);
332
+ appendSessionEndCloseLog(closeLogFile, `closed ${closed} active snapshot(s) for session ${closeSessionId}`);
333
+ }
334
+ else {
335
+ appendSessionEndCloseLog(closeLogFile, 'skip: no session_id in SessionEnd payload, active snapshot left untouched');
336
+ }
337
+ }
338
+ catch (err) {
339
+ appendSessionEndCloseLog(closeLogFile, `snapshot close failed: ${err.message}`);
340
+ }
341
+ }
342
+ /** Books the ending session's re-reads in each store its ledger rows can land in (project and global); returns the log lines. */
343
+ async function bookSessionRereads(hippoRoot, transcriptPath, sessionId) {
344
+ if (!transcriptPath || !sessionId)
345
+ return [];
346
+ let read;
347
+ try {
348
+ read = await readApiCalls(transcriptPath);
349
+ }
350
+ catch (err) {
351
+ return [`skip re-read count: cannot read the transcript: ${err instanceof Error ? err.message : String(err)}`];
352
+ }
353
+ const roots = new Set([hippoRoot, getGlobalRoot()].filter((root) => isInitialized(root)).map((root) => path.resolve(root)));
354
+ const lines = [];
355
+ let tokens = 0;
356
+ for (const root of roots) {
357
+ try {
358
+ const db = openHippoDb(root);
359
+ try {
360
+ tokens += recordRereads(db, resolveTenantId({}), sessionId, read.calls);
361
+ }
362
+ finally {
363
+ closeHippoDb(db);
364
+ }
365
+ }
366
+ catch (err) {
367
+ lines.push(`re-read count failed: ${err instanceof Error ? err.message : String(err)}`);
368
+ }
369
+ }
370
+ const skipped = read.malformed > 0 ? `, ${read.malformed} unparsable transcript lines skipped` : '';
371
+ lines.push(`re-read ${tokens} tokens over ${read.calls.length} model calls for session ${sessionId}${skipped}`);
372
+ return lines;
373
+ }
374
+ function loadCodexWrapperMetadata() {
375
+ const { metadataPath } = resolveCodexWrapperPaths();
376
+ if (!fs.existsSync(metadataPath)) {
377
+ throw new Error('Codex wrapper is not installed. Run `hippo hook install codex` first.');
378
+ }
379
+ return JSON.parse(fs.readFileSync(metadataPath, 'utf8'));
380
+ }
381
+ /** Quotes one cmd.exe argument; each `%` leaves the quotes as `^%`, so no %NAME% pair can expand. */
382
+ export function quoteCmdArg(arg) {
383
+ if (arg.length === 0)
384
+ return '""';
385
+ if (!/[ \t"&()^<>|%!]/.test(arg))
386
+ return arg;
387
+ return `"${arg.replace(/"/g, '""').replace(/%/g, '"^%"')}"`;
388
+ }
389
+ /** cmd.exe arguments that run a .cmd or .bat shim with every forwarded argument delivered verbatim. */
390
+ export function cmdShimArgs(shimPath, forwardArgs) {
391
+ const command = `"${shimPath}"${forwardArgs.length > 0 ? ` ${forwardArgs.map(quoteCmdArg).join(' ')}` : ''}`;
392
+ // The line is already quoted for cmd.exe, so Node must not quote it again; /s strips the outer pair.
393
+ return ['/d', '/v:off', '/s', '/c', `"${command}"`];
394
+ }
395
+ function spawnRealCodex(realCodexPath, forwardArgs, cwd) {
396
+ const ext = path.extname(realCodexPath).toLowerCase();
397
+ if (process.platform === 'win32' && ext === '.ps1') {
398
+ return spawn('powershell.exe', ['-NoProfile', '-ExecutionPolicy', 'Bypass', '-File', realCodexPath, ...forwardArgs], { cwd, stdio: 'inherit', windowsHide: false });
399
+ }
400
+ if (process.platform === 'win32' && (ext === '.cmd' || ext === '.bat')) {
401
+ return spawn('cmd.exe', cmdShimArgs(realCodexPath, forwardArgs), { cwd, stdio: 'inherit', windowsHide: false, windowsVerbatimArguments: true });
402
+ }
403
+ return spawn(realCodexPath, forwardArgs, { cwd, stdio: 'inherit', windowsHide: false });
404
+ }
405
+ export function cmdCodexRun(hippoRoot, args) {
406
+ const metadata = loadCodexWrapperMetadata();
407
+ const startedAtMs = Date.now();
408
+ // Codex reads CODEX_HOME at each launch, so resolve it now, not from the install-time metadata.
409
+ const { historyPath } = resolveCodexWrapperPaths();
410
+ const startOffsetBytes = fs.existsSync(historyPath) ? fs.statSync(historyPath).size : 0;
411
+ try {
412
+ cmdLastSleep({ path: metadata.logFile });
413
+ }
414
+ catch {
415
+ // best-effort only
416
+ }
417
+ const child = spawnRealCodex(metadata.realCodexPath, args, process.cwd());
418
+ child.on('error', (err) => {
419
+ printError(`Failed to launch Codex: ${err.message}`);
420
+ process.exit(1);
421
+ });
422
+ child.on('exit', async (code, signal) => {
423
+ const workerArgs = [
424
+ process.argv[1],
425
+ '__codex-session-end-worker',
426
+ '--codex-home',
427
+ path.dirname(historyPath),
428
+ '--history-path',
429
+ historyPath,
430
+ '--start-offset',
431
+ String(startOffsetBytes),
432
+ '--started-at',
433
+ String(startedAtMs),
434
+ '--log-file',
435
+ metadata.logFile,
436
+ ];
437
+ try {
438
+ const worker = spawn(process.execPath, workerArgs, {
439
+ detached: true,
440
+ stdio: 'ignore',
441
+ windowsHide: true,
442
+ });
443
+ worker.unref();
444
+ }
445
+ catch {
446
+ // Fall back to the inline path if the detached worker cannot be created.
447
+ // Awaited so the sleep write can't be killed by the exit calls below.
448
+ try {
449
+ await cmdCodexSessionEndWorker(hippoRoot, {
450
+ 'codex-home': path.dirname(historyPath),
451
+ 'history-path': historyPath,
452
+ 'start-offset': String(startOffsetBytes),
453
+ 'started-at': String(startedAtMs),
454
+ 'log-file': metadata.logFile,
455
+ });
456
+ }
457
+ catch {
458
+ // cmdCodexSessionEndWorker already fail-softs internally; this is belt-and-braces.
459
+ }
460
+ }
461
+ if (signal) {
462
+ try {
463
+ process.kill(process.pid, signal);
464
+ }
465
+ catch {
466
+ // Cannot re-raise the child's signal on this platform; a non-zero exit still reports the failure.
467
+ process.exit(1);
468
+ }
469
+ return;
470
+ }
471
+ process.exit(code ?? 0);
472
+ });
473
+ }
474
+ export async function cmdCodexSessionEndWorker(hippoRoot, flags) {
475
+ const logFile = typeof flags['log-file'] === 'string' ? flags['log-file'] : undefined;
476
+ // Like the other hooks: project store, else global; a folder with neither must not get one made.
477
+ const store = hookStoreRoot(hippoRoot);
478
+ if (!isInitialized(store)) {
479
+ appendSessionEndCloseLog(logFile ?? null, 'skip: no hippo store for this folder or globally', { startFresh: true });
480
+ return;
481
+ }
482
+ // Sleeping the global store from here would learn this folder's git commits into it; it has its own daily sleep.
483
+ if (isInitialized(hippoRoot)) {
484
+ try {
485
+ await (await import('./sleep.js')).cmdSleep(hippoRoot, logFile ? { 'log-file': logFile } : {});
486
+ }
487
+ catch {
488
+ // sleep errors are already written via cmdSleep
489
+ }
490
+ }
491
+ else {
492
+ appendSessionEndCloseLog(logFile ?? null, 'skip sleep: this folder has no store of its own', { startFresh: true });
493
+ logSessionEndImport(logFile ?? null, undefined);
494
+ }
495
+ try {
496
+ const codexHome = typeof flags['codex-home'] === 'string'
497
+ ? flags['codex-home']
498
+ : resolveCodexWrapperPaths().codexHome;
499
+ const historyPath = typeof flags['history-path'] === 'string'
500
+ ? flags['history-path']
501
+ : path.join(codexHome, 'history.jsonl');
502
+ const startOffsetBytes = parseInt(String(flags['start-offset'] ?? '0'), 10) || 0;
503
+ const startedAtMs = parseInt(String(flags['started-at'] ?? Date.now()), 10) || Date.now();
504
+ const transcriptPath = resolveCodexSessionTranscript({
505
+ codexHome,
506
+ historyPath,
507
+ startOffsetBytes,
508
+ startedAtMs,
509
+ }) ?? undefined;
510
+ // No Codex transcript must not fall through to the scan of Claude Code projects.
511
+ if (!transcriptPath) {
512
+ appendSessionEndCloseLog(logFile ?? null, 'skip capture: no Codex transcript for this session');
513
+ return;
514
+ }
515
+ const digestLog = (message) => appendSessionEndCloseLog(logFile ?? null, message);
516
+ const scan = readSessionScan(transcriptPath, digestLog);
517
+ const captureOpts = {
518
+ source: 'last-session',
519
+ transcriptPath,
520
+ logFile,
521
+ dryRun: false,
522
+ global: false,
523
+ tenantId: resolveTenantId({}),
524
+ originProject: store === hippoRoot ? undefined : deriveOriginProject(process.cwd()),
525
+ sessionTurns: scan?.turns,
526
+ };
527
+ try {
528
+ cmdCapture(store, captureOpts);
529
+ }
530
+ catch {
531
+ // capture path logs its own failures
532
+ }
533
+ // The Codex wrapper passes no session id, so the rollout file names the session.
534
+ recordSessionDigest(hippoRoot, scan, { key: path.basename(transcriptPath, '.jsonl'), tenantId: resolveTenantId({}), log: digestLog });
535
+ }
536
+ catch {
537
+ // capture path logs its own failures
538
+ }
539
+ }
540
+ export async function handlePreCompact({ hippoRoot, flags }) {
541
+ // Bounded wait, not a TTY guard: an idle non-TTY pipe must not hang.
542
+ const { text: stdinText, timedOut: stdinTimedOut } = await readStdinBounded();
543
+ await runHookWithStores(async () => {
544
+ resetHookInjection(hippoRoot, stdinText, null);
545
+ await cmdPreCompact(hookStoreRoot(hippoRoot), {
546
+ stdinText,
547
+ stdinTimedOut,
548
+ logFile: typeof flags['log-file'] === 'string' ? flags['log-file'] : undefined,
549
+ });
550
+ });
551
+ }
552
+ export async function handlePostCompact({ hippoRoot, flags }) {
553
+ // PostCompact hook: saves the compaction summary and its memories, then prints one plain line, because Claude Code shows this hook's stdout as-is. Always exits 0.
554
+ const { text } = await readStdinBounded();
555
+ const logFlag = flags['log-file'];
556
+ const store = hookStoreRoot(hippoRoot);
557
+ const line = await runHookWithStores(() => cmdPostCompact(store, {
558
+ stdinText: text,
559
+ logFile: logFlag === true || logFlag === false || Array.isArray(logFlag) ? undefined : logFlag,
560
+ // Passed in, since capture.ts importing the sync would close an import cycle.
561
+ afterSave: (transcriptPath, originProject, log) => {
562
+ const report = importAtCompaction(store, transcriptPath, originProject, { machine: currentMachine(), busyWaitMs: COMPACTION_DB_WAIT_MS });
563
+ const summary = summaryLine(report);
564
+ if (summary !== null)
565
+ log(summary);
566
+ for (const warning of report.warnings)
567
+ log(`agent memories: ${warning}`);
568
+ },
569
+ }));
570
+ if (line !== null && line !== undefined)
571
+ console.log(line);
572
+ }
573
+ export async function handleCaptureError({ hippoRoot }) {
574
+ // PostToolUseFailure hook: every path exits 0, and nothing is created
575
+ // when no store exists (the hook fires in every directory).
576
+ const { text } = await readStdinBounded();
577
+ try {
578
+ const root = hookStoreRoot(hippoRoot);
579
+ const payload = (text ?? '').trim();
580
+ if (isInitialized(root) && payload) {
581
+ // SAFETY: JSON.parse returns a JSON value by definition.
582
+ const failure = JSON.parse(payload);
583
+ await runHookWithStores(() => captureToolFailure(root, resolveTenantId({}), failure));
584
+ }
585
+ }
586
+ catch {
587
+ // A malformed payload or store error must never fail the agent's tool call.
588
+ }
589
+ }
590
+ export async function handleCompactResume({ hippoRoot }) {
591
+ const { text: stdinText, timedOut: stdinTimedOut } = await readStdinBounded();
592
+ await runHookWithStores(() => {
593
+ resetHookInjection(hippoRoot, stdinText, 'compact');
594
+ cmdCompactResume(hookStoreRoot(hippoRoot), stdinText, stdinTimedOut);
595
+ });
596
+ }
597
+ export async function handleCapture({ hippoRoot, flags }) {
598
+ let captureSource = null;
599
+ let captureFile;
600
+ let transcriptPath;
601
+ if (flags['stdin']) {
602
+ captureSource = 'stdin';
603
+ }
604
+ else if (flags['file']) {
605
+ captureSource = 'file';
606
+ captureFile = String(flags['file']);
607
+ }
608
+ else if (flags['last-session']) {
609
+ captureSource = 'last-session';
610
+ }
611
+ if (flags['transcript']) {
612
+ transcriptPath = String(flags['transcript']);
613
+ if (!captureSource)
614
+ captureSource = 'last-session';
615
+ }
616
+ if (!captureSource) {
617
+ printError('Usage: hippo capture --stdin|--file <path>|--last-session [--transcript <path>] [--log-file <path>] [--dry-run] [--global]');
618
+ process.exit(1);
619
+ }
620
+ // Bounded, and only when last-session has no explicit path: the
621
+ // --stdin source keeps its own blocking read in capture.ts by design.
622
+ const bounded = captureSource === 'last-session' && !transcriptPath
623
+ ? await readStdinBounded()
624
+ : { text: undefined, timedOut: false };
625
+ cmdCapture(hippoRoot, {
626
+ source: captureSource,
627
+ filePath: captureFile,
628
+ transcriptPath,
629
+ stdinText: bounded.text,
630
+ stdinTimedOut: bounded.timedOut,
631
+ logFile: typeof flags['log-file'] === 'string' ? flags['log-file'] : undefined,
632
+ dryRun: Boolean(flags['dry-run']),
633
+ global: Boolean(flags['global']),
634
+ tenantId: resolveTenantId({}),
635
+ });
636
+ }
637
+ //# sourceMappingURL=session-hooks.js.map
@@ -0,0 +1,4 @@
1
+ export declare function cmdHook(args: string[], flags: Record<string, string | boolean | string[]>): void;
2
+ export declare function cmdSetup(flags: Record<string, string | boolean | string[]>): void;
3
+ export declare function cmdDailyRunner(): void;
4
+ //# sourceMappingURL=setup.d.ts.map