@qwen-code/qwen-code 0.21.7 → 0.21.8-nightly.20260810.55e20db328

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 (334) hide show
  1. package/README.md +2 -0
  2. package/bundled/qc-helper/docs/configuration/settings.md +73 -59
  3. package/bundled/qc-helper/docs/extension/introduction.md +15 -1
  4. package/bundled/qc-helper/docs/features/channels/dingtalk.md +40 -2
  5. package/bundled/qc-helper/docs/features/channels/feishu.md +13 -2
  6. package/bundled/qc-helper/docs/features/channels/github.md +13 -11
  7. package/bundled/qc-helper/docs/features/channels/gitlab.md +13 -11
  8. package/bundled/qc-helper/docs/features/channels/overview.md +49 -31
  9. package/bundled/qc-helper/docs/features/channels/plugins.md +2 -2
  10. package/bundled/qc-helper/docs/features/channels/qqbot.md +4 -2
  11. package/bundled/qc-helper/docs/features/channels/telegram.md +4 -2
  12. package/bundled/qc-helper/docs/features/channels/wecom.md +1 -1
  13. package/bundled/qc-helper/docs/features/code-review.md +4 -0
  14. package/bundled/qc-helper/docs/features/commands.md +1 -1
  15. package/bundled/qc-helper/docs/features/hooks.md +52 -0
  16. package/bundled/qc-helper/docs/integration-jetbrains.md +1 -0
  17. package/bundled/qc-helper/docs/qwen-serve-deploy-local.md +1 -1
  18. package/bundled/qc-helper/docs/qwen-serve.md +10 -5
  19. package/bundled/qc-helper/docs/reference/keyboard-shortcuts.md +50 -36
  20. package/bundled/review/SKILL.md +32 -5
  21. package/chunks/{MaxSizedBox-ANWZBPTS.js → MaxSizedBox-A52T4GEU.js} +29 -25
  22. package/chunks/{StandaloneSessionPicker-XKS3VU3A.js → StandaloneSessionPicker-4J654SOB.js} +48 -44
  23. package/chunks/{acp-startup-profiler-ORIQ2CCQ.js → acp-startup-profiler-B5BYAMYQ.js} +2 -2
  24. package/chunks/{acpAgent-KUAZ3GCZ.js → acpAgent-65AM4AOR.js} +1833 -843
  25. package/chunks/{agent-T6PTGX5R.js → agent-SVQ7U7NJ.js} +28 -24
  26. package/chunks/{agent-headless-PR7YCB7S.js → agent-headless-XXGY2SQO.js} +28 -24
  27. package/chunks/{artifact-tool-U4VOZIK5.js → artifact-tool-N652YE4L.js} +1 -1
  28. package/chunks/{askUserQuestion-XOBQLPFA.js → askUserQuestion-ONW74PKJ.js} +1 -1
  29. package/chunks/{bridge-NU6YEEHK.js → bridge-Y32B5S3G.js} +34 -30
  30. package/chunks/{ca-NYKNH222.js → ca-ZLKAB4K3.js} +6 -0
  31. package/chunks/{channel-management-service-FSQ7SHYI.js → channel-management-service-PHELKOW2.js} +19 -10
  32. package/chunks/{channel-settings-store-35VQVUVV.js → channel-settings-store-OW43U6VB.js} +36 -32
  33. package/chunks/{channel-worker-group-JWQK224X.js → channel-worker-group-MSHT6CWR.js} +7 -7
  34. package/chunks/{channel-worker-manager-77E3OXRQ.js → channel-worker-manager-XXD3GDSK.js} +7 -7
  35. package/chunks/{channel-worker-supervisor-62YWUGP2.js → channel-worker-supervisor-IVSDIMI4.js} +4 -4
  36. package/chunks/{chunk-HYRDKNUY.js → chunk-2545EHZR.js} +1 -1
  37. package/chunks/{chunk-SPMY6CX6.js → chunk-2ASQDZSJ.js} +3 -3
  38. package/chunks/{chunk-CJXIIILK.js → chunk-2FRY5CRX.js} +1 -1
  39. package/chunks/{chunk-CNIID3TV.js → chunk-2UUMVNYT.js} +1 -1
  40. package/chunks/{chunk-KXSDEOFU.js → chunk-3KJQZEN3.js} +1 -1
  41. package/chunks/{chunk-22NBYCPD.js → chunk-3P2LV43B.js} +1 -1
  42. package/chunks/{chunk-Y7E5LNLO.js → chunk-47ZUMGGY.js} +2634 -2114
  43. package/chunks/{chunk-LA7YLSR6.js → chunk-4EOURKA4.js} +839 -153
  44. package/chunks/chunk-4JRM2BSM.js +48 -0
  45. package/chunks/{chunk-BGG4MBYD.js → chunk-4PYCZH2V.js} +4 -187
  46. package/chunks/{chunk-L4N6TIP7.js → chunk-4TRQPFDP.js} +4 -2
  47. package/chunks/{chunk-6XJMFJ4D.js → chunk-5WZL724W.js} +177 -120
  48. package/chunks/{chunk-23RZCH76.js → chunk-5ZTS3OQ3.js} +3 -3
  49. package/chunks/{chunk-VWOVHOTT.js → chunk-67EWJE77.js} +1 -1
  50. package/chunks/{chunk-3K7FH2KQ.js → chunk-67N6HB5H.js} +1310 -171
  51. package/chunks/{chunk-CXE7E23H.js → chunk-6Q5ABMTU.js} +45 -17
  52. package/chunks/{chunk-NG2R4N5O.js → chunk-6ZRFAKXK.js} +1 -1
  53. package/chunks/{chunk-RERATVSK.js → chunk-7XX5IBXL.js} +145 -10
  54. package/chunks/{chunk-S7CV4KO6.js → chunk-AKJQSWV4.js} +4 -4
  55. package/chunks/{chunk-5KH532V7.js → chunk-AUWN7BAG.js} +1 -1
  56. package/chunks/{chunk-DBOFL3LQ.js → chunk-BL65MO72.js} +10 -10
  57. package/chunks/{chunk-AKA24BGO.js → chunk-BT6GQIEJ.js} +1 -1
  58. package/chunks/{chunk-W7U4ESW2.js → chunk-CG3WBKJK.js} +1 -1
  59. package/chunks/{chunk-2M5N3DHY.js → chunk-CMOBWHWW.js} +1 -1
  60. package/chunks/chunk-COBO5EBO.js +135 -0
  61. package/chunks/chunk-CPG6P4GG.js +82 -0
  62. package/chunks/{chunk-3NB7TSE2.js → chunk-D2D7J3EW.js} +1 -1
  63. package/chunks/{chunk-NLREQJFK.js → chunk-DA4HRSBW.js} +15 -0
  64. package/chunks/{chunk-RNVQB725.js → chunk-DPMJLKUP.js} +2 -2
  65. package/chunks/{chunk-DIEFUBV6.js → chunk-DX3RGJMS.js} +218 -37
  66. package/chunks/{chunk-33ACCIIY.js → chunk-DZUO626D.js} +1 -1
  67. package/chunks/chunk-E2FPSSKP.js +244 -0
  68. package/chunks/{chunk-72LNFGUY.js → chunk-E2N554HK.js} +3 -3
  69. package/chunks/{chunk-6EOI4HOK.js → chunk-E2T7FLDU.js} +12 -17
  70. package/chunks/{chunk-EUQTXRKZ.js → chunk-EISUQQPS.js} +6 -6
  71. package/chunks/{chunk-H2UQ2M5Z.js → chunk-EUVOKP6Y.js} +96 -22
  72. package/chunks/{chunk-RMH5OWLD.js → chunk-F3II4BTZ.js} +1 -1
  73. package/chunks/{chunk-P3LEG54R.js → chunk-F6TUUA2U.js} +3 -3
  74. package/chunks/chunk-F6WFNA7U.js +22 -0
  75. package/chunks/{chunk-RZHU3ILK.js → chunk-FAD7OC7V.js} +4 -4
  76. package/chunks/{chunk-OMKQH5C5.js → chunk-FWWQIFDT.js} +6 -23
  77. package/chunks/{chunk-TLV2IMHR.js → chunk-FYB4GIDW.js} +3 -3
  78. package/chunks/{chunk-ZJ3VGYHK.js → chunk-GY24H6IA.js} +40 -22
  79. package/chunks/{chunk-P2AJ7FTI.js → chunk-H4JC7LZX.js} +1 -1
  80. package/chunks/{chunk-55LYDVPU.js → chunk-HDYQYYWB.js} +1 -1
  81. package/chunks/{chunk-PQBHU2IA.js → chunk-HKI3KHAO.js} +11 -11
  82. package/chunks/{chunk-Y4NGLFGJ.js → chunk-HUWENAHO.js} +1 -1
  83. package/chunks/{chunk-3ULCB3NE.js → chunk-HV76SFIA.js} +1 -1
  84. package/chunks/{chunk-CSZEXZBE.js → chunk-HWXGX534.js} +3 -3
  85. package/chunks/{chunk-E33LOKRA.js → chunk-I5VM3SKY.js} +22 -5
  86. package/chunks/{chunk-LZC3B5N2.js → chunk-IA7TGCN2.js} +2 -2
  87. package/chunks/{chunk-RGSBTHSU.js → chunk-KMS57JDD.js} +137 -7
  88. package/chunks/{chunk-VOARQPTA.js → chunk-KP25NJNM.js} +65 -21
  89. package/chunks/{chunk-6M26GBKX.js → chunk-L2AFWWJE.js} +42 -3
  90. package/chunks/{chunk-ZXU5UHMI.js → chunk-LHEC5V6G.js} +2 -2
  91. package/chunks/{chunk-J26HHFI5.js → chunk-LP2QGNSP.js} +32 -2
  92. package/chunks/{chunk-R574ATRM.js → chunk-M2PNLYGY.js} +41 -0
  93. package/chunks/{chunk-MKVZE4ZJ.js → chunk-MFDYOYZZ.js} +3 -2
  94. package/chunks/{chunk-ALGGS7UH.js → chunk-NPQ5ZKRP.js} +82 -1
  95. package/chunks/{chunk-YHEEE624.js → chunk-NV3F44FL.js} +7 -3
  96. package/chunks/{chunk-6GONZVLS.js → chunk-NZMXUSKS.js} +1 -1
  97. package/chunks/{chunk-HQB2KUAN.js → chunk-O277O7U6.js} +1 -1
  98. package/chunks/{chunk-Y4EWSQF7.js → chunk-OBP6QWD5.js} +2 -2
  99. package/chunks/{chunk-CYR3HI5X.js → chunk-OQTXYMKW.js} +2 -2
  100. package/chunks/{chunk-TYKC75AX.js → chunk-OR6R3IUW.js} +2 -2
  101. package/chunks/{chunk-TRLYP7OF.js → chunk-OSVH4SMN.js} +16 -141
  102. package/chunks/{chunk-FPM27XN4.js → chunk-OW2BWT2P.js} +4 -4
  103. package/chunks/{chunk-TDXGKHDN.js → chunk-P5ULXPK5.js} +2 -2
  104. package/chunks/{chunk-24ER7UV4.js → chunk-PBRVUF5B.js} +1 -1
  105. package/chunks/{chunk-LKRMNRSN.js → chunk-PDPFQ2FO.js} +2 -0
  106. package/chunks/{chunk-2VSTGY6M.js → chunk-PJRW65JO.js} +1 -1
  107. package/chunks/{chunk-6HVUFDS2.js → chunk-PNVPFARW.js} +22 -13
  108. package/chunks/{chunk-IC4Z6LX6.js → chunk-PYQADEFD.js} +5 -0
  109. package/chunks/chunk-R4ZA6GBK.js +208 -0
  110. package/chunks/{chunk-KR4ZSC7K.js → chunk-RMPLEWF3.js} +3 -3
  111. package/chunks/{chunk-EORNAQDT.js → chunk-RQ6U2JJQ.js} +1 -1
  112. package/chunks/{chunk-AE77C5ZU.js → chunk-RYQMJCUO.js} +1 -1
  113. package/chunks/{chunk-6UWFTUQL.js → chunk-S5CULOHB.js} +75 -31
  114. package/chunks/{chunk-7UFKAV7Y.js → chunk-S6HYI3MF.js} +2 -2
  115. package/chunks/chunk-SAH4BD2J.js +92 -0
  116. package/chunks/chunk-SR7RZ4MS.js +202 -0
  117. package/chunks/{chunk-QETYKPMG.js → chunk-T2O6NIOY.js} +1 -1
  118. package/chunks/chunk-TQOF5KBL.js +71 -0
  119. package/chunks/{chunk-OHJLEW5J.js → chunk-TWFFY5BP.js} +4 -4
  120. package/chunks/{chunk-SCI7K3GM.js → chunk-TXO5BMR2.js} +19 -10
  121. package/chunks/{chunk-YJQCUTT2.js → chunk-UAB6J2IE.js} +4 -4
  122. package/chunks/{chunk-OFI7IGST.js → chunk-UGUKH3SU.js} +10 -10
  123. package/chunks/{chunk-SHZYHGQH.js → chunk-V2226RFW.js} +1 -1
  124. package/chunks/{chunk-KKJJB5X6.js → chunk-V47QNK5W.js} +1526 -833
  125. package/chunks/{chunk-W4B7UBUS.js → chunk-VHXPSL57.js} +6 -6
  126. package/chunks/{chunk-WUC6ZFXO.js → chunk-VKJ4KTPJ.js} +1 -1
  127. package/chunks/{chunk-MAJS7AT4.js → chunk-VNNWAZSI.js} +2 -2
  128. package/chunks/{chunk-BVWVWGLE.js → chunk-WAUGQKUU.js} +4 -64
  129. package/chunks/{chunk-OH2VKQXH.js → chunk-WH6QMLUW.js} +37 -30
  130. package/chunks/{chunk-PJOBIWUG.js → chunk-WQYWK4DG.js} +1 -1
  131. package/chunks/{chunk-LEMXGVEP.js → chunk-YFRFZCIP.js} +3 -3
  132. package/chunks/{chunk-2U3WZGZG.js → chunk-YGT2AUJ7.js} +103 -135
  133. package/chunks/{chunk-6XU3PH66.js → chunk-YR7ZQ4RD.js} +22 -69
  134. package/chunks/{chunk-OA4JVLSA.js → chunk-Z7VOMGDC.js} +22 -1
  135. package/chunks/{chunk-RUL4S3K3.js → chunk-ZCJBCKL5.js} +175 -60
  136. package/chunks/{chunk-GSS34377.js → chunk-ZI5IH2HP.js} +2 -2
  137. package/chunks/{chunk-CB2464BK.js → chunk-ZIKTCMQF.js} +117 -10
  138. package/chunks/chunk-ZLBIFIMV.js +1099 -0
  139. package/chunks/{chunk-D3UEZIQH.js → chunk-ZSNBQXMZ.js} +48 -55
  140. package/chunks/{chunk-FZBZSYKU.js → chunk-ZV7LTLFE.js} +1 -1
  141. package/chunks/{computer-use-KEAPATUY.js → computer-use-SLN7DV2E.js} +28 -24
  142. package/chunks/{config-utils-K7SCOWHD.js → config-utils-ULCSRMWD.js} +4 -4
  143. package/chunks/{contextCommand-ZJA6A5K5.js → contextCommand-EHFYX6FW.js} +30 -26
  144. package/chunks/{core-runtime-QMJPWHCI.js → core-runtime-FBSP5IIG.js} +33 -29
  145. package/chunks/{create-sub-session-E4PBYXV5.js → create-sub-session-QIDZUOPU.js} +1 -1
  146. package/chunks/{create-sub-session-DJE6XICH.js → create-sub-session-WC7YGVSL.js} +29 -25
  147. package/chunks/{cron-create-GRBWYMIJ.js → cron-create-VONA5JYY.js} +1 -1
  148. package/chunks/{cron-delete-4CMKBR2M.js → cron-delete-5JXSP2MI.js} +1 -1
  149. package/chunks/{cron-list-W7K4ASOA.js → cron-list-KE4F2CIR.js} +1 -1
  150. package/chunks/{daemon-SCTQMM7Z.js → daemon-VSX3FHTY.js} +119 -4
  151. package/chunks/{daemon-status-provider-FSWDPE2G.js → daemon-status-provider-WW2AD2T7.js} +39 -35
  152. package/chunks/{daemon-trust-policy-P5L5VFAY.js → daemon-trust-policy-E4MAYWPI.js} +35 -31
  153. package/chunks/{daemon-trust-policy-monitor-73JYN6ET.js → daemon-trust-policy-monitor-XVIDV6T4.js} +35 -31
  154. package/chunks/{de-VL76CPLV.js → de-LIW4XVLN.js} +5 -0
  155. package/chunks/{deferred-core-runtime-BWRCCFTE.js → deferred-core-runtime-5SVUC6UC.js} +28 -24
  156. package/chunks/{display-image-O2XFPQTC.js → display-image-NQRSIBXM.js} +2 -2
  157. package/chunks/{dist-HVBMEYWK.js → dist-3NTTUAHT.js} +1 -1
  158. package/chunks/{dist-7JGAAQSC.js → dist-6BMOAE3Z.js} +2 -2
  159. package/chunks/{dist-3BMEUGTG.js → dist-B2CGTW6T.js} +1 -1
  160. package/chunks/{dist-C5U4LJKW.js → dist-EWW3J4HQ.js} +5 -4
  161. package/chunks/{dist-K4WWQBHS.js → dist-EZE3V3Q7.js} +55 -15
  162. package/chunks/{dist-DPPHJAVL.js → dist-J47AXBZC.js} +918 -142
  163. package/chunks/{dist-SFQ34F4M.js → dist-OTUO3AS2.js} +8 -1091
  164. package/chunks/{dist-KS4O2NKE.js → dist-Z3CS4OVP.js} +14 -8
  165. package/chunks/{earlyInputCapture-L5ST23A6.js → earlyInputCapture-72FYHYRD.js} +28 -24
  166. package/chunks/{edit-LHHRFNFK.js → edit-SWVVWHXW.js} +28 -24
  167. package/chunks/{en-IRJ2WN5T.js → en-SY5GTIGX.js} +6 -0
  168. package/chunks/{enter-worktree-6NXCRZPF.js → enter-worktree-2HF6WQEO.js} +28 -24
  169. package/chunks/{enterPlanMode-ZVQT4U7D.js → enterPlanMode-OW6S7L4P.js} +28 -24
  170. package/chunks/{environment-GJ2HWJOS.js → environment-LRTBTDXH.js} +32 -28
  171. package/chunks/{errors-6RLH3XXC.js → errors-4CO2DME6.js} +30 -26
  172. package/chunks/{exit-worktree-I2YLUHHY.js → exit-worktree-GHJEIRGL.js} +28 -24
  173. package/chunks/{exitPlanMode-7CCWKO7I.js → exitPlanMode-JVP4FNNK.js} +28 -24
  174. package/chunks/{fast-path-DVFD4HQD.js → fast-path-HCCY7GR2.js} +24 -3
  175. package/chunks/{fast-path-settings-WQJU2LAT.js → fast-path-settings-MN5QQQET.js} +6 -3
  176. package/chunks/{fr-GK3HQYVB.js → fr-RQFO7U4P.js} +5 -0
  177. package/chunks/{gemini-7FWGOYD4.js → gemini-V3YVRKXU.js} +85 -72
  178. package/chunks/{geminiContentGenerator-V2WVLIXU.js → geminiContentGenerator-LVPMQUWX.js} +1 -1
  179. package/chunks/{glob-3N6GGI75.js → glob-7HRXHYDR.js} +28 -24
  180. package/chunks/{goal-tools-APOW6UXL.js → goal-tools-PXWN5VK3.js} +4 -2
  181. package/chunks/{grep-V43ILZVX.js → grep-BITQUON5.js} +28 -24
  182. package/chunks/{handleAutoUpdate-A5WFVWIA.js → handleAutoUpdate-DKFY454S.js} +32 -28
  183. package/chunks/{i18n-PLVQ4FBZ.js → i18n-53BQIQSH.js} +29 -25
  184. package/chunks/{image-gen-7C6IK6DC.js → image-gen-H62FLDFB.js} +7 -5
  185. package/chunks/{initializer-CVAIKZYL.js → initializer-Q7NUQRSU.js} +35 -31
  186. package/chunks/{installationInfo-J6QDHNTK.js → installationInfo-BWFHT7WU.js} +29 -25
  187. package/chunks/{ja-3FA46IKD.js → ja-KOZKHJHZ.js} +5 -0
  188. package/chunks/{list-ZZ4OUUWV.js → list-OWQKR6JK.js} +38 -34
  189. package/chunks/{list-agents-KFFIIS2G.js → list-agents-Z4WABFDZ.js} +1 -1
  190. package/chunks/{loadedSettingsAdapter-QRYRJSWL.js → loadedSettingsAdapter-HNPKQMFA.js} +35 -31
  191. package/chunks/{loggingContentGenerator-OJCO75HM.js → loggingContentGenerator-A5I3VQUC.js} +10 -8
  192. package/chunks/{loop-wakeup-TLMJPMMP.js → loop-wakeup-UZ5RL5Y2.js} +2 -2
  193. package/chunks/{ls-UVVE2XGE.js → ls-TVHDGIES.js} +1 -1
  194. package/chunks/{lsp-QMEA2VLB.js → lsp-CVN6OQPI.js} +1 -1
  195. package/chunks/main-PXAUXNF2.js +8 -0
  196. package/chunks/{managed-npm-update-PCOSCP2N.js → managed-npm-update-CUUJGUTV.js} +29 -25
  197. package/chunks/{mcp-M3WKKWKY.js → mcp-GJSC7ZPO.js} +35 -31
  198. package/chunks/{monitor-GN24FH6C.js → monitor-TZ2II7JM.js} +38 -30
  199. package/chunks/{nonInteractiveCli-KPTU3VSQ.js → nonInteractiveCli-22RS4EVH.js} +72 -66
  200. package/chunks/{notebook-edit-4YM65BBO.js → notebook-edit-YZC3YPY2.js} +36 -24
  201. package/chunks/{openaiContentGenerator-EDQT6GTV.js → openaiContentGenerator-OIGO5XNF.js} +21 -11
  202. package/chunks/{pidfile-JOIIRN2C.js → pidfile-QJQ65RJ2.js} +28 -24
  203. package/chunks/{process-registry-2CHQBXH5.js → process-registry-PMJOA5CO.js} +15 -0
  204. package/chunks/{processUtils-5SV4MX3Q.js → processUtils-V5VSDIKS.js} +2 -2
  205. package/chunks/{pt-3AOBKPIJ.js → pt-U6AOCTMF.js} +5 -0
  206. package/chunks/{qwenContentGenerator-ODRJSUGR.js → qwenContentGenerator-HXM25BGB.js} +35 -30
  207. package/chunks/{qwenOAuth2-NESCMZ47.js → qwenOAuth2-7MTMS2Z5.js} +7 -5
  208. package/chunks/{read-file-HPSODLPK.js → read-file-PMGXB3ZB.js} +8 -6
  209. package/chunks/{read-mcp-resource-2TNSJTC3.js → read-mcp-resource-PZ4ZF6YL.js} +1 -1
  210. package/chunks/{record-artifact-RAON52FC.js → record-artifact-P4HFMS7X.js} +2 -2
  211. package/chunks/{resumeHistoryUtils-TXCOFFMQ.js → resumeHistoryUtils-YUTPLHUH.js} +33 -29
  212. package/chunks/{ripGrep-ZKQGTQAO.js → ripGrep-XUS66YIV.js} +28 -24
  213. package/chunks/{ru-VJRAMC4W.js → ru-CMX4UMYP.js} +5 -0
  214. package/chunks/{run-qwen-serve-ZPKPKECF.js → run-qwen-serve-4NVSU75L.js} +261 -62
  215. package/chunks/{runtime-2FLNNM36.js → runtime-QLRVP6HM.js} +40 -36
  216. package/chunks/{scheduler-365PJHNR.js → scheduler-PBB2NSOP.js} +28 -24
  217. package/chunks/{sdk-exporters-http-KHAB5JSD.js → sdk-exporters-http-XVTZQRCE.js} +2 -2
  218. package/chunks/{sdk-impl-KD7FSTC3.js → sdk-impl-7W7AKCS4.js} +7 -3
  219. package/chunks/{send-message-ZM7MRUGP.js → send-message-CAMSLG2L.js} +4 -3
  220. package/chunks/{serve-QD2RNLKJ.js → serve-BWKTRX72.js} +37 -31
  221. package/chunks/{server-XLJVLTYM.js → server-E7CH7WPK.js} +1437 -593
  222. package/chunks/{session-3VTUHH4Q.js → session-QEKSJ6YU.js} +166 -105
  223. package/chunks/{settings-KULVPCQC.js → settings-BRAOSJIM.js} +34 -30
  224. package/chunks/{shell-3SWW22MH.js → shell-OF3CK4AT.js} +28 -24
  225. package/chunks/{skill-KDHWYS7W.js → skill-HLH2NO2H.js} +9 -7
  226. package/chunks/{skill-settings-NMY4JEJC.js → skill-settings-DRPU7YI5.js} +34 -30
  227. package/chunks/{spawnChannel-ZKS4Q5OU.js → spawnChannel-4KO7YTFM.js} +31 -27
  228. package/chunks/{standalone-update-7CXPGAQ4.js → standalone-update-DJN2R3YW.js} +30 -26
  229. package/chunks/{startInteractiveUI-2QQLEKM6.js → startInteractiveUI-O3WQQ2WC.js} +384 -173
  230. package/chunks/{syntheticOutput-ZLCUTKO2.js → syntheticOutput-PEBJQYJV.js} +2 -2
  231. package/chunks/{task-create-CQP5UEA3.js → task-create-5NWCQSJF.js} +5 -4
  232. package/chunks/{task-list-XLEZOJXP.js → task-list-53265TRZ.js} +1 -1
  233. package/chunks/{task-stop-7ZQM5CFF.js → task-stop-FPCOIRYX.js} +1 -1
  234. package/chunks/{task-update-JA75U2SN.js → task-update-5HN577LS.js} +5 -4
  235. package/chunks/{team-create-2WTNGAOX.js → team-create-2E4ACBJD.js} +28 -24
  236. package/chunks/{team-delete-MHY3UZGY.js → team-delete-MMQB4OSC.js} +1 -1
  237. package/chunks/{team-plan-approval-LZTYLEG4.js → team-plan-approval-LWIDXYOA.js} +28 -24
  238. package/chunks/{terminal-image-renderer-R5HHAFJN.js → terminal-image-renderer-PJM7663W.js} +30 -26
  239. package/chunks/{theme-manager-PAUCSJFF.js → theme-manager-FDQTM3RP.js} +28 -24
  240. package/chunks/{todoWrite-UPVOHYGD.js → todoWrite-JGV6VLOX.js} +1 -1
  241. package/chunks/{tool-search-2BFCGLI6.js → tool-search-TL5ZXBF4.js} +11 -8
  242. package/chunks/{total-session-admission-MK4SINFK.js → total-session-admission-LS6EY5KT.js} +37 -32
  243. package/chunks/{trustedFolders-TJ5S26N7.js → trustedFolders-5RWP5OB7.js} +32 -26
  244. package/chunks/{types-ML3TRJQ5.js → types-WYCFCEHR.js} +5 -3
  245. package/chunks/{update-relaunch-N7AYLARF.js → update-relaunch-HWQ4USKY.js} +5 -5
  246. package/chunks/{updateCheck-QRZ3DVT5.js → updateCheck-EZMBTEIR.js} +31 -27
  247. package/chunks/{useAutoAcceptIndicator-DBJ7Y5AF.js → useAutoAcceptIndicator-JDMI627A.js} +37 -33
  248. package/chunks/{validateNonInterActiveAuth-6ZQWUDS3.js → validateNonInterActiveAuth-RRUHC5RO.js} +67 -63
  249. package/chunks/{version-AJQGQWXC.js → version-XS4UTKUX.js} +1 -1
  250. package/chunks/{web-fetch-QWJYRXFL.js → web-fetch-2JV7H6OM.js} +14 -10
  251. package/chunks/{web-search-2AOXJGHU.js → web-search-RCTN2GAM.js} +10 -7
  252. package/chunks/{workflow-ERH3SJG2.js → workflow-6MKLKQ6R.js} +909 -273
  253. package/chunks/{workspace-providers-status-HZ474RA4.js → workspace-providers-status-YZ2IJ4DK.js} +38 -34
  254. package/chunks/{workspace-registration-store-6EUP4JXG.js → workspace-registration-store-IYN72LBS.js} +1 -1
  255. package/chunks/{workspace-registry-R4APRRNC.js → workspace-registry-7LFBZQLT.js} +37 -32
  256. package/chunks/{workspace-service-HFIFDMU7.js → workspace-service-2EHSPRJB.js} +45 -39
  257. package/chunks/{workspace-skills-status-HAHEIHGK.js → workspace-skills-status-5VJ2D5HN.js} +36 -32
  258. package/chunks/{workspace-trust-reconciler-65GTAGDK.js → workspace-trust-reconciler-X2LZ6XCI.js} +44 -39
  259. package/chunks/{write-file-B34CDELV.js → write-file-CJK6SCCF.js} +28 -24
  260. package/chunks/{zh-ARWDLDLR.js → zh-AGL2FVBI.js} +6 -0
  261. package/chunks/{zh-TW-Y4RGI3P7.js → zh-TW-KI66MHQY.js} +6 -0
  262. package/chunks/{zoom-image-HPRBZHSS.js → zoom-image-BVW4RFYW.js} +8 -6
  263. package/cli.js +13 -13
  264. package/locales/ca.js +10 -0
  265. package/locales/de.js +9 -0
  266. package/locales/en.js +10 -0
  267. package/locales/fr.js +9 -0
  268. package/locales/ja.js +9 -0
  269. package/locales/pt.js +9 -0
  270. package/locales/ru.js +9 -0
  271. package/locales/zh-TW.js +10 -0
  272. package/locales/zh.js +10 -0
  273. package/package.json +3 -3
  274. package/web-shell/assets/{arc-Ip-FFDJ0.js → arc-DDtoJrAW.js} +1 -1
  275. package/web-shell/assets/{architectureDiagram-3BPJPVTR-CChqgwIb.js → architectureDiagram-3BPJPVTR-BAInIW4O.js} +1 -1
  276. package/web-shell/assets/{blockDiagram-GPEHLZMM-BHN-Tfss.js → blockDiagram-GPEHLZMM-ChPDk7fP.js} +1 -1
  277. package/web-shell/assets/{c4Diagram-AAUBKEIU-BhyjzDjN.js → c4Diagram-AAUBKEIU-Cd9BJuUy.js} +1 -1
  278. package/web-shell/assets/channel-0OQklTfP.js +1 -0
  279. package/web-shell/assets/{chunk-2J33WTMH-BB9eyHrx.js → chunk-2J33WTMH-COQkLp56.js} +1 -1
  280. package/web-shell/assets/{chunk-4BX2VUAB-BeV7ce_J.js → chunk-4BX2VUAB-GUJshQ_l.js} +1 -1
  281. package/web-shell/assets/{chunk-55IACEB6-DO7kXDiV.js → chunk-55IACEB6-Boaa7c10.js} +1 -1
  282. package/web-shell/assets/{chunk-727SXJPM-B27MPznD.js → chunk-727SXJPM-CcRXaly2.js} +1 -1
  283. package/web-shell/assets/{chunk-AQP2D5EJ-DHIjqjD_.js → chunk-AQP2D5EJ-BY0OARHh.js} +1 -1
  284. package/web-shell/assets/{chunk-FMBD7UC4-DabMqyN2.js → chunk-FMBD7UC4-DLFQfv0S.js} +1 -1
  285. package/web-shell/assets/{chunk-ND2GUHAM-Dw7Nnnxc.js → chunk-ND2GUHAM-C_S0u-D2.js} +1 -1
  286. package/web-shell/assets/{chunk-QZHKN3VN-DdaZew1Q.js → chunk-QZHKN3VN-DP9m64hw.js} +1 -1
  287. package/web-shell/assets/classDiagram-4FO5ZUOK-CZ4-apsu.js +1 -0
  288. package/web-shell/assets/classDiagram-v2-Q7XG4LA2-CZ4-apsu.js +1 -0
  289. package/web-shell/assets/{cose-bilkent-S5V4N54A-CgBpCYH5.js → cose-bilkent-S5V4N54A-CGY6zGE1.js} +1 -1
  290. package/web-shell/assets/{dagre-BM42HDAG-BB4IU8G0.js → dagre-BM42HDAG-yB7whKNn.js} +1 -1
  291. package/web-shell/assets/{diagram-2AECGRRQ-BcUTHU37.js → diagram-2AECGRRQ-Bdlc59La.js} +1 -1
  292. package/web-shell/assets/{diagram-5GNKFQAL-B6Lyihyv.js → diagram-5GNKFQAL-BUClP18L.js} +1 -1
  293. package/web-shell/assets/{diagram-KO2AKTUF-CRIJOjpG.js → diagram-KO2AKTUF-aZm08kjn.js} +1 -1
  294. package/web-shell/assets/{diagram-LMA3HP47-DdNiwWWT.js → diagram-LMA3HP47-7DGwEkxC.js} +1 -1
  295. package/web-shell/assets/{diagram-OG6HWLK6-Dz4b32Do.js → diagram-OG6HWLK6-CAGKayxx.js} +1 -1
  296. package/web-shell/assets/{erDiagram-TEJ5UH35-D-8NGw77.js → erDiagram-TEJ5UH35-CptoHHQi.js} +1 -1
  297. package/web-shell/assets/{flowDiagram-I6XJVG4X-Dun26LyM.js → flowDiagram-I6XJVG4X-CNOH0s7Q.js} +1 -1
  298. package/web-shell/assets/{ganttDiagram-6RSMTGT7-F10Hu1Gc.js → ganttDiagram-6RSMTGT7-CCQuCU3y.js} +1 -1
  299. package/web-shell/assets/{gitGraphDiagram-PVQCEYII-Bf8Ez6-D.js → gitGraphDiagram-PVQCEYII-B7gv9f4E.js} +1 -1
  300. package/web-shell/assets/{index-BXqw-nGq.js → index-BoUPVvpf.js} +1 -1
  301. package/web-shell/assets/index-D1YQXYsB.css +5 -0
  302. package/web-shell/assets/index-J4N7zCmU.js +1768 -0
  303. package/web-shell/assets/{infoDiagram-5YYISTIA-DVgTMLvj.js → infoDiagram-5YYISTIA-Bb3KYEbR.js} +1 -1
  304. package/web-shell/assets/{ishikawaDiagram-YF4QCWOH-uT-KepvK.js → ishikawaDiagram-YF4QCWOH-DWEzbAGi.js} +1 -1
  305. package/web-shell/assets/{journeyDiagram-JHISSGLW-Vg_XadQf.js → journeyDiagram-JHISSGLW-CmxwEqeb.js} +1 -1
  306. package/web-shell/assets/{kanban-definition-UN3LZRKU-Dyv1ESBE.js → kanban-definition-UN3LZRKU-Ci0gDD8O.js} +1 -1
  307. package/web-shell/assets/{linear-BMIepYX3.js → linear-BqxZqGhS.js} +1 -1
  308. package/web-shell/assets/{mermaid.core-zA8pJ9ag.js → mermaid.core-BDAFffHv.js} +5 -5
  309. package/web-shell/assets/{mindmap-definition-RKZ34NQL-BCW_BZ_5.js → mindmap-definition-RKZ34NQL-Btvx-xvS.js} +1 -1
  310. package/web-shell/assets/{pieDiagram-4H26LBE5-DseNEGp2.js → pieDiagram-4H26LBE5-CKAg7yG7.js} +1 -1
  311. package/web-shell/assets/{quadrantDiagram-W4KKPZXB-6Z7wr1Fi.js → quadrantDiagram-W4KKPZXB-DIt8E1mC.js} +1 -1
  312. package/web-shell/assets/{requirementDiagram-4Y6WPE33-CVOlCRPf.js → requirementDiagram-4Y6WPE33-BA7mQWQJ.js} +1 -1
  313. package/web-shell/assets/{sankeyDiagram-5OEKKPKP-CGhgrUJZ.js → sankeyDiagram-5OEKKPKP-D0JppnVU.js} +1 -1
  314. package/web-shell/assets/{sequenceDiagram-3UESZ5HK-dlqmpLuQ.js → sequenceDiagram-3UESZ5HK-29DIQFjB.js} +1 -1
  315. package/web-shell/assets/{stateDiagram-AJRCARHV-B9EW10Xb.js → stateDiagram-AJRCARHV-iiXMdK--.js} +1 -1
  316. package/web-shell/assets/stateDiagram-v2-BHNVJYJU-CEGK3l80.js +1 -0
  317. package/web-shell/assets/{timeline-definition-PNZ67QCA-BBRh0mgZ.js → timeline-definition-PNZ67QCA-CeF7ngSW.js} +1 -1
  318. package/web-shell/assets/{vennDiagram-CIIHVFJN-B8Gs-REP.js → vennDiagram-CIIHVFJN-Beilq8D6.js} +1 -1
  319. package/web-shell/assets/{wardley-L42UT6IY-D_y80Ur7.js → wardley-L42UT6IY-DOYjY4zO.js} +1 -1
  320. package/web-shell/assets/{wardleyDiagram-YWT4CUSO-D-CNfHJ-.js → wardleyDiagram-YWT4CUSO-Dtqp8o18.js} +1 -1
  321. package/web-shell/assets/{xychartDiagram-2RQKCTM6-DQ5CvELo.js → xychartDiagram-2RQKCTM6-cdAc0Dfv.js} +1 -1
  322. package/web-shell/index.html +2 -2
  323. package/chunks/chunk-6PEXNQTX.js +0 -68
  324. package/chunks/chunk-IUFV6FYU.js +0 -81
  325. package/chunks/chunk-RXFQM6FQ.js +0 -42
  326. package/web-shell/assets/channel-Cu8qd6OB.js +0 -1
  327. package/web-shell/assets/classDiagram-4FO5ZUOK-BI3KrXhq.js +0 -1
  328. package/web-shell/assets/classDiagram-v2-Q7XG4LA2-BI3KrXhq.js +0 -1
  329. package/web-shell/assets/index-QQlUCJGg.css +0 -5
  330. package/web-shell/assets/index-hcgjV7vS.js +0 -1768
  331. package/web-shell/assets/stateDiagram-v2-BHNVJYJU-CJTZJJ5X.js +0 -1
  332. package/chunks/{anthropicContentGenerator-DTMVEL5M.js → anthropicContentGenerator-SSFE2753.js} +9 -9
  333. /package/chunks/{chunk-VXZBKKQR.js → chunk-NTTBXH7U.js} +0 -0
  334. /package/chunks/{chunk-GRC5HGPI.js → chunk-OIBUG24X.js} +0 -0
