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,356 @@
1
+ /**
2
+ * Hook install/uninstall for AI coding tools.
3
+ *
4
+ * Two integration models live in this file:
5
+ *
6
+ * 1. JSON-hook install (Claude Code only). Writes a `hooks` block into the
7
+ * tool's settings.json with two entries:
8
+ * - SessionEnd: `hippo session-end --log-file <path>` - spawns a detached
9
+ * child that runs `hippo sleep` then `hippo capture --last-session` in
10
+ * sequence, writing both outputs to the log file. The parent returns in
11
+ * <100ms so the TUI teardown can't kill the child before it finishes.
12
+ * - SessionStart: `hippo last-sleep --path <path>` - prints the log
13
+ * written by the previous session's detached worker to stderr, which
14
+ * keeps it out of the model's context, and then clears it.
15
+ * Earlier Claude Code forms are detected and migrated automatically:
16
+ * - < 0.20.2: `Stop` hook firing `hippo sleep` on every assistant turn.
17
+ * - < 0.21.0: bare `hippo sleep` in SessionEnd, no `--log-file`.
18
+ * - 0.22.x: separate sleep + capture SessionEnd entries.
19
+ * PreCompact and PostCompact entries go in too: the first records the compaction and
20
+ * asks the summariser for a "Memories for hippo" list, the second saves that list.
21
+ * Codex's hooks.json gets only two groups (per-prompt memory and
22
+ * compact-resume); see installCodexHooks.
23
+ *
24
+ * 2. Plugin install (OpenCode only). OpenCode does NOT share Claude Code's
25
+ * JSON-hook schema — its config has `additionalProperties: false` and no
26
+ * `hooks` key, so v1.10.x-v1.11.1's JSON-hook installer broke opencode
27
+ * launch (issue #24). Hippo now installs a TypeScript plugin at
28
+ * `~/.config/opencode/plugins/hippo.ts` subscribing to opencode's
29
+ * `session.idle` (→ `hippo session-end`) and `session.created` (→
30
+ * `hippo last-sleep`) events. See OPENCODE_PLUGIN_SOURCE below for the
31
+ * plugin file content + design rationale; see installOpencodePlugin for
32
+ * the installer + the migration that removes any pre-existing broken
33
+ * `hooks` block from opencode.json.
34
+ */
35
+ import * as fs from 'fs';
36
+ import * as path from 'path';
37
+ import { isJsonString, isJsonObject, HIPPO_SLEEP_MARKER, HIPPO_LAST_SLEEP_MARKER, HIPPO_CAPTURE_MARKER, HIPPO_SESSION_END_MARKER, HIPPO_PINNED_INJECT_MARKER, HIPPO_PINNED_INJECT_COMMAND, HIPPO_PRE_COMPACT_MARKER, HIPPO_COMPACT_RESUME_MARKER, HIPPO_CAPTURE_ERROR_MARKER, HIPPO_POST_COMPACT_MARKER, homeDir, codexHomeDir, defaultPreCompactLogPath } from './shared.js';
38
+ export function resolveJsonHookPaths(target) {
39
+ const home = homeDir();
40
+ const logsDir = path.join(home, '.hippo', 'logs');
41
+ switch (target) {
42
+ case 'claude-code':
43
+ return {
44
+ settings: path.join(home, '.claude', 'settings.json'),
45
+ logFile: path.join(logsDir, 'claude-code-sleep.log'),
46
+ display: 'Claude Code',
47
+ };
48
+ case 'codex':
49
+ return {
50
+ settings: path.join(codexHomeDir(home), 'hooks.json'),
51
+ logFile: path.join(logsDir, 'codex-sleep.log'),
52
+ display: 'Codex',
53
+ };
54
+ }
55
+ }
56
+ function hookArrayContains(hookArray, marker) {
57
+ if (!Array.isArray(hookArray))
58
+ return false;
59
+ return JSON.stringify(hookArray).includes(marker);
60
+ }
61
+ function addIncludeRecentToPinnedCommand(command) {
62
+ if (!command.includes(HIPPO_PINNED_INJECT_MARKER) || command.includes('--include-recent'))
63
+ return command;
64
+ return command.includes(' --format ')
65
+ ? command.replace(' --format ', ' --include-recent 5 --format ')
66
+ : `${command} --include-recent 5`;
67
+ }
68
+ function migratePinnedInjectRecentCommands(hookArray) {
69
+ if (!Array.isArray(hookArray))
70
+ return false;
71
+ let changed = false;
72
+ for (const entry of hookArray) {
73
+ if (!isJsonObject(entry))
74
+ continue;
75
+ const innerHooks = entry.hooks;
76
+ if (!Array.isArray(innerHooks))
77
+ continue;
78
+ for (const hook of innerHooks) {
79
+ if (!isJsonObject(hook))
80
+ continue;
81
+ if (!isJsonString(hook.command))
82
+ continue;
83
+ const next = addIncludeRecentToPinnedCommand(hook.command);
84
+ if (next !== hook.command) {
85
+ hook.command = next;
86
+ changed = true;
87
+ }
88
+ }
89
+ }
90
+ return changed;
91
+ }
92
+ /**
93
+ * Returns true when `hooks.SessionEnd` still contains either of the legacy
94
+ * v0.22.x split entries (bare `hippo sleep` / `hippo capture --last-session`)
95
+ * without the current consolidated `hippo session-end` entry.
96
+ */
97
+ function hasLegacySplitSessionEnd(hookArray) {
98
+ if (!Array.isArray(hookArray))
99
+ return false;
100
+ const serialized = JSON.stringify(hookArray);
101
+ const hasSleep = serialized.includes(HIPPO_SLEEP_MARKER);
102
+ const hasCapture = serialized.includes(HIPPO_CAPTURE_MARKER);
103
+ return (hasSleep || hasCapture) && !serialized.includes(HIPPO_SESSION_END_MARKER);
104
+ }
105
+ function nothingInstalled(target, settingsPath) {
106
+ return {
107
+ target,
108
+ settingsPath,
109
+ installedSessionEnd: false,
110
+ installedSessionStart: false,
111
+ installedUserPromptSubmit: false,
112
+ installedPreCompact: false,
113
+ installedCompactResume: false,
114
+ installedPostCompact: false,
115
+ installedCaptureError: false,
116
+ migratedPinnedInjectRecent: false,
117
+ migratedFromStop: false,
118
+ migratedLegacySessionEnd: false,
119
+ migratedSplitSessionEnd: false,
120
+ invalidJson: false,
121
+ };
122
+ }
123
+ /** A command hook with a Windows form: Codex runs hooks in PowerShell there, whose execution policy can block npm's hippo.ps1. */
124
+ function codexCommandHook(command, timeout) {
125
+ return { type: 'command', command, commandWindows: command.replace(/^hippo /, 'hippo.cmd '), timeout };
126
+ }
127
+ /** Codex keys trust to each hook's position and hash and re-asks for a changed one, so hippo only appends and never edits an entry. */
128
+ function installCodexHooks(settingsPath, settings) {
129
+ const result = nothingInstalled('codex', settingsPath);
130
+ if (!isJsonObject(settings))
131
+ return { ...result, invalidJson: true };
132
+ if (settings.hooks === undefined)
133
+ settings.hooks = {};
134
+ const hooks = settings.hooks;
135
+ const events = ['UserPromptSubmit', 'SessionStart'];
136
+ if (!isJsonObject(hooks) || events.some((e) => hooks[e] !== undefined && !Array.isArray(hooks[e]))) {
137
+ return { ...result, invalidJson: true };
138
+ }
139
+ const append = (event, marker, group) => {
140
+ const groups = hooks[event];
141
+ if (hookArrayContains(groups, marker))
142
+ return false;
143
+ hooks[event] = [...(Array.isArray(groups) ? groups : []), group];
144
+ return true;
145
+ };
146
+ const installedUserPromptSubmit = append('UserPromptSubmit', HIPPO_PINNED_INJECT_MARKER, {
147
+ hooks: [codexCommandHook(HIPPO_PINNED_INJECT_COMMAND, 5)],
148
+ });
149
+ const installedCompactResume = append('SessionStart', HIPPO_COMPACT_RESUME_MARKER, {
150
+ matcher: 'compact',
151
+ hooks: [codexCommandHook(HIPPO_COMPACT_RESUME_MARKER, 10)],
152
+ });
153
+ if (installedUserPromptSubmit || installedCompactResume) {
154
+ fs.writeFileSync(settingsPath, JSON.stringify(settings, null, 2) + '\n', 'utf8');
155
+ }
156
+ return { ...result, installedUserPromptSubmit, installedCompactResume };
157
+ }
158
+ export function installJsonHooks(target) {
159
+ const { settings: settingsPath, logFile } = resolveJsonHookPaths(target);
160
+ const dir = path.dirname(settingsPath);
161
+ if (!fs.existsSync(dir))
162
+ fs.mkdirSync(dir, { recursive: true });
163
+ let settings = {};
164
+ if (fs.existsSync(settingsPath)) {
165
+ try {
166
+ settings = JSON.parse(fs.readFileSync(settingsPath, 'utf8'));
167
+ }
168
+ catch {
169
+ return { ...nothingInstalled(target, settingsPath), invalidJson: true };
170
+ }
171
+ }
172
+ if (target === 'codex')
173
+ return installCodexHooks(settingsPath, settings);
174
+ return installClaudeCodeHooks(settingsPath, settings, logFile);
175
+ }
176
+ function migrateLegacyClaudeHooks(hooks) {
177
+ let migratedFromStop = false;
178
+ if (Array.isArray(hooks.Stop) && hookArrayContains(hooks.Stop, HIPPO_SLEEP_MARKER)) {
179
+ hooks.Stop = hooks.Stop.filter((entry) => !JSON.stringify(entry).includes(HIPPO_SLEEP_MARKER));
180
+ if (hooks.Stop.length === 0)
181
+ delete hooks.Stop;
182
+ migratedFromStop = true;
183
+ }
184
+ // Migrate legacy SessionEnd forms:
185
+ // - pre-0.21 bare `hippo sleep`
186
+ // - 0.21.x+ `hippo sleep --log-file` split across two entries
187
+ // - 0.22.x `hippo capture --last-session --log-file` second entry
188
+ // All of these get collapsed into the single `hippo session-end` entry.
189
+ let migratedLegacySessionEnd = false;
190
+ let migratedSplitSessionEnd = false;
191
+ if (Array.isArray(hooks.SessionEnd) && hasLegacySplitSessionEnd(hooks.SessionEnd)) {
192
+ const before = hooks.SessionEnd.length;
193
+ hooks.SessionEnd = hooks.SessionEnd.filter((entry) => {
194
+ const s = JSON.stringify(entry);
195
+ return !s.includes(HIPPO_SLEEP_MARKER) && !s.includes(HIPPO_CAPTURE_MARKER);
196
+ });
197
+ if (hooks.SessionEnd.length === 0)
198
+ delete hooks.SessionEnd;
199
+ // If the removed entries used the log-file pattern (0.21.x-0.22.x) we
200
+ // call it a "split" migration; otherwise it was the older bare form.
201
+ migratedSplitSessionEnd = true;
202
+ migratedLegacySessionEnd = before > 1;
203
+ }
204
+ return { migratedFromStop, migratedLegacySessionEnd, migratedSplitSessionEnd };
205
+ }
206
+ function claudeCommandGroup(command, timeout, matcher) {
207
+ const hooks = [{ type: 'command', command, timeout }];
208
+ return matcher === undefined ? { hooks } : { matcher, hooks };
209
+ }
210
+ function appendHookIfMissing(hooks, event, marker, group) {
211
+ if (hookArrayContains(hooks[event], marker))
212
+ return false;
213
+ if (!Array.isArray(hooks[event]))
214
+ hooks[event] = [];
215
+ hooks[event].push(group);
216
+ return true;
217
+ }
218
+ function installClaudeCodeHooks(settingsPath, settings, logFile) {
219
+ if (!settings.hooks)
220
+ settings.hooks = {};
221
+ // SAFETY: settings.hooks is either freshly initialised to {} on the line above, or an
222
+ // existing value from settings.json — Claude Code's own schema always writes an object
223
+ // there; each event key below is still re-validated with Array.isArray before use.
224
+ const hooks = settings.hooks;
225
+ const migration = migrateLegacyClaudeHooks(hooks);
226
+ const installedSessionEnd = appendHookIfMissing(hooks, 'SessionEnd', HIPPO_SESSION_END_MARKER, claudeCommandGroup(`hippo session-end --log-file "${logFile}"`, 5));
227
+ const installedSessionStart = appendHookIfMissing(hooks, 'SessionStart', HIPPO_LAST_SLEEP_MARKER, claudeCommandGroup(`hippo last-sleep --path "${logFile}"`, 5));
228
+ // Mid-session pinned-rule re-injection: UserPromptSubmit runs every turn,
229
+ // so pinned memories stay in context even after the model would otherwise
230
+ // "forget" them in a long session. Include the fresh write tail so lessons
231
+ // saved earlier in the same session become visible on the next prompt even
232
+ // before the user pins them explicitly.
233
+ const migratedPinnedInjectRecent = migratePinnedInjectRecentCommands(hooks.UserPromptSubmit);
234
+ const installedUserPromptSubmit = appendHookIfMissing(hooks, 'UserPromptSubmit', HIPPO_PINNED_INJECT_MARKER, claudeCommandGroup(HIPPO_PINNED_INJECT_COMMAND, 5));
235
+ // PreCompact: fires on manual AND auto compaction (no matcher). Records the compaction, asks the
236
+ // summariser for a "Memories for hippo" list and saves a working-state snapshot before the summary drops detail.
237
+ // Exit-0 contract lives in the verb itself (src/capture.ts cmdPreCompact),
238
+ // not here — this is install-time wiring only.
239
+ const installedPreCompact = appendHookIfMissing(hooks, 'PreCompact', HIPPO_PRE_COMPACT_MARKER, claudeCommandGroup(`hippo pre-compact --log-file "${defaultPreCompactLogPath()}"`, 30));
240
+ // SessionStart(compact): a SECOND SessionStart entry alongside the
241
+ // un-matched last-sleep entry above. The matcher is an optimization, not
242
+ // a dependency — compact-resume itself checks payload.source too, so an
243
+ // older Claude Code that ignores the matcher just runs a silent no-op on
244
+ // normal starts. Marker check keys on the command string, so this stays
245
+ // idempotent alongside the sibling last-sleep entry.
246
+ const installedCompactResume = appendHookIfMissing(hooks, 'SessionStart', HIPPO_COMPACT_RESUME_MARKER, claudeCommandGroup('hippo compact-resume', 10, 'compact'));
247
+ // PostCompact: saves the memories the summariser listed and prints one line, which Claude Code only shows.
248
+ // PreCompact stdout, by contrast, is handed to the summariser as instructions, so pre-compact prints just the request.
249
+ const installedPostCompact = appendHookIfMissing(hooks, 'PostCompact', HIPPO_POST_COMPACT_MARKER, claudeCommandGroup(`hippo post-compact --log-file "${defaultPreCompactLogPath()}"`, 10));
250
+ // PostToolUseFailure: a failed tool call becomes an error memory, after
251
+ // `hippo capture-error` drops routine failures (interrupts, declined
252
+ // permissions, empty searches) and repeats. Same hook the plugin ships.
253
+ const installedCaptureError = appendHookIfMissing(hooks, 'PostToolUseFailure', HIPPO_CAPTURE_ERROR_MARKER, claudeCommandGroup('hippo capture-error', 10, '.*'));
254
+ const result = {
255
+ target: 'claude-code',
256
+ settingsPath,
257
+ installedSessionEnd,
258
+ installedSessionStart,
259
+ installedUserPromptSubmit,
260
+ installedPreCompact,
261
+ installedCompactResume,
262
+ installedPostCompact,
263
+ installedCaptureError,
264
+ migratedPinnedInjectRecent,
265
+ ...migration,
266
+ invalidJson: false,
267
+ };
268
+ if (Object.values(result).some((v) => v === true)) {
269
+ fs.writeFileSync(settingsPath, JSON.stringify(settings, null, 2) + '\n', 'utf8');
270
+ }
271
+ return result;
272
+ }
273
+ /** The exact command hippo writes for each Codex event; uninstall removes only these handlers. */
274
+ const CODEX_HOOK_COMMANDS = [
275
+ ['UserPromptSubmit', HIPPO_PINNED_INJECT_COMMAND],
276
+ ['SessionStart', HIPPO_COMPACT_RESUME_MARKER],
277
+ ];
278
+ /** A group loses only hippo's handlers and goes only once empty, so a user's hook beside or like hippo's stays. */
279
+ function uninstallCodexHooks(hooks) {
280
+ let changed = false;
281
+ for (const [event, command] of CODEX_HOOK_COMMANDS) {
282
+ const groups = hooks[event];
283
+ if (!Array.isArray(groups))
284
+ continue;
285
+ let removed = false;
286
+ const kept = groups.flatMap((group) => {
287
+ if (!isJsonObject(group) || !Array.isArray(group.hooks))
288
+ return [group];
289
+ const handlers = group.hooks.filter((h) => !(isJsonObject(h) && h.command === command));
290
+ if (handlers.length === group.hooks.length)
291
+ return [group];
292
+ removed = true;
293
+ return handlers.length > 0 ? [{ ...group, hooks: handlers }] : [];
294
+ });
295
+ if (!removed)
296
+ continue;
297
+ changed = true;
298
+ if (kept.length > 0)
299
+ hooks[event] = kept;
300
+ else
301
+ delete hooks[event];
302
+ }
303
+ return changed;
304
+ }
305
+ export function uninstallJsonHooks(target) {
306
+ const { settings: settingsPath } = resolveJsonHookPaths(target);
307
+ if (!fs.existsSync(settingsPath))
308
+ return false;
309
+ let settings;
310
+ try {
311
+ settings = JSON.parse(fs.readFileSync(settingsPath, 'utf8'));
312
+ }
313
+ catch {
314
+ // Never rewrite a settings file we cannot parse; report nothing uninstalled.
315
+ return false;
316
+ }
317
+ if (!isJsonObject(settings) || !isJsonObject(settings.hooks))
318
+ return false;
319
+ const changed = target === 'codex' ? uninstallCodexHooks(settings.hooks) : uninstallClaudeCodeHooks(settings.hooks);
320
+ if (!changed)
321
+ return false;
322
+ if (Object.keys(settings.hooks).length === 0)
323
+ delete settings.hooks;
324
+ fs.writeFileSync(settingsPath, JSON.stringify(settings, null, 2) + '\n', 'utf8');
325
+ return true;
326
+ }
327
+ function uninstallClaudeCodeHooks(settingsHooks) {
328
+ // SAFETY: each event key below is re-validated with Array.isArray before use.
329
+ const hooks = settingsHooks;
330
+ let changed = false;
331
+ const markersByKey = {
332
+ SessionEnd: [HIPPO_SESSION_END_MARKER, HIPPO_SLEEP_MARKER, HIPPO_CAPTURE_MARKER],
333
+ // Both the un-matched last-sleep entry and the matcher:'compact'
334
+ // compact-resume entry live under the SessionStart key; the matcher
335
+ // field doesn't affect this substring match, so removal covers both.
336
+ SessionStart: [HIPPO_LAST_SLEEP_MARKER, HIPPO_COMPACT_RESUME_MARKER],
337
+ UserPromptSubmit: [HIPPO_PINNED_INJECT_MARKER],
338
+ PreCompact: [HIPPO_PRE_COMPACT_MARKER],
339
+ PostCompact: [HIPPO_POST_COMPACT_MARKER],
340
+ PostToolUseFailure: [HIPPO_CAPTURE_ERROR_MARKER],
341
+ Stop: [HIPPO_SLEEP_MARKER],
342
+ };
343
+ for (const [key, markers] of Object.entries(markersByKey)) {
344
+ if (!Array.isArray(hooks[key]))
345
+ continue;
346
+ const before = hooks[key].length;
347
+ hooks[key] = hooks[key].filter((entry) => !markers.some((m) => JSON.stringify(entry).includes(m)));
348
+ if (hooks[key].length !== before) {
349
+ changed = true;
350
+ if (hooks[key].length === 0)
351
+ delete hooks[key];
352
+ }
353
+ }
354
+ return changed;
355
+ }
356
+ //# sourceMappingURL=json-hooks.js.map
@@ -0,0 +1,50 @@
1
+ declare const HIPPO_OPENCODE_PLUGIN_MARKER = "HIPPO_OPENCODE_PLUGIN_V1";
2
+ /**
3
+ * The opencode plugin file we install at ~/.config/opencode/plugins/hippo.ts.
4
+ *
5
+ * Per https://opencode.ai/docs/plugins/, plugins are TS/JS modules exporting an
6
+ * async function returning hooks. We subscribe to `event` and route:
7
+ * session.idle → `hippo session-end` (Claude Code's SessionEnd equiv)
8
+ * session.created → `hippo last-sleep` (Claude Code's SessionStart equiv)
9
+ *
10
+ * Design choices forced by plan-eng-critic Rev 0 review (2026-05-23):
11
+ *
12
+ * 1. No `import type { Plugin } from "@opencode-ai/plugin"`. The package's npm
13
+ * publication status was unverifiable from the build sandbox (npmjs.com
14
+ * returned 403); an unresolved type-only import would still crash the TS
15
+ * runtime opencode uses to load the plugin. opencode infers plugin shape
16
+ * from the returned object, so the type was convenience-only.
17
+ *
18
+ * 2. Defensive `typeof $ !== 'function'` guard. opencode runs in Bun (where
19
+ * `$` is the shell-template helper), but a future Node-mode deployment
20
+ * would have `$` undefined in the destructured context and the plugin
21
+ * would throw on every session.idle, killing opencode sessions in a
22
+ * hard-to-recover way (the idempotence marker prevents auto-reinstall).
23
+ * Fail closed, let opencode continue.
24
+ *
25
+ * 3. `.quiet().nothrow()` on each `$\`...\`` so a missing hippo binary
26
+ * (e.g. PATH-misconfigured user) does NOT throw out of the event handler.
27
+ * The surrounding try/catch is belt-and-braces.
28
+ *
29
+ * 4. UserPromptSubmit equivalent NOT wired. opencode's `message.updated`
30
+ * fires per-token, not per-prompt-submit; no clean per-prompt event.
31
+ * Users wanting pinned-context auto-injection can call `hippo context`
32
+ * via the MCP server (`hippo mcp`).
33
+ *
34
+ * 5. Versioned marker `HIPPO_OPENCODE_PLUGIN_V1` allows future versions to
35
+ * overwrite cleanly. The installer's idempotence check requires BOTH
36
+ * marker match AND content equality, so a plugin-source revision under
37
+ * the same V1 marker re-writes the file on next install.
38
+ */
39
+ export declare const OPENCODE_PLUGIN_SOURCE = "// HIPPO_OPENCODE_PLUGIN_V1\n// hippo-memory opencode plugin. DO NOT EDIT \u2014 regenerated on every\n// `hippo hook install opencode` from src/hooks.ts OPENCODE_PLUGIN_SOURCE\n// in https://github.com/kitfunso/hippo-memory. Local changes will be lost.\n\nexport const HippoPlugin = async ({ $ }) => {\n return {\n event: async ({ event }) => {\n // Defense in depth: opencode currently runs in Bun where $ is the shell\n // template helper. A non-Bun runtime would have $ as undefined; fail\n // closed instead of crashing the host session.\n if (typeof $ !== \"function\") return;\n try {\n if (event.type === \"session.idle\") {\n await $`hippo session-end`.quiet().nothrow();\n } else if (event.type === \"session.created\") {\n await $`hippo last-sleep`.quiet().nothrow();\n }\n } catch {\n // hippo CLI not on PATH or other failure \u2014 never crash the host session.\n }\n },\n };\n};\n";
40
+ export { HIPPO_OPENCODE_PLUGIN_MARKER };
41
+ export interface OpencodePluginInstallResult {
42
+ installed: boolean;
43
+ pluginPath: string;
44
+ migratedLegacyHooks: boolean;
45
+ jsonRepairFailed: boolean;
46
+ }
47
+ export declare function resolveOpencodePluginPath(): string;
48
+ export declare function installOpencodePlugin(): OpencodePluginInstallResult;
49
+ export declare function uninstallOpencodePlugin(): boolean;
50
+ //# sourceMappingURL=opencode.d.ts.map
@@ -0,0 +1,202 @@
1
+ import * as fs from 'fs';
2
+ import * as path from 'path';
3
+ import { isJsonString, isJsonObject, homeDir } from './shared.js';
4
+ const HIPPO_OPENCODE_PLUGIN_MARKER = 'HIPPO_OPENCODE_PLUGIN_V1';
5
+ /**
6
+ * The opencode plugin file we install at ~/.config/opencode/plugins/hippo.ts.
7
+ *
8
+ * Per https://opencode.ai/docs/plugins/, plugins are TS/JS modules exporting an
9
+ * async function returning hooks. We subscribe to `event` and route:
10
+ * session.idle → `hippo session-end` (Claude Code's SessionEnd equiv)
11
+ * session.created → `hippo last-sleep` (Claude Code's SessionStart equiv)
12
+ *
13
+ * Design choices forced by plan-eng-critic Rev 0 review (2026-05-23):
14
+ *
15
+ * 1. No `import type { Plugin } from "@opencode-ai/plugin"`. The package's npm
16
+ * publication status was unverifiable from the build sandbox (npmjs.com
17
+ * returned 403); an unresolved type-only import would still crash the TS
18
+ * runtime opencode uses to load the plugin. opencode infers plugin shape
19
+ * from the returned object, so the type was convenience-only.
20
+ *
21
+ * 2. Defensive `typeof $ !== 'function'` guard. opencode runs in Bun (where
22
+ * `$` is the shell-template helper), but a future Node-mode deployment
23
+ * would have `$` undefined in the destructured context and the plugin
24
+ * would throw on every session.idle, killing opencode sessions in a
25
+ * hard-to-recover way (the idempotence marker prevents auto-reinstall).
26
+ * Fail closed, let opencode continue.
27
+ *
28
+ * 3. `.quiet().nothrow()` on each `$\`...\`` so a missing hippo binary
29
+ * (e.g. PATH-misconfigured user) does NOT throw out of the event handler.
30
+ * The surrounding try/catch is belt-and-braces.
31
+ *
32
+ * 4. UserPromptSubmit equivalent NOT wired. opencode's `message.updated`
33
+ * fires per-token, not per-prompt-submit; no clean per-prompt event.
34
+ * Users wanting pinned-context auto-injection can call `hippo context`
35
+ * via the MCP server (`hippo mcp`).
36
+ *
37
+ * 5. Versioned marker `HIPPO_OPENCODE_PLUGIN_V1` allows future versions to
38
+ * overwrite cleanly. The installer's idempotence check requires BOTH
39
+ * marker match AND content equality, so a plugin-source revision under
40
+ * the same V1 marker re-writes the file on next install.
41
+ */
42
+ export const OPENCODE_PLUGIN_SOURCE = `// ${HIPPO_OPENCODE_PLUGIN_MARKER}
43
+ // hippo-memory opencode plugin. DO NOT EDIT — regenerated on every
44
+ // \`hippo hook install opencode\` from src/hooks.ts OPENCODE_PLUGIN_SOURCE
45
+ // in https://github.com/kitfunso/hippo-memory. Local changes will be lost.
46
+
47
+ export const HippoPlugin = async ({ $ }) => {
48
+ return {
49
+ event: async ({ event }) => {
50
+ // Defense in depth: opencode currently runs in Bun where $ is the shell
51
+ // template helper. A non-Bun runtime would have $ as undefined; fail
52
+ // closed instead of crashing the host session.
53
+ if (typeof $ !== "function") return;
54
+ try {
55
+ if (event.type === "session.idle") {
56
+ await $\`hippo session-end\`.quiet().nothrow();
57
+ } else if (event.type === "session.created") {
58
+ await $\`hippo last-sleep\`.quiet().nothrow();
59
+ }
60
+ } catch {
61
+ // hippo CLI not on PATH or other failure — never crash the host session.
62
+ }
63
+ },
64
+ };
65
+ };
66
+ `;
67
+ export { HIPPO_OPENCODE_PLUGIN_MARKER };
68
+ export function resolveOpencodePluginPath() {
69
+ return path.join(homeDir(), '.config', 'opencode', 'plugins', 'hippo.ts');
70
+ }
71
+ function resolveOpencodeConfigPath() {
72
+ return path.join(homeDir(), '.config', 'opencode', 'opencode.json');
73
+ }
74
+ /**
75
+ * Return true iff a single hook-array entry's command string starts with
76
+ * `hippo ` (the verb-prefix). Used to surgically remove only hippo-owned
77
+ * commands when migrating an opencode.json. We own the install side, so only
78
+ * the canonical `hippo <verb>` form needs to match — and only canonical verbs
79
+ * hippo itself installs (session-end, last-sleep, sleep, capture, context),
80
+ * not any third-party tool that happens to be named `hippo`.
81
+ *
82
+ * Critic-mandated structural check (Rev 0): substring matching against
83
+ * arbitrary user content is unsafe — a user's
84
+ * `echo "remember to hippo sleep your laptop"` is not a hippo-owned hook.
85
+ *
86
+ * Per-hook (not per-entry) granularity (Rev 1 review): an entry whose inner
87
+ * hooks array mixes hippo-installed commands with user-authored commands
88
+ * must NOT lose the user-authored commands. The migration filters the inner
89
+ * array per-hook, then drops the entry only when its inner array is empty.
90
+ */
91
+ const HIPPO_OWNED_COMMAND_RE = /^\s*hippo\s+(session-end|last-sleep|sleep|capture|context)\b/;
92
+ function hookIsHippoOwned(hook) {
93
+ if (!isJsonObject(hook))
94
+ return false;
95
+ const cmd = hook.command;
96
+ return isJsonString(cmd) && HIPPO_OWNED_COMMAND_RE.test(cmd);
97
+ }
98
+ /**
99
+ * Structurally strip every hippo-owned hook from opencode.json's hooks key.
100
+ * Returns one of:
101
+ * { migrated: true, jsonRepairFailed: false } — at least one hook removed.
102
+ * { migrated: false, jsonRepairFailed: false } — file fine, nothing to do.
103
+ * { migrated: false, jsonRepairFailed: true } — file present but unparseable.
104
+ *
105
+ * Per-hook surgery:
106
+ * - For each entry in each event-key array, filter the inner `hooks` array
107
+ * to remove hippo-owned hooks only. User-authored hooks in the same
108
+ * inner array are preserved.
109
+ * - When an entry's inner `hooks` array becomes empty, that entry is
110
+ * removed from the outer array.
111
+ * - When an event-key array becomes empty, the key is deleted.
112
+ * - When the top-level `hooks` object becomes empty, it is deleted.
113
+ * - Other keys (theme, etc.) are always preserved.
114
+ */
115
+ function migrateLegacyOpencodeHooksBlock() {
116
+ const configPath = resolveOpencodeConfigPath();
117
+ if (!fs.existsSync(configPath))
118
+ return { migrated: false, jsonRepairFailed: false };
119
+ let settings;
120
+ try {
121
+ settings = JSON.parse(fs.readFileSync(configPath, 'utf8'));
122
+ }
123
+ catch {
124
+ return { migrated: false, jsonRepairFailed: true };
125
+ }
126
+ const hooks = settings.hooks;
127
+ // Non-object hooks values (string, array, null) are user content we don't
128
+ // recognise — leave them alone, return migrated=false.
129
+ if (!isJsonObject(hooks)) {
130
+ return { migrated: false, jsonRepairFailed: false };
131
+ }
132
+ const hooksObj = hooks;
133
+ let changed = false;
134
+ for (const key of Object.keys(hooksObj)) {
135
+ if (!Array.isArray(hooksObj[key]))
136
+ continue;
137
+ const survivingEntries = [];
138
+ for (const entry of hooksObj[key]) {
139
+ if (!isJsonObject(entry)) {
140
+ survivingEntries.push(entry);
141
+ continue;
142
+ }
143
+ const innerHooks = entry.hooks;
144
+ if (!Array.isArray(innerHooks)) {
145
+ survivingEntries.push(entry);
146
+ continue;
147
+ }
148
+ const beforeInner = innerHooks.length;
149
+ const survivingInner = innerHooks.filter((h) => !hookIsHippoOwned(h));
150
+ if (survivingInner.length !== beforeInner)
151
+ changed = true;
152
+ if (survivingInner.length === 0)
153
+ continue; // drop entry, nothing left
154
+ entry.hooks = survivingInner;
155
+ survivingEntries.push(entry);
156
+ }
157
+ if (survivingEntries.length !== hooksObj[key].length)
158
+ changed = true;
159
+ hooksObj[key] = survivingEntries;
160
+ if (hooksObj[key].length === 0)
161
+ delete hooksObj[key];
162
+ }
163
+ if (!changed)
164
+ return { migrated: false, jsonRepairFailed: false };
165
+ if (Object.keys(hooksObj).length === 0)
166
+ delete settings.hooks;
167
+ fs.writeFileSync(configPath, JSON.stringify(settings, null, 2) + '\n', 'utf8');
168
+ return { migrated: true, jsonRepairFailed: false };
169
+ }
170
+ export function installOpencodePlugin() {
171
+ const pluginPath = resolveOpencodePluginPath();
172
+ const { migrated, jsonRepairFailed } = migrateLegacyOpencodeHooksBlock();
173
+ // Idempotence: skip the write only if BOTH the marker is present AND the
174
+ // content matches the current source. Marker-only matches (with stale
175
+ // content) overwrite cleanly so future plugin-source patches reach
176
+ // existing installs.
177
+ if (fs.existsSync(pluginPath)) {
178
+ const existing = fs.readFileSync(pluginPath, 'utf8');
179
+ if (existing.includes(HIPPO_OPENCODE_PLUGIN_MARKER) && existing === OPENCODE_PLUGIN_SOURCE) {
180
+ return { installed: false, pluginPath, migratedLegacyHooks: migrated, jsonRepairFailed };
181
+ }
182
+ }
183
+ fs.mkdirSync(path.dirname(pluginPath), { recursive: true });
184
+ fs.writeFileSync(pluginPath, OPENCODE_PLUGIN_SOURCE, 'utf8');
185
+ return { installed: true, pluginPath, migratedLegacyHooks: migrated, jsonRepairFailed };
186
+ }
187
+ export function uninstallOpencodePlugin() {
188
+ const pluginPath = resolveOpencodePluginPath();
189
+ let removedFile = false;
190
+ if (fs.existsSync(pluginPath)) {
191
+ const existing = fs.readFileSync(pluginPath, 'utf8');
192
+ if (existing.includes(HIPPO_OPENCODE_PLUGIN_MARKER)) {
193
+ fs.unlinkSync(pluginPath);
194
+ removedFile = true;
195
+ }
196
+ }
197
+ // Always run the legacy migration on uninstall — the downgrade path (user
198
+ // removing hippo entirely) must leave opencode launchable.
199
+ const { migrated } = migrateLegacyOpencodeHooksBlock();
200
+ return removedFile || migrated;
201
+ }
202
+ //# sourceMappingURL=opencode.js.map
@@ -0,0 +1,54 @@
1
+ import type { JsonValue, JsonObject } from '../working-memory.js';
2
+ /** JSON-value string check. `constructor` narrows a primitive via its boxed wrapper
3
+ * instead of inspecting the `typeof` tag (anti-slop/no-runtime-typeof); equivalent to
4
+ * `typeof value === 'string'` for every value JSON.parse can ever produce. */
5
+ export declare function isJsonString(value: JsonValue | undefined): value is string;
6
+ /** JSON-value plain-object check (excludes arrays and null), typeof-free for the same
7
+ * reason as isJsonString above. */
8
+ export declare function isJsonObject(value: JsonValue | undefined): value is JsonObject;
9
+ export type JsonHookTarget = 'claude-code' | 'codex';
10
+ export interface ToolDetection {
11
+ name: string;
12
+ configDir: string;
13
+ detected: boolean;
14
+ kind: 'json-hook' | 'markdown-instruction' | 'plugin' | 'wrapper';
15
+ notes?: string;
16
+ }
17
+ export declare const HIPPO_SLEEP_MARKER = "hippo sleep";
18
+ export declare const HIPPO_LAST_SLEEP_MARKER = "hippo last-sleep";
19
+ export declare const HIPPO_CAPTURE_MARKER = "hippo capture --last-session";
20
+ export declare const HIPPO_SESSION_END_MARKER = "hippo session-end";
21
+ export declare const HIPPO_PINNED_INJECT_MARKER = "hippo context --pinned-only";
22
+ export declare const HIPPO_PINNED_INJECT_COMMAND = "hippo context --pinned-only --include-recent 5 --format additional-context";
23
+ export declare const HIPPO_CODEX_WRAPPER_MARKER = "hippo codex wrapper";
24
+ export declare const HIPPO_PRE_COMPACT_MARKER = "hippo pre-compact";
25
+ export declare const HIPPO_COMPACT_RESUME_MARKER = "hippo compact-resume";
26
+ export declare const HIPPO_CAPTURE_ERROR_MARKER = "hippo capture-error";
27
+ export declare const HIPPO_POST_COMPACT_MARKER = "hippo post-compact";
28
+ export declare function homeDir(): string;
29
+ /** Codex's config folder: $CODEX_HOME, else ~/.codex, as the Codex hooks docs describe. */
30
+ export declare function codexHomeDir(home?: string, env?: Readonly<Record<string, string | undefined>>): string;
31
+ /** Codex counts as installed only when its config folder exists: Codex itself refuses a CODEX_HOME that is not a folder. */
32
+ export declare function isCodexPresent(home?: string): boolean;
33
+ /** Codex hashes each hook and skips new or changed ones until the user reviews them in `/hooks`, so the reminder says what they would trust. */
34
+ export declare const CODEX_TRUST_LINE = "The per-prompt hook sends your pinned memories plus up to 5 that match the prompt. Codex runs hippo's hooks only after you trust them once in `/hooks`.";
35
+ /**
36
+ * Default log path consumed by `hippo last-sleep`. Shared fallback when
37
+ * a caller doesn't pass --path explicitly.
38
+ */
39
+ export declare function defaultSleepLogPath(): string;
40
+ /**
41
+ * Diagnostic-only log path for `hippo pre-compact`. Deliberately separate
42
+ * from the SessionEnd sleep log: `hippo last-sleep` truncates that file on
43
+ * every SessionStart, which would wipe pre-compact lines before anyone
44
+ * could read them. Nothing consumes this file programmatically — it exists
45
+ * for manual troubleshooting only. Overridden by `--log-file`.
46
+ */
47
+ export declare function defaultPreCompactLogPath(): string;
48
+ export declare function ensureDir(dir: string): void;
49
+ /**
50
+ * Detect which AI coding tools are installed based on config directory presence.
51
+ * Used by `hippo setup` to decide which JSON-hook installs to run.
52
+ */
53
+ export declare function detectInstalledTools(): ToolDetection[];
54
+ //# sourceMappingURL=shared.d.ts.map