@namzu/sdk 51.1.0 → 52.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 (395) hide show
  1. package/CHANGELOG.md +119 -0
  2. package/dist/agents/QueryAgent.d.ts.map +1 -1
  3. package/dist/agents/QueryAgent.js +2 -0
  4. package/dist/agents/QueryAgent.js.map +1 -1
  5. package/dist/agents/SupervisorAgent.d.ts +1 -1
  6. package/dist/agents/SupervisorAgent.d.ts.map +1 -1
  7. package/dist/agents/SupervisorAgent.js.map +1 -1
  8. package/dist/agents/examples/SupervisorAgent.d.ts +42 -0
  9. package/dist/agents/examples/SupervisorAgent.d.ts.map +1 -1
  10. package/dist/agents/examples/SupervisorAgent.js +80 -4
  11. package/dist/agents/examples/SupervisorAgent.js.map +1 -1
  12. package/dist/agents/index.d.ts +1 -1
  13. package/dist/agents/index.d.ts.map +1 -1
  14. package/dist/agents/index.js.map +1 -1
  15. package/dist/authorization/protected-paths.d.ts +36 -0
  16. package/dist/authorization/protected-paths.d.ts.map +1 -0
  17. package/dist/authorization/protected-paths.js +107 -0
  18. package/dist/authorization/protected-paths.js.map +1 -0
  19. package/dist/authorization/readonly-commands.d.ts +39 -0
  20. package/dist/authorization/readonly-commands.d.ts.map +1 -0
  21. package/dist/authorization/readonly-commands.js +797 -0
  22. package/dist/authorization/readonly-commands.js.map +1 -0
  23. package/dist/authorization/readonly-flags.d.ts +19 -0
  24. package/dist/authorization/readonly-flags.d.ts.map +1 -0
  25. package/dist/authorization/readonly-flags.js +178 -0
  26. package/dist/authorization/readonly-flags.js.map +1 -0
  27. package/dist/authorization/removal.d.ts +52 -0
  28. package/dist/authorization/removal.d.ts.map +1 -0
  29. package/dist/authorization/removal.js +283 -0
  30. package/dist/authorization/removal.js.map +1 -0
  31. package/dist/authorization/shell-paths.d.ts +66 -0
  32. package/dist/authorization/shell-paths.d.ts.map +1 -0
  33. package/dist/authorization/shell-paths.js +697 -0
  34. package/dist/authorization/shell-paths.js.map +1 -0
  35. package/dist/bridge/acp/update.d.ts.map +1 -1
  36. package/dist/bridge/acp/update.js +1 -0
  37. package/dist/bridge/acp/update.js.map +1 -1
  38. package/dist/compaction/context-window.d.ts +24 -0
  39. package/dist/compaction/context-window.d.ts.map +1 -1
  40. package/dist/compaction/context-window.js +34 -0
  41. package/dist/compaction/context-window.js.map +1 -1
  42. package/dist/compaction/manual.d.ts.map +1 -1
  43. package/dist/compaction/manual.js +10 -2
  44. package/dist/compaction/manual.js.map +1 -1
  45. package/dist/compaction/plan.d.ts +4 -0
  46. package/dist/compaction/plan.d.ts.map +1 -1
  47. package/dist/compaction/plan.js +6 -2
  48. package/dist/compaction/plan.js.map +1 -1
  49. package/dist/compaction/verifier.d.ts +11 -1
  50. package/dist/compaction/verifier.d.ts.map +1 -1
  51. package/dist/compaction/verifier.js +75 -23
  52. package/dist/compaction/verifier.js.map +1 -1
  53. package/dist/config/runtime.d.ts +55 -7
  54. package/dist/config/runtime.d.ts.map +1 -1
  55. package/dist/config/runtime.js +23 -2
  56. package/dist/config/runtime.js.map +1 -1
  57. package/dist/connector/web/guarded-fetch.d.ts.map +1 -1
  58. package/dist/connector/web/guarded-fetch.js +24 -0
  59. package/dist/connector/web/guarded-fetch.js.map +1 -1
  60. package/dist/connector/web/index.d.ts +1 -1
  61. package/dist/connector/web/index.d.ts.map +1 -1
  62. package/dist/connector/web/page.d.ts +59 -0
  63. package/dist/connector/web/page.d.ts.map +1 -0
  64. package/dist/connector/web/page.js +112 -0
  65. package/dist/connector/web/page.js.map +1 -0
  66. package/dist/connector/web/types.d.ts +47 -0
  67. package/dist/connector/web/types.d.ts.map +1 -1
  68. package/dist/connector/web/types.js.map +1 -1
  69. package/dist/constants/continuation.d.ts +8 -0
  70. package/dist/constants/continuation.d.ts.map +1 -1
  71. package/dist/constants/continuation.js +8 -0
  72. package/dist/constants/continuation.js.map +1 -1
  73. package/dist/constants/plugin/index.d.ts +1 -1
  74. package/dist/constants/plugin/index.d.ts.map +1 -1
  75. package/dist/constants/plugin/index.js +1 -1
  76. package/dist/constants/plugin/index.js.map +1 -1
  77. package/dist/contracts/a2a.d.ts +2 -2
  78. package/dist/manager/agent/lifecycle.d.ts +7 -0
  79. package/dist/manager/agent/lifecycle.d.ts.map +1 -1
  80. package/dist/manager/agent/lifecycle.js +11 -2
  81. package/dist/manager/agent/lifecycle.js.map +1 -1
  82. package/dist/manager/session/turn-recorder.d.ts.map +1 -1
  83. package/dist/manager/session/turn-recorder.js +4 -2
  84. package/dist/manager/session/turn-recorder.js.map +1 -1
  85. package/dist/plugin/index.d.ts +1 -1
  86. package/dist/plugin/index.d.ts.map +1 -1
  87. package/dist/plugin/index.js +1 -1
  88. package/dist/plugin/index.js.map +1 -1
  89. package/dist/plugin/lifecycle.d.ts +6 -0
  90. package/dist/plugin/lifecycle.d.ts.map +1 -1
  91. package/dist/plugin/lifecycle.js +98 -114
  92. package/dist/plugin/lifecycle.js.map +1 -1
  93. package/dist/plugin/shell-hook.d.ts +90 -22
  94. package/dist/plugin/shell-hook.d.ts.map +1 -1
  95. package/dist/plugin/shell-hook.js +434 -41
  96. package/dist/plugin/shell-hook.js.map +1 -1
  97. package/dist/provider/capabilities.d.ts +9 -0
  98. package/dist/provider/capabilities.d.ts.map +1 -1
  99. package/dist/provider/capabilities.js +15 -0
  100. package/dist/provider/capabilities.js.map +1 -1
  101. package/dist/provider/errors.d.ts.map +1 -1
  102. package/dist/provider/errors.js +13 -0
  103. package/dist/provider/errors.js.map +1 -1
  104. package/dist/provider/fallback.d.ts.map +1 -1
  105. package/dist/provider/fallback.js +10 -0
  106. package/dist/provider/fallback.js.map +1 -1
  107. package/dist/provider/idle-timeout.d.ts.map +1 -1
  108. package/dist/provider/idle-timeout.js +5 -0
  109. package/dist/provider/idle-timeout.js.map +1 -1
  110. package/dist/provider/image-input-refusal.d.ts +9 -0
  111. package/dist/provider/image-input-refusal.d.ts.map +1 -0
  112. package/dist/provider/image-input-refusal.js +54 -0
  113. package/dist/provider/image-input-refusal.js.map +1 -0
  114. package/dist/provider/index.d.ts +2 -1
  115. package/dist/provider/index.d.ts.map +1 -1
  116. package/dist/provider/index.js +2 -1
  117. package/dist/provider/index.js.map +1 -1
  118. package/dist/provider/retry.d.ts +7 -2
  119. package/dist/provider/retry.d.ts.map +1 -1
  120. package/dist/provider/retry.js +38 -4
  121. package/dist/provider/retry.js.map +1 -1
  122. package/dist/public-runtime.d.ts +5 -2
  123. package/dist/public-runtime.d.ts.map +1 -1
  124. package/dist/public-runtime.js +5 -2
  125. package/dist/public-runtime.js.map +1 -1
  126. package/dist/public-types.d.ts +2 -2
  127. package/dist/public-types.d.ts.map +1 -1
  128. package/dist/runtime/jobs/registry.d.ts +21 -0
  129. package/dist/runtime/jobs/registry.d.ts.map +1 -1
  130. package/dist/runtime/jobs/registry.js +15 -2
  131. package/dist/runtime/jobs/registry.js.map +1 -1
  132. package/dist/runtime/query/deferred-sandbox.d.ts +54 -0
  133. package/dist/runtime/query/deferred-sandbox.d.ts.map +1 -0
  134. package/dist/runtime/query/deferred-sandbox.js +75 -0
  135. package/dist/runtime/query/deferred-sandbox.js.map +1 -0
  136. package/dist/runtime/query/executor/tool-call-admission.d.ts +10 -0
  137. package/dist/runtime/query/executor/tool-call-admission.d.ts.map +1 -1
  138. package/dist/runtime/query/executor/tool-call-admission.js +74 -13
  139. package/dist/runtime/query/executor/tool-call-admission.js.map +1 -1
  140. package/dist/runtime/query/executor.d.ts +51 -2
  141. package/dist/runtime/query/executor.d.ts.map +1 -1
  142. package/dist/runtime/query/executor.js +214 -9
  143. package/dist/runtime/query/executor.js.map +1 -1
  144. package/dist/runtime/query/finalize-turn.d.ts +6 -0
  145. package/dist/runtime/query/finalize-turn.d.ts.map +1 -1
  146. package/dist/runtime/query/finalize-turn.js +1 -1
  147. package/dist/runtime/query/finalize-turn.js.map +1 -1
  148. package/dist/runtime/query/index.d.ts +29 -0
  149. package/dist/runtime/query/index.d.ts.map +1 -1
  150. package/dist/runtime/query/index.js +108 -28
  151. package/dist/runtime/query/index.js.map +1 -1
  152. package/dist/runtime/query/iteration/index.d.ts +57 -0
  153. package/dist/runtime/query/iteration/index.d.ts.map +1 -1
  154. package/dist/runtime/query/iteration/index.js +380 -28
  155. package/dist/runtime/query/iteration/index.js.map +1 -1
  156. package/dist/runtime/query/iteration/phases/compaction-breaker.d.ts +61 -0
  157. package/dist/runtime/query/iteration/phases/compaction-breaker.d.ts.map +1 -0
  158. package/dist/runtime/query/iteration/phases/compaction-breaker.js +94 -0
  159. package/dist/runtime/query/iteration/phases/compaction-breaker.js.map +1 -0
  160. package/dist/runtime/query/iteration/phases/compaction.d.ts +42 -1
  161. package/dist/runtime/query/iteration/phases/compaction.d.ts.map +1 -1
  162. package/dist/runtime/query/iteration/phases/compaction.js +203 -23
  163. package/dist/runtime/query/iteration/phases/compaction.js.map +1 -1
  164. package/dist/runtime/query/iteration/phases/context.d.ts +10 -0
  165. package/dist/runtime/query/iteration/phases/context.d.ts.map +1 -1
  166. package/dist/runtime/query/iteration/phases/context.js.map +1 -1
  167. package/dist/runtime/query/iteration/phases/tool-review.d.ts.map +1 -1
  168. package/dist/runtime/query/iteration/phases/tool-review.js +165 -2
  169. package/dist/runtime/query/iteration/phases/tool-review.js.map +1 -1
  170. package/dist/runtime/query/iteration/provider-rejected-image.d.ts +21 -1
  171. package/dist/runtime/query/iteration/provider-rejected-image.d.ts.map +1 -1
  172. package/dist/runtime/query/iteration/provider-rejected-image.js +53 -7
  173. package/dist/runtime/query/iteration/provider-rejected-image.js.map +1 -1
  174. package/dist/runtime/query/iteration/request-repair.d.ts +108 -0
  175. package/dist/runtime/query/iteration/request-repair.d.ts.map +1 -0
  176. package/dist/runtime/query/iteration/request-repair.js +593 -0
  177. package/dist/runtime/query/iteration/request-repair.js.map +1 -0
  178. package/dist/runtime/query/iteration/stream-turn.d.ts +6 -0
  179. package/dist/runtime/query/iteration/stream-turn.d.ts.map +1 -1
  180. package/dist/runtime/query/iteration/stream-turn.js +2 -2
  181. package/dist/runtime/query/iteration/stream-turn.js.map +1 -1
  182. package/dist/runtime/query/path-escalation.d.ts +36 -0
  183. package/dist/runtime/query/path-escalation.d.ts.map +1 -0
  184. package/dist/runtime/query/path-escalation.js +184 -0
  185. package/dist/runtime/query/path-escalation.js.map +1 -0
  186. package/dist/runtime/query/plugin-hooks.d.ts.map +1 -1
  187. package/dist/runtime/query/plugin-hooks.js +8 -0
  188. package/dist/runtime/query/plugin-hooks.js.map +1 -1
  189. package/dist/runtime/query/reminders.d.ts +35 -0
  190. package/dist/runtime/query/reminders.d.ts.map +1 -0
  191. package/dist/runtime/query/reminders.js +7 -0
  192. package/dist/runtime/query/reminders.js.map +1 -0
  193. package/dist/runtime/query/request-rich-content.d.ts +5 -1
  194. package/dist/runtime/query/request-rich-content.d.ts.map +1 -1
  195. package/dist/runtime/query/request-rich-content.js +67 -25
  196. package/dist/runtime/query/request-rich-content.js.map +1 -1
  197. package/dist/runtime/query/resume-pending.d.ts.map +1 -1
  198. package/dist/runtime/query/resume-pending.js +26 -0
  199. package/dist/runtime/query/resume-pending.js.map +1 -1
  200. package/dist/runtime/query/review-policy.d.ts +26 -0
  201. package/dist/runtime/query/review-policy.d.ts.map +1 -1
  202. package/dist/runtime/query/review-policy.js +79 -5
  203. package/dist/runtime/query/review-policy.js.map +1 -1
  204. package/dist/runtime/query/tool-output-budget.d.ts +46 -0
  205. package/dist/runtime/query/tool-output-budget.d.ts.map +1 -1
  206. package/dist/runtime/query/tool-output-budget.js +85 -1
  207. package/dist/runtime/query/tool-output-budget.js.map +1 -1
  208. package/dist/runtime/query/tooling.d.ts +1 -0
  209. package/dist/runtime/query/tooling.d.ts.map +1 -1
  210. package/dist/runtime/query/tooling.js +5 -0
  211. package/dist/runtime/query/tooling.js.map +1 -1
  212. package/dist/session/paths.d.ts +5 -1
  213. package/dist/session/paths.d.ts.map +1 -1
  214. package/dist/session/paths.js +8 -0
  215. package/dist/session/paths.js.map +1 -1
  216. package/dist/store/memory/disk.d.ts.map +1 -1
  217. package/dist/store/memory/disk.js +2 -2
  218. package/dist/store/memory/disk.js.map +1 -1
  219. package/dist/store/memory/markdown.d.ts.map +1 -1
  220. package/dist/store/memory/markdown.js +2 -2
  221. package/dist/store/memory/markdown.js.map +1 -1
  222. package/dist/store/memory/naming.d.ts +9 -0
  223. package/dist/store/memory/naming.d.ts.map +1 -1
  224. package/dist/store/memory/naming.js +12 -0
  225. package/dist/store/memory/naming.js.map +1 -1
  226. package/dist/tools/builtins/bash.d.ts +30 -1
  227. package/dist/tools/builtins/bash.d.ts.map +1 -1
  228. package/dist/tools/builtins/bash.js +170 -26
  229. package/dist/tools/builtins/bash.js.map +1 -1
  230. package/dist/tools/builtins/computer-use.d.ts +1 -1
  231. package/dist/tools/builtins/computer-use.d.ts.map +1 -1
  232. package/dist/tools/builtins/computer-use.js +12 -5
  233. package/dist/tools/builtins/computer-use.js.map +1 -1
  234. package/dist/tools/builtins/content-fingerprint.d.ts +2 -0
  235. package/dist/tools/builtins/content-fingerprint.d.ts.map +1 -1
  236. package/dist/tools/builtins/content-fingerprint.js +4 -0
  237. package/dist/tools/builtins/content-fingerprint.js.map +1 -1
  238. package/dist/tools/builtins/edit.d.ts.map +1 -1
  239. package/dist/tools/builtins/edit.js +60 -18
  240. package/dist/tools/builtins/edit.js.map +1 -1
  241. package/dist/tools/builtins/grep.d.ts +8 -1
  242. package/dist/tools/builtins/grep.d.ts.map +1 -1
  243. package/dist/tools/builtins/grep.js +152 -33
  244. package/dist/tools/builtins/grep.js.map +1 -1
  245. package/dist/tools/builtins/read-file.d.ts +1 -0
  246. package/dist/tools/builtins/read-file.d.ts.map +1 -1
  247. package/dist/tools/builtins/read-file.js +44 -5
  248. package/dist/tools/builtins/read-file.js.map +1 -1
  249. package/dist/tools/builtins/read-render.d.ts +52 -0
  250. package/dist/tools/builtins/read-render.d.ts.map +1 -1
  251. package/dist/tools/builtins/read-render.js +143 -0
  252. package/dist/tools/builtins/read-render.js.map +1 -1
  253. package/dist/tools/builtins/web.d.ts +13 -2
  254. package/dist/tools/builtins/web.d.ts.map +1 -1
  255. package/dist/tools/builtins/web.js +225 -32
  256. package/dist/tools/builtins/web.js.map +1 -1
  257. package/dist/tools/coordinator/ask-user-question.d.ts +2 -0
  258. package/dist/tools/coordinator/ask-user-question.d.ts.map +1 -1
  259. package/dist/tools/coordinator/ask-user-question.js +256 -92
  260. package/dist/tools/coordinator/ask-user-question.js.map +1 -1
  261. package/dist/tools/coordinator/question-options.d.ts +1 -0
  262. package/dist/tools/coordinator/question-options.d.ts.map +1 -1
  263. package/dist/tools/coordinator/question-options.js +6 -1
  264. package/dist/tools/coordinator/question-options.js.map +1 -1
  265. package/dist/tools/defineTool.d.ts +4 -1
  266. package/dist/tools/defineTool.d.ts.map +1 -1
  267. package/dist/tools/defineTool.js +6 -1
  268. package/dist/tools/defineTool.js.map +1 -1
  269. package/dist/tools/paths.d.ts +6 -0
  270. package/dist/tools/paths.d.ts.map +1 -1
  271. package/dist/tools/paths.js +1 -1
  272. package/dist/tools/paths.js.map +1 -1
  273. package/dist/types/agent/query.d.ts +3 -0
  274. package/dist/types/agent/query.d.ts.map +1 -1
  275. package/dist/types/errors/catalog.js +1 -1
  276. package/dist/types/errors/catalog.js.map +1 -1
  277. package/dist/types/hitl/index.d.ts +104 -0
  278. package/dist/types/hitl/index.d.ts.map +1 -1
  279. package/dist/types/hitl/index.js.map +1 -1
  280. package/dist/types/message/index.d.ts +1 -1
  281. package/dist/types/message/index.d.ts.map +1 -1
  282. package/dist/types/message/index.js +2 -0
  283. package/dist/types/message/index.js.map +1 -1
  284. package/dist/types/plugin/index.d.ts +93 -19
  285. package/dist/types/plugin/index.d.ts.map +1 -1
  286. package/dist/types/plugin/index.js +3 -0
  287. package/dist/types/plugin/index.js.map +1 -1
  288. package/dist/types/provider/errors.d.ts +19 -0
  289. package/dist/types/provider/errors.d.ts.map +1 -1
  290. package/dist/types/provider/errors.js +54 -5
  291. package/dist/types/provider/errors.js.map +1 -1
  292. package/dist/types/provider/interface.d.ts +12 -0
  293. package/dist/types/provider/interface.d.ts.map +1 -1
  294. package/dist/types/provider/stream.d.ts +1 -1
  295. package/dist/types/session/config.d.ts +14 -0
  296. package/dist/types/session/config.d.ts.map +1 -1
  297. package/dist/types/session/events.d.ts +27 -4
  298. package/dist/types/session/events.d.ts.map +1 -1
  299. package/dist/types/session/events.js.map +1 -1
  300. package/dist/types/session/records.d.ts +9 -9
  301. package/dist/types/session/records.d.ts.map +1 -1
  302. package/dist/types/session/records.js +1 -0
  303. package/dist/types/session/records.js.map +1 -1
  304. package/dist/types/session/stop-reason.d.ts +5 -0
  305. package/dist/types/session/stop-reason.d.ts.map +1 -1
  306. package/dist/types/tool/index.d.ts +52 -0
  307. package/dist/types/tool/index.d.ts.map +1 -1
  308. package/dist/types/tool/index.js.map +1 -1
  309. package/package.json +4 -2
  310. package/src/agents/QueryAgent.ts +5 -1
  311. package/src/agents/SupervisorAgent.ts +1 -1
  312. package/src/agents/examples/SupervisorAgent.ts +217 -106
  313. package/src/agents/index.ts +1 -1
  314. package/src/authorization/protected-paths.ts +110 -0
  315. package/src/authorization/readonly-commands.ts +771 -0
  316. package/src/authorization/readonly-flags.ts +196 -0
  317. package/src/authorization/removal.ts +326 -0
  318. package/src/authorization/shell-paths.ts +927 -0
  319. package/src/bridge/acp/update.ts +1 -0
  320. package/src/compaction/context-window.ts +41 -0
  321. package/src/compaction/manual.ts +10 -2
  322. package/src/compaction/plan.ts +11 -2
  323. package/src/compaction/verifier.ts +84 -22
  324. package/src/config/runtime.ts +23 -2
  325. package/src/connector/web/guarded-fetch.ts +26 -0
  326. package/src/connector/web/index.ts +3 -0
  327. package/src/connector/web/page.ts +130 -0
  328. package/src/connector/web/types.ts +47 -0
  329. package/src/constants/continuation.ts +10 -0
  330. package/src/constants/plugin/index.ts +1 -1
  331. package/src/manager/agent/lifecycle.ts +12 -4
  332. package/src/manager/session/turn-recorder.ts +10 -2
  333. package/src/plugin/index.ts +1 -0
  334. package/src/plugin/lifecycle.ts +107 -119
  335. package/src/plugin/shell-hook.ts +477 -43
  336. package/src/provider/capabilities.ts +17 -0
  337. package/src/provider/errors.ts +13 -0
  338. package/src/provider/fallback.ts +10 -0
  339. package/src/provider/idle-timeout.ts +5 -0
  340. package/src/provider/image-input-refusal.ts +54 -0
  341. package/src/provider/index.ts +2 -0
  342. package/src/provider/retry.ts +42 -4
  343. package/src/public-runtime.ts +11 -0
  344. package/src/public-types.ts +4 -0
  345. package/src/runtime/jobs/registry.ts +39 -2
  346. package/src/runtime/query/deferred-sandbox.ts +110 -0
  347. package/src/runtime/query/executor/tool-call-admission.ts +79 -13
  348. package/src/runtime/query/executor.ts +267 -11
  349. package/src/runtime/query/finalize-turn.ts +7 -1
  350. package/src/runtime/query/index.ts +169 -52
  351. package/src/runtime/query/iteration/index.ts +439 -35
  352. package/src/runtime/query/iteration/phases/compaction-breaker.ts +108 -0
  353. package/src/runtime/query/iteration/phases/compaction.ts +241 -38
  354. package/src/runtime/query/iteration/phases/context.ts +11 -0
  355. package/src/runtime/query/iteration/phases/tool-review.ts +177 -2
  356. package/src/runtime/query/iteration/provider-rejected-image.ts +71 -5
  357. package/src/runtime/query/iteration/request-repair.ts +743 -0
  358. package/src/runtime/query/iteration/stream-turn.ts +11 -1
  359. package/src/runtime/query/path-escalation.ts +204 -0
  360. package/src/runtime/query/plugin-hooks.ts +8 -0
  361. package/src/runtime/query/reminders.ts +45 -0
  362. package/src/runtime/query/request-rich-content.ts +77 -27
  363. package/src/runtime/query/resume-pending.ts +27 -0
  364. package/src/runtime/query/review-policy.ts +106 -5
  365. package/src/runtime/query/tool-output-budget.ts +115 -1
  366. package/src/runtime/query/tooling.ts +6 -0
  367. package/src/session/paths.ts +11 -1
  368. package/src/store/memory/disk.ts +2 -1
  369. package/src/store/memory/markdown.ts +2 -1
  370. package/src/store/memory/naming.ts +13 -0
  371. package/src/tools/builtins/bash.ts +203 -34
  372. package/src/tools/builtins/computer-use.ts +13 -4
  373. package/src/tools/builtins/content-fingerprint.ts +5 -0
  374. package/src/tools/builtins/edit.ts +69 -19
  375. package/src/tools/builtins/grep.ts +159 -38
  376. package/src/tools/builtins/read-file.ts +48 -5
  377. package/src/tools/builtins/read-render.ts +193 -0
  378. package/src/tools/builtins/web.ts +258 -33
  379. package/src/tools/coordinator/ask-user-question.ts +309 -103
  380. package/src/tools/coordinator/question-options.ts +8 -1
  381. package/src/tools/defineTool.ts +11 -2
  382. package/src/tools/paths.ts +1 -1
  383. package/src/types/agent/query.ts +3 -0
  384. package/src/types/errors/catalog.ts +1 -1
  385. package/src/types/hitl/index.ts +104 -0
  386. package/src/types/message/index.ts +2 -0
  387. package/src/types/plugin/index.ts +101 -18
  388. package/src/types/provider/errors.ts +66 -5
  389. package/src/types/provider/interface.ts +13 -0
  390. package/src/types/provider/stream.ts +1 -1
  391. package/src/types/session/config.ts +14 -0
  392. package/src/types/session/events.ts +32 -4
  393. package/src/types/session/records.ts +1 -0
  394. package/src/types/session/stop-reason.ts +5 -0
  395. package/src/types/tool/index.ts +53 -2
