@namzu/sdk 49.0.0 → 50.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 (737) hide show
  1. package/CHANGELOG.md +507 -0
  2. package/README.md +137 -125
  3. package/dist/agents/QueryAgent.d.ts.map +1 -1
  4. package/dist/agents/QueryAgent.js +1 -0
  5. package/dist/agents/QueryAgent.js.map +1 -1
  6. package/dist/agents/examples/SupervisorAgent.d.ts.map +1 -1
  7. package/dist/agents/examples/SupervisorAgent.js +1 -0
  8. package/dist/agents/examples/SupervisorAgent.js.map +1 -1
  9. package/dist/agents/runAgent.d.ts +2 -0
  10. package/dist/agents/runAgent.d.ts.map +1 -1
  11. package/dist/agents/runAgent.js +1 -0
  12. package/dist/agents/runAgent.js.map +1 -1
  13. package/dist/authorization/shell-lexer.d.ts.map +1 -1
  14. package/dist/authorization/shell-lexer.js +16 -1
  15. package/dist/authorization/shell-lexer.js.map +1 -1
  16. package/dist/bridge/acp/permission.d.ts +8 -2
  17. package/dist/bridge/acp/permission.d.ts.map +1 -1
  18. package/dist/bridge/acp/permission.js +1 -0
  19. package/dist/bridge/acp/permission.js.map +1 -1
  20. package/dist/bridge/acp/server.d.ts +25 -1
  21. package/dist/bridge/acp/server.d.ts.map +1 -1
  22. package/dist/bridge/acp/server.js +205 -21
  23. package/dist/bridge/acp/server.js.map +1 -1
  24. package/dist/bridge/acp/tasks.d.ts +5 -0
  25. package/dist/bridge/acp/tasks.d.ts.map +1 -0
  26. package/dist/bridge/acp/tasks.js +19 -0
  27. package/dist/bridge/acp/tasks.js.map +1 -0
  28. package/dist/bridge/acp/update.d.ts.map +1 -1
  29. package/dist/bridge/acp/update.js +148 -13
  30. package/dist/bridge/acp/update.js.map +1 -1
  31. package/dist/config/runtime.d.ts +31 -31
  32. package/dist/connector/mcp/adapter.d.ts.map +1 -1
  33. package/dist/connector/mcp/adapter.js +11 -4
  34. package/dist/connector/mcp/adapter.js.map +1 -1
  35. package/dist/connector/mcp/client.d.ts.map +1 -1
  36. package/dist/connector/mcp/client.js +6 -3
  37. package/dist/connector/mcp/client.js.map +1 -1
  38. package/dist/constants/acp/index.d.ts +3 -0
  39. package/dist/constants/acp/index.d.ts.map +1 -1
  40. package/dist/constants/acp/index.js +3 -0
  41. package/dist/constants/acp/index.js.map +1 -1
  42. package/dist/contracts/a2a.d.ts +80 -80
  43. package/dist/contracts/schemas.d.ts +2 -2
  44. package/dist/contracts/session/schemas.d.ts +10 -10
  45. package/dist/manager/agent/lifecycle.d.ts +11 -0
  46. package/dist/manager/agent/lifecycle.d.ts.map +1 -1
  47. package/dist/manager/agent/lifecycle.js +178 -3
  48. package/dist/manager/agent/lifecycle.js.map +1 -1
  49. package/dist/manager/plan/lifecycle.d.ts +7 -8
  50. package/dist/manager/plan/lifecycle.d.ts.map +1 -1
  51. package/dist/manager/plan/lifecycle.js +7 -8
  52. package/dist/manager/plan/lifecycle.js.map +1 -1
  53. package/dist/manager/resident/consumption.d.ts +8 -8
  54. package/dist/manager/resident/learning-cycle.d.ts +2 -2
  55. package/dist/manager/resident/learning-observation.d.ts +12 -12
  56. package/dist/manager/resident/learning.d.ts +82 -82
  57. package/dist/manager/resident/outbox.d.ts +8 -8
  58. package/dist/manager/resident/proposal.d.ts +2 -2
  59. package/dist/manager/resident/store.d.ts +10 -10
  60. package/dist/manager/session/attribution.d.ts +1 -0
  61. package/dist/manager/session/attribution.d.ts.map +1 -1
  62. package/dist/manager/session/attribution.js +9 -1
  63. package/dist/manager/session/attribution.js.map +1 -1
  64. package/dist/manager/session/streamed-message-identity.d.ts +6 -0
  65. package/dist/manager/session/streamed-message-identity.d.ts.map +1 -0
  66. package/dist/manager/session/streamed-message-identity.js +14 -0
  67. package/dist/manager/session/streamed-message-identity.js.map +1 -0
  68. package/dist/manager/session/turn-recorder.d.ts.map +1 -1
  69. package/dist/manager/session/turn-recorder.js +4 -3
  70. package/dist/manager/session/turn-recorder.js.map +1 -1
  71. package/dist/pals/activity/causality.d.ts +23 -0
  72. package/dist/pals/activity/causality.d.ts.map +1 -0
  73. package/dist/pals/activity/causality.js +205 -0
  74. package/dist/pals/activity/causality.js.map +1 -0
  75. package/dist/pals/activity/projection.d.ts +5 -0
  76. package/dist/pals/activity/projection.d.ts.map +1 -0
  77. package/dist/pals/activity/projection.js +79 -0
  78. package/dist/pals/activity/projection.js.map +1 -0
  79. package/dist/pals/activity/source.d.ts +16 -0
  80. package/dist/pals/activity/source.d.ts.map +1 -0
  81. package/dist/pals/activity/source.js +235 -0
  82. package/dist/pals/activity/source.js.map +1 -0
  83. package/dist/pals/activity/subscription-policy.d.ts +38 -0
  84. package/dist/pals/activity/subscription-policy.d.ts.map +1 -0
  85. package/dist/pals/activity/subscription-policy.js +183 -0
  86. package/dist/pals/activity/subscription-policy.js.map +1 -0
  87. package/dist/pals/activity/subscription-schema.d.ts +353 -0
  88. package/dist/pals/activity/subscription-schema.d.ts.map +1 -0
  89. package/dist/pals/activity/subscription-schema.js +24 -0
  90. package/dist/pals/activity/subscription-schema.js.map +1 -0
  91. package/dist/pals/activity/subscription-store.d.ts +25 -0
  92. package/dist/pals/activity/subscription-store.d.ts.map +1 -0
  93. package/dist/pals/activity/subscription-store.js +152 -0
  94. package/dist/pals/activity/subscription-store.js.map +1 -0
  95. package/dist/pals/activity/subscription-types.d.ts +42 -0
  96. package/dist/pals/activity/subscription-types.d.ts.map +1 -0
  97. package/dist/pals/activity/subscription-types.js +2 -0
  98. package/dist/pals/activity/subscription-types.js.map +1 -0
  99. package/dist/pals/activity/subscriptions.d.ts +32 -0
  100. package/dist/pals/activity/subscriptions.d.ts.map +1 -0
  101. package/dist/pals/activity/subscriptions.js +151 -0
  102. package/dist/pals/activity/subscriptions.js.map +1 -0
  103. package/dist/pals/activity/types.d.ts +77 -0
  104. package/dist/pals/activity/types.d.ts.map +1 -0
  105. package/dist/pals/activity/types.js +2 -0
  106. package/dist/pals/activity/types.js.map +1 -0
  107. package/dist/pals/channels/ingress.d.ts +9 -0
  108. package/dist/pals/channels/ingress.d.ts.map +1 -0
  109. package/dist/pals/channels/ingress.js +131 -0
  110. package/dist/pals/channels/ingress.js.map +1 -0
  111. package/dist/pals/channels/routes.d.ts +20 -0
  112. package/dist/pals/channels/routes.d.ts.map +1 -0
  113. package/dist/pals/channels/routes.js +111 -0
  114. package/dist/pals/channels/routes.js.map +1 -0
  115. package/dist/pals/channels/routing.d.ts +37 -0
  116. package/dist/pals/channels/routing.d.ts.map +1 -0
  117. package/dist/pals/channels/routing.js +150 -0
  118. package/dist/pals/channels/routing.js.map +1 -0
  119. package/dist/pals/channels/schema.d.ts +234 -0
  120. package/dist/pals/channels/schema.d.ts.map +1 -0
  121. package/dist/pals/channels/schema.js +94 -0
  122. package/dist/pals/channels/schema.js.map +1 -0
  123. package/dist/pals/channels/types.d.ts +115 -0
  124. package/dist/pals/channels/types.d.ts.map +1 -0
  125. package/dist/pals/channels/types.js +2 -0
  126. package/dist/pals/channels/types.js.map +1 -0
  127. package/dist/pals/communication/broker.d.ts +8 -0
  128. package/dist/pals/communication/broker.d.ts.map +1 -0
  129. package/dist/pals/communication/broker.js +121 -0
  130. package/dist/pals/communication/broker.js.map +1 -0
  131. package/dist/pals/communication/dispatch.d.ts +4 -0
  132. package/dist/pals/communication/dispatch.d.ts.map +1 -0
  133. package/dist/pals/communication/dispatch.js +57 -0
  134. package/dist/pals/communication/dispatch.js.map +1 -0
  135. package/dist/pals/communication/inbound.d.ts +9 -0
  136. package/dist/pals/communication/inbound.d.ts.map +1 -0
  137. package/dist/pals/communication/inbound.js +155 -0
  138. package/dist/pals/communication/inbound.js.map +1 -0
  139. package/dist/pals/communication/ingress-dispatch.d.ts +5 -0
  140. package/dist/pals/communication/ingress-dispatch.d.ts.map +1 -0
  141. package/dist/pals/communication/ingress-dispatch.js +51 -0
  142. package/dist/pals/communication/ingress-dispatch.js.map +1 -0
  143. package/dist/pals/communication/ingress-inbound.d.ts +9 -0
  144. package/dist/pals/communication/ingress-inbound.d.ts.map +1 -0
  145. package/dist/pals/communication/ingress-inbound.js +222 -0
  146. package/dist/pals/communication/ingress-inbound.js.map +1 -0
  147. package/dist/pals/communication/ingress-schema.d.ts +7829 -0
  148. package/dist/pals/communication/ingress-schema.d.ts.map +1 -0
  149. package/dist/pals/communication/ingress-schema.js +479 -0
  150. package/dist/pals/communication/ingress-schema.js.map +1 -0
  151. package/dist/pals/communication/ingress-types.d.ts +187 -0
  152. package/dist/pals/communication/ingress-types.d.ts.map +1 -0
  153. package/dist/pals/communication/ingress-types.js +73 -0
  154. package/dist/pals/communication/ingress-types.js.map +1 -0
  155. package/dist/pals/communication/operator.d.ts +75 -0
  156. package/dist/pals/communication/operator.d.ts.map +1 -0
  157. package/dist/pals/communication/operator.js +217 -0
  158. package/dist/pals/communication/operator.js.map +1 -0
  159. package/dist/pals/communication/policy.d.ts +41 -0
  160. package/dist/pals/communication/policy.d.ts.map +1 -0
  161. package/dist/pals/communication/policy.js +138 -0
  162. package/dist/pals/communication/policy.js.map +1 -0
  163. package/dist/pals/communication/schema.d.ts +2000 -0
  164. package/dist/pals/communication/schema.d.ts.map +1 -0
  165. package/dist/pals/communication/schema.js +170 -0
  166. package/dist/pals/communication/schema.js.map +1 -0
  167. package/dist/pals/communication/store.d.ts +61 -0
  168. package/dist/pals/communication/store.d.ts.map +1 -0
  169. package/dist/pals/communication/store.js +450 -0
  170. package/dist/pals/communication/store.js.map +1 -0
  171. package/dist/pals/communication/tools.d.ts +23 -0
  172. package/dist/pals/communication/tools.d.ts.map +1 -0
  173. package/dist/pals/communication/tools.js +107 -0
  174. package/dist/pals/communication/tools.js.map +1 -0
  175. package/dist/pals/communication/types.d.ts +168 -0
  176. package/dist/pals/communication/types.d.ts.map +1 -0
  177. package/dist/pals/communication/types.js +24 -0
  178. package/dist/pals/communication/types.js.map +1 -0
  179. package/dist/pals/communication/verify.d.ts +22 -0
  180. package/dist/pals/communication/verify.d.ts.map +1 -0
  181. package/dist/pals/communication/verify.js +142 -0
  182. package/dist/pals/communication/verify.js.map +1 -0
  183. package/dist/pals/lifecycle.d.ts +37 -0
  184. package/dist/pals/lifecycle.d.ts.map +1 -0
  185. package/dist/pals/lifecycle.js +22 -0
  186. package/dist/pals/lifecycle.js.map +1 -0
  187. package/dist/pals/prompt.d.ts +30 -0
  188. package/dist/pals/prompt.d.ts.map +1 -0
  189. package/dist/pals/prompt.js +65 -0
  190. package/dist/pals/prompt.js.map +1 -0
  191. package/dist/pals/reference-images.d.ts +44 -0
  192. package/dist/pals/reference-images.d.ts.map +1 -0
  193. package/dist/pals/reference-images.js +248 -0
  194. package/dist/pals/reference-images.js.map +1 -0
  195. package/dist/pals/runtime.d.ts +46 -0
  196. package/dist/pals/runtime.d.ts.map +1 -0
  197. package/dist/pals/runtime.js +624 -0
  198. package/dist/pals/runtime.js.map +1 -0
  199. package/dist/pals/store.d.ts +26 -0
  200. package/dist/pals/store.d.ts.map +1 -0
  201. package/dist/pals/store.js +334 -0
  202. package/dist/pals/store.js.map +1 -0
  203. package/dist/pals/types.d.ts +145 -0
  204. package/dist/pals/types.d.ts.map +1 -0
  205. package/dist/pals/types.js +2 -0
  206. package/dist/pals/types.js.map +1 -0
  207. package/dist/peers/envelope.js +1 -1
  208. package/dist/peers/envelope.js.map +1 -1
  209. package/dist/peers/protocol.d.ts +83 -83
  210. package/dist/peers/record.d.ts +10 -10
  211. package/dist/plugin/shell-hook.d.ts.map +1 -1
  212. package/dist/plugin/shell-hook.js +7 -2
  213. package/dist/plugin/shell-hook.js.map +1 -1
  214. package/dist/process/kill-tree.d.ts.map +1 -1
  215. package/dist/process/kill-tree.js +9 -1
  216. package/dist/process/kill-tree.js.map +1 -1
  217. package/dist/provider/errors.d.ts +19 -0
  218. package/dist/provider/errors.d.ts.map +1 -1
  219. package/dist/provider/errors.js +123 -2
  220. package/dist/provider/errors.js.map +1 -1
  221. package/dist/public-runtime.d.ts +41 -13
  222. package/dist/public-runtime.d.ts.map +1 -1
  223. package/dist/public-runtime.js +35 -7
  224. package/dist/public-runtime.js.map +1 -1
  225. package/dist/public-tools.d.ts +8 -3
  226. package/dist/public-tools.d.ts.map +1 -1
  227. package/dist/public-tools.js +8 -3
  228. package/dist/public-tools.js.map +1 -1
  229. package/dist/public-types.d.ts +27 -7
  230. package/dist/public-types.d.ts.map +1 -1
  231. package/dist/registry/tool/presentation.d.ts +1 -0
  232. package/dist/registry/tool/presentation.d.ts.map +1 -1
  233. package/dist/registry/tool/presentation.js +9 -7
  234. package/dist/registry/tool/presentation.js.map +1 -1
  235. package/dist/runtime/harness-session/index.d.ts +5 -0
  236. package/dist/runtime/harness-session/index.d.ts.map +1 -0
  237. package/dist/runtime/harness-session/index.js +928 -0
  238. package/dist/runtime/harness-session/index.js.map +1 -0
  239. package/dist/runtime/harness-session/journal.d.ts +37 -0
  240. package/dist/runtime/harness-session/journal.d.ts.map +1 -0
  241. package/dist/runtime/harness-session/journal.js +177 -0
  242. package/dist/runtime/harness-session/journal.js.map +1 -0
  243. package/dist/runtime/harness-session/saved-view.d.ts +8 -0
  244. package/dist/runtime/harness-session/saved-view.d.ts.map +1 -0
  245. package/dist/runtime/harness-session/saved-view.js +112 -0
  246. package/dist/runtime/harness-session/saved-view.js.map +1 -0
  247. package/dist/runtime/jobs/awaited-jobs.d.ts +2 -1
  248. package/dist/runtime/jobs/awaited-jobs.d.ts.map +1 -1
  249. package/dist/runtime/jobs/awaited-jobs.js +2 -1
  250. package/dist/runtime/jobs/awaited-jobs.js.map +1 -1
  251. package/dist/runtime/jobs/registry.d.ts +56 -1
  252. package/dist/runtime/jobs/registry.d.ts.map +1 -1
  253. package/dist/runtime/jobs/registry.js +351 -34
  254. package/dist/runtime/jobs/registry.js.map +1 -1
  255. package/dist/runtime/query/abandon-turn.d.ts +12 -1
  256. package/dist/runtime/query/abandon-turn.d.ts.map +1 -1
  257. package/dist/runtime/query/abandon-turn.js +3 -1
  258. package/dist/runtime/query/abandon-turn.js.map +1 -1
  259. package/dist/runtime/query/checkpoint.d.ts +4 -0
  260. package/dist/runtime/query/checkpoint.d.ts.map +1 -1
  261. package/dist/runtime/query/checkpoint.js +10 -0
  262. package/dist/runtime/query/checkpoint.js.map +1 -1
  263. package/dist/runtime/query/durable-inbound.d.ts +5 -0
  264. package/dist/runtime/query/durable-inbound.d.ts.map +1 -0
  265. package/dist/runtime/query/durable-inbound.js +89 -0
  266. package/dist/runtime/query/durable-inbound.js.map +1 -0
  267. package/dist/runtime/query/events.d.ts +4 -0
  268. package/dist/runtime/query/events.d.ts.map +1 -1
  269. package/dist/runtime/query/events.js +22 -5
  270. package/dist/runtime/query/events.js.map +1 -1
  271. package/dist/runtime/query/executor/tool-call-admission.d.ts +5 -1
  272. package/dist/runtime/query/executor/tool-call-admission.d.ts.map +1 -1
  273. package/dist/runtime/query/executor/tool-call-admission.js +85 -13
  274. package/dist/runtime/query/executor/tool-call-admission.js.map +1 -1
  275. package/dist/runtime/query/executor.d.ts +41 -18
  276. package/dist/runtime/query/executor.d.ts.map +1 -1
  277. package/dist/runtime/query/executor.js +227 -114
  278. package/dist/runtime/query/executor.js.map +1 -1
  279. package/dist/runtime/query/index.d.ts +3 -0
  280. package/dist/runtime/query/index.d.ts.map +1 -1
  281. package/dist/runtime/query/index.js +21 -4
  282. package/dist/runtime/query/index.js.map +1 -1
  283. package/dist/runtime/query/iteration/index.d.ts +18 -6
  284. package/dist/runtime/query/iteration/index.d.ts.map +1 -1
  285. package/dist/runtime/query/iteration/index.js +144 -67
  286. package/dist/runtime/query/iteration/index.js.map +1 -1
  287. package/dist/runtime/query/iteration/outstanding-work.d.ts +9 -5
  288. package/dist/runtime/query/iteration/outstanding-work.d.ts.map +1 -1
  289. package/dist/runtime/query/iteration/outstanding-work.js +61 -6
  290. package/dist/runtime/query/iteration/outstanding-work.js.map +1 -1
  291. package/dist/runtime/query/iteration/phases/context.d.ts +4 -0
  292. package/dist/runtime/query/iteration/phases/context.d.ts.map +1 -1
  293. package/dist/runtime/query/iteration/phases/context.js.map +1 -1
  294. package/dist/runtime/query/iteration/phases/tool-review.d.ts.map +1 -1
  295. package/dist/runtime/query/iteration/phases/tool-review.js +99 -16
  296. package/dist/runtime/query/iteration/phases/tool-review.js.map +1 -1
  297. package/dist/runtime/query/observation-context.d.ts +2 -2
  298. package/dist/runtime/query/observation-context.d.ts.map +1 -1
  299. package/dist/runtime/query/observation-context.js +20 -13
  300. package/dist/runtime/query/observation-context.js.map +1 -1
  301. package/dist/runtime/query/prepare-turn.js +2 -2
  302. package/dist/runtime/query/prepare-turn.js.map +1 -1
  303. package/dist/runtime/query/prompt-cache.d.ts +1 -0
  304. package/dist/runtime/query/prompt-cache.d.ts.map +1 -1
  305. package/dist/runtime/query/prompt-cache.js +2 -0
  306. package/dist/runtime/query/prompt-cache.js.map +1 -1
  307. package/dist/runtime/query/prompt.d.ts +2 -0
  308. package/dist/runtime/query/prompt.d.ts.map +1 -1
  309. package/dist/runtime/query/prompt.js +23 -1
  310. package/dist/runtime/query/prompt.js.map +1 -1
  311. package/dist/runtime/query/repeat-call.d.ts +12 -3
  312. package/dist/runtime/query/repeat-call.d.ts.map +1 -1
  313. package/dist/runtime/query/repeat-call.js +33 -10
  314. package/dist/runtime/query/repeat-call.js.map +1 -1
  315. package/dist/runtime/query/resume-pending.d.ts +5 -6
  316. package/dist/runtime/query/resume-pending.d.ts.map +1 -1
  317. package/dist/runtime/query/resume-pending.js +30 -3
  318. package/dist/runtime/query/resume-pending.js.map +1 -1
  319. package/dist/runtime/query/resume-session.js +1 -1
  320. package/dist/runtime/query/resume-session.js.map +1 -1
  321. package/dist/runtime/query/review-policy.d.ts +8 -1
  322. package/dist/runtime/query/review-policy.d.ts.map +1 -1
  323. package/dist/runtime/query/review-policy.js +6 -0
  324. package/dist/runtime/query/review-policy.js.map +1 -1
  325. package/dist/runtime/query/saved-presentation.d.ts +13 -0
  326. package/dist/runtime/query/saved-presentation.d.ts.map +1 -0
  327. package/dist/runtime/query/saved-presentation.js +63 -0
  328. package/dist/runtime/query/saved-presentation.js.map +1 -0
  329. package/dist/runtime/query/steering.d.ts +6 -9
  330. package/dist/runtime/query/steering.d.ts.map +1 -1
  331. package/dist/runtime/query/steering.js.map +1 -1
  332. package/dist/runtime/query/tool-executions.d.ts +7 -3
  333. package/dist/runtime/query/tool-executions.d.ts.map +1 -1
  334. package/dist/runtime/query/tool-executions.js +89 -9
  335. package/dist/runtime/query/tool-executions.js.map +1 -1
  336. package/dist/runtime/query/tooling.d.ts +3 -1
  337. package/dist/runtime/query/tooling.d.ts.map +1 -1
  338. package/dist/runtime/query/tooling.js +3 -0
  339. package/dist/runtime/query/tooling.js.map +1 -1
  340. package/dist/scheduler/completion-inbox.d.ts +25 -1
  341. package/dist/scheduler/completion-inbox.d.ts.map +1 -1
  342. package/dist/scheduler/completion-inbox.js +102 -8
  343. package/dist/scheduler/completion-inbox.js.map +1 -1
  344. package/dist/scheduler/delegating.d.ts.map +1 -1
  345. package/dist/scheduler/delegating.js +5 -0
  346. package/dist/scheduler/delegating.js.map +1 -1
  347. package/dist/scheduler/local.d.ts.map +1 -1
  348. package/dist/scheduler/local.js +2 -0
  349. package/dist/scheduler/local.js.map +1 -1
  350. package/dist/session/summary/materialize.d.ts +10 -6
  351. package/dist/session/summary/materialize.d.ts.map +1 -1
  352. package/dist/session/summary/materialize.js +41 -8
  353. package/dist/session/summary/materialize.js.map +1 -1
  354. package/dist/store/budget/ledger.d.ts +9 -0
  355. package/dist/store/budget/ledger.d.ts.map +1 -1
  356. package/dist/store/budget/ledger.js +58 -6
  357. package/dist/store/budget/ledger.js.map +1 -1
  358. package/dist/store/evidence/index-page.d.ts +12 -12
  359. package/dist/store/evidence/source-text.d.ts +4 -4
  360. package/dist/store/session/disk.d.ts +9 -4
  361. package/dist/store/session/disk.d.ts.map +1 -1
  362. package/dist/store/session/disk.js +57 -11
  363. package/dist/store/session/disk.js.map +1 -1
  364. package/dist/store/session/memory.d.ts +5 -3
  365. package/dist/store/session/memory.d.ts.map +1 -1
  366. package/dist/store/session/memory.js +24 -7
  367. package/dist/store/session/memory.js.map +1 -1
  368. package/dist/store/session-log/core.d.ts +26 -6
  369. package/dist/store/session-log/core.d.ts.map +1 -1
  370. package/dist/store/session-log/core.js +61 -8
  371. package/dist/store/session-log/core.js.map +1 -1
  372. package/dist/store/session-log/disk.d.ts +2 -2
  373. package/dist/store/session-log/disk.d.ts.map +1 -1
  374. package/dist/store/session-log/disk.js +1 -0
  375. package/dist/store/session-log/disk.js.map +1 -1
  376. package/dist/store/session-log/fold.d.ts +7 -0
  377. package/dist/store/session-log/fold.d.ts.map +1 -1
  378. package/dist/store/session-log/fold.js +21 -0
  379. package/dist/store/session-log/fold.js.map +1 -1
  380. package/dist/store/session-log/index.d.ts +5 -3
  381. package/dist/store/session-log/index.d.ts.map +1 -1
  382. package/dist/store/session-log/index.js +3 -1
  383. package/dist/store/session-log/index.js.map +1 -1
  384. package/dist/store/session-log/memory.d.ts +1 -1
  385. package/dist/store/session-log/memory.d.ts.map +1 -1
  386. package/dist/store/session-log/memory.js +1 -0
  387. package/dist/store/session-log/memory.js.map +1 -1
  388. package/dist/store/session-log/spill.d.ts +10 -3
  389. package/dist/store/session-log/spill.d.ts.map +1 -1
  390. package/dist/store/session-log/spill.js +70 -5
  391. package/dist/store/session-log/spill.js.map +1 -1
  392. package/dist/store/session-log/structured-result.d.ts +21 -0
  393. package/dist/store/session-log/structured-result.d.ts.map +1 -0
  394. package/dist/store/session-log/structured-result.js +67 -0
  395. package/dist/store/session-log/structured-result.js.map +1 -0
  396. package/dist/store/task/disk.d.ts +11 -0
  397. package/dist/store/task/disk.d.ts.map +1 -1
  398. package/dist/store/task/disk.js +41 -2
  399. package/dist/store/task/disk.js.map +1 -1
  400. package/dist/store/task/memory.d.ts.map +1 -1
  401. package/dist/store/task/memory.js +15 -3
  402. package/dist/store/task/memory.js.map +1 -1
  403. package/dist/tools/admit-facts.d.ts +13 -0
  404. package/dist/tools/admit-facts.d.ts.map +1 -0
  405. package/dist/tools/admit-facts.js +142 -0
  406. package/dist/tools/admit-facts.js.map +1 -0
  407. package/dist/tools/builtins/bash.d.ts +4 -1
  408. package/dist/tools/builtins/bash.d.ts.map +1 -1
  409. package/dist/tools/builtins/bash.js +108 -22
  410. package/dist/tools/builtins/bash.js.map +1 -1
  411. package/dist/tools/builtins/browser.d.ts +10 -10
  412. package/dist/tools/builtins/computer-use.d.ts +90 -90
  413. package/dist/tools/builtins/edit.d.ts +17 -0
  414. package/dist/tools/builtins/edit.d.ts.map +1 -1
  415. package/dist/tools/builtins/edit.js +34 -0
  416. package/dist/tools/builtins/edit.js.map +1 -1
  417. package/dist/tools/builtins/file-write-result.d.ts.map +1 -1
  418. package/dist/tools/builtins/file-write-result.js +13 -0
  419. package/dist/tools/builtins/file-write-result.js.map +1 -1
  420. package/dist/tools/builtins/glob.d.ts.map +1 -1
  421. package/dist/tools/builtins/glob.js +12 -0
  422. package/dist/tools/builtins/glob.js.map +1 -1
  423. package/dist/tools/builtins/grep.d.ts.map +1 -1
  424. package/dist/tools/builtins/grep.js +14 -0
  425. package/dist/tools/builtins/grep.js.map +1 -1
  426. package/dist/tools/builtins/index.d.ts +2 -0
  427. package/dist/tools/builtins/index.d.ts.map +1 -1
  428. package/dist/tools/builtins/index.js +1 -0
  429. package/dist/tools/builtins/index.js.map +1 -1
  430. package/dist/tools/builtins/job.d.ts.map +1 -1
  431. package/dist/tools/builtins/job.js +4 -1
  432. package/dist/tools/builtins/job.js.map +1 -1
  433. package/dist/tools/builtins/lsp.d.ts +2 -2
  434. package/dist/tools/builtins/read-file.d.ts.map +1 -1
  435. package/dist/tools/builtins/read-file.js +49 -0
  436. package/dist/tools/builtins/read-file.js.map +1 -1
  437. package/dist/tools/builtins/view-image.d.ts +24 -0
  438. package/dist/tools/builtins/view-image.d.ts.map +1 -0
  439. package/dist/tools/builtins/view-image.js +385 -0
  440. package/dist/tools/builtins/view-image.js.map +1 -0
  441. package/dist/tools/builtins/wait-for-job-bounds.d.ts +2 -0
  442. package/dist/tools/builtins/wait-for-job-bounds.d.ts.map +1 -1
  443. package/dist/tools/builtins/wait-for-job-bounds.js +1 -0
  444. package/dist/tools/builtins/wait-for-job-bounds.js.map +1 -1
  445. package/dist/tools/builtins/wait-for-job.d.ts +2 -0
  446. package/dist/tools/builtins/wait-for-job.d.ts.map +1 -1
  447. package/dist/tools/builtins/wait-for-job.js +104 -6
  448. package/dist/tools/builtins/wait-for-job.js.map +1 -1
  449. package/dist/tools/builtins/write-file.d.ts.map +1 -1
  450. package/dist/tools/builtins/write-file.js +1 -0
  451. package/dist/tools/builtins/write-file.js.map +1 -1
  452. package/dist/tools/command-shell.d.ts +37 -2
  453. package/dist/tools/command-shell.d.ts.map +1 -1
  454. package/dist/tools/command-shell.js +100 -3
  455. package/dist/tools/command-shell.js.map +1 -1
  456. package/dist/tools/coordinator/agent.d.ts +9 -19
  457. package/dist/tools/coordinator/agent.d.ts.map +1 -1
  458. package/dist/tools/coordinator/agent.js.map +1 -1
  459. package/dist/tools/coordinator/index.d.ts.map +1 -1
  460. package/dist/tools/coordinator/index.js +127 -67
  461. package/dist/tools/coordinator/index.js.map +1 -1
  462. package/dist/tools/coordinator/wait-with-idle-bound.d.ts +2 -0
  463. package/dist/tools/coordinator/wait-with-idle-bound.d.ts.map +1 -1
  464. package/dist/tools/coordinator/wait-with-idle-bound.js +1 -1
  465. package/dist/tools/coordinator/wait-with-idle-bound.js.map +1 -1
  466. package/dist/tools/defineTool.d.ts.map +1 -1
  467. package/dist/tools/defineTool.js +4 -0
  468. package/dist/tools/defineTool.js.map +1 -1
  469. package/dist/tools/failure-facts.d.ts +8 -0
  470. package/dist/tools/failure-facts.d.ts.map +1 -0
  471. package/dist/tools/failure-facts.js +24 -0
  472. package/dist/tools/failure-facts.js.map +1 -0
  473. package/dist/tools/host-output.d.ts +24 -0
  474. package/dist/tools/host-output.d.ts.map +1 -0
  475. package/dist/tools/host-output.js +117 -0
  476. package/dist/tools/host-output.js.map +1 -0
  477. package/dist/tools/oem-code-pages.d.ts +8 -0
  478. package/dist/tools/oem-code-pages.d.ts.map +1 -0
  479. package/dist/tools/oem-code-pages.js +23 -0
  480. package/dist/tools/oem-code-pages.js.map +1 -0
  481. package/dist/tools/schedules/schedule-tool.d.ts.map +1 -1
  482. package/dist/tools/schedules/schedule-tool.js +35 -6
  483. package/dist/tools/schedules/schedule-tool.js.map +1 -1
  484. package/dist/tools/schedules/types.d.ts +23 -3
  485. package/dist/tools/schedules/types.d.ts.map +1 -1
  486. package/dist/tools/task/list.d.ts.map +1 -1
  487. package/dist/tools/task/list.js +14 -6
  488. package/dist/tools/task/list.js.map +1 -1
  489. package/dist/tools/task/present.d.ts.map +1 -1
  490. package/dist/tools/task/present.js +26 -6
  491. package/dist/tools/task/present.js.map +1 -1
  492. package/dist/tools/task/update.d.ts.map +1 -1
  493. package/dist/tools/task/update.js +12 -5
  494. package/dist/tools/task/update.js.map +1 -1
  495. package/dist/tools/text-window.d.ts +19 -0
  496. package/dist/tools/text-window.d.ts.map +1 -0
  497. package/dist/tools/text-window.js +83 -0
  498. package/dist/tools/text-window.js.map +1 -0
  499. package/dist/toolsets/manager.d.ts +11 -0
  500. package/dist/toolsets/manager.d.ts.map +1 -1
  501. package/dist/toolsets/manager.js +45 -1
  502. package/dist/toolsets/manager.js.map +1 -1
  503. package/dist/types/acp/index.d.ts +137 -1
  504. package/dist/types/acp/index.d.ts.map +1 -1
  505. package/dist/types/agent/base.d.ts +3 -0
  506. package/dist/types/agent/base.d.ts.map +1 -1
  507. package/dist/types/agent/manager.d.ts +8 -23
  508. package/dist/types/agent/manager.d.ts.map +1 -1
  509. package/dist/types/agent/scheduler.d.ts +10 -1
  510. package/dist/types/agent/scheduler.d.ts.map +1 -1
  511. package/dist/types/agent/task.d.ts +4 -0
  512. package/dist/types/agent/task.d.ts.map +1 -1
  513. package/dist/types/authorization/index.d.ts +30 -30
  514. package/dist/types/connector/mcp.d.ts +7 -0
  515. package/dist/types/connector/mcp.d.ts.map +1 -1
  516. package/dist/types/errors/catalog.d.ts.map +1 -1
  517. package/dist/types/errors/catalog.js +4 -2
  518. package/dist/types/errors/catalog.js.map +1 -1
  519. package/dist/types/harness/schema.d.ts +354 -0
  520. package/dist/types/harness/schema.d.ts.map +1 -0
  521. package/dist/types/harness/schema.js +203 -0
  522. package/dist/types/harness/schema.js.map +1 -0
  523. package/dist/types/harness/session.d.ts +278 -0
  524. package/dist/types/harness/session.d.ts.map +1 -0
  525. package/dist/types/harness/session.js +2 -0
  526. package/dist/types/harness/session.js.map +1 -0
  527. package/dist/types/hitl/index.d.ts +12 -0
  528. package/dist/types/hitl/index.d.ts.map +1 -1
  529. package/dist/types/hitl/index.js.map +1 -1
  530. package/dist/types/job/index.d.ts +47 -0
  531. package/dist/types/job/index.d.ts.map +1 -0
  532. package/dist/types/job/index.js +2 -0
  533. package/dist/types/job/index.js.map +1 -0
  534. package/dist/types/message/inbound-delivery.d.ts +44 -0
  535. package/dist/types/message/inbound-delivery.d.ts.map +1 -0
  536. package/dist/types/message/inbound-delivery.js +14 -0
  537. package/dist/types/message/inbound-delivery.js.map +1 -0
  538. package/dist/types/message/index.d.ts +4 -1
  539. package/dist/types/message/index.d.ts.map +1 -1
  540. package/dist/types/message/index.js +5 -1
  541. package/dist/types/message/index.js.map +1 -1
  542. package/dist/types/plugin/index.d.ts +6 -6
  543. package/dist/types/sandbox/index.d.ts +39 -2
  544. package/dist/types/sandbox/index.d.ts.map +1 -1
  545. package/dist/types/sandbox/index.js.map +1 -1
  546. package/dist/types/session/checkpoint.d.ts +24 -17
  547. package/dist/types/session/checkpoint.d.ts.map +1 -1
  548. package/dist/types/session/checkpoint.js +1 -0
  549. package/dist/types/session/checkpoint.js.map +1 -1
  550. package/dist/types/session/events.d.ts +23 -1
  551. package/dist/types/session/events.d.ts.map +1 -1
  552. package/dist/types/session/events.js.map +1 -1
  553. package/dist/types/session/records.d.ts +1514 -565
  554. package/dist/types/session/records.d.ts.map +1 -1
  555. package/dist/types/session/records.js +89 -1
  556. package/dist/types/session/records.js.map +1 -1
  557. package/dist/types/session/step.d.ts +2 -0
  558. package/dist/types/session/step.d.ts.map +1 -1
  559. package/dist/types/session/step.js.map +1 -1
  560. package/dist/types/session/store.d.ts +19 -10
  561. package/dist/types/session/store.d.ts.map +1 -1
  562. package/dist/types/session/tool-execution.d.ts +6 -0
  563. package/dist/types/session/tool-execution.d.ts.map +1 -1
  564. package/dist/types/structured-output/index.d.ts +12 -2
  565. package/dist/types/structured-output/index.d.ts.map +1 -1
  566. package/dist/types/summary/ref.d.ts +3 -1
  567. package/dist/types/summary/ref.d.ts.map +1 -1
  568. package/dist/types/tool/index.d.ts +32 -4
  569. package/dist/types/tool/index.d.ts.map +1 -1
  570. package/dist/types/tool/index.js.map +1 -1
  571. package/dist/types/tool/presentation.d.ts +106 -0
  572. package/dist/types/tool/presentation.d.ts.map +1 -1
  573. package/dist/utils/json-snapshot.d.ts +6 -2
  574. package/dist/utils/json-snapshot.d.ts.map +1 -1
  575. package/dist/utils/json-snapshot.js +19 -9
  576. package/dist/utils/json-snapshot.js.map +1 -1
  577. package/dist/utils/structured-result-json.d.ts +5 -0
  578. package/dist/utils/structured-result-json.d.ts.map +1 -0
  579. package/dist/utils/structured-result-json.js +10 -0
  580. package/dist/utils/structured-result-json.js.map +1 -0
  581. package/package.json +1 -1
  582. package/src/agents/QueryAgent.ts +1 -0
  583. package/src/agents/examples/SupervisorAgent.ts +1 -0
  584. package/src/agents/runAgent.ts +3 -0
  585. package/src/authorization/shell-lexer.ts +16 -1
  586. package/src/bridge/acp/permission.ts +17 -3
  587. package/src/bridge/acp/server.ts +271 -25
  588. package/src/bridge/acp/tasks.ts +23 -0
  589. package/src/bridge/acp/update.ts +167 -13
  590. package/src/connector/mcp/adapter.ts +16 -4
  591. package/src/connector/mcp/client.ts +6 -2
  592. package/src/constants/acp/index.ts +4 -0
  593. package/src/manager/agent/lifecycle.ts +230 -3
  594. package/src/manager/plan/lifecycle.ts +11 -9
  595. package/src/manager/session/attribution.ts +12 -2
  596. package/src/manager/session/streamed-message-identity.ts +21 -0
  597. package/src/manager/session/turn-recorder.ts +4 -3
  598. package/src/pals/activity/causality.ts +261 -0
  599. package/src/pals/activity/projection.ts +89 -0
  600. package/src/pals/activity/source.ts +240 -0
  601. package/src/pals/activity/subscription-policy.ts +230 -0
  602. package/src/pals/activity/subscription-schema.ts +27 -0
  603. package/src/pals/activity/subscription-store.ts +172 -0
  604. package/src/pals/activity/subscription-types.ts +48 -0
  605. package/src/pals/activity/subscriptions.ts +209 -0
  606. package/src/pals/activity/types.ts +108 -0
  607. package/src/pals/channels/ingress.ts +153 -0
  608. package/src/pals/channels/routes.ts +118 -0
  609. package/src/pals/channels/routing.ts +197 -0
  610. package/src/pals/channels/schema.ts +108 -0
  611. package/src/pals/channels/types.ts +156 -0
  612. package/src/pals/communication/broker.ts +131 -0
  613. package/src/pals/communication/dispatch.ts +66 -0
  614. package/src/pals/communication/inbound.ts +193 -0
  615. package/src/pals/communication/ingress-dispatch.ts +63 -0
  616. package/src/pals/communication/ingress-inbound.ts +269 -0
  617. package/src/pals/communication/ingress-schema.ts +526 -0
  618. package/src/pals/communication/ingress-types.ts +336 -0
  619. package/src/pals/communication/operator.ts +315 -0
  620. package/src/pals/communication/policy.ts +174 -0
  621. package/src/pals/communication/schema.ts +173 -0
  622. package/src/pals/communication/store.ts +577 -0
  623. package/src/pals/communication/tools.ts +139 -0
  624. package/src/pals/communication/types.ts +227 -0
  625. package/src/pals/communication/verify.ts +220 -0
  626. package/src/pals/lifecycle.ts +54 -0
  627. package/src/pals/prompt.ts +101 -0
  628. package/src/pals/reference-images.ts +322 -0
  629. package/src/pals/runtime.ts +670 -0
  630. package/src/pals/store.ts +369 -0
  631. package/src/pals/types.ts +157 -0
  632. package/src/peers/envelope.ts +1 -1
  633. package/src/plugin/shell-hook.ts +8 -2
  634. package/src/process/kill-tree.ts +10 -1
  635. package/src/provider/errors.ts +135 -2
  636. package/src/public-runtime.ts +117 -12
  637. package/src/public-tools.ts +13 -1
  638. package/src/public-types.ts +69 -7
  639. package/src/registry/tool/presentation.ts +9 -4
  640. package/src/runtime/harness-session/index.ts +1125 -0
  641. package/src/runtime/harness-session/journal.ts +209 -0
  642. package/src/runtime/harness-session/saved-view.ts +122 -0
  643. package/src/runtime/jobs/awaited-jobs.ts +2 -1
  644. package/src/runtime/jobs/registry.ts +397 -41
  645. package/src/runtime/query/abandon-turn.ts +18 -2
  646. package/src/runtime/query/checkpoint.ts +11 -0
  647. package/src/runtime/query/durable-inbound.ts +101 -0
  648. package/src/runtime/query/events.ts +22 -5
  649. package/src/runtime/query/executor/tool-call-admission.ts +125 -32
  650. package/src/runtime/query/executor.ts +316 -130
  651. package/src/runtime/query/index.ts +24 -4
  652. package/src/runtime/query/iteration/index.ts +218 -104
  653. package/src/runtime/query/iteration/outstanding-work.ts +55 -7
  654. package/src/runtime/query/iteration/phases/context.ts +4 -0
  655. package/src/runtime/query/iteration/phases/tool-review.ts +118 -21
  656. package/src/runtime/query/observation-context.ts +22 -16
  657. package/src/runtime/query/prepare-turn.ts +2 -2
  658. package/src/runtime/query/prompt-cache.ts +3 -0
  659. package/src/runtime/query/prompt.ts +32 -1
  660. package/src/runtime/query/repeat-call.ts +40 -10
  661. package/src/runtime/query/resume-pending.ts +60 -7
  662. package/src/runtime/query/resume-session.ts +1 -1
  663. package/src/runtime/query/review-policy.ts +23 -2
  664. package/src/runtime/query/saved-presentation.ts +70 -0
  665. package/src/runtime/query/steering.ts +6 -9
  666. package/src/runtime/query/tool-executions.ts +108 -9
  667. package/src/runtime/query/tooling.ts +6 -1
  668. package/src/scheduler/completion-inbox.ts +108 -7
  669. package/src/scheduler/delegating.ts +5 -0
  670. package/src/scheduler/local.ts +2 -0
  671. package/src/session/summary/materialize.ts +51 -9
  672. package/src/store/budget/ledger.ts +60 -5
  673. package/src/store/session/disk.ts +77 -10
  674. package/src/store/session/memory.ts +32 -7
  675. package/src/store/session-log/core.ts +118 -11
  676. package/src/store/session-log/disk.ts +9 -2
  677. package/src/store/session-log/fold.ts +22 -0
  678. package/src/store/session-log/index.ts +5 -0
  679. package/src/store/session-log/memory.ts +2 -1
  680. package/src/store/session-log/spill.ts +89 -6
  681. package/src/store/session-log/structured-result.ts +96 -0
  682. package/src/store/task/disk.ts +46 -2
  683. package/src/store/task/memory.ts +13 -3
  684. package/src/tools/admit-facts.ts +145 -0
  685. package/src/tools/builtins/bash.ts +132 -24
  686. package/src/tools/builtins/edit.ts +42 -0
  687. package/src/tools/builtins/file-write-result.ts +14 -0
  688. package/src/tools/builtins/glob.ts +12 -0
  689. package/src/tools/builtins/grep.ts +14 -0
  690. package/src/tools/builtins/index.ts +2 -0
  691. package/src/tools/builtins/job.ts +4 -1
  692. package/src/tools/builtins/read-file.ts +57 -0
  693. package/src/tools/builtins/view-image.ts +409 -0
  694. package/src/tools/builtins/wait-for-job-bounds.ts +3 -0
  695. package/src/tools/builtins/wait-for-job.ts +141 -32
  696. package/src/tools/builtins/write-file.ts +4 -2
  697. package/src/tools/command-shell.ts +132 -5
  698. package/src/tools/coordinator/agent.ts +9 -19
  699. package/src/tools/coordinator/index.ts +150 -75
  700. package/src/tools/coordinator/wait-with-idle-bound.ts +3 -1
  701. package/src/tools/defineTool.ts +4 -0
  702. package/src/tools/failure-facts.ts +24 -0
  703. package/src/tools/host-output.ts +136 -0
  704. package/src/tools/oem-code-pages.ts +22 -0
  705. package/src/tools/schedules/schedule-tool.ts +38 -5
  706. package/src/tools/schedules/types.ts +23 -3
  707. package/src/tools/task/list.ts +15 -7
  708. package/src/tools/task/present.ts +37 -7
  709. package/src/tools/task/update.ts +12 -5
  710. package/src/tools/text-window.ts +87 -0
  711. package/src/toolsets/manager.ts +58 -1
  712. package/src/types/acp/index.ts +150 -4
  713. package/src/types/agent/base.ts +3 -0
  714. package/src/types/agent/manager.ts +8 -23
  715. package/src/types/agent/scheduler.ts +10 -1
  716. package/src/types/agent/task.ts +4 -0
  717. package/src/types/connector/mcp.ts +7 -0
  718. package/src/types/errors/catalog.ts +4 -2
  719. package/src/types/harness/schema.ts +203 -0
  720. package/src/types/harness/session.ts +306 -0
  721. package/src/types/hitl/index.ts +17 -1
  722. package/src/types/job/index.ts +42 -0
  723. package/src/types/message/inbound-delivery.ts +63 -0
  724. package/src/types/message/index.ts +8 -1
  725. package/src/types/sandbox/index.ts +46 -0
  726. package/src/types/session/checkpoint.ts +4 -1
  727. package/src/types/session/events.ts +23 -1
  728. package/src/types/session/records.ts +114 -2
  729. package/src/types/session/step.ts +2 -0
  730. package/src/types/session/store.ts +23 -9
  731. package/src/types/session/tool-execution.ts +6 -0
  732. package/src/types/structured-output/index.ts +13 -2
  733. package/src/types/summary/ref.ts +3 -1
  734. package/src/types/tool/index.ts +39 -5
  735. package/src/types/tool/presentation.ts +121 -0
  736. package/src/utils/json-snapshot.ts +26 -9
  737. package/src/utils/structured-result-json.ts +10 -0
