hippo-memory 1.71.0 → 2.0.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 (625) hide show
  1. package/README.md +7 -5
  2. package/dist/agent-memories/apply.d.ts +0 -11
  3. package/dist/agent-memories/apply.js +11 -26
  4. package/dist/agent-memories/claude-code.js +1 -1
  5. package/dist/agent-memories/codex.js +1 -1
  6. package/dist/agent-memories/copilot.d.ts +1 -3
  7. package/dist/agent-memories/copilot.js +1 -17
  8. package/dist/agent-memories/project-folds.d.ts +10 -0
  9. package/dist/agent-memories/project-folds.js +34 -0
  10. package/dist/agent-memories/sync.js +8 -6
  11. package/dist/api/assemble.js +3 -2
  12. package/dist/api/audit.d.ts +30 -2
  13. package/dist/api/audit.js +48 -7
  14. package/dist/api/auth.d.ts +11 -9
  15. package/dist/api/auth.js +39 -40
  16. package/dist/api/auto-sleep.d.ts +5 -2
  17. package/dist/api/auto-sleep.js +7 -3
  18. package/dist/api/availability.js +2 -3
  19. package/dist/api/cards.d.ts +42 -0
  20. package/dist/api/cards.js +52 -0
  21. package/dist/api/conflicts.d.ts +28 -0
  22. package/dist/api/conflicts.js +61 -0
  23. package/dist/api/context-auto.js +4 -2
  24. package/dist/api/context-render.js +4 -3
  25. package/dist/api/context-select.js +15 -29
  26. package/dist/api/context.js +29 -18
  27. package/dist/api/continuity.d.ts +47 -0
  28. package/dist/api/continuity.js +66 -0
  29. package/dist/api/dormant.js +4 -2
  30. package/dist/api/drill-down.js +3 -2
  31. package/dist/api/embeddings.d.ts +17 -0
  32. package/dist/api/embeddings.js +28 -0
  33. package/dist/api/error-reply.d.ts +8 -0
  34. package/dist/api/error-reply.js +21 -0
  35. package/dist/api/forget.d.ts +7 -3
  36. package/dist/api/forget.js +24 -14
  37. package/dist/api/goals.d.ts +1 -1
  38. package/dist/api/goals.js +5 -9
  39. package/dist/api/graph.js +2 -1
  40. package/dist/api/index.d.ts +4 -2
  41. package/dist/api/index.js +4 -2
  42. package/dist/api/instruction-detect.js +5 -1
  43. package/dist/api/learn.d.ts +5 -1
  44. package/dist/api/learn.js +71 -44
  45. package/dist/api/ledger-db.d.ts +2 -6
  46. package/dist/api/ledger-db.js +4 -36
  47. package/dist/api/memories.d.ts +21 -1
  48. package/dist/api/memories.js +51 -1
  49. package/dist/api/objects.d.ts +1 -1
  50. package/dist/api/objects.js +2 -1
  51. package/dist/api/outcome.d.ts +5 -5
  52. package/dist/api/outcome.js +17 -16
  53. package/dist/api/pilot-arm.d.ts +1 -11
  54. package/dist/api/pilot-arm.js +5 -45
  55. package/dist/api/predictions.d.ts +3 -1
  56. package/dist/api/predictions.js +8 -1
  57. package/dist/api/projects.d.ts +21 -0
  58. package/dist/api/projects.js +24 -0
  59. package/dist/api/promote.d.ts +3 -3
  60. package/dist/api/promote.js +26 -28
  61. package/dist/api/prompt-hook.d.ts +17 -2
  62. package/dist/api/prompt-hook.js +45 -4
  63. package/dist/api/quarantine.js +2 -1
  64. package/dist/api/recall-cli.d.ts +3 -0
  65. package/dist/api/recall-cli.js +13 -4
  66. package/dist/api/recall-core.js +10 -5
  67. package/dist/api/recall-pipeline.js +23 -24
  68. package/dist/api/recall-request.js +1 -1
  69. package/dist/api/recall-types.d.ts +3 -1
  70. package/dist/api/recall.d.ts +0 -3
  71. package/dist/api/recall.js +51 -73
  72. package/dist/api/remember-local.d.ts +5 -2
  73. package/dist/api/remember-local.js +15 -7
  74. package/dist/api/remember.d.ts +7 -3
  75. package/dist/api/remember.js +19 -16
  76. package/dist/api/session-end.d.ts +46 -0
  77. package/dist/api/session-end.js +131 -0
  78. package/dist/api/sleep-run.d.ts +1 -1
  79. package/dist/api/sleep-run.js +16 -11
  80. package/dist/api/sleep.js +4 -3
  81. package/dist/api/status.d.ts +24 -0
  82. package/dist/api/status.js +40 -0
  83. package/dist/api/store-init.d.ts +4 -0
  84. package/dist/api/store-init.js +9 -0
  85. package/dist/api/tokens.js +2 -2
  86. package/dist/api/types.d.ts +3 -7
  87. package/dist/api/types.js +6 -1
  88. package/dist/capture/caller-session.d.ts +0 -3
  89. package/dist/capture/caller-session.js +1 -12
  90. package/dist/capture/capture-error.d.ts +2 -2
  91. package/dist/capture/capture-error.js +23 -18
  92. package/dist/capture/codex-patch.js +3 -1
  93. package/dist/capture/command.js +36 -95
  94. package/dist/capture/compact.js +10 -5
  95. package/dist/capture/compaction-items-caller.js +11 -20
  96. package/dist/capture/compaction-record.d.ts +7 -93
  97. package/dist/capture/compaction-record.js +29 -426
  98. package/dist/capture/compaction-spool.d.ts +7 -7
  99. package/dist/capture/compaction-spool.js +60 -51
  100. package/dist/capture/copilot-transcript.d.ts +2 -1
  101. package/dist/capture/copilot-transcript.js +2 -1
  102. package/dist/capture/extract.d.ts +5 -2
  103. package/dist/capture/extract.js +4 -3
  104. package/dist/capture/failure-caller.d.ts +1 -1
  105. package/dist/capture/failure-caller.js +21 -16
  106. package/dist/capture/failure-reading.d.ts +2 -1
  107. package/dist/capture/failure-reading.js +7 -9
  108. package/dist/capture/pre-compact-caller.js +5 -4
  109. package/dist/capture/session-digest.js +4 -3
  110. package/dist/capture/session-end-caller.js +3 -2
  111. package/dist/capture/session-worker.js +22 -10
  112. package/dist/capture/transcript.d.ts +2 -1
  113. package/dist/capture/transcript.js +6 -3
  114. package/dist/capture/working-state.d.ts +4 -2
  115. package/dist/capture/working-state.js +4 -2
  116. package/dist/cli/audit-prune.d.ts +0 -25
  117. package/dist/cli/audit-prune.js +1 -27
  118. package/dist/cli/audit.js +20 -20
  119. package/dist/cli/auth.d.ts +1 -1
  120. package/dist/cli/auth.js +16 -17
  121. package/dist/cli/briefs.d.ts +1 -4
  122. package/dist/cli/briefs.js +37 -292
  123. package/dist/cli/card.js +41 -33
  124. package/dist/cli/client.d.ts +6 -2
  125. package/dist/cli/client.js +37 -21
  126. package/dist/cli/compact-resume-payload.js +1 -1
  127. package/dist/cli/context.d.ts +1 -1
  128. package/dist/cli/context.js +13 -13
  129. package/dist/cli/continuity.d.ts +1 -1
  130. package/dist/cli/continuity.js +36 -39
  131. package/dist/cli/curate.d.ts +2 -2
  132. package/dist/cli/curate.js +32 -36
  133. package/dist/cli/dag.d.ts +1 -1
  134. package/dist/cli/dag.js +23 -8
  135. package/dist/cli/decisions.d.ts +0 -2
  136. package/dist/cli/decisions.js +7 -285
  137. package/dist/cli/eval.d.ts +1 -1
  138. package/dist/cli/eval.js +12 -13
  139. package/dist/cli/explain.d.ts +1 -1
  140. package/dist/cli/explain.js +21 -25
  141. package/dist/cli/flag-values.js +16 -6
  142. package/dist/cli/flags.d.ts +0 -289
  143. package/dist/cli/flags.js +3 -138
  144. package/dist/cli/graph.d.ts +3 -0
  145. package/dist/cli/graph.js +83 -0
  146. package/dist/cli/hook-runtime.d.ts +6 -6
  147. package/dist/cli/hook-runtime.js +9 -36
  148. package/dist/cli/incidents.d.ts +3 -0
  149. package/dist/cli/incidents.js +112 -0
  150. package/dist/cli/init.d.ts +1 -1
  151. package/dist/cli/init.js +28 -19
  152. package/dist/cli/install-steps.d.ts +2 -1
  153. package/dist/cli/install-steps.js +11 -3
  154. package/dist/cli/last-sleep.js +1 -1
  155. package/dist/cli/maintenance.d.ts +3 -3
  156. package/dist/cli/maintenance.js +29 -30
  157. package/dist/cli/notes.d.ts +2 -0
  158. package/dist/cli/notes.js +41 -0
  159. package/dist/cli/object-verbs.d.ts +2 -2
  160. package/dist/cli/object-verbs.js +4 -4
  161. package/dist/cli/open-browser.d.ts +14 -0
  162. package/dist/cli/open-browser.js +26 -0
  163. package/dist/cli/playbooks.d.ts +3 -4
  164. package/dist/cli/playbooks.js +126 -290
  165. package/dist/cli/predictions.d.ts +3 -0
  166. package/dist/cli/predictions.js +174 -0
  167. package/dist/cli/print.js +2 -1
  168. package/dist/cli/projects.js +30 -22
  169. package/dist/cli/quality-repair-once.d.ts +1 -1
  170. package/dist/cli/quality-repair-once.js +6 -5
  171. package/dist/cli/recall.js +13 -7
  172. package/dist/cli/refine-llm.js +18 -17
  173. package/dist/cli/remember.js +17 -17
  174. package/dist/cli/scheduler.js +2 -1
  175. package/dist/cli/serve.js +11 -6
  176. package/dist/cli/session-hooks.d.ts +1 -5
  177. package/dist/cli/session-hooks.js +89 -168
  178. package/dist/cli/setup.d.ts +1 -1
  179. package/dist/cli/setup.js +17 -10
  180. package/dist/cli/shared.d.ts +2 -6
  181. package/dist/cli/shared.js +9 -29
  182. package/dist/cli/sleep-render.js +6 -3
  183. package/dist/cli/sleep.js +6 -37
  184. package/dist/cli/status.d.ts +3 -3
  185. package/dist/cli/status.js +32 -35
  186. package/dist/cli/transfer.d.ts +3 -3
  187. package/dist/cli/transfer.js +64 -43
  188. package/dist/cli/usage.d.ts +1 -80
  189. package/dist/cli/usage.js +2 -696
  190. package/dist/cli/verb-row.d.ts +34 -0
  191. package/dist/cli/verb-row.js +6 -0
  192. package/dist/cli/verbs/health.d.ts +27 -0
  193. package/dist/cli/verbs/health.js +234 -0
  194. package/dist/cli/verbs/memory.d.ts +16 -0
  195. package/dist/cli/verbs/memory.js +236 -0
  196. package/dist/cli/verbs/objects.d.ts +20 -0
  197. package/dist/cli/verbs/objects.js +257 -0
  198. package/dist/cli/verbs/sessions.d.ts +31 -0
  199. package/dist/cli/verbs/sessions.js +314 -0
  200. package/dist/cli/verbs.d.ts +81 -0
  201. package/dist/cli/verbs.js +7 -0
  202. package/dist/cli/versioned-verbs.d.ts +51 -0
  203. package/dist/cli/versioned-verbs.js +79 -0
  204. package/dist/cli.d.ts +1 -272
  205. package/dist/cli.js +24 -315
  206. package/dist/connectors/dlq.d.ts +39 -3
  207. package/dist/connectors/dlq.js +39 -4
  208. package/dist/connectors/github/backfill.js +12 -3
  209. package/dist/connectors/github/deletion.js +2 -1
  210. package/dist/connectors/github/dlq.js +31 -73
  211. package/dist/connectors/github/ingest.d.ts +2 -6
  212. package/dist/connectors/github/ingest.js +5 -29
  213. package/dist/connectors/github/tenant-routing.js +2 -1
  214. package/dist/connectors/github/webhook.d.ts +2 -1
  215. package/dist/connectors/github/webhook.js +35 -2
  216. package/dist/connectors/ingest.d.ts +10 -0
  217. package/dist/connectors/ingest.js +29 -0
  218. package/dist/connectors/slack/deletion.js +2 -1
  219. package/dist/connectors/slack/dlq.js +49 -71
  220. package/dist/connectors/slack/ingest.d.ts +2 -6
  221. package/dist/connectors/slack/ingest.js +4 -28
  222. package/dist/connectors/slack/tenant-routing.js +2 -1
  223. package/dist/connectors/slack/webhook.d.ts +2 -1
  224. package/dist/connectors/slack/webhook.js +2 -1
  225. package/dist/consolidate/conflicts.js +2 -2
  226. package/dist/consolidate/dag.js +29 -18
  227. package/dist/consolidate/dedupe.d.ts +7 -0
  228. package/dist/consolidate/dedupe.js +6 -4
  229. package/dist/consolidate/llm-passes.js +45 -19
  230. package/dist/consolidate/memory-value.js +3 -2
  231. package/dist/consolidate/merge.js +8 -8
  232. package/dist/consolidate/physics-pass.d.ts +6 -1
  233. package/dist/consolidate/physics-pass.js +26 -6
  234. package/dist/consolidate/replay.js +11 -4
  235. package/dist/consolidate/sleep.js +9 -6
  236. package/dist/consolidate/traces.js +5 -5
  237. package/dist/core/ablation.d.ts +10 -0
  238. package/dist/core/ablation.js +12 -0
  239. package/dist/{sharing/scope.d.ts → core/active-scope.d.ts} +1 -1
  240. package/dist/{sharing/scope.js → core/active-scope.js} +1 -1
  241. package/dist/core/ambient.d.ts +4 -0
  242. package/dist/core/ambient.js +39 -18
  243. package/dist/core/api-errors.d.ts +16 -0
  244. package/dist/core/api-errors.js +20 -0
  245. package/dist/core/card.js +3 -1
  246. package/dist/core/compaction-timing.d.ts +7 -0
  247. package/dist/core/compaction-timing.js +9 -0
  248. package/dist/core/config.d.ts +1 -1
  249. package/dist/core/config.js +22 -18
  250. package/dist/core/cosine.d.ts +3 -0
  251. package/dist/core/cosine.js +19 -0
  252. package/dist/{store → core}/markdown.d.ts +1 -1
  253. package/dist/{store → core}/markdown.js +4 -4
  254. package/dist/core/memory-audit.d.ts +17 -0
  255. package/dist/core/memory-audit.js +54 -0
  256. package/dist/core/memory.d.ts +14 -8
  257. package/dist/core/memory.js +35 -23
  258. package/dist/{consolidate → core}/merged-row.d.ts +1 -1
  259. package/dist/{consolidate → core}/merged-row.js +1 -1
  260. package/dist/core/physics.d.ts +3 -1
  261. package/dist/core/physics.js +23 -18
  262. package/dist/core/prediction.d.ts +3 -0
  263. package/dist/core/prediction.js +6 -0
  264. package/dist/core/project-identity.d.ts +3 -0
  265. package/dist/core/project-identity.js +12 -2
  266. package/dist/{store → core}/recall-scope.d.ts +1 -10
  267. package/dist/{store → core}/recall-scope.js +2 -19
  268. package/dist/core/search-types.d.ts +1 -1
  269. package/dist/dashboard/dashboard-actions.d.ts +2 -2
  270. package/dist/dashboard/dashboard-actions.js +5 -5
  271. package/dist/dashboard/dashboard-queries.js +2 -7
  272. package/dist/dashboard/dashboard-snapshot.js +1 -3
  273. package/dist/dashboard/dashboard.js +16 -5
  274. package/dist/db/busy.d.ts +2 -7
  275. package/dist/db/busy.js +21 -26
  276. package/dist/db/connect.d.ts +2 -2
  277. package/dist/db/connect.js +7 -7
  278. package/dist/db/index.d.ts +3 -3
  279. package/dist/db/index.js +3 -3
  280. package/dist/db/migrate.js +14 -7
  281. package/dist/db/migrations/index.d.ts +1 -1
  282. package/dist/db/migrations/index.js +3 -1
  283. package/dist/db/migrations/v11.js +1 -0
  284. package/dist/db/migrations/v14.js +1 -0
  285. package/dist/db/migrations/v55.d.ts +3 -0
  286. package/dist/db/migrations/v55.js +17 -0
  287. package/dist/db/open.d.ts +0 -2
  288. package/dist/db/open.js +6 -10
  289. package/dist/db/physics-state.d.ts +0 -4
  290. package/dist/db/physics-state.js +7 -33
  291. package/dist/db/request-stores.d.ts +1 -0
  292. package/dist/db/request-stores.js +2 -1
  293. package/dist/db/tables.d.ts +2 -0
  294. package/dist/db/tables.js +6 -2
  295. package/dist/db/vector-store.js +19 -5
  296. package/dist/db/wal-checkpointer.js +2 -1
  297. package/dist/doctor.d.ts +3 -0
  298. package/dist/doctor.js +18 -15
  299. package/dist/embeddings/local.d.ts +62 -0
  300. package/dist/embeddings/local.js +146 -0
  301. package/dist/{store/embeddings → embeddings}/provider.d.ts +5 -2
  302. package/dist/{store/embeddings → embeddings}/provider.js +19 -25
  303. package/dist/embeddings/transformers.d.ts +26 -0
  304. package/dist/embeddings/transformers.js +89 -0
  305. package/dist/entry/session-text.d.ts +1 -1
  306. package/dist/entry/session-text.js +1 -1
  307. package/dist/entry/store-kit.d.ts +37 -0
  308. package/dist/entry/store-kit.js +25 -0
  309. package/dist/entry/testing.d.ts +6 -0
  310. package/dist/entry/testing.js +7 -0
  311. package/dist/eval/eval-suite.js +17 -11
  312. package/dist/eval/eval.js +1 -1
  313. package/dist/eval/judgment.js +12 -5
  314. package/dist/graph/extract.js +3 -3
  315. package/dist/graph/recall.js +1 -1
  316. package/dist/graph/view.js +13 -5
  317. package/dist/graph/write.d.ts +1 -1
  318. package/dist/graph/write.js +9 -9
  319. package/dist/hooks/codex-session.js +3 -2
  320. package/dist/hooks/codex-wrapper.js +2 -1
  321. package/dist/hooks/json-hooks.js +10 -4
  322. package/dist/hooks/opencode.js +8 -5
  323. package/dist/hooks/shared.d.ts +0 -6
  324. package/dist/hooks/shared.js +4 -15
  325. package/dist/importers/core.js +4 -4
  326. package/dist/importers/sources.js +5 -4
  327. package/dist/importers/vault.d.ts +1 -1
  328. package/dist/importers/vault.js +25 -23
  329. package/dist/index.d.ts +5 -4
  330. package/dist/index.js +4 -3
  331. package/dist/learn/autolearn.d.ts +15 -3
  332. package/dist/learn/autolearn.js +38 -16
  333. package/dist/learn/churn-git.js +13 -4
  334. package/dist/learn/extract.d.ts +3 -2
  335. package/dist/learn/extract.js +7 -5
  336. package/dist/learn/forward-claim-detector.js +4 -2
  337. package/dist/learn/invalidation.d.ts +2 -1
  338. package/dist/learn/invalidation.js +18 -9
  339. package/dist/mcp/admin-tools.d.ts +2 -2
  340. package/dist/mcp/admin-tools.js +27 -48
  341. package/dist/mcp/format.js +3 -2
  342. package/dist/mcp/framing.d.ts +1 -0
  343. package/dist/mcp/framing.js +1 -1
  344. package/dist/mcp/memory-tools.d.ts +1 -1
  345. package/dist/mcp/memory-tools.js +8 -9
  346. package/dist/mcp/protocol.d.ts +11 -7
  347. package/dist/mcp/protocol.js +25 -12
  348. package/dist/mcp/recall-tools.js +12 -9
  349. package/dist/mcp/request.js +22 -20
  350. package/dist/mcp/stdio.js +37 -16
  351. package/dist/mcp/tool-args.js +2 -1
  352. package/dist/mcp/tools.js +44 -21
  353. package/dist/objects/customer-notes.d.ts +2 -2
  354. package/dist/objects/decisions.d.ts +2 -2
  355. package/dist/objects/descriptor.d.ts +1 -1
  356. package/dist/objects/incidents.d.ts +2 -2
  357. package/dist/objects/lifecycle.d.ts +1 -1
  358. package/dist/objects/lifecycle.js +2 -1
  359. package/dist/objects/policies.d.ts +2 -2
  360. package/dist/objects/policies.js +2 -1
  361. package/dist/objects/processes.d.ts +2 -2
  362. package/dist/objects/project-briefs.d.ts +2 -2
  363. package/dist/objects/project-briefs.js +2 -3
  364. package/dist/objects/skills.d.ts +2 -2
  365. package/dist/postinstall.js +1 -1
  366. package/dist/rerankers/clef.js +3 -6
  367. package/dist/rerankers/cross-encoder.d.ts +31 -2
  368. package/dist/rerankers/cross-encoder.js +71 -98
  369. package/dist/rerankers/index.js +5 -4
  370. package/dist/rerankers/jev.js +2 -4
  371. package/dist/rerankers/outage-warning.d.ts +3 -1
  372. package/dist/rerankers/outage-warning.js +5 -3
  373. package/dist/search/bm25-search.js +1 -1
  374. package/dist/search/boosts.js +1 -1
  375. package/dist/search/embed-memories.d.ts +12 -0
  376. package/dist/search/embed-memories.js +389 -0
  377. package/dist/search/engine.d.ts +8 -0
  378. package/dist/search/engine.js +10 -0
  379. package/dist/search/goal-boost.d.ts +1 -1
  380. package/dist/search/goal-boost.js +6 -3
  381. package/dist/search/hybrid.d.ts +9 -2
  382. package/dist/search/hybrid.js +9 -4
  383. package/dist/search/physics-search.d.ts +6 -3
  384. package/dist/search/physics-search.js +22 -15
  385. package/dist/search/rerank.js +1 -1
  386. package/dist/search/vector.d.ts +8 -6
  387. package/dist/search/vector.js +14 -17
  388. package/dist/server/auth.d.ts +3 -1
  389. package/dist/server/auth.js +24 -15
  390. package/dist/server/boot.d.ts +2 -1
  391. package/dist/server/boot.js +34 -84
  392. package/dist/server/client-ip.d.ts +9 -6
  393. package/dist/server/client-ip.js +36 -17
  394. package/dist/server/deadline.d.ts +0 -2
  395. package/dist/server/deadline.js +1 -7
  396. package/dist/server/defaults.d.ts +1 -0
  397. package/dist/server/defaults.js +1 -0
  398. package/dist/server/mcp-http.js +16 -11
  399. package/dist/server/request.js +7 -2
  400. package/dist/server/route-checks.d.ts +7 -0
  401. package/dist/server/route-checks.js +42 -0
  402. package/dist/server/route-table.d.ts +9 -8
  403. package/dist/server/route-table.js +127 -133
  404. package/dist/server/routes/admin.d.ts +8 -8
  405. package/dist/server/routes/admin.js +13 -21
  406. package/dist/server/routes/customer-notes.d.ts +6 -6
  407. package/dist/server/routes/customer-notes.js +1 -2
  408. package/dist/server/routes/decisions.d.ts +6 -6
  409. package/dist/server/routes/decisions.js +2 -4
  410. package/dist/server/routes/incidents.d.ts +6 -6
  411. package/dist/server/routes/incidents.js +2 -5
  412. package/dist/server/routes/memories.d.ts +9 -9
  413. package/dist/server/routes/memories.js +19 -40
  414. package/dist/server/routes/object-routes.d.ts +6 -6
  415. package/dist/server/routes/object-routes.js +4 -7
  416. package/dist/server/routes/policies.d.ts +7 -7
  417. package/dist/server/routes/policies.js +2 -4
  418. package/dist/server/routes/predictions.d.ts +6 -6
  419. package/dist/server/routes/predictions.js +9 -13
  420. package/dist/server/routes/processes.d.ts +6 -6
  421. package/dist/server/routes/processes.js +1 -2
  422. package/dist/server/routes/project-briefs.d.ts +7 -7
  423. package/dist/server/routes/project-briefs.js +2 -4
  424. package/dist/server/routes/recall.d.ts +5 -5
  425. package/dist/server/routes/recall.js +6 -10
  426. package/dist/server/routes/skills.d.ts +7 -7
  427. package/dist/server/routes/skills.js +2 -4
  428. package/dist/server/server-detect.d.ts +7 -1
  429. package/dist/server/server-detect.js +36 -11
  430. package/dist/server/sleep-child.js +26 -7
  431. package/dist/server/sleep-offload.d.ts +11 -5
  432. package/dist/server/sleep-offload.js +17 -11
  433. package/dist/server/tls.d.ts +7 -2
  434. package/dist/server/tls.js +17 -5
  435. package/dist/server/types.d.ts +29 -12
  436. package/dist/server/validation.d.ts +1 -2
  437. package/dist/server/validation.js +6 -11
  438. package/dist/server.d.ts +4 -40
  439. package/dist/server.js +3 -29
  440. package/dist/sharing/global-store.d.ts +4 -5
  441. package/dist/sharing/global-store.js +8 -13
  442. package/dist/sharing/global-sync.js +38 -45
  443. package/dist/sharing/project-merge.d.ts +7 -14
  444. package/dist/sharing/project-merge.js +57 -121
  445. package/dist/sharing/search-both.js +10 -3
  446. package/dist/sharing/share.d.ts +2 -0
  447. package/dist/sharing/share.js +39 -38
  448. package/dist/store/ambient.js +7 -7
  449. package/dist/store/audit-event.d.ts +1 -1
  450. package/dist/store/audit.d.ts +0 -16
  451. package/dist/store/audit.js +4 -55
  452. package/dist/store/auth.d.ts +4 -2
  453. package/dist/store/auth.js +7 -3
  454. package/dist/store/candidates.d.ts +3 -2
  455. package/dist/store/candidates.js +59 -30
  456. package/dist/store/capture-write.d.ts +17 -0
  457. package/dist/store/capture-write.js +35 -0
  458. package/dist/store/cards.js +6 -5
  459. package/dist/store/compaction-caller.d.ts +18 -0
  460. package/dist/store/compaction-caller.js +29 -0
  461. package/dist/store/compactions-record.d.ts +115 -0
  462. package/dist/store/compactions-record.js +418 -0
  463. package/dist/store/compactions.js +6 -4
  464. package/dist/store/conflicts.d.ts +7 -1
  465. package/dist/store/conflicts.js +13 -9
  466. package/dist/store/connectors/dlq.d.ts +10 -0
  467. package/dist/store/connectors/dlq.js +33 -0
  468. package/dist/store/connectors/event-log.d.ts +13 -0
  469. package/dist/store/connectors/event-log.js +24 -0
  470. package/dist/store/connectors/github.d.ts +7 -9
  471. package/dist/store/connectors/github.js +35 -60
  472. package/dist/store/connectors/slack.d.ts +2 -11
  473. package/dist/store/connectors/slack.js +24 -57
  474. package/dist/store/dashboard-reads.js +8 -6
  475. package/dist/store/delete-and-batch.d.ts +6 -0
  476. package/dist/store/delete-and-batch.js +40 -6
  477. package/dist/store/delivery-recorder.d.ts +12 -5
  478. package/dist/store/delivery-recorder.js +13 -11
  479. package/dist/store/descendant-page.js +8 -4
  480. package/dist/store/dormant.d.ts +1 -1
  481. package/dist/store/dormant.js +10 -4
  482. package/dist/store/embeddings/index.d.ts +2 -12
  483. package/dist/store/embeddings/index.js +5 -374
  484. package/dist/store/entry-reads.d.ts +35 -4
  485. package/dist/store/entry-reads.js +86 -19
  486. package/dist/store/entry-row.js +9 -2
  487. package/dist/store/entry-writes.d.ts +15 -12
  488. package/dist/store/entry-writes.js +54 -22
  489. package/dist/store/failure-log-at.d.ts +8 -0
  490. package/dist/store/failure-log-at.js +16 -0
  491. package/dist/store/failure-log.d.ts +2 -2
  492. package/dist/store/failure-log.js +5 -3
  493. package/dist/{trust → store}/gated-write.d.ts +3 -1
  494. package/dist/{trust → store}/gated-write.js +7 -5
  495. package/dist/store/goals.js +22 -19
  496. package/dist/store/graph-reads.js +9 -6
  497. package/dist/store/graph-view-rows.js +2 -1
  498. package/dist/store/graph-writes.d.ts +6 -6
  499. package/dist/store/graph-writes.js +48 -71
  500. package/dist/store/half-life.js +2 -2
  501. package/dist/store/handoffs.d.ts +10 -4
  502. package/dist/store/handoffs.js +10 -9
  503. package/dist/store/index-and-stats.js +2 -2
  504. package/dist/store/index.d.ts +2 -2
  505. package/dist/store/index.js +1 -1
  506. package/dist/store/key-writes.js +1 -1
  507. package/dist/store/ledger-turn.d.ts +9 -0
  508. package/dist/store/ledger-turn.js +38 -0
  509. package/dist/store/mirrors.js +19 -10
  510. package/dist/store/open.d.ts +2 -5
  511. package/dist/store/open.js +42 -54
  512. package/dist/store/pilot-arm.d.ts +12 -0
  513. package/dist/store/pilot-arm.js +42 -0
  514. package/dist/store/port.d.ts +68 -6
  515. package/dist/store/port.js +8 -0
  516. package/dist/store/predictions.d.ts +1 -2
  517. package/dist/store/predictions.js +3 -6
  518. package/dist/store/project-tags.d.ts +62 -0
  519. package/dist/store/project-tags.js +67 -0
  520. package/dist/store/quality-repair.js +1 -1
  521. package/dist/store/quarantine.js +2 -1
  522. package/dist/store/recall-trace.d.ts +2 -0
  523. package/dist/store/recall-trace.js +20 -3
  524. package/dist/store/rejected-values.js +16 -10
  525. package/dist/store/rejection-probe.d.ts +4 -0
  526. package/dist/store/rejection-probe.js +19 -0
  527. package/dist/store/rejection.d.ts +0 -17
  528. package/dist/store/rejection.js +1 -21
  529. package/dist/store/rows.js +2 -2
  530. package/dist/store/rule-sql.d.ts +11 -0
  531. package/dist/store/rule-sql.js +31 -6
  532. package/dist/store/search-rows.d.ts +5 -5
  533. package/dist/store/search-rows.js +18 -16
  534. package/dist/store/sessions.js +4 -2
  535. package/dist/store/set-aside.d.ts +14 -0
  536. package/dist/store/set-aside.js +23 -0
  537. package/dist/store/sqlite/busy.d.ts +3 -0
  538. package/dist/store/sqlite/busy.js +8 -0
  539. package/dist/store/sqlite/connector-events-group.js +4 -7
  540. package/dist/store/sqlite/connector-writes-group.js +6 -4
  541. package/dist/store/sqlite/entry-writes-group.d.ts +3 -3
  542. package/dist/store/sqlite/entry-writes-group.js +3 -3
  543. package/dist/store/sqlite/error-codec.js +4 -3
  544. package/dist/store/sqlite/executor.js +10 -4
  545. package/dist/store/sqlite/graph-reads-group.js +1 -1
  546. package/dist/store/sqlite/held-connection.d.ts +11 -0
  547. package/dist/store/sqlite/held-connection.js +41 -0
  548. package/dist/store/sqlite/last-recall-group.d.ts +13 -0
  549. package/dist/store/sqlite/last-recall-group.js +57 -0
  550. package/dist/store/sqlite/local.d.ts +0 -17
  551. package/dist/store/sqlite/local.js +0 -31
  552. package/dist/store/sqlite/maintenance-groups.d.ts +6 -0
  553. package/dist/store/sqlite/maintenance-groups.js +60 -0
  554. package/dist/store/sqlite/object-rows.d.ts +1 -1
  555. package/dist/store/sqlite/objects-group.d.ts +1 -1
  556. package/dist/store/sqlite/objects-group.js +15 -7
  557. package/dist/store/sqlite/store.d.ts +1 -8
  558. package/dist/store/sqlite/store.js +13 -22
  559. package/dist/store/summaries.d.ts +10 -3
  560. package/dist/store/summaries.js +54 -11
  561. package/dist/store/token-ledger-rows.js +3 -2
  562. package/dist/store/token-ledger.d.ts +0 -7
  563. package/dist/store/token-ledger.js +0 -35
  564. package/dist/store/vector-index.js +8 -4
  565. package/dist/support-bundle.js +2 -3
  566. package/dist/trust/reject-flow.js +2 -2
  567. package/dist/util/agent-homes.d.ts +15 -0
  568. package/dist/util/agent-homes.js +34 -0
  569. package/dist/util/anthropic-messages.d.ts +6 -1
  570. package/dist/util/anthropic-messages.js +26 -7
  571. package/dist/util/atomic-write.d.ts +5 -2
  572. package/dist/util/atomic-write.js +12 -8
  573. package/dist/util/chunked.d.ts +3 -0
  574. package/dist/util/chunked.js +10 -0
  575. package/dist/util/ellipsize.d.ts +3 -0
  576. package/dist/util/ellipsize.js +5 -0
  577. package/dist/util/env.d.ts +12 -2
  578. package/dist/util/env.js +12 -2
  579. package/dist/util/format.d.ts +5 -0
  580. package/dist/util/format.js +10 -0
  581. package/dist/util/hook-payload.d.ts +8 -0
  582. package/dist/util/hook-payload.js +37 -0
  583. package/dist/util/http-retry.d.ts +6 -0
  584. package/dist/util/http-retry.js +43 -5
  585. package/dist/util/http-util.d.ts +0 -8
  586. package/dist/util/http-util.js +10 -21
  587. package/dist/util/limits.d.ts +7 -0
  588. package/dist/util/limits.js +14 -0
  589. package/dist/util/log.d.ts +4 -0
  590. package/dist/util/log.js +9 -0
  591. package/dist/util/request-scope.d.ts +9 -3
  592. package/dist/util/request-scope.js +18 -9
  593. package/dist/util/secret-detect.js +6 -1
  594. package/dist/util/spawn-argv.d.ts +9 -0
  595. package/dist/util/spawn-argv.js +57 -0
  596. package/dist/util/sql.d.ts +3 -0
  597. package/dist/util/sql.js +6 -0
  598. package/dist/util/sqlite-blocked.d.ts +2 -0
  599. package/dist/util/sqlite-blocked.js +5 -0
  600. package/dist/util/stream-tee.d.ts +3 -0
  601. package/dist/util/stream-tee.js +35 -0
  602. package/dist/util/time.d.ts +4 -0
  603. package/dist/util/time.js +4 -0
  604. package/dist/util/vector-codec.d.ts +4 -0
  605. package/dist/util/vector-codec.js +15 -0
  606. package/dist/util/version.d.ts +1 -1
  607. package/dist/util/version.js +1 -1
  608. package/extensions/openclaw-plugin/openclaw.plugin.json +1 -1
  609. package/extensions/openclaw-plugin/package.json +1 -1
  610. package/openclaw.plugin.json +1 -1
  611. package/package.json +4 -2
  612. package/dist/api/on-store.d.ts +0 -16
  613. package/dist/api/on-store.js +0 -38
  614. package/dist/store/embeddings/local.d.ts +0 -15
  615. package/dist/store/embeddings/local.js +0 -175
  616. /package/dist/{cli → api}/correction-latency.d.ts +0 -0
  617. /package/dist/{cli → api}/correction-latency.js +0 -0
  618. /package/dist/{cli → api}/provenance-coverage.d.ts +0 -0
  619. /package/dist/{cli → api}/provenance-coverage.js +0 -0
  620. /package/dist/{store → core}/object-types.d.ts +0 -0
  621. /package/dist/{store → core}/object-types.js +0 -0
  622. /package/dist/{capture → util}/compaction-items.d.ts +0 -0
  623. /package/dist/{capture → util}/compaction-items.js +0 -0
  624. /package/dist/{store → util}/yaml.d.ts +0 -0
  625. /package/dist/{store → util}/yaml.js +0 -0
