hippo-memory 2.0.0 → 2.1.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 (965) hide show
  1. package/dist/agent-memories/apply.d.ts +7 -5
  2. package/dist/agent-memories/apply.js +66 -39
  3. package/dist/agent-memories/claude-code.d.ts +8 -2
  4. package/dist/agent-memories/claude-code.js +26 -7
  5. package/dist/agent-memories/copilot.js +2 -1
  6. package/dist/agent-memories/files.js +2 -1
  7. package/dist/agent-memories/legacy.d.ts +6 -3
  8. package/dist/agent-memories/legacy.js +35 -14
  9. package/dist/agent-memories/markdown.d.ts +3 -1
  10. package/dist/agent-memories/markdown.js +3 -1
  11. package/dist/agent-memories/openclaw.js +5 -2
  12. package/dist/agent-memories/plan.js +11 -1
  13. package/dist/agent-memories/project-folds.js +2 -1
  14. package/dist/agent-memories/report.d.ts +4 -1
  15. package/dist/agent-memories/report.js +43 -9
  16. package/dist/agent-memories/source.d.ts +8 -2
  17. package/dist/agent-memories/source.js +11 -3
  18. package/dist/agent-memories/sync.d.ts +7 -2
  19. package/dist/agent-memories/sync.js +141 -101
  20. package/dist/api/assemble.d.ts +6 -4
  21. package/dist/api/assemble.js +11 -6
  22. package/dist/api/{audit.d.ts → auth/audit.d.ts} +18 -16
  23. package/dist/api/{audit.js → auth/audit.js} +11 -11
  24. package/dist/api/{auth.d.ts → auth/auth.d.ts} +19 -15
  25. package/dist/api/{auth.js → auth/auth.js} +46 -29
  26. package/dist/api/{quarantine.d.ts → auth/quarantine.d.ts} +8 -7
  27. package/dist/api/{quarantine.js → auth/quarantine.js} +8 -8
  28. package/dist/api/auth/session-owners.d.ts +10 -0
  29. package/dist/api/auth/session-owners.js +35 -0
  30. package/dist/api/availability.d.ts +3 -1
  31. package/dist/api/availability.js +3 -1
  32. package/dist/api/busy.d.ts +2 -0
  33. package/dist/api/busy.js +2 -0
  34. package/dist/api/cli-surface.d.ts +6 -0
  35. package/dist/api/cli-surface.js +6 -0
  36. package/dist/api/config-of.d.ts +5 -0
  37. package/dist/api/config-of.js +6 -0
  38. package/dist/api/context-auto.d.ts +4 -1
  39. package/dist/api/context-auto.js +10 -2
  40. package/dist/api/context-render.js +14 -7
  41. package/dist/api/context-select.d.ts +4 -1
  42. package/dist/api/context-select.js +23 -14
  43. package/dist/api/context-types.d.ts +38 -12
  44. package/dist/api/context.d.ts +8 -5
  45. package/dist/api/context.js +112 -57
  46. package/dist/api/continuity.d.ts +24 -21
  47. package/dist/api/continuity.js +18 -20
  48. package/dist/api/correction-latency.d.ts +3 -1
  49. package/dist/api/correction-latency.js +3 -1
  50. package/dist/api/error-reply.d.ts +4 -1
  51. package/dist/api/error-reply.js +12 -3
  52. package/dist/api/index.d.ts +39 -23
  53. package/dist/api/index.js +21 -23
  54. package/dist/api/instruction-detect.d.ts +4 -1
  55. package/dist/api/instruction-detect.js +75 -20
  56. package/dist/api/ledger-db.d.ts +15 -11
  57. package/dist/api/ledger-db.js +21 -23
  58. package/dist/api/memories/conflicts.d.ts +33 -0
  59. package/dist/api/memories/conflicts.js +67 -0
  60. package/dist/api/{forget.d.ts → memories/forget.d.ts} +11 -9
  61. package/dist/api/{forget.js → memories/forget.js} +22 -15
  62. package/dist/api/memories/memories.d.ts +27 -0
  63. package/dist/api/{memories.js → memories/memories.js} +16 -21
  64. package/dist/api/memories/outcome.d.ts +22 -0
  65. package/dist/api/{outcome.js → memories/outcome.js} +14 -8
  66. package/dist/api/memories/promote.d.ts +40 -0
  67. package/dist/api/{promote.js → memories/promote.js} +35 -22
  68. package/dist/api/memories/refine.d.ts +10 -0
  69. package/dist/api/memories/refine.js +12 -0
  70. package/dist/api/{remember-local.d.ts → memories/remember-local.d.ts} +16 -11
  71. package/dist/api/{remember-local.js → memories/remember-local.js} +34 -20
  72. package/dist/api/{remember.d.ts → memories/remember.d.ts} +19 -13
  73. package/dist/api/{remember.js → memories/remember.js} +42 -26
  74. package/dist/api/objects/cards.d.ts +39 -0
  75. package/dist/api/{cards.js → objects/cards.js} +12 -14
  76. package/dist/api/{drill-down.d.ts → objects/drill-down.d.ts} +12 -10
  77. package/dist/api/{drill-down.js → objects/drill-down.js} +7 -8
  78. package/dist/api/objects/goals.d.ts +18 -0
  79. package/dist/api/{goals.js → objects/goals.js} +12 -12
  80. package/dist/api/objects/graph.d.ts +11 -0
  81. package/dist/api/objects/graph.js +16 -0
  82. package/dist/api/objects/objects.d.ts +9 -0
  83. package/dist/api/{objects.js → objects/objects.js} +2 -4
  84. package/dist/api/objects/predictions.d.ts +11 -0
  85. package/dist/api/{predictions.js → objects/predictions.js} +7 -6
  86. package/dist/api/{projects.d.ts → objects/projects.d.ts} +8 -5
  87. package/dist/api/{projects.js → objects/projects.js} +8 -4
  88. package/dist/api/pilot-arm.d.ts +8 -4
  89. package/dist/api/pilot-arm.js +5 -4
  90. package/dist/api/prompt-hook.d.ts +32 -19
  91. package/dist/api/prompt-hook.js +65 -44
  92. package/dist/api/provenance-coverage.d.ts +3 -1
  93. package/dist/api/provenance-coverage.js +3 -1
  94. package/dist/api/recall/finish.d.ts +185 -0
  95. package/dist/api/recall/finish.js +301 -0
  96. package/dist/api/{recall-pipeline.d.ts → recall/pipeline.d.ts} +12 -8
  97. package/dist/api/{recall-pipeline.js → recall/pipeline.js} +176 -92
  98. package/dist/api/recall/recall.d.ts +6 -0
  99. package/dist/api/{recall.js → recall/recall.js} +101 -60
  100. package/dist/api/recall/render.d.ts +39 -0
  101. package/dist/api/recall/render.js +60 -0
  102. package/dist/api/{recall-request.d.ts → recall/request.d.ts} +7 -5
  103. package/dist/api/recall/request.js +261 -0
  104. package/dist/api/{recall-cli.d.ts → recall/rows.d.ts} +18 -12
  105. package/dist/api/{recall-cli.js → recall/rows.js} +28 -27
  106. package/dist/api/{recall-types.d.ts → recall/types.d.ts} +95 -70
  107. package/dist/api/{recall-types.js → recall/types.js} +1 -1
  108. package/dist/api/session-end.d.ts +16 -12
  109. package/dist/api/session-end.js +46 -30
  110. package/dist/api/{auto-sleep.d.ts → sleep/auto-sleep.d.ts} +9 -5
  111. package/dist/api/{auto-sleep.js → sleep/auto-sleep.js} +7 -12
  112. package/dist/api/sleep/dormant.d.ts +25 -0
  113. package/dist/api/sleep/dormant.js +64 -0
  114. package/dist/api/{learn.d.ts → sleep/learn.d.ts} +5 -4
  115. package/dist/api/sleep/learn.js +138 -0
  116. package/dist/api/sleep/sleep-run.d.ts +38 -0
  117. package/dist/api/{sleep-run.js → sleep/sleep-run.js} +51 -43
  118. package/dist/api/{sleep.d.ts → sleep/sleep.d.ts} +17 -11
  119. package/dist/api/sleep/sleep.js +9 -0
  120. package/dist/api/status.d.ts +3 -1
  121. package/dist/api/status.js +3 -1
  122. package/dist/api/store-init.d.ts +4 -1
  123. package/dist/api/store-init.js +4 -1
  124. package/dist/api/tokens.d.ts +10 -9
  125. package/dist/api/tokens.js +9 -10
  126. package/dist/api/types.d.ts +28 -7
  127. package/dist/api/types.js +13 -4
  128. package/dist/capture/caller-session.d.ts +8 -2
  129. package/dist/capture/caller-session.js +16 -6
  130. package/dist/capture/capture-error.d.ts +3 -1
  131. package/dist/capture/capture-error.js +3 -1
  132. package/dist/capture/codex-patch.js +7 -2
  133. package/dist/capture/command.d.ts +4 -2
  134. package/dist/capture/command.js +33 -14
  135. package/dist/capture/compact-resume-caller.js +15 -8
  136. package/dist/capture/compact.d.ts +8 -5
  137. package/dist/capture/compact.js +34 -23
  138. package/dist/capture/compaction-items-caller.js +9 -3
  139. package/dist/capture/compaction-record.d.ts +4 -3
  140. package/dist/capture/compaction-record.js +20 -12
  141. package/dist/capture/compaction-spool.d.ts +15 -4
  142. package/dist/capture/compaction-spool.js +64 -17
  143. package/dist/capture/copilot-transcript.d.ts +11 -3
  144. package/dist/capture/copilot-transcript.js +16 -6
  145. package/dist/capture/extract.js +20 -8
  146. package/dist/capture/failure-caller.js +23 -12
  147. package/dist/capture/failure-reading.d.ts +10 -3
  148. package/dist/capture/failure-reading.js +24 -7
  149. package/dist/capture/pre-compact-caller.js +11 -4
  150. package/dist/capture/session-digest.d.ts +15 -4
  151. package/dist/capture/session-digest.js +39 -13
  152. package/dist/capture/session-end-caller.d.ts +4 -1
  153. package/dist/capture/session-end-caller.js +20 -8
  154. package/dist/capture/session-texts.d.ts +6 -2
  155. package/dist/capture/session-texts.js +22 -7
  156. package/dist/capture/session-worker.d.ts +4 -2
  157. package/dist/capture/session-worker.js +45 -17
  158. package/dist/capture/transcript.d.ts +13 -4
  159. package/dist/capture/transcript.js +32 -10
  160. package/dist/capture/working-state.d.ts +13 -4
  161. package/dist/capture/working-state.js +50 -56
  162. package/dist/cli/api-context.d.ts +14 -2
  163. package/dist/cli/api-context.js +45 -2
  164. package/dist/cli/audit.js +23 -23
  165. package/dist/cli/auth.js +19 -27
  166. package/dist/cli/briefs.d.ts +1 -1
  167. package/dist/cli/briefs.js +20 -15
  168. package/dist/cli/card.d.ts +1 -1
  169. package/dist/cli/card.js +56 -73
  170. package/dist/cli/client.d.ts +12 -4
  171. package/dist/cli/client.js +43 -13
  172. package/dist/cli/compact-resume-payload.d.ts +4 -1
  173. package/dist/cli/compact-resume-payload.js +12 -5
  174. package/dist/cli/context.js +42 -17
  175. package/dist/cli/continuity.d.ts +5 -5
  176. package/dist/cli/continuity.js +90 -107
  177. package/dist/cli/curate.d.ts +4 -3
  178. package/dist/cli/curate.js +46 -68
  179. package/dist/cli/dag.d.ts +1 -1
  180. package/dist/cli/dag.js +14 -17
  181. package/dist/cli/decisions.js +27 -26
  182. package/dist/cli/eval.js +16 -21
  183. package/dist/cli/exit.d.ts +4 -1
  184. package/dist/cli/exit.js +10 -2
  185. package/dist/cli/explain.js +12 -11
  186. package/dist/cli/flag-values.d.ts +1 -1
  187. package/dist/cli/flag-values.js +9 -18
  188. package/dist/cli/github.d.ts +6 -0
  189. package/dist/cli/github.js +25 -13
  190. package/dist/cli/goals.d.ts +1 -1
  191. package/dist/cli/goals.js +39 -56
  192. package/dist/cli/graph.d.ts +1 -1
  193. package/dist/cli/graph.js +15 -11
  194. package/dist/cli/hook-runtime.d.ts +31 -9
  195. package/dist/cli/hook-runtime.js +40 -15
  196. package/dist/cli/incidents.d.ts +1 -1
  197. package/dist/cli/incidents.js +25 -25
  198. package/dist/cli/init.js +26 -11
  199. package/dist/cli/install-steps.d.ts +12 -3
  200. package/dist/cli/install-steps.js +42 -18
  201. package/dist/cli/last-sleep.d.ts +4 -1
  202. package/dist/cli/last-sleep.js +9 -4
  203. package/dist/cli/maintenance.d.ts +1 -1
  204. package/dist/cli/maintenance.js +11 -12
  205. package/dist/cli/notes.d.ts +1 -1
  206. package/dist/cli/notes.js +8 -5
  207. package/dist/cli/object-verbs.d.ts +4 -4
  208. package/dist/cli/object-verbs.js +10 -13
  209. package/dist/cli/open-browser.js +11 -2
  210. package/dist/cli/playbooks.d.ts +3 -3
  211. package/dist/cli/playbooks.js +40 -32
  212. package/dist/cli/predictions.js +15 -19
  213. package/dist/cli/print.js +4 -2
  214. package/dist/cli/projects.js +21 -11
  215. package/dist/cli/quality-repair-once.js +5 -4
  216. package/dist/cli/recall.js +129 -93
  217. package/dist/cli/refine-llm.d.ts +15 -4
  218. package/dist/cli/refine-llm.js +16 -7
  219. package/dist/cli/remember.js +46 -50
  220. package/dist/cli/scheduler.d.ts +4 -1
  221. package/dist/cli/scheduler.js +9 -5
  222. package/dist/cli/serve.js +22 -17
  223. package/dist/cli/session-hooks.d.ts +2 -2
  224. package/dist/cli/session-hooks.js +87 -50
  225. package/dist/cli/setup.js +54 -32
  226. package/dist/cli/shared.d.ts +3 -1
  227. package/dist/cli/shared.js +24 -9
  228. package/dist/cli/slack.js +15 -24
  229. package/dist/cli/sleep-render.d.ts +3 -1
  230. package/dist/cli/sleep-render.js +8 -5
  231. package/dist/cli/sleep.js +14 -6
  232. package/dist/cli/status.d.ts +4 -4
  233. package/dist/cli/status.js +32 -27
  234. package/dist/cli/stdin.d.ts +10 -3
  235. package/dist/cli/stdin.js +10 -3
  236. package/dist/cli/transfer.d.ts +1 -1
  237. package/dist/cli/transfer.js +71 -75
  238. package/dist/cli/verbs/memory.js +8 -6
  239. package/dist/cli/verbs/objects.js +10 -4
  240. package/dist/cli/versioned-verbs.d.ts +8 -7
  241. package/dist/cli/versioned-verbs.js +31 -21
  242. package/dist/cli.js +13 -16
  243. package/dist/connectors/dlq.d.ts +6 -6
  244. package/dist/connectors/dlq.js +12 -8
  245. package/dist/connectors/github/backfill.d.ts +4 -4
  246. package/dist/connectors/github/backfill.js +6 -4
  247. package/dist/connectors/github/deletion.d.ts +6 -4
  248. package/dist/connectors/github/deletion.js +5 -5
  249. package/dist/connectors/github/dlq.d.ts +8 -6
  250. package/dist/connectors/github/dlq.js +11 -5
  251. package/dist/connectors/github/ingest.d.ts +2 -2
  252. package/dist/connectors/github/ingest.js +9 -6
  253. package/dist/connectors/github/octokit-client.d.ts +3 -1
  254. package/dist/connectors/github/octokit-client.js +7 -2
  255. package/dist/connectors/github/ratelimit.d.ts +6 -2
  256. package/dist/connectors/github/ratelimit.js +6 -2
  257. package/dist/connectors/github/signature.d.ts +14 -3
  258. package/dist/connectors/github/signature.js +17 -3
  259. package/dist/connectors/github/tenant-routing.d.ts +6 -4
  260. package/dist/connectors/github/tenant-routing.js +6 -6
  261. package/dist/connectors/github/transform.js +50 -67
  262. package/dist/connectors/github/types.d.ts +10 -3
  263. package/dist/connectors/github/types.js +6 -2
  264. package/dist/connectors/github/webhook.d.ts +5 -5
  265. package/dist/connectors/github/webhook.js +34 -23
  266. package/dist/connectors/ingest.d.ts +5 -3
  267. package/dist/connectors/ingest.js +3 -4
  268. package/dist/connectors/slack/backfill.d.ts +5 -5
  269. package/dist/connectors/slack/backfill.js +3 -3
  270. package/dist/connectors/slack/deletion.d.ts +4 -4
  271. package/dist/connectors/slack/deletion.js +6 -6
  272. package/dist/connectors/slack/dlq.d.ts +4 -4
  273. package/dist/connectors/slack/dlq.js +6 -6
  274. package/dist/connectors/slack/ingest.d.ts +6 -4
  275. package/dist/connectors/slack/ingest.js +5 -5
  276. package/dist/connectors/slack/signature.d.ts +4 -1
  277. package/dist/connectors/slack/tenant-routing.d.ts +6 -4
  278. package/dist/connectors/slack/tenant-routing.js +6 -6
  279. package/dist/connectors/slack/transform.d.ts +6 -2
  280. package/dist/connectors/slack/transform.js +6 -2
  281. package/dist/connectors/slack/types.d.ts +3 -1
  282. package/dist/connectors/slack/web-client.js +8 -3
  283. package/dist/connectors/slack/webhook.d.ts +5 -5
  284. package/dist/connectors/slack/webhook.js +19 -11
  285. package/dist/connectors/slack/workspaces.d.ts +7 -3
  286. package/dist/connectors/slack/workspaces.js +7 -3
  287. package/dist/connectors/store.d.ts +8 -0
  288. package/dist/connectors/store.js +2 -0
  289. package/dist/consolidate/conflicts.js +23 -9
  290. package/dist/consolidate/dag-summary.js +2 -1
  291. package/dist/consolidate/dag.d.ts +10 -5
  292. package/dist/consolidate/dag.js +37 -36
  293. package/dist/consolidate/decay.js +19 -6
  294. package/dist/consolidate/dedupe.d.ts +14 -5
  295. package/dist/consolidate/dedupe.js +27 -16
  296. package/dist/consolidate/flush-units.d.ts +4 -1
  297. package/dist/consolidate/flush-units.js +4 -1
  298. package/dist/consolidate/half-life-migration.d.ts +18 -8
  299. package/dist/consolidate/half-life-migration.js +48 -18
  300. package/dist/consolidate/llm-passes.js +27 -11
  301. package/dist/consolidate/memory-value-weights.d.ts +6 -2
  302. package/dist/consolidate/memory-value-weights.js +6 -2
  303. package/dist/consolidate/memory-value.d.ts +30 -10
  304. package/dist/consolidate/memory-value.js +36 -13
  305. package/dist/consolidate/merge.d.ts +4 -1
  306. package/dist/consolidate/merge.js +42 -32
  307. package/dist/consolidate/overlap-index.d.ts +8 -2
  308. package/dist/consolidate/overlap-index.js +11 -4
  309. package/dist/consolidate/physics-pass.d.ts +3 -1
  310. package/dist/consolidate/physics-pass.js +10 -7
  311. package/dist/consolidate/replay.d.ts +11 -4
  312. package/dist/consolidate/replay.js +19 -7
  313. package/dist/consolidate/run.d.ts +13 -5
  314. package/dist/consolidate/run.js +4 -4
  315. package/dist/consolidate/sleep.d.ts +14 -6
  316. package/dist/consolidate/sleep.js +41 -38
  317. package/dist/consolidate/trace.d.ts +7 -2
  318. package/dist/consolidate/trace.js +7 -2
  319. package/dist/consolidate/traces.js +26 -29
  320. package/dist/core/ablation.d.ts +9 -3
  321. package/dist/core/ablation.js +14 -4
  322. package/dist/core/active-scope.d.ts +3 -1
  323. package/dist/core/active-scope.js +3 -1
  324. package/dist/core/agent-memory-tools.d.ts +2 -0
  325. package/dist/core/agent-memory-tools.js +2 -0
  326. package/dist/core/ambient.d.ts +4 -3
  327. package/dist/core/ambient.js +8 -6
  328. package/dist/core/api-errors.d.ts +9 -3
  329. package/dist/core/api-errors.js +9 -3
  330. package/dist/core/capture-contract.d.ts +4 -1
  331. package/dist/core/capture-contract.js +27 -8
  332. package/dist/core/compare.d.ts +24 -8
  333. package/dist/core/compare.js +24 -8
  334. package/dist/core/config.d.ts +18 -9
  335. package/dist/core/config.js +24 -14
  336. package/dist/core/cosine.d.ts +4 -1
  337. package/dist/core/cosine.js +4 -1
  338. package/dist/core/handoff.d.ts +7 -2
  339. package/dist/core/handoff.js +4 -1
  340. package/dist/core/markdown.js +21 -16
  341. package/dist/core/memory-audit.js +14 -3
  342. package/dist/core/memory-quality.d.ts +12 -3
  343. package/dist/core/memory-quality.js +57 -21
  344. package/dist/core/memory.d.ts +84 -27
  345. package/dist/core/memory.js +73 -29
  346. package/dist/core/merged-row.d.ts +8 -2
  347. package/dist/core/merged-row.js +10 -3
  348. package/dist/core/package-root.d.ts +3 -1
  349. package/dist/core/package-root.js +3 -1
  350. package/dist/core/particle-refresh.d.ts +8 -0
  351. package/dist/core/particle-refresh.js +22 -0
  352. package/dist/core/physics-config.d.ts +4 -1
  353. package/dist/core/physics-config.js +6 -2
  354. package/dist/core/physics.d.ts +37 -11
  355. package/dist/core/physics.js +55 -20
  356. package/dist/core/project-identity.d.ts +34 -17
  357. package/dist/core/project-identity.js +33 -17
  358. package/dist/core/project-remote.d.ts +8 -4
  359. package/dist/core/project-remote.js +31 -14
  360. package/dist/core/recall-scope.d.ts +33 -11
  361. package/dist/core/recall-scope.js +42 -15
  362. package/dist/core/rejection-digest.d.ts +7 -0
  363. package/dist/core/rejection-digest.js +13 -0
  364. package/dist/core/salience.d.ts +3 -1
  365. package/dist/core/salience.js +10 -4
  366. package/dist/core/search-types.d.ts +15 -2
  367. package/dist/core/search-types.js +11 -0
  368. package/dist/dashboard/dashboard-actions.js +13 -2
  369. package/dist/dashboard/dashboard-snapshot.d.ts +2 -2
  370. package/dist/dashboard/dashboard-snapshot.js +4 -4
  371. package/dist/dashboard/dashboard.js +6 -3
  372. package/dist/db/backup.js +2 -2
  373. package/dist/db/busy.d.ts +10 -3
  374. package/dist/db/busy.js +27 -5
  375. package/dist/db/connect.d.ts +10 -3
  376. package/dist/db/connect.js +8 -3
  377. package/dist/db/continuity.d.ts +1 -1
  378. package/dist/db/continuity.js +27 -11
  379. package/dist/db/meta.d.ts +4 -1
  380. package/dist/db/meta.js +4 -1
  381. package/dist/db/migrate.d.ts +10 -5
  382. package/dist/db/migrate.js +26 -13
  383. package/dist/db/migrations/index.d.ts +1 -1
  384. package/dist/db/migrations/index.js +3 -1
  385. package/dist/db/migrations/types.d.ts +2 -1
  386. package/dist/db/migrations/v12.js +2 -1
  387. package/dist/db/migrations/v14.js +2 -1
  388. package/dist/db/migrations/v15.js +4 -2
  389. package/dist/db/migrations/v16.js +6 -3
  390. package/dist/db/migrations/v17.js +2 -1
  391. package/dist/db/migrations/v19.js +4 -2
  392. package/dist/db/migrations/v20.js +2 -1
  393. package/dist/db/migrations/v22.js +12 -6
  394. package/dist/db/migrations/v23.js +6 -3
  395. package/dist/db/migrations/v24.js +6 -3
  396. package/dist/db/migrations/v25.js +4 -2
  397. package/dist/db/migrations/v26.js +4 -2
  398. package/dist/db/migrations/v27.js +6 -3
  399. package/dist/db/migrations/v28.js +4 -2
  400. package/dist/db/migrations/v29.js +4 -2
  401. package/dist/db/migrations/v30.js +6 -3
  402. package/dist/db/migrations/v31.js +4 -2
  403. package/dist/db/migrations/v32.js +6 -3
  404. package/dist/db/migrations/v33.js +4 -2
  405. package/dist/db/migrations/v34.js +2 -1
  406. package/dist/db/migrations/v35.js +2 -1
  407. package/dist/db/migrations/v36.js +2 -1
  408. package/dist/db/migrations/v37.js +10 -5
  409. package/dist/db/migrations/v38.js +10 -5
  410. package/dist/db/migrations/v39.js +14 -6
  411. package/dist/db/migrations/v40.js +4 -2
  412. package/dist/db/migrations/v41.js +4 -2
  413. package/dist/db/migrations/v42.js +2 -1
  414. package/dist/db/migrations/v44.js +4 -2
  415. package/dist/db/migrations/v45.js +4 -2
  416. package/dist/db/migrations/v49.js +2 -1
  417. package/dist/db/migrations/v50.js +4 -2
  418. package/dist/db/migrations/v51.js +4 -2
  419. package/dist/db/migrations/v52.js +2 -1
  420. package/dist/db/migrations/v53.js +8 -4
  421. package/dist/db/migrations/v54.js +2 -1
  422. package/dist/db/migrations/v55.js +4 -2
  423. package/dist/db/migrations/v56.d.ts +3 -0
  424. package/dist/db/migrations/v56.js +28 -0
  425. package/dist/db/open.d.ts +24 -12
  426. package/dist/db/open.js +25 -13
  427. package/dist/db/physics-state.d.ts +8 -4
  428. package/dist/db/physics-state.js +13 -20
  429. package/dist/db/raw-archive-mirror-cleanup.d.ts +4 -2
  430. package/dist/db/raw-archive-mirror-cleanup.js +6 -4
  431. package/dist/db/request-stores.d.ts +19 -5
  432. package/dist/db/request-stores.js +14 -5
  433. package/dist/db/tables.d.ts +2 -1
  434. package/dist/db/tables.js +12 -4
  435. package/dist/db/vector-store.d.ts +13 -4
  436. package/dist/db/vector-store.js +34 -14
  437. package/dist/db/wal-checkpointer.d.ts +2 -1
  438. package/dist/db/wal-checkpointer.js +19 -7
  439. package/dist/doctor.d.ts +4 -1
  440. package/dist/doctor.js +121 -39
  441. package/dist/embeddings/local.d.ts +8 -4
  442. package/dist/embeddings/local.js +9 -5
  443. package/dist/embeddings/provider.d.ts +19 -10
  444. package/dist/embeddings/provider.js +31 -17
  445. package/dist/embeddings/transformers.d.ts +16 -4
  446. package/dist/embeddings/transformers.js +32 -15
  447. package/dist/entry/json-hooks.d.ts +1 -1
  448. package/dist/entry/json-hooks.js +1 -1
  449. package/dist/entry/project-identity.js +2 -1
  450. package/dist/entry/session-text.d.ts +1 -1
  451. package/dist/entry/session-text.js +1 -1
  452. package/dist/entry/sqlite-handles.d.ts +10 -0
  453. package/dist/entry/sqlite-handles.js +9 -0
  454. package/dist/entry/store-kit.d.ts +19 -6
  455. package/dist/entry/store-kit.js +6 -4
  456. package/dist/eval/eval-stats.d.ts +27 -8
  457. package/dist/eval/eval-stats.js +17 -5
  458. package/dist/eval/eval-suite.d.ts +3 -1
  459. package/dist/eval/eval-suite.js +409 -187
  460. package/dist/eval/eval.d.ts +8 -2
  461. package/dist/eval/eval.js +8 -2
  462. package/dist/eval/judgment.js +16 -6
  463. package/dist/graph/delta.d.ts +9 -42
  464. package/dist/graph/delta.js +17 -11
  465. package/dist/graph/extract.d.ts +10 -7
  466. package/dist/graph/extract.js +57 -25
  467. package/dist/graph/recall.d.ts +12 -4
  468. package/dist/graph/recall.js +30 -13
  469. package/dist/graph/stream.d.ts +18 -6
  470. package/dist/graph/stream.js +32 -10
  471. package/dist/graph/view.d.ts +19 -6
  472. package/dist/graph/view.js +42 -17
  473. package/dist/hooks/codex-session.js +2 -2
  474. package/dist/hooks/codex-wrapper.d.ts +3 -1
  475. package/dist/hooks/codex-wrapper.js +9 -4
  476. package/dist/hooks/copilot.d.ts +19 -5
  477. package/dist/hooks/copilot.js +54 -15
  478. package/dist/hooks/hook-blocks.d.ts +4 -1
  479. package/dist/hooks/hook-blocks.js +8 -3
  480. package/dist/hooks/json-hooks.d.ts +9 -5
  481. package/dist/hooks/json-hooks.js +69 -34
  482. package/dist/hooks/opencode.js +15 -5
  483. package/dist/hooks/shared.d.ts +27 -8
  484. package/dist/hooks/shared.js +57 -16
  485. package/dist/importers/core.d.ts +12 -4
  486. package/dist/importers/core.js +8 -7
  487. package/dist/importers/markdown-parse.d.ts +15 -5
  488. package/dist/importers/markdown-parse.js +16 -7
  489. package/dist/importers/markdown.js +6 -9
  490. package/dist/importers/sources.js +10 -23
  491. package/dist/importers/vault.d.ts +2 -2
  492. package/dist/importers/vault.js +43 -27
  493. package/dist/index.d.ts +32 -6
  494. package/dist/index.js +25 -7
  495. package/dist/learn/autolearn.d.ts +17 -6
  496. package/dist/learn/autolearn.js +53 -24
  497. package/dist/learn/churn-git.d.ts +4 -1
  498. package/dist/learn/churn-git.js +29 -5
  499. package/dist/learn/extract.d.ts +4 -1
  500. package/dist/learn/extract.js +16 -9
  501. package/dist/learn/forward-claim-detector.d.ts +17 -5
  502. package/dist/learn/forward-claim-detector.js +34 -15
  503. package/dist/learn/invalidation.d.ts +12 -7
  504. package/dist/learn/invalidation.js +56 -27
  505. package/dist/learn/roots.d.ts +3 -0
  506. package/dist/learn/roots.js +5 -0
  507. package/dist/mcp/admin-tools.d.ts +5 -5
  508. package/dist/mcp/admin-tools.js +28 -23
  509. package/dist/mcp/format.d.ts +1 -1
  510. package/dist/mcp/format.js +4 -2
  511. package/dist/mcp/framing.d.ts +3 -1
  512. package/dist/mcp/framing.js +20 -8
  513. package/dist/mcp/memory-tools.d.ts +3 -3
  514. package/dist/mcp/memory-tools.js +18 -14
  515. package/dist/mcp/protocol.d.ts +32 -16
  516. package/dist/mcp/protocol.js +12 -9
  517. package/dist/mcp/recall-tools.d.ts +3 -3
  518. package/dist/mcp/recall-tools.js +62 -74
  519. package/dist/mcp/request.d.ts +7 -5
  520. package/dist/mcp/request.js +57 -74
  521. package/dist/mcp/server.d.ts +3 -1
  522. package/dist/mcp/server.js +8 -3
  523. package/dist/mcp/session-state.d.ts +1 -1
  524. package/dist/mcp/session-state.js +4 -3
  525. package/dist/mcp/shared-gate.d.ts +3 -2
  526. package/dist/mcp/shared-gate.js +3 -2
  527. package/dist/mcp/stdio.d.ts +6 -3
  528. package/dist/mcp/stdio.js +52 -21
  529. package/dist/mcp/tool-args.d.ts +4 -1
  530. package/dist/mcp/tool-args.js +8 -3
  531. package/dist/mcp/tools.js +76 -32
  532. package/dist/objects/customer-notes.d.ts +12 -10
  533. package/dist/objects/customer-notes.js +21 -15
  534. package/dist/objects/decisions.d.ts +18 -10
  535. package/dist/objects/decisions.js +23 -17
  536. package/dist/objects/descriptor.js +2 -1
  537. package/dist/objects/fields.d.ts +4 -1
  538. package/dist/objects/fields.js +6 -2
  539. package/dist/objects/incidents.d.ts +14 -16
  540. package/dist/objects/incidents.js +29 -30
  541. package/dist/objects/lifecycle.d.ts +0 -4
  542. package/dist/objects/lifecycle.js +21 -24
  543. package/dist/objects/policies.d.ts +12 -16
  544. package/dist/objects/policies.js +17 -21
  545. package/dist/objects/processes.d.ts +16 -10
  546. package/dist/objects/processes.js +20 -15
  547. package/dist/objects/project-briefs.d.ts +13 -14
  548. package/dist/objects/project-briefs.js +33 -39
  549. package/dist/objects/skills.d.ts +10 -12
  550. package/dist/objects/skills.js +17 -22
  551. package/dist/postinstall.js +15 -7
  552. package/dist/predictions/planning-fallacy.d.ts +19 -6
  553. package/dist/predictions/planning-fallacy.js +4 -2
  554. package/dist/rerankers/clef.d.ts +8 -2
  555. package/dist/rerankers/clef.js +14 -9
  556. package/dist/rerankers/cross-encoder.d.ts +2 -1
  557. package/dist/rerankers/cross-encoder.js +9 -6
  558. package/dist/rerankers/index.js +2 -1
  559. package/dist/rerankers/jev.js +2 -1
  560. package/dist/rerankers/llm.d.ts +6 -2
  561. package/dist/rerankers/llm.js +8 -3
  562. package/dist/rerankers/remote.d.ts +3 -1
  563. package/dist/rerankers/remote.js +5 -2
  564. package/dist/rerankers/types.d.ts +6 -2
  565. package/dist/search/bm25-search.d.ts +3 -1
  566. package/dist/search/bm25-search.js +15 -2
  567. package/dist/search/boosts.js +4 -3
  568. package/dist/search/embed-memories.d.ts +10 -5
  569. package/dist/search/embed-memories.js +62 -36
  570. package/dist/search/engine.d.ts +4 -1
  571. package/dist/search/engine.js +6 -2
  572. package/dist/search/goal-boost.d.ts +10 -3
  573. package/dist/search/goal-boost.js +13 -6
  574. package/dist/search/hybrid-score.d.ts +4 -1
  575. package/dist/search/hybrid-score.js +4 -1
  576. package/dist/search/hybrid.d.ts +23 -8
  577. package/dist/search/hybrid.js +12 -7
  578. package/dist/search/multihop.js +14 -13
  579. package/dist/search/path-context.d.ts +10 -3
  580. package/dist/search/path-context.js +10 -3
  581. package/dist/search/physics-search.d.ts +9 -4
  582. package/dist/search/physics-search.js +38 -14
  583. package/dist/search/rerank.d.ts +2 -1
  584. package/dist/search/rerank.js +2 -1
  585. package/dist/search/rrf.d.ts +14 -5
  586. package/dist/search/rrf.js +11 -4
  587. package/dist/search/vector.d.ts +8 -2
  588. package/dist/search/vector.js +9 -3
  589. package/dist/server/auth.d.ts +18 -14
  590. package/dist/server/auth.js +69 -38
  591. package/dist/server/boot.d.ts +3 -1
  592. package/dist/server/boot.js +95 -56
  593. package/dist/server/client-ip.d.ts +11 -4
  594. package/dist/server/client-ip.js +27 -10
  595. package/dist/server/cursor.d.ts +10 -3
  596. package/dist/server/cursor.js +10 -3
  597. package/dist/server/deadline.d.ts +5 -2
  598. package/dist/server/deadline.js +10 -3
  599. package/dist/server/key-check-bounds.js +12 -4
  600. package/dist/server/lifecycle.d.ts +4 -1
  601. package/dist/server/lifecycle.js +10 -4
  602. package/dist/server/mcp-http.d.ts +2 -1
  603. package/dist/server/mcp-http.js +37 -22
  604. package/dist/server/rate-limit.d.ts +17 -5
  605. package/dist/server/rate-limit.js +55 -26
  606. package/dist/server/ready.js +7 -4
  607. package/dist/server/request.d.ts +15 -4
  608. package/dist/server/request.js +42 -15
  609. package/dist/server/route-checks.d.ts +4 -1
  610. package/dist/server/route-checks.js +8 -3
  611. package/dist/server/route-table.d.ts +8 -6
  612. package/dist/server/route-table.js +547 -93
  613. package/dist/server/routes/admin.d.ts +7 -7
  614. package/dist/server/routes/admin.js +36 -15
  615. package/dist/server/routes/customer-notes.d.ts +5 -5
  616. package/dist/server/routes/customer-notes.js +5 -4
  617. package/dist/server/routes/decisions.d.ts +5 -5
  618. package/dist/server/routes/decisions.js +12 -6
  619. package/dist/server/routes/incidents.d.ts +5 -5
  620. package/dist/server/routes/incidents.js +10 -4
  621. package/dist/server/routes/memories.d.ts +8 -8
  622. package/dist/server/routes/memories.js +12 -19
  623. package/dist/server/routes/object-routes.d.ts +8 -5
  624. package/dist/server/routes/object-routes.js +4 -2
  625. package/dist/server/routes/policies.d.ts +6 -6
  626. package/dist/server/routes/policies.js +11 -4
  627. package/dist/server/routes/predictions.d.ts +5 -5
  628. package/dist/server/routes/predictions.js +9 -4
  629. package/dist/server/routes/processes.d.ts +5 -5
  630. package/dist/server/routes/processes.js +15 -6
  631. package/dist/server/routes/project-briefs.d.ts +6 -6
  632. package/dist/server/routes/project-briefs.js +3 -2
  633. package/dist/server/routes/recall.d.ts +3 -3
  634. package/dist/server/routes/recall.js +21 -10
  635. package/dist/server/routes/skills.d.ts +6 -6
  636. package/dist/server/routes/skills.js +12 -4
  637. package/dist/server/server-detect.d.ts +24 -8
  638. package/dist/server/server-detect.js +57 -22
  639. package/dist/server/sleep-child.js +16 -10
  640. package/dist/server/sleep-offload.d.ts +8 -5
  641. package/dist/server/sleep-offload.js +41 -19
  642. package/dist/server/tls.d.ts +4 -1
  643. package/dist/server/tls.js +13 -5
  644. package/dist/server/types.d.ts +38 -26
  645. package/dist/server/validation.d.ts +4 -1
  646. package/dist/server/validation.js +22 -9
  647. package/dist/server.d.ts +15 -10
  648. package/dist/server.js +32 -12
  649. package/dist/sharing/global-store.d.ts +5 -10
  650. package/dist/sharing/global-store.js +8 -43
  651. package/dist/sharing/global-sync.d.ts +3 -1
  652. package/dist/sharing/global-sync.js +16 -6
  653. package/dist/sharing/project-merge.d.ts +25 -7
  654. package/dist/sharing/project-merge.js +49 -17
  655. package/dist/sharing/search-both.d.ts +8 -4
  656. package/dist/sharing/search-both.js +19 -12
  657. package/dist/sharing/share.d.ts +8 -4
  658. package/dist/sharing/share.js +39 -15
  659. package/dist/store/ambient.js +9 -5
  660. package/dist/store/audit-event.d.ts +2 -2
  661. package/dist/store/audit-event.js +8 -3
  662. package/dist/store/audit.d.ts +6 -3
  663. package/dist/store/audit.js +16 -6
  664. package/dist/store/auth.d.ts +4 -2
  665. package/dist/store/auth.js +63 -20
  666. package/dist/store/busy.d.ts +9 -0
  667. package/dist/store/busy.js +16 -0
  668. package/dist/store/candidates.d.ts +12 -5
  669. package/dist/store/candidates.js +75 -36
  670. package/dist/store/capture-write.d.ts +2 -1
  671. package/dist/store/capture-write.js +2 -1
  672. package/dist/store/card-detail.d.ts +4 -4
  673. package/dist/store/card-detail.js +15 -8
  674. package/dist/store/cards.d.ts +24 -10
  675. package/dist/store/cards.js +93 -60
  676. package/dist/store/compaction-caller.d.ts +2 -1
  677. package/dist/store/compaction-caller.js +2 -1
  678. package/dist/store/compactions-record.d.ts +14 -8
  679. package/dist/store/compactions-record.js +95 -32
  680. package/dist/store/compactions.js +35 -15
  681. package/dist/store/conflicts.d.ts +9 -4
  682. package/dist/store/conflicts.js +100 -45
  683. package/dist/store/connectors/dlq.d.ts +17 -5
  684. package/dist/store/connectors/dlq.js +56 -5
  685. package/dist/store/connectors/event-log.d.ts +111 -2
  686. package/dist/store/connectors/event-log.js +2 -1
  687. package/dist/store/connectors/github.d.ts +6 -3
  688. package/dist/store/connectors/github.js +24 -40
  689. package/dist/store/connectors/slack.d.ts +2 -1
  690. package/dist/store/connectors/slack.js +25 -37
  691. package/dist/store/dashboard-reads.d.ts +7 -3
  692. package/dist/store/dashboard-reads.js +32 -11
  693. package/dist/store/delete-and-batch.d.ts +17 -11
  694. package/dist/store/delete-and-batch.js +67 -26
  695. package/dist/store/delivery-recorder.d.ts +8 -5
  696. package/dist/store/delivery-recorder.js +70 -32
  697. package/dist/store/descendant-page.d.ts +2 -1
  698. package/dist/store/descendant-page.js +24 -9
  699. package/dist/store/diagnostics.d.ts +2 -1
  700. package/dist/store/diagnostics.js +2 -1
  701. package/dist/store/doctor-reads.d.ts +2 -1
  702. package/dist/store/doctor-reads.js +13 -5
  703. package/dist/store/dormant.d.ts +19 -11
  704. package/dist/store/dormant.js +40 -18
  705. package/dist/store/embeddings/index.d.ts +13 -9
  706. package/dist/store/embeddings/index.js +19 -12
  707. package/dist/store/entry-reads.d.ts +49 -20
  708. package/dist/store/entry-reads.js +181 -66
  709. package/dist/store/entry-row.d.ts +10 -6
  710. package/dist/store/entry-row.js +17 -12
  711. package/dist/store/entry-writes.d.ts +22 -10
  712. package/dist/store/entry-writes.js +41 -14
  713. package/dist/store/failure-log-at.js +1 -1
  714. package/dist/store/failure-log.d.ts +4 -2
  715. package/dist/store/failure-log.js +13 -6
  716. package/dist/store/gated-write.d.ts +3 -3
  717. package/dist/store/gated-write.js +3 -3
  718. package/dist/store/goals.d.ts +5 -4
  719. package/dist/store/goals.js +8 -10
  720. package/dist/store/graph-apply.d.ts +21 -0
  721. package/dist/{graph/write.js → store/graph-apply.js} +31 -11
  722. package/dist/store/graph-queue.d.ts +9 -6
  723. package/dist/store/graph-queue.js +15 -10
  724. package/dist/store/graph-reads.d.ts +16 -11
  725. package/dist/store/graph-reads.js +24 -15
  726. package/dist/store/graph-rows.d.ts +41 -3
  727. package/dist/store/graph-rows.js +10 -7
  728. package/dist/store/graph-view-rows.js +14 -7
  729. package/dist/store/graph-writes.d.ts +16 -10
  730. package/dist/store/graph-writes.js +59 -36
  731. package/dist/store/handoffs.d.ts +4 -4
  732. package/dist/store/handoffs.js +40 -19
  733. package/dist/store/index-and-stats.d.ts +2 -2
  734. package/dist/store/index-and-stats.js +6 -5
  735. package/dist/store/index.d.ts +3 -1
  736. package/dist/store/index.js +1 -0
  737. package/dist/store/key-audit.d.ts +2 -1
  738. package/dist/store/key-audit.js +2 -1
  739. package/dist/store/key-writes.d.ts +2 -1
  740. package/dist/store/key-writes.js +9 -2
  741. package/dist/store/ledger-turn.d.ts +4 -1
  742. package/dist/store/ledger-turn.js +7 -2
  743. package/dist/store/mirrors.d.ts +11 -4
  744. package/dist/store/mirrors.js +88 -16
  745. package/dist/store/narrow.d.ts +6 -0
  746. package/dist/store/narrow.js +11 -0
  747. package/dist/store/open.d.ts +4 -2
  748. package/dist/store/open.js +18 -9
  749. package/dist/store/pilot-arm.d.ts +2 -1
  750. package/dist/store/pilot-arm.js +18 -6
  751. package/dist/store/planning-fallacy-evidence.d.ts +2 -2
  752. package/dist/store/planning-fallacy-evidence.js +8 -5
  753. package/dist/store/port/agent-import.d.ts +62 -0
  754. package/dist/store/port/agent-import.js +2 -0
  755. package/dist/store/port/consolidation.d.ts +129 -0
  756. package/dist/store/port/consolidation.js +2 -0
  757. package/dist/store/port/learning.d.ts +19 -0
  758. package/dist/store/port/learning.js +2 -0
  759. package/dist/store/port/local-files.d.ts +18 -0
  760. package/dist/store/port/local-files.js +2 -0
  761. package/dist/store/port/promotion.d.ts +20 -0
  762. package/dist/store/port/promotion.js +3 -0
  763. package/dist/store/port-groups.d.ts +160 -0
  764. package/dist/store/port-groups.js +2 -0
  765. package/dist/store/port.d.ts +215 -229
  766. package/dist/store/port.js +3 -9
  767. package/dist/store/predictions.d.ts +14 -10
  768. package/dist/store/predictions.js +37 -17
  769. package/dist/store/project-tags.d.ts +4 -1
  770. package/dist/store/project-tags.js +16 -5
  771. package/dist/store/quality-repair.d.ts +8 -4
  772. package/dist/store/quality-repair.js +53 -20
  773. package/dist/store/quarantine.d.ts +1 -0
  774. package/dist/store/quarantine.js +23 -9
  775. package/dist/store/raw-archive.d.ts +5 -4
  776. package/dist/store/raw-archive.js +11 -10
  777. package/dist/store/recall-trace.d.ts +22 -17
  778. package/dist/store/recall-trace.js +126 -63
  779. package/dist/store/rejected-values.d.ts +15 -10
  780. package/dist/store/rejected-values.js +33 -12
  781. package/dist/store/rejection.d.ts +12 -11
  782. package/dist/store/rejection.js +18 -19
  783. package/dist/store/report-reads.d.ts +2 -1
  784. package/dist/store/report-reads.js +2 -1
  785. package/dist/store/rows.d.ts +7 -5
  786. package/dist/store/rows.js +18 -11
  787. package/dist/store/rule-sql.d.ts +6 -4
  788. package/dist/store/rule-sql.js +16 -9
  789. package/dist/store/search-rows.d.ts +14 -9
  790. package/dist/store/search-rows.js +48 -23
  791. package/dist/store/sessions.d.ts +12 -10
  792. package/dist/store/sessions.js +40 -21
  793. package/dist/store/set-aside.d.ts +2 -2
  794. package/dist/store/set-aside.js +18 -5
  795. package/dist/store/sqlite/agent-import.d.ts +3 -0
  796. package/dist/store/sqlite/agent-import.js +77 -0
  797. package/dist/store/sqlite/cards-group.d.ts +6 -0
  798. package/dist/store/sqlite/cards-group.js +37 -0
  799. package/dist/store/sqlite/conflicts-group.d.ts +6 -0
  800. package/dist/store/sqlite/conflicts-group.js +18 -0
  801. package/dist/store/sqlite/connector-events-group.d.ts +2 -1
  802. package/dist/store/sqlite/connector-events-group.js +17 -6
  803. package/dist/store/sqlite/connector-writes-group.d.ts +2 -1
  804. package/dist/store/sqlite/connector-writes-group.js +9 -4
  805. package/dist/store/sqlite/consolidation-group.d.ts +4 -0
  806. package/dist/store/sqlite/consolidation-group.js +64 -0
  807. package/dist/store/sqlite/dag-reads-group.js +1 -1
  808. package/dist/store/sqlite/dormant-group.d.ts +6 -0
  809. package/dist/store/sqlite/dormant-group.js +29 -0
  810. package/dist/store/sqlite/entry-writes-group.d.ts +6 -3
  811. package/dist/store/sqlite/entry-writes-group.js +37 -14
  812. package/dist/store/sqlite/error-codec.d.ts +4 -2
  813. package/dist/store/sqlite/error-codec.js +32 -10
  814. package/dist/store/sqlite/executor-counts.js +2 -1
  815. package/dist/store/sqlite/executor.d.ts +8 -3
  816. package/dist/store/sqlite/executor.js +56 -18
  817. package/dist/store/sqlite/global-promote.d.ts +5 -0
  818. package/dist/store/sqlite/global-promote.js +48 -0
  819. package/dist/store/sqlite/goals-group.d.ts +6 -0
  820. package/dist/store/sqlite/goals-group.js +23 -0
  821. package/dist/store/sqlite/graph-reads-group.d.ts +2 -1
  822. package/dist/store/sqlite/graph-reads-group.js +2 -1
  823. package/dist/store/sqlite/held-connection.d.ts +7 -1
  824. package/dist/store/sqlite/held-connection.js +34 -7
  825. package/dist/store/sqlite/last-recall-group.d.ts +4 -2
  826. package/dist/store/sqlite/last-recall-group.js +9 -4
  827. package/dist/store/sqlite/learning-group.d.ts +4 -0
  828. package/dist/store/sqlite/learning-group.js +17 -0
  829. package/dist/store/sqlite/maintenance-groups.js +2 -1
  830. package/dist/store/sqlite/object-rows.d.ts +6 -3
  831. package/dist/store/sqlite/object-rows.js +34 -5
  832. package/dist/store/sqlite/objects-group.d.ts +5 -4
  833. package/dist/store/sqlite/objects-group.js +84 -33
  834. package/dist/store/sqlite/predictions-group.d.ts +2 -1
  835. package/dist/store/sqlite/predictions-group.js +4 -2
  836. package/dist/store/sqlite/promotion-group.d.ts +3 -0
  837. package/dist/store/sqlite/promotion-group.js +10 -0
  838. package/dist/store/sqlite/quarantine-group.d.ts +2 -1
  839. package/dist/store/sqlite/quarantine-group.js +4 -2
  840. package/dist/store/sqlite/reports-group.d.ts +6 -0
  841. package/dist/store/sqlite/reports-group.js +33 -0
  842. package/dist/store/sqlite/request-scope.d.ts +6 -0
  843. package/dist/store/sqlite/request-scope.js +18 -0
  844. package/dist/store/sqlite/sessions-group.d.ts +6 -0
  845. package/dist/store/sqlite/sessions-group.js +46 -0
  846. package/dist/store/sqlite/store.d.ts +22 -11
  847. package/dist/store/sqlite/store.js +84 -11
  848. package/dist/store/sqlite/vector-pack.js +2 -1
  849. package/dist/store/sqlite/vector-reads-group.js +2 -1
  850. package/dist/store/sqlite/worker-jobs.d.ts +2 -1
  851. package/dist/store/sqlite/worker-jobs.js +19 -7
  852. package/dist/store/sqlite/worker-ops.d.ts +10 -5
  853. package/dist/store/sqlite/worker-ops.js +6 -3
  854. package/dist/store/sqlite/worker-store.d.ts +4 -3
  855. package/dist/store/sqlite/worker-store.js +24 -14
  856. package/dist/store/summaries.d.ts +19 -12
  857. package/dist/store/summaries.js +36 -21
  858. package/dist/store/summary-dirty.d.ts +2 -1
  859. package/dist/store/summary-dirty.js +2 -1
  860. package/dist/store/tenant.d.ts +3 -2
  861. package/dist/store/tenant.js +5 -4
  862. package/dist/store/token-ledger-rows.js +6 -3
  863. package/dist/store/token-ledger.d.ts +19 -13
  864. package/dist/store/token-ledger.js +27 -14
  865. package/dist/store/tombstone-checks.d.ts +4 -1
  866. package/dist/store/tombstone-checks.js +10 -1
  867. package/dist/store/usage-reports.js +2 -1
  868. package/dist/store/vector-index.d.ts +8 -5
  869. package/dist/store/vector-index.js +24 -10
  870. package/dist/store/working-memory.d.ts +6 -4
  871. package/dist/store/working-memory.js +14 -9
  872. package/dist/support-bundle.js +10 -5
  873. package/dist/trust/quarantine.d.ts +1 -2
  874. package/dist/trust/quarantine.js +1 -5
  875. package/dist/trust/reject-flow.d.ts +12 -3
  876. package/dist/trust/reject-flow.js +12 -4
  877. package/dist/util/anthropic-messages.d.ts +4 -1
  878. package/dist/util/anthropic-messages.js +14 -5
  879. package/dist/util/atomic-write.d.ts +4 -2
  880. package/dist/util/atomic-write.js +25 -14
  881. package/dist/util/compaction-items.d.ts +4 -1
  882. package/dist/util/compaction-items.js +8 -2
  883. package/dist/util/crash-handlers.d.ts +7 -2
  884. package/dist/util/crash-handlers.js +13 -4
  885. package/dist/util/env.d.ts +16 -4
  886. package/dist/util/env.js +78 -25
  887. package/dist/util/home-path.js +12 -6
  888. package/dist/util/hook-payload.d.ts +3 -1
  889. package/dist/util/hook-payload.js +3 -1
  890. package/dist/util/http-retry.d.ts +12 -6
  891. package/dist/util/http-retry.js +16 -6
  892. package/dist/util/http-util.d.ts +20 -5
  893. package/dist/util/http-util.js +28 -9
  894. package/dist/util/json.d.ts +4 -1
  895. package/dist/util/json.js +4 -1
  896. package/dist/util/keyset.js +2 -1
  897. package/dist/util/limits.js +4 -2
  898. package/dist/util/log.d.ts +13 -5
  899. package/dist/util/log.js +29 -6
  900. package/dist/util/net.d.ts +5 -0
  901. package/dist/util/net.js +19 -0
  902. package/dist/util/real-path.d.ts +2 -1
  903. package/dist/util/real-path.js +4 -3
  904. package/dist/util/request-scope.d.ts +11 -3
  905. package/dist/util/request-scope.js +13 -4
  906. package/dist/util/same-text.d.ts +10 -3
  907. package/dist/util/same-text.js +10 -3
  908. package/dist/util/secret-detect.d.ts +24 -7
  909. package/dist/util/secret-detect.js +49 -14
  910. package/dist/util/spawn-argv.d.ts +3 -1
  911. package/dist/util/spawn-argv.js +13 -4
  912. package/dist/util/sqlite-blocked.d.ts +15 -4
  913. package/dist/util/sqlite-blocked.js +19 -6
  914. package/dist/util/stored-json.d.ts +4 -1
  915. package/dist/util/stored-json.js +6 -2
  916. package/dist/util/stream-tee.d.ts +2 -1
  917. package/dist/util/stream-tee.js +8 -5
  918. package/dist/util/transcript-tail.d.ts +4 -1
  919. package/dist/util/transcript-tail.js +4 -1
  920. package/dist/util/version.d.ts +8 -3
  921. package/dist/util/version.js +8 -3
  922. package/dist/util/write-budget.d.ts +7 -2
  923. package/dist/util/write-budget.js +5 -2
  924. package/dist/util/yaml.d.ts +4 -1
  925. package/dist/util/yaml.js +4 -1
  926. package/extensions/openclaw-plugin/openclaw.plugin.json +1 -1
  927. package/extensions/openclaw-plugin/package.json +1 -1
  928. package/openclaw.plugin.json +1 -1
  929. package/package.json +2 -1
  930. package/scripts/postinstall.cjs +3 -1
  931. package/dist/api/cards.d.ts +0 -42
  932. package/dist/api/conflicts.d.ts +0 -28
  933. package/dist/api/conflicts.js +0 -61
  934. package/dist/api/dormant.d.ts +0 -14
  935. package/dist/api/dormant.js +0 -58
  936. package/dist/api/goals.d.ts +0 -18
  937. package/dist/api/graph.d.ts +0 -8
  938. package/dist/api/graph.js +0 -8
  939. package/dist/api/learn.js +0 -125
  940. package/dist/api/memories.d.ts +0 -25
  941. package/dist/api/objects.d.ts +0 -9
  942. package/dist/api/outcome.d.ts +0 -19
  943. package/dist/api/predictions.d.ts +0 -11
  944. package/dist/api/promote.d.ts +0 -36
  945. package/dist/api/recall-core.d.ts +0 -4
  946. package/dist/api/recall-core.js +0 -125
  947. package/dist/api/recall-finish.d.ts +0 -53
  948. package/dist/api/recall-finish.js +0 -30
  949. package/dist/api/recall-history.d.ts +0 -64
  950. package/dist/api/recall-history.js +0 -159
  951. package/dist/api/recall-record.d.ts +0 -43
  952. package/dist/api/recall-record.js +0 -78
  953. package/dist/api/recall-request.js +0 -121
  954. package/dist/api/recall.d.ts +0 -6
  955. package/dist/api/refine.d.ts +0 -7
  956. package/dist/api/refine.js +0 -10
  957. package/dist/api/session-owners.d.ts +0 -4
  958. package/dist/api/session-owners.js +0 -17
  959. package/dist/api/sleep-run.d.ts +0 -26
  960. package/dist/api/sleep.js +0 -11
  961. package/dist/graph/write.d.ts +0 -14
  962. package/dist/store/sqlite/busy.d.ts +0 -3
  963. package/dist/store/sqlite/busy.js +0 -8
  964. package/dist/store/sqlite/local.d.ts +0 -4
  965. package/dist/store/sqlite/local.js +0 -8
