hippo-memory 1.59.0 → 1.61.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (596) hide show
  1. package/README.md +1 -1
  2. package/dist/ablation.js +9 -27
  3. package/dist/agent-memories/apply.js +4 -1
  4. package/dist/agent-memories/claude-code.js +1 -1
  5. package/dist/agent-memories/codex.js +1 -1
  6. package/dist/agent-memories/gemini.js +1 -1
  7. package/dist/agent-memories/legacy.js +1 -1
  8. package/dist/agent-memories/source.js +1 -1
  9. package/dist/agent-memories/sync.js +8 -3
  10. package/dist/ambient-store.d.ts +14 -0
  11. package/dist/ambient-store.js +90 -0
  12. package/dist/ambient.d.ts +23 -0
  13. package/dist/ambient.js +72 -50
  14. package/dist/api/assemble.d.ts +93 -0
  15. package/dist/api/assemble.js +152 -0
  16. package/dist/api/audit.d.ts +17 -0
  17. package/dist/api/audit.js +23 -0
  18. package/dist/api/auth.d.ts +79 -0
  19. package/dist/api/auth.js +178 -0
  20. package/dist/api/context-types.d.ts +105 -0
  21. package/dist/api/context-types.js +3 -0
  22. package/dist/api/context.d.ts +31 -0
  23. package/dist/api/context.js +705 -0
  24. package/dist/api/dormant.d.ts +30 -0
  25. package/dist/api/dormant.js +140 -0
  26. package/dist/api/drill-down.d.ts +84 -0
  27. package/dist/api/drill-down.js +123 -0
  28. package/dist/api/forget.d.ts +57 -0
  29. package/dist/api/forget.js +87 -0
  30. package/dist/api/goals.d.ts +18 -0
  31. package/dist/api/goals.js +33 -0
  32. package/dist/api/learn.d.ts +31 -0
  33. package/dist/api/learn.js +88 -0
  34. package/dist/api/outcome.d.ts +61 -0
  35. package/dist/api/outcome.js +66 -0
  36. package/dist/api/promote.d.ts +54 -0
  37. package/dist/api/promote.js +203 -0
  38. package/dist/api/quarantine.d.ts +24 -0
  39. package/dist/api/quarantine.js +121 -0
  40. package/dist/api/recall-types.d.ts +390 -0
  41. package/dist/api/recall-types.js +3 -0
  42. package/dist/api/recall.d.ts +36 -0
  43. package/dist/api/recall.js +634 -0
  44. package/dist/api/remember.d.ts +35 -0
  45. package/dist/api/remember.js +43 -0
  46. package/dist/api/sleep.d.ts +136 -0
  47. package/dist/api/sleep.js +271 -0
  48. package/dist/api/tokens.d.ts +26 -0
  49. package/dist/api/tokens.js +60 -0
  50. package/dist/api/types.d.ts +56 -0
  51. package/dist/api/types.js +38 -0
  52. package/dist/api.d.ts +20 -1260
  53. package/dist/api.js +25 -2711
  54. package/dist/audit.d.ts +3 -0
  55. package/dist/audit.js +7 -3
  56. package/dist/auth.d.ts +45 -4
  57. package/dist/auth.js +125 -48
  58. package/dist/autolearn.js +7 -4
  59. package/dist/capture/command.d.ts +33 -0
  60. package/dist/capture/command.js +264 -0
  61. package/dist/capture/compact.d.ts +44 -0
  62. package/dist/capture/compact.js +354 -0
  63. package/dist/capture/extract.d.ts +21 -0
  64. package/dist/capture/extract.js +464 -0
  65. package/dist/capture/transcript.d.ts +40 -0
  66. package/dist/capture/transcript.js +193 -0
  67. package/dist/capture-error.js +2 -1
  68. package/dist/churn-git.js +4 -2
  69. package/dist/cli/audit.d.ts +3 -0
  70. package/dist/cli/audit.js +159 -0
  71. package/dist/cli/auth.d.ts +2 -0
  72. package/dist/cli/auth.js +171 -0
  73. package/dist/cli/briefs.d.ts +4 -0
  74. package/dist/cli/briefs.js +435 -0
  75. package/dist/cli/card.d.ts +3 -0
  76. package/dist/cli/card.js +333 -0
  77. package/dist/cli/context.d.ts +15 -0
  78. package/dist/cli/context.js +366 -0
  79. package/dist/cli/continuity.d.ts +6 -0
  80. package/dist/cli/continuity.js +445 -0
  81. package/dist/cli/curate.d.ts +19 -0
  82. package/dist/cli/curate.js +555 -0
  83. package/dist/cli/dag.d.ts +5 -0
  84. package/dist/cli/dag.js +177 -0
  85. package/dist/cli/decisions.d.ts +4 -0
  86. package/dist/cli/decisions.js +528 -0
  87. package/dist/cli/eval.d.ts +5 -0
  88. package/dist/cli/eval.js +213 -0
  89. package/dist/cli/explain.d.ts +4 -0
  90. package/dist/cli/explain.js +150 -0
  91. package/dist/cli/goals.d.ts +2 -0
  92. package/dist/cli/goals.js +196 -0
  93. package/dist/cli/hook-blocks.d.ts +18 -0
  94. package/dist/cli/hook-blocks.js +233 -0
  95. package/dist/cli/init.d.ts +2 -0
  96. package/dist/cli/init.js +305 -0
  97. package/dist/cli/maintenance.d.ts +4 -0
  98. package/dist/cli/maintenance.js +179 -0
  99. package/dist/cli/playbooks.d.ts +4 -0
  100. package/dist/cli/playbooks.js +556 -0
  101. package/dist/cli/projects.js +1 -1
  102. package/dist/cli/recall.d.ts +7 -0
  103. package/dist/cli/recall.js +597 -0
  104. package/dist/cli/remember.d.ts +5 -0
  105. package/dist/cli/remember.js +442 -0
  106. package/dist/cli/serve.d.ts +5 -0
  107. package/dist/cli/serve.js +40 -0
  108. package/dist/cli/session-hooks.d.ts +29 -0
  109. package/dist/cli/session-hooks.js +637 -0
  110. package/dist/cli/setup.d.ts +4 -0
  111. package/dist/cli/setup.js +376 -0
  112. package/dist/cli/shared.d.ts +15 -19
  113. package/dist/cli/shared.js +50 -341
  114. package/dist/cli/slack.d.ts +2 -0
  115. package/dist/cli/slack.js +171 -0
  116. package/dist/cli/status.d.ts +18 -0
  117. package/dist/cli/status.js +400 -0
  118. package/dist/cli/transfer.d.ts +10 -0
  119. package/dist/cli/transfer.js +438 -0
  120. package/dist/cli/usage.d.ts +85 -0
  121. package/dist/cli/usage.js +741 -0
  122. package/dist/cli.d.ts +319 -13
  123. package/dist/cli.js +436 -8580
  124. package/dist/client.js +15 -8
  125. package/dist/compaction-record.js +12 -9
  126. package/dist/config.js +12 -11
  127. package/dist/connectors/github/backfill.js +94 -87
  128. package/dist/connectors/github/cli-impl.js +5 -3
  129. package/dist/connectors/github/dlq.js +67 -54
  130. package/dist/connectors/github/ingest.js +34 -35
  131. package/dist/connectors/github/tenant-routing.js +3 -2
  132. package/dist/connectors/github/webhook.js +135 -216
  133. package/dist/connectors/slack/dlq.js +49 -61
  134. package/dist/connectors/slack/ingest.js +55 -48
  135. package/dist/connectors/slack/tenant-routing.js +4 -3
  136. package/dist/connectors/slack/webhook.js +72 -74
  137. package/dist/consolidate/conflicts.d.ts +10 -0
  138. package/dist/consolidate/conflicts.js +178 -0
  139. package/dist/consolidate/decay.d.ts +12 -0
  140. package/dist/consolidate/decay.js +145 -0
  141. package/dist/consolidate/llm-passes.d.ts +3 -0
  142. package/dist/consolidate/llm-passes.js +141 -0
  143. package/dist/consolidate/merge.d.ts +7 -0
  144. package/dist/consolidate/merge.js +251 -0
  145. package/dist/consolidate/physics-pass.d.ts +3 -0
  146. package/dist/consolidate/physics-pass.js +60 -0
  147. package/dist/consolidate/run.d.ts +69 -0
  148. package/dist/consolidate/run.js +76 -0
  149. package/dist/consolidate/sleep.d.ts +18 -0
  150. package/dist/consolidate/sleep.js +209 -0
  151. package/dist/consolidate/traces.d.ts +4 -0
  152. package/dist/consolidate/traces.js +178 -0
  153. package/dist/context-auto.js +7 -11
  154. package/dist/context-render.d.ts +1 -1
  155. package/dist/context-render.js +1 -1
  156. package/dist/customer-notes.d.ts +3 -0
  157. package/dist/customer-notes.js +6 -4
  158. package/dist/dag.js +13 -12
  159. package/dist/dashboard-actions.d.ts +20 -0
  160. package/dist/dashboard-actions.js +88 -0
  161. package/dist/dashboard-params.d.ts +45 -0
  162. package/dist/dashboard-params.js +127 -0
  163. package/dist/dashboard-queries.d.ts +15 -0
  164. package/dist/dashboard-queries.js +355 -0
  165. package/dist/dashboard-snapshot.d.ts +138 -0
  166. package/dist/dashboard-snapshot.js +308 -0
  167. package/dist/dashboard-types.d.ts +163 -0
  168. package/dist/dashboard-types.js +3 -0
  169. package/dist/dashboard.d.ts +6 -7
  170. package/dist/dashboard.js +231 -203
  171. package/dist/db/busy.d.ts +5 -0
  172. package/dist/db/busy.js +24 -0
  173. package/dist/db/continuity.d.ts +5 -0
  174. package/dist/db/continuity.js +145 -0
  175. package/dist/db/meta.d.ts +8 -0
  176. package/dist/db/meta.js +35 -0
  177. package/dist/db/migrate.d.ts +9 -0
  178. package/dist/db/migrate.js +138 -0
  179. package/dist/db/migrations/index.d.ts +5 -0
  180. package/dist/db/migrations/index.js +109 -0
  181. package/dist/db/migrations/types.d.ts +14 -0
  182. package/dist/db/migrations/types.js +2 -0
  183. package/dist/db/migrations/v01.d.ts +3 -0
  184. package/dist/db/migrations/v01.js +38 -0
  185. package/dist/db/migrations/v02.d.ts +3 -0
  186. package/dist/db/migrations/v02.js +21 -0
  187. package/dist/db/migrations/v03.d.ts +3 -0
  188. package/dist/db/migrations/v03.js +22 -0
  189. package/dist/db/migrations/v04.d.ts +3 -0
  190. package/dist/db/migrations/v04.js +28 -0
  191. package/dist/db/migrations/v05.d.ts +3 -0
  192. package/dist/db/migrations/v05.js +21 -0
  193. package/dist/db/migrations/v06.d.ts +3 -0
  194. package/dist/db/migrations/v06.js +25 -0
  195. package/dist/db/migrations/v07.d.ts +3 -0
  196. package/dist/db/migrations/v07.js +13 -0
  197. package/dist/db/migrations/v08.d.ts +3 -0
  198. package/dist/db/migrations/v08.js +8 -0
  199. package/dist/db/migrations/v09.d.ts +3 -0
  200. package/dist/db/migrations/v09.js +13 -0
  201. package/dist/db/migrations/v10.d.ts +3 -0
  202. package/dist/db/migrations/v10.js +17 -0
  203. package/dist/db/migrations/v11.d.ts +3 -0
  204. package/dist/db/migrations/v11.js +15 -0
  205. package/dist/db/migrations/v12.d.ts +3 -0
  206. package/dist/db/migrations/v12.js +11 -0
  207. package/dist/db/migrations/v13.d.ts +3 -0
  208. package/dist/db/migrations/v13.js +15 -0
  209. package/dist/db/migrations/v14.d.ts +3 -0
  210. package/dist/db/migrations/v14.js +66 -0
  211. package/dist/db/migrations/v15.d.ts +3 -0
  212. package/dist/db/migrations/v15.js +42 -0
  213. package/dist/db/migrations/v16.d.ts +3 -0
  214. package/dist/db/migrations/v16.js +61 -0
  215. package/dist/db/migrations/v17.d.ts +3 -0
  216. package/dist/db/migrations/v17.js +46 -0
  217. package/dist/db/migrations/v18.d.ts +3 -0
  218. package/dist/db/migrations/v18.js +60 -0
  219. package/dist/db/migrations/v19.d.ts +3 -0
  220. package/dist/db/migrations/v19.js +28 -0
  221. package/dist/db/migrations/v20.d.ts +3 -0
  222. package/dist/db/migrations/v20.js +42 -0
  223. package/dist/db/migrations/v21.d.ts +3 -0
  224. package/dist/db/migrations/v21.js +16 -0
  225. package/dist/db/migrations/v22.d.ts +3 -0
  226. package/dist/db/migrations/v22.js +82 -0
  227. package/dist/db/migrations/v23.d.ts +3 -0
  228. package/dist/db/migrations/v23.js +48 -0
  229. package/dist/db/migrations/v24.d.ts +3 -0
  230. package/dist/db/migrations/v24.js +72 -0
  231. package/dist/db/migrations/v25.d.ts +3 -0
  232. package/dist/db/migrations/v25.js +46 -0
  233. package/dist/db/migrations/v26.d.ts +3 -0
  234. package/dist/db/migrations/v26.js +23 -0
  235. package/dist/db/migrations/v27.d.ts +3 -0
  236. package/dist/db/migrations/v27.js +57 -0
  237. package/dist/db/migrations/v28.d.ts +3 -0
  238. package/dist/db/migrations/v28.js +38 -0
  239. package/dist/db/migrations/v29.d.ts +3 -0
  240. package/dist/db/migrations/v29.js +78 -0
  241. package/dist/db/migrations/v30.d.ts +3 -0
  242. package/dist/db/migrations/v30.js +92 -0
  243. package/dist/db/migrations/v31.d.ts +3 -0
  244. package/dist/db/migrations/v31.js +74 -0
  245. package/dist/db/migrations/v32.d.ts +3 -0
  246. package/dist/db/migrations/v32.js +102 -0
  247. package/dist/db/migrations/v33.d.ts +3 -0
  248. package/dist/db/migrations/v33.js +104 -0
  249. package/dist/db/migrations/v34.d.ts +3 -0
  250. package/dist/db/migrations/v34.js +93 -0
  251. package/dist/db/migrations/v35.d.ts +3 -0
  252. package/dist/db/migrations/v35.js +98 -0
  253. package/dist/db/migrations/v36.d.ts +3 -0
  254. package/dist/db/migrations/v36.js +98 -0
  255. package/dist/db/migrations/v37.d.ts +3 -0
  256. package/dist/db/migrations/v37.js +219 -0
  257. package/dist/db/migrations/v38.d.ts +3 -0
  258. package/dist/db/migrations/v38.js +277 -0
  259. package/dist/db/migrations/v39.d.ts +3 -0
  260. package/dist/db/migrations/v39.js +59 -0
  261. package/dist/db/migrations/v40.d.ts +3 -0
  262. package/dist/db/migrations/v40.js +74 -0
  263. package/dist/db/migrations/v41.d.ts +3 -0
  264. package/dist/db/migrations/v41.js +43 -0
  265. package/dist/db/migrations/v42.d.ts +3 -0
  266. package/dist/db/migrations/v42.js +41 -0
  267. package/dist/db/migrations/v43.d.ts +3 -0
  268. package/dist/db/migrations/v43.js +67 -0
  269. package/dist/db/migrations/v44.d.ts +3 -0
  270. package/dist/db/migrations/v44.js +28 -0
  271. package/dist/db/migrations/v45.d.ts +3 -0
  272. package/dist/db/migrations/v45.js +30 -0
  273. package/dist/db/migrations/v46.d.ts +3 -0
  274. package/dist/db/migrations/v46.js +25 -0
  275. package/dist/db/migrations/v47.d.ts +3 -0
  276. package/dist/db/migrations/v47.js +17 -0
  277. package/dist/db/migrations/v48.d.ts +3 -0
  278. package/dist/db/migrations/v48.js +10 -0
  279. package/dist/db/migrations/v49.d.ts +3 -0
  280. package/dist/db/migrations/v49.js +31 -0
  281. package/dist/db/migrations/v50.d.ts +3 -0
  282. package/dist/db/migrations/v50.js +67 -0
  283. package/dist/db/migrations/v51.d.ts +3 -0
  284. package/dist/db/migrations/v51.js +14 -0
  285. package/dist/db/migrations/v52.d.ts +3 -0
  286. package/dist/db/migrations/v52.js +7 -0
  287. package/dist/db/open.d.ts +23 -0
  288. package/dist/db/open.js +146 -0
  289. package/dist/db/sqlite.d.ts +21 -0
  290. package/dist/db/sqlite.js +8 -0
  291. package/dist/db/tables.d.ts +7 -0
  292. package/dist/db/tables.js +38 -0
  293. package/dist/db.d.ts +6 -46
  294. package/dist/db.js +5 -3036
  295. package/dist/decisions.d.ts +4 -1
  296. package/dist/decisions.js +9 -7
  297. package/dist/dedupe.js +3 -2
  298. package/dist/delivery-recorder.js +5 -1
  299. package/dist/doctor.js +4 -3
  300. package/dist/dormant.js +1 -0
  301. package/dist/embedding-provider.d.ts +1 -1
  302. package/dist/embedding-provider.js +7 -5
  303. package/dist/embeddings.d.ts +9 -52
  304. package/dist/embeddings.js +47 -298
  305. package/dist/env.d.ts +75 -0
  306. package/dist/env.js +119 -0
  307. package/dist/eval-suite.js +1 -1
  308. package/dist/eval.js +2 -2
  309. package/dist/extract.js +5 -4
  310. package/dist/gated-write.js +3 -1
  311. package/dist/goals.d.ts +3 -1
  312. package/dist/goals.js +18 -0
  313. package/dist/graph/read.d.ts +73 -0
  314. package/dist/graph/read.js +325 -0
  315. package/dist/graph/rows.d.ts +45 -0
  316. package/dist/graph/rows.js +51 -0
  317. package/dist/graph/types.d.ts +83 -0
  318. package/dist/graph/types.js +11 -0
  319. package/dist/graph/write.d.ts +93 -0
  320. package/dist/{graph.js → graph/write.js} +8 -391
  321. package/dist/graph-extract.js +2 -1
  322. package/dist/graph-recall.d.ts +1 -1
  323. package/dist/graph-recall.js +2 -2
  324. package/dist/graph-stream.js +1 -1
  325. package/dist/graph-view.d.ts +1 -1
  326. package/dist/graph-view.js +1 -1
  327. package/dist/half-life-migration.d.ts +1 -1
  328. package/dist/half-life-migration.js +2 -1
  329. package/dist/handoff.js +3 -0
  330. package/dist/hooks/codex-session.d.ts +8 -0
  331. package/dist/hooks/codex-session.js +76 -0
  332. package/dist/hooks/codex-wrapper.d.ts +55 -0
  333. package/dist/hooks/codex-wrapper.js +288 -0
  334. package/dist/hooks/json-hooks.d.ts +63 -0
  335. package/dist/hooks/json-hooks.js +356 -0
  336. package/dist/hooks/opencode.d.ts +50 -0
  337. package/dist/hooks/opencode.js +202 -0
  338. package/dist/hooks/shared.d.ts +54 -0
  339. package/dist/hooks/shared.js +77 -0
  340. package/dist/http-retry.d.ts +2 -0
  341. package/dist/http-retry.js +4 -3
  342. package/dist/http-util.d.ts +3 -0
  343. package/dist/http-util.js +10 -0
  344. package/dist/{importers.d.ts → importers/core.d.ts} +13 -17
  345. package/dist/importers/core.js +141 -0
  346. package/dist/importers/markdown-parse.d.ts +41 -0
  347. package/dist/importers/markdown-parse.js +132 -0
  348. package/dist/importers/markdown.d.ts +3 -0
  349. package/dist/importers/markdown.js +92 -0
  350. package/dist/importers/sources.d.ts +7 -0
  351. package/dist/importers/sources.js +229 -0
  352. package/dist/importers/vault.d.ts +11 -0
  353. package/dist/importers/vault.js +352 -0
  354. package/dist/incidents.d.ts +3 -0
  355. package/dist/incidents.js +8 -5
  356. package/dist/index.d.ts +25 -6
  357. package/dist/index.js +23 -6
  358. package/dist/invalidation.js +2 -1
  359. package/dist/judgment.js +7 -3
  360. package/dist/keyset.d.ts +13 -0
  361. package/dist/keyset.js +8 -0
  362. package/dist/local-embedding.d.ts +13 -0
  363. package/dist/local-embedding.js +165 -0
  364. package/dist/log.d.ts +7 -0
  365. package/dist/log.js +19 -1
  366. package/dist/mcp/admin-tools.d.ts +8 -0
  367. package/dist/mcp/admin-tools.js +116 -0
  368. package/dist/mcp/format.d.ts +27 -0
  369. package/dist/mcp/format.js +135 -0
  370. package/dist/mcp/memory-tools.d.ts +5 -0
  371. package/dist/mcp/memory-tools.js +83 -0
  372. package/dist/mcp/protocol.d.ts +83 -0
  373. package/dist/mcp/protocol.js +55 -0
  374. package/dist/mcp/recall-tools.d.ts +6 -0
  375. package/dist/mcp/recall-tools.js +320 -0
  376. package/dist/mcp/request.d.ts +10 -0
  377. package/dist/mcp/request.js +163 -0
  378. package/dist/mcp/server.d.ts +4 -70
  379. package/dist/mcp/server.js +8 -1172
  380. package/dist/mcp/session-state.d.ts +11 -0
  381. package/dist/mcp/session-state.js +28 -0
  382. package/dist/mcp/stdio.d.ts +8 -0
  383. package/dist/mcp/stdio.js +79 -0
  384. package/dist/mcp/tools.d.ts +11 -0
  385. package/dist/mcp/tools.js +247 -0
  386. package/dist/memory.d.ts +8 -3
  387. package/dist/memory.js +27 -1
  388. package/dist/multihop.d.ts +1 -1
  389. package/dist/multihop.js +2 -1
  390. package/dist/owner-validation.js +2 -1
  391. package/dist/physics-state.js +10 -7
  392. package/dist/policies.d.ts +3 -0
  393. package/dist/policies.js +8 -6
  394. package/dist/postinstall.js +3 -2
  395. package/dist/predictions/planning-fallacy.d.ts +100 -0
  396. package/dist/predictions/planning-fallacy.js +190 -0
  397. package/dist/{predictions.d.ts → predictions/store.d.ts} +7 -102
  398. package/dist/predictions/store.js +434 -0
  399. package/dist/processes.d.ts +3 -0
  400. package/dist/processes.js +8 -5
  401. package/dist/project-briefs.d.ts +3 -0
  402. package/dist/project-briefs.js +7 -5
  403. package/dist/project-identity.d.ts +1 -1
  404. package/dist/project-identity.js +12 -6
  405. package/dist/project-merge.js +3 -1
  406. package/dist/quarantine.d.ts +2 -1
  407. package/dist/quarantine.js +8 -5
  408. package/dist/raw-archive-mirror-cleanup.js +2 -1
  409. package/dist/raw-archive.js +1 -1
  410. package/dist/recall-history.js +3 -2
  411. package/dist/recall-pipeline.d.ts +2 -2
  412. package/dist/recall-pipeline.js +16 -8
  413. package/dist/recall-scope.js +1 -1
  414. package/dist/recall-trace.d.ts +3 -3
  415. package/dist/recall-trace.js +10 -14
  416. package/dist/refine-llm.js +20 -11
  417. package/dist/reject-flow.js +6 -1
  418. package/dist/rerankers/clef.d.ts +2 -2
  419. package/dist/rerankers/clef.js +72 -30
  420. package/dist/rerankers/cross-encoder.js +6 -4
  421. package/dist/rerankers/jev.d.ts +4 -2
  422. package/dist/rerankers/jev.js +24 -19
  423. package/dist/rerankers/llm.d.ts +4 -2
  424. package/dist/rerankers/llm.js +61 -41
  425. package/dist/rerankers/types.d.ts +1 -1
  426. package/dist/salience.js +1 -1
  427. package/dist/same-text.d.ts +2 -0
  428. package/dist/same-text.js +4 -0
  429. package/dist/scheduler.d.ts +1 -0
  430. package/dist/scheduler.js +26 -3
  431. package/dist/scope.js +4 -3
  432. package/dist/search/as-of.d.ts +10 -0
  433. package/dist/search/as-of.js +22 -0
  434. package/dist/search/bm25-search.d.ts +14 -0
  435. package/dist/search/bm25-search.js +43 -0
  436. package/dist/search/bm25.d.ts +15 -0
  437. package/dist/search/bm25.js +54 -0
  438. package/dist/search/boosts.d.ts +54 -0
  439. package/dist/search/boosts.js +94 -0
  440. package/dist/search/breakdown.d.ts +7 -0
  441. package/dist/search/breakdown.js +20 -0
  442. package/dist/search/explain.d.ts +25 -0
  443. package/dist/search/explain.js +31 -0
  444. package/dist/search/finalize.d.ts +8 -0
  445. package/dist/search/finalize.js +52 -0
  446. package/dist/search/fusion.d.ts +27 -0
  447. package/dist/search/fusion.js +42 -0
  448. package/dist/search/hybrid-score.d.ts +20 -0
  449. package/dist/search/hybrid-score.js +73 -0
  450. package/dist/search/hybrid.d.ts +46 -0
  451. package/dist/search/hybrid.js +64 -0
  452. package/dist/search/physics-search.d.ts +29 -0
  453. package/dist/search/physics-search.js +162 -0
  454. package/dist/search/rerank.d.ts +10 -0
  455. package/dist/search/rerank.js +72 -0
  456. package/dist/search/temporal.d.ts +15 -0
  457. package/dist/search/temporal.js +45 -0
  458. package/dist/search/types.d.ts +91 -0
  459. package/dist/search/types.js +2 -0
  460. package/dist/search/vector.d.ts +30 -0
  461. package/dist/search/vector.js +71 -0
  462. package/dist/secret-detect.d.ts +2 -0
  463. package/dist/secret-detect.js +3 -1
  464. package/dist/server/auth.d.ts +52 -0
  465. package/dist/server/auth.js +221 -0
  466. package/dist/server/client-ip.d.ts +25 -0
  467. package/dist/server/client-ip.js +92 -0
  468. package/dist/server/cursor.d.ts +23 -0
  469. package/dist/server/cursor.js +58 -0
  470. package/dist/server/lifecycle.d.ts +7 -0
  471. package/dist/server/lifecycle.js +29 -0
  472. package/dist/server/mcp-http.d.ts +5 -0
  473. package/dist/server/mcp-http.js +199 -0
  474. package/dist/server/request.d.ts +33 -0
  475. package/dist/server/request.js +103 -0
  476. package/dist/server/routes/admin.d.ts +9 -0
  477. package/dist/server/routes/admin.js +158 -0
  478. package/dist/server/routes/customer-notes.d.ts +7 -0
  479. package/dist/server/routes/customer-notes.js +112 -0
  480. package/dist/server/routes/decisions.d.ts +7 -0
  481. package/dist/server/routes/decisions.js +133 -0
  482. package/dist/server/routes/incidents.d.ts +7 -0
  483. package/dist/server/routes/incidents.js +126 -0
  484. package/dist/server/routes/memories.d.ts +10 -0
  485. package/dist/server/routes/memories.js +179 -0
  486. package/dist/server/routes/policies.d.ts +8 -0
  487. package/dist/server/routes/policies.js +151 -0
  488. package/dist/server/routes/predictions.d.ts +7 -0
  489. package/dist/server/routes/predictions.js +164 -0
  490. package/dist/server/routes/processes.d.ts +7 -0
  491. package/dist/server/routes/processes.js +161 -0
  492. package/dist/server/routes/project-briefs.d.ts +8 -0
  493. package/dist/server/routes/project-briefs.js +136 -0
  494. package/dist/server/routes/recall.d.ts +8 -0
  495. package/dist/server/routes/recall.js +340 -0
  496. package/dist/server/routes/skills.d.ts +8 -0
  497. package/dist/server/routes/skills.js +150 -0
  498. package/dist/server/types.d.ts +56 -0
  499. package/dist/server/types.js +2 -0
  500. package/dist/server/validation.d.ts +14 -0
  501. package/dist/server/validation.js +91 -0
  502. package/dist/server.d.ts +7 -61
  503. package/dist/server.js +92 -2368
  504. package/dist/session-digest.d.ts +1 -1
  505. package/dist/session-digest.js +9 -2
  506. package/dist/shared.d.ts +3 -1
  507. package/dist/shared.js +46 -40
  508. package/dist/skills.d.ts +3 -0
  509. package/dist/skills.js +7 -5
  510. package/dist/stdin.js +3 -2
  511. package/dist/store/audit-event.d.ts +19 -0
  512. package/dist/store/audit-event.js +33 -0
  513. package/dist/store/candidates.d.ts +42 -0
  514. package/dist/store/candidates.js +152 -0
  515. package/dist/store/conflicts.d.ts +44 -0
  516. package/dist/store/conflicts.js +444 -0
  517. package/dist/store/delete-and-batch.d.ts +63 -0
  518. package/dist/store/delete-and-batch.js +310 -0
  519. package/dist/store/entry-reads.d.ts +92 -0
  520. package/dist/store/entry-reads.js +255 -0
  521. package/dist/store/entry-row.d.ts +67 -0
  522. package/dist/store/entry-row.js +208 -0
  523. package/dist/store/entry-writes.d.ts +46 -0
  524. package/dist/store/entry-writes.js +148 -0
  525. package/dist/store/handoffs.d.ts +26 -0
  526. package/dist/store/handoffs.js +184 -0
  527. package/dist/store/index-and-stats.d.ts +52 -0
  528. package/dist/store/index-and-stats.js +214 -0
  529. package/dist/store/markdown.d.ts +10 -0
  530. package/dist/store/markdown.js +108 -0
  531. package/dist/store/mirrors.d.ts +49 -0
  532. package/dist/store/mirrors.js +312 -0
  533. package/dist/store/open.d.ts +15 -0
  534. package/dist/store/open.js +223 -0
  535. package/dist/store/rows.d.ts +178 -0
  536. package/dist/store/rows.js +158 -0
  537. package/dist/store/search-rows.d.ts +86 -0
  538. package/dist/store/search-rows.js +254 -0
  539. package/dist/store/sessions.d.ts +83 -0
  540. package/dist/store/sessions.js +272 -0
  541. package/dist/store/summaries.d.ts +94 -0
  542. package/dist/store/summaries.js +377 -0
  543. package/dist/store/tenant-lookup.d.ts +12 -0
  544. package/dist/store/tenant-lookup.js +16 -0
  545. package/dist/store-cards.js +2 -1
  546. package/dist/summary-dirty.d.ts +4 -0
  547. package/dist/summary-dirty.js +32 -0
  548. package/dist/support-bundle.js +4 -3
  549. package/dist/tenant.js +2 -2
  550. package/dist/token-ledger.js +1 -0
  551. package/dist/tokenize.d.ts +2 -0
  552. package/dist/tokenize.js +16 -0
  553. package/dist/transcript-tail.d.ts +7 -0
  554. package/dist/transcript-tail.js +48 -0
  555. package/dist/vector-store.d.ts +27 -0
  556. package/dist/vector-store.js +210 -0
  557. package/dist/version.d.ts +2 -2
  558. package/dist/version.js +2 -2
  559. package/dist/working-memory.js +1 -1
  560. package/dist/yaml.js +36 -11
  561. package/dist-ui/assets/ibm-plex-mono-latin-400-normal-CvHOgSBP.woff +0 -0
  562. package/dist-ui/assets/ibm-plex-mono-latin-400-normal-DMJ8VG8y.woff2 +0 -0
  563. package/dist-ui/assets/ibm-plex-mono-latin-500-normal-CB9ihrfo.woff +0 -0
  564. package/dist-ui/assets/ibm-plex-mono-latin-500-normal-DSY6xOcd.woff2 +0 -0
  565. package/dist-ui/assets/ibm-plex-mono-latin-600-normal-BgSNZQsw.woff2 +0 -0
  566. package/dist-ui/assets/ibm-plex-mono-latin-600-normal-DWFSQ4vo.woff +0 -0
  567. package/dist-ui/assets/ibm-plex-sans-latin-400-normal-CDDApCn2.woff2 +0 -0
  568. package/dist-ui/assets/ibm-plex-sans-latin-400-normal-CYLoc0-x.woff +0 -0
  569. package/dist-ui/assets/ibm-plex-sans-latin-500-normal-6ng42L7E.woff2 +0 -0
  570. package/dist-ui/assets/ibm-plex-sans-latin-500-normal-BgVn5rGT.woff +0 -0
  571. package/dist-ui/assets/ibm-plex-sans-latin-600-normal-Cu4Hd6ag.woff +0 -0
  572. package/dist-ui/assets/ibm-plex-sans-latin-600-normal-CuJfVYMP.woff2 +0 -0
  573. package/dist-ui/assets/index-DPN7cP19.js +33 -0
  574. package/dist-ui/assets/index-dFloKRVr.css +1 -0
  575. package/dist-ui/index.html +3 -25
  576. package/extensions/openclaw-plugin/openclaw.plugin.json +1 -1
  577. package/extensions/openclaw-plugin/package.json +1 -1
  578. package/openclaw.plugin.json +1 -1
  579. package/package.json +2 -1
  580. package/dist/capture.d.ts +0 -155
  581. package/dist/capture.js +0 -1293
  582. package/dist/consolidate.d.ts +0 -58
  583. package/dist/consolidate.js +0 -1123
  584. package/dist/graph.d.ts +0 -245
  585. package/dist/hooks.d.ts +0 -208
  586. package/dist/hooks.js +0 -1073
  587. package/dist/importers.js +0 -897
  588. package/dist/predictions.js +0 -620
  589. package/dist/search.d.ts +0 -320
  590. package/dist/search.js +0 -968
  591. package/dist/store.d.ts +0 -744
  592. package/dist/store.js +0 -3372
  593. package/dist-ui/assets/d3-BiWEKnn4.js +0 -1
  594. package/dist-ui/assets/index-BhT8RvO6.js +0 -61
  595. package/dist-ui/assets/index-RoXXJ5dq.css +0 -1
  596. package/dist-ui/assets/three-BDgTxR1l.js +0 -4112
