@skaile/workspaces 5.7.0 → 5.9.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 (419) hide show
  1. package/CHANGELOG.md +120 -0
  2. package/dist/app-sdk/index.js +1 -1
  3. package/dist/{asset-feeds-K36CR52Q.js → asset-feeds-XMKKUUK6.js} +54 -30
  4. package/dist/asset-feeds-XMKKUUK6.js.map +1 -0
  5. package/dist/asset-manager/catalog-deployer.js +9 -9
  6. package/dist/asset-manager/index.js +15 -15
  7. package/dist/asset-manager/installer.js +11 -11
  8. package/dist/asset-manager/renderers.js +10 -10
  9. package/dist/asset-manager/src/index.d.ts +268 -24
  10. package/dist/asset-manager/src/index.d.ts.map +1 -1
  11. package/dist/asset-manager/src/install-agent.d.ts +11 -0
  12. package/dist/asset-manager/src/install-agent.d.ts.map +1 -1
  13. package/dist/asset-manager/src/installer.d.ts +2 -2
  14. package/dist/asset-manager/src/installer.d.ts.map +1 -1
  15. package/dist/bridge/drivers/claude-sdk.js +301 -212
  16. package/dist/bridge/drivers/claude-sdk.js.map +1 -1
  17. package/dist/bridge/drivers/codex.js +92 -66
  18. package/dist/bridge/drivers/codex.js.map +1 -1
  19. package/dist/bridge/drivers/continue.js +14 -15
  20. package/dist/bridge/drivers/continue.js.map +1 -1
  21. package/dist/bridge/drivers/echo.js +4 -4
  22. package/dist/bridge/drivers/gemini.js +8 -8
  23. package/dist/bridge/drivers/goose.js +14 -15
  24. package/dist/bridge/drivers/goose.js.map +1 -1
  25. package/dist/bridge/drivers/omp.js +70 -104
  26. package/dist/bridge/drivers/omp.js.map +1 -1
  27. package/dist/bridge/drivers/opencode.js +14 -15
  28. package/dist/bridge/drivers/opencode.js.map +1 -1
  29. package/dist/bridge/drivers/qwen.js +8 -8
  30. package/dist/bridge/index.js +16 -17
  31. package/dist/bridge/src/codex/managed-driver.d.ts +13 -10
  32. package/dist/bridge/src/codex/managed-driver.d.ts.map +1 -1
  33. package/dist/bridge/src/drivers/_subprocess-cli.d.ts +12 -2
  34. package/dist/bridge/src/drivers/_subprocess-cli.d.ts.map +1 -1
  35. package/dist/bridge/src/drivers/claude-sdk.d.ts +67 -62
  36. package/dist/bridge/src/drivers/claude-sdk.d.ts.map +1 -1
  37. package/dist/bridge/src/drivers/claude-tool-allowlist.d.ts +43 -0
  38. package/dist/bridge/src/drivers/claude-tool-allowlist.d.ts.map +1 -0
  39. package/dist/bridge/src/drivers/codex.d.ts +26 -10
  40. package/dist/bridge/src/drivers/codex.d.ts.map +1 -1
  41. package/dist/bridge/src/drivers/continue.d.ts +2 -2
  42. package/dist/bridge/src/drivers/continue.d.ts.map +1 -1
  43. package/dist/bridge/src/drivers/gemini.d.ts +2 -2
  44. package/dist/bridge/src/drivers/gemini.d.ts.map +1 -1
  45. package/dist/bridge/src/drivers/goose.d.ts +2 -2
  46. package/dist/bridge/src/drivers/goose.d.ts.map +1 -1
  47. package/dist/bridge/src/drivers/omp.d.ts +24 -35
  48. package/dist/bridge/src/drivers/omp.d.ts.map +1 -1
  49. package/dist/bridge/src/drivers/opencode.d.ts +2 -2
  50. package/dist/bridge/src/drivers/opencode.d.ts.map +1 -1
  51. package/dist/bridge/src/drivers/recovery-policy.d.ts +79 -0
  52. package/dist/bridge/src/drivers/recovery-policy.d.ts.map +1 -0
  53. package/dist/bridge/src/index.d.ts +1 -0
  54. package/dist/bridge/src/index.d.ts.map +1 -1
  55. package/dist/bridge/src/reconfigure-ledger.d.ts +117 -0
  56. package/dist/bridge/src/reconfigure-ledger.d.ts.map +1 -0
  57. package/dist/bridge/src/types.d.ts +77 -7
  58. package/dist/bridge/src/types.d.ts.map +1 -1
  59. package/dist/{chunk-WIEC3ZE4.js → chunk-2FRUUDZY.js} +5 -5
  60. package/dist/{chunk-WIEC3ZE4.js.map → chunk-2FRUUDZY.js.map} +1 -1
  61. package/dist/{chunk-NARITJS2.js → chunk-2H73V6XR.js} +3 -3
  62. package/dist/{chunk-NARITJS2.js.map → chunk-2H73V6XR.js.map} +1 -1
  63. package/dist/{chunk-O4Z7MAW7.js → chunk-2LWYNQK7.js} +3 -3
  64. package/dist/{chunk-O4Z7MAW7.js.map → chunk-2LWYNQK7.js.map} +1 -1
  65. package/dist/{chunk-OOLT6HGP.js → chunk-36AFURKZ.js} +7 -7
  66. package/dist/{chunk-OOLT6HGP.js.map → chunk-36AFURKZ.js.map} +1 -1
  67. package/dist/{chunk-DFFD4BFG.js → chunk-4MQS7CAF.js} +174 -86
  68. package/dist/chunk-4MQS7CAF.js.map +1 -0
  69. package/dist/{chunk-RNPHRRLG.js → chunk-4PTSR4UU.js} +3 -3
  70. package/dist/{chunk-RNPHRRLG.js.map → chunk-4PTSR4UU.js.map} +1 -1
  71. package/dist/{chunk-BTK7ECLH.js → chunk-5NNNV76P.js} +41 -8
  72. package/dist/chunk-5NNNV76P.js.map +1 -0
  73. package/dist/{chunk-IZLQ4GDO.js → chunk-7AI3Q5AQ.js} +43 -21
  74. package/dist/chunk-7AI3Q5AQ.js.map +1 -0
  75. package/dist/{chunk-NFGRW3L7.js → chunk-7RGTAEG6.js} +3 -3
  76. package/dist/{chunk-NFGRW3L7.js.map → chunk-7RGTAEG6.js.map} +1 -1
  77. package/dist/{chunk-XBSQ4KMC.js → chunk-B4X2N7JQ.js} +205 -3
  78. package/dist/chunk-B4X2N7JQ.js.map +1 -0
  79. package/dist/{chunk-FRHE7FFB.js → chunk-B6GIW55K.js} +5 -3
  80. package/dist/chunk-B6GIW55K.js.map +1 -0
  81. package/dist/{chunk-RVIZQ5XD.js → chunk-BTE2V4IW.js} +3 -3
  82. package/dist/{chunk-RVIZQ5XD.js.map → chunk-BTE2V4IW.js.map} +1 -1
  83. package/dist/{chunk-EB4XN3KE.js → chunk-CGT45WN7.js} +3 -3
  84. package/dist/{chunk-EB4XN3KE.js.map → chunk-CGT45WN7.js.map} +1 -1
  85. package/dist/{chunk-FAP63KV7.js → chunk-CKQEIY43.js} +4 -4
  86. package/dist/{chunk-FAP63KV7.js.map → chunk-CKQEIY43.js.map} +1 -1
  87. package/dist/{chunk-NWQB7UTY.js → chunk-DNZYOKOJ.js} +3 -3
  88. package/dist/{chunk-NWQB7UTY.js.map → chunk-DNZYOKOJ.js.map} +1 -1
  89. package/dist/{chunk-AVCUPPG6.js → chunk-EF7NPDDU.js} +4 -4
  90. package/dist/{chunk-AVCUPPG6.js.map → chunk-EF7NPDDU.js.map} +1 -1
  91. package/dist/chunk-EPBKISS5.js +84 -0
  92. package/dist/chunk-EPBKISS5.js.map +1 -0
  93. package/dist/{chunk-DMLDYFDS.js → chunk-F4NJDSR7.js} +9 -5
  94. package/dist/chunk-F4NJDSR7.js.map +1 -0
  95. package/dist/{chunk-PSA6ONFB.js → chunk-FVJK4QWM.js} +4 -4
  96. package/dist/{chunk-PSA6ONFB.js.map → chunk-FVJK4QWM.js.map} +1 -1
  97. package/dist/{chunk-KNWCFEWU.js → chunk-FYXZRVID.js} +20 -7
  98. package/dist/{chunk-KNWCFEWU.js.map → chunk-FYXZRVID.js.map} +1 -1
  99. package/dist/{chunk-LBQ4BBX4.js → chunk-FZNG4V4J.js} +16 -30
  100. package/dist/chunk-FZNG4V4J.js.map +1 -0
  101. package/dist/{chunk-SWO25LTO.js → chunk-GB7WDMH2.js} +4 -4
  102. package/dist/{chunk-SWO25LTO.js.map → chunk-GB7WDMH2.js.map} +1 -1
  103. package/dist/{chunk-EU3Q5AQ4.js → chunk-GKMZ6THE.js} +23 -32
  104. package/dist/chunk-GKMZ6THE.js.map +1 -0
  105. package/dist/{chunk-TTPSDC2G.js → chunk-GTILM2CI.js} +34 -13
  106. package/dist/chunk-GTILM2CI.js.map +1 -0
  107. package/dist/{chunk-LXY4BUA3.js → chunk-GXLQLPE5.js} +9 -5
  108. package/dist/chunk-GXLQLPE5.js.map +1 -0
  109. package/dist/{chunk-D5HOETOB.js → chunk-IMKSM5NL.js} +981 -126
  110. package/dist/chunk-IMKSM5NL.js.map +1 -0
  111. package/dist/{chunk-6UFFKMVC.js → chunk-IR33D6EP.js} +6 -6
  112. package/dist/{chunk-6UFFKMVC.js.map → chunk-IR33D6EP.js.map} +1 -1
  113. package/dist/{chunk-CT6NQSA4.js → chunk-ISHJITXJ.js} +3 -3
  114. package/dist/{chunk-CT6NQSA4.js.map → chunk-ISHJITXJ.js.map} +1 -1
  115. package/dist/chunk-IZCR27MU.js +60 -0
  116. package/dist/chunk-IZCR27MU.js.map +1 -0
  117. package/dist/{chunk-GWXFSLBK.js → chunk-J7U3PIOE.js} +4 -4
  118. package/dist/{chunk-GWXFSLBK.js.map → chunk-J7U3PIOE.js.map} +1 -1
  119. package/dist/{chunk-LCU5U5IW.js → chunk-JAKOMFC6.js} +67 -19
  120. package/dist/chunk-JAKOMFC6.js.map +1 -0
  121. package/dist/{chunk-THEJJBOU.js → chunk-JZ5EHBPI.js} +3 -3
  122. package/dist/{chunk-THEJJBOU.js.map → chunk-JZ5EHBPI.js.map} +1 -1
  123. package/dist/{chunk-BWZF2ZIF.js → chunk-K3CVFRVS.js} +3 -3
  124. package/dist/{chunk-BWZF2ZIF.js.map → chunk-K3CVFRVS.js.map} +1 -1
  125. package/dist/{chunk-VOOI7B2L.js → chunk-LAMCXQGA.js} +241 -73
  126. package/dist/chunk-LAMCXQGA.js.map +1 -0
  127. package/dist/{chunk-37FTLYFP.js → chunk-LNFKL23K.js} +3 -3
  128. package/dist/{chunk-37FTLYFP.js.map → chunk-LNFKL23K.js.map} +1 -1
  129. package/dist/{chunk-XUUYAS3Z.js → chunk-M3WPBTGJ.js} +3 -3
  130. package/dist/{chunk-XUUYAS3Z.js.map → chunk-M3WPBTGJ.js.map} +1 -1
  131. package/dist/{chunk-QZLWJETK.js → chunk-MGGFBZWA.js} +3 -3
  132. package/dist/{chunk-QZLWJETK.js.map → chunk-MGGFBZWA.js.map} +1 -1
  133. package/dist/{chunk-34C42MJX.js → chunk-MR5HBOUF.js} +5 -5
  134. package/dist/{chunk-34C42MJX.js.map → chunk-MR5HBOUF.js.map} +1 -1
  135. package/dist/{chunk-QCI6D7E4.js → chunk-NUELZWCF.js} +266 -170
  136. package/dist/chunk-NUELZWCF.js.map +1 -0
  137. package/dist/{chunk-GIC3G5YG.js → chunk-P67WJVP4.js} +7 -13
  138. package/dist/chunk-P67WJVP4.js.map +1 -0
  139. package/dist/{chunk-G67BOI2J.js → chunk-PMECEZK3.js} +15 -9
  140. package/dist/chunk-PMECEZK3.js.map +1 -0
  141. package/dist/{chunk-OKGUDNDT.js → chunk-Q6E6FM7P.js} +35 -33
  142. package/dist/chunk-Q6E6FM7P.js.map +1 -0
  143. package/dist/{chunk-CWM3MYGX.js → chunk-QVEKLSEH.js} +8 -9
  144. package/dist/chunk-QVEKLSEH.js.map +1 -0
  145. package/dist/{chunk-O7VPNKYN.js → chunk-QVNRCDTV.js} +23 -7
  146. package/dist/chunk-QVNRCDTV.js.map +1 -0
  147. package/dist/{chunk-UX3K4RKE.js → chunk-S53LOR7B.js} +3 -3
  148. package/dist/{chunk-UX3K4RKE.js.map → chunk-S53LOR7B.js.map} +1 -1
  149. package/dist/{chunk-53MSCGR2.js → chunk-SCOT677Q.js} +5 -5
  150. package/dist/{chunk-53MSCGR2.js.map → chunk-SCOT677Q.js.map} +1 -1
  151. package/dist/{chunk-SZWRPEF7.js → chunk-TTRYE6AC.js} +39 -29
  152. package/dist/chunk-TTRYE6AC.js.map +1 -0
  153. package/dist/{chunk-KM7XWC4Y.js → chunk-UAROCOXF.js} +3 -3
  154. package/dist/{chunk-KM7XWC4Y.js.map → chunk-UAROCOXF.js.map} +1 -1
  155. package/dist/{chunk-MKLBK7HI.js → chunk-UM7RIAHO.js} +17 -13
  156. package/dist/chunk-UM7RIAHO.js.map +1 -0
  157. package/dist/{chunk-JMKB7IB4.js → chunk-UMVKJM4Q.js} +4 -4
  158. package/dist/chunk-UMVKJM4Q.js.map +1 -0
  159. package/dist/{chunk-JLSCA5T5.js → chunk-UO7WPLDY.js} +3 -3
  160. package/dist/{chunk-JLSCA5T5.js.map → chunk-UO7WPLDY.js.map} +1 -1
  161. package/dist/{chunk-HCYS7GFP.js → chunk-V2DXZYBB.js} +3 -3
  162. package/dist/{chunk-HCYS7GFP.js.map → chunk-V2DXZYBB.js.map} +1 -1
  163. package/dist/{chunk-47ZD34KB.js → chunk-VMKMFS2Q.js} +28 -7
  164. package/dist/chunk-VMKMFS2Q.js.map +1 -0
  165. package/dist/{chunk-IUUYRXT6.js → chunk-W5DWWE4Y.js} +4 -4
  166. package/dist/{chunk-IUUYRXT6.js.map → chunk-W5DWWE4Y.js.map} +1 -1
  167. package/dist/{chunk-FK6HPLQA.js → chunk-X4BAYGMT.js} +3 -3
  168. package/dist/{chunk-FK6HPLQA.js.map → chunk-X4BAYGMT.js.map} +1 -1
  169. package/dist/{chunk-OJ4N4T4H.js → chunk-XDVR7QIT.js} +20 -6
  170. package/dist/chunk-XDVR7QIT.js.map +1 -0
  171. package/dist/{chunk-7FJQT3GT.js → chunk-Y4N2NUZD.js} +4 -4
  172. package/dist/{chunk-7FJQT3GT.js.map → chunk-Y4N2NUZD.js.map} +1 -1
  173. package/dist/{chunk-6VRJH4MR.js → chunk-Y7QA2OLD.js} +6 -6
  174. package/dist/{chunk-6VRJH4MR.js.map → chunk-Y7QA2OLD.js.map} +1 -1
  175. package/dist/{chunk-74EEFB52.js → chunk-YSHVQGUS.js} +115 -27
  176. package/dist/chunk-YSHVQGUS.js.map +1 -0
  177. package/dist/{chunk-6C654TFI.js → chunk-ZAOGFXDO.js} +36 -8
  178. package/dist/chunk-ZAOGFXDO.js.map +1 -0
  179. package/dist/{chunk-N6FBTXQ5.js → chunk-ZTBAYUDY.js} +2 -2
  180. package/dist/{chunk-N6FBTXQ5.js.map → chunk-ZTBAYUDY.js.map} +1 -1
  181. package/dist/cli/index.js +373 -188
  182. package/dist/cli/index.js.map +1 -1
  183. package/dist/cli/src/asset-feeds.d.ts +5 -2
  184. package/dist/cli/src/asset-feeds.d.ts.map +1 -1
  185. package/dist/cli/src/commands/asset-cmd.d.ts.map +1 -1
  186. package/dist/cli/src/commands/catalog.d.ts +15 -2
  187. package/dist/cli/src/commands/catalog.d.ts.map +1 -1
  188. package/dist/cli/src/commands/library-cmd.d.ts.map +1 -1
  189. package/dist/cli/src/commands/library-index.d.ts +8 -0
  190. package/dist/cli/src/commands/library-index.d.ts.map +1 -1
  191. package/dist/cli/src/commands/library-publish.d.ts.map +1 -1
  192. package/dist/cli/src/commands/manage.d.ts.map +1 -1
  193. package/dist/cli/src/commands/outdated.d.ts +7 -2
  194. package/dist/cli/src/commands/outdated.d.ts.map +1 -1
  195. package/dist/cli/src/commands/project.d.ts +2 -0
  196. package/dist/cli/src/commands/project.d.ts.map +1 -1
  197. package/dist/cli/src/commands/publish-core.d.ts +10 -1
  198. package/dist/cli/src/commands/publish-core.d.ts.map +1 -1
  199. package/dist/cli/src/commands/session.d.ts.map +1 -1
  200. package/dist/cli/src/commands/source.d.ts +14 -0
  201. package/dist/cli/src/commands/source.d.ts.map +1 -1
  202. package/dist/cli/src/commands/tree.d.ts.map +1 -1
  203. package/dist/cli/src/commands/update.d.ts.map +1 -1
  204. package/dist/cli/src/commands/validate.d.ts.map +1 -1
  205. package/dist/cli/src/flow-discovery.d.ts +8 -5
  206. package/dist/cli/src/flow-discovery.d.ts.map +1 -1
  207. package/dist/cli/src/open-library.d.ts +0 -11
  208. package/dist/cli/src/open-library.d.ts.map +1 -1
  209. package/dist/cli/src/skill-checks.d.ts +11 -2
  210. package/dist/cli/src/skill-checks.d.ts.map +1 -1
  211. package/dist/client/index.js +1 -1
  212. package/dist/client/src/client.d.ts +10 -3
  213. package/dist/client/src/client.d.ts.map +1 -1
  214. package/dist/connectors/config.js +5 -5
  215. package/dist/connectors/index.js +25 -26
  216. package/dist/connectors/src/access-policy.d.ts +33 -0
  217. package/dist/connectors/src/access-policy.d.ts.map +1 -0
  218. package/dist/connectors/src/connector-manager.d.ts.map +1 -1
  219. package/dist/connectors/src/index.d.ts +2 -0
  220. package/dist/connectors/src/index.d.ts.map +1 -1
  221. package/dist/connectors-C7UQ73BK.js +44 -0
  222. package/dist/{connectors-SSOTIDHT.js.map → connectors-C7UQ73BK.js.map} +1 -1
  223. package/dist/connectors-shared/index.js +2 -2
  224. package/dist/core/index.js +8 -8
  225. package/dist/core/logging.js +1 -1
  226. package/dist/core/manifest.js +2 -2
  227. package/dist/core/models.js +1 -1
  228. package/dist/core/publish-manifest.js +2 -2
  229. package/dist/core/ref.js +1 -1
  230. package/dist/core/runtime-assets.js +5 -5
  231. package/dist/core/src/index.d.ts +3 -3
  232. package/dist/core/src/index.d.ts.map +1 -1
  233. package/dist/core/src/logging/config.d.ts +9 -1
  234. package/dist/core/src/logging/config.d.ts.map +1 -1
  235. package/dist/core/src/manifest.d.ts +11 -1
  236. package/dist/core/src/manifest.d.ts.map +1 -1
  237. package/dist/core/src/models.d.ts +14 -6
  238. package/dist/core/src/models.d.ts.map +1 -1
  239. package/dist/core/src/repo-manager.d.ts +41 -6
  240. package/dist/core/src/repo-manager.d.ts.map +1 -1
  241. package/dist/core/src/store.d.ts +16 -2
  242. package/dist/core/src/store.d.ts.map +1 -1
  243. package/dist/core/src/workspace-config.d.ts +10 -1
  244. package/dist/core/src/workspace-config.d.ts.map +1 -1
  245. package/dist/core/store.js +1 -1
  246. package/dist/core/workspace-config.js +4 -4
  247. package/dist/deploy/index.js +8 -8
  248. package/dist/discovery/index.js +5 -5
  249. package/dist/{ensure-sources-277VI7R3.js → ensure-sources-SRC2DVR5.js} +18 -18
  250. package/dist/{ensure-sources-277VI7R3.js.map → ensure-sources-SRC2DVR5.js.map} +1 -1
  251. package/dist/factory-assets/connectors/box.js +25 -26
  252. package/dist/factory-assets/connectors/deploy.js +25 -26
  253. package/dist/factory-assets/connectors/devserver.js +25 -26
  254. package/dist/factory-assets/connectors/flow/adapter.d.ts +6 -0
  255. package/dist/factory-assets/connectors/flow/adapter.d.ts.map +1 -1
  256. package/dist/factory-assets/connectors/flow/adapter.js +25 -26
  257. package/dist/factory-assets/connectors/flow/contract/expression.d.ts +3 -0
  258. package/dist/factory-assets/connectors/flow/contract/expression.d.ts.map +1 -1
  259. package/dist/factory-assets/connectors/flow/contract/output-fields.d.ts +1 -1
  260. package/dist/factory-assets/connectors/flow/contract/output-fields.d.ts.map +1 -1
  261. package/dist/factory-assets/connectors/flow/contract/schema.d.ts.map +1 -1
  262. package/dist/factory-assets/connectors/flow/contract.js +4 -4
  263. package/dist/factory-assets/connectors/flow/engine/flow-output.d.ts +4 -3
  264. package/dist/factory-assets/connectors/flow/engine/flow-output.d.ts.map +1 -1
  265. package/dist/factory-assets/connectors/flow/engine/output-schema.d.ts +6 -1
  266. package/dist/factory-assets/connectors/flow/engine/output-schema.d.ts.map +1 -1
  267. package/dist/factory-assets/connectors/flow/engine.js +12 -12
  268. package/dist/factory-assets/connectors/flow/inline-sub-flow-host.d.ts.map +1 -1
  269. package/dist/factory-assets/connectors/flow/prompt-fragments.js +3 -3
  270. package/dist/factory-assets/connectors/flow/run-flow.d.ts.map +1 -1
  271. package/dist/factory-assets/connectors/flow/run-flow.js +27 -28
  272. package/dist/factory-assets/connectors/flow.js +25 -26
  273. package/dist/factory-assets/connectors/git/config.d.ts.map +1 -1
  274. package/dist/factory-assets/connectors/git.js +25 -26
  275. package/dist/factory-assets/connectors/gmail.js +25 -26
  276. package/dist/factory-assets/connectors/googledrive.js +25 -26
  277. package/dist/factory-assets/connectors/local.js +25 -26
  278. package/dist/factory-assets/connectors/mattermost.js +25 -26
  279. package/dist/factory-assets/connectors/memory.js +25 -26
  280. package/dist/factory-assets/connectors/minio.js +25 -26
  281. package/dist/factory-assets/connectors/postgres.js +25 -26
  282. package/dist/factory-assets/connectors/s3.js +25 -26
  283. package/dist/factory-assets/connectors/sharepoint.js +25 -26
  284. package/dist/factory-assets/connectors/sqlite.js +25 -26
  285. package/dist/factory-assets/connectors/static-server.js +25 -26
  286. package/dist/factory-assets/connectors/tunnel.js +25 -26
  287. package/dist/factory-assets/connectors/webdav.js +25 -26
  288. package/dist/factory-assets/connectors/xstate-store.js +25 -26
  289. package/dist/factory-assets/connectors/xstate.js +25 -26
  290. package/dist/factory-assets/skills/skaile-author-asset/SKILL.md +10 -7
  291. package/dist/{flows-J2UEU2QM.js → flows-CBYRSAGS.js} +13 -13
  292. package/dist/{flows-J2UEU2QM.js.map → flows-CBYRSAGS.js.map} +1 -1
  293. package/dist/{helpers-KC5O7CML.js → helpers-XAEKCZKT.js} +18 -18
  294. package/dist/{helpers-KC5O7CML.js.map → helpers-XAEKCZKT.js.map} +1 -1
  295. package/dist/library/index.js +12 -12
  296. package/dist/library/install.js +3 -3
  297. package/dist/library/src/index.d.ts +3 -1
  298. package/dist/library/src/index.d.ts.map +1 -1
  299. package/dist/library/src/local/scan-authoring-libraries.d.ts +43 -0
  300. package/dist/library/src/local/scan-authoring-libraries.d.ts.map +1 -0
  301. package/dist/library/src/manifest-writer.d.ts +26 -3
  302. package/dist/library/src/manifest-writer.d.ts.map +1 -1
  303. package/dist/library/src/sync/git-driver.d.ts.map +1 -1
  304. package/dist/{library-publish-FGXF5TJO.js → library-publish-VJSWMOLH.js} +73 -37
  305. package/dist/library-publish-VJSWMOLH.js.map +1 -0
  306. package/dist/open-library-DB2PNL2X.js +40 -0
  307. package/dist/{open-library-P3D337NH.js.map → open-library-DB2PNL2X.js.map} +1 -1
  308. package/dist/open-registry-ZUZJ7MS7.js +32 -0
  309. package/dist/{open-registry-Z3P2X2AB.js.map → open-registry-ZUZJ7MS7.js.map} +1 -1
  310. package/dist/paths-FQ64OLJG.js +22 -0
  311. package/dist/{paths-JKEKXM52.js.map → paths-FQ64OLJG.js.map} +1 -1
  312. package/dist/{plugin-store-WI4MZJLP.js → plugin-store-MPAMD5OT.js} +10 -10
  313. package/dist/{plugin-store-WI4MZJLP.js.map → plugin-store-MPAMD5OT.js.map} +1 -1
  314. package/dist/project-I6NX3NFB.js +41 -0
  315. package/dist/{project-WFUDVYNN.js.map → project-I6NX3NFB.js.map} +1 -1
  316. package/dist/resolver/index.js +9 -9
  317. package/dist/runner/index.js +40 -41
  318. package/dist/runner/src/context-usage/compose.d.ts.map +1 -1
  319. package/dist/runner/src/logging-bootstrap.d.ts +6 -0
  320. package/dist/runner/src/logging-bootstrap.d.ts.map +1 -1
  321. package/dist/runner/src/platform-blocks.d.ts +55 -0
  322. package/dist/runner/src/platform-blocks.d.ts.map +1 -0
  323. package/dist/runner/src/reconfigure-handler.d.ts +38 -17
  324. package/dist/runner/src/reconfigure-handler.d.ts.map +1 -1
  325. package/dist/runner/src/serve.d.ts.map +1 -1
  326. package/dist/runner/src/session-builder.d.ts.map +1 -1
  327. package/dist/runner/src/session-capability-wiring.d.ts +0 -2
  328. package/dist/runner/src/session-capability-wiring.d.ts.map +1 -1
  329. package/dist/sdk/asset-manager.js +15 -15
  330. package/dist/sdk/bridge.js +16 -17
  331. package/dist/sdk/client.js +1 -1
  332. package/dist/sdk/core.js +8 -8
  333. package/dist/sdk/flow.js +12 -12
  334. package/dist/sdk/index.js +69 -46
  335. package/dist/sdk/index.js.map +1 -1
  336. package/dist/sdk/resolver.js +9 -9
  337. package/dist/sdk/runner.js +40 -41
  338. package/dist/sdk/session.js +2 -2
  339. package/dist/sdk/src/agent-session.d.ts +8 -0
  340. package/dist/sdk/src/agent-session.d.ts.map +1 -1
  341. package/dist/sdk/store.js +2 -1
  342. package/dist/sdk/types.js +1 -1
  343. package/dist/session/index.js +2 -2
  344. package/dist/session/src/dispatcher.d.ts +25 -4
  345. package/dist/session/src/dispatcher.d.ts.map +1 -1
  346. package/dist/session/src/index.d.ts +1 -1
  347. package/dist/session/src/index.d.ts.map +1 -1
  348. package/dist/{setup-RAMLTORM.js → setup-B7JUHYJW.js} +26 -27
  349. package/dist/setup-B7JUHYJW.js.map +1 -0
  350. package/dist/skills-TVO26Y4V.js +26 -0
  351. package/dist/{skills-EOHZ2DZ4.js.map → skills-TVO26Y4V.js.map} +1 -1
  352. package/dist/source-PJBMDCKX.js +41 -0
  353. package/dist/{source-FYVSFYEI.js.map → source-PJBMDCKX.js.map} +1 -1
  354. package/dist/{source-manifest-publish-4FPIPPLV.js → source-manifest-publish-LLJWXGID.js} +27 -27
  355. package/dist/{source-manifest-publish-4FPIPPLV.js.map → source-manifest-publish-LLJWXGID.js.map} +1 -1
  356. package/dist/store/index.js +2 -1
  357. package/dist/store/src/store.d.ts +8 -5
  358. package/dist/store/src/store.d.ts.map +1 -1
  359. package/dist/tui/index.js +40 -41
  360. package/dist/tui/index.js.map +1 -1
  361. package/dist/types/index.js +1 -1
  362. package/dist/types/manifests.js +1 -1
  363. package/dist/types/src/ask-slots.d.ts +68 -0
  364. package/dist/types/src/ask-slots.d.ts.map +1 -0
  365. package/dist/types/src/delivery.d.ts.map +1 -1
  366. package/dist/types/src/events.d.ts +30 -2
  367. package/dist/types/src/events.d.ts.map +1 -1
  368. package/dist/types/src/index.d.ts +3 -3
  369. package/dist/types/src/index.d.ts.map +1 -1
  370. package/dist/types/src/manifests/index.d.ts +1 -1
  371. package/dist/types/src/manifests/index.d.ts.map +1 -1
  372. package/dist/types/src/manifests/preset.d.ts +4 -0
  373. package/dist/types/src/manifests/preset.d.ts.map +1 -1
  374. package/dist/types/src/protocol.d.ts +43 -1
  375. package/dist/types/src/protocol.d.ts.map +1 -1
  376. package/dist/types/src/version.d.ts +28 -1
  377. package/dist/types/src/version.d.ts.map +1 -1
  378. package/dist/workspace-plugin/adapters/mcp.js +32 -33
  379. package/dist/workspace-plugin/adapters/omp.js +14 -14
  380. package/dist/workspace-plugin/index.js +2 -2
  381. package/package.json +1 -1
  382. package/dist/asset-feeds-K36CR52Q.js.map +0 -1
  383. package/dist/chunk-47ZD34KB.js.map +0 -1
  384. package/dist/chunk-6C654TFI.js.map +0 -1
  385. package/dist/chunk-74EEFB52.js.map +0 -1
  386. package/dist/chunk-BTK7ECLH.js.map +0 -1
  387. package/dist/chunk-CWM3MYGX.js.map +0 -1
  388. package/dist/chunk-D5HOETOB.js.map +0 -1
  389. package/dist/chunk-DFFD4BFG.js.map +0 -1
  390. package/dist/chunk-DMLDYFDS.js.map +0 -1
  391. package/dist/chunk-EINLFFP6.js +0 -59
  392. package/dist/chunk-EINLFFP6.js.map +0 -1
  393. package/dist/chunk-EU3Q5AQ4.js.map +0 -1
  394. package/dist/chunk-FRHE7FFB.js.map +0 -1
  395. package/dist/chunk-G67BOI2J.js.map +0 -1
  396. package/dist/chunk-GIC3G5YG.js.map +0 -1
  397. package/dist/chunk-IZLQ4GDO.js.map +0 -1
  398. package/dist/chunk-JMKB7IB4.js.map +0 -1
  399. package/dist/chunk-LBQ4BBX4.js.map +0 -1
  400. package/dist/chunk-LCU5U5IW.js.map +0 -1
  401. package/dist/chunk-LXY4BUA3.js.map +0 -1
  402. package/dist/chunk-MKLBK7HI.js.map +0 -1
  403. package/dist/chunk-O7VPNKYN.js.map +0 -1
  404. package/dist/chunk-OJ4N4T4H.js.map +0 -1
  405. package/dist/chunk-OKGUDNDT.js.map +0 -1
  406. package/dist/chunk-QCI6D7E4.js.map +0 -1
  407. package/dist/chunk-SZWRPEF7.js.map +0 -1
  408. package/dist/chunk-TTPSDC2G.js.map +0 -1
  409. package/dist/chunk-VOOI7B2L.js.map +0 -1
  410. package/dist/chunk-XBSQ4KMC.js.map +0 -1
  411. package/dist/connectors-SSOTIDHT.js +0 -45
  412. package/dist/library-publish-FGXF5TJO.js.map +0 -1
  413. package/dist/open-library-P3D337NH.js +0 -40
  414. package/dist/open-registry-Z3P2X2AB.js +0 -32
  415. package/dist/paths-JKEKXM52.js +0 -22
  416. package/dist/project-WFUDVYNN.js +0 -41
  417. package/dist/setup-RAMLTORM.js.map +0 -1
  418. package/dist/skills-EOHZ2DZ4.js +0 -26
  419. package/dist/source-FYVSFYEI.js +0 -41
