@qwen-code/qwen-code 0.19.8 → 0.19.9-nightly.20260714.9dd8389eb

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 (449) hide show
  1. package/bundled/qc-helper/SKILL.md +1 -0
  2. package/bundled/qc-helper/docs/configuration/auth.md +40 -55
  3. package/bundled/qc-helper/docs/configuration/model-providers.md +224 -218
  4. package/bundled/qc-helper/docs/configuration/settings.md +61 -51
  5. package/bundled/qc-helper/docs/features/_meta.ts +1 -0
  6. package/bundled/qc-helper/docs/features/channels/dingtalk.md +12 -2
  7. package/bundled/qc-helper/docs/features/channels/overview.md +82 -7
  8. package/bundled/qc-helper/docs/features/channels/wecom.md +6 -0
  9. package/bundled/qc-helper/docs/features/code-review.md +109 -41
  10. package/bundled/qc-helper/docs/features/commands.md +45 -44
  11. package/bundled/qc-helper/docs/features/computer-use.md +77 -0
  12. package/bundled/qc-helper/docs/features/hooks.md +29 -0
  13. package/bundled/qc-helper/docs/features/tool-use-summaries.md +19 -23
  14. package/bundled/qc-helper/docs/integration-vscode.md +2 -2
  15. package/bundled/qc-helper/docs/qwen-serve.md +60 -22
  16. package/bundled/qc-helper/docs/reference/keyboard-shortcuts.md +2 -2
  17. package/bundled/review/DESIGN.md +303 -46
  18. package/bundled/review/SKILL.md +658 -165
  19. package/chunks/MaxSizedBox-QAYHOC4F.js +71 -0
  20. package/chunks/{StandaloneSessionPicker-EYRGH6PJ.js → StandaloneSessionPicker-D3R6YYX3.js} +82 -79
  21. package/chunks/{acpAgent-GRFTTRHW.js → acpAgent-ENHBW72A.js} +1178 -421
  22. package/chunks/agent-57LX4KMG.js +69 -0
  23. package/chunks/agent-headless-AC6EVNAP.js +63 -0
  24. package/chunks/{anthropicContentGenerator-CPF22MA7.js → anthropicContentGenerator-56U3YCP2.js} +187 -31
  25. package/chunks/{artifact-tool-D233YJFH.js → artifact-tool-BWZZJ42H.js} +5 -5
  26. package/chunks/{askUserQuestion-MKL5ZTMC.js → askUserQuestion-WU3S5A5T.js} +6 -6
  27. package/chunks/bridge-4OZH44MK.js +79 -0
  28. package/chunks/{ca-MKD32FQL.js → ca-C2JTT2N5.js} +68 -6
  29. package/chunks/channel-worker-group-K7QKH6IG.js +13 -0
  30. package/chunks/channel-worker-manager-5RWKSGEU.js +418 -0
  31. package/chunks/channel-worker-supervisor-PCDAZN4D.js +20 -0
  32. package/chunks/{chunk-CSOTA7KX.js → chunk-2FO5GFKZ.js} +2 -2
  33. package/chunks/{chunk-QQDPRDVW.js → chunk-2HRYPZT5.js} +1 -1
  34. package/chunks/{chunk-I6WGFJJ3.js → chunk-2MF6ICOL.js} +38 -12
  35. package/chunks/{chunk-X3YGAX7V.js → chunk-2UUAIFQO.js} +4 -2
  36. package/chunks/{chunk-2PSWA5ID.js → chunk-2X56YUSZ.js} +1 -1
  37. package/chunks/{chunk-NQKLOAVJ.js → chunk-2Z5UX4KI.js} +2 -2
  38. package/chunks/chunk-3MX7D6QN.js +516 -0
  39. package/chunks/{chunk-YDOXPLYL.js → chunk-4DYYRLIE.js} +3890 -975
  40. package/chunks/{chunk-OQXDAMKY.js → chunk-4FPUAYTT.js} +8 -8
  41. package/chunks/{chunk-55ZMG67I.js → chunk-4LD5APFL.js} +4 -4
  42. package/chunks/{chunk-YKZIAK7C.js → chunk-4LJNI7MU.js} +166 -37
  43. package/chunks/{chunk-BOBOCR5H.js → chunk-4QOPEEL2.js} +4 -4
  44. package/chunks/{chunk-UIDXQNMV.js → chunk-4WGODMVR.js} +1 -1
  45. package/chunks/{chunk-E6US47KI.js → chunk-4WKAA4KS.js} +1 -1
  46. package/chunks/{chunk-3GONHQOA.js → chunk-57OAHC2Y.js} +1 -1
  47. package/chunks/{chunk-JZSY4WP3.js → chunk-5DTTYNB7.js} +1 -1
  48. package/chunks/chunk-5HBA2Z7V.js +28 -0
  49. package/chunks/{chunk-SKAZWEV5.js → chunk-5M6IDOMF.js} +35 -98
  50. package/chunks/{chunk-A4BMJM77.js → chunk-5O2XNYP6.js} +1 -0
  51. package/chunks/{chunk-GO6LNQXT.js → chunk-6AM5D4ME.js} +1 -1
  52. package/chunks/{chunk-BJBWRCSK.js → chunk-6H67XLET.js} +1 -1
  53. package/chunks/{chunk-AYNCLGTW.js → chunk-6HHAADP2.js} +8 -51
  54. package/chunks/{chunk-VZ7HY3YU.js → chunk-6OATMEYN.js} +3 -3
  55. package/chunks/{chunk-3UP777ZS.js → chunk-6RLROE6G.js} +1 -1
  56. package/chunks/{chunk-ZERZSAZL.js → chunk-75DOP5OR.js} +2 -2
  57. package/chunks/{chunk-RMLZAUWH.js → chunk-7BIZARI2.js} +10 -12
  58. package/chunks/{chunk-GN3F6PIU.js → chunk-7NAWTFVY.js} +5 -5
  59. package/chunks/{chunk-22MNNNXE.js → chunk-7NFB7LBQ.js} +11 -3
  60. package/chunks/{chunk-ZL5HN75Q.js → chunk-7R4DPSRA.js} +37 -3
  61. package/chunks/{chunk-BVYU3ZTI.js → chunk-7U7UIO5W.js} +1005 -942
  62. package/chunks/{chunk-SAIILPQ3.js → chunk-7X7TEQNX.js} +5 -3
  63. package/chunks/{chunk-IRJWHZWU.js → chunk-A4UCTEB5.js} +2 -2
  64. package/chunks/{chunk-WF4FAXDL.js → chunk-AAS2Q2TV.js} +62 -62
  65. package/chunks/{chunk-O7FIRWJV.js → chunk-AAWKZ5R7.js} +3 -3
  66. package/chunks/{chunk-JCH35JB3.js → chunk-AGBFWLA5.js} +2 -2
  67. package/chunks/{chunk-QYUE6W3T.js → chunk-ALGGS7UH.js} +2 -39
  68. package/chunks/{chunk-WMPVYQ4P.js → chunk-ARKANCNX.js} +3 -2
  69. package/chunks/{chunk-HDOH3QYE.js → chunk-ASVORVFT.js} +2 -2
  70. package/chunks/{chunk-CHB5SLZZ.js → chunk-AUGSSJX3.js} +3 -3
  71. package/chunks/{chunk-PUVCVELY.js → chunk-B6ABUBYY.js} +4 -4
  72. package/chunks/{chunk-L4AMBVQG.js → chunk-B6KHOCU7.js} +49 -21
  73. package/chunks/{chunk-HW4N45EE.js → chunk-B7NUUEXC.js} +38 -11
  74. package/chunks/{chunk-CD6USWHZ.js → chunk-BBNVFRGD.js} +2 -2
  75. package/chunks/{chunk-ZN5T4BHI.js → chunk-BPZALHVR.js} +2 -2
  76. package/chunks/{chunk-VGGOPZUL.js → chunk-C4CXFRKY.js} +12 -5
  77. package/chunks/{chunk-OFEVLU4C.js → chunk-CARU2RR2.js} +1 -1
  78. package/chunks/{chunk-SQ2UATK7.js → chunk-CLTWL6HD.js} +11 -11
  79. package/chunks/{chunk-GLE2YUPU.js → chunk-COH43MRJ.js} +1 -1
  80. package/chunks/{chunk-E5A7LHNN.js → chunk-CPBF7KYF.js} +1 -1
  81. package/chunks/{chunk-UWCTAVOD.js → chunk-CR3C7WXL.js} +1 -1
  82. package/chunks/{chunk-DIWVZ3VM.js → chunk-CSACSGAW.js} +5 -5
  83. package/chunks/{chunk-5P5XGNYH.js → chunk-CU3L64TP.js} +1 -1
  84. package/chunks/{chunk-IWKSG2AR.js → chunk-CXAOG665.js} +1 -1
  85. package/chunks/{chunk-64WXLC72.js → chunk-DJ2GSRLV.js} +1 -1
  86. package/chunks/chunk-DKXW66XA.js +38 -0
  87. package/chunks/{chunk-QN5NZ3UQ.js → chunk-DMTGGOSA.js} +2 -2
  88. package/chunks/{chunk-JZHIQJOE.js → chunk-DMTQY5GY.js} +6 -6
  89. package/chunks/{chunk-GSHQYYIV.js → chunk-DNKX35GS.js} +6 -26
  90. package/chunks/{chunk-6IAWPIQ6.js → chunk-DPSWJWZI.js} +4 -3
  91. package/chunks/{chunk-X2XNQQJI.js → chunk-E2UVIFI2.js} +186 -399
  92. package/chunks/{chunk-KHDZHZMH.js → chunk-E5Z2AVNV.js} +1 -1
  93. package/chunks/{chunk-3B26UVCX.js → chunk-E67NFMF4.js} +39 -10
  94. package/chunks/{chunk-ON3JA3RU.js → chunk-EU3U7USF.js} +7 -9
  95. package/chunks/{chunk-L46XKEGM.js → chunk-EUNRLYJG.js} +5 -8
  96. package/chunks/{chunk-OACJLMLD.js → chunk-FBU7WRZI.js} +18 -2
  97. package/chunks/{chunk-5IFG2VC4.js → chunk-FCMNKVXT.js} +1 -1
  98. package/chunks/{chunk-A5JOJ77H.js → chunk-FDL4PB5H.js} +38 -15
  99. package/chunks/{chunk-E7KNELIZ.js → chunk-FSA7ERJ2.js} +2 -2
  100. package/chunks/{chunk-TI3BWD4D.js → chunk-G6QTKQN4.js} +39 -19
  101. package/chunks/{chunk-44NROQYV.js → chunk-GDQQRV43.js} +4 -4
  102. package/chunks/{chunk-O2YT7VB4.js → chunk-GOXKNSDZ.js} +2 -65
  103. package/chunks/{chunk-V35MD7KN.js → chunk-GRC5HGPI.js} +1 -1
  104. package/chunks/chunk-GYGGUR4Q.js +253 -0
  105. package/chunks/{chunk-S6RLAIUR.js → chunk-GYTKQYDB.js} +1 -1
  106. package/chunks/{chunk-A2X3KLC3.js → chunk-GZXCZHCT.js} +3 -3
  107. package/chunks/{chunk-K5PGHDBN.js → chunk-H6XPXXMH.js} +1 -1
  108. package/chunks/{chunk-E7EMCSUG.js → chunk-HE54PGVI.js} +64 -42
  109. package/chunks/{chunk-KYMBIKIW.js → chunk-HTHUX2T5.js} +1 -1
  110. package/chunks/{chunk-LQ7TMOCE.js → chunk-HTO4JFDZ.js} +1 -1
  111. package/chunks/chunk-HZYUNZDQ.js +296 -0
  112. package/chunks/chunk-IDS7MSUP.js +74 -0
  113. package/chunks/chunk-J2TDDOSM.js +493 -0
  114. package/chunks/{chunk-4CGOWHKM.js → chunk-J4MOFEOK.js} +2 -2
  115. package/chunks/{chunk-22IFUCVR.js → chunk-JESCGQM3.js} +1 -1
  116. package/chunks/chunk-JR63TOV4.js +91 -0
  117. package/chunks/chunk-K3PPUB46.js +445 -0
  118. package/chunks/{chunk-42XGFRJS.js → chunk-KKRTYONM.js} +8 -6
  119. package/chunks/{chunk-GGQQA4JW.js → chunk-KSO42X3Z.js} +15 -2
  120. package/chunks/{chunk-MRO43B25.js → chunk-KW7NOTN6.js} +1 -1
  121. package/chunks/{chunk-54YZOP7P.js → chunk-L573Z2QZ.js} +11894 -5190
  122. package/chunks/{chunk-TLWA7TPR.js → chunk-L5U3ELZX.js} +2 -2
  123. package/chunks/{chunk-WHJQ3JUS.js → chunk-LAM6CGP5.js} +10 -10
  124. package/chunks/{chunk-H6EMK6QK.js → chunk-LQIDP6K5.js} +11913 -5207
  125. package/chunks/{chunk-MZ7BABX3.js → chunk-LXLTBIDP.js} +44 -7
  126. package/chunks/{chunk-HLKG6CZN.js → chunk-M5GB774H.js} +1 -1
  127. package/chunks/{chunk-EEN2TKST.js → chunk-MBJ3D6SF.js} +2 -2
  128. package/chunks/{chunk-PMFULMLX.js → chunk-MBP3K324.js} +2234 -377
  129. package/chunks/chunk-MR3PXB6E.js +48 -0
  130. package/chunks/{chunk-ZE6E424U.js → chunk-N7FCSERB.js} +2 -2
  131. package/chunks/{chunk-332PWN27.js → chunk-NHDKSOEY.js} +1 -1
  132. package/chunks/chunk-OATTJGPJ.js +448 -0
  133. package/chunks/{chunk-UX6OTBVD.js → chunk-OCC3UTWA.js} +2 -2
  134. package/chunks/{chunk-P7M4GA57.js → chunk-OCPBI7J5.js} +1 -1
  135. package/chunks/chunk-OJAMDVF5.js +66 -0
  136. package/chunks/{chunk-IJRL2S3D.js → chunk-OKAIGAYW.js} +6 -6
  137. package/chunks/{chunk-WQTHLB5T.js → chunk-P3S67A5R.js} +7 -7
  138. package/chunks/{chunk-FBET5XZ2.js → chunk-PEJWA3QQ.js} +29 -10
  139. package/chunks/{chunk-J7RCB6N5.js → chunk-PHYCWSDG.js} +2 -2
  140. package/chunks/{chunk-LAXNEOBG.js → chunk-PMRH4YYW.js} +18 -3
  141. package/chunks/{chunk-AGHU5VRK.js → chunk-PZL23GTM.js} +1 -1
  142. package/chunks/{chunk-PC4ZXHU2.js → chunk-Q6TUALBE.js} +3 -3
  143. package/chunks/{chunk-FXGLL2HL.js → chunk-Q7YDKOGY.js} +1 -1
  144. package/chunks/{chunk-P3XEEI3X.js → chunk-QABSSDQH.js} +36 -7
  145. package/chunks/{chunk-XOHNA2S6.js → chunk-QAW7PIHT.js} +3 -3
  146. package/chunks/{chunk-LGFAYIKX.js → chunk-QHTIBUWB.js} +1 -1
  147. package/chunks/{chunk-P3MYAZBY.js → chunk-QMGX2KO2.js} +1 -1
  148. package/chunks/{chunk-Z3I3QJK3.js → chunk-QRUIS3DN.js} +1 -1
  149. package/chunks/{chunk-ITOGNELQ.js → chunk-QSWDGAIC.js} +2 -2
  150. package/chunks/{chunk-GHOTR7HL.js → chunk-QUPXZXLV.js} +1 -1
  151. package/chunks/{chunk-W7EEOR7D.js → chunk-RCEEXIOO.js} +8 -6
  152. package/chunks/{chunk-2EM7ECZD.js → chunk-RJL5T4WJ.js} +281 -65
  153. package/chunks/{chunk-TLRYABYP.js → chunk-RKUWKYED.js} +1 -1
  154. package/chunks/{chunk-RNBYOUGV.js → chunk-RXFQM6FQ.js} +1 -1
  155. package/chunks/{chunk-JRQ7EVGE.js → chunk-S2QXYLUB.js} +2 -2
  156. package/chunks/{chunk-QXPI7FEC.js → chunk-S3TWXGKA.js} +4 -4
  157. package/chunks/{chunk-O33TBKDC.js → chunk-SE74CIZD.js} +155 -19
  158. package/chunks/{chunk-FV7425LN.js → chunk-SPJQO2CE.js} +18 -5
  159. package/chunks/{chunk-3GNOQZDC.js → chunk-SSFDPGFN.js} +11866 -11542
  160. package/chunks/{chunk-DCZWC4PF.js → chunk-SUWGUGAD.js} +5 -5
  161. package/chunks/{chunk-IBY3Q3HG.js → chunk-SXU3KKNI.js} +963 -181
  162. package/chunks/{chunk-MLZQVCF3.js → chunk-SZRN75WQ.js} +1 -1
  163. package/chunks/{chunk-M7S4GK5Z.js → chunk-T2L6SGQY.js} +115 -29
  164. package/chunks/{chunk-7RYW5LQV.js → chunk-T2NCM2ET.js} +2 -2
  165. package/chunks/{chunk-JPALE3PA.js → chunk-T5C2OUCI.js} +6 -6
  166. package/chunks/{chunk-BUZ6HGL4.js → chunk-T7FSRWQ5.js} +248 -55
  167. package/chunks/{chunk-Z2Z3GUXZ.js → chunk-TB6UDU4T.js} +1 -1
  168. package/chunks/{chunk-EXPMGZZV.js → chunk-TEGEBB2I.js} +1 -1
  169. package/chunks/{chunk-MX2YXRER.js → chunk-TJTKSVIV.js} +1 -1
  170. package/chunks/{chunk-CCGOFQV3.js → chunk-TQBODCFD.js} +8 -7
  171. package/chunks/chunk-TV6K2FB4.js +224 -0
  172. package/chunks/{chunk-5MBO76SL.js → chunk-TXY2C3D2.js} +3 -3
  173. package/chunks/{chunk-H6BD2ELD.js → chunk-TYAMGABM.js} +2 -2
  174. package/chunks/{chunk-QYNNN7BK.js → chunk-TYLOFD2U.js} +2 -2
  175. package/chunks/{chunk-VRDMOSQS.js → chunk-UDXSXLER.js} +2 -2
  176. package/chunks/{chunk-UXEW557D.js → chunk-UI3W56WF.js} +3 -3
  177. package/chunks/{chunk-CJCKDMWO.js → chunk-URK542T4.js} +1 -1
  178. package/chunks/{channel-worker-supervisor-NZQUOEFJ.js → chunk-URU5UEK6.js} +190 -34
  179. package/chunks/{chunk-AHNXYU4O.js → chunk-V6WHFGST.js} +1 -1
  180. package/chunks/chunk-V75IOTWF.js +71 -0
  181. package/chunks/{chunk-ZTQ26VBE.js → chunk-VDDGDZMA.js} +1 -1
  182. package/chunks/{chunk-OMX7CUOE.js → chunk-VGC4I5JJ.js} +1 -1
  183. package/chunks/{chunk-43W4YSO6.js → chunk-VJNBRRZG.js} +2 -2
  184. package/chunks/{chunk-ER3BKOLB.js → chunk-W7FJ3N32.js} +1 -1
  185. package/chunks/{chunk-3HX5LZ6R.js → chunk-WBL3FJEU.js} +2 -2
  186. package/chunks/{chunk-7LTB54MK.js → chunk-WIEO4CWB.js} +2 -2
  187. package/chunks/{chunk-BMFMJINR.js → chunk-WL4L7EZH.js} +1 -1
  188. package/chunks/{chunk-6VK6FIMQ.js → chunk-WM5HY72H.js} +415 -379
  189. package/chunks/{chunk-BOBRZZKD.js → chunk-WN4D7YCI.js} +5 -5
  190. package/chunks/{chunk-DHOLNQLC.js → chunk-WWQ3QIJS.js} +60 -40
  191. package/chunks/{chunk-FEJ2FZ3U.js → chunk-WX6SD4IQ.js} +2 -2
  192. package/chunks/{chunk-DICGXFAI.js → chunk-X7EBAABW.js} +11 -9
  193. package/chunks/{chunk-3RW4AZJV.js → chunk-XFSFZCM5.js} +1 -1
  194. package/chunks/{chunk-YHKAK72D.js → chunk-XHW5VUIQ.js} +102 -16
  195. package/chunks/{chunk-2MPVVENX.js → chunk-XU457J4V.js} +2 -2
  196. package/chunks/{chunk-SIUQ3YYX.js → chunk-XVNQMZ2I.js} +1 -1
  197. package/chunks/{chunk-SYCJMSIJ.js → chunk-XWRJCPHC.js} +1 -1
  198. package/chunks/{chunk-SUAKHHK7.js → chunk-Y66VOBRP.js} +3 -3
  199. package/chunks/chunk-YAF2MQZ6.js +19 -0
  200. package/chunks/{chunk-FQNC62B2.js → chunk-YH4J5XI3.js} +11 -11
  201. package/chunks/chunk-YHN5SUIJ.js +219 -0
  202. package/chunks/{chunk-BR4QREVK.js → chunk-YQ3U5MUC.js} +1 -1
  203. package/chunks/{chunk-Y6Z2O3WR.js → chunk-YUZI3WAC.js} +1 -1
  204. package/chunks/{chunk-II73RK2S.js → chunk-YVEDCAUE.js} +1 -1
  205. package/chunks/{chunk-XYR5RUA5.js → chunk-YWUK7OS7.js} +10 -3
  206. package/chunks/{chunk-27BHARDE.js → chunk-Z56JO4JZ.js} +2124 -30
  207. package/chunks/{chunk-TSPB77TG.js → chunk-ZLM3KXBT.js} +1015 -2967
  208. package/chunks/{chunk-AHNJGLFV.js → chunk-ZPAHLFZU.js} +3 -3
  209. package/chunks/chunk-ZRKBI3DP.js +34 -0
  210. package/chunks/cli-entry-path-4VJ3Y6T2.js +10 -0
  211. package/chunks/{computer-use-WMY3UOBX.js → computer-use-DIP5BWXP.js} +51 -50
  212. package/chunks/config-utils-CFT33LTP.js +24 -0
  213. package/chunks/contextCommand-QU4GJWWD.js +69 -0
  214. package/chunks/create-sub-session-TCLIYVGR.js +376 -0
  215. package/chunks/create-sub-session-WNX2OQVX.js +207 -0
  216. package/chunks/{cron-create-JSXEIPVS.js → cron-create-36TIFKRT.js} +9 -9
  217. package/chunks/{cron-delete-OIFVEPGU.js → cron-delete-OQD3WULU.js} +7 -7
  218. package/chunks/{cron-list-D4ZX4IOE.js → cron-list-4533T2FH.js} +14 -10
  219. package/chunks/{daemon-WPAENEBW.js → daemon-CEZ27OH4.js} +734 -24
  220. package/chunks/daemon-status-provider-SIBFMLBQ.js +77 -0
  221. package/chunks/{de-ZFPPQVSF.js → de-2VCDRDGU.js} +68 -6
  222. package/chunks/{devtools-FM6GJPYG.js → devtools-4QFYJT6U.js} +3 -3
  223. package/chunks/{dist-E6UANPIM.js → dist-3V3ZV6ML.js} +1011 -197
  224. package/chunks/{dist-SCFLLYMK.js → dist-ERCPDVA6.js} +12 -11
  225. package/chunks/{dist-Z34QPAQW.js → dist-HNN7DR2L.js} +529 -79
  226. package/chunks/{dist-O2IRTRPP.js → dist-JZE7F6YR.js} +10 -10
  227. package/chunks/{dist-BEXOZXLQ.js → dist-MOEC47TR.js} +36 -15
  228. package/chunks/{dist-H2AEJCZ5.js → dist-PHEPJLXD.js} +5 -5
  229. package/chunks/{dist-63IS3ZMI.js → dist-PZV5RKM6.js} +4 -4
  230. package/chunks/earlyInputCapture-L66BEG2C.js +70 -0
  231. package/chunks/{edit-OTYWAXGP.js → edit-Y5LAJSST.js} +52 -51
  232. package/chunks/{en-N4EPZAQI.js → en-NJCA3TAA.js} +78 -6
  233. package/chunks/{enter-worktree-HNYBDVCX.js → enter-worktree-X5LML7T4.js} +51 -50
  234. package/chunks/{enterPlanMode-CJCNGT63.js → enterPlanMode-XWF32QOW.js} +67 -51
  235. package/chunks/environment-YVMA5F4I.js +90 -0
  236. package/chunks/errors-4Y5SUAOC.js +76 -0
  237. package/chunks/{exit-worktree-DUUKOE3X.js → exit-worktree-SFHU7XYC.js} +51 -50
  238. package/chunks/{exitPlanMode-AMMSXOAJ.js → exitPlanMode-FP3NAN6E.js} +52 -51
  239. package/chunks/{fast-path-OV6NIP3K.js → fast-path-ZJNFFCBM.js} +8 -8
  240. package/chunks/{fast-path-settings-7RIFI3PK.js → fast-path-settings-DAOVFADC.js} +8 -6
  241. package/chunks/{fileFromPath-IBEHA3CO.js → fileFromPath-UDALK7FM.js} +3 -3
  242. package/chunks/{fr-5WWMY53B.js → fr-5F3E7WKD.js} +68 -6
  243. package/chunks/{gemini-NQ3WWBKB.js → gemini-5CAB22BI.js} +122 -109
  244. package/chunks/{geminiContentGenerator-CDUNEJQE.js → geminiContentGenerator-GE3HPIFB.js} +9 -9
  245. package/chunks/{getMachineId-bsd-4CASPIU4.js → getMachineId-bsd-EXV7SWPA.js} +3 -3
  246. package/chunks/{getMachineId-darwin-HPQPEMZR.js → getMachineId-darwin-IUOMFXU3.js} +3 -3
  247. package/chunks/{getMachineId-linux-AUARKYHL.js → getMachineId-linux-K7XJYFHL.js} +2 -2
  248. package/chunks/{getMachineId-unsupported-S32ZDA2T.js → getMachineId-unsupported-EA5FDRJ6.js} +2 -2
  249. package/chunks/{getMachineId-win-4EFLHYIJ.js → getMachineId-win-KBA6RAI5.js} +3 -3
  250. package/chunks/{glob-ROV3YS4R.js → glob-YPACZAEL.js} +98 -75
  251. package/chunks/{grep-NRITKDCD.js → grep-IPR4XW37.js} +51 -50
  252. package/chunks/handleAutoUpdate-P2KEP56V.js +70 -0
  253. package/chunks/i18n-BRCT66AA.js +85 -0
  254. package/chunks/initializer-34HXSK3A.js +74 -0
  255. package/chunks/installationInfo-WOTDQMSC.js +66 -0
  256. package/chunks/{ja-CUHZOLEJ.js → ja-66J6B53L.js} +69 -7
  257. package/chunks/{keychain-token-storage-UJV5XP4Z.js → keychain-token-storage-AU22CQI6.js} +4 -4
  258. package/chunks/{kittyProtocolDetector-OJRCJLIU.js → kittyProtocolDetector-HCNNKJTI.js} +2 -2
  259. package/chunks/list-XOGP7UPP.js +77 -0
  260. package/chunks/loadedSettingsAdapter-L4YKGU6F.js +71 -0
  261. package/chunks/{loop-wakeup-OHWEMFP5.js → loop-wakeup-MVUKDVCP.js} +10 -10
  262. package/chunks/{lowlight-FYAAUU5J.js → lowlight-J2OZNPCA.js} +1 -1
  263. package/chunks/{ls-7MFU2QYW.js → ls-RXNIAQDE.js} +6 -6
  264. package/chunks/{lsp-XHDTPTGV.js → lsp-HB5LM5IL.js} +4 -4
  265. package/chunks/mcp-HH7DIP7Y.js +71 -0
  266. package/chunks/{monitor-FL2ZO33W.js → monitor-25DEBT6U.js} +51 -50
  267. package/chunks/{multipart-parser-AJ4WASWR.js → multipart-parser-AWZKXSQN.js} +3 -3
  268. package/chunks/nonInteractiveCli-CT3VSSLK.js +130 -0
  269. package/chunks/{notebook-edit-6PULTHL5.js → notebook-edit-TAVXSWQ6.js} +52 -51
  270. package/chunks/openaiContentGenerator-6I7DKUAN.js +56 -0
  271. package/chunks/pidfile-SIQGCFLZ.js +74 -0
  272. package/chunks/{pt-OLYN42DS.js → pt-TFZO5Y6T.js} +68 -6
  273. package/chunks/{qwenContentGenerator-NX2E7PB7.js → qwenContentGenerator-5DDIXI2N.js} +53 -52
  274. package/chunks/{qwenOAuth2-ZV7YLMND.js → qwenOAuth2-LEYOU7RU.js} +9 -9
  275. package/chunks/read-file-WDOAYRFU.js +30 -0
  276. package/chunks/{read-mcp-resource-CNQHBSJM.js → read-mcp-resource-6LRTZKXI.js} +5 -5
  277. package/chunks/{read-package-up-ER5OJUGP.js → read-package-up-TCM6I7S2.js} +2 -2
  278. package/chunks/{record-artifact-SQ2OKRJW.js → record-artifact-PMDTY4OS.js} +4 -4
  279. package/chunks/ripGrep-MI7PHN3Q.js +61 -0
  280. package/chunks/{ru-LDM3GWVQ.js → ru-4L4LFHIT.js} +68 -6
  281. package/chunks/{run-qwen-serve-JK2DL7PI.js → run-qwen-serve-PNTYF3RE.js} +1289 -256
  282. package/chunks/runtime-V3FBMUTG.js +100 -0
  283. package/chunks/{scheduler-O4IGVZKK.js → scheduler-4TAUIJBM.js} +52 -51
  284. package/chunks/{send-message-76GT3JMC.js → send-message-SR4WSXP2.js} +7 -7
  285. package/chunks/serve-WB2TR7XM.js +77 -0
  286. package/chunks/{server-SGNPKX2O.js → server-AF6LNFPK.js} +8094 -2800
  287. package/chunks/{session-5BNM25EZ.js → session-BIGK4NRW.js} +341 -135
  288. package/chunks/settings-IXF5FIQO.js +121 -0
  289. package/chunks/shell-5VWJ2PPG.js +69 -0
  290. package/chunks/{skill-I22QK5XS.js → skill-SI667Y3B.js} +24 -24
  291. package/chunks/spawnChannel-IKX6DD7J.js +71 -0
  292. package/chunks/{src-BBQSM46M.js → src-55DZWDAK.js} +151 -52
  293. package/chunks/{src-7XL4G4DC.js → src-VLI3TKEY.js} +4 -4
  294. package/chunks/standalone-update-MHLSFHE6.js +80 -0
  295. package/chunks/{startInteractiveUI-JII36UGN.js → startInteractiveUI-V2EDWLAX.js} +2239 -1846
  296. package/chunks/stdioHelpers-UMY72QRP.js +14 -0
  297. package/chunks/{syntheticOutput-F7LSDCAR.js → syntheticOutput-YKFNUQZD.js} +5 -5
  298. package/chunks/task-create-NUFOHU53.js +23 -0
  299. package/chunks/{task-list-TGGJX7EA.js → task-list-Z2IKQY3S.js} +11 -10
  300. package/chunks/{task-stop-W7NGTMYQ.js → task-stop-KQFIVQTJ.js} +4 -4
  301. package/chunks/{task-update-XYWMHJGJ.js → task-update-HKADXSTD.js} +13 -12
  302. package/chunks/{team-create-A7NUU5AQ.js → team-create-IZAMLBJS.js} +51 -50
  303. package/chunks/{team-delete-UHQQ2QQX.js → team-delete-SDNTGZLG.js} +11 -10
  304. package/chunks/{team-plan-approval-TOQRJ2KI.js → team-plan-approval-3R4RCKCP.js} +51 -50
  305. package/chunks/theme-manager-LCOXZ5DO.js +65 -0
  306. package/chunks/{todoWrite-C4ZAMSR3.js → todoWrite-YNXB27GB.js} +6 -6
  307. package/chunks/{tool-search-SZ4EFS2T.js → tool-search-NYNCD5LF.js} +24 -24
  308. package/chunks/total-session-admission-PJWGOMQE.js +73 -0
  309. package/chunks/tree-sitter-YJVE2ZUK.js +2980 -0
  310. package/chunks/trustedFolders-DOJDHNYP.js +81 -0
  311. package/chunks/{types-QX5C3CHJ.js → types-JNKGKUJT.js} +2 -2
  312. package/chunks/updateCheck-ZXL66KIG.js +70 -0
  313. package/chunks/updateEventEmitter-5MKC7BLQ.js +10 -0
  314. package/chunks/validateNonInterActiveAuth-JSNJZCYY.js +195 -0
  315. package/chunks/{version-NO2XSNNP.js → version-3NLBENG5.js} +3 -3
  316. package/chunks/{web-fetch-UYGMOHW4.js → web-fetch-ZSPR3PRR.js} +8 -8
  317. package/chunks/{workflow-WO2H6NRI.js → workflow-BQYLF7XP.js} +52 -51
  318. package/chunks/workspace-providers-status-FA2DGEZW.js +74 -0
  319. package/chunks/workspace-registration-store-TARTAGMI.js +27 -0
  320. package/chunks/workspace-registry-AGE7WAXX.js +77 -0
  321. package/chunks/workspace-service-ERC5VR2B.js +83 -0
  322. package/chunks/workspace-skills-status-FKYWGNCN.js +73 -0
  323. package/chunks/{write-file-PX2Z7IBE.js → write-file-S47KSK7Z.js} +52 -51
  324. package/chunks/{yargs-B64EYTCF.js → yargs-6H2AUULL.js} +2 -2
  325. package/chunks/{zh-J4F6QWQV.js → zh-FSAH32JB.js} +79 -7
  326. package/chunks/{zh-TW-XVDWOLSW.js → zh-TW-D2YIE2LO.js} +79 -7
  327. package/cli.js +18 -17
  328. package/locales/ca.js +91 -7
  329. package/locales/de.js +90 -7
  330. package/locales/en.js +109 -7
  331. package/locales/fr.js +91 -7
  332. package/locales/ja.js +93 -7
  333. package/locales/pt.js +90 -7
  334. package/locales/ru.js +90 -7
  335. package/locales/zh-TW.js +106 -7
  336. package/locales/zh.js +106 -7
  337. package/package.json +3 -6
  338. package/web-shell/assets/{arc-BWyoJpY2.js → arc-Zj4EkBUY.js} +1 -1
  339. package/web-shell/assets/{architectureDiagram-3BPJPVTR-BT0mGrz2.js → architectureDiagram-3BPJPVTR-DAk1Ua3Y.js} +1 -1
  340. package/web-shell/assets/{blockDiagram-GPEHLZMM-BLgUWvyf.js → blockDiagram-GPEHLZMM-DBNqUthM.js} +1 -1
  341. package/web-shell/assets/{c4Diagram-AAUBKEIU-DYx9M7oU.js → c4Diagram-AAUBKEIU-Dq5QGJ53.js} +1 -1
  342. package/web-shell/assets/channel-DWfYijFS.js +1 -0
  343. package/web-shell/assets/{chunk-2J33WTMH-CfMHWbuZ.js → chunk-2J33WTMH-DY0AeGru.js} +1 -1
  344. package/web-shell/assets/{chunk-4BX2VUAB-B1URoqEV.js → chunk-4BX2VUAB-COX3OyIi.js} +1 -1
  345. package/web-shell/assets/{chunk-55IACEB6-DAIaM4QF.js → chunk-55IACEB6-Csoyddbh.js} +1 -1
  346. package/web-shell/assets/{chunk-727SXJPM-B2X34knw.js → chunk-727SXJPM-BJPONdxX.js} +1 -1
  347. package/web-shell/assets/{chunk-AQP2D5EJ-Cif-zLTQ.js → chunk-AQP2D5EJ-syLVH6fg.js} +1 -1
  348. package/web-shell/assets/{chunk-FMBD7UC4-H18WCXdY.js → chunk-FMBD7UC4-Cfm59Nhw.js} +1 -1
  349. package/web-shell/assets/{chunk-ND2GUHAM-YFtetHi0.js → chunk-ND2GUHAM-DZf6tAqS.js} +1 -1
  350. package/web-shell/assets/{chunk-QZHKN3VN-By2hiH3r.js → chunk-QZHKN3VN-DKBp_v5q.js} +1 -1
  351. package/web-shell/assets/classDiagram-4FO5ZUOK-DDht-78J.js +1 -0
  352. package/web-shell/assets/classDiagram-v2-Q7XG4LA2-DDht-78J.js +1 -0
  353. package/web-shell/assets/{cose-bilkent-S5V4N54A-VrcnnLZu.js → cose-bilkent-S5V4N54A-DUU3mMQ5.js} +1 -1
  354. package/web-shell/assets/{dagre-BM42HDAG-CGo-IaVV.js → dagre-BM42HDAG-BUgNfbh-.js} +1 -1
  355. package/web-shell/assets/{diagram-2AECGRRQ-Dl4QjzIB.js → diagram-2AECGRRQ-DT7MVfAg.js} +1 -1
  356. package/web-shell/assets/{diagram-5GNKFQAL-qMLmsO0u.js → diagram-5GNKFQAL-Cv4YG-ec.js} +1 -1
  357. package/web-shell/assets/{diagram-KO2AKTUF-CHlmuxPI.js → diagram-KO2AKTUF-BAe9LLkn.js} +1 -1
  358. package/web-shell/assets/{diagram-LMA3HP47-BUwU3GwT.js → diagram-LMA3HP47-DW8wqTIP.js} +1 -1
  359. package/web-shell/assets/{diagram-OG6HWLK6-HEhwPDUM.js → diagram-OG6HWLK6-CmkuWbaK.js} +1 -1
  360. package/web-shell/assets/{erDiagram-TEJ5UH35-1n0llBmM.js → erDiagram-TEJ5UH35-DwvdHjZ9.js} +1 -1
  361. package/web-shell/assets/{flowDiagram-I6XJVG4X-BN74uMnt.js → flowDiagram-I6XJVG4X-CSsXrhW_.js} +1 -1
  362. package/web-shell/assets/{ganttDiagram-6RSMTGT7-BoOq78i3.js → ganttDiagram-6RSMTGT7-BtuznCdi.js} +3 -3
  363. package/web-shell/assets/{gitGraphDiagram-PVQCEYII-CN8b00c8.js → gitGraphDiagram-PVQCEYII-DGmAm06g.js} +1 -1
  364. package/web-shell/assets/index-B9Xwf4OS.css +5 -0
  365. package/web-shell/assets/index-BEtz1cvN.js +3 -0
  366. package/web-shell/assets/index-BUkM4ZXX.js +1088 -0
  367. package/web-shell/assets/{infoDiagram-5YYISTIA-CCurnIna.js → infoDiagram-5YYISTIA-OAiZ1q0K.js} +1 -1
  368. package/web-shell/assets/{ishikawaDiagram-YF4QCWOH-AwuRqdUP.js → ishikawaDiagram-YF4QCWOH-DyK0KTIT.js} +1 -1
  369. package/web-shell/assets/{journeyDiagram-JHISSGLW-B7IICk-E.js → journeyDiagram-JHISSGLW-DzYJlwfO.js} +1 -1
  370. package/web-shell/assets/{kanban-definition-UN3LZRKU-BYF0OKhx.js → kanban-definition-UN3LZRKU-CU_tcDwi.js} +1 -1
  371. package/web-shell/assets/{linear-GWWguGfD.js → linear-DvZXjF17.js} +1 -1
  372. package/web-shell/assets/{mermaid.core-JqtkxvCl.js → mermaid.core-_ZFEQlOl.js} +5 -5
  373. package/web-shell/assets/{mindmap-definition-RKZ34NQL-B0MmHsZ6.js → mindmap-definition-RKZ34NQL-Or4p64HB.js} +1 -1
  374. package/web-shell/assets/{pieDiagram-4H26LBE5-DhImUZLQ.js → pieDiagram-4H26LBE5-lXE-zZ6b.js} +1 -1
  375. package/web-shell/assets/{quadrantDiagram-W4KKPZXB-DGeSC3DT.js → quadrantDiagram-W4KKPZXB-DUXb9mUV.js} +1 -1
  376. package/web-shell/assets/{requirementDiagram-4Y6WPE33-DkspY6Re.js → requirementDiagram-4Y6WPE33-D_10uHfo.js} +1 -1
  377. package/web-shell/assets/{sankeyDiagram-5OEKKPKP-CaOofS2x.js → sankeyDiagram-5OEKKPKP-E8c0fPqe.js} +1 -1
  378. package/web-shell/assets/{sequenceDiagram-3UESZ5HK-DFQ_kFnN.js → sequenceDiagram-3UESZ5HK-CJMtFttK.js} +1 -1
  379. package/web-shell/assets/{stateDiagram-AJRCARHV-D3snw0Tz.js → stateDiagram-AJRCARHV-DhbviRbB.js} +1 -1
  380. package/web-shell/assets/stateDiagram-v2-BHNVJYJU-CntljfwW.js +1 -0
  381. package/web-shell/assets/{timeline-definition-PNZ67QCA-l4zH8nLM.js → timeline-definition-PNZ67QCA-CM5yMkFK.js} +1 -1
  382. package/web-shell/assets/{vennDiagram-CIIHVFJN-BnRlA98M.js → vennDiagram-CIIHVFJN-BCi-zWNN.js} +1 -1
  383. package/web-shell/assets/{wardley-L42UT6IY-BS0xUdmd.js → wardley-L42UT6IY-BJ_yJNjJ.js} +1 -1
  384. package/web-shell/assets/{wardleyDiagram-YWT4CUSO-DKGBUWyQ.js → wardleyDiagram-YWT4CUSO-TjtLk-qN.js} +1 -1
  385. package/web-shell/assets/{xychartDiagram-2RQKCTM6-DVb2HuOB.js → xychartDiagram-2RQKCTM6-D1TjyoQ3.js} +1 -1
  386. package/web-shell/index.html +16 -4
  387. package/chunks/MaxSizedBox-5DT2SD7B.js +0 -71
  388. package/chunks/agent-H2DGKS77.js +0 -68
  389. package/chunks/agent-headless-KFMFIT6J.js +0 -62
  390. package/chunks/bridge-NA3ZQQKJ.js +0 -78
  391. package/chunks/chunk-6SHO7WFF.js +0 -79
  392. package/chunks/chunk-IFEWJXFS.js +0 -37
  393. package/chunks/chunk-XNXVCNAT.js +0 -88
  394. package/chunks/contextCommand-LXFZRP4L.js +0 -68
  395. package/chunks/daemon-status-provider-GJRXY5EN.js +0 -76
  396. package/chunks/earlyInputCapture-KNOYZ4MJ.js +0 -69
  397. package/chunks/environment-ATFTYMLZ.js +0 -88
  398. package/chunks/errors-A54HAADA.js +0 -75
  399. package/chunks/handleAutoUpdate-CEZJAARW.js +0 -65
  400. package/chunks/initializer-BRFJKRRX.js +0 -71
  401. package/chunks/list-KVHF7O4X.js +0 -73
  402. package/chunks/loadedSettingsAdapter-LL5PSFKX.js +0 -68
  403. package/chunks/mcp-3GCXRTOQ.js +0 -68
  404. package/chunks/nonInteractiveCli-PTQI3DV6.js +0 -119
  405. package/chunks/openaiContentGenerator-YE42PKCY.js +0 -56
  406. package/chunks/pidfile-NZYSCFRK.js +0 -73
  407. package/chunks/read-file-33XGP5HF.js +0 -30
  408. package/chunks/ripGrep-QWZLGTAN.js +0 -60
  409. package/chunks/serve-JTMIGANH.js +0 -74
  410. package/chunks/settings-3MI4XXP6.js +0 -118
  411. package/chunks/shell-YJKBE67T.js +0 -68
  412. package/chunks/spawnChannel-UNV6W4DU.js +0 -70
  413. package/chunks/task-create-WCHTB435.js +0 -22
  414. package/chunks/theme-manager-WZ4RRMMB.js +0 -64
  415. package/chunks/total-session-admission-ULXJWXFV.js +0 -72
  416. package/chunks/trustedFolders-LAZZPZ3D.js +0 -79
  417. package/chunks/updateCheck-KONLM73X.js +0 -65
  418. package/chunks/validateNonInterActiveAuth-MPKSRCXD.js +0 -184
  419. package/chunks/workspace-providers-status-3W7E7DFW.js +0 -71
  420. package/chunks/workspace-registry-SXJZNN3O.js +0 -74
  421. package/chunks/workspace-service-CZRQZ4Q4.js +0 -80
  422. package/chunks/workspace-skills-status-K7WFREPD.js +0 -70
  423. package/node_modules/@qwen-code/audio-capture/dist/index.d.ts +0 -35
  424. package/node_modules/@qwen-code/audio-capture/dist/index.js +0 -48
  425. package/node_modules/@qwen-code/audio-capture/dist/index.js.map +0 -1
  426. package/node_modules/@qwen-code/audio-capture/dist/platform.d.ts +0 -7
  427. package/node_modules/@qwen-code/audio-capture/dist/platform.js +0 -18
  428. package/node_modules/@qwen-code/audio-capture/dist/platform.js.map +0 -1
  429. package/node_modules/@qwen-code/audio-capture/node_modules/node-gyp-build/LICENSE +0 -21
  430. package/node_modules/@qwen-code/audio-capture/node_modules/node-gyp-build/README.md +0 -58
  431. package/node_modules/@qwen-code/audio-capture/node_modules/node-gyp-build/SECURITY.md +0 -5
  432. package/node_modules/@qwen-code/audio-capture/node_modules/node-gyp-build/bin.js +0 -84
  433. package/node_modules/@qwen-code/audio-capture/node_modules/node-gyp-build/build-test.js +0 -19
  434. package/node_modules/@qwen-code/audio-capture/node_modules/node-gyp-build/index.js +0 -6
  435. package/node_modules/@qwen-code/audio-capture/node_modules/node-gyp-build/node-gyp-build.js +0 -207
  436. package/node_modules/@qwen-code/audio-capture/node_modules/node-gyp-build/optional.js +0 -7
  437. package/node_modules/@qwen-code/audio-capture/node_modules/node-gyp-build/package.json +0 -43
  438. package/node_modules/@qwen-code/audio-capture/package.json +0 -30
  439. package/node_modules/@qwen-code/audio-capture/prebuilds/darwin-arm64/@qwen-code+audio-capture.node +0 -0
  440. package/node_modules/@qwen-code/audio-capture/prebuilds/darwin-x64/@qwen-code+audio-capture.node +0 -0
  441. package/node_modules/@qwen-code/audio-capture/prebuilds/linux-arm64/@qwen-code+audio-capture.node +0 -0
  442. package/node_modules/@qwen-code/audio-capture/prebuilds/linux-x64/@qwen-code+audio-capture.node +0 -0
  443. package/node_modules/@qwen-code/audio-capture/prebuilds/win32-x64/@qwen-code+audio-capture.node +0 -0
  444. package/web-shell/assets/channel-wmPUGHtg.js +0 -1
  445. package/web-shell/assets/classDiagram-4FO5ZUOK-BA2ljEjW.js +0 -1
  446. package/web-shell/assets/classDiagram-v2-Q7XG4LA2-BA2ljEjW.js +0 -1
  447. package/web-shell/assets/index-CNwoO1Cn.js +0 -783
  448. package/web-shell/assets/index-CWQ0z6kZ.css +0 -5
  449. package/web-shell/assets/stateDiagram-v2-BHNVJYJU-BbSm_9d0.js +0 -1