@@ -5,29 +5,30 @@ import {
5
5
  FileDiscoveryService,
6
6
  GitWorktreeService,
7
7
  generateAgentWorktreeSlug,
8
+ isTerminalWorkflowStatus,
8
9
  rebuildToolRegistryOnOverride,
9
10
  resolveSavedWorkflowScript,
10
11
  stripAnsiAndControl,
11
12
  toModelVisibleSubagentResult,
12
13
  writeWorkflowSnapshot,
13
14
  writeWorktreeSessionMarker
14
- } from "./chunk-Y7E5LNLO.js";
15
+ } from "./chunk-47ZUMGGY.js";
15
16
  import "./chunk-GOFAQQZA.js";
16
17
  import "./chunk-5M6IDOMF.js";
17
18
  import "./chunk-TWPJO254.js";
18
19
  import "./chunk-H6XPXXMH.js";
19
- import "./chunk-CNIID3TV.js";
20
+ import "./chunk-2UUMVNYT.js";
20
21
  import "./chunk-MVUQRLOH.js";
21
22
  import "./chunk-XCWO3SMQ.js";
22
23
  import "./chunk-7MH4J33A.js";
23
24
  import {
24
25
  parsePositiveIntegerEnv
25
26
  } from "./chunk-6PVPNMXU.js";
