@namzu/sdk 49.0.0 → 50.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 (742) hide show
  1. package/CHANGELOG.md +541 -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/provider/strict-schema.d.ts +28 -0
  222. package/dist/provider/strict-schema.d.ts.map +1 -1
  223. package/dist/provider/strict-schema.js +86 -0
  224. package/dist/provider/strict-schema.js.map +1 -1
  225. package/dist/public-runtime.d.ts +42 -14
  226. package/dist/public-runtime.d.ts.map +1 -1
  227. package/dist/public-runtime.js +36 -8
  228. package/dist/public-runtime.js.map +1 -1
  229. package/dist/public-tools.d.ts +8 -3
  230. package/dist/public-tools.d.ts.map +1 -1
  231. package/dist/public-tools.js +8 -3
  232. package/dist/public-tools.js.map +1 -1
  233. package/dist/public-types.d.ts +27 -7
  234. package/dist/public-types.d.ts.map +1 -1
  235. package/dist/registry/tool/presentation.d.ts +1 -0
  236. package/dist/registry/tool/presentation.d.ts.map +1 -1
  237. package/dist/registry/tool/presentation.js +9 -7
  238. package/dist/registry/tool/presentation.js.map +1 -1
  239. package/dist/runtime/harness-session/index.d.ts +5 -0
  240. package/dist/runtime/harness-session/index.d.ts.map +1 -0
  241. package/dist/runtime/harness-session/index.js +928 -0
  242. package/dist/runtime/harness-session/index.js.map +1 -0
  243. package/dist/runtime/harness-session/journal.d.ts +37 -0
  244. package/dist/runtime/harness-session/journal.d.ts.map +1 -0
  245. package/dist/runtime/harness-session/journal.js +177 -0
  246. package/dist/runtime/harness-session/journal.js.map +1 -0
  247. package/dist/runtime/harness-session/saved-view.d.ts +8 -0
  248. package/dist/runtime/harness-session/saved-view.d.ts.map +1 -0
  249. package/dist/runtime/harness-session/saved-view.js +112 -0
  250. package/dist/runtime/harness-session/saved-view.js.map +1 -0
  251. package/dist/runtime/jobs/awaited-jobs.d.ts +2 -1
  252. package/dist/runtime/jobs/awaited-jobs.d.ts.map +1 -1
  253. package/dist/runtime/jobs/awaited-jobs.js +2 -1
  254. package/dist/runtime/jobs/awaited-jobs.js.map +1 -1
  255. package/dist/runtime/jobs/registry.d.ts +56 -1
  256. package/dist/runtime/jobs/registry.d.ts.map +1 -1
  257. package/dist/runtime/jobs/registry.js +351 -34
  258. package/dist/runtime/jobs/registry.js.map +1 -1
  259. package/dist/runtime/query/abandon-turn.d.ts +12 -1
  260. package/dist/runtime/query/abandon-turn.d.ts.map +1 -1
  261. package/dist/runtime/query/abandon-turn.js +3 -1
  262. package/dist/runtime/query/abandon-turn.js.map +1 -1
  263. package/dist/runtime/query/checkpoint.d.ts +4 -0
  264. package/dist/runtime/query/checkpoint.d.ts.map +1 -1
  265. package/dist/runtime/query/checkpoint.js +10 -0
  266. package/dist/runtime/query/checkpoint.js.map +1 -1
  267. package/dist/runtime/query/durable-inbound.d.ts +5 -0
  268. package/dist/runtime/query/durable-inbound.d.ts.map +1 -0
  269. package/dist/runtime/query/durable-inbound.js +89 -0
  270. package/dist/runtime/query/durable-inbound.js.map +1 -0
  271. package/dist/runtime/query/events.d.ts +4 -0
  272. package/dist/runtime/query/events.d.ts.map +1 -1
  273. package/dist/runtime/query/events.js +22 -5
  274. package/dist/runtime/query/events.js.map +1 -1
  275. package/dist/runtime/query/executor/tool-call-admission.d.ts +5 -1
  276. package/dist/runtime/query/executor/tool-call-admission.d.ts.map +1 -1
  277. package/dist/runtime/query/executor/tool-call-admission.js +85 -13
  278. package/dist/runtime/query/executor/tool-call-admission.js.map +1 -1
  279. package/dist/runtime/query/executor.d.ts +41 -18
  280. package/dist/runtime/query/executor.d.ts.map +1 -1
  281. package/dist/runtime/query/executor.js +227 -114
  282. package/dist/runtime/query/executor.js.map +1 -1
  283. package/dist/runtime/query/index.d.ts +3 -0
  284. package/dist/runtime/query/index.d.ts.map +1 -1
  285. package/dist/runtime/query/index.js +21 -4
  286. package/dist/runtime/query/index.js.map +1 -1
  287. package/dist/runtime/query/iteration/index.d.ts +18 -6
  288. package/dist/runtime/query/iteration/index.d.ts.map +1 -1
  289. package/dist/runtime/query/iteration/index.js +144 -67
  290. package/dist/runtime/query/iteration/index.js.map +1 -1
  291. package/dist/runtime/query/iteration/outstanding-work.d.ts +9 -5
  292. package/dist/runtime/query/iteration/outstanding-work.d.ts.map +1 -1
  293. package/dist/runtime/query/iteration/outstanding-work.js +61 -6
  294. package/dist/runtime/query/iteration/outstanding-work.js.map +1 -1
  295. package/dist/runtime/query/iteration/phases/context.d.ts +4 -0
  296. package/dist/runtime/query/iteration/phases/context.d.ts.map +1 -1
  297. package/dist/runtime/query/iteration/phases/context.js.map +1 -1
  298. package/dist/runtime/query/iteration/phases/tool-review.d.ts.map +1 -1
  299. package/dist/runtime/query/iteration/phases/tool-review.js +99 -16
  300. package/dist/runtime/query/iteration/phases/tool-review.js.map +1 -1
  301. package/dist/runtime/query/observation-context.d.ts +2 -2
  302. package/dist/runtime/query/observation-context.d.ts.map +1 -1
  303. package/dist/runtime/query/observation-context.js +20 -13
  304. package/dist/runtime/query/observation-context.js.map +1 -1
  305. package/dist/runtime/query/prepare-turn.js +2 -2
  306. package/dist/runtime/query/prepare-turn.js.map +1 -1
  307. package/dist/runtime/query/prompt-cache.d.ts +1 -0
  308. package/dist/runtime/query/prompt-cache.d.ts.map +1 -1
  309. package/dist/runtime/query/prompt-cache.js +2 -0
  310. package/dist/runtime/query/prompt-cache.js.map +1 -1
  311. package/dist/runtime/query/prompt.d.ts +2 -0
  312. package/dist/runtime/query/prompt.d.ts.map +1 -1
  313. package/dist/runtime/query/prompt.js +23 -1
  314. package/dist/runtime/query/prompt.js.map +1 -1
  315. package/dist/runtime/query/repeat-call.d.ts +12 -3
  316. package/dist/runtime/query/repeat-call.d.ts.map +1 -1
  317. package/dist/runtime/query/repeat-call.js +33 -10
  318. package/dist/runtime/query/repeat-call.js.map +1 -1
  319. package/dist/runtime/query/resume-pending.d.ts +5 -6
  320. package/dist/runtime/query/resume-pending.d.ts.map +1 -1
  321. package/dist/runtime/query/resume-pending.js +30 -3
  322. package/dist/runtime/query/resume-pending.js.map +1 -1
  323. package/dist/runtime/query/resume-session.js +1 -1
  324. package/dist/runtime/query/resume-session.js.map +1 -1
  325. package/dist/runtime/query/review-policy.d.ts +8 -1
  326. package/dist/runtime/query/review-policy.d.ts.map +1 -1
  327. package/dist/runtime/query/review-policy.js +6 -0
  328. package/dist/runtime/query/review-policy.js.map +1 -1
  329. package/dist/runtime/query/saved-presentation.d.ts +13 -0
  330. package/dist/runtime/query/saved-presentation.d.ts.map +1 -0
  331. package/dist/runtime/query/saved-presentation.js +63 -0
  332. package/dist/runtime/query/saved-presentation.js.map +1 -0
  333. package/dist/runtime/query/steering.d.ts +6 -9
  334. package/dist/runtime/query/steering.d.ts.map +1 -1
  335. package/dist/runtime/query/steering.js.map +1 -1
  336. package/dist/runtime/query/tool-executions.d.ts +7 -3
  337. package/dist/runtime/query/tool-executions.d.ts.map +1 -1
  338. package/dist/runtime/query/tool-executions.js +89 -9
  339. package/dist/runtime/query/tool-executions.js.map +1 -1
  340. package/dist/runtime/query/tooling.d.ts +3 -1
  341. package/dist/runtime/query/tooling.d.ts.map +1 -1
  342. package/dist/runtime/query/tooling.js +3 -0
  343. package/dist/runtime/query/tooling.js.map +1 -1
  344. package/dist/scheduler/completion-inbox.d.ts +25 -1
  345. package/dist/scheduler/completion-inbox.d.ts.map +1 -1
  346. package/dist/scheduler/completion-inbox.js +102 -8
  347. package/dist/scheduler/completion-inbox.js.map +1 -1
  348. package/dist/scheduler/delegating.d.ts.map +1 -1
  349. package/dist/scheduler/delegating.js +5 -0
  350. package/dist/scheduler/delegating.js.map +1 -1
  351. package/dist/scheduler/local.d.ts.map +1 -1
  352. package/dist/scheduler/local.js +2 -0
  353. package/dist/scheduler/local.js.map +1 -1
  354. package/dist/session/summary/materialize.d.ts +10 -6
  355. package/dist/session/summary/materialize.d.ts.map +1 -1
  356. package/dist/session/summary/materialize.js +41 -8
  357. package/dist/session/summary/materialize.js.map +1 -1
  358. package/dist/store/budget/ledger.d.ts +9 -0
  359. package/dist/store/budget/ledger.d.ts.map +1 -1
  360. package/dist/store/budget/ledger.js +58 -6
  361. package/dist/store/budget/ledger.js.map +1 -1
  362. package/dist/store/evidence/index-page.d.ts +12 -12
  363. package/dist/store/evidence/source-text.d.ts +4 -4
  364. package/dist/store/session/disk.d.ts +9 -4
  365. package/dist/store/session/disk.d.ts.map +1 -1
  366. package/dist/store/session/disk.js +57 -11
  367. package/dist/store/session/disk.js.map +1 -1
  368. package/dist/store/session/memory.d.ts +5 -3
  369. package/dist/store/session/memory.d.ts.map +1 -1
  370. package/dist/store/session/memory.js +24 -7
  371. package/dist/store/session/memory.js.map +1 -1
  372. package/dist/store/session-log/core.d.ts +26 -6
  373. package/dist/store/session-log/core.d.ts.map +1 -1
  374. package/dist/store/session-log/core.js +61 -8
  375. package/dist/store/session-log/core.js.map +1 -1
  376. package/dist/store/session-log/disk.d.ts +2 -2
  377. package/dist/store/session-log/disk.d.ts.map +1 -1
  378. package/dist/store/session-log/disk.js +1 -0
  379. package/dist/store/session-log/disk.js.map +1 -1
  380. package/dist/store/session-log/fold.d.ts +7 -0
  381. package/dist/store/session-log/fold.d.ts.map +1 -1
  382. package/dist/store/session-log/fold.js +21 -0
  383. package/dist/store/session-log/fold.js.map +1 -1
  384. package/dist/store/session-log/index.d.ts +5 -3
  385. package/dist/store/session-log/index.d.ts.map +1 -1
  386. package/dist/store/session-log/index.js +3 -1
  387. package/dist/store/session-log/index.js.map +1 -1
  388. package/dist/store/session-log/memory.d.ts +1 -1
  389. package/dist/store/session-log/memory.d.ts.map +1 -1
  390. package/dist/store/session-log/memory.js +1 -0
  391. package/dist/store/session-log/memory.js.map +1 -1
  392. package/dist/store/session-log/spill.d.ts +10 -3
  393. package/dist/store/session-log/spill.d.ts.map +1 -1
  394. package/dist/store/session-log/spill.js +70 -5
  395. package/dist/store/session-log/spill.js.map +1 -1
  396. package/dist/store/session-log/structured-result.d.ts +21 -0
  397. package/dist/store/session-log/structured-result.d.ts.map +1 -0
  398. package/dist/store/session-log/structured-result.js +67 -0
  399. package/dist/store/session-log/structured-result.js.map +1 -0
  400. package/dist/store/task/disk.d.ts +11 -0
  401. package/dist/store/task/disk.d.ts.map +1 -1
  402. package/dist/store/task/disk.js +41 -2
  403. package/dist/store/task/disk.js.map +1 -1
  404. package/dist/store/task/memory.d.ts.map +1 -1
  405. package/dist/store/task/memory.js +15 -3
  406. package/dist/store/task/memory.js.map +1 -1
  407. package/dist/tools/admit-facts.d.ts +13 -0
  408. package/dist/tools/admit-facts.d.ts.map +1 -0
  409. package/dist/tools/admit-facts.js +142 -0
  410. package/dist/tools/admit-facts.js.map +1 -0
  411. package/dist/tools/builtins/bash.d.ts +4 -1
  412. package/dist/tools/builtins/bash.d.ts.map +1 -1
  413. package/dist/tools/builtins/bash.js +108 -22
  414. package/dist/tools/builtins/bash.js.map +1 -1
  415. package/dist/tools/builtins/browser.d.ts +10 -10
  416. package/dist/tools/builtins/computer-use.d.ts +90 -90
  417. package/dist/tools/builtins/edit.d.ts +17 -0
  418. package/dist/tools/builtins/edit.d.ts.map +1 -1
  419. package/dist/tools/builtins/edit.js +46 -1
  420. package/dist/tools/builtins/edit.js.map +1 -1
  421. package/dist/tools/builtins/file-write-result.d.ts.map +1 -1
  422. package/dist/tools/builtins/file-write-result.js +13 -0
  423. package/dist/tools/builtins/file-write-result.js.map +1 -1
  424. package/dist/tools/builtins/glob.d.ts.map +1 -1
  425. package/dist/tools/builtins/glob.js +12 -0
  426. package/dist/tools/builtins/glob.js.map +1 -1
  427. package/dist/tools/builtins/grep.d.ts.map +1 -1
  428. package/dist/tools/builtins/grep.js +14 -0
  429. package/dist/tools/builtins/grep.js.map +1 -1
  430. package/dist/tools/builtins/index.d.ts +2 -0
  431. package/dist/tools/builtins/index.d.ts.map +1 -1
  432. package/dist/tools/builtins/index.js +1 -0
  433. package/dist/tools/builtins/index.js.map +1 -1
  434. package/dist/tools/builtins/job.d.ts.map +1 -1
  435. package/dist/tools/builtins/job.js +4 -1
  436. package/dist/tools/builtins/job.js.map +1 -1
  437. package/dist/tools/builtins/lsp.d.ts +2 -2
  438. package/dist/tools/builtins/read-file.d.ts.map +1 -1
  439. package/dist/tools/builtins/read-file.js +49 -0
  440. package/dist/tools/builtins/read-file.js.map +1 -1
  441. package/dist/tools/builtins/view-image.d.ts +24 -0
  442. package/dist/tools/builtins/view-image.d.ts.map +1 -0
  443. package/dist/tools/builtins/view-image.js +385 -0
  444. package/dist/tools/builtins/view-image.js.map +1 -0
  445. package/dist/tools/builtins/wait-for-job-bounds.d.ts +2 -0
  446. package/dist/tools/builtins/wait-for-job-bounds.d.ts.map +1 -1
  447. package/dist/tools/builtins/wait-for-job-bounds.js +1 -0
  448. package/dist/tools/builtins/wait-for-job-bounds.js.map +1 -1
  449. package/dist/tools/builtins/wait-for-job.d.ts +2 -0
  450. package/dist/tools/builtins/wait-for-job.d.ts.map +1 -1
  451. package/dist/tools/builtins/wait-for-job.js +104 -6
  452. package/dist/tools/builtins/wait-for-job.js.map +1 -1
  453. package/dist/tools/builtins/write-file.d.ts.map +1 -1
  454. package/dist/tools/builtins/write-file.js +1 -0
  455. package/dist/tools/builtins/write-file.js.map +1 -1
  456. package/dist/tools/command-shell.d.ts +37 -2
  457. package/dist/tools/command-shell.d.ts.map +1 -1
  458. package/dist/tools/command-shell.js +100 -3
  459. package/dist/tools/command-shell.js.map +1 -1
  460. package/dist/tools/coordinator/agent.d.ts +9 -19
  461. package/dist/tools/coordinator/agent.d.ts.map +1 -1
  462. package/dist/tools/coordinator/agent.js.map +1 -1
  463. package/dist/tools/coordinator/index.d.ts.map +1 -1
  464. package/dist/tools/coordinator/index.js +127 -67
  465. package/dist/tools/coordinator/index.js.map +1 -1
  466. package/dist/tools/coordinator/wait-with-idle-bound.d.ts +2 -0
  467. package/dist/tools/coordinator/wait-with-idle-bound.d.ts.map +1 -1
  468. package/dist/tools/coordinator/wait-with-idle-bound.js +1 -1
  469. package/dist/tools/coordinator/wait-with-idle-bound.js.map +1 -1
  470. package/dist/tools/defineTool.d.ts.map +1 -1
  471. package/dist/tools/defineTool.js +4 -0
  472. package/dist/tools/defineTool.js.map +1 -1
  473. package/dist/tools/failure-facts.d.ts +8 -0
  474. package/dist/tools/failure-facts.d.ts.map +1 -0
  475. package/dist/tools/failure-facts.js +24 -0
  476. package/dist/tools/failure-facts.js.map +1 -0
  477. package/dist/tools/host-output.d.ts +24 -0
  478. package/dist/tools/host-output.d.ts.map +1 -0
  479. package/dist/tools/host-output.js +117 -0
  480. package/dist/tools/host-output.js.map +1 -0
  481. package/dist/tools/oem-code-pages.d.ts +8 -0
  482. package/dist/tools/oem-code-pages.d.ts.map +1 -0
  483. package/dist/tools/oem-code-pages.js +23 -0
  484. package/dist/tools/oem-code-pages.js.map +1 -0
  485. package/dist/tools/schedules/schedule-tool.d.ts.map +1 -1
  486. package/dist/tools/schedules/schedule-tool.js +35 -6
  487. package/dist/tools/schedules/schedule-tool.js.map +1 -1
  488. package/dist/tools/schedules/types.d.ts +23 -3
  489. package/dist/tools/schedules/types.d.ts.map +1 -1
  490. package/dist/tools/task/list.d.ts.map +1 -1
  491. package/dist/tools/task/list.js +14 -6
  492. package/dist/tools/task/list.js.map +1 -1
  493. package/dist/tools/task/present.d.ts.map +1 -1
  494. package/dist/tools/task/present.js +26 -6
  495. package/dist/tools/task/present.js.map +1 -1
  496. package/dist/tools/task/update.d.ts.map +1 -1
  497. package/dist/tools/task/update.js +12 -5
  498. package/dist/tools/task/update.js.map +1 -1
  499. package/dist/tools/text-window.d.ts +19 -0
  500. package/dist/tools/text-window.d.ts.map +1 -0
  501. package/dist/tools/text-window.js +83 -0
  502. package/dist/tools/text-window.js.map +1 -0
  503. package/dist/toolsets/manager.d.ts +11 -0
  504. package/dist/toolsets/manager.d.ts.map +1 -1
  505. package/dist/toolsets/manager.js +45 -1
  506. package/dist/toolsets/manager.js.map +1 -1
  507. package/dist/types/acp/index.d.ts +137 -1
  508. package/dist/types/acp/index.d.ts.map +1 -1
  509. package/dist/types/agent/base.d.ts +3 -0
  510. package/dist/types/agent/base.d.ts.map +1 -1
  511. package/dist/types/agent/manager.d.ts +8 -23
  512. package/dist/types/agent/manager.d.ts.map +1 -1
  513. package/dist/types/agent/scheduler.d.ts +10 -1
  514. package/dist/types/agent/scheduler.d.ts.map +1 -1
  515. package/dist/types/agent/task.d.ts +4 -0
  516. package/dist/types/agent/task.d.ts.map +1 -1
  517. package/dist/types/authorization/index.d.ts +30 -30
  518. package/dist/types/connector/mcp.d.ts +7 -0
  519. package/dist/types/connector/mcp.d.ts.map +1 -1
  520. package/dist/types/errors/catalog.d.ts.map +1 -1
  521. package/dist/types/errors/catalog.js +4 -2
  522. package/dist/types/errors/catalog.js.map +1 -1
  523. package/dist/types/harness/schema.d.ts +354 -0
  524. package/dist/types/harness/schema.d.ts.map +1 -0
  525. package/dist/types/harness/schema.js +203 -0
  526. package/dist/types/harness/schema.js.map +1 -0
  527. package/dist/types/harness/session.d.ts +278 -0
  528. package/dist/types/harness/session.d.ts.map +1 -0
  529. package/dist/types/harness/session.js +2 -0
  530. package/dist/types/harness/session.js.map +1 -0
  531. package/dist/types/hitl/index.d.ts +12 -0
  532. package/dist/types/hitl/index.d.ts.map +1 -1
  533. package/dist/types/hitl/index.js.map +1 -1
  534. package/dist/types/job/index.d.ts +47 -0
  535. package/dist/types/job/index.d.ts.map +1 -0
  536. package/dist/types/job/index.js +2 -0
  537. package/dist/types/job/index.js.map +1 -0
  538. package/dist/types/message/inbound-delivery.d.ts +44 -0
  539. package/dist/types/message/inbound-delivery.d.ts.map +1 -0
  540. package/dist/types/message/inbound-delivery.js +14 -0
  541. package/dist/types/message/inbound-delivery.js.map +1 -0
  542. package/dist/types/message/index.d.ts +4 -1
  543. package/dist/types/message/index.d.ts.map +1 -1
  544. package/dist/types/message/index.js +5 -1
  545. package/dist/types/message/index.js.map +1 -1
  546. package/dist/types/plugin/index.d.ts +6 -6
  547. package/dist/types/sandbox/index.d.ts +39 -2
  548. package/dist/types/sandbox/index.d.ts.map +1 -1
  549. package/dist/types/sandbox/index.js.map +1 -1
  550. package/dist/types/session/checkpoint.d.ts +24 -17
  551. package/dist/types/session/checkpoint.d.ts.map +1 -1
  552. package/dist/types/session/checkpoint.js +1 -0
  553. package/dist/types/session/checkpoint.js.map +1 -1
  554. package/dist/types/session/events.d.ts +23 -1
  555. package/dist/types/session/events.d.ts.map +1 -1
  556. package/dist/types/session/events.js.map +1 -1
  557. package/dist/types/session/records.d.ts +1514 -565
  558. package/dist/types/session/records.d.ts.map +1 -1
  559. package/dist/types/session/records.js +89 -1
  560. package/dist/types/session/records.js.map +1 -1
  561. package/dist/types/session/step.d.ts +2 -0
  562. package/dist/types/session/step.d.ts.map +1 -1
  563. package/dist/types/session/step.js.map +1 -1
  564. package/dist/types/session/store.d.ts +19 -10
  565. package/dist/types/session/store.d.ts.map +1 -1
  566. package/dist/types/session/tool-execution.d.ts +6 -0
  567. package/dist/types/session/tool-execution.d.ts.map +1 -1
  568. package/dist/types/structured-output/index.d.ts +12 -2
  569. package/dist/types/structured-output/index.d.ts.map +1 -1
  570. package/dist/types/summary/ref.d.ts +3 -1
  571. package/dist/types/summary/ref.d.ts.map +1 -1
  572. package/dist/types/tool/index.d.ts +32 -4
  573. package/dist/types/tool/index.d.ts.map +1 -1
  574. package/dist/types/tool/index.js.map +1 -1
  575. package/dist/types/tool/presentation.d.ts +106 -0
  576. package/dist/types/tool/presentation.d.ts.map +1 -1
  577. package/dist/utils/json-snapshot.d.ts +6 -2
  578. package/dist/utils/json-snapshot.d.ts.map +1 -1
  579. package/dist/utils/json-snapshot.js +19 -9
  580. package/dist/utils/json-snapshot.js.map +1 -1
  581. package/dist/utils/structured-result-json.d.ts +5 -0
  582. package/dist/utils/structured-result-json.d.ts.map +1 -0
  583. package/dist/utils/structured-result-json.js +10 -0
  584. package/dist/utils/structured-result-json.js.map +1 -0
  585. package/package.json +1 -1
  586. package/src/agents/QueryAgent.ts +1 -0
  587. package/src/agents/examples/SupervisorAgent.ts +1 -0
  588. package/src/agents/runAgent.ts +3 -0
  589. package/src/authorization/shell-lexer.ts +16 -1
  590. package/src/bridge/acp/permission.ts +17 -3
  591. package/src/bridge/acp/server.ts +271 -25
  592. package/src/bridge/acp/tasks.ts +23 -0
  593. package/src/bridge/acp/update.ts +167 -13
  594. package/src/connector/mcp/adapter.ts +16 -4
  595. package/src/connector/mcp/client.ts +6 -2
  596. package/src/constants/acp/index.ts +4 -0
  597. package/src/manager/agent/lifecycle.ts +230 -3
  598. package/src/manager/plan/lifecycle.ts +11 -9
  599. package/src/manager/session/attribution.ts +12 -2
  600. package/src/manager/session/streamed-message-identity.ts +21 -0
  601. package/src/manager/session/turn-recorder.ts +4 -3
  602. package/src/pals/activity/causality.ts +261 -0
  603. package/src/pals/activity/projection.ts +89 -0
  604. package/src/pals/activity/source.ts +240 -0
  605. package/src/pals/activity/subscription-policy.ts +230 -0
  606. package/src/pals/activity/subscription-schema.ts +27 -0
  607. package/src/pals/activity/subscription-store.ts +172 -0
  608. package/src/pals/activity/subscription-types.ts +48 -0
  609. package/src/pals/activity/subscriptions.ts +209 -0
  610. package/src/pals/activity/types.ts +108 -0
  611. package/src/pals/channels/ingress.ts +153 -0
  612. package/src/pals/channels/routes.ts +118 -0
  613. package/src/pals/channels/routing.ts +197 -0
  614. package/src/pals/channels/schema.ts +108 -0
  615. package/src/pals/channels/types.ts +156 -0
  616. package/src/pals/communication/broker.ts +131 -0
  617. package/src/pals/communication/dispatch.ts +66 -0
  618. package/src/pals/communication/inbound.ts +193 -0
  619. package/src/pals/communication/ingress-dispatch.ts +63 -0
  620. package/src/pals/communication/ingress-inbound.ts +269 -0
  621. package/src/pals/communication/ingress-schema.ts +526 -0
  622. package/src/pals/communication/ingress-types.ts +336 -0
  623. package/src/pals/communication/operator.ts +315 -0
  624. package/src/pals/communication/policy.ts +174 -0
  625. package/src/pals/communication/schema.ts +173 -0
  626. package/src/pals/communication/store.ts +577 -0
  627. package/src/pals/communication/tools.ts +139 -0
  628. package/src/pals/communication/types.ts +227 -0
  629. package/src/pals/communication/verify.ts +220 -0
  630. package/src/pals/lifecycle.ts +54 -0
  631. package/src/pals/prompt.ts +101 -0
  632. package/src/pals/reference-images.ts +322 -0
  633. package/src/pals/runtime.ts +670 -0
  634. package/src/pals/store.ts +369 -0
  635. package/src/pals/types.ts +157 -0
  636. package/src/peers/envelope.ts +1 -1
  637. package/src/plugin/shell-hook.ts +8 -2
  638. package/src/process/kill-tree.ts +10 -1
  639. package/src/provider/errors.ts +135 -2
  640. package/src/provider/strict-schema.ts +90 -0
  641. package/src/public-runtime.ts +118 -12
  642. package/src/public-tools.ts +13 -1
  643. package/src/public-types.ts +69 -7
  644. package/src/registry/tool/presentation.ts +9 -4
  645. package/src/runtime/harness-session/index.ts +1125 -0
  646. package/src/runtime/harness-session/journal.ts +209 -0
  647. package/src/runtime/harness-session/saved-view.ts +122 -0
  648. package/src/runtime/jobs/awaited-jobs.ts +2 -1
  649. package/src/runtime/jobs/registry.ts +397 -41
  650. package/src/runtime/query/abandon-turn.ts +18 -2
  651. package/src/runtime/query/checkpoint.ts +11 -0
  652. package/src/runtime/query/durable-inbound.ts +101 -0
  653. package/src/runtime/query/events.ts +22 -5
  654. package/src/runtime/query/executor/tool-call-admission.ts +125 -32
  655. package/src/runtime/query/executor.ts +316 -130
  656. package/src/runtime/query/index.ts +24 -4
  657. package/src/runtime/query/iteration/index.ts +218 -104
  658. package/src/runtime/query/iteration/outstanding-work.ts +55 -7
  659. package/src/runtime/query/iteration/phases/context.ts +4 -0
  660. package/src/runtime/query/iteration/phases/tool-review.ts +118 -21
  661. package/src/runtime/query/observation-context.ts +22 -16
  662. package/src/runtime/query/prepare-turn.ts +2 -2
  663. package/src/runtime/query/prompt-cache.ts +3 -0
  664. package/src/runtime/query/prompt.ts +32 -1
  665. package/src/runtime/query/repeat-call.ts +40 -10
  666. package/src/runtime/query/resume-pending.ts +60 -7
  667. package/src/runtime/query/resume-session.ts +1 -1
  668. package/src/runtime/query/review-policy.ts +23 -2
  669. package/src/runtime/query/saved-presentation.ts +70 -0
  670. package/src/runtime/query/steering.ts +6 -9
  671. package/src/runtime/query/tool-executions.ts +108 -9
  672. package/src/runtime/query/tooling.ts +6 -1
  673. package/src/scheduler/completion-inbox.ts +108 -7
  674. package/src/scheduler/delegating.ts +5 -0
  675. package/src/scheduler/local.ts +2 -0
  676. package/src/session/summary/materialize.ts +51 -9
  677. package/src/store/budget/ledger.ts +60 -5
  678. package/src/store/session/disk.ts +77 -10
  679. package/src/store/session/memory.ts +32 -7
  680. package/src/store/session-log/core.ts +118 -11
  681. package/src/store/session-log/disk.ts +9 -2
  682. package/src/store/session-log/fold.ts +22 -0
  683. package/src/store/session-log/index.ts +5 -0
  684. package/src/store/session-log/memory.ts +2 -1
  685. package/src/store/session-log/spill.ts +89 -6
  686. package/src/store/session-log/structured-result.ts +96 -0
  687. package/src/store/task/disk.ts +46 -2
  688. package/src/store/task/memory.ts +13 -3
  689. package/src/tools/admit-facts.ts +145 -0
  690. package/src/tools/builtins/bash.ts +132 -24
  691. package/src/tools/builtins/edit.ts +54 -1
  692. package/src/tools/builtins/file-write-result.ts +14 -0
  693. package/src/tools/builtins/glob.ts +12 -0
  694. package/src/tools/builtins/grep.ts +14 -0
  695. package/src/tools/builtins/index.ts +2 -0
  696. package/src/tools/builtins/job.ts +4 -1
  697. package/src/tools/builtins/read-file.ts +57 -0
  698. package/src/tools/builtins/view-image.ts +409 -0
  699. package/src/tools/builtins/wait-for-job-bounds.ts +3 -0
  700. package/src/tools/builtins/wait-for-job.ts +141 -32
  701. package/src/tools/builtins/write-file.ts +4 -2
  702. package/src/tools/command-shell.ts +132 -5
  703. package/src/tools/coordinator/agent.ts +9 -19
  704. package/src/tools/coordinator/index.ts +150 -75
  705. package/src/tools/coordinator/wait-with-idle-bound.ts +3 -1
  706. package/src/tools/defineTool.ts +4 -0
  707. package/src/tools/failure-facts.ts +24 -0
  708. package/src/tools/host-output.ts +136 -0
  709. package/src/tools/oem-code-pages.ts +22 -0
  710. package/src/tools/schedules/schedule-tool.ts +38 -5
  711. package/src/tools/schedules/types.ts +23 -3
  712. package/src/tools/task/list.ts +15 -7
  713. package/src/tools/task/present.ts +37 -7
  714. package/src/tools/task/update.ts +12 -5
  715. package/src/tools/text-window.ts +87 -0
  716. package/src/toolsets/manager.ts +58 -1
  717. package/src/types/acp/index.ts +150 -4
  718. package/src/types/agent/base.ts +3 -0
  719. package/src/types/agent/manager.ts +8 -23
  720. package/src/types/agent/scheduler.ts +10 -1
  721. package/src/types/agent/task.ts +4 -0
  722. package/src/types/connector/mcp.ts +7 -0
  723. package/src/types/errors/catalog.ts +4 -2
  724. package/src/types/harness/schema.ts +203 -0
  725. package/src/types/harness/session.ts +306 -0
  726. package/src/types/hitl/index.ts +17 -1
  727. package/src/types/job/index.ts +42 -0
  728. package/src/types/message/inbound-delivery.ts +63 -0
  729. package/src/types/message/index.ts +8 -1
  730. package/src/types/sandbox/index.ts +46 -0
  731. package/src/types/session/checkpoint.ts +4 -1
  732. package/src/types/session/events.ts +23 -1
  733. package/src/types/session/records.ts +114 -2
  734. package/src/types/session/step.ts +2 -0
  735. package/src/types/session/store.ts +23 -9
  736. package/src/types/session/tool-execution.ts +6 -0
  737. package/src/types/structured-output/index.ts +13 -2
  738. package/src/types/summary/ref.ts +3 -1
  739. package/src/types/tool/index.ts +39 -5
  740. package/src/types/tool/presentation.ts +121 -0
  741. package/src/utils/json-snapshot.ts +26 -9
  742. package/src/utils/structured-result-json.ts +10 -0