@@ -1,29 +1,30 @@
1
1
  import { formatDroppedToolsNotice, filterInProcessMcpServerTools, checkToolPropertyKeys } from '../../chunk-X5O56UO4.js';
2
- import { scrubPoisonedTranscript, transcriptStoreForRuntime, resolveClaudeConfigDir, claudeEndpointMode, buildClaudeEndpointEnv } from '../../chunk-UX3K4RKE.js';
3
- import { scopeReconfigureModel } from '../../chunk-EINLFFP6.js';
4
- import { dispatchCapability } from '../../chunk-NARITJS2.js';
5
- import { fetchProviderModels } from '../../chunk-GWXFSLBK.js';
6
- import { AuthError, stripRunnerPrivateEnv, classifyClaudeSdkError, reclassifyAuthAsAccountUnavailable, AccountUnavailableError, isLongContextEntitlementRejection, LONG_CONTEXT_CREDITS_API_ERROR } from '../../chunk-XBSQ4KMC.js';
2
+ import { freshBudget, isFirstAttempt, spend, isSpent, decide, isAvailable } from '../../chunk-IZCR27MU.js';
3
+ import { AskSlots } from '../../chunk-EPBKISS5.js';
4
+ import { scrubPoisonedTranscript, transcriptStoreForRuntime, resolveClaudeConfigDir, claudeEndpointMode, buildClaudeEndpointEnv } from '../../chunk-S53LOR7B.js';
5
+ import { dispatchCapability } from '../../chunk-2H73V6XR.js';
6
+ import { fetchProviderModels } from '../../chunk-J7U3PIOE.js';
7
+ import { ReconfigureLedger, AuthError, stripRunnerPrivateEnv, classifyClaudeSdkError, reclassifyAuthAsAccountUnavailable, AccountUnavailableError, isLongContextEntitlementRejection, LONG_CONTEXT_CREDITS_API_ERROR } from '../../chunk-B4X2N7JQ.js';
7
8
  import { agentExecRequested, wrapAgentCommand, resolveAgentExec } from '../../chunk-YROR332M.js';