26
- import "./chunk-RMH5OWLD.js";
27
+ import "./chunk-F3II4BTZ.js";
27
28
  import "./chunk-IRH27ZC2.js";
28
29
  import "./chunk-QHWCP53L.js";
29
30
  import "./chunk-GNPNYXJB.js";
30
- import "./chunk-Y4NGLFGJ.js";
31
+ import "./chunk-HUWENAHO.js";
31
32
  import "./chunk-O6GEWCJA.js";
32
33
  import "./chunk-T26EAKDL.js";
33
34
  import "./chunk-ZPJWUGCS.js";
@@ -36,65 +37,70 @@ import "./chunk-J6SZID63.js";
36
37
  import "./chunk-KRXPRVGL.js";
37
38
  import "./chunk-GM463R2B.js";
38
39
  import "./chunk-SEZ556DZ.js";
39
- import "./chunk-CJXIIILK.js";
40
- import "./chunk-3K7FH2KQ.js";
40
+ import "./chunk-2FRY5CRX.js";
41
+ import "./chunk-67N6HB5H.js";
42
+ import {
43
+ SUBAGENT_PLAN_LIFECYCLE_TOOLS
44
+ } from "./chunk-WAUGQKUU.js";
45
+ import "./chunk-DZUO626D.js";
46
+ import "./chunk-4TRQPFDP.js";
47
+ import "./chunk-SAH4BD2J.js";
41
48
  import {
42
- SUBAGENT_PLAN_LIFECYCLE_TOOLS,
43
49
  runWithAgentContext
44
- } from "./chunk-BVWVWGLE.js";
50
+ } from "./chunk-CPG6P4GG.js";
45
51
  import "./chunk-S6LOFUVP.js";
46
- import "./chunk-LZC3B5N2.js";
52
+ import "./chunk-2J3OJGTL.js";
53
+ import "./chunk-IA7TGCN2.js";
47
54
  import "./chunk-K623ENWT.js";
48
55
  import "./chunk-AQ37AY7B.js";
49
56
  import {
50
57
  WorkspaceContext
51
58
  } from "./chunk-EQL65XGA.js";
52
- import "./chunk-IIJEYBNH.js";
53
- import "./chunk-22NBYCPD.js";
59
+ import "./chunk-3P2LV43B.js";
54
60
  import "./chunk-NAVJD2PQ.js";
55
- import "./chunk-3ULCB3NE.js";
56
- import "./chunk-BGG4MBYD.js";
61
+ import "./chunk-HV76SFIA.js";
62
+ import "./chunk-4PYCZH2V.js";
63
+ import "./chunk-P3QQPMQA.js";
64
+ import "./chunk-SR7RZ4MS.js";
65
+ import "./chunk-M6HMMKVG.js";
57
66
  import "./chunk-DGEIYUC3.js";
58
67
  import "./chunk-MPHPFVKK.js";
59
68
  import "./chunk-AXMWHKXA.js";
69
+ import "./chunk-GLCZKT5V.js";
60
70
  import {
61
71
  createAbortController,
62
72
  createChildAbortController
63
73
  } from "./chunk-DJ2GSRLV.js";
64
- import "./chunk-33ACCIIY.js";
65
- import "./chunk-L4N6TIP7.js";
66
- import "./chunk-2J3OJGTL.js";
67
- import "./chunk-P3QQPMQA.js";
68
- import "./chunk-M6HMMKVG.js";
69
- import "./chunk-GLCZKT5V.js";
70
74
  import "./chunk-EI3HZX6C.js";
71
75
  import {
72
76
  WorkflowRunEvent,
73
77
  logWorkflowRun,
74
78
  read,
75
79
  writeLine
76
- } from "./chunk-2U3WZGZG.js";
80
+ } from "./chunk-YGT2AUJ7.js";
77
81
  import "./chunk-WOJZWRAZ.js";
78
82
  import "./chunk-VGC4I5JJ.js";
79
83
  import "./chunk-FVKHVJZQ.js";
84
+ import "./chunk-COBO5EBO.js";
80
85
  import {
81
86
  SyntheticOutputTool
82
- } from "./chunk-NG2R4N5O.js";
87
+ } from "./chunk-6ZRFAKXK.js";
83
88
  import {
84
89
  BaseDeclarativeTool,
85
90
  BaseToolInvocation,
86
91
  ToolDisplayNames,
87
92
  ToolNames
88
- } from "./chunk-IC4Z6LX6.js";
89
- import "./chunk-6EOI4HOK.js";
93
+ } from "./chunk-PYQADEFD.js";
94
+ import "./chunk-E2T7FLDU.js";
95
+ import "./chunk-F6WFNA7U.js";
90
96
  import "./chunk-46UV252V.js";
91
97
  import "./chunk-ZBVS26BY.js";
92
98
  import "./chunk-KKBPOU75.js";
93
99
  import "./chunk-EUNWC2VS.js";
94
100
  import "./chunk-FOGU3LJX.js";
95
- import "./chunk-6M26GBKX.js";
101
+ import "./chunk-L2AFWWJE.js";
96
102
  import "./chunk-W4RQUHY3.js";
97
- import "./chunk-LKRMNRSN.js";
103
+ import "./chunk-PDPFQ2FO.js";
98
104
  import {
99
105
  createDebugLogger
100
106
  } from "./chunk-OIVKILPI.js";