@@ -1,13 +1,19 @@
1
1
  /** One retry policy for outbound HTTP: a timeout on every attempt, backoff on 429 and 5xx, and on a dropped connection where a replay is safe. */
2
+ import { MINUTE_MS } from './time.js';
2
3
  import { envLlmTimeoutMs } from './env.js';
4
+ import { errorCode, errorFields, log } from './log.js';
3
5
  const DEFAULT_ATTEMPTS = 3;
4
6
  const DEFAULT_BASE_DELAY_MS = 250;
5
7
  const DEFAULT_MAX_DELAY_MS = 8_000;
6
- const DEFAULT_LLM_TIMEOUT_MS = 60_000;
8
+ const DEFAULT_LLM_TIMEOUT_MS = MINUTE_MS;
7
9
  /** LLM calls (consolidation refine, DAG summaries, fact extraction) share one budget; `HIPPO_LLM_TIMEOUT_MS` overrides it. */
8
10
  export function llmTimeoutMs() {
9
11
  return envLlmTimeoutMs() ?? DEFAULT_LLM_TIMEOUT_MS;
10
12
  }
13
+ /** One LLM call with its retries: two full attempts and the longest wait between them, where three slow failures would hold a sleep for 3x the timeout. */
14
+ export function llmTotalMs() {
15
+ return 2 * llmTimeoutMs() + DEFAULT_MAX_DELAY_MS;
16
+ }
11
17
  export function isRetryableStatus(status) {
12
18
  return status === 429 || (status >= 500 && status <= 599);
13
19
  }
