@qwen-code/qwen-code 0.23.5-dev.codemode-responses.20260915.af4da34719 → 0.23.5-preview.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (377) hide show
  1. package/bundled/computer-use/SKILL.md +24 -3
  2. package/bundled/qc-helper/docs/configuration/model-providers.md +43 -0
  3. package/bundled/qc-helper/docs/configuration/settings.md +10 -9
  4. package/bundled/qc-helper/docs/extension/agent-plugins.md +1 -0
  5. package/bundled/qc-helper/docs/extension/introduction.md +49 -0
  6. package/bundled/qc-helper/docs/features/channels/dingtalk.md +39 -4
  7. package/bundled/qc-helper/docs/features/channels/overview.md +12 -0
  8. package/bundled/qc-helper/docs/features/commands.md +57 -52
  9. package/bundled/qc-helper/docs/features/computer-use.md +1 -1
  10. package/bundled/qc-helper/docs/features/goals.md +8 -0
  11. package/bundled/qc-helper/docs/features/hooks.md +16 -0
  12. package/bundled/qc-helper/docs/qwen-serve.md +3 -1
  13. package/bundled/workflow-authoring/SKILL.md +48 -22
  14. package/chunks/{MaxSizedBox-3K65WFGY.js → MaxSizedBox-FCF6M53W.js} +40 -43
  15. package/chunks/{StandaloneSessionPicker-JKM33JPY.js → StandaloneSessionPicker-V635V72I.js} +60 -63
  16. package/chunks/{acp-startup-profiler-RUQNTNU5.js → acp-startup-profiler-MOOU37VM.js} +2 -2
  17. package/chunks/{acp-subagent-executor-KIZBB2CL.js → acp-subagent-executor-TND6W2O5.js} +46 -47
  18. package/chunks/{acpAgent-SHI4L5EV.js → acpAgent-3DPWZTNC.js} +954 -322
  19. package/chunks/{agent-AJXNVRX2.js → agent-KIHGINKN.js} +27 -30
  20. package/chunks/{agent-headless-2JPJKYHK.js → agent-headless-EJ4QOUSM.js} +27 -30
  21. package/chunks/{anthropicContentGenerator-H5YPXIDE.js → anthropicContentGenerator-4FGOM5LK.js} +46 -64
  22. package/chunks/{artifact-tool-MFGORTWZ.js → artifact-tool-MUTNH4NI.js} +1 -1
  23. package/chunks/{askUserQuestion-WS4GUT7C.js → askUserQuestion-AKIRLVB5.js} +1 -1
  24. package/chunks/bareMode-QWKZPLPX.js +14 -0
  25. package/chunks/{bridge-KZYSMV4N.js → bridge-MUX5YJZT.js} +46 -49
  26. package/chunks/{ca-GZ4FDJU2.js → ca-WC3A5B3Q.js} +12 -1
  27. package/chunks/{channel-management-service-AFVIT4VH.js → channel-management-service-RRILWSXX.js} +4 -4
  28. package/chunks/{channel-settings-store-IJG52IDV.js → channel-settings-store-7CBIRZER.js} +51 -54
  29. package/chunks/{channel-worker-group-JR6JOELM.js → channel-worker-group-3DUJFZJR.js} +8 -8
  30. package/chunks/{channel-worker-manager-AVKJEZFL.js → channel-worker-manager-E5UW2VLA.js} +8 -8
  31. package/chunks/{channel-worker-supervisor-OOYY7BAQ.js → channel-worker-supervisor-VN33GSEC.js} +5 -5
  32. package/chunks/{chunk-2YMRRI2C.js → chunk-2C5TR6HN.js} +82 -9
  33. package/chunks/{chunk-YDFOHRS5.js → chunk-2GP6BQ2J.js} +1 -1
  34. package/chunks/{chunk-JATZTB7X.js → chunk-347O2YZJ.js} +158 -290
  35. package/chunks/{chunk-RYREFZFH.js → chunk-36NRLIR6.js} +10 -8
  36. package/chunks/{chunk-AXZMWAJV.js → chunk-36SDZ2Q4.js} +8 -0
  37. package/chunks/{chunk-QR4Q425T.js → chunk-3BZI5GDP.js} +1 -1
  38. package/chunks/{chunk-IP6NRULS.js → chunk-3HTUE6ZR.js} +3 -3
  39. package/chunks/{chunk-B2VSRPS6.js → chunk-3LLEB5CU.js} +2 -2
  40. package/chunks/{chunk-L2XNHRDL.js → chunk-3UGMLA4V.js} +10 -8
  41. package/chunks/{chunk-66N6C4EH.js → chunk-3WILPKTJ.js} +2 -2
  42. package/chunks/{chunk-SROLVJFY.js → chunk-3WWPEFMX.js} +1 -1
  43. package/chunks/{chunk-ZKIAGIGH.js → chunk-3XBUCOWS.js} +1 -1
  44. package/chunks/{chunk-737SVOO7.js → chunk-43Y26NPF.js} +3 -3
  45. package/chunks/{chunk-INGBUYL6.js → chunk-4FLUQWJ4.js} +1 -1
  46. package/chunks/{chunk-BTBJEB27.js → chunk-4JFLRHNE.js} +1 -1
  47. package/chunks/{chunk-MJHLKWGJ.js → chunk-4QPVZA5J.js} +70 -23
  48. package/chunks/{chunk-XX5HQLCZ.js → chunk-6OTF7TTE.js} +32 -1
  49. package/chunks/{chunk-4Y2I3CI3.js → chunk-6USYH3EU.js} +99 -6
  50. package/chunks/{chunk-Q3TFRP5G.js → chunk-7D4CV7JH.js} +102 -9
  51. package/chunks/{chunk-EWJTAP3Y.js → chunk-7O5PYQ3M.js} +20 -1
  52. package/chunks/chunk-ADN5KESB.js +28 -0
  53. package/chunks/chunk-AKRSSKUT.js +229 -0
  54. package/chunks/{chunk-IOXJX7XE.js → chunk-AQP3H22J.js} +1 -1
  55. package/chunks/{chunk-YP7QCE7X.js → chunk-AUX2FL5T.js} +24 -7
  56. package/chunks/{chunk-YGFJ6BRT.js → chunk-AZCTY64Z.js} +1 -1
  57. package/chunks/{chunk-5CDDYYNI.js → chunk-B5TJK7B3.js} +1 -1
  58. package/chunks/{chunk-7MKB7L25.js → chunk-B6RMK4ED.js} +4 -4
  59. package/chunks/{chunk-YH24ZJ65.js → chunk-BHG3H6OZ.js} +1 -1
  60. package/chunks/{chunk-BRPYJQDD.js → chunk-BHVF3R6B.js} +7 -5
  61. package/chunks/{chunk-HFJSQ4GL.js → chunk-BTICBRPL.js} +1 -1
  62. package/chunks/{chunk-KZCK5JUN.js → chunk-C3T6HPNM.js} +1 -1
  63. package/chunks/{chunk-UB2MATP5.js → chunk-CDDP4ONL.js} +164 -27
  64. package/chunks/{chunk-OL3TNHFM.js → chunk-CQPM66MG.js} +4 -4
  65. package/chunks/{chunk-WKVZES7O.js → chunk-CXONOVBN.js} +1 -1
  66. package/chunks/{chunk-6IHJLXNF.js → chunk-CXY6BICQ.js} +501 -479
  67. package/chunks/{chunk-I5QPDANL.js → chunk-D3KVGQUV.js} +1 -1
  68. package/chunks/{chunk-LMJSPC55.js → chunk-D7JMO2GP.js} +3 -7
  69. package/chunks/{chunk-CXXAZ2LZ.js → chunk-DC4ZNGH4.js} +1 -1
  70. package/chunks/{chunk-FMLBBXHB.js → chunk-DRAX5YAI.js} +2 -2
  71. package/chunks/{chunk-DOTF2PF2.js → chunk-DRD6VBNH.js} +1 -1
  72. package/chunks/chunk-DX6JTDMR.js +105 -0
  73. package/chunks/{chunk-HJAJ6MR6.js → chunk-E2VSBAFA.js} +53 -11
  74. package/chunks/{chunk-G7ZYRFHS.js → chunk-EIBECN2J.js} +3 -3
  75. package/chunks/{chunk-LWWRJRCD.js → chunk-ESBYWATJ.js} +1 -1
  76. package/chunks/{chunk-2PLQ3CXJ.js → chunk-FASYATAZ.js} +5 -7
  77. package/chunks/{chunk-3ADU34IF.js → chunk-FBY32737.js} +4 -4
  78. package/chunks/{chunk-SIDVJZWH.js → chunk-FCPJXKDG.js} +10 -7
  79. package/chunks/{chunk-5GXJBU7K.js → chunk-FEDFZBGR.js} +3 -3
  80. package/chunks/{chunk-CALVKIIG.js → chunk-FIJODK52.js} +3 -3
  81. package/chunks/{chunk-ZTVYMZBD.js → chunk-FX6PZBOV.js} +3 -3
  82. package/chunks/{chunk-L6DIANLD.js → chunk-G45B3INR.js} +1 -1
  83. package/chunks/{chunk-TATT2THJ.js → chunk-GI7SLDOI.js} +2 -2
  84. package/chunks/chunk-GJKP6XOB.js +1092 -0
  85. package/chunks/{chunk-I6YJZGHS.js → chunk-GSAOVDTH.js} +9 -9
  86. package/chunks/{chunk-7MIOAF77.js → chunk-H6L4NEAT.js} +1 -1
  87. package/chunks/{chunk-MJGJF6G6.js → chunk-HNFKYKHH.js} +103 -22
  88. package/chunks/{chunk-PN6D5LWJ.js → chunk-HX4WXX3H.js} +301 -138
  89. package/chunks/{chunk-HG46TTAG.js → chunk-HXUI5D4H.js} +1 -1
  90. package/chunks/{chunk-JF2CFBDK.js → chunk-HYHSMTRA.js} +4 -4
  91. package/chunks/{chunk-4DZMYFZA.js → chunk-IKBEIDOH.js} +14 -14
  92. package/chunks/{chunk-QEENIXYB.js → chunk-INN5ORKX.js} +1 -1
  93. package/chunks/{chunk-GNV2SFO7.js → chunk-IVFTLUZD.js} +26 -1
  94. package/chunks/{chunk-L2NII7PZ.js → chunk-IXO2OCIP.js} +2 -2
  95. package/chunks/{chunk-6MAHSVMB.js → chunk-K4XMAIRX.js} +30 -33
  96. package/chunks/{chunk-AYMSNIYL.js → chunk-KAYC5FBN.js} +5269 -2785
  97. package/chunks/chunk-KEM7MWS7.js +3541 -0
  98. package/chunks/{chunk-ADQUK6WA.js → chunk-KVC7HZWK.js} +1 -1
  99. package/chunks/{chunk-Z35OSDIT.js → chunk-KVQ3QL4K.js} +3 -3
  100. package/chunks/{chunk-7U5G6JXI.js → chunk-KWYTSSTJ.js} +105 -6
  101. package/chunks/{chunk-PZRAE65J.js → chunk-L2A5VBDL.js} +3019 -2352
  102. package/chunks/{chunk-WD6YQI5M.js → chunk-L3SNMEDW.js} +1 -1
  103. package/chunks/{chunk-BYUAT5OC.js → chunk-L7TJUPNR.js} +19 -3
  104. package/chunks/{chunk-ABNX6E6K.js → chunk-LFKXIOGC.js} +1 -1
  105. package/chunks/{chunk-NFQOOITE.js → chunk-LO2UWNO5.js} +2 -2
  106. package/chunks/{chunk-LWUTZKDU.js → chunk-M22WLKLI.js} +5 -5
  107. package/chunks/{chunk-54B2LTKP.js → chunk-M23GFJ5B.js} +24 -5
  108. package/chunks/{chunk-VGY2RGXL.js → chunk-M4U2LTD2.js} +1 -1
  109. package/chunks/{chunk-ZNI3YJHS.js → chunk-MFDKHGTD.js} +1 -1
  110. package/chunks/{chunk-R7OO56VZ.js → chunk-MMRGG6R4.js} +1 -1
  111. package/chunks/{chunk-E6IR653O.js → chunk-MO4XID7S.js} +1 -1
  112. package/chunks/{chunk-FZQQMVLB.js → chunk-NKTMUPHJ.js} +3 -6
  113. package/chunks/{chunk-V77DTVCM.js → chunk-NQ272MQG.js} +1 -1
  114. package/chunks/{chunk-TDFLM7BE.js → chunk-OALXNGUA.js} +6 -6
  115. package/chunks/{chunk-FBDHP23D.js → chunk-OSG23MR3.js} +1 -1
  116. package/chunks/{chunk-NJ2OFVUX.js → chunk-P42KMMU6.js} +860 -1
  117. package/chunks/{chunk-Y33TCKXL.js → chunk-PF7GAP6K.js} +60 -58
  118. package/chunks/{chunk-MQRLLBMQ.js → chunk-PPJSG2PU.js} +2 -2
  119. package/chunks/{chunk-EPVEPTI3.js → chunk-PZRXWQUA.js} +753 -18
  120. package/chunks/{chunk-OLN7QX4P.js → chunk-Q54O3EIA.js} +30 -28
  121. package/chunks/{chunk-DQH3EVAD.js → chunk-QGEISOJ2.js} +4 -4
  122. package/chunks/{chunk-3M4O2AY3.js → chunk-QHSOINX6.js} +2 -2
  123. package/chunks/{chunk-HIQEL7EM.js → chunk-QIPLWW6Q.js} +1 -1
  124. package/chunks/chunk-QMENOK5T.js +1246 -0
  125. package/chunks/chunk-QT6Z2IBF.js +347 -0
  126. package/chunks/{chunk-TBSCTWKF.js → chunk-RN6A53UJ.js} +25 -0
  127. package/chunks/{chunk-65BKWMMH.js → chunk-RRI764F7.js} +21 -19
  128. package/chunks/{chunk-YI2YCNSP.js → chunk-SENYKRII.js} +1 -1
  129. package/chunks/chunk-SFHX5G2S.js +2796 -0
  130. package/chunks/chunk-SK3RZOPS.js +34 -0
  131. package/chunks/{chunk-MD6KXINN.js → chunk-SOLRBF7L.js} +13 -9
  132. package/chunks/{chunk-6BCN3VOY.js → chunk-SSWTA7CH.js} +12 -12
  133. package/chunks/{chunk-IAS753HG.js → chunk-SYMXYRM5.js} +11 -2
  134. package/chunks/{chunk-FGROOEKM.js → chunk-TDKUXSJO.js} +34 -6
  135. package/chunks/{chunk-ZJ7JQUGY.js → chunk-TKF4JINY.js} +1 -1
  136. package/chunks/{chunk-RVK37FWG.js → chunk-TPY6HW55.js} +4 -4
  137. package/chunks/{chunk-EDB556X7.js → chunk-TRZ22SG5.js} +1 -1
  138. package/chunks/{chunk-7LG4MUUD.js → chunk-TXTCM3TC.js} +4 -4
  139. package/chunks/{chunk-5ODRE7E5.js → chunk-U4AASWUQ.js} +28 -12
  140. package/chunks/{chunk-WPMRT4AR.js → chunk-UQGRJTDK.js} +2 -2
  141. package/chunks/{chunk-JBS56C7O.js → chunk-UZSB57EV.js} +6 -8
  142. package/chunks/{chunk-S4M6BDNE.js → chunk-V4JJAVHQ.js} +2 -2
  143. package/chunks/chunk-VEXUA6DX.js +1026 -0
  144. package/chunks/{chunk-ME4JBHSB.js → chunk-VQDWCQOE.js} +2 -0
  145. package/chunks/{chunk-3XXDCC5C.js → chunk-VU3XMZ5I.js} +23 -4
  146. package/chunks/{chunk-RD2HAF25.js → chunk-WL36KHUQ.js} +6 -6
  147. package/chunks/{chunk-WYRSEVBQ.js → chunk-WNQIJTOP.js} +8 -8
  148. package/chunks/{chunk-GTBXQ5W2.js → chunk-WSJI6ODG.js} +99 -30
  149. package/chunks/{chunk-VN5G33G7.js → chunk-WZWTY7SG.js} +6 -6
  150. package/chunks/{chunk-EKMJR7M3.js → chunk-X7AYIXC7.js} +1 -1
  151. package/chunks/{chunk-IBRQG2MP.js → chunk-XAJZFGD2.js} +11 -11
  152. package/chunks/{chunk-VRQZESKP.js → chunk-XICCGDWF.js} +2 -2
  153. package/chunks/{chunk-OZ2KDR2L.js → chunk-Y2KJC55Y.js} +12 -7
  154. package/chunks/{chunk-2S2WIGCM.js → chunk-Y4NNIGYO.js} +1 -1
  155. package/chunks/{chunk-J7LBAKDH.js → chunk-YL3UJML3.js} +7 -7
  156. package/chunks/{chunk-GSS4SZNG.js → chunk-YP2K3WOS.js} +40 -56
  157. package/chunks/{chunk-ZZUXUBEB.js → chunk-YQQ2U7AS.js} +8 -5
  158. package/chunks/{chunk-FAWTMDX7.js → chunk-YXHY6BKS.js} +15 -0
  159. package/chunks/{chunk-VIV2I3R7.js → chunk-YZXSDPOQ.js} +140 -39
  160. package/chunks/{chunk-KZ63S3HX.js → chunk-ZFHKUQZ4.js} +3 -3
  161. package/chunks/{chunk-B6KSTADQ.js → chunk-ZMYKNKET.js} +6 -6
  162. package/chunks/{codex-subagent-executor-6M7TD3MF.js → codex-subagent-executor-AEAIQZDC.js} +48 -49
  163. package/chunks/{config-utils-TB4QERW7.js → config-utils-KX2YS725.js} +43 -46
  164. package/chunks/{contextCommand-BFQMDECM.js → contextCommand-RV6Y5LNJ.js} +41 -44
  165. package/chunks/{core-runtime-Z2QJJMHR.js → core-runtime-ZI4RTOJQ.js} +45 -48
  166. package/chunks/{create-sub-session-GE4U3D7C.js → create-sub-session-BBWFQARJ.js} +46 -48
  167. package/chunks/{daemon-NJB4PWZ7.js → daemon-INCM4VBX.js} +3 -1
  168. package/chunks/{daemon-git-worktree-guard-IPA22S72.js → daemon-git-worktree-guard-KECEMV6A.js} +39 -42
  169. package/chunks/{daemon-status-provider-2U5WPCCB.js → daemon-status-provider-NULJNAEV.js} +53 -56
  170. package/chunks/{daemon-trust-policy-GEIGMVDQ.js → daemon-trust-policy-S4KWGPV3.js} +47 -50
  171. package/chunks/{daemon-trust-policy-monitor-JETBW5FX.js → daemon-trust-policy-monitor-546N5ZVL.js} +47 -50
  172. package/chunks/{de-VGY3VNBU.js → de-6AVKPTXQ.js} +11 -0
  173. package/chunks/{deferred-core-runtime-LANRK77C.js → deferred-core-runtime-T23ZT443.js} +39 -42
  174. package/chunks/{dist-NIOJXMGY.js → dist-4P3ZJYGI.js} +1 -1
  175. package/chunks/{dist-VDLSBCLM.js → dist-7MGRENQ5.js} +1 -1
  176. package/chunks/{dist-SE4J6Z4O.js → dist-BNW423XT.js} +326 -77
  177. package/chunks/{dist-TFGETXFN.js → dist-CESMUYGN.js} +4 -4
  178. package/chunks/{dist-MPUZZOG5.js → dist-DBBOFWSC.js} +1 -1
  179. package/chunks/{dist-T6DDPDLQ.js → dist-G5UMXIGF.js} +1 -1
  180. package/chunks/{dist-PA7WPFVE.js → dist-UXVNLQHG.js} +3 -3
  181. package/chunks/{dist-GUB7QRYA.js → dist-VA4LREAQ.js} +2 -2
  182. package/chunks/{dist-2QYIVNS6.js → dist-XDRTR4QP.js} +1 -1
  183. package/chunks/{edit-QC63PJOZ.js → edit-CMSQB7NP.js} +27 -30
  184. package/chunks/{en-E5ZO5TZW.js → en-56QLKXS2.js} +23 -1
  185. package/chunks/{enter-worktree-CAARFWBI.js → enter-worktree-DA6A4XC5.js} +3 -3
  186. package/chunks/{enterPlanMode-5TMWDRXD.js → enterPlanMode-UDPMNESD.js} +27 -30
  187. package/chunks/{environment-TNQVM5B3.js → environment-TSQJUTPV.js} +42 -45
  188. package/chunks/{errors-KWDDLG7P.js → errors-RIVYJS6T.js} +41 -44
  189. package/chunks/{exit-worktree-JXGGUOBP.js → exit-worktree-4H6Z2VQI.js} +3 -3
  190. package/chunks/{exitPlanMode-CLEWPZIE.js → exitPlanMode-BYBBFN2T.js} +27 -30
  191. package/chunks/{fast-path-PMRLQT7J.js → fast-path-F2CYDDZ4.js} +4 -4
  192. package/chunks/{fast-path-settings-XDYX7X5Z.js → fast-path-settings-N2VGRGDJ.js} +2 -2
  193. package/chunks/{fr-UAZJJH5N.js → fr-EBUDHJL3.js} +11 -0
  194. package/chunks/{glob-3AK4KKCE.js → glob-Z2JMJKKN.js} +27 -30
  195. package/chunks/{goal-tools-FD6OCE6Q.js → goal-tools-HXVVLGCV.js} +27 -30
  196. package/chunks/{handleAutoUpdate-QUNNMMY6.js → handleAutoUpdate-FZP45KOR.js} +43 -46
  197. package/chunks/{i18n-DVN326VM.js → i18n-OTB62AKW.js} +40 -43
  198. package/chunks/{image-gen-5G2TQ3DY.js → image-gen-HIAZCB5T.js} +6 -7
  199. package/chunks/{initializer-JHEJBPVJ.js → initializer-4JXZEC4B.js} +47 -50
  200. package/chunks/{installationInfo-DYOI4I5U.js → installationInfo-2IJV5QKC.js} +39 -42
  201. package/chunks/{ja-2RITCMAJ.js → ja-NCDT4CGV.js} +11 -0
  202. package/chunks/{list-MW74DDMO.js → list-KQSQ4A5G.js} +50 -53
  203. package/chunks/{llm-HUDP76IA.js → llm-LSUBOJAR.js} +154 -974
  204. package/chunks/{llm-content-generator-KYD6ZEM6.js → llm-content-generator-MLIONRXE.js} +17 -12
  205. package/chunks/{loadedSettingsAdapter-RRAZOPRB.js → loadedSettingsAdapter-TZTTNRHI.js} +47 -50
  206. package/chunks/{loggingContentGenerator-MHE6Z2OZ.js → loggingContentGenerator-TUPEXFMM.js} +31 -34
  207. package/chunks/{loop-wakeup-VG6CGBQA.js → loop-wakeup-ZBVRI6VH.js} +1 -1
  208. package/chunks/{managed-npm-update-3G3O3T3R.js → managed-npm-update-WEA5XMFZ.js} +40 -43
  209. package/chunks/{mcp-JGLBFJQB.js → mcp-TFDTUPIA.js} +47 -50
  210. package/chunks/{model-configuration-EGWMLK4P.js → model-configuration-ZCAKKIOF.js} +48 -51
  211. package/chunks/{modelConfigUtils-H4WFGWQD.js → modelConfigUtils-J3ZPW7ZK.js} +41 -44
  212. package/chunks/{monitor-62V72TGX.js → monitor-CI7YE7MT.js} +29 -32
  213. package/chunks/{nonInteractiveCli-GYKHG7RX.js → nonInteractiveCli-GPT3TVOK.js} +96 -98
  214. package/chunks/{notebook-edit-HOJLHP3F.js → notebook-edit-3WCVRNGL.js} +27 -30
  215. package/chunks/{openaiContentGenerator-ZAJTUWVO.js → openaiContentGenerator-OGILGUZE.js} +12 -17
  216. package/chunks/{openaiResponsesContentGenerator-AWRYZLJU.js → openaiResponsesContentGenerator-NXOXUPFM.js} +45 -13
  217. package/chunks/{pidfile-CS7LHAN5.js → pidfile-GBTBIGHF.js} +39 -42
  218. package/chunks/{process-registry-X6ZCASEN.js → process-registry-7LAPI3ZB.js} +1 -1
  219. package/chunks/{processUtils-OWQU3JQM.js → processUtils-O4II3RYH.js} +2 -2
  220. package/chunks/{prompt-terminal-ledger-76P527XD.js → prompt-terminal-ledger-ILIXZI3E.js} +40 -43
  221. package/chunks/{pt-5ZF7ZQUV.js → pt-FYYFWYUC.js} +11 -0
  222. package/chunks/{qwenContentGenerator-QZCQ3UTX.js → qwenContentGenerator-I4LRYADV.js} +33 -36
  223. package/chunks/{qwenOAuth2-WIEUEFEY.js → qwenOAuth2-3J66TOT5.js} +6 -7
  224. package/chunks/{read-file-KR5BES2E.js → read-file-G4XKW2CS.js} +5 -9
  225. package/chunks/{record-artifact-PXMNP7GZ.js → record-artifact-L3CFJOMA.js} +2 -2
  226. package/chunks/{report-findings-W6GR7SYZ.js → report-findings-LY5HQY4K.js} +3 -3
  227. package/chunks/{resumeHistoryUtils-36NM5S3D.js → resumeHistoryUtils-YPJU4XFE.js} +44 -47
  228. package/chunks/{ripGrep-QGFIVODS.js → ripGrep-AAKMALLM.js} +7 -11
  229. package/chunks/{ru-7BNZFQKG.js → ru-RHEB3RNS.js} +11 -0
  230. package/chunks/{run-qwen-serve-UFEOUIDD.js → run-qwen-serve-ZVEKGS7Y.js} +177 -98
  231. package/chunks/{runtime-7LTR2C7Q.js → runtime-SJCRYNPA.js} +52 -55
  232. package/chunks/safe-mode-KLGUG54M.js +11 -0
  233. package/chunks/sandbox-UIXL423Z.js +146 -0
  234. package/chunks/sandboxConfig-CY343YNJ.js +114 -0
  235. package/chunks/{scheduled-tasks-MV22T3JO.js → scheduled-tasks-5UGBEVNZ.js} +50 -53
  236. package/chunks/{scheduler-HSNQ53ML.js → scheduler-GCZYLZ2P.js} +41 -44
  237. package/chunks/{sdk-exporters-http-3R2TRQHE.js → sdk-exporters-http-DR4G663K.js} +1 -1
  238. package/chunks/{sdk-impl-4WF3VZ2F.js → sdk-impl-SJR26MQF.js} +3 -3
  239. package/chunks/{send-message-UMJKN27Q.js → send-message-DN76MXDX.js} +6 -6
  240. package/chunks/{serve-LDD4FEJQ.js → serve-2XXQLVK2.js} +48 -51
  241. package/chunks/{server-IKTZFW3E.js → server-UHMKPCAZ.js} +408 -211
  242. package/chunks/{session-T77EXOOI.js → session-ZLUK7E4P.js} +108 -108
  243. package/chunks/{session-attachments-root-FBASBVAO.js → session-attachments-root-DHQM5IEZ.js} +39 -42
  244. package/chunks/{session-pr-refresh-2BHKIMIN.js → session-pr-refresh-3OMTQWCZ.js} +48 -51
  245. package/chunks/{settings-TJNUFBGG.js → settings-P4DHIIUP.js} +50 -53
  246. package/chunks/{shell-HDI5VPGD.js → shell-IMFUVQQ5.js} +27 -30
  247. package/chunks/{skill-VTA6FNDX.js → skill-NB5RJGZW.js} +7 -11
  248. package/chunks/{skill-settings-K4LSGCKA.js → skill-settings-IXG5CTQO.js} +47 -50
  249. package/chunks/{spawnChannel-YSGSPD5D.js → spawnChannel-Q3YALTCJ.js} +44 -45
  250. package/chunks/{standalone-update-O5LYCCMB.js → standalone-update-H5OJ7MM7.js} +41 -44
  251. package/chunks/{start-opentui-ui-CS6HKYCE.js → start-opentui-ui-JKAIWGF7.js} +733 -386
  252. package/chunks/{startInteractiveUI-IVP5HEDD.js → startInteractiveUI-YRPOT6GH.js} +370 -337
  253. package/chunks/task-create-75HVPEAH.js +1 -1
  254. package/chunks/{team-create-DW4KE2PR.js → team-create-2XTBYRJF.js} +31 -34
  255. package/chunks/{team-plan-approval-33UL4JDG.js → team-plan-approval-CFNWW7ZQ.js} +27 -30
  256. package/chunks/{terminal-image-renderer-4FK76L22.js → terminal-image-renderer-UDPJPGPQ.js} +39 -42
  257. package/chunks/{theme-manager-UQ3EKEJ4.js → theme-manager-SK57EKMO.js} +39 -42
  258. package/chunks/{tool-search-QUOG6M6M.js → tool-search-ZHTJU2MV.js} +5 -9
  259. package/chunks/{total-session-admission-QRWPWSK5.js → total-session-admission-UUZBDQCG.js} +47 -50
  260. package/chunks/{tree-sitter-ALGO6NDO.js → tree-sitter-4D7QS7F6.js} +1 -1
  261. package/chunks/{tree-sitter-bash-H6YH7EBF.js → tree-sitter-bash-VEJGF5XF.js} +1 -1
  262. package/chunks/{trustedFolders-HESP75BK.js → trustedFolders-4LDBLNTS.js} +40 -43
  263. package/chunks/{update-relaunch-YROJ7A26.js → update-relaunch-LI7GRP36.js} +5 -5
  264. package/chunks/{updateCheck-CUKTRHID.js → updateCheck-PKSSORPO.js} +43 -46
  265. package/chunks/{useAutoAcceptIndicator-BQGSRBHX.js → useAutoAcceptIndicator-I32UEQPI.js} +50 -53
  266. package/chunks/{validateNonInterActiveAuth-UM5U2ZZI.js → validateNonInterActiveAuth-YFPCYYNL.js} +93 -95
  267. package/chunks/{version-A6G2KO4K.js → version-4MTL4JVU.js} +1 -1
  268. package/chunks/{web-fetch-A3RMCVQY.js → web-fetch-O6RG6ISB.js} +9 -13
  269. package/chunks/{web-search-3XGJ773E.js → web-search-JHAXVEMD.js} +9 -14
  270. package/chunks/{web-shell-static-T7UGLVE4.js → web-shell-static-FFWCUUZS.js} +8 -4
  271. package/chunks/{workflow-4TWAFNIB.js → workflow-O7L6VDYU.js} +396 -113
  272. package/chunks/{workspace-providers-status-GNTJ4OIZ.js → workspace-providers-status-WRX6CJM4.js} +53 -56
  273. package/chunks/{workspace-registration-store-D3K34O63.js → workspace-registration-store-7G4E7YPY.js} +1 -1
  274. package/chunks/{workspace-registry-ZE5ZSWNF.js → workspace-registry-SXIMGT4D.js} +47 -50
  275. package/chunks/{workspace-runtime-coordinator-DEXM2635.js → workspace-runtime-coordinator-7DOEHXYT.js} +47 -50
  276. package/chunks/{workspace-service-OGYORPWD.js → workspace-service-HDXOZMYC.js} +53 -56
  277. package/chunks/{workspace-skills-status-4W4H3BGJ.js → workspace-skills-status-VN4L37CA.js} +50 -53
  278. package/chunks/{workspace-trust-reconciler-BHR7S7UJ.js → workspace-trust-reconciler-XEBW5FUL.js} +57 -60
  279. package/chunks/{write-file-EP5AEO5E.js → write-file-LKX4ETIO.js} +29 -32
  280. package/chunks/{zh-V2EYTYJP.js → zh-F76MZTL3.js} +23 -1
  281. package/chunks/{zh-TW-7PRVUGLW.js → zh-TW-S3YTQ4DS.js} +23 -1
  282. package/chunks/{zoom-image-DDEGWG3R.js → zoom-image-RDPRTP4B.js} +5 -9
  283. package/cli.js +19 -15
  284. package/export-transcript-document.css +1 -1
  285. package/export-transcript-document.js +151 -150
  286. package/locales/ca.js +19 -2
  287. package/locales/de.js +18 -0
  288. package/locales/en.js +33 -2
  289. package/locales/fr.js +18 -0
  290. package/locales/ja.js +18 -0
  291. package/locales/pt.js +18 -0
  292. package/locales/ru.js +18 -0
  293. package/locales/zh-TW.js +33 -2
  294. package/locales/zh.js +33 -2
  295. package/package.json +3 -3
  296. package/web-shell/assets/{abnfDiagram-VCTEODGH-BtpzKw3A.js → abnfDiagram-VCTEODGH-RxykUDmi.js} +1 -1
  297. package/web-shell/assets/{arc-CQiVKZJP.js → arc-CZpgGCJC.js} +1 -1
  298. package/web-shell/assets/{architectureDiagram-5GKGNRK7-ekIPBb2d.js → architectureDiagram-5GKGNRK7-BHSMzNDT.js} +1 -1
  299. package/web-shell/assets/{blockDiagram-NRAW4CY4-BrRWkWri.js → blockDiagram-NRAW4CY4-Bn4mF9SZ.js} +1 -1
  300. package/web-shell/assets/{c4Diagram-UCG6FXSJ-qYS8CYZ3.js → c4Diagram-UCG6FXSJ-CBM-Bj6t.js} +1 -1
  301. package/web-shell/assets/channel-DFYs_LlK.js +1 -0
  302. package/web-shell/assets/{chunk-2Q5K7J3B-ZasyyEZm.js → chunk-2Q5K7J3B-D5Fin58O.js} +1 -1
  303. package/web-shell/assets/{chunk-5VM5RSS4-C_IzCGeA.js → chunk-5VM5RSS4-CY05weF7.js} +1 -1
  304. package/web-shell/assets/{chunk-F27PBJKO-C25NZOyD.js → chunk-F27PBJKO-3neZnj5Y.js} +1 -1
  305. package/web-shell/assets/{chunk-G27WJ6UU-XPOHNSGX.js → chunk-G27WJ6UU-Cd7EU4BE.js} +1 -1
  306. package/web-shell/assets/{chunk-JWPE2WC7-BQBh0Xni.js → chunk-JWPE2WC7-DwK1mqFw.js} +1 -1
  307. package/web-shell/assets/{chunk-LCL6LL3I-CoShjpX7.js → chunk-LCL6LL3I-Sl7vY22C.js} +1 -1
  308. package/web-shell/assets/{chunk-POPQ4Y6H-BwRmCDSz.js → chunk-POPQ4Y6H-BXNzpbVg.js} +1 -1
  309. package/web-shell/assets/{chunk-SVP7TREG-DSzE5-Mw.js → chunk-SVP7TREG-DjjButcp.js} +1 -1
  310. package/web-shell/assets/{chunk-XXDRQBXY-BQSQv30h.js → chunk-XXDRQBXY-DNOiCjOJ.js} +1 -1
  311. package/web-shell/assets/classDiagram-DTDB5LWJ-DnGrKXoM.js +1 -0
  312. package/web-shell/assets/classDiagram-v2-JRS7N3AN-DnGrKXoM.js +1 -0
  313. package/web-shell/assets/{cose-bilkent-JH36ORCC-XVUVTHVo.js → cose-bilkent-JH36ORCC-BUnker7a.js} +1 -1
  314. package/web-shell/assets/{cynefin-OW5HDTMX-CrsKx4lQ.js → cynefin-OW5HDTMX-DcUgdWE5.js} +1 -1
  315. package/web-shell/assets/{cynefinDiagram-5FMLGOSQ-BPeZEuHw.js → cynefinDiagram-5FMLGOSQ-CvDKsZsL.js} +1 -1
  316. package/web-shell/assets/{dagre-3AP2YEHR-D31cQ2Qs.js → dagre-3AP2YEHR-jpCmUbr1.js} +1 -1
  317. package/web-shell/assets/{diagram-S7CK7UJ4-zyiG097Q.js → diagram-S7CK7UJ4-DBe_bKE5.js} +1 -1
  318. package/web-shell/assets/{diagram-UQ7AKVKN-Br3vtfsy.js → diagram-UQ7AKVKN-oXvPpDgs.js} +1 -1
  319. package/web-shell/assets/{diagram-VSXAHHWV-Bxkhjx4u.js → diagram-VSXAHHWV-BD7-_SGh.js} +1 -1
  320. package/web-shell/assets/{diagram-VX7I27RA-BQH8QiDk.js → diagram-VX7I27RA-DOJL0wub.js} +1 -1
  321. package/web-shell/assets/{diagram-Z3DM3KII-B_aQ1cw0.js → diagram-Z3DM3KII-DRIiodDD.js} +1 -1
  322. package/web-shell/assets/{ebnfDiagram-PWID7BFC-B9N7BRQE.js → ebnfDiagram-PWID7BFC-Db31Ulmb.js} +1 -1
  323. package/web-shell/assets/{erDiagram-SSCWMZ5O-Cx6Hb1Re.js → erDiagram-SSCWMZ5O-CVHhwI2_.js} +1 -1
  324. package/web-shell/assets/{flowDiagram-A5DVABFB-DTuLP7GU.js → flowDiagram-A5DVABFB-DWOFy1FK.js} +1 -1
  325. package/web-shell/assets/{ganttDiagram-EL5Y4UJY-DYS3d-sL.js → ganttDiagram-EL5Y4UJY-C0sxQtPd.js} +1 -1
  326. package/web-shell/assets/{gitGraphDiagram-WWUBYQGX-Cp0EGx04.js → gitGraphDiagram-WWUBYQGX-CNituBYC.js} +1 -1
  327. package/web-shell/assets/index-B15NlwB8.js +2213 -0
  328. package/web-shell/assets/index-BSrS0tQ6.css +36 -0
  329. package/web-shell/assets/{index-45-LkPDB.js → index-gm9tLk7h.js} +1 -1
  330. package/web-shell/assets/{infoDiagram-RXCK75RN-9--kukiT.js → infoDiagram-RXCK75RN-CxhJYtIR.js} +1 -1
  331. package/web-shell/assets/{ishikawaDiagram-5VMMS53U-CGBdsDLD.js → ishikawaDiagram-5VMMS53U-By2mchUy.js} +1 -1
  332. package/web-shell/assets/{journeyDiagram-EYS64GPL-DeXhcscd.js → journeyDiagram-EYS64GPL-CVH-OweI.js} +1 -1
  333. package/web-shell/assets/{kanban-definition-3QL26DDD-CFdvsU3b.js → kanban-definition-3QL26DDD-Cc9dQXLy.js} +1 -1
  334. package/web-shell/assets/knowledge-Dg9788h4.svg +1 -0
  335. package/web-shell/assets/{layout-DAnwQ3KB.js → layout-C_60ysHw.js} +1 -1
  336. package/web-shell/assets/{linear-CTo7v7Nh.js → linear-BvAVfqwu.js} +1 -1
  337. package/web-shell/assets/{mermaid.core-jggSxF1i.js → mermaid.core-C3CoBKAc.js} +6 -6
  338. package/web-shell/assets/{mindmap-definition-FBJOCRG2-DzIepvlJ.js → mindmap-definition-FBJOCRG2-Cuu8Q8LM.js} +1 -1
  339. package/web-shell/assets/{pegDiagram-XKGWAZYB-BFGS9GJv.js → pegDiagram-XKGWAZYB-DmAeyDO2.js} +1 -1
  340. package/web-shell/assets/{pieDiagram-E7YTZNPT-B2UUcNIT.js → pieDiagram-E7YTZNPT-B7vbB_xv.js} +1 -1
  341. package/web-shell/assets/{quadrantDiagram-AXDQQJYC-BgM6htrX.js → quadrantDiagram-AXDQQJYC-BqOBkRR7.js} +1 -1
  342. package/web-shell/assets/{railroadDiagram-O6MQD6OU-Dk9cS7N-.js → railroadDiagram-O6MQD6OU-sI06lZIu.js} +1 -1
  343. package/web-shell/assets/{requirementDiagram-EFPCY7ZU-C9oRg7xi.js → requirementDiagram-EFPCY7ZU-Bg13d10S.js} +1 -1
  344. package/web-shell/assets/{sankeyDiagram-P5KCCOFB-B-_c7GzI.js → sankeyDiagram-P5KCCOFB-WFOzZHrR.js} +1 -1
  345. package/web-shell/assets/{sequenceDiagram-WJ2MYXX4-R0M-347u.js → sequenceDiagram-WJ2MYXX4-CCdRbA4E.js} +1 -1
  346. package/web-shell/assets/{sizeCapture-X5ZJPWSS-Df0f8UAW.js → sizeCapture-X5ZJPWSS-BH5F3bGg.js} +1 -1
  347. package/web-shell/assets/{stateDiagram-HBIQ2CUA-CsUEfAA-.js → stateDiagram-HBIQ2CUA-NwS2X3QB.js} +1 -1
  348. package/web-shell/assets/stateDiagram-v2-4QOOHH4V-1aU2JZXO.js +1 -0
  349. package/web-shell/assets/{swimlanes-XN3QIQJK-9OGHVSrx.js → swimlanes-XN3QIQJK-Bm38pM28.js} +1 -1
  350. package/web-shell/assets/swimlanesDiagram-VK2B7HYN-Dp-u6kQG.js +8 -0
  351. package/web-shell/assets/{timeline-definition-24CTP7MA-DAfGqS2B.js → timeline-definition-24CTP7MA-Do-agLSo.js} +1 -1
  352. package/web-shell/assets/{vennDiagram-4TSXK5OY-CKATpwHi.js → vennDiagram-4TSXK5OY-aggLfZzl.js} +1 -1
  353. package/web-shell/assets/{wardleyDiagram-VM6X3IG4-CQHdhTrm.js → wardleyDiagram-VM6X3IG4-D5JR3mXX.js} +1 -1
  354. package/web-shell/assets/{xychartDiagram-S5SC5T6Z-5k9NLqlY.js → xychartDiagram-S5SC5T6Z-DhtLDuXs.js} +1 -1
  355. package/web-shell/index.html +2 -2
  356. package/chunks/chunk-7MIBD3LG.js +0 -137
  357. package/chunks/chunk-ARDHE6MM.js +0 -235
  358. package/chunks/chunk-C75BXMPM.js +0 -169
  359. package/chunks/chunk-ERU3SDXT.js +0 -27
  360. package/chunks/chunk-FPGTNKCP.js +0 -251
  361. package/chunks/chunk-JL6APGBX.js +0 -43
  362. package/chunks/chunk-L5OBTAXN.js +0 -137
  363. package/chunks/chunk-MZ3W3F44.js +0 -4172
  364. package/chunks/chunk-OIDF7L67.js +0 -514
  365. package/chunks/chunk-VSXX6VUI.js +0 -2812
  366. package/chunks/chunk-ZFYACOVD.js +0 -1416
  367. package/web-shell/assets/channel-DSQQnOZj.js +0 -1
  368. package/web-shell/assets/classDiagram-DTDB5LWJ-V94ta08R.js +0 -1
  369. package/web-shell/assets/classDiagram-v2-JRS7N3AN-V94ta08R.js +0 -1
  370. package/web-shell/assets/index-H8um-iEl.js +0 -2207
  371. package/web-shell/assets/index-n6N-2a3v.css +0 -36
  372. package/web-shell/assets/stateDiagram-v2-4QOOHH4V-CnSuTPJ2.js +0 -1
  373. package/web-shell/assets/swimlanesDiagram-VK2B7HYN-Bb7TcWQw.js +0 -8
  374. package/chunks/{chunk-QZW6WRB7.js → chunk-5NUKK2DT.js} +2 -2
  375. package/chunks/{chunk-JS73NNWF.js → chunk-FUSEMYFX.js} +0 -0
  376. package/chunks/{chunk-SVWWF5TZ.js → chunk-WVURIAEE.js} +3 -3
  377. package/chunks/{task-update-RI7QNVDP.js → task-update-3LSYQDRW.js} +4 -4