@@ -1,6 +1,8 @@
1
1
  // Bearer and loopback auth for the HTTP server.
2
2
  import { envAllowKeylessLocal, envKeylessLocalRole, envRequireAuth } from '../util/env.js';
3
+ import { loadConfig } from '../core/config.js';
3
4
  import { resolveTenantId } from '../store/tenant.js';
5
+ import { sqliteReach } from '../store/sqlite/store.js';
4
6
  import { errorFields, errorMessage, log } from '../util/log.js';
5
7
  import { API_KEY_PREFIX, verifyApiKeyCached } from '../store/auth.js';
6
8
  import { ownerOrSubject } from '../api/index.js';
@@ -9,38 +11,40 @@ import { MAX_ID_LEN } from '../util/limits.js';
9
11
  import { clientLimitKey } from './client-ip.js';
10
12
  import { keyCheckBounds } from './key-check-bounds.js';
11
13
  import { isJsonString } from '../util/json.js';
12
- /** Recognises loopback remote addresses, including the IPv6-mapped '::ffff:127.0.0.1' Node reports on dual-stack sockets; anything else is remote. */
13
- export function isLoopback(remoteAddress) {
14
- if (!remoteAddress)
15
- return false;
16
- if (remoteAddress === '127.0.0.1')
17
- return true;
18
- if (remoteAddress === '::1')
19
- return true;
20
- if (remoteAddress === '::ffff:127.0.0.1')
21
- return true;
22
- return false;
23
- }
24
- // A proxy on this host (nginx, Caddy, cloudflared) connects from loopback, so these headers mean the caller is not local.
14
+ import { MINUTE_MS } from '../util/time.js';
15
+ import { isLoopbackAddress } from '../util/net.js';
16
+ /** Kept under its old name because src/server.ts publishes it. */
17
+ export const isLoopback = isLoopbackAddress;
18
+ // A proxy on this host (nginx, Caddy, cloudflared) connects
19
+ // from loopback, so these headers mean the caller is not local.
25
20
  const PROXY_HEADERS = [
26
- 'forwarded', 'x-forwarded-for', 'x-forwarded-host', 'x-forwarded-proto', 'x-real-ip', 'cf-connecting-ip', 'true-client-ip',
21
+ 'forwarded',
22
+ 'x-forwarded-for',
23
+ 'x-forwarded-host',
24
+ 'x-forwarded-proto',
25
+ 'x-real-ip',
26
+ 'cf-connecting-ip',
27
+ 'true-client-ip',
27
28
  'fly-client-ip',
28
29
  ];