@@ -17,7 +17,7 @@ import {
17
17
  TenantIsolationError,
18
18
  } from '../../session/errors.js'
19
19
  import { SessionAlreadySummarizedError } from '../../session/summary/errors.js'
20
- import type { SessionId, TenantId } from '../../types/ids/index.js'
20
+ import type { SessionId, TenantId, TurnId } from '../../types/ids/index.js'
21
21
  import type { Project, ProjectStatus } from '../../types/project/entity.js'
22
22
  import type { Session } from '../../types/session/entity.js'
23
23
  import type { ProjectId, SubSessionId, TopicId } from '../../types/session/ids.js'
@@ -34,6 +34,7 @@ import type { SessionSummaryRef } from '../../types/summary/ref.js'
34
34
  import {
35
35
  asProjectId,
36
36
  asTenantId,
37
+ asTurnId,
37
38
  generateProjectId,
38
39
  generateSessionId,
39
40
  generateSubSessionId,
@@ -62,6 +63,10 @@ interface SummaryRecord {
62
63
  summary: SessionSummaryRef
63
64
  }
64
65
 
66
+ function summaryKey(sessionId: SessionId, turnId?: TurnId): string {
67
+ return JSON.stringify([sessionId, turnId === undefined ? null : asTurnId(turnId)])
68
+ }
69
+
65
70
  /**
66
71
  * Non-terminal statuses from which {@link InMemorySessionStore.recordSummary}
67
72
  * flips the owning session to `'idle'` as part of the atomic materialize +
@@ -75,10 +80,12 @@ const SUMMARY_TERMINAL_FLIP_STATUSES: ReadonlySet<Session['status']> = new Set([
75
80
  ])
76
81
 
77
82
  export class InMemorySessionStore implements SessionStore {
83
+ readonly supportsInvocationSummaries: boolean = true
84
+ readonly supportsOwnerVersionCas: boolean = true
78
85
  private readonly projects = new Map<ProjectId, ProjectRecord>()
79
86
  private readonly sessions = new Map<SessionId, SessionRecord>()
80
87
  private readonly subSessions = new Map<SubSessionId, SubSessionRecord>()
81
- private readonly summaries = new Map<SessionId, SummaryRecord>()
88
+ private readonly summaries = new Map<string, SummaryRecord>()
82
89
 
83
90
  /** Hydrate existing Project snapshots without minting replacement identities. */
84
91
  constructor(projects: readonly Project[] = []) {
@@ -364,7 +371,9 @@ export class InMemorySessionStore implements SessionStore {
364
371
  }
365
372
 
366
373
  this.sessions.delete(sessionId)
367
- this.summaries.delete(sessionId)
374
+ for (const [key, record] of this.summaries) {
375
+ if (record.summary.sessionRef === sessionId) this.summaries.delete(key)
376
+ }
368
377
  }
369
378
 
370
379
  // SubSession CRUD ---------------------------------------------------------
@@ -460,6 +469,7 @@ export class InMemorySessionStore implements SessionStore {
460
469
  async recordSummary(
461
470
  summary: SessionSummaryRef & { materializedBy: 'kernel' },
462
471
  tenantId: TenantId,
472
+ expectedOwnerVersion?: number,
463
473
  ): Promise<void> {
464
474
  if (summary.tenantId !== tenantId) {
465
475
  throw new TenantIsolationError({
@@ -472,11 +482,22 @@ export class InMemorySessionStore implements SessionStore {
472
482
  throw new Error(`Session ${summary.sessionRef} not found`)
473
483
  }
474
484
  this.assertTenant(sessionRecord.tenantId, tenantId, `session(${summary.sessionRef})`)
485
+ if (
486
+ expectedOwnerVersion !== undefined &&
487
+ sessionRecord.session.ownerVersion !== expectedOwnerVersion
488
+ ) {
489
+ throw new StaleSessionError({
490
+ sessionId: summary.sessionRef,
491
+ expectedVersion: expectedOwnerVersion,
492
+ actualVersion: sessionRecord.session.ownerVersion,
493
+ })
494
+ }
475
495
 
476
496
  // Atomic within the call: summary persist + session status flip commit
477
497
  // together. An existing summary with the same id is the recovery path —
478
498
  // idempotently replay the status flip without duplicating the record.
479
- const existing = this.summaries.get(summary.sessionRef)
499
+ const key = summaryKey(summary.sessionRef, summary.turnRef)
500
+ const existing = this.summaries.get(key)
480
501
  if (existing && existing.summary.id !== summary.id) {
481
502
  throw new SessionAlreadySummarizedError({
482
503
  sessionId: summary.sessionRef,
@@ -485,7 +506,7 @@ export class InMemorySessionStore implements SessionStore {
485
506
  }
486
507
 
487
508
  if (!existing) {
488
- this.summaries.set(summary.sessionRef, { tenantId, summary })
509
+ this.summaries.set(key, { tenantId, summary })
489
510
  }
490
511
 
491
512
  if (SUMMARY_TERMINAL_FLIP_STATUSES.has(sessionRecord.session.status)) {
@@ -500,8 +521,12 @@ export class InMemorySessionStore implements SessionStore {
500
521
  }
501
522
  }
502
523
 
503
- async getSummary(sessionId: SessionId, tenantId: TenantId): Promise<SessionSummaryRef | null> {
504
- const record = this.summaries.get(sessionId)
524
+ async getSummary(
525
+ sessionId: SessionId,
526
+ tenantId: TenantId,
527
+ turnId?: TurnId,
528
+ ): Promise<SessionSummaryRef | null> {
529
+ const record = this.summaries.get(summaryKey(sessionId, turnId))
505
530
  if (!record) return null
506
531
  this.assertTenant(record.tenantId, tenantId, `summary(${record.summary.id})`)
507
532
  return record.summary
@@ -18,6 +18,8 @@ import {
18
18
  type TurnSettlement,
19
19
  } from '../../types/session/turn.js'
20
20
  import { generateRecordId } from '../../utils/id.js'
21
+ import { cloneJsonValue } from '../../utils/json-snapshot.js'
22
+ import { STRUCTURED_RESULT_MAX_BYTES } from '../../utils/structured-result-json.js'
21
23
  import {
22
24
  LineSplitter,
23
25
  type LogBytes,
@@ -28,6 +30,7 @@ import {
28
30
  } from './chain.js'
29
31
  import {
30
32
  type ActiveTurnRecord,
33
+ MESSAGES_WITHDRAWN_DETAIL,
31
34
  SessionTurnState,
32
35
  TurnRuleError,
33
36
  foldSessionMessages,
@@ -47,7 +50,7 @@ import {
47
50
  StaleSessionLeaseError,
48
51
  isLeaseLive,
49
52
  } from './lease.js'
50
- import type { SpillRef, SpillStore } from './spill.js'
53
+ import type { SpillReadOptions, SpillRef, SpillStore } from './spill.js'
51
54
 
52
55
  // ─── public types ─────────────────────────────────────────────────────────
53
56
 
@@ -122,6 +125,16 @@ export interface BeginTurnOptions {
122
125
  readonly abandonInterrupted?: boolean
123
126
  }
124
127
 
128
+ export interface AbandonTurnLogOptions {
129
+ /**
130
+ * The caller hands the turn's messages back to the person (a client that
131
+ * puts the prompt back in its message box). The fold then leaves them out
132
+ * of the next turn's context; the records stay in the log. Absent: the
133
+ * abandoned turn's messages remain in the context, as they always have.
134
+ */
135
+ readonly withdrawMessages?: boolean
136
+ }
137
+
125
138
  export interface ActiveTurnOptions {
126
139
  /** The lease the caller holds; the default asks the store for the current one. */
127
140
  readonly lease?: SessionLease
@@ -175,8 +188,18 @@ export interface SessionLog {
175
188
  draft: TurnStartedDraft,
176
189
  options?: BeginTurnOptions,
177
190
  ): Promise<SessionLogEntry>
178
- /** Close a paused or interrupted turn with `turn_failed{failure.code:'abandoned'}`. */
179
- abandonTurn(lease: SessionLease, turnId: TurnId, reason: string): Promise<SessionLogEntry>
191
+ /**
192
+ * Close a paused or interrupted turn with `turn_failed{failure.code:'abandoned'}`.
193
+ * With `withdrawMessages` the closing record also says so
194
+ * ({@link MESSAGES_WITHDRAWN_DETAIL}), and the fold then leaves the turn's
195
+ * messages out of the context the next turn carries. The records stay.
196
+ */
197
+ abandonTurn(
198
+ lease: SessionLease,
199
+ turnId: TurnId,
200
+ reason: string,
201
+ options?: AbandonTurnLogOptions,
202
+ ): Promise<SessionLogEntry>
180
203
  /** The active turn, if any, and whether it is running, paused or interrupted. */
181
204
  activeTurn(options?: ActiveTurnOptions): Promise<ActiveTurn | null>
182
205
 
@@ -186,7 +209,7 @@ export interface SessionLog {
186
209
  readAll(options?: ReadSessionLogOptions): Promise<SessionLogRead>
187
210
  /** The folded conversation (spec §4.5), spills read back. */
188
211
  messages(options?: { readonly throughSeq?: number }): Promise<Message[]>
189
- readSpill(ref: SpillRef): Promise<string>
212
+ readSpill(ref: SpillRef, options?: SpillReadOptions): Promise<string>
190
213
  }
191
214
 
192
215
  /** A draft that is not a valid session record once enveloped. */
@@ -227,6 +250,12 @@ export interface SessionLogCoreOptions {
227
250
  * bytes spills its body first. Default {@link SESSION_RECORD_MAX_BYTES}.
228
251
  */
229
252
  readonly spillAboveBytes?: number
253
+ /**
254
+ * Spill screened structured tool JSON and accepted structured output when
255
+ * their record exceeds spillAboveBytes. Default false preserves inline
256
+ * records. Each JSON body is limited to STRUCTURED_RESULT_MAX_BYTES.
257
+ */
258
+ readonly structuredResultSpilling?: boolean
230
259
  /**
231
260
  * Which appends are fsynced. `boundaries` (the default): the records
232
261
  * others depend on — `session_started`, the turn lifecycle, checkpoints
@@ -285,6 +314,7 @@ export class SessionLogCore implements SessionLog {
285
314
  readonly #spills: SpillStore
286
315
  readonly #now: () => number
287
316
  readonly #spillAbove: number
317
+ readonly #structuredResultSpilling: boolean
288
318
  readonly #sync: 'boundaries' | 'all' | 'none'
289
319
  readonly #mutex = new Mutex()
290
320
 
@@ -303,6 +333,13 @@ export class SessionLogCore implements SessionLog {
303
333
  this.#medium = options.medium
304
334
  this.#leases = options.leases
305
335
  this.#spills = options.spills
336
+ if (
337
+ options.structuredResultSpilling !== undefined &&
338
+ typeof options.structuredResultSpilling !== 'boolean'
339
+ ) {
340
+ throw new TypeError('structuredResultSpilling must be a boolean')
341
+ }
342
+ this.#structuredResultSpilling = options.structuredResultSpilling ?? false
306
343
  this.#now = options.now ?? Date.now
307
344
  this.#spillAbove = Math.min(
308
345
  options.spillAboveBytes ?? SESSION_RECORD_MAX_BYTES,
@@ -499,7 +536,12 @@ export class SessionLogCore implements SessionLog {
499
536
  })
500
537
  }
501
538
 
502
- abandonTurn(lease: SessionLease, turnId: TurnId, reason: string): Promise<SessionLogEntry> {
539
+ abandonTurn(
540
+ lease: SessionLease,
541
+ turnId: TurnId,
542
+ reason: string,
543
+ options: AbandonTurnLogOptions = {},
544
+ ): Promise<SessionLogEntry> {
503
545
  return this.#mutex.run(async () => {
504
546
  await this.#requireCurrent(lease)
505
547
  await this.#catchUp()
@@ -512,7 +554,15 @@ export class SessionLogCore implements SessionLog {
512
554
  if (state === 'running') {
513
555
  throw new TurnInProgressError({ sessionId: this.sessionId, activeTurnId: turnId, state })
514
556
  }
515
- return this.#write(lease, this.#failedDraft(active, 'abandoned', reason))
557
+ return this.#write(
558
+ lease,
559
+ this.#failedDraft(
560
+ active,
561
+ 'abandoned',
562
+ reason,
563
+ options.withdrawMessages ? { [MESSAGES_WITHDRAWN_DETAIL]: true } : undefined,
564
+ ),
565
+ )
516
566
  })
517
567
  }
518
568
 
@@ -521,7 +571,12 @@ export class SessionLogCore implements SessionLog {
521
571
  return active.ownerGen === fence ? 'running' : 'interrupted'
522
572
  }
523
573
 
524
- #failedDraft(active: ActiveTurnRecord, code: string, message: string): SessionRecordDraft {
574
+ #failedDraft(
575
+ active: ActiveTurnRecord,
576
+ code: string,
577
+ message: string,
578
+ details?: Record<string, unknown>,
579
+ ): SessionRecordDraft {
525
580
  const settlement: TurnSettlement = {
526
581
  status: 'failed',
527
582
  iterations: 0,
@@ -536,7 +591,7 @@ export class SessionLogCore implements SessionLog {
536
591
  type: 'turn_failed',
537
592
  turnId: active.turnId,
538
593
  error: message,
539
- failure: { code, message, retryable: false },
594
+ failure: { code, message, retryable: false, ...(details ? { details } : {}) },
540
595
  settlement,
541
596
  } as SessionRecordDraft
542
597
  }
@@ -591,7 +646,10 @@ export class SessionLogCore implements SessionLog {
591
646
  return entry
592
647
  }
593
648
 
594
- async #spillIfLarge(candidate: Record<string, unknown>): Promise<Record<string, unknown>> {
649
+ async #spillIfLarge(original: Record<string, unknown>): Promise<Record<string, unknown>> {
650
+ const candidate = this.#structuredResultSpilling
651
+ ? await this.#spillStructuredResults(original)
652
+ : original
595
653
  const type = candidate.type
596
654
  if (
597
655
  type !== 'message' &&
@@ -639,6 +697,55 @@ export class SessionLogCore implements SessionLog {
639
697
  return { ...candidate, content: preview, spill: ref }
640
698
  }
641
699
 
700
+ async #spillStructuredResults(
701
+ candidate: Record<string, unknown>,
702
+ ): Promise<Record<string, unknown>> {
703
+ const hasCandidate =
704
+ candidate.type === 'tool_completed' && candidate.structuredResultJson !== undefined
705
+ const settlement =
706
+ candidate.type === 'turn_completed'
707
+ ? (candidate.settlement as Record<string, unknown> | undefined)
708
+ : undefined
709
+ const hasOutput = settlement?.structuredOutput !== undefined
710
+ if (!hasCandidate && !hasOutput) return candidate
711
+ // Check the original classification before removing any inline evidence.
712
+ // Otherwise spilling could hide malformed or contradictory metadata.
713
+ const parsed = SessionRecordSchema.safeParse(candidate)
714
+ if (!parsed.success) throw new InvalidSessionRecordError(parsed.error.message)
715
+ if (
716
+ hasOutput &&
717
+ (settlement?.status !== 'completed' || settlement.resultSource !== 'structured_output')
718
+ ) {
719
+ throw new InvalidSessionRecordError(
720
+ 'Only a completed structured_output settlement can retain structured output.',
721
+ )
722
+ }
723
+ let json: string
724
+ try {
725
+ json = hasCandidate
726
+ ? (candidate.structuredResultJson as string)
727
+ : JSON.stringify(cloneJsonValue(settlement?.structuredOutput, false))
728
+ } catch (error) {
729
+ throw new InvalidSessionRecordError(`Structured result must be JSON-safe: ${String(error)}`)
730
+ }
731
+ const size = Buffer.byteLength(`${JSON.stringify(candidate)}\n`, 'utf8')
732
+ if (size <= this.#spillAbove) return candidate
733
+ if (Buffer.byteLength(json, 'utf8') > STRUCTURED_RESULT_MAX_BYTES) {
734
+ throw new InvalidSessionRecordError(
735
+ `Structured result exceeds ${STRUCTURED_RESULT_MAX_BYTES} bytes.`,
736
+ )
737
+ }
738
+ // Separate from model-preview spills and from other bodies in this record.
739
+ const field = hasCandidate ? 'structuredResult' : 'structuredOutput'
740
+ const ref = await this.#spills.write(`record:${String(candidate.id)}:${field}`, 'text', json)
741
+ if (hasCandidate) {
742
+ const { structuredResultJson: _json, ...rest } = candidate
743
+ return { ...rest, structuredResultSpill: ref }
744
+ }
745
+ const { structuredOutput: _output, ...rest } = settlement as Record<string, unknown>
746
+ return { ...candidate, settlement: rest, structuredOutputSpill: ref }
747
+ }
748
+
642
749
  // ── reads ──
643
750
 
644
751
  activeTurn(options: ActiveTurnOptions = {}): Promise<ActiveTurn | null> {
@@ -686,8 +793,8 @@ export class SessionLogCore implements SessionLog {
686
793
  })
687
794
  }
688
795
 
689
- readSpill(ref: SpillRef): Promise<string> {
690
- return this.#spills.read(ref)
796
+ readSpill(ref: SpillRef, options?: SpillReadOptions): Promise<string> {
797
+ return this.#spills.read(ref, options)
691
798
  }
692
799
  }
693
800
 
@@ -133,7 +133,10 @@ export class DiskLogMedium implements LogMedium {
133
133
  }
134
134
 
135
135
  export interface DiskSessionLogOptions
136
- extends Pick<SessionLogCoreOptions, 'now' | 'spillAboveBytes' | 'sync'> {
136
+ extends Pick<
137
+ SessionLogCoreOptions,
138
+ 'now' | 'spillAboveBytes' | 'structuredResultSpilling' | 'sync'
139
+ > {
137
140
  readonly sessionId: SessionId
138
141
  /** `<session-id>.jsonl`. */
139
142
  readonly file: string
@@ -168,6 +171,7 @@ export class DiskSessionLog extends SessionLogCore {
168
171
  spills: new DiskSpillStore(options.sessionDir, options.now),
169
172
  now: options.now,
170
173
  spillAboveBytes: options.spillAboveBytes,
174
+ structuredResultSpilling: options.structuredResultSpilling,
171
175
  sync: options.sync,
172
176
  })
173
177
  this.file = options.file
@@ -184,7 +188,10 @@ export class DiskSessionLog extends SessionLogCore {
184
188
  static at(
185
189
  paths: SessionPaths,
186
190
  locator: SessionLocator,
187
- options: Pick<SessionLogCoreOptions, 'now' | 'spillAboveBytes' | 'sync'> = {},
191
+ options: Pick<
192
+ SessionLogCoreOptions,
193
+ 'now' | 'spillAboveBytes' | 'structuredResultSpilling' | 'sync'
194
+ > = {},
188
195
  ): DiskSessionLog {
189
196
  return new DiskSessionLog({
190
197
  ...options,
@@ -47,6 +47,14 @@ export function withMessageId<M extends Message>(message: M, id: MessageId | und
47
47
  return { ...message, id }
48
48
  }
49
49
 
50
+ /**
51
+ * The key in an `abandoned` `turn_failed`'s `failure.details` that withdraws
52
+ * the turn's messages from the fold. A detail, not a record field: a log that
53
+ * carries it still validates for a reader that predates it, which then keeps
54
+ * the messages, as it always did.
55
+ */
56
+ export const MESSAGES_WITHDRAWN_DETAIL = 'messagesWithdrawn'
57
+
50
58
  /** One message of the folded context. */
51
59
  export interface FoldedMessage {
52
60
  /** Absent for a compaction summary message, which has no record of its own. */
@@ -61,6 +69,7 @@ export interface FoldedMessage {
61
69
  }
62
70
 
63
71
  interface Slot {
72
+ turnId?: TurnId
64
73
  messageId?: MessageId
65
74
  seq: number
66
75
  message: Message
@@ -128,6 +137,12 @@ export class SessionMessageFold {
128
137
  case 'compaction':
129
138
  this.#compaction(record as CompactionRecord)
130
139
  return
140
+ case 'turn_failed': {
141
+ const failure = record.failure
142
+ if (failure?.code === 'abandoned' && failure.details?.[MESSAGES_WITHDRAWN_DETAIL] === true)
143
+ this.#withdraw(record.turnId)
144
+ return
145
+ }
131
146
  default:
132
147
  return
133
148
  }
@@ -137,6 +152,7 @@ export class SessionMessageFold {
137
152
  const replaced = this.#replacements.get(record.messageId)
138
153
  const existing = this.#byId.get(record.messageId)
139
154
  const slot: Slot = {
155
+ turnId: record.turnId,
140
156
  messageId: record.messageId,
141
157
  seq: record.seq,
142
158
  message: replaced?.message ?? record.content,
@@ -163,6 +179,12 @@ export class SessionMessageFold {
163
179
  this.#byId.set(record.messageId, slot)
164
180
  }
165
181
 
182
+ /** An abandoned turn handed back to the person: its messages leave the context. */
183
+ #withdraw(turnId: TurnId): void {
184
+ this.#slots = this.#slots.filter((slot) => slot.turnId !== turnId)
185
+ for (const [id, slot] of this.#byId) if (slot.turnId === turnId) this.#byId.delete(id)
186
+ }
187
+
166
188
  #compaction(record: CompactionRecord): void {
167
189
  const [, toSeq] = record.replacesSeqRange
168
190
  const keep = new Set<string>([...record.keptMessageIds, ...(record.pinned ?? [])])
@@ -19,6 +19,7 @@ export {
19
19
  export {
20
20
  type ActiveTurn,
21
21
  type ActiveTurnOptions,
22
+ type AbandonTurnLogOptions,
22
23
  type BeginTurnOptions,
23
24
  InvalidSessionRecordError,
24
25
  type LogMedium,
@@ -51,6 +52,7 @@ export {
51
52
  type SpilledSummary,
52
53
  SpillUnavailableError,
53
54
  TurnRuleError,
55
+ MESSAGES_WITHDRAWN_DETAIL,
54
56
  foldSessionMessages,
55
57
  withMessageId,
56
58
  } from './fold.js'
@@ -83,7 +85,10 @@ export {
83
85
  SPILL_DIR,
84
86
  SpillIntegrityError,
85
87
  type SpillManifest,
88
+ type SpillReadOptions,
86
89
  type SpillRef,
87
90
  type SpillStore,
88
91
  spillFileName,
89
92
  } from './spill.js'
93
+ export { readStructuredOutput, type StructuredResultReadOptions } from './structured-result.js'
94
+ export { STRUCTURED_RESULT_MAX_BYTES } from '../../utils/structured-result-json.js'
@@ -63,7 +63,7 @@ export class InMemoryLogMedium implements LogMedium {
63
63
  }
64
64
 
65
65
  export interface InMemorySessionLogOptions
66
- extends Pick<SessionLogCoreOptions, 'now' | 'spillAboveBytes'> {
66
+ extends Pick<SessionLogCoreOptions, 'now' | 'spillAboveBytes' | 'structuredResultSpilling'> {
67
67
  readonly sessionId: SessionId
68
68
  /**
69
69
  * Share storage with another instance, as a second process would see one
@@ -91,6 +91,7 @@ export class InMemorySessionLog extends SessionLogCore {
91
91
  spills,
92
92
  now: options.now,
93
93
  spillAboveBytes: options.spillAboveBytes,
94
+ structuredResultSpilling: options.structuredResultSpilling,
94
95
  sync: 'none',
95
96
  })
96
97
  this.medium = medium
@@ -2,6 +2,8 @@ import { createHash, randomBytes } from 'node:crypto'
2
2
  import { type FileHandle, link, mkdir, open, readFile, rename, unlink } from 'node:fs/promises'
3
3
  import { dirname, isAbsolute, join, normalize, sep } from 'node:path'
4
4
 
5
+ import { decode, openEvidence, readBytes, stamp } from '../evidence/io.js'
6
+
5
7
  /**
6
8
  * Content too large for one record, written beside the log before the record
7
9
  * that names it.
@@ -183,7 +185,52 @@ async function durableCreateFile(target: string, content: string): Promise<boole
183
185
  /** Where spills are kept. The disk log uses files; the in-memory log a map. */
184
186
  export interface SpillStore {
185
187
  write(key: string, content: SpillManifest['content'], text: string): Promise<SpillRef>
186
- read(ref: SpillRef): Promise<string>
188
+ read(ref: SpillRef, options?: SpillReadOptions): Promise<string>
189
+ }
190
+
191
+ /** Optional bounds for full-body spill reads; omitted limits preserve legacy reads. */
192
+ export interface SpillReadOptions {
193
+ /** Maximum UTF-8 body bytes. Must be a nonnegative safe integer. */
194
+ readonly maxBytes?: number
195
+ /** Stops waiting at I/O boundaries and prevents publication of a cancelled read. */
196
+ readonly signal?: AbortSignal
197
+ }
198
+
199
+ function checkedReadLimit(ref: SpillRef, options?: SpillReadOptions): number | undefined {
200
+ options?.signal?.throwIfAborted()
201
+ const maxBytes = options?.maxBytes
202
+ if (maxBytes === undefined) return undefined
203
+ if (!Number.isSafeInteger(maxBytes) || maxBytes < 0) {
204
+ throw new RangeError('SpillReadOptions.maxBytes must be a nonnegative safe integer.')
205
+ }
206
+ if (!Number.isSafeInteger(ref.bytes) || ref.bytes < 0) {
207
+ throw new SpillIntegrityError(
208
+ ref.path,
209
+ `Spill ${ref.path} has an invalid declared byte length.`,
210
+ )
211
+ }
212
+ if (ref.bytes > maxBytes) {
213
+ throw new SpillIntegrityError(
214
+ ref.path,
215
+ `Spill ${ref.path} declares ${ref.bytes} bytes, exceeding the ${maxBytes}-byte read limit.`,
216
+ )
217
+ }
218
+ return maxBytes
219
+ }
220
+
221
+ function checkActualReadSize(ref: SpillRef, bytes: number, maxBytes: number): void {
222
+ if (bytes > maxBytes) {
223
+ throw new SpillIntegrityError(
224
+ ref.path,
225
+ `Spill ${ref.path} is ${bytes} bytes, exceeding the ${maxBytes}-byte read limit.`,
226
+ )
227
+ }
228
+ if (bytes !== ref.bytes) {
229
+ throw new SpillIntegrityError(
230
+ ref.path,
231
+ `Spill ${ref.path} is ${bytes} bytes; its record says ${ref.bytes}.`,
232
+ )
233
+ }
187
234
  }
188
235
 
189
236
  function checkRelative(path: string): string {
@@ -262,19 +309,50 @@ export class DiskSpillStore implements SpillStore {
262
309
  return ref
263
310
  }
264
311
 
265
- async read(ref: SpillRef): Promise<string> {
312
+ async read(ref: SpillRef, options?: SpillReadOptions): Promise<string> {
313
+ const maxBytes = checkedReadLimit(ref, options)
266
314
  const path = join(this.sessionDir, checkRelative(ref.path))
267
315
  let text: string
268
316
  try {
269
- text = await readFile(path, 'utf8')
317
+ options?.signal?.throwIfAborted()
318
+ if (maxBytes === undefined) {
319
+ text = await readFile(path, { encoding: 'utf8', signal: options?.signal })
320
+ } else {
321
+ // Reject links and special files before allocating a body buffer. The
322
+ // same narrow I/O primitives protect retained evidence readers.
323
+ const handle = await openEvidence(path)
324
+ try {
325
+ options?.signal?.throwIfAborted()
326
+ const before = await handle.stat()
327
+ checkActualReadSize(ref, before.size, maxBytes)
328
+ const bytes = await readBytes(handle, 0, before.size, {
329
+ bytes: 0,
330
+ limit: maxBytes,
331
+ signal: options?.signal,
332
+ })
333
+ options?.signal?.throwIfAborted()
334
+ if (stamp(before) !== stamp(await handle.stat())) {
335
+ throw new SpillIntegrityError(ref.path, `Spill ${ref.path} changed while reading.`)
336
+ }
337
+ options?.signal?.throwIfAborted()
338
+ text = decode(bytes)
339
+ } finally {
340
+ await handle.close()
341
+ }
342
+ }
270
343
  } catch (error) {
344
+ options?.signal?.throwIfAborted()
345
+ if (error instanceof SpillIntegrityError) throw error
271
346
  throw new SpillIntegrityError(
272
347
  ref.path,
273
348
  `Spill ${ref.path} cannot be read (${(error as NodeJS.ErrnoException).code ?? 'error'}). Refusing rather than folding a message the log cannot vouch for.`,
274
349
  { cause: error },
275
350
  )
276
351
  }
277
- return verify(ref, text)
352
+ options?.signal?.throwIfAborted()
353
+ const verified = verify(ref, text)
354
+ options?.signal?.throwIfAborted()
355
+ return verified
278
356
  }
279
357
  }
280
358
 
@@ -301,11 +379,16 @@ export class InMemorySpillStore implements SpillStore {
301
379
  return ref
302
380
  }
303
381
 
304
- async read(ref: SpillRef): Promise<string> {
382
+ async read(ref: SpillRef, options?: SpillReadOptions): Promise<string> {
383
+ const maxBytes = checkedReadLimit(ref, options)
305
384
  const text = this.#files.get(checkRelative(ref.path).split(sep).join('/'))
306
385
  if (text === undefined) {
307
386
  throw new SpillIntegrityError(ref.path, `Spill ${ref.path} does not exist.`)
308
387
  }
309
- return verify(ref, text)
388
+ if (maxBytes !== undefined) checkActualReadSize(ref, Buffer.byteLength(text, 'utf8'), maxBytes)
389
+ options?.signal?.throwIfAborted()
390
+ const verified = verify(ref, text)
391
+ options?.signal?.throwIfAborted()
392
+ return verified
310
393
  }
311
394
  }