8
- import { BUILTIN_DRIVER_CATALOG, AgentDriver, getBridgeLogger, entryCredentialValue, registryDriverConfig } from '../../chunk-BTK7ECLH.js';
9
+ import { BUILTIN_DRIVER_CATALOG, AgentDriver, getBridgeLogger, entryCredentialValue, registryDriverConfig } from '../../chunk-5NNNV76P.js';
9
10
  import '../../chunk-6E6PKKAD.js';
10
- import { withActivityLabelShape } from '../../chunk-DMLDYFDS.js';
11
- import '../../chunk-FRHE7FFB.js';
12
- import '../../chunk-OOLT6HGP.js';
11
+ import { withActivityLabelShape } from '../../chunk-F4NJDSR7.js';
12
+ import '../../chunk-B6GIW55K.js';
13
+ import '../../chunk-36AFURKZ.js';
13
14
  import '../../chunk-4GY63JU6.js';
14
- import '../../chunk-SWO25LTO.js';
15
- import '../../chunk-G67BOI2J.js';
15
+ import '../../chunk-GB7WDMH2.js';
16
+ import '../../chunk-PMECEZK3.js';
16
17
  import '../../chunk-5BEFNLOR.js';
17
18
  import '../../chunk-A2ULN3KX.js';
18
- import '../../chunk-LCU5U5IW.js';
19
+ import '../../chunk-JAKOMFC6.js';
19
20
  import '../../chunk-L5VSIPQD.js';