package/dist/audit.d.ts CHANGED
@@ -1,6 +1,7 @@
1
1
  import { type MemoryEntry } from './memory.js';
2
2
  import type { DatabaseSyncLike } from './db.js';
3
3
  import type { JsonObject } from './working-memory.js';
4
+ import { type KeysetPosition } from './keyset.js';
4
5
  export type AuditSeverity = 'warning' | 'error';
5
6
  export interface AuditIssue {
6
7
  memoryId: string;
@@ -42,6 +43,8 @@ export interface QueryAuditOpts {
42
43
  op?: AuditOp;
43
44
  since?: string;
44
45
  limit?: number;
46
+ /** Resume after this row: the (ts, id) position the previous page ended on. */
47
+ after?: KeysetPosition;
45
48
  }
46
49
  export interface AuditEvent {
47
50
  id: number;
package/dist/audit.js CHANGED
@@ -1,6 +1,7 @@
1
1
  import { createHash } from 'node:crypto';
2
2
  import { canAutoDelete } from './memory.js';
3
3
  import { log } from './log.js';
4
+ import { keysetAfter } from './keyset.js';
4
5
  export const STOP_WORDS = new Set([
5
6
  'the', 'a', 'an', 'is', 'was', 'are', 'were', 'be', 'been', 'being',
6
7
  'to', 'of', 'in', 'for', 'on', 'with', 'at', 'by', 'from', 'it',
@@ -274,11 +275,13 @@ export function queryAuditEvents(db, opts) {
274
275
  where.push('ts >= ?');
275
276
  params.push(opts.since);
276
277
  }
277
- const limit = Math.max(1, Math.min(opts.limit ?? 100, 10000));
278
+ const after = keysetAfter('ts', 'id', opts.after);
279
+ // One past the route's 10000 cap: GET /v1/audit reads a row ahead to tell whether another page exists.
280
+ const limit = Math.max(1, Math.min(opts.limit ?? 100, 10001));
278
281
  // SAFETY: AUDIT_COLUMNS names exactly the AuditRow columns, in this order.
279
282
  const rows = db
280
- .prepare(`SELECT ${AUDIT_COLUMNS} FROM audit_log WHERE ${where.join(' AND ')} ORDER BY ts DESC, id DESC LIMIT ?`)
281
- .all(...params, limit);
283
+ .prepare(`SELECT ${AUDIT_COLUMNS} FROM audit_log WHERE ${where.join(' AND ')}${after.sql} ORDER BY ts DESC, id DESC LIMIT ?`)
284
+ .all(...params, ...after.params, limit);
282
285
  return rows.map(rowToAuditEvent);
283
286
  }
284
287
  /**
@@ -330,6 +333,7 @@ function safeJsonParse(raw) {
330
333
  return v instanceof Object ? v : {};
331
334
  }
332
335
  catch {
336
+ // Malformed metadata reads as empty so the audit row itself stays listable.
333
337
  return {};
334
338
  }
335
339
  }
package/dist/auth.d.ts CHANGED
@@ -1,7 +1,13 @@
1
- import type { DatabaseSyncLike } from './db.js';
1
+ import { type DatabaseSyncLike } from './db.js';
2
+ import { type KeysetPosition } from './keyset.js';
2
3
  /** Every minted API key starts with this, so the server can route a bearer token by shape. */
3
4
  export declare const API_KEY_PREFIX = "hk_";
4
- export declare function _dummyHashForTests(): string;
5
+ /** Counts since process start, so a flood of bad tokens shows as scrypt work, not just as 401s. */
6
+ export interface ApiKeyVerifyStats {
7
+ readonly storeLookups: number;
8
+ readonly scryptRuns: number;
9
+ }
10
+ export declare function apiKeyVerifyStats(): ApiKeyVerifyStats;
5
11
  export interface CreateApiKeyOpts {
6
12
  tenantId: string;
7
13
  label?: string;
@@ -22,7 +28,29 @@ export interface ValidateResult {
22
28
  /** EI2: scope grants for this key. Present only when valid=true. */
23
29
  scopes?: string[];
24
30
  }
31
+ /** The identity a verified API key carries. */
32
+ export interface VerifiedApiKey {
33
+ tenantId: string;
34
+ keyId: string;
35
+ role: 'admin' | 'member';
36
+ scopes: string[];
37
+ }
25
38
  export declare function validateApiKey(db: DatabaseSyncLike, plaintext: string): ValidateResult;
39
+ /** How long a verified key is trusted without a store read; also the ceiling on a revoke made by another process. */
40
+ export declare const VERIFIED_KEY_TTL_MS = 60000;
41
+ /** LRU of verified keys with an absolute TTL. Holds a SHA-256 of the token, never the token. */
42
+ export declare class VerifiedKeyCache {
43
+ private readonly capacity;
44
+ private readonly ttlMs;
45
+ private readonly entries;
46
+ constructor(capacity: number, ttlMs: number);
47
+ get size(): number;
48
+ get(hippoRoot: string, keyId: string, plaintext: string, now: number): VerifiedApiKey | undefined;
49
+ set(hippoRoot: string, keyId: string, plaintext: string, key: VerifiedApiKey, now: number): void;
50
+ delete(keyId: string): void;
51
+ }
52
+ /** Verify a bearer API key for `hippoRoot`; a cache hit skips both scrypt and the DB open. Null when invalid. */
53
+ export declare function verifyApiKeyCached(hippoRoot: string, plaintext: string): VerifiedApiKey | null;
26
54
  export declare function revokeApiKey(db: DatabaseSyncLike, keyId: string): void;
27
55
  /** EI2: grant `keyId` read access to one restricted `scope`. Idempotent. */
28
56
  export declare function grantScope(db: DatabaseSyncLike, keyId: string, scope: string): void;
@@ -45,7 +73,20 @@ export interface ApiKeyListItem {
45
73
  /** EI2: restricted scopes this key may read. */
46
74
  scopes: string[];
47
75
  }
48
- export declare function listApiKeys(db: DatabaseSyncLike, opts: {
76
+ export interface ListApiKeysOpts {
49
77
  active: boolean;
50
- }): ApiKeyListItem[];
78
+ /** Only this tenant's keys; omit for every tenant (the CLI's single-tenant view). */
79
+ tenantId?: string;
80
+ /** Resume after this row: the position the previous page ended on (key and id are both the row id). */
81
+ after?: KeysetPosition;
82
+ limit?: number;
83
+ }
84
+ /** A listed key plus its row id, the paging key the list item itself does not expose. */
85
+ export interface ApiKeyListRow {
86
+ rowId: number;
87
+ key: ApiKeyListItem;
88
+ }
89
+ /** Keys newest first, with their row ids, filtered and limited in SQL. */
90
+ export declare function listApiKeyRows(db: DatabaseSyncLike, opts: ListApiKeysOpts): ApiKeyListRow[];
91
+ export declare function listApiKeys(db: DatabaseSyncLike, opts: ListApiKeysOpts): ApiKeyListItem[];
51
92
  //# sourceMappingURL=auth.d.ts.map
package/dist/auth.js CHANGED
@@ -1,10 +1,13 @@
1
- import { randomBytes, scryptSync, timingSafeEqual } from 'node:crypto';
1
+ import { createHash, randomBytes, scryptSync, timingSafeEqual } from 'node:crypto';
2
+ import { openHippoDb, closeHippoDb } from './db.js';
3
+ import { keysetAfter } from './keyset.js';
2
4
  /** Every minted API key starts with this, so the server can route a bearer token by shape. */
3
5
  export const API_KEY_PREFIX = 'hk_';
4
6
  const ID_LEN = 24; // base32 chars after prefix
5
7
  const SECRET_LEN = 32; // base32 chars after dot
6
8
  const SCRYPT_KEYLEN = 32;
7
9
  const BASE32 = 'abcdefghijklmnopqrstuvwxyz234567';
10
+ const MINTED_KEY_PATTERN = new RegExp(`^${API_KEY_PREFIX}[a-z2-7]{${ID_LEN}}\\.[a-z2-7]{${SECRET_LEN}}$`);
8
11
  function randBase32(n) {
9
12
  const bytes = randomBytes(n);
10
13
  let out = '';
@@ -18,18 +21,9 @@ function hashKey(plaintext) {
18
21
  const hash = scryptSync(plaintext, salt, SCRYPT_KEYLEN);
19
22
  return `scrypt$${salt.toString('hex')}$${hash.toString('hex')}`;
20
23
  }
21
- // Constant dummy hash precomputed once at module load. Used by validateApiKey
22
- // to pay the scrypt cost on the miss path (unknown / revoked / malformed key)
23
- // so the timing signal between hit and miss is reduced. The DB lookup branch
24
- // itself can still leak via cache effects — v0.40 follow-up: request-level
25
- // rate limit on /v1/* to bound key-id enumeration. Stored format identical to
26
- // real hashes: scrypt$saltHex$hashHex.
27
- const DUMMY_PLAINTEXT = 'hk_dummy_constant_padding_for_timing.dummy_secret_padding_for_timing_x';
28
- // Precomputed `hashKey(DUMMY_PLAINTEXT)`: computing it at module load put one scrypt on every CLI start.
29
- const DUMMY_HASH = 'scrypt$5b2117156f1ad78738fd8b6a5bace454$92e098fa28003b7c38ba8f1451bd8618260a4a3c5a64b87cc2b471567c0960e7';
30
- // Not a secret (it's padding, not a real key hash): exposed only so a test can pin its shape.
31
- export function _dummyHashForTests() {
32
- return DUMMY_HASH;
24
+ const verifyStats = { storeLookups: 0, scryptRuns: 0 };
25
+ export function apiKeyVerifyStats() {
26
+ return { ...verifyStats };
33
27
  }
34
28
  function verifyKey(plaintext, stored) {
35
29
  const parts = stored.split('$');
@@ -37,6 +31,7 @@ function verifyKey(plaintext, stored) {
37
31
  return false;
38
32
  const salt = Buffer.from(parts[1], 'hex');
39
33
  const expected = Buffer.from(parts[2], 'hex');
34
+ verifyStats.scryptRuns++;
40
35
  const actual = scryptSync(plaintext, salt, expected.length);
41
36
  return expected.length === actual.length && timingSafeEqual(expected, actual);
42
37
  }
@@ -52,49 +47,115 @@ export function createApiKey(db, opts) {
52
47
  db.prepare(`INSERT INTO api_keys (key_id, key_hash, tenant_id, label, created_at, role) VALUES (?, ?, ?, ?, ?, ?)`).run(keyId, hash, opts.tenantId, opts.label ?? null, new Date().toISOString(), opts.role ?? 'admin');
53
48
  return { keyId, plaintext };
54
49
  }
55
- export function validateApiKey(db, plaintext) {
56
- const dot = plaintext.indexOf('.');
57
- if (dot < 0) {
58
- // Malformed input still pays the scrypt cost so caller cannot distinguish
59
- // "no dot" from "unknown key_id" by timing.
60
- verifyKey(DUMMY_PLAINTEXT, DUMMY_HASH);
61
- return { valid: false };
62
- }
63
- const keyId = plaintext.slice(0, dot);
50
+ /** One full check against the store: shape, row, revocation, then scrypt. Null for any failure. */
51
+ function lookupApiKey(db, plaintext) {
52
+ if (!MINTED_KEY_PATTERN.test(plaintext))
53
+ return null;
54
+ const keyId = plaintext.slice(0, API_KEY_PREFIX.length + ID_LEN);
64
55
  // SAFETY: row comes from the SELECT above, which projects exactly
65
56
  // key_hash, tenant_id, revoked_at, role; `.get` returns undefined when no
66
57
  // row matches key_id.
67
58
  const row = db
68
59
  .prepare(`SELECT key_hash, tenant_id, revoked_at, role FROM api_keys WHERE key_id = ?`)
69
60
  .get(keyId);
70
- // Always run verifyKey — on miss/revoked, against DUMMY_HASH so scrypt cost
71
- // is paid. This reduces timing signal between hit and miss, but the DB
72
- // lookup itself can still leak via cache effects. v0.40 follow-up: add
73
- // request-level rate limit on /v1/* to bound enumeration.
74
- const target = (row && !row.revoked_at) ? row.key_hash : DUMMY_HASH;
75
- const matches = verifyKey(plaintext, target);
76
- if (!row || row.revoked_at || !matches)
77
- return { valid: false };
78
- // v1.12.0: fail-safe to least privilege — only 'admin' is admitted as admin,
79
- // anything else (including future schema drift, manual DB tampering inserting
80
- // 'superuser', or a NULL slipped past the NOT NULL constraint) downgrades to
81
- // 'member'. The migration constrains to 'admin' DEFAULT, but defense-in-depth.
61
+ // Ids are 120 random bits and not secret, so padding the miss path with scrypt hid nothing and let junk tokens burn CPU.
62
+ if (!row || row.revoked_at || !verifyKey(plaintext, row.key_hash))
63
+ return null;
64
+ // Fail-safe to least privilege: any role value but 'admin' reads as 'member'.
82
65
  const role = row.role === 'admin' ? 'admin' : 'member';
83
- const scopes = listScopeGrants(db, keyId);
84
- return { valid: true, tenantId: row.tenant_id, keyId, role, scopes };
66
+ return { tenantId: row.tenant_id, keyId, role, scopes: listScopeGrants(db, keyId) };
67
+ }
68
+ export function validateApiKey(db, plaintext) {
69
+ const key = lookupApiKey(db, plaintext);
70
+ return key ? { valid: true, ...key } : { valid: false };
71
+ }
72
+ /** How long a verified key is trusted without a store read; also the ceiling on a revoke made by another process. */
73
+ export const VERIFIED_KEY_TTL_MS = 60_000;
74
+ const VERIFIED_KEY_CACHE_CAP = 1_000;
75
+ function secretDigest(plaintext) {
76
+ return createHash('sha256').update(plaintext).digest();
77
+ }
78
+ /** LRU of verified keys with an absolute TTL. Holds a SHA-256 of the token, never the token. */
79
+ export class VerifiedKeyCache {
80
+ capacity;
81
+ ttlMs;
82
+ // Map iterates in insertion order, so re-inserting on a hit makes the first key the least recent.
83
+ entries = new Map();
84
+ constructor(capacity, ttlMs) {
85
+ this.capacity = capacity;
86
+ this.ttlMs = ttlMs;
87
+ }
88
+ get size() {
89
+ return this.entries.size;
90
+ }
91
+ get(hippoRoot, keyId, plaintext, now) {
92
+ const entry = this.entries.get(keyId);
93
+ if (!entry || entry.hippoRoot !== hippoRoot)
94
+ return undefined;
95
+ if (now >= entry.expiresAt) {
96
+ this.entries.delete(keyId);
97
+ return undefined;
98
+ }
99
+ // A wrong secret misses but leaves the entry, so a flood of bad guesses cannot evict a good key.
100
+ if (!timingSafeEqual(entry.digest, secretDigest(plaintext)))
101
+ return undefined;
102
+ this.entries.delete(keyId);
103
+ this.entries.set(keyId, entry);
104
+ return { ...entry.key, scopes: [...entry.key.scopes] };
105
+ }
106
+ set(hippoRoot, keyId, plaintext, key, now) {
107
+ this.entries.delete(keyId);
108
+ if (this.entries.size >= this.capacity) {
109
+ const oldest = this.entries.keys().next();
110
+ if (!oldest.done)
111
+ this.entries.delete(oldest.value);
112
+ }
113
+ const frozen = Object.freeze({ ...key, scopes: [...key.scopes] });
114
+ this.entries.set(keyId, { hippoRoot, digest: secretDigest(plaintext), key: frozen, expiresAt: now + this.ttlMs });
115
+ }
116
+ delete(keyId) {
117
+ this.entries.delete(keyId);
118
+ }
119
+ }
120
+ // SHORTCUT: per-process cache, so a revoke or scope change made by another process (the CLI) lands within VERIFIED_KEY_TTL_MS; a shared revocation epoch in the store if that is too slow.
121
+ const verifiedKeys = new VerifiedKeyCache(VERIFIED_KEY_CACHE_CAP, VERIFIED_KEY_TTL_MS);
122
+ /** Verify a bearer API key for `hippoRoot`; a cache hit skips both scrypt and the DB open. Null when invalid. */
123
+ export function verifyApiKeyCached(hippoRoot, plaintext) {
124
+ if (!MINTED_KEY_PATTERN.test(plaintext))
125
+ return null;
126
+ const keyId = plaintext.slice(0, API_KEY_PREFIX.length + ID_LEN);
127
+ const hit = verifiedKeys.get(hippoRoot, keyId, plaintext, Date.now());
128
+ if (hit)
129
+ return hit;
130
+ verifyStats.storeLookups++;
131
+ const db = openHippoDb(hippoRoot);
132
+ let key;
133
+ try {
134
+ key = lookupApiKey(db, plaintext);
135
+ }
136
+ finally {
137
+ closeHippoDb(db);
138
+ }
139
+ // Only successes are cached: caching misses would let junk tokens fill the cache and evict real keys.
140
+ if (key)
141
+ verifiedKeys.set(hippoRoot, keyId, plaintext, key, Date.now());
142
+ return key;
85
143
  }
86
144
  export function revokeApiKey(db, keyId) {
87
145
  db.prepare(`UPDATE api_keys SET revoked_at = ? WHERE key_id = ? AND revoked_at IS NULL`)
88
146
  .run(new Date().toISOString(), keyId);
147
+ verifiedKeys.delete(keyId);
89
148
  }
90
149
  /** EI2: grant `keyId` read access to one restricted `scope`. Idempotent. */
91
150
  export function grantScope(db, keyId, scope) {
92
151
  db.prepare(`INSERT INTO api_key_scope_grants (key_id, scope, granted_at) VALUES (?, ?, ?)
93
152
  ON CONFLICT(key_id, scope) DO NOTHING`).run(keyId, scope, new Date().toISOString());
153
+ verifiedKeys.delete(keyId);
94
154
  }
95
155
  /** EI2: revoke `keyId`'s grant on `scope`. Not an error when no such grant exists. */
96
156
  export function ungrantScope(db, keyId, scope) {
97
157
  db.prepare(`DELETE FROM api_key_scope_grants WHERE key_id = ? AND scope = ?`).run(keyId, scope);
158
+ verifiedKeys.delete(keyId);
98
159
  }
99
160
  /** EI2: every restricted scope `keyId` may read. */
100
161
  export function listScopeGrants(db, keyId) {
@@ -104,19 +165,35 @@ export function listScopeGrants(db, keyId) {
104
165
  .all(keyId);
105
166
  return rows.map((r) => r.scope);
106
167
  }
107
- export function listApiKeys(db, opts) {
108
- const sql = opts.active
109
- ? `SELECT key_id, tenant_id, label, created_at, revoked_at, role FROM api_keys WHERE revoked_at IS NULL ORDER BY id DESC`
110
- : `SELECT key_id, tenant_id, label, created_at, revoked_at, role FROM api_keys ORDER BY id DESC`;
111
- // SAFETY: rows come from one of the two SELECTs above, both of which
112
- // project the same 6 columns (key_id, tenant_id, label, created_at,
113
- // revoked_at, role) in the same order.
114
- const rows = db.prepare(sql).all();
168
+ /** Keys newest first, with their row ids, filtered and limited in SQL. */
169
+ export function listApiKeyRows(db, opts) {
170
+ const where = ['1 = 1'];
171
+ const params = [];
172
+ if (opts.active)
173
+ where.push('revoked_at IS NULL');
174
+ if (opts.tenantId !== undefined) {
175
+ where.push('tenant_id = ?');
176
+ params.push(opts.tenantId);
177
+ }
178
+ const after = keysetAfter('id', 'id', opts.after);
179
+ params.push(...after.params);
180
+ const limitSql = opts.limit === undefined ? '' : ' LIMIT ?';
181
+ if (opts.limit !== undefined)
182
+ params.push(opts.limit);
183
+ const sql = `SELECT id, key_id, tenant_id, label, created_at, revoked_at, role FROM api_keys WHERE ${where.join(' AND ')}${after.sql} ORDER BY id DESC${limitSql}`;
184
+ // SAFETY: the SELECT above projects exactly these 7 columns, in this order.
185
+ const rows = db.prepare(sql).all(...params);
115
186
  return rows.map(r => ({
116
- keyId: r.key_id, tenantId: r.tenant_id, label: r.label,
117
- createdAt: r.created_at, revokedAt: r.revoked_at,
118
- role: r.role === 'admin' ? 'admin' : 'member',
119
- scopes: listScopeGrants(db, r.key_id),
187
+ rowId: r.id,
188
+ key: {
189
+ keyId: r.key_id, tenantId: r.tenant_id, label: r.label,
190
+ createdAt: r.created_at, revokedAt: r.revoked_at,
191
+ role: r.role === 'admin' ? 'admin' : 'member',
192
+ scopes: listScopeGrants(db, r.key_id),
193
+ },
120
194
  }));
121
195
  }
196
+ export function listApiKeys(db, opts) {
197
+ return listApiKeyRows(db, opts).map(r => r.key);
198
+ }
122
199
  //# sourceMappingURL=auth.js.map
package/dist/autolearn.js CHANGED
@@ -4,10 +4,11 @@
4
4
  */
5
5
  import { execSync, execFileSync, spawn } from 'child_process';
6
6
  import { createMemory, Layer, DEFAULT_HALF_LIFE_DAYS } from './memory.js';
7
- import { loadAllEntries } from './store.js';
8
- import { textOverlap } from './search.js';
7
+ import { loadAllEntries } from './store/entry-reads.js';
8
+ import { textOverlap } from './tokenize.js';
9
9
  import { isContentWorthStoring } from './audit.js';
10
10
  import { redactSecretsStrict } from './secret-detect.js';
11
+ import { log } from './log.js';
11
12
  /** A memory of a failed command, "Command '<cmd>' failed: <truncated stderr>"; no store is in reach, so `hippo watch` re-derives its half-life from the store's config. */
12
13
  export function captureError(exitCode, stderr, command, tenantId) {
13
14
  // Truncate to first 500 chars to avoid storing megabytes of build logs
@@ -154,7 +155,8 @@ export function isGitRepo(cwd) {
154
155
  });
155
156
  return raw.trim() === 'true';
156
157
  }
157
- catch {
158
+ catch (err) {
159
+ log.debug(`autolearn: not a git repo: ${err instanceof Error ? err.message : String(err)}`);
158
160
  return false;
159
161
  }
160
162
  }
@@ -169,7 +171,8 @@ export function fetchGitLog(cwd, days) {
169
171
  ], { encoding: 'utf8', cwd, timeout: 10000, stdio: ['pipe', 'pipe', 'pipe'], windowsHide: true });
170
172
  return raw;
171
173
  }
172
- catch {
174
+ catch (err) {
175
+ log.debug(`autolearn: git log unavailable: ${err instanceof Error ? err.message : String(err)}`);
173
176
  return '';
174
177
  }
175
178
  }
@@ -0,0 +1,33 @@
1
+ import { type SessionTurn } from './transcript.js';
2
+ export interface CaptureOptions {
3
+ source: 'stdin' | 'file' | 'last-session';
4
+ filePath?: string;
5
+ /** Explicit transcript path for `--last-session`. Without one, `stdinText`
6
+ * is used, then auto-discovery under `~/.claude/projects/` on a manual run. */
7
+ transcriptPath?: string;
8
+ /** Read from stdin by the caller (cli.ts), which owns the bounded wait.
9
+ * `stdinTimedOut` marks an empty read "unknown", not "no payload". */
10
+ stdinText?: string;
11
+ stdinTimedOut?: boolean;
12
+ sessionTurns?: readonly SessionTurn[];
13
+ /**
14
+ * Tee stdout/stderr to this log file while capture runs. Mirrors the
15
+ * pattern used by `hippo sleep --log-file` so the SessionEnd hook output
16
+ * (invisible during TUI teardown) can be surfaced via `hippo last-sleep`
17
+ * on the next session start. Appends rather than truncates — `hippo sleep`
18
+ * writes the same file first in the SessionEnd sequence.
19
+ */
20
+ logFile?: string;
21
+ dryRun: boolean;
22
+ global: boolean;
23
+ /**
24
+ * L9: tenant scope for the dedup read in `cmdCaptureCore`. When provided
25
+ * AND `global` is false, the dedup check only considers this tenant's
26
+ * existing memories. Undefined preserves pre-1.12.1 host-wide dedup
27
+ * behaviour. Ignored when `global: true` (global captures are host-wide).
28
+ */
29
+ tenantId?: string;
30
+ originProject?: string;
31
+ }
32
+ export declare function cmdCapture(hippoRoot: string, options: CaptureOptions): void;
33
+ //# sourceMappingURL=command.d.ts.map