@@ -3,10 +3,7 @@
3
3
  import {
4
4
  DaemonMetricsRing,
5
5
  computeCpuPercent
6
- } from "./chunk-II73RK2S.js";
7
- import {
8
- findCliEntryPath
9
- } from "./chunk-AHNXYU4O.js";
6
+ } from "./chunk-YVEDCAUE.js";
10
7
  import {
11
8
  CAPABILITIES_SCHEMA_VERSION,
12
9
  ClientMcpSenderRegistry,
@@ -22,71 +19,93 @@ import {
22
19
  getRateLimiter,
23
20
  getServeProtocolVersions,
24
21
  hostAllowlist,
22
+ isBrowserAutomationMcpAvailable,
25
23
  listenerMaxConnections,
26
24
  parseAllowOriginPatterns,
27
25
  parseDaemonStatusDetail,
28
26
  positiveFiniteOrNull,
29
27
  require_express,
30
28
  resolveWebShellDir
31
- } from "./chunk-YKZIAK7C.js";
29
+ } from "./chunk-4LJNI7MU.js";
32
30
  import {
33
31
  isLoopbackBind
34
- } from "./chunk-RNBYOUGV.js";
35
- import "./chunk-3HX5LZ6R.js";
36
- import "./chunk-7RYW5LQV.js";
32
+ } from "./chunk-RXFQM6FQ.js";
37
33
  import {
38
34
  RUNTIME_STARTUP_CANCELLED_MESSAGE
39
- } from "./chunk-GHOTR7HL.js";
35
+ } from "./chunk-QUPXZXLV.js";
40
36
  import {
41
37
  LOAD_REPLAY_META_KEY
42
- } from "./chunk-AGHU5VRK.js";
38
+ } from "./chunk-PZL23GTM.js";
43
39
  import {
44
40
  DEFAULT_COMPACTED_REPLAY_MAX_BYTES,
45
41
  normalizeCompactedReplayMaxBytes
46
- } from "./chunk-GLE2YUPU.js";
42
+ } from "./chunk-COH43MRJ.js";
43
+ import "./chunk-WBL3FJEU.js";
47
44
  import {
48
- canonicalizeWorkspace
49
- } from "./chunk-ER3BKOLB.js";
45
+ resolveChannelCwd
46
+ } from "./chunk-ZRKBI3DP.js";
50
47
  import {
51
- loadServeFastPathSettings,
52
- preResolveServeFastPathHomeEnvOverrides
53
- } from "./chunk-FBET5XZ2.js";
48
+ MAX_REGISTERED_WORKSPACES,
49
+ resolveWorkspaceInputs,
50
+ workspaceRegistrationId
51
+ } from "./chunk-J2TDDOSM.js";
52
+ import {
53
+ canonicalizeWorkspace
54
+ } from "./chunk-W7FJ3N32.js";
55
+ import "./chunk-3MX7D6QN.js";
54
56
  import {
55
57
  QWEN_SERVER_TOKEN_ENV
56
- } from "./chunk-S6RLAIUR.js";
58
+ } from "./chunk-GYTKQYDB.js";
57
59
  import {
58
60
  channelSelectionNames
59
- } from "./chunk-MX2YXRER.js";
61
+ } from "./chunk-TJTKSVIV.js";
62
+ import "./chunk-5HBA2Z7V.js";
63
+ import {
64
+ ChannelWebhookEnqueueError
65
+ } from "./chunk-OJAMDVF5.js";
66
+ import "./chunk-T2NCM2ET.js";
67
+ import {
68
+ sanitizeLogText
69
+ } from "./chunk-SXU3KKNI.js";
70
+ import "./chunk-UDXSXLER.js";
71
+ import {
72
+ loadServeFastPathSettings,
73
+ preResolveServeFastPathHomeEnvOverrides
74
+ } from "./chunk-PEJWA3QQ.js";
75
+ import "./chunk-GOXKNSDZ.js";
60
76
  import {
61
77
  getGlobalQwenDirLite,
62
78
  resolveConfigPathLite
63
- } from "./chunk-O2YT7VB4.js";
64
- import "./chunk-Z3I3QJK3.js";
79
+ } from "./chunk-IDS7MSUP.js";
80
+ import "./chunk-QRUIS3DN.js";
81
+ import "./chunk-ALGGS7UH.js";
65
82
  import {
66
- getCliVersion
67
- } from "./chunk-UXEW557D.js";
68
- import "./chunk-43W4YSO6.js";
83
+ isWithinRoot
84
+ } from "./chunk-MR3PXB6E.js";
69
85
  import {
70
86
  writeStderrLine,
71
87
  writeStdoutLine
72
- } from "./chunk-Y6Z2O3WR.js";
88
+ } from "./chunk-YUZI3WAC.js";
73
89
  import {
74
- isWithinRoot
75
- } from "./chunk-QYUE6W3T.js";
76
- import "./chunk-5P5XGNYH.js";
77
- import "./chunk-SKAZWEV5.js";
78
- import "./chunk-UWCTAVOD.js";
79
- import "./chunk-SYCJMSIJ.js";
90
+ getCliVersion
91
+ } from "./chunk-UI3W56WF.js";
92
+ import "./chunk-VJNBRRZG.js";
93
+ import "./chunk-CU3L64TP.js";
94
+ import "./chunk-H6XPXXMH.js";
95
+ import "./chunk-5M6IDOMF.js";
96
+ import "./chunk-E2UVIFI2.js";
97
+ import "./chunk-CR3C7WXL.js";
98
+ import "./chunk-XWRJCPHC.js";
80
99
  import {
81
100
  finalizeStartupProfile,
82
101
  profileCheckpoint
83
- } from "./chunk-ITOGNELQ.js";
84
- import "./chunk-FXGLL2HL.js";
85
- import "./chunk-QN5NZ3UQ.js";
86
- import "./chunk-BR4QREVK.js";
102
+ } from "./chunk-QSWDGAIC.js";
103
+ import "./chunk-Q7YDKOGY.js";
104
+ import "./chunk-DMTGGOSA.js";
105
+ import "./chunk-YQ3U5MUC.js";
87
106
  import {
88
107
  init_esbuild_shims
89
- } from "./chunk-A4BMJM77.js";
108
+ } from "./chunk-5O2XNYP6.js";
90
109
  import {
91
110
  __name,
92
111
  __toESM
@@ -95,99 +114,13 @@ import {
95
114
  // packages/cli/src/serve/run-qwen-serve.ts
96
115
  init_esbuild_shims();
97
116
  var import_express = __toESM(require_express(), 1);
98
- import { X509Certificate } from "node:crypto";
117
+ import { X509Certificate, createHash as createHash2, timingSafeEqual } from "node:crypto";
99
118
  import * as fs from "node:fs";
100
119
  import * as https from "node:https";
101
120
  import * as path from "node:path";
102
121
  import * as os from "node:os";
103
122
  import { monitorEventLoopDelay, performance } from "node:perf_hooks";
104
123
 
105
- // packages/cli/src/serve/workspace-inputs.ts
106
- init_esbuild_shims();
107
- var DuplicateWorkspaceInputError = class extends Error {
108
- static {
109
- __name(this, "DuplicateWorkspaceInputError");
110
- }
111
- constructor(workspace) {
112
- super(
113
- `Duplicate --workspace value resolves to ${JSON.stringify(workspace)}. Pass distinct --workspace values.`
114
- );
115
- this.name = "DuplicateWorkspaceInputError";
116
- }
117
- };
118
- var NestedWorkspaceInputError = class extends Error {
119
- static {
120
- __name(this, "NestedWorkspaceInputError");
121
- }
122
- constructor(parent, child) {
123
- super(
124
- `Nested --workspace values are not supported yet: ${JSON.stringify(child)} is inside ${JSON.stringify(parent)}. Pass non-nested --workspace values.`
125
- );
126
- this.name = "NestedWorkspaceInputError";
127
- }
128
- };
129
- var MissingWorkspaceInputError = class extends Error {
130
- static {
131
- __name(this, "MissingWorkspaceInputError");
132
- }
133
- constructor() {
134
- super("--workspace requires a value.");
135
- this.name = "MissingWorkspaceInputError";
136
- }
137
- };
138
- function normalizeWorkspaceInputs(workspace) {
139
- if (Array.isArray(workspace)) {
140
- if (workspace.length === 0) {
141
- throw new MissingWorkspaceInputError();
142
- }
143
- return workspace.map((value) => String(value));
144
- }
145
- if (workspace === void 0) return [process.cwd()];
146
- return [String(workspace)];
147
- }
148
- __name(normalizeWorkspaceInputs, "normalizeWorkspaceInputs");
149
- function isNestedWorkspace(parent, child) {
150
- return parent !== child && isWithinRoot(child, parent);
151
- }
152
- __name(isNestedWorkspace, "isNestedWorkspace");
153
- function rejectDuplicateOrNestedWorkspaceInputs(workspaces) {
154
- if (workspaces.length <= 1) return;
155
- let canonicalWorkspaces;
156
- try {
157
- canonicalWorkspaces = workspaces.map(
158
- (workspace) => canonicalizeWorkspace(workspace)
159
- );
160
- } catch {
161
- return;
162
- }
163
- const seen = /* @__PURE__ */ new Set();
164
- for (const workspace of canonicalWorkspaces) {
165
- if (seen.has(workspace)) {
166
- throw new DuplicateWorkspaceInputError(workspace);
167
- }
168
- seen.add(workspace);
169
- }
170
- for (let i = 0; i < canonicalWorkspaces.length; i++) {
171
- for (let j = i + 1; j < canonicalWorkspaces.length; j++) {
172
- const first = canonicalWorkspaces[i];
173
- const second = canonicalWorkspaces[j];
174
- if (isNestedWorkspace(first, second)) {
175
- throw new NestedWorkspaceInputError(first, second);
176
- }
177
- if (isNestedWorkspace(second, first)) {
178
- throw new NestedWorkspaceInputError(second, first);
179
- }
180
- }
181
- }
182
- }
183
- __name(rejectDuplicateOrNestedWorkspaceInputs, "rejectDuplicateOrNestedWorkspaceInputs");
184
- function resolveWorkspaceInputs(workspace) {
185
- const workspaces = normalizeWorkspaceInputs(workspace);
186
- rejectDuplicateOrNestedWorkspaceInputs(workspaces);
187
- return workspaces;
188
- }
189
- __name(resolveWorkspaceInputs, "resolveWorkspaceInputs");
190
-
191
124
  // packages/cli/src/serve/permission-audit.ts
192
125
  init_esbuild_shims();
193
126
  var DEFAULT_PERMISSION_AUDIT_RING_SIZE = 512;
@@ -885,6 +818,120 @@ function asRecord(value) {
885
818
  }
886
819
  __name(asRecord, "asRecord");
887
820
 
821
+ // packages/cli/src/serve/channel-workspace-grouping.ts
822
+ init_esbuild_shims();
823
+ function resolveChannelOwnerCwd(rawCwd, workspaceCwd) {
824
+ return canonicalizeWorkspace(resolveChannelCwd(rawCwd, workspaceCwd));
825
+ }
826
+ __name(resolveChannelOwnerCwd, "resolveChannelOwnerCwd");
827
+ function rawChannelCwd(entry) {
828
+ if (!entry || typeof entry !== "object") return void 0;
829
+ const cwd = entry.cwd;
830
+ return typeof cwd === "string" && cwd.length > 0 ? cwd : void 0;
831
+ }
832
+ __name(rawChannelCwd, "rawChannelCwd");
833
+ function resolveChannelWorkspaceGroups(input) {
834
+ const { workspaces, selection, loadChannelsConfig } = input;
835
+ const primary = workspaces.find((workspace) => workspace.primary);
836
+ if (!primary) {
837
+ return {
838
+ ok: false,
839
+ error: {
840
+ code: "no_primary_workspace",
841
+ message: "No primary workspace is registered."
842
+ }
843
+ };
844
+ }
845
+ if (selection.mode === "all") {
846
+ if (!primary.trusted) {
847
+ return {
848
+ ok: false,
849
+ error: {
850
+ code: "untrusted_workspace",
851
+ message: `Primary workspace "${primary.workspaceCwd}" is not trusted; cannot host channels.`
852
+ }
853
+ };
854
+ }
855
+ return {
856
+ ok: true,
857
+ groups: [
858
+ { workspaceCwd: primary.workspaceCwd, selection: { mode: "all" } }
859
+ ]
860
+ };
861
+ }
862
+ const channelsConfigByWorkspace = /* @__PURE__ */ new Map();
863
+ for (const workspace of workspaces) {
864
+ channelsConfigByWorkspace.set(
865
+ workspace.workspaceCwd,
866
+ loadChannelsConfig(workspace.workspaceCwd)
867
+ );
868
+ }
869
+ const namesByWorkspace = /* @__PURE__ */ new Map();
870
+ for (const name of selection.names) {
871
+ const owners = [];
872
+ for (const workspace of workspaces) {
873
+ const entry = (channelsConfigByWorkspace.get(workspace.workspaceCwd) ?? {})[name];
874
+ if (!entry || typeof entry !== "object") continue;
875
+ let ownerCwd;
876
+ try {
877
+ ownerCwd = resolveChannelOwnerCwd(
878
+ rawChannelCwd(entry),
879
+ workspace.workspaceCwd
880
+ );
881
+ } catch {
882
+ continue;
883
+ }
884
+ if (ownerCwd === workspace.workspaceCwd) {
885
+ owners.push(workspace);
886
+ }
887
+ }
888
+ if (owners.length === 0) {
889
+ return {
890
+ ok: false,
891
+ error: {
892
+ code: "channel_workspace_mismatch",
893
+ channel: name,
894
+ message: `Channel "${name}" is not configured in any registered workspace, or its "cwd" points outside them.`
895
+ }
896
+ };
897
+ }
898
+ if (owners.length > 1) {
899
+ return {
900
+ ok: false,
901
+ error: {
902
+ code: "ambiguous_channel_workspace",
903
+ channel: name,
904
+ message: `Channel "${name}" is configured in multiple registered workspaces (${owners.map((owner2) => owner2.workspaceCwd).join(
905
+ ", "
906
+ )}). Define it in one workspace's settings or set an explicit "cwd".`
907
+ }
908
+ };
909
+ }
910
+ const owner = owners[0];
911
+ if (!owner.trusted) {
912
+ return {
913
+ ok: false,
914
+ error: {
915
+ code: "untrusted_workspace",
916
+ channel: name,
917
+ message: `Channel "${name}" targets untrusted workspace "${owner.workspaceCwd}".`
918
+ }
919
+ };
920
+ }
921
+ const names = namesByWorkspace.get(owner.workspaceCwd) ?? [];
922
+ names.push(name);
923
+ namesByWorkspace.set(owner.workspaceCwd, names);
924
+ }
925
+ return {
926
+ ok: true,
927
+ groups: [...namesByWorkspace.entries()].map(([workspaceCwd, names]) => ({
928
+ workspaceCwd,
929
+ selection: { mode: "names", names }
930
+ }))
931
+ };
932
+ }
933
+ __name(resolveChannelWorkspaceGroups, "resolveChannelWorkspaceGroups");
934
+
888
935
  // packages/cli/src/serve/run-qwen-serve.ts
889
936
  var QWEN_SERVE_CLIENT_MCP_OVER_WS_ENV = "QWEN_SERVE_CLIENT_MCP_OVER_WS";
890
937
  var QWEN_SERVE_CDP_TUNNEL_OVER_WS_ENV = "QWEN_SERVE_CDP_TUNNEL_OVER_WS";
@@ -1074,6 +1121,10 @@ function extractContextFilename(value) {
1074
1121
  return void 0;
1075
1122
  }
1076
1123
  __name(extractContextFilename, "extractContextFilename");
1124
+ function sessionArtifactsPersistenceAvailableFromSettings(settings) {
1125
+ return settings?.general?.chatRecording !== false;
1126
+ }
1127
+ __name(sessionArtifactsPersistenceAvailableFromSettings, "sessionArtifactsPersistenceAvailableFromSettings");
1077
1128
  var settingsWriteLocks = /* @__PURE__ */ new Map();
1078
1129
  function withSettingsLock(workspace, fn) {
1079
1130
  const prev = settingsWriteLocks.get(workspace) ?? Promise.resolve();
@@ -1085,12 +1136,29 @@ __name(withSettingsLock, "withSettingsLock");
1085
1136
  var channelWorkerRuntimePromise;
1086
1137
  async function loadChannelWorkerRuntime() {
1087
1138
  channelWorkerRuntimePromise ??= Promise.all([
1088
- import("./channel-worker-supervisor-NZQUOEFJ.js"),
1089
- import("./pidfile-NZYSCFRK.js")
1090
- ]).then(([supervisor, pidfile]) => ({
1091
- createChannelWorkerSupervisor: supervisor.createChannelWorkerSupervisor,
1092
- channelServicePidfile: pidfile
1093
- })).catch((err) => {
1139
+ import("./channel-worker-supervisor-PCDAZN4D.js"),
1140
+ import("./pidfile-SIQGCFLZ.js"),
1141
+ import("./runtime-V3FBMUTG.js"),
1142
+ import("./cli-entry-path-4VJ3Y6T2.js"),
1143
+ import("./channel-worker-group-K7QKH6IG.js"),
1144
+ import("./channel-worker-manager-5RWKSGEU.js")
1145
+ ]).then(
1146
+ ([
1147
+ supervisor,
1148
+ pidfile,
1149
+ channelRuntime,
1150
+ cliEntryPath,
1151
+ workerGroup,
1152
+ workerManager
1153
+ ]) => ({
1154
+ createChannelWorkerSupervisor: supervisor.createChannelWorkerSupervisor,
1155
+ channelServicePidfile: pidfile,
1156
+ loadChannelsConfig: channelRuntime.loadChannelsConfig,
1157
+ createChannelWorkerGroup: workerGroup.createChannelWorkerGroup,
1158
+ createChannelWorkerManager: workerManager.createChannelWorkerManager,
1159
+ findCliEntryPath: cliEntryPath.findCliEntryPath
1160
+ })
1161
+ ).catch((err) => {
1094
1162
  channelWorkerRuntimePromise = void 0;
1095
1163
  throw err;
1096
1164
  });
@@ -1108,9 +1176,18 @@ function createDisabledChannelWorkerSupervisor() {
1108
1176
  },
1109
1177
  async stop() {
1110
1178
  },
1179
+ async restart() {
1180
+ return { ...snapshot, channels: [] };
1181
+ },
1111
1182
  killAllSync() {
1112
1183
  },
1113
- snapshot: /* @__PURE__ */ __name(() => ({ ...snapshot, channels: [] }), "snapshot")
1184
+ snapshot: /* @__PURE__ */ __name(() => ({ ...snapshot, channels: [] }), "snapshot"),
1185
+ async enqueueWebhookTask() {
1186
+ throw new ChannelWebhookEnqueueError(
1187
+ "channel_worker_unavailable",
1188
+ "Channel worker is not running."
1189
+ );
1190
+ }
1114
1191
  };
1115
1192
  }
1116
1193
  __name(createDisabledChannelWorkerSupervisor, "createDisabledChannelWorkerSupervisor");
@@ -1123,11 +1200,23 @@ function writeServeChannelReservation(channelServicePidfile, channels) {
1123
1200
  __name(writeServeChannelReservation, "writeServeChannelReservation");
1124
1201
  function channelServicePidfileConflictError(info) {
1125
1202
  const owner = info.owner === "serve" ? "qwen serve" : "qwen channel start";
1126
- return new Error(
1127
- `Channel service is already running under ${owner} (PID ${info.pid}). Stop it before starting qwen serve --channel.`
1203
+ return Object.assign(
1204
+ new Error(
1205
+ `Channel service is already running under ${owner} (PID ${info.pid}). Stop it before enabling daemon-managed channels.`
1206
+ ),
1207
+ { code: "channel_service_conflict", owner: info.owner, pid: info.pid }
1128
1208
  );
1129
1209
  }
1130
1210
  __name(channelServicePidfileConflictError, "channelServicePidfileConflictError");
1211
+ function channelServiceStartingConflictError() {
1212
+ return Object.assign(
1213
+ new Error(
1214
+ "Channel service is already starting. Retry after the current startup finishes."
1215
+ ),
1216
+ { code: "channel_service_conflict" }
1217
+ );
1218
+ }
1219
+ __name(channelServiceStartingConflictError, "channelServiceStartingConflictError");
1131
1220
  function normalizeInstallModelIds(req, provider, getDefaultModelIds) {
1132
1221
  const fromRequest = req.modelIds?.map((id) => id.trim()).filter((id) => id.length > 0);
1133
1222
  const modelIds = fromRequest && fromRequest.length > 0 ? fromRequest : getDefaultModelIds(provider);
@@ -1157,7 +1246,7 @@ function shouldPreheatBridge(deps) {
1157
1246
  __name(shouldPreheatBridge, "shouldPreheatBridge");
1158
1247
  var coreRuntimePromise;
1159
1248
  function loadCoreRuntime() {
1160
- coreRuntimePromise ??= import("./src-BBQSM46M.js");
1249
+ coreRuntimePromise ??= import("./src-55DZWDAK.js");
1161
1250
  return coreRuntimePromise;
1162
1251
  }
1163
1252
  __name(loadCoreRuntime, "loadCoreRuntime");
@@ -1187,10 +1276,10 @@ __name(resolveDaemonLogBaseDirForRun, "resolveDaemonLogBaseDirForRun");
1187
1276
  var settingsRuntimePromise;
1188
1277
  function loadSettingsRuntimeModules() {
1189
1278
  settingsRuntimePromise ??= Promise.all([
1190
- import("./settings-3MI4XXP6.js"),
1191
- import("./environment-ATFTYMLZ.js"),
1192
- import("./loadedSettingsAdapter-LL5PSFKX.js"),
1193
- import("./trustedFolders-LAZZPZ3D.js")
1279
+ import("./settings-IXF5FIQO.js"),
1280
+ import("./environment-YVMA5F4I.js"),
1281
+ import("./loadedSettingsAdapter-L4YKGU6F.js"),
1282
+ import("./trustedFolders-DOJDHNYP.js")
1194
1283
  ]).then(([settings, environment, loadedSettingsAdapter, trustedFolders]) => ({
1195
1284
  settings,
1196
1285
  environment,
@@ -1200,6 +1289,21 @@ function loadSettingsRuntimeModules() {
1200
1289
  return settingsRuntimePromise;
1201
1290
  }
1202
1291
  __name(loadSettingsRuntimeModules, "loadSettingsRuntimeModules");
1292
+ var channelWebhookConfigRuntimePromise;
1293
+ function loadChannelWebhookConfigRuntime() {
1294
+ channelWebhookConfigRuntimePromise ??= Promise.all([
1295
+ import("./runtime-V3FBMUTG.js"),
1296
+ import("./config-utils-CFT33LTP.js")
1297
+ ]).then(([channelRuntime, configUtils]) => ({
1298
+ loadChannelsConfig: channelRuntime.loadChannelsConfig,
1299
+ parseChannelWebhookConfig: configUtils.parseChannelWebhookConfig
1300
+ })).catch((err) => {
1301
+ channelWebhookConfigRuntimePromise = void 0;
1302
+ throw err;
1303
+ });
1304
+ return channelWebhookConfigRuntimePromise;
1305
+ }
1306
+ __name(loadChannelWebhookConfigRuntime, "loadChannelWebhookConfigRuntime");
1203
1307
  async function loadServeRuntimeModules() {
1204
1308
  const [
1205
1309
  serverModule,
@@ -1213,16 +1317,16 @@ async function loadServeRuntimeModules() {
1213
1317
  totalSessionAdmissionModule,
1214
1318
  workspaceRegistryModule
1215
1319
  ] = await Promise.all([
1216
- import("./server-SGNPKX2O.js"),
1217
- import("./bridge-NA3ZQQKJ.js"),
1218
- import("./spawnChannel-UNV6W4DU.js"),
1219
- import("./workspace-service-CZRQZ4Q4.js"),
1220
- import("./types-QX5C3CHJ.js"),
1221
- import("./daemon-status-provider-GJRXY5EN.js"),
1222
- import("./workspace-providers-status-3W7E7DFW.js"),
1223
- import("./workspace-skills-status-K7WFREPD.js"),
1224
- import("./total-session-admission-ULXJWXFV.js"),
1225
- import("./workspace-registry-SXJZNN3O.js")
1320
+ import("./server-AF6LNFPK.js"),
1321
+ import("./bridge-4OZH44MK.js"),
1322
+ import("./spawnChannel-IKX6DD7J.js"),
1323
+ import("./workspace-service-ERC5VR2B.js"),
1324
+ import("./types-JNKGKUJT.js"),
1325
+ import("./daemon-status-provider-SIBFMLBQ.js"),
1326
+ import("./workspace-providers-status-FA2DGEZW.js"),
1327
+ import("./workspace-skills-status-FKYWGNCN.js"),
1328
+ import("./total-session-admission-PJWGOMQE.js"),
1329
+ import("./workspace-registry-AGE7WAXX.js")
1226
1330
  ]);
1227
1331
  return {
1228
1332
  createServeApp: serverModule.createServeApp,
@@ -1237,7 +1341,8 @@ async function loadServeRuntimeModules() {
1237
1341
  createWorkspaceProvidersStatusProvider: workspaceProvidersStatusModule.createWorkspaceProvidersStatusProvider,
1238
1342
  createWorkspaceSkillsStatusProvider: workspaceSkillsStatusModule.createWorkspaceSkillsStatusProvider,
1239
1343
  createTotalSessionAdmissionController: totalSessionAdmissionModule.createTotalSessionAdmissionController,
1240
- createWorkspaceRegistry: workspaceRegistryModule.createWorkspaceRegistry
1344
+ createWorkspaceRegistry: workspaceRegistryModule.createWorkspaceRegistry,
1345
+ createWorkspaceSessionOwnerIndex: workspaceRegistryModule.createWorkspaceSessionOwnerIndex
1241
1346
  };
1242
1347
  }
1243
1348
  __name(loadServeRuntimeModules, "loadServeRuntimeModules");
@@ -1261,7 +1366,7 @@ function sessionIdleTimeoutMs(value) {
1261
1366
  return value !== void 0 ? channelIdleTimeoutMs(value) : DEFAULT_SESSION_IDLE_TIMEOUT_MS;
1262
1367
  }
1263
1368
  __name(sessionIdleTimeoutMs, "sessionIdleTimeoutMs");
1264
- function currentServeFeaturesForRunQwenServe(opts, sessionShellCommandEnabled) {
1369
+ function currentServeFeaturesForRunQwenServe(opts, sessionShellCommandEnabled, sessionArtifactsPersistenceAvailable, env) {
1265
1370
  return getAdvertisedServeFeatures(void 0, {
1266
1371
  requireAuth: opts.requireAuth === true,
1267
1372
  mcpPoolActive: opts.mcpPoolActive !== false,
@@ -1270,12 +1375,18 @@ function currentServeFeaturesForRunQwenServe(opts, sessionShellCommandEnabled) {
1270
1375
  ...opts.writerIdleTimeoutMs !== void 0 ? { writerIdleTimeoutMs: opts.writerIdleTimeoutMs } : {},
1271
1376
  persistSettingAvailable: true,
1272
1377
  sessionShellCommandEnabled,
1378
+ sessionArtifactsPersistenceAvailable,
1273
1379
  rateLimit: opts.rateLimit === true,
1274
1380
  reloadAvailable: true,
1381
+ channelReloadAvailable: opts.channelSelection !== void 0,
1382
+ channelControlAvailable: true,
1383
+ persistentWorkspaceRegistrationAvailable: true,
1384
+ workspaceRuntimeRemovalAvailable: true,
1275
1385
  // Advertise the same WS feature flags as the runtime path (serve-features.ts)
1276
1386
  // so the bootstrap `/capabilities` window doesn't briefly under-report them.
1277
1387
  clientMcpOverWsEnabled: opts.clientMcpOverWs === true,
1278
- cdpTunnelOverWsEnabled: opts.cdpTunnelOverWs === true
1388
+ cdpTunnelOverWsEnabled: opts.cdpTunnelOverWs === true,
1389
+ browserAutomationMcpAvailable: isBrowserAutomationMcpAvailable(opts, env)
1279
1390
  });
1280
1391
  }
1281
1392
  __name(currentServeFeaturesForRunQwenServe, "currentServeFeaturesForRunQwenServe");
@@ -1287,7 +1398,9 @@ function createBootstrapCapabilities(input) {
1287
1398
  mode: input.opts.mode,
1288
1399
  features: currentServeFeaturesForRunQwenServe(
1289
1400
  input.opts,
1290
- input.sessionShellCommandEnabled
1401
+ input.sessionShellCommandEnabled,
1402
+ input.sessionArtifactsPersistenceAvailable,
1403
+ input.env
1291
1404
  ),
1292
1405
  modelServices: [],
1293
1406
  workspaceCwd: input.boundWorkspace,
@@ -1432,10 +1545,12 @@ function createBootstrapServeApp(input) {
1432
1545
  daemonLog,
1433
1546
  qwenCodeVersion,
1434
1547
  sessionShellCommandEnabled,
1548
+ sessionArtifactsPersistenceAvailable,
1435
1549
  permissionPolicy,
1436
1550
  multiWorkspaceCapabilitiesRequireRuntime,
1437
1551
  getRuntimeError,
1438
1552
  getChannelWorkerSnapshot,
1553
+ getChannelWorkerSnapshots,
1439
1554
  onHealthServed
1440
1555
  } = input;
1441
1556
  const app = (0, import_express.default)();
@@ -1487,7 +1602,9 @@ function createBootstrapServeApp(input) {
1487
1602
  boundWorkspace,
1488
1603
  qwenCodeVersion,
1489
1604
  sessionShellCommandEnabled,
1490
- permissionPolicy
1605
+ sessionArtifactsPersistenceAvailable,
1606
+ permissionPolicy,
1607
+ env: process.env
1491
1608
  })
1492
1609
  );
1493
1610
  });
@@ -1502,6 +1619,7 @@ function createBootstrapServeApp(input) {
1502
1619
  }
1503
1620
  const runtimeError = getRuntimeError();
1504
1621
  const channelWorker = getChannelWorkerSnapshot();
1622
+ const channelWorkers = getChannelWorkerSnapshots();
1505
1623
  const runtimeFailed = runtimeError !== void 0;
1506
1624
  const issue = runtimeError ? {
1507
1625
  code: "daemon_runtime_failed",
@@ -1558,7 +1676,9 @@ function createBootstrapServeApp(input) {
1558
1676
  protocolVersions: getServeProtocolVersions(),
1559
1677
  features: currentServeFeaturesForRunQwenServe(
1560
1678
  opts,
1561
- sessionShellCommandEnabled
1679
+ sessionShellCommandEnabled,
1680
+ sessionArtifactsPersistenceAvailable,
1681
+ process.env
1562
1682
  )
1563
1683
  },
1564
1684
  runtime: {
@@ -1571,6 +1691,7 @@ function createBootstrapServeApp(input) {
1571
1691
  },
1572
1692
  channel: { live: false },
1573
1693
  channelWorker,
1694
+ ...channelWorkers.length > 0 ? { channelWorkers } : {},
1574
1695
  transport: {
1575
1696
  restSseActive: 0,
1576
1697
  acp: {
@@ -1630,13 +1751,12 @@ function createDelegatingServeApp(bootstrapApp, getRuntimeApp, options = {}) {
1630
1751
  const dispatch = /* @__PURE__ */ __name(async () => {
1631
1752
  let target = getRuntimeApp();
1632
1753
  if (!target && options.waitForDeferredRuntimeRoutes === true && !isBootstrapServeRoute(req) && !isCorsPreflightRequest(req) && options.startRuntime && options.runtimeReady) {
1633
- if (options.authenticateDeferredRuntimeRequest && !runSynchronousRequestGate(
1634
- options.authenticateDeferredRuntimeRequest,
1635
- req,
1636
- res,
1637
- next
1638
- )) {
1639
- return;
1754
+ const webhookRequest = isChannelWebhookRequest(req);
1755
+ const authGate = webhookRequest ? options.authenticateDeferredChannelWebhookRequest ?? options.authenticateDeferredRuntimeRequest : options.authenticateDeferredRuntimeRequest;
1756
+ if (authGate) {
1757
+ if (!runSynchronousRequestGate(authGate, req, res, next)) {
1758
+ return;
1759
+ }
1640
1760
  }
1641
1761
  options.startRuntime();
1642
1762
  try {
@@ -1658,6 +1778,83 @@ function isBootstrapServeRoute(req) {
1658
1778
  return BOOTSTRAP_SERVE_PATHS.has(path2);
1659
1779
  }
1660
1780
  __name(isBootstrapServeRoute, "isBootstrapServeRoute");
1781
+ function isChannelWebhookRequest(req) {
1782
+ return req.method === "POST" && /^\/channels\/[^/]+\/webhooks\/[^/]+\/?$/u.test(req.path);
1783
+ }
1784
+ __name(isChannelWebhookRequest, "isChannelWebhookRequest");
1785
+ function createDeferredChannelWebhookAuth(resolveSource, runtime, daemonLog) {
1786
+ return (req, res, next) => {
1787
+ const match = /^\/channels\/([^/]+)\/webhooks\/([^/]+)\/?$/u.exec(req.path);
1788
+ const channelName = decodeDeferredWebhookPathSegment(match?.[1]);
1789
+ const source = decodeDeferredWebhookPathSegment(match?.[2]);
1790
+ if (!channelName || !source) {
1791
+ daemonLog.warn("deferred webhook auth failed", {
1792
+ channelName: channelName ?? "unknown",
1793
+ source: source ?? "unknown",
1794
+ reason: "invalid webhook path"
1795
+ });
1796
+ res.status(401).json({ error: "Invalid webhook secret" });
1797
+ return;
1798
+ }
1799
+ const configSource = resolveSource(channelName);
1800
+ const secret = readDeferredWebhookSecret(
1801
+ runtime,
1802
+ configSource.workspaceCwd,
1803
+ channelName,
1804
+ source,
1805
+ configSource.env
1806
+ );
1807
+ if (!matchesWebhookSecret(req.get("x-qwen-webhook-secret"), secret)) {
1808
+ daemonLog.warn("deferred webhook auth failed", {
1809
+ channelName,
1810
+ source,
1811
+ reason: secret ? "secret mismatch" : "source not configured"
1812
+ });
1813
+ res.status(401).json({ error: "Invalid webhook secret" });
1814
+ return;
1815
+ }
1816
+ next();
1817
+ };
1818
+ }
1819
+ __name(createDeferredChannelWebhookAuth, "createDeferredChannelWebhookAuth");
1820
+ function decodeDeferredWebhookPathSegment(segment) {
1821
+ if (segment === void 0) return void 0;
1822
+ try {
1823
+ return decodeURIComponent(segment);
1824
+ } catch {
1825
+ return void 0;
1826
+ }
1827
+ }
1828
+ __name(decodeDeferredWebhookPathSegment, "decodeDeferredWebhookPathSegment");
1829
+ function readDeferredWebhookSecret(runtime, workspace, channelName, source, env) {
1830
+ try {
1831
+ const rawConfig = runtime.loadChannelsConfig(workspace)[channelName];
1832
+ if (typeof rawConfig !== "object" || rawConfig === null) {
1833
+ return void 0;
1834
+ }
1835
+ return runtime.parseChannelWebhookConfig(
1836
+ channelName,
1837
+ rawConfig,
1838
+ env
1839
+ )?.sources[source]?.secret;
1840
+ } catch (err) {
1841
+ const reason = err instanceof Error ? err.message : String(err);
1842
+ writeStderrLine(
1843
+ `[webhook-secret] failed to read deferred webhook secret for ${sanitizeLogText(channelName, 128)}/${sanitizeLogText(source, 128)}: ${sanitizeLogText(reason, 512)}`
1844
+ );
1845
+ return void 0;
1846
+ }
1847
+ }
1848
+ __name(readDeferredWebhookSecret, "readDeferredWebhookSecret");
1849
+ function matchesWebhookSecret(candidate, expected) {
1850
+ if (typeof candidate !== "string" || typeof expected !== "string" || expected.length === 0) {
1851
+ return false;
1852
+ }
1853
+ const expectedDigest = createHash2("sha256").update(expected).digest();
1854
+ const candidateDigest = createHash2("sha256").update(candidate).digest();
1855
+ return timingSafeEqual(expectedDigest, candidateDigest);
1856
+ }
1857
+ __name(matchesWebhookSecret, "matchesWebhookSecret");
1661
1858
  function isCorsPreflightRequest(req) {
1662
1859
  return req.method === "OPTIONS" && Boolean(req.headers.origin) && Boolean(
1663
1860
  req.headers["access-control-request-method"] || req.headers["access-control-request-headers"]
@@ -1723,30 +1920,42 @@ async function runQwenServe(optsIn, deps = {}) {
1723
1920
  clientMcpOverWs: optsIn.clientMcpOverWs ?? (!envFlagDisabled(clientMcpOverWsEnv) && clientMcpOverWsEnv !== void 0),
1724
1921
  cdpTunnelOverWs: optsIn.cdpTunnelOverWs ?? (!envFlagDisabled(cdpTunnelOverWsEnv) && (cdpTunnelOverWsEnv !== void 0 || chromeExtensionOriginAllowed))
1725
1922
  };
1726
- const channelRuntime = opts.channelSelection ? await loadChannelWorkerRuntime() : void 0;
1727
- const channelServicePidfile = deps.channelServicePidfile ?? channelRuntime?.channelServicePidfile;
1923
+ let channelRuntime = opts.channelSelection ? await loadChannelWorkerRuntime() : void 0;
1924
+ let channelServicePidfile = deps.channelServicePidfile ?? channelRuntime?.channelServicePidfile;
1925
+ const ensureChannelRuntime = /* @__PURE__ */ __name(async () => {
1926
+ channelRuntime ??= await loadChannelWorkerRuntime();
1927
+ channelServicePidfile ??= channelRuntime.channelServicePidfile;
1928
+ return channelRuntime;
1929
+ }, "ensureChannelRuntime");
1728
1930
  let channelPidfileReserved = false;
1729
1931
  const removeCurrentServePidfile = /* @__PURE__ */ __name(() => {
1730
- if (!opts.channelSelection || !channelServicePidfile) return;
1932
+ if (!channelServicePidfile) return;
1731
1933
  if (!channelPidfileReserved) return;
1732
1934
  if (channelServicePidfile.removeServeServiceInfo) {
1733
1935
  if (channelServicePidfile.removeServeServiceInfo(process.pid)) {
1734
1936
  channelPidfileReserved = false;
1937
+ } else {
1938
+ const info2 = channelServicePidfile.readServiceInfo();
1939
+ if (!info2 || info2.owner !== "serve" || info2.pid !== process.pid || info2.servePid !== process.pid) {
1940
+ channelPidfileReserved = false;
1941
+ }
1735
1942
  }
1736
1943
  return;
1737
1944
  }
1738
1945
  const info = channelServicePidfile.readServiceInfo();
1739
1946
  if (info?.owner === "serve" && info.pid === process.pid && info.servePid === process.pid) {
1740
1947
  channelServicePidfile.removeServiceInfo();
1948
+ const remaining = channelServicePidfile.readServiceInfo();
1949
+ channelPidfileReserved = remaining?.owner === "serve" && remaining.pid === process.pid && remaining.servePid === process.pid;
1950
+ } else {
1741
1951
  channelPidfileReserved = false;
1742
1952
  }
1743
1953
  }, "removeCurrentServePidfile");
1744
- const reserveChannelServicePidfile = /* @__PURE__ */ __name(() => {
1745
- if (!opts.channelSelection) return;
1954
+ const reserveChannelServicePidfile = /* @__PURE__ */ __name((selection) => {
1746
1955
  if (!channelServicePidfile) {
1747
1956
  throw new Error("Channel service pidfile runtime is not available.");
1748
1957
  }
1749
- const channelPidfileNames = channelSelectionNames(opts.channelSelection);
1958
+ const channelPidfileNames = channelSelectionNames(selection);
1750
1959
  const existingChannelService = channelServicePidfile.readServiceInfo();
1751
1960
  if (existingChannelService) {
1752
1961
  throw channelServicePidfileConflictError(existingChannelService);
@@ -1771,9 +1980,7 @@ async function runQwenServe(optsIn, deps = {}) {
1771
1980
  return;
1772
1981
  } catch (retryErr) {
1773
1982
  if (retryErr && typeof retryErr === "object" && "code" in retryErr && retryErr.code === "EEXIST") {
1774
- throw new Error(
1775
- "Channel service is already starting. Retry after the current startup finishes."
1776
- );
1983
+ throw channelServiceStartingConflictError();
1777
1984
  }
1778
1985
  throw retryErr;
1779
1986
  }
@@ -1892,7 +2099,9 @@ async function runQwenServe(optsIn, deps = {}) {
1892
2099
  }, "validateAndCanonicalizeWorkspace");
1893
2100
  const workspaceInputs = rawWorkspaces.map((workspace) => ({
1894
2101
  raw: workspace,
1895
- cwd: validateAndCanonicalizeWorkspace(workspace)
2102
+ cwd: validateAndCanonicalizeWorkspace(workspace),
2103
+ removable: false,
2104
+ registrationIds: []
1896
2105
  }));
1897
2106
  const boundWorkspace = workspaceInputs[0].cwd;
1898
2107
  const seenCanonicalWorkspaces = /* @__PURE__ */ new Set();
@@ -1924,6 +2133,71 @@ async function runQwenServe(optsIn, deps = {}) {
1924
2133
  }
1925
2134
  }
1926
2135
  }
2136
+ if (workspaceInputs.length > MAX_REGISTERED_WORKSPACES) {
2137
+ throw new Error(
2138
+ `At most ${MAX_REGISTERED_WORKSPACES} --workspace values may be registered.`
2139
+ );
2140
+ }
2141
+ let workspaceRegistrationStore = deps.workspaceRegistrationStore;
2142
+ if (workspaceRegistrationStore === void 0 && process.env["QWEN_SERVE_NO_PERSISTENT_REGISTRATION"] !== "1") {
2143
+ const { WorkspaceRegistrationStore } = await import("./workspace-registration-store-TARTAGMI.js");
2144
+ workspaceRegistrationStore = new WorkspaceRegistrationStore(boundWorkspace);
2145
+ }
2146
+ if (workspaceRegistrationStore) {
2147
+ try {
2148
+ const stored = await workspaceRegistrationStore.read();
2149
+ for (const storedWorkspace of stored.workspaces) {
2150
+ const registrationId = workspaceRegistrationId(storedWorkspace);
2151
+ let cwd;
2152
+ try {
2153
+ cwd = validateAndCanonicalizeWorkspace(storedWorkspace);
2154
+ } catch (err) {
2155
+ writeStderrLine(
2156
+ `qwen serve: skipping persisted workspace registration ${JSON.stringify(
2157
+ storedWorkspace
2158
+ )}: ${err instanceof Error ? err.message : String(err)}`
2159
+ );
2160
+ continue;
2161
+ }
2162
+ const existingInput = workspaceInputs.find(
2163
+ (workspace) => workspace.cwd === cwd
2164
+ );
2165
+ if (existingInput) {
2166
+ existingInput.registrationIds.push(registrationId);
2167
+ continue;
2168
+ }
2169
+ const nested = workspaceInputs.some(
2170
+ (workspace) => isWithinRoot(cwd, workspace.cwd) || isWithinRoot(workspace.cwd, cwd)
2171
+ );
2172
+ if (nested) {
2173
+ writeStderrLine(
2174
+ `qwen serve: skipping persisted workspace registration ${JSON.stringify(
2175
+ storedWorkspace
2176
+ )}: path nests with an explicit or earlier restored workspace`
2177
+ );
2178
+ continue;
2179
+ }
2180
+ if (workspaceInputs.length >= MAX_REGISTERED_WORKSPACES) {
2181
+ writeStderrLine(
2182
+ `qwen serve: skipping persisted workspace registration ${JSON.stringify(
2183
+ storedWorkspace
2184
+ )}: workspace limit reached`
2185
+ );
2186
+ continue;
2187
+ }
2188
+ workspaceInputs.push({
2189
+ raw: storedWorkspace,
2190
+ cwd,
2191
+ removable: true,
2192
+ registrationIds: [registrationId]
2193
+ });
2194
+ }
2195
+ } catch (err) {
2196
+ writeStderrLine(
2197
+ `qwen serve: failed to read persisted workspace registrations: ${err instanceof Error ? err.message : String(err)}; continuing with explicit workspaces only`
2198
+ );
2199
+ }
2200
+ }
1927
2201
  if (workspaceInputs.length > 1 && deps.bridge) {
1928
2202
  throw new Error(
1929
2203
  "Injected bridge dependencies are only supported with a single workspace; multiple --workspace values require runQwenServe to construct one bridge per workspace."
@@ -1933,8 +2207,10 @@ async function runQwenServe(optsIn, deps = {}) {
1933
2207
  let permissionPolicy;
1934
2208
  let permissionConsensusQuorum;
1935
2209
  let bootSettings;
2210
+ let sessionArtifactsPersistenceAvailable = true;
1936
2211
  try {
1937
2212
  bootSettings = deps.bootSettings ?? loadServeFastPathSettings(boundWorkspace);
2213
+ sessionArtifactsPersistenceAvailable = sessionArtifactsPersistenceAvailableFromSettings(bootSettings);
1938
2214
  contextFilenameForInit = extractContextFilename(
1939
2215
  bootSettings.context?.fileName
1940
2216
  );
@@ -2112,15 +2388,120 @@ async function runQwenServe(optsIn, deps = {}) {
2112
2388
  daemonMetricsSampler?.dispose();
2113
2389
  daemonMetricsSampler = void 0;
2114
2390
  }, "disposeDaemonEventLoopMonitor");
2115
- let channelWorker = createDisabledChannelWorkerSupervisor();
2116
- const getChannelWorkerSnapshot = /* @__PURE__ */ __name(() => channelWorker.snapshot(), "getChannelWorkerSnapshot");
2117
- const writeChannelWorkerPidfile = /* @__PURE__ */ __name((snapshot = channelWorker.snapshot(), options = {}) => {
2118
- if (!opts.channelSelection || !channelServicePidfile) return;
2391
+ let channelWorkerManager;
2392
+ let channelWorkerManagerStarting;
2393
+ let channelControlDraining = false;
2394
+ let channelWorkspaceGroups;
2395
+ const channelWebhookEnvByWorkspace = /* @__PURE__ */ new Map();
2396
+ let channelWebhookConfigVersion = 0;
2397
+ let refreshChannelWebhookConfigs;
2398
+ let ensureChannelWorkerManager;
2399
+ const getChannelWebhookConfigSources = /* @__PURE__ */ __name(() => {
2400
+ const app2 = runtimeApp ?? runtimeAppForCleanup;
2401
+ const registry = app2?.locals?.["workspaceRegistry"];
2402
+ return (channelWorkspaceGroups ?? []).map((group) => {
2403
+ const env = registry?.getByWorkspaceCwd(group.workspaceCwd)?.env.effectiveEnv ?? channelWebhookEnvByWorkspace.get(group.workspaceCwd);
2404
+ return {
2405
+ workspaceCwd: group.workspaceCwd,
2406
+ ...group.selection.mode === "names" ? { channelNames: group.selection.names } : {},
2407
+ ...env ? { env } : {}
2408
+ };
2409
+ });
2410
+ }, "getChannelWebhookConfigSources");
2411
+ const resolveChannelWebhookConfigSource = /* @__PURE__ */ __name((channelName) => {
2412
+ const source = getChannelWebhookConfigSources().find(
2413
+ (source2) => !source2.channelNames || source2.channelNames.includes(channelName)
2414
+ );
2415
+ if (source) return source;
2416
+ const env = channelWebhookEnvByWorkspace.get(boundWorkspace);
2417
+ return {
2418
+ workspaceCwd: boundWorkspace,
2419
+ ...env ? { env } : {}
2420
+ };
2421
+ }, "resolveChannelWebhookConfigSource");
2422
+ let closeServerAfterChannelWorkerStartupFailure = false;
2423
+ let runtimeFailureListenerClose;
2424
+ const getChannelWorkerSnapshot = /* @__PURE__ */ __name(() => channelWorkerManager?.primarySnapshot() ?? {
2425
+ enabled: false,
2426
+ state: "disabled",
2427
+ channels: []
2428
+ }, "getChannelWorkerSnapshot");
2429
+ const getChannelWorkerSnapshots = /* @__PURE__ */ __name(() => channelWorkerManager?.snapshots() ?? [], "getChannelWorkerSnapshots");
2430
+ const getChannelWorkerControl = /* @__PURE__ */ __name(() => channelWorkerManager?.state() ?? {
2431
+ enabled: false,
2432
+ selection: null,
2433
+ transition: "idle",
2434
+ workers: []
2435
+ }, "getChannelWorkerControl");
2436
+ const daemonDrainingError = /* @__PURE__ */ __name(() => Object.assign(new Error("Daemon is shutting down."), {
2437
+ code: "daemon_draining"
2438
+ }), "daemonDrainingError");
2439
+ const setChannelWorkerSelection = /* @__PURE__ */ __name(async (selection) => {
2440
+ if (channelControlDraining) throw daemonDrainingError();
2441
+ const manager = await ensureChannelWorkerManager?.();
2442
+ if (!manager) throw new Error("Channel worker manager is unavailable.");
2443
+ if (channelControlDraining) {
2444
+ await manager.shutdown().catch(() => void 0);
2445
+ throw daemonDrainingError();
2446
+ }
2447
+ return manager.setSelection(selection);
2448
+ }, "setChannelWorkerSelection");
2449
+ const stopChannelWorker = /* @__PURE__ */ __name(async () => {
2450
+ if (channelControlDraining) throw daemonDrainingError();
2451
+ const manager = channelWorkerManager ?? await channelWorkerManagerStarting;
2452
+ if (channelControlDraining) {
2453
+ await manager?.shutdown().catch(() => void 0);
2454
+ throw daemonDrainingError();
2455
+ }
2456
+ if (!manager) {
2457
+ return { changed: false, state: getChannelWorkerControl() };
2458
+ }
2459
+ return manager.stopSelection();
2460
+ }, "stopChannelWorker");
2461
+ const reloadChannelWorker = /* @__PURE__ */ __name(async () => {
2462
+ if (channelControlDraining) throw daemonDrainingError();
2463
+ const manager = channelWorkerManager ?? await channelWorkerManagerStarting;
2464
+ if (channelControlDraining) {
2465
+ await manager?.shutdown().catch(() => void 0);
2466
+ throw daemonDrainingError();
2467
+ }
2468
+ if (!manager) {
2469
+ return { enabled: false, state: "disabled", channels: [] };
2470
+ }
2471
+ try {
2472
+ return await manager.reload();
2473
+ } finally {
2474
+ writeChannelWorkerPidfile();
2475
+ }
2476
+ }, "reloadChannelWorker");
2477
+ const isLiveWorker = /* @__PURE__ */ __name((snapshot) => snapshot.state === "running" || snapshot.state === "starting", "isLiveWorker");
2478
+ let channelWorkerPidfileUsesWorkers = workspaceInputs.length > 1;
2479
+ const writeChannelWorkerPidfile = /* @__PURE__ */ __name(() => {
2480
+ if (runtimeStartupError !== void 0) return;
2481
+ if (!channelPidfileReserved || !channelServicePidfile) return;
2482
+ const snapshots = getChannelWorkerSnapshots();
2483
+ const workers = snapshots.map((snapshot) => ({
2484
+ workspaceId: snapshot.workspaceId,
2485
+ workspaceCwd: snapshot.workspaceCwd,
2486
+ channels: snapshot.channels,
2487
+ // Drop a stale pid (worker exited/failed/stopped) so readers never signal
2488
+ // a dead process — mirrors the pre-4b clear-on-exit behavior.
2489
+ ...isLiveWorker(snapshot) && snapshot.pid !== void 0 ? { workerPid: snapshot.pid } : {}
2490
+ }));
2491
+ const channels = [
2492
+ ...new Set(snapshots.flatMap((snapshot) => snapshot.channels))
2493
+ ];
2494
+ const primary = snapshots.find((snapshot) => snapshot.primary);
2495
+ if (workers.length > 1 || snapshots.some((snapshot) => !snapshot.primary)) {
2496
+ channelWorkerPidfileUsesWorkers = true;
2497
+ }
2498
+ const includeWorkers = channelWorkerPidfileUsesWorkers && workers.length > 0;
2119
2499
  try {
2120
2500
  channelServicePidfile.writeServeServiceInfo({
2121
- channels: snapshot.channels,
2501
+ channels,
2122
2502
  servePid: process.pid,
2123
- ...!options.clearWorkerPid && snapshot.pid !== void 0 ? { workerPid: snapshot.pid } : {}
2503
+ ...primary && isLiveWorker(primary) && primary.pid !== void 0 ? { workerPid: primary.pid } : {},
2504
+ ...includeWorkers ? { workers } : {}
2124
2505
  });
2125
2506
  } catch (err) {
2126
2507
  daemonLog.warn(
@@ -2137,7 +2518,7 @@ async function runQwenServe(optsIn, deps = {}) {
2137
2518
  const appForCleanup = runtimeApp ?? runtimeAppForCleanup;
2138
2519
  const registry = appForCleanup?.locals?.["workspaceRegistry"];
2139
2520
  const bridges = [
2140
- ...registry ? registry.list().map((runtime) => runtime.bridge) : [],
2521
+ ...registry ? registry.listManaged().map((runtime) => runtime.bridge) : [],
2141
2522
  ...bridgeRef ? [bridgeRef] : [],
2142
2523
  ...internalRuntimeBridgesForCleanup
2143
2524
  ];
@@ -2414,6 +2795,7 @@ async function runQwenServe(optsIn, deps = {}) {
2414
2795
  getBridges: /* @__PURE__ */ __name(() => runtimeBridges.length > 0 ? runtimeBridges : bridgeRef ? [bridgeRef] : [], "getBridges")
2415
2796
  }
2416
2797
  );
2798
+ const sessionOwnerIndex = runtime.createWorkspaceSessionOwnerIndex();
2417
2799
  const persistDisabledToolsFn = /* @__PURE__ */ __name((workspace, toolName, enabled) => withSettingsLock(workspace, async () => {
2418
2800
  const fresh = settingsRuntime.settings.loadSettings(workspace);
2419
2801
  const wsScope = fresh.forScope(WORKSPACE_SETTING_SCOPE).settings;
@@ -2460,12 +2842,19 @@ async function runQwenServe(optsIn, deps = {}) {
2460
2842
  );
2461
2843
  }
2462
2844
  }), "persistSettingsFn");
2845
+ const { createSubSessionLauncher } = await import("./create-sub-session-TCLIYVGR.js");
2846
+ const subSessionLauncher = createSubSessionLauncher({
2847
+ getBridge: /* @__PURE__ */ __name(() => bridgeRef, "getBridge"),
2848
+ boundWorkspace
2849
+ });
2463
2850
  const bridge = deps.bridge ?? runtime.createAcpSessionBridge({
2464
2851
  // Reverse tool channel: let `BridgeClient.extMethod` reach the WS
2465
2852
  // connection that hosts a named client MCP server (#5626).
2466
2853
  clientMcpSender: clientMcpSenderRegistry.lookup,
2854
+ onCreateSubSession: subSessionLauncher.launch,
2467
2855
  maxSessions: opts.maxSessions,
2468
2856
  freshSessionAdmission: totalSessionAdmission.admit,
2857
+ sessionLifecycle: sessionOwnerIndex.handleBridgeSessionLifecycle,
2469
2858
  ...opts.maxPendingPromptsPerSession !== void 0 ? { maxPendingPromptsPerSession: opts.maxPendingPromptsPerSession } : {},
2470
2859
  ...opts.eventRingSize !== void 0 ? { eventRingSize: opts.eventRingSize } : {},
2471
2860
  ...opts.compactedReplayMaxBytes !== void 0 ? { compactedReplayMaxBytes: opts.compactedReplayMaxBytes } : {},
@@ -2504,6 +2893,7 @@ async function runQwenServe(optsIn, deps = {}) {
2504
2893
  persistDisabledTools: persistDisabledToolsFn,
2505
2894
  persistSetting: persistSettingFn,
2506
2895
  persistSettings: persistSettingsFn,
2896
+ preheatAcpChild: /* @__PURE__ */ __name(() => bridge.preheat(), "preheatAcpChild"),
2507
2897
  reloadDaemonEnv: /* @__PURE__ */ __name((workspace) => withSettingsLock(workspace, async () => {
2508
2898
  const fresh = settingsRuntime.settings.loadSettings(workspace, {
2509
2899
  skipLoadEnvironment: true
@@ -2574,6 +2964,8 @@ async function runQwenServe(optsIn, deps = {}) {
2574
2964
  workspaceCwd: boundWorkspace,
2575
2965
  primary: true,
2576
2966
  trusted: trustedWorkspace,
2967
+ removable: false,
2968
+ registrationIds: workspaceInputs[0]?.registrationIds ?? [],
2577
2969
  env: primaryRuntimeEnv,
2578
2970
  bridge,
2579
2971
  workspaceService,
@@ -2614,6 +3006,13 @@ async function runQwenServe(optsIn, deps = {}) {
2614
3006
  }
2615
3007
  };
2616
3008
  }, "createRuntimeEnvMetadata");
3009
+ const subSessionStoppers = [];
3010
+ const subSessionStoppersByWorkspace = /* @__PURE__ */ new Map();
3011
+ const runtimeCleanupPromises = /* @__PURE__ */ new WeakMap();
3012
+ const removeArrayValue = /* @__PURE__ */ __name((values, value) => {
3013
+ const index = values.indexOf(value);
3014
+ if (index >= 0) values.splice(index, 1);
3015
+ }, "removeArrayValue");
2617
3016
  for (const workspaceInput of workspaceInputs.slice(1)) {
2618
3017
  let secondarySettings;
2619
3018
  try {
@@ -2667,10 +3066,17 @@ async function runQwenServe(optsIn, deps = {}) {
2667
3066
  ...opts.experimentalLsp === true ? { extraArgs: ["--experimental-lsp"] } : {}
2668
3067
  });
2669
3068
  const secondaryClientMcpSenderRegistry = new ClientMcpSenderRegistry();
3069
+ let secondaryBridgeRef;
3070
+ const secondarySubSessionLauncher = createSubSessionLauncher({
3071
+ getBridge: /* @__PURE__ */ __name(() => secondaryBridgeRef, "getBridge"),
3072
+ boundWorkspace: workspaceInput.cwd
3073
+ });
2670
3074
  const secondaryBridge = runtime.createAcpSessionBridge({
2671
3075
  clientMcpSender: secondaryClientMcpSenderRegistry.lookup,
3076
+ onCreateSubSession: secondarySubSessionLauncher.launch,
2672
3077
  maxSessions: opts.maxSessions,
2673
3078
  freshSessionAdmission: totalSessionAdmission.admit,
3079
+ sessionLifecycle: sessionOwnerIndex.handleBridgeSessionLifecycle,
2674
3080
  ...opts.maxPendingPromptsPerSession !== void 0 ? { maxPendingPromptsPerSession: opts.maxPendingPromptsPerSession } : {},
2675
3081
  ...opts.eventRingSize !== void 0 ? { eventRingSize: opts.eventRingSize } : {},
2676
3082
  ...opts.compactedReplayMaxBytes !== void 0 ? { compactedReplayMaxBytes: opts.compactedReplayMaxBytes } : {},
@@ -2696,8 +3102,14 @@ async function runQwenServe(optsIn, deps = {}) {
2696
3102
  fresh.setValue(WORKSPACE_SETTING_SCOPE, "tools.approvalMode", mode);
2697
3103
  }), "persistApprovalMode")
2698
3104
  });
3105
+ secondaryBridgeRef = secondaryBridge;
2699
3106
  runtimeBridges.push(secondaryBridge);
2700
3107
  internalRuntimeBridgesForCleanup.push(secondaryBridge);
3108
+ subSessionStoppers.push(secondarySubSessionLauncher.stop);
3109
+ subSessionStoppersByWorkspace.set(
3110
+ workspaceInput.cwd,
3111
+ secondarySubSessionLauncher.stop
3112
+ );
2701
3113
  const secondaryWorkspaceService = runtime.createDaemonWorkspaceService({
2702
3114
  boundWorkspace: workspaceInput.cwd,
2703
3115
  contextFilename: contextFilenameForInit ?? "QWEN.md",
@@ -2707,6 +3119,7 @@ async function runQwenServe(optsIn, deps = {}) {
2707
3119
  }),
2708
3120
  workspaceSkillsStatusProvider: runtime.createWorkspaceSkillsStatusProvider(),
2709
3121
  isChannelLive: /* @__PURE__ */ __name(() => secondaryBridge.isChannelLive(), "isChannelLive"),
3122
+ preheatAcpChild: /* @__PURE__ */ __name(() => secondaryBridge.preheat(), "preheatAcpChild"),
2710
3123
  persistDisabledTools: persistDisabledToolsFn,
2711
3124
  persistSetting: persistSettingFn,
2712
3125
  persistSettings: persistSettingsFn,
@@ -2765,6 +3178,8 @@ async function runQwenServe(optsIn, deps = {}) {
2765
3178
  workspaceCwd: workspaceInput.cwd,
2766
3179
  primary: false,
2767
3180
  trusted: secondaryTrusted,
3181
+ removable: workspaceInput.removable,
3182
+ registrationIds: workspaceInput.registrationIds,
2768
3183
  env: secondaryEnv.metadata,
2769
3184
  bridge: secondaryBridge,
2770
3185
  workspaceService: secondaryWorkspaceService,
@@ -2772,7 +3187,9 @@ async function runQwenServe(optsIn, deps = {}) {
2772
3187
  clientMcpSenderRegistry: secondaryClientMcpSenderRegistry
2773
3188
  });
2774
3189
  }
2775
- const workspaceRegistry = runtime.createWorkspaceRegistry(workspaceRuntimes);
3190
+ const workspaceRegistry = runtime.createWorkspaceRegistry(workspaceRuntimes, {
3191
+ sessionOwnerIndex
3192
+ });
2776
3193
  core.registerDaemonGaugeCallbacks({
2777
3194
  sessionCount: /* @__PURE__ */ __name(() => workspaceRegistry.list().reduce((sum, item) => sum + item.bridge.sessionCount, 0), "sessionCount"),
2778
3195
  sseCount: /* @__PURE__ */ __name(() => runtime.getActiveSseCount(), "sseCount"),
@@ -2801,7 +3218,7 @@ async function runQwenServe(optsIn, deps = {}) {
2801
3218
  prevCpu = cpu;
2802
3219
  prevCpuAt = nowMs;
2803
3220
  }
2804
- const acp = app2.locals?.["acpHandle"]?.registry.getSnapshot();
3221
+ const acp = app2.locals?.["acpHandle"]?.getSnapshot();
2805
3222
  const hits = getRateLimiter(app2)?.getHitCounts();
2806
3223
  const rejectedTotal = hits ? hits.prompt + hits.mutation + hits.read : 0;
2807
3224
  const rateLimitRejected = prevRateRejected === void 0 ? 0 : Math.max(0, rejectedTotal - prevRateRejected);
@@ -2864,8 +3281,305 @@ async function runQwenServe(optsIn, deps = {}) {
2864
3281
  metricsLoopDelay.disable();
2865
3282
  }
2866
3283
  };
3284
+ const createDynamicWorkspaceRuntime = /* @__PURE__ */ __name(async (cwd) => {
3285
+ let wsSettings;
3286
+ try {
3287
+ wsSettings = settingsRuntime.settings.loadSettings(cwd);
3288
+ } catch (err) {
3289
+ writeStderrLine(
3290
+ `qwen serve: could not read full settings for dynamic workspace ${cwd} (${err instanceof Error ? err.message : String(err)}); falling back to defaults.`
3291
+ );
3292
+ }
3293
+ const trusted = wsSettings ? settingsRuntime.trustedFolders.getWorkspaceTrustStatus(
3294
+ wsSettings.merged,
3295
+ cwd
3296
+ ).effective.state === "trusted" : false;
3297
+ const wsEnv = createRuntimeEnvMetadata(cwd, wsSettings);
3298
+ const wsHash = core.hashDaemonWorkspace(cwd);
3299
+ const wsFsFactory = runtime.resolveBridgeFsFactory({
3300
+ boundWorkspaces: [cwd],
3301
+ trusted,
3302
+ emit: deps.fsAuditEmit,
3303
+ pathLocks: sharedPathLocks,
3304
+ ...customIgnoreFiles !== void 0 ? { customIgnoreFiles } : {}
3305
+ });
3306
+ const wsChannelFactory = runtime.createSpawnChannelFactory({
3307
+ sourceEnv: wsEnv.effectiveEnv,
3308
+ onDiagnosticLine: diagnosticSink,
3309
+ pipeHooks: {
3310
+ onMessageSent: /* @__PURE__ */ __name((bytes) => recordPipeMessage("outbound", bytes), "onMessageSent"),
3311
+ onMessageReceived: /* @__PURE__ */ __name((bytes) => recordPipeMessage("inbound", bytes), "onMessageReceived"),
3312
+ onMessageObserved: /* @__PURE__ */ __name(({ direction, bytes, message }) => observeLargePipeFrame({
3313
+ direction: daemonPipeDirection(direction),
3314
+ bytes,
3315
+ message
3316
+ }), "onMessageObserved")
3317
+ },
3318
+ ...opts.experimentalLsp === true ? { extraArgs: ["--experimental-lsp"] } : {}
3319
+ });
3320
+ const wsClientMcpRegistry = new ClientMcpSenderRegistry();
3321
+ let wsBridgeRef;
3322
+ const wsSubSessionLauncher = createSubSessionLauncher({
3323
+ getBridge: /* @__PURE__ */ __name(() => wsBridgeRef, "getBridge"),
3324
+ boundWorkspace: cwd
3325
+ });
3326
+ let wsBridge;
3327
+ try {
3328
+ wsBridge = runtime.createAcpSessionBridge({
3329
+ clientMcpSender: wsClientMcpRegistry.lookup,
3330
+ onCreateSubSession: wsSubSessionLauncher.launch,
3331
+ maxSessions: opts.maxSessions,
3332
+ freshSessionAdmission: totalSessionAdmission.admit,
3333
+ sessionLifecycle: sessionOwnerIndex.handleBridgeSessionLifecycle,
3334
+ ...opts.maxPendingPromptsPerSession !== void 0 ? { maxPendingPromptsPerSession: opts.maxPendingPromptsPerSession } : {},
3335
+ ...opts.eventRingSize !== void 0 ? { eventRingSize: opts.eventRingSize } : {},
3336
+ ...opts.compactedReplayMaxBytes !== void 0 ? { compactedReplayMaxBytes: opts.compactedReplayMaxBytes } : {},
3337
+ ...opts.channelIdleTimeoutMs !== void 0 ? { channelIdleTimeoutMs: opts.channelIdleTimeoutMs } : {},
3338
+ ...opts.sessionReapIntervalMs !== void 0 ? { sessionReapIntervalMs: opts.sessionReapIntervalMs } : {},
3339
+ ...opts.sessionIdleTimeoutMs !== void 0 ? { sessionIdleTimeoutMs: opts.sessionIdleTimeoutMs } : {},
3340
+ ...opts.permissionResponseTimeoutMs !== void 0 ? { permissionResponseTimeoutMs: opts.permissionResponseTimeoutMs } : {},
3341
+ boundWorkspace: cwd,
3342
+ sessionShellCommandEnabled,
3343
+ childEnvOverrides,
3344
+ channelFactory: wsChannelFactory,
3345
+ onDiagnosticLine: diagnosticSink,
3346
+ telemetry: createRuntimeBridgeTelemetry(wsHash),
3347
+ ...permissionPolicy !== void 0 ? { permissionPolicy } : {},
3348
+ ...permissionConsensusQuorum !== void 0 ? { permissionConsensusQuorum } : {},
3349
+ permissionAudit: permissionAuditPublisher,
3350
+ statusProvider: runtime.createDaemonStatusProvider({
3351
+ env: wsEnv.effectiveEnv
3352
+ }),
3353
+ fileSystem: createBridgeFileSystemAdapter(wsFsFactory),
3354
+ persistApprovalMode: /* @__PURE__ */ __name((workspace, mode) => withSettingsLock(workspace, async () => {
3355
+ const fresh = settingsRuntime.settings.loadSettings(workspace);
3356
+ fresh.setValue(
3357
+ WORKSPACE_SETTING_SCOPE,
3358
+ "tools.approvalMode",
3359
+ mode
3360
+ );
3361
+ }), "persistApprovalMode")
3362
+ });
3363
+ } catch (err) {
3364
+ wsSubSessionLauncher.stop();
3365
+ throw err;
3366
+ }
3367
+ wsBridgeRef = wsBridge;
3368
+ let wsService;
3369
+ try {
3370
+ wsService = runtime.createDaemonWorkspaceService({
3371
+ boundWorkspace: cwd,
3372
+ contextFilename: contextFilenameForInit ?? "QWEN.md",
3373
+ statusProvider: runtime.createDaemonStatusProvider({
3374
+ env: wsEnv.effectiveEnv
3375
+ }),
3376
+ workspaceProvidersStatusProvider: runtime.createWorkspaceProvidersStatusProvider({
3377
+ env: wsEnv.effectiveEnv
3378
+ }),
3379
+ workspaceSkillsStatusProvider: runtime.createWorkspaceSkillsStatusProvider(),
3380
+ isChannelLive: /* @__PURE__ */ __name(() => wsBridge.isChannelLive(), "isChannelLive"),
3381
+ preheatAcpChild: /* @__PURE__ */ __name(() => wsBridge.preheat(), "preheatAcpChild"),
3382
+ persistDisabledTools: persistDisabledToolsFn,
3383
+ persistSetting: persistSettingFn,
3384
+ persistSettings: persistSettingsFn,
3385
+ reloadDaemonEnv: /* @__PURE__ */ __name((workspace) => withSettingsLock(workspace, async () => {
3386
+ const fresh = settingsRuntime.settings.loadSettings(workspace, {
3387
+ skipLoadEnvironment: true
3388
+ });
3389
+ const result = settingsRuntime.settings.reloadEnvironment(
3390
+ fresh.merged,
3391
+ workspace
3392
+ );
3393
+ try {
3394
+ const refreshedRuntimeEnv = settingsRuntime.environment.buildRuntimeEnvironment(
3395
+ fresh.merged,
3396
+ workspace,
3397
+ daemonRuntimeBaseEnv
3398
+ );
3399
+ logRuntimeEnvFileReadFailures(workspace, refreshedRuntimeEnv);
3400
+ wsEnv.replace(refreshedRuntimeEnv.effectiveEnv);
3401
+ wsEnv.metadata.envFileReadFailed = refreshedRuntimeEnv.envFileReadFailed;
3402
+ wsEnv.metadata.envFileReadFailures.splice(
3403
+ 0,
3404
+ wsEnv.metadata.envFileReadFailures.length,
3405
+ ...refreshedRuntimeEnv.envFileReadFailures
3406
+ );
3407
+ wsEnv.metadata.overlayKeys.splice(
3408
+ 0,
3409
+ wsEnv.metadata.overlayKeys.length,
3410
+ ...refreshedRuntimeEnv.overlayKeys
3411
+ );
3412
+ wsEnv.metadata.envFilePaths.splice(
3413
+ 0,
3414
+ wsEnv.metadata.envFilePaths.length,
3415
+ ...refreshedRuntimeEnv.envFilePaths
3416
+ );
3417
+ delete wsEnv.metadata.fallbackReason;
3418
+ } catch (err) {
3419
+ wsEnv.metadata.fallbackReason = err instanceof Error ? err.message : String(err);
3420
+ daemonLog.warn(
3421
+ "failed to rebuild dynamic runtime env snapshot after daemon env reload; preserving previous runtime env",
3422
+ {
3423
+ workspace,
3424
+ error: wsEnv.metadata.fallbackReason
3425
+ }
3426
+ );
3427
+ }
3428
+ return result;
3429
+ }), "reloadDaemonEnv"),
3430
+ queryWorkspaceStatus: /* @__PURE__ */ __name((method, idle) => wsBridge.queryWorkspaceStatus(method, idle), "queryWorkspaceStatus"),
3431
+ invokeWorkspaceCommand: /* @__PURE__ */ __name((method, params, invokeOpts) => wsBridge.invokeWorkspaceCommand(method, params, invokeOpts), "invokeWorkspaceCommand"),
3432
+ refreshExtensionsForAllSessions: /* @__PURE__ */ __name(() => wsBridge.refreshExtensionsForAllSessions(), "refreshExtensionsForAllSessions"),
3433
+ publishWorkspaceEvent: /* @__PURE__ */ __name((event) => wsBridge.publishWorkspaceEvent(event), "publishWorkspaceEvent")
3434
+ });
3435
+ } catch (err) {
3436
+ wsSubSessionLauncher.stop();
3437
+ await wsBridge.shutdown().catch(() => {
3438
+ try {
3439
+ wsBridge.killAllSync();
3440
+ } catch {
3441
+ }
3442
+ });
3443
+ throw err;
3444
+ }
3445
+ runtimeBridges.push(wsBridge);
3446
+ internalRuntimeBridgesForCleanup.push(wsBridge);
3447
+ subSessionStoppers.push(wsSubSessionLauncher.stop);
3448
+ subSessionStoppersByWorkspace.set(cwd, wsSubSessionLauncher.stop);
3449
+ return {
3450
+ workspaceId: wsHash,
3451
+ workspaceCwd: cwd,
3452
+ primary: false,
3453
+ trusted,
3454
+ removable: true,
3455
+ registrationIds: [],
3456
+ env: wsEnv.metadata,
3457
+ bridge: wsBridge,
3458
+ workspaceService: wsService,
3459
+ routeFileSystemFactory: wsFsFactory,
3460
+ clientMcpSenderRegistry: wsClientMcpRegistry
3461
+ };
3462
+ }, "createDynamicWorkspaceRuntime");
3463
+ const workspaceRuntimeRemoval = {
3464
+ async runtimeAdded(runtimeAdded) {
3465
+ const app3 = runtimeApp ?? runtimeAppForCleanup;
3466
+ const startScheduledTaskKeepaliveForWorkspace = app3?.locals?.["startScheduledTaskKeepaliveForWorkspace"];
3467
+ startScheduledTaskKeepaliveForWorkspace?.(runtimeAdded);
3468
+ if (!channelWorkerManager) return;
3469
+ try {
3470
+ await channelWorkerManager.restoreWorkspace(
3471
+ runtimeAdded.workspaceCwd
3472
+ );
3473
+ await channelWorkerManager.refreshWorkspaces();
3474
+ } catch (err) {
3475
+ daemonLog.error(
3476
+ "workspace channel worker startup error",
3477
+ err instanceof Error ? err : null
3478
+ );
3479
+ } finally {
3480
+ writeChannelWorkerPidfile();
3481
+ }
3482
+ },
3483
+ beginDrain(runtimeToDrain) {
3484
+ totalSessionAdmission.beginWorkspaceDrain(runtimeToDrain.workspaceCwd);
3485
+ channelWorkerManager?.beginWorkspaceDrain(runtimeToDrain.workspaceCwd);
3486
+ },
3487
+ cancelDrain(runtimeToDrain) {
3488
+ channelWorkerManager?.cancelWorkspaceDrain(runtimeToDrain.workspaceCwd);
3489
+ totalSessionAdmission.cancelWorkspaceDrain(runtimeToDrain.workspaceCwd);
3490
+ },
3491
+ completeDrain(runtimeToDrain) {
3492
+ totalSessionAdmission.completeWorkspaceDrain(
3493
+ runtimeToDrain.workspaceCwd
3494
+ );
3495
+ },
3496
+ getActivity(runtimeToDrain) {
3497
+ return {
3498
+ pendingSessionStarts: totalSessionAdmission.snapshotForWorkspace(
3499
+ runtimeToDrain.workspaceCwd
3500
+ ).inFlight,
3501
+ channelWorkers: channelWorkerManager?.workspaceActivity(
3502
+ runtimeToDrain.workspaceCwd
3503
+ ) ?? 0
3504
+ };
3505
+ },
3506
+ disposeRuntime(runtimeToDrain, reason = "workspace_removed") {
3507
+ const existing = runtimeCleanupPromises.get(runtimeToDrain);
3508
+ if (existing) return existing;
3509
+ const cleanup = (async () => {
3510
+ const stopSubSessions = subSessionStoppersByWorkspace.get(
3511
+ runtimeToDrain.workspaceCwd
3512
+ );
3513
+ try {
3514
+ stopSubSessions?.();
3515
+ } catch {
3516
+ }
3517
+ if (reason === "workspace_removed" && channelWorkerManager) {
3518
+ await channelWorkerManager.removeWorkspace(runtimeToDrain.workspaceCwd).catch((err) => {
3519
+ daemonLog.error(
3520
+ "workspace channel worker cleanup error",
3521
+ err instanceof Error ? err : null
3522
+ );
3523
+ });
3524
+ try {
3525
+ await channelWorkerManager.refreshWorkspaces();
3526
+ } catch (err) {
3527
+ channelWorkspaceGroups = (channelWorkspaceGroups ?? []).filter(
3528
+ (group) => group.workspaceCwd !== runtimeToDrain.workspaceCwd
3529
+ );
3530
+ channelWebhookConfigVersion += 1;
3531
+ refreshChannelWebhookConfigs?.();
3532
+ daemonLog.error(
3533
+ "workspace channel worker topology refresh error",
3534
+ err instanceof Error ? err : null
3535
+ );
3536
+ }
3537
+ writeChannelWorkerPidfile();
3538
+ }
3539
+ if (reason === "workspace_removed") {
3540
+ const app3 = runtimeApp ?? runtimeAppForCleanup;
3541
+ const stopWorkspaceGitStateForWorkspace = app3?.locals?.["stopWorkspaceGitStateForWorkspace"];
3542
+ const stopScheduledTaskKeepaliveForWorkspace = app3?.locals?.["stopScheduledTaskKeepaliveForWorkspace"];
3543
+ stopWorkspaceGitStateForWorkspace?.(runtimeToDrain.workspaceCwd);
3544
+ stopScheduledTaskKeepaliveForWorkspace?.(
3545
+ runtimeToDrain.workspaceCwd
3546
+ );
3547
+ }
3548
+ let bridgeStopped = false;
3549
+ try {
3550
+ if (!shutdownBridges.has(runtimeToDrain.bridge)) {
3551
+ await runtimeToDrain.bridge.shutdown({ reason });
3552
+ }
3553
+ bridgeStopped = true;
3554
+ } finally {
3555
+ if (bridgeStopped || reason === "workspace_removed") {
3556
+ subSessionStoppersByWorkspace.delete(runtimeToDrain.workspaceCwd);
3557
+ if (stopSubSessions) {
3558
+ removeArrayValue(subSessionStoppers, stopSubSessions);
3559
+ }
3560
+ removeArrayValue(runtimeBridges, runtimeToDrain.bridge);
3561
+ removeArrayValue(
3562
+ internalRuntimeBridgesForCleanup,
3563
+ runtimeToDrain.bridge
3564
+ );
3565
+ shutdownBridges.add(runtimeToDrain.bridge);
3566
+ }
3567
+ }
3568
+ })();
3569
+ runtimeCleanupPromises.set(runtimeToDrain, cleanup);
3570
+ void cleanup.catch(() => {
3571
+ if (reason === "daemon_shutdown" && runtimeCleanupPromises.get(runtimeToDrain) === cleanup) {
3572
+ runtimeCleanupPromises.delete(runtimeToDrain);
3573
+ }
3574
+ });
3575
+ return cleanup;
3576
+ }
3577
+ };
2867
3578
  const app2 = runtime.createServeApp(opts, () => actualPort, {
2868
3579
  workspaceRegistry,
3580
+ createWorkspaceRuntime: createDynamicWorkspaceRuntime,
3581
+ workspaceRegistrationStore,
3582
+ workspaceRuntimeRemoval,
2869
3583
  bridge,
2870
3584
  webShellDir,
2871
3585
  boundWorkspace,
@@ -2880,6 +3594,27 @@ async function runQwenServe(optsIn, deps = {}) {
2880
3594
  primaryRuntimeEnv,
2881
3595
  daemonLog,
2882
3596
  getChannelWorkerSnapshot,
3597
+ getChannelWorkerSnapshots,
3598
+ getChannelWorkerControl,
3599
+ isChannelControlDraining: /* @__PURE__ */ __name(() => channelControlDraining, "isChannelControlDraining"),
3600
+ isChannelControlInitializing: /* @__PURE__ */ __name(() => channelWorkerManagerStarting !== void 0, "isChannelControlInitializing"),
3601
+ setChannelWorkerSelection,
3602
+ stopChannelWorker,
3603
+ getChannelWebhookConfigSources,
3604
+ getChannelWebhookConfigVersion: /* @__PURE__ */ __name(() => channelWebhookConfigVersion, "getChannelWebhookConfigVersion"),
3605
+ registerChannelWebhookConfigRefresh: /* @__PURE__ */ __name((refresh) => {
3606
+ refreshChannelWebhookConfigs = refresh;
3607
+ }, "registerChannelWebhookConfigRefresh"),
3608
+ enqueueChannelWebhookTask: /* @__PURE__ */ __name(async (task) => {
3609
+ if (!channelWorkerManager) {
3610
+ throw new ChannelWebhookEnqueueError(
3611
+ "channel_worker_unavailable",
3612
+ "Channel worker is not running."
3613
+ );
3614
+ }
3615
+ return channelWorkerManager.enqueueWebhookTask(task);
3616
+ }, "enqueueChannelWebhookTask"),
3617
+ reloadChannelWorker,
2883
3618
  getPerfSnapshot: /* @__PURE__ */ __name(() => ({
2884
3619
  eventLoop: currentDaemonEventLoopMonitor.snapshot(),
2885
3620
  promptQueueWait: {
@@ -2903,6 +3638,9 @@ async function runQwenServe(optsIn, deps = {}) {
2903
3638
  persistDisabledTools: persistDisabledToolsFn,
2904
3639
  persistSetting: persistSettingFn,
2905
3640
  persistSettings: persistSettingsFn,
3641
+ sessionArtifactsPersistenceAvailable: sessionArtifactsPersistenceAvailableFromSettings(
3642
+ runtimeBootSettings?.merged
3643
+ ),
2906
3644
  installAuthProvider: /* @__PURE__ */ __name((req) => withSettingsLock(
2907
3645
  boundWorkspace,
2908
3646
  async () => {
@@ -2941,14 +3679,17 @@ async function runQwenServe(optsIn, deps = {}) {
2941
3679
  }
2942
3680
  ), "installAuthProvider")
2943
3681
  });
3682
+ app2.locals.subSessionStoppers = subSessionStoppers;
3683
+ subSessionStoppers.push(subSessionLauncher.stop);
3684
+ subSessionStoppersByWorkspace.set(boundWorkspace, subSessionLauncher.stop);
2944
3685
  return { app: app2, bridge };
2945
3686
  }, "buildRuntime");
2946
3687
  if (deps.bridge) {
2947
3688
  const runtime = await buildRuntime();
2948
3689
  runtimeAppForCleanup = runtime.app;
2949
- runtimeApp = runtime.app;
2950
3690
  bridgeRef = runtime.bridge;
2951
3691
  if (!opts.channelSelection) {
3692
+ runtimeApp = runtime.app;
2952
3693
  runtimeStartupSettled = true;
2953
3694
  markRuntimeReady();
2954
3695
  }
@@ -2962,17 +3703,25 @@ async function runQwenServe(optsIn, deps = {}) {
2962
3703
  daemonLog,
2963
3704
  qwenCodeVersion: cliVersion,
2964
3705
  sessionShellCommandEnabled,
3706
+ sessionArtifactsPersistenceAvailable,
2965
3707
  permissionPolicy,
2966
3708
  multiWorkspaceCapabilitiesRequireRuntime: workspaceInputs.length > 1,
2967
3709
  getRuntimeError: /* @__PURE__ */ __name(() => runtimeStartupError, "getRuntimeError"),
2968
3710
  getChannelWorkerSnapshot,
3711
+ getChannelWorkerSnapshots,
2969
3712
  onHealthServed: deferRuntimeUntilFirstHealth ? () => startRuntimeAfterHealth?.() : void 0
2970
3713
  });
3714
+ const deferredChannelWebhookAuth = deferRuntimeUntilFirstHealth ? createDeferredChannelWebhookAuth(
3715
+ resolveChannelWebhookConfigSource,
3716
+ await loadChannelWebhookConfigRuntime(),
3717
+ daemonLog
3718
+ ) : void 0;
2971
3719
  const app = runtimeApp ?? createDelegatingServeApp(bootstrapApp, () => runtimeApp, {
2972
3720
  waitForDeferredRuntimeRoutes: deferRuntimeUntilFirstHealth,
2973
3721
  startRuntime: /* @__PURE__ */ __name(() => startRuntimeForRequest?.(), "startRuntime"),
2974
3722
  runtimeReady,
2975
- authenticateDeferredRuntimeRequest: bearerAuth(opts.token)
3723
+ authenticateDeferredRuntimeRequest: bearerAuth(opts.token),
3724
+ authenticateDeferredChannelWebhookRequest: deferredChannelWebhookAuth
2976
3725
  });
2977
3726
  let listenHostname = opts.hostname;
2978
3727
  if (opts.hostname.startsWith("[")) {
@@ -2989,7 +3738,70 @@ async function runQwenServe(optsIn, deps = {}) {
2989
3738
  `Invalid maxConnections: ${opts.maxConnections}. Must be >= 0 (0 / Infinity = unlimited).`
2990
3739
  );
2991
3740
  }
2992
- reserveChannelServicePidfile();
3741
+ const channelValidationSettingsRuntime = opts.channelSelection ? await loadSettingsRuntimeModules() : void 0;
3742
+ const resolveChannelWorkspaceGroupsAtListen = /* @__PURE__ */ __name(() => {
3743
+ if (!opts.channelSelection || !channelValidationSettingsRuntime || !channelRuntime) {
3744
+ return void 0;
3745
+ }
3746
+ const settingsByWorkspace = /* @__PURE__ */ new Map();
3747
+ if (workspaceInputs.length === 1) {
3748
+ const workspace = workspaceInputs[0];
3749
+ const settings = channelValidationSettingsRuntime.settings.loadSettings(
3750
+ workspace.cwd
3751
+ );
3752
+ channelWebhookEnvByWorkspace.set(
3753
+ workspace.cwd,
3754
+ channelValidationSettingsRuntime.environment.buildRuntimeEnvironment(
3755
+ settings.merged,
3756
+ workspace.cwd,
3757
+ daemonRuntimeBaseEnv
3758
+ ).effectiveEnv
3759
+ );
3760
+ return void 0;
3761
+ }
3762
+ const workspaces = workspaceInputs.map((workspace, index) => {
3763
+ const settings = channelValidationSettingsRuntime.settings.loadSettings(
3764
+ workspace.cwd
3765
+ );
3766
+ settingsByWorkspace.set(workspace.cwd, settings);
3767
+ channelWebhookEnvByWorkspace.set(
3768
+ workspace.cwd,
3769
+ channelValidationSettingsRuntime.environment.buildRuntimeEnvironment(
3770
+ settings.merged,
3771
+ workspace.cwd,
3772
+ daemonRuntimeBaseEnv
3773
+ ).effectiveEnv
3774
+ );
3775
+ const trusted = index === 0 && deps.trustedWorkspace !== void 0 ? deps.trustedWorkspace : channelValidationSettingsRuntime.trustedFolders.getWorkspaceTrustStatus(
3776
+ settings.merged,
3777
+ workspace.cwd
3778
+ ).effective.state === "trusted";
3779
+ return {
3780
+ workspaceCwd: workspace.cwd,
3781
+ primary: index === 0,
3782
+ trusted
3783
+ };
3784
+ });
3785
+ const grouping = resolveChannelWorkspaceGroups({
3786
+ workspaces,
3787
+ selection: opts.channelSelection,
3788
+ loadChannelsConfig: /* @__PURE__ */ __name((cwd) => {
3789
+ const settings = settingsByWorkspace.get(cwd);
3790
+ if (!settings) return {};
3791
+ return channelRuntime.loadChannelsConfig(cwd, settings);
3792
+ }, "loadChannelsConfig")
3793
+ });
3794
+ if (!grouping.ok) {
3795
+ throw Object.assign(new Error(grouping.error.message), {
3796
+ code: grouping.error.code,
3797
+ ...grouping.error.channel ? { channel: grouping.error.channel } : {}
3798
+ });
3799
+ }
3800
+ return grouping.groups;
3801
+ }, "resolveChannelWorkspaceGroupsAtListen");
3802
+ if (opts.channelSelection) {
3803
+ reserveChannelServicePidfile(opts.channelSelection);
3804
+ }
2993
3805
  return await new Promise((resolve, reject) => {
2994
3806
  const onListening = /* @__PURE__ */ __name(() => {
2995
3807
  startup.listenerReadyAt = (/* @__PURE__ */ new Date()).toISOString();
@@ -3008,45 +3820,14 @@ async function runQwenServe(optsIn, deps = {}) {
3008
3820
  const scheme = tlsOptions ? "https" : "http";
3009
3821
  const url = `${scheme}://${formatHostForUrl(opts.hostname)}:${actualPort}`;
3010
3822
  try {
3011
- if (opts.channelSelection) {
3012
- const createSupervisor = deps.channelWorkerSupervisorFactory ?? channelRuntime?.createChannelWorkerSupervisor;
3013
- if (!createSupervisor) {
3014
- throw new Error(
3015
- "Channel worker supervisor runtime is not available."
3016
- );
3017
- }
3018
- channelWorker = createSupervisor({
3019
- cliEntryPath: findCliEntryPath(),
3020
- daemonUrl: formatChannelWorkerDaemonUrl(opts.hostname, actualPort),
3021
- ...token ? { daemonToken: token } : {},
3022
- workspace: boundWorkspace,
3023
- selection: opts.channelSelection,
3024
- onReady: /* @__PURE__ */ __name((snapshot) => {
3025
- writeChannelWorkerPidfile(snapshot);
3026
- }, "onReady"),
3027
- onLog: /* @__PURE__ */ __name(({ stream, line }) => {
3028
- const message = `channel worker ${stream}: ${line}`;
3029
- if (stream === "stderr") {
3030
- daemonLog.warn(message);
3031
- } else {
3032
- daemonLog.info(message);
3033
- }
3034
- }, "onLog"),
3035
- onExit: /* @__PURE__ */ __name((snapshot) => {
3036
- daemonLog.warn(
3037
- `channel worker exited (state=${snapshot.state}, pid=${snapshot.pid ?? "unknown"}, code=${snapshot.exitCode ?? "null"}, signal=${snapshot.signal ?? "null"}, error=${snapshot.error ?? "none"}, restartCount=${snapshot.restartCount ?? 0}, nextRestartAt=${snapshot.nextRestartAt ?? "none"}, staleHeartbeatAt=${snapshot.staleHeartbeatAt ?? "none"})`
3038
- );
3039
- writeChannelWorkerPidfile(snapshot, { clearWorkerPid: true });
3040
- }, "onExit")
3041
- });
3042
- }
3823
+ channelWorkspaceGroups = resolveChannelWorkspaceGroupsAtListen();
3043
3824
  } catch (err) {
3044
3825
  removeCurrentServePidfile();
3045
3826
  const error = err instanceof Error ? err : new Error(String(err));
3046
3827
  server.close((closeErr) => {
3047
3828
  if (closeErr) {
3048
3829
  daemonLog.error(
3049
- "server close after channel worker setup error failed",
3830
+ "server close after channel worker validation error failed",
3050
3831
  closeErr
3051
3832
  );
3052
3833
  }
@@ -3054,6 +3835,19 @@ async function runQwenServe(optsIn, deps = {}) {
3054
3835
  });
3055
3836
  return;
3056
3837
  }
3838
+ if (channelWorkspaceGroups) {
3839
+ for (const group of channelWorkspaceGroups) {
3840
+ daemonLog.info("channel worker group assigned", {
3841
+ workspace: group.workspaceCwd,
3842
+ channels: group.selection.mode === "all" ? ["all"] : group.selection.names
3843
+ });
3844
+ }
3845
+ if (opts.channelSelection?.mode === "all") {
3846
+ writeStderrLine(
3847
+ "qwen serve: --channel all is primary-workspace only; non-primary workspace channels are not hosted."
3848
+ );
3849
+ }
3850
+ }
3057
3851
  writeStdoutLine(
3058
3852
  `qwen serve listening on ${url} (mode=${opts.mode}, workspace=${boundWorkspace})`
3059
3853
  );
@@ -3129,12 +3923,17 @@ async function runQwenServe(optsIn, deps = {}) {
3129
3923
  }
3130
3924
  }, "shutdownBridgeAfterFailedStartup");
3131
3925
  const stopChannelWorkerAfterFailedStartup = /* @__PURE__ */ __name(async () => {
3132
- await channelWorker.stop().catch((stopErr) => {
3926
+ if (!channelWorkerManager) return true;
3927
+ try {
3928
+ await channelWorkerManager.shutdown();
3929
+ return true;
3930
+ } catch (stopErr) {
3133
3931
  daemonLog.error(
3134
3932
  "channel worker stop after runtime startup error failed",
3135
3933
  stopErr instanceof Error ? stopErr : null
3136
3934
  );
3137
- });
3935
+ return false;
3936
+ }
3138
3937
  }, "stopChannelWorkerAfterFailedStartup");
3139
3938
  const failRuntimeStartup = /* @__PURE__ */ __name(async (err, bridgeForCleanup) => {
3140
3939
  const error = err instanceof Error ? err : new Error(String(err));
@@ -3143,6 +3942,7 @@ async function runQwenServe(optsIn, deps = {}) {
3143
3942
  return;
3144
3943
  }
3145
3944
  runtimeStartupSettled = true;
3945
+ runtimeApp = void 0;
3146
3946
  clearRuntimeStartupTimer();
3147
3947
  const message = error.message;
3148
3948
  runtimeStartupError = message;
@@ -3152,14 +3952,28 @@ async function runQwenServe(optsIn, deps = {}) {
3152
3952
  }
3153
3953
  writeStderrLine(`qwen serve: runtime startup failed: ${message}`);
3154
3954
  daemonLog.error("runtime startup failed", error);
3155
- await stopChannelWorkerAfterFailedStartup();
3955
+ markRuntimeFailed(error);
3956
+ if (closeServerAfterChannelWorkerStartupFailure && server.listening) {
3957
+ runtimeFailureListenerClose = new Promise((resolve2) => {
3958
+ server.close((closeErr) => {
3959
+ if (closeErr) {
3960
+ daemonLog.error(
3961
+ "server close after runtime startup error failed",
3962
+ closeErr
3963
+ );
3964
+ }
3965
+ resolve2();
3966
+ });
3967
+ });
3968
+ server.closeAllConnections();
3969
+ }
3970
+ const channelWorkerStopped = await stopChannelWorkerAfterFailedStartup();
3156
3971
  disposeDaemonEventLoopMonitor();
3157
- removeCurrentServePidfile();
3972
+ if (channelWorkerStopped) removeCurrentServePidfile();
3158
3973
  const bridgesForCleanup = bridgeForCleanup ? [bridgeForCleanup, ...getRuntimeBridgesForCleanup()] : getRuntimeBridgesForCleanup();
3159
3974
  for (const bridge of [...new Set(bridgesForCleanup)]) {
3160
3975
  await shutdownBridgeAfterFailedStartup(bridge);
3161
3976
  }
3162
- markRuntimeFailed(error);
3163
3977
  }, "failRuntimeStartup");
3164
3978
  const armRuntimeStartupTimer = /* @__PURE__ */ __name(() => {
3165
3979
  if (runtimeStartupTimeoutMs <= 0 || runtimeStartupTimer) return;
@@ -3172,10 +3986,152 @@ async function runQwenServe(optsIn, deps = {}) {
3172
3986
  }, runtimeStartupTimeoutMs);
3173
3987
  runtimeStartupTimer.unref();
3174
3988
  }, "armRuntimeStartupTimer");
3175
- const completeRuntimeStartup = /* @__PURE__ */ __name(async () => {
3989
+ const resolveRuntimeChannelGroups = /* @__PURE__ */ __name(async (channelSelection, candidateApp, operation) => {
3990
+ const registry = candidateApp.locals?.["workspaceRegistry"];
3991
+ if (!registry) {
3992
+ throw new Error(
3993
+ "Workspace registry is not available for channel workers."
3994
+ );
3995
+ }
3996
+ const runtimes = registry.list();
3997
+ if (runtimes.length <= 1 && operation === "initial") {
3998
+ return [
3999
+ {
4000
+ workspaceCwd: registry.primary.workspaceCwd,
4001
+ selection: channelSelection
4002
+ }
4003
+ ];
4004
+ }
4005
+ const workerRuntime = await ensureChannelRuntime();
4006
+ const settingsRuntime = await loadSettingsRuntimeModules();
4007
+ const settingsByWorkspace = /* @__PURE__ */ new Map();
4008
+ const grouping = resolveChannelWorkspaceGroups({
4009
+ workspaces: runtimes.map((runtime) => {
4010
+ const settings = settingsRuntime.settings.loadSettings(
4011
+ runtime.workspaceCwd
4012
+ );
4013
+ settingsByWorkspace.set(runtime.workspaceCwd, settings);
4014
+ return {
4015
+ workspaceCwd: runtime.workspaceCwd,
4016
+ primary: runtime.primary,
4017
+ trusted: runtime.trusted
4018
+ };
4019
+ }),
4020
+ selection: channelSelection,
4021
+ loadChannelsConfig: /* @__PURE__ */ __name((cwd) => {
4022
+ const settings = settingsByWorkspace.get(cwd);
4023
+ return settings ? workerRuntime.loadChannelsConfig(cwd, settings) : {};
4024
+ }, "loadChannelsConfig")
4025
+ });
4026
+ if (!grouping.ok) {
4027
+ throw Object.assign(new Error(grouping.error.message), {
4028
+ code: grouping.error.code,
4029
+ ...grouping.error.channel ? { channel: grouping.error.channel } : {}
4030
+ });
4031
+ }
4032
+ return grouping.groups;
4033
+ }, "resolveRuntimeChannelGroups");
4034
+ ensureChannelWorkerManager = /* @__PURE__ */ __name(() => {
4035
+ if (channelWorkerManager) return Promise.resolve(channelWorkerManager);
4036
+ if (channelWorkerManagerStarting) return channelWorkerManagerStarting;
4037
+ const starting = (async () => {
4038
+ const candidateApp = runtimeApp ?? runtimeAppForCleanup;
4039
+ const registry = candidateApp?.locals?.["workspaceRegistry"];
4040
+ if (!candidateApp || !registry) {
4041
+ throw new Error(
4042
+ "Workspace registry is not available for channels."
4043
+ );
4044
+ }
4045
+ const workerRuntime = await ensureChannelRuntime();
4046
+ const createSupervisor = deps.channelWorkerSupervisorFactory ?? workerRuntime.createChannelWorkerSupervisor;
4047
+ const createGroup = /* @__PURE__ */ __name((groups) => workerRuntime.createChannelWorkerGroup({
4048
+ groups,
4049
+ registry,
4050
+ createSupervisor,
4051
+ shared: {
4052
+ cliEntryPath: workerRuntime.findCliEntryPath(),
4053
+ daemonUrl: formatChannelWorkerDaemonUrl(
4054
+ opts.hostname,
4055
+ actualPort
4056
+ ),
4057
+ ...token ? { daemonToken: token } : {}
4058
+ },
4059
+ onReady: /* @__PURE__ */ __name((snapshot) => {
4060
+ if (runtimeStartupError !== void 0) return;
4061
+ if (workspaceInputs.length > 1) {
4062
+ daemonLog.info("channel worker ready", {
4063
+ workspace: snapshot.workspaceCwd,
4064
+ pid: snapshot.pid,
4065
+ channels: snapshot.channels
4066
+ });
4067
+ }
4068
+ channelWorkerManager?.workerChanged();
4069
+ if (!runtimeStartupSettled) writeChannelWorkerPidfile();
4070
+ }, "onReady"),
4071
+ onExit: /* @__PURE__ */ __name((snapshot) => {
4072
+ const workspacePrefix = workspaceInputs.length > 1 ? `workspace=${snapshot.workspaceCwd}, ` : "";
4073
+ daemonLog.warn(
4074
+ `channel worker exited (${workspacePrefix}state=${snapshot.state}, pid=${snapshot.pid ?? "unknown"}, code=${snapshot.exitCode ?? "null"}, signal=${snapshot.signal ?? "null"}, error=${snapshot.error ?? "none"}, restartCount=${snapshot.restartCount ?? 0}, nextRestartAt=${snapshot.nextRestartAt ?? "none"}, staleHeartbeatAt=${snapshot.staleHeartbeatAt ?? "none"})`
4075
+ );
4076
+ channelWorkerManager?.workerChanged();
4077
+ if (!runtimeStartupSettled) writeChannelWorkerPidfile();
4078
+ }, "onExit"),
4079
+ onStateChange: /* @__PURE__ */ __name(() => {
4080
+ channelWorkerManager?.workerChanged();
4081
+ if (!runtimeStartupSettled) writeChannelWorkerPidfile();
4082
+ }, "onStateChange"),
4083
+ onLog: /* @__PURE__ */ __name(({ stream, line, workspaceCwd }) => {
4084
+ const message = workspaceInputs.length > 1 ? `channel worker [${workspaceCwd}] ${stream}: ${line}` : `channel worker ${stream}: ${line}`;
4085
+ if (stream === "stderr") daemonLog.warn(message);
4086
+ else daemonLog.info(message);
4087
+ }, "onLog")
4088
+ }), "createGroup");
4089
+ channelWorkerManager = workerRuntime.createChannelWorkerManager({
4090
+ resolveGroups: /* @__PURE__ */ __name((selection, operation) => resolveRuntimeChannelGroups(selection, candidateApp, operation), "resolveGroups"),
4091
+ createGroup,
4092
+ reserveLease: reserveChannelServicePidfile,
4093
+ releaseLease: /* @__PURE__ */ __name(() => {
4094
+ removeCurrentServePidfile();
4095
+ if (channelPidfileReserved) {
4096
+ throw new Error("Failed to release the channel service lease.");
4097
+ }
4098
+ }, "releaseLease"),
4099
+ initialLeaseReserved: channelPidfileReserved,
4100
+ onCommittedSelection: /* @__PURE__ */ __name((_selection, groups) => {
4101
+ channelWorkspaceGroups = groups;
4102
+ channelWebhookConfigVersion += 1;
4103
+ refreshChannelWebhookConfigs?.();
4104
+ }, "onCommittedSelection"),
4105
+ onStateChange: /* @__PURE__ */ __name(() => {
4106
+ if (runtimeStartupSettled) writeChannelWorkerPidfile();
4107
+ }, "onStateChange")
4108
+ });
4109
+ return channelWorkerManager;
4110
+ })();
4111
+ channelWorkerManagerStarting = starting;
4112
+ void starting.then(
4113
+ () => {
4114
+ if (channelWorkerManagerStarting === starting) {
4115
+ channelWorkerManagerStarting = void 0;
4116
+ }
4117
+ },
4118
+ () => {
4119
+ if (channelWorkerManagerStarting === starting) {
4120
+ channelWorkerManagerStarting = void 0;
4121
+ }
4122
+ }
4123
+ );
4124
+ return starting;
4125
+ }, "ensureChannelWorkerManager");
4126
+ const completeRuntimeStartup = /* @__PURE__ */ __name(async (candidateApp) => {
3176
4127
  if (runtimeStartupSettled) return;
4128
+ runtimeApp = candidateApp;
4129
+ const acpHandle = candidateApp.locals?.["acpHandle"];
4130
+ acpHandle?.attachServer?.(server);
3177
4131
  if (opts.channelSelection) {
3178
- await channelWorker.start();
4132
+ closeServerAfterChannelWorkerStartupFailure = true;
4133
+ const manager = await ensureChannelWorkerManager();
4134
+ await manager.startInitial(opts.channelSelection);
3179
4135
  if (runtimeStartupSettled) return;
3180
4136
  }
3181
4137
  if (runtimeStartupSettled) return;
@@ -3222,13 +4178,10 @@ async function runQwenServe(optsIn, deps = {}) {
3222
4178
  );
3223
4179
  return;
3224
4180
  }
3225
- runtimeApp = runtime.app;
3226
- const acpHandle = runtime.app.locals?.["acpHandle"];
3227
- acpHandle?.attachServer?.(server);
3228
4181
  if (shouldPreheat) {
3229
4182
  startBridgePreheat(runtime.bridge);
3230
4183
  }
3231
- await completeRuntimeStartup();
4184
+ await completeRuntimeStartup(runtime.app);
3232
4185
  }).catch((err) => failRuntimeStartup(err));
3233
4186
  }, "startRuntime");
3234
4187
  startRuntimeForRequest = startRuntime;
@@ -3266,11 +4219,10 @@ async function runQwenServe(optsIn, deps = {}) {
3266
4219
  if (shuttingDown) {
3267
4220
  daemonLog.warn(`received ${signal} during drain \u2014 forcing exit`);
3268
4221
  try {
3269
- channelWorker.killAllSync();
4222
+ channelWorkerManager?.killAllSync();
3270
4223
  for (const runtimeBridge of getRuntimeBridgesForCleanup()) {
3271
4224
  runtimeBridge.killAllSync();
3272
4225
  }
3273
- removeCurrentServePidfile();
3274
4226
  } catch (err) {
3275
4227
  daemonLog.error(
3276
4228
  "force-kill error",
@@ -3286,16 +4238,24 @@ async function runQwenServe(optsIn, deps = {}) {
3286
4238
  try {
3287
4239
  await handle.close();
3288
4240
  await daemonLog.flush();
3289
- process.exit(0);
4241
+ process.exit(runtimeStartupError === void 0 ? 0 : 1);
3290
4242
  } catch (err) {
3291
4243
  daemonLog.error("shutdown error", err instanceof Error ? err : null);
3292
4244
  await daemonLog.flush().catch(() => {
3293
4245
  });
4246
+ if (channelWorkerManager?.state().enabled) {
4247
+ daemonLog.error(
4248
+ "refusing to exit while a channel worker or service lease remains; signal again to retry after the child exits (another signal during that retry forces exit)"
4249
+ );
4250
+ await daemonLog.flush().catch(() => {
4251
+ });
4252
+ return;
4253
+ }
3294
4254
  process.exit(1);
3295
4255
  }
3296
4256
  }, "onSignal");
3297
4257
  const onUncaughtExceptionMonitor = /* @__PURE__ */ __name(() => {
3298
- if (process.listenerCount("uncaughtException") === 0) {
4258
+ if (process.listenerCount("uncaughtException") === 0 && !channelWorkerManager?.state().enabled) {
3299
4259
  removeCurrentServePidfile();
3300
4260
  }
3301
4261
  }, "onUncaughtExceptionMonitor");
@@ -3310,17 +4270,24 @@ async function runQwenServe(optsIn, deps = {}) {
3310
4270
  if (closePromise) return closePromise;
3311
4271
  closePromise = new Promise((res, rej) => {
3312
4272
  shuttingDown = true;
3313
- app.locals.stopScheduledTaskKeepalive?.();
4273
+ channelControlDraining = true;
4274
+ const initiallyMountedApp = runtimeApp ?? runtimeAppForCleanup;
4275
+ const initiallyMountedManagement = initiallyMountedApp?.locals?.["workspaceManagementHandle"];
4276
+ const initialManagementWait = initiallyMountedManagement?.sealAndWait?.();
3314
4277
  clearRuntimeStartAfterHealthTimer();
3315
4278
  clearRuntimeStartFallbackTimer();
3316
4279
  cancelDeferredRuntimeStartup();
3317
4280
  let settled = false;
3318
4281
  let bridgeShutdownError;
4282
+ let channelWorkerShutdownError;
3319
4283
  const finish = /* @__PURE__ */ __name((err) => {
3320
4284
  if (settled) return;
3321
4285
  settled = true;
3322
- process.removeListener("SIGINT", onSignal);
3323
- process.removeListener("SIGTERM", onSignal);
4286
+ const preserveSignalHandlers = channelWorkerShutdownError !== void 0 && channelWorkerManager?.state().enabled === true;
4287
+ if (!preserveSignalHandlers) {
4288
+ process.removeListener("SIGINT", onSignal);
4289
+ process.removeListener("SIGTERM", onSignal);
4290
+ }
3324
4291
  process.removeListener(
3325
4292
  "uncaughtExceptionMonitor",
3326
4293
  onUncaughtExceptionMonitor
@@ -3331,9 +4298,17 @@ async function runQwenServe(optsIn, deps = {}) {
3331
4298
  );
3332
4299
  }).finally(() => daemonLog.flush().catch(() => {
3333
4300
  })).finally(() => {
3334
- const finalErr = err ?? bridgeShutdownError;
3335
- if (finalErr) rej(finalErr);
3336
- else res();
4301
+ const finalErr = err ?? bridgeShutdownError ?? channelWorkerShutdownError;
4302
+ if (finalErr) {
4303
+ if (channelWorkerShutdownError && channelWorkerManager?.state().enabled) {
4304
+ closePromise = void 0;
4305
+ shuttingDown = false;
4306
+ channelControlDraining = false;
4307
+ }
4308
+ rej(finalErr);
4309
+ } else {
4310
+ res();
4311
+ }
3337
4312
  });
3338
4313
  }, "finish");
3339
4314
  void (coreRuntimePromise ? coreRuntimePromise.then((core) => core.forceFlushMetrics()) : Promise.resolve()).catch((flushErr) => {
@@ -3347,6 +4322,19 @@ async function runQwenServe(optsIn, deps = {}) {
3347
4322
  daemonLog
3348
4323
  );
3349
4324
  const appForCleanup = runtimeApp ?? runtimeAppForCleanup;
4325
+ const workspaceManagementHandle = appForCleanup?.locals?.["workspaceManagementHandle"];
4326
+ await initialManagementWait;
4327
+ if (workspaceManagementHandle !== initiallyMountedManagement) {
4328
+ await workspaceManagementHandle?.sealAndWait?.();
4329
+ }
4330
+ const stopScheduledTaskKeepalive = appForCleanup?.locals?.["stopScheduledTaskKeepalive"];
4331
+ stopScheduledTaskKeepalive?.();
4332
+ const stopWorkspaceGitState = appForCleanup?.locals?.["stopWorkspaceGitState"];
4333
+ stopWorkspaceGitState?.();
4334
+ const stoppers = appForCleanup?.locals?.["subSessionStoppers"];
4335
+ if (stoppers) {
4336
+ for (const stop of stoppers) stop();
4337
+ }
3350
4338
  const deviceFlowRegistry = appForCleanup ? getDeviceFlowRegistry(appForCleanup) : void 0;
3351
4339
  if (deviceFlowRegistry) {
3352
4340
  try {
@@ -3373,17 +4361,43 @@ async function runQwenServe(optsIn, deps = {}) {
3373
4361
  rl.dispose();
3374
4362
  }
3375
4363
  disposeDaemonEventLoopMonitor();
3376
- await channelWorker.stop().catch((err) => {
3377
- daemonLog.error(
3378
- "channel worker stop error",
3379
- err instanceof Error ? err : null
3380
- );
3381
- });
3382
- removeCurrentServePidfile();
4364
+ if (channelWorkerManager) {
4365
+ await channelWorkerManager.shutdown().catch((err) => {
4366
+ daemonLog.error(
4367
+ "channel worker stop error",
4368
+ err instanceof Error ? err : null
4369
+ );
4370
+ channelWorkerShutdownError = err instanceof Error ? err : new Error(String(err));
4371
+ });
4372
+ } else {
4373
+ removeCurrentServePidfile();
4374
+ }
4375
+ const runtimeRemoval = appForCleanup?.locals?.["workspaceRuntimeRemoval"];
4376
+ const workspaceRegistry = appForCleanup?.locals?.["workspaceRegistry"];
4377
+ const managedRuntimeBridges = /* @__PURE__ */ new Set();
4378
+ if (runtimeRemoval && workspaceRegistry) {
4379
+ const managedRuntimes = workspaceRegistry.listManaged();
4380
+ for (const workspaceRuntime of managedRuntimes) {
4381
+ managedRuntimeBridges.add(workspaceRuntime.bridge);
4382
+ await runtimeRemoval.disposeRuntime(workspaceRuntime, "daemon_shutdown").catch((err) => {
4383
+ daemonLog.error(
4384
+ "workspace runtime shutdown error",
4385
+ err instanceof Error ? err : null
4386
+ );
4387
+ bridgeShutdownError = err instanceof Error ? err : new Error(String(err));
4388
+ try {
4389
+ workspaceRuntime.bridge.killAllSync();
4390
+ } catch {
4391
+ }
4392
+ });
4393
+ }
4394
+ }
3383
4395
  for (const bridgeForShutdown of getRuntimeBridgesForCleanup()) {
4396
+ if (managedRuntimeBridges.has(bridgeForShutdown)) continue;
3384
4397
  if (shutdownBridges.has(bridgeForShutdown)) continue;
3385
4398
  shutdownBridges.add(bridgeForShutdown);
3386
4399
  await bridgeForShutdown.shutdown().catch((err) => {
4400
+ shutdownBridges.delete(bridgeForShutdown);
3387
4401
  daemonLog.error(
3388
4402
  "bridge shutdown error",
3389
4403
  err instanceof Error ? err : null
@@ -3392,6 +4406,12 @@ async function runQwenServe(optsIn, deps = {}) {
3392
4406
  });
3393
4407
  }
3394
4408
  }).finally(() => {
4409
+ if (!server.listening) {
4410
+ void (runtimeFailureListenerClose ?? Promise.resolve()).then(
4411
+ () => finish()
4412
+ );
4413
+ return;
4414
+ }
3395
4415
  const SECONDARY_DEADLINE_MS = 2e3;
3396
4416
  let secondaryTimer;
3397
4417
  const forceTimer = setTimeout(() => {
@@ -3425,17 +4445,19 @@ async function runQwenServe(optsIn, deps = {}) {
3425
4445
  server.on("error", (err) => {
3426
4446
  daemonLog.error("server error", err instanceof Error ? err : null);
3427
4447
  });
3428
- if (runtimeApp && bridgeRef) {
3429
- const acpHandle = runtimeApp.locals?.["acpHandle"];
3430
- acpHandle?.attachServer?.(server);
4448
+ const preparedRuntimeApp = runtimeApp ?? runtimeAppForCleanup;
4449
+ if (preparedRuntimeApp && bridgeRef && deps.bridge) {
3431
4450
  if (shouldPreheat) {
3432
4451
  startBridgePreheat(bridgeRef);
3433
4452
  }
3434
4453
  if (opts.channelSelection && !runtimeStartupSettled) {
3435
4454
  armRuntimeStartupTimer();
3436
- runtimeStarting = completeRuntimeStartup().catch(
4455
+ runtimeStarting = completeRuntimeStartup(preparedRuntimeApp).catch(
3437
4456
  (err) => failRuntimeStartup(err, bridgeRef)
3438
4457
  );
4458
+ } else {
4459
+ const acpHandle = preparedRuntimeApp.locals?.["acpHandle"];
4460
+ acpHandle?.attachServer?.(server);
3439
4461
  }
3440
4462
  } else if (deferRuntimeUntilFirstHealth) {
3441
4463
  scheduleRuntimeStartFallback();
@@ -3448,14 +4470,24 @@ async function runQwenServe(optsIn, deps = {}) {
3448
4470
  void runtimeReady.then(
3449
4471
  () => resolve(handle),
3450
4472
  (err) => {
3451
- void handle.close().catch((closeErr) => {
3452
- daemonLog.error(
3453
- "shutdown after runtime startup error failed",
3454
- closeErr instanceof Error ? closeErr : null
3455
- );
3456
- }).finally(() => {
3457
- reject(err instanceof Error ? err : new Error(String(err)));
3458
- });
4473
+ void handle.close().then(
4474
+ () => {
4475
+ reject(err instanceof Error ? err : new Error(String(err)));
4476
+ },
4477
+ (closeErr) => {
4478
+ daemonLog.error(
4479
+ "shutdown after runtime startup error failed",
4480
+ closeErr instanceof Error ? closeErr : null
4481
+ );
4482
+ if (channelWorkerManager?.state().enabled) {
4483
+ daemonLog.error(
4484
+ "runtime startup failed, but qwen serve remains alive to retain the channel service lease until worker exit is confirmed"
4485
+ );
4486
+ return;
4487
+ }
4488
+ reject(err instanceof Error ? err : new Error(String(err)));
4489
+ }
4490
+ );
3459
4491
  }
3460
4492
  );
3461
4493
  }
@@ -3512,6 +4544,7 @@ async function runQwenServe(optsIn, deps = {}) {
3512
4544
  __name(runQwenServe, "runQwenServe");
3513
4545
  export {
3514
4546
  InvalidPolicyConfigError,
4547
+ createDisabledChannelWorkerSupervisor,
3515
4548
  createLazyBridgeProxy,
3516
4549
  extractContextFilename,
3517
4550
  formatChannelWorkerDaemonUrl,
@@ -3522,11 +4555,11 @@ export {
3522
4555
  };
3523
4556
  /**
3524
4557
  * @license
3525
- * Copyright 2026 Qwen Team
4558
+ * Copyright 2025 Qwen Team
3526
4559
  * SPDX-License-Identifier: Apache-2.0
3527
4560
  */
3528
4561
  /**
3529
4562
  * @license
3530
- * Copyright 2025 Qwen Team
4563
+ * Copyright 2026 Qwen Team
3531
4564
  * SPDX-License-Identifier: Apache-2.0
3532
4565
  */