20
21
  import '../../chunk-CPSIPIX7.js';
21
- import '../../chunk-RVIZQ5XD.js';
22
+ import '../../chunk-BTE2V4IW.js';
22
23
  import '../../chunk-RVRB27AN.js';
23
- import '../../chunk-TTPSDC2G.js';
24
- import '../../chunk-O7VPNKYN.js';
24
+ import '../../chunk-GTILM2CI.js';
25
+ import '../../chunk-QVNRCDTV.js';
25
26
  import '../../chunk-ICSCSM5D.js';
26
- import '../../chunk-JMKB7IB4.js';
27
+ import '../../chunk-UMVKJM4Q.js';
27
28
  import { mergeRegistries, parseModelRef, isEntryEnabled, resolveEntryBaseUrl } from '../../chunk-MJHSLODD.js';
28
29
  import '../../chunk-C3CAXQMA.js';
29
30
  import { createLogger } from '../../chunk-BOFL7GIF.js';
@@ -163,6 +164,71 @@ function sumBucket(items) {
163
164
  return { tokens: sumTokens(items), items };
164
165
  }
165
166
 
167
+ // bridge/src/drivers/claude-tool-allowlist.ts
168
+ var CAPABILITY_MCP_SERVER = "skaile-capabilities";
169
+ var CLAUDE_CODE_BUILTIN_TOOLS = /* @__PURE__ */ new Set([
170
+ "Agent",
171
+ "AskUserQuestion",
172
+ "Bash",
173
+ "BashOutput",
174
+ "Edit",
175
+ "EnterPlanMode",
176
+ "ExitPlanMode",
177
+ "Glob",
178
+ "Grep",
179
+ "KillShell",
180
+ "LS",
181
+ "ListMcpResourcesTool",
182
+ "Monitor",
183
+ "MultiEdit",
184
+ "NotebookEdit",
185
+ "NotebookRead",
186
+ "Read",
187
+ "ReadMcpResourceTool",
188
+ "Skill",
189
+ "SlashCommand",
190
+ "Task",
191
+ "TaskOutput",
192
+ "TaskStop",
193
+ "TodoWrite",
194
+ "ToolSearch",
195
+ "WebFetch",
196
+ "WebSearch",
197
+ "Write"
198
+ ]);
199
+ function mcpServerOf(name) {
200
+ if (!name.startsWith("mcp__")) return null;
201
+ const rest = name.slice("mcp__".length);
202
+ const sep = rest.indexOf("__");
203
+ if (sep <= 0 || sep + 2 >= rest.length) return null;
204
+ return { server: rest.slice(0, sep), tool: rest.slice(sep + 2) };
205
+ }
206
+ function canonicalToolName(entry, universe) {
207
+ return universe.capabilityNames.includes(entry) ? `mcp__${CAPABILITY_MCP_SERVER}__${entry}` : entry;
208
+ }
209
+ function unknownToolNames(allowlist, universe) {
210
+ const unknown = [];
211
+ for (const entry of allowlist) {
212
+ if (typeof entry !== "string" || !isKnownTool(entry, universe)) unknown.push(String(entry));
213
+ }
214
+ return unknown;
215
+ }
216
+ function isKnownTool(name, universe) {
217
+ if (CLAUDE_CODE_BUILTIN_TOOLS.has(name)) return true;
218
+ if (universe.capabilityNames.includes(name)) return true;
219
+ const mcp = mcpServerOf(name);
220
+ if (!mcp) return false;
221
+ if (mcp.server === CAPABILITY_MCP_SERVER) return universe.capabilityNames.includes(mcp.tool);
222
+ return universe.mcpServerNames.includes(mcp.server);
223
+ }
224
+ function toolAllowSet(allowlist, universe) {
225
+ return new Set(allowlist.map((entry) => canonicalToolName(entry, universe)));
226
+ }
227
+ function toolAllowlistDenial(toolName, allowed) {
228
+ if (!allowed || allowed.has(toolName)) return null;
229
+ return `The tool ${toolName} is not available in this turn. Answer with the tools you have.`;
230
+ }
231
+
166
232
  // bridge/src/drivers/sanitize-assistant-text.ts