29
30
  function proxyHeaderOf(req) {
30
31
  return PROXY_HEADERS.find((name) => req.headers[name] !== undefined);
31
32
  }
32
- /** A page in a browser on this machine: another site's request, or a hostile name resolved to loopback (DNS rebinding). */
33
+ /** A page in a browser on this machine: another site's request,
34
+ * or a hostile name resolved to loopback (DNS rebinding). */
33
35
  function isForeignPage(req) {
34
36
  const host = req.headers.host;
35
37
  return (host !== undefined && !LOOPBACK_HOST_HEADER.test(host)) || isCrossSite(req);
36
38
  }
37
- /** True only for a request made on this machine by its own user: a proxy and a browser page are loopback too, so the socket alone proves nothing. */
39
+ /** True only for a request made on this machine by its own user: a proxy and a browser page are loopback too, so the
40
+ * socket alone proves nothing. */
38
41
  export function isLocalCaller(req) {
39
- return isLoopback(req.socket.remoteAddress) && proxyHeaderOf(req) === undefined && !isForeignPage(req);
42
+ return isLoopbackAddress(req.socket.remoteAddress) && proxyHeaderOf(req) === undefined && !isForeignPage(req);
40
43
  }
41
- // The throwing twin of isLocalCaller, for the no-key fallback: each refusal has its own status, and a proxied one is logged.
44
+ // The throwing twin of isLocalCaller, for the no-key fallback:
45
+ // each refusal has its own status, and a proxied one is logged.
42
46
  function assertLocalCaller(req) {
43
- if (!isLoopback(req.socket.remoteAddress))
47
+ if (!isLoopbackAddress(req.socket.remoteAddress))
44
48
  throw new HttpError(401, 'auth required');
45
49
  const proxyHeader = proxyHeaderOf(req);
46
50
  if (proxyHeader !== undefined) {
@@ -52,10 +56,11 @@ function assertLocalCaller(req) {
52
56
  throw new HttpError(403, 'cross-site or non-local request refused; send an API key');
53
57
  }
54
58
  }
55
- /** The 401 a keyless request from this machine gets by default; it names both fixes, since an upgrade is where most people meet it. */
59
+ /** The 401 a keyless request from this machine gets by default; it names both fixes, since an upgrade is where most
60
+ * people meet it. */
56
61
  const KEY_REQUIRED_MESSAGE = 'auth required: this server takes no request without an API key. Mint one with `hippo auth create` and send it as ' +
57
- '"Authorization: Bearer <key>" (the hippo CLI reads HIPPO_API_KEY), or start the server with HIPPO_ALLOW_KEYLESS_LOCAL=1 ' +
58
- 'to let requests from this machine in without a key.';
62
+ '"Authorization: Bearer <key>" (the hippo CLI reads HIPPO_API_KEY), or start the server with ' +
63
+ 'HIPPO_ALLOW_KEYLESS_LOCAL=1 to let requests from this machine in without a key.';
59
64
  export function readAuthHeader(req) {
60
65
  const raw = req.headers['authorization'];
61
66
  if (raw === undefined)
@@ -149,7 +154,8 @@ async function askResolver(resolver, token, deadlineMs) {
149
154
  return clean;
150
155
  }
151
156
  const DEFAULT_RESOLVER_DEADLINE_MS = 5000;
152
- /** Runs only before scrypt, so junk, unknown, revoked and expired tokens and a proven key's re-check never spend a colleague's budget. */
157
+ /** Runs only before scrypt, so junk, unknown, revoked and expired
158
+ * tokens and a proven key's re-check never spend a colleague's budget. */
153
159
  function chargeScryptRun(req, opts) {
154
160
  const limiter = opts.failedAuthLimiter;
155
161
  // Reserving rather than peeking bounds scrypt runs exactly, even when concurrent misses await a slow store.
@@ -164,17 +170,24 @@ async function resolveBearer(req, token, opts) {
164
170
  const t = opts.authResolverTimeoutMs;
165
171
  const deadlineMs = t !== undefined && Number.isFinite(t) && t > 0 ? t : DEFAULT_RESOLVER_DEADLINE_MS;
166
172
  const clean = await askResolver(opts.authResolver, token, deadlineMs);
167
- return { ...clean, viaAuthResolver: true, owner: clean.subject }; // a resolver vouches for a person, never names one
173
+ // A resolver vouches for a person, never names one.
174
+ return { ...clean, viaAuthResolver: true, owner: clean.subject };
168
175
  }
169
176
  const key = await verifyApiKeyCached(token, opts.store, (keyId, derive) => {
170
- // The key's own bucket first, so a flood on one key id ends at its five tries and leaves the address's budget to the callers who share it.
177
+ // The key's own bucket first, so a flood on one key id ends at its five tries and leaves the address's budget to
178
+ // the callers who share it.
171
179
  keyChecks.admit(keyId, clientLimitKey(req));
172
180
  chargeScryptRun(req, opts);
173
181
  return keyChecks.run(derive);
174
182
  });
175
183
  if (!key)
176
184
  throw new HttpError(401, 'invalid api key');
177
- const id = { tenantId: key.tenantId, subject: `api_key:${key.keyId}`, role: key.role, scopes: key.scopes };
185
+ const id = {
186
+ tenantId: key.tenantId,
187
+ subject: `api_key:${key.keyId}`,
188
+ role: key.role,
189
+ scopes: key.scopes,
190
+ };
178
191
  if (key.ownerSubject)
179
192
  id.owner = key.ownerSubject;
180
193
  return id;
@@ -213,7 +226,7 @@ function bearerActor(id) {
213
226
  export const LIMITER_MAX_KEYS = 10_000;
214
227
  // One for the process, as the thread pool its derivations run on is.
215
228
  const keyChecks = keyCheckBounds(LIMITER_MAX_KEYS);
216
- const CALLER_WARN_EVERY_MS = 60_000;
229
+ const CALLER_WARN_EVERY_MS = MINUTE_MS;
217
230
  const callerWarnedAt = new Map();
218
231
  function warnCallerLimited(key, tenantId, person) {
219
232
  const now = Date.now();
@@ -240,8 +253,8 @@ function chargeCaller(tenantId, actor, opts) {
240
253
  warnCallerLimited(key, tenantId, person);
241
254
  throw new HttpError(429, 'rate limit exceeded for this caller', limiter.retryAfterSec);
242
255
  }
243
- /** Builds a per-request Context from the Authorization header and remote address; throws HttpError(401) for invalid or missing credentials.
244
- * Reads the store only for an API-key-shaped Bearer (or any Bearer when no auth resolver is registered), so keyless local requests stay cheap. */
256
+ /** Builds a per-request Context from the Authorization header and remote address; throws HttpError(401) on bad ones.
257
+ * Reads the store only for an API-key-shaped Bearer (or any Bearer with no resolver), so keyless calls stay cheap. */
245
258
  export async function buildContextWithAuth(req, opts) {
246
259
  const id = await checkAuth(req, opts);
247
260
  const ctx = contextFor(id, opts);
@@ -249,28 +262,46 @@ export async function buildContextWithAuth(req, opts) {
249
262
  chargeCaller(id.tenantId, ctx.actor, opts);
250
263
  return ctx;
251
264
  }
252
- /** The auth check again, uncharged, for a handler that authenticated with requireAuth before a slow body read and must re-check right before it acts. */
265
+ /** The auth check again, uncharged, for a handler that authenticated with requireAuth before a slow body read and
266
+ * must re-check right before it acts. */
253
267
  export async function recheckContextWithAuth(req, opts) {
254
268
  return contextFor(await checkAuth(req, opts), opts);
255
269
  }
256
- /** The keyless local caller: any process on this machine can reach loopback, so it is a member unless the operator names admin. */
270
+ /** The keyless local caller: any process on this machine can reach
271
+ * loopback, so it is a member unless the operator names admin. */
257
272
  function keylessLocalActor(opts) {
258
273
  const role = opts.keylessLocalRole ?? envKeylessLocalRole();
259
- return role === 'admin' ? { subject: 'localhost:cli', role: 'admin', hostAdmin: true } : { subject: 'localhost:cli', role: 'member' };
274
+ return role === 'admin'
275
+ ? { subject: 'localhost:cli', role: 'admin', hostAdmin: true }
276
+ : { subject: 'localhost:cli', role: 'member' };
260
277
  }
261
278
  function contextFor(id, opts) {
262
- if (id !== null)
263
- return { hippoRoot: opts.hippoRoot, tenantId: id.tenantId, actor: bearerActor(id), store: opts.store };
264
- return { hippoRoot: opts.hippoRoot, tenantId: resolveTenantId({}), actor: keylessLocalActor(opts), store: opts.store };
279
+ // Per request, never cached at serve: the global store can be created while the server runs.
280
+ const reach = sqliteReach(opts.hippoRoot, opts.store);
281
+ // loadConfig caches by file mtime, so each request still sees an edit made while the server runs.
282
+ const config = loadConfig(opts.hippoRoot);
283
+ if (id !== null) {
284
+ const actor = bearerActor(id);
285
+ return { hippoRoot: opts.hippoRoot, tenantId: id.tenantId, actor, store: opts.store, reach, config };
286
+ }
287
+ return {
288
+ hippoRoot: opts.hippoRoot,
289
+ tenantId: resolveTenantId({}),
290
+ actor: keylessLocalActor(opts),
291
+ store: opts.store,
292
+ reach,
293
+ config,
294
+ };
265
295
  }
266
- /** Auth check for routes that need no tenant Context (e.g. the MCP transport, which resolves its own root): throws HttpError 401 like buildContextWithAuth.
267
- * A keyless local request passes only under HIPPO_ALLOW_KEYLESS_LOCAL=1. */
296
+ /** Auth check for routes that need no tenant Context (e.g. the MCP transport, which resolves its own root): throws
297
+ * HttpError 401 like buildContextWithAuth. A keyless local request passes only under HIPPO_ALLOW_KEYLESS_LOCAL=1. */
268
298
  export async function requireAuth(req, opts) {
269
299
  const id = await checkAuth(req, opts);
270
300
  if (id !== null)
271
301
  chargeCaller(id.tenantId, bearerActor(id), opts);
272
302
  }
273
- /** Never rejects or charges a caller bucket: an outage (5xx) or a throttle (429) skips one tick; only a definite 4xx denial closes the stream. */
303
+ /** Never rejects or charges a caller bucket: an outage (5xx) or a throttle (429) skips one tick; only a definite 4xx
304
+ * denial closes the stream. */
274
305
  export async function heartbeatVerdict(req, opts) {
275
306
  try {
276
307
  await checkAuth(req, opts);
@@ -1,5 +1,7 @@
1
1
  import type { ServeOpts, ServerHandle } from './types.js';
2
- /** Boots the HTTP daemon on host:port and writes the pidfile under hippoRoot; refuses a non-loopback host unless HIPPO_REQUIRE_AUTH=1 and
2
+ /**
3
+ * Boots the HTTP daemon on host:port and writes the pidfile under hippoRoot; refuses a non-loopback host unless
4
+ * HIPPO_REQUIRE_AUTH=1 and
3
5
  * either `tls` or allowCleartext is given, and refuses HIPPO_CLIENT_IP_HEADER without HIPPO_TRUSTED_PROXIES.
4
6
  * Use port: 0 in tests for an ephemeral port. See docs/ARCHITECTURE.md#srcserverbootts. */
5
7
  export declare function serve(opts: ServeOpts): Promise<ServerHandle>;
@@ -1,18 +1,18 @@
1
1
  import { envAllowCleartext, envCallerRps, envPort, envRequireAuth, envV1Rps } from '../util/env.js';
2
2
  import { detectServer, removePidfileIfOwned, writePidfile } from './server-detect.js';
3
- import { outsideSqliteOffLoop, runWithRequestStores, SERVER_DB_WAIT_MS, withSqliteBlocked } from '../db/index.js';
4
3
  import { hasGroup } from '../store/index.js';
5
- import { isStoreBusy } from '../store/sqlite/busy.js';
6
- import { holdSqliteConnection } from '../store/sqlite/held-connection.js';
4
+ import { isStoreBusy } from '../api/busy.js';
5
+ import { createStoreHolder, offLoopFor, outsideRouteBlock, } from '../store/sqlite/held-connection.js';
7
6
  import { workerSqliteStore } from '../store/sqlite/worker-store.js';
8
7
  import { markSharedStore } from '../core/config.js';
9
8
  import { auditWriteFailureCount } from '../store/audit.js';
10
9
  import { PACKAGE_VERSION } from '../util/version.js';
10
+ import { MINUTE_MS } from '../util/time.js';
11
11
  import { errorFields, errorMessage, log } from '../util/log.js';
12
12
  import { runWithRequestId } from '../util/request-scope.js';
13
13
  import { createRateLimiter } from './rate-limit.js';
14
14
  import { RecallContractError } from '../api/index.js';
15
- import { BodyTimeoutError, BodyTooLargeError, closeAfterReply, DeadlineExceededError, HttpError, JSON_HEADERS, sendJson } from '../util/http-util.js';
15
+ import { BodyTimeoutError, BodyTooLargeError, closeAfterReply, DeadlineExceededError, HttpError, JSON_HEADERS, sendJson, } from '../util/http-util.js';
16
16
  import { workerCounts } from '../store/sqlite/executor-counts.js';
17
17
  import { isLocalCaller, LIMITER_MAX_KEYS } from './auth.js';
18
18
  import { assertClientIpHeaderPinned, enforceRateLimit } from './client-ip.js';
@@ -23,7 +23,7 @@ import { DEFAULT_SERVER_HOST, DEFAULT_SERVER_PORT } from './defaults.js';
23
23
  import { installCrashHandlers, installSignalHandlers } from '../util/crash-handlers.js';
24
24
  import { handleMcpPost, handleMcpStream } from './mcp-http.js';
25
25
  import { MCP_PROJECT_SCOPED_HEADER } from '../core/project-identity.js';
26
- import { accessRouteOf, logRequestFailure, noteAccess, openRequest, parseRequest, rejectEncodedSlash, replyFor, sendError } from './request.js';
26
+ import { accessRouteOf, logRequestFailure, noteAccess, openRequest, parseRequest, rejectEncodedSlash, replyFor, sendError, } from './request.js';
27
27
  import { assertTlsOrCleartextAllowed, createListener } from './tls.js';
28
28
  import { assertAddonRoutes, assertPublicJson } from './route-checks.js';
29
29
  import { dispatchAddonRoute, dispatchPublicJson, dispatchV1Route } from './route-table.js';
@@ -32,7 +32,8 @@ import { dispatchAddonRoute, dispatchPublicJson, dispatchV1Route } from './route
32
32
  function isAddressInfo(a) {
33
33
  return a !== null && typeof a !== 'string';
34
34
  }
35
- // Pinned at module load, bumped with package.json on releases; reading package.json synchronously here would couple the daemon to its install path,
35
+ // Pinned at module load, bumped with package.json on releases; reading package.json synchronously here would couple the
36
+ // daemon to its install path,
36
37
  // which tests that mkdtemp a hippoRoot avoid.
37
38
  const VERSION = PACKAGE_VERSION;
38
39
  const LOOPBACK_HOSTS = new Set(['127.0.0.1', '::1', 'localhost']);
@@ -42,7 +43,8 @@ async function handleRequest(req, res, opts, options) {
42
43
  // Node's URL parser collapses them and they slip past the route table.
43
44
  rejectEncodedSlash(req.url ?? '/');
44
45
  const { method, path, query } = parseRequest(req);
45
- // An older core ignores X-Hippo-Project, so every /mcp reply, a 429 or 401 too, tells the client this one filters by it.
46
+ // An older core ignores X-Hippo-Project, so every /mcp reply, a 429 or 401 too, tells the client this one filters by
47
+ // it.
46
48
  if (path === '/mcp')
47
49
  res.setHeader(MCP_PROJECT_SCOPED_HEADER, '1');
48
50
  if (method === 'GET' && path === '/health') {
@@ -57,19 +59,22 @@ async function handleRequest(req, res, opts, options) {
57
59
  }
58
60
  enforceRateLimit(req, path, limiter);
59
61
  const routeRequest = { req, res, opts, query };
60
- if (await runWithRequestStores(() => dispatchScopedRoute(routeRequest, method, path), { busyWaitMs: SERVER_DB_WAIT_MS }))
62
+ if (await dispatchScopedRoute(routeRequest, method, path))
61
63
  return;
62
- // A scope of its own, which the heartbeat timer keeps after it closes, so the key check and every
63
- // heartbeat wait the server's lock wait. Store-ready: the stream only authenticates, through the port.
64
+ // The request scope (the server's lock wait) is kept by the heartbeat timer after it closes, so the key check and
65
+ // every heartbeat wait that long. Store-ready: the stream only authenticates, through the port.
64
66
  if (method === 'GET' && path === '/mcp/stream') {
65
67
  noteAccess(req, { route: path });
66
- await runWithRequestStores(() => handleMcpStream(req, res, opts, streamSlots), { busyWaitMs: SERVER_DB_WAIT_MS });
68
+ await handleMcpStream(req, res, opts, streamSlots);
67
69
  return;
68
70
  }
69
71
  res.writeHead(404, JSON_HEADERS);
70
72
  res.end(JSON.stringify({ error: 'not found' }));
71
73
  }
72
- /** Every route that runs inside a request scope, so it opens each store once: the /v1 table with the webhooks, public JSON, add-on routes and POST /mcp. */
74
+ /**
75
+ * Every route that runs inside a request scope, so it opens each store once: the /v1 table with the webhooks, public
76
+ * JSON, add-on routes and POST /mcp.
77
+ */
73
78
  async function dispatchScopedRoute(r, method, path) {
74
79
  if (await dispatchV1Route(r, method, path))
75
80
  return true;
@@ -87,8 +92,10 @@ async function dispatchScopedRoute(r, method, path) {
87
92
  return false;
88
93
  }
89
94
  function sendHealth(req, res, startedAt) {
90
- // A caller on this machine (detectServer's probe reads version and pid) gets the full body; anyone else, even a proxied caller or a browser page on loopback,
91
- // gets liveness only: the version would fingerprint the build and the pid is noise. Platform health checks only need the 200.
95
+ // A caller on this machine (detectServer's probe reads version and pid) gets the full body; anyone else, even a
96
+ // proxied caller or a browser page on loopback,
97
+ // gets liveness only: the version would fingerprint the build and the pid is noise. Platform health checks only need
98
+ // the 200.
92
99
  if (isLocalCaller(req)) {
93
100
  sendJson(res, 200, {
94
101
  ok: true,
@@ -128,7 +135,8 @@ function assertBindable(host) {
128
135
  }
129
136
  }
130
137
  async function assertNoLiveServer(hippoRoot) {
131
- // Refuse to start if a live hippo server already serves this hippoRoot (detectServer probes the recorded /health and unlinks a stale pidfile):
138
+ // Refuse to start if a live hippo server already serves this hippoRoot (detectServer probes the recorded /health and
139
+ // unlinks a stale pidfile):
132
140
  // a concurrent `hippo serve` would race for the port and clobber the pidfile.
133
141
  const existing = await detectServer(hippoRoot);
134
142
  if (existing) {
@@ -136,35 +144,47 @@ async function assertNoLiveServer(hippoRoot) {
136
144
  `Stop that server before starting another on the same hippoRoot.`);
137
145
  }
138
146
  }
139
- // SHORTCUT: buckets live in this process and reset on restart or LRU eviction; move them to the store if serve ever runs as several processes.
147
+ // SHORTCUT: buckets live in this process and reset on restart or LRU eviction; move them to the store if serve ever
148
+ // runs as several processes.
140
149
  function limiterFor({ ratePerSec, burst }) {
141
- return createRateLimiter({ ratePerSec, burst, idleEvictMs: 60000, maxKeys: LIMITER_MAX_KEYS });
150
+ return createRateLimiter({ ratePerSec, burst, idleEvictMs: MINUTE_MS, maxKeys: LIMITER_MAX_KEYS });
142
151
  }
143
152
  function bootRateLimiter(perAddress) {
144
153
  if (perAddress === 'off')
145
154
  return undefined;
146
155
  if (perAddress !== undefined)
147
156
  return limiterFor(perAddress);
148
- // Per-IP rate limiter for /v1/* and /mcp*, built here (not at module scope) so HIPPO_V1_RPS is read at boot and a test can set it before serve().
149
- // A non-positive or non-finite value disables limiting (the opt-out knob).
150
- const v1Rps = Number(envV1Rps() ?? 20);
151
- return Number.isFinite(v1Rps) && v1Rps > 0 ? limiterFor({ ratePerSec: v1Rps, burst: v1Rps * 2 }) : undefined;
157
+ // Per-IP rate limiter for /v1/* and /mcp*, built here (not at module scope) so HIPPO_V1_RPS is read at boot and a
158
+ // test can set it before serve().
159
+ // A typo must not switch the limit off, so only an explicit 0 does.
160
+ const raw = envV1Rps();
161
+ const v1Rps = raw === undefined ? 20 : Number(raw);
162
+ if (!Number.isFinite(v1Rps) || v1Rps < 0) {
163
+ throw new Error(`HIPPO_V1_RPS must be a number of at least 0 (0 turns the per-address limit off), not '${raw}'`);
164
+ }
165
+ return v1Rps > 0 ? limiterFor({ ratePerSec: v1Rps, burst: v1Rps * 2 }) : undefined;
152
166
  }
153
167
  const DEFAULT_FAILED_AUTH = { ratePerSec: 20, burst: 40 };
154
168
  function assertRateLimitSpec(name, { ratePerSec, burst }) {
155
- if (!Number.isFinite(ratePerSec) || ratePerSec <= 0)
169
+ if (!Number.isFinite(ratePerSec) || ratePerSec <= 0) {
156
170
  throw new Error(`rateLimits.${name}.ratePerSec must be a finite number above 0`);
157
- if (!Number.isFinite(burst) || burst < 1)
171
+ }
172
+ if (!Number.isFinite(burst) || burst < 1) {
158
173
  throw new Error(`rateLimits.${name}.burst must be a finite number of at least 1`);
174
+ }
159
175
  }
160
176
  const DEFAULT_CALLER_RPS = 20;
161
- /** The per-caller spec when serve() names none: HIPPO_CALLER_RPS (0 is off), else 20 per second with a burst of twice that. */
177
+ /**
178
+ * The per-caller spec when serve() names none: HIPPO_CALLER_RPS (0 is off), else 20 per second with a burst of twice
179
+ * that.
180
+ */
162
181
  function defaultCallerSpec() {
163
182
  const raw = envCallerRps();
164
183
  const rps = raw === undefined ? DEFAULT_CALLER_RPS : Number(raw);
165
184
  // A typo must not switch the limit off, so only an explicit 0 does.
166
- if (!Number.isFinite(rps) || rps < 0)
185
+ if (!Number.isFinite(rps) || rps < 0) {
167
186
  throw new Error(`HIPPO_CALLER_RPS must be a number of at least 0 (0 turns the per-caller limit off), not '${raw}'`);
187
+ }
168
188
  return rps === 0 ? 'off' : { ratePerSec: rps, burst: Math.max(1, rps * 2) };
169
189
  }
170
190
  /** Refuses a bad spec at boot, since a NaN or zero rate would otherwise turn a bucket off or refuse every request. */
@@ -182,17 +202,6 @@ function bootLimiters(rateLimits) {
182
202
  failedAuthLimiter: limiterFor(failedAuthPerAddress),
183
203
  };
184
204
  }
185
- function createStoreHolder(hippoRoot, store) {
186
- if (hasGroup(store, 'localFiles'))
187
- return holdSqliteConnection(hippoRoot);
188
- log.info(`serve: the '${store.kind}' store serves ${hippoRoot}, so no hippo.db connection is held`);
189
- // A missed port under another store would otherwise create and write a hippo.db that store never reads.
190
- return { hold: () => { }, afterResponse: () => { }, release: async () => { }, runRequest: (run) => withSqliteBlocked(store.kind, run) };
191
- }
192
- // A plugin's resolver may read hippo.db through this package's synchronous functions, so it runs outside the block of a `loop: 'off'` route.
193
- function outsideRouteBlock(resolver) {
194
- return resolver && ((token) => outsideSqliteOffLoop(() => resolver(token)));
195
- }
196
205
  function replyWithFailure(req, res, err, requestId) {
197
206
  const mapped = replyFor(err);
198
207
  logRequestFailure(req, err, mapped.status);
@@ -203,10 +212,12 @@ function replyWithFailure(req, res, err, requestId) {
203
212
  catch { /* socket already gone */ }
204
213
  return;
205
214
  }
206
- if (isStoreBusy(err))
215
+ if (isStoreBusy(err)) {
207
216
  res.setHeader('Retry-After', '1');
208
- else if (err instanceof HttpError && err.retryAfterSec !== undefined)
217
+ }
218
+ else if (err instanceof HttpError && err.retryAfterSec !== undefined) {
209
219
  res.setHeader('Retry-After', String(err.retryAfterSec));
220
+ }
210
221
  if (mapped.status === 500) {
211
222
  // The id lets an operator find the logged cause without the client seeing internal text.
212
223
  sendJson(res, 500, { error: mapped.message, requestId });
@@ -221,29 +232,43 @@ function replyWithFailure(req, res, err, requestId) {
221
232
  sendJson(res, 504, { error: err.message, code: err.code, requestId });
222
233
  return;
223
234
  }
224
- // readBody hit its cap or deadline, so close once the 413 or 408 is out rather than drain what the client keeps sending.
225
- if (err instanceof BodyTooLargeError || err instanceof BodyTimeoutError)
235
+ // readBody hit its cap or deadline, so close once the 413 or 408 is out rather than drain what the client keeps
236
+ // sending.
237
+ if (err instanceof BodyTooLargeError || err instanceof BodyTimeoutError) {
226
238
  res.once('finish', () => closeAfterReply(req));
239
+ }
227
240
  sendError(res, mapped.status, mapped.message);
228
241
  }
229
242
  const HANDLER_LATE = 'the request did not finish by its deadline and was abandoned; a write it started may or may not be saved';
230
- // The caller already has its 504, so this line is the only trace of the failure. The path and the error text can hold caller data, so it carries neither.
243
+ // The caller already has its 504, so this line is the only trace of the failure. The path and the error text can hold
244
+ // caller data, so it carries neither.
231
245
  function logLateFailure(req, err, requestId) {
232
- const fields = { requestId, method: req.method ?? 'GET', route: accessRouteOf(req), failureStatus: replyFor(err).status };
246
+ const fields = {
247
+ requestId,
248
+ method: req.method ?? 'GET',
249
+ route: accessRouteOf(req),
250
+ failureStatus: replyFor(err).status,
251
+ };
233
252
  log.warn('request failed after its deadline reply', { ...fields, errorClass: errorFields(err).errorClass });
234
253
  }
235
- // A handler that ends after the 504 finds the response finished, so sending its own reply throws this: its work ran to the end.
254
+ // A handler that ends after the 504 finds the response finished, so sending its own reply throws this: its work ran to
255
+ // the end.
236
256
  function isDroppedLateReply(err) {
237
257
  return err instanceof Error && 'code' in err && err.code === 'ERR_HTTP_HEADERS_SENT';
238
258
  }
239
259
  /** A GET only reads; every other method this server routes can write. */
240
260
  const isRead = (method) => method === 'GET';
241
- // A read that ends late changed nothing. A write that ends late ran to its end after its caller was told it may not have been saved.
261
+ // A read that ends late changed nothing. A write that ends late ran to its end after its caller was told it may not
262
+ // have been saved.
242
263
  function logLateFinish(req, requestId) {
243
264
  const method = req.method ?? 'GET';
244
265
  if (isRead(method))
245
266
  return;
246
- log.info('request finished after its deadline reply; its own reply was dropped', { requestId, method, route: accessRouteOf(req) });
267
+ log.info('request finished after its deadline reply; its own reply was dropped', {
268
+ requestId,
269
+ method,
270
+ route: accessRouteOf(req),
271
+ });
247
272
  }
248
273
  function replyOrClose(req, res, err, requestId) {
249
274
  try {
@@ -255,14 +280,19 @@ function replyOrClose(req, res, err, requestId) {
255
280
  res.destroy();
256
281
  }
257
282
  }
258
- /** Runs `handle` under the request's id and deadline; a failure becomes the reply, unless the deadline has already answered. */
283
+ /**
284
+ * Runs `handle` under the request's id and deadline; a failure becomes the reply, unless the deadline has already
285
+ * answered.
286
+ */
259
287
  function answerRequest(req, res, handle, slowWarnMs) {
260
288
  const requestId = openRequest(req, res, slowWarnMs);
261
289
  const deadline = requestDeadlineFor(req);
290
+ const abort = deadline ? new AbortController() : undefined;
262
291
  // Inside the scope, so the failure reply's log line carries the id too.
263
292
  runWithRequestId(requestId, () => {
264
- if (deadline)
265
- answerAtDeadline(res, deadline, () => replyOrClose(req, res, new DeadlineExceededError(HANDLER_LATE), requestId));
293
+ if (deadline) {
294
+ answerAtDeadline(res, deadline, () => replyOrClose(req, res, new DeadlineExceededError(HANDLER_LATE), requestId), () => abort?.abort(new DeadlineExceededError(HANDLER_LATE)));
295
+ }
266
296
  handle().then(() => {
267
297
  if (isAbandoned(res))
268
298
  logLateFinish(req, requestId);
@@ -274,7 +304,7 @@ function answerRequest(req, res, handle, slowWarnMs) {
274
304
  else
275
305
  logLateFailure(req, err, requestId);
276
306
  });
277
- }, deadline);
307
+ }, deadline, abort?.signal);
278
308
  }
279
309
  function listenOn(server, port, host) {
280
310
  return new Promise((resolve, reject) => {
@@ -298,7 +328,9 @@ function exitOnSignalOrCrash(stop, drainMs) {
298
328
  installSignalHandlers('serve', shutdown);
299
329
  installCrashHandlers('serve', shutdown);
300
330
  }
301
- /** Boots the HTTP daemon on host:port and writes the pidfile under hippoRoot; refuses a non-loopback host unless HIPPO_REQUIRE_AUTH=1 and
331
+ /**
332
+ * Boots the HTTP daemon on host:port and writes the pidfile under hippoRoot; refuses a non-loopback host unless
333
+ * HIPPO_REQUIRE_AUTH=1 and
302
334
  * either `tls` or allowCleartext is given, and refuses HIPPO_CLIENT_IP_HEADER without HIPPO_TRUSTED_PROXIES.
303
335
  * Use port: 0 in tests for an ephemeral port. See docs/ARCHITECTURE.md#srcserverbootts. */
304
336
  export async function serve(opts) {
@@ -310,7 +342,8 @@ export async function serve(opts) {
310
342
  assertBindable(host);
311
343
  assertTlsOrCleartextAllowed(host, opts.tls, LOOPBACK_HOSTS, opts.allowCleartext ?? envAllowCleartext());
312
344
  await assertNoLiveServer(opts.hippoRoot);
313
- // Single source of truth for the start time: returned by GET /health and written into the pidfile, so detectServer can prove a pid-reusing impostor is not
345
+ // Single source of truth for the start time: returned by GET /health and written into the pidfile, so detectServer
346
+ // can prove a pid-reusing impostor is not
314
347
  // this server.
315
348
  const startedAt = new Date().toISOString();
316
349
  // Open /mcp/stream count per client key, so the cap is per server rather than per process.
@@ -343,15 +376,20 @@ export async function serve(opts) {
343
376
  }
344
377
  function frozenAddonRoutes(addonRoutes) {
345
378
  // A frozen copy, so a route the caller adds or renames after boot never skips the check below.
346
- const routes = Object.freeze((addonRoutes ?? []).map(({ path, handler, storeReady }) => Object.freeze(storeReady === undefined
347
- ? { path, handler }
348
- : { path, handler, storeReady })));
379
+ const routes = Object.freeze((addonRoutes ?? []).map(({ path, handler, storeReady }) => Object.freeze(storeReady === undefined ? { path, handler } : { path, handler, storeReady })));
349
380
  assertAddonRoutes(routes);
350
381
  return routes;
351
382
  }
352
383
  function servedOptsFor(opts, routes, publicJsonBodies, { callerLimiter, failedAuthLimiter }) {
384
+ const store = opts.store ?? workerSqliteStore(opts.hippoRoot);
353
385
  return {
354
- ...opts, routes, publicJsonBodies, store: opts.store ?? workerSqliteStore(opts.hippoRoot), callerLimiter, failedAuthLimiter,
386
+ ...opts,
387
+ routes,
388
+ publicJsonBodies,
389
+ store,
390
+ offLoop: offLoopFor(store),
391
+ callerLimiter,
392
+ failedAuthLimiter,
355
393
  authResolver: outsideRouteBlock(opts.authResolver),
356
394
  };
357
395
  }
@@ -375,7 +413,8 @@ async function listenAndDescribe(server, port, host, tls) {
375
413
  return { port: actualPort, url };
376
414
  }
377
415
  async function stopListening(opts, server, inflight, startedAt) {
378
- // Remove the pidfile only if it still names this server: a newer server may have rewritten it, and an unconditional unlink would orphan it.
416
+ // Remove the pidfile only if it still names this server: a newer server may have rewritten it, and an unconditional
417
+ // unlink would orphan it.
379
418
  removePidfileIfOwned(opts.hippoRoot, { pid: process.pid, startedAt });
380
419
  await drainAndClose(server, inflight, opts.shutdownDrainMs ?? DEFAULT_SHUTDOWN_DRAIN_MS);
381
420
  }
@@ -1,11 +1,18 @@
1
1
  import type { IncomingMessage } from 'node:http';
2
2
  import type { RateLimiter } from './rate-limit.js';
3
3
  /**
4
- * Rate-limit key: the socket's remote address, which behind a TLS proxy collapses into one bucket unauthenticated traffic can drain.
5
- * HIPPO_CLIENT_IP_HEADER (fly-client-ip on Fly) is read only from a peer in HIPPO_TRUSTED_PROXIES (IPs or CIDRs, or `*` for any peer),
6
- * so a caller that reaches the port past the proxy cannot pick its own bucket. In a comma-joined chain the key is the rightmost hop no trusted proxy added. */
4
+ * Rate-limit key: the socket's remote address, which behind a TLS proxy collapses into one bucket unauthenticated
5
+ * traffic can drain.
6
+ * HIPPO_CLIENT_IP_HEADER (fly-client-ip on Fly) is read only from a peer in HIPPO_TRUSTED_PROXIES (IPs or CIDRs, or `*`
7
+ * for any peer),
8
+ * so a caller that reaches the port past the proxy cannot pick its own bucket. In a comma-joined chain the key is the
9
+ * rightmost hop no trusted proxy added.
10
+ */
7
11
  export declare function clientIpForRateLimit(req: IncomingMessage): string;
8
- /** serve() refused HIPPO_CLIENT_IP_HEADER with no HIPPO_TRUSTED_PROXIES: the header would be read from no one, so the setting is a mistake. */
12
+ /**
13
+ * serve() refused HIPPO_CLIENT_IP_HEADER with no HIPPO_TRUSTED_PROXIES: the header would be read from no one, so the
14
+ * setting is a mistake.
15
+ */
9
16
  export declare class UntrustedClientIpHeaderError extends Error {
10
17
  readonly header: string;
11
18
  constructor(header: string);
@@ -5,9 +5,13 @@ import { log } from '../util/log.js';
5
5
  import { HttpError } from '../util/http-util.js';
6
6
  const IPV6_PREFIX_GROUPS = 4;
7
7
  /**
8
- * Rate-limit key: the socket's remote address, which behind a TLS proxy collapses into one bucket unauthenticated traffic can drain.
9
- * HIPPO_CLIENT_IP_HEADER (fly-client-ip on Fly) is read only from a peer in HIPPO_TRUSTED_PROXIES (IPs or CIDRs, or `*` for any peer),
10
- * so a caller that reaches the port past the proxy cannot pick its own bucket. In a comma-joined chain the key is the rightmost hop no trusted proxy added. */
8
+ * Rate-limit key: the socket's remote address, which behind a TLS proxy collapses into one bucket unauthenticated
9
+ * traffic can drain.
10
+ * HIPPO_CLIENT_IP_HEADER (fly-client-ip on Fly) is read only from a peer in HIPPO_TRUSTED_PROXIES (IPs or CIDRs, or `*`
11
+ * for any peer),
12
+ * so a caller that reaches the port past the proxy cannot pick its own bucket. In a comma-joined chain the key is the
13
+ * rightmost hop no trusted proxy added.
14
+ */
11
15
  export function clientIpForRateLimit(req) {
12
16
  const socketIp = req.socket.remoteAddress ?? 'unknown';
13
17
  const header = envClientIpHeader();
@@ -57,12 +61,17 @@ function proxyTrust(raw) {
57
61
  trustedProxyCache = { raw: value, list };
58
62
  return list;
59
63
  }
60
- /** serve() refused HIPPO_CLIENT_IP_HEADER with no HIPPO_TRUSTED_PROXIES: the header would be read from no one, so the setting is a mistake. */
64
+ /**
65
+ * serve() refused HIPPO_CLIENT_IP_HEADER with no HIPPO_TRUSTED_PROXIES: the header would be read from no one, so the
66
+ * setting is a mistake.
67
+ */
61
68
  export class UntrustedClientIpHeaderError extends Error {
62
69
  header;
63
70
  constructor(header) {
64
- super(`hippo serve: HIPPO_CLIENT_IP_HEADER is ${header} but HIPPO_TRUSTED_PROXIES is unset, so no peer may set that header. ` +
65
- "Set HIPPO_TRUSTED_PROXIES to the proxy's addresses or CIDRs, or to * when the proxy is the only peer that can reach this port.");
71
+ super(`hippo serve: HIPPO_CLIENT_IP_HEADER is ${header} but HIPPO_TRUSTED_PROXIES is unset, so no peer may set that ` +
72
+ `header. ` +
73
+ "Set HIPPO_TRUSTED_PROXIES to the proxy's addresses or CIDRs, or to * when the proxy is the only peer that " +
74
+ "can reach this port.");
66
75
  this.header = header;
67
76
  this.name = 'UntrustedClientIpHeaderError';
68
77
  }
@@ -76,7 +85,10 @@ export function assertClientIpHeaderPinned() {
76
85
  if (trust === undefined)
77
86
  throw new UntrustedClientIpHeaderError(header);
78
87
  if (trust === ANY_PEER) {
79
- log.warn(`serve: HIPPO_TRUSTED_PROXIES is *, so ${header} is read from any peer; keep the proxy the only route to this port.`);
88
+ log.warn(`serve: HIPPO_TRUSTED_PROXIES is *, so ${header} is read from any peer: a client that reaches this port ` +
89
+ `without the proxy can put any address ` +
90
+ `in ${header} and so escape every per-address limit. Keep the proxy the only route to this port, or list the ` +
91
+ `proxy's addresses instead of *.`);
80
92
  }
81
93
  }
82
94
  /** The key for one subscriber: an IPv6 address's /64, since one host may hold the whole /64; any other key as is. */
@@ -92,7 +104,10 @@ function subscriberKey(ip) {
92
104
  // A trailing dotted quad holds two groups; isIP has already checked the shape.
93
105
  const rightGroups = right.length + (right.at(-1)?.includes('.') ? 1 : 0);
94
106
  const groups = tail === undefined ? left : [...left, ...Array(8 - left.length - rightGroups).fill('0'), ...right];
95
- return `${groups.slice(0, IPV6_PREFIX_GROUPS).map((g) => parseInt(g, 16).toString(16)).join(':')}::/64`;
107
+ return `${groups
108
+ .slice(0, IPV6_PREFIX_GROUPS)
109
+ .map((g) => parseInt(g, 16).toString(16))
110
+ .join(':')}::/64`;
96
111
  }
97
112
  /** The one key every per-address limit and slot count uses, so rotating inside a /64 never buys a fresh bucket. */
98
113
  export function clientLimitKey(req) {
@@ -104,8 +119,10 @@ function isTrustedProxy(list, ip) {
104
119
  return family !== 0 && list.check(bare, family === 6 ? 'ipv6' : 'ipv4');
105
120
  }
106
121
  export function enforceRateLimit(req, path, limiter) {
107
- // Per-IP rate limit on /v1/* and /mcp* to bound api-key-id enumeration; /health and other paths are never throttled, and a 429 lands in the createServer
108
- // catch. Keyed per clientIpForRateLimit (set HIPPO_CLIENT_IP_HEADER behind a TLS-terminating proxy, or all clients share one bucket).
122
+ // Per-IP rate limit on /v1/* and /mcp* to bound api-key-id enumeration; /health and other paths are never throttled,
123
+ // and a 429 lands in the createServer
124
+ // catch. Keyed per clientIpForRateLimit (set HIPPO_CLIENT_IP_HEADER behind a TLS-terminating proxy, or all clients
125
+ // share one bucket).
109
126
  if (limiter && (path.startsWith('/v1/') || path === '/mcp' || path === '/mcp/stream')) {
110
127
  if (!limiter.check(clientLimitKey(req))) {
111
128
  throw new HttpError(429, 'rate limit exceeded', limiter.retryAfterSec);