@@ -39,6 +45,22 @@ function isIdempotent(method) {
39
45
  const verb = (method ?? 'GET').toUpperCase();
40
46
  return verb === 'GET' || verb === 'HEAD';
41
47
  }
48
+ /** Host plus pathname only: a query string can carry a key. */
49
+ function redactedTarget(url) {
50
+ try {
51
+ const u = new URL(url);
52
+ return `${u.host}${u.pathname}`;
53
+ }
54
+ catch {
55
+ return 'unparseable-url';
56
+ }
57
+ }
58
+ function logRetry(init, url, reason, attempt, attempts, delayMs) {
59
+ // Debug: an attempt that may still succeed is not a warning, and the caller reports the final failure.
60
+ log.debug('http retry', {
61
+ method: (init.method ?? 'GET').toUpperCase(), target: redactedTarget(url), reason, attempt: `${attempt}/${attempts}`, delayMs: Math.round(delayMs),
62
+ });
63
+ }
42
64
  // `cancel` clears the timer, so a wait the caller left does not keep the process alive.
43
65
  const timerSleep = (ms, cancel) => new Promise((resolve) => {
44
66
  const timer = setTimeout(resolve, ms);
@@ -71,13 +93,16 @@ export async function fetchWithRetry(url, init, policy) {
71
93
  const random = policy.random ?? Math.random;
72
94
  const retryOn = policy.retryOn ?? ((res) => isRetryableStatus(res.status));
73
95
  const retryTransport = policy.retryTransport ?? isIdempotent(init.method);
96
+ const now = policy.now ?? Date.now;
97
+ const deadline = policy.totalMs === undefined ? Infinity : now() + policy.totalMs;
98
+ const fitsBudget = (delayMs) => now() + delayMs < deadline;
74
99
  // Jitter over the upper half keeps parallel callers from retrying in lockstep.
75
100
  const backoffMs = (attempt) => {
76
101
  const ceiling = Math.min(maxDelayMs, baseDelayMs * 2 ** (attempt - 1));
77
102
  return ceiling / 2 + random() * (ceiling / 2);
78
103
  };
79
104
  for (let attempt = 1;; attempt++) {
80
- const timeout = AbortSignal.timeout(policy.timeoutMs);
105
+ const timeout = AbortSignal.timeout(Math.max(1, Math.min(policy.timeoutMs, deadline - now())));
81
106
  const signal = init.signal ? AbortSignal.any([init.signal, timeout]) : timeout;
82
107
  let res;
83
108
  try {
@@ -87,7 +112,11 @@ export async function fetchWithRetry(url, init, policy) {
87
112
  // The caller's own abort is a decision, not a fault, so it ends the call.
88
113
  if (!retryTransport || attempt >= attempts || init.signal?.aborted || !isTransientTransportError(err))
89
114
  throw err;
90
- await backoffWait(backoffMs(attempt), policy.sleep, init.signal);
115
+ const delay = backoffMs(attempt);
116
+ if (!fitsBudget(delay))
117
+ throw err;
118
+ logRetry(init, url, errorCode(err) || (err instanceof Error ? err.name : 'transport'), attempt, attempts, delay);
119
+ await backoffWait(delay, policy.sleep, init.signal);
91
120
  continue;
92
121
  }
93
122
  if (!retryOn(res) || attempt >= attempts)
@@ -95,9 +124,18 @@ export async function fetchWithRetry(url, init, policy) {
95
124
  const retryAfter = parseRetryAfterMs(res.headers.get('retry-after'));
96
125
  if (retryAfter !== null && retryAfter > maxDelayMs)
97
126
  return res;
127
+ const delay = retryAfter ?? backoffMs(attempt);
128
+ if (!fitsBudget(delay))
129
+ return res;
98
130
  // Frees the pooled socket before the next attempt.
99
- await res.body?.cancel();
100
- await backoffWait(retryAfter ?? backoffMs(attempt), policy.sleep, init.signal);
131
+ try {
132
+ await res.body?.cancel();
133
+ }
134
+ catch (err) {
135
+ log.debug('http retry: body cancel failed', errorFields(err));
136
+ }
137
+ logRetry(init, url, `status ${res.status}`, attempt, attempts, delay);
138
+ await backoffWait(delay, policy.sleep, init.signal);
101
139
  }
102
140
  }
103
141
  //# sourceMappingURL=http-retry.js.map
@@ -1,7 +1,6 @@
1
1
  import type { IncomingMessage, ServerResponse } from 'node:http';
2
2
  export declare function isHeaderString(value: string | string[] | undefined): value is string;
3
3
  export declare const MAX_BODY_BYTES: number;
4
- export declare const MAX_ID_LEN = 256;
5
4
  export declare const JSON_HEADERS: {
6
5
  readonly 'content-type': "application/json";
7
6
  };
@@ -21,16 +20,9 @@ export declare class BodyTooLargeError extends Error {
21
20
  /** The body did not arrive in time. Its own class so mapApiError answers 408 and the server drops the socket. */
22
21
  export declare class BodyTimeoutError extends Error {
23
22
  }
24
- /** The status and client-facing message for one failed request. */
25
- export interface ApiErrorReply {
26
- status: number;
27
- message: string;
28
- }
29
23
  export declare const INTERNAL_ERROR_MESSAGE = "internal server error";
30
24
  /** The reply when a request under another store reaches code that still opens hippo.db. */
31
25
  export declare const STORE_NOT_PORTED_MESSAGE = "store_not_ported";
32
- /** Maps by class so rewording a message never moves a status; an untyped error is a 500 whose text stays in the server log. */
33
- export declare function mapApiError<E>(err: E): ApiErrorReply;
34
26
  /** Serialises before the head goes out, so a body that is not JSON still reaches the caller's error reply. */
35
27
  export declare function sendJson<T>(res: ServerResponse, status: number, body: T): void;
36
28
  /** How long any route waits for a request body, so a client that sends headers and then stalls cannot hold a request open: 30 s, or HIPPO_BODY_TIMEOUT_MS. */
@@ -1,5 +1,3 @@
1
- import { ApiError } from '../core/api-errors.js';
2
- import { SqliteBlockedError } from './sqlite-blocked.js';
3
1
  import { envBodyTimeoutMs } from './env.js';
4
2
  // Leaf module shared by server.ts and the connector webhook receivers; it must not import either.
5
3
  // node:http header values are `string | string[] | undefined` (never a bare
@@ -15,8 +13,6 @@ function sizeLabel(bytes) {
15
13
  }
16
14
  // How long a refused upload is still read and discarded after its reply, so a client that never stops cannot hold the socket.
17
15
  const REFUSED_UPLOAD_LINGER_MS = 2000;
18
- // Cap for id-shaped request fields (ids, tenant, session, scope, class): far above real values, small enough to bound logs and indexes.
19
- export const MAX_ID_LEN = 256;
20
16
  export const JSON_HEADERS = { 'content-type': 'application/json' };
21
17
  export class HttpError extends Error {
22
18
  status;
@@ -43,22 +39,6 @@ export class BodyTimeoutError extends Error {
43
39
  export const INTERNAL_ERROR_MESSAGE = 'internal server error';
44
40
  /** The reply when a request under another store reaches code that still opens hippo.db. */
45
41
  export const STORE_NOT_PORTED_MESSAGE = 'store_not_ported';
46
- /** Maps by class so rewording a message never moves a status; an untyped error is a 500 whose text stays in the server log. */
47
- export function mapApiError(err) {
48
- // An add-on can build an HttpError from any number, and writeHead throws on one outside 100-999.
49
- if (err instanceof HttpError && !(Number.isInteger(err.status) && err.status >= 100 && err.status <= 999)) {
50
- return { status: 500, message: INTERNAL_ERROR_MESSAGE };
51
- }
52
- if (err instanceof HttpError || err instanceof ApiError)
53
- return { status: err.status, message: err.message };
54
- if (err instanceof BodyTooLargeError)
55
- return { status: 413, message: err.message };
56
- if (err instanceof BodyTimeoutError)
57
- return { status: 408, message: err.message };
58
- if (err instanceof SqliteBlockedError)
59
- return { status: 501, message: STORE_NOT_PORTED_MESSAGE };
60
- return { status: 500, message: INTERNAL_ERROR_MESSAGE };
61
- }
62
42
  /** Serialises before the head goes out, so a body that is not JSON still reaches the caller's error reply. */
63
43
  export function sendJson(res, status, body) {
64
44
  const text = JSON.stringify(body);
@@ -121,7 +101,16 @@ export function isCrossSite(req) {
121
101
  if (site !== undefined && site !== 'same-origin' && site !== 'none')
122
102
  return true;
123
103
  const origin = req.headers.origin;
124
- return origin !== undefined && origin !== `http://${req.headers.host}`;
104
+ return origin !== undefined && originHost(origin) !== req.headers.host;
105
+ }
106
+ // Scheme is ignored so an https page behind a TLS-terminating proxy still matches its own Host.
107
+ function originHost(origin) {
108
+ try {
109
+ return new URL(origin).host;
110
+ }
111
+ catch {
112
+ return null;
113
+ }
125
114
  }
126
115
  // A webhook route takes no key, so anyone holding a signature header could otherwise keep a socket open with a body that never ends.
127
116
  const WEBHOOK_BODY_DEADLINE_MS = 10_000;
@@ -0,0 +1,7 @@
1
+ export declare const MAX_ID_LEN = 256;
2
+ export declare const DEFAULT_LIST_LIMIT = 100;
3
+ export declare const MAX_LIST_LIMIT = 1000;
4
+ /** The one list-limit rule: absent means the default; a positive integer up to the ceiling passes.
5
+ * Anything else returns undefined, so each surface words its own error. */
6
+ export declare function resolveListLimit(requested: number | undefined, defaultLimit?: number, maxLimit?: number): number | undefined;
7
+ //# sourceMappingURL=limits.d.ts.map
@@ -0,0 +1,14 @@
1
+ // Cap for id-shaped request fields (ids, tenant, session, scope, class): far above real values, small enough to bound logs and indexes.
2
+ export const MAX_ID_LEN = 256;
3
+ // Page size every list surface (CLI, HTTP, store) falls back to when the caller names none.
4
+ export const DEFAULT_LIST_LIMIT = 100;
5
+ // Ceiling for a caller-named list page; SQLite `LIMIT ?` and one response's size bound it, and every list surface shares it.
6
+ export const MAX_LIST_LIMIT = 1000;
7
+ /** The one list-limit rule: absent means the default; a positive integer up to the ceiling passes.
8
+ * Anything else returns undefined, so each surface words its own error. */
9
+ export function resolveListLimit(requested, defaultLimit = DEFAULT_LIST_LIMIT, maxLimit = Infinity) {
10
+ if (requested === undefined)
11
+ return defaultLimit;
12
+ return Number.isInteger(requested) && requested > 0 && requested <= maxLimit ? requested : undefined;
13
+ }
14
+ //# sourceMappingURL=limits.js.map
@@ -30,6 +30,10 @@ export declare const log: {
30
30
  };
31
31
  /** Message for a caught value of unknown shape. `cause` names the sanctioned unknown-input case (error-cause enrichment). */
32
32
  export declare function errorMessage(cause: unknown): string;
33
+ /** One post-compact failure, told once to the hook's output (`say`) and once to the structured log. */
34
+ export declare function reportCompactionFailure(say: (message: string) => void, step: string, reason: string): void;
35
+ /** The string `code` of a caught value (an errno name such as EACCES), or '' when it has none. */
36
+ export declare function errorCode(cause: unknown): string;
33
37
  /** Test hook: forget which once-keys have fired. */
34
38
  export declare function resetLogOnce(): void;
35
39
  export {};
package/dist/util/log.js CHANGED
@@ -83,6 +83,15 @@ export const log = {
83
83
  export function errorMessage(cause) {
84
84
  return cause instanceof Error ? cause.message : String(cause);
85
85
  }
86
+ /** One post-compact failure, told once to the hook's output (`say`) and once to the structured log. */
87
+ export function reportCompactionFailure(say, step, reason) {
88
+ say(`${step} failed: ${reason}`);
89
+ log.error(`post-compact: ${step} failed: ${reason}`);
90
+ }
91
+ /** The string `code` of a caught value (an errno name such as EACCES), or '' when it has none. */
92
+ export function errorCode(cause) {
93
+ return cause instanceof Error && 'code' in cause ? String(cause.code) : '';
94
+ }
86
95
  /** Test hook: forget which once-keys have fired. */
87
96
  export function resetLogOnce() {
88
97
  onceKeys.clear();
@@ -5,7 +5,11 @@ export interface RequestScope {
5
5
  readonly requestId: string | undefined;
6
6
  /** Set for a served request that must be answered by a given time. */
7
7
  readonly deadline?: RequestDeadline | undefined;
8
+ /** Aborts when the request passes its deadline, so a handler that checks it stops starting work nobody waits for. */
9
+ readonly signal?: AbortSignal | undefined;
8
10
  }
11
+ /** How long a request may run: 120 s, or HIPPO_REQUEST_DEADLINE_MS, where 0 turns the deadline off. */
12
+ export declare function requestDeadlineMs(): number;
9
13
  /** When a request must be answered, and the store calls it still waits on: the store ends each of those soon after `at`, with the outcome only it knows. */
10
14
  export declare class RequestDeadline {
11
15
  #private;
@@ -14,7 +18,7 @@ export declare class RequestDeadline {
14
18
  constructor(at: number);
15
19
  /** Counts `call` as one the request waits on until it settles. */
16
20
  track<T>(call: Promise<T>): Promise<T>;
17
- /** Runs `fn` now, or once the last store call the request waits on has settled. */
21
+ /** Runs `fn` now, or once the last store call the request waits on has settled; every function registered meanwhile runs, in order. */
18
22
  onceIdle(fn: () => void): void;
19
23
  }
20
24
  export declare const requestScopes: AsyncLocalStorage<RequestScope>;
@@ -22,7 +26,9 @@ export declare const requestScopes: AsyncLocalStorage<RequestScope>;
22
26
  export declare function currentRequestId(): string | undefined;
23
27
  /** The deadline of the request this code runs for, if it has one. */
24
28
  export declare function currentDeadline(): RequestDeadline | undefined;
29
+ /** The abort signal of the request this code runs for, if it has one. */
30
+ export declare function currentSignal(): AbortSignal | undefined;
25
31
  /** Runs `fn` with `requestId` on every log line it writes, including the ones from
26
- * timers and promises it starts. `deadline` reaches every store call made inside. */
27
- export declare function runWithRequestId<T>(requestId: string, fn: () => T, deadline?: RequestDeadline): T;
32
+ * timers and promises it starts. `deadline` reaches every store call made inside, and `signal` every check of `currentSignal`. */
33
+ export declare function runWithRequestId<T>(requestId: string, fn: () => T, deadline?: RequestDeadline, signal?: AbortSignal): T;
28
34
  //# sourceMappingURL=request-scope.d.ts.map
@@ -1,11 +1,17 @@
1
1
  // The one ambient scope of a request. A leaf module, so the logger can read the request id without importing the store layer.
2
2
  import { AsyncLocalStorage } from 'node:async_hooks';
3
+ import { envRequestDeadlineMs } from './env.js';
4
+ const DEFAULT_REQUEST_DEADLINE_MS = 120_000;
5
+ /** How long a request may run: 120 s, or HIPPO_REQUEST_DEADLINE_MS, where 0 turns the deadline off. */
6
+ export function requestDeadlineMs() {
7
+ return envRequestDeadlineMs() ?? DEFAULT_REQUEST_DEADLINE_MS;
8
+ }
3
9
  /** When a request must be answered, and the store calls it still waits on: the store ends each of those soon after `at`, with the outcome only it knows. */
4
10
  export class RequestDeadline {
5
11
  /** Epoch milliseconds. */
6
12
  at;
7
13
  #storeCalls = 0;
8
- #whenIdle;
14
+ #whenIdle = [];
9
15
  constructor(at) {
10
16
  this.at = at;
11
17
  }
@@ -16,19 +22,18 @@ export class RequestDeadline {
16
22
  this.#storeCalls -= 1;
17
23
  if (this.#storeCalls > 0)
18
24
  return;
19
- const idle = this.#whenIdle;
20
- this.#whenIdle = undefined;
21
- idle?.();
25
+ for (const idle of this.#whenIdle.splice(0))
26
+ idle();
22
27
  };
23
28
  call.then(done, done);
24
29
  return call;
25
30
  }
26
- /** Runs `fn` now, or once the last store call the request waits on has settled. */
31
+ /** Runs `fn` now, or once the last store call the request waits on has settled; every function registered meanwhile runs, in order. */
27
32
  onceIdle(fn) {
28
33
  if (this.#storeCalls === 0)
29
34
  fn();
30
35
  else
31
- this.#whenIdle = fn;
36
+ this.#whenIdle.push(fn);
32
37
  }
33
38
  }
34
39
  export const requestScopes = new AsyncLocalStorage();
@@ -40,9 +45,13 @@ export function currentRequestId() {
40
45
  export function currentDeadline() {
41
46
  return requestScopes.getStore()?.deadline;
42
47
  }
48
+ /** The abort signal of the request this code runs for, if it has one. */
49
+ export function currentSignal() {
50
+ return requestScopes.getStore()?.signal;
51
+ }
43
52
  /** Runs `fn` with `requestId` on every log line it writes, including the ones from
44
- * timers and promises it starts. `deadline` reaches every store call made inside. */
45
- export function runWithRequestId(requestId, fn, deadline) {
46
- return requestScopes.run({ requestId, deadline }, fn);
53
+ * timers and promises it starts. `deadline` reaches every store call made inside, and `signal` every check of `currentSignal`. */
54
+ export function runWithRequestId(requestId, fn, deadline, signal) {
55
+ return requestScopes.run({ requestId, deadline, signal }, fn);
47
56
  }
48
57
  //# sourceMappingURL=request-scope.js.map
@@ -28,7 +28,12 @@ const SECRET_PATTERNS = [
28
28
  { name: 'sk-underscore-key', re: /\bsk_[A-Za-z0-9]+_[A-Za-z0-9_]{6,}\b/ },
29
29
  // Value needs 12+ token-safe chars and a digit, or `token = estimateTokens(...)` and user:password@ templates would hide code lessons from ambient context.
30
30
  // Secret names end in the keyword (dbPassword), so the match opens there, no prefix scan; pwd and pass need a _ (OLDPWD, bypass are not secrets).
31
- { name: 'secret-assignment', re: /(?:(?:api[_-]?key|access[_-]?key|private[_-]?key|secret|token|passw(?:or)?d|(?<=_)(?:pwd|pass))(?:[_-]?(?:key(?:[_-]?base)?|value|secret))?['"]?\s*(?::=?|=>?)\s*['"]?|(?<=--)password(?:=|\s+))(?=[A-Za-z0-9_\-+/]*\d)[A-Za-z0-9_\-+/=]{12,}/i },
31
+ {
32
+ name: 'secret-assignment',
33
+ re: new RegExp(String.raw `(?:(?:api[_-]?key|access[_-]?key|private[_-]?key|secret|token|passw(?:or)?d|(?<=_)(?:pwd|pass))` +
34
+ String.raw `(?:[_-]?(?:key(?:[_-]?base)?|value|secret))?['"]?\s*(?::=?|=>?)\s*['"]?|(?<=--)password(?:=|\s+))` +
35
+ String.raw `(?=[A-Za-z0-9_\-+/]*\d)[A-Za-z0-9_\-+/=]{12,}`, 'i'),
36
+ },
32
37
  { name: 'url-password', re: /(?<=[A-Za-z0-9]:\/\/)[^\s/:@?#]*:(?=[^\s/@?#]*\d)[^\s/@?#]+(?=@)/ },
33
38
  ];
34
39
  const KEYISH_CONTEXT_RE = /key|token|secret|credential|bearer|auth|password/i;
@@ -0,0 +1,9 @@
1
+ import { type ChildProcess, type SpawnOptions } from 'node:child_process';
2
+ /** Quotes one cmd.exe argument; each `%` leaves the quotes as `^%`, so no %NAME% pair can expand. */
3
+ export declare function quoteCmdArg(arg: string): string;
4
+ /** cmd.exe arguments that run a .cmd or .bat shim with every forwarded argument delivered verbatim. */
5
+ export declare function cmdShimArgs(shimPath: string, forwardArgs: readonly string[]): string[];
6
+ /** Spawns argv[0] with the rest as its arguments and no shell. Node refuses to start a .cmd or .bat without one (CVE-2024-27980),
7
+ * so on win32 such a shim runs through cmd.exe with every argument quoted for it. */
8
+ export declare function spawnArgv(argv: readonly string[], options: SpawnOptions): ChildProcess;
9
+ //# sourceMappingURL=spawn-argv.d.ts.map
@@ -0,0 +1,57 @@
1
+ // Starting a command from an argv list with no shell, Windows .cmd and .bat shims included, so no argument is ever parsed as shell syntax.
2
+ import { spawn } from 'node:child_process';
3
+ import * as fs from 'node:fs';
4
+ import * as path from 'node:path';
5
+ import { envPath, envPathExt } from './env.js';
6
+ /** Quotes one cmd.exe argument; each `%` leaves the quotes as `^%`, so no %NAME% pair can expand. */
7
+ export function quoteCmdArg(arg) {
8
+ if (arg.length === 0)
9
+ return '""';
10
+ if (!/[ \t"&()^<>|%!]/.test(arg))
11
+ return arg;
12
+ return `"${arg.replace(/"/g, '""').replace(/%/g, '"^%"')}"`;
13
+ }
14
+ /** cmd.exe arguments that run a .cmd or .bat shim with every forwarded argument delivered verbatim. */
15
+ export function cmdShimArgs(shimPath, forwardArgs) {
16
+ const command = `"${shimPath}"${forwardArgs.length > 0 ? ` ${forwardArgs.map(quoteCmdArg).join(' ')}` : ''}`;
17
+ // The line is already quoted for cmd.exe, so Node must not quote it again; /s strips the outer pair.
18
+ return ['/d', '/v:off', '/s', '/c', `"${command}"`];
19
+ }
20
+ const DEFAULT_PATHEXT = '.COM;.EXE;.BAT;.CMD';
21
+ function isFile(candidate) {
22
+ return fs.statSync(candidate, { throwIfNoEntry: false })?.isFile() === true;
23
+ }
24
+ /** The file `command` names on win32: as given when it has a folder, else the first hit in the working folder then PATH, trying each PATHEXT. */
25
+ function resolveWindowsCommand(command) {
26
+ const exts = (envPathExt() ?? DEFAULT_PATHEXT).split(';').filter((ext) => ext.length > 0);
27
+ const dirs = /[\\/]/.test(command) ? [''] : [process.cwd(), ...(envPath() ?? '').split(path.delimiter).filter((dir) => dir.length > 0)];
28
+ for (const dir of dirs) {
29
+ const base = dir === '' ? command : path.join(dir, command);
30
+ const candidates = path.extname(command) === '' ? exts.map((ext) => base + ext) : [base, ...exts.map((ext) => base + ext)];
31
+ const hit = candidates.find(isFile);
32
+ if (hit !== undefined)
33
+ return hit;
34
+ }
35
+ return null;
36
+ }
37
+ /** Spawns argv[0] with the rest as its arguments and no shell. Node refuses to start a .cmd or .bat without one (CVE-2024-27980),
38
+ * so on win32 such a shim runs through cmd.exe with every argument quoted for it. */
39
+ export function spawnArgv(argv, options) {
40
+ const [command, ...args] = argv;
41
+ if (command === undefined || command.length === 0)
42
+ throw new RangeError('spawnArgv needs a command: argv is empty');
43
+ if (process.platform === 'win32') {
44
+ const resolved = resolveWindowsCommand(command);
45
+ const ext = resolved === null ? '' : path.extname(resolved).toLowerCase();
46
+ if (resolved !== null && (ext === '.cmd' || ext === '.bat')) {
47
+ return spawn('cmd.exe', cmdShimArgs(resolved, args), {
48
+ ...options,
49
+ windowsHide: options.windowsHide ?? true,
50
+ shell: false,
51
+ windowsVerbatimArguments: true,
52
+ });
53
+ }
54
+ }
55
+ return spawn(command, args, { ...options, windowsHide: options.windowsHide ?? true, shell: false });
56
+ }
57
+ //# sourceMappingURL=spawn-argv.js.map
@@ -0,0 +1,3 @@
1
+ /** `n` bound-parameter marks joined for an IN list or VALUES row, e.g. 3 -> "?, ?, ?". */
2
+ export declare function placeholders(n: number): string;
3
+ //# sourceMappingURL=sql.d.ts.map
@@ -0,0 +1,6 @@
1
+ // SQL text helpers shared by every layer that builds an IN list or VALUES row.
2
+ /** `n` bound-parameter marks joined for an IN list or VALUES row, e.g. 3 -> "?, ?, ?". */
3
+ export function placeholders(n) {
4
+ return Array.from({ length: n }, () => '?').join(', ');
5
+ }
6
+ //# sourceMappingURL=sql.js.map
@@ -13,4 +13,6 @@ export declare class OtherStoreFolderError extends SqliteBlockedError {
13
13
  readonly markerPath: string;
14
14
  constructor(storeKind: string, markerPath: string);
15
15
  }
16
+ /** First line of a best-effort catch around a hippo.db open: an unported path must fail closed, not fall back silently. */
17
+ export declare function rethrowIfSqliteBlocked<E>(err: E): void;
16
18
  //# sourceMappingURL=sqlite-blocked.d.ts.map
@@ -26,4 +26,9 @@ export class OtherStoreFolderError extends SqliteBlockedError {
26
26
  this.name = 'OtherStoreFolderError';
27
27
  }
28
28
  }
29
+ /** First line of a best-effort catch around a hippo.db open: an unported path must fail closed, not fall back silently. */
30
+ export function rethrowIfSqliteBlocked(err) {
31
+ if (err instanceof SqliteBlockedError)
32
+ throw err;
33
+ }
29
34
  //# sourceMappingURL=sqlite-blocked.js.map
@@ -0,0 +1,3 @@
1
+ /** Mirrors every stdout and stderr chunk to `logFile` until the returned restore runs; an append failure warns once and never stops the real write. */
2
+ export declare function teeStdStreams(logFile: string): () => void;
3
+ //# sourceMappingURL=stream-tee.d.ts.map
@@ -0,0 +1,35 @@
1
+ import * as fs from 'fs';
2
+ import { errorMessage, log } from './log.js';
3
+ /** Mirrors every stdout and stderr chunk to `logFile` until the returned restore runs; an append failure warns once and never stops the real write. */
4
+ export function teeStdStreams(logFile) {
5
+ const origStdoutWrite = process.stdout.write.bind(process.stdout);
6
+ const origStderrWrite = process.stderr.write.bind(process.stderr);
7
+ let warned = false;
8
+ const tee = (chunk) => {
9
+ try {
10
+ fs.appendFileSync(logFile, chunk instanceof Uint8Array ? Buffer.from(chunk).toString('utf8') : chunk, 'utf8');
11
+ }
12
+ catch (err) {
13
+ if (warned)
14
+ return;
15
+ warned = true;
16
+ log.warn(`log file ${logFile} is no longer writable; output continues without it: ${errorMessage(err)}`);
17
+ }
18
+ };
19
+ const wrapWrite = (origWrite) => {
20
+ const wrapped = (...args) => {
21
+ tee(args[0]);
22
+ // SAFETY: forwarding the exact arguments the real overloaded `write` received is safe; `StreamWriteArgs` is the union of both overloads' parameter lists.
23
+ return origWrite(...args);
24
+ };
25
+ // SAFETY: `wrapped` matches both real `write` overload shapes; TS cannot verify one implementation covers an overloaded type.
26
+ return wrapped;
27
+ };
28
+ process.stdout.write = wrapWrite(origStdoutWrite);
29
+ process.stderr.write = wrapWrite(origStderrWrite);
30
+ return () => {
31
+ process.stdout.write = origStdoutWrite;
32
+ process.stderr.write = origStderrWrite;
33
+ };
34
+ }
35
+ //# sourceMappingURL=stream-tee.js.map
@@ -1,2 +1,6 @@
1
1
  export declare const DAY_MS = 86400000;
2
+ export declare const MINUTE_MS = 60000;
3
+ export declare const HOUR_MS = 3600000;
4
+ /** One 365-day year in seconds. */
5
+ export declare const YEAR_S = 31536000;
2
6
  //# sourceMappingURL=time.d.ts.map
package/dist/util/time.js CHANGED
@@ -1,3 +1,7 @@
1
1
  // Durations in the base layer, so no layer imports a higher one for a constant.
2
2
  export const DAY_MS = 86_400_000;
3
+ export const MINUTE_MS = 60_000;
4
+ export const HOUR_MS = 3_600_000;
5
+ /** One 365-day year in seconds. */
6
+ export const YEAR_S = 31_536_000;
3
7
  //# sourceMappingURL=time.js.map
@@ -0,0 +1,4 @@
1
+ /** Float32 vector <-> Buffer codec for BLOB columns. */
2
+ export declare function float32ToBuffer(arr: number[]): Buffer;
3
+ export declare function bufferToFloat32(buf: Buffer | Uint8Array): number[];
4
+ //# sourceMappingURL=vector-codec.d.ts.map
@@ -0,0 +1,15 @@
1
+ /** Float32 vector <-> Buffer codec for BLOB columns. */
2
+ export function float32ToBuffer(arr) {
3
+ const f32 = new Float32Array(arr);
4
+ return Buffer.from(f32.buffer);
5
+ }
6
+ export function bufferToFloat32(buf) {
7
+ if (buf.byteLength === 0 || buf.byteLength % 4 !== 0)
8
+ return [];
9
+ // Ensure we have a properly aligned copy (SQLite may return Uint8Array, not Buffer)
10
+ const bytes = new Uint8Array(buf.buffer, buf.byteOffset, buf.byteLength);
11
+ const aligned = new ArrayBuffer(bytes.length);
12
+ new Uint8Array(aligned).set(bytes);
13
+ return Array.from(new Float32Array(aligned));
14
+ }
15
+ //# sourceMappingURL=vector-codec.js.map
@@ -1,6 +1,6 @@
1
1
  /** Single source of truth for the package version, written by scripts/sync-version.mjs; never edit by hand. Read by the db rollback guard, /health, MCP.
2
2
  * A constant, not a runtime package.json read: the published bundle may lack package.json on a path ESM can resolve. */
3
- export declare const PACKAGE_VERSION = "1.71.0";
3
+ export declare const PACKAGE_VERSION = "2.0.0";
4
4
  /** The floor a store takes on its first expiring key: the first release with schema
5
5
  * v53, set by hand in that release; scripts/check-expiring-keys-floor.mjs gates it. */
6
6
  export declare const EXPIRING_KEYS_MIN_BINARY = "1.64.0";
@@ -1,6 +1,6 @@
1
1
  /** Single source of truth for the package version, written by scripts/sync-version.mjs; never edit by hand. Read by the db rollback guard, /health, MCP.
2
2
  * A constant, not a runtime package.json read: the published bundle may lack package.json on a path ESM can resolve. */
3
- export const PACKAGE_VERSION = '1.71.0';
3
+ export const PACKAGE_VERSION = '2.0.0';
4
4
  /** The floor a store takes on its first expiring key: the first release with schema
5
5
  * v53, set by hand in that release; scripts/check-expiring-keys-floor.mjs gates it. */
6
6
  export const EXPIRING_KEYS_MIN_BINARY = '1.64.0';
@@ -2,7 +2,7 @@
2
2
  "id": "hippo-memory",
3
3
  "name": "Hippo Memory",
4
4
  "description": "Make your agent's memory work like a brain. Hippo is long-term memory for coding agents.",
5
- "version": "1.71.0",
5
+ "version": "2.0.0",
6
6
 
7
7
  "configSchema": {
8
8
  "type": "object",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "hippo-memory",
3
- "version": "1.71.0",
3
+ "version": "2.0.0",
4
4
  "type": "module",
5
5
  "description": "Make your agent's memory work like a brain. Hippo is long-term memory for coding agents.",
6
6
  "main": "index.ts",
@@ -2,7 +2,7 @@
2
2
  "id": "hippo-memory",
3
3
  "name": "Hippo Memory",
4
4
  "description": "Make your agent's memory work like a brain. Hippo is long-term memory for coding agents.",
5
- "version": "1.71.0",
5
+ "version": "2.0.0",
6
6
  "configSchema": {
7
7
  "type": "object",
8
8
  "additionalProperties": false,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "hippo-memory",
3
- "version": "1.71.0",
3
+ "version": "2.0.0",
4
4
  "description": "Make your agent's memory work like a brain. Hippo is long-term memory for coding agents.",
5
5
  "mcpName": "io.github.kitfunso/hippo-memory",
6
6
  "type": "module",
@@ -8,6 +8,8 @@
8
8
  "exports": {
9
9
  ".": "./dist/index.js",
10
10
  "./server": "./dist/server.js",
11
+ "./store-kit": "./dist/entry/store-kit.js",
12
+ "./testing": "./dist/entry/testing.js",
11
13
  "./project-identity": "./dist/entry/project-identity.js",
12
14
  "./json-hooks": "./dist/entry/json-hooks.js",
13
15
  "./session-text": "./dist/entry/session-text.js"
@@ -39,7 +41,7 @@
39
41
  "test": "vitest run",
40
42
  "test:watch": "vitest",
41
43
  "test:coverage": "vitest run --coverage",
42
- "test:delivery-ledger": "vitest run tests/delivery-ledger",
44
+ "test:delivery-ledger": "vitest run tests/delivery-ledger tests/migration-v55",
43
45
  "test:eval": "vitest run --config vitest.eval.config.ts",
44
46
  "lint": "oxlint",
45
47
  "sbom": "node scripts/sbom.mjs",
@@ -1,16 +0,0 @@
1
- import type { HippoStore, StoreGroups } from '../store/port.js';
2
- import { type SqliteLocal } from '../store/sqlite/local.js';
3
- import { type SqliteSyncStore } from '../store/sqlite/store.js';
4
- import type { Context, StoreReply } from './types.js';
5
- /** What a port call answers: a Promise from a served store, the value itself from hippo.db. */
6
- export type Reply<T> = T | Promise<T>;
7
- /** The port one body is written against: a served store, or hippo.db answering the same methods at once. */
8
- export type StorePort = HippoStore | SqliteSyncStore;
9
- /** `next` on the reply's value, at once for a value, so hippo.db's path never becomes a Promise. */
10
- export declare function andThen<T, U>(reply: Reply<T>, next: (value: T) => Reply<U>): Reply<U>;
11
- /** Stands in for a group the store lacks, as `port.keyAudit ?? notPorted(port, 'keyAudit')`; it answers 501 as any unported path does. */
12
- export declare function notPorted(port: StorePort, group: keyof StoreGroups): never;
13
- /** Runs `run` on `ctx.store`, where a throw rejects, else on hippo.db under `ctx.hippoRoot`, where it throws. The store path never reads `hippoRoot`.
14
- * `local` runs what needs hippo.db's own handle or meta table; a served store refuses it, or does without where the write allows. */
15
- export declare function onStore<C extends Context, R>(ctx: C, run: (port: StorePort, local: SqliteLocal) => Reply<R>): StoreReply<C, R>;
16
- //# sourceMappingURL=on-store.d.ts.map