@@ -42,7 +42,11 @@ import { generateMessageId, generateToolCallId } from '../../../utils/id.js'
42
42
  import type { Logger } from '../../../utils/logger.js'
43
43
  import type { EmitEvent } from '../events.js'
44
44
  import type { RequestImageIdentity } from '../request-rich-content.js'
45
- import { streamWithProviderRejectedImageRecovery } from './provider-rejected-image.js'
45
+ import {
46
+ type TextOnlyModelRecovery,
47
+ streamWithProviderRejectedImageRecovery,
48
+ } from './provider-rejected-image.js'
49
+ import type { RequestRepair } from './request-repair.js'
46
50
  import {
47
51
  type ParsedToolArguments,
48
52
  capPartialArguments,
@@ -237,6 +241,10 @@ export async function* streamProviderTurn(
237
241
  announceAs?: import('../../../types/ids/index.js').MessageId,
238
242
  imageRecovery?: {
239
243
  readonly onAccepted: (identity: RequestImageIdentity) => Promise<void>
244
+ /** A model refused the request for holding an image it cannot read; the retry sent none. */
245
+ readonly textOnly?: TextOnlyModelRecovery
246
+ /** Repairs and resends a request the provider rejects as invalid. */
247
+ readonly repair?: RequestRepair
240
248
  },
241
249
  captureRequest = false,
242
250
  /** The session the turn belongs to, named on the chat span as `gen_ai.conversation.id`. */
@@ -363,6 +371,8 @@ export async function* streamProviderTurn(
363
371
  streamParams,
364
372
  imageRecovery.onAccepted,
365
373
  observeRequest,
374
+ imageRecovery.textOnly,
375
+ imageRecovery.repair,
366
376
  )
367
377
  : provider.chatStream(streamParams)
368
378
  ) as AsyncIterable<StreamChunk>
@@ -0,0 +1,204 @@
1
+ /**
2
+ * What a call writes or removes that no mode may approve in advance.
3
+ *
4
+ * Three questions the kernel answers about a prepared call before it runs, all
5
+ * of them about the call's own arguments and none about the model's intent:
6
+ *
7
+ * - does it write a protected path (a git hook, a shell rc file, editor or
8
+ * tool configuration, the project's `.namzu` directory)?
9
+ * - does its shell line remove something catastrophic?
10
+ * - does its shell line reach a path outside the turn's roots, through a
11
+ * command whose operands are paths or through a redirection?
12
+ *
13
+ * The first two are floors: they hold in every mode, the way a sandbox escape
14
+ * does. The third is the existing outside-root boundary, extended from the
15
+ * file tools' one declared argument to the paths a shell line names.
16
+ */
17
+
18
+ import { homedir } from 'node:os'
19
+ import { isAbsolute, relative, resolve } from 'node:path'
20
+
21
+ import { isProtectedPath } from '../../authorization/protected-paths.js'
22
+ import { dangerousRemoval } from '../../authorization/removal.js'
23
+ import type { ShellDialect } from '../../authorization/shell-lexer.js'
24
+ import { readShellLine, shellPathAccess } from '../../authorization/shell-paths.js'
25
+ import { canonicalize, pathOutsideRoots } from '../../tools/paths.js'
26
+
27
+ /** What the escalation records carry. */
28
+ export interface PathEscalations {
29
+ readonly outsidePaths: readonly string[]
30
+ readonly protectedPaths: readonly string[]
31
+ readonly dangerousRemoval?: string
32
+ }
33
+
34
+ export interface PathEscalationContext {
35
+ /** The working directory first, then the added directories. */
36
+ readonly roots: readonly string[]
37
+ /** Whether to report paths outside the roots (`outsideRootAccess: 'review'`, no sandbox). */
38
+ readonly reviewOutside: boolean
39
+ }
40
+
41
+ /**
42
+ * The part of `absolute` that protected names are looked for in.
43
+ *
44
+ * Inside a root (the working directory or an added directory) that is the part
45
+ * below the root, not the whole path: the root is where the turn was put, and
46
+ * a root that itself sits under a protected name is not a reason to ask about
47
+ * every file in it. The case that matters is the managed worktree a sub-agent
48
+ * runs in, `~/.namzu/projects/<slug>/worktrees/<name>`, which lies under
49
+ * `.namzu` by construction; the reference terminal makes the same exception
50
+ * for its own worktrees directory. A path in no root is looked at whole.
51
+ */
52
+ function protectedScope(absolute: string, roots: readonly string[]): string {
53
+ let best: string | undefined
54
+ for (const root of roots) {
55
+ const base = resolve(root)
56
+ const below = relative(base, absolute)
57
+ if (below === '' || below.startsWith('..') || isAbsolute(below)) continue
58
+ if (best === undefined || below.length < best.length) best = below
59
+ }
60
+ return best ?? absolute
61
+ }
62
+
63
+ /** A write is protected when its spelling, or the place a link leads to, is. */
64
+ async function isProtectedWrite(
65
+ spelled: string,
66
+ absolute: string,
67
+ roots: readonly string[],
68
+ ): Promise<boolean> {
69
+ if (isProtectedPath(isAbsolute(spelled) ? protectedScope(absolute, roots) : spelled)) return true
70
+ if (isProtectedPath(protectedScope(absolute, roots))) return true
71
+ const real = await canonicalize(absolute)
72
+ const realRoots = await Promise.all(roots.map((root) => canonicalize(resolve(root))))
73
+ return isProtectedPath(protectedScope(real, [...roots, ...realRoots]))
74
+ }
75
+
76
+ /** `{a,b}` with plain comma lists, one level at a time, bounded. */
77
+ export function expandBraces(value: string, limit = 16): string[] {
78
+ const open = value.indexOf('{')
79
+ if (open < 0) return [value]
80
+ let depth = 0
81
+ let close = -1
82
+ const commas: number[] = []
83
+ for (let i = open; i < value.length; i += 1) {
84
+ const c = value[i]
85
+ if (c === '{') depth += 1
86
+ else if (c === '}') {
87
+ depth -= 1
88
+ if (depth === 0) {
89
+ close = i
90
+ break
91
+ }
92
+ } else if (c === ',' && depth === 1) commas.push(i)
93
+ }
94
+ if (close < 0 || commas.length === 0) return [value]
95
+ const head = value.slice(0, open)
96
+ const tail = value.slice(close + 1)
97
+ const parts: string[] = []
98
+ let start = open + 1
99
+ for (const comma of [...commas, close]) {
100
+ parts.push(value.slice(start, comma))
101
+ start = comma + 1
102
+ }
103
+ const out: string[] = []
104
+ for (const part of parts) {
105
+ for (const rest of expandBraces(head + part + tail, limit)) {
106
+ out.push(rest)
107
+ if (out.length >= limit) return out
108
+ }
109
+ }
110
+ return out
111
+ }
112
+
113
+ /** The path a use names with `~` and `$HOME` read as the home directory, or why it cannot be. */
114
+ function settle(
115
+ value: string,
116
+ home: string,
117
+ ): { readonly path: string } | { readonly unresolved: true } {
118
+ if (value === '~') return { path: home }
119
+ if (value.startsWith('~/')) return { path: resolve(home, value.slice(2)) }
120
+ if (value.startsWith('~')) return { unresolved: true }
121
+ const variable = /^\$(?:\{HOME\}|HOME)(?=\/|$)/.exec(value)
122
+ if (variable !== null) return { path: resolve(home, `.${value.slice(variable[0].length)}`) }
123
+ if (/[$`]/.test(value)) return { unresolved: true }
124
+ return { path: value }
125
+ }
126
+
127
+ /** The part of a glob path before the first segment that holds a glob character. */
128
+ function beforeGlob(path: string): string {
129
+ const at = path.search(/[*?[]/)
130
+ if (at < 0) return path
131
+ const cut = path.lastIndexOf('/', at)
132
+ return cut <= 0 ? '/' : path.slice(0, cut)
133
+ }
134
+
135
+ /** A write the file tool's own declared path argument names. */
136
+ export async function declaredWriteEscalation(
137
+ roots: readonly string[],
138
+ value: string,
139
+ ): Promise<string | undefined> {
140
+ const [first] = roots
141
+ if (first === undefined || value === '') return undefined
142
+ const absolute = resolve(resolve(first), value)
143
+ return (await isProtectedWrite(value, absolute, roots)) ? absolute : undefined
144
+ }
145
+
146
+ /** What a shell line reaches. */
147
+ export async function shellEscalations(
148
+ line: string,
149
+ dialect: ShellDialect,
150
+ context: PathEscalationContext,
151
+ ): Promise<PathEscalations> {
152
+ const reading = readShellLine(line, dialect)
153
+ const access = shellPathAccess(reading)
154
+ const [cwd, ...added] = context.roots
155
+ const outside = new Set<string>()
156
+ const protectedPaths = new Set<string>()
157
+ const home = homedir()
158
+ if (cwd !== undefined) {
159
+ for (const use of access.uses) {
160
+ for (const spelled of expandBraces(use.path)) {
161
+ const settled = settle(spelled, home)
162
+ const unresolved = use.unresolved || 'unresolved' in settled
163
+ const base = 'path' in settled ? settled.path : spelled
164
+ const absolute = isAbsolute(base) ? resolve(base) : resolve(cwd, base)
165
+ if (use.access === 'write' && (await isProtectedWrite(spelled, absolute, context.roots))) {
166
+ protectedPaths.add(absolute)
167
+ }
168
+ if (!context.reviewOutside) continue
169
+ if (unresolved) {
170
+ // A write whose target is decided at runtime cannot be checked; a
171
+ // read of one is left, as the reference leaves it.
172
+ if (use.access === 'write') outside.add(spelled)
173
+ continue
174
+ }
175
+ if (
176
+ access.changesDirectory &&
177
+ use.access === 'write' &&
178
+ !isAbsolute(base) &&
179
+ !spelled.startsWith('~')
180
+ ) {
181
+ // A `cd` earlier in the line moves a relative target somewhere the
182
+ // roots cannot be compared with.
183
+ outside.add(spelled)
184
+ continue
185
+ }
186
+ const reached = await pathOutsideRoots(context.roots, beforeGlob(absolute))
187
+ if (reached !== undefined) outside.add(reached)
188
+ }
189
+ }
190
+ }
191
+ const removal =
192
+ cwd === undefined
193
+ ? undefined
194
+ : dangerousRemoval(reading, access.changesDirectory, {
195
+ cwd,
196
+ additionalDirectories: added,
197
+ home,
198
+ })
199
+ return {
200
+ outsidePaths: [...outside],
201
+ protectedPaths: [...protectedPaths],
202
+ ...(removal !== undefined ? { dangerousRemoval: removal } : {}),
203
+ }
204
+ }
@@ -27,6 +27,14 @@ export function applyLifecycleHookResults(
27
27
  if (result.text.trim().length > 0) annotations.push(result.text.trim())
28
28
  continue
29
29
  case 'skip':
30
+ // `turn_end`, `subagent_stop` and `pre_compact` answer with `skip`
31
+ // to keep the turn going or to cancel a pass. The sites that can act
32
+ // on that read the results themselves; a site that cannot (the
33
+ // final `turn_end` of a turn that already ended) has nothing to
34
+ // refuse and carries on.
35
+ if (event === 'turn_end' || event === 'subagent_stop' || event === 'pre_compact') {
36
+ continue
37
+ }
30
38
  // The one lifecycle event with a verdict: a hook may refuse the
31
39
  // prompt before the model sees it, and the turn ends there.
32
40
  if (event === 'user_prompt_submit') {
@@ -0,0 +1,45 @@
1
+ import type { SessionId, TurnId } from '../../types/ids/index.js'
2
+ import type { Message } from '../../types/message/index.js'
3
+
4
+ /**
5
+ * What a reminder source is told when the kernel asks it for hidden reminders.
6
+ */
7
+ export interface ReminderContext {
8
+ readonly sessionId: SessionId
9
+ readonly turnId: TurnId
10
+ /** The model request about to be made; 1 for the first of the turn. */
11
+ readonly iteration: number
12
+ /**
13
+ * The conversation as it stands, reminders included. Read-only: a source
14
+ * derives its cadence from this (how many assistant turns since it last
15
+ * spoke), so a resumed or compacted conversation needs no counter of its own.
16
+ */
17
+ readonly messages: readonly Message[]
18
+ }
19
+
20
+ /**
21
+ * A host's hidden reminders for the next model request.
22
+ *
23
+ * The kernel calls it once at the start of every model request of a turn
24
+ * (never the closing one) and appends each returned text to the conversation
25
+ * as a user-role message with provenance `{ type: 'runtime-context', kind:
26
+ * 'reminder' }`. The message is part of the durable history, so it is not
27
+ * operator input, never counts as the latest user request, and is not shown as
28
+ * something the operator typed. The channel is opt-in
29
+ * (`QueryParams.reminders`): a turn without a source behaves as before.
30
+ *
31
+ * A source that throws is treated as having nothing to say; a reminder is
32
+ * context, and a fault in one must not end a turn.
33
+ */
34
+ export type ReminderSource = (
35
+ context: ReminderContext,
36
+ ) => readonly string[] | undefined | Promise<readonly string[] | undefined>
37
+
38
+ /** Whether a message is a reminder the kernel appended for a {@link ReminderSource}. */
39
+ export function isReminderMessage(message: Message): boolean {
40
+ return (
41
+ message.role === 'user' &&
42
+ message.source?.type === 'runtime-context' &&
43
+ message.source.kind === 'reminder'
44
+ )
45
+ }
@@ -34,7 +34,8 @@ interface RichOccurrence {
34
34
  readonly source: 'user' | 'tool'
35
35
  readonly kind: RichKind
36
36
  readonly bytes: number
37
- readonly reason: 'budget' | 'provider-rejected' | 'invalid-image'
37
+ readonly mediaType?: string
38
+ readonly reason: 'budget' | 'provider-rejected' | 'invalid-image' | 'model-text-only'
38
39
  }
39
40
 
40
41
  export interface RequestImageIdentity {
@@ -65,6 +66,24 @@ const invalidUserImageMarker = (): string =>
65
66
  const invalidToolImageMarker = (): string =>
66
67
  `[image omitted from this model request because the producing tool returned encoded bytes that are not a complete supported raster matching the declared media type. ${toolRecovery} Correct the image source before presenting it again.]`
67
68
 
69
+ /** `12 KB`-style size of an encoded payload, so the model can tell a thumbnail from a full screenshot. */
70
+ function describeEncodedSize(base64Length: number): string {
71
+ const bytes = Math.floor((base64Length * 3) / 4)
72
+ if (bytes < 1024) return `${bytes} B`
73
+ if (bytes < 1024 * 1024) return `${Math.round(bytes / 1024)} KB`
74
+ return `${(bytes / (1024 * 1024)).toFixed(1)} MB`
75
+ }
76
+
77
+ /**
78
+ * What stands in for an image the current model cannot read. It says so, and
79
+ * what the image was, because the model otherwise sees a tool that reported
80
+ * success next to nothing and tends to retry it or claim to have seen the screen.
81
+ */
82
+ const textOnlyImageMarker = (mediaType: string | undefined, base64Length: number): string =>
83
+ `[image omitted: the current model cannot read images${
84
+ mediaType ? ` (${mediaType}, ${describeEncodedSize(base64Length)})` : ''
85
+ }]`
86
+
68
87
  function assertInlineAttachment(
69
88
  attachment: MessageAttachment,
70
89
  ): asserts attachment is Exclude<MessageAttachment, { readonly type: 'stored' }> {
@@ -75,7 +94,10 @@ function assertInlineAttachment(
75
94
  }
76
95
  }
77
96
 
78
- function collectRichOccurrences(messages: readonly Message[]): RichOccurrence[] {
97
+ function collectRichOccurrences(
98
+ messages: readonly Message[],
99
+ imagesReadable: boolean,
100
+ ): RichOccurrence[] {
79
101
  const occurrences: RichOccurrence[] = []
80
102
 
81
103
  for (const [messageIndex, message] of messages.entries()) {
@@ -88,13 +110,17 @@ function collectRichOccurrences(messages: readonly Message[]): RichOccurrence[]
88
110
  source: 'user',
89
111
  kind: attachment.type === 'document' ? 'document' : 'image',
90
112
  bytes: attachment.data.length,
113
+ mediaType: attachment.mediaType,
91
114
  reason:
92
- attachment.type !== 'document' && attachment.modelOmission?.reason === 'invalid-image'
93
- ? 'invalid-image'
115
+ attachment.type !== 'document' && !imagesReadable
116
+ ? 'model-text-only'
94
117
  : attachment.type !== 'document' &&
95
- attachment.modelOmission?.reason === 'provider-rejected'
96
- ? 'provider-rejected'
97
- : 'budget',
118
+ attachment.modelOmission?.reason === 'invalid-image'
119
+ ? 'invalid-image'
120
+ : attachment.type !== 'document' &&
121
+ attachment.modelOmission?.reason === 'provider-rejected'
122
+ ? 'provider-rejected'
123
+ : 'budget',
98
124
  })
99
125
  }
100
126
  continue
@@ -109,12 +135,15 @@ function collectRichOccurrences(messages: readonly Message[]): RichOccurrence[]
109
135
  source: 'tool',
110
136
  kind: block.type,
111
137
  bytes: block.data.length,
138
+ mediaType: block.mediaType,
112
139
  reason:
113
- block.type === 'image' && block.modelOmission?.reason === 'invalid-image'
114
- ? 'invalid-image'
115
- : block.type === 'image' && block.modelOmission?.reason === 'provider-rejected'
116
- ? 'provider-rejected'
117
- : 'budget',
140
+ block.type === 'image' && !imagesReadable
141
+ ? 'model-text-only'
142
+ : block.type === 'image' && block.modelOmission?.reason === 'invalid-image'
143
+ ? 'invalid-image'
144
+ : block.type === 'image' && block.modelOmission?.reason === 'provider-rejected'
145
+ ? 'provider-rejected'
146
+ : 'budget',
118
147
  })
119
148
  }
120
149
  }
@@ -130,11 +159,13 @@ function appendTextMarkers(content: string, markers: readonly string[]): string
130
159
 
131
160
  function appendMarkers(content: string, occurrences: readonly RichOccurrence[]): string {
132
161
  const markers = occurrences.map((occurrence) =>
133
- occurrence.reason === 'provider-rejected'
134
- ? rejectedUserImageMarker()
135
- : occurrence.reason === 'invalid-image'
136
- ? invalidUserImageMarker()
137
- : userMarker(occurrence.kind),
162
+ occurrence.reason === 'model-text-only'
163
+ ? textOnlyImageMarker(occurrence.mediaType, occurrence.bytes)
164
+ : occurrence.reason === 'provider-rejected'
165
+ ? rejectedUserImageMarker()
166
+ : occurrence.reason === 'invalid-image'
167
+ ? invalidUserImageMarker()
168
+ : userMarker(occurrence.kind),
138
169
  )
139
170
  return appendTextMarkers(content, markers)
140
171
  }
@@ -148,8 +179,12 @@ function appendMarkers(content: string, occurrences: readonly RichOccurrence[]):
148
179
  * original array when nothing is omitted makes the no-op and exact-boundary
149
180
  * cases observable and keeps the common path allocation-free.
150
181
  */
151
- export function projectRequestRichContent(messages: Message[], maxBytes: number): Message[] {
152
- const occurrences = collectRichOccurrences(messages)
182
+ export function projectRequestRichContent(
183
+ messages: Message[],
184
+ maxBytes: number,
185
+ options: { readonly imagesReadable?: boolean } = {},
186
+ ): Message[] {
187
+ const occurrences = collectRichOccurrences(messages, options.imagesReadable ?? true)
153
188
  if (occurrences.length === 0) return messages
154
189
 
155
190
  const omitted = new Map<number, Map<number, RichOccurrence>>()
@@ -163,9 +198,7 @@ export function projectRequestRichContent(messages: Message[], maxBytes: number)
163
198
  }
164
199
 
165
200
  for (const occurrence of occurrences) {
166
- if (occurrence.reason === 'provider-rejected' || occurrence.reason === 'invalid-image') {
167
- omit(occurrence)
168
- }
201
+ if (occurrence.reason !== 'budget') omit(occurrence)
169
202
  }
170
203
 
171
204
  let total = occurrences.reduce(
@@ -206,11 +239,13 @@ export function projectRequestRichContent(messages: Message[], maxBytes: number)
206
239
  ? {
207
240
  type: 'text',
208
241
  text:
209
- occurrence.reason === 'provider-rejected'
210
- ? rejectedToolImageMarker()
211
- : occurrence.reason === 'invalid-image'
212
- ? invalidToolImageMarker()
213
- : toolMarker(occurrence.kind),
242
+ occurrence.reason === 'model-text-only'
243
+ ? textOnlyImageMarker(occurrence.mediaType, occurrence.bytes)
244
+ : occurrence.reason === 'provider-rejected'
245
+ ? rejectedToolImageMarker()
246
+ : occurrence.reason === 'invalid-image'
247
+ ? invalidToolImageMarker()
248
+ : toolMarker(occurrence.kind),
214
249
  }
215
250
  : block
216
251
  })
@@ -221,6 +256,21 @@ export function projectRequestRichContent(messages: Message[], maxBytes: number)
221
256
  })
222
257
  }
223
258
 
259
+ /** Whether the provider-bound request carries an image anywhere, in a user attachment or a tool result. */
260
+ export function requestHasImages(messages: readonly Message[]): boolean {
261
+ for (const message of messages) {
262
+ if (message.role === 'user') {
263
+ for (const attachment of message.attachments ?? []) {
264
+ if (attachment.type !== 'stored' && attachment.type !== 'document') return true
265
+ }
266
+ continue
267
+ }
268
+ if (message.role !== 'tool' || !Array.isArray(message.content)) continue
269
+ if (message.content.some((block) => block.type === 'image')) return true
270
+ }
271
+ return false
272
+ }
273
+
224
274
  function sameImage(
225
275
  image: { readonly data: string; readonly mediaType: string },
226
276
  identity: RequestImageIdentity,
@@ -517,6 +517,24 @@ export async function applyPendingResume(
517
517
  reason: "the turn's review approved this call, answered across a restart",
518
518
  })
519
519
  }
520
+ for (const path of call.escalation?.protectedPaths ?? []) {
521
+ await recorder.recordAudit({
522
+ what: { action: 'protected_path_write', tool: call.name, resource: path },
523
+ outcome: 'approved',
524
+ reason: "the turn's review approved this call, answered across a restart",
525
+ })
526
+ }
527
+ if (call.escalation?.dangerousRemoval !== undefined) {
528
+ await recorder.recordAudit({
529
+ what: {
530
+ action: 'dangerous_removal',
531
+ tool: call.name,
532
+ resource: call.escalation.dangerousRemoval,
533
+ },
534
+ outcome: 'approved',
535
+ reason: "the turn's review approved this call, answered across a restart",
536
+ })
537
+ }
520
538
  }
521
539
 
522
540
  // The parked assistant message is already in the log: it goes back into
@@ -562,6 +580,15 @@ export function escalationRefusal(
562
580
  for (const path of escalation.outsidePaths ?? []) {
563
581
  if (!shown?.outsidePaths?.includes(path)) return refusal
564
582
  }
583
+ for (const path of escalation.protectedPaths ?? []) {
584
+ if (!shown?.protectedPaths?.includes(path)) return refusal
585
+ }
586
+ if (
587
+ escalation.dangerousRemoval !== undefined &&
588
+ shown?.dangerousRemoval !== escalation.dangerousRemoval
589
+ ) {
590
+ return refusal
591
+ }
565
592
  if (escalation.sandboxEscape && (!shown?.sandboxEscape || !confirmed?.includes(id))) {
566
593
  return 'Refused after resume: running this command outside the sandbox needs a person to confirm it for this call, and the durable approval did not.'
567
594
  }