@@ -1,3 +1,4 @@
1
+ import { createHash } from 'node:crypto'
1
2
  import { createRuntimeContextMessage } from '../../types/message/index.js'
2
3
  import type { Message } from '../../types/message/index.js'
3
4
  import { stableStringify } from './tool-grants.js'
@@ -66,8 +67,8 @@ export class RepeatCallTracker {
66
67
  /** Which keys have already been reported at which level, so one repeat
67
68
  * does not produce the same sentence on every subsequent turn. */
68
69
  private readonly announced = new Map<string, 'notice' | 'escalated'>()
69
- /** Consecutive failures per key; a success deletes the entry. */
70
- private readonly failures = new Map<string, number>()
70
+ /** Identical actual results since the last successful possible mutation. */
71
+ private readonly failures = new Map<string, { fingerprint: string; count: number }>()
71
72
 
72
73
  constructor(private readonly thresholds: RepeatCallThresholds = DEFAULT_REPEAT_THRESHOLDS) {}
73
74
 
@@ -80,13 +81,12 @@ export class RepeatCallTracker {
80
81
  record(
81
82
  toolName: string,
82
83
  input: unknown,
83
- outcome?: { readonly failed: boolean },
84
+ outcome?: { readonly failed: boolean; readonly result?: unknown },
84
85
  ): RepeatCallNotice | undefined {
85
86
  const key = keyFor(toolName, input)
86
87
  const count = (this.counts.get(key) ?? 0) + 1
87
88
  this.counts.set(key, count)
88
- if (outcome?.failed === true) this.failures.set(key, (this.failures.get(key) ?? 0) + 1)
89
- else if (outcome?.failed === false) this.failures.delete(key)
89
+ if (outcome) this.recordOutcome(toolName, input, outcome)
90
90
 
91
91
  const already = this.announced.get(key)
92
92
  if (count >= this.thresholds.escalateAfter && already !== 'escalated') {
@@ -95,7 +95,7 @@ export class RepeatCallTracker {
95
95
  toolName,
96
96
  count,
97
97
  level: 'escalated',
98
- text: `You have now called \`${toolName}\` with identical arguments ${count} times in this turn. Repeating it again will produce the same result. Change the arguments, use a different tool, or tell the user what is blocking you and stop.`,
98
+ text: `You have now called \`${toolName}\` with identical arguments ${count} times in this turn. Check whether the results or the state have changed. If there is no progress, change the approach or tell the user what is blocking you.`,
99
99
  }
100
100
  }
101
101
  if (count >= this.thresholds.notifyAfter && already === undefined) {
@@ -110,6 +110,33 @@ export class RepeatCallTracker {
110
110
  return undefined
111
111
  }
112
112
 
113
+ /** Only actual executions count. Denials and recovered receipts do not. */
114
+ recordOutcome(
115
+ toolName: string,
116
+ input: unknown,
117
+ outcome: { readonly failed: boolean; readonly result?: unknown },
118
+ ): void {
119
+ const key = keyFor(toolName, input)
120
+ if (!outcome.failed) {
121
+ this.failures.delete(key)
122
+ return
123
+ }
124
+ const fingerprint = createHash('sha256')
125
+ .update(stableStringify(outcome.result ?? null))
126
+ .digest('hex')
127
+ const previous = this.failures.get(key)
128
+ this.failures.set(key, {
129
+ fingerprint,
130
+ count: previous?.fingerprint === fingerprint ? previous.count + 1 : 1,
131
+ })
132
+ }
133
+
134
+ /** A successful potentially mutating execution permits a new experiment.
135
+ * This does not prove progress; the turn's existing budgets still apply. */
136
+ stateMayHaveChanged(): void {
137
+ this.failures.clear()
138
+ }
139
+
113
140
  /** Repeats seen for one call, for a host that wants to render it. */
114
141
  countOf(toolName: string, input: unknown): number {
115
142
  return this.counts.get(keyFor(toolName, input)) ?? 0
@@ -118,11 +145,11 @@ export class RepeatCallTracker {
118
145
  /**
119
146
  * The refusal for a call that has failed identically too many times in
120
147
  * a row, or `undefined` when the call may run. Asked BEFORE execution;
121
- * the refused call is still recorded afterwards, as a failure, so the
122
- * refusal holds until the model changes something.
148
+ * a synthetic refusal is not an execution and does not replace its result
149
+ * fingerprint. The refusal holds until a real state change or new outcome.
123
150
  */
124
151
  refusal(toolName: string, input: unknown): string | undefined {
125
- const failed = this.failures.get(keyFor(toolName, input)) ?? 0
152
+ const failed = this.failures.get(keyFor(toolName, input))?.count ?? 0
126
153
  if (failed < this.thresholds.refuseFailedAfter) return undefined
127
154
  return `Refused: \`${toolName}\` with these exact arguments has failed ${failed} times in a row in this turn, with the same result each time. It will not be run again with these arguments. Change the arguments, use a different tool, or tell the user what is blocking you and stop.`
128
155
  }
@@ -167,7 +194,10 @@ export function attachRepeatNotice(
167
194
 
168
195
  if (target && typeof target.content === 'string') {
169
196
  const next = [...messages]
170
- next[lastToolIndex] = { ...target, content: `${target.content}\n\n${noticeText}` }
197
+ next[lastToolIndex] = {
198
+ ...target,
199
+ content: `${target.content}\n\n${noticeText}`,
200
+ }
171
201
  return next
172
202
  }
173
203
 
@@ -15,7 +15,14 @@ import type { ToolExecutionSnapshot } from '../../types/session/tool-execution.j
15
15
  import type { Logger } from '../../utils/logger.js'
16
16
  import type { RestoredCheckpoint } from './checkpoint.js'
17
17
  import { DECLINED_TOOL_CALL_FEEDBACK } from './declined.js'
18
- import type { PriorToolResults, ToolCallDenials, ToolExecutor } from './executor.js'
18
+ import type {
19
+ PriorToolResult,
20
+ PriorToolResults,
21
+ ToolCallDeclines,
22
+ ToolCallDenials,
23
+ ToolExecutionBatch,
24
+ ToolExecutor,
25
+ } from './executor.js'
19
26
  import { PendingAnswers } from './question-park.js'
20
27
  import { readToolExecutions } from './tool-executions.js'
21
28
  import { isPauseForCall } from './tool-pause.js'
@@ -60,6 +67,8 @@ export interface PendingResumePlan {
60
67
  readonly response: ChatCompletionResponse
61
68
  /** Per-call refusals derived from the decision. */
62
69
  readonly denials: ToolCallDenials
70
+ /** The denials a person gave; see {@link ToolCallDeclines}. Absent for every other refusal. */
71
+ readonly declines?: ToolCallDeclines
63
72
  /** Exact projections and gate decisions persisted with a tool review. */
64
73
  readonly reviewedCalls?: readonly ToolCallSummary[]
65
74
  /** Calls whose raw input the human replaced in the durable decision. */
@@ -139,6 +148,7 @@ export function planPendingResume(
139
148
 
140
149
  const denials = derriveDenials(assistant.toolCalls, decision)
141
150
  if (!denials) return null
151
+ const declines = derriveDeclines(assistant.toolCalls, decision, pending.request.toolCalls)
142
152
 
143
153
  return {
144
154
  source: 'decision',
@@ -146,6 +156,7 @@ export function planPendingResume(
146
156
  assistant,
147
157
  response: synthesizeResponse(assistant),
148
158
  denials,
159
+ ...(declines ? { declines } : {}),
149
160
  reviewedCalls: pending.request.toolCalls,
150
161
  modifiedCallIds: modifiedCallIds(decision),
151
162
  ...((decision.action === 'approve_tools' || decision.action === 'modify_tools') &&
@@ -417,7 +428,7 @@ export async function applyPendingResume(
417
428
  executor: ToolExecutor,
418
429
  prior?: PriorToolResults,
419
430
  assistantMessageId?: MessageId,
420
- ): Promise<void> {
431
+ ): Promise<ToolExecutionBatch> {
421
432
  const denials = new Map(plan.denials)
422
433
  const reviewedById = new Map(plan.reviewedCalls?.map((call) => [call.id, call]))
423
434
 
@@ -439,7 +450,10 @@ export async function applyPendingResume(
439
450
  ...plan.response,
440
451
  message: { ...plan.response.message, toolCalls: callsToPrepare },
441
452
  }
442
- const preparedBatch = await executor.prepareBatchForReview(responseToPrepare)
453
+ const preparedBatch = await executor.prepareBatchForReview(
454
+ responseToPrepare,
455
+ plan.modifiedCallIds,
456
+ )
443
457
 
444
458
  for (const call of preparedBatch.reviewCalls) {
445
459
  const reviewed = reviewedById.get(call.id)
@@ -508,10 +522,17 @@ export async function applyPendingResume(
508
522
  // The parked assistant message is already in the log: it goes back into
509
523
  // the context under its own record id, never as a second copy.
510
524
  recorder.pushMessage(plan.assistant, assistantMessageId ? { messageId: assistantMessageId } : {})
511
- const batch = await executor.executeBatch(plan.response, denials, prior, preparedBatch)
525
+ const batch = await executor.executeBatch(
526
+ plan.response,
527
+ denials,
528
+ prior,
529
+ preparedBatch,
530
+ plan.declines,
531
+ )
512
532
  for (const msg of batch.messages) {
513
533
  recorder.pushMessage(msg)
514
534
  }
535
+ return batch
515
536
  }
516
537
 
517
538
  /**
@@ -567,8 +588,8 @@ export async function recoverCompletedCalls(
567
588
  toolCalls: readonly ToolCall[],
568
589
  log: Logger,
569
590
  options: { answers?: PendingAnswers; signal?: AbortSignal } = {},
570
- ): Promise<Map<string, { result: string; isError: boolean }>> {
571
- const recovered = new Map<string, { result: string; isError: boolean }>()
591
+ ): Promise<Map<string, PriorToolResult>> {
592
+ const recovered = new Map<string, PriorToolResult>()
572
593
  let snapshot: ToolExecutionSnapshot | undefined
573
594
  try {
574
595
  await recorder.flush()
@@ -592,7 +613,15 @@ export async function recoverCompletedCalls(
592
613
  ) {
593
614
  if (!record) continue // Complete evidence proves this call has no recorded start.
594
615
  if (record.status === 'completed') {
595
- recovered.set(call.id, { result: record.result, isError: record.isError })
616
+ recovered.set(call.id, {
617
+ result: record.result,
618
+ isError: record.isError,
619
+ ...(record.inputFailure ? { inputFailure: record.inputFailure } : {}),
620
+ ...(record.skipped ? { skipped: true as const } : {}),
621
+ ...(record.structuredResultJson !== undefined
622
+ ? { structuredResultJson: record.structuredResultJson }
623
+ : {}),
624
+ })
596
625
  continue
597
626
  }
598
627
  }
@@ -615,6 +644,30 @@ export async function recoverCompletedCalls(
615
644
  return recovered
616
645
  }
617
646
 
647
+ /** The calls a person refused in `decision`, for the record; `undefined` when none. */
648
+ function derriveDeclines(
649
+ toolCalls: readonly ToolCall[],
650
+ decision: HITLResumeDecision,
651
+ reviewed: readonly ToolCallSummary[] = [],
652
+ ): ToolCallDeclines | undefined {
653
+ // A call the gate refused was never the person's to decline.
654
+ const gateDenied = new Set(
655
+ reviewed.filter((call) => call.authorization?.decision === 'deny').map((call) => call.id),
656
+ )
657
+ if (decision.action === 'reject_tools' && decision.declined) {
658
+ const declined = decision.declined
659
+ const calls = toolCalls.filter((tc) => !gateDenied.has(tc.id))
660
+ return calls.length > 0 ? new Map(calls.map((tc) => [tc.id, declined])) : undefined
661
+ }
662
+ if (decision.action === 'modify_tools') {
663
+ const denied = decision.modifications.filter(
664
+ (mod) => mod.action === 'deny' && !gateDenied.has(mod.toolCallId),
665
+ )
666
+ if (denied.length > 0) return new Map(denied.map((mod) => [mod.toolCallId, {}]))
667
+ }
668
+ return undefined
669
+ }
670
+
618
671
  /**
619
672
  * Turn a decision into per-call refusals, or `null` when the decision does
620
673
  * not resolve the park at all.
@@ -79,7 +79,7 @@ export async function resumeSession(params: ResumeSessionParams): Promise<Resume
79
79
  // A caller-chosen checkpoint scope is not proof that the source log belongs
80
80
  // to it. Refuse foreign attribution before reading any checkpoint or park.
81
81
  assertResumeRequestAttribution(params, scope)
82
- if (!(await assertSessionLogAttribution(sessionLog, scope))) {
82
+ if (!(await assertSessionLogAttribution(sessionLog, scope, { execution: 'kernel' }))) {
83
83
  return { resumed: false, reason: 'no-checkpoint' }
84
84
  }
85
85
  const checkpointStore =
@@ -23,7 +23,12 @@
23
23
 
24
24
  import { isTrustedReadOnly } from '../../tools/trusted-read-only.js'
25
25
  import type { ToolManager } from '../../toolsets/manager.js'
26
- import type { HITLResumeDecision, ResumeHandler, ToolCallSummary } from '../../types/hitl/index.js'
26
+ import type {
27
+ HITLResumeDecision,
28
+ ResumeHandler,
29
+ ToolCallDeclined,
30
+ ToolCallSummary,
31
+ } from '../../types/hitl/index.js'
27
32
  import type { ApprovalPolicy } from '../../types/hitl/policy.js'
28
33
  import type { SessionId, TurnId } from '../../types/ids/index.js'
29
34
  import { PLAN_MODE_REFUSAL } from '../../types/permission/index.js'
@@ -266,7 +271,17 @@ export type ToolReviewAnswer =
266
271
  | { readonly kind: 'approve' }
267
272
  /** Approve, and stop asking for the rest of the turn. */
268
273
  | { readonly kind: 'approve-all' }
269
- | { readonly kind: 'reject'; readonly feedback?: string }
274
+ | {
275
+ readonly kind: 'reject'
276
+ readonly feedback?: string
277
+ /**
278
+ * Set by a host when a person said No, so the refusal is recorded as
279
+ * theirs. `feedback` is what the model is told and a host may fill it
280
+ * for its own reasons (a closed screen, an interrupted turn), so it
281
+ * cannot carry this. `note` is the person's own words.
282
+ */
283
+ readonly declined?: ToolCallDeclined
284
+ }
270
285
 
271
286
  /** How a host asks a person. The one thing the kernel cannot supply. */
272
287
  export type ToolReviewPrompt = (request: ToolReviewRequest) => Promise<ToolReviewAnswer>
@@ -400,6 +415,7 @@ export function createReviewHandler(options: ReviewPolicyOptions = {}): ResumeHa
400
415
  return {
401
416
  action: 'reject_tools',
402
417
  feedback: answer.feedback ?? SCREEN_CONSENT_DECLINED_FEEDBACK,
418
+ ...(answer.declined ? { declined: answer.declined } : {}),
403
419
  }
404
420
  }
405
421
  consent.sessions.add(sessionKey)
@@ -471,6 +487,7 @@ export function createReviewHandler(options: ReviewPolicyOptions = {}): ResumeHa
471
487
  return {
472
488
  action: 'reject_tools',
473
489
  feedback: answer.feedback ?? DECLINED_TOOL_CALL_FEEDBACK,
490
+ ...(answer.declined ? { declined: answer.declined } : {}),
474
491
  }
475
492
  }
476
493
  // "Approve all" still latches for the calls that follow; it never
@@ -489,6 +506,7 @@ export function createReviewHandler(options: ReviewPolicyOptions = {}): ResumeHa
489
506
  return {
490
507
  action: 'reject_tools',
491
508
  feedback: answer.feedback ?? DECLINED_TOOL_CALL_FEEDBACK,
509
+ ...(answer.declined ? { declined: answer.declined } : {}),
492
510
  }
493
511
  }
494
512
  // Latches for the ordinary calls that follow, never for the next path.
@@ -508,6 +526,7 @@ export function createReviewHandler(options: ReviewPolicyOptions = {}): ResumeHa
508
526
  return {
509
527
  action: 'reject_tools',
510
528
  feedback: answer.feedback ?? DECLINED_TOOL_CALL_FEEDBACK,
529
+ ...(answer.declined ? { declined: answer.declined } : {}),
511
530
  }
512
531
  }
513
532
  if (answer.kind === 'approve-all') remembered.all = true
@@ -527,6 +546,7 @@ export function createReviewHandler(options: ReviewPolicyOptions = {}): ResumeHa
527
546
  return {
528
547
  action: 'reject_tools',
529
548
  feedback: answer.feedback ?? DECLINED_TOOL_CALL_FEEDBACK,
549
+ ...(answer.declined ? { declined: answer.declined } : {}),
530
550
  }
531
551
  }
532
552
  if (answer.kind === 'approve-all') remembered.all = true
@@ -573,6 +593,7 @@ export function createReviewHandler(options: ReviewPolicyOptions = {}): ResumeHa
573
593
  return {
574
594
  action: 'reject_tools',
575
595
  feedback: answer.feedback ?? DECLINED_TOOL_CALL_FEEDBACK,
596
+ ...(answer.declined ? { declined: answer.declined } : {}),
576
597
  }
577
598
  }
578
599
  }
@@ -0,0 +1,70 @@
1
+ import { genericPrimary } from '../../registry/tool/presentation.js'
2
+ import type { ToolCallView, ToolResultView } from '../../types/tool/presentation.js'
3
+
4
+ /** One line is all a saved row needs; the output is not kept. */
5
+ export const SAVED_LABEL_MAX = 200
6
+
7
+ function firstLine(text: string | undefined): string | undefined {
8
+ const line = text
9
+ ?.split(/\r?\n/)
10
+ .find((candidate) => candidate.trim())
11
+ ?.trim()
12
+ if (!line) return undefined
13
+ // By code point so a surrogate pair is never split.
14
+ const points = Array.from(line)
15
+ return points.length > SAVED_LABEL_MAX
16
+ ? `${points.slice(0, SAVED_LABEL_MAX - 1).join('')}…`
17
+ : line
18
+ }
19
+
20
+ /**
21
+ * What the journal keeps of a successful call that has no diff: the label the
22
+ * live row already showed, never the output. A host that replays history then
23
+ * names the action instead of calling it a saved one.
24
+ *
25
+ * `undefined` means there is nothing worth saving (no label, no command), so
26
+ * the host falls back to the tool's name.
27
+ */
28
+ export function savedPresentation(
29
+ input: unknown,
30
+ callView: ToolCallView | undefined,
31
+ resultView: ToolResultView | undefined,
32
+ ): ToolResultView | undefined {
33
+ if (resultView?.kind === 'diff') return undefined
34
+ const callLabel = callView?.kind === 'generic' ? firstLine(callView.label) : undefined
35
+ const commandInput =
36
+ input &&
37
+ typeof input === 'object' &&
38
+ typeof (input as { command?: unknown }).command === 'string'
39
+ ? (input as { command: string }).command
40
+ : undefined
41
+ // A tool with no view of its own is drawn as a terminal, so a command input is a command.
42
+ const command =
43
+ resultView?.kind === 'terminal' || callView?.kind === 'terminal'
44
+ ? ((resultView?.kind === 'terminal' ? resultView.command : undefined) ??
45
+ (callView?.kind === 'terminal' ? callView.command : undefined) ??
46
+ commandInput ??
47
+ callLabel ??
48
+ '')
49
+ : !resultView && !callView && commandInput !== undefined
50
+ ? commandInput
51
+ : undefined
52
+ if (command !== undefined) {
53
+ const line = firstLine(command)
54
+ return line ? { kind: 'terminal', command: line, output: '' } : undefined
55
+ }
56
+ const label =
57
+ callLabel ??
58
+ (resultView?.kind === 'generic' ? firstLine(resultView.label) : undefined) ??
59
+ (callView || resultView ? undefined : firstLine(genericPrimary(input)))
60
+ if (!label) return undefined
61
+ const own = callView?.kind === 'generic' ? callView : undefined
62
+ const hidden = resultView?.kind === 'generic' && resultView.visibility === 'hidden'
63
+ return {
64
+ kind: 'generic',
65
+ label,
66
+ ...(own?.presentation === 'activity' ? { presentation: 'activity' as const } : {}),
67
+ ...(own?.activity === 'exploration' ? { activity: 'exploration' as const } : {}),
68
+ ...(hidden ? { visibility: 'hidden' as const } : {}),
69
+ }
70
+ }
@@ -14,14 +14,11 @@ export function isOperatorUserMessage(message: Message): message is UserMessage
14
14
  /**
15
15
  * Guidance a host hands to a turn that is already running.
16
16
  *
17
- * The gap this closes is narrow and was documented rather than fixed:
18
- * `AgentManager` has had `queueMessage` / `drainMessages` for a while, and
19
- * nothing in the iteration loop ever read them — the type says so in as many
20
- * words. So a host watching a turn go the wrong way had two options, and both
21
- * are worse than they sound. Cancel and start over throws away every tool
22
- * result the turn had already paid for. Reject through the review gate only
23
- * works if a tool call happens to be pending approval, and it says "no" when
24
- * the host wanted to say "yes, but look at this first".
17
+ * This tool-result channel is distinct from `inboundMessages`. The manager
18
+ * injects its mailbox through that callback, and query-backed agents consume
19
+ * it at provider-valid message boundaries. Custom agents must consume their
20
+ * injected callback themselves. This channel instead lets a host attach
21
+ * guidance to a completed tool batch without adding another user message.
25
22
  *
26
23
  * **Why the text rides on a tool result rather than arriving as a user
27
24
  * message.** A `tool_use` block must be answered by a `tool_result` with the
@@ -34,7 +31,7 @@ export function isOperatorUserMessage(message: Message): message is UserMessage
34
31
  * attends to for tool outcomes. Steering is the same delivery with the
35
32
  * refusal removed.
36
33
  *
37
- * **What it deliberately is not.** It does not interrupt. The batch in flight
34
+ * It does not interrupt. The batch in flight
38
35
  * finishes, and the guidance lands where the model looks next. A host that
39
36
  * wants the current work stopped wants `AbortSignal`, which is a different
40
37
  * question with a different answer — and conflating the two is how "please
@@ -1,20 +1,30 @@
1
1
  import type { SessionLog } from '../../store/session-log/index.js'
2
+ import type { SpillRef } from '../../store/session-log/spill.js'
3
+ import { readStructuredResultSpill } from '../../store/session-log/structured-result.js'
4
+ import { STRUCTURED_OUTPUT_TOOL_NAME } from '../../tools/builtins/structuredOutput.js'
2
5
  import type { TurnId } from '../../types/ids/index.js'
3
- import type { SessionRecord } from '../../types/session/records.js'
6
+ import { type SessionRecord, SessionRecordSchema } from '../../types/session/records.js'
4
7
  import type {
8
+ CompletedToolRecord,
5
9
  ToolExecutionRecord,
6
10
  ToolExecutionSnapshot,
7
11
  } from '../../types/session/tool-execution.js'
12
+ import { parseStructuredResultJson } from '../../utils/structured-result-json.js'
13
+
14
+ /** Full JSON retained across one recovery snapshot, after superseded calls are removed. */
15
+ const STRUCTURED_RECOVERY_MAX_BYTES = 64 * 1024 * 1024
8
16
 
9
17
  /**
10
18
  * Collects the latest execution boundary of selected tool calls from one
11
- * turn's records: metadata only, never retained output bodies beyond the
12
- * completion's own result.
19
+ * turn's records, including bounded receipts and optional runtime-owned JSON
20
+ * candidates. Structured spill bodies are hydrated separately, after the
21
+ * whole log has verified; ordinary output spills remain bounded receipts.
13
22
  */
14
23
  export class ToolExecutionCollector {
15
24
  private started = false
16
25
  private readonly wanted: Set<string>
17
26
  private readonly records = new Map<string, ToolExecutionRecord>()
27
+ private readonly structuredSpills = new Map<string, SpillRef>()
18
28
 
19
29
  constructor(
20
30
  private readonly turnId: TurnId,
@@ -36,21 +46,101 @@ export class ToolExecutionCollector {
36
46
  if (record.type === 'tool_executing') {
37
47
  // A later start invalidates an earlier completion, including retries.
38
48
  this.records.set(event.toolUseId, { ...identity, status: 'started' })
49
+ this.structuredSpills.delete(event.toolUseId)
39
50
  return
40
51
  }
41
52
  if (typeof event.result !== 'string' || typeof event.isError !== 'boolean')
42
53
  throw new Error('Tool recovery found an invalid completion.')
54
+ const inputFailure = event.inputFailure
55
+ if (
56
+ inputFailure !== undefined &&
57
+ (typeof inputFailure !== 'string' ||
58
+ !['invalid_json', 'schema_validation', 'input_truncated'].includes(inputFailure) ||
59
+ event.isError !== true)
60
+ )
61
+ throw new Error('Tool recovery found an invalid input failure classification.')
62
+ const skipped = event.skipped
63
+ if (
64
+ skipped !== undefined &&
65
+ (skipped !== true || event.isError !== false || inputFailure !== undefined)
66
+ )
67
+ throw new Error('Tool recovery found an invalid skipped completion classification.')
68
+ const structuredResultJson = event.structuredResultJson
69
+ const structuredResultSpill = event.structuredResultSpill
70
+ if (structuredResultJson !== undefined || structuredResultSpill !== undefined) {
71
+ if (
72
+ event.toolName !== STRUCTURED_OUTPUT_TOOL_NAME ||
73
+ event.isError !== false ||
74
+ skipped !== undefined ||
75
+ inputFailure !== undefined ||
76
+ event.via !== undefined
77
+ )
78
+ throw new Error(
79
+ 'Tool recovery found an invalid durable structured completion classification.',
80
+ )
81
+ if (structuredResultSpill !== undefined) {
82
+ // Also refuse malformed references and contradictory inline evidence
83
+ // when the collector is driven outside the strict log reader.
84
+ SessionRecordSchema.parse(record)
85
+ } else {
86
+ parseStructuredResultJson(structuredResultJson)
87
+ }
88
+ }
89
+ this.structuredSpills.delete(event.toolUseId)
90
+ if (structuredResultSpill !== undefined)
91
+ this.structuredSpills.set(event.toolUseId, structuredResultSpill as SpillRef)
43
92
  this.records.set(event.toolUseId, {
44
93
  ...identity,
45
94
  status: 'completed',
46
95
  result: event.result,
47
96
  isError: event.isError,
97
+ ...(inputFailure !== undefined
98
+ ? { inputFailure: inputFailure as CompletedToolRecord['inputFailure'] }
99
+ : {}),
100
+ ...(skipped ? { skipped: true as const } : {}),
101
+ ...(structuredResultJson !== undefined
102
+ ? { structuredResultJson: structuredResultJson as string }
103
+ : {}),
48
104
  })
49
105
  }
50
106
 
51
107
  /** Complete only when the turn's beginning was seen and the whole log verified. */
52
108
  finish(complete = true): ToolExecutionSnapshot {
53
- return { complete: complete && this.started, records: this.records }
109
+ // A synchronous fold cannot establish spilled structured evidence.
110
+ // Its snapshot is incomplete until checked hydration finishes.
111
+ return {
112
+ complete: complete && this.started && this.structuredSpills.size === 0,
113
+ records: this.records,
114
+ }
115
+ }
116
+
117
+ /** Hydrate only the latest selected completion; overwritten retry bodies are irrelevant. */
118
+ async finishWithSpills(
119
+ log: SessionLog,
120
+ complete = true,
121
+ signal?: AbortSignal,
122
+ ): Promise<ToolExecutionSnapshot> {
123
+ signal?.throwIfAborted()
124
+ if (!complete || !this.started) return this.finish(false)
125
+ let totalBytes = 0
126
+ for (const ref of this.structuredSpills.values()) {
127
+ totalBytes += ref.bytes
128
+ if (totalBytes > STRUCTURED_RECOVERY_MAX_BYTES) {
129
+ throw new Error(
130
+ `Structured recovery exceeds the ${STRUCTURED_RECOVERY_MAX_BYTES}-byte aggregate limit.`,
131
+ )
132
+ }
133
+ }
134
+ const records = new Map(this.records)
135
+ for (const [id, ref] of this.structuredSpills) {
136
+ const record = records.get(id)
137
+ if (!record || record.status !== 'completed')
138
+ throw new Error('Structured spill lacks a completed call.')
139
+ const { json: structuredResultJson } = await readStructuredResultSpill(log, ref, signal)
140
+ records.set(id, { ...record, structuredResultJson })
141
+ }
142
+ signal?.throwIfAborted()
143
+ return { complete: true, records }
54
144
  }
55
145
  }
56
146
 
@@ -68,10 +158,19 @@ export async function readToolExecutions(
68
158
  signal?.throwIfAborted()
69
159
  const collector = new ToolExecutionCollector(turnId, ids)
70
160
  const walk = log.read({ mode: 'strict' })
71
- for (;;) {
72
- signal?.throwIfAborted()
73
- const step = await walk.next()
74
- if (step.done) return collector.finish(step.value.intact && step.value.tornBytes === 0)
75
- collector.accept(step.value.record)
161
+ try {
162
+ for (;;) {
163
+ signal?.throwIfAborted()
164
+ const step = await walk.next()
165
+ if (step.done)
166
+ return collector.finishWithSpills(
167
+ log,
168
+ step.value.intact && step.value.tornBytes === 0,
169
+ signal,
170
+ )
171
+ collector.accept(step.value.record)
172
+ }
173
+ } finally {
174
+ await walk.return({ intact: false, throughSeq: 0, head: null, tornBytes: 0 })
76
175
  }
77
176
  }
@@ -8,7 +8,7 @@ import type { InvocationState } from '../../types/invocation/index.js'
8
8
  import type { PermissionMode } from '../../types/permission/index.js'
9
9
  import type { AuditEventInput } from '../../types/session/audit.js'
10
10
  import type { SessionRecord } from '../../types/session/records.js'
11
- import type { RequestToolPause, SkillRegistryRef } from '../../types/tool/index.js'
11
+ import type { RequestToolPause, SkillRegistryRef, ToolDefinition } from '../../types/tool/index.js'
12
12
  import type { RepairToolCall } from '../../types/tool/repair.js'
13
13
  import type { BackoffPolicy } from '../../utils/backoff.js'
14
14
  import type { Logger } from '../../utils/logger.js'
@@ -20,6 +20,8 @@ import type { EmitEvent } from './events.js'
20
20
  export interface ToolingBootstrapConfig {
21
21
  fileReadTracker?: import('../../types/tool/index.js').FileReadTracker
22
22
  tools: ToolManager
23
+ /** Exact runtime output-tool owner for opt-in JSON retention; see ToolExecutorConfig. */
24
+ durableStructuredOutputTool?: ToolDefinition
23
25
  sessionId: SessionId
24
26
  turnId: TurnId
25
27
  workingDirectory: string
@@ -79,6 +81,9 @@ export class ToolingBootstrap {
79
81
  return new ToolExecutor(
80
82
  {
81
83
  tools: config.tools,
84
+ ...(config.durableStructuredOutputTool
85
+ ? { durableStructuredOutputTool: config.durableStructuredOutputTool }
86
+ : {}),
82
87
  ...(config.fileReadTracker ? { fileReadTracker: config.fileReadTracker } : {}),
83
88
  sessionId: config.sessionId,
84
89
  turnId: config.turnId,