167
233
  var NS = "(?:[a-z][a-z0-9]*:)?";
168
234
  var FUNCTION_CALL_BLOCK = new RegExp(
@@ -305,9 +371,6 @@ if (typeof globalThis.require === "undefined") {
305
371
  }
306
372
  }
307
373
  var LIVE_SET_MODEL_TIMEOUT_MS = 5e3;
308
- function freshRetryBudget() {
309
- return { staleResume: false, poison: false, auth: false, queryEnded: false, limit: false };
310
- }
311
374
  function isSeatCapacityFailure(detail, subtype) {
312
375
  if (detail.category !== "rate_limit") return false;
313
376
  if (subtype === "error_max_budget_usd") return false;
@@ -357,10 +420,6 @@ function apiErrorExcerpt(text) {
357
420
  ).replace(/\b(access_token|api_key|token|key|sig|signature)=[^\s&"]+/gi, "$1=[redacted]").replace(/\b(sk-ant-|sk-)[A-Za-z0-9_-]{6,}/g, "[redacted]").replace(/\beyJ[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+/g, "[redacted]");
358
421
  return masked.length > API_ERROR_EXCERPT_MAX ? `${masked.slice(0, API_ERROR_EXCERPT_MAX)}\u2026` : masked;
359
422
  }
360
- var STALE_RESUME_PATTERN = /No conversation found with session ID/i;
361
- function isPoisonedHistoryError(message) {
362
- return /invalid_request_error/i.test(message) && /media[_ ]?type|could not process image|image exceeds|cache_control/i.test(message);
363
- }
364
423
  function snapshotProcessEnv() {
365
424
  const env = {};
366
425
  for (const [k, v] of Object.entries(process.env)) {
@@ -559,10 +618,6 @@ var ClaudeSdkDriver = class extends AgentDriver {
559
618
  * {@link shouldRecycleQuery}; reset on every fresh spawn.
560
619
  */
561
620
  lastNumTurns = null;
562
- /** What the resident query runs; `null` until the first spawn. */
563
- liveQueryConfig = null;
564
- /** A config change the resident query cannot take live: respawn at the next turn. */
565
- recycleForConfig = false;
566
621
  /**
567
622
  * The capability tool set the resident query's `skaile-capabilities` server
568
623
  * was built from ({@link capabilityToolsKey}); `null` without capability hooks.
@@ -571,8 +626,8 @@ var ClaudeSdkDriver = class extends AgentDriver {
571
626
  * respawn rebuilds the server — see {@link capabilityToolsChanged}.
572
627
  */
573
628
  liveCapabilityToolsKey = null;
574
- /** In-flight {@link syncLiveQueryConfig} chain, so switches apply in order. */
575
- liveConfigSync = null;
629
+ /** Owns the desired config, drift and ordering of live reconfigures. */
630
+ reconfig;
576
631
  /** {@link LIVE_SET_MODEL_TIMEOUT_MS}, as a field so tests can shorten it. */
577
632
  setModelTimeoutMs = LIVE_SET_MODEL_TIMEOUT_MS;
578
633
  /**
@@ -592,6 +647,16 @@ var ClaudeSdkDriver = class extends AgentDriver {
592
647
  * the tail so one failed turn cannot wedge later callers.
593
648
  */
594
649
  promptTail = Promise.resolve();
650
+ /**
651
+ * Tools the running turn may call, or `null` when it is unrestricted. Set for
652
+ * the whole FIFO slot of a prompt that carried an allowlist, retries included.
653
+ */
654
+ turnToolAllowlist = null;
655
+ /**
656
+ * Subagents started under a restricted turn keep that turn's allowlist after
657
+ * it ends: a background subagent must not gain tools when its parent turn does.
658
+ */
659
+ subagentToolAllowlists = /* @__PURE__ */ new Map();
595
660
  /** Guards against duplicate agent_end emissions per turn. */
596
661
  turnCompleted = false;
597
662
  /** Set by {@link kill}: no turn may start or replay on this driver again. */
@@ -607,30 +672,24 @@ var ClaudeSdkDriver = class extends AgentDriver {
607
672
  */
608
673
  errorResultGraceTimer = null;
609
674
  /**
610
- * Mirror of the in-flight {@link prompt} call's auth retry budget: `false`
611
- * while the `onAuthError` self-heal is still available, `true` once it has
612
- * been spent. Read by {@link failTurn} to decide whether to defer the
613
- * `agent-event: error` emission for a self-healable auth error.
675
+ * The in-flight turn's recovery budget: which one-shot recoveries (stale
676
+ * resume, poison scrub, auth refresh, limit failover, query-ended replay) have
677
+ * been spent. Owned by the recovery policy; the single source for "was this
678
+ * kind already spent?" and "is it still available?".
614
679
  *
615
680
  * Set unconditionally at the top of every {@link runPrompt} attempt; never
616
- * reset elsewhere — the next call's set is the only legitimate transition.
681
+ * reset elsewhere — the next attempt's set is the only legitimate transition.
617
682
  */
618
- authSelfHealUsed = false;
683
+ recoveryBudget = freshBudget();
619
684
  /**
620
- * Mirror of the in-flight turn's seat-failover budget — same contract as
621
- * {@link authSelfHealUsed}, for the `onLimitBlocked` path.
685
+ * The recovery policy's answer for the failure that rejected this attempt,
686
+ * recorded where the failure was classified ({@link failTurn}, or the
687
+ * dispatch-failure site in {@link consumeMessages}). {@link failTurn} defers
688
+ * the error event on it and {@link runPrompt}'s catch carries it out — the
689
+ * policy is never consulted a second time for the same failure. `null` until
690
+ * a failure is recorded; cleared at every attempt start and turn end.
622
691
  */
623
- limitFailoverUsed = false;
624
- /**
625
- * Mirror of the in-flight turn's stale-resume retry budget — same contract as
626
- * {@link authSelfHealUsed}, for the "No conversation found" fresh-session retry.
627
- */
628
- staleResumeRetryUsed = false;
629
- /**
630
- * Mirror of the in-flight turn's poisoned-transcript scrub budget — same
631
- * contract as {@link authSelfHealUsed}.
632
- */
633
- poisonScrubUsed = false;
692
+ recoveryDecision = null;
634
693
  /**
635
694
  * Set when THIS attempt saw an upstream usage-limit rejection: either the
636
695
  * SDK's `rate_limit_event` telemetry with `status: "rejected"`, or an error
@@ -775,6 +834,13 @@ var ClaudeSdkDriver = class extends AgentDriver {
775
834
  constructor(config) {
776
835
  super();
777
836
  this.config = config;
837
+ this.reconfig = new ReconfigureLedger({
838
+ config: () => this.config,
839
+ isLive: () => this.query != null,
840
+ isIdle: () => !this.running,
841
+ applyLive: (delta, live) => this.applyLive(delta, live),
842
+ log: this.log
843
+ });
778
844
  }
779
845
  get runtimeSessionId() {
780
846
  return this.sessionId || void 0;
@@ -786,76 +852,35 @@ var ClaudeSdkDriver = class extends AgentDriver {
786
852
  * applies at the start of the next one, as omp does). A change it cannot take
787
853
  * live (thinking/effort, a model on another registry entry, a rejected or
788
854
  * timed-out `setModel`) recycles the query at the next turn boundary, so the
789
- * fresh CLI resumes with the new config.
855
+ * fresh CLI resumes with the new config. The {@link ReconfigureLedger} owns
856
+ * the scope rule, ordering and drift; {@link applyLive} is this driver's hook.
790
857
  */
791
858
  reconfigure(patch) {
792
- if (patch.model !== void 0) {
793
- const scope = scopeReconfigureModel({
794
- model: patch.model,
795
- modelRef: this.config.modelRef,
796
- registry: this.config.registry,
797
- roles: this.config.roles
798
- });
799
- if (scope.ok) {
800
- this.config.model = patch.model;
801
- if (scope.modelRef !== void 0) this.config.modelRef = scope.modelRef;
802
- } else {
803
- this.log.warn("model change refused; keeping the current model", {
804
- model: patch.model,
805
- providerId: scope.providerId
806
- });
807
- }
808
- }
809
- if (patch.thinking !== void 0) this.config.thinking = patch.thinking;
810
- if (patch.effort !== void 0) this.config.effort = patch.effort;
811
- if (this.query && !this.running) void this.syncLiveQueryConfig();
812
- }
813
- /** Whether the driver config moved away from what the resident query runs. */
814
- liveConfigDrifted() {
815
- const live = this.liveQueryConfig;
816
- if (!this.query || !live) return false;
817
- const { model, modelRef, thinking, effort } = this.config;
818
- return model !== live.model || modelRef !== live.modelRef || thinking !== live.thinking || effort !== live.effort;
819
- }
820
- /** Queue {@link applyConfigToLiveQuery} behind any switch still in flight. */
821
- syncLiveQueryConfig() {
822
- const next = (this.liveConfigSync ?? Promise.resolve()).then(
823
- () => this.applyConfigToLiveQuery()
824
- );
825
- this.liveConfigSync = next;
826
- void next.finally(() => {
827
- if (this.liveConfigSync === next) this.liveConfigSync = null;
828
- });
829
- return next;
859
+ return this.reconfig.reconfigure(patch);
830
860
  }
831
- /** Bring the resident query in line with the driver config. Never rejects. */
832
- async applyConfigToLiveQuery() {
861
+ /** Bring the resident query in line with a drifted config. Never rejects. */
862
+ async applyLive(delta, live) {
833
863
  const query = this.query;
834
- const live = this.liveQueryConfig;
835
- if (!query || !live || this.recycleForConfig || !this.liveConfigDrifted()) return;
836
- const { model, modelRef, thinking, effort } = this.config;
837
- const recycle = (reason, data = {}) => {
838
- this.recycleForConfig = true;
864
+ if (!query) return "respawn";
865
+ const respawn = (reason, data = {}) => {
839
866
  this.log.info("config change needs a fresh query; recycling at the next turn", {
840
867
  reason,
841
868
  ...data
842
869
  });
870
+ return "respawn";
843
871
  };
844
872
  try {
845
- if (thinking !== live.thinking || effort !== live.effort) {
846
- recycle("thinking_or_effort");
847
- return;
873
+ if (delta.thinking !== void 0 || delta.effort !== void 0) {
874
+ return respawn("thinking_or_effort");
848
875
  }
849
876
  const endpoint = this.resolveEndpoint();
850
877
  if (endpoint.providerId !== live.providerId) {
851
- recycle("provider_changed", { from: live.providerId, to: endpoint.providerId });
852
- return;
878
+ return respawn("provider_changed", { from: live.providerId, to: endpoint.providerId });
853
879
  }
854
- const providerModel = endpoint.model || model || "sonnet";
880
+ const providerModel = endpoint.model || this.config.model || "sonnet";
855
881
  if (providerModel !== live.providerModel) {
856
882
  if (this.inputStream == null || this.inputStream.ended || this.shouldRecycleQuery()) {
857
- recycle("query_due_for_recycle");
858
- return;
883
+ return respawn("query_due_for_recycle");
859
884
  }
860
885
  let timer;
861
886
  try {
@@ -871,17 +896,18 @@ var ClaudeSdkDriver = class extends AgentDriver {
871
896
  } finally {
872
897
  clearTimeout(timer);
873
898
  }
874
- if (this.query !== query) return;
899
+ if (this.query !== query) return "applied";
875
900
  this.log.info("switched the resident query's model", {
876
901
  from: live.providerModel,
877
902
  to: providerModel
878
903
  });
904
+ live.providerModel = providerModel;
879
905
  }
880
- Object.assign(live, { model, modelRef, providerModel });
906
+ return "applied";
881
907
  } catch (err) {
882
- if (this.query === query) {
883
- recycle("set_model_failed", { error: err instanceof Error ? err.message : String(err) });
884
- }
908
+ return respawn("set_model_failed", {
909
+ error: err instanceof Error ? err.message : String(err)
910
+ });
885
911
  }
886
912
  }
887
913
  getModel() {
@@ -919,8 +945,44 @@ var ClaudeSdkDriver = class extends AgentDriver {
919
945
  * occurs after a container crash that prevented the SDK from flushing its session file.
920
946
  */
921
947
  prompt(message) {
948
+ return this.enqueuePrompt(message, null);
949
+ }
950
+ /**
951
+ * Text plus an optional per-turn tool allowlist. An allowlist naming a tool
952
+ * this driver does not recognize is rejected before the turn is queued.
953
+ */
954
+ promptInput(input) {
955
+ if (input.attachments?.length) return Promise.reject(new Error("Structured input unsupported"));
956
+ if (input.toolAllowlist === void 0) return this.prompt(input.text);
957
+ if (!Array.isArray(input.toolAllowlist))
958
+ return Promise.reject(new Error("toolAllowlist must be an array of tool names"));
959
+ const unknown = this.unknownAllowlistedTools(input.toolAllowlist);
960
+ if (unknown.length > 0)
961
+ return Promise.reject(new Error(`Unknown tool(s) in toolAllowlist: ${unknown.join(", ")}`));
962
+ return this.enqueuePrompt(input.text, toolAllowSet(input.toolAllowlist, this.toolUniverse()));
963
+ }
964
+ get enforcesToolAllowlist() {
965
+ return true;
966
+ }
967
+ unknownAllowlistedTools(allowlist) {
968
+ return unknownToolNames(allowlist, this.toolUniverse());
969
+ }
970
+ toolUniverse() {
971
+ return {
972
+ capabilityNames: this.config.capabilities?.composeTools().map((tool) => tool.name) ?? [],
973
+ mcpServerNames: Object.keys(this.config.mcpServers ?? {})
974
+ };
975
+ }
976
+ enqueuePrompt(message, allowlist) {
922
977
  this.supersedePendingQuestion();
923
- const queuedPrompt = this.promptTail.then(() => this.runPrompt(message, freshRetryBudget()));
978
+ const queuedPrompt = this.promptTail.then(async () => {
979
+ this.turnToolAllowlist = allowlist;
980
+ try {
981
+ await this.runPrompt(message, freshBudget());
982
+ } finally {
983
+ this.turnToolAllowlist = null;
984
+ }
985
+ });
924
986
  this.promptTail = queuedPrompt.then(
925
987
  () => void 0,
926
988
  () => void 0
@@ -933,13 +995,11 @@ var ClaudeSdkDriver = class extends AgentDriver {
933
995
  * Retries recurse here rather than through {@link prompt}, so they cannot
934
996
  * enqueue behind themselves and deadlock.
935
997
  */
936
- async runPrompt(message, _budget) {
998
+ async runPrompt(message, budget) {
937
999
  if (this.killed) throw new Error(KILLED_TURN_MESSAGE);
938
1000
  if (!this.sdk) await this.start();
939
- this.authSelfHealUsed = _budget.auth;
940
- this.limitFailoverUsed = _budget.limit;
941
- this.staleResumeRetryUsed = _budget.staleResume;
942
- this.poisonScrubUsed = _budget.poison;
1001
+ this.recoveryBudget = budget;
1002
+ this.recoveryDecision = null;
943
1003
  this.limitRejectionSeen = false;
944
1004
  this.limitTurnRejectedForFailover = false;
945
1005
  this.providerResponseReported = false;
@@ -948,8 +1008,8 @@ var ClaudeSdkDriver = class extends AgentDriver {
948
1008
  this.deferredTurnError = null;
949
1009
  this.heldFailoverResult = null;
950
1010
  let retrying = false;
951
- const isFirstAttempt = !_budget.staleResume && !_budget.poison && !_budget.auth && !_budget.queryEnded && !_budget.limit;
952
- if (isFirstAttempt) {
1011
+ const isFirstAttempt2 = isFirstAttempt(budget);
1012
+ if (isFirstAttempt2) {
953
1013
  this._lastTokens = null;
954
1014
  this._lastContextTokens = null;
955
1015
  this._lastModelUsage = null;
@@ -963,8 +1023,8 @@ var ClaudeSdkDriver = class extends AgentDriver {
963
1023
  this.lastApiErrorRender = null;
964
1024
  this.turnCompleted = false;
965
1025
  this.disarmErrorResultGrace();
966
- if (this.liveConfigSync || this.liveConfigDrifted()) await this.syncLiveQueryConfig();
967
- if (this.query && (this.inputStream == null || this.inputStream.ended || this.recycleForConfig || this.shouldRecycleQuery() || this.capabilityToolsChanged())) {
1026
+ await this.reconfig.flushBeforeTurn();
1027
+ if (this.query && (this.inputStream == null || this.inputStream.ended || this.reconfig.needsRespawn || this.shouldRecycleQuery() || this.capabilityToolsChanged())) {
968
1028
  this.recycleQueryForNextTurn();
969
1029
  }
970
1030
  const turnPromise = new Promise((resolve, reject) => {
@@ -989,35 +1049,33 @@ var ClaudeSdkDriver = class extends AgentDriver {
989
1049
  await turnPromise;
990
1050
  } catch (err) {
991
1051
  if (this.killed) throw err;
992
- if (!_budget.queryEnded && err instanceof QueryEndedBeforeTurnError) {
1052
+ const decision = this.recoveryDecision;
1053
+ const attempt = decision && "attempt" in decision ? decision.attempt : null;
1054
+ if (attempt === "query_ended_replay") {
993
1055
  this.log.warn("turn was enqueued into an ending query; replaying on a fresh one");
994
1056
  this.retractUnfinishedText();
995
1057
  retrying = true;
996
- return this.runPrompt(message, { ..._budget, queryEnded: true });
1058
+ return this.runPrompt(message, spend(budget, attempt));
997
1059
  }
998
- const errMsg = err instanceof Error ? err.message : String(err);
999
- const isStaleResume = !_budget.staleResume && STALE_RESUME_PATTERN.test(errMsg);
1000
- if (isStaleResume) {
1060
+ if (attempt === "stale_resume") {
1001
1061
  this.prepareStaleResumeRetry();
1002
1062
  retrying = true;
1003
- return this.runPrompt(message, { ..._budget, staleResume: true });
1063
+ return this.runPrompt(message, spend(budget, attempt));
1004
1064
  }
1005
- const isPoisonedHistory = !_budget.poison && isPoisonedHistoryError(errMsg);
1006
- const poisonSessionId = this.config.resumeSessionId || this.sessionId;
1007
- if (isPoisonedHistory && poisonSessionId) {
1008
- if (await this.attemptPoisonScrubRetry(poisonSessionId)) {
1065
+ if (attempt === "poison_scrub") {
1066
+ const poisonSessionId = this.config.resumeSessionId || this.sessionId;
1067
+ if (poisonSessionId && await this.attemptPoisonScrubRetry(poisonSessionId)) {
1009
1068
  retrying = true;
1010
- return this.runPrompt(message, { ..._budget, poison: true });
1069
+ return this.runPrompt(message, spend(budget, attempt));
1011
1070
  }
1012
1071
  }
1013
- const authOwns = err instanceof AuthError && !_budget.auth && this.config.onAuthError != null;
1014
- if (authOwns) {
1072
+ if (attempt === "auth_refresh" && err instanceof AuthError) {
1015
1073
  if (await this.attemptAuthSelfHeal(err)) {
1016
1074
  this.retractUnfinishedText();
1017
1075
  retrying = true;
1018
- return this.runPrompt(message, { ..._budget, auth: true });
1076
+ return this.runPrompt(message, spend(budget, attempt));
1019
1077
  }
1020
- } else if (!_budget.limit && this.limitRejectionSeen && this.config.onLimitBlocked) {
1078
+ } else if (attempt === "limit_failover") {
1021
1079
  if (await this.attemptLimitFailover(err)) {
1022
1080
  if (this.abortController?.signal.aborted) {
1023
1081
  this.log.info("aborted during the seat failover; not replaying the prompt");
@@ -1030,7 +1088,7 @@ var ClaudeSdkDriver = class extends AgentDriver {
1030
1088
  this.heldFailoverResult = null;
1031
1089
  this.retractUnfinishedText();
1032
1090
  retrying = true;
1033
- return this.runPrompt(message, { ..._budget, limit: true });
1091
+ return this.runPrompt(message, spend(budget, attempt));
1034
1092
  }
1035
1093
  if (this.limitTurnRejectedForFailover) {
1036
1094
  this.emitAgentEnd();
@@ -1050,6 +1108,7 @@ var ClaudeSdkDriver = class extends AgentDriver {
1050
1108
  this.limitTurnRejectedForFailover = false;
1051
1109
  this.lastLimitInfo = null;
1052
1110
  this.deferredTurnError = null;
1111
+ this.recoveryDecision = null;
1053
1112
  this.heldFailoverResult = null;
1054
1113
  this.failoverUsageCarry = null;
1055
1114
  this.suppressedAuthRenderText = null;
@@ -1686,7 +1745,13 @@ var ClaudeSdkDriver = class extends AgentDriver {
1686
1745
  ...this.config.thinking ? { thinking: this.mapThinkingConfig(this.config.thinking) } : {},
1687
1746
  // Reasoning effort — passed directly to the SDK
1688
1747
  ...this.config.effort ? { effort: this.config.effort } : {},
1689
- hooks: {},
1748
+ // The per-turn tool allowlist: hooks fire for every call, subagents'
1749
+ // included, under bypassPermissions, and read the turn's state live.
1750
+ hooks: {
1751
+ PreToolUse: [{ hooks: [this.handlePreToolUse] }],
1752
+ SubagentStart: [{ hooks: [this.handleSubagentStart] }],
1753
+ SubagentStop: [{ hooks: [this.handleSubagentStop] }]
1754
+ },
1690
1755
  stderr: onStderr,
1691
1756
  // Spawn the CLI ourselves to capture its OS pid for snapshotDescendantPids()
1692
1757
  // (Query never exposes it otherwise). This replaces the SDK's own default
@@ -1788,12 +1853,11 @@ var ClaudeSdkDriver = class extends AgentDriver {
1788
1853
  };
1789
1854
  if (apiKey) queryArgs.apiKey = apiKey;
1790
1855
  this.query = query(queryArgs);
1791
- this.recycleForConfig = false;
1792
- this.liveQueryConfig = {
1856
+ this.reconfig.setSnapshot({
1793
1857
  ...spawnConfig,
1794
1858
  providerId: endpoint.providerId,
1795
1859
  providerModel: String(options.model)
1796
- };
1860
+ });
1797
1861
  this.consumeMessages().catch((err) => {
1798
1862
  this.log.error("message loop terminated unexpectedly", err);
1799
1863
  });
@@ -1813,6 +1877,8 @@ var ClaudeSdkDriver = class extends AgentDriver {
1813
1877
  * `options.canUseTool` by value.
1814
1878
  */
1815
1879
  handleCanUseTool = (toolName, input, opts) => {
1880
+ const denial = this.toolAllowlistDenialFor(toolName, opts.agentID);
1881
+ if (denial) return Promise.resolve({ behavior: "deny", message: denial });
1816
1882
  if (toolName !== "AskUserQuestion") {
1817
1883
  return Promise.resolve({ behavior: "allow", updatedInput: input });
1818
1884
  }
@@ -1829,6 +1895,7 @@ var ClaudeSdkDriver = class extends AgentDriver {
1829
1895
  resolve,
1830
1896
  originalInput: input,
1831
1897
  questionTexts,
1898
+ slots: new AskSlots(questionTexts),
1832
1899
  answers: {}
1833
1900
  };
1834
1901
  opts.signal.addEventListener(
@@ -1839,6 +1906,42 @@ var ClaudeSdkDriver = class extends AgentDriver {
1839
1906
  this.log.debug("paused on AskUserQuestion", { questions: questionTexts.length });
1840
1907
  });
1841
1908
  };
1909
+ /**
1910
+ * Denial reason when the per-turn allowlist forbids `toolName`, else `null`.
1911
+ * A subagent seen under a restricted turn is bound to that turn's allowlist
1912
+ * for its whole life.
1913
+ */
1914
+ toolAllowlistDenialFor(toolName, agentId) {
1915
+ if (agentId !== void 0 && this.turnToolAllowlist && !this.subagentToolAllowlists.has(agentId))
1916
+ this.subagentToolAllowlists.set(agentId, this.turnToolAllowlist);
1917
+ const allowed = (agentId !== void 0 ? this.subagentToolAllowlists.get(agentId) : void 0) ?? this.turnToolAllowlist;
1918
+ return toolAllowlistDenial(toolName, allowed);
1919
+ }
1920
+ /** `PreToolUse` hook: deny a call outside the turn's allowlist. */
1921
+ handlePreToolUse = async (input) => {
1922
+ if (input.hook_event_name !== "PreToolUse") return {};
1923
+ const denial = this.toolAllowlistDenialFor(input.tool_name, input.agent_id);
1924
+ if (!denial) return {};
1925
+ this.log.info("tool call refused by the turn's allowlist", { tool: input.tool_name });
1926
+ return {
1927
+ hookSpecificOutput: {
1928
+ hookEventName: "PreToolUse",
1929
+ permissionDecision: "deny",
1930
+ permissionDecisionReason: denial
1931
+ }
1932
+ };
1933
+ };
1934
+ /** `SubagentStart` hook: bind a subagent started under a restricted turn to its allowlist. */
1935
+ handleSubagentStart = async (input) => {
1936
+ if (input.hook_event_name === "SubagentStart" && this.turnToolAllowlist)
1937
+ this.subagentToolAllowlists.set(input.agent_id, this.turnToolAllowlist);
1938
+ return {};
1939
+ };
1940
+ handleSubagentStop = async (input) => {
1941
+ if (input.hook_event_name === "SubagentStop")
1942
+ this.subagentToolAllowlists.delete(input.agent_id);
1943
+ return {};
1944
+ };
1842
1945
  supersedePendingQuestion() {
1843
1946
  this.denyPendingQuestion(QUESTION_SUPERSEDED_BY_PROMPT);
1844
1947
  }
@@ -1848,11 +1951,11 @@ var ClaudeSdkDriver = class extends AgentDriver {
1848
1951
  answerQuestion(answer, question) {
1849
1952
  const pending = this.pendingQuestion;
1850
1953
  if (!pending) return false;
1851
- const key = question !== void 0 && pending.questionTexts.includes(question) ? question : pending.questionTexts.find((q) => !Object.hasOwn(pending.answers, q));
1852
- if (key !== void 0) {
1853
- pending.answers[key] = answer;
1954
+ const { slot, complete } = pending.slots.answer(question);
1955
+ if (slot !== void 0) {
1956
+ pending.answers[slot] = answer;
1854
1957
  }
1855
- if (pending.questionTexts.every((q) => Object.hasOwn(pending.answers, q))) {
1958
+ if (complete) {
1856
1959
  this.pendingQuestion = null;
1857
1960
  this.lastSdkMessageAt = Date.now();
1858
1961
  pending.resolve({
@@ -2064,11 +2167,11 @@ var ClaudeSdkDriver = class extends AgentDriver {
2064
2167
  this.endInputStream();
2065
2168
  const neverDispatched = !this.turnCompleted && this.turnReject != null && !this.firstSdkMessageSeen && !this.abortController?.signal.aborted;
2066
2169
  if (neverDispatched) {
2067
- this.rejectTurnSilently(
2068
- new QueryEndedBeforeTurnError(
2069
- "The model process ended before this turn was dispatched."
2070
- )
2170
+ const neverDispatchedErr = new QueryEndedBeforeTurnError(
2171
+ "The model process ended before this turn was dispatched."
2071
2172
  );
2173
+ this.recoveryDecision = this.decideRecovery(neverDispatchedErr);
2174
+ this.rejectTurnSilently(neverDispatchedErr);
2072
2175
  } else {
2073
2176
  this.completeTurn();
2074
2177
  }
@@ -2101,7 +2204,7 @@ var ClaudeSdkDriver = class extends AgentDriver {
2101
2204
  errors: [error.message],
2102
2205
  oauthCredential: this.usingOauthCredential
2103
2206
  });
2104
- const detail = rawDetail.category === "auth" && this.authSelfHealUsed ? reclassifyAuthAsAccountUnavailable(rawDetail) : rawDetail;
2207
+ const detail = rawDetail.category === "auth" && isSpent(this.recoveryBudget, "auth_refresh") ? reclassifyAuthAsAccountUnavailable(rawDetail) : rawDetail;
2105
2208
  this.log.error("consumer error", {
2106
2209
  message: error.message,
2107
2210
  category: detail.category,
@@ -2192,13 +2295,15 @@ var ClaudeSdkDriver = class extends AgentDriver {
2192
2295
  * caller transitions even if the listener chain misbehaves; the emit is
2193
2296
  * wrapped in try/catch so a listener failure cannot leak out.
2194
2297
  *
2195
- * Self-heal deferral: when the failure is an {@link AuthError} and the auth
2196
- * self-heal budget is still available (`!authSelfHealUsed`) AND the caller
2197
- * wired an `onAuthError` callback, the downstream `agent-event: error`
2198
- * emission is deferred. The rejected turn promise still travels to
2199
- * {@link prompt}'s catch block where the self-heal runs; if the retry
2200
- * succeeds the user never sees a 401, if the retry fails the second
2201
- * `failTurn` call (now with `authSelfHealUsed === true`) emits the error
2298
+ * Recovery deferral: the recovery policy is asked ONCE per failure
2299
+ * ({@link decideRecovery}) — unless the caller already decided and passes its
2300
+ * answer as `decided` — and the answer is recorded on the turn. When it names
2301
+ * an attempt, the downstream `agent-event: error` emission is deferred: the
2302
+ * rejected turn promise still travels to {@link runPrompt}'s catch, which
2303
+ * carries out that recorded attempt. If the attempt succeeds the user never
2304
+ * sees the failure (a 401 self-heal, a seat switch, a stale-resume replay);
2305
+ * if it declines, the catch emits the held-back error exactly once. A retry
2306
+ * that fails again is decided afresh against the spent budget, so it emits
2202
2307
  * normally. This stops the historical "401 flashes in the UI even though
2203
2308
  * self-heal worked" misbehaviour where the bridge emitted the error event
2204
2309
  * before the retry decision was known.
@@ -2207,7 +2312,7 @@ var ClaudeSdkDriver = class extends AgentDriver {
2207
2312
  * § "Runner-side handling on 401" (the AI 401 mediation path that
2208
2313
  * exposed this hang).
2209
2314
  */
2210
- failTurn(err, detail) {
2315
+ failTurn(err, detail, decided) {
2211
2316
  this.disarmTurnStallWatchdog();
2212
2317
  this.disarmErrorResultGrace();
2213
2318
  const hadPendingTurn = this.turnReject != null;
@@ -2222,54 +2327,43 @@ var ClaudeSdkDriver = class extends AgentDriver {
2222
2327
  error: err.message,
2223
2328
  ...detail ? { detail } : {}
2224
2329
  };
2225
- const willSelfHeal = err instanceof AuthError && !this.authSelfHealUsed && this.config.onAuthError != null;
2226
- if (hadPendingTurn && willSelfHeal) {
2227
- this.log.info("deferring auth-error event; self-heal will attempt refresh");
2228
- this.deferredTurnError = event;
2229
- return;
2230
- }
2231
- if (hadPendingTurn && this.willRetryStaleResume(err.message)) {
2232
- this.log.info("deferring stale-resume error event; retrying on a fresh session");
2233
- this.deferredTurnError = event;
2234
- return;
2235
- }
2236
- if (hadPendingTurn && this.willFailoverOnLimit()) {
2237
- this.log.info("deferring limit error event; seat failover will be attempted");
2238
- this.deferredTurnError = event;
2239
- return;
2240
- }
2241
- if (hadPendingTurn && this.willAttemptPoisonScrub(err.message)) {
2242
- this.log.info("deferring poisoned-history error event; a transcript scrub will be attempted");
2243
- this.deferredTurnError = event;
2244
- return;
2330
+ if (hadPendingTurn) {
2331
+ const decision = decided ?? this.decideRecovery(err);
2332
+ this.recoveryDecision = decision;
2333
+ if ("attempt" in decision) {
2334
+ this.log.info("deferring turn error event; recovery attempt pending", {
2335
+ attempt: decision.attempt
2336
+ });
2337
+ this.deferredTurnError = event;
2338
+ return;
2339
+ }
2245
2340
  }
2246
2341
  this.emitTurnErrorEvent(event);
2247
2342
  }
2248
2343
  /**
2249
- * Whether a usage-limit block on the current attempt still has a seat
2250
- * failover available. Evaluated identically by {@link failTurn} (to decide
2251
- * whether to withhold the error event) and by {@link handleResultErrorPayload}
2252
- * (to decide whether to reject the turn at all) — one predicate so the two
2253
- * can never disagree and strand a deferred event.
2344
+ * Ask the recovery policy what to do about `err`. Called once per failure, by
2345
+ * the code that classifies it; the answer is recorded in
2346
+ * {@link recoveryDecision} and acted on by {@link runPrompt}'s catch.
2254
2347
  */
2255
- willFailoverOnLimit() {
2256
- return this.limitRejectionSeen && !this.limitFailoverUsed && this.config.onLimitBlocked != null;
2257
- }
2258
- /**
2259
- * Whether `message` is a lost-transcript resume failure that `runPrompt` will
2260
- * still retry on a fresh session. The same test `runPrompt`'s catch applies,
2261
- * so a deferred error is always followed by the retry that drops it.
2262
- */
2263
- willRetryStaleResume(message) {
2264
- return !this.staleResumeRetryUsed && STALE_RESUME_PATTERN.test(message);
2348
+ decideRecovery(err) {
2349
+ return decide(
2350
+ {
2351
+ message: err.message,
2352
+ authError: err instanceof AuthError,
2353
+ limitRejected: this.limitRejectionSeen,
2354
+ queryEnded: err instanceof QueryEndedBeforeTurnError
2355
+ },
2356
+ this.recoveryBudget,
2357
+ this.recoveryWiring()
2358
+ );
2265
2359
  }
2266
- /**
2267
- * Whether `runPrompt`'s catch will attempt a transcript scrub for `message`.
2268
- * The scrub may still find nothing, so unlike {@link willRetryStaleResume}
2269
- * the deferred error is not always dropped: `runPrompt` flushes it then.
2270
- */
2271
- willAttemptPoisonScrub(message) {
2272
- return !this.poisonScrubUsed && isPoisonedHistoryError(message) && Boolean(this.config.resumeSessionId || this.sessionId);
2360
+ /** Which host callbacks and session state a recovery could use right now. */
2361
+ recoveryWiring() {
2362
+ return {
2363
+ onAuthError: this.config.onAuthError != null,
2364
+ onLimitBlocked: this.config.onLimitBlocked != null,
2365
+ resumableSessionId: Boolean(this.config.resumeSessionId || this.sessionId)
2366
+ };
2273
2367
  }
2274
2368
  /** Emit one `agent-event: error`, swallowing a throwing listener. */
2275
2369
  emitTurnErrorEvent(event) {
@@ -2532,12 +2626,7 @@ var ClaudeSdkDriver = class extends AgentDriver {
2532
2626
  * why that is forced: `_devlog/notes/2026-06-08-auth-error-text-suppress.md`.
2533
2627
  */
2534
2628
  isSuppressibleAuthRenderText(text) {
2535
- if (!this.authSelfHealAvailable()) return false;
2536
- return this.textIsAuthRender(text) && isCliAuthRenderText(text);
2537
- }
2538
- /** Whether a 401 on this attempt can still be self-healed and retried. */
2539
- authSelfHealAvailable() {
2540
- return !this.authSelfHealUsed && this.config.onAuthError != null;
2629
+ return this.textIsAuthRender(text) && isCliAuthRenderText(text) && isAvailable(this.recoveryBudget, "auth_refresh", this.recoveryWiring());
2541
2630
  }
2542
2631
  /**
2543
2632
  * Stash a dropped auth render as evidence for {@link handleResultErrorPayload}.
@@ -2550,7 +2639,7 @@ var ClaudeSdkDriver = class extends AgentDriver {
2550
2639
  * qualifies; requiring a marker only the CLI itself emits keeps that prose out.
2551
2640
  */
2552
2641
  stashSuppressedAuthRender(text) {
2553
- if (!this.authSelfHealAvailable()) return;
2642
+ if (!isAvailable(this.recoveryBudget, "auth_refresh", this.recoveryWiring())) return;
2554
2643
  if (!isCliAuthRenderText(text)) return;
2555
2644
  this.suppressedAuthRenderText = text;
2556
2645
  }
@@ -2752,7 +2841,7 @@ var ClaudeSdkDriver = class extends AgentDriver {
2752
2841
  subtype: msg.subtype,
2753
2842
  oauthCredential: this.usingOauthCredential
2754
2843
  });
2755
- const detail = rawDetail.category === "auth" && this.authSelfHealUsed ? reclassifyAuthAsAccountUnavailable(rawDetail) : rawDetail;
2844
+ const detail = rawDetail.category === "auth" && isSpent(this.recoveryBudget, "auth_refresh") ? reclassifyAuthAsAccountUnavailable(rawDetail) : rawDetail;
2756
2845
  this.log.error("turn ended with error", {
2757
2846
  subtype: msg.subtype,
2758
2847
  terminalReason: msg.terminal_reason,
@@ -2775,7 +2864,9 @@ var ClaudeSdkDriver = class extends AgentDriver {
2775
2864
  });
2776
2865
  }
2777
2866
  const errorText = effectiveErrors.join("; ") || `Agent stopped: ${msg.subtype}`;
2778
- if (this.turnReject != null && this.willRetryStaleResume(errorText)) {
2867
+ const failure = detail.category === "auth" ? new AuthError({ ...detail, message: errorText }) : detail.category === "account" ? new AccountUnavailableError({ ...detail, message: errorText }) : new Error(errorText);
2868
+ const decision = this.decideRecovery(failure);
2869
+ if (this.turnReject != null && "attempt" in decision && decision.attempt === "stale_resume") {
2779
2870
  const detached = this.query;
2780
2871
  this.query = null;
2781
2872
  this.endInputStream();
@@ -2783,16 +2874,14 @@ var ClaudeSdkDriver = class extends AgentDriver {
2783
2874
  detached?.close();
2784
2875
  } catch {
2785
2876
  }
2786
- this.failTurn(new Error(errorText), detail);
2877
+ this.failTurn(new Error(errorText), detail, decision);
2787
2878
  return true;
2788
2879
  }
2789
- if (detail.category === "auth") {
2790
- this.failTurn(new AuthError({ ...detail, message: errorText }), detail);
2791
- } else if (detail.category === "account") {
2792
- this.failTurn(new AccountUnavailableError({ ...detail, message: errorText }), detail);
2793
- } else if (this.willFailoverOnLimit()) {
2880
+ if (detail.category === "auth" || detail.category === "account") {
2881
+ this.failTurn(failure, detail, decision);
2882
+ } else if ("attempt" in decision && decision.attempt === "limit_failover") {
2794
2883
  this.limitTurnRejectedForFailover = true;
2795
- this.failTurn(new Error(errorText), detail);
2884
+ this.failTurn(failure, detail, decision);
2796
2885
  } else if (errors.length > 0) {
2797
2886
  this.emit("agent-event", {
2798
2887
  type: "error",