@@ -114,95 +120,6 @@ import {
114
120
  // packages/core/src/tools/workflow/workflow.ts
115
121
  init_esbuild_shims();
116
122
 
117
- // packages/core/src/agents/runtime/workflow-budget.ts
118
- init_esbuild_shims();
119
- var debugLogger = createDebugLogger("WORKFLOW_BUDGET");
120
- var MAX_TOKENS_PER_WORKFLOW_ENV = "QWEN_CODE_MAX_TOKENS_PER_WORKFLOW";
121
- var HARD_MAX_TOKENS_CEILING = 1e8;
122
- function resolveMaxTokensPerWorkflow(env = process.env) {
123
- const raw = env[MAX_TOKENS_PER_WORKFLOW_ENV];
124
- if (raw === void 0 || raw.trim() === "") {
125
- return null;
126
- }
127
- const parsed = parsePositiveIntegerEnv(raw, 0);
128
- if (parsed < 1) {
129
- debugLogger.warn(
130
- `Invalid ${MAX_TOKENS_PER_WORKFLOW_ENV}=${JSON.stringify(raw)}, treating as unset (no cap)`
131
- );
132
- return null;
133
- }
134
- if (parsed > HARD_MAX_TOKENS_CEILING) {
135
- debugLogger.warn(
136
- `${MAX_TOKENS_PER_WORKFLOW_ENV}=${parsed} exceeds hard ceiling (${HARD_MAX_TOKENS_CEILING}); clamping.`
137
- );
138
- return HARD_MAX_TOKENS_CEILING;
139
- }
140
- return parsed;
141
- }
142
- __name(resolveMaxTokensPerWorkflow, "resolveMaxTokensPerWorkflow");
143
- var WorkflowBudgetImpl = class _WorkflowBudgetImpl {
144
- static {
145
- __name(this, "WorkflowBudgetImpl");
146
- }
147
- total;
148
- _spent;
149
- constructor(total) {
150
- this.total = total;
151
- this._spent = 0;
152
- }
153
- spent() {
154
- return this._spent;
155
- }
156
- remaining() {
157
- if (this.total === null) return Infinity;
158
- return Math.max(0, this.total - this._spent);
159
- }
160
- /**
161
- * Host-side increment. NOT exposed to the script — the
162
- * `WorkflowBudget` interface deliberately omits any setter so a
163
- * malicious workflow cannot inflate / deflate the budget. Only the
164
- * orchestrator (in `countedDispatch`) calls this after a dispatch
165
- * resolves with the agent's output token count.
166
- *
167
- * Non-positive deltas are silently dropped (some dispatches return
168
- * `output_tokens: 0` on early failures); negative deltas would be a
169
- * caller bug and are also dropped rather than silently rewinding
170
- * the counter.
171
- */
172
- recordSpent(deltaTokens) {
173
- if (!Number.isFinite(deltaTokens) || deltaTokens <= 0) return;
174
- this._spent += deltaTokens;
175
- }
176
- /**
177
- * Factory: build a budget from the current environment. Convenience
178
- * over `new WorkflowBudgetImpl(resolveMaxTokensPerWorkflow(env))`.
179
- */
180
- static fromEnv(env = process.env) {
181
- return new _WorkflowBudgetImpl(resolveMaxTokensPerWorkflow(env));
182
- }
183
- };
184
- var WorkflowBudgetExceededError = class extends Error {
185
- static {
186
- __name(this, "WorkflowBudgetExceededError");
187
- }
188
- name = "WorkflowBudgetExceededError";
189
- runId;
190
- budgetTotal;
191
- spent;
192
- constructor(runId, budgetTotal, spent) {
193
- super(
194
- `Workflow ${runId} exceeded the token budget (${spent} / ${budgetTotal} output tokens spent).`
195
- );
196
- this.runId = runId;
197
- this.budgetTotal = budgetTotal;
198
- this.spent = spent;
199
- }
200
- };
201
-
202
- // packages/core/src/agents/runtime/workflow-runner.ts
203
- init_esbuild_shims();
204
- import { randomBytes as randomBytes2 } from "node:crypto";
205
-
206
123
  // packages/core/src/agents/runtime/workflow-orchestrator.ts
207
124
  init_esbuild_shims();
208
125
  import { randomBytes } from "node:crypto";
@@ -388,7 +305,7 @@ function isRegexContext(source, i) {
388
305
  return /[{[(,;:=!&|?+\-*/%^~<>]/.test(prev);
389
306
  }
390
307
  __name(isRegexContext, "isRegexContext");
391
- var debugLogger2 = createDebugLogger("WORKFLOW");
308
+ var debugLogger = createDebugLogger("WORKFLOW");
392
309
  var MAX_LOG_LINES = 1e4;
393
310
  var MAX_PHASE_ENTRIES = 1e4;
394
311
  var ARGS_MAX_DEPTH = 64;
@@ -402,6 +319,50 @@ function resolveMaxWallClockMs(opts) {
402
319
  return DEFAULT_MAX_WALL_CLOCK_MS;
403
320
  }
404
321
  __name(resolveMaxWallClockMs, "resolveMaxWallClockMs");
322
+ var WallClockWatchdog = class {
323
+ constructor(budgetMs, onFire) {
324
+ this.onFire = onFire;
325
+ this.remainingMs = budgetMs;
326
+ this.arm();
327
+ }
328
+ static {
329
+ __name(this, "WallClockWatchdog");
330
+ }
331
+ timer;
332
+ remainingMs;
333
+ armedAt = 0;
334
+ paused = false;
335
+ stopped = false;
336
+ pause() {
337
+ if (this.stopped || this.paused || this.timer === void 0) return;
338
+ this.paused = true;
339
+ clearTimeout(this.timer);
340
+ this.timer = void 0;
341
+ this.remainingMs = Math.max(
342
+ 0,
343
+ this.remainingMs - (performance.now() - this.armedAt)
344
+ );
345
+ }
346
+ resume() {
347
+ if (this.stopped || !this.paused) return;
348
+ this.paused = false;
349
+ this.arm();
350
+ }
351
+ stop() {
352
+ this.stopped = true;
353
+ if (this.timer !== void 0) clearTimeout(this.timer);
354
+ this.timer = void 0;
355
+ }
356
+ arm() {
357
+ this.armedAt = performance.now();
358
+ this.timer = setTimeout(() => {
359
+ this.stopped = true;
360
+ this.timer = void 0;
361
+ this.onFire();
362
+ }, this.remainingMs);
363
+ this.timer.unref?.();
364
+ }
365
+ };
405
366
  function validateArgs(val, depth = 0, seen = /* @__PURE__ */ new WeakSet()) {
406
367
  if (depth > ARGS_MAX_DEPTH) {
407
368
  throw new Error(
@@ -447,7 +408,7 @@ function createWorkflowSandbox(opts) {
447
408
  try {
448
409
  opts.emitter?.logAppended?.(line);
449
410
  } catch (e) {
450
- debugLogger2.warn("emitter.logAppended threw:", e);
411
+ debugLogger.warn("emitter.logAppended threw:", e);
451
412
  }
452
413
  } else if (logs.length === MAX_LOG_LINES) {
453
414
  logs.push(`[workflow log truncated at ${MAX_LOG_LINES} lines]`);
@@ -461,7 +422,7 @@ function createWorkflowSandbox(opts) {
461
422
  try {
462
423
  opts.emitter?.phaseStarted?.(t);
463
424
  } catch (e) {
464
- debugLogger2.warn("emitter.phaseStarted threw:", e);
425
+ debugLogger.warn("emitter.phaseStarted threw:", e);
465
426
  }
466
427
  } else if (phases.length === MAX_PHASE_ENTRIES) {
467
428
  phases.push(
@@ -471,6 +432,17 @@ function createWorkflowSandbox(opts) {
471
432
  }, "safePhase");
472
433
  if (opts.args !== void 0) validateArgs(opts.args);
473
434
  const argsJson = opts.args === void 0 ? null : JSON.stringify(opts.args);
435
+ const unconsumedRoots = /* @__PURE__ */ new Map();
436
+ const unconsumedRejections = /* @__PURE__ */ new Map();
437
+ let nextUnconsumedId = 1;
438
+ let unconsumedSettled = false;
439
+ let mirroredEscapeKeys = /* @__PURE__ */ new Set();
440
+ const unconsumedRejectionLine = /* @__PURE__ */ __name((rec) => {
441
+ if (rec.dispatchFailed) {
442
+ return rec.isRoot ? "dispatch failed (result not consumed): " + rec.msg : "dispatch failed (rejection not handled): " + rec.msg;
443
+ }
444
+ return "script handler failed (rejection not handled): " + rec.msg;
445
+ }, "unconsumedRejectionLine");
474
446
  const bridge = {
475
447
  argsJson,
476
448
  pushPhase: safePhase,
@@ -484,10 +456,56 @@ function createWorkflowSandbox(opts) {
484
456
  // value" (this warn). Receives only primitive strings/numbers — the bridge
485
457
  // contract forbids host objects crossing back to the script.
486
458
  logRevivalFailure: /* @__PURE__ */ __name((idx, reason) => {
487
- debugLogger2.warn(
459
+ debugLogger.warn(
488
460
  `Workflow result revival failed at index ${idx}: ${reason}; slot set to null (non-JSON-serializable thunk return).`
489
461
  );
490
462
  }, "logRevivalFailure"),
463
+ // --- Unconsumed-rejection mirror bookkeeping ---
464
+ wfRegisterRoot: /* @__PURE__ */ __name(() => {
465
+ const id = nextUnconsumedId++;
466
+ unconsumedRoots.set(id, { rejectionHandled: false, adoptedOut: false });
467
+ return id;
468
+ }, "wfRegisterRoot"),
469
+ wfMarkRejectionHandled: /* @__PURE__ */ __name((rootId) => {
470
+ const root = unconsumedRoots.get(rootId);
471
+ if (root) root.rejectionHandled = true;
472
+ }, "wfMarkRejectionHandled"),
473
+ wfIsRootHandled: /* @__PURE__ */ __name((rootId) => unconsumedRoots.get(rootId)?.rejectionHandled === true, "wfIsRootHandled"),
474
+ wfMarkAdopted: /* @__PURE__ */ __name((rootId) => {
475
+ const root = unconsumedRoots.get(rootId);
476
+ if (root) root.adoptedOut = true;
477
+ }, "wfMarkAdopted"),
478
+ runId: opts.runId ?? "",
479
+ wfReportUnconsumed: /* @__PURE__ */ __name((rootId, isRoot, dispatchFailed, msg) => {
480
+ if (unconsumedSettled) {
481
+ const rec = {
482
+ rootId,
483
+ isRoot,
484
+ dispatchFailed,
485
+ msg
486
+ };
487
+ const rootState = unconsumedRoots.get(rootId);
488
+ if (!rootState?.rejectionHandled && !(dispatchFailed && rootState?.adoptedOut)) {
489
+ safeLog(unconsumedRejectionLine(rec));
490
+ }
491
+ return 0;
492
+ }
493
+ const id = nextUnconsumedId++;
494
+ unconsumedRejections.set(id, { rootId, isRoot, dispatchFailed, msg });
495
+ return id;
496
+ }, "wfReportUnconsumed"),
497
+ wfClearUnconsumed: /* @__PURE__ */ __name((id) => {
498
+ unconsumedRejections.delete(id);
499
+ }, "wfClearUnconsumed"),
500
+ // R10-1: teardown discrimination cannot key on the error name alone.
501
+ // The dominant in-flight cancellation path (controller.abort() →
502
+ // subagent returns terminateMode=CANCELLED → runSingleDispatch throws
503
+ // a PLAIN Error) never produces an 'AbortError', so the mirror would
504
+ // log a spurious dispatch failure for a correctly-cancelled run. Once
505
+ // the run's abort signal has fired, the run is already settling as
506
+ // cancelled / timed-out — every rejection still crossing the boundary
507
+ // is teardown noise regardless of its shape.
508
+ isRunAborted: /* @__PURE__ */ __name(() => opts.abortOnTimeout?.signal.aborted === true, "isRunAborted"),
491
509
  // The truthy flags distinguish "injected" from "default stub" inside the
492
510
  // init script without leaking the host function itself when not used.
493
511
  hasParallel: !!opts.parallel,
@@ -555,27 +573,318 @@ function createWorkflowSandbox(opts) {
555
573
  // those wrappers will produce vm-realm results); reject with a
556
574
  // freshly-constructed vm-realm Error so e.constructor.constructor
557
575
  // stays in the vm realm.
576
+ // Dispatch promises are ObservedPromise instances (a vm-realm
577
+ // Promise subclass). Its then override marks the result consumed
578
+ // and re-attaches the teardown observer to the derived promise, so
579
+ // script-derived chains (agent(...).then(...), await, and the
580
+ // ELEMENTS of static-combinator aggregates \u2014 everything that
581
+ // funnels through then) stay observed at every depth. The
582
+ // AGGREGATES of Promise.all/race/any are built by the native
583
+ // statics and never pass through the observed then, so those
584
+ // statics are wrapped explicitly below (observeAggregate).
585
+ // Without this, a correctly-cancelled run holding a pending derived
586
+ // chain fired a process-level unhandledRejection even though the
587
+ // bare dispatch promise was observed.
588
+ //
589
+ // Unconsumed rejections of an observed node are recorded through
590
+ // the bridge and mirrored into the run log at run settlement (a
591
+ // later consumption clears the record first) \u2014 a dispatch refused
592
+ // at the entry gate (budget / agent cap) or failing mid-run reaches
593
+ // no other surface, so without the mirror the failure leaves no
594
+ // log, alarm, or telemetry.
595
+ function mapDispatchError(hostErr) {
596
+ var msg;
597
+ try {
598
+ msg = (hostErr && hostErr.message != null)
599
+ ? String(hostErr.message)
600
+ : String(hostErr);
601
+ } catch (e) {
602
+ msg = '[unserializable rejection value]';
603
+ }
604
+ const vmErr = new Error(msg);
605
+ // Teardown discrimination at the host boundary \u2014 before the error
606
+ // is flattened into a vm-realm Error. Two shapes count as
607
+ // teardown: an error NAMED 'AbortError' (the scheduler's
608
+ // abortError() DOMException), and ANY rejection that crosses
609
+ // after the run's abort signal has fired \u2014 the dominant
610
+ // cancellation path rejects with a plain Error ('did not complete
611
+ // (terminate mode: CANCELLED).'), which a name-only match would
612
+ // mirror as a spurious dispatch failure on a correctly-cancelled
613
+ // run. Matching the name here (rather than the message text)
614
+ // still suppresses teardown noise without swallowing genuine
615
+ // failures whose message merely contains 'aborted' (e.g. a
616
+ // network-layer 'connection aborted by peer').
617
+ var isAbort = false;
618
+ try {
619
+ isAbort = !!(hostErr && hostErr.name === 'AbortError');
620
+ } catch (e) {
621
+ isAbort = false;
622
+ }
623
+ if (isAbort || __b.isRunAborted()) vmErr.__wfAbort = true;
624
+ vmErr.__wfDispatchFailed = true;
625
+ return vmErr;
626
+ }
627
+ function readFlag(value, name) {
628
+ try {
629
+ return !!(value && value[name]);
630
+ } catch (e) {
631
+ return false;
632
+ }
633
+ }
634
+ function observeDispatch(promise) {
635
+ // Direct native-then call: routing through ObservedPromise.then
636
+ // would mark the promise consumed and recurse the observer. The
637
+ // observer body must be exception-safe on ANY rejection value:
638
+ // a script handler can throw an exotic value (a message getter
639
+ // that throws, a Proxy with throwing traps), and an observer
640
+ // killed mid-body would turn the very rejection it watches into
641
+ // a process-level unhandledRejection \u2014 the exact failure class
642
+ // the observer exists to remove.
643
+ Promise.prototype.then.call(promise, undefined, function (err) {
644
+ if (promise.__wfConsumed) return;
645
+ // R11-30: also suppress on the run-level abort state, not just
646
+ // the rejection's own marker \u2014 a wrapped Promise.any aggregate
647
+ // rejects with a natively built AggregateError that carries
648
+ // neither marker, so teardown rejections of a correctly-
649
+ // cancelled run would still be mirrored when it is unconsumed.
650
+ if (readFlag(err, '__wfAbort') || __b.isRunAborted()) return;
651
+ var dispatchFailed = readFlag(err, '__wfDispatchFailed');
652
+ var errors = null;
653
+ try {
654
+ if (err && Array.isArray(err.errors)) errors = err.errors;
655
+ } catch (e) {
656
+ errors = null;
657
+ }
658
+ if (!dispatchFailed && errors) {
659
+ // R11-4: Promise.any rejects with a fresh vm-realm
660
+ // AggregateError carrying no flags; the element errors are
661
+ // reachable on .errors with their markers preserved. Derive
662
+ // the attribution from the causes instead of blaming the
663
+ // script for a dispatch failure.
664
+ for (var i = 0; i < errors.length; i++) {
665
+ if (readFlag(errors[i], '__wfDispatchFailed')) {
666
+ dispatchFailed = true;
667
+ break;
668
+ }
669
+ }
670
+ }
671
+ // R11-15: cross-root suppression \u2014 aggregate roots track
672
+ // rejectionHandled independently of their elements' roots, so
673
+ // a forwarded dispatch failure whose originating element root
674
+ // the script already handled must not mirror from the
675
+ // aggregate. The element rootId is stamped in vmAsync;
676
+ // Promise.all/race forward the element's own reason,
677
+ // Promise.any surfaces them on .errors.
678
+ try {
679
+ var sourceIds = [];
680
+ if (err && err.__wfRootId) {
681
+ sourceIds.push(err.__wfRootId);
682
+ } else if (errors) {
683
+ for (var j = 0; j < errors.length; j++) {
684
+ if (errors[j] && errors[j].__wfRootId) {
685
+ sourceIds.push(errors[j].__wfRootId);
686
+ }
687
+ }
688
+ }
689
+ for (var k = 0; k < sourceIds.length; k++) {
690
+ if (
691
+ sourceIds[k] !== promise.__wfRootId &&
692
+ __b.wfIsRootHandled(sourceIds[k])
693
+ ) {
694
+ return;
695
+ }
696
+ }
697
+ } catch (e) {
698
+ // A throwing exotic value must not kill the observer; fall
699
+ // through and mirror conservatively.
700
+ }
701
+ var msg;
702
+ try {
703
+ msg = String(err && err.message != null ? err.message : err);
704
+ } catch (e) {
705
+ msg = '[unserializable rejection value]';
706
+ }
707
+ promise.__wfUnconsumedId = __b.wfReportUnconsumed(
708
+ promise.__wfRootId,
709
+ promise.__wfIsRoot === true,
710
+ dispatchFailed,
711
+ msg,
712
+ );
713
+ });
714
+ }
715
+ // R11-3: await / Promise.resolve / returning a thenable from a
716
+ // handler adopts an ObservedPromise through this then with the
717
+ // adopting promise's capability (resolve, reject) pair \u2014 native
718
+ // functions, indistinguishable from real handlers by arity. They
719
+ // are detected by the native toString signature. Adoption
720
+ // CONSUMES the result (a delayed adoption clears a recorded
721
+ // verdict exactly like a delayed await) but is NOT a rejection
722
+ // handler: the rejection transfers into the adopting promise \u2014
723
+ // typically an async wrapper's implicit promise, which is a plain
724
+ // vm-realm Promise the mirror cannot observe. Marking adoption as
725
+ // handling would silently disarm the mirror for the forgotten-
726
+ // await failure class; the run-level escape hook in the host
727
+ // surfaces those escapes instead. Bound script functions also
728
+ // stringify as native code; misreading one as adoption only
729
+ // forgoes the rejectionHandled marking, never native semantics.
730
+ function isAdoptionAttach(handler) {
731
+ try {
732
+ return (
733
+ typeof handler === 'function' &&
734
+ Function.prototype.toString
735
+ .call(handler)
736
+ .indexOf('[native code]') !== -1
737
+ );
738
+ } catch (e) {
739
+ return false;
740
+ }
741
+ }
742
+ class ObservedPromise extends Promise {
743
+ then(onFulfilled, onRejected) {
744
+ // R11-26: introspect the handler BEFORE any state mutation.
745
+ // The read is guarded because a script-supplied handler can
746
+ // be exotic (a revoked Proxy wrapping a function, a throwing
747
+ // accessor) \u2014 an unguarded read made .then() throw
748
+ // synchronously, something native then never does, leaving
749
+ // the promise marked consumed with no handler attached.
750
+ var rethrows = false;
751
+ try {
752
+ rethrows = !!(onRejected && onRejected.__wfRethrows);
753
+ } catch (e) {
754
+ rethrows = false;
755
+ }
756
+ this.__wfConsumed = true;
757
+ // An attached rejection handler means the script can surface the
758
+ // root rejection itself; the mirror stays silent for it. The
759
+ // finally override below routes through this then with marked
760
+ // rethrow combinators \u2014 those re-raise the rejection instead of
761
+ // handling it, so they must NOT set the flag (marking them
762
+ // handled would silently drop a fire-and-forget
763
+ // agent(...).finally(...) failure). Adoption attaches count
764
+ // as consumption only, never handling (see isAdoptionAttach):
765
+ // they mark adoptedOut so forwarded sibling entries defer to
766
+ // the adopting chain / escape hook instead of mirroring.
767
+ if (isAdoptionAttach(onRejected)) {
768
+ __b.wfMarkAdopted(this.__wfRootId);
769
+ } else if (typeof onRejected === 'function' && !rethrows) {
770
+ __b.wfMarkRejectionHandled(this.__wfRootId);
771
+ }
772
+ // A delayed consumption clears a verdict recorded at
773
+ // rejection-settlement time, so a late-but-real await is not
774
+ // misreported as unconsumed.
775
+ if (this.__wfUnconsumedId !== undefined) {
776
+ __b.wfClearUnconsumed(this.__wfUnconsumedId);
777
+ this.__wfUnconsumedId = undefined;
778
+ }
779
+ const derived = super.then(onFulfilled, onRejected);
780
+ derived.__wfRootId = this.__wfRootId;
781
+ observeDispatch(derived);
782
+ return derived;
783
+ }
784
+ finally(onFinally) {
785
+ // Native Promise.prototype.finally calls the observed then with
786
+ // two function combinators, indistinguishable there from a real
787
+ // then(f, g) \u2014 which would mark the root rejection handled even
788
+ // though finally rethrows it. Implement finally through the
789
+ // observed then with an explicitly-marked rethrow combinator so
790
+ // the mirror stays armed for finally-only chains.
791
+ if (typeof onFinally !== 'function') {
792
+ return this.then(undefined, undefined);
793
+ }
794
+ const onRethrow = function (err) {
795
+ return Promise.resolve(onFinally()).then(function () {
796
+ throw err;
797
+ });
798
+ };
799
+ onRethrow.__wfRethrows = true;
800
+ return this.then(
801
+ function (value) {
802
+ return Promise.resolve(onFinally()).then(function () {
803
+ return value;
804
+ });
805
+ },
806
+ onRethrow,
807
+ );
808
+ }
809
+ }
810
+ // --- Static combinators: observe the aggregate promise ---
811
+ // Promise.all/race/any build their aggregate via the native static;
812
+ // it never passes through the observed then, so a fire-and-forget
813
+ // aggregate holding a failed dispatch would escape the run-log
814
+ // mirror. While the run is live the host's adoption-escape hook
815
+ // (R11-3) still catches and mirrors the process-level
816
+ // unhandledRejection \u2014 a round-14 A/B confirmed that hook, not
817
+ // this wrap, is the live-run backstop \u2014 but only with the coarse
818
+ // '(rejection not handled)' wording, and once the run's hook is
819
+ // detached nothing in the sandbox catches the escape. R14-A:
820
+ // wrapping the statics gives each aggregate its own observer, so
821
+ // consumption tracking works through the aggregate's own observed
822
+ // then (await / .catch / .then marks it handled) and the mirror
823
+ // itself classifies the rejection; the elements still funnel
824
+ // through the then override via the native static's internal
825
+ // attach, so they stay marked consumed.
826
+ function observeAggregate(nativeAggregate) {
827
+ const rootId = __b.wfRegisterRoot();
828
+ const observed = new ObservedPromise(function (resolve, reject) {
829
+ Promise.prototype.then.call(nativeAggregate, resolve, reject);
830
+ });
831
+ observed.__wfRootId = rootId;
832
+ observed.__wfIsRoot = true;
833
+ observeDispatch(observed);
834
+ return observed;
835
+ }
836
+ const nativePromiseAll = Promise.all;
837
+ const nativePromiseRace = Promise.race;
838
+ const nativePromiseAny = Promise.any;
839
+ // R11-16: a static called on a script-defined Promise subclass
840
+ // must honor the species contract and return a subclass instance,
841
+ // so non-default receivers bypass observation (their elements
842
+ // still funnel through the observed then, and a fire-and-forget
843
+ // dispatch failure escaping such an aggregate is still caught by
844
+ // the host's adoption-escape hook via its stamped markers).
845
+ Promise.all = function (items) {
846
+ if (this !== Promise) return nativePromiseAll.call(this, items);
847
+ return observeAggregate(nativePromiseAll.call(this, items));
848
+ };
849
+ Promise.race = function (items) {
850
+ if (this !== Promise) return nativePromiseRace.call(this, items);
851
+ return observeAggregate(nativePromiseRace.call(this, items));
852
+ };
853
+ Promise.any = function (items) {
854
+ if (this !== Promise) return nativePromiseAny.call(this, items);
855
+ return observeAggregate(nativePromiseAny.call(this, items));
856
+ };
558
857
  function vmAsync(hostFn) {
559
858
  return function (...vmArgs) {
560
- return new Promise(function (resolve, reject) {
859
+ const rootId = __b.wfRegisterRoot();
860
+ const p = new ObservedPromise(function (resolve, reject) {
861
+ function rejectMapped(hostErr) {
862
+ const vmErr = mapDispatchError(hostErr);
863
+ // Stamp the originating root and run BEFORE the error can
864
+ // be forwarded into aggregate promises: the observer's
865
+ // cross-root suppression (R11-15) reads __wfRootId and
866
+ // the host's adoption-escape hook (R11-3) attributes by
867
+ // __wfRunId.
868
+ try {
869
+ vmErr.__wfRootId = rootId;
870
+ vmErr.__wfRunId = __b.runId;
871
+ } catch (e) {}
872
+ reject(vmErr);
873
+ }
561
874
  try {
562
875
  const hostPromise = hostFn.apply(null, vmArgs);
563
876
  hostPromise.then(
564
877
  function (value) { resolve(value); },
565
- function (hostErr) {
566
- const msg = (hostErr && hostErr.message != null)
567
- ? String(hostErr.message)
568
- : String(hostErr);
569
- reject(new Error(msg));
570
- }
878
+ rejectMapped
571
879
  );
572
880
  } catch (hostErr) {
573
- const msg = (hostErr && hostErr.message != null)
574
- ? String(hostErr.message)
575
- : String(hostErr);
576
- reject(new Error(msg));
881
+ rejectMapped(hostErr);
577
882
  }
578
883
  });
884
+ p.__wfRootId = rootId;
885
+ p.__wfIsRoot = true;
886
+ observeDispatch(p);
887
+ return p;
579
888
  };
580
889
  }
581
890
 
@@ -873,46 +1182,208 @@ function createWorkflowSandbox(opts) {
873
1182
  { filename: "workflow-sandbox-init.js" }
874
1183
  );
875
1184
  const maxWallClockMs = resolveMaxWallClockMs(opts);
1185
+ const flushUnconsumedRejections = /* @__PURE__ */ __name(async () => {
1186
+ unconsumedSettled = true;
1187
+ if (nextUnconsumedId === 1) return;
1188
+ await new Promise((resolve) => {
1189
+ setImmediate(resolve);
1190
+ });
1191
+ for (const rec of unconsumedRejections.values()) {
1192
+ const rootState = unconsumedRoots.get(rec.rootId);
1193
+ if (rootState?.rejectionHandled) {
1194
+ continue;
1195
+ }
1196
+ if (rec.dispatchFailed && rootState?.adoptedOut) {
1197
+ continue;
1198
+ }
1199
+ const key = rec.rootId + "\0" + rec.msg;
1200
+ if (mirroredEscapeKeys.has(key)) continue;
1201
+ mirroredEscapeKeys.add(key);
1202
+ safeLog(unconsumedRejectionLine(rec));
1203
+ }
1204
+ unconsumedRejections.clear();
1205
+ }, "flushUnconsumedRejections");
1206
+ const hookRunId = opts.runId ?? "";
1207
+ const adoptionEscapeHook = /* @__PURE__ */ __name((reason, _promise) => {
1208
+ try {
1209
+ if (!reason || typeof reason !== "object") return;
1210
+ const marked = reason;
1211
+ if (marked.__wfDispatchFailed !== true) return;
1212
+ if (String(marked.__wfRunId ?? "") !== hookRunId) return;
1213
+ const rootId = typeof marked.__wfRootId === "number" ? marked.__wfRootId : void 0;
1214
+ if (rootId !== void 0 && unconsumedRoots.get(rootId)?.rejectionHandled) {
1215
+ return;
1216
+ }
1217
+ let msg;
1218
+ try {
1219
+ msg = marked.message != null ? String(marked.message) : String(reason);
1220
+ } catch {
1221
+ msg = "[unserializable rejection value]";
1222
+ }
1223
+ const key = String(rootId ?? "") + "\0" + msg;
1224
+ if (mirroredEscapeKeys.has(key)) return;
1225
+ mirroredEscapeKeys.add(key);
1226
+ safeLog("dispatch failed (rejection not handled): " + msg);
1227
+ } catch (e) {
1228
+ debugLogger.warn("adoptionEscapeHook failed:", e);
1229
+ }
1230
+ }, "adoptionEscapeHook");
876
1231
  let extractedMeta = null;
877
1232
  return {
878
1233
  async run(scriptSource) {
879
- const { stripped, meta } = extractAndStripMeta(scriptSource);
880
- extractedMeta = meta;
881
- const wrapped = `(async () => {
1234
+ unconsumedSettled = false;
1235
+ unconsumedRoots.clear();
1236
+ unconsumedRejections.clear();
1237
+ nextUnconsumedId = 1;
1238
+ mirroredEscapeKeys = /* @__PURE__ */ new Set();
1239
+ let watchdog;
1240
+ let stopWatchingState;
1241
+ let rearmWatchdogOnAbort;
1242
+ process.on("unhandledRejection", adoptionEscapeHook);
1243
+ try {
1244
+ const { stripped, meta } = extractAndStripMeta(scriptSource);
1245
+ extractedMeta = meta;
1246
+ const wrapped = `(async () => {
882
1247
  ${stripped}
883
1248
  })()`;
884
- const script = new vm.Script(wrapped, {
885
- filename: "workflow.js"
886
- });
887
- const runOpts = {
888
- timeout: 3e4
889
- };
890
- const result = script.runInContext(ctx, runOpts);
891
- let timer;
892
- const timeoutPromise = new Promise((_, reject) => {
893
- timer = setTimeout(() => {
894
- opts.abortOnTimeout?.abort();
895
- reject(
896
- new Error(
897
- `Workflow execution timed out after ${maxWallClockMs} ms wall clock. Override via SandboxOptions.maxWallClockMs or QWEN_CODE_MAX_WORKFLOW_SECONDS env var.`
898
- )
899
- );
900
- }, maxWallClockMs);
901
- timer.unref?.();
902
- });
903
- try {
1249
+ const script = new vm.Script(wrapped, {
1250
+ filename: "workflow.js"
1251
+ });
1252
+ const runOpts = {
1253
+ timeout: 3e4
1254
+ };
1255
+ const result = script.runInContext(ctx, runOpts);
1256
+ const timeoutPromise = new Promise((_, reject) => {
1257
+ watchdog = new WallClockWatchdog(maxWallClockMs, () => {
1258
+ opts.abortOnTimeout?.abort();
1259
+ reject(
1260
+ new Error(
1261
+ `Workflow execution exceeded ${maxWallClockMs} ms of active time (paused time is not counted). Override via SandboxOptions.maxWallClockMs or QWEN_CODE_MAX_WORKFLOW_SECONDS env var.`
1262
+ )
1263
+ );
1264
+ });
1265
+ });
1266
+ const aborted = /* @__PURE__ */ __name(() => opts.abortOnTimeout?.signal.aborted === true, "aborted");
1267
+ stopWatchingState = opts.scheduler?.onStateChange(({ state }) => {
1268
+ if (state === "paused" && !aborted()) watchdog?.pause();
1269
+ else watchdog?.resume();
1270
+ });
1271
+ if (opts.scheduler?.snapshot().state === "paused" && !aborted()) {
1272
+ watchdog?.pause();
1273
+ }
1274
+ rearmWatchdogOnAbort = /* @__PURE__ */ __name(() => watchdog?.resume(), "rearmWatchdogOnAbort");
1275
+ opts.abortOnTimeout?.signal.addEventListener(
1276
+ "abort",
1277
+ rearmWatchdogOnAbort,
1278
+ { once: true }
1279
+ );
904
1280
  return await Promise.race([result, timeoutPromise]);
905
1281
  } finally {
906
- if (timer !== void 0) clearTimeout(timer);
1282
+ if (rearmWatchdogOnAbort) {
1283
+ opts.abortOnTimeout?.signal.removeEventListener(
1284
+ "abort",
1285
+ rearmWatchdogOnAbort
1286
+ );
1287
+ }
1288
+ stopWatchingState?.();
1289
+ watchdog?.stop();
1290
+ await flushUnconsumedRejections();
1291
+ process.off("unhandledRejection", adoptionEscapeHook);
907
1292
  }
908
1293
  },
909
1294
  getPhases: /* @__PURE__ */ __name(() => [...phases], "getPhases"),
910
1295
  getLogs: /* @__PURE__ */ __name(() => [...logs], "getLogs"),
1296
+ appendLog: /* @__PURE__ */ __name((line) => safeLog(line), "appendLog"),
911
1297
  getMeta: /* @__PURE__ */ __name(() => extractedMeta, "getMeta")
912
1298
  };
913
1299
  }
914
1300
  __name(createWorkflowSandbox, "createWorkflowSandbox");
915
1301
 
1302
+ // packages/core/src/agents/runtime/workflow-budget.ts
1303
+ init_esbuild_shims();
1304
+ var debugLogger2 = createDebugLogger("WORKFLOW_BUDGET");
1305
+ var MAX_TOKENS_PER_WORKFLOW_ENV = "QWEN_CODE_MAX_TOKENS_PER_WORKFLOW";
1306
+ var HARD_MAX_TOKENS_CEILING = 1e8;
1307
+ function resolveMaxTokensPerWorkflow(env = process.env) {
1308
+ const raw = env[MAX_TOKENS_PER_WORKFLOW_ENV];
1309
+ if (raw === void 0 || raw.trim() === "") {
1310
+ return null;
1311
+ }
1312
+ const parsed = parsePositiveIntegerEnv(raw, 0);
1313
+ if (parsed < 1) {
1314
+ debugLogger2.warn(
1315
+ `Invalid ${MAX_TOKENS_PER_WORKFLOW_ENV}=${JSON.stringify(raw)}, treating as unset (no cap)`
1316
+ );
1317
+ return null;
1318
+ }
1319
+ if (parsed > HARD_MAX_TOKENS_CEILING) {
1320
+ debugLogger2.warn(
1321
+ `${MAX_TOKENS_PER_WORKFLOW_ENV}=${parsed} exceeds hard ceiling (${HARD_MAX_TOKENS_CEILING}); clamping.`
1322
+ );
1323
+ return HARD_MAX_TOKENS_CEILING;
1324
+ }
1325
+ return parsed;
1326
+ }
1327
+ __name(resolveMaxTokensPerWorkflow, "resolveMaxTokensPerWorkflow");
1328
+ var WorkflowBudgetImpl = class _WorkflowBudgetImpl {
1329
+ static {
1330
+ __name(this, "WorkflowBudgetImpl");
1331
+ }
1332
+ total;
1333
+ _spent;
1334
+ constructor(total) {
1335
+ this.total = total;
1336
+ this._spent = 0;
1337
+ }
1338
+ spent() {
1339
+ return this._spent;
1340
+ }
1341
+ remaining() {
1342
+ if (this.total === null) return Infinity;
1343
+ return Math.max(0, this.total - this._spent);
1344
+ }
1345
+ /**
1346
+ * Host-side increment. NOT exposed to the script — the
1347
+ * `WorkflowBudget` interface deliberately omits any setter so a
1348
+ * malicious workflow cannot inflate / deflate the budget. Only the
1349
+ * orchestrator (in `countedDispatch`) calls this after a dispatch
1350
+ * resolves with the agent's output token count.
1351
+ *
1352
+ * Non-positive deltas are silently dropped (some dispatches return
1353
+ * `output_tokens: 0` on early failures); negative deltas would be a
1354
+ * caller bug and are also dropped rather than silently rewinding
1355
+ * the counter.
1356
+ */
1357
+ recordSpent(deltaTokens) {
1358
+ if (!Number.isFinite(deltaTokens) || deltaTokens <= 0) return;
1359
+ this._spent += deltaTokens;
1360
+ }
1361
+ /**
1362
+ * Factory: build a budget from the current environment. Convenience
1363
+ * over `new WorkflowBudgetImpl(resolveMaxTokensPerWorkflow(env))`.
1364
+ */
1365
+ static fromEnv(env = process.env) {
1366
+ return new _WorkflowBudgetImpl(resolveMaxTokensPerWorkflow(env));
1367
+ }
1368
+ };
1369
+ var WorkflowBudgetExceededError = class extends Error {
1370
+ static {
1371
+ __name(this, "WorkflowBudgetExceededError");
1372
+ }
1373
+ name = "WorkflowBudgetExceededError";
1374
+ runId;
1375
+ budgetTotal;
1376
+ spent;
1377
+ constructor(runId, budgetTotal, spent) {
1378
+ super(
1379
+ `Workflow ${runId} exceeded the token budget (${spent} / ${budgetTotal} output tokens spent).`
1380
+ );
1381
+ this.runId = runId;
1382
+ this.budgetTotal = budgetTotal;
1383
+ this.spent = spent;
1384
+ }
1385
+ };
1386
+
916
1387
  // packages/core/src/agents/runtime/workflow-stall.ts
917
1388
  init_esbuild_shims();
918
1389
  var DEFAULT_STALL_MS = 6e4;
@@ -1144,58 +1615,122 @@ init_esbuild_shims();
1144
1615
  var WORKFLOW_SUBAGENT_SYSTEM_PROMPT = 'You are a subagent spawned by a workflow orchestration script. Use the tools available to complete the task.\nCRITICAL: Your final text response is returned **verbatim** as a string to the calling script \u2014 it is your return value, not a message to a human.\n- Output the literal result (data, JSON, text). Do NOT output confirmations like "Done." or "Sent."\n- If asked for JSON, return ONLY the raw JSON \u2014 no code fences, no prose, no markdown.\n- Do NOT use SendUserMessage to deliver your answer. Put your answer in your final text response.\n- Be concise. The script will parse your output.';
1145
1616
  var WORKFLOW_SUBAGENT_SYSTEM_PROMPT_WITH_SCHEMA = "You are a subagent spawned by a workflow orchestration script. Use the tools available to complete the task.\nCRITICAL: You MUST deliver your final answer by calling the `structured_output` tool with arguments that conform to its parameter schema. Plain-text final answers are DISCARDED \u2014 only a valid `structured_output` call returns a result to the calling script.\n- Use other tools (Read, Grep, etc.) to gather information first.\n- When ready, call `structured_output` ONCE with the conforming JSON object.\n- If validation fails, the error tells you what to fix. Try again with corrected fields.\n- After two failed attempts, the run terminates \u2014 get the arguments right.\n- Do NOT use SendUserMessage to deliver your answer.\n- Be concise; the script reads only the structured payload, not your prose.";
1146
1617
 
1147
- // packages/core/src/utils/concurrencyLimiter.ts
1618
+ // packages/core/src/agents/runtime/workflow-dispatch-scheduler.ts
1148
1619
  init_esbuild_shims();
1149
1620
  function abortError() {
1150
- return new DOMException("Concurrency limiter aborted.", "AbortError");
1621
+ return new DOMException("Workflow dispatch scheduler aborted.", "AbortError");
1151
1622
  }
1152
1623
  __name(abortError, "abortError");
1153
- function createConcurrencyLimiter(limit, signal) {
1154
- if (!Number.isInteger(limit) || limit < 1) {
1155
- throw new Error(
1156
- `Concurrency limit must be a positive integer, got ${String(limit)}.`
1157
- );
1624
+ var WorkflowDispatchScheduler = class {
1625
+ constructor(limit, signal, onStateChange) {
1626
+ this.limit = limit;
1627
+ this.signal = signal;
1628
+ if (!Number.isInteger(limit) || limit < 1) {
1629
+ throw new Error(
1630
+ `Workflow dispatch limit must be a positive integer, got ${String(limit)}.`
1631
+ );
1632
+ }
1633
+ if (onStateChange) this.stateListeners.add(onStateChange);
1634
+ if (signal && !signal.aborted) {
1635
+ signal.addEventListener("abort", () => this.abortPending(), {
1636
+ once: true
1637
+ });
1638
+ }
1639
+ }
1640
+ static {
1641
+ __name(this, "WorkflowDispatchScheduler");
1642
+ }
1643
+ state = "running";
1644
+ inFlight = 0;
1645
+ queue = [];
1646
+ gateWaiters = [];
1647
+ stateListeners = /* @__PURE__ */ new Set();
1648
+ /**
1649
+ * Subscribe to state transitions. Returns an unsubscribe function.
1650
+ * The constructor callback (when given) is registered as the first
1651
+ * listener; this method lets additional observers — e.g. the sandbox's
1652
+ * pause-aware wall-clock watchdog — hook the same transitions.
1653
+ */
1654
+ onStateChange(listener) {
1655
+ this.stateListeners.add(listener);
1656
+ return () => {
1657
+ this.stateListeners.delete(listener);
1658
+ };
1659
+ }
1660
+ run(thunk) {
1661
+ return new Promise((resolve, reject) => {
1662
+ if (this.signal?.aborted) {
1663
+ reject(abortError());
1664
+ return;
1665
+ }
1666
+ this.queue.push({
1667
+ thunk,
1668
+ resolve,
1669
+ reject
1670
+ });
1671
+ this.pump();
1672
+ });
1673
+ }
1674
+ pause() {
1675
+ if (this.state !== "running" || this.signal?.aborted) return false;
1676
+ this.setState("pausing");
1677
+ if (this.inFlight === 0) this.setState("paused");
1678
+ return true;
1679
+ }
1680
+ resume() {
1681
+ if (this.state !== "paused" || this.signal?.aborted) return false;
1682
+ this.setState("running");
1683
+ while (this.gateWaiters.length > 0) {
1684
+ this.gateWaiters.shift().resolve();
1685
+ }
1686
+ this.pump();
1687
+ return true;
1688
+ }
1689
+ waitUntilRunning() {
1690
+ if (this.signal?.aborted) return Promise.reject(abortError());
1691
+ if (this.state === "running") return Promise.resolve();
1692
+ return new Promise((resolve, reject) => {
1693
+ this.gateWaiters.push({ resolve, reject });
1694
+ });
1695
+ }
1696
+ snapshot() {
1697
+ return {
1698
+ state: this.state,
1699
+ queued: this.queue.length,
1700
+ inFlight: this.inFlight
1701
+ };
1158
1702
  }
1159
- let active = 0;
1160
- const queue = [];
1161
- const pump = /* @__PURE__ */ __name(() => {
1162
- while (active < limit && queue.length > 0) {
1163
- const job = queue.shift();
1164
- if (signal?.aborted) {
1703
+ pump() {
1704
+ while (this.state === "running" && this.inFlight < this.limit && this.queue.length > 0) {
1705
+ const job = this.queue.shift();
1706
+ if (this.signal?.aborted) {
1165
1707
  job.reject(abortError());
1166
1708
  continue;
1167
1709
  }
1168
- active++;
1710
+ this.inFlight++;
1169
1711
  Promise.resolve().then(job.thunk).then(job.resolve, job.reject).finally(() => {
1170
- active--;
1171
- pump();
1712
+ this.inFlight--;
1713
+ if (this.state === "pausing" && this.inFlight === 0) {
1714
+ this.setState("paused");
1715
+ }
1716
+ this.pump();
1172
1717
  });
1173
1718
  }
1174
- }, "pump");
1175
- const run = /* @__PURE__ */ __name((thunk) => new Promise((resolve, reject) => {
1176
- if (signal?.aborted) {
1177
- reject(abortError());
1178
- return;
1719
+ }
1720
+ setState(state) {
1721
+ if (this.state === state) return;
1722
+ this.state = state;
1723
+ const snapshot = this.snapshot();
1724
+ for (const listener of [...this.stateListeners]) listener(snapshot);
1725
+ }
1726
+ abortPending() {
1727
+ const error = abortError();
1728
+ while (this.queue.length > 0) this.queue.shift().reject(error);
1729
+ while (this.gateWaiters.length > 0) {
1730
+ this.gateWaiters.shift().reject(error);
1179
1731
  }
1180
- queue.push({
1181
- thunk,
1182
- resolve,
1183
- reject
1184
- });
1185
- pump();
1186
- }), "run");
1187
- if (signal && !signal.aborted) {
1188
- signal.addEventListener(
1189
- "abort",
1190
- () => {
1191
- while (queue.length > 0) queue.shift().reject(abortError());
1192
- },
1193
- { once: true }
1194
- );
1195
1732
  }
1196
- return { run };
1197
- }
1198
- __name(createConcurrencyLimiter, "createConcurrencyLimiter");
1733
+ };
1199
1734
 
1200
1735
  // packages/core/src/agents/runtime/workflow-orchestrator.ts
1201
1736
  var DEFAULT_MAX_AGENTS_PER_RUN = 1e3;
@@ -1208,13 +1743,13 @@ function resolveMaxAgentsPerRun(env = process.env) {
1208
1743
  }
1209
1744
  const parsed = parsePositiveIntegerEnv(raw, 0);
1210
1745
  if (parsed < 1) {
1211
- debugLogger2.warn(
1746
+ debugLogger.warn(
1212
1747
  `Invalid ${MAX_WORKFLOW_AGENTS_ENV}=${JSON.stringify(raw)}, using default (${DEFAULT_MAX_AGENTS_PER_RUN})`
1213
1748
  );
1214
1749
  return DEFAULT_MAX_AGENTS_PER_RUN;
1215
1750
  }
1216
1751
  if (parsed > HARD_MAX_AGENTS_PER_RUN_CEILING) {
1217
- debugLogger2.warn(
1752
+ debugLogger.warn(
1218
1753
  `${MAX_WORKFLOW_AGENTS_ENV}=${parsed} exceeds hard ceiling (${HARD_MAX_AGENTS_PER_RUN_CEILING}); clamping.`
1219
1754
  );
1220
1755
  return HARD_MAX_AGENTS_PER_RUN_CEILING;
@@ -1230,14 +1765,14 @@ function resolveConcurrencyLimit(env = process.env) {
1230
1765
  const parsed = parsePositiveIntegerEnv(raw, 0);
1231
1766
  if (parsed >= 1) {
1232
1767
  if (parsed > HARD_MAX_CONCURRENCY_CEILING) {
1233
- debugLogger2.warn(
1768
+ debugLogger.warn(
1234
1769
  `${MAX_WORKFLOW_CONCURRENCY_ENV}=${parsed} exceeds hard ceiling (${HARD_MAX_CONCURRENCY_CEILING}); clamping.`
1235
1770
  );
1236
1771
  return HARD_MAX_CONCURRENCY_CEILING;
1237
1772
  }
1238
1773
  return parsed;
1239
1774
  }
1240
- debugLogger2.warn(
1775
+ debugLogger.warn(
1241
1776
  `Invalid ${MAX_WORKFLOW_CONCURRENCY_ENV}=${JSON.stringify(raw)}, using cpu-derived default`
1242
1777
  );
1243
1778
  }
@@ -1310,11 +1845,11 @@ function createProductionDispatch(config, signal, onTokens, bridgeApprovalEvents
1310
1845
  }
1311
1846
  __name(createProductionDispatch, "createProductionDispatch");
1312
1847
  async function runSingleDispatch(config, prompt, opts, attemptSignal, emitter, onTokens) {
1313
- const { AgentHeadless, ContextState } = await import("./agent-headless-PR7YCB7S.js");
1848
+ const { AgentHeadless, ContextState } = await import("./agent-headless-XXGY2SQO.js");
1314
1849
  const ctx = new ContextState();
1315
1850
  ctx.set("task_prompt", prompt);
1316
1851
  const workflowAgentId = `workflow-agent-${randomBytes(8).toString("hex")}`;
1317
- debugLogger2.debug(`[workflow] Dispatch ${workflowAgentId}`);
1852
+ debugLogger.debug(`[workflow] Dispatch ${workflowAgentId}`);
1318
1853
  if (opts.agentType === void 0 && opts.model === void 0 && opts.isolation === void 0 && opts.schema === void 0) {
1319
1854
  const subagent = await AgentHeadless.create(
1320
1855
  opts.label ?? "workflow-agent",
@@ -1372,7 +1907,7 @@ function reportTokens(subagent, opts, onTokens) {
1372
1907
  const summary = subagent.getExecutionSummary();
1373
1908
  onTokens(summary.outputTokens, opts);
1374
1909
  } catch (e) {
1375
- debugLogger2.warn("onTokens callback threw:", e);
1910
+ debugLogger.warn("onTokens callback threw:", e);
1376
1911
  }
1377
1912
  }
1378
1913
  __name(reportTokens, "reportTokens");
@@ -1491,7 +2026,7 @@ ${WORKFLOW_SUBAGENT_SYSTEM_PROMPT_WITH_SCHEMA}` : WORKFLOW_SUBAGENT_SYSTEM_PROMP
1491
2026
  worktreeIsolation = null;
1492
2027
  const preserved = await cleanupWorkflowWorktree(isolation);
1493
2028
  if (preserved) {
1494
- debugLogger2.info(
2029
+ debugLogger.info(
1495
2030
  `[Workflow] Schema-mode subagent preserved worktree at ${preserved.path ?? "(directory removed)"} on branch ${preserved.branch}. The structured payload is returned verbatim; recover the work from the preserved path / branch.`
1496
2031
  );
1497
2032
  }
@@ -1546,7 +2081,7 @@ ${WORKFLOW_SUBAGENT_SYSTEM_PROMPT_WITH_SCHEMA}` : WORKFLOW_SUBAGENT_SYSTEM_PROMP
1546
2081
  try {
1547
2082
  await cleanupWorkflowWorktree(worktreeIsolation);
1548
2083
  } catch (error) {
1549
- debugLogger2.warn(
2084
+ debugLogger.warn(
1550
2085
  `Workflow worktree cleanup in fallback finally failed for ${worktreeIsolation.path}: ${error instanceof Error ? error.message : String(error)}`
1551
2086
  );
1552
2087
  }
@@ -1579,7 +2114,7 @@ async function provisionWorkflowWorktree(config) {
1579
2114
  try {
1580
2115
  parentDirty = await wtService.hasWorktreeChanges(projectRoot);
1581
2116
  } catch (error) {
1582
- debugLogger2.warn(
2117
+ debugLogger.warn(
1583
2118
  `[Workflow] hasWorktreeChanges failed at ${projectRoot}: ${error}`
1584
2119
  );
1585
2120
  parentDirty = true;
@@ -1594,7 +2129,7 @@ async function provisionWorkflowWorktree(config) {
1594
2129
  try {
1595
2130
  parentBranch = await wtService.getCurrentBranch();
1596
2131
  } catch (error) {
1597
- debugLogger2.warn(
2132
+ debugLogger.warn(
1598
2133
  `[Workflow] getCurrentBranch failed at ${projectRoot}: ${error}`
1599
2134
  );
1600
2135
  }
@@ -1612,7 +2147,7 @@ async function provisionWorkflowWorktree(config) {
1612
2147
  config.getSessionId()
1613
2148
  );
1614
2149
  } catch (error) {
1615
- debugLogger2.warn(
2150
+ debugLogger.warn(
1616
2151
  `[Workflow] failed to write session marker at ${created.worktree.path}: ${error}`
1617
2152
  );
1618
2153
  }
@@ -1645,20 +2180,20 @@ async function cleanupWorkflowWorktree(isolation) {
1645
2180
  const wtService = new GitWorktreeService(isolation.repoRoot);
1646
2181
  const [hasChanges, hasUnmerged] = await Promise.all([
1647
2182
  wtService.hasWorktreeChanges(isolation.path).catch((error) => {
1648
- debugLogger2.warn(
2183
+ debugLogger.warn(
1649
2184
  `[Workflow] hasWorktreeChanges failed for ${isolation.path}: ${error}`
1650
2185
  );
1651
2186
  return true;
1652
2187
  }),
1653
2188
  wtService.hasUnmergedWorktreeCommits(isolation.slug).catch((error) => {
1654
- debugLogger2.warn(
2189
+ debugLogger.warn(
1655
2190
  `[Workflow] hasUnmergedWorktreeCommits failed for ${isolation.slug}: ${error}`
1656
2191
  );
1657
2192
  return true;
1658
2193
  })
1659
2194
  ]);
1660
2195
  if (hasChanges || hasUnmerged) {
1661
- debugLogger2.info(
2196
+ debugLogger.info(
1662
2197
  `[Workflow] Preserving isolation worktree ${isolation.path} (branch ${isolation.branch}, hasChanges=${hasChanges}, hasUnmerged=${hasUnmerged})`
1663
2198
  );
1664
2199
  return { path: isolation.path, branch: isolation.branch };
@@ -1668,19 +2203,19 @@ async function cleanupWorkflowWorktree(isolation) {
1668
2203
  deleteBranch: true
1669
2204
  });
1670
2205
  if (!result.success) {
1671
- debugLogger2.warn(
2206
+ debugLogger.warn(
1672
2207
  `[Workflow] Failed to remove ephemeral worktree ${isolation.path}: ${result.error}`
1673
2208
  );
1674
2209
  return { path: isolation.path, branch: isolation.branch };
1675
2210
  }
1676
2211
  if (result.branchPreserved) {
1677
- debugLogger2.warn(
2212
+ debugLogger.warn(
1678
2213
  `[Workflow] Removed worktree directory ${isolation.path} but kept branch ${isolation.branch} (unmerged commits at delete time)`
1679
2214
  );
1680
2215
  return { branch: isolation.branch };
1681
2216
  }
1682
2217
  } catch (error) {
1683
- debugLogger2.warn(
2218
+ debugLogger.warn(
1684
2219
  `[Workflow] Failed to remove ephemeral worktree ${isolation.path}: ${error}`
1685
2220
  );
1686
2221
  return { path: isolation.path, branch: isolation.branch };
@@ -1748,7 +2283,15 @@ var WorkflowOrchestrator = class {
1748
2283
  const runId = req.runId ?? generateRunId();
1749
2284
  const maxAgents = resolveMaxAgentsPerRun();
1750
2285
  const signal = req.abortOnTimeout?.signal;
1751
- const limiter = createConcurrencyLimiter(resolveConcurrencyLimit(), signal);
2286
+ const scheduler = req.scheduler ?? new WorkflowDispatchScheduler(resolveConcurrencyLimit(), signal);
2287
+ const rejectThroughPauseGate = /* @__PURE__ */ __name((error) => scheduler.waitUntilRunning().then(
2288
+ () => {
2289
+ throw error;
2290
+ },
2291
+ () => {
2292
+ throw error;
2293
+ }
2294
+ ), "rejectThroughPauseGate");
1752
2295
  let agentCount = 0;
1753
2296
  const emitter = req.emitter;
1754
2297
  const budget = req.budget;
@@ -1768,7 +2311,7 @@ var WorkflowOrchestrator = class {
1768
2311
  if (cached !== void 0) {
1769
2312
  const respawns = replay.started.get(journalKey);
1770
2313
  if (respawns && respawns.length > 0) {
1771
- debugLogger2.info(
2314
+ debugLogger.info(
1772
2315
  `[Workflow] resume cache hit after ${respawns.length} prior respawn(s) for runId=${runId}.`
1773
2316
  );
1774
2317
  }
@@ -1776,33 +2319,36 @@ var WorkflowOrchestrator = class {
1776
2319
  try {
1777
2320
  emitter?.agentDispatched?.(label2);
1778
2321
  } catch (e) {
1779
- debugLogger2.warn("emitter.agentDispatched threw:", e);
2322
+ debugLogger.warn("emitter.agentDispatched threw:", e);
1780
2323
  }
1781
2324
  try {
1782
2325
  emitter?.agentCompleted?.(label2);
1783
2326
  } catch (e) {
1784
- debugLogger2.warn("emitter.agentCompleted threw:", e);
2327
+ debugLogger.warn("emitter.agentCompleted threw:", e);
1785
2328
  }
1786
- return Promise.resolve(cached.result);
2329
+ return scheduler.waitUntilRunning().then(
2330
+ () => cached.result,
2331
+ () => cached.result
2332
+ );
1787
2333
  }
1788
2334
  }
1789
2335
  hadMiss = true;
1790
2336
  journalEntryId = String(journalAgentId += 1);
1791
2337
  journal.append({ type: "started", key: journalKey, agentId: journalEntryId }).catch(
1792
- (e) => debugLogger2.warn(`journal started-append failed: ${e}`)
2338
+ (e) => debugLogger.warn(`journal started-append failed: ${e}`)
1793
2339
  );
1794
2340
  }
1795
2341
  if (budget && budget.total !== null && budget.remaining() <= 0) {
1796
- debugLogger2.warn(
2342
+ debugLogger.warn(
1797
2343
  `[Workflow] budget gate refused dispatch at entry: runId=${runId} spent=${budget.spent()} total=${budget.total}`
1798
2344
  );
1799
- return Promise.reject(
2345
+ return rejectThroughPauseGate(
1800
2346
  new WorkflowBudgetExceededError(runId, budget.total, budget.spent())
1801
2347
  );
1802
2348
  }
1803
2349
  agentCount += 1;
1804
2350
  if (agentCount > maxAgents) {
1805
- return Promise.reject(
2351
+ return rejectThroughPauseGate(
1806
2352
  new Error(
1807
2353
  `Workflow exceeded the maximum of ${maxAgents} agent() calls per run.`
1808
2354
  )
@@ -1812,27 +2358,33 @@ var WorkflowOrchestrator = class {
1812
2358
  try {
1813
2359
  emitter?.agentDispatched?.(label);
1814
2360
  } catch (e) {
1815
- debugLogger2.warn("emitter.agentDispatched threw:", e);
2361
+ debugLogger.warn("emitter.agentDispatched threw:", e);
1816
2362
  }
1817
- return limiter.run(() => {
1818
- if (budget && budget.total !== null && budget.remaining() <= 0) {
1819
- debugLogger2.warn(
1820
- `[Workflow] budget gate refused dispatch at slot-acquire: runId=${runId} spent=${budget.spent()} total=${budget.total}`
1821
- );
1822
- throw new WorkflowBudgetExceededError(
1823
- runId,
1824
- budget.total,
1825
- budget.spent()
1826
- );
2363
+ let completionEmitted = false;
2364
+ const emitCompletion = /* @__PURE__ */ __name((error) => {
2365
+ if (completionEmitted) return;
2366
+ completionEmitted = true;
2367
+ const message = error === void 0 ? void 0 : error instanceof Error ? error.message : String(error);
2368
+ try {
2369
+ emitter?.agentCompleted?.(label, message);
2370
+ } catch (e) {
2371
+ debugLogger.warn("emitter.agentCompleted threw:", e);
1827
2372
  }
1828
- return this.dispatch(prompt, opts);
1829
- }).then(
1830
- (result) => {
1831
- try {
1832
- emitter?.agentCompleted?.(label);
1833
- } catch (e) {
1834
- debugLogger2.warn("emitter.agentCompleted threw:", e);
2373
+ }, "emitCompletion");
2374
+ return scheduler.run(async () => {
2375
+ try {
2376
+ if (budget && budget.total !== null && budget.remaining() <= 0) {
2377
+ debugLogger.warn(
2378
+ `[Workflow] budget gate refused dispatch at slot-acquire: runId=${runId} spent=${budget.spent()} total=${budget.total}`
2379
+ );
2380
+ throw new WorkflowBudgetExceededError(
2381
+ runId,
2382
+ budget.total,
2383
+ budget.spent()
2384
+ );
1835
2385
  }
2386
+ const result = await this.dispatch(prompt, opts);
2387
+ emitCompletion();
1836
2388
  if (journal && journalKey !== void 0) {
1837
2389
  journal.append({
1838
2390
  type: "result",
@@ -1840,63 +2392,92 @@ var WorkflowOrchestrator = class {
1840
2392
  agentId: journalEntryId ?? "",
1841
2393
  result
1842
2394
  }).catch(
1843
- (e) => debugLogger2.warn(`journal result-append failed: ${e}`)
2395
+ (e) => debugLogger.warn(`journal result-append failed: ${e}`)
1844
2396
  );
1845
2397
  }
1846
2398
  if (budget) {
1847
2399
  try {
1848
2400
  emitter?.budgetUpdated?.(budget.spent(), budget.total);
1849
2401
  } catch (e) {
1850
- debugLogger2.warn("emitter.budgetUpdated threw:", e);
2402
+ debugLogger.warn("emitter.budgetUpdated threw:", e);
1851
2403
  }
1852
2404
  }
1853
2405
  return result;
1854
- },
1855
- (err) => {
1856
- const msg = err instanceof Error ? err.message : String(err);
1857
- try {
1858
- emitter?.agentCompleted?.(label, msg);
1859
- } catch (e) {
1860
- debugLogger2.warn("emitter.agentCompleted threw:", e);
1861
- }
2406
+ } catch (err) {
2407
+ emitCompletion(err);
1862
2408
  if (budget) {
1863
2409
  try {
1864
2410
  emitter?.budgetUpdated?.(budget.spent(), budget.total);
1865
2411
  } catch (e) {
1866
- debugLogger2.warn("emitter.budgetUpdated threw:", e);
2412
+ debugLogger.warn("emitter.budgetUpdated threw:", e);
1867
2413
  }
1868
2414
  }
1869
2415
  throw err;
1870
2416
  }
2417
+ }).then(
2418
+ // Resolve even if the gate aborts: a successful dispatch must not
2419
+ // turn into a teardown rejection — for a fire-and-forget call the
2420
+ // script never attached a handler, so the rejection would surface
2421
+ // as a spurious process-level unhandledRejection alarm on a
2422
+ // correctly-cancelled run.
2423
+ (result) => scheduler.waitUntilRunning().then(
2424
+ () => result,
2425
+ () => result
2426
+ ),
2427
+ (error) => {
2428
+ emitCompletion(error);
2429
+ return scheduler.waitUntilRunning().then(
2430
+ () => {
2431
+ throw error;
2432
+ },
2433
+ () => {
2434
+ throw error;
2435
+ }
2436
+ );
2437
+ }
1871
2438
  );
1872
2439
  }, "countedDispatch");
1873
2440
  const parallelImpl = makeParallelImpl(signal);
1874
2441
  const pipelineImpl = makePipelineImpl(signal);
1875
2442
  const resolveSavedWorkflow = req.resolveSavedWorkflow;
2443
+ const parentSandboxRef = {
2444
+ current: void 0
2445
+ };
1876
2446
  const workflowImpl = resolveSavedWorkflow ? async (nameOrRef, nestedArgs) => {
1877
2447
  const resolved = await resolveSavedWorkflow(nameOrRef);
1878
2448
  const nestedSandbox = createWorkflowSandbox({
1879
2449
  args: nestedArgs,
2450
+ runId,
1880
2451
  dispatch: countedDispatch,
1881
2452
  parallel: parallelImpl,
1882
2453
  pipeline: pipelineImpl,
1883
2454
  abortOnTimeout: req.abortOnTimeout,
1884
2455
  emitter,
1885
- budget
2456
+ budget,
2457
+ scheduler
1886
2458
  // No `workflow` — single-level nesting limit.
1887
2459
  });
1888
- return nestedSandbox.run(resolved.script);
2460
+ try {
2461
+ return await nestedSandbox.run(resolved.script);
2462
+ } finally {
2463
+ for (const line of nestedSandbox.getLogs()) {
2464
+ parentSandboxRef.current?.appendLog(line);
2465
+ }
2466
+ }
1889
2467
  } : void 0;
1890
2468
  const sandbox = createWorkflowSandbox({
1891
2469
  args: req.args,
2470
+ runId,
1892
2471
  dispatch: countedDispatch,
1893
2472
  parallel: parallelImpl,
1894
2473
  pipeline: pipelineImpl,
1895
2474
  workflow: workflowImpl,
1896
2475
  abortOnTimeout: req.abortOnTimeout,
1897
2476
  emitter,
1898
- budget
2477
+ budget,
2478
+ scheduler
1899
2479
  });
2480
+ parentSandboxRef.current = sandbox;
1900
2481
  try {
1901
2482
  const result = await sandbox.run(req.script);
1902
2483
  return {
@@ -1929,14 +2510,14 @@ async function settleToNullArray(thunks, signal, kind = "parallel") {
1929
2510
  if (reason?.name === "WorkflowBudgetExceededError") {
1930
2511
  budgetDropped += 1;
1931
2512
  } else {
1932
- debugLogger2.warn(
2513
+ debugLogger.warn(
1933
2514
  `Workflow thunk at index ${i} rejected: ${String(reason?.message ?? r.reason)}`
1934
2515
  );
1935
2516
  }
1936
2517
  return null;
1937
2518
  });
1938
2519
  if (budgetDropped > 0) {
1939
- debugLogger2.warn(
2520
+ debugLogger.warn(
1940
2521
  `${kind}: ${budgetDropped} slot${budgetDropped === 1 ? "" : "s"} dropped \u2014 token budget exceeded.`
1941
2522
  );
1942
2523
  }
@@ -2010,12 +2591,15 @@ function extractErrorMessage(err) {
2010
2591
  __name(extractErrorMessage, "extractErrorMessage");
2011
2592
 
2012
2593
  // packages/core/src/agents/runtime/workflow-runner.ts
2594
+ init_esbuild_shims();
2595
+ import { randomBytes as randomBytes2 } from "node:crypto";
2013
2596
  var WorkflowRunHandle = class {
2014
- constructor(runId, budget, registry, controller, start) {
2597
+ constructor(runId, budget, registry, controller, scheduler, start) {
2015
2598
  this.runId = runId;
2016
2599
  this.budget = budget;
2017
2600
  this.registry = registry;
2018
2601
  this.controller = controller;
2602
+ this.scheduler = scheduler;
2019
2603
  this.completion = Promise.resolve().then(start);
2020
2604
  }
2021
2605
  static {
@@ -2025,6 +2609,12 @@ var WorkflowRunHandle = class {
2025
2609
  abort() {
2026
2610
  this.controller.abort();
2027
2611
  }
2612
+ pause() {
2613
+ return this.scheduler.pause();
2614
+ }
2615
+ resume() {
2616
+ return this.scheduler.resume();
2617
+ }
2028
2618
  };
2029
2619
  var WorkflowRunner = class {
2030
2620
  static {
@@ -2103,11 +2693,17 @@ var WorkflowRunner = class {
2103
2693
  emitUpdate();
2104
2694
  }, "budgetUpdated")
2105
2695
  };
2696
+ const scheduler = new WorkflowDispatchScheduler(
2697
+ resolveConcurrencyLimit(),
2698
+ controller.signal,
2699
+ ({ state }) => registry?.onDispatchStateChange(runId, state)
2700
+ );
2106
2701
  const handle = new WorkflowRunHandle(
2107
2702
  runId,
2108
2703
  budget,
2109
2704
  registry,
2110
2705
  controller,
2706
+ scheduler,
2111
2707
  async () => {
2112
2708
  try {
2113
2709
  const outcome = await orchestrator.run({
@@ -2119,7 +2715,8 @@ var WorkflowRunner = class {
2119
2715
  budget,
2120
2716
  resolveSavedWorkflow: /* @__PURE__ */ __name((ref) => resolveSavedWorkflowScript(ref, config), "resolveSavedWorkflow"),
2121
2717
  journal,
2122
- resumeReplay
2718
+ resumeReplay,
2719
+ scheduler
2123
2720
  });
2124
2721
  if (entry) {
2125
2722
  entry.meta = outcome.meta;
@@ -2128,6 +2725,12 @@ var WorkflowRunner = class {
2128
2725
  }
2129
2726
  }
2130
2727
  registry?.setRecentLogs(runId, outcome.logs);
2728
+ if (entry && isTerminalWorkflowStatus(entry.status)) {
2729
+ return {
2730
+ ok: false,
2731
+ message: entry.status === "cancelled" ? "Workflow run cancelled." : entry.error ?? "Workflow run failed."
2732
+ };
2733
+ }
2131
2734
  registry?.complete(runId, outcome.result, Date.now());
2132
2735
  return { ok: true, outcome };
2133
2736
  } catch (error) {
@@ -2143,20 +2746,18 @@ var WorkflowRunner = class {
2143
2746
  return { ok: false, message, details };
2144
2747
  } finally {
2145
2748
  controller.abort();
2146
- if (entry && entry.status !== "running") {
2749
+ if (entry && isTerminalWorkflowStatus(entry.status)) {
2750
+ const telemetryEvent = new WorkflowRunEvent({
2751
+ status: entry.status,
2752
+ agents_dispatched: entry.agentsDispatched,
2753
+ agents_completed: entry.agentsCompleted,
2754
+ phase_count: entry.phases.length,
2755
+ tokens_spent: entry.tokensSpent,
2756
+ duration_ms: (entry.endTime ?? entry.startTime) - entry.startTime
2757
+ });
2147
2758
  await writeWorkflowSnapshot(config, entry);
2148
2759
  try {
2149
- logWorkflowRun(
2150
- config,
2151
- new WorkflowRunEvent({
2152
- status: entry.status,
2153
- agents_dispatched: entry.agentsDispatched,
2154
- agents_completed: entry.agentsCompleted,
2155
- phase_count: entry.phases.length,
2156
- tokens_spent: entry.tokensSpent,
2157
- duration_ms: (entry.endTime ?? entry.startTime) - entry.startTime
2158
- })
2159
- );
2760
+ logWorkflowRun(config, telemetryEvent);
2160
2761
  } catch {
2161
2762
  }
2162
2763
  }
@@ -2185,7 +2786,7 @@ var WORKFLOW_PARAM_SCHEMA = {
2185
2786
  properties: {
2186
2787
  script: {
2187
2788
  type: "string",
2188
- description: "JavaScript source of the workflow. Wrapped as an async IIFE. May call the injected globals `phase(title)`, `log(msg)`, `agent(prompt, opts?)`, and read `args`. agent() opts: `{ label?, phase?, schema?, model?, agentType?, isolation? }`. `schema` (JSON Schema object): the subagent must deliver its result by calling `structured_output` with arguments matching the schema; agent() resolves to the validated object. Two failed attempts produce a terminal error \"subagent completed without calling StructuredOutput (after 2 in-conversation nudges)\". `agentType` (string): resolves against the declarative-agents registry (`.qwen/agents/<name>.md`, project then user then built-in). Unresolved names throw \"agent({agentType}): agent type 'X' not found\". `model` (string): per-call model override; routes provider correctly via the subagent runtime view. `isolation`: `'worktree'` provisions a fresh git worktree under `<projectRoot>/.qwen/worktrees/agent-<7hex>`; the worktree is auto-removed if no changes, otherwise the path and branch are returned alongside the result. `'remote'` throws \"agent({isolation:'remote'}) is not available in this build\" (parity with upstream). isolation=worktree refuses to run when the parent working tree has uncommitted changes (the subagent would see a stale HEAD). Workflow subagents always have SendMessage / Monitor / EnterPlanMode / ExitPlanMode in their disallowed-tool floor regardless of agentType. Concurrency: `parallel([() => agent(...), ...])` runs thunks through a shared per-run window (default `max(1, min(16, cpus-2))` agents in flight; override via `QWEN_CODE_MAX_WORKFLOW_CONCURRENCY`) and resolves to a position-aligned array \u2014 a thunk that throws, or resolves to a non-JSON-serializable value, becomes `null` at its index (errors-as-data); parallel() itself rejects only on invalid arguments or abort. `pipeline(items, ...stages)` runs each item through the stages (staggered, no inter-stage barrier); a stage that throws, returns `null`, or returns a non-JSON-serializable value drops that item to `null`. Pass THUNKS to parallel, not eager calls: `parallel([() => agent(...)])`, not `parallel([agent(...)])`. At most 1000 agent() calls per run (override via `QWEN_CODE_MAX_WORKFLOW_AGENTS`). `Date.now()` and `Math.random()` both throw \u2014 workflow scripts must be deterministic for resume. `export const meta = {...}` declarations are stripped before execution."
2789
+ description: `JavaScript source of the workflow. Wrapped as an async IIFE. May call the injected globals \`phase(title)\`, \`log(msg)\`, \`agent(prompt, opts?)\`, and read \`args\`. agent() opts: \`{ label?, phase?, schema?, model?, agentType?, isolation? }\`. \`schema\` (JSON Schema object): the subagent must deliver its result by calling \`structured_output\` with arguments matching the schema; agent() resolves to the validated object. Two failed attempts produce a terminal error "subagent completed without calling StructuredOutput (after 2 in-conversation nudges)". \`agentType\` (string): resolves against the declarative-agents registry (\`.qwen/agents/<name>.md\`, project then user then built-in). Unresolved names throw "agent({agentType}): agent type 'X' not found". \`model\` (string): per-call model override; routes provider correctly via the subagent runtime view. \`isolation\`: \`'worktree'\` provisions a fresh git worktree under \`<projectRoot>/.qwen/worktrees/agent-<7hex>\`; the worktree is auto-removed if no changes, otherwise the path and branch are returned alongside the result. \`'remote'\` throws "agent({isolation:'remote'}) is not available in this build" (parity with upstream). isolation=worktree refuses to run when the parent working tree has uncommitted changes (the subagent would see a stale HEAD). Workflow subagents always have SendMessage / Monitor / EnterPlanMode / ExitPlanMode in their disallowed-tool floor regardless of agentType. Concurrency: \`parallel([() => agent(...), ...])\` runs thunks through a shared per-run window (default \`max(1, min(16, cpus-2))\` agents in flight; override via \`${MAX_WORKFLOW_CONCURRENCY_ENV}\`) and resolves to a position-aligned array \u2014 a thunk that throws, or resolves to a non-JSON-serializable value, becomes \`null\` at its index (errors-as-data); parallel() itself rejects only on invalid arguments or abort. \`pipeline(items, ...stages)\` runs each item through the stages (staggered, no inter-stage barrier); a stage that throws, returns \`null\`, or returns a non-JSON-serializable value drops that item to \`null\`. Pass THUNKS to parallel, not eager calls: \`parallel([() => agent(...)])\`, not \`parallel([agent(...)])\`. At most ${DEFAULT_MAX_AGENTS_PER_RUN} agent() calls per run (override via \`${MAX_WORKFLOW_AGENTS_ENV}\`). \`Date.now()\` and \`Math.random()\` both throw \u2014 workflow scripts must be deterministic for resume. \`export const meta = {...}\` declarations are stripped before execution.`
2189
2790
  },
2190
2791
  scriptPath: {
2191
2792
  type: "string",
@@ -2201,7 +2802,7 @@ var WORKFLOW_PARAM_SCHEMA = {
2201
2802
  run_in_background: {
2202
2803
  type: "boolean",
2203
2804
  default: false,
2204
- description: "Optional. When true, start the workflow under the interactive session and return a run handle immediately. The Background Tasks view can observe or stop it, and completion is delivered to the conversation when the run settles. Interactive TUI only. Defaults to false."
2805
+ description: "Optional. When true, start the workflow under the interactive session and return a run handle immediately. The Background Tasks view can observe, cooperatively pause/resume, or stop it, and completion is delivered to the conversation when the run settles. Interactive TUI only. Defaults to false."
2205
2806
  }
2206
2807
  }
2207
2808
  // `script` is required UNLESS `scriptPath` is supplied; this XOR can't be
@@ -2269,7 +2870,7 @@ Run ID: ${handle.runId}
2269
2870
  Status: ${status}`
2270
2871
  }
2271
2872
  ],
2272
- returnDisplay: usageBanner + `Workflow ${handle.runId} started in the background (status: ${status}). Use Background Tasks to observe or stop it.`
2873
+ returnDisplay: usageBanner + `Workflow ${handle.runId} started in the background (status: ${status}). Use Background Tasks to observe, cooperatively pause/resume, or stop it.`
2273
2874
  };
2274
2875
  }
2275
2876
  const settlement = await handle.completion;
@@ -2414,12 +3015,47 @@ function safeStringifyDisplayPayload(payload) {
2414
3015
  }
2415
3016
  }
2416
3017
  __name(safeStringifyDisplayPayload, "safeStringifyDisplayPayload");
3018
+ var WORKFLOW_TOOL_DESCRIPTION = `Execute a workflow script that orchestrates subagents deterministically.
3019
+
3020
+ **What a workflow is for**
3021
+
3022
+ Reach for one to be comprehensive (decompose the work and cover every part in parallel), to be confident (independent perspectives and adversarial checks before an answer is committed to), or to take on scale a single context cannot hold \u2014 migrations, audits, broad sweeps. The script is where that structure is encoded: what fans out, what verifies, what synthesizes. Parallelism on its own is not a reason; work that is already one short sequence of edits belongs in the main loop.
3023
+
3024
+ **Runtime** \u2014 see the \`script\` parameter for the detailed authoring contract.
3025
+
3026
+ \`phase(title)\`, \`log(msg)\`, \`agent(prompt, opts?)\`, \`parallel(thunks)\`, \`pipeline(items, ...stages)\`, \`workflow(nameOrRef, args?)\`, plus the \`args\` and \`budget\` globals. \`workflow()\` runs a saved workflow inline under this run's caps and nests one level only \u2014 a workflow reached through \`workflow()\` cannot call \`workflow()\` itself, and doing so throws. Saved workflows are \`<name>.js\` files under \`<projectRoot>/.qwen/workflows\` (project scope, also surfaced as \`/<name>\` slash commands) or \`~/.qwen/workflows\` (user scope, lower precedence when both define the same name); \`workflow('<name>')\` resolves against those two directories, while \`scriptPath\` takes an absolute path to a script anywhere. Default \`max(1, min(16, cpus-2))\` agents in flight per run (\`${MAX_WORKFLOW_CONCURRENCY_ENV}\`), up to ${DEFAULT_MAX_AGENTS_PER_RUN} agents total (\`${MAX_WORKFLOW_AGENTS_ENV}\`), under a 30-minute wall-clock cap per run (\`QWEN_CODE_MAX_WORKFLOW_SECONDS\`) \u2014 a fan-out near the agent cap will not fit inside the default cap. A per-run output-token cap may also be in effect: read \`budget.total\` (\`null\` = uncapped) before committing to a large fan-out, because once the cap is reached every further \`agent()\` call is refused \u2014 a bare sequential \`await agent()\` sees the rejection, while inside \`parallel()\`/\`pipeline()\` the refused slot becomes \`null\` and the script keeps running on partial results. Per-call \`agent({ schema, agentType, model, isolation: 'worktree' })\` covers structured-output contracts, declarative-agent selection, model override, and git-worktree-isolated subagents. \`resumeFromRunId\` resumes a prior run \u2014 agent() calls whose rolling prefix-hash matches the journal are served from cache for the longest unchanged prefix. Runs appear in the background-tasks view and the \`/workflows\` dialog (live phase tree, token usage, cooperative pause/resume, cancel); \`run_in_background: true\` returns a run handle immediately in the interactive TUI and delivers completion through the conversation. Scripts run in a node:vm sandbox with no filesystem or shell access \u2014 all I/O happens through the spawned agents.
3027
+
3028
+ **Scout first, then orchestrate**
3029
+
3030
+ The strongest pattern is hybrid: discover the work list in the main loop (list the files, scope the diff, read the failing test), then hand that list to a workflow. You do not need to know the shape of the work before the task \u2014 only before the orchestration step. When the work has distinct phases, run several small workflows across turns and read each result before choosing the next, rather than authoring one large script that runs unattended.
3031
+
3032
+ Common single-phase shapes: understand (parallel readers over subsystems, merged into one map), design (independent approaches, judged, then synthesized), review (dimensions, find, verify each finding), research (broad sweep, deep read, synthesis), migrate (discover sites, transform each under \`isolation: 'worktree'\`, verify).
3033
+
3034
+ **Default to \`pipeline()\`**
3035
+
3036
+ \`pipeline()\` runs each item through every stage independently \u2014 item A can be in stage 3 while item B is still in stage 1 \u2014 so wall-clock is the slowest single chain. \`parallel()\` is a barrier: it waits for every thunk before anything moves on, so it costs the slowest item of every stage.
3037
+
3038
+ A barrier is right only when a stage genuinely needs cross-item context: deduplicating or merging across the full result set before expensive downstream work, exiting early when the total count is zero, or a prompt that compares one finding against all the others. It is not justified by needing to flatten, map, or filter between stages (do that inside a pipeline stage), by two stages being conceptually separate, or by the code reading more tidily. Smell test: \`parallel()\` \u2192 a pure transform \u2192 \`parallel()\` is a pipeline someone wrote with an unnecessary barrier. When in doubt, \`pipeline()\`.
3039
+
3040
+ **Verify before believing**
3041
+
3042
+ A subagent's answer is a claim, not a result. For findings that matter, spawn independent verifiers prompted to *refute*, and drop what a majority refutes. When a claim can be wrong in several different ways, give each verifier a distinct lens (correctness, security, performance, does it actually reproduce) \u2014 diversity catches what repetition cannot. For a wide solution space, generate several independent attempts, judge them in parallel, and synthesize from the winner while grafting the best ideas from the rest.
3043
+
3044
+ **Converge deliberately**
3045
+
3046
+ For discovery of unknown size, keep running finders until some number of consecutive rounds turn up nothing new; a fixed round count stops partway into the tail. Deduplicate each round against everything already seen, never against only what survived judging \u2014 otherwise rejected findings reappear every round and the loop never terminates. A closing pass that asks what is still missing (a search angle never run, a claim never verified, a file never read) usually produces the next round of real work.
3047
+
3048
+ **Report honestly**
3049
+
3050
+ Scale the fleet to what was actually asked: a quick check gets a few agents and one verification pass; an explicit request to be thorough or exhaustive earns a larger pool and a multi-vote adversarial round. Whenever a run bounds its own coverage \u2014 top-N, sampling, no retry \u2014 \`log()\` what was dropped. Silent truncation reads as full coverage, which is worse than a smaller honest result.
3051
+
3052
+ These shapes are a starting point, not a menu; compose the harness the task actually needs.`;
2417
3053
  var WorkflowTool = class extends BaseDeclarativeTool {
2418
3054
  constructor(config, toolOptions = {}) {
2419
3055
  super(
2420
3056
  ToolNames.WORKFLOW,
2421
3057
  ToolDisplayNames.WORKFLOW,
2422
- "Execute a workflow script that orchestrates subagents. Supports `phase`, `log`, sequential `agent`, concurrent fan-out via `parallel(thunks)` / `pipeline(items, ...stages)` (default `max(1, min(16, cpus-2))` agents in flight per run, up to 1000 agents total; both env-overridable), per-call `agent({ schema, agentType, model, isolation: 'worktree' })` for structured-output contracts, declarative-agent selection, model override, and git-worktree-isolated subagents. Pass `resumeFromRunId` to resume a prior run \u2014 agent() calls whose rolling prefix-hash matches the journal are served from cache for the longest unchanged prefix. Runs are tracked in the background-tasks view and the `/workflows` dialog (live phase tree, token usage, cancel). Set `run_in_background: true` to return a run handle immediately in the interactive TUI and receive completion through the conversation. Scripts run in a node:vm sandbox without access to the filesystem or shell; all I/O happens through the spawned agents.",
3058
+ WORKFLOW_TOOL_DESCRIPTION,
2423
3059
  "other" /* Other */,
2424
3060
  WORKFLOW_PARAM_SCHEMA,
2425
3061
  /* isOutputMarkdown */
@@ -2464,11 +3100,11 @@ export {
2464
3100
  };
2465
3101
  /**
2466
3102
  * @license
2467
- * Copyright 2026 Qwen Team
3103
+ * Copyright 2025 Qwen
2468
3104
  * SPDX-License-Identifier: Apache-2.0
2469
3105
  */
2470
3106
  /**
2471
3107
  * @license
2472
- * Copyright 2025 Qwen
3108
+ * Copyright 2026 Qwen Team
2473
3109
  * SPDX-License-Identifier: Apache-2.0
2474
3110
  */