@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
@@ -135,6 +135,38 @@ const inputSchema = z
135
135
 
136
136
  export type EditInput = z.infer<typeof inputSchema>
137
137
 
138
+ /**
139
+ * What an `edit` call WOULD produce for a file body, without touching any file.
140
+ *
141
+ * The same schema, the same normalisation and the same `applyEdit` fold that
142
+ * `execute` runs, so a host that shows a proposed change before approval is
143
+ * showing what the tool will do, not a second reading of the arguments. Pure:
144
+ * the caller supplies the current body (and decides what to do when there is no
145
+ * file). The no-op refusal is repeated because a call `execute` would refuse
146
+ * has no change to preview.
147
+ */
148
+ export function dryRunEdit(
149
+ content: string,
150
+ input: unknown,
151
+ ): { success: true; content: string } | { success: false; error: string } {
152
+ const parsed = inputSchema.safeParse(input)
153
+ if (!parsed.success) {
154
+ return { success: false, error: parsed.error.issues.map((issue) => issue.message).join('; ') }
155
+ }
156
+ const normalized = normalizeEditInput(parsed.data)
157
+ if (!normalized.success) return normalized
158
+ if (
159
+ normalized.operations.some(
160
+ (operation) =>
161
+ operation.operation === 'replace' && operation.oldString === operation.newString,
162
+ )
163
+ ) {
164
+ return { success: false, error: 'old_string and new_string are identical — no change needed' }
165
+ }
166
+ const result = applyEdit(content, normalized.operations)
167
+ return result.success ? { success: true, content: result.content } : result
168
+ }
169
+
138
170
  /**
139
171
  * What a capable provider constrains the model to emit: one shape, closed.
140
172
  *
@@ -412,6 +444,11 @@ export const EditTool = defineTool({
412
444
  success: true as const,
413
445
  output: `Edited ${parsed.data.path}: ${result.replacements} replacement(s) [sandboxed]`,
414
446
  data: { path: parsed.data.path, replacements: result.replacements, sandboxed: true },
447
+ facts: {
448
+ kind: 'edit' as const,
449
+ path: parsed.data.path,
450
+ replacements: result.replacements,
451
+ },
415
452
  }
416
453
  }
417
454
 
@@ -438,6 +475,11 @@ export const EditTool = defineTool({
438
475
  success: true as const,
439
476
  output: `Edited ${hostPath}: ${result.replacements} replacement(s)`,
440
477
  data: { path: hostPath, replacements: result.replacements },
478
+ facts: {
479
+ kind: 'edit' as const,
480
+ path: hostPath,
481
+ replacements: result.replacements,
482
+ },
441
483
  }
442
484
  })
443
485
  },
@@ -59,6 +59,20 @@ export function fileWriteResult(
59
59
  return {
60
60
  success: true,
61
61
  output: `${summary} · ${bytes} bytes`,
62
+ facts: {
63
+ kind: 'write',
64
+ path,
65
+ operation:
66
+ operation === 'create'
67
+ ? 'created'
68
+ : operation === 'replace'
69
+ ? 'updated'
70
+ : operation === 'unchanged'
71
+ ? 'unchanged'
72
+ : 'wrote',
73
+ bytes,
74
+ ...(before === null ? {} : { added: added.length, removed: removed.length }),
75
+ },
62
76
  data: {
63
77
  path,
64
78
  size: after.length,
@@ -77,6 +77,11 @@ export const GlobTool = defineTool({
77
77
  label: `Find ${input.pattern} in ${input.path ?? '.'}`,
78
78
  presentation: 'activity',
79
79
  activity: 'exploration',
80
+ facts: {
81
+ kind: 'list',
82
+ pattern: input.pattern,
83
+ ...(input.path !== undefined ? { path: input.path } : {}),
84
+ },
80
85
  }
81
86
  },
82
87
 
@@ -142,6 +147,13 @@ export const GlobTool = defineTool({
142
147
  [...files.map(displayPath), ...(notice ? [notice] : [])].join('\n') ||
143
148
  `No files found matching pattern "${input.pattern}" in ${root}`,
144
149
  data: { count: files.length, files, truncated, ...(sandbox ? { sandboxed: true } : {}) },
150
+ facts: {
151
+ kind: 'list',
152
+ pattern: input.pattern,
153
+ ...(input.path !== undefined ? { path: input.path } : {}),
154
+ count: files.length,
155
+ truncated,
156
+ },
145
157
  ...(failure ? { error: failure } : {}),
146
158
  }
147
159
  },
@@ -109,6 +109,11 @@ export const GrepTool = defineTool({
109
109
  label: `Search ${input.pattern} in ${input.path ?? '.'}`,
110
110
  presentation: 'activity',
111
111
  activity: 'exploration',
112
+ facts: {
113
+ kind: 'search',
114
+ pattern: input.pattern,
115
+ ...(input.path !== undefined ? { path: input.path } : {}),
116
+ },
112
117
  }
113
118
  },
114
119
  timeoutMs: 15_000,
@@ -265,6 +270,15 @@ export const GrepTool = defineTool({
265
270
  success: failure === undefined,
266
271
  output: [results.join('\n'), summary, notice].filter(Boolean).join('\n\n'),
267
272
  data: { totalMatches, filesSearched, filesMatched, truncated },
273
+ facts: {
274
+ kind: 'search',
275
+ pattern: input.pattern,
276
+ ...(input.path !== undefined ? { path: input.path } : {}),
277
+ matches: totalMatches,
278
+ filesMatched,
279
+ filesSearched,
280
+ truncated,
281
+ },
268
282
  ...(failure ? { error: failure } : {}),
269
283
  }
270
284
  },
@@ -25,6 +25,8 @@ export { RUN_CODE_TOOL_NAME, buildRunCodeTool } from './run-code.js'
25
25
  export { LsTool } from './ls.js'
26
26
  export { SearchToolsTool } from './search-tools.js'
27
27
  export { VerifyOutputsTool } from './verify-outputs.js'
28
+ export { ViewImageTool, createViewImageTool } from './view-image.js'
29
+ export type { ViewImageToolOptions } from './view-image.js'
28
30
  export { createStructuredOutputTool, STRUCTURED_OUTPUT_TOOL_NAME } from './structuredOutput.js'
29
31
  export { createComputerUseTool, COMPUTER_USE_TOOL_NAME } from './computer-use.js'
30
32
 
@@ -113,7 +113,9 @@ export const JobTool = defineTool({
113
113
  const status =
114
114
  read.status === 'running'
115
115
  ? 'still running'
116
- : `${read.status}${read.exitCode === undefined ? '' : ` with code ${read.exitCode}`}`
116
+ : read.error !== undefined
117
+ ? `failed to start: ${read.error}`
118
+ : `${read.status}${read.exitCode === undefined ? '' : ` with code ${read.exitCode}`}`
117
119
 
118
120
  return {
119
121
  success: true,
@@ -124,6 +126,7 @@ export const JobTool = defineTool({
124
126
  nextOffset: read.nextOffset,
125
127
  droppedBytes: read.droppedBytes,
126
128
  ...(read.exitCode === undefined ? {} : { exitCode: read.exitCode }),
129
+ ...(read.error === undefined ? {} : { error: read.error }),
127
130
  },
128
131
  }
129
132
  } catch (err) {
@@ -2,8 +2,10 @@ import { readFile } from 'node:fs/promises'
2
2
  import { extname } from 'node:path'
3
3
  import { z } from 'zod'
4
4
  import type { ToolContext } from '../../types/tool/index.js'
5
+ import type { ToolFacts } from '../../types/tool/presentation.js'
5
6
  import { defineTool } from '../defineTool.js'
6
7
  import { resolveWithinAnyReal, toolRoots } from '../paths.js'
8
+ import { looksBinary } from '../text-window.js'
7
9
  import { fingerprintContent } from './content-fingerprint.js'
8
10
  import { type RenderedRead, renderNumberedRead } from './read-render.js'
9
11
 
@@ -55,6 +57,7 @@ export const ReadFileTool = defineTool({
55
57
  label: `Read ${input.path}`,
56
58
  presentation: 'activity',
57
59
  activity: 'exploration',
60
+ facts: { kind: 'read', path: input.path },
58
61
  }
59
62
  },
60
63
 
@@ -72,6 +75,12 @@ export const ReadFileTool = defineTool({
72
75
  sandboxed: true,
73
76
  binary: true,
74
77
  },
78
+ facts: {
79
+ kind: 'read',
80
+ path: input.path,
81
+ binary: true,
82
+ bytes: buffer.length,
83
+ },
75
84
  }
76
85
  }
77
86
  const content = buffer.toString('utf-8')
@@ -88,6 +97,7 @@ export const ReadFileTool = defineTool({
88
97
  path: input.path,
89
98
  sandboxed: true,
90
99
  },
100
+ facts: readFacts(input.path, buffer, content, rendered),
91
101
  }
92
102
  }
93
103
 
@@ -102,6 +112,12 @@ export const ReadFileTool = defineTool({
102
112
  path: filePath,
103
113
  binary: true,
104
114
  },
115
+ facts: {
116
+ kind: 'read',
117
+ path: filePath,
118
+ binary: true,
119
+ bytes: buffer.length,
120
+ },
105
121
  }
106
122
  }
107
123
  const content = buffer.toString('utf-8')
@@ -117,10 +133,37 @@ export const ReadFileTool = defineTool({
117
133
  truncated: rendered.partial,
118
134
  path: filePath,
119
135
  },
136
+ facts: readFacts(filePath, buffer, content, rendered),
120
137
  }
121
138
  },
122
139
  })
123
140
 
141
+ /**
142
+ * What a read returned, as fields. A file that is not text is named as such,
143
+ * so a host says "Binary file, 4 KB" instead of drawing the bytes the model's
144
+ * numbered rendering contains.
145
+ */
146
+ function readFacts(
147
+ path: string,
148
+ buffer: Buffer,
149
+ content: string,
150
+ rendered: RenderedRead,
151
+ ): ToolFacts {
152
+ return {
153
+ kind: 'read',
154
+ path,
155
+ bytes: buffer.length,
156
+ ...(looksBinary(content) ? { binary: true } : {}),
157
+ // A final newline ends a line; it does not start another.
158
+ totalLines: content.endsWith('\n') ? rendered.totalLines - 1 : rendered.totalLines,
159
+ returnedLines:
160
+ content.endsWith('\n') && !rendered.partial
161
+ ? rendered.returnedLines - 1
162
+ : rendered.returnedLines,
163
+ ...(rendered.partial ? { partial: true } : {}),
164
+ }
165
+ }
166
+
124
167
  /**
125
168
  * Put this read on the observation ledger.
126
169
  *
@@ -153,6 +196,20 @@ function recordObservedRead(
153
196
 
154
197
  function describeStructuredBinaryRead(path: string, buffer: Buffer): string | null {
155
198
  const ext = extname(path).toLowerCase()
199
+ const image = buffer.subarray(0, 8).equals(Buffer.from('89504e470d0a1a0a', 'hex'))
200
+ ? 'PNG'
201
+ : buffer[0] === 0xff && buffer[1] === 0xd8
202
+ ? 'JPEG'
203
+ : buffer.toString('ascii', 0, 4) === 'RIFF' && buffer.toString('ascii', 8, 12) === 'WEBP'
204
+ ? 'WebP'
205
+ : null
206
+ if (image) {
207
+ return [
208
+ `The file "${path}" is a ${image} raster image, not UTF-8 text.`,
209
+ 'Use an available view_image tool with this path to inspect the actual pixels. Reading binary bytes as text does not provide visual evidence.',
210
+ 'If image inspection is unavailable, open the file in an application and use an available screenshot tool; report the limitation if neither can show the image.',
211
+ ].join('\n')
212
+ }
156
213
  if (ext === '.docx') return buildStructuredBinaryGuidance(path, 'DOCX', 'python-docx')
157
214
  if (ext === '.pptx') return buildStructuredBinaryGuidance(path, 'PPTX', 'python-pptx')
158
215
  if (ext === '.xlsx') return buildStructuredBinaryGuidance(path, 'XLSX', 'openpyxl')
@@ -0,0 +1,409 @@
1
+ import { createHash } from 'node:crypto'
2
+ import { open } from 'node:fs/promises'
3
+ import { inflateSync } from 'node:zlib'
4
+ import { z } from 'zod'
5
+ import { admitMcpImageBatch } from '../../connector/mcp/image-admission.js'
6
+ import type { ToolContext, ToolDefinition } from '../../types/tool/index.js'
7
+ import { defineTool } from '../defineTool.js'
8
+ import { resolveWithinAnyReal, toolRoots } from '../paths.js'
9
+ import { STANDARD_SCREENSHOT_LIMITS, fitPng, screenshotTargetSize } from './computer-use-image.js'
10
+
11
+ // 16 MiB becomes less than the runtime's 24 MiB encoded rich-content budget.
12
+ // Admission is per artifact; the runtime still budgets accumulated images.
13
+ const MAX_BYTES = 16 * 1024 * 1024
14
+ const READ_CHUNK_BYTES = 1024 * 1024
15
+ const MAX_EDGE = 16_384
16
+ const MAX_PIXELS = 16_000_000
17
+ const PNG_SIGNATURE = Buffer.from('89504e470d0a1a0a', 'hex')
18
+ const JPEG_FRAME_MARKERS = new Set([
19
+ 0xc0, 0xc1, 0xc2, 0xc3, 0xc5, 0xc6, 0xc7, 0xc9, 0xca, 0xcb, 0xcd, 0xce, 0xcf,
20
+ ])
21
+
22
+ const inputSchema = z.object({
23
+ path: z.string().min(1).describe("Path to a saved PNG, JPEG or WebP image in this turn's files"),
24
+ })
25
+
26
+ /** Host admission for a model which cannot receive image tool results. */
27
+ export interface ViewImageToolOptions {
28
+ readonly unavailableReason?: string
29
+ }
30
+
31
+ interface Raster {
32
+ readonly mediaType: 'image/png' | 'image/jpeg' | 'image/webp'
33
+ readonly width: number
34
+ readonly height: number
35
+ }
36
+
37
+ async function readBounded(
38
+ read: (offset: number, length: number) => Promise<Buffer>,
39
+ signal: AbortSignal,
40
+ ): Promise<Buffer> {
41
+ const chunks: Buffer[] = []
42
+ let offset = 0
43
+ for (;;) {
44
+ signal.throwIfAborted()
45
+ const length = Math.min(READ_CHUNK_BYTES, MAX_BYTES + 1 - offset)
46
+ const chunk = await read(offset, length)
47
+ signal.throwIfAborted()
48
+ if (chunk.length > length)
49
+ throw new Error('The file backend returned more bytes than the requested bounded range.')
50
+ offset += chunk.length
51
+ if (offset > MAX_BYTES)
52
+ throw new Error('Image exceeds the 16 MiB inspection limit. Export a smaller image.')
53
+ chunks.push(chunk)
54
+ if (chunk.length < length) return Buffer.concat(chunks, offset)
55
+ }
56
+ }
57
+
58
+ async function readArtifact(
59
+ path: string,
60
+ context: ToolContext,
61
+ ): Promise<{ path: string; bytes: Buffer; sandboxed: boolean }> {
62
+ context.abortSignal.throwIfAborted()
63
+ if (context.sandbox) {
64
+ const bytes = await context.sandbox.readFile(path, {
65
+ offset: 0,
66
+ length: MAX_BYTES + 1,
67
+ signal: context.abortSignal,
68
+ })
69
+ context.abortSignal.throwIfAborted()
70
+ if (bytes.length > MAX_BYTES)
71
+ throw new Error('Image exceeds the 16 MiB inspection limit. Export a smaller image.')
72
+ return { path, bytes, sandboxed: true }
73
+ }
74
+ const resolved = await resolveWithinAnyReal(toolRoots(context), path)
75
+ const file = await open(resolved, 'r')
76
+ try {
77
+ const stat = await file.stat()
78
+ if (!stat.isFile()) throw new Error('Image inspection requires a regular file.')
79
+ if (stat.size > MAX_BYTES)
80
+ throw new Error('Image exceeds the 16 MiB inspection limit. Export a smaller image.')
81
+ const bytes = await readBounded(async (offset, length) => {
82
+ const buffer = Buffer.allocUnsafe(length)
83
+ const { bytesRead } = await file.read(buffer, 0, length, offset)
84
+ return buffer.subarray(0, bytesRead)
85
+ }, context.abortSignal)
86
+ return { path: resolved, bytes, sandboxed: false }
87
+ } finally {
88
+ await file.close()
89
+ }
90
+ }
91
+
92
+ function malformed(): never {
93
+ throw new Error('Image is malformed or truncated. Export a complete static PNG, JPEG or WebP.')
94
+ }
95
+
96
+ function jpegDimensions(bytes: Buffer): Pick<Raster, 'width' | 'height'> {
97
+ let offset = 2
98
+ let inScan = false
99
+ let frame: Pick<Raster, 'width' | 'height'> | undefined
100
+ while (offset < bytes.length) {
101
+ if (inScan && bytes[offset] !== 0xff) {
102
+ offset += 1
103
+ continue
104
+ }
105
+ if (bytes[offset] !== 0xff) malformed()
106
+ while (bytes[offset] === 0xff) offset += 1
107
+ const marker = bytes[offset]
108
+ if (marker === undefined) malformed()
109
+ offset += 1
110
+ if (inScan && (marker === 0 || (marker >= 0xd0 && marker <= 0xd7))) continue
111
+ inScan = false
112
+ if (marker === 0xd9) break
113
+ if (marker === 0xd8 || marker === 0x01 || (marker >= 0xd0 && marker <= 0xd7)) continue
114
+ if (offset + 2 > bytes.length) malformed()
115
+ const length = bytes.readUInt16BE(offset)
116
+ if (length < 2 || offset + length > bytes.length) malformed()
117
+ if (JPEG_FRAME_MARKERS.has(marker)) {
118
+ if (length < 8 || frame) malformed()
119
+ frame = {
120
+ width: bytes.readUInt16BE(offset + 5),
121
+ height: bytes.readUInt16BE(offset + 3),
122
+ }
123
+ }
124
+ offset += length
125
+ if (marker === 0xda) inScan = true
126
+ }
127
+ return frame ?? malformed()
128
+ }
129
+
130
+ function webpDimensions(bytes: Buffer): Pick<Raster, 'width' | 'height'> {
131
+ let offset = 12
132
+ let dimensions: Pick<Raster, 'width' | 'height'> | undefined
133
+ while (offset + 8 <= bytes.length) {
134
+ const type = bytes.toString('ascii', offset, offset + 4)
135
+ const length = bytes.readUInt32LE(offset + 4)
136
+ const start = offset + 8
137
+ if (start + length > bytes.length) malformed()
138
+ let current: Pick<Raster, 'width' | 'height'> | undefined
139
+ if (type === 'ANIM' || type === 'ANMF')
140
+ throw new Error('Animated WebP is unsupported. Export the required frame as a static PNG.')
141
+ if (type === 'VP8X' && length >= 10) {
142
+ current = {
143
+ width: bytes.readUIntLE(start + 4, 3) + 1,
144
+ height: bytes.readUIntLE(start + 7, 3) + 1,
145
+ }
146
+ } else if (type === 'VP8L' && length >= 5 && bytes[start] === 0x2f) {
147
+ const packed = bytes.readUInt32LE(start + 1)
148
+ current = {
149
+ width: (packed & 0x3fff) + 1,
150
+ height: ((packed >>> 14) & 0x3fff) + 1,
151
+ }
152
+ } else if (type === 'VP8 ' && length >= 10) {
153
+ current = {
154
+ width: bytes.readUInt16LE(start + 6) & 0x3fff,
155
+ height: bytes.readUInt16LE(start + 8) & 0x3fff,
156
+ }
157
+ }
158
+ if (current) {
159
+ if (
160
+ dimensions &&
161
+ (dimensions.width !== current.width || dimensions.height !== current.height)
162
+ )
163
+ malformed()
164
+ dimensions = current
165
+ }
166
+ offset = start + length + (length & 1)
167
+ }
168
+ return dimensions ?? malformed()
169
+ }
170
+
171
+ function describeRaster(bytes: Buffer): Raster {
172
+ let raster: Raster
173
+ if (bytes.subarray(0, 8).equals(PNG_SIGNATURE)) {
174
+ if (bytes.length < 33) malformed()
175
+ raster = {
176
+ mediaType: 'image/png',
177
+ width: bytes.readUInt32BE(16),
178
+ height: bytes.readUInt32BE(20),
179
+ }
180
+ } else if (bytes[0] === 0xff && bytes[1] === 0xd8) {
181
+ raster = { mediaType: 'image/jpeg', ...jpegDimensions(bytes) }
182
+ } else if (
183
+ bytes.toString('ascii', 0, 4) === 'RIFF' &&
184
+ bytes.toString('ascii', 8, 12) === 'WEBP'
185
+ ) {
186
+ raster = { mediaType: 'image/webp', ...webpDimensions(bytes) }
187
+ } else {
188
+ throw new Error(
189
+ 'Unsupported image bytes. Export a static PNG, JPEG or WebP; renaming the file does not convert it.',
190
+ )
191
+ }
192
+ if (
193
+ raster.width < 1 ||
194
+ raster.height < 1 ||
195
+ raster.width > MAX_EDGE ||
196
+ raster.height > MAX_EDGE ||
197
+ raster.width * raster.height > MAX_PIXELS
198
+ )
199
+ throw new Error(
200
+ 'Image dimensions exceed the inspection limit (16,384 pixels per edge, 16 million pixels total). Export a smaller image.',
201
+ )
202
+ return raster
203
+ }
204
+
205
+ /** Validate bounded pixel data without inflating ancillary metadata. */
206
+ async function validatedPng(bytes: Buffer, raster: Raster): Promise<Buffer> {
207
+ const depth = bytes[24] ?? 0
208
+ const colour = bytes[25] ?? -1
209
+ const channels = ({ 0: 1, 2: 3, 3: 1, 4: 2, 6: 4 } as Record<number, number>)[colour]
210
+ const allowedDepths = colour === 0 ? [1, 2, 4, 8, 16] : colour === 3 ? [1, 2, 4, 8] : [8, 16]
211
+ if (
212
+ !channels ||
213
+ !allowedDepths.includes(depth) ||
214
+ bytes[26] !== 0 ||
215
+ bytes[27] !== 0 ||
216
+ (bytes[28] !== 0 && bytes[28] !== 1)
217
+ )
218
+ malformed()
219
+ // fast-png's Adam7 reader lays out sub-byte pixels as whole bytes. Do not
220
+ // return a success observation whose unpacked pixels differ from the file.
221
+ if (bytes[28] === 1 && depth < 8)
222
+ throw new Error(
223
+ 'Interlaced PNGs below 8 bits per sample are unsupported by this decoder. Export a non-interlaced or 8-bit PNG and inspect that file.',
224
+ )
225
+ const passes =
226
+ bytes[28] === 1
227
+ ? [
228
+ [0, 0, 8, 8],
229
+ [4, 0, 8, 8],
230
+ [0, 4, 4, 8],
231
+ [2, 0, 4, 4],
232
+ [0, 2, 2, 4],
233
+ [1, 0, 2, 2],
234
+ [0, 1, 1, 2],
235
+ ]
236
+ : [[0, 0, 1, 1]]
237
+ let expected = 0
238
+ for (const [x = 0, y = 0, dx = 1, dy = 1] of passes) {
239
+ const width = Math.max(0, Math.ceil((raster.width - x) / dx))
240
+ const height = Math.max(0, Math.ceil((raster.height - y) / dy))
241
+ if (width > 0 && height > 0)
242
+ expected += (Math.ceil((width * channels * depth) / 8) + 1) * height
243
+ }
244
+ const chunks: Buffer[] = [PNG_SIGNATURE]
245
+ const compressed: Buffer[] = []
246
+ let offset = 8
247
+ while (offset + 12 <= bytes.length) {
248
+ const length = bytes.readUInt32BE(offset)
249
+ const type = bytes.toString('ascii', offset + 4, offset + 8)
250
+ const end = offset + length + 12
251
+ if (end > bytes.length) malformed()
252
+ if (type === 'acTL' || type === 'fcTL' || type === 'fdAT')
253
+ throw new Error('Animated PNG is unsupported. Export the required frame as a static PNG.')
254
+ if (type === 'IDAT') compressed.push(bytes.subarray(offset + 8, end - 4))
255
+ if (['IHDR', 'PLTE', 'tRNS', 'IDAT', 'IEND'].includes(type))
256
+ chunks.push(bytes.subarray(offset, end))
257
+ else if (/^[A-Z]/.test(type)) throw new Error(`Unsupported critical PNG chunk: ${type}.`)
258
+ offset = end
259
+ }
260
+ // fast-png's inflater does not expose a byte ceiling. Check the complete
261
+ // compressed pixel stream with Node's ceiling before handing it the image.
262
+ try {
263
+ const inflated = inflateSync(Buffer.concat(compressed), {
264
+ maxOutputLength: expected,
265
+ })
266
+ if (inflated.length !== expected) malformed()
267
+ } catch {
268
+ malformed()
269
+ }
270
+ const canonical = Buffer.concat(chunks)
271
+ const { decode, encode, convertIndexedToRgb } = await import('fast-png')
272
+ try {
273
+ const decoded = decode(canonical, { checkCrc: true })
274
+ if (decoded.width !== raster.width || decoded.height !== raster.height) malformed()
275
+ // Decode indexed pixels too: a complete PLTE/IDAT container can still
276
+ // refer to a palette entry that does not exist.
277
+ if (decoded.palette) convertIndexedToRgb(decoded)
278
+ else if (decoded.depth < 8 || decoded.transparency) {
279
+ // Screenshot resizing assumes unpacked 8/16-bit samples and explicit
280
+ // alpha. Saved images can use packed greyscale or tRNS colour keys.
281
+ const rgba = new Uint8Array(raster.width * raster.height * 4)
282
+ const packedStride = Math.ceil((raster.width * decoded.depth) / 8)
283
+ const maxSample = 2 ** decoded.depth - 1
284
+ for (let y = 0; y < raster.height; y += 1) {
285
+ for (let x = 0; x < raster.width; x += 1) {
286
+ const i = y * raster.width + x
287
+ const packed = decoded.data[y * packedStride + Math.floor((x * decoded.depth) / 8)] ?? 0
288
+ const grey =
289
+ decoded.depth < 8
290
+ ? (packed >>> (8 - decoded.depth - ((x * decoded.depth) % 8))) & maxSample
291
+ : (decoded.data[i * decoded.channels] ?? 0)
292
+ const r = grey
293
+ const g = decoded.channels >= 3 ? (decoded.data[i * decoded.channels + 1] ?? 0) : grey
294
+ const b = decoded.channels >= 3 ? (decoded.data[i * decoded.channels + 2] ?? 0) : grey
295
+ rgba[i * 4] = Math.round((r * 255) / maxSample)
296
+ rgba[i * 4 + 1] = Math.round((g * 255) / maxSample)
297
+ rgba[i * 4 + 2] = Math.round((b * 255) / maxSample)
298
+ const transparent =
299
+ decoded.transparency &&
300
+ r === decoded.transparency[0] &&
301
+ (decoded.channels === 1 ||
302
+ (g === decoded.transparency[1] && b === decoded.transparency[2]))
303
+ rgba[i * 4 + 3] = transparent ? 0 : 255
304
+ }
305
+ }
306
+ return Buffer.from(
307
+ encode({ width: raster.width, height: raster.height, data: rgba, channels: 4, depth: 8 }),
308
+ )
309
+ }
310
+ } catch {
311
+ malformed()
312
+ }
313
+ return canonical
314
+ }
315
+
316
+ /**
317
+ * Inspect an artifact without granting screen-coordinate authority. An image
318
+ * file can be a reference, render or export; it is never a computer_use frame.
319
+ */
320
+ export function createViewImageTool(
321
+ options: ViewImageToolOptions = {},
322
+ ): ToolDefinition<z.infer<typeof inputSchema>> {
323
+ const unavailableReason = options.unavailableReason
324
+ return defineTool({
325
+ name: 'view_image',
326
+ description: `Visually inspect a saved PNG, JPEG or WebP reference, render or exported image. Reads this turn's files and returns actual image pixels to the model, with source dimensions. PNGs are decoded and fitted; JPEG/WebP containers are checked and must already fit standard vision size. File pixels are not a live desktop screenshot and cannot authorize mouse coordinates.${unavailableReason ? ` Unavailable: ${unavailableReason} Do not retry; tell the user.` : ''}`,
327
+ inputSchema,
328
+ category: 'filesystem',
329
+ pathArgument: 'path',
330
+ permissions: ['file_read'],
331
+ readOnly: true,
332
+ destructive: false,
333
+ concurrencySafe: true,
334
+ presentCall: (input) => ({
335
+ kind: 'generic',
336
+ label: `Inspect ${input.path}`,
337
+ presentation: 'activity',
338
+ activity: 'exploration',
339
+ }),
340
+ async execute(input, context) {
341
+ if (unavailableReason) {
342
+ const message = `view_image unavailable: ${unavailableReason} No image was read or shown. Do not retry; tell the user.`
343
+ return { success: false, output: message, error: message }
344
+ }
345
+ const artifact = await readArtifact(input.path, context)
346
+ const source = describeRaster(artifact.bytes)
347
+ if (
348
+ !admitMcpImageBatch([
349
+ {
350
+ type: 'image',
351
+ mimeType: source.mediaType,
352
+ data: artifact.bytes.toString('base64'),
353
+ },
354
+ ])
355
+ )
356
+ malformed()
357
+ context.abortSignal.throwIfAborted()
358
+ let image = {
359
+ data: artifact.bytes,
360
+ width: source.width,
361
+ height: source.height,
362
+ }
363
+ if (source.mediaType === 'image/png') {
364
+ const png = await validatedPng(artifact.bytes, source)
365
+ image = await fitPng(png, STANDARD_SCREENSHOT_LIMITS)
366
+ } else {
367
+ const target = screenshotTargetSize(source.width, source.height)
368
+ if (target.width !== source.width || target.height !== source.height)
369
+ throw new Error(
370
+ `This ${source.mediaType} image needs resizing. JPEG/WebP decoding and resizing are unavailable here; export a PNG (or a smaller JPEG/WebP) and inspect that file.`,
371
+ )
372
+ }
373
+ context.abortSignal.throwIfAborted()
374
+ const validation = source.mediaType === 'image/png' ? 'decoded' : 'container'
375
+ const output = `Image artifact: ${artifact.path} (${source.width}x${source.height}, ${source.mediaType}); shown at ${image.width}x${image.height}.`
376
+ return {
377
+ success: true,
378
+ output,
379
+ content: [
380
+ {
381
+ type: 'text',
382
+ text: `${output}\n${validation === 'container' ? 'The complete container and dimensions were validated; compressed JPEG/WebP pixels were not decoded by this tool. ' : ''}Inspect these pixels for visual evidence. This saved artifact is not a current computer_use screenshot; capture the application before GUI input.`,
383
+ },
384
+ {
385
+ type: 'image',
386
+ mediaType: source.mediaType,
387
+ data: image.data.toString('base64'),
388
+ },
389
+ ],
390
+ data: {
391
+ path: artifact.path,
392
+ sandboxed: artifact.sandboxed,
393
+ artifact: true,
394
+ mediaType: source.mediaType,
395
+ sourceWidth: source.width,
396
+ sourceHeight: source.height,
397
+ width: image.width,
398
+ height: image.height,
399
+ sourceBytes: artifact.bytes.length,
400
+ sha256: createHash('sha256').update(artifact.bytes).digest('hex'),
401
+ validation,
402
+ },
403
+ }
404
+ },
405
+ })
406
+ }
407
+
408
+ /** An optional artifact inspection tool; hosts must mount it explicitly. */
409
+ export const ViewImageTool = createViewImageTool()