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
@@ -82,13 +82,6 @@ interface ModelTagged {
82
82
  }
83
83
  /** Claude Code writes its own API errors and limit notices as assistant lines from this model; no model call made them. */
84
84
  export declare function isSyntheticMessage(message: ModelTagged): boolean;
85
- /** A hook payload's non-empty `session_id`, or null; with `requiredSource`, also null when its `source` differs. */
86
- export declare function hookPayloadSessionId(stdinText: string | undefined, requiredSource?: string | null): string | null;
87
- /** A hook payload's string `field` as sent, or null when the payload or the field is missing or not a string. */
88
- export declare function hookPayloadString(stdinText: string | undefined, field: string): string | null;
89
- /** Whether a hook fired inside a sub-agent, the only payload with `agent_id` (https://code.claude.com/docs/en/hooks#common-input-fields).
90
- * Its `session_id` is the parent's, so a sub-agent's blocks and compactions must not count as the parent's. */
91
- export declare function isSubagentPayload(stdinText: string | undefined): boolean;
92
85
  /** Tokens hippo sent and skipped in one session, for {@link tokensBySession}. */
93
86
  export interface SessionTokens {
94
87
  sessionId: string;
@@ -90,41 +90,6 @@ export function summarizeTokenUse(db, tenantId, sinceIso) {
90
90
  export function isSyntheticMessage(message) {
91
91
  return message.model === '<synthetic>';
92
92
  }
93
- /** A Claude Code hook payload on stdin as a JSON object; null when empty, malformed or not an object. */
94
- function parseHookPayload(stdinText) {
95
- if (!stdinText || stdinText.trim() === '')
96
- return null;
97
- try {
98
- // SAFETY: JSON.parse returns a JSON value by definition.
99
- const payload = JSON.parse(stdinText.trim());
100
- return isJsonObjectLiteral(payload) ? payload : null;
101
- }
102
- catch {
103
- // Malformed is one of the null cases the docblock names.
104
- return null;
105
- }
106
- }
107
- /** A hook payload's non-empty `session_id`, or null; with `requiredSource`, also null when its `source` differs. */
108
- export function hookPayloadSessionId(stdinText, requiredSource = null) {
109
- const payload = parseHookPayload(stdinText);
110
- const sessionId = payload?.session_id;
111
- if (!payload || !isJsonString(sessionId) || sessionId.trim() === '')
112
- return null;
113
- if (requiredSource !== null && payload.source !== requiredSource)
114
- return null;
115
- return sessionId;
116
- }
117
- /** A hook payload's string `field` as sent, or null when the payload or the field is missing or not a string. */
118
- export function hookPayloadString(stdinText, field) {
119
- const value = parseHookPayload(stdinText)?.[field];
120
- return isJsonString(value) ? value : null;
121
- }
122
- /** Whether a hook fired inside a sub-agent, the only payload with `agent_id` (https://code.claude.com/docs/en/hooks#common-input-fields).
123
- * Its `session_id` is the parent's, so a sub-agent's blocks and compactions must not count as the parent's. */
124
- export function isSubagentPayload(stdinText) {
125
- const agentId = parseHookPayload(stdinText)?.agent_id;
126
- return isJsonString(agentId) && agentId.trim() !== '';
127
- }
128
93
  /** Ledger totals per session id since `sinceIso`, across surfaces; hook rows carry the host's session id (the transcript file name), so they join to its
129
94
  * usage records. */
130
95
  export function tokensBySession(db, tenantId, sinceIso) {
@@ -1,11 +1,15 @@
1
1
  // Owns hippo.db's stored vectors, the identity of the model that built them, and the particle rows: every read and write of the three.
2
2
  import { getMeta, setMeta, withWriteScope } from '../db/index.js';
3
3
  import { onHandle } from './open.js';
4
- import { DEFAULT_EMBEDDING_MODEL } from './embeddings/local.js';
5
- import { float32ToBuffer, initializeParticle, loadPhysicsState, resetAllPhysicsState, savePhysicsState } from '../db/physics-state.js';
4
+ import { DEFAULT_EMBEDDING_MODEL } from '../embeddings/local.js';
5
+ import { loadPhysicsState, resetAllPhysicsState, savePhysicsState } from '../db/physics-state.js';
6
+ import { initializeParticle } from '../core/physics.js';
7
+ import { float32ToBuffer } from '../util/vector-codec.js';
6
8
  import { EMBEDDING_MODEL_META_KEY, deleteOrphanVectors, hasStoredVectors, loadVectors, loadVectorViews, replaceAllVectors, storedVectorDims, storedVectorIds, upsertVectors, } from '../db/vector-store.js';
7
- import { chunked, selectEntriesByIds } from './entry-reads.js';
9
+ import { selectEntriesByIds } from './entry-reads.js';
10
+ import { chunked } from '../util/chunked.js';
8
11
  import { MEMORY_SELECT_COLUMNS, rowToEntry } from './rows.js';
12
+ import { placeholders } from '../util/sql.js';
9
13
  const MAX_BACKFILL_PAGE = 500;
10
14
  /** The model the index was built by: the stored identity, else the default model when vectors exist. */
11
15
  export function indexedModel(state) {
@@ -97,7 +101,7 @@ function ownedIds(db, ids, tenantId) {
97
101
  const owned = new Set();
98
102
  for (const chunk of chunked([...new Set(ids)])) {
99
103
  // SAFETY: the SELECT names one column, id.
100
- const rows = db.prepare(`SELECT id FROM memories WHERE +tenant_id = ? AND id IN (${chunk.map(() => '?').join(', ')})`).all(tenantId, ...chunk);
104
+ const rows = db.prepare(`SELECT id FROM memories WHERE +tenant_id = ? AND id IN (${placeholders(chunk.length)})`).all(tenantId, ...chunk);
101
105
  for (const row of rows)
102
106
  owned.add(row.id);
103
107
  }
@@ -5,10 +5,9 @@ import * as fs from 'fs';
5
5
  import * as os from 'os';
6
6
  import * as path from 'path';
7
7
  import { pathToFileURL } from 'url';
8
- import { findHippoStoreDir, isGlobalStoreRoot } from './core/project-identity.js';
8
+ import { findHippoStoreDir, isGlobalStoreRoot, isInitialized } from './core/project-identity.js';
9
9
  import { realpathOrResolve } from './util/real-path.js';
10
10
  import { getGlobalRoot } from './sharing/global-store.js';
11
- import { isInitialized } from './store/open.js';
12
11
  import { readStoreInventory } from './store/diagnostics.js';
13
12
  import { runDoctor } from './doctor.js';
14
13
  import { loadConfig } from './core/config.js';
@@ -21,7 +20,7 @@ export const TAIL_MAX_LINES = 200;
21
20
  const TAIL_MAX_LINE_CHARS = 2000;
22
21
  // Greedy on purpose: complete key blocks are redacted first, so any END left is an orphan and what precedes it may be key body.
23
22
  const ORPHAN_KEY_END_RE = /^[\s\S]*-----END [A-Z ]*PRIVATE KEY-----/;
24
- // The other env vars hippo reads outside the HIPPO_ prefix (src/store/embeddings/provider.ts, connectors/*).
23
+ // The other env vars hippo reads outside the HIPPO_ prefix (src/embeddings/provider.ts, connectors/*).
25
24
  const OTHER_ENV_NAMES = [
26
25
  'ANTHROPIC_API_KEY', 'OPENAI_API_KEY', 'VOYAGE_API_KEY', 'COHERE_API_KEY', 'TYPESAFE_API_KEY',
27
26
  'GITHUB_TOKEN', 'GITHUB_WEBHOOK_SECRET', 'GITHUB_WEBHOOK_SECRET_PREVIOUS',
@@ -1,8 +1,8 @@
1
1
  // The reject, unreject and list flow the CLI verbs and the api functions share: the rules and their wording live here,
2
2
  // and src/store/rejected-values.ts runs each one on a single handle.
3
3
  import { BadRequestError } from '../core/api-errors.js';
4
- import { isPersonalScope } from '../store/recall-scope.js';
5
- import { mergedSuccessor } from '../consolidate/merged-row.js';
4
+ import { isPersonalScope } from '../core/recall-scope.js';
5
+ import { mergedSuccessor } from '../core/merged-row.js';
6
6
  import { normalizeValueForRejection } from '../store/rejection.js';
7
7
  import { applyRejection, liftRejection, loadRejectedValues, } from '../store/rejected-values.js';
8
8
  function assertRejectOpts(opts) {
@@ -0,0 +1,15 @@
1
+ type Env = Readonly<Record<string, string | undefined>>;
2
+ export declare function homeDir(): string;
3
+ /** Codex's config folder: $CODEX_HOME, else ~/.codex, as the Codex hooks docs describe. */
4
+ export declare function codexHomeDir(home?: string, env?: Env): string;
5
+ /** Claude Code's config folder, where it reads settings.json: $CLAUDE_CONFIG_DIR when set and non-empty, else
6
+ * ~/.claude under os.homedir(), as Claude Code does (a HOME that differs from the profile must not move it). */
7
+ export declare function claudeConfigDir(home?: string, env?: Env): string;
8
+ /** VS Code's user-data resolution: portable install first, then the app-data override, then the platform default. */
9
+ export declare function vscodeDataFolders(ctx: {
10
+ readonly env: Env;
11
+ readonly home: string;
12
+ readonly platform: NodeJS.Platform;
13
+ }): string[];
14
+ export {};
15
+ //# sourceMappingURL=agent-homes.d.ts.map
@@ -0,0 +1,34 @@
1
+ // Where the agent tools keep their config and data, shared by the hook installers and the agent-memory readers.
2
+ import * as os from 'os';
3
+ import * as path from 'path';
4
+ import { envHomeDir, processEnv } from './env.js';
5
+ const VSCODE_PRODUCTS = ['Code', 'Code - Insiders'];
6
+ export function homeDir() {
7
+ return envHomeDir() || os.homedir();
8
+ }
9
+ /** Codex's config folder: $CODEX_HOME, else ~/.codex, as the Codex hooks docs describe. */
10
+ export function codexHomeDir(home = homeDir(), env = processEnv()) {
11
+ return env.CODEX_HOME || path.join(home, '.codex');
12
+ }
13
+ /** Claude Code's config folder, where it reads settings.json: $CLAUDE_CONFIG_DIR when set and non-empty, else
14
+ * ~/.claude under os.homedir(), as Claude Code does (a HOME that differs from the profile must not move it). */
15
+ export function claudeConfigDir(home = os.homedir(), env = processEnv()) {
16
+ return env.CLAUDE_CONFIG_DIR || path.join(home, '.claude');
17
+ }
18
+ /** VS Code's user-data resolution: portable install first, then the app-data override, then the platform default. */
19
+ export function vscodeDataFolders(ctx) {
20
+ const { env, home, platform } = ctx;
21
+ if (env.VSCODE_PORTABLE)
22
+ return [path.join(env.VSCODE_PORTABLE, 'user-data')];
23
+ let appData;
24
+ if (env.VSCODE_APPDATA)
25
+ appData = env.VSCODE_APPDATA;
26
+ else if (platform === 'win32')
27
+ appData = env.APPDATA || path.join(home, 'AppData', 'Roaming');
28
+ else if (platform === 'darwin')
29
+ appData = path.join(home, 'Library', 'Application Support');
30
+ else
31
+ appData = env.XDG_CONFIG_HOME || path.join(home, '.config');
32
+ return VSCODE_PRODUCTS.map((product) => path.join(appData, product));
33
+ }
34
+ //# sourceMappingURL=agent-homes.js.map
@@ -13,9 +13,12 @@ export type AnthropicMessageFailure = {
13
13
  } | {
14
14
  kind: 'http';
15
15
  status: number;
16
+ detail: string;
16
17
  } | {
17
18
  kind: 'unreadable';
18
19
  message: string;
20
+ } | {
21
+ kind: 'empty';
19
22
  };
20
23
  export type AnthropicMessageResult = {
21
24
  ok: true;
@@ -24,7 +27,9 @@ export type AnthropicMessageResult = {
24
27
  ok: false;
25
28
  failure: AnthropicMessageFailure;
26
29
  };
27
- /** The reply's first text block, trimmed (empty when the reply has none); never throws. */
30
+ /** True for a failure the next call would repeat, so a caller looping over items should stop rather than retry. */
31
+ export declare function isPermanentFailure(failure: AnthropicMessageFailure): boolean;
32
+ /** The reply's first text block, trimmed; a reply with no text is a failure of kind 'empty'. Never throws. */
28
33
  export declare function sendAnthropicMessage(req: AnthropicMessageRequest): Promise<AnthropicMessageResult>;
29
34
  /** The text extraction and DAG summaries hand to their `onError` callback. */
30
35
  export declare function describeMessageFailure(failure: AnthropicMessageFailure): string;
@@ -1,20 +1,37 @@
1
1
  /** The one Anthropic Messages client: sends one user prompt and returns the reply text or a typed failure the caller reacts to. */
2
- import { fetchWithRetry, llmTimeoutMs } from './http-retry.js';
2
+ import { fetchWithRetry, llmTimeoutMs, llmTotalMs } from './http-retry.js';
3
3
  import { errorMessage } from './log.js';
4
- import { readCappedJson } from './capped-json.js';
4
+ import { readCappedJson, readCappedText } from './capped-json.js';
5
5
  import { isJsonObject, isJsonString } from './json.js';
6
+ import { redactSecretsStrict } from './secret-detect.js';
6
7
  const MESSAGES_URL = 'https://api.anthropic.com/v1/messages';
7
8
  const API_VERSION = '2023-06-01';
8
9
  const DEFAULT_MODEL = 'claude-sonnet-4-6';
9
10
  // Callers ask for at most 1,200 tokens, a reply of a few KB; 1 MiB leaves room for a verbose envelope.
10
11
  const MAX_REPLY_BYTES = 1024 * 1024;
12
+ // The error body names the cause (bad key, no credit, unknown model) in its first line or two.
13
+ const ERROR_SNIPPET_CHARS = 256;
14
+ const UTF8_MAX_BYTES_PER_CHAR = 4;
15
+ // A bad or missing key, no credit, no permission, an unknown model: every later call gets the same answer.
16
+ const PERMANENT_STATUSES = new Set([401, 402, 403, 404]);
11
17
  /** The first content block's text, trimmed; empty when the reply has no such block. */
12
18
  function firstText(reply) {
13
19
  const first = Array.isArray(reply.content) ? reply.content[0] : undefined;
14
20
  const text = isJsonObject(first) ? first.text : undefined;
15
21
  return isJsonString(text) ? text.trim() : '';
16
22
  }
17
- /** The reply's first text block, trimmed (empty when the reply has none); never throws. */
23
+ /** True for a failure the next call would repeat, so a caller looping over items should stop rather than retry. */
24
+ export function isPermanentFailure(failure) {
25
+ return failure.kind === 'http' && PERMANENT_STATUSES.has(failure.status);
26
+ }
27
+ /** The start of a failed reply's body, on one line with any key-shaped text masked; empty when the body cannot be read. */
28
+ async function errorSnippet(res) {
29
+ // The status is the failure reported; a body that cannot be read only costs its snippet.
30
+ const body = await readCappedText(res, ERROR_SNIPPET_CHARS * UTF8_MAX_BYTES_PER_CHAR).catch(() => '');
31
+ // Masked before the cut, so a key that straddles the cut is never left half shown.
32
+ return redactSecretsStrict(body.replace(/\s+/g, ' ').trim()).slice(0, ERROR_SNIPPET_CHARS);
33
+ }
34
+ /** The reply's first text block, trimmed; a reply with no text is a failure of kind 'empty'. Never throws. */
18
35
  export async function sendAnthropicMessage(req) {
19
36
  let res;
20
37
  try {
@@ -30,18 +47,19 @@ export async function sendAnthropicMessage(req) {
30
47
  max_tokens: req.maxTokens,
31
48
  messages: [{ role: 'user', content: req.prompt }],
32
49
  }),
33
- }, { timeoutMs: llmTimeoutMs(), fetchFn: req.fetcher ?? fetch });
50
+ }, { timeoutMs: llmTimeoutMs(), totalMs: llmTotalMs(), fetchFn: req.fetcher ?? fetch });
34
51
  }
35
52
  catch (err) {
36
53
  return { ok: false, failure: { kind: 'request', message: errorMessage(err) } };
37
54
  }
38
55
  if (!res.ok)
39
- return { ok: false, failure: { kind: 'http', status: res.status } };
56
+ return { ok: false, failure: { kind: 'http', status: res.status, detail: await errorSnippet(res) } };
40
57
  try {
41
58
  const data = await readCappedJson(res, MAX_REPLY_BYTES);
42
59
  if (!isJsonObject(data))
43
60
  return { ok: false, failure: { kind: 'unreadable', message: 'the reply is not a JSON object' } };
44
- return { ok: true, text: firstText(data) };
61
+ const text = firstText(data);
62
+ return text === '' ? { ok: false, failure: { kind: 'empty' } } : { ok: true, text };
45
63
  }
46
64
  catch (err) {
47
65
  return { ok: false, failure: { kind: 'unreadable', message: errorMessage(err) } };
@@ -51,8 +69,9 @@ export async function sendAnthropicMessage(req) {
51
69
  export function describeMessageFailure(failure) {
52
70
  switch (failure.kind) {
53
71
  case 'request': return `request failed: ${failure.message}`;
54
- case 'http': return `HTTP ${failure.status}`;
72
+ case 'http': return failure.detail ? `HTTP ${failure.status}: ${failure.detail}` : `HTTP ${failure.status}`;
55
73
  case 'unreadable': return `unparseable response: ${failure.message}`;
74
+ case 'empty': return 'the reply held no text';
56
75
  }
57
76
  }
58
77
  //# sourceMappingURL=anthropic-messages.js.map
@@ -1,4 +1,7 @@
1
1
  /** Replaces `file` through a flushed temp file and a rename, so a reader, or a crash at any point, finds the old content or the new, whole.
2
- * A file with other hard links, or a rename the platform refuses (logged), is written in place: a crash mid-write can leave it truncated. */
3
- export declare function writeFileAtomic(file: string, text: string): void;
2
+ * A file with other hard links, or a rename the platform refuses (logged), is written in place: a crash mid-write can leave it truncated.
3
+ * `durable: false` skips the fsyncs for derived files that can be rebuilt; a reader still never sees a torn file. */
4
+ export declare function writeFileAtomic(file: string, text: string, opts?: {
5
+ readonly durable?: boolean;
6
+ }): void;
4
7
  //# sourceMappingURL=atomic-write.d.ts.map
@@ -53,13 +53,14 @@ function removeTemp(tmp) {
53
53
  }
54
54
  }
55
55
  /** Flushed before the rename, or a crash soon after could leave the file's name on bytes that never reached the disk. */
56
- function writeFlushed(tmp, text, old) {
56
+ function writeFlushed(tmp, text, old, durable) {
57
57
  const fd = fs.openSync(tmp, 'w', (old?.mode ?? 0o666) & 0o777);
58
58
  try {
59
59
  fs.writeFileSync(fd, text, 'utf8');
60
60
  if (old)
61
61
  keepAccess(tmp, old);
62
- fs.fsyncSync(fd);
62
+ if (durable)
63
+ fs.fsyncSync(fd);
63
64
  }
64
65
  finally {
65
66
  fs.closeSync(fd);
@@ -82,17 +83,18 @@ function flushFolder(dir) {
82
83
  log.warn(`could not flush the folder ${dir} to disk after replacing a file in it: ${errorMessage(err)}`);
83
84
  }
84
85
  }
85
- function replaceViaTemp(target, text, old) {
86
+ function replaceViaTemp(target, text, old, durable) {
86
87
  const tmp = `${target}.${process.pid}.tmp`;
87
88
  try {
88
- writeFlushed(tmp, text, old);
89
+ writeFlushed(tmp, text, old, durable);
89
90
  renameOnto(tmp, target);
90
91
  }
91
92
  catch (err) {
92
93
  removeTemp(tmp);
93
94
  throw err;
94
95
  }
95
- flushFolder(path.dirname(target));
96
+ if (durable)
97
+ flushFolder(path.dirname(target));
96
98
  }
97
99
  /** The pre-rename write: it truncates first, so it is only the fallback, but it needs just a writable file and keeps hard links together. */
98
100
  function writeInPlace(target, text) {
@@ -109,8 +111,10 @@ function writeInPlace(target, text) {
109
111
  }
110
112
  }
111
113
  /** Replaces `file` through a flushed temp file and a rename, so a reader, or a crash at any point, finds the old content or the new, whole.
112
- * A file with other hard links, or a rename the platform refuses (logged), is written in place: a crash mid-write can leave it truncated. */
113
- export function writeFileAtomic(file, text) {
114
+ * A file with other hard links, or a rename the platform refuses (logged), is written in place: a crash mid-write can leave it truncated.
115
+ * `durable: false` skips the fsyncs for derived files that can be rebuilt; a reader still never sees a torn file. */
116
+ export function writeFileAtomic(file, text, opts = {}) {
117
+ const durable = opts.durable !== false;
114
118
  const target = writeTarget(file);
115
119
  const old = fs.statSync(target, { throwIfNoEntry: false });
116
120
  if (old === undefined) {
@@ -126,7 +130,7 @@ export function writeFileAtomic(file, text) {
126
130
  return;
127
131
  }
128
132
  try {
129
- replaceViaTemp(target, text, old);
133
+ replaceViaTemp(target, text, old, durable);
130
134
  }
131
135
  catch (err) {
132
136
  if (!(err instanceof Error) || !REPLACE_REFUSALS.includes(errnoCode(err)))
@@ -0,0 +1,3 @@
1
+ /** `items` in consecutive slices of at most `size`. */
2
+ export declare function chunked<T>(items: readonly T[], size?: number): T[][];
3
+ //# sourceMappingURL=chunked.d.ts.map
@@ -0,0 +1,10 @@
1
+ /** Ids per `IN (...)` list: far under SQLite's bound-parameter limit, with room for the tenant filter. */
2
+ const ID_CHUNK = 500;
3
+ /** `items` in consecutive slices of at most `size`. */
4
+ export function chunked(items, size = ID_CHUNK) {
5
+ const out = [];
6
+ for (let i = 0; i < items.length; i += size)
7
+ out.push(items.slice(i, i + size));
8
+ return out;
9
+ }
10
+ //# sourceMappingURL=chunked.js.map
@@ -0,0 +1,3 @@
1
+ /** `text` cut to `max` characters plus a marker, or unchanged when it already fits. */
2
+ export declare function truncateWithEllipsis(text: string, max: number, marker?: string): string;
3
+ //# sourceMappingURL=ellipsize.d.ts.map
@@ -0,0 +1,5 @@
1
+ /** `text` cut to `max` characters plus a marker, or unchanged when it already fits. */
2
+ export function truncateWithEllipsis(text, max, marker = '...') {
3
+ return text.length > max ? `${text.slice(0, max)}${marker}` : text;
4
+ }
5
+ //# sourceMappingURL=ellipsize.js.map
@@ -22,6 +22,8 @@ export declare function envHippoHome(): string | undefined;
22
22
  export declare function envXdgDataHome(): string | undefined;
23
23
  export declare function envHomeDir(): string | undefined;
24
24
  export declare function envPath(): string | undefined;
25
+ /** The extensions win32 tries on a bare command name, in order. */
26
+ export declare function envPathExt(): string | undefined;
25
27
  export declare function envModelCache(): string | undefined;
26
28
  export declare function envHippoSessionId(): string | undefined;
27
29
  export declare function envClaudeCodeSessionId(): string | undefined;
@@ -34,6 +36,7 @@ export declare const DEFAULT_TENANT_ID = "default";
34
36
  export declare function envTenant(): string;
35
37
  export declare function envSkipAutoIntegrations(): boolean;
36
38
  export declare function envSkipPostinstall(): boolean;
39
+ export declare function envSkipSchedule(): boolean;
37
40
  export declare function envMcpStdio(): boolean;
38
41
  /** `1` or `true`, so `0` and `false` turn it off; `true` stays on for anyone who set it that way. */
39
42
  export declare function envRequireServer(): boolean;
@@ -46,15 +49,21 @@ export declare function envPort(): string | undefined;
46
49
  /** How long a client waits for a running server's /health before writing to the store directly; server-detect.ts holds the default. */
47
50
  export declare function envHealthProbeMs(): number | undefined;
48
51
  export declare function envRequireAuth(): boolean;
49
- /** `1` lets a request made on this machine in with no key, as host admin; HIPPO_REQUIRE_AUTH=1 wins over it. */
52
+ /** `1` lets a request made on this machine in with no key; HIPPO_REQUIRE_AUTH=1 wins over it. */
50
53
  export declare function envAllowKeylessLocal(): boolean;
54
+ /** The role a keyless local request gets: `admin` (host admin) only when asked for by name, else `member`. */
55
+ export declare function envKeylessLocalRole(): 'admin' | 'member';
56
+ /** `1` lets a non-loopback bind start without TLS, for TLS that ends at a proxy in front. */
57
+ export declare function envAllowCleartext(): boolean;
51
58
  export declare function envV1Rps(): string | undefined;
59
+ /** Requests per second each authenticated caller may make; `0` turns the per-caller limit off. */
60
+ export declare function envCallerRps(): string | undefined;
52
61
  /** How long a request body may take to arrive; http-util.ts holds the default. */
53
62
  export declare function envBodyTimeoutMs(): number | undefined;
54
63
  /** How long POST /v1/sleep lets its consolidation run; server/sleep-offload.ts holds the default. */
55
64
  export declare function envSleepTimeoutMs(): number | undefined;
56
65
  /** How long a /v1 or /mcp request may run before the server answers 504, and a stdio MCP
57
- * request before its timeout error; 0 for no deadline; server/deadline.ts holds the default. */
66
+ * request before its timeout error; 0 for no deadline; util/request-scope.ts holds the default. */
58
67
  export declare function envRequestDeadlineMs(): number | undefined;
59
68
  /** How many store calls may wait for one worker thread before the next is refused; store/sqlite/executor.ts holds the default. */
60
69
  export declare function envStoreQueueMax(): number | undefined;
@@ -62,6 +71,7 @@ export declare function envStoreQueueMax(): number | undefined;
62
71
  export declare function envDailyStepTimeoutMs(): number | undefined;
63
72
  export declare function envApiKey(): string | undefined;
64
73
  export declare function envClientIpHeader(): string | undefined;
74
+ /** The peers whose HIPPO_CLIENT_IP_HEADER is believed: IPs or CIDRs, or `*` for any peer. */
65
75
  export declare function envTrustedProxies(): string | undefined;
66
76
  /** Paths to the PEM certificate and key `hippo serve` answers HTTPS with; the --tls-cert and --tls-key flags win. */
67
77
  export declare function envTlsCert(): string | undefined;
package/dist/util/env.js CHANGED
@@ -64,6 +64,8 @@ export function envHippoHome() { return raw('HIPPO_HOME')?.trim(); }
64
64
  export function envXdgDataHome() { return raw('XDG_DATA_HOME')?.trim(); }
65
65
  export function envHomeDir() { return raw('HOME') || raw('USERPROFILE'); }
66
66
  export function envPath() { return raw('PATH'); }
67
+ /** The extensions win32 tries on a bare command name, in order. */
68
+ export function envPathExt() { return raw('PATHEXT'); }
67
69
  export function envModelCache() { return trimmed('HIPPO_MODEL_CACHE'); }
68
70
  // Session, scope and tenant.
69
71
  export function envHippoSessionId() { return trimmed('HIPPO_SESSION_ID'); }
@@ -80,6 +82,7 @@ export function envTenant() {
80
82
  // Install and CLI switches.
81
83
  export function envSkipAutoIntegrations() { return isOne('HIPPO_SKIP_AUTO_INTEGRATIONS'); }
82
84
  export function envSkipPostinstall() { return isOne('HIPPO_SKIP_POSTINSTALL'); }
85
+ export function envSkipSchedule() { return isOne('HIPPO_SKIP_SCHEDULE'); }
83
86
  export function envMcpStdio() { return isOne('HIPPO_MCP_STDIO'); }
84
87
  /** `1` or `true`, so `0` and `false` turn it off; `true` stays on for anyone who set it that way. */
85
88
  export function envRequireServer() { return isOneOrTrue('HIPPO_REQUIRE_SERVER'); }
@@ -93,15 +96,21 @@ export function envPort() { return raw('HIPPO_PORT'); }
93
96
  /** How long a client waits for a running server's /health before writing to the store directly; server-detect.ts holds the default. */
94
97
  export function envHealthProbeMs() { return positiveInt('HIPPO_HEALTH_PROBE_MS'); }
95
98
  export function envRequireAuth() { return isOne('HIPPO_REQUIRE_AUTH'); }
96
- /** `1` lets a request made on this machine in with no key, as host admin; HIPPO_REQUIRE_AUTH=1 wins over it. */
99
+ /** `1` lets a request made on this machine in with no key; HIPPO_REQUIRE_AUTH=1 wins over it. */
97
100
  export function envAllowKeylessLocal() { return isOne('HIPPO_ALLOW_KEYLESS_LOCAL'); }
101
+ /** The role a keyless local request gets: `admin` (host admin) only when asked for by name, else `member`. */
102
+ export function envKeylessLocalRole() { return trimmed('HIPPO_KEYLESS_LOCAL_ROLE')?.toLowerCase() === 'admin' ? 'admin' : 'member'; }
103
+ /** `1` lets a non-loopback bind start without TLS, for TLS that ends at a proxy in front. */
104
+ export function envAllowCleartext() { return isOne('HIPPO_ALLOW_CLEARTEXT'); }
98
105
  export function envV1Rps() { return raw('HIPPO_V1_RPS'); }
106
+ /** Requests per second each authenticated caller may make; `0` turns the per-caller limit off. */
107
+ export function envCallerRps() { return trimmed('HIPPO_CALLER_RPS'); }
99
108
  /** How long a request body may take to arrive; http-util.ts holds the default. */
100
109
  export function envBodyTimeoutMs() { return positiveInt('HIPPO_BODY_TIMEOUT_MS'); }
101
110
  /** How long POST /v1/sleep lets its consolidation run; server/sleep-offload.ts holds the default. */
102
111
  export function envSleepTimeoutMs() { return positiveInt('HIPPO_SLEEP_TIMEOUT_MS'); }
103
112
  /** How long a /v1 or /mcp request may run before the server answers 504, and a stdio MCP
104
- * request before its timeout error; 0 for no deadline; server/deadline.ts holds the default. */
113
+ * request before its timeout error; 0 for no deadline; util/request-scope.ts holds the default. */
105
114
  export function envRequestDeadlineMs() { return nonNegativeInt('HIPPO_REQUEST_DEADLINE_MS'); }
106
115
  /** How many store calls may wait for one worker thread before the next is refused; store/sqlite/executor.ts holds the default. */
107
116
  export function envStoreQueueMax() { return positiveInt('HIPPO_STORE_QUEUE_MAX'); }
@@ -109,6 +118,7 @@ export function envStoreQueueMax() { return positiveInt('HIPPO_STORE_QUEUE_MAX')
109
118
  export function envDailyStepTimeoutMs() { return positiveInt('HIPPO_DAILY_STEP_TIMEOUT_MS'); }
110
119
  export function envApiKey() { return raw('HIPPO_API_KEY'); }
111
120
  export function envClientIpHeader() { return raw('HIPPO_CLIENT_IP_HEADER')?.trim().toLowerCase(); }
121
+ /** The peers whose HIPPO_CLIENT_IP_HEADER is believed: IPs or CIDRs, or `*` for any peer. */
112
122
  export function envTrustedProxies() { return raw('HIPPO_TRUSTED_PROXIES'); }
113
123
  /** Paths to the PEM certificate and key `hippo serve` answers HTTPS with; the --tls-cert and --tls-key flags win. */
114
124
  export function envTlsCert() { return trimmed('HIPPO_TLS_CERT'); }
@@ -0,0 +1,5 @@
1
+ /** A 0..1 fraction as a percentage with one decimal, e.g. 0.256 -> "25.6%". */
2
+ export declare function pct(fraction: number): string;
3
+ /** Rounds to one decimal place. */
4
+ export declare function round1(value: number): number;
5
+ //# sourceMappingURL=format.d.ts.map
@@ -0,0 +1,10 @@
1
+ // Number-to-text helpers shared by report and eval output.
2
+ /** A 0..1 fraction as a percentage with one decimal, e.g. 0.256 -> "25.6%". */
3
+ export function pct(fraction) {
4
+ return (fraction * 100).toFixed(1) + '%';
5
+ }
6
+ /** Rounds to one decimal place. */
7
+ export function round1(value) {
8
+ return Math.round(value * 10) / 10;
9
+ }
10
+ //# sourceMappingURL=format.js.map
@@ -0,0 +1,8 @@
1
+ /** A hook payload's non-empty `session_id`, or null; with `requiredSource`, also null when its `source` differs. */
2
+ export declare function hookPayloadSessionId(stdinText: string | undefined, requiredSource?: string | null): string | null;
3
+ /** A hook payload's string `field` as sent, or null when the payload or the field is missing or not a string. */
4
+ export declare function hookPayloadString(stdinText: string | undefined, field: string): string | null;
5
+ /** Whether a hook fired inside a sub-agent, the only payload with `agent_id` (https://code.claude.com/docs/en/hooks#common-input-fields).
6
+ * Its `session_id` is the parent's, so a sub-agent's blocks and compactions must not count as the parent's. */
7
+ export declare function isSubagentPayload(stdinText: string | undefined): boolean;
8
+ //# sourceMappingURL=hook-payload.d.ts.map
@@ -0,0 +1,37 @@
1
+ import { isJsonObjectLiteral, isJsonString } from './json.js';
2
+ /** A Claude Code hook payload on stdin as a JSON object; null when empty, malformed or not an object. */
3
+ function parseHookPayload(stdinText) {
4
+ if (!stdinText || stdinText.trim() === '')
5
+ return null;
6
+ try {
7
+ // SAFETY: JSON.parse returns a JSON value by definition.
8
+ const payload = JSON.parse(stdinText.trim());
9
+ return isJsonObjectLiteral(payload) ? payload : null;
10
+ }
11
+ catch {
12
+ // Malformed is one of the null cases the docblock names.
13
+ return null;
14
+ }
15
+ }
16
+ /** A hook payload's non-empty `session_id`, or null; with `requiredSource`, also null when its `source` differs. */
17
+ export function hookPayloadSessionId(stdinText, requiredSource = null) {
18
+ const payload = parseHookPayload(stdinText);
19
+ const sessionId = payload?.session_id;
20
+ if (!payload || !isJsonString(sessionId) || sessionId.trim() === '')
21
+ return null;
22
+ if (requiredSource !== null && payload.source !== requiredSource)
23
+ return null;
24
+ return sessionId;
25
+ }
26
+ /** A hook payload's string `field` as sent, or null when the payload or the field is missing or not a string. */
27
+ export function hookPayloadString(stdinText, field) {
28
+ const value = parseHookPayload(stdinText)?.[field];
29
+ return isJsonString(value) ? value : null;
30
+ }
31
+ /** Whether a hook fired inside a sub-agent, the only payload with `agent_id` (https://code.claude.com/docs/en/hooks#common-input-fields).
32
+ * Its `session_id` is the parent's, so a sub-agent's blocks and compactions must not count as the parent's. */
33
+ export function isSubagentPayload(stdinText) {
34
+ const agentId = parseHookPayload(stdinText)?.agent_id;
35
+ return isJsonString(agentId) && agentId.trim() !== '';
36
+ }
37
+ //# sourceMappingURL=hook-payload.js.map
@@ -4,6 +4,8 @@ export interface RetryPolicy {
4
4
  timeoutMs: number;
5
5
  /** Total attempts including the first. */
6
6
  attempts?: number;
7
+ /** Limit on the whole call, waits included: an attempt is cut short at it and no retry starts whose wait would reach it. */
8
+ totalMs?: number;
7
9
  baseDelayMs?: number;
8
10
  /** A Retry-After longer than this hands the response back, so a caller with its own long pause keeps it. */
9
11
  maxDelayMs?: number;
@@ -15,9 +17,13 @@ export interface RetryPolicy {
15
17
  /** Replaces the timer between attempts. A caller `signal` that aborts still ends the wait at once. */
16
18
  sleep?: (ms: number) => Promise<void>;
17
19
  random?: () => number;
20
+ /** Replaces the clock `totalMs` is measured on. */
21
+ now?: () => number;
18
22
  }
19
23
  /** LLM calls (consolidation refine, DAG summaries, fact extraction) share one budget; `HIPPO_LLM_TIMEOUT_MS` overrides it. */
20
24
  export declare function llmTimeoutMs(): number;
25
+ /** 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. */
26
+ export declare function llmTotalMs(): number;
21
27
  export declare function isRetryableStatus(status: number): boolean;
22
28
  /** Retry-After as milliseconds: delta-seconds or an HTTP date; null when absent or unreadable. */
23
29
  export declare function parseRetryAfterMs(header: string | null, now?: number): number | null;