@@ -1,4172 +0,0 @@
1
- // Force strict mode and setup for ESM
2
- "use strict";
3
- import {
4
- AgentEventEmitter,
5
- attachJsonlTranscriptWriter,
6
- buildAgentTranscriptAttach,
7
- deriveApprovalModeConfig,
8
- deriveConfig,
9
- deriveWorktreeConfig,
10
- installSessionWorkflowRevisionWriteThrough,
11
- isActiveWorkflowStatus,
12
- isTerminalWorkflowStatus,
13
- isWorkflowRunPersistenceActive,
14
- parseSkillContent,
15
- rebuildToolRegistryOnOverride,
16
- resolveExternalWorktreeDir,
17
- toModelVisibleSubagentResult
18
- } from "./chunk-AYMSNIYL.js";
19
- import {
20
- parsePositiveIntegerEnv
21
- } from "./chunk-6PVPNMXU.js";
22
- import {
23
- GitWorktreeService,
24
- generateAgentWorktreeSlug,
25
- writeWorktreeSessionMarker
26
- } from "./chunk-WKVZES7O.js";
27
- import {
28
- resolveBundleDir
29
- } from "./chunk-ACHCT36C.js";
30
- import {
31
- SUBAGENT_PLAN_LIFECYCLE_TOOLS
32
- } from "./chunk-AEWCOE64.js";
33
- import {
34
- runWithAgentContext
35
- } from "./chunk-BW2SMO6L.js";
36
- import {
37
- read,
38
- writeLine
39
- } from "./chunk-UB2MATP5.js";
40
- import {
41
- REASONING_EFFORT_TIERS,
42
- normalizeReasoningEffort
43
- } from "./chunk-ARDHE6MM.js";
44
- import {
45
- atomicWriteFile
46
- } from "./chunk-XFFRI3WM.js";
47
- import {
48
- stripAnsiAndControl
49
- } from "./chunk-4Y2I3CI3.js";
50
- import {
51
- SyntheticOutputTool
52
- } from "./chunk-SYROIHU7.js";
53
- import {
54
- ToolNames,
55
- resolveBuiltinToolName
56
- } from "./chunk-RSWBT7AZ.js";
57
- import {
58
- Storage,
59
- createDebugLogger
60
- } from "./chunk-ZAFYHRVY.js";
61
- import {
62
- init_esbuild_shims
63
- } from "./chunk-5O2XNYP6.js";
64
- import {
65
- __name
66
- } from "./chunk-J2S4EL5Y.js";
67
-
68
- // packages/core/src/agents/runtime/workflow-sandbox.ts
69
- init_esbuild_shims();
70
- import * as vm from "node:vm";
71
-
72
- // packages/core/src/agents/runtime/workflow-meta-literal.ts
73
- init_esbuild_shims();
74
- var WorkflowMetaSyntaxError = class extends Error {
75
- static {
76
- __name(this, "WorkflowMetaSyntaxError");
77
- }
78
- index;
79
- constructor(message, index) {
80
- super(message);
81
- this.name = "WorkflowMetaSyntaxError";
82
- this.index = index;
83
- }
84
- };
85
- function parseWorkflowMetaLiteral(source) {
86
- const parser = new MetaLiteralParser(source);
87
- parser.skipTrivia();
88
- const value = parser.parseValue(0);
89
- parser.skipTrivia();
90
- if (parser.index < source.length) {
91
- throw parser.fail("unexpected trailing content");
92
- }
93
- return value;
94
- }
95
- __name(parseWorkflowMetaLiteral, "parseWorkflowMetaLiteral");
96
- var MAX_DEPTH = 32;
97
- var WHITESPACE = /* @__PURE__ */ new Set([" ", " ", "\n", "\r", "\f", "\v", "\xA0", "\uFEFF"]);
98
- var ID_START = /[A-Za-z_$]/;
99
- var ID_PART = /[A-Za-z0-9_$]/;
100
- var MetaLiteralParser = class {
101
- constructor(src) {
102
- this.src = src;
103
- }
104
- static {
105
- __name(this, "MetaLiteralParser");
106
- }
107
- index = 0;
108
- fail(message) {
109
- const from = Math.max(0, this.index - 24);
110
- const snippet = this.src.slice(from, this.index + 24).replace(/\s+/g, " ").trim();
111
- return new WorkflowMetaSyntaxError(
112
- `${message} at position ${this.index} (near "${snippet}"). meta must be a plain object literal \u2014 strings, numbers, booleans, null, arrays and objects only, with no variables, function calls, spreads, accessors or template substitutions.`,
113
- this.index
114
- );
115
- }
116
- skipTrivia() {
117
- for (; ; ) {
118
- while (this.index < this.src.length && WHITESPACE.has(this.src[this.index])) {
119
- this.index++;
120
- }
121
- if (this.src.startsWith("//", this.index)) {
122
- let end = this.index + 2;
123
- while (end < this.src.length && !"\n\r\u2028\u2029".includes(this.src[end])) {
124
- end++;
125
- }
126
- if (this.src[end] === "\r" && this.src[end + 1] === "\n") end++;
127
- this.index = end < this.src.length ? end + 1 : this.src.length;
128
- continue;
129
- }
130
- if (this.src.startsWith("/*", this.index)) {
131
- const end = this.src.indexOf("*/", this.index + 2);
132
- if (end === -1) throw this.fail("unterminated comment");
133
- this.index = end + 2;
134
- continue;
135
- }
136
- return;
137
- }
138
- }
139
- parseValue(depth) {
140
- if (depth > MAX_DEPTH) throw this.fail("meta literal is nested too deeply");
141
- this.skipTrivia();
142
- const c = this.src[this.index];
143
- if (c === void 0) throw this.fail("unexpected end of meta literal");
144
- if (c === "{") return this.parseObject(depth);
145
- if (c === "[") return this.parseArray(depth);
146
- if (c === '"' || c === "'" || c === "`") return this.parseString();
147
- if (c === "-" || c >= "0" && c <= "9") return this.parseNumber();
148
- if (this.src.startsWith("true", this.index)) return this.word("true", true);
149
- if (this.src.startsWith("false", this.index)) {
150
- return this.word("false", false);
151
- }
152
- if (this.src.startsWith("null", this.index)) return this.word("null", null);
153
- if (c === "/")
154
- throw this.fail("regular expressions are not allowed in meta");
155
- throw this.fail("unsupported value");
156
- }
157
- word(literal, value) {
158
- const after = this.src[this.index + literal.length];
159
- if (after !== void 0 && ID_PART.test(after)) {
160
- throw this.fail("unsupported value");
161
- }
162
- this.index += literal.length;
163
- return value;
164
- }
165
- parseObject(depth) {
166
- this.index++;
167
- const out = /* @__PURE__ */ Object.create(null);
168
- for (; ; ) {
169
- this.skipTrivia();
170
- const c = this.src[this.index];
171
- if (c === "}") {
172
- this.index++;
173
- return out;
174
- }
175
- if (c === void 0) throw this.fail("unterminated object");
176
- if (this.src.startsWith("...", this.index)) {
177
- throw this.fail("spread is not allowed in meta");
178
- }
179
- if (c === "[") throw this.fail("computed keys are not allowed in meta");
180
- const key = this.parseKey();
181
- this.skipTrivia();
182
- if (this.src[this.index] === "(") {
183
- throw this.fail("methods are not allowed in meta");
184
- }
185
- if (this.src[this.index] !== ":")
186
- throw this.fail('expected ":" after key');
187
- this.index++;
188
- out[key] = this.parseValue(depth + 1);
189
- this.skipTrivia();
190
- if (this.src[this.index] === ",") {
191
- this.index++;
192
- continue;
193
- }
194
- if (this.src[this.index] === "}") {
195
- this.index++;
196
- return out;
197
- }
198
- throw this.fail('expected "," or "}"');
199
- }
200
- }
201
- parseKey() {
202
- const c = this.src[this.index];
203
- if (c === '"' || c === "'" || c === "`") return this.parseString();
204
- if (c !== void 0 && ID_START.test(c)) {
205
- const start = this.index;
206
- while (this.index < this.src.length && ID_PART.test(this.src[this.index])) {
207
- this.index++;
208
- }
209
- const word = this.src.slice(start, this.index);
210
- if (word === "get" || word === "set" || word === "async") {
211
- const save = this.index;
212
- this.skipTrivia();
213
- const next = this.src[this.index];
214
- const startsPropertyName = next !== void 0 && (ID_START.test(next) || next === '"' || next === "'" || next === "[");
215
- this.index = save;
216
- if (startsPropertyName) {
217
- throw this.fail(
218
- word === "async" ? "async members are not allowed in meta" : `${word}ters are not allowed in meta`
219
- );
220
- }
221
- }
222
- return word;
223
- }
224
- throw this.fail("expected a property name");
225
- }
226
- parseArray(depth) {
227
- this.index++;
228
- const out = [];
229
- for (; ; ) {
230
- this.skipTrivia();
231
- const c = this.src[this.index];
232
- if (c === "]") {
233
- this.index++;
234
- return out;
235
- }
236
- if (c === void 0) throw this.fail("unterminated array");
237
- if (this.src.startsWith("...", this.index)) {
238
- throw this.fail("spread is not allowed in meta");
239
- }
240
- if (c === ",") throw this.fail("missing array element");
241
- out.push(this.parseValue(depth + 1));
242
- this.skipTrivia();
243
- if (this.src[this.index] === ",") {
244
- this.index++;
245
- continue;
246
- }
247
- if (this.src[this.index] === "]") {
248
- this.index++;
249
- return out;
250
- }
251
- throw this.fail('expected "," or "]"');
252
- }
253
- }
254
- parseString() {
255
- const quote = this.src[this.index++];
256
- let out = "";
257
- for (; ; ) {
258
- const c = this.src[this.index];
259
- if (c === void 0) throw this.fail("unterminated string");
260
- if (c === quote) {
261
- this.index++;
262
- return out;
263
- }
264
- if (c === "\n" || c === "\r") {
265
- if (quote !== "`") throw this.fail("unterminated string");
266
- if (c === "\r") {
267
- this.index++;
268
- if (this.src[this.index] === "\n") this.index++;
269
- out += "\n";
270
- continue;
271
- }
272
- }
273
- if (quote === "`" && c === "$" && this.src[this.index + 1] === "{") {
274
- throw this.fail("template substitutions are not allowed in meta");
275
- }
276
- if (c === "\\") {
277
- out += this.parseEscape();
278
- continue;
279
- }
280
- out += c;
281
- this.index++;
282
- }
283
- }
284
- parseEscape() {
285
- this.index++;
286
- const c = this.src[this.index++];
287
- switch (c) {
288
- case "n":
289
- return "\n";
290
- case "t":
291
- return " ";
292
- case "r":
293
- return "\r";
294
- case "b":
295
- return "\b";
296
- case "f":
297
- return "\f";
298
- case "v":
299
- return "\v";
300
- case "0":
301
- if (/[0-9]/.test(this.src[this.index] ?? "")) {
302
- throw this.fail("octal escapes are not allowed in meta");
303
- }
304
- return "\0";
305
- case "x": {
306
- const hex = this.src.slice(this.index, this.index + 2);
307
- if (!/^[0-9a-fA-F]{2}$/.test(hex)) {
308
- throw this.fail("invalid \\x escape");
309
- }
310
- this.index += 2;
311
- return String.fromCharCode(parseInt(hex, 16));
312
- }
313
- case "u": {
314
- if (this.src[this.index] === "{") {
315
- const end = this.src.indexOf("}", this.index);
316
- const hex2 = end === -1 ? "" : this.src.slice(this.index + 1, end);
317
- if (!/^[0-9a-fA-F]{1,6}$/.test(hex2)) {
318
- throw this.fail("invalid \\u{...} escape");
319
- }
320
- const code = parseInt(hex2, 16);
321
- if (code > 1114111) throw this.fail("invalid \\u{...} escape");
322
- this.index = end + 1;
323
- return String.fromCodePoint(code);
324
- }
325
- const hex = this.src.slice(this.index, this.index + 4);
326
- if (!/^[0-9a-fA-F]{4}$/.test(hex)) {
327
- throw this.fail("invalid \\u escape");
328
- }
329
- this.index += 4;
330
- return String.fromCharCode(parseInt(hex, 16));
331
- }
332
- case "\n":
333
- return "";
334
- // line continuation
335
- case "\r":
336
- if (this.src[this.index] === "\n") this.index++;
337
- return "";
338
- case "\u2028":
339
- case "\u2029":
340
- return "";
341
- case void 0:
342
- throw this.fail("unterminated escape sequence");
343
- default:
344
- return c;
345
- }
346
- }
347
- parseNumber() {
348
- const start = this.index;
349
- if (this.src[this.index] === "-") this.index++;
350
- while (this.index < this.src.length && /[0-9]/.test(this.src[this.index])) {
351
- this.index++;
352
- }
353
- if (this.src[this.index] === ".") {
354
- this.index++;
355
- while (this.index < this.src.length && /[0-9]/.test(this.src[this.index])) {
356
- this.index++;
357
- }
358
- }
359
- if (this.src[this.index] === "e" || this.src[this.index] === "E") {
360
- this.index++;
361
- if (this.src[this.index] === "+" || this.src[this.index] === "-") {
362
- this.index++;
363
- }
364
- while (this.index < this.src.length && /[0-9]/.test(this.src[this.index])) {
365
- this.index++;
366
- }
367
- }
368
- const after = this.src[this.index];
369
- if (after !== void 0 && ID_PART.test(after)) {
370
- throw this.fail("unsupported numeric literal");
371
- }
372
- const text = this.src.slice(start, this.index);
373
- const value = Number(text);
374
- if (text.length === 0 || !Number.isFinite(value)) {
375
- throw this.fail("unsupported numeric literal");
376
- }
377
- return value;
378
- }
379
- };
380
-
381
- // packages/core/src/agents/runtime/workflow-sandbox.ts
382
- function findMetaBlockBounds(source) {
383
- const re = /^\s*export\s+const\s+meta\s*=\s*\{/;
384
- const match = re.exec(source);
385
- if (!match) return null;
386
- const exportIdx = match.index;
387
- const startBrace = source.indexOf("{", exportIdx);
388
- let depth = 1;
389
- let i = startBrace + 1;
390
- while (i < source.length && depth > 0) {
391
- const ch = source[i];
392
- const next = source[i + 1];
393
- if (ch === "/" && next === "/") {
394
- i += 2;
395
- while (i < source.length && source[i] !== "\n") i++;
396
- continue;
397
- }
398
- if (ch === "/" && next === "*") {
399
- i += 2;
400
- while (i < source.length && !(source[i] === "*" && source[i + 1] === "/"))
401
- i++;
402
- i += 2;
403
- continue;
404
- }
405
- if (ch === "/" && isRegexContext(source, i)) {
406
- i++;
407
- let inClass = false;
408
- while (i < source.length && (inClass || source[i] !== "/") && source[i] !== "\n") {
409
- if (source[i] === "\\") i += 2;
410
- else if (source[i] === "[") {
411
- inClass = true;
412
- i++;
413
- } else if (source[i] === "]") {
414
- inClass = false;
415
- i++;
416
- } else {
417
- i++;
418
- }
419
- }
420
- i++;
421
- while (i < source.length && /[gimsuy]/.test(source[i])) i++;
422
- continue;
423
- }
424
- if (ch === '"' || ch === "'" || ch === "`") {
425
- const q = ch;
426
- i++;
427
- while (i < source.length && source[i] !== q) {
428
- if (source[i] === "\\") i++;
429
- i++;
430
- }
431
- i++;
432
- continue;
433
- }
434
- if (ch === "{") depth++;
435
- else if (ch === "}") depth--;
436
- i++;
437
- }
438
- if (depth !== 0) {
439
- throw new Error(
440
- "unbalanced braces in export const meta declaration \u2014 the workflow script cannot be safely stripped. Check the meta block syntax."
441
- );
442
- }
443
- const endBraceIncl = i - 1;
444
- while (i < source.length && /[\s;]/.test(source[i])) i++;
445
- return { exportIdx, startBrace, endBraceIncl, afterMeta: i };
446
- }
447
- __name(findMetaBlockBounds, "findMetaBlockBounds");
448
- function extractAndStripMeta(source) {
449
- const bounds = findMetaBlockBounds(source);
450
- if (!bounds) return { stripped: source, meta: null };
451
- const metaSource = source.slice(bounds.startBrace, bounds.endBraceIncl + 1);
452
- const stripped = source.slice(0, bounds.exportIdx) + source.slice(bounds.afterMeta);
453
- let raw;
454
- try {
455
- raw = parseWorkflowMetaLiteral(metaSource);
456
- } catch (e) {
457
- const msg = e instanceof Error ? e.message : String(e);
458
- throw new Error(`invalid meta object literal: ${msg}`);
459
- }
460
- const meta = validateMeta(raw);
461
- return { stripped, meta };
462
- }
463
- __name(extractAndStripMeta, "extractAndStripMeta");
464
- var WORKFLOW_SCRIPT_FILENAME = "workflow.js";
465
- function wrapWorkflowBody(strippedSource) {
466
- return `(async () => {'use strict';
467
- ${strippedSource}
468
- })()`;
469
- }
470
- __name(wrapWorkflowBody, "wrapWorkflowBody");
471
- function compileWorkflowScript(scriptSource) {
472
- const { stripped, meta } = extractAndStripMeta(scriptSource);
473
- const bounds = findMetaBlockBounds(scriptSource);
474
- const compilable = bounds ? scriptSource.slice(0, bounds.exportIdx) + scriptSource.slice(bounds.exportIdx, bounds.afterMeta).replace(/[^\r\n\u2028\u2029]/g, " ") + scriptSource.slice(bounds.afterMeta) : stripped;
475
- const script = new vm.Script(wrapWorkflowBody(compilable), {
476
- filename: WORKFLOW_SCRIPT_FILENAME
477
- });
478
- return { script, meta };
479
- }
480
- __name(compileWorkflowScript, "compileWorkflowScript");
481
- function workflowCancelledError() {
482
- const error = new Error("Workflow run was aborted (cancelled).");
483
- error.name = "AbortError";
484
- return error;
485
- }
486
- __name(workflowCancelledError, "workflowCancelledError");
487
- var COMPILE_ERROR_LINE_WIDTH = 80;
488
- function describeWorkflowCompileError(error, authorLineCount) {
489
- const err = error instanceof Error ? error : new Error(String(error));
490
- const stack = typeof err.stack === "string" ? err.stack : "";
491
- const frame = [];
492
- for (const line of stack.split("\n")) {
493
- if (frame.length >= 3 && /^\s+at\s/.test(line)) break;
494
- frame.push(line);
495
- }
496
- const header = frame[0] ?? "";
497
- const match = /^.*?:(\d+)$/.exec(header);
498
- if (frame.length < 3 || !match) {
499
- return err.message;
500
- }
501
- const bodyLine = Number(match[1]) - 1;
502
- if (bodyLine < 1) return err.message;
503
- if (bodyLine > authorLineCount) {
504
- return "The script ends with unmatched or incomplete syntax. Check parentheses, brackets, braces, quotes, and template literals near the end.";
505
- }
506
- const rendered = clampSourceFrame(frame[1] ?? "", frame[2] ?? "");
507
- const tail = frame.slice(3).filter((l) => l.trim().length > 0).join("\n");
508
- return [`line ${bodyLine}`, rendered, tail].filter(Boolean).join("\n");
509
- }
510
- __name(describeWorkflowCompileError, "describeWorkflowCompileError");
511
- function clampSourceFrame(sourceLine, caretLine) {
512
- if (sourceLine.length <= COMPILE_ERROR_LINE_WIDTH) {
513
- return `${sourceLine}
514
- ${caretLine}`;
515
- }
516
- const caret = /\^+/.exec(caretLine);
517
- if (!caret) return "";
518
- const caretCol = caret.index;
519
- const start = Math.max(
520
- 0,
521
- Math.min(
522
- caretCol - Math.floor(COMPILE_ERROR_LINE_WIDTH / 2),
523
- sourceLine.length - COMPILE_ERROR_LINE_WIDTH
524
- )
525
- );
526
- const prefix = start > 0 ? "\u2026" : "";
527
- const window = sourceLine.slice(start, start + COMPILE_ERROR_LINE_WIDTH);
528
- const suffix = start + COMPILE_ERROR_LINE_WIDTH < sourceLine.length ? "\u2026" : "";
529
- const visibleCaretStart = Math.max(caretCol, start);
530
- const visibleCaretEnd = Math.min(
531
- caretCol + caret[0].length,
532
- start + COMPILE_ERROR_LINE_WIDTH
533
- );
534
- const shiftedCaret = " ".repeat(prefix.length + visibleCaretStart - start) + "^".repeat(visibleCaretEnd - visibleCaretStart);
535
- return `${prefix}${window}${suffix}
536
- ${shiftedCaret}`;
537
- }
538
- __name(clampSourceFrame, "clampSourceFrame");
539
- function validateMeta(value) {
540
- if (value === null || typeof value !== "object") {
541
- throw new Error("meta must be an object");
542
- }
543
- const obj = value;
544
- if (typeof obj["name"] !== "string" || obj["name"].length === 0) {
545
- throw new Error("meta.name must be a non-empty string");
546
- }
547
- if (typeof obj["description"] !== "string" || obj["description"].length === 0) {
548
- throw new Error("meta.description must be a non-empty string");
549
- }
550
- if (obj["whenToUse"] !== void 0 && typeof obj["whenToUse"] !== "string") {
551
- throw new Error("meta.whenToUse must be a string");
552
- }
553
- let phases;
554
- if (obj["phases"] !== void 0) {
555
- if (!Array.isArray(obj["phases"])) {
556
- throw new Error("meta.phases must be an array");
557
- }
558
- phases = [];
559
- for (const p of obj["phases"]) {
560
- if (p === null || typeof p !== "object") {
561
- throw new Error("meta.phases entries must be objects");
562
- }
563
- const ph = p;
564
- if (typeof ph["title"] !== "string" || ph["title"].length === 0) {
565
- throw new Error("meta.phases[].title must be a non-empty string");
566
- }
567
- const phase = {
568
- title: ph["title"]
569
- };
570
- if (ph["detail"] !== void 0) {
571
- if (typeof ph["detail"] !== "string") {
572
- throw new Error("meta.phases[].detail must be a string");
573
- }
574
- phase.detail = ph["detail"];
575
- }
576
- if (ph["model"] !== void 0) {
577
- if (typeof ph["model"] !== "string") {
578
- throw new Error("meta.phases[].model must be a string");
579
- }
580
- phase.model = ph["model"];
581
- }
582
- phases.push(phase);
583
- }
584
- }
585
- const out = {
586
- name: obj["name"],
587
- description: obj["description"]
588
- };
589
- if (obj["whenToUse"] !== void 0) {
590
- out.whenToUse = obj["whenToUse"];
591
- }
592
- if (phases !== void 0) {
593
- out.phases = phases;
594
- }
595
- return out;
596
- }
597
- __name(validateMeta, "validateMeta");
598
- function isRegexContext(source, i) {
599
- let j = i - 1;
600
- while (j >= 0 && /\s/.test(source[j])) j--;
601
- if (j < 0) return true;
602
- const prev = source[j];
603
- return /[{[(,;:=!&|?+\-*/%^~<>]/.test(prev);
604
- }
605
- __name(isRegexContext, "isRegexContext");
606
- var debugLogger = createDebugLogger("WORKFLOW");
607
- var MAX_LOG_LINES = 1e4;
608
- var MAX_PHASE_ENTRIES = 1e4;
609
- var ARGS_MAX_DEPTH = 64;
610
- var DEFAULT_MAX_WALL_CLOCK_MS = 30 * 60 * 1e3;
611
- var WORKFLOW_SYNC_EVALUATION_TIMEOUT_MS = 3e4;
612
- function resolveMaxWallClockMs(opts) {
613
- if (typeof opts.maxWallClockMs === "number" && opts.maxWallClockMs > 0) {
614
- return opts.maxWallClockMs;
615
- }
616
- const envSec = Number(process.env["QWEN_CODE_MAX_WORKFLOW_SECONDS"]);
617
- if (Number.isFinite(envSec) && envSec > 0) return envSec * 1e3;
618
- return DEFAULT_MAX_WALL_CLOCK_MS;
619
- }
620
- __name(resolveMaxWallClockMs, "resolveMaxWallClockMs");
621
- var WallClockWatchdog = class {
622
- constructor(budgetMs, onFire) {
623
- this.onFire = onFire;
624
- this.remainingMs = budgetMs;
625
- this.arm();
626
- }
627
- static {
628
- __name(this, "WallClockWatchdog");
629
- }
630
- timer;
631
- remainingMs;
632
- armedAt = 0;
633
- paused = false;
634
- stopped = false;
635
- pause() {
636
- if (this.stopped || this.paused || this.timer === void 0) return;
637
- this.paused = true;
638
- clearTimeout(this.timer);
639
- this.timer = void 0;
640
- this.remainingMs = Math.max(
641
- 0,
642
- this.remainingMs - (performance.now() - this.armedAt)
643
- );
644
- }
645
- resume() {
646
- if (this.stopped || !this.paused) return;
647
- this.paused = false;
648
- this.arm();
649
- }
650
- stop() {
651
- this.stopped = true;
652
- if (this.timer !== void 0) clearTimeout(this.timer);
653
- this.timer = void 0;
654
- }
655
- arm() {
656
- this.armedAt = performance.now();
657
- this.timer = setTimeout(() => {
658
- this.stopped = true;
659
- this.timer = void 0;
660
- this.onFire();
661
- }, this.remainingMs);
662
- this.timer.unref?.();
663
- }
664
- };
665
- function validateArgs(val, depth = 0, seen = /* @__PURE__ */ new WeakSet()) {
666
- if (depth > ARGS_MAX_DEPTH) {
667
- throw new Error(
668
- `WorkflowSandbox: args exceeded max nesting depth of ${ARGS_MAX_DEPTH}`
669
- );
670
- }
671
- if (val === null) return;
672
- const t = typeof val;
673
- if (t === "function") {
674
- throw new Error(
675
- "WorkflowSandbox: args must be JSON-serializable (functions are not allowed)."
676
- );
677
- }
678
- if (t === "bigint") {
679
- throw new Error(
680
- "WorkflowSandbox: args must be JSON-serializable (BigInt is not allowed \u2014 pass as string)."
681
- );
682
- }
683
- if (t !== "object") return;
684
- const obj = val;
685
- if (seen.has(obj)) {
686
- throw new Error(
687
- "WorkflowSandbox: args must be JSON-serializable (circular reference detected)."
688
- );
689
- }
690
- seen.add(obj);
691
- if (Array.isArray(val)) {
692
- for (const item of val) validateArgs(item, depth + 1, seen);
693
- } else {
694
- for (const v of Object.values(val)) {
695
- validateArgs(v, depth + 1, seen);
696
- }
697
- }
698
- }
699
- __name(validateArgs, "validateArgs");
700
- function createWorkflowSandbox(opts) {
701
- const phases = [];
702
- const logs = [];
703
- const emitLog = /* @__PURE__ */ __name((line) => {
704
- try {
705
- opts.emitter?.logAppended?.(line);
706
- } catch (e) {
707
- debugLogger.warn("emitter.logAppended threw:", e);
708
- }
709
- }, "emitLog");
710
- const safeLog = /* @__PURE__ */ __name((msg, notify = true) => {
711
- if (logs.length < MAX_LOG_LINES) {
712
- const line = String(msg);
713
- logs.push(line);
714
- if (notify) emitLog(line);
715
- } else if (logs.length === MAX_LOG_LINES) {
716
- const line = `[workflow log truncated at ${MAX_LOG_LINES} lines]`;
717
- logs.push(line);
718
- if (notify) emitLog(line);
719
- }
720
- }, "safeLog");
721
- const safePhase = /* @__PURE__ */ __name((title) => {
722
- if (phases.length < MAX_PHASE_ENTRIES) {
723
- const t = stripAnsiAndControl(String(title)).slice(0, 200) || "phase";
724
- if (phases[phases.length - 1] === t) return;
725
- phases.push(t);
726
- try {
727
- opts.emitter?.phaseStarted?.(t);
728
- } catch (e) {
729
- debugLogger.warn("emitter.phaseStarted threw:", e);
730
- }
731
- } else if (phases.length === MAX_PHASE_ENTRIES) {
732
- phases.push(
733
- `[workflow phases truncated at ${MAX_PHASE_ENTRIES} entries]`
734
- );
735
- }
736
- }, "safePhase");
737
- if (opts.args !== void 0) validateArgs(opts.args);
738
- const argsJson = opts.args === void 0 ? null : JSON.stringify(opts.args);
739
- const unconsumedRoots = /* @__PURE__ */ new Map();
740
- const unconsumedRejections = /* @__PURE__ */ new Map();
741
- let nextUnconsumedId = 1;
742
- let unconsumedSettled = false;
743
- let mirroredEscapeKeys = /* @__PURE__ */ new Set();
744
- const unconsumedRejectionLine = /* @__PURE__ */ __name((rec) => {
745
- if (rec.dispatchFailed) {
746
- return rec.isRoot ? "dispatch failed (result not consumed): " + rec.msg : "dispatch failed (rejection not handled): " + rec.msg;
747
- }
748
- return "script handler failed (rejection not handled): " + rec.msg;
749
- }, "unconsumedRejectionLine");
750
- const bridge = {
751
- argsJson,
752
- pushPhase: safePhase,
753
- pushLog: safeLog,
754
- lastPhase: /* @__PURE__ */ __name(() => phases[phases.length - 1], "lastPhase"),
755
- hostAgent: opts.dispatch,
756
- // Effort tiers are resolved host-side so the sandbox accepts exactly the
757
- // aliases `/effort` does without a second copy of the alias table. Takes
758
- // and returns primitives only.
759
- normalizeEffort: /* @__PURE__ */ __name((raw) => typeof raw === "string" ? normalizeReasoningEffort(raw) ?? null : null, "normalizeEffort"),
760
- effortTiers: REASONING_EFFORT_TIERS.join(", "),
761
- // A built-in tool named by its display name or a legacy alias becomes its
762
- // tool name, so both spellings share one resume key; any other entry comes
763
- // back as given for the host to judge. Primitives only.
764
- canonicalDenyName: /* @__PURE__ */ __name((raw) => typeof raw === "string" ? resolveBuiltinToolName(raw) ?? raw : null, "canonicalDenyName"),
765
- // JSON.stringify escapes only C0: strip DEL / C1 (incl. NEL) from a
766
- // script-controlled echo so it cannot fragment a rejection message.
767
- sanitizeForMessage: /* @__PURE__ */ __name((raw) => typeof raw === "string" ? stripAnsiAndControl(raw) : "", "sanitizeForMessage"),
768
- // PR #4947 R2 T7 (qwen-code-ci-bot): host-side log hook for reviveInRealm's
769
- // catch path. Mirrors the rejection-logging in settleToNullArray so an
770
- // operator running with debug logging can distinguish "thunk rejected"
771
- // (settleToNullArray.warn) from "thunk resolved to a non-JSON-serializable
772
- // value" (this warn). Receives only primitive strings/numbers — the bridge
773
- // contract forbids host objects crossing back to the script.
774
- logRevivalFailure: /* @__PURE__ */ __name((idx, reason) => {
775
- debugLogger.warn(
776
- `Workflow result revival failed at index ${idx}: ${reason}; slot set to null (non-JSON-serializable thunk return).`
777
- );
778
- }, "logRevivalFailure"),
779
- // --- Unconsumed-rejection mirror bookkeeping ---
780
- wfRegisterRoot: /* @__PURE__ */ __name(() => {
781
- const id = nextUnconsumedId++;
782
- unconsumedRoots.set(id, { rejectionHandled: false, adoptedOut: false });
783
- return id;
784
- }, "wfRegisterRoot"),
785
- wfMarkRejectionHandled: /* @__PURE__ */ __name((rootId) => {
786
- const root = unconsumedRoots.get(rootId);
787
- if (root) root.rejectionHandled = true;
788
- }, "wfMarkRejectionHandled"),
789
- wfIsRootHandled: /* @__PURE__ */ __name((rootId) => unconsumedRoots.get(rootId)?.rejectionHandled === true, "wfIsRootHandled"),
790
- wfMarkAdopted: /* @__PURE__ */ __name((rootId) => {
791
- const root = unconsumedRoots.get(rootId);
792
- if (root) root.adoptedOut = true;
793
- }, "wfMarkAdopted"),
794
- runId: opts.runId ?? "",
795
- wfReportUnconsumed: /* @__PURE__ */ __name((rootId, isRoot, dispatchFailed, msg) => {
796
- if (unconsumedSettled) {
797
- const rec = {
798
- rootId,
799
- isRoot,
800
- dispatchFailed,
801
- msg
802
- };
803
- const rootState = unconsumedRoots.get(rootId);
804
- if (!rootState?.rejectionHandled && !(dispatchFailed && rootState?.adoptedOut)) {
805
- safeLog(unconsumedRejectionLine(rec));
806
- }
807
- return 0;
808
- }
809
- const id = nextUnconsumedId++;
810
- unconsumedRejections.set(id, { rootId, isRoot, dispatchFailed, msg });
811
- return id;
812
- }, "wfReportUnconsumed"),
813
- wfClearUnconsumed: /* @__PURE__ */ __name((id) => {
814
- unconsumedRejections.delete(id);
815
- }, "wfClearUnconsumed"),
816
- // R10-1: teardown discrimination cannot key on the error name alone.
817
- // The dominant in-flight cancellation path (controller.abort() →
818
- // subagent returns terminateMode=CANCELLED → runSingleDispatch throws
819
- // a PLAIN Error) never produces an 'AbortError', so the mirror would
820
- // log a spurious dispatch failure for a correctly-cancelled run. Once
821
- // the run's abort signal has fired, the run is already settling as
822
- // cancelled / timed-out — every rejection still crossing the boundary
823
- // is teardown noise regardless of its shape.
824
- isRunAborted: /* @__PURE__ */ __name(() => opts.abortOnTimeout?.signal.aborted === true, "isRunAborted"),
825
- // The truthy flags distinguish "injected" from "default stub" inside the
826
- // init script without leaking the host function itself when not used.
827
- hasParallel: !!opts.parallel,
828
- hasPipeline: !!opts.pipeline,
829
- hasWorkflow: !!opts.workflow,
830
- hasBudget: !!opts.budget,
831
- hostParallel: opts.parallel,
832
- hostPipeline: opts.pipeline,
833
- hostWorkflow: opts.workflow,
834
- budgetTotal: opts.budget ? opts.budget.total : null,
835
- hostBudgetSpent: opts.budget ? opts.budget.spent.bind(opts.budget) : null,
836
- hostBudgetRemaining: opts.budget ? opts.budget.remaining.bind(opts.budget) : null
837
- };
838
- Object.setPrototypeOf(bridge, null);
839
- const sandboxGlobals = Object.assign(
840
- /* @__PURE__ */ Object.create(null),
841
- { __workflowBridge: bridge }
842
- );
843
- const ctx = vm.createContext(sandboxGlobals);
844
- vm.runInContext(
845
- `(() => {
846
- const __b = globalThis.__workflowBridge;
847
- delete globalThis.__workflowBridge;
848
-
849
- // --- Math (vm-realm, random throws) ---
850
- const realMath = Math;
851
- const safeMath = Object.create(null);
852
- for (const k of Object.getOwnPropertyNames(realMath)) {
853
- if (k === 'random' || k === 'constructor') continue;
854
- safeMath[k] = realMath[k];
855
- }
856
- safeMath.random = () => {
857
- throw new Error(
858
- 'Math.random() is unavailable in workflow scripts (breaks resume). ' +
859
- 'For N independent samples, include the index in the agent label or prompt.'
860
- );
861
- };
862
- globalThis.Math = safeMath;
863
-
864
- // --- Date (vm-realm function that throws on any access) ---
865
- const dateMsg = 'Date.now() / new Date() are unavailable in workflow ' +
866
- 'scripts (breaks resume). Stamp results after the workflow returns, ' +
867
- 'or pass timestamps via args.';
868
- const safeDate = function Date() { throw new Error(dateMsg); };
869
- safeDate.now = () => { throw new Error(dateMsg); };
870
- safeDate.UTC = () => { throw new Error(dateMsg); };
871
- safeDate.parse = () => { throw new Error(dateMsg); };
872
- Object.setPrototypeOf(safeDate, null);
873
- Object.defineProperty(safeDate, 'constructor', {
874
- value: undefined, writable: false, configurable: false,
875
- });
876
- globalThis.Date = safeDate;
877
-
878
- // --- args (parsed via vm-realm JSON \u2192 vm-realm objects/arrays) ---
879
- // FIX-Round1-T2: vm-realm arrays keep their vm-realm Array.prototype,
880
- // so for...of, .map, .forEach, spread, destructuring all work \u2014 and
881
- // their inherited methods' constructors are vm-realm Function, which
882
- // cannot reach host process.
883
- globalThis.args = __b.argsJson === null ? undefined : JSON.parse(__b.argsJson);
884
-
885
- // --- Wrap a host async function so it returns a vm-realm Promise ---
886
- // FIX-Round1-T1/T8/T14: success and failure both cross the boundary
887
- // as vm-realm values: resolve with the host's value (a primitive
888
- // string for dispatch; vm-realm arrays for parallel/pipeline because
889
- // those wrappers will produce vm-realm results); reject with a
890
- // freshly-constructed vm-realm Error so e.constructor.constructor
891
- // stays in the vm realm.
892
- // Dispatch promises are ObservedPromise instances (a vm-realm
893
- // Promise subclass). Its then override marks the result consumed
894
- // and re-attaches the teardown observer to the derived promise, so
895
- // script-derived chains (agent(...).then(...), await, and the
896
- // ELEMENTS of static-combinator aggregates \u2014 everything that
897
- // funnels through then) stay observed at every depth. The
898
- // AGGREGATES of Promise.all/race/any are built by the native
899
- // statics and never pass through the observed then, so those
900
- // statics are wrapped explicitly below (observeAggregate).
901
- // Without this, a correctly-cancelled run holding a pending derived
902
- // chain fired a process-level unhandledRejection even though the
903
- // bare dispatch promise was observed.
904
- //
905
- // Unconsumed rejections of an observed node are recorded through
906
- // the bridge and mirrored into the run log at run settlement (a
907
- // later consumption clears the record first) \u2014 a dispatch refused
908
- // at the entry gate (budget / agent cap) or failing mid-run reaches
909
- // no other surface, so without the mirror the failure leaves no
910
- // log, alarm, or telemetry.
911
- function mapDispatchError(hostErr) {
912
- var msg;
913
- try {
914
- msg = (hostErr && hostErr.message != null)
915
- ? String(hostErr.message)
916
- : String(hostErr);
917
- } catch (e) {
918
- msg = '[unserializable rejection value]';
919
- }
920
- const vmErr = new Error(msg);
921
- // Teardown discrimination at the host boundary \u2014 before the error
922
- // is flattened into a vm-realm Error. Two shapes count as
923
- // teardown: an error NAMED 'AbortError' (the scheduler's
924
- // abortError() DOMException), and ANY rejection that crosses
925
- // after the run's abort signal has fired \u2014 the dominant
926
- // cancellation path rejects with a plain Error ('did not complete
927
- // (terminate mode: CANCELLED).'), which a name-only match would
928
- // mirror as a spurious dispatch failure on a correctly-cancelled
929
- // run. Matching the name here (rather than the message text)
930
- // still suppresses teardown noise without swallowing genuine
931
- // failures whose message merely contains 'aborted' (e.g. a
932
- // network-layer 'connection aborted by peer').
933
- var isAbort = false;
934
- try {
935
- isAbort = !!(hostErr && hostErr.name === 'AbortError');
936
- } catch (e) {
937
- isAbort = false;
938
- }
939
- if (isAbort || __b.isRunAborted()) vmErr.__wfAbort = true;
940
- var isRunFailure = false;
941
- try {
942
- isRunFailure = !!(hostErr && (
943
- hostErr.__wfRunFailure === true ||
944
- hostErr.name === 'WorkflowBudgetExceededError' ||
945
- hostErr.name === 'WorkflowAgentCapExceededError'
946
- ));
947
- } catch (e) {
948
- isRunFailure = false;
949
- }
950
- if (isRunFailure) vmErr.__wfRunFailure = true;
951
- vmErr.__wfDispatchFailed = true;
952
- return vmErr;
953
- }
954
- function readFlag(value, name) {
955
- try {
956
- return !!(value && value[name]);
957
- } catch (e) {
958
- return false;
959
- }
960
- }
961
- function observeDispatch(promise) {
962
- // Direct native-then call: routing through ObservedPromise.then
963
- // would mark the promise consumed and recurse the observer. The
964
- // observer body must be exception-safe on ANY rejection value:
965
- // a script handler can throw an exotic value (a message getter
966
- // that throws, a Proxy with throwing traps), and an observer
967
- // killed mid-body would turn the very rejection it watches into
968
- // a process-level unhandledRejection \u2014 the exact failure class
969
- // the observer exists to remove.
970
- Promise.prototype.then.call(promise, undefined, function (err) {
971
- if (promise.__wfConsumed) return;
972
- // R11-30: also suppress on the run-level abort state, not just
973
- // the rejection's own marker \u2014 a wrapped Promise.any aggregate
974
- // rejects with a natively built AggregateError that carries
975
- // neither marker, so teardown rejections of a correctly-
976
- // cancelled run would still be mirrored when it is unconsumed.
977
- if (readFlag(err, '__wfAbort') || __b.isRunAborted()) return;
978
- var dispatchFailed = readFlag(err, '__wfDispatchFailed');
979
- var errors = null;
980
- try {
981
- if (err && Array.isArray(err.errors)) errors = err.errors;
982
- } catch (e) {
983
- errors = null;
984
- }
985
- if (!dispatchFailed && errors) {
986
- // R11-4: Promise.any rejects with a fresh vm-realm
987
- // AggregateError carrying no flags; the element errors are
988
- // reachable on .errors with their markers preserved. Derive
989
- // the attribution from the causes instead of blaming the
990
- // script for a dispatch failure.
991
- for (var i = 0; i < errors.length; i++) {
992
- if (readFlag(errors[i], '__wfDispatchFailed')) {
993
- dispatchFailed = true;
994
- break;
995
- }
996
- }
997
- }
998
- // R11-15: cross-root suppression \u2014 aggregate roots track
999
- // rejectionHandled independently of their elements' roots, so
1000
- // a forwarded dispatch failure whose originating element root
1001
- // the script already handled must not mirror from the
1002
- // aggregate. The element rootId is stamped in vmAsync;
1003
- // Promise.all/race forward the element's own reason,
1004
- // Promise.any surfaces them on .errors.
1005
- try {
1006
- var sourceIds = [];
1007
- if (err && err.__wfRootId) {
1008
- sourceIds.push(err.__wfRootId);
1009
- } else if (errors) {
1010
- for (var j = 0; j < errors.length; j++) {
1011
- if (errors[j] && errors[j].__wfRootId) {
1012
- sourceIds.push(errors[j].__wfRootId);
1013
- }
1014
- }
1015
- }
1016
- for (var k = 0; k < sourceIds.length; k++) {
1017
- if (
1018
- sourceIds[k] !== promise.__wfRootId &&
1019
- __b.wfIsRootHandled(sourceIds[k])
1020
- ) {
1021
- return;
1022
- }
1023
- }
1024
- } catch (e) {
1025
- // A throwing exotic value must not kill the observer; fall
1026
- // through and mirror conservatively.
1027
- }
1028
- var msg;
1029
- try {
1030
- msg = String(err && err.message != null ? err.message : err);
1031
- } catch (e) {
1032
- msg = '[unserializable rejection value]';
1033
- }
1034
- promise.__wfUnconsumedId = __b.wfReportUnconsumed(
1035
- promise.__wfRootId,
1036
- promise.__wfIsRoot === true,
1037
- dispatchFailed,
1038
- msg,
1039
- );
1040
- });
1041
- }
1042
- // R11-3: await / Promise.resolve / returning a thenable from a
1043
- // handler adopts an ObservedPromise through this then with the
1044
- // adopting promise's capability (resolve, reject) pair \u2014 native
1045
- // functions, indistinguishable from real handlers by arity. They
1046
- // are detected by the native toString signature. Adoption
1047
- // CONSUMES the result (a delayed adoption clears a recorded
1048
- // verdict exactly like a delayed await) but is NOT a rejection
1049
- // handler: the rejection transfers into the adopting promise \u2014
1050
- // typically an async wrapper's implicit promise, which is a plain
1051
- // vm-realm Promise the mirror cannot observe. Marking adoption as
1052
- // handling would silently disarm the mirror for the forgotten-
1053
- // await failure class; the run-level escape hook in the host
1054
- // surfaces those escapes instead. Bound script functions also
1055
- // stringify as native code; misreading one as adoption only
1056
- // forgoes the rejectionHandled marking, never native semantics.
1057
- function isAdoptionAttach(handler) {
1058
- try {
1059
- return (
1060
- typeof handler === 'function' &&
1061
- Function.prototype.toString
1062
- .call(handler)
1063
- .indexOf('[native code]') !== -1
1064
- );
1065
- } catch (e) {
1066
- return false;
1067
- }
1068
- }
1069
- class ObservedPromise extends Promise {
1070
- then(onFulfilled, onRejected) {
1071
- // R11-26: introspect the handler BEFORE any state mutation.
1072
- // The read is guarded because a script-supplied handler can
1073
- // be exotic (a revoked Proxy wrapping a function, a throwing
1074
- // accessor) \u2014 an unguarded read made .then() throw
1075
- // synchronously, something native then never does, leaving
1076
- // the promise marked consumed with no handler attached.
1077
- var rethrows = false;
1078
- try {
1079
- rethrows = !!(onRejected && onRejected.__wfRethrows);
1080
- } catch (e) {
1081
- rethrows = false;
1082
- }
1083
- this.__wfConsumed = true;
1084
- // An attached rejection handler means the script can surface the
1085
- // root rejection itself; the mirror stays silent for it. The
1086
- // finally override below routes through this then with marked
1087
- // rethrow combinators \u2014 those re-raise the rejection instead of
1088
- // handling it, so they must NOT set the flag (marking them
1089
- // handled would silently drop a fire-and-forget
1090
- // agent(...).finally(...) failure). Adoption attaches count
1091
- // as consumption only, never handling (see isAdoptionAttach):
1092
- // they mark adoptedOut so forwarded sibling entries defer to
1093
- // the adopting chain / escape hook instead of mirroring.
1094
- if (isAdoptionAttach(onRejected)) {
1095
- __b.wfMarkAdopted(this.__wfRootId);
1096
- } else if (typeof onRejected === 'function' && !rethrows) {
1097
- __b.wfMarkRejectionHandled(this.__wfRootId);
1098
- }
1099
- // A delayed consumption clears a verdict recorded at
1100
- // rejection-settlement time, so a late-but-real await is not
1101
- // misreported as unconsumed.
1102
- if (this.__wfUnconsumedId !== undefined) {
1103
- __b.wfClearUnconsumed(this.__wfUnconsumedId);
1104
- this.__wfUnconsumedId = undefined;
1105
- }
1106
- const derived = super.then(onFulfilled, onRejected);
1107
- derived.__wfRootId = this.__wfRootId;
1108
- observeDispatch(derived);
1109
- return derived;
1110
- }
1111
- finally(onFinally) {
1112
- // Native Promise.prototype.finally calls the observed then with
1113
- // two function combinators, indistinguishable there from a real
1114
- // then(f, g) \u2014 which would mark the root rejection handled even
1115
- // though finally rethrows it. Implement finally through the
1116
- // observed then with an explicitly-marked rethrow combinator so
1117
- // the mirror stays armed for finally-only chains.
1118
- if (typeof onFinally !== 'function') {
1119
- return this.then(undefined, undefined);
1120
- }
1121
- const onRethrow = function (err) {
1122
- return Promise.resolve(onFinally()).then(function () {
1123
- throw err;
1124
- });
1125
- };
1126
- onRethrow.__wfRethrows = true;
1127
- return this.then(
1128
- function (value) {
1129
- return Promise.resolve(onFinally()).then(function () {
1130
- return value;
1131
- });
1132
- },
1133
- onRethrow,
1134
- );
1135
- }
1136
- }
1137
- // --- Static combinators: observe the aggregate promise ---
1138
- // Promise.all/race/any build their aggregate via the native static;
1139
- // it never passes through the observed then, so a fire-and-forget
1140
- // aggregate holding a failed dispatch would escape the run-log
1141
- // mirror. While the run is live the host's adoption-escape hook
1142
- // (R11-3) still catches and mirrors the process-level
1143
- // unhandledRejection \u2014 a round-14 A/B confirmed that hook, not
1144
- // this wrap, is the live-run backstop \u2014 but only with the coarse
1145
- // '(rejection not handled)' wording, and once the run's hook is
1146
- // detached nothing in the sandbox catches the escape. R14-A:
1147
- // wrapping the statics gives each aggregate its own observer, so
1148
- // consumption tracking works through the aggregate's own observed
1149
- // then (await / .catch / .then marks it handled) and the mirror
1150
- // itself classifies the rejection; the elements still funnel
1151
- // through the then override via the native static's internal
1152
- // attach, so they stay marked consumed.
1153
- function observeAggregate(nativeAggregate) {
1154
- const rootId = __b.wfRegisterRoot();
1155
- const observed = new ObservedPromise(function (resolve, reject) {
1156
- Promise.prototype.then.call(nativeAggregate, resolve, reject);
1157
- });
1158
- observed.__wfRootId = rootId;
1159
- observed.__wfIsRoot = true;
1160
- observeDispatch(observed);
1161
- return observed;
1162
- }
1163
- const nativePromiseAll = Promise.all;
1164
- const nativePromiseRace = Promise.race;
1165
- const nativePromiseAny = Promise.any;
1166
- // R11-16: a static called on a script-defined Promise subclass
1167
- // must honor the species contract and return a subclass instance,
1168
- // so non-default receivers bypass observation (their elements
1169
- // still funnel through the observed then, and a fire-and-forget
1170
- // dispatch failure escaping such an aggregate is still caught by
1171
- // the host's adoption-escape hook via its stamped markers).
1172
- Promise.all = function (items) {
1173
- if (this !== Promise) return nativePromiseAll.call(this, items);
1174
- return observeAggregate(nativePromiseAll.call(this, items));
1175
- };
1176
- Promise.race = function (items) {
1177
- if (this !== Promise) return nativePromiseRace.call(this, items);
1178
- return observeAggregate(nativePromiseRace.call(this, items));
1179
- };
1180
- Promise.any = function (items) {
1181
- if (this !== Promise) return nativePromiseAny.call(this, items);
1182
- return observeAggregate(nativePromiseAny.call(this, items));
1183
- };
1184
- function vmAsync(hostFn) {
1185
- return function (...vmArgs) {
1186
- const rootId = __b.wfRegisterRoot();
1187
- const p = new ObservedPromise(function (resolve, reject) {
1188
- function rejectMapped(hostErr) {
1189
- const vmErr = mapDispatchError(hostErr);
1190
- // Stamp the originating root and run BEFORE the error can
1191
- // be forwarded into aggregate promises: the observer's
1192
- // cross-root suppression (R11-15) reads __wfRootId and
1193
- // the host's adoption-escape hook (R11-3) attributes by
1194
- // __wfRunId.
1195
- try {
1196
- vmErr.__wfRootId = rootId;
1197
- vmErr.__wfRunId = __b.runId;
1198
- } catch (e) {}
1199
- reject(vmErr);
1200
- }
1201
- try {
1202
- const hostPromise = hostFn.apply(null, vmArgs);
1203
- hostPromise.then(
1204
- function (value) { resolve(value); },
1205
- rejectMapped
1206
- );
1207
- } catch (hostErr) {
1208
- rejectMapped(hostErr);
1209
- }
1210
- });
1211
- p.__wfRootId = rootId;
1212
- p.__wfIsRoot = true;
1213
- observeDispatch(p);
1214
- return p;
1215
- };
1216
- }
1217
-
1218
- // --- phase / log ---
1219
- globalThis.phase = function phase(title) {
1220
- __b.pushPhase(String(title));
1221
- };
1222
- globalThis.log = function log(msg) {
1223
- __b.pushLog(msg);
1224
- };
1225
-
1226
- // --- console (object with hardened methods, all in vm-realm) ---
1227
- const safeConsole = Object.create(null);
1228
- safeConsole.log = function () {
1229
- const parts = [];
1230
- for (let i = 0; i < arguments.length; i++) parts.push(String(arguments[i]));
1231
- __b.pushLog(parts.join(' '));
1232
- };
1233
- safeConsole.warn = safeConsole.log;
1234
- safeConsole.error = safeConsole.log;
1235
- globalThis.console = safeConsole;
1236
-
1237
- // --- agent (with runtime allowlist + named throws, all vm-realm) ---
1238
- // FIX-Round1-T13: throw on any opts key not in the allowlist \u2014 catches
1239
- // typos like { scema: ... } that previously slipped through the
1240
- // [key:string]: unknown index signature.
1241
- const KNOWN_AGENT_OPTS = ['label', 'phase', 'schema', 'model', 'effort', 'isolation', 'agentType', 'stallMs', 'workingDir', 'disallowedTools'];
1242
- globalThis.agent = vmAsync(function (prompt, agentOpts) {
1243
- agentOpts = agentOpts || {};
1244
- const keys = Object.keys(agentOpts);
1245
- for (let i = 0; i < keys.length; i++) {
1246
- const k = keys[i];
1247
- if (KNOWN_AGENT_OPTS.indexOf(k) === -1) {
1248
- throw new Error(
1249
- "agent({" + k + "}): unknown option. " +
1250
- "Known options are: " + KNOWN_AGENT_OPTS.join(', ') + "."
1251
- );
1252
- }
1253
- }
1254
- // P3: schema + model + agentType + isolation are all wired through
1255
- // createProductionDispatch \u2192 SubagentManager.createAgentHeadless.
1256
- // The dispatch surfaces descriptive errors for "agent type not found",
1257
- // "isolation:'remote' is not available in this build", parent-dirty
1258
- // refuse, worktree creation failures, and StructuredOutput contract
1259
- // violations ("completed without calling StructuredOutput after 2
1260
- // in-conversation nudges").
1261
- if (
1262
- agentOpts.isolation !== undefined &&
1263
- agentOpts.isolation !== 'worktree' &&
1264
- agentOpts.isolation !== 'remote'
1265
- ) {
1266
- throw new Error(
1267
- "agent({isolation: '" + agentOpts.isolation + "'}): unknown isolation mode. " +
1268
- "Known modes are: 'worktree', 'remote'."
1269
- );
1270
- }
1271
- // NOTE: this init script is a host-side template literal \u2014 no
1272
- // backticks anywhere below, in code or comments.
1273
- //
1274
- // A non-number stallMs is silently dropped downstream and the
1275
- // default watchdog applies, contradicting "0 disables the watchdog"
1276
- // \u2014 refuse it loudly like the other option gates.
1277
- if (agentOpts.stallMs !== undefined && (typeof agentOpts.stallMs !== 'number' || !Number.isFinite(agentOpts.stallMs))) {
1278
- throw new Error("agent({stallMs}): must be a finite number of milliseconds (0 disables the watchdog).");
1279
- }
1280
- // workingDir pins the agent to a worktree the CALLER already owns;
1281
- // isolation creates and reaps one. Asking for both is a contradiction
1282
- // about who owns the directory's lifetime, so name it here rather than
1283
- // silently letting one win.
1284
- if (agentOpts.workingDir !== undefined) {
1285
- if (typeof agentOpts.workingDir !== 'string' || agentOpts.workingDir.trim().length === 0) {
1286
- throw new Error(
1287
- "agent({workingDir}): must be a non-empty string naming an existing " +
1288
- "git worktree of this repository."
1289
- );
1290
- }
1291
- if (agentOpts.isolation !== undefined) {
1292
- throw new Error(
1293
- "agent({workingDir, isolation}): incompatible options. workingDir " +
1294
- "pins the agent to a worktree you already own; isolation creates " +
1295
- "a fresh one and removes it afterwards. Pass one."
1296
- );
1297
- }
1298
- }
1299
- // SECURITY (P3 R2 self-review): user-script-controlled agentOpts
1300
- // cross the vm/host boundary verbatim via vmAsync's hostFn.apply.
1301
- // A Proxy / inherited-getter / non-plain object in agentOpts.schema
1302
- // would let host-side code (SyntheticOutputTool constructor + AJV
1303
- // compile) trigger user-controlled trap handlers that execute with
1304
- // the host realm's full surface. Revive agentOpts through JSON
1305
- // round-trip BEFORE crossing so the host only ever sees vm-realm
1306
- // plain objects with vm-realm prototypes. Same mechanism that
1307
- // makes args + parallel/pipeline results safe.
1308
- var safeOpts;
1309
- try {
1310
- safeOpts = JSON.parse(JSON.stringify(agentOpts));
1311
- } catch (e) {
1312
- throw new Error(
1313
- "agent() opts contain a non-JSON-serializable value: " +
1314
- String(e && e.message != null ? e.message : e)
1315
- );
1316
- }
1317
- // effort and disallowedTools are validated on the REVIVED copy: that
1318
- // is the object the host dispatch and the resume key see, so a getter
1319
- // cannot show one value here and hand another to the dispatch. Both
1320
- // are normalized in place (an effort alias becomes its tier; a deny
1321
- // list has built-in display names mapped to tool names and is sorted
1322
- // and de-duplicated) so equivalent spellings share one resume key.
1323
- if (safeOpts.effort !== undefined) {
1324
- var tier = __b.normalizeEffort(safeOpts.effort);
1325
- if (tier === null) {
1326
- throw new Error(
1327
- "agent({effort}): unknown effort tier " + __b.sanitizeForMessage(JSON.stringify(safeOpts.effort)) + ". " +
1328
- "Known tiers are: " + __b.effortTiers + "."
1329
- );
1330
- }
1331
- safeOpts.effort = tier;
1332
- }
1333
- if (safeOpts.disallowedTools !== undefined) {
1334
- var denied = safeOpts.disallowedTools;
1335
- if (
1336
- !Array.isArray(denied) ||
1337
- denied.some(function (name) {
1338
- return typeof name !== 'string' || name.length === 0 || name !== name.trim();
1339
- })
1340
- ) {
1341
- throw new Error(
1342
- "agent({disallowedTools}): must be an array of non-empty tool-name strings " +
1343
- "without surrounding whitespace, e.g. ['run_shell_command', 'write_file']."
1344
- );
1345
- }
1346
- var uniqueDenied = [];
1347
- for (var d = 0; d < denied.length; d++) {
1348
- var deniedName = __b.canonicalDenyName(denied[d]);
1349
- if (uniqueDenied.indexOf(deniedName) === -1) uniqueDenied.push(deniedName);
1350
- }
1351
- uniqueDenied.sort();
1352
- if (uniqueDenied.length === 0) {
1353
- delete safeOpts.disallowedTools;
1354
- } else {
1355
- safeOpts.disallowedTools = uniqueDenied;
1356
- }
1357
- }
1358
- // The phase is recorded only once every option gate above has passed,
1359
- // so a call its options rejected leaves no phase that dispatched
1360
- // nothing.
1361
- if (typeof agentOpts.phase === 'string' && agentOpts.phase.length > 0) {
1362
- if (__b.lastPhase() !== agentOpts.phase) {
1363
- __b.pushPhase(agentOpts.phase);
1364
- }
1365
- }
1366
- // SECURITY (PR #4947 R1 wenshao, extended for P3): vmAsync's resolve
1367
- // path is verbatim (no re-wrap of resolved values). Host-realm
1368
- // strings cross the boundary harmlessly because primitives have no
1369
- // prototype identity. But P3's schema-mode dispatch returns the
1370
- // validated structured_output args as a host-realm OBJECT --
1371
- // handing that to the script reopens the T1/T8/T14 escape:
1372
- // result.constructor.constructor("return process")() would walk
1373
- // the host Object.prototype chain to the host Function
1374
- // constructor. Per-call JSON revival inside this vm runInContext
1375
- // block makes the returned object carry vm-realm prototypes (same
1376
- // mechanism as parallel/pipeline reviveInRealm and the args
1377
- // global revival). The fallback to null on a non-serializable
1378
- // resolve mirrors the errors-as-data convention parallel/pipeline
1379
- // already use for individual slot failures.
1380
- // R3 review (wenshao T3 [Suggestion]): the null fallback below is
1381
- // a SECURITY backstop, not a contract path. In schema mode the
1382
- // host return is the validated args of a structured_output tool
1383
- // call -- LLM tool_call payloads are always JSON-serializable
1384
- // (the model sends them through the OpenAI tool-call protocol
1385
- // which serializes through JSON itself) and SyntheticOutputTool's
1386
- // AJV validation runs over the parsed JSON, so a non-serializable
1387
- // host return is unreachable in production schema mode. The
1388
- // sentinel preserves the errors-as-data convention parallel /
1389
- // pipeline already use for individual slot failures, and stays as
1390
- // residual defense for any future dispatch path whose return
1391
- // value isn't a tool_call payload. logRevivalFailure surfaces
1392
- // the actionable detail (slot 0 + the error string) to operators
1393
- // so a real trigger in production isn't silent.
1394
- return __b.hostAgent(prompt, safeOpts).then(function (value) {
1395
- if (value === null || typeof value !== 'object') {
1396
- return value;
1397
- }
1398
- try {
1399
- return JSON.parse(JSON.stringify(value));
1400
- } catch (e) {
1401
- __b.logRevivalFailure(0, String(e && e.message != null ? e.message : e));
1402
- return null;
1403
- }
1404
- });
1405
- });
1406
-
1407
- // --- parallel / pipeline ---
1408
- // SECURITY (PR #4732 P2): the host impl resolves with a HOST-realm array.
1409
- // vmAsync's resolve path is verbatim (it does NOT re-wrap resolved
1410
- // values), so handing that host array to the script would reopen the
1411
- // T1/T8/T14 escape: result.constructor.constructor('return process')()
1412
- // walks the host Array.prototype chain to the host Function constructor.
1413
- // We revive the array INSIDE the vm realm with JSON.parse(JSON.stringify)
1414
- // -- the same mechanism that makes the args global safe (see the args
1415
- // revival above) -- so the value the script sees has vm-realm prototypes
1416
- // whose constructors can't reach host process. Agent results are JSON
1417
- // strings (and null slots), so the round-trip is lossless for P2.
1418
- //
1419
- // EAD-1 (P2 self-review): revive PER-ELEMENT, not the whole array in one
1420
- // JSON.stringify. A single slot whose VALUE is non-serializable (a thunk
1421
- // that returns a BigInt or a circular object) must become null at its
1422
- // index -- it must NOT throw on the whole array and destroy every sibling
1423
- // result, which would defeat errors-as-data for return values. The outer
1424
- // [] is built in-realm here, so the result keeps vm-realm prototypes.
1425
- //
1426
- // SECURITY (PR #4947 R1 wenshao): reviveInRealm MUST remain inside this
1427
- // vm init runInContext block. JSON, Array, Object here are vm-realm
1428
- // globals; extracting this function to a host-side utility (e.g. a
1429
- // shared utils/jsonRevive.ts) would resolve those references against
1430
- // the HOST realm, silently reopening the T1/T8/T14 escape that the
1431
- // revival is designed to prevent. The textual identity to a host-side
1432
- // util is exactly the trap.
1433
- function reviveInRealm(hostArr) {
1434
- const out = [];
1435
- for (let i = 0; i < hostArr.length; i++) {
1436
- try {
1437
- out[i] = JSON.parse(JSON.stringify(hostArr[i]));
1438
- } catch (e) {
1439
- // Cross to host realm for debug logging. The bridge function
1440
- // accepts only primitive strings/numbers; the error message is
1441
- // coerced to a String here so no vm-realm Error object crosses.
1442
- __b.logRevivalFailure(i, String(e?.message ?? e));
1443
- out[i] = null;
1444
- }
1445
- }
1446
- return out;
1447
- }
1448
- if (__b.hasParallel) {
1449
- const callParallel = vmAsync(function (thunks) {
1450
- return __b.hostParallel(thunks);
1451
- });
1452
- globalThis.parallel = function parallel(thunks) {
1453
- return callParallel(thunks).then(reviveInRealm);
1454
- };
1455
- } else {
1456
- globalThis.parallel = function parallel() {
1457
- return new Promise(function (_, reject) {
1458
- reject(new Error(
1459
- 'parallel() is unavailable: this sandbox was created without a ' +
1460
- 'parallel implementation. The orchestrator injects one; a bare ' +
1461
- 'sandbox has no concurrent-dispatch capability.'
1462
- ));
1463
- });
1464
- };
1465
- }
1466
- if (__b.hasPipeline) {
1467
- const callPipeline = vmAsync(function (items) {
1468
- const stages = [];
1469
- for (let i = 1; i < arguments.length; i++) stages.push(arguments[i]);
1470
- return __b.hostPipeline.apply(null, [items].concat(stages));
1471
- });
1472
- globalThis.pipeline = function pipeline() {
1473
- return callPipeline.apply(null, arguments).then(reviveInRealm);
1474
- };
1475
- } else {
1476
- globalThis.pipeline = function pipeline() {
1477
- return new Promise(function (_, reject) {
1478
- reject(new Error(
1479
- 'pipeline() is unavailable: this sandbox was created without a ' +
1480
- 'pipeline implementation. The orchestrator injects one; a bare ' +
1481
- 'sandbox has no staggered multi-stage capability.'
1482
- ));
1483
- });
1484
- };
1485
- }
1486
- // --- workflow (nested, single-level) ---
1487
- // Mirrors agent(): args cross vm\u2192host verbatim (safe direction), the
1488
- // single result is revived back into the vm realm via JSON round-trip
1489
- // (same T1/T8/T14 escape defense as agent / parallel / pipeline). The
1490
- // host impl resolves a saved workflow and runs it sharing this run's
1491
- // agent-count cap + token budget. When __b.hasWorkflow is false, the
1492
- // sandbox is either bare (no resolver wired) OR is itself a nested
1493
- // workflow \u2014 in both cases workflow() must throw, which is how the
1494
- // single-level nesting limit is enforced (a nested sandbox is created
1495
- // without a workflow impl, so its workflow() lands in the else branch).
1496
- if (__b.hasWorkflow) {
1497
- const callWorkflow = vmAsync(function (nameOrRef, wfArgs) {
1498
- // Sanitize args through a JSON round-trip BEFORE crossing so the
1499
- // host only ever sees vm-realm plain objects (same defense as
1500
- // agent()'s safeOpts). nameOrRef may be a string or {scriptPath}.
1501
- var safeRef;
1502
- var safeArgs;
1503
- try {
1504
- safeRef = nameOrRef === undefined
1505
- ? undefined
1506
- : JSON.parse(JSON.stringify(nameOrRef));
1507
- safeArgs = wfArgs === undefined
1508
- ? undefined
1509
- : JSON.parse(JSON.stringify(wfArgs));
1510
- } catch (e) {
1511
- throw new Error(
1512
- 'workflow() received a non-JSON-serializable argument: ' +
1513
- String(e && e.message != null ? e.message : e)
1514
- );
1515
- }
1516
- return __b.hostWorkflow(safeRef, safeArgs).then(function (value) {
1517
- if (value === null || typeof value !== 'object') {
1518
- return value;
1519
- }
1520
- try {
1521
- return JSON.parse(JSON.stringify(value));
1522
- } catch (e) {
1523
- __b.logRevivalFailure(0, String(e && e.message != null ? e.message : e));
1524
- return null;
1525
- }
1526
- });
1527
- });
1528
- globalThis.workflow = function workflow(nameOrRef, wfArgs) {
1529
- return callWorkflow(nameOrRef, wfArgs);
1530
- };
1531
- } else {
1532
- globalThis.workflow = function workflow() {
1533
- return new Promise(function (_, reject) {
1534
- reject(new Error(
1535
- "workflow() is unavailable here. Either this sandbox was created " +
1536
- "without a saved-workflow resolver, or this script is already " +
1537
- "running as a nested workflow \u2014 workflow() nesting is limited to " +
1538
- "a single level (a workflow cannot call another workflow that " +
1539
- "itself calls workflow())."
1540
- ));
1541
- });
1542
- };
1543
- }
1544
-
1545
- // --- budget ---
1546
- const safeBudget = Object.create(null);
1547
- Object.defineProperty(safeBudget, 'total', {
1548
- value: __b.budgetTotal,
1549
- writable: false, configurable: false,
1550
- });
1551
- if (__b.hasBudget) {
1552
- Object.defineProperty(safeBudget, 'spent', {
1553
- value: function spent() { return __b.hostBudgetSpent(); },
1554
- writable: false, configurable: false,
1555
- });
1556
- Object.defineProperty(safeBudget, 'remaining', {
1557
- value: function remaining() { return __b.hostBudgetRemaining(); },
1558
- writable: false, configurable: false,
1559
- });
1560
- } else {
1561
- Object.defineProperty(safeBudget, 'spent', {
1562
- value: function spent() {
1563
- throw new Error(
1564
- 'budget.spent() is not supported in P1. Token tracking is scheduled for P5.'
1565
- );
1566
- },
1567
- writable: false, configurable: false,
1568
- });
1569
- Object.defineProperty(safeBudget, 'remaining', {
1570
- value: function remaining() {
1571
- throw new Error(
1572
- 'budget.remaining() is not supported in P1. Token tracking is scheduled for P5.'
1573
- );
1574
- },
1575
- writable: false, configurable: false,
1576
- });
1577
- }
1578
- globalThis.budget = safeBudget;
1579
- })();`,
1580
- ctx,
1581
- { filename: "workflow-sandbox-init.js" }
1582
- );
1583
- const maxWallClockMs = resolveMaxWallClockMs(opts);
1584
- const flushUnconsumedRejections = /* @__PURE__ */ __name(async () => {
1585
- unconsumedSettled = true;
1586
- if (nextUnconsumedId === 1) return;
1587
- await new Promise((resolve2) => {
1588
- setImmediate(resolve2);
1589
- });
1590
- for (const rec of unconsumedRejections.values()) {
1591
- const rootState = unconsumedRoots.get(rec.rootId);
1592
- if (rootState?.rejectionHandled) {
1593
- continue;
1594
- }
1595
- if (rec.dispatchFailed && rootState?.adoptedOut) {
1596
- continue;
1597
- }
1598
- const key = rec.rootId + "\0" + rec.msg;
1599
- if (mirroredEscapeKeys.has(key)) continue;
1600
- mirroredEscapeKeys.add(key);
1601
- safeLog(unconsumedRejectionLine(rec));
1602
- }
1603
- unconsumedRejections.clear();
1604
- }, "flushUnconsumedRejections");
1605
- const hookRunId = opts.runId ?? "";
1606
- const adoptionEscapeHook = /* @__PURE__ */ __name((reason, _promise) => {
1607
- try {
1608
- if (!reason || typeof reason !== "object") return;
1609
- const marked = reason;
1610
- if (marked.__wfDispatchFailed !== true) return;
1611
- if (String(marked.__wfRunId ?? "") !== hookRunId) return;
1612
- const rootId = typeof marked.__wfRootId === "number" ? marked.__wfRootId : void 0;
1613
- if (rootId !== void 0 && unconsumedRoots.get(rootId)?.rejectionHandled) {
1614
- return;
1615
- }
1616
- let msg;
1617
- try {
1618
- msg = marked.message != null ? String(marked.message) : String(reason);
1619
- } catch {
1620
- msg = "[unserializable rejection value]";
1621
- }
1622
- const key = String(rootId ?? "") + "\0" + msg;
1623
- if (mirroredEscapeKeys.has(key)) return;
1624
- mirroredEscapeKeys.add(key);
1625
- safeLog("dispatch failed (rejection not handled): " + msg);
1626
- } catch (e) {
1627
- debugLogger.warn("adoptionEscapeHook failed:", e);
1628
- }
1629
- }, "adoptionEscapeHook");
1630
- let extractedMeta = null;
1631
- return {
1632
- async run(scriptSource) {
1633
- unconsumedSettled = false;
1634
- unconsumedRoots.clear();
1635
- unconsumedRejections.clear();
1636
- nextUnconsumedId = 1;
1637
- mirroredEscapeKeys = /* @__PURE__ */ new Set();
1638
- let watchdog;
1639
- let stopWatchingState;
1640
- let rearmWatchdogOnAbort;
1641
- let settleOnAbort;
1642
- let wallClockFired = false;
1643
- process.on("unhandledRejection", adoptionEscapeHook);
1644
- try {
1645
- const { script, meta } = compileWorkflowScript(scriptSource);
1646
- extractedMeta = meta;
1647
- if (opts.abortOnTimeout?.signal.aborted) {
1648
- throw workflowCancelledError();
1649
- }
1650
- const runOpts = {
1651
- timeout: WORKFLOW_SYNC_EVALUATION_TIMEOUT_MS
1652
- };
1653
- const result = script.runInContext(ctx, runOpts);
1654
- const timeoutPromise = new Promise((_, reject) => {
1655
- watchdog = new WallClockWatchdog(maxWallClockMs, () => {
1656
- wallClockFired = true;
1657
- opts.abortOnTimeout?.abort();
1658
- reject(
1659
- new Error(
1660
- `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.`
1661
- )
1662
- );
1663
- });
1664
- });
1665
- const aborted = /* @__PURE__ */ __name(() => opts.abortOnTimeout?.signal.aborted === true, "aborted");
1666
- stopWatchingState = opts.scheduler?.onStateChange(({ state }) => {
1667
- if (state === "paused" && !aborted()) watchdog?.pause();
1668
- else watchdog?.resume();
1669
- });
1670
- if (opts.scheduler?.snapshot().state === "paused" && !aborted()) {
1671
- watchdog?.pause();
1672
- }
1673
- rearmWatchdogOnAbort = /* @__PURE__ */ __name(() => watchdog?.resume(), "rearmWatchdogOnAbort");
1674
- opts.abortOnTimeout?.signal.addEventListener(
1675
- "abort",
1676
- rearmWatchdogOnAbort,
1677
- { once: true }
1678
- );
1679
- const abortPromise = new Promise((_, reject) => {
1680
- const signal = opts.abortOnTimeout?.signal;
1681
- if (!signal) return;
1682
- settleOnAbort = /* @__PURE__ */ __name(() => {
1683
- if (!wallClockFired) reject(workflowCancelledError());
1684
- }, "settleOnAbort");
1685
- signal.addEventListener("abort", settleOnAbort, { once: true });
1686
- });
1687
- return await Promise.race([result, timeoutPromise, abortPromise]);
1688
- } finally {
1689
- if (rearmWatchdogOnAbort) {
1690
- opts.abortOnTimeout?.signal.removeEventListener(
1691
- "abort",
1692
- rearmWatchdogOnAbort
1693
- );
1694
- }
1695
- if (settleOnAbort) {
1696
- opts.abortOnTimeout?.signal.removeEventListener(
1697
- "abort",
1698
- settleOnAbort
1699
- );
1700
- }
1701
- stopWatchingState?.();
1702
- watchdog?.stop();
1703
- await flushUnconsumedRejections();
1704
- process.off("unhandledRejection", adoptionEscapeHook);
1705
- }
1706
- },
1707
- getPhases: /* @__PURE__ */ __name(() => [...phases], "getPhases"),
1708
- getLogs: /* @__PURE__ */ __name(() => [...logs], "getLogs"),
1709
- appendLog: /* @__PURE__ */ __name((line) => safeLog(line, false), "appendLog"),
1710
- getMeta: /* @__PURE__ */ __name(() => extractedMeta, "getMeta")
1711
- };
1712
- }
1713
- __name(createWorkflowSandbox, "createWorkflowSandbox");
1714
-
1715
- // packages/core/src/agents/runtime/workflow-budget.ts
1716
- init_esbuild_shims();
1717
- var debugLogger2 = createDebugLogger("WORKFLOW_BUDGET");
1718
- var MAX_TOKENS_PER_WORKFLOW_ENV = "QWEN_CODE_MAX_TOKENS_PER_WORKFLOW";
1719
- var HARD_MAX_TOKENS_CEILING = 1e8;
1720
- function resolveMaxTokensPerWorkflow(env = process.env) {
1721
- const raw = env[MAX_TOKENS_PER_WORKFLOW_ENV];
1722
- if (raw === void 0 || raw.trim() === "") {
1723
- return null;
1724
- }
1725
- const parsed = parsePositiveIntegerEnv(raw, 0);
1726
- if (parsed < 1) {
1727
- debugLogger2.warn(
1728
- `Invalid ${MAX_TOKENS_PER_WORKFLOW_ENV}=${JSON.stringify(raw)}, treating as unset (no cap)`
1729
- );
1730
- return null;
1731
- }
1732
- if (parsed > HARD_MAX_TOKENS_CEILING) {
1733
- debugLogger2.warn(
1734
- `${MAX_TOKENS_PER_WORKFLOW_ENV}=${parsed} exceeds hard ceiling (${HARD_MAX_TOKENS_CEILING}); clamping.`
1735
- );
1736
- return HARD_MAX_TOKENS_CEILING;
1737
- }
1738
- return parsed;
1739
- }
1740
- __name(resolveMaxTokensPerWorkflow, "resolveMaxTokensPerWorkflow");
1741
- var WorkflowBudgetImpl = class _WorkflowBudgetImpl {
1742
- static {
1743
- __name(this, "WorkflowBudgetImpl");
1744
- }
1745
- total;
1746
- _spent;
1747
- constructor(total) {
1748
- this.total = total;
1749
- this._spent = 0;
1750
- }
1751
- spent() {
1752
- return this._spent;
1753
- }
1754
- remaining() {
1755
- if (this.total === null) return Infinity;
1756
- return Math.max(0, this.total - this._spent);
1757
- }
1758
- /**
1759
- * Host-side increment. NOT exposed to the script — the
1760
- * `WorkflowBudget` interface deliberately omits any setter so a
1761
- * malicious workflow cannot inflate / deflate the budget. Only the
1762
- * orchestrator (in `countedDispatch`) calls this after a dispatch
1763
- * resolves with the agent's output token count.
1764
- *
1765
- * Non-positive deltas are silently dropped (some dispatches return
1766
- * `output_tokens: 0` on early failures); negative deltas would be a
1767
- * caller bug and are also dropped rather than silently rewinding
1768
- * the counter.
1769
- */
1770
- recordSpent(deltaTokens) {
1771
- if (!Number.isFinite(deltaTokens) || deltaTokens <= 0) return;
1772
- this._spent += deltaTokens;
1773
- }
1774
- /**
1775
- * Factory: build a budget from the current environment. Convenience
1776
- * over `new WorkflowBudgetImpl(resolveMaxTokensPerWorkflow(env))`.
1777
- */
1778
- static fromEnv(env = process.env) {
1779
- return new _WorkflowBudgetImpl(resolveMaxTokensPerWorkflow(env));
1780
- }
1781
- };
1782
- var WorkflowBudgetExceededError = class extends Error {
1783
- static {
1784
- __name(this, "WorkflowBudgetExceededError");
1785
- }
1786
- name = "WorkflowBudgetExceededError";
1787
- runId;
1788
- budgetTotal;
1789
- spent;
1790
- constructor(runId, budgetTotal, spent) {
1791
- super(
1792
- `Workflow ${runId} exceeded the token budget (${spent} / ${budgetTotal} output tokens spent).`
1793
- );
1794
- this.runId = runId;
1795
- this.budgetTotal = budgetTotal;
1796
- this.spent = spent;
1797
- }
1798
- };
1799
-
1800
- // packages/core/src/agents/runtime/workflow-saved.ts
1801
- init_esbuild_shims();
1802
- import { promises as fs } from "node:fs";
1803
- import * as path from "node:path";
1804
- var debugLogger3 = createDebugLogger("WORKFLOW_SAVED");
1805
- var WORKFLOW_NAME_PATTERN = /^[a-z][a-z0-9-]{0,40}$/;
1806
- function validateWorkflowName(name) {
1807
- if (!name) return "Workflow name is required.";
1808
- if (!WORKFLOW_NAME_PATTERN.test(name)) {
1809
- return `Invalid workflow name "${name}". Use lower-case letters, digits, and hyphens only (must start with a letter, max 41 chars).`;
1810
- }
1811
- return null;
1812
- }
1813
- __name(validateWorkflowName, "validateWorkflowName");
1814
- function getSavedWorkflowDirs(config) {
1815
- return [
1816
- { dir: config.storage.getProjectWorkflowsDir(), source: "project" },
1817
- { dir: Storage.getUserWorkflowsDir(), source: "user" }
1818
- ];
1819
- }
1820
- __name(getSavedWorkflowDirs, "getSavedWorkflowDirs");
1821
- function getWorkflowScriptRoots(config) {
1822
- return [
1823
- ...getSavedWorkflowDirs(config).map(({ dir }) => dir),
1824
- config.storage.getGeneratedWorkflowsDir()
1825
- ];
1826
- }
1827
- __name(getWorkflowScriptRoots, "getWorkflowScriptRoots");
1828
- async function isSymlinkedRoot(dir) {
1829
- return fs.lstat(dir).then((st) => st.isSymbolicLink()).catch(() => false);
1830
- }
1831
- __name(isSymlinkedRoot, "isSymlinkedRoot");
1832
- async function listJsFiles(dir) {
1833
- if (await isSymlinkedRoot(dir)) {
1834
- debugLogger3.warn(`refusing symlinked saved-workflow dir: ${dir}`);
1835
- return [];
1836
- }
1837
- try {
1838
- const names = await fs.readdir(dir);
1839
- const out = [];
1840
- for (const n of names) {
1841
- if (!n.endsWith(".js")) continue;
1842
- const st = await fs.lstat(path.join(dir, n)).catch(() => null);
1843
- if (!st || st.isSymbolicLink()) continue;
1844
- out.push(n);
1845
- }
1846
- return out;
1847
- } catch (e) {
1848
- const code = e?.code;
1849
- if (code !== "ENOENT") {
1850
- debugLogger3.warn(`listJsFiles failed for ${dir}: ${e}`);
1851
- }
1852
- return [];
1853
- }
1854
- }
1855
- __name(listJsFiles, "listJsFiles");
1856
- async function readWorkflowFileSecurely(filePath, config) {
1857
- const real = await fs.realpath(filePath);
1858
- const roots = await Promise.all(
1859
- getWorkflowScriptRoots(config).map(async (dir) => {
1860
- if (await isSymlinkedRoot(dir)) return { dir, real: null };
1861
- try {
1862
- return { dir, real: await fs.realpath(dir) };
1863
- } catch {
1864
- return { dir, real: path.resolve(dir) };
1865
- }
1866
- })
1867
- );
1868
- const dirs = roots.flatMap((r) => r.real === null ? [] : [r.real]);
1869
- const inside = dirs.some((d) => real === d || real.startsWith(d + path.sep));
1870
- if (!inside) {
1871
- const refused = roots.flatMap((r) => r.real === null ? [r.dir] : []);
1872
- const refusedNote = refused.length > 0 ? `; refused symlinked ${refused.length === 1 ? "root" : "roots"}: ${refused.join(", ")}` : "";
1873
- throw new Error(
1874
- `refusing to load a workflow file outside the workflow script roots (checked: ${dirs.join(", ")}${refusedNote}): '${filePath}'.`
1875
- );
1876
- }
1877
- return fs.readFile(real, "utf8");
1878
- }
1879
- __name(readWorkflowFileSecurely, "readWorkflowFileSecurely");
1880
- async function resolveSavedWorkflowNameForPath(scriptPath, config) {
1881
- const realScriptPath = await fs.realpath(scriptPath);
1882
- for (const { dir } of getSavedWorkflowDirs(config)) {
1883
- if (await isSymlinkedRoot(dir)) continue;
1884
- let realDir;
1885
- try {
1886
- realDir = await fs.realpath(dir);
1887
- } catch {
1888
- continue;
1889
- }
1890
- if (realScriptPath !== realDir && !realScriptPath.startsWith(realDir + path.sep)) {
1891
- continue;
1892
- }
1893
- const name = path.basename(realScriptPath).replace(/\.js$/, "");
1894
- return WORKFLOW_NAME_PATTERN.test(name) ? name : void 0;
1895
- }
1896
- return void 0;
1897
- }
1898
- __name(resolveSavedWorkflowNameForPath, "resolveSavedWorkflowNameForPath");
1899
- async function listSavedWorkflows(config) {
1900
- const byName = /* @__PURE__ */ new Map();
1901
- for (const { dir, source } of [...getSavedWorkflowDirs(config)].reverse()) {
1902
- for (const file of await listJsFiles(dir)) {
1903
- const name = file.slice(0, -".js".length);
1904
- if (!WORKFLOW_NAME_PATTERN.test(name)) continue;
1905
- byName.set(name, { name, scriptPath: path.join(dir, file), source });
1906
- }
1907
- }
1908
- return Array.from(byName.values()).sort(
1909
- (a, b) => a.name.localeCompare(b.name)
1910
- );
1911
- }
1912
- __name(listSavedWorkflows, "listSavedWorkflows");
1913
- async function resolveSavedWorkflowScript(nameOrRef, config) {
1914
- if (typeof nameOrRef === "object" && nameOrRef !== null) {
1915
- const scriptPath = nameOrRef.scriptPath;
1916
- if (typeof scriptPath !== "string" || scriptPath.length === 0) {
1917
- throw new Error(
1918
- "workflow() expects a workflow name (string) or {scriptPath: string}."
1919
- );
1920
- }
1921
- let script;
1922
- try {
1923
- script = await readWorkflowFileSecurely(scriptPath, config);
1924
- } catch (e) {
1925
- throw new Error(
1926
- `workflow({scriptPath: '${scriptPath}'}): ${e instanceof Error ? e.message : String(e)}`
1927
- );
1928
- }
1929
- const name2 = path.basename(scriptPath).replace(/\.js$/, "");
1930
- const savedWorkflowName = await resolveSavedWorkflowNameForPath(
1931
- scriptPath,
1932
- config
1933
- );
1934
- return {
1935
- name: name2,
1936
- scriptPath,
1937
- script,
1938
- ...savedWorkflowName ? { savedWorkflowName } : {}
1939
- };
1940
- }
1941
- if (typeof nameOrRef !== "string") {
1942
- throw new Error(
1943
- "workflow() expects a workflow name (string) or {scriptPath: string}."
1944
- );
1945
- }
1946
- const name = nameOrRef;
1947
- const nameError = validateWorkflowName(name);
1948
- if (nameError) {
1949
- throw new Error(`workflow('${name}'): ${nameError}`);
1950
- }
1951
- for (const { dir } of getSavedWorkflowDirs(config)) {
1952
- const scriptPath = path.join(dir, `${name}.js`);
1953
- try {
1954
- const script = await readWorkflowFileSecurely(scriptPath, config);
1955
- return { name, scriptPath, script, savedWorkflowName: name };
1956
- } catch {
1957
- }
1958
- }
1959
- const available = (await listSavedWorkflows(config)).map((e) => e.name);
1960
- throw new Error(
1961
- `workflow('${name}'): no workflow with that name. Available: ${available.length > 0 ? available.join(", ") : "(none)"}.`
1962
- );
1963
- }
1964
- __name(resolveSavedWorkflowScript, "resolveSavedWorkflowScript");
1965
- async function saveWorkflowScript(config, opts) {
1966
- const { name, scope, script, overwrite = false } = opts;
1967
- const nameError = validateWorkflowName(name);
1968
- if (nameError) return { status: "invalid-name", error: nameError };
1969
- if (!script || script.trim().length === 0) {
1970
- return {
1971
- status: "empty-script",
1972
- error: "This run has no script source to save."
1973
- };
1974
- }
1975
- const dir = scope === "project" ? config.storage.getProjectWorkflowsDir() : Storage.getUserWorkflowsDir();
1976
- if (await isSymlinkedRoot(dir)) {
1977
- throw new Error(
1978
- `refusing to save into a symlinked saved-workflow directory: '${dir}'.`
1979
- );
1980
- }
1981
- const filePath = path.join(dir, `${name}.js`);
1982
- if (!overwrite) {
1983
- try {
1984
- await fs.access(filePath);
1985
- return { status: "exists", name, scope, path: filePath };
1986
- } catch {
1987
- }
1988
- }
1989
- await fs.mkdir(dir, { recursive: true });
1990
- await fs.writeFile(filePath, script, "utf8");
1991
- return { status: "saved", name, scope, path: filePath };
1992
- }
1993
- __name(saveWorkflowScript, "saveWorkflowScript");
1994
- var INLINE_RUN_ID_PATTERN = /^wf_[0-9a-f]+$/;
1995
- async function persistInlineWorkflowScript(config, runId, script) {
1996
- if (!INLINE_RUN_ID_PATTERN.test(runId)) {
1997
- debugLogger3.warn(`refusing to persist a script for run id: ${runId}`);
1998
- return null;
1999
- }
2000
- const storage = config.storage;
2001
- if (!storage) return null;
2002
- try {
2003
- const filePath = storage.getInlineWorkflowScriptPath(runId);
2004
- const dir = path.dirname(filePath);
2005
- if (await isSymlinkedRoot(storage.getGeneratedWorkflowsDir()) || await isSymlinkedRoot(dir)) {
2006
- debugLogger3.warn(
2007
- `refusing to persist an inline workflow script into a symlinked root: '${dir}'.`
2008
- );
2009
- return null;
2010
- }
2011
- await fs.mkdir(dir, { recursive: true });
2012
- await atomicWriteFile(filePath, script, {
2013
- encoding: "utf8",
2014
- mode: 384,
2015
- forceMode: true,
2016
- noFollow: true
2017
- });
2018
- return filePath;
2019
- } catch (error) {
2020
- debugLogger3.warn(
2021
- `failed to persist inline workflow script for ${runId}: ${error}`
2022
- );
2023
- return null;
2024
- }
2025
- }
2026
- __name(persistInlineWorkflowScript, "persistInlineWorkflowScript");
2027
- async function deleteInlineWorkflowScript(config, runId) {
2028
- if (!INLINE_RUN_ID_PATTERN.test(runId)) return false;
2029
- const storage = config.storage;
2030
- if (!storage) return false;
2031
- try {
2032
- await fs.rm(storage.getInlineWorkflowScriptPath(runId), { force: true });
2033
- return true;
2034
- } catch (error) {
2035
- debugLogger3.warn(
2036
- `failed to delete inline workflow script for ${runId}: ${error}`
2037
- );
2038
- return false;
2039
- }
2040
- }
2041
- __name(deleteInlineWorkflowScript, "deleteInlineWorkflowScript");
2042
-
2043
- // packages/core/src/agents/runtime/workflow-orchestrator.ts
2044
- init_esbuild_shims();
2045
- import { randomBytes } from "node:crypto";
2046
- import { AsyncLocalStorage } from "node:async_hooks";
2047
- import * as os from "node:os";
2048
-
2049
- // packages/core/src/agents/runtime/workflow-agent-failure.ts
2050
- init_esbuild_shims();
2051
- var WorkflowAgentFailedError = class extends Error {
2052
- static {
2053
- __name(this, "WorkflowAgentFailedError");
2054
- }
2055
- name = "WorkflowAgentFailedError";
2056
- kind;
2057
- terminateMode;
2058
- constructor(message, kind, terminateMode) {
2059
- super(message);
2060
- this.kind = kind;
2061
- this.terminateMode = terminateMode;
2062
- }
2063
- };
2064
- function isWorkflowAgentFailedError(error) {
2065
- return typeof error === "object" && error !== null && error.name === "WorkflowAgentFailedError";
2066
- }
2067
- __name(isWorkflowAgentFailedError, "isWorkflowAgentFailedError");
2068
- var WorkflowAgentCapExceededError = class extends Error {
2069
- static {
2070
- __name(this, "WorkflowAgentCapExceededError");
2071
- }
2072
- name = "WorkflowAgentCapExceededError";
2073
- constructor(maxAgents) {
2074
- super(
2075
- `Workflow exceeded the maximum of ${maxAgents} agent() calls per run.`
2076
- );
2077
- }
2078
- };
2079
- function isWorkflowRunLevelError(error) {
2080
- if (typeof error !== "object" || error === null) return false;
2081
- const name = error.name;
2082
- return name === "WorkflowBudgetExceededError" || name === "WorkflowAgentCapExceededError";
2083
- }
2084
- __name(isWorkflowRunLevelError, "isWorkflowRunLevelError");
2085
- var WORKFLOW_ABORT_REASON_STALLED = "stalled";
2086
-
2087
- // packages/core/src/agents/runtime/workflow-stall.ts
2088
- init_esbuild_shims();
2089
- var DEFAULT_STALL_MS = 18e4;
2090
- var MAX_STALL_ATTEMPTS = 3;
2091
- var MAX_WORKFLOW_STALL_MS_ENV = "QWEN_CODE_WORKFLOW_STALL_SECONDS";
2092
- function resolveStallMs(perCall, env = process.env) {
2093
- if (typeof perCall === "number" && Number.isFinite(perCall)) {
2094
- if (perCall === 0) return 0;
2095
- if (perCall > 0) return perCall;
2096
- }
2097
- const raw = env[MAX_WORKFLOW_STALL_MS_ENV];
2098
- const trimmed = raw?.trim();
2099
- if (trimmed) {
2100
- if (trimmed === "0") return 0;
2101
- const sec = parsePositiveIntegerEnv(trimmed, 0);
2102
- if (sec > 0) return sec * 1e3;
2103
- }
2104
- return DEFAULT_STALL_MS;
2105
- }
2106
- __name(resolveStallMs, "resolveStallMs");
2107
- var debugLogger4 = createDebugLogger("WORKFLOW_STALL");
2108
- function attachStallWatchdog(emitter, controller, stallMs) {
2109
- if (stallMs <= 0) {
2110
- return { stalled: /* @__PURE__ */ __name(() => false, "stalled"), dispose: /* @__PURE__ */ __name(() => {
2111
- }, "dispose") };
2112
- }
2113
- let inFlightTools = 0;
2114
- let fired = false;
2115
- let timer;
2116
- let disposed = false;
2117
- const clear = /* @__PURE__ */ __name(() => {
2118
- if (timer) {
2119
- clearTimeout(timer);
2120
- timer = void 0;
2121
- }
2122
- }, "clear");
2123
- const arm = /* @__PURE__ */ __name(() => {
2124
- clear();
2125
- if (disposed || fired) return;
2126
- if (inFlightTools > 0) return;
2127
- timer = setTimeout(() => {
2128
- if (disposed || fired) return;
2129
- fired = true;
2130
- debugLogger4.warn(
2131
- `[Workflow] agent dispatch stalled \u2014 no progress for ${stallMs}ms; aborting.`
2132
- );
2133
- try {
2134
- controller.abort(WORKFLOW_ABORT_REASON_STALLED);
2135
- } catch (e) {
2136
- debugLogger4.warn("stall watchdog abort threw:", e);
2137
- }
2138
- }, stallMs);
2139
- if (typeof timer.unref === "function") {
2140
- timer.unref();
2141
- }
2142
- }, "arm");
2143
- const onActivity = /* @__PURE__ */ __name(() => arm(), "onActivity");
2144
- const onToolCall = /* @__PURE__ */ __name(() => {
2145
- inFlightTools += 1;
2146
- clear();
2147
- }, "onToolCall");
2148
- const onToolResult = /* @__PURE__ */ __name(() => {
2149
- inFlightTools = Math.max(0, inFlightTools - 1);
2150
- arm();
2151
- }, "onToolResult");
2152
- emitter.on("round_start" /* ROUND_START */, onActivity);
2153
- emitter.on("round_end" /* ROUND_END */, onActivity);
2154
- emitter.on("stream_text" /* STREAM_TEXT */, onActivity);
2155
- emitter.on("usage_metadata" /* USAGE_METADATA */, onActivity);
2156
- emitter.on("tool_call" /* TOOL_CALL */, onToolCall);
2157
- emitter.on("tool_result" /* TOOL_RESULT */, onToolResult);
2158
- return {
2159
- stalled: /* @__PURE__ */ __name(() => fired, "stalled"),
2160
- dispose: /* @__PURE__ */ __name(() => {
2161
- if (disposed) return;
2162
- disposed = true;
2163
- clear();
2164
- emitter.off("round_start" /* ROUND_START */, onActivity);
2165
- emitter.off("round_end" /* ROUND_END */, onActivity);
2166
- emitter.off("stream_text" /* STREAM_TEXT */, onActivity);
2167
- emitter.off("usage_metadata" /* USAGE_METADATA */, onActivity);
2168
- emitter.off("tool_call" /* TOOL_CALL */, onToolCall);
2169
- emitter.off("tool_result" /* TOOL_RESULT */, onToolResult);
2170
- }, "dispose")
2171
- };
2172
- }
2173
- __name(attachStallWatchdog, "attachStallWatchdog");
2174
- async function runStallResilient(attemptFn, opts) {
2175
- const { stallMs, signal, label } = opts;
2176
- if (stallMs <= 0) {
2177
- const emitter = new AgentEventEmitter();
2178
- return attemptFn(signal ?? new AbortController().signal, emitter);
2179
- }
2180
- let attempt = 0;
2181
- for (; ; ) {
2182
- attempt += 1;
2183
- const controller = new AbortController();
2184
- let onParentAbort;
2185
- if (signal) {
2186
- if (signal.aborted) {
2187
- controller.abort(signal.reason);
2188
- } else {
2189
- onParentAbort = /* @__PURE__ */ __name(() => controller.abort(signal.reason), "onParentAbort");
2190
- signal.addEventListener("abort", onParentAbort);
2191
- }
2192
- }
2193
- const emitter = new AgentEventEmitter();
2194
- const watchdog = attachStallWatchdog(emitter, controller, stallMs);
2195
- try {
2196
- return await attemptFn(controller.signal, emitter);
2197
- } catch (err) {
2198
- if (signal?.aborted) throw err;
2199
- if (watchdog.stalled() && attempt < MAX_STALL_ATTEMPTS) {
2200
- debugLogger4.warn(
2201
- `[Workflow] agent "${label ?? "workflow-agent"}" stalled (attempt ${attempt}/${MAX_STALL_ATTEMPTS}) \u2014 retrying.`
2202
- );
2203
- continue;
2204
- }
2205
- if (watchdog.stalled()) {
2206
- throw new WorkflowAgentFailedError(
2207
- `agent "${label ?? "workflow-agent"}" stalled on all ${MAX_STALL_ATTEMPTS} attempts (no progress for ${stallMs}ms each).`,
2208
- "stalled"
2209
- );
2210
- }
2211
- throw err;
2212
- } finally {
2213
- watchdog.dispose();
2214
- if (onParentAbort && signal) {
2215
- signal.removeEventListener("abort", onParentAbort);
2216
- }
2217
- }
2218
- }
2219
- }
2220
- __name(runStallResilient, "runStallResilient");
2221
-
2222
- // packages/core/src/agents/runtime/workflow-journal.ts
2223
- init_esbuild_shims();
2224
- import { createHash } from "node:crypto";
2225
- import { constants, promises as fs2 } from "node:fs";
2226
- import path2 from "node:path";
2227
- var debugLogger5 = createDebugLogger("WORKFLOW_JOURNAL");
2228
- var JOURNAL_KEY_VERSION = "v2";
2229
- var DISPATCH_AFFECTING_AGENT_OPTS = [
2230
- "schema",
2231
- "model",
2232
- "effort",
2233
- "isolation",
2234
- "agentType",
2235
- "workingDir",
2236
- "disallowedTools"
2237
- ];
2238
- function canonicalizeAgentOpts(opts) {
2239
- const projected = {};
2240
- for (const k of DISPATCH_AFFECTING_AGENT_OPTS) {
2241
- const v = opts[k];
2242
- if (v === void 0 || typeof v === "function") continue;
2243
- projected[k] = v;
2244
- }
2245
- const sortDeep = /* @__PURE__ */ __name((val) => {
2246
- if (typeof val === "function") return void 0;
2247
- if (Array.isArray(val)) return val.map(sortDeep);
2248
- if (val && typeof val === "object") {
2249
- const out = {};
2250
- for (const key of Object.keys(val).sort()) {
2251
- if (key === "__proto__") continue;
2252
- out[key] = sortDeep(val[key]);
2253
- }
2254
- return out;
2255
- }
2256
- return val;
2257
- }, "sortDeep");
2258
- try {
2259
- return JSON.stringify(sortDeep(projected));
2260
- } catch {
2261
- return "{}";
2262
- }
2263
- }
2264
- __name(canonicalizeAgentOpts, "canonicalizeAgentOpts");
2265
- function deriveAgentKey(prefixHash, prompt, opts) {
2266
- const hash = createHash("sha256");
2267
- hash.update(prefixHash);
2268
- hash.update("\0");
2269
- hash.update(prompt);
2270
- hash.update("\0");
2271
- hash.update(canonicalizeAgentOpts(opts));
2272
- return `${JOURNAL_KEY_VERSION}:${hash.digest("hex")}`;
2273
- }
2274
- __name(deriveAgentKey, "deriveAgentKey");
2275
- function deriveArgsSeed(args) {
2276
- const hash = createHash("sha256");
2277
- let serialized;
2278
- try {
2279
- serialized = JSON.stringify(args ?? null) ?? "null";
2280
- } catch {
2281
- serialized = "non-serializable-args";
2282
- }
2283
- hash.update(serialized);
2284
- return `${JOURNAL_KEY_VERSION}:${hash.digest("hex")}`;
2285
- }
2286
- __name(deriveArgsSeed, "deriveArgsSeed");
2287
- function buildReplay(entries) {
2288
- const results = /* @__PURE__ */ new Map();
2289
- const started = /* @__PURE__ */ new Map();
2290
- const failed = /* @__PURE__ */ new Set();
2291
- for (const e of entries) {
2292
- if (e.type === "result") {
2293
- results.set(e.key, e);
2294
- } else if (e.type === "started") {
2295
- failed.delete(e.key);
2296
- const list = started.get(e.key);
2297
- if (list) list.push(e);
2298
- else started.set(e.key, [e]);
2299
- } else if (e.type === "failed") {
2300
- failed.add(e.key);
2301
- }
2302
- }
2303
- return { results, started, failed };
2304
- }
2305
- __name(buildReplay, "buildReplay");
2306
- var WorkflowJournal = class {
2307
- constructor(journalPath, root = path2.dirname(path2.dirname(journalPath))) {
2308
- this.root = root;
2309
- this.path = journalPath;
2310
- }
2311
- static {
2312
- __name(this, "WorkflowJournal");
2313
- }
2314
- pending = Promise.resolve();
2315
- path;
2316
- async hasSymlinkedPath() {
2317
- if (await isSymlinkedRoot(this.root) || await isSymlinkedRoot(path2.dirname(this.path))) {
2318
- return true;
2319
- }
2320
- return fs2.lstat(this.path).then((stat) => stat.isSymbolicLink()).catch(() => false);
2321
- }
2322
- /** Ensure the advertised journal path exists without affecting the run. */
2323
- async ensureExists() {
2324
- try {
2325
- if (await this.hasSymlinkedPath()) return false;
2326
- await fs2.mkdir(path2.dirname(this.path), { recursive: true });
2327
- if (await this.hasSymlinkedPath()) return false;
2328
- const noFollow = process.platform === "win32" ? 0 : constants.O_NOFOLLOW;
2329
- const file = await fs2.open(
2330
- this.path,
2331
- constants.O_APPEND | constants.O_CREAT | constants.O_WRONLY | noFollow,
2332
- 384
2333
- );
2334
- try {
2335
- await file.chmod(384);
2336
- } finally {
2337
- await file.close();
2338
- }
2339
- return true;
2340
- } catch (error) {
2341
- debugLogger5.warn(
2342
- `WorkflowJournal.ensureExists failed for ${this.path}: ${error}`
2343
- );
2344
- return false;
2345
- }
2346
- }
2347
- /** Remove a never-registered run's journal file, best-effort. */
2348
- async remove() {
2349
- try {
2350
- if (await this.hasSymlinkedPath()) return;
2351
- await fs2.rm(this.path, { force: true });
2352
- await fs2.rmdir(path2.dirname(this.path)).catch((error) => {
2353
- const code = error.code;
2354
- if (code !== "ENOENT" && code !== "ENOTEMPTY") throw error;
2355
- });
2356
- } catch (error) {
2357
- debugLogger5.warn(
2358
- `WorkflowJournal.remove failed for ${this.path}: ${error}`
2359
- );
2360
- }
2361
- }
2362
- /** Load + parse all entries into replay maps. Empty maps if no file. */
2363
- async load() {
2364
- try {
2365
- const entries = await read(this.path);
2366
- return buildReplay(entries);
2367
- } catch (e) {
2368
- debugLogger5.warn(`WorkflowJournal.load failed for ${this.path}: ${e}`);
2369
- return { results: /* @__PURE__ */ new Map(), started: /* @__PURE__ */ new Map(), failed: /* @__PURE__ */ new Set() };
2370
- }
2371
- }
2372
- /** Append one entry. Rejects only on I/O error (callers `.catch`). */
2373
- append(entry) {
2374
- const operation = this.pending.then(() => writeLine(this.path, entry));
2375
- this.pending = operation.catch(() => void 0);
2376
- return operation;
2377
- }
2378
- /** Wait until every append issued so far has settled. */
2379
- drain() {
2380
- return this.pending;
2381
- }
2382
- };
2383
-
2384
- // packages/core/src/agents/runtime/workflow-prompts.ts
2385
- init_esbuild_shims();
2386
- 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.';
2387
- 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.";
2388
-
2389
- // packages/core/src/agents/runtime/workflow-dispatch-scheduler.ts
2390
- init_esbuild_shims();
2391
- function abortError() {
2392
- return new DOMException("Workflow dispatch scheduler aborted.", "AbortError");
2393
- }
2394
- __name(abortError, "abortError");
2395
- var WorkflowDispatchScheduler = class {
2396
- constructor(limit, signal, onStateChange) {
2397
- this.limit = limit;
2398
- this.signal = signal;
2399
- if (!Number.isInteger(limit) || limit < 1) {
2400
- throw new Error(
2401
- `Workflow dispatch limit must be a positive integer, got ${String(limit)}.`
2402
- );
2403
- }
2404
- if (onStateChange) this.stateListeners.add(onStateChange);
2405
- if (signal && !signal.aborted) {
2406
- signal.addEventListener("abort", () => this.abortPending(), {
2407
- once: true
2408
- });
2409
- }
2410
- }
2411
- static {
2412
- __name(this, "WorkflowDispatchScheduler");
2413
- }
2414
- state = "running";
2415
- inFlight = 0;
2416
- queue = [];
2417
- gateWaiters = [];
2418
- stateListeners = /* @__PURE__ */ new Set();
2419
- /**
2420
- * Subscribe to state transitions. Returns an unsubscribe function.
2421
- * The constructor callback (when given) is registered as the first
2422
- * listener; this method lets additional observers — e.g. the sandbox's
2423
- * pause-aware wall-clock watchdog — hook the same transitions.
2424
- */
2425
- onStateChange(listener) {
2426
- this.stateListeners.add(listener);
2427
- return () => {
2428
- this.stateListeners.delete(listener);
2429
- };
2430
- }
2431
- run(thunk) {
2432
- return new Promise((resolve2, reject) => {
2433
- if (this.signal?.aborted) {
2434
- reject(abortError());
2435
- return;
2436
- }
2437
- this.queue.push({
2438
- thunk,
2439
- resolve: resolve2,
2440
- reject
2441
- });
2442
- this.pump();
2443
- });
2444
- }
2445
- pause() {
2446
- if (this.state !== "running" || this.signal?.aborted) return false;
2447
- this.setState("pausing");
2448
- if (this.inFlight === 0) this.setState("paused");
2449
- return true;
2450
- }
2451
- resume() {
2452
- if (this.state !== "paused" || this.signal?.aborted) return false;
2453
- this.setState("running");
2454
- while (this.gateWaiters.length > 0) {
2455
- this.gateWaiters.shift().resolve();
2456
- }
2457
- this.pump();
2458
- return true;
2459
- }
2460
- waitUntilRunning() {
2461
- if (this.signal?.aborted) return Promise.reject(abortError());
2462
- if (this.state === "running") return Promise.resolve();
2463
- return new Promise((resolve2, reject) => {
2464
- this.gateWaiters.push({ resolve: resolve2, reject });
2465
- });
2466
- }
2467
- snapshot() {
2468
- return {
2469
- state: this.state,
2470
- queued: this.queue.length,
2471
- inFlight: this.inFlight
2472
- };
2473
- }
2474
- pump() {
2475
- while (this.state === "running" && this.inFlight < this.limit && this.queue.length > 0) {
2476
- const job = this.queue.shift();
2477
- if (this.signal?.aborted) {
2478
- job.reject(abortError());
2479
- continue;
2480
- }
2481
- this.inFlight++;
2482
- Promise.resolve().then(job.thunk).then(job.resolve, job.reject).finally(() => {
2483
- this.inFlight--;
2484
- if (this.state === "pausing" && this.inFlight === 0) {
2485
- this.setState("paused");
2486
- }
2487
- this.pump();
2488
- });
2489
- }
2490
- }
2491
- setState(state) {
2492
- if (this.state === state) return;
2493
- this.state = state;
2494
- const snapshot = this.snapshot();
2495
- for (const listener of [...this.stateListeners]) listener(snapshot);
2496
- }
2497
- abortPending() {
2498
- const error = abortError();
2499
- while (this.queue.length > 0) this.queue.shift().reject(error);
2500
- while (this.gateWaiters.length > 0) {
2501
- this.gateWaiters.shift().reject(error);
2502
- }
2503
- }
2504
- };
2505
-
2506
- // packages/core/src/agents/runtime/workflow-orchestrator.ts
2507
- var DEFAULT_MAX_AGENTS_PER_RUN = 1e3;
2508
- var MAX_WORKFLOW_AGENTS_ENV = "QWEN_CODE_MAX_WORKFLOW_AGENTS";
2509
- var HARD_MAX_AGENTS_PER_RUN_CEILING = 1e4;
2510
- function resolveMaxAgentsPerRun(env = process.env) {
2511
- const raw = env[MAX_WORKFLOW_AGENTS_ENV];
2512
- if (raw === void 0 || raw.trim() === "") {
2513
- return DEFAULT_MAX_AGENTS_PER_RUN;
2514
- }
2515
- const parsed = parsePositiveIntegerEnv(raw, 0);
2516
- if (parsed < 1) {
2517
- debugLogger.warn(
2518
- `Invalid ${MAX_WORKFLOW_AGENTS_ENV}=${JSON.stringify(raw)}, using default (${DEFAULT_MAX_AGENTS_PER_RUN})`
2519
- );
2520
- return DEFAULT_MAX_AGENTS_PER_RUN;
2521
- }
2522
- if (parsed > HARD_MAX_AGENTS_PER_RUN_CEILING) {
2523
- debugLogger.warn(
2524
- `${MAX_WORKFLOW_AGENTS_ENV}=${parsed} exceeds hard ceiling (${HARD_MAX_AGENTS_PER_RUN_CEILING}); clamping.`
2525
- );
2526
- return HARD_MAX_AGENTS_PER_RUN_CEILING;
2527
- }
2528
- return parsed;
2529
- }
2530
- __name(resolveMaxAgentsPerRun, "resolveMaxAgentsPerRun");
2531
- var MAX_WORKFLOW_CONCURRENCY_ENV = "QWEN_CODE_MAX_WORKFLOW_CONCURRENCY";
2532
- var HARD_MAX_CONCURRENCY_CEILING = 64;
2533
- function resolveConcurrencyLimit(env = process.env, availableParallelism2 = os.availableParallelism) {
2534
- const raw = env[MAX_WORKFLOW_CONCURRENCY_ENV];
2535
- if (raw !== void 0 && raw.trim() !== "") {
2536
- const parsed = parsePositiveIntegerEnv(raw, 0);
2537
- if (parsed >= 1) {
2538
- if (parsed > HARD_MAX_CONCURRENCY_CEILING) {
2539
- debugLogger.warn(
2540
- `${MAX_WORKFLOW_CONCURRENCY_ENV}=${parsed} exceeds hard ceiling (${HARD_MAX_CONCURRENCY_CEILING}); clamping.`
2541
- );
2542
- return HARD_MAX_CONCURRENCY_CEILING;
2543
- }
2544
- return parsed;
2545
- }
2546
- debugLogger.warn(
2547
- `Invalid ${MAX_WORKFLOW_CONCURRENCY_ENV}=${JSON.stringify(raw)}, using cpu-derived default`
2548
- );
2549
- }
2550
- return Math.max(2, Math.min(16, availableParallelism2() - 2));
2551
- }
2552
- __name(resolveConcurrencyLimit, "resolveConcurrencyLimit");
2553
- var DEFAULT_WORKFLOW_SUBAGENT_MAX_TURNS = 50;
2554
- var DEFAULT_WORKFLOW_SUBAGENT_MAX_TIME_MINUTES = 10;
2555
- var WORKFLOW_SUBAGENT_MAX_TURNS_ENV = "QWEN_CODE_WORKFLOW_AGENT_MAX_TURNS";
2556
- var WORKFLOW_SUBAGENT_MAX_MINUTES_ENV = "QWEN_CODE_WORKFLOW_AGENT_MAX_MINUTES";
2557
- var HARD_WORKFLOW_SUBAGENT_MAX_TURNS_CEILING = 500;
2558
- var HARD_WORKFLOW_SUBAGENT_MAX_MINUTES_CEILING = 100;
2559
- function resolveSubagentBound(envName, defaultValue, ceiling, env) {
2560
- const raw = env[envName];
2561
- if (raw === void 0 || raw.trim() === "") return defaultValue;
2562
- const parsed = parsePositiveIntegerEnv(raw, 0);
2563
- if (parsed < 1) {
2564
- debugLogger.warn(
2565
- `Invalid ${envName}=${JSON.stringify(raw)}, using default (${defaultValue})`
2566
- );
2567
- return defaultValue;
2568
- }
2569
- if (parsed > ceiling) {
2570
- debugLogger.warn(
2571
- `${envName}=${parsed} exceeds hard ceiling (${ceiling}); clamping.`
2572
- );
2573
- return ceiling;
2574
- }
2575
- return parsed;
2576
- }
2577
- __name(resolveSubagentBound, "resolveSubagentBound");
2578
- function resolveSubagentMaxTurns(env = process.env, defaultValue = DEFAULT_WORKFLOW_SUBAGENT_MAX_TURNS) {
2579
- return resolveSubagentBound(
2580
- WORKFLOW_SUBAGENT_MAX_TURNS_ENV,
2581
- defaultValue,
2582
- HARD_WORKFLOW_SUBAGENT_MAX_TURNS_CEILING,
2583
- env
2584
- );
2585
- }
2586
- __name(resolveSubagentMaxTurns, "resolveSubagentMaxTurns");
2587
- function resolveSubagentMaxTimeMinutes(env = process.env, defaultValue = DEFAULT_WORKFLOW_SUBAGENT_MAX_TIME_MINUTES) {
2588
- return resolveSubagentBound(
2589
- WORKFLOW_SUBAGENT_MAX_MINUTES_ENV,
2590
- defaultValue,
2591
- HARD_WORKFLOW_SUBAGENT_MAX_MINUTES_CEILING,
2592
- env
2593
- );
2594
- }
2595
- __name(resolveSubagentMaxTimeMinutes, "resolveSubagentMaxTimeMinutes");
2596
- var WORKFLOW_SUBAGENT_DISALLOWED_TOOLS = [
2597
- ToolNames.ASK_USER_QUESTION,
2598
- ToolNames.SEND_MESSAGE,
2599
- ToolNames.MONITOR,
2600
- ...SUBAGENT_PLAN_LIFECYCLE_TOOLS,
2601
- // AgentTool: workflow subagents must not spawn sub-agents even where
2602
- // maxSubagentDepth would permit nesting — a leaf-spawned agent would run
2603
- // outside the orchestrator's concurrency cap, agent counter, and token
2604
- // budget, and its result would bypass the script's return-value contract.
2605
- // The WorkflowTool itself is already excluded from every subagent; this
2606
- // closes the same loop for plain `agent` calls (review #6189).
2607
- ToolNames.AGENT
2608
- ];
2609
- var WorkflowExecutionError = class extends Error {
2610
- constructor(message, phases, logs, meta = null) {
2611
- super(message);
2612
- this.phases = phases;
2613
- this.logs = logs;
2614
- this.meta = meta;
2615
- }
2616
- static {
2617
- __name(this, "WorkflowExecutionError");
2618
- }
2619
- name = "WorkflowExecutionError";
2620
- };
2621
- function generateRunId() {
2622
- return `wf_${randomBytes(8).toString("hex")}`;
2623
- }
2624
- __name(generateRunId, "generateRunId");
2625
- function sanitizeForErrorMessage(value) {
2626
- return stripAnsiAndControl(value);
2627
- }
2628
- __name(sanitizeForErrorMessage, "sanitizeForErrorMessage");
2629
- function createProductionDispatch(config, signal, onTokens, bridgeApprovalEvents, subagentBounds) {
2630
- return async (prompt, opts, dispatchId) => {
2631
- if (typeof prompt !== "string" || prompt.length === 0) {
2632
- throw new Error("agent() requires a non-empty string prompt.");
2633
- }
2634
- const stallMs = resolveStallMs(
2635
- typeof opts.stallMs === "number" ? opts.stallMs : void 0
2636
- );
2637
- const workflowAgentId = `workflow-agent-${randomBytes(8).toString("hex")}`;
2638
- const agentIdentity = await resolveWorkflowAgentIdentity(config, opts);
2639
- if (agentIdentity.resolvedAgentType?.executor !== void 0) {
2640
- throw new Error(
2641
- "Workflow agent() does not support external-executor agents: token budgets, schema output, and workflow tool restrictions cannot be enforced. Use an in-process agent definition instead."
2642
- );
2643
- }
2644
- let attempt = 0;
2645
- return runStallResilient(
2646
- async (attemptSignal, emitter) => {
2647
- attempt += 1;
2648
- const cleanupApprovalBridge = bridgeApprovalEvents?.(
2649
- emitter,
2650
- dispatchId
2651
- );
2652
- const cleanupTranscript = attachDispatchTranscript(
2653
- config,
2654
- workflowAgentId,
2655
- prompt,
2656
- agentIdentity.name,
2657
- emitter,
2658
- attempt
2659
- );
2660
- try {
2661
- return await runSingleDispatch(
2662
- config,
2663
- prompt,
2664
- opts,
2665
- attemptSignal,
2666
- emitter,
2667
- workflowAgentId,
2668
- agentIdentity,
2669
- onTokens,
2670
- subagentBounds
2671
- );
2672
- } finally {
2673
- cleanupTranscript();
2674
- cleanupApprovalBridge?.();
2675
- }
2676
- },
2677
- {
2678
- stallMs,
2679
- signal,
2680
- // The name can carry a model-authored agentType spelling — keep
2681
- // the stall log / abandoned error single-line the same way the
2682
- // "not found" throw site sanitizes it.
2683
- label: sanitizeForErrorMessage(agentIdentity.name)
2684
- }
2685
- );
2686
- };
2687
- }
2688
- __name(createProductionDispatch, "createProductionDispatch");
2689
- async function resolveWorkflowAgentIdentity(config, opts) {
2690
- if (opts.agentType) {
2691
- const resolved = await config.getSubagentManager().findSubagentByName(opts.agentType);
2692
- if (resolved) {
2693
- return { name: resolved.name, resolvedAgentType: resolved };
2694
- }
2695
- }
2696
- if (typeof opts.label === "string" && opts.label) {
2697
- return { name: opts.label };
2698
- }
2699
- return { name: opts.agentType || "workflow-agent" };
2700
- }
2701
- __name(resolveWorkflowAgentIdentity, "resolveWorkflowAgentIdentity");
2702
- function attachDispatchTranscript(config, agentId, prompt, agentName, emitter, attempt) {
2703
- const append = attempt > 1;
2704
- try {
2705
- const { jsonlPath, options } = buildAgentTranscriptAttach(config, agentId, {
2706
- agentName,
2707
- // The prompt the SCRIPT dispatched, seeded as the transcript's first
2708
- // user record — the same shape AgentTool writes, so a reader that
2709
- // recovers a launch prompt from a transcript needs no workflow-
2710
- // specific branch. A retry re-uses the first attempt's record rather
2711
- // than seeding a second one.
2712
- initialUserPrompt: append ? void 0 : prompt,
2713
- appendToExisting: append,
2714
- retryAttempt: append ? attempt : void 0
2715
- });
2716
- return attachJsonlTranscriptWriter(emitter, jsonlPath, options).cleanup;
2717
- } catch (error) {
2718
- debugLogger.warn(
2719
- `[Workflow] failed to attach transcript for ${agentId}: ${error}`
2720
- );
2721
- return () => {
2722
- };
2723
- }
2724
- }
2725
- __name(attachDispatchTranscript, "attachDispatchTranscript");
2726
- function terminalDispatchError(workflowAgentId, mode) {
2727
- const message = `Workflow subagent ${workflowAgentId} did not complete (terminate mode: ${mode}).`;
2728
- switch (mode) {
2729
- case "MAX_TURNS" /* MAX_TURNS */:
2730
- return new WorkflowAgentFailedError(message, "max_turns", mode);
2731
- case "TIMEOUT" /* TIMEOUT */:
2732
- return new WorkflowAgentFailedError(message, "timeout", mode);
2733
- case "ERROR" /* ERROR */:
2734
- return new WorkflowAgentFailedError(message, "error", mode);
2735
- default:
2736
- return new Error(message);
2737
- }
2738
- }
2739
- __name(terminalDispatchError, "terminalDispatchError");
2740
- async function runSingleDispatch(config, prompt, opts, attemptSignal, emitter, workflowAgentId, agentIdentity, onTokens, subagentBounds) {
2741
- const { AgentHeadless, ContextState } = await import("./agent-headless-2JPJKYHK.js");
2742
- const ctx = new ContextState();
2743
- ctx.set("task_prompt", prompt);
2744
- debugLogger.debug(`[workflow] Dispatch ${workflowAgentId}`);
2745
- if (DISPATCH_AFFECTING_AGENT_OPTS.every((key) => opts[key] === void 0)) {
2746
- const subagent = await AgentHeadless.create(
2747
- agentIdentity.name,
2748
- config,
2749
- {
2750
- systemPrompt: WORKFLOW_SUBAGENT_SYSTEM_PROMPT
2751
- },
2752
- {},
2753
- // T11 (PR #4732 R1): bound resource ceiling so a single agent() call
2754
- // cannot loop the model indefinitely. Without this, runConfig was {}
2755
- // and the loop guards never tripped — combined with the cancellation
2756
- // bug below, workflows were effectively unkillable.
2757
- subagentBounds ?? {
2758
- max_turns: resolveSubagentMaxTurns(),
2759
- max_time_minutes: resolveSubagentMaxTimeMinutes()
2760
- },
2761
- // T11 (PR #4732 R1): disallow SendMessage / ExitPlanMode to align with
2762
- // upstream Tg8 — closes the back-channel that would let a subagent
2763
- // deliver its answer via user message instead of the script's read.
2764
- { tools: ["*"], disallowedTools: WORKFLOW_SUBAGENT_DISALLOWED_TOOLS },
2765
- // P-stall: the stall-watchdog emitter observes reasoning-loop events
2766
- // (round/tool/usage) to detect a hang and abort `attemptSignal`.
2767
- emitter,
2768
- void 0,
2769
- void 0,
2770
- prompt,
2771
- workflowAgentId
2772
- );
2773
- try {
2774
- await runWithAgentContext(
2775
- workflowAgentId,
2776
- () => subagent.execute(ctx, attemptSignal)
2777
- );
2778
- } finally {
2779
- reportTokens(subagent, opts, onTokens);
2780
- }
2781
- const mode = subagent.getTerminateMode();
2782
- if (mode !== "GOAL" /* GOAL */) {
2783
- throw terminalDispatchError(workflowAgentId, mode);
2784
- }
2785
- return toModelVisibleSubagentResult(subagent.getFinalText(), mode);
2786
- }
2787
- return runOverridePath(
2788
- config,
2789
- ctx,
2790
- opts,
2791
- attemptSignal,
2792
- workflowAgentId,
2793
- agentIdentity,
2794
- onTokens,
2795
- emitter,
2796
- subagentBounds
2797
- );
2798
- }
2799
- __name(runSingleDispatch, "runSingleDispatch");
2800
- function reportTokens(subagent, opts, onTokens) {
2801
- if (!onTokens) return;
2802
- try {
2803
- const summary = subagent.getExecutionSummary();
2804
- onTokens(summary.outputTokens, opts);
2805
- } catch (e) {
2806
- debugLogger.warn("onTokens callback threw:", e);
2807
- }
2808
- }
2809
- __name(reportTokens, "reportTokens");
2810
- function resolveDispatchEffort(raw) {
2811
- if (raw === void 0) return void 0;
2812
- const tier = typeof raw === "string" ? normalizeReasoningEffort(raw) : void 0;
2813
- if (tier === void 0) {
2814
- throw new Error(
2815
- `agent({effort}): unknown effort tier ${sanitizeForErrorMessage(
2816
- JSON.stringify(raw) ?? String(raw)
2817
- )}. Known tiers are: ${REASONING_EFFORT_TIERS.join(", ")}.`
2818
- );
2819
- }
2820
- return tier;
2821
- }
2822
- __name(resolveDispatchEffort, "resolveDispatchEffort");
2823
- function resolveDispatchDenies(raw) {
2824
- if (raw === void 0) return [];
2825
- if (!Array.isArray(raw) || raw.some(
2826
- (name) => typeof name !== "string" || name.length === 0 || name !== name.trim()
2827
- )) {
2828
- throw new Error(
2829
- "agent({disallowedTools}): must be an array of non-empty tool-name strings without surrounding whitespace, e.g. ['run_shell_command', 'write_file']."
2830
- );
2831
- }
2832
- return raw.map((name) => resolveBuiltinToolName(name) ?? name);
2833
- }
2834
- __name(resolveDispatchDenies, "resolveDispatchDenies");
2835
- async function runOverridePath(config, ctx, opts, signal, workflowAgentId, agentIdentity, onTokens, emitter, subagentBounds) {
2836
- if (opts.isolation === "remote") {
2837
- throw new Error(
2838
- "agent({isolation:'remote'}) is not available in this build."
2839
- );
2840
- }
2841
- const effort = resolveDispatchEffort(opts.effort);
2842
- const requestedDenies = resolveDispatchDenies(opts.disallowedTools);
2843
- const subagentMgr = config.getSubagentManager();
2844
- let baseConfig;
2845
- if (opts.agentType !== void 0) {
2846
- const resolved = agentIdentity.resolvedAgentType;
2847
- if (!resolved) {
2848
- const safeAgentType = sanitizeForErrorMessage(opts.agentType);
2849
- throw new Error(
2850
- `agent({agentType}): agent type '${safeAgentType}' not found.`
2851
- );
2852
- }
2853
- baseConfig = resolved;
2854
- } else {
2855
- baseConfig = {
2856
- name: agentIdentity.name,
2857
- description: "Default workflow subagent (per-call overrides).",
2858
- systemPrompt: WORKFLOW_SUBAGENT_SYSTEM_PROMPT,
2859
- level: "session",
2860
- isBuiltin: false
2861
- };
2862
- }
2863
- let schemaSystemPrompt;
2864
- if (opts.schema !== void 0) {
2865
- schemaSystemPrompt = opts.agentType !== void 0 && baseConfig.systemPrompt ? `${baseConfig.systemPrompt}
2866
-
2867
- ${WORKFLOW_SUBAGENT_SYSTEM_PROMPT_WITH_SCHEMA}` : WORKFLOW_SUBAGENT_SYSTEM_PROMPT_WITH_SCHEMA;
2868
- }
2869
- let schemaTools;
2870
- if (opts.schema !== void 0 && baseConfig.tools && baseConfig.tools.length > 0 && !baseConfig.tools.includes("*") && !baseConfig.tools.includes(ToolNames.STRUCTURED_OUTPUT)) {
2871
- schemaTools = [...baseConfig.tools, ToolNames.STRUCTURED_OUTPUT];
2872
- }
2873
- const augmented = {
2874
- ...baseConfig,
2875
- ...opts.model !== void 0 ? { model: opts.model } : {},
2876
- ...schemaSystemPrompt !== void 0 ? { systemPrompt: schemaSystemPrompt } : {},
2877
- ...schemaTools !== void 0 ? { tools: schemaTools } : {},
2878
- disallowedTools: Array.from(
2879
- /* @__PURE__ */ new Set([
2880
- ...baseConfig.disallowedTools ?? [],
2881
- ...WORKFLOW_SUBAGENT_DISALLOWED_TOOLS,
2882
- ...requestedDenies
2883
- ])
2884
- )
2885
- };
2886
- if (requestedDenies.length > 0) {
2887
- const unmatched = await subagentMgr.findUnmatchedToolNames(requestedDenies);
2888
- if (unmatched.length > 0) {
2889
- throw new Error(
2890
- `agent({disallowedTools}): ${sanitizeForErrorMessage(
2891
- unmatched.map((name) => JSON.stringify(name)).join(", ")
2892
- )} ${unmatched.length === 1 ? "matches" : "match"} no tool. Use a tool name (run_shell_command, write_file, edit), a display name (Shell, WriteFile, Edit), or an MCP pattern (mcp__<server>, mcp__<server>__*, mcp__<server>__<tool>).`
2893
- );
2894
- }
2895
- }
2896
- if (opts.schema !== void 0 && [...baseConfig.disallowedTools ?? [], ...requestedDenies].some(
2897
- (name) => (resolveBuiltinToolName(name) ?? name) === ToolNames.STRUCTURED_OUTPUT
2898
- )) {
2899
- throw new Error(
2900
- "agent({schema, disallowedTools}): schema mode needs the structured_output tool, but disallowedTools deny it (from this call or from the agent type)."
2901
- );
2902
- }
2903
- let worktreeIsolation = null;
2904
- let effectiveContext = config;
2905
- let approvalCleanup;
2906
- if (opts.isolation !== void 0 && opts.workingDir !== void 0) {
2907
- throw new Error(
2908
- "agent({workingDir, isolation}): incompatible options. workingDir pins the agent to a worktree you already own; isolation creates a fresh one and removes it afterwards. Pass one."
2909
- );
2910
- }
2911
- if (opts.isolation === "worktree") {
2912
- worktreeIsolation = await provisionWorkflowWorktree(config);
2913
- effectiveContext = deriveWorktreeConfig(config, worktreeIsolation.path, {
2914
- customIgnoreFiles: config.getFileFilteringOptions().customIgnoreFiles
2915
- });
2916
- installSessionWorkflowRevisionWriteThrough(effectiveContext, config);
2917
- } else if (opts.workingDir !== void 0) {
2918
- if (typeof opts.workingDir !== "string" || opts.workingDir.trim().length === 0) {
2919
- throw new Error(
2920
- "agent({workingDir}): must be a non-empty string naming an existing git worktree of this repository."
2921
- );
2922
- }
2923
- const resolved = await resolveExternalWorktreeDir(
2924
- config,
2925
- opts.workingDir,
2926
- "workingDir"
2927
- );
2928
- if ("error" in resolved) {
2929
- throw new Error(
2930
- `agent({workingDir: ${sanitizeForErrorMessage(JSON.stringify(opts.workingDir))}}): ${sanitizeForErrorMessage(resolved.error)}`
2931
- );
2932
- }
2933
- effectiveContext = deriveWorktreeConfig(config, resolved.path, {
2934
- customIgnoreFiles: config.getFileFilteringOptions().customIgnoreFiles
2935
- });
2936
- installSessionWorkflowRevisionWriteThrough(effectiveContext, config);
2937
- }
2938
- if (effectiveContext !== config) {
2939
- const approvalHandle = deriveApprovalModeConfig(
2940
- effectiveContext,
2941
- config.getApprovalMode()
2942
- );
2943
- approvalCleanup = approvalHandle.cleanup;
2944
- effectiveContext = approvalHandle.config;
2945
- }
2946
- let onParentAbort;
2947
- try {
2948
- let schemaState = null;
2949
- if (opts.schema !== void 0) {
2950
- effectiveContext = await createSchemaConfigOverride(
2951
- effectiveContext,
2952
- opts.schema
2953
- );
2954
- schemaState = createSchemaModeState();
2955
- }
2956
- let dispatchSignal = signal;
2957
- if (schemaState) {
2958
- const child = new AbortController();
2959
- if (signal) {
2960
- if (signal.aborted) {
2961
- child.abort(signal.reason);
2962
- } else {
2963
- onParentAbort = /* @__PURE__ */ __name(() => child.abort(signal.reason), "onParentAbort");
2964
- signal.addEventListener("abort", onParentAbort);
2965
- }
2966
- }
2967
- schemaState.abortController = child;
2968
- dispatchSignal = child.signal;
2969
- }
2970
- const eventEmitter = emitter ?? (schemaState ? new AgentEventEmitter() : void 0);
2971
- if (schemaState && eventEmitter) {
2972
- attachSchemaListeners(eventEmitter, schemaState);
2973
- }
2974
- const { subagent, dispose } = await subagentMgr.createAgentHeadless(
2975
- augmented,
2976
- effectiveContext,
2977
- {
2978
- // Workflow always bounds resource ceiling regardless of agentType's
2979
- // own runConfig / maxTurns — these are workflow-level safety bounds,
2980
- // not subagent-level preferences. P5 will refine via budget.
2981
- runConfigOverrides: subagentBounds ?? {
2982
- max_turns: resolveSubagentMaxTurns(),
2983
- max_time_minutes: resolveSubagentMaxTimeMinutes()
2984
- },
2985
- ...effort !== void 0 ? { modelConfigOverrides: { reasoningEffort: effort } } : {},
2986
- eventEmitter,
2987
- taskName: String(ctx.get("task_prompt")),
2988
- subagentId: workflowAgentId
2989
- }
2990
- );
2991
- try {
2992
- try {
2993
- await runWithAgentContext(
2994
- workflowAgentId,
2995
- () => subagent.execute(ctx, dispatchSignal)
2996
- );
2997
- } finally {
2998
- reportTokens(subagent, opts, onTokens);
2999
- }
3000
- if (schemaState) {
3001
- if (schemaState.result !== null) {
3002
- if (worktreeIsolation) {
3003
- const isolation = worktreeIsolation;
3004
- worktreeIsolation = null;
3005
- const preserved = await cleanupWorkflowWorktree(isolation);
3006
- if (preserved) {
3007
- debugLogger.info(
3008
- `[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.`
3009
- );
3010
- }
3011
- }
3012
- return schemaState.result;
3013
- }
3014
- if (signal?.aborted) {
3015
- throw new DOMException("Workflow aborted.", "AbortError");
3016
- }
3017
- const mode2 = subagent.getTerminateMode();
3018
- if (mode2 !== "GOAL" /* GOAL */ && mode2 !== "CANCELLED" /* CANCELLED */) {
3019
- throw terminalDispatchError(workflowAgentId, mode2);
3020
- }
3021
- if (schemaState.attempts > 2) {
3022
- throw new WorkflowAgentFailedError(
3023
- "subagent completed without calling StructuredOutput (after 2 in-conversation nudges).",
3024
- "no_structured_output"
3025
- );
3026
- }
3027
- throw new WorkflowAgentFailedError(
3028
- "subagent completed without calling structured_output (no validation attempt \u2014 model produced plain-text content).",
3029
- "no_structured_output"
3030
- );
3031
- }
3032
- const mode = subagent.getTerminateMode();
3033
- if (mode !== "GOAL" /* GOAL */) {
3034
- throw terminalDispatchError(workflowAgentId, mode);
3035
- }
3036
- let finalText = toModelVisibleSubagentResult(
3037
- subagent.getFinalText(),
3038
- mode
3039
- );
3040
- if (worktreeIsolation) {
3041
- const isolation = worktreeIsolation;
3042
- worktreeIsolation = null;
3043
- const preserved = await cleanupWorkflowWorktree(isolation);
3044
- if (preserved && typeof finalText === "string") {
3045
- finalText = appendWorktreePreservedSuffix(finalText, preserved);
3046
- }
3047
- }
3048
- return finalText;
3049
- } finally {
3050
- await dispose();
3051
- }
3052
- } finally {
3053
- if (onParentAbort && signal) {
3054
- signal.removeEventListener("abort", onParentAbort);
3055
- }
3056
- approvalCleanup?.();
3057
- if (worktreeIsolation) {
3058
- try {
3059
- await cleanupWorkflowWorktree(worktreeIsolation);
3060
- } catch (error) {
3061
- debugLogger.warn(
3062
- `Workflow worktree cleanup in fallback finally failed for ${worktreeIsolation.path}: ${error instanceof Error ? error.message : String(error)}`
3063
- );
3064
- }
3065
- }
3066
- }
3067
- }
3068
- __name(runOverridePath, "runOverridePath");
3069
- async function provisionWorkflowWorktree(config) {
3070
- const cwd = config.getTargetDir();
3071
- if (/\.qwen[\\/]worktrees[\\/]/.test(cwd)) {
3072
- throw new Error(
3073
- `agent({isolation:'worktree'}): parent is already inside a worktree (${cwd}). Nested isolation worktrees are not supported \u2014 the subagent's inherited paths would still reference the outer worktree.`
3074
- );
3075
- }
3076
- const probe = new GitWorktreeService(cwd);
3077
- const gitCheck = await probe.checkGitAvailable();
3078
- if (!gitCheck.available) {
3079
- throw new Error(
3080
- `agent({isolation:'worktree'}): ${gitCheck.error ?? "git is not available"}.`
3081
- );
3082
- }
3083
- if (!await probe.isGitRepository()) {
3084
- throw new Error(
3085
- `agent({isolation:'worktree'}): ${cwd} is not a git repository.`
3086
- );
3087
- }
3088
- const projectRoot = await probe.getRepoTopLevel() ?? cwd;
3089
- const wtService = projectRoot === cwd ? probe : new GitWorktreeService(projectRoot);
3090
- let parentDirty = false;
3091
- try {
3092
- parentDirty = await wtService.hasWorktreeChanges(projectRoot);
3093
- } catch (error) {
3094
- debugLogger.warn(
3095
- `[Workflow] hasWorktreeChanges failed at ${projectRoot}: ${error}`
3096
- );
3097
- parentDirty = true;
3098
- }
3099
- if (parentDirty) {
3100
- throw new Error(
3101
- `agent({isolation:'worktree'}): parent working tree at ${projectRoot} has uncommitted changes that would not propagate into the isolated worktree. The subagent would see the prior HEAD instead of the current state. Commit or stash the changes, then re-run.`
3102
- );
3103
- }
3104
- const slug = generateAgentWorktreeSlug();
3105
- let parentBranch;
3106
- try {
3107
- parentBranch = await wtService.getCurrentBranch();
3108
- } catch (error) {
3109
- debugLogger.warn(
3110
- `[Workflow] getCurrentBranch failed at ${projectRoot}: ${error}`
3111
- );
3112
- }
3113
- const created = await wtService.createUserWorktree(slug, parentBranch, {
3114
- symlinkDirectories: config.getWorktreeSymlinkDirectories()
3115
- });
3116
- if (!created.success || !created.worktree) {
3117
- throw new Error(
3118
- `agent({isolation:'worktree'}): failed to create worktree: ${created.error ?? "unknown error"}.`
3119
- );
3120
- }
3121
- try {
3122
- await writeWorktreeSessionMarker(
3123
- created.worktree.path,
3124
- config.getSessionId()
3125
- );
3126
- } catch (error) {
3127
- debugLogger.warn(
3128
- `[Workflow] failed to write session marker at ${created.worktree.path}: ${error}`
3129
- );
3130
- }
3131
- return {
3132
- slug,
3133
- path: created.worktree.path,
3134
- branch: created.worktree.branch,
3135
- repoRoot: projectRoot
3136
- };
3137
- }
3138
- __name(provisionWorkflowWorktree, "provisionWorkflowWorktree");
3139
- async function cleanupWorkflowWorktree(isolation) {
3140
- const wtService = new GitWorktreeService(isolation.repoRoot);
3141
- const [hasChanges, hasUnmerged] = await Promise.all([
3142
- wtService.hasWorktreeChanges(isolation.path).catch((error) => {
3143
- debugLogger.warn(
3144
- `[Workflow] hasWorktreeChanges failed for ${isolation.path}: ${error}`
3145
- );
3146
- return true;
3147
- }),
3148
- wtService.hasUnmergedWorktreeCommits(isolation.slug).catch((error) => {
3149
- debugLogger.warn(
3150
- `[Workflow] hasUnmergedWorktreeCommits failed for ${isolation.slug}: ${error}`
3151
- );
3152
- return true;
3153
- })
3154
- ]);
3155
- if (hasChanges || hasUnmerged) {
3156
- debugLogger.info(
3157
- `[Workflow] Preserving isolation worktree ${isolation.path} (branch ${isolation.branch}, hasChanges=${hasChanges}, hasUnmerged=${hasUnmerged})`
3158
- );
3159
- return { path: isolation.path, branch: isolation.branch };
3160
- }
3161
- try {
3162
- const result = await wtService.removeUserWorktree(isolation.slug, {
3163
- deleteBranch: true
3164
- });
3165
- if (!result.success) {
3166
- debugLogger.warn(
3167
- `[Workflow] Failed to remove ephemeral worktree ${isolation.path}: ${result.error}`
3168
- );
3169
- return { path: isolation.path, branch: isolation.branch };
3170
- }
3171
- if (result.branchPreserved) {
3172
- debugLogger.warn(
3173
- `[Workflow] Removed worktree directory ${isolation.path} but kept branch ${isolation.branch} (unmerged commits at delete time)`
3174
- );
3175
- return { branch: isolation.branch };
3176
- }
3177
- } catch (error) {
3178
- debugLogger.warn(
3179
- `[Workflow] Failed to remove ephemeral worktree ${isolation.path}: ${error}`
3180
- );
3181
- return { path: isolation.path, branch: isolation.branch };
3182
- }
3183
- return null;
3184
- }
3185
- __name(cleanupWorkflowWorktree, "cleanupWorkflowWorktree");
3186
- function appendWorktreePreservedSuffix(finalText, preserved) {
3187
- const sep2 = finalText.endsWith("\n") ? "\n" : "\n\n";
3188
- if (preserved.path) {
3189
- return `${finalText}${sep2}[worktree preserved: ${preserved.path} (branch ${preserved.branch})]`;
3190
- }
3191
- return `${finalText}${sep2}[worktree directory removed; branch ${preserved.branch} preserved \u2014 recover with \`git worktree add <path> ${preserved.branch}\`]`;
3192
- }
3193
- __name(appendWorktreePreservedSuffix, "appendWorktreePreservedSuffix");
3194
- function createSchemaModeState() {
3195
- return {
3196
- result: null,
3197
- attempts: 0,
3198
- pendingArgs: /* @__PURE__ */ new Map(),
3199
- abortController: new AbortController()
3200
- };
3201
- }
3202
- __name(createSchemaModeState, "createSchemaModeState");
3203
- function attachSchemaListeners(emitter, state) {
3204
- const targetTool = ToolNames.STRUCTURED_OUTPUT;
3205
- emitter.on("tool_call" /* TOOL_CALL */, (evt) => {
3206
- if (evt.name !== targetTool) return;
3207
- state.pendingArgs.set(evt.callId, evt.args);
3208
- });
3209
- emitter.on("tool_result" /* TOOL_RESULT */, (evt) => {
3210
- if (evt.name !== targetTool) return;
3211
- const args = state.pendingArgs.get(evt.callId);
3212
- state.pendingArgs.delete(evt.callId);
3213
- if (evt.success) {
3214
- if (args !== void 0 && state.result === null) {
3215
- state.result = args;
3216
- state.abortController.abort();
3217
- }
3218
- return;
3219
- }
3220
- state.attempts += 1;
3221
- if (state.attempts > 2 && state.result === null) {
3222
- state.abortController.abort();
3223
- }
3224
- });
3225
- }
3226
- __name(attachSchemaListeners, "attachSchemaListeners");
3227
- async function createSchemaConfigOverride(base, schema) {
3228
- const override = deriveConfig(base);
3229
- installSessionWorkflowRevisionWriteThrough(override, base);
3230
- await rebuildToolRegistryOnOverride(override, base);
3231
- const registry = override.getToolRegistry();
3232
- registry.registerTool(new SyntheticOutputTool(schema));
3233
- return override;
3234
- }
3235
- __name(createSchemaConfigOverride, "createSchemaConfigOverride");
3236
- var WorkflowOrchestrator = class {
3237
- constructor(dispatch) {
3238
- this.dispatch = dispatch;
3239
- }
3240
- static {
3241
- __name(this, "WorkflowOrchestrator");
3242
- }
3243
- async run(req) {
3244
- const runId = req.runId ?? generateRunId();
3245
- const maxAgents = resolveMaxAgentsPerRun();
3246
- const signal = req.abortOnTimeout?.signal;
3247
- const scheduler = req.scheduler ?? new WorkflowDispatchScheduler(resolveConcurrencyLimit(), signal);
3248
- const rejectThroughPauseGate = /* @__PURE__ */ __name((error) => scheduler.waitUntilRunning().then(
3249
- () => {
3250
- throw error;
3251
- },
3252
- () => {
3253
- throw error;
3254
- }
3255
- ), "rejectThroughPauseGate");
3256
- let agentCount = 0;
3257
- let dispatchTraceCount = 0;
3258
- const emitter = req.emitter;
3259
- const budget = req.budget;
3260
- const dependencyContext = new AsyncLocalStorage();
3261
- const issueDispatchTrace = /* @__PURE__ */ __name((prompt, opts, cached = false) => {
3262
- const id = `dispatch-${dispatchTraceCount += 1}`;
3263
- const store = dependencyContext.getStore();
3264
- const dependsOn = Array.from(new Set(store?.tails ?? []));
3265
- if (store) store.tails = [id];
3266
- try {
3267
- emitter?.dispatchQueued?.({
3268
- id,
3269
- ...typeof opts.label === "string" ? { label: opts.label } : {},
3270
- prompt,
3271
- dependsOn,
3272
- queuedAt: Date.now(),
3273
- ...cached ? { cached: true } : {}
3274
- });
3275
- } catch (e) {
3276
- debugLogger.warn("emitter.dispatchQueued threw:", e);
3277
- }
3278
- return id;
3279
- }, "issueDispatchTrace");
3280
- const journal = req.journal;
3281
- const replay = req.resumeReplay;
3282
- let prefixHash = deriveArgsSeed(req.args);
3283
- let hadMiss = false;
3284
- let journalAgentId = 0;
3285
- const parentSandboxRef = {
3286
- current: void 0
3287
- };
3288
- const countedDispatch = /* @__PURE__ */ __name((prompt, opts) => {
3289
- if (typeof prompt !== "string" || prompt.length === 0) {
3290
- return rejectThroughPauseGate(
3291
- new Error("agent() requires a non-empty string prompt.")
3292
- );
3293
- }
3294
- let journalKey;
3295
- let journalEntryId;
3296
- let respawnLine;
3297
- if (journal) {
3298
- journalKey = deriveAgentKey(prefixHash, prompt, opts);
3299
- prefixHash = journalKey;
3300
- if (!hadMiss && replay) {
3301
- const cached = replay.results.get(journalKey);
3302
- if (cached !== void 0) {
3303
- const respawns = replay.started.get(journalKey);
3304
- if (respawns && respawns.length > 0) {
3305
- debugLogger.info(
3306
- `[Workflow] resume cache hit after ${respawns.length} prior respawn(s) for runId=${runId}.`
3307
- );
3308
- }
3309
- const label2 = typeof opts.label === "string" ? opts.label : void 0;
3310
- const dispatchId2 = issueDispatchTrace(prompt, opts, true);
3311
- try {
3312
- emitter?.agentDispatched?.(label2);
3313
- } catch (e) {
3314
- debugLogger.warn("emitter.agentDispatched threw:", e);
3315
- }
3316
- try {
3317
- emitter?.agentCompleted?.(label2);
3318
- } catch (e) {
3319
- debugLogger.warn("emitter.agentCompleted threw:", e);
3320
- }
3321
- try {
3322
- emitter?.dispatchSettled?.(dispatchId2, void 0, Date.now());
3323
- } catch (e) {
3324
- debugLogger.warn("emitter.dispatchSettled threw:", e);
3325
- }
3326
- return scheduler.waitUntilRunning().then(
3327
- () => cached.result,
3328
- () => cached.result
3329
- );
3330
- }
3331
- }
3332
- const priorStarts = replay?.started.get(journalKey);
3333
- if (priorStarts && priorStarts.length > 0 && !replay?.results.has(journalKey)) {
3334
- const name = typeof opts.label === "string" ? `"${stripAnsiAndControl(opts.label)}"` : "an agent";
3335
- respawnLine = replay?.failed.has(journalKey) ? `[resume] re-running ${name}: it failed in the previous run` : `[resume] respawning ${name}: interrupted in a previous run (${priorStarts.length} prior attempt${priorStarts.length === 1 ? "" : "s"})`;
3336
- }
3337
- hadMiss = true;
3338
- }
3339
- if (budget && budget.total !== null && budget.remaining() <= 0) {
3340
- debugLogger.warn(
3341
- `[Workflow] budget gate refused dispatch at entry: runId=${runId} spent=${budget.spent()} total=${budget.total}`
3342
- );
3343
- return rejectThroughPauseGate(
3344
- new WorkflowBudgetExceededError(runId, budget.total, budget.spent())
3345
- );
3346
- }
3347
- if (agentCount >= maxAgents) {
3348
- return rejectThroughPauseGate(
3349
- new WorkflowAgentCapExceededError(maxAgents)
3350
- );
3351
- }
3352
- agentCount += 1;
3353
- if (journal && journalKey !== void 0) {
3354
- journalEntryId = String(journalAgentId += 1);
3355
- }
3356
- const label = typeof opts.label === "string" ? opts.label : void 0;
3357
- const dispatchId = issueDispatchTrace(prompt, opts);
3358
- try {
3359
- emitter?.agentDispatched?.(label);
3360
- } catch (e) {
3361
- debugLogger.warn("emitter.agentDispatched threw:", e);
3362
- }
3363
- let completionEmitted = false;
3364
- const emitCompletion = /* @__PURE__ */ __name((error) => {
3365
- if (completionEmitted) return;
3366
- completionEmitted = true;
3367
- const message = error === void 0 ? void 0 : error instanceof Error ? error.message : String(error);
3368
- try {
3369
- emitter?.agentCompleted?.(label, message);
3370
- } catch (e) {
3371
- debugLogger.warn("emitter.agentCompleted threw:", e);
3372
- }
3373
- try {
3374
- emitter?.dispatchSettled?.(dispatchId, message, Date.now());
3375
- } catch (e) {
3376
- debugLogger.warn("emitter.dispatchSettled threw:", e);
3377
- }
3378
- }, "emitCompletion");
3379
- return scheduler.run(async () => {
3380
- try {
3381
- try {
3382
- emitter?.dispatchStarted?.(dispatchId, Date.now());
3383
- } catch (e) {
3384
- debugLogger.warn("emitter.dispatchStarted threw:", e);
3385
- }
3386
- if (budget && budget.total !== null && budget.remaining() <= 0) {
3387
- debugLogger.warn(
3388
- `[Workflow] budget gate refused dispatch at slot-acquire: runId=${runId} spent=${budget.spent()} total=${budget.total}`
3389
- );
3390
- throw new WorkflowBudgetExceededError(
3391
- runId,
3392
- budget.total,
3393
- budget.spent()
3394
- );
3395
- }
3396
- if (journal && journalKey !== void 0 && journalEntryId !== void 0) {
3397
- journal.append({
3398
- type: "started",
3399
- key: journalKey,
3400
- agentId: journalEntryId
3401
- }).catch(
3402
- (e) => debugLogger.warn(`journal started-append failed: ${e}`)
3403
- );
3404
- }
3405
- if (respawnLine) {
3406
- parentSandboxRef.current?.appendLog(respawnLine);
3407
- try {
3408
- emitter?.resumeRespawn?.(respawnLine);
3409
- } catch (e) {
3410
- debugLogger.warn("emitter.resumeRespawn threw:", e);
3411
- }
3412
- }
3413
- const result = await this.dispatch(prompt, opts, dispatchId);
3414
- emitCompletion();
3415
- if (journal && journalKey !== void 0) {
3416
- journal.append({
3417
- type: "result",
3418
- key: journalKey,
3419
- agentId: journalEntryId ?? "",
3420
- result
3421
- }).catch(
3422
- (e) => debugLogger.warn(`journal result-append failed: ${e}`)
3423
- );
3424
- }
3425
- if (budget) {
3426
- try {
3427
- emitter?.budgetUpdated?.(budget.spent(), budget.total);
3428
- } catch (e) {
3429
- debugLogger.warn("emitter.budgetUpdated threw:", e);
3430
- }
3431
- }
3432
- return result;
3433
- } catch (err) {
3434
- emitCompletion(err);
3435
- if (budget) {
3436
- try {
3437
- emitter?.budgetUpdated?.(budget.spent(), budget.total);
3438
- } catch (e) {
3439
- debugLogger.warn("emitter.budgetUpdated threw:", e);
3440
- }
3441
- }
3442
- if (journal && journalKey !== void 0 && !signal?.aborted && !isWorkflowRunLevelError(err)) {
3443
- journal.append({
3444
- type: "failed",
3445
- key: journalKey,
3446
- agentId: journalEntryId ?? ""
3447
- }).catch(
3448
- (e) => debugLogger.warn(`journal failed-append failed: ${e}`)
3449
- );
3450
- }
3451
- if (signal?.aborted || isWorkflowRunLevelError(err)) throw err;
3452
- if (isWorkflowAgentFailedError(err)) {
3453
- debugLogger.warn(
3454
- `[Workflow] agent settled to null (${err.kind}): ${err.message}`
3455
- );
3456
- } else {
3457
- debugLogger.warn(
3458
- `[Workflow] agent settled to null: ${extractErrorMessage(err)}`
3459
- );
3460
- }
3461
- return null;
3462
- }
3463
- }).then(
3464
- // Resolve even if the gate aborts: a successful dispatch must not
3465
- // turn into a teardown rejection — for a fire-and-forget call the
3466
- // script never attached a handler, so the rejection would surface
3467
- // as a spurious process-level unhandledRejection alarm on a
3468
- // correctly-cancelled run.
3469
- (result) => scheduler.waitUntilRunning().then(
3470
- () => result,
3471
- () => result
3472
- ),
3473
- (error) => {
3474
- emitCompletion(error);
3475
- return scheduler.waitUntilRunning().then(
3476
- () => {
3477
- throw error;
3478
- },
3479
- () => {
3480
- throw error;
3481
- }
3482
- );
3483
- }
3484
- );
3485
- }, "countedDispatch");
3486
- const parallelImpl = makeParallelImpl(signal, dependencyContext);
3487
- const pipelineImpl = makePipelineImpl(signal, dependencyContext);
3488
- const resolveSavedWorkflow = req.resolveSavedWorkflow;
3489
- const workflowImpl = resolveSavedWorkflow ? async (nameOrRef, nestedArgs) => {
3490
- const resolved = await resolveSavedWorkflow(nameOrRef);
3491
- const nestedSandbox = createWorkflowSandbox({
3492
- args: nestedArgs,
3493
- runId,
3494
- dispatch: countedDispatch,
3495
- parallel: parallelImpl,
3496
- pipeline: pipelineImpl,
3497
- abortOnTimeout: req.abortOnTimeout,
3498
- emitter,
3499
- budget,
3500
- scheduler
3501
- // No `workflow` — single-level nesting limit.
3502
- });
3503
- try {
3504
- return await nestedSandbox.run(resolved.script);
3505
- } finally {
3506
- for (const line of nestedSandbox.getLogs()) {
3507
- parentSandboxRef.current?.appendLog(line);
3508
- }
3509
- }
3510
- } : void 0;
3511
- const sandbox = createWorkflowSandbox({
3512
- args: req.args,
3513
- maxWallClockMs: req.maxWallClockMs,
3514
- runId,
3515
- dispatch: countedDispatch,
3516
- parallel: parallelImpl,
3517
- pipeline: pipelineImpl,
3518
- workflow: workflowImpl,
3519
- abortOnTimeout: req.abortOnTimeout,
3520
- emitter,
3521
- budget,
3522
- scheduler
3523
- });
3524
- parentSandboxRef.current = sandbox;
3525
- try {
3526
- const result = await dependencyContext.run(
3527
- { tails: [] },
3528
- () => sandbox.run(req.script)
3529
- );
3530
- return {
3531
- runId,
3532
- result,
3533
- phases: sandbox.getPhases(),
3534
- logs: sandbox.getLogs(),
3535
- meta: sandbox.getMeta()
3536
- };
3537
- } catch (err) {
3538
- throw new WorkflowExecutionError(
3539
- extractErrorMessage(err),
3540
- sandbox.getPhases(),
3541
- sandbox.getLogs(),
3542
- sandbox.getMeta()
3543
- );
3544
- }
3545
- }
3546
- };
3547
- async function settleToNullArray(thunks, signal) {
3548
- const settled = await Promise.allSettled(
3549
- thunks.map((t) => Promise.resolve().then(t))
3550
- );
3551
- if (signal?.aborted)
3552
- throw new DOMException("Workflow run aborted.", "AbortError");
3553
- const visitedReasons = /* @__PURE__ */ new WeakSet();
3554
- const findRunFailureReason = /* @__PURE__ */ __name((reason) => {
3555
- if (reason === null || typeof reason !== "object") return void 0;
3556
- if (visitedReasons.has(reason)) return void 0;
3557
- visitedReasons.add(reason);
3558
- try {
3559
- if (reason.__wfRunFailure === true) {
3560
- return reason;
3561
- }
3562
- const errors = reason?.errors;
3563
- if (!Array.isArray(errors)) return void 0;
3564
- for (const error of errors) {
3565
- const runFailure = findRunFailureReason(error);
3566
- if (runFailure !== void 0) return runFailure;
3567
- }
3568
- } catch {
3569
- return void 0;
3570
- }
3571
- return void 0;
3572
- }, "findRunFailureReason");
3573
- for (const result of settled) {
3574
- if (result.status !== "rejected") continue;
3575
- const runFailure = findRunFailureReason(result.reason);
3576
- if (runFailure !== void 0) throw runFailure;
3577
- }
3578
- return settled.map((r, i) => {
3579
- if (r.status === "fulfilled") return r.value;
3580
- const reason = r.reason;
3581
- debugLogger.warn(
3582
- `Workflow thunk at index ${i} rejected: ${String(reason?.message ?? r.reason)}`
3583
- );
3584
- return null;
3585
- });
3586
- }
3587
- __name(settleToNullArray, "settleToNullArray");
3588
- function makeParallelImpl(signal, dependencyContext) {
3589
- return (thunks) => {
3590
- if (!Array.isArray(thunks)) {
3591
- return Promise.reject(
3592
- new Error(
3593
- "parallel() expects an array of thunks (functions returning promises)."
3594
- )
3595
- );
3596
- }
3597
- for (const t of thunks) {
3598
- if (typeof t !== "function") {
3599
- return Promise.reject(
3600
- new Error(
3601
- "parallel() expects an array of functions, not values \u2014 wrap each call: parallel([() => agent(...), () => agent(...)])."
3602
- )
3603
- );
3604
- }
3605
- }
3606
- const parent = dependencyContext.getStore();
3607
- const inheritedTails = parent?.tails ?? [];
3608
- const branches = thunks.map((thunk) => {
3609
- const store = { tails: [...inheritedTails] };
3610
- return {
3611
- store,
3612
- thunk: /* @__PURE__ */ __name(() => dependencyContext.run(store, thunk), "thunk")
3613
- };
3614
- });
3615
- return settleToNullArray(
3616
- branches.map(({ thunk }) => thunk),
3617
- signal
3618
- ).then((result) => {
3619
- if (parent && branches.length > 0) {
3620
- parent.tails = mergeFanoutTails(
3621
- parent.tails,
3622
- inheritedTails,
3623
- branches.flatMap(({ store }) => store.tails)
3624
- );
3625
- }
3626
- return result;
3627
- });
3628
- };
3629
- }
3630
- __name(makeParallelImpl, "makeParallelImpl");
3631
- function makePipelineImpl(signal, dependencyContext) {
3632
- return (items, ...stages) => {
3633
- if (!Array.isArray(items)) {
3634
- return Promise.reject(
3635
- new Error(
3636
- "pipeline() expects an array of items as its first argument."
3637
- )
3638
- );
3639
- }
3640
- for (const s of stages) {
3641
- if (typeof s !== "function") {
3642
- return Promise.reject(
3643
- new Error(
3644
- "pipeline() stages must be functions: pipeline(items, item => ..., result => ...)."
3645
- )
3646
- );
3647
- }
3648
- }
3649
- const parent = dependencyContext.getStore();
3650
- const inheritedTails = parent?.tails ?? [];
3651
- const branches = items.map((item, idx) => {
3652
- const store = { tails: [...inheritedTails] };
3653
- return {
3654
- store,
3655
- thunk: /* @__PURE__ */ __name(() => dependencyContext.run(
3656
- store,
3657
- () => runPipelineChain(item, idx, stages)
3658
- ), "thunk")
3659
- };
3660
- });
3661
- return settleToNullArray(
3662
- branches.map(({ thunk }) => thunk),
3663
- signal
3664
- ).then((result) => {
3665
- if (parent && branches.length > 0) {
3666
- parent.tails = mergeFanoutTails(
3667
- parent.tails,
3668
- inheritedTails,
3669
- branches.flatMap(({ store }) => store.tails)
3670
- );
3671
- }
3672
- return result;
3673
- });
3674
- };
3675
- }
3676
- __name(makePipelineImpl, "makePipelineImpl");
3677
- function mergeFanoutTails(currentParentTails, inheritedTails, branchTails) {
3678
- const inherited = new Set(inheritedTails);
3679
- const newBranchTails = branchTails.filter((tail) => !inherited.has(tail));
3680
- const merged = newBranchTails.length > 0 ? [
3681
- ...newBranchTails,
3682
- ...currentParentTails.filter((tail) => !inherited.has(tail))
3683
- ] : currentParentTails;
3684
- return Array.from(new Set(merged));
3685
- }
3686
- __name(mergeFanoutTails, "mergeFanoutTails");
3687
- async function runPipelineChain(item, idx, stages) {
3688
- let prev = item;
3689
- for (const stage of stages) {
3690
- if (prev === null) break;
3691
- prev = await stage(prev, item, idx);
3692
- }
3693
- return prev;
3694
- }
3695
- __name(runPipelineChain, "runPipelineChain");
3696
- function extractErrorMessage(err) {
3697
- if (err && typeof err === "object" && "message" in err) {
3698
- const m = err.message;
3699
- if (typeof m === "string") return m;
3700
- return String(m);
3701
- }
3702
- return String(err);
3703
- }
3704
- __name(extractErrorMessage, "extractErrorMessage");
3705
-
3706
- // packages/core/src/agents/workflow-snapshot.ts
3707
- init_esbuild_shims();
3708
- import { promises as fs3 } from "node:fs";
3709
- import path3 from "node:path";
3710
- var debugLogger6 = createDebugLogger("WORKFLOW_SNAPSHOT");
3711
- var MAX_RETAINED_SNAPSHOTS = 30;
3712
- function toSnapshot(task) {
3713
- if (!isTerminalWorkflowStatus(task.status)) {
3714
- throw new Error(`Cannot snapshot active workflow ${task.runId}.`);
3715
- }
3716
- return {
3717
- runId: task.runId,
3718
- ...task.toolUseId ? { toolUseId: task.toolUseId } : {},
3719
- description: task.description,
3720
- ...task.workflowName ? { workflowName: task.workflowName } : {},
3721
- sourceRunId: task.sourceRunId,
3722
- startMode: task.startMode,
3723
- meta: task.meta,
3724
- status: task.status,
3725
- script: task.script ?? "",
3726
- scriptPath: task.scriptPath,
3727
- phases: [...task.phases],
3728
- phaseVisits: task.phaseVisits.map((visit) => ({ ...visit })),
3729
- dispatches: task.dispatches.map((dispatch) => ({
3730
- ...dispatch,
3731
- dependsOn: [...dispatch.dependsOn]
3732
- })),
3733
- agentsDispatched: task.agentsDispatched,
3734
- agentsCompleted: task.agentsCompleted,
3735
- agentsRespawned: task.agentsRespawned ?? 0,
3736
- tokensSpent: task.tokensSpent,
3737
- tokenBudgetTotal: task.tokenBudgetTotal,
3738
- perPhaseTokens: Array.from(task.perPhaseTokens.entries()),
3739
- recentLogs: [...task.recentLogs],
3740
- events: task.events.map((event) => ({ ...event })),
3741
- startTime: task.startTime,
3742
- endTime: task.endTime,
3743
- result: safeResult(task.result),
3744
- error: task.error
3745
- };
3746
- }
3747
- __name(toSnapshot, "toSnapshot");
3748
- function safeResult(result) {
3749
- if (result === void 0) return void 0;
3750
- try {
3751
- JSON.stringify(result);
3752
- return result;
3753
- } catch {
3754
- return `(non-JSON-serializable ${typeof result})`;
3755
- }
3756
- }
3757
- __name(safeResult, "safeResult");
3758
- async function writeWorkflowSnapshot(config, task) {
3759
- const storage = config.storage;
3760
- if (!storage) return false;
3761
- try {
3762
- const snapshot = toSnapshot(task);
3763
- const dir = storage.getWorkflowRunsDir();
3764
- await fs3.mkdir(dir, { recursive: true });
3765
- await fs3.writeFile(
3766
- storage.getWorkflowRunSnapshotPath(task.runId),
3767
- JSON.stringify(snapshot, null, 2),
3768
- "utf8"
3769
- );
3770
- await pruneSnapshots(config, dir);
3771
- return true;
3772
- } catch (e) {
3773
- debugLogger6.warn(`writeWorkflowSnapshot failed for ${task.runId}: ${e}`);
3774
- return false;
3775
- }
3776
- }
3777
- __name(writeWorkflowSnapshot, "writeWorkflowSnapshot");
3778
- async function listWorkflowSnapshots(config) {
3779
- const storage = config.storage;
3780
- if (!storage) return [];
3781
- const dir = storage.getWorkflowRunsDir();
3782
- let files;
3783
- try {
3784
- files = (await fs3.readdir(dir)).filter((f) => f.endsWith(".json"));
3785
- } catch {
3786
- return [];
3787
- }
3788
- const snapshots = [];
3789
- for (const file of files) {
3790
- try {
3791
- const raw = await fs3.readFile(`${dir}/${file}`, "utf8");
3792
- const parsed = JSON.parse(raw);
3793
- if (!isWorkflowSnapshot(parsed)) {
3794
- debugLogger6.warn(`skipping invalid workflow snapshot ${file}`);
3795
- continue;
3796
- }
3797
- snapshots.push(parsed);
3798
- } catch (e) {
3799
- debugLogger6.warn(`skipping unparseable snapshot ${file}: ${e}`);
3800
- }
3801
- }
3802
- snapshots.sort((a, b) => (b.startTime ?? 0) - (a.startTime ?? 0));
3803
- return snapshots;
3804
- }
3805
- __name(listWorkflowSnapshots, "listWorkflowSnapshots");
3806
- async function deleteWorkflowSnapshot(config, runId) {
3807
- const storage = config.storage;
3808
- if (!storage || !/^wf_[0-9a-f]+$/.test(runId)) return false;
3809
- try {
3810
- await fs3.rm(path3.dirname(storage.getWorkflowRunJournalPath(runId)), {
3811
- recursive: true,
3812
- force: true
3813
- });
3814
- } catch (error) {
3815
- debugLogger6.warn(`delete workflow journal failed for ${runId}: ${error}`);
3816
- return false;
3817
- }
3818
- if (!await deleteInlineWorkflowScript(config, runId)) return false;
3819
- try {
3820
- await fs3.unlink(storage.getWorkflowRunSnapshotPath(runId));
3821
- } catch (error) {
3822
- if (error.code !== "ENOENT") {
3823
- debugLogger6.warn(`deleteWorkflowSnapshot failed for ${runId}: ${error}`);
3824
- return false;
3825
- }
3826
- }
3827
- return true;
3828
- }
3829
- __name(deleteWorkflowSnapshot, "deleteWorkflowSnapshot");
3830
- function isRecord(value) {
3831
- return typeof value === "object" && value !== null && !Array.isArray(value);
3832
- }
3833
- __name(isRecord, "isRecord");
3834
- function isFiniteNumber(value) {
3835
- return typeof value === "number" && Number.isFinite(value);
3836
- }
3837
- __name(isFiniteNumber, "isFiniteNumber");
3838
- function isOptionalString(value) {
3839
- return value === void 0 || typeof value === "string";
3840
- }
3841
- __name(isOptionalString, "isOptionalString");
3842
- function isStringArray(value) {
3843
- return Array.isArray(value) && value.every((item) => typeof item === "string");
3844
- }
3845
- __name(isStringArray, "isStringArray");
3846
- function isWorkflowMeta(value) {
3847
- if (value === null) return true;
3848
- if (!isRecord(value)) return false;
3849
- if (typeof value["name"] !== "string" || typeof value["description"] !== "string" || !isOptionalString(value["whenToUse"])) {
3850
- return false;
3851
- }
3852
- const phases = value["phases"];
3853
- return phases === void 0 || Array.isArray(phases) && phases.every(
3854
- (phase) => isRecord(phase) && typeof phase["title"] === "string" && isOptionalString(phase["detail"]) && isOptionalString(phase["model"])
3855
- );
3856
- }
3857
- __name(isWorkflowMeta, "isWorkflowMeta");
3858
- function isWorkflowPhaseVisit(value) {
3859
- return isRecord(value) && typeof value["id"] === "string" && isFiniteNumber(value["index"]) && typeof value["title"] === "string" && isFiniteNumber(value["startedAt"]) && (value["endedAt"] === void 0 || isFiniteNumber(value["endedAt"]));
3860
- }
3861
- __name(isWorkflowPhaseVisit, "isWorkflowPhaseVisit");
3862
- function isWorkflowDispatch(value) {
3863
- if (!isRecord(value)) return false;
3864
- const status = value["status"];
3865
- return typeof value["id"] === "string" && (value["phaseVisitId"] === null || typeof value["phaseVisitId"] === "string") && typeof value["label"] === "string" && typeof value["prompt"] === "string" && isOptionalString(value["subagentId"]) && (status === "queued" || status === "running" || status === "completed" || status === "failed" || status === "cancelled" || status === "cached") && isStringArray(value["dependsOn"]) && isFiniteNumber(value["queuedAt"]) && (value["startedAt"] === void 0 || isFiniteNumber(value["startedAt"])) && (value["endedAt"] === void 0 || isFiniteNumber(value["endedAt"])) && isOptionalString(value["error"]);
3866
- }
3867
- __name(isWorkflowDispatch, "isWorkflowDispatch");
3868
- function hasOnlyKeys(value, keys) {
3869
- const allowed = new Set(keys);
3870
- return Object.keys(value).every((key) => allowed.has(key));
3871
- }
3872
- __name(hasOnlyKeys, "hasOnlyKeys");
3873
- function isWorkflowEvent(value) {
3874
- if (!isRecord(value) || typeof value["id"] !== "string" || !isFiniteNumber(value["at"]) || typeof value["type"] !== "string") {
3875
- return false;
3876
- }
3877
- const base = ["id", "type", "at"];
3878
- switch (value["type"]) {
3879
- case "phase-started":
3880
- return hasOnlyKeys(value, [...base, "phaseVisitId", "title"]) && typeof value["phaseVisitId"] === "string" && typeof value["title"] === "string";
3881
- case "phase-completed":
3882
- return hasOnlyKeys(value, [...base, "phaseVisitId"]) && typeof value["phaseVisitId"] === "string";
3883
- case "dispatch-queued":
3884
- case "dispatch-started":
3885
- case "dispatch-completed":
3886
- case "dispatch-cancelled":
3887
- case "dispatch-cached":
3888
- return hasOnlyKeys(value, [...base, "dispatchId"]) && typeof value["dispatchId"] === "string";
3889
- case "dispatch-failed":
3890
- return hasOnlyKeys(value, [...base, "dispatchId", "error"]) && typeof value["dispatchId"] === "string" && typeof value["error"] === "string";
3891
- case "log":
3892
- return hasOnlyKeys(value, [...base, "message"]) && typeof value["message"] === "string";
3893
- case "approval-requested":
3894
- case "approval-settled":
3895
- return hasOnlyKeys(value, [...base, "name", "dispatchId"]) && typeof value["name"] === "string" && isOptionalString(value["dispatchId"]);
3896
- case "workflow-completed":
3897
- case "workflow-cancelled":
3898
- return hasOnlyKeys(value, base);
3899
- case "workflow-failed":
3900
- return hasOnlyKeys(value, [...base, "error"]) && typeof value["error"] === "string";
3901
- default:
3902
- return false;
3903
- }
3904
- }
3905
- __name(isWorkflowEvent, "isWorkflowEvent");
3906
- function isWorkflowSnapshot(value) {
3907
- if (!isRecord(value)) return false;
3908
- const status = value["status"];
3909
- const phaseVisits = value["phaseVisits"];
3910
- const dispatches = value["dispatches"];
3911
- const events = value["events"];
3912
- const perPhaseTokens = value["perPhaseTokens"];
3913
- return typeof value["runId"] === "string" && value["runId"].length > 0 && isOptionalString(value["toolUseId"]) && isOptionalString(value["description"]) && isOptionalString(value["workflowName"]) && isOptionalString(value["sourceRunId"]) && (value["startMode"] === void 0 || value["startMode"] === "retry" || value["startMode"] === "rerun") && isWorkflowMeta(value["meta"]) && (status === "completed" || status === "failed" || status === "cancelled") && typeof value["script"] === "string" && isOptionalString(value["scriptPath"]) && isStringArray(value["phases"]) && (phaseVisits === void 0 || Array.isArray(phaseVisits) && phaseVisits.every(isWorkflowPhaseVisit)) && (dispatches === void 0 || Array.isArray(dispatches) && dispatches.every(isWorkflowDispatch)) && (events === void 0 || Array.isArray(events) && events.every(isWorkflowEvent)) && isFiniteNumber(value["agentsDispatched"]) && isFiniteNumber(value["agentsCompleted"]) && (value["agentsRespawned"] === void 0 || isFiniteNumber(value["agentsRespawned"])) && isFiniteNumber(value["tokensSpent"]) && (value["tokenBudgetTotal"] === null || isFiniteNumber(value["tokenBudgetTotal"])) && Array.isArray(perPhaseTokens) && perPhaseTokens.every(
3914
- (entry) => Array.isArray(entry) && entry.length === 2 && (entry[0] === null || typeof entry[0] === "string") && isFiniteNumber(entry[1])
3915
- ) && isStringArray(value["recentLogs"]) && isFiniteNumber(value["startTime"]) && (value["endTime"] === void 0 || isFiniteNumber(value["endTime"])) && isOptionalString(value["error"]);
3916
- }
3917
- __name(isWorkflowSnapshot, "isWorkflowSnapshot");
3918
- async function pruneSnapshots(config, dir) {
3919
- let files;
3920
- try {
3921
- files = (await fs3.readdir(dir)).filter((f) => f.endsWith(".json"));
3922
- } catch {
3923
- return;
3924
- }
3925
- if (files.length <= MAX_RETAINED_SNAPSHOTS) return;
3926
- const stats = await Promise.all(
3927
- files.map(async (f) => {
3928
- try {
3929
- const s = await fs3.stat(`${dir}/${f}`);
3930
- return { f, mtime: s.mtimeMs };
3931
- } catch {
3932
- return { f, mtime: 0 };
3933
- }
3934
- })
3935
- );
3936
- stats.sort((a, b) => a.mtime - b.mtime);
3937
- const toPrune = stats.slice(0, stats.length - MAX_RETAINED_SNAPSHOTS);
3938
- const registry = config.getWorkflowRunRegistry?.();
3939
- const protectedRunIds = /* @__PURE__ */ new Set([
3940
- ...(registry?.list() ?? []).filter((entry) => isActiveWorkflowStatus(entry.status)).map((entry) => entry.runId),
3941
- ...registry?.listStartingRunIds() ?? []
3942
- ]);
3943
- await Promise.all(
3944
- toPrune.map((s) => {
3945
- const runId = s.f.replace(/\.json$/, "");
3946
- const isRunDir = /^wf_[0-9a-f]+$/.test(runId);
3947
- const deleteArtifacts = isRunDir && !protectedRunIds.has(runId) && !isWorkflowRunPersistenceActive(config, runId);
3948
- return Promise.all([
3949
- fs3.unlink(`${dir}/${s.f}`).catch(
3950
- (e) => debugLogger6.warn(`prune unlink failed for ${s.f}: ${e}`)
3951
- ),
3952
- ...deleteArtifacts ? [
3953
- fs3.rm(
3954
- path3.dirname(config.storage.getWorkflowRunJournalPath(runId)),
3955
- { recursive: true, force: true }
3956
- ).catch(
3957
- (e) => debugLogger6.warn(
3958
- `prune journal dir failed for ${runId}: ${e}`
3959
- )
3960
- ),
3961
- deleteInlineWorkflowScript(config, runId)
3962
- ] : []
3963
- ]);
3964
- })
3965
- );
3966
- }
3967
- __name(pruneSnapshots, "pruneSnapshots");
3968
-
3969
- // packages/core/src/skills/workflow-authoring-skill.ts
3970
- init_esbuild_shims();
3971
- import { readFileSync } from "node:fs";
3972
- import * as path4 from "node:path";
3973
- var debugLogger7 = createDebugLogger("WORKFLOW_AUTHORING_SKILL");
3974
- var WORKFLOW_AUTHORING_SKILL_NAME = "workflow-authoring";
3975
- var cachedReference;
3976
- function referencePath() {
3977
- return path4.join(
3978
- resolveBundleDir(import.meta.url),
3979
- "bundled",
3980
- WORKFLOW_AUTHORING_SKILL_NAME,
3981
- "SKILL.md"
3982
- );
3983
- }
3984
- __name(referencePath, "referencePath");
3985
- function readWorkflowAuthoringReference() {
3986
- if (cachedReference !== void 0) return cachedReference;
3987
- try {
3988
- const filePath = referencePath();
3989
- const parsed = parseSkillContent(readFileSync(filePath, "utf8"), filePath);
3990
- cachedReference = { body: parsed.body, baseDir: path4.dirname(filePath) };
3991
- } catch (error) {
3992
- debugLogger7.warn(`cannot read the workflow-authoring reference: ${error}`);
3993
- cachedReference = null;
3994
- }
3995
- return cachedReference;
3996
- }
3997
- __name(readWorkflowAuthoringReference, "readWorkflowAuthoringReference");
3998
- function resolveWorkflowAuthoringRoute(config) {
3999
- try {
4000
- if (config.getDisabledSkillLevels?.()?.has("bundled")) return "withheld";
4001
- if (config.isSkillEnabled?.({
4002
- name: WORKFLOW_AUTHORING_SKILL_NAME,
4003
- level: "bundled"
4004
- }) === false) {
4005
- return "withheld";
4006
- }
4007
- if (!config.getSkillManager?.()) return "inline";
4008
- const registry = config.getToolRegistry?.();
4009
- const toolNames = registry?.getAllToolNames?.();
4010
- if (!Array.isArray(toolNames)) return "skill";
4011
- if (!toolNames.includes(ToolNames.SKILL)) return "inline";
4012
- if (isToolDeferredBehindToolSearch(config, ToolNames.SKILL)) {
4013
- return toolNames.includes(ToolNames.TOOL_SEARCH) ? "skill-via-tool-search" : "inline";
4014
- }
4015
- return "skill";
4016
- } catch (error) {
4017
- debugLogger7.warn(`cannot resolve the workflow-authoring route: ${error}`);
4018
- return "skill";
4019
- }
4020
- }
4021
- __name(resolveWorkflowAuthoringRoute, "resolveWorkflowAuthoringRoute");
4022
- function resolveWorkflowAuthoringSurface(config) {
4023
- const route = resolveWorkflowAuthoringRoute(config);
4024
- switch (route) {
4025
- case "skill":
4026
- return "pointer";
4027
- case "skill-via-tool-search":
4028
- return "pointer-via-tool-search";
4029
- case "withheld":
4030
- return "withheld";
4031
- case "inline":
4032
- return readWorkflowAuthoringReference() ? "inline" : "pointer";
4033
- default: {
4034
- const unhandled = route;
4035
- return unhandled;
4036
- }
4037
- }
4038
- }
4039
- __name(resolveWorkflowAuthoringSurface, "resolveWorkflowAuthoringSurface");
4040
- function isToolDeferredBehindToolSearch(config, name) {
4041
- if (!config.getToolRegistry?.()?.isPermissionDeferred?.(name)) return false;
4042
- return !config.getVisibleTools?.()?.has(name);
4043
- }
4044
- __name(isToolDeferredBehindToolSearch, "isToolDeferredBehindToolSearch");
4045
- function isToolHiddenBehindToolSearch(config, name) {
4046
- if (!isToolDeferredBehindToolSearch(config, name)) return false;
4047
- return !config.getToolRegistry?.()?.isDeferredToolRevealed?.(name);
4048
- }
4049
- __name(isToolHiddenBehindToolSearch, "isToolHiddenBehindToolSearch");
4050
- function toolSearchRevealSentence(toolDisplayName) {
4051
- return `If the ${toolDisplayName} tool is not in your tool list, reveal it with ToolSearch first.`;
4052
- }
4053
- __name(toolSearchRevealSentence, "toolSearchRevealSentence");
4054
-
4055
- // packages/core/src/agents/runtime/review-workflow.ts
4056
- init_esbuild_shims();
4057
- import { createHash as createHash2 } from "node:crypto";
4058
- import { promises as fs4 } from "node:fs";
4059
- import path5 from "node:path";
4060
- var debugLogger8 = createDebugLogger("REVIEW_WORKFLOW");
4061
- function resolveReviewWorkflowConcurrency(env = process.env) {
4062
- const configured = parsePositiveIntegerEnv(env[MAX_WORKFLOW_CONCURRENCY_ENV], 0) || parsePositiveIntegerEnv(env["QWEN_CODE_MAX_TOOL_CONCURRENCY"], 10);
4063
- return resolveConcurrencyLimit({
4064
- [MAX_WORKFLOW_CONCURRENCY_ENV]: String(configured)
4065
- });
4066
- }
4067
- __name(resolveReviewWorkflowConcurrency, "resolveReviewWorkflowConcurrency");
4068
- async function resolveReviewWorkflowLimits(scriptPath, generatedDir, scriptContent, env = process.env, nowMs = Date.now()) {
4069
- let canonicalScript;
4070
- try {
4071
- if ((await fs4.lstat(generatedDir)).isSymbolicLink()) return void 0;
4072
- const generatedRoot = await fs4.realpath(generatedDir);
4073
- canonicalScript = await fs4.realpath(scriptPath);
4074
- if (!canonicalScript.startsWith(path5.join(generatedRoot, "review") + path5.sep)) {
4075
- return void 0;
4076
- }
4077
- } catch (error) {
4078
- if (error.code !== "ENOENT") {
4079
- debugLogger8.warn(
4080
- "Cannot classify review workflow; using generic limits:",
4081
- error
4082
- );
4083
- }
4084
- return void 0;
4085
- }
4086
- const digest = /^qwen-review-[a-f0-9]{10}-([a-f0-9]{64})\.js$/.exec(
4087
- path5.basename(canonicalScript)
4088
- )?.[1];
4089
- if (!digest || createHash2("sha256").update(scriptContent).digest("hex") !== digest) {
4090
- return void 0;
4091
- }
4092
- const seconds = Number(env["QWEN_CODE_MAX_WORKFLOW_SECONDS"]);
4093
- let maxWallClockMs = (Number.isFinite(seconds) && seconds > 0 ? seconds : 6 * 60 * 60) * 1e3;
4094
- const deadline = Number(env["QWEN_REVIEW_DEADLINE_EPOCH"]);
4095
- if (Number.isFinite(deadline) && deadline > 0) {
4096
- const rawFloor = env["QWEN_REVIEW_DEADLINE_COMPOSE_FLOOR_SECONDS"];
4097
- const floor = Number(rawFloor);
4098
- const floorSeconds = rawFloor?.trim() && Number.isFinite(floor) && floor >= 0 ? floor : 1200;
4099
- const remainingMs = deadline * 1e3 - nowMs - floorSeconds * 1e3;
4100
- if (remainingMs <= 0) {
4101
- throw new Error(
4102
- "Review workflow was not launched: the review deadline has reached the compose reserve floor. Recover completed findings and compose now."
4103
- );
4104
- }
4105
- maxWallClockMs = Math.min(maxWallClockMs, remainingMs);
4106
- }
4107
- return {
4108
- subagent: {
4109
- max_turns: resolveSubagentMaxTurns(env, 500),
4110
- max_time_minutes: resolveSubagentMaxTimeMinutes(env, 100)
4111
- },
4112
- concurrency: resolveReviewWorkflowConcurrency(env),
4113
- maxWallClockMs
4114
- };
4115
- }
4116
- __name(resolveReviewWorkflowLimits, "resolveReviewWorkflowLimits");
4117
-
4118
- export {
4119
- extractAndStripMeta,
4120
- compileWorkflowScript,
4121
- describeWorkflowCompileError,
4122
- MAX_TOKENS_PER_WORKFLOW_ENV,
4123
- resolveMaxTokensPerWorkflow,
4124
- WorkflowBudgetImpl,
4125
- validateWorkflowName,
4126
- isSymlinkedRoot,
4127
- listSavedWorkflows,
4128
- resolveSavedWorkflowScript,
4129
- saveWorkflowScript,
4130
- persistInlineWorkflowScript,
4131
- deleteInlineWorkflowScript,
4132
- WorkflowJournal,
4133
- WorkflowDispatchScheduler,
4134
- DEFAULT_MAX_AGENTS_PER_RUN,
4135
- MAX_WORKFLOW_AGENTS_ENV,
4136
- MAX_WORKFLOW_CONCURRENCY_ENV,
4137
- resolveConcurrencyLimit,
4138
- DEFAULT_WORKFLOW_SUBAGENT_MAX_TURNS,
4139
- DEFAULT_WORKFLOW_SUBAGENT_MAX_TIME_MINUTES,
4140
- WORKFLOW_SUBAGENT_MAX_TURNS_ENV,
4141
- WORKFLOW_SUBAGENT_MAX_MINUTES_ENV,
4142
- WorkflowExecutionError,
4143
- createProductionDispatch,
4144
- WorkflowOrchestrator,
4145
- MAX_RETAINED_SNAPSHOTS,
4146
- toSnapshot,
4147
- writeWorkflowSnapshot,
4148
- listWorkflowSnapshots,
4149
- deleteWorkflowSnapshot,
4150
- resolveReviewWorkflowConcurrency,
4151
- resolveReviewWorkflowLimits,
4152
- WORKFLOW_AUTHORING_SKILL_NAME,
4153
- readWorkflowAuthoringReference,
4154
- resolveWorkflowAuthoringSurface,
4155
- isToolHiddenBehindToolSearch,
4156
- toolSearchRevealSentence
4157
- };
4158
- /**
4159
- * @license
4160
- * Copyright 2025 Google LLC
4161
- * SPDX-License-Identifier: Apache-2.0
4162
- */
4163
- /**
4164
- * @license
4165
- * Copyright 2025 Qwen
4166
- * SPDX-License-Identifier: Apache-2.0
4167
- */
4168
- /**
4169
- * @license
4170
- * Copyright 2026 Qwen Team
4171
- * SPDX-License-Identifier: Apache-2.0
4172
- */