@qwen-code/qwen-code 0.20.1-preview.7215 → 0.20.2-gdpval-vl-agent.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (327) hide show
  1. package/bundled/qc-helper/docs/configuration/settings.md +1 -1
  2. package/bundled/qc-helper/docs/features/auto-mode.md +19 -16
  3. package/bundled/qc-helper/docs/features/commands.md +54 -0
  4. package/bundled/qc-helper/docs/features/sub-agents.md +16 -7
  5. package/bundled/qc-helper/docs/integration-github-action.md +1 -1
  6. package/bundled/qc-helper/docs/qwen-serve.md +2 -1
  7. package/bundled/review/DESIGN.md +2 -2
  8. package/bundled/review/SKILL.md +4 -4
  9. package/chunks/{MaxSizedBox-EH6G5AEH.js → MaxSizedBox-KYNG7EN7.js} +38 -35
  10. package/chunks/{StandaloneSessionPicker-264A3TEA.js → StandaloneSessionPicker-7XN4WVVG.js} +55 -52
  11. package/chunks/{acpAgent-6RBIJFDI.js → acpAgent-FTFFYP5G.js} +1536 -512
  12. package/chunks/{agent-QURXGAA3.js → agent-Y76LTTOT.js} +34 -31
  13. package/chunks/{agent-headless-CRGX4ICQ.js → agent-headless-IVAEQPK6.js} +34 -31
  14. package/chunks/{anthropicContentGenerator-BWBAZGTW.js → anthropicContentGenerator-HGWAHO24.js} +11 -13
  15. package/chunks/{artifact-tool-IUJ7QWCX.js → artifact-tool-56T5IMBP.js} +3 -3
  16. package/chunks/{askUserQuestion-IUMUUTDQ.js → askUserQuestion-E25OBIC2.js} +3 -3
  17. package/chunks/{bridge-MNFVKPMI.js → bridge-4M77KUEV.js} +39 -36
  18. package/chunks/{build-SSCNEHZZ.js → build-GHIZ4MSZ.js} +1 -1
  19. package/chunks/{ca-2SL2BXTK.js → ca-N6VVUFVB.js} +611 -201
  20. package/chunks/{channel-worker-group-53CMOPFT.js → channel-worker-group-QZV2SP5U.js} +4 -4
  21. package/chunks/{channel-worker-manager-UTXILKC2.js → channel-worker-manager-3GMAU45H.js} +4 -4
  22. package/chunks/{channel-worker-supervisor-ZGO2W2MD.js → channel-worker-supervisor-QCXSXCRY.js} +3 -3
  23. package/chunks/{chunk-UQES76OO.js → chunk-2HGTVAOW.js} +6 -6
  24. package/chunks/{chunk-2HOVDT7W.js → chunk-2LI23QA6.js} +1 -1
  25. package/chunks/{chunk-ANHT55MR.js → chunk-2P6CNEHB.js} +1 -1
  26. package/chunks/chunk-2RFKHEXL.js +74 -0
  27. package/chunks/{chunk-BF32GYSY.js → chunk-3IABAQR6.js} +1 -1
  28. package/chunks/chunk-3Z43GZUQ.js +32 -0
  29. package/chunks/chunk-43T5WDQ7.js +127 -0
  30. package/chunks/{chunk-DA7OOKVN.js → chunk-4CTP6VR6.js} +29 -2
  31. package/chunks/{chunk-JD3MKVKL.js → chunk-4K56OJFJ.js} +1 -1
  32. package/chunks/{chunk-KTUQMDEP.js → chunk-4K7VDKAD.js} +1 -1
  33. package/chunks/{chunk-QKYTTBYW.js → chunk-4LVZNIDO.js} +1 -1
  34. package/chunks/{chunk-ZEOZL37W.js → chunk-57FIIFJN.js} +1 -1
  35. package/chunks/{chunk-7YBZGNEC.js → chunk-5G3ZVADU.js} +308 -199
  36. package/chunks/{chunk-X4CGDBKA.js → chunk-6GEJX3LE.js} +3 -3
  37. package/chunks/{chunk-6GUTHAN7.js → chunk-6HOCJNO5.js} +1 -1
  38. package/chunks/{chunk-GMGDLUC7.js → chunk-6IL7KRLE.js} +1 -1
  39. package/chunks/chunk-6PVPNMXU.js +29 -0
  40. package/chunks/{chunk-BDBMYST4.js → chunk-6X4GWOPW.js} +1 -1
  41. package/chunks/{chunk-4ODB7WIB.js → chunk-6ZBPS62S.js} +1 -1
  42. package/chunks/{chunk-AYCDXHZB.js → chunk-7Z6JQEL6.js} +1 -1
  43. package/chunks/{chunk-WAX3ITOA.js → chunk-A3TAEAHX.js} +1 -1
  44. package/chunks/{chunk-OLMETXLX.js → chunk-ACW3VNUE.js} +2 -2
  45. package/chunks/{chunk-IB35C3IL.js → chunk-AVQ6EX4J.js} +1 -1
  46. package/chunks/{chunk-TTSKHF43.js → chunk-BK6UOUJ2.js} +2 -2
  47. package/chunks/{chunk-6OH6A5EX.js → chunk-BLAEKN6K.js} +20603 -17709
  48. package/chunks/chunk-BULDBTYC.js +153 -0
  49. package/chunks/{chunk-XNP57UDV.js → chunk-C3EXYVFX.js} +2 -2
  50. package/chunks/{chunk-FVS747N7.js → chunk-C54UTDOC.js} +23 -19
  51. package/chunks/{chunk-MAQQGNQ5.js → chunk-CBOQ3HY7.js} +466 -10
  52. package/chunks/{chunk-VFAE4AGH.js → chunk-CGZ5SV23.js} +72 -67
  53. package/chunks/{chunk-WKRXIHD6.js → chunk-COAARUPK.js} +8 -8
  54. package/chunks/{chunk-GA7VRJVN.js → chunk-E2ZK5M4P.js} +5 -5
  55. package/chunks/{chunk-5SCI6E3E.js → chunk-E4IMU4Y5.js} +1 -1
  56. package/chunks/{chunk-E5GIFWE3.js → chunk-EEFRJ5CT.js} +54 -33
  57. package/chunks/{chunk-WXAXH7IJ.js → chunk-ESQHGKPJ.js} +1 -1
  58. package/chunks/{chunk-NEEB7UEN.js → chunk-FFFM6NJV.js} +1 -2
  59. package/chunks/{chunk-Z5R4JMOL.js → chunk-FJ2IUWNQ.js} +4 -4
  60. package/chunks/{chunk-JVTCARQ6.js → chunk-FQI7LT7T.js} +4 -4
  61. package/chunks/{chunk-BRXIO5WY.js → chunk-FTNI3D7D.js} +7 -7
  62. package/chunks/{chunk-OMH3276Y.js → chunk-GHRSKGHF.js} +7 -7
  63. package/chunks/{chunk-OONJNQ42.js → chunk-GPSKDNEE.js} +3 -3
  64. package/chunks/{chunk-KPZNOZPC.js → chunk-GWM4PDYK.js} +19 -19
  65. package/chunks/{chunk-NBMIC7DR.js → chunk-H24SOJIQ.js} +2 -2
  66. package/chunks/{chunk-FNGK2Z5B.js → chunk-H4AR2JQF.js} +3 -3
  67. package/chunks/{chunk-WOT64EP2.js → chunk-HCJQORKC.js} +2 -2
  68. package/chunks/{chunk-7KDI2IB2.js → chunk-HDATOR4J.js} +4 -4
  69. package/chunks/{chunk-IE4JSQ5L.js → chunk-HIYP7IR4.js} +39 -37
  70. package/chunks/{chunk-N6YTEVLV.js → chunk-HL6AKUGD.js} +10 -4
  71. package/chunks/{chunk-BAIEQKR5.js → chunk-HPQFGWOD.js} +5 -5
  72. package/chunks/chunk-HTR4WV6U.js +327 -0
  73. package/chunks/{chunk-SDXIH6OA.js → chunk-IFUNDCQ6.js} +137 -5
  74. package/chunks/{chunk-Z6UEAQTP.js → chunk-IFVECEIK.js} +178 -61
  75. package/chunks/{chunk-QOK6RMIP.js → chunk-IKP54WUL.js} +4 -4
  76. package/chunks/{chunk-IUSNI6IX.js → chunk-ISMD2AB3.js} +1 -1
  77. package/chunks/{chunk-G45X5TRN.js → chunk-JCW2R7WC.js} +1 -72
  78. package/chunks/{chunk-LZYWWWCZ.js → chunk-KF6CTNTJ.js} +8 -9
  79. package/chunks/{chunk-EIAK6Q2B.js → chunk-KHOVYUHX.js} +2 -2
  80. package/chunks/chunk-KWK7UE6L.js +6194 -0
  81. package/chunks/{chunk-WBTZGWQ6.js → chunk-L5F3T6TQ.js} +1 -1
  82. package/chunks/{chunk-RELYEO3R.js → chunk-L7ASZD66.js} +244 -1607
  83. package/chunks/{chunk-UJEZQ562.js → chunk-LESHKUWF.js} +3 -5
  84. package/chunks/{chunk-OOCI5VVU.js → chunk-LIZRAKPB.js} +1 -1
  85. package/chunks/{chunk-Q3ZBFXK4.js → chunk-LKB5YL5T.js} +143 -36
  86. package/chunks/{chunk-MKLKHZAK.js → chunk-LU3RXCM7.js} +1 -1
  87. package/chunks/{chunk-B453NMZJ.js → chunk-M3EQ3GZC.js} +3 -3
  88. package/chunks/{chunk-TCKTNY66.js → chunk-M4VFMLQK.js} +6 -6
  89. package/chunks/{chunk-26LLB6FM.js → chunk-MDZTPSXO.js} +2 -2
  90. package/chunks/{chunk-4SLLEAQP.js → chunk-MJPBB2GK.js} +591 -316
  91. package/chunks/chunk-NABLFI57.js +82 -0
  92. package/chunks/{chunk-T7DDD7CZ.js → chunk-NAXEEGJU.js} +4 -4
  93. package/chunks/{chunk-467G3SV5.js → chunk-NPQDJGKU.js} +1 -1
  94. package/chunks/{chunk-FLTN6NRU.js → chunk-O4OT3DM3.js} +5 -1
  95. package/chunks/{chunk-3EUZWNWA.js → chunk-OPDZT2VG.js} +1 -1
  96. package/chunks/chunk-OQ5SYCPE.js +10017 -0
  97. package/chunks/{chunk-C27BYUX6.js → chunk-OQB4EXO4.js} +14 -11
  98. package/chunks/{chunk-V25Z5UUB.js → chunk-P6PBZL3N.js} +7 -6
  99. package/chunks/{chunk-5NWV4NFB.js → chunk-PRAUGUNM.js} +3 -3
  100. package/chunks/{chunk-MC2DOZS7.js → chunk-PVT6E3ZI.js} +3 -3
  101. package/chunks/{chunk-KXEGCGUG.js → chunk-Q22WWVR6.js} +31 -6
  102. package/chunks/{chunk-JDI67JFB.js → chunk-Q2YKNMLS.js} +3 -3
  103. package/chunks/{chunk-PBATSWUQ.js → chunk-QBUDF33N.js} +1 -1
  104. package/chunks/{chunk-Y2ENGUD6.js → chunk-QKTHJXCS.js} +1 -1
  105. package/chunks/{chunk-BVLROR2T.js → chunk-QLJUC7TG.js} +1 -1
  106. package/chunks/{chunk-UEY4AYUL.js → chunk-QNLNLENL.js} +2 -2
  107. package/chunks/{chunk-OKWRU4NO.js → chunk-RC7A7SSL.js} +3 -3
  108. package/chunks/chunk-RCUEYZDE.js +2290 -0
  109. package/chunks/{chunk-EVSTCA7S.js → chunk-RMY5SX7S.js} +368 -113
  110. package/chunks/{chunk-4WUAQ2DO.js → chunk-RTQSXHS7.js} +2 -2
  111. package/chunks/{chunk-RFIAR4YL.js → chunk-RV4C2ZFG.js} +1 -1
  112. package/chunks/{chunk-NIJEXGV6.js → chunk-RVLZCXEE.js} +79 -10
  113. package/chunks/{chunk-Q4RBU7WX.js → chunk-S333CBIA.js} +6 -6
  114. package/chunks/{chunk-JNWZQ27S.js → chunk-SP5WRGVG.js} +3 -3
  115. package/chunks/{chunk-FSL5W5TI.js → chunk-T2L47JJK.js} +3 -3
  116. package/chunks/{chunk-PWVTCGBP.js → chunk-TA4S377U.js} +30 -20
  117. package/chunks/{chunk-TB6UDU4T.js → chunk-THJNPLI4.js} +16 -16
  118. package/chunks/chunk-U6TQGUNB.js +20687 -0
  119. package/chunks/chunk-U7ZFW55U.js +2098 -0
  120. package/chunks/{chunk-W7H223ZZ.js → chunk-UGYMA4EI.js} +1 -1
  121. package/chunks/{chunk-X6YQWCIJ.js → chunk-UH3WSE5L.js} +13 -1
  122. package/chunks/{chunk-P2YAOGJD.js → chunk-UKU3NGW6.js} +3 -3
  123. package/chunks/{chunk-NOWTNYC7.js → chunk-UVFCANV5.js} +8 -8
  124. package/chunks/{chunk-CVDW42JT.js → chunk-V4AKJQ26.js} +1 -1
  125. package/chunks/{chunk-Z5Q65RVH.js → chunk-VJPRLNLR.js} +1 -1
  126. package/chunks/{chunk-Y4CRUWFZ.js → chunk-VTXX72XS.js} +60 -35
  127. package/chunks/{chunk-R3VWUU2E.js → chunk-VYPFXUCB.js} +1 -1
  128. package/chunks/chunk-WHGVTP7Q.js +1049 -0
  129. package/chunks/{chunk-IKP5DXZY.js → chunk-WOWQQGGN.js} +5 -5
  130. package/chunks/{chunk-D2VIDMVM.js → chunk-X6N25LXS.js} +2 -2
  131. package/chunks/chunk-XHATNRQA.js +1500 -0
  132. package/chunks/{chunk-2DXOIVUI.js → chunk-YLSB23Y2.js} +11 -11
  133. package/chunks/{chunk-S35ZDXOS.js → chunk-YM3SZTH4.js} +2 -1
  134. package/chunks/{chunk-OF2BBLYQ.js → chunk-YNWJAOPL.js} +2 -2
  135. package/chunks/{chunk-GKY2OJ7R.js → chunk-ZHERRXZJ.js} +1 -1
  136. package/chunks/{chunk-AR27OPIU.js → chunk-ZKFJKN23.js} +2 -2
  137. package/chunks/{computer-use-R7KA6UJ6.js → computer-use-UKQBH7UM.js} +39 -36
  138. package/chunks/{config-utils-6FXFJUYB.js → config-utils-FYTBZLCJ.js} +3 -3
  139. package/chunks/{contextCommand-KAQQPHZ4.js → contextCommand-ESHGAVWX.js} +36 -33
  140. package/chunks/{create-sub-session-TDPDBU4K.js → create-sub-session-574EPZUU.js} +34 -31
  141. package/chunks/{create-sub-session-X5RVIHCK.js → create-sub-session-AZ77LBL3.js} +3 -3
  142. package/chunks/{cron-create-AC5FFLN7.js → cron-create-KTWJM7QT.js} +5 -5
  143. package/chunks/{cron-delete-JEB3FAHA.js → cron-delete-2P3I5ULL.js} +5 -5
  144. package/chunks/{cron-list-NBYPCNIB.js → cron-list-PXDPGEDQ.js} +5 -5
  145. package/chunks/{daemon-RG2MAI6T.js → daemon-GJRFILYS.js} +323 -99
  146. package/chunks/daemon-status-provider-GZXZP3NU.js +80 -0
  147. package/chunks/{de-I7ZIYXZC.js → de-4IBXM7CN.js} +5 -1
  148. package/chunks/{dist-AU7NQQRP.js → dist-OAV7LJGJ.js} +1 -1
  149. package/chunks/{dist-FUTEXY6A.js → dist-OMW6WDEO.js} +1 -1
  150. package/chunks/{dist-2MIU4UUH.js → dist-PJLG2XYX.js} +1 -1
  151. package/chunks/{dist-53PZYC5B.js → dist-UIFWIFRO.js} +2 -2
  152. package/chunks/{dist-2BHAYBKP.js → dist-XBJVSWS2.js} +1 -1
  153. package/chunks/{dist-WGTQO7F2.js → dist-XRYV6TJP.js} +65 -25
  154. package/chunks/{earlyInputCapture-WC7RI5HV.js → earlyInputCapture-GI3HGQIT.js} +35 -32
  155. package/chunks/{edit-6MHKCJCM.js → edit-EBJK74B3.js} +42 -41
  156. package/chunks/{en-XE34GKAA.js → en-USMCCJAJ.js} +5 -1
  157. package/chunks/{enter-worktree-O7VJ2E7A.js → enter-worktree-2ETY5CSV.js} +39 -36
  158. package/chunks/{enterPlanMode-5XYAALIO.js → enterPlanMode-NY4U2727.js} +45 -37
  159. package/chunks/{environment-LSKFNLBU.js → environment-33IR3NOU.js} +36 -33
  160. package/chunks/{errors-ZFVCY6HG.js → errors-2OCY23IC.js} +36 -33
  161. package/chunks/{exit-worktree-MYIK66T7.js → exit-worktree-Y4ULJ45U.js} +39 -36
  162. package/chunks/{exitPlanMode-7MBNU76O.js → exitPlanMode-SECI2EQ6.js} +39 -36
  163. package/chunks/{fast-path-RNLIB64C.js → fast-path-6Z7RW5J5.js} +3 -2
  164. package/chunks/{fr-X7KDVZIY.js → fr-WVHEBDDB.js} +5 -1
  165. package/chunks/{gemini-WK5ISEAQ.js → gemini-XLGLUGSU.js} +93 -89
  166. package/chunks/{geminiContentGenerator-NUJQBZBW.js → geminiContentGenerator-NNZZDH24.js} +5 -5
  167. package/chunks/{getMachineId-bsd-EXV7SWPA.js → getMachineId-bsd-QFVLPUPT.js} +1 -1
  168. package/chunks/{getMachineId-darwin-IUOMFXU3.js → getMachineId-darwin-DGMQQE2E.js} +1 -1
  169. package/chunks/{getMachineId-linux-K7XJYFHL.js → getMachineId-linux-R4Z6CSWC.js} +1 -1
  170. package/chunks/{getMachineId-unsupported-EA5FDRJ6.js → getMachineId-unsupported-Z3SBVBUV.js} +1 -1
  171. package/chunks/{getMachineId-win-KBA6RAI5.js → getMachineId-win-SCK5UFDT.js} +1 -1
  172. package/chunks/{glob-7P6RYY4L.js → glob-KZA64SSV.js} +41 -38
  173. package/chunks/{grep-V3QHNP2J.js → grep-ONHQMY3V.js} +41 -38
  174. package/chunks/handleAutoUpdate-PRTJISXQ.js +73 -0
  175. package/chunks/{i18n-B7IO7WQT.js → i18n-ZTKKG5R5.js} +35 -32
  176. package/chunks/{initializer-E5TIC3CW.js → initializer-FPPZGBYN.js} +40 -37
  177. package/chunks/{installationInfo-XLPNAISK.js → installationInfo-DV2C27HT.js} +37 -32
  178. package/chunks/{ja-2ICT3KXF.js → ja-KY4ROZTE.js} +5 -1
  179. package/chunks/{keychain-token-storage-DWRJMNH3.js → keychain-token-storage-6ACJDYIB.js} +3 -3
  180. package/chunks/{list-3CZR5I42.js → list-KEHCNUAK.js} +42 -39
  181. package/chunks/{loadedSettingsAdapter-X5BSC6CE.js → loadedSettingsAdapter-7RZ6M3WH.js} +39 -36
  182. package/chunks/{loop-wakeup-HMHCT5GU.js → loop-wakeup-RNMRVA66.js} +6 -6
  183. package/chunks/{ls-IW5HYDG4.js → ls-J2ZI5XYK.js} +5 -5
  184. package/chunks/{lsp-4RL52YIZ.js → lsp-UMS3NUB5.js} +3 -3
  185. package/chunks/managed-npm-update-EBKNOG37.js +332 -0
  186. package/chunks/{mcp-4C4HWXAR.js → mcp-NHXKZRRP.js} +39 -36
  187. package/chunks/{monitor-3CJDNZB2.js → monitor-FMUAIFFH.js} +39 -36
  188. package/chunks/nonInteractiveCli-I2GPZNTP.js +132 -0
  189. package/chunks/{notebook-edit-MX366HCT.js → notebook-edit-V7RNXKVL.js} +43 -42
  190. package/chunks/{openaiContentGenerator-KRPNNJGZ.js → openaiContentGenerator-IBVUUZDH.js} +19 -18
  191. package/chunks/{pidfile-K7T2JLUJ.js → pidfile-AMTGL2H2.js} +35 -32
  192. package/chunks/{processUtils-YXL3VIBR.js → processUtils-3ZT2JF6D.js} +2 -2
  193. package/chunks/{pt-JJ4XPIBP.js → pt-OK455PLH.js} +5 -1
  194. package/chunks/{qwenContentGenerator-GJVXFZ3U.js → qwenContentGenerator-E72VVWS3.js} +41 -38
  195. package/chunks/{qwenOAuth2-UZTIBQLY.js → qwenOAuth2-YCC3HP24.js} +17 -16
  196. package/chunks/{read-file-S5XQSYOW.js → read-file-5EWNGUXN.js} +13 -11
  197. package/chunks/{read-mcp-resource-OIBCNIX7.js → read-mcp-resource-F6HYMDUY.js} +3 -3
  198. package/chunks/{record-artifact-HDMK4LHG.js → record-artifact-7GCFLDD7.js} +3 -3
  199. package/chunks/{resumeHistoryUtils-IKR6XD2S.js → resumeHistoryUtils-IH4RNB76.js} +41 -38
  200. package/chunks/{ripGrep-H65GRSQX.js → ripGrep-B6A6N7GI.js} +34 -31
  201. package/chunks/{ru-STR4KTW7.js → ru-7SPDGMGD.js} +5 -1
  202. package/chunks/{run-qwen-serve-7SKAQOAA.js → run-qwen-serve-6PKSMF6Z.js} +115 -74
  203. package/chunks/{runtime-I2STBGPR.js → runtime-ASRANXO6.js} +45 -40
  204. package/chunks/{scheduler-6F7HETNO.js → scheduler-IABM76UZ.js} +34 -31
  205. package/chunks/sdk-exporters-grpc-ETLH47EP.js +23214 -0
  206. package/chunks/sdk-exporters-http-6MCQH335.js +563 -0
  207. package/chunks/sdk-impl-HOLWAXC6.js +9193 -0
  208. package/chunks/{send-message-WXVVK4DB.js → send-message-KBO6X4ZS.js} +7 -5
  209. package/chunks/{serve-4ATEWSEA.js → serve-A4DT5D32.js} +39 -36
  210. package/chunks/{server-YPUPFV2O.js → server-DZ5ZSVRE.js} +2317 -472
  211. package/chunks/{session-AZFIERIY.js → session-G2R3CYU6.js} +87 -172
  212. package/chunks/{settings-EFQHLTM3.js → settings-7TNSXUTO.js} +43 -40
  213. package/chunks/{shell-FWXWBJ4Q.js → shell-5BRFGEMK.js} +34 -31
  214. package/chunks/{skill-A634MNCD.js → skill-3SWYEK7M.js} +24 -20
  215. package/chunks/{spawnChannel-KKBGGR47.js → spawnChannel-GGN2WVWW.js} +36 -33
  216. package/chunks/{src-BVROLD6N.js → src-5BPBNQ5S.js} +314 -236
  217. package/chunks/{standalone-update-ERLA3BDC.js → standalone-update-AHOZ56LS.js} +37 -34
  218. package/chunks/{startInteractiveUI-3VZ23WAY.js → startInteractiveUI-TLGOQVV7.js} +1105 -906
  219. package/chunks/{syntheticOutput-HCUFXSIA.js → syntheticOutput-H7RTI5KL.js} +4 -4
  220. package/chunks/{task-create-RIY5JTFC.js → task-create-7474AJJD.js} +10 -8
  221. package/chunks/{task-list-XBUCV3CO.js → task-list-633HGOIB.js} +6 -6
  222. package/chunks/{task-stop-QDFCCYR5.js → task-stop-MNUGHPIA.js} +3 -3
  223. package/chunks/{task-update-7PXKJQOI.js → task-update-66GQB5LI.js} +10 -8
  224. package/chunks/{team-create-ZZO7QFQ7.js → team-create-XHDF7UKM.js} +42 -39
  225. package/chunks/{team-delete-TNSSE2S5.js → team-delete-BB3CG3QF.js} +6 -6
  226. package/chunks/{team-plan-approval-3BZBJ46K.js → team-plan-approval-XKSBXWMH.js} +39 -36
  227. package/chunks/{theme-manager-FSFWNXFJ.js → theme-manager-6ZKLBFAN.js} +35 -32
  228. package/chunks/{todoWrite-OMAIGB6V.js → todoWrite-KRAUN54W.js} +5 -5
  229. package/chunks/{tool-search-VYXAAIDW.js → tool-search-UDNJCXYS.js} +21 -17
  230. package/chunks/{total-session-admission-PSMLQICS.js → total-session-admission-VWRCCDYM.js} +40 -37
  231. package/chunks/{tree-sitter-4D7QS7F6.js → tree-sitter-L5BFT64K.js} +1 -1
  232. package/chunks/{tree-sitter-bash-VEJGF5XF.js → tree-sitter-bash-ZKDNQGID.js} +1 -1
  233. package/chunks/{trustedFolders-QA3RK2NV.js → trustedFolders-TJI6OLAN.js} +35 -32
  234. package/chunks/{chunk-6EFTQYW7.js → undici-3FJYTMOF.js} +24 -399
  235. package/chunks/{chunk-L573Z2QZ.js → undici-PYHBDDPN.js} +1 -5
  236. package/chunks/{update-relaunch-LNLZFX3J.js → update-relaunch-RS5GB74A.js} +17 -17
  237. package/chunks/updateCheck-T4EEA5YR.js +88 -0
  238. package/chunks/{useAutoAcceptIndicator-DIWN27LT.js → useAutoAcceptIndicator-LLWMXC7F.js} +44 -41
  239. package/chunks/{validateNonInterActiveAuth-LOEOFCAF.js → validateNonInterActiveAuth-OJ3KYXAR.js} +74 -71
  240. package/chunks/{version-HBF2VBLE.js → version-ZCEUV5DO.js} +1 -1
  241. package/chunks/{web-fetch-BWGSD2BD.js → web-fetch-KQF4YFCI.js} +99 -42
  242. package/chunks/{web-search-OOHTCVR3.js → web-search-QDDGFGKI.js} +113 -61
  243. package/chunks/{workflow-LJAJBOR4.js → workflow-GIRKCX4P.js} +47 -43
  244. package/chunks/{workspace-providers-status-FYV7TTHA.js → workspace-providers-status-UTMAVTNE.js} +42 -39
  245. package/chunks/{workspace-registration-store-4EHGQW4Y.js → workspace-registration-store-EYJMJFZU.js} +8 -2
  246. package/chunks/{workspace-registry-BKD7VC4Y.js → workspace-registry-4W4UW6MY.js} +40 -37
  247. package/chunks/{workspace-service-75RHX6KR.js → workspace-service-DJCPY6ZN.js} +46 -43
  248. package/chunks/{workspace-skills-status-WBZBZI6A.js → workspace-skills-status-VQ2LKXXX.js} +40 -37
  249. package/chunks/write-file-PLK6RQ7M.js +65 -0
  250. package/chunks/{zh-TW-4RR3YHNN.js → zh-TW-BM47YBFH.js} +5 -1
  251. package/chunks/{zh-6ANG2HTL.js → zh-WY5DWYZD.js} +5 -1
  252. package/cli-entry.js +164 -12
  253. package/cli.js +18 -11
  254. package/locales/ca.js +772 -203
  255. package/locales/de.js +8 -2
  256. package/locales/en.js +8 -2
  257. package/locales/fr.js +8 -2
  258. package/locales/ja.js +8 -2
  259. package/locales/pt.js +8 -2
  260. package/locales/ru.js +8 -2
  261. package/locales/zh-TW.js +8 -2
  262. package/locales/zh.js +8 -2
  263. package/package.json +3 -3
  264. package/web-shell/assets/{arc-Buk1besA.js → arc-DIQrcXXh.js} +1 -1
  265. package/web-shell/assets/{architectureDiagram-3BPJPVTR-B1aUKYDC.js → architectureDiagram-3BPJPVTR-CbPd-DSw.js} +1 -1
  266. package/web-shell/assets/{blockDiagram-GPEHLZMM-CRTdg3Zx.js → blockDiagram-GPEHLZMM-yzBIVhMX.js} +1 -1
  267. package/web-shell/assets/{c4Diagram-AAUBKEIU-DFdRMp5g.js → c4Diagram-AAUBKEIU-B88Swcsu.js} +1 -1
  268. package/web-shell/assets/channel-BaTMUesZ.js +1 -0
  269. package/web-shell/assets/{chunk-2J33WTMH-4rYQdkEI.js → chunk-2J33WTMH-BbOLo6NX.js} +1 -1
  270. package/web-shell/assets/{chunk-4BX2VUAB-Coi-pQJy.js → chunk-4BX2VUAB-Bg6in0r0.js} +1 -1
  271. package/web-shell/assets/{chunk-55IACEB6-BtBjz02t.js → chunk-55IACEB6-Bv9QRyLI.js} +1 -1
  272. package/web-shell/assets/{chunk-727SXJPM-CGYOWorl.js → chunk-727SXJPM-CFokiv61.js} +1 -1
  273. package/web-shell/assets/{chunk-AQP2D5EJ-CH5AKhqx.js → chunk-AQP2D5EJ-DS2Oxf6L.js} +1 -1
  274. package/web-shell/assets/{chunk-FMBD7UC4-Cd50-w85.js → chunk-FMBD7UC4-D2NkHD3B.js} +1 -1
  275. package/web-shell/assets/{chunk-ND2GUHAM-C2wF3KCK.js → chunk-ND2GUHAM-BsT_UC5B.js} +1 -1
  276. package/web-shell/assets/{chunk-QZHKN3VN-pCeRTaWi.js → chunk-QZHKN3VN-tnJo3zln.js} +1 -1
  277. package/web-shell/assets/classDiagram-4FO5ZUOK-CyBPzWud.js +1 -0
  278. package/web-shell/assets/classDiagram-v2-Q7XG4LA2-CyBPzWud.js +1 -0
  279. package/web-shell/assets/{cose-bilkent-S5V4N54A-B-_fAB6D.js → cose-bilkent-S5V4N54A-BTMa6DAZ.js} +1 -1
  280. package/web-shell/assets/{dagre-BM42HDAG-ChSPNHpL.js → dagre-BM42HDAG-ujGX7Owg.js} +1 -1
  281. package/web-shell/assets/{diagram-2AECGRRQ-BX7cFOF3.js → diagram-2AECGRRQ-fU4-dbPa.js} +1 -1
  282. package/web-shell/assets/{diagram-5GNKFQAL-BQUTW92n.js → diagram-5GNKFQAL-Bdm-TYSA.js} +1 -1
  283. package/web-shell/assets/{diagram-KO2AKTUF-BkYPh3e4.js → diagram-KO2AKTUF-Bkhz85Z9.js} +1 -1
  284. package/web-shell/assets/{diagram-LMA3HP47-Cl6jsNyx.js → diagram-LMA3HP47-Bzu3q26p.js} +1 -1
  285. package/web-shell/assets/{diagram-OG6HWLK6-DRWoHz8n.js → diagram-OG6HWLK6-CZrXbG5Q.js} +1 -1
  286. package/web-shell/assets/{erDiagram-TEJ5UH35-CGvFcZco.js → erDiagram-TEJ5UH35-BjozEAYu.js} +1 -1
  287. package/web-shell/assets/{flowDiagram-I6XJVG4X-vms6oVdv.js → flowDiagram-I6XJVG4X-B3a2I8c-.js} +1 -1
  288. package/web-shell/assets/{ganttDiagram-6RSMTGT7-ukT_sfmi.js → ganttDiagram-6RSMTGT7-CIMn9fNm.js} +1 -1
  289. package/web-shell/assets/{gitGraphDiagram-PVQCEYII-Bn2ZE2Ut.js → gitGraphDiagram-PVQCEYII-DlFy9KRx.js} +1 -1
  290. package/web-shell/assets/{index-wFXp7W68.js → index-BODUAzQA.js} +1 -1
  291. package/web-shell/assets/index-C54DNMF7.js +1209 -0
  292. package/web-shell/assets/index-lWqBfc78.css +5 -0
  293. package/web-shell/assets/{infoDiagram-5YYISTIA-DHJdSi7x.js → infoDiagram-5YYISTIA-BmKjQgCy.js} +1 -1
  294. package/web-shell/assets/{ishikawaDiagram-YF4QCWOH-DOvd2Wph.js → ishikawaDiagram-YF4QCWOH-BrQEMZz2.js} +1 -1
  295. package/web-shell/assets/{journeyDiagram-JHISSGLW-CH_urMCT.js → journeyDiagram-JHISSGLW-D-2r7Xrt.js} +1 -1
  296. package/web-shell/assets/{kanban-definition-UN3LZRKU-FKiBdgbH.js → kanban-definition-UN3LZRKU-CndsFHCX.js} +1 -1
  297. package/web-shell/assets/{linear-0ZVQFVKf.js → linear-D-IwNnKx.js} +1 -1
  298. package/web-shell/assets/{mermaid.core-DJ05ZZIK.js → mermaid.core-4ll09sri.js} +5 -5
  299. package/web-shell/assets/{mindmap-definition-RKZ34NQL-BPuUhkUm.js → mindmap-definition-RKZ34NQL-maMRIxjo.js} +1 -1
  300. package/web-shell/assets/{pieDiagram-4H26LBE5-yLFKcXyG.js → pieDiagram-4H26LBE5-aunUDhrJ.js} +1 -1
  301. package/web-shell/assets/{quadrantDiagram-W4KKPZXB-irWqc1pE.js → quadrantDiagram-W4KKPZXB-D3K0P1NZ.js} +1 -1
  302. package/web-shell/assets/{requirementDiagram-4Y6WPE33-B_4uMoIV.js → requirementDiagram-4Y6WPE33-CX2X9HRc.js} +1 -1
  303. package/web-shell/assets/{sankeyDiagram-5OEKKPKP-ciA4GPwk.js → sankeyDiagram-5OEKKPKP-CDroWk7l.js} +1 -1
  304. package/web-shell/assets/{sequenceDiagram-3UESZ5HK-CRdZvy0U.js → sequenceDiagram-3UESZ5HK-DTk-2b16.js} +1 -1
  305. package/web-shell/assets/{stateDiagram-AJRCARHV-DaYIkCCn.js → stateDiagram-AJRCARHV-Cud64hQr.js} +1 -1
  306. package/web-shell/assets/stateDiagram-v2-BHNVJYJU-g-uUpecT.js +1 -0
  307. package/web-shell/assets/{timeline-definition-PNZ67QCA-oBUKv6iH.js → timeline-definition-PNZ67QCA-DfD5okf_.js} +1 -1
  308. package/web-shell/assets/{vennDiagram-CIIHVFJN-CGW9Sdmb.js → vennDiagram-CIIHVFJN-BYl8ay25.js} +1 -1
  309. package/web-shell/assets/{wardley-L42UT6IY-CvwKJOCm.js → wardley-L42UT6IY-BZFAt10J.js} +1 -1
  310. package/web-shell/assets/{wardleyDiagram-YWT4CUSO-Ipc260sN.js → wardleyDiagram-YWT4CUSO-BIWn0GA7.js} +1 -1
  311. package/web-shell/assets/{xychartDiagram-2RQKCTM6-D6-CM7pK.js → xychartDiagram-2RQKCTM6-1_H4xblT.js} +1 -1
  312. package/web-shell/index.html +2 -2
  313. package/chunks/chunk-ETD6K42I.js +0 -358
  314. package/chunks/chunk-I5NLVPZJ.js +0 -45
  315. package/chunks/chunk-ONWW74X6.js +0 -74639
  316. package/chunks/chunk-W7FJ3N32.js +0 -49
  317. package/chunks/daemon-status-provider-LVTVJGAD.js +0 -77
  318. package/chunks/handleAutoUpdate-AAQ6PL3E.js +0 -70
  319. package/chunks/nonInteractiveCli-QTEHDDFH.js +0 -129
  320. package/chunks/updateCheck-JJEUQ54U.js +0 -73
  321. package/chunks/write-file-M2DTFILF.js +0 -599
  322. package/web-shell/assets/channel-04R0vLbG.js +0 -1
  323. package/web-shell/assets/classDiagram-4FO5ZUOK-Bw9SOwAV.js +0 -1
  324. package/web-shell/assets/classDiagram-v2-Q7XG4LA2-Bw9SOwAV.js +0 -1
  325. package/web-shell/assets/index-DgkKrjw3.js +0 -1187
  326. package/web-shell/assets/index-Rv6mOAN9.css +0 -5
  327. package/web-shell/assets/stateDiagram-v2-BHNVJYJU-DWBoO4UY.js +0 -1
@@ -14,15 +14,16 @@ import {
14
14
  shouldSuppressRememberErrorDetails,
15
15
  workspaceMemoryFailureCode,
16
16
  workspaceMemoryFailureDiagnostics
17
- } from "./chunk-TTSKHF43.js";
17
+ } from "./chunk-BK6UOUJ2.js";
18
18
  import {
19
19
  openQwenAsrRealtimeStream,
20
20
  openVoiceStream,
21
21
  openVoiceStreamWithRetry
22
- } from "./chunk-GKY2OJ7R.js";
22
+ } from "./chunk-ZHERRXZJ.js";
23
23
  import {
24
24
  SetupGithubError,
25
25
  collectSessionData,
26
+ createTranscriptMessageUpdate,
26
27
  generateExportFilename,
27
28
  normalizeSessionData,
28
29
  setupGithub,
@@ -30,25 +31,21 @@ import {
30
31
  toJson,
31
32
  toJsonl,
32
33
  toMarkdown
33
- } from "./chunk-FVS747N7.js";
34
+ } from "./chunk-C54UTDOC.js";
34
35
  import {
35
36
  OBSERVED_CONTACT_MAX_FRESH_WITHIN_SECONDS,
36
37
  ObservedChannelContactStore
37
- } from "./chunk-KTUQMDEP.js";
38
+ } from "./chunk-4K7VDKAD.js";
39
+ import "./chunk-V4AKJQ26.js";
38
40
  import "./chunk-RS7MT2QG.js";
39
- import "./chunk-CVDW42JT.js";
40
41
  import "./chunk-H2XVO6NE.js";
41
- import "./chunk-QTERJVPZ.js";
42
42
  import "./chunk-QHTIBUWB.js";
43
- import "./chunk-L573Z2QZ.js";
44
- import {
45
- createTotalSessionAdmissionController
46
- } from "./chunk-R3VWUU2E.js";
43
+ import "./chunk-QTERJVPZ.js";
44
+ import "./chunk-3Z43GZUQ.js";
47
45
  import {
48
46
  createSingleWorkspaceRegistry,
49
47
  createWorkspaceSessionOwnerIndex
50
- } from "./chunk-W7H223ZZ.js";
51
- import "./chunk-GRC5HGPI.js";
48
+ } from "./chunk-UGYMA4EI.js";
52
49
  import {
53
50
  CAPABILITIES_SCHEMA_VERSION,
54
51
  CLIENT_ID_HEADER,
@@ -73,6 +70,7 @@ import {
73
70
  createBridgeFileSystemAdapter,
74
71
  createBuildWorkspaceCtx,
75
72
  createClientMcpServerProvider,
73
+ createManagedScratchDirectory,
76
74
  createMutationGate,
77
75
  createRateLimiter,
78
76
  denyBrowserOriginCors,
@@ -84,6 +82,7 @@ import {
84
82
  installAccessLogMiddleware,
85
83
  isBrowserAutomationMcpAvailable,
86
84
  isDeepHealthQuery,
85
+ isScratchRootCompatible,
87
86
  parseAllowOriginPatterns,
88
87
  parseAndValidateWorkspaceClientId,
89
88
  parseClientIdHeader,
@@ -104,42 +103,29 @@ import {
104
103
  setRateLimiter,
105
104
  unsafeRevealSecret,
106
105
  validateMcpRuntimeServerName
107
- } from "./chunk-7YBZGNEC.js";
106
+ } from "./chunk-5G3ZVADU.js";
108
107
  import {
109
108
  isLoopbackBind
110
109
  } from "./chunk-RXFQM6FQ.js";
111
110
  import {
112
111
  createDaemonStatusProvider
113
- } from "./chunk-T7DDD7CZ.js";
112
+ } from "./chunk-NAXEEGJU.js";
114
113
  import "./chunk-LXXMOYPL.js";
115
- import "./chunk-7KDI2IB2.js";
114
+ import "./chunk-HDATOR4J.js";
116
115
  import "./chunk-E5Z2AVNV.js";
117
- import {
118
- SessionArtifactAuthorizationError,
119
- SessionArtifactValidationError,
120
- createAcpSessionBridge,
121
- parseSessionSource
122
- } from "./chunk-EVSTCA7S.js";
123
- import {
124
- EVENT_SCHEMA_VERSION,
125
- SubscriberLimitExceededError
126
- } from "./chunk-6RLROE6G.js";
127
- import "./chunk-COH43MRJ.js";
128
- import "./chunk-QR6U5QPP.js";
129
- import "./chunk-6GUTHAN7.js";
130
116
  import {
131
117
  createWorkspaceProvidersStatusProvider
132
- } from "./chunk-WKRXIHD6.js";
118
+ } from "./chunk-COAARUPK.js";
133
119
  import {
134
120
  getAuthTypeFromEnv,
135
121
  resolveCliGenerationConfig
136
- } from "./chunk-TCKTNY66.js";
122
+ } from "./chunk-M4VFMLQK.js";
137
123
  import {
138
124
  snapshotProcessEnv
139
- } from "./chunk-AR27OPIU.js";
125
+ } from "./chunk-ZKFJKN23.js";
140
126
  import {
141
127
  createWorkspaceSkillsStatusProvider
142
- } from "./chunk-5NWV4NFB.js";
128
+ } from "./chunk-PRAUGUNM.js";
143
129
  import "./chunk-2W3OOD4W.js";
144
130
  import {
145
131
  EMPTY_WORKSPACE_VOICE_UPDATE_ERROR,
@@ -154,14 +140,14 @@ import {
154
140
  validateWorkspaceSkillName,
155
141
  validateWorkspaceVoiceState,
156
142
  voiceSettingsScopeToWire
157
- } from "./chunk-Y4CRUWFZ.js";
143
+ } from "./chunk-VTXX72XS.js";
158
144
  import {
159
145
  PermissionRulesValidationError,
160
146
  buildPermissionSettings,
161
147
  isPermissionRuleType,
162
148
  normalizePermissionRules,
163
149
  readPermissionRuleSet
164
- } from "./chunk-WAX3ITOA.js";
150
+ } from "./chunk-A3TAEAHX.js";
165
151
  import {
166
152
  assertVoiceBaseUrlNetworkAllowed,
167
153
  isStreamingVoiceModel,
@@ -169,13 +155,36 @@ import {
169
155
  resolveVoiceTranscriptionConfig,
170
156
  sanitizeVoiceErrorMessage,
171
157
  transcribeVoiceAudio
172
- } from "./chunk-B453NMZJ.js";
158
+ } from "./chunk-M3EQ3GZC.js";
173
159
  import {
174
160
  isVoiceEnabled,
175
161
  isVoiceMode,
176
162
  readVoiceModel
177
- } from "./chunk-IB35C3IL.js";
178
- import "./chunk-BVLROR2T.js";
163
+ } from "./chunk-AVQ6EX4J.js";
164
+ import "./chunk-QLJUC7TG.js";
165
+ import {
166
+ WorkspacePermissionRulesSessionRequiredError,
167
+ WorkspaceSettingsPartialPersistError,
168
+ WorkspaceSkillNotFoundError,
169
+ WorkspaceSkillNotToggleableError
170
+ } from "./chunk-OA4JVLSA.js";
171
+ import {
172
+ createTotalSessionAdmissionController
173
+ } from "./chunk-VYPFXUCB.js";
174
+ import "./chunk-GRC5HGPI.js";
175
+ import {
176
+ SessionArtifactAuthorizationError,
177
+ SessionArtifactValidationError,
178
+ createAcpSessionBridge,
179
+ parseSessionSource
180
+ } from "./chunk-RMY5SX7S.js";
181
+ import {
182
+ EVENT_SCHEMA_VERSION,
183
+ EventBus,
184
+ SubscriberLimitExceededError
185
+ } from "./chunk-6RLROE6G.js";
186
+ import "./chunk-COH43MRJ.js";
187
+ import "./chunk-QR6U5QPP.js";
179
188
  import {
180
189
  BranchWhilePromptActiveError,
181
190
  CancelSentinelCollisionError,
@@ -189,6 +198,7 @@ import {
189
198
  McpServerRestartFailedError,
190
199
  PermissionForbiddenError,
191
200
  PermissionPolicyNotImplementedError,
201
+ PromptDeadlineExceededError,
192
202
  PromptQueueFullError,
193
203
  RestoreInProgressError,
194
204
  SessionArchivedError,
@@ -207,42 +217,39 @@ import {
207
217
  WorkspaceInitRaceError,
208
218
  WorkspaceInitSymlinkError,
209
219
  WorkspaceMismatchError
210
- } from "./chunk-X6YQWCIJ.js";
211
- import {
212
- STATUS_SCHEMA_VERSION,
213
- createIdleWorkspaceMemoryStatus,
214
- mapDomainErrorToErrorKind
215
- } from "./chunk-WXAXH7IJ.js";
216
- import {
217
- WorkspacePermissionRulesSessionRequiredError,
218
- WorkspaceSettingsPartialPersistError,
219
- WorkspaceSkillNotFoundError,
220
- WorkspaceSkillNotToggleableError
221
- } from "./chunk-OA4JVLSA.js";
220
+ } from "./chunk-UH3WSE5L.js";
222
221
  import "./chunk-WBL3FJEU.js";
223
- import "./chunk-T2NCM2ET.js";
224
222
  import {
225
223
  daemonObservedContactsPath,
226
224
  loadChannelsConfig
227
- } from "./chunk-KXEGCGUG.js";
228
- import "./chunk-JVTCARQ6.js";
225
+ } from "./chunk-Q22WWVR6.js";
226
+ import "./chunk-FQI7LT7T.js";
229
227
  import "./chunk-57OAHC2Y.js";
230
228
  import {
231
229
  parseChannelWebhookConfigLenient
232
- } from "./chunk-OMH3276Y.js";
233
- import "./chunk-4ODB7WIB.js";
230
+ } from "./chunk-GHRSKGHF.js";
231
+ import "./chunk-6ZBPS62S.js";
234
232
  import "./chunk-V6WHFGST.js";
233
+ import "./chunk-6HOCJNO5.js";
234
+ import {
235
+ STATUS_SCHEMA_VERSION,
236
+ createIdleWorkspaceMemoryStatus,
237
+ mapDomainErrorToErrorKind
238
+ } from "./chunk-ESQHGKPJ.js";
235
239
  import {
236
240
  MAX_REGISTERED_WORKSPACES,
241
+ WorkspaceDisplayNameValidationError,
237
242
  WorkspaceRegistrationStoreCommittedError,
238
243
  WorkspaceRegistrationStoreLimitError,
244
+ normalizeWorkspaceDisplayName,
239
245
  workspaceRegistrationId
240
- } from "./chunk-SDXIH6OA.js";
246
+ } from "./chunk-IFUNDCQ6.js";
241
247
  import {
242
248
  MAX_WORKSPACE_PATH_LENGTH,
243
249
  canonicalizeWorkspace,
244
- canonicalizeWorkspaces
245
- } from "./chunk-W7FJ3N32.js";
250
+ canonicalizeWorkspaces,
251
+ translateAndCheckAbsoluteWorkspacePath
252
+ } from "./chunk-2RFKHEXL.js";
246
253
  import {
247
254
  MAX_CHANNEL_STARTUP_FAILURES,
248
255
  MAX_CHANNEL_STARTUP_FAILURE_CHANNEL_LENGTH,
@@ -251,7 +258,7 @@ import {
251
258
  QWEN_SERVER_TOKEN_ENV,
252
259
  isChannelWebhookEnqueueError,
253
260
  normalizeWorkerDiagnostic
254
- } from "./chunk-Y2ENGUD6.js";
261
+ } from "./chunk-QKTHJXCS.js";
255
262
  import {
256
263
  normalizeServeChannelSelection
257
264
  } from "./chunk-TJTKSVIV.js";
@@ -259,9 +266,10 @@ import {
259
266
  redactLogCredentials
260
267
  } from "./chunk-M5GB774H.js";
261
268
  import "./chunk-5HBA2Z7V.js";
269
+ import "./chunk-T2NCM2ET.js";
262
270
  import {
263
271
  sanitizeLogText
264
- } from "./chunk-NIJEXGV6.js";
272
+ } from "./chunk-RVLZCXEE.js";
265
273
  import "./chunk-UDXSXLER.js";
266
274
  import {
267
275
  getDialogSettingKeys,
@@ -272,20 +280,23 @@ import {
272
280
  getWritableScopes,
273
281
  loadSettings,
274
282
  validateSettingValue
275
- } from "./chunk-KPZNOZPC.js";
283
+ } from "./chunk-GWM4PDYK.js";
276
284
  import "./chunk-RKUWKYED.js";
285
+ import {
286
+ SUPPORTED_LANGUAGES,
287
+ detectSystemLanguage,
288
+ resolveLanguageSetting,
289
+ resolveSupportedLanguage
290
+ } from "./chunk-YLSB23Y2.js";
291
+ import "./chunk-YNWJAOPL.js";
277
292
  import "./chunk-GOXKNSDZ.js";
278
293
  import "./chunk-IDS7MSUP.js";
279
- import {
280
- SUPPORTED_LANGUAGES
281
- } from "./chunk-2DXOIVUI.js";
282
- import "./chunk-OF2BBLYQ.js";
283
294
  import "./chunk-QRUIS3DN.js";
284
- import "./chunk-IUSNI6IX.js";
295
+ import "./chunk-ISMD2AB3.js";
285
296
  import "./chunk-VJNBRRZG.js";
286
297
  import {
287
298
  getWorkspaceTrustStatus
288
- } from "./chunk-MC2DOZS7.js";
299
+ } from "./chunk-PVT6E3ZI.js";
289
300
  import "./chunk-ALGGS7UH.js";
290
301
  import {
291
302
  isWithinRoot as isWithinRoot2
@@ -299,15 +310,19 @@ import {
299
310
  BuiltinAgentRegistry,
300
311
  Client,
301
312
  ClientMcpRegistrar,
313
+ DEFAULT_LOG_LIMIT,
302
314
  ExtensionManager,
303
315
  GROUP_COLOR_OPTIONS,
316
+ GitWorktreeService,
304
317
  IMAGE_CAPABILITY,
305
318
  InvalidSessionTranscriptCursorError,
319
+ MAX_LOG_LIMIT,
306
320
  ModelsConfig,
307
321
  RUNTIME_MCP_IF_ABSENT_CONFIG_FLAG,
308
322
  SESSION_TRANSCRIPT_MAX_INDEX_BYTES,
309
323
  SESSION_TRANSCRIPT_MAX_LIMIT,
310
324
  SESSION_TRANSCRIPT_MAX_PAGE_BYTES,
325
+ SESSION_WRITER_RPC_CODES,
311
326
  SessionOrganizationError,
312
327
  SessionOrganizationService,
313
328
  SessionService,
@@ -316,6 +331,7 @@ import {
316
331
  SessionTranscriptReader,
317
332
  SessionTranscriptSnapshotUnavailableError,
318
333
  SessionTranscriptTooLargeError,
334
+ SessionWriterError,
319
335
  StandardFileSystemService,
320
336
  StdioClientTransport,
321
337
  StreamableHTTPClientTransport,
@@ -326,13 +342,18 @@ import {
326
342
  buildUsageDashboard,
327
343
  detectLineEnding,
328
344
  encodeTextFileContent,
345
+ fetchGitCommitDetail,
329
346
  fetchGitDiff,
330
347
  fetchGitDiffHunksForFile,
348
+ fetchGitLog,
331
349
  getGitWorkingTreeStatus,
350
+ getSubagentSessionDir,
332
351
  glob,
333
352
  loadIgnoreRules,
334
353
  loadUsageHistoryWithLive,
335
354
  parseInstallSource,
355
+ readAgentMeta,
356
+ readWorktreeSession,
336
357
  redactUrlCredentials,
337
358
  resolveBranchName,
338
359
  resolveProviderProtocol,
@@ -340,16 +361,22 @@ import {
340
361
  stripAnsiAndControl,
341
362
  stripTerminalControlSequences,
342
363
  watchRepoBranch,
343
- writeWorkspaceContextFile
344
- } from "./chunk-6OH6A5EX.js";
345
- import "./chunk-5M6IDOMF.js";
364
+ writeWorkspaceContextFile,
365
+ writeWorktreeSession,
366
+ writeWorktreeSessionMarker
367
+ } from "./chunk-BLAEKN6K.js";
346
368
  import "./chunk-T4TZQJ7W.js";
347
369
  import "./chunk-H6XPXXMH.js";
348
- import "./chunk-OONJNQ42.js";
370
+ import "./chunk-5M6IDOMF.js";
371
+ import "./chunk-T2L47JJK.js";
372
+ import "./chunk-GPSKDNEE.js";
373
+ import "./chunk-X6N25LXS.js";
374
+ import "./chunk-E2UVIFI2.js";
375
+ import "./chunk-L5F3T6TQ.js";
349
376
  import {
350
377
  MAX_JOBS,
351
378
  nextDurableFireMs
352
- } from "./chunk-JDI67JFB.js";
379
+ } from "./chunk-Q2YKNMLS.js";
353
380
  import {
354
381
  nextFireTime,
355
382
  parseCron
@@ -362,24 +389,22 @@ import {
362
389
  readCronTasks,
363
390
  taskHasLegacyCondition,
364
391
  updateCronTasks
365
- } from "./chunk-EIAK6Q2B.js";
366
- import "./chunk-FSL5W5TI.js";
367
- import "./chunk-D2VIDMVM.js";
368
- import "./chunk-E2UVIFI2.js";
369
- import "./chunk-WBTZGWQ6.js";
392
+ } from "./chunk-KHOVYUHX.js";
370
393
  import "./chunk-SZRN75WQ.js";
371
- import "./chunk-HTO4JFDZ.js";
394
+ import "./chunk-6PVPNMXU.js";
372
395
  import "./chunk-CPBF7KYF.js";
396
+ import "./chunk-NABLFI57.js";
397
+ import "./chunk-QBUDF33N.js";
398
+ import "./chunk-LIZRAKPB.js";
373
399
  import {
374
400
  APPROVAL_MODES,
375
401
  SubagentError,
376
402
  SubagentErrorCode
377
- } from "./chunk-ETD6K42I.js";
403
+ } from "./chunk-WHGVTP7Q.js";
378
404
  import "./chunk-6AM5D4ME.js";
379
- import "./chunk-G45X5TRN.js";
380
- import "./chunk-PBATSWUQ.js";
381
- import "./chunk-ZEOZL37W.js";
382
- import "./chunk-OOCI5VVU.js";
405
+ import "./chunk-JCW2R7WC.js";
406
+ import "./chunk-57FIIFJN.js";
407
+ import "./chunk-HTO4JFDZ.js";
383
408
  import {
384
409
  QwenOAuth2Client,
385
410
  QwenOAuthPollError,
@@ -388,10 +413,15 @@ import {
388
413
  isDeviceAuthorizationSuccess,
389
414
  isDeviceTokenPending,
390
415
  isDeviceTokenSuccess
391
- } from "./chunk-UQES76OO.js";
392
- import "./chunk-OKWRU4NO.js";
393
- import "./chunk-XNP57UDV.js";
416
+ } from "./chunk-2HGTVAOW.js";
394
417
  import "./chunk-JESCGQM3.js";
418
+ import "./chunk-RC7A7SSL.js";
419
+ import "./chunk-C3EXYVFX.js";
420
+ import "./chunk-XVNQMZ2I.js";
421
+ import "./chunk-CR3C7WXL.js";
422
+ import "./chunk-FODK6UMO.js";
423
+ import "./chunk-GLNBDYUX.js";
424
+ import "./chunk-DJ2GSRLV.js";
395
425
  import {
396
426
  addDaemonRequestAttribute,
397
427
  decodeBufferWithEncodingInfo,
@@ -400,43 +430,42 @@ import {
400
430
  hashDaemonWorkspace,
401
431
  isBinaryFile,
402
432
  isWithinRoot,
433
+ parseLineTolerant,
434
+ read,
403
435
  recordDaemonBridgeError,
404
436
  recordDaemonError,
405
437
  recordDaemonHttpRequest,
406
438
  recordDaemonHttpResponse,
407
439
  withDaemonRequestSpan
408
- } from "./chunk-ONWW74X6.js";
409
- import "./chunk-4WKAA4KS.js";
410
- import "./chunk-CR3C7WXL.js";
440
+ } from "./chunk-U6TQGUNB.js";
411
441
  import "./chunk-VGC4I5JJ.js";
412
- import "./chunk-JD3MKVKL.js";
413
- import "./chunk-UEY4AYUL.js";
414
- import "./chunk-BDBMYST4.js";
415
- import "./chunk-467G3SV5.js";
416
- import "./chunk-S35ZDXOS.js";
417
- import "./chunk-XVNQMZ2I.js";
418
- import "./chunk-FODK6UMO.js";
419
- import "./chunk-GLNBDYUX.js";
420
- import "./chunk-DJ2GSRLV.js";
421
- import "./chunk-6EFTQYW7.js";
422
- import "./chunk-MAQQGNQ5.js";
442
+ import "./chunk-4K56OJFJ.js";
443
+ import "./chunk-CBOQ3HY7.js";
423
444
  import "./chunk-A4UCTEB5.js";
424
445
  import "./chunk-XWRJCPHC.js";
446
+ import "./chunk-QNLNLENL.js";
447
+ import "./chunk-6X4GWOPW.js";
425
448
  import "./chunk-TYQMGACW.js";
426
449
  import {
427
450
  import_websocket_server
428
451
  } from "./chunk-TYAMGABM.js";
429
452
  import "./chunk-FCMNKVXT.js";
453
+ import "./chunk-RCUEYZDE.js";
454
+ import "./chunk-HTR4WV6U.js";
455
+ import "./chunk-BULDBTYC.js";
456
+ import "./chunk-U7ZFW55U.js";
457
+ import "./chunk-NPQDJGKU.js";
458
+ import "./chunk-YM3SZTH4.js";
430
459
  import {
431
460
  FatalConfigError,
432
461
  Storage,
433
462
  createDebugLogger,
434
463
  runWithoutDebugLogSession
435
- } from "./chunk-C27BYUX6.js";
464
+ } from "./chunk-OQB4EXO4.js";
436
465
  import "./chunk-75DOP5OR.js";
437
466
  import "./chunk-DMTGGOSA.js";
438
467
  import "./chunk-YQ3U5MUC.js";
439
- import "./chunk-TB6UDU4T.js";
468
+ import "./chunk-THJNPLI4.js";
440
469
  import {
441
470
  init_esbuild_shims
442
471
  } from "./chunk-5O2XNYP6.js";
@@ -455,7 +484,6 @@ import { createHash as createHash3, timingSafeEqual } from "node:crypto";
455
484
 
456
485
  // packages/cli/src/serve/acp-http/dispatch.ts
457
486
  init_esbuild_shims();
458
- import path9 from "node:path";
459
487
 
460
488
  // packages/cli/src/serve/fs/errors.ts
461
489
  init_esbuild_shims();
@@ -629,9 +657,9 @@ async function findExistingAncestor(absolute) {
629
657
  let current = absolute;
630
658
  const tailParts = [];
631
659
  for (let i = 0; i < MAX_ANCESTOR_HOPS; i++) {
632
- let stat2 = null;
660
+ let stat3 = null;
633
661
  try {
634
- stat2 = await fsp.stat(current);
662
+ stat3 = await fsp.stat(current);
635
663
  } catch (err) {
636
664
  const code = err?.code;
637
665
  if (code === "ENOENT" || code === "ENOTDIR") {
@@ -639,8 +667,8 @@ async function findExistingAncestor(absolute) {
639
667
  throw err;
640
668
  }
641
669
  }
642
- if (stat2) {
643
- if (tailParts.length > 0 && !stat2.isDirectory()) {
670
+ if (stat3) {
671
+ if (tailParts.length > 0 && !stat3.isDirectory()) {
644
672
  throw new FsError(
645
673
  "parse_error",
646
674
  `path component is not a directory: ${absolute}`,
@@ -713,7 +741,7 @@ async function resolveWithinWorkspace(input, boundWorkspaces, intent) {
713
741
  boundCanonicals
714
742
  );
715
743
  if (boundCanonical !== void 0) {
716
- const finalPathIsSymlink = await fsp.lstat(absolute).then((stat2) => stat2.isSymbolicLink()).catch((lstatErr) => {
744
+ const finalPathIsSymlink = await fsp.lstat(absolute).then((stat3) => stat3.isSymbolicLink()).catch((lstatErr) => {
717
745
  if (lstatErr.code === "ENOENT" || lstatErr.code === "ENOTDIR") {
718
746
  return false;
719
747
  }
@@ -1204,8 +1232,8 @@ var WorkspaceFileSystemImpl = class {
1204
1232
  const toRead = Math.min(maxBytes, available);
1205
1233
  buf = Buffer.allocUnsafe(toRead);
1206
1234
  if (toRead > 0) {
1207
- const read = await fh.read(buf, 0, toRead, offset);
1208
- buf = read.bytesRead === toRead ? buf : buf.subarray(0, read.bytesRead);
1235
+ const read2 = await fh.read(buf, 0, toRead, offset);
1236
+ buf = read2.bytesRead === toRead ? buf : buf.subarray(0, read2.bytesRead);
1209
1237
  }
1210
1238
  const afterRead = await fh.stat();
1211
1239
  assertSameFile(st, afterRead, p, "read");
@@ -1746,17 +1774,17 @@ var WorkspaceFileSystemImpl = class {
1746
1774
  * for their `sendFsError` serializer.
1747
1775
  */
1748
1776
  recordAndWrap(err, intent, input) {
1749
- const fs3 = wrapAsFsError(err);
1777
+ const fs6 = wrapAsFsError(err);
1750
1778
  this.deps.audit.recordDenied(this.deps.ctx, {
1751
1779
  intent,
1752
1780
  input,
1753
- errorKind: fs3.kind,
1754
- hint: fs3.hint,
1781
+ errorKind: fs6.kind,
1782
+ hint: fs6.hint,
1755
1783
  // Quote the underlying OS / FsError message so audit
1756
1784
  // consumers debugging a production incident can see the
1757
1785
  // actual cause (errno text, byte counts, glob pattern,
1758
1786
  // etc.) rather than just `errorKind` + `hint`.
1759
- message: fs3.message,
1787
+ message: fs6.message,
1760
1788
  // For glob denials (parse_error pattern rejection,
1761
1789
  // catastrophic walk failures) the input IS the pattern
1762
1790
  // already; surfacing it on the dedicated `pattern` field
@@ -1765,7 +1793,7 @@ var WorkspaceFileSystemImpl = class {
1765
1793
  // branching on intent.
1766
1794
  pattern: intent === "glob" ? input : void 0
1767
1795
  });
1768
- return fs3;
1796
+ return fs6;
1769
1797
  }
1770
1798
  };
1771
1799
  var CONTENT_HASH_RE = /^sha256:[0-9a-f]{64}$/;
@@ -1873,9 +1901,9 @@ async function readStableRegularFileBuffer(p, pre) {
1873
1901
  const out = Buffer.alloc(opened.size);
1874
1902
  let offset = 0;
1875
1903
  while (offset < opened.size) {
1876
- const read = await fh.read(out, offset, opened.size - offset, offset);
1877
- if (read.bytesRead === 0) break;
1878
- offset += read.bytesRead;
1904
+ const read2 = await fh.read(out, offset, opened.size - offset, offset);
1905
+ if (read2.bytesRead === 0) break;
1906
+ offset += read2.bytesRead;
1879
1907
  }
1880
1908
  const afterRead = await fh.stat();
1881
1909
  assertSameFile(opened, afterRead, p, "read");
@@ -2130,15 +2158,15 @@ async function hashRegularFileAtPath(p, pre) {
2130
2158
  const buf = Buffer.allocUnsafe(64 * 1024);
2131
2159
  let offset = 0;
2132
2160
  while (offset < opened.size) {
2133
- const read = await fh.read(
2161
+ const read2 = await fh.read(
2134
2162
  buf,
2135
2163
  0,
2136
2164
  Math.min(buf.length, opened.size - offset),
2137
2165
  offset
2138
2166
  );
2139
- if (read.bytesRead === 0) break;
2140
- hash.update(buf.subarray(0, read.bytesRead));
2141
- offset += read.bytesRead;
2167
+ if (read2.bytesRead === 0) break;
2168
+ hash.update(buf.subarray(0, read2.bytesRead));
2169
+ offset += read2.bytesRead;
2142
2170
  }
2143
2171
  } finally {
2144
2172
  await fh.close();
@@ -2247,7 +2275,7 @@ async function renameWithRetryLocal(src, dest, retries, delayMs) {
2247
2275
  const retryable = code === "EPERM" || code === "EACCES";
2248
2276
  if (!retryable || attempt === retries) throw err;
2249
2277
  await new Promise(
2250
- (resolve5) => setTimeout(resolve5, delayMs * 2 ** attempt)
2278
+ (resolve6) => setTimeout(resolve6, delayMs * 2 ** attempt)
2251
2279
  );
2252
2280
  }
2253
2281
  }
@@ -2502,12 +2530,12 @@ __name(applyReadHeaders, "applyReadHeaders");
2502
2530
  function sendFsError(res, err, route) {
2503
2531
  applyReadHeaders(res);
2504
2532
  if (isFsError(err)) {
2505
- const fs3 = err;
2506
- res.status(fs3.status).json({
2507
- errorKind: fs3.kind,
2508
- error: fs3.message,
2509
- hint: fs3.hint,
2510
- status: fs3.status
2533
+ const fs6 = err;
2534
+ res.status(fs6.status).json({
2535
+ errorKind: fs6.kind,
2536
+ error: fs6.message,
2537
+ hint: fs6.hint,
2538
+ status: fs6.status
2511
2539
  });
2512
2540
  return;
2513
2541
  }
@@ -2609,13 +2637,13 @@ async function handleGetFile(req, res, deps) {
2609
2637
  });
2610
2638
  return;
2611
2639
  }
2612
- const fs3 = factory.forRequest({
2640
+ const fs6 = factory.forRequest({
2613
2641
  originatorClientId: clientId ?? void 0,
2614
2642
  route: ROUTE2
2615
2643
  });
2616
2644
  try {
2617
- const resolved = await fs3.resolve(queryPath, "read");
2618
- const out = await fs3.readText(resolved, { maxBytes, line, limit });
2645
+ const resolved = await fs6.resolve(queryPath, "read");
2646
+ const out = await fs6.readText(resolved, { maxBytes, line, limit });
2619
2647
  const returnedBytes = Buffer.byteLength(out.content, "utf-8");
2620
2648
  applyReadHeaders(res);
2621
2649
  res.status(200).json({
@@ -2669,13 +2697,13 @@ async function handleGetFileBytes(req, res, deps) {
2669
2697
  });
2670
2698
  return;
2671
2699
  }
2672
- const fs3 = factory.forRequest({
2700
+ const fs6 = factory.forRequest({
2673
2701
  originatorClientId: clientId ?? void 0,
2674
2702
  route: ROUTE2
2675
2703
  });
2676
2704
  try {
2677
- const resolved = await fs3.resolve(queryPath, "read");
2678
- const out = await fs3.readBytesWindow(resolved, {
2705
+ const resolved = await fs6.resolve(queryPath, "read");
2706
+ const out = await fs6.readBytesWindow(resolved, {
2679
2707
  offset: offset ?? 0,
2680
2708
  maxBytes: maxBytes ?? DEFAULT_FILE_BYTES_MAX_BYTES
2681
2709
  });
@@ -2703,13 +2731,13 @@ async function handleGetStat(req, res, deps) {
2703
2731
  if (clientId === null) return;
2704
2732
  const queryPath = requireStringQuery(res, req.query["path"], "path", ROUTE2);
2705
2733
  if (queryPath === null) return;
2706
- const fs3 = factory.forRequest({
2734
+ const fs6 = factory.forRequest({
2707
2735
  originatorClientId: clientId ?? void 0,
2708
2736
  route: ROUTE2
2709
2737
  });
2710
2738
  try {
2711
- const resolved = await fs3.resolve(queryPath, "stat");
2712
- const st = await fs3.stat(resolved);
2739
+ const resolved = await fs6.resolve(queryPath, "stat");
2740
+ const st = await fs6.stat(resolved);
2713
2741
  applyReadHeaders(res);
2714
2742
  res.status(200).json({
2715
2743
  kind: "stat",
@@ -2732,13 +2760,13 @@ async function handleGetList(req, res, deps) {
2732
2760
  const queryPath = requireStringQuery(res, req.query["path"], "path", ROUTE2);
2733
2761
  if (queryPath === null) return;
2734
2762
  const includeIgnored = parseBoolFlag(req.query["includeIgnored"]);
2735
- const fs3 = factory.forRequest({
2763
+ const fs6 = factory.forRequest({
2736
2764
  originatorClientId: clientId ?? void 0,
2737
2765
  route: ROUTE2
2738
2766
  });
2739
2767
  try {
2740
- const resolved = await fs3.resolve(queryPath, "list");
2741
- const entries = await fs3.list(resolved, {
2768
+ const resolved = await fs6.resolve(queryPath, "list");
2769
+ const entries = await fs6.list(resolved, {
2742
2770
  includeIgnored,
2743
2771
  maxEntries: MAX_LIST_ENTRIES + 1
2744
2772
  });
@@ -2791,15 +2819,15 @@ async function handleGetGlob(req, res, deps) {
2791
2819
  }
2792
2820
  const cwdRaw = req.query["cwd"];
2793
2821
  const cwdString = typeof cwdRaw === "string" && cwdRaw.length > 0 ? cwdRaw : void 0;
2794
- const fs3 = factory.forRequest({
2822
+ const fs6 = factory.forRequest({
2795
2823
  originatorClientId: clientId ?? void 0,
2796
2824
  route: ROUTE2
2797
2825
  });
2798
2826
  const start = performance.now();
2799
2827
  try {
2800
- const cwdResolved = cwdString ? await fs3.resolve(cwdString, "list") : void 0;
2828
+ const cwdResolved = cwdString ? await fs6.resolve(cwdString, "list") : void 0;
2801
2829
  const cap = maxResults ?? DEFAULT_GLOB_MAX_RESULTS;
2802
- const probe = await fs3.glob(pattern, {
2830
+ const probe = await fs6.glob(pattern, {
2803
2831
  cwd: cwdResolved,
2804
2832
  includeIgnored,
2805
2833
  maxResults: cap + 1
@@ -2861,7 +2889,7 @@ function registerWorkspaceFileReadRoutes(app, deps) {
2861
2889
  }
2862
2890
  __name(registerWorkspaceFileReadRoutes, "registerWorkspaceFileReadRoutes");
2863
2891
  function registerWorkspaceQualifiedFileReadRoutes(app, deps) {
2864
- const resolve5 = /* @__PURE__ */ __name((req, res) => {
2892
+ const resolve6 = /* @__PURE__ */ __name((req, res) => {
2865
2893
  const runtime = resolveWorkspaceRuntimeFromParam(
2866
2894
  deps.workspaceRegistry,
2867
2895
  req,
@@ -2875,23 +2903,23 @@ function registerWorkspaceQualifiedFileReadRoutes(app, deps) {
2875
2903
  return true;
2876
2904
  }, "resolve");
2877
2905
  app.get("/workspaces/:workspace/file", (req, res) => {
2878
- if (!resolve5(req, res)) return;
2906
+ if (!resolve6(req, res)) return;
2879
2907
  void handleGetFile(req, res, deps);
2880
2908
  });
2881
2909
  app.get("/workspaces/:workspace/file/bytes", (req, res) => {
2882
- if (!resolve5(req, res)) return;
2910
+ if (!resolve6(req, res)) return;
2883
2911
  void handleGetFileBytes(req, res, deps);
2884
2912
  });
2885
2913
  app.get("/workspaces/:workspace/stat", (req, res) => {
2886
- if (!resolve5(req, res)) return;
2914
+ if (!resolve6(req, res)) return;
2887
2915
  void handleGetStat(req, res, deps);
2888
2916
  });
2889
2917
  app.get("/workspaces/:workspace/list", (req, res) => {
2890
- if (!resolve5(req, res)) return;
2918
+ if (!resolve6(req, res)) return;
2891
2919
  void handleGetList(req, res, deps);
2892
2920
  });
2893
2921
  app.get("/workspaces/:workspace/glob", (req, res) => {
2894
- if (!resolve5(req, res)) return;
2922
+ if (!resolve6(req, res)) return;
2895
2923
  void handleGetGlob(req, res, deps);
2896
2924
  });
2897
2925
  }
@@ -2973,7 +3001,7 @@ function validateClientId(clientId, deps, res) {
2973
3001
  }
2974
3002
  __name(validateClientId, "validateClientId");
2975
3003
  function createSetupGithubFileOps(factory, route, originatorClientId) {
2976
- const fs3 = factory.forRequest({
3004
+ const fs6 = factory.forRequest({
2977
3005
  route,
2978
3006
  ...originatorClientId ? { originatorClientId } : {}
2979
3007
  });
@@ -2996,14 +3024,14 @@ function createSetupGithubFileOps(factory, route, originatorClientId) {
2996
3024
  ]);
2997
3025
  },
2998
3026
  async writeTextFile(_gitRepoRoot, relativePath, content) {
2999
- const resolved = await fs3.resolve(relativePath, "write");
3000
- const out = await fs3.writeTextOverwrite(resolved, content);
3027
+ const resolved = await fs6.resolve(relativePath, "write");
3028
+ const out = await fs6.writeTextOverwrite(resolved, content);
3001
3029
  return { sizeBytes: out.sizeBytes };
3002
3030
  },
3003
3031
  async readTextFile(_gitRepoRoot, relativePath) {
3004
3032
  try {
3005
- const resolved = await fs3.resolve(relativePath, "read");
3006
- const out = await fs3.readText(resolved);
3033
+ const resolved = await fs6.resolve(relativePath, "read");
3034
+ const out = await fs6.readText(resolved);
3007
3035
  return out.content;
3008
3036
  } catch (error2) {
3009
3037
  if (isFsError(error2) && error2.kind === "path_not_found") {
@@ -3024,15 +3052,15 @@ async function ensureDirectoryWithoutSymlink(root, segments) {
3024
3052
  checkedSegments.push(segment);
3025
3053
  const label = `Workspace path "${checkedSegments.join("/")}"`;
3026
3054
  try {
3027
- const stat2 = await fsp3.lstat(current);
3028
- if (stat2.isSymbolicLink()) {
3055
+ const stat3 = await fsp3.lstat(current);
3056
+ if (stat3.isSymbolicLink()) {
3029
3057
  throw new SetupGithubError(
3030
3058
  "github_setup_invalid_workspace",
3031
3059
  `${label} must not be a symlink.`,
3032
3060
  400
3033
3061
  );
3034
3062
  }
3035
- if (!stat2.isDirectory()) {
3063
+ if (!stat3.isDirectory()) {
3036
3064
  throw new SetupGithubError(
3037
3065
  "github_setup_invalid_workspace",
3038
3066
  `${label} must be a directory.`,
@@ -3069,15 +3097,15 @@ async function ensureDirectoryWithoutSymlink(root, segments) {
3069
3097
  }
3070
3098
  __name(ensureDirectoryWithoutSymlink, "ensureDirectoryWithoutSymlink");
3071
3099
  async function assertDirectoryWithoutSymlink(target, label) {
3072
- const stat2 = await fsp3.lstat(target);
3073
- if (stat2.isSymbolicLink()) {
3100
+ const stat3 = await fsp3.lstat(target);
3101
+ if (stat3.isSymbolicLink()) {
3074
3102
  throw new SetupGithubError(
3075
3103
  "github_setup_invalid_workspace",
3076
3104
  `${label} must not be a symlink.`,
3077
3105
  400
3078
3106
  );
3079
3107
  }
3080
- if (!stat2.isDirectory()) {
3108
+ if (!stat3.isDirectory()) {
3081
3109
  throw new SetupGithubError(
3082
3110
  "github_setup_invalid_workspace",
3083
3111
  `${label} must be a directory.`,
@@ -4718,12 +4746,12 @@ async function collectWorkspaceMemoryStatus(boundWorkspace) {
4718
4746
  for (const filename of filenames) {
4719
4747
  const candidate = path8.join(globalDir, filename);
4720
4748
  try {
4721
- const stat2 = await fs.stat(candidate);
4722
- if (stat2.isFile()) {
4749
+ const stat3 = await fs.stat(candidate);
4750
+ if (stat3.isFile()) {
4723
4751
  files.push({
4724
4752
  absolutePath: candidate,
4725
4753
  scope: "global",
4726
- bytes: stat2.size
4754
+ bytes: stat3.size
4727
4755
  });
4728
4756
  }
4729
4757
  } catch (err) {
@@ -4767,12 +4795,12 @@ async function walkWorkspaceForMemory(start, filenames, errors) {
4767
4795
  for (const filename of filenames) {
4768
4796
  const candidate = path8.join(start, filename);
4769
4797
  try {
4770
- const stat2 = await fs.stat(candidate);
4771
- if (stat2.isFile()) {
4798
+ const stat3 = await fs.stat(candidate);
4799
+ if (stat3.isFile()) {
4772
4800
  out.push({
4773
4801
  absolutePath: candidate,
4774
4802
  scope: "workspace",
4775
- bytes: stat2.size
4803
+ bytes: stat3.size
4776
4804
  });
4777
4805
  }
4778
4806
  } catch (err) {
@@ -6563,6 +6591,43 @@ function errMsg(err) {
6563
6591
  return err instanceof Error ? err.message : String(err);
6564
6592
  }
6565
6593
  __name(errMsg, "errMsg");
6594
+ var SESSION_WRITER_RPC_ERRORS = {
6595
+ session_writer_conflict: {
6596
+ code: SESSION_WRITER_RPC_CODES.session_writer_conflict,
6597
+ message: "This session is already open in another Qwen process."
6598
+ },
6599
+ session_writer_lost: {
6600
+ code: SESSION_WRITER_RPC_CODES.session_writer_lost,
6601
+ message: "Write ownership for this session was lost."
6602
+ },
6603
+ session_transcript_changed: {
6604
+ code: SESSION_WRITER_RPC_CODES.session_transcript_changed,
6605
+ message: "The session transcript changed outside its active writer."
6606
+ },
6607
+ session_writer_unavailable: {
6608
+ code: SESSION_WRITER_RPC_CODES.session_writer_unavailable,
6609
+ message: "Session write ownership could not be verified."
6610
+ }
6611
+ };
6612
+ function sessionWriterRpcError(err) {
6613
+ if (!err || typeof err !== "object") return void 0;
6614
+ const candidate = err;
6615
+ const data = isObject(candidate["data"]) ? candidate["data"] : void 0;
6616
+ const errorKind = data?.["errorKind"] ?? candidate["errorKind"];
6617
+ if (typeof errorKind !== "string" || !(errorKind in SESSION_WRITER_RPC_ERRORS)) {
6618
+ return void 0;
6619
+ }
6620
+ const typedKind = errorKind;
6621
+ const expected = SESSION_WRITER_RPC_ERRORS[typedKind];
6622
+ const code = candidate["code"] ?? candidate["rpcCode"];
6623
+ if (code !== expected.code) return void 0;
6624
+ return {
6625
+ code: expected.code,
6626
+ message: expected.message,
6627
+ data: { errorKind: typedKind }
6628
+ };
6629
+ }
6630
+ __name(sessionWriterRpcError, "sessionWriterRpcError");
6566
6631
  var debugLogger2 = createDebugLogger("ACP_HTTP_DISPATCH");
6567
6632
  var SESSION_SHELL_METHOD = `${QWEN_METHOD_NS}session/shell`;
6568
6633
  var INVALID_PERMISSION_OUTCOME_ERROR = '`outcome` must be `{ outcome: "cancelled" }` or `{ outcome: "selected", optionId: string }`';
@@ -6695,10 +6760,11 @@ function parseOptionalWorkspaceCwd2(params, boundWorkspace) {
6695
6760
  `\`cwd\` exceeds the ${MAX_WORKSPACE_PATH_LENGTH}-character limit`
6696
6761
  );
6697
6762
  }
6698
- if (!path9.isAbsolute(cwd)) {
6763
+ const sandboxCwd = translateAndCheckAbsoluteWorkspacePath(cwd);
6764
+ if (sandboxCwd === null) {
6699
6765
  throw new AcpParamError("`cwd` must be an absolute path when provided");
6700
6766
  }
6701
- return cwd;
6767
+ return sandboxCwd;
6702
6768
  }
6703
6769
  __name(parseOptionalWorkspaceCwd2, "parseOptionalWorkspaceCwd");
6704
6770
  function validatePrompt(params) {
@@ -6775,6 +6841,8 @@ function pickSessionArtifactInput(params) {
6775
6841
  }
6776
6842
  __name(pickSessionArtifactInput, "pickSessionArtifactInput");
6777
6843
  function toRpcError(err) {
6844
+ const writerError = sessionWriterRpcError(err);
6845
+ if (writerError) return writerError;
6778
6846
  if (err instanceof AcpParamError || err instanceof InvalidCursorError) {
6779
6847
  return { code: RPC.INVALID_PARAMS, message: err.message };
6780
6848
  }
@@ -7511,22 +7579,21 @@ var AcpDispatcher = class {
7511
7579
  conn.ownedSessions.delete(sessionId);
7512
7580
  conn.closingSessions.add(sessionId);
7513
7581
  let closeStarted = false;
7514
- const closeSession = /* @__PURE__ */ __name(async () => {
7515
- closeStarted = true;
7582
+ const closeLocalSessionStream = /* @__PURE__ */ __name(() => {
7516
7583
  try {
7517
- await this.bridge.closeSession(
7518
- sessionId,
7519
- this.sessionCtx(conn, sessionId, loopback)
7584
+ conn.closeSessionStream(sessionId);
7585
+ } catch (teardownErr) {
7586
+ writeStderrLine(
7587
+ `qwen serve: /acp session/close local teardown failed (${logSafe(sessionId)}): ${logSafe(errMsg(teardownErr))}`
7520
7588
  );
7521
- } finally {
7522
- try {
7523
- conn.closeSessionStream(sessionId);
7524
- } catch (teardownErr) {
7525
- writeStderrLine(
7526
- `qwen serve: /acp session/close local teardown failed (${logSafe(sessionId)}): ${logSafe(errMsg(teardownErr))}`
7527
- );
7528
- }
7529
7589
  }
7590
+ }, "closeLocalSessionStream");
7591
+ const closeSession = /* @__PURE__ */ __name(async () => {
7592
+ closeStarted = true;
7593
+ await this.bridge.closeSession(
7594
+ sessionId,
7595
+ this.sessionCtx(conn, sessionId, loopback)
7596
+ );
7530
7597
  }, "closeSession");
7531
7598
  try {
7532
7599
  try {
@@ -7548,11 +7615,19 @@ var AcpDispatcher = class {
7548
7615
  } catch (err) {
7549
7616
  if (!closeStarted) {
7550
7617
  conn.ownedSessions.add(sessionId);
7618
+ } else {
7619
+ try {
7620
+ this.bridge.getSessionSummary(sessionId);
7621
+ conn.ownedSessions.add(sessionId);
7622
+ } catch {
7623
+ closeLocalSessionStream();
7624
+ }
7551
7625
  }
7552
7626
  throw err;
7553
7627
  } finally {
7554
7628
  conn.closingSessions.delete(sessionId);
7555
7629
  }
7630
+ closeLocalSessionStream();
7556
7631
  this.replyConn(conn, id, {});
7557
7632
  return;
7558
7633
  }
@@ -8977,7 +9052,7 @@ var AcpDispatcher = class {
8977
9052
  );
8978
9053
  return;
8979
9054
  }
8980
- const fs3 = this.fsFactory.forRequest({
9055
+ const fs6 = this.fsFactory.forRequest({
8981
9056
  originatorClientId: conn.clientId,
8982
9057
  route: `ACP ${method}`
8983
9058
  });
@@ -9029,8 +9104,8 @@ var AcpDispatcher = class {
9029
9104
  );
9030
9105
  return;
9031
9106
  }
9032
- const resolved = await fs3.resolve(p, "read");
9033
- const out = await fs3.readText(resolved, { maxBytes, line, limit });
9107
+ const resolved = await fs6.resolve(p, "read");
9108
+ const out = await fs6.readText(resolved, { maxBytes, line, limit });
9034
9109
  this.replyConn(conn, id, {
9035
9110
  path: p,
9036
9111
  content: out.content,
@@ -9052,7 +9127,7 @@ var AcpDispatcher = class {
9052
9127
  conn.sendConn(error(id, RPC.INVALID_PARAMS, "`path` required"));
9053
9128
  return;
9054
9129
  }
9055
- const fs3 = this.fsFactory.forRequest({
9130
+ const fs6 = this.fsFactory.forRequest({
9056
9131
  originatorClientId: conn.clientId,
9057
9132
  route: `ACP ${method}`
9058
9133
  });
@@ -9088,8 +9163,8 @@ var AcpDispatcher = class {
9088
9163
  );
9089
9164
  return;
9090
9165
  }
9091
- const resolved = await fs3.resolve(p, "read");
9092
- const buf = await fs3.readBytesWindow(resolved, { offset, maxBytes });
9166
+ const resolved = await fs6.resolve(p, "read");
9167
+ const buf = await fs6.readBytesWindow(resolved, { offset, maxBytes });
9093
9168
  this.replyConn(conn, id, { path: p, ...buf });
9094
9169
  return;
9095
9170
  }
@@ -9107,12 +9182,12 @@ var AcpDispatcher = class {
9107
9182
  conn.sendConn(error(id, RPC.INVALID_PARAMS, "`path` required"));
9108
9183
  return;
9109
9184
  }
9110
- const fs3 = this.fsFactory.forRequest({
9185
+ const fs6 = this.fsFactory.forRequest({
9111
9186
  originatorClientId: conn.clientId,
9112
9187
  route: `ACP ${method}`
9113
9188
  });
9114
- const resolved = await fs3.resolve(p, "read");
9115
- const result = await fs3.stat(resolved);
9189
+ const resolved = await fs6.resolve(p, "read");
9190
+ const result = await fs6.stat(resolved);
9116
9191
  this.replyConn(conn, id, { path: p, ...result });
9117
9192
  return;
9118
9193
  }
@@ -9130,13 +9205,13 @@ var AcpDispatcher = class {
9130
9205
  conn.sendConn(error(id, RPC.INVALID_PARAMS, "`path` required"));
9131
9206
  return;
9132
9207
  }
9133
- const fs3 = this.fsFactory.forRequest({
9208
+ const fs6 = this.fsFactory.forRequest({
9134
9209
  originatorClientId: conn.clientId,
9135
9210
  route: `ACP ${method}`
9136
9211
  });
9137
- const resolved = await fs3.resolve(p, "read");
9212
+ const resolved = await fs6.resolve(p, "read");
9138
9213
  const MAX_LIST = 2e3;
9139
- const entries = await fs3.list(resolved, { maxEntries: MAX_LIST + 1 });
9214
+ const entries = await fs6.list(resolved, { maxEntries: MAX_LIST + 1 });
9140
9215
  const truncated = entries.length > MAX_LIST;
9141
9216
  this.replyConn(conn, id, {
9142
9217
  path: p,
@@ -9161,7 +9236,7 @@ var AcpDispatcher = class {
9161
9236
  );
9162
9237
  return;
9163
9238
  }
9164
- const fs3 = this.fsFactory.forRequest({
9239
+ const fs6 = this.fsFactory.forRequest({
9165
9240
  originatorClientId: conn.clientId,
9166
9241
  route: `ACP ${method}`
9167
9242
  });
@@ -9181,7 +9256,7 @@ var AcpDispatcher = class {
9181
9256
  );
9182
9257
  return;
9183
9258
  }
9184
- const matches = await fs3.glob(pattern, {
9259
+ const matches = await fs6.glob(pattern, {
9185
9260
  maxResults: maxResults + 1
9186
9261
  });
9187
9262
  const truncated = matches.length > maxResults;
@@ -9213,11 +9288,11 @@ var AcpDispatcher = class {
9213
9288
  );
9214
9289
  return;
9215
9290
  }
9216
- const fs3 = this.fsFactory.forRequest({
9291
+ const fs6 = this.fsFactory.forRequest({
9217
9292
  originatorClientId: conn.clientId,
9218
9293
  route: `ACP ${method}`
9219
9294
  });
9220
- const resolved = await fs3.resolve(p, "write");
9295
+ const resolved = await fs6.resolve(p, "write");
9221
9296
  if (Buffer.byteLength(params["content"], "utf8") > 10 * 1024 * 1024) {
9222
9297
  if (id !== void 0)
9223
9298
  conn.sendConn(
@@ -9225,7 +9300,7 @@ var AcpDispatcher = class {
9225
9300
  );
9226
9301
  return;
9227
9302
  }
9228
- await fs3.writeTextOverwrite(resolved, params["content"]);
9303
+ await fs6.writeTextOverwrite(resolved, params["content"]);
9229
9304
  this.replyConn(conn, id, { ok: true, path: p });
9230
9305
  return;
9231
9306
  }
@@ -9254,12 +9329,12 @@ var AcpDispatcher = class {
9254
9329
  );
9255
9330
  return;
9256
9331
  }
9257
- const fs3 = this.fsFactory.forRequest({
9332
+ const fs6 = this.fsFactory.forRequest({
9258
9333
  originatorClientId: conn.clientId,
9259
9334
  route: `ACP ${method}`
9260
9335
  });
9261
- const resolved = await fs3.resolve(p, "write");
9262
- const result = await fs3.edit(
9336
+ const resolved = await fs6.resolve(p, "write");
9337
+ const result = await fs6.edit(
9263
9338
  resolved,
9264
9339
  params["oldText"],
9265
9340
  params["newText"]
@@ -10802,9 +10877,9 @@ var SseStream = class {
10802
10877
  return next;
10803
10878
  }
10804
10879
  doWrite(chunk) {
10805
- return new Promise((resolve5, reject) => {
10880
+ return new Promise((resolve6, reject) => {
10806
10881
  if (this.closed || this.res.writableEnded) {
10807
- resolve5();
10882
+ resolve6();
10808
10883
  return;
10809
10884
  }
10810
10885
  let ok;
@@ -10815,7 +10890,7 @@ var SseStream = class {
10815
10890
  return;
10816
10891
  }
10817
10892
  if (ok) {
10818
- resolve5();
10893
+ resolve6();
10819
10894
  return;
10820
10895
  }
10821
10896
  const cleanup = /* @__PURE__ */ __name(() => {
@@ -10825,11 +10900,11 @@ var SseStream = class {
10825
10900
  }, "cleanup");
10826
10901
  const onDrain = /* @__PURE__ */ __name(() => {
10827
10902
  cleanup();
10828
- resolve5();
10903
+ resolve6();
10829
10904
  }, "onDrain");
10830
10905
  const onCloseEv = /* @__PURE__ */ __name(() => {
10831
10906
  cleanup();
10832
- resolve5();
10907
+ resolve6();
10833
10908
  }, "onCloseEv");
10834
10909
  const onErrorEv = /* @__PURE__ */ __name((err) => {
10835
10910
  cleanup();
@@ -10891,14 +10966,14 @@ var WsStream = class {
10891
10966
  send(message, _id) {
10892
10967
  const data = JSON.stringify(message);
10893
10968
  const next = this.writeChain.then(
10894
- () => new Promise((resolve5, reject) => {
10969
+ () => new Promise((resolve6, reject) => {
10895
10970
  if (this._closed) {
10896
- resolve5();
10971
+ resolve6();
10897
10972
  return;
10898
10973
  }
10899
10974
  this.ws.send(data, (err) => {
10900
10975
  if (err) reject(err);
10901
- else resolve5();
10976
+ else resolve6();
10902
10977
  });
10903
10978
  })
10904
10979
  );
@@ -11203,7 +11278,7 @@ var CdpReverseLink = class {
11203
11278
  throw { code: -32e3, message: "CDP tunnel closed" };
11204
11279
  }
11205
11280
  await this.attach();
11206
- return new Promise((resolve5, reject) => {
11281
+ return new Promise((resolve6, reject) => {
11207
11282
  if (this.disposed) {
11208
11283
  reject({ code: -32e3, message: "CDP tunnel closed" });
11209
11284
  return;
@@ -11214,7 +11289,7 @@ var CdpReverseLink = class {
11214
11289
  `CDP command id=${id} method=${method} timed out after ${this.commandTimeoutMs}ms`
11215
11290
  );
11216
11291
  const progressTimer = this.armProgressLog(id, method);
11217
- this.pending.set(id, { resolve: resolve5, reject, timer, progressTimer });
11292
+ this.pending.set(id, { resolve: resolve6, reject, timer, progressTimer });
11218
11293
  try {
11219
11294
  this.log?.(
11220
11295
  `qwen serve: /cdp forwarded command id=${id} method=${method} to extension`
@@ -11241,7 +11316,7 @@ var CdpReverseLink = class {
11241
11316
  if (this.attached) return Promise.resolve({});
11242
11317
  if (this.attachPromise) return this.attachPromise;
11243
11318
  this.attachPromise = new Promise(
11244
- (resolve5, reject) => {
11319
+ (resolve6, reject) => {
11245
11320
  if (this.disposed) {
11246
11321
  reject({ code: -32e3, message: "CDP tunnel closed" });
11247
11322
  return;
@@ -11251,7 +11326,7 @@ var CdpReverseLink = class {
11251
11326
  this.pendingAttach = {
11252
11327
  id,
11253
11328
  pending: {
11254
- resolve: /* @__PURE__ */ __name((result) => resolve5(result ?? {}), "resolve"),
11329
+ resolve: /* @__PURE__ */ __name((result) => resolve6(result ?? {}), "resolve"),
11255
11330
  reject,
11256
11331
  timer
11257
11332
  }
@@ -11819,7 +11894,7 @@ function isAcpChannelUnavailable(err) {
11819
11894
  }
11820
11895
  __name(isAcpChannelUnavailable, "isAcpChannelUnavailable");
11821
11896
  function delay(ms) {
11822
- return new Promise((resolve5) => setTimeout(resolve5, ms));
11897
+ return new Promise((resolve6) => setTimeout(resolve6, ms));
11823
11898
  }
11824
11899
  __name(delay, "delay");
11825
11900
  function buildChromeDevToolsMcpRuntimeConfig(localPort, hostname, env) {
@@ -13700,7 +13775,7 @@ var CdpTunnelRegistry = class {
13700
13775
  // packages/cli/src/serve/web-shell-static.ts
13701
13776
  init_esbuild_shims();
13702
13777
  var import_express2 = __toESM(require_express(), 1);
13703
- import * as path10 from "node:path";
13778
+ import * as path9 from "node:path";
13704
13779
  var WEB_SHELL_CSP_DIRECTIVES = [
13705
13780
  "default-src 'self'",
13706
13781
  "script-src 'self' 'unsafe-inline' 'unsafe-eval' 'wasm-unsafe-eval'",
@@ -13728,7 +13803,7 @@ function isDocumentNavigation(req) {
13728
13803
  }
13729
13804
  __name(isDocumentNavigation, "isDocumentNavigation");
13730
13805
  function createSendIndex(webShellDir, frameAncestors = []) {
13731
- const indexPath = path10.join(webShellDir, "index.html");
13806
+ const indexPath = path9.join(webShellDir, "index.html");
13732
13807
  const csp = buildWebShellCsp(frameAncestors);
13733
13808
  return (res) => {
13734
13809
  res.status(200).set("Content-Security-Policy", csp).set("X-Content-Type-Options", "nosniff").set("Referrer-Policy", "no-referrer").set(
@@ -13764,7 +13839,7 @@ function mountWebShellAssets(app, webShellDir, frameAncestors = []) {
13764
13839
  const sendIndex = createSendIndex(webShellDir, frameAncestors);
13765
13840
  app.use(
13766
13841
  "/assets",
13767
- import_express2.default.static(path10.join(webShellDir, "assets"), {
13842
+ import_express2.default.static(path9.join(webShellDir, "assets"), {
13768
13843
  index: false,
13769
13844
  immutable: true,
13770
13845
  maxAge: "1y"
@@ -15109,7 +15184,7 @@ function createFifoTaskQueue(limit) {
15109
15184
  Promise.resolve().then(() => item.task(release)).then(item.resolve, item.reject).finally(release);
15110
15185
  }
15111
15186
  }, "pump");
15112
- const enqueue = /* @__PURE__ */ __name((task, options = {}) => new Promise((resolve5, reject) => {
15187
+ const enqueue = /* @__PURE__ */ __name((task, options = {}) => new Promise((resolve6, reject) => {
15113
15188
  if (options.signal?.aborted) {
15114
15189
  reject(abortReason(options.signal));
15115
15190
  return;
@@ -15118,7 +15193,7 @@ function createFifoTaskQueue(limit) {
15118
15193
  task,
15119
15194
  ...options.signal ? { signal: options.signal } : {},
15120
15195
  ...options.onStart ? { onStart: options.onStart } : {},
15121
- resolve: resolve5,
15196
+ resolve: resolve6,
15122
15197
  reject
15123
15198
  };
15124
15199
  if (options.signal) {
@@ -15160,6 +15235,14 @@ var redactExtensionDisplaySource = /* @__PURE__ */ __name((source) => {
15160
15235
  var EXTENSION_PREPARATION_CONCURRENCY = 2;
15161
15236
  var EXTENSION_REFRESH_TIMEOUT_MS = 3e4;
15162
15237
  var RECONCILE_SLOW_MS = 3e4;
15238
+ var resolveExtensionLocale = /* @__PURE__ */ __name((workspaceDir) => {
15239
+ const configuredLanguage = loadSettings(workspaceDir).merged.general?.language;
15240
+ const requestedLocale = resolveLanguageSetting(configuredLanguage);
15241
+ if (requestedLocale === "auto") {
15242
+ return detectSystemLanguage();
15243
+ }
15244
+ return resolveSupportedLanguage(requestedLocale) ?? requestedLocale;
15245
+ }, "resolveExtensionLocale");
15163
15246
  var EXTENSION_QUEUE_FULL_MESSAGE = "Extension operation queue is full";
15164
15247
  function createExtensionsController(deps) {
15165
15248
  const { boundWorkspace, bridge, workspace } = deps;
@@ -15187,6 +15270,7 @@ function createExtensionsController(deps) {
15187
15270
  }, "acquireOperationSlot");
15188
15271
  const createExtensionManager = /* @__PURE__ */ __name((workspaceDir = boundWorkspace, trustedOverride, interactions) => new ExtensionManager({
15189
15272
  workspaceDir,
15273
+ locale: resolveExtensionLocale(workspaceDir),
15190
15274
  isWorkspaceTrusted: trustedOverride ?? getWorkspaceTrustStatus(loadSettings(workspaceDir).merged, workspaceDir).effective.state === "trusted",
15191
15275
  requestConsent: /* @__PURE__ */ __name(() => Promise.resolve(), "requestConsent"),
15192
15276
  networkPolicy: "public",
@@ -15714,8 +15798,9 @@ function createExtensionsController(deps) {
15714
15798
  })();
15715
15799
  }, "runQueuedExtensionMutation");
15716
15800
  const buildLocalExtensionsStatus = /* @__PURE__ */ __name(async () => {
15801
+ const locale = resolveExtensionLocale(boundWorkspace);
15717
15802
  const now = Date.now();
15718
- if (extensionsStatusCache && extensionsStatusCache.expiresAt > now) {
15803
+ if (extensionsStatusCache?.locale === locale && extensionsStatusCache.expiresAt > now) {
15719
15804
  return extensionsStatusCache.value;
15720
15805
  }
15721
15806
  const extensionManager = createExtensionManager();
@@ -15771,6 +15856,7 @@ function createExtensionsController(deps) {
15771
15856
  extensions: entries
15772
15857
  };
15773
15858
  extensionsStatusCache = {
15859
+ locale,
15774
15860
  expiresAt: Date.now() + 2e3,
15775
15861
  value: status
15776
15862
  };
@@ -15939,7 +16025,7 @@ function registerWorkspaceExtensionRoutes(app, deps) {
15939
16025
  ...interaction,
15940
16026
  id: crypto2.randomUUID()
15941
16027
  };
15942
- return new Promise((resolve5, reject) => {
16028
+ return new Promise((resolve6, reject) => {
15943
16029
  const timeout = setTimeout(() => {
15944
16030
  pendingExtensionInteractions.delete(operationId);
15945
16031
  controller.updateOperation(operationId, {
@@ -15953,7 +16039,7 @@ function registerWorkspaceExtensionRoutes(app, deps) {
15953
16039
  timeout.unref?.();
15954
16040
  pendingExtensionInteractions.set(operationId, {
15955
16041
  interaction: pendingInteraction,
15956
- resolve: resolve5,
16042
+ resolve: resolve6,
15957
16043
  reject,
15958
16044
  timeout
15959
16045
  });
@@ -15998,8 +16084,8 @@ function registerWorkspaceExtensionRoutes(app, deps) {
15998
16084
  const reserveRuntimeReconciliation = /* @__PURE__ */ __name(() => {
15999
16085
  let provideTask;
16000
16086
  const task = new Promise(
16001
- (resolve5) => {
16002
- provideTask = resolve5;
16087
+ (resolve6) => {
16088
+ provideTask = resolve6;
16003
16089
  }
16004
16090
  );
16005
16091
  const queued = runtimeReconciliationQueue.run(async () => {
@@ -16100,9 +16186,9 @@ function registerWorkspaceExtensionRoutes(app, deps) {
16100
16186
  generationPoller.unref();
16101
16187
  app.locals.stopExtensionGenerationReconciler = () => clearInterval(generationPoller);
16102
16188
  }
16103
- const registerFor = /* @__PURE__ */ __name((base, resolve5) => {
16189
+ const registerFor = /* @__PURE__ */ __name((base, resolve6) => {
16104
16190
  app.get(base, async (req, res) => {
16105
- const ctrl = resolve5(req, res, false);
16191
+ const ctrl = resolve6(req, res, false);
16106
16192
  if (!ctrl) return;
16107
16193
  try {
16108
16194
  res.status(200).json(await ctrl.buildLocalExtensionsStatus());
@@ -16111,12 +16197,12 @@ function registerWorkspaceExtensionRoutes(app, deps) {
16111
16197
  }
16112
16198
  });
16113
16199
  app.get(`${base}/operations`, async (req, res) => {
16114
- const ctrl = resolve5(req, res, false);
16200
+ const ctrl = resolve6(req, res, false);
16115
16201
  if (!ctrl) return;
16116
16202
  res.status(200).json({ v: 1, operations: ctrl.getActiveOperations() });
16117
16203
  });
16118
16204
  app.get(`${base}/operations/:operationId`, async (req, res) => {
16119
- const ctrl = resolve5(req, res, false);
16205
+ const ctrl = resolve6(req, res, false);
16120
16206
  if (!ctrl) return;
16121
16207
  try {
16122
16208
  const operationId = req.params["operationId"];
@@ -16160,7 +16246,7 @@ function registerWorkspaceExtensionRoutes(app, deps) {
16160
16246
  `${base}/operations/:operationId/interactions/:interactionId`,
16161
16247
  mutate({ strict: true }),
16162
16248
  async (req, res) => {
16163
- const ctrl = resolve5(req, res, false);
16249
+ const ctrl = resolve6(req, res, false);
16164
16250
  if (!ctrl) return;
16165
16251
  try {
16166
16252
  if (!ctrl.validateExtensionMutationClient(req, res, {
@@ -16229,7 +16315,7 @@ function registerWorkspaceExtensionRoutes(app, deps) {
16229
16315
  }
16230
16316
  );
16231
16317
  app.post(`${base}/install`, mutate({ strict: true }), async (req, res) => {
16232
- const ctrl = resolve5(req, res, true);
16318
+ const ctrl = resolve6(req, res, true);
16233
16319
  if (!ctrl) return;
16234
16320
  try {
16235
16321
  if (!ctrl.validateExtensionMutationClient(req, res, {
@@ -16412,7 +16498,7 @@ function registerWorkspaceExtensionRoutes(app, deps) {
16412
16498
  `${base}/check-updates`,
16413
16499
  mutate({ strict: true }),
16414
16500
  async (req, res) => {
16415
- const ctrl = resolve5(req, res, true);
16501
+ const ctrl = resolve6(req, res, true);
16416
16502
  if (!ctrl) return;
16417
16503
  let timer;
16418
16504
  let releaseOperationSlot;
@@ -16476,7 +16562,7 @@ function registerWorkspaceExtensionRoutes(app, deps) {
16476
16562
  }
16477
16563
  );
16478
16564
  app.post(`${base}/refresh`, mutate({ strict: true }), async (req, res) => {
16479
- const ctrl = resolve5(req, res, true);
16565
+ const ctrl = resolve6(req, res, true);
16480
16566
  if (!ctrl) return;
16481
16567
  try {
16482
16568
  if (!ctrl.validateExtensionMutationClient(req, res, {
@@ -16500,7 +16586,7 @@ function registerWorkspaceExtensionRoutes(app, deps) {
16500
16586
  `${base}/:name/enable`,
16501
16587
  mutate({ strict: true }),
16502
16588
  async (req, res) => {
16503
- const ctrl = resolve5(req, res, true);
16589
+ const ctrl = resolve6(req, res, true);
16504
16590
  if (!ctrl) return;
16505
16591
  try {
16506
16592
  if (!ctrl.validateExtensionMutationClient(req, res, {
@@ -16547,7 +16633,7 @@ function registerWorkspaceExtensionRoutes(app, deps) {
16547
16633
  `${base}/:name/disable`,
16548
16634
  mutate({ strict: true }),
16549
16635
  async (req, res) => {
16550
- const ctrl = resolve5(req, res, true);
16636
+ const ctrl = resolve6(req, res, true);
16551
16637
  if (!ctrl) return;
16552
16638
  try {
16553
16639
  if (!ctrl.validateExtensionMutationClient(req, res, {
@@ -16594,7 +16680,7 @@ function registerWorkspaceExtensionRoutes(app, deps) {
16594
16680
  `${base}/:name/update`,
16595
16681
  mutate({ strict: true }),
16596
16682
  async (req, res) => {
16597
- const ctrl = resolve5(req, res, true);
16683
+ const ctrl = resolve6(req, res, true);
16598
16684
  if (!ctrl) return;
16599
16685
  try {
16600
16686
  if (!ctrl.validateExtensionMutationClient(req, res, {
@@ -16677,7 +16763,7 @@ function registerWorkspaceExtensionRoutes(app, deps) {
16677
16763
  }
16678
16764
  );
16679
16765
  app.delete(`${base}/:name`, mutate({ strict: true }), async (req, res) => {
16680
- const ctrl = resolve5(req, res, true);
16766
+ const ctrl = resolve6(req, res, true);
16681
16767
  if (!ctrl) return;
16682
16768
  try {
16683
16769
  if (!ctrl.validateExtensionMutationClient(req, res, {
@@ -17439,13 +17525,13 @@ async function handlePostFileWrite(req, res, deps) {
17439
17525
  req
17440
17526
  );
17441
17527
  if (originatorClientId === null) return;
17442
- const fs3 = factory.forRequest({
17528
+ const fs6 = factory.forRequest({
17443
17529
  originatorClientId,
17444
17530
  route: ROUTE2
17445
17531
  });
17446
17532
  try {
17447
- const resolved = await fs3.resolve(queryPath, "write");
17448
- const out = await fs3.writeTextAtomic(resolved, content, {
17533
+ const resolved = await fs6.resolve(queryPath, "write");
17534
+ const out = await fs6.writeTextAtomic(resolved, content, {
17449
17535
  mode,
17450
17536
  ...expectedHash ? { expectedHash } : {},
17451
17537
  ...bom !== void 0 ? { bom } : {},
@@ -17498,13 +17584,13 @@ async function handlePostFileEdit(req, res, deps) {
17498
17584
  req
17499
17585
  );
17500
17586
  if (originatorClientId === null) return;
17501
- const fs3 = factory.forRequest({
17587
+ const fs6 = factory.forRequest({
17502
17588
  originatorClientId,
17503
17589
  route: ROUTE2
17504
17590
  });
17505
17591
  try {
17506
- const resolved = await fs3.resolve(queryPath, "edit");
17507
- const out = await fs3.editAtomic(resolved, oldText, newText, {
17592
+ const resolved = await fs6.resolve(queryPath, "edit");
17593
+ const out = await fs6.editAtomic(resolved, oldText, newText, {
17508
17594
  expectedHash
17509
17595
  });
17510
17596
  applyReadHeaders(res);
@@ -17538,7 +17624,7 @@ function registerWorkspaceFileWriteRoutes(app, deps) {
17538
17624
  }
17539
17625
  __name(registerWorkspaceFileWriteRoutes, "registerWorkspaceFileWriteRoutes");
17540
17626
  function registerWorkspaceQualifiedFileWriteRoutes(app, deps) {
17541
- const resolve5 = /* @__PURE__ */ __name((req, res) => {
17627
+ const resolve6 = /* @__PURE__ */ __name((req, res) => {
17542
17628
  const runtime = resolveWorkspaceRuntimeFromParam(
17543
17629
  deps.workspaceRegistry,
17544
17630
  req,
@@ -17556,7 +17642,7 @@ function registerWorkspaceQualifiedFileWriteRoutes(app, deps) {
17556
17642
  "/workspaces/:workspace/file/write",
17557
17643
  deps.mutate({ strict: true }),
17558
17644
  (req, res) => {
17559
- if (!resolve5(req, res)) return;
17645
+ if (!resolve6(req, res)) return;
17560
17646
  void handlePostFileWrite(req, res, deps);
17561
17647
  }
17562
17648
  );
@@ -17564,7 +17650,7 @@ function registerWorkspaceQualifiedFileWriteRoutes(app, deps) {
17564
17650
  "/workspaces/:workspace/file/edit",
17565
17651
  deps.mutate({ strict: true }),
17566
17652
  (req, res) => {
17567
- if (!resolve5(req, res)) return;
17653
+ if (!resolve6(req, res)) return;
17568
17654
  void handlePostFileEdit(req, res, deps);
17569
17655
  }
17570
17656
  );
@@ -17832,6 +17918,18 @@ var legacySessionTelemetryRoutes = [
17832
17918
  attribution: "handler_resolved",
17833
17919
  route: "GET /session/:id/tasks"
17834
17920
  },
17921
+ {
17922
+ method: "GET",
17923
+ path: "/session/:id/subagents/:toolCallId",
17924
+ attribution: "handler_resolved",
17925
+ route: "GET /session/:id/subagents/:toolCallId"
17926
+ },
17927
+ {
17928
+ method: "POST",
17929
+ path: "/session/:id/subagents/:toolCallId/cancel",
17930
+ attribution: "handler_resolved",
17931
+ route: "POST /session/:id/subagents/:toolCallId/cancel"
17932
+ },
17835
17933
  {
17836
17934
  method: "GET",
17837
17935
  path: "/session/:id/lsp",
@@ -18309,7 +18407,7 @@ function daemonTelemetryMiddleware(resolveWorkspaceCwd, recordRequest) {
18309
18407
  deferredRuntimePath: deferredRuntime.path
18310
18408
  } : {}
18311
18409
  },
18312
- async (span) => await new Promise((resolve5, reject) => {
18410
+ async (span) => await new Promise((resolve6, reject) => {
18313
18411
  let done = false;
18314
18412
  const finish = /* @__PURE__ */ __name(() => {
18315
18413
  if (done) return;
@@ -18339,7 +18437,7 @@ function daemonTelemetryMiddleware(resolveWorkspaceCwd, recordRequest) {
18339
18437
  if (!successfulSse && route.route !== "GET /daemon/status" && route.route !== "POST /session/:id/heartbeat") {
18340
18438
  recordRequest?.(durationMs, res.statusCode);
18341
18439
  }
18342
- resolve5();
18440
+ resolve6();
18343
18441
  }, "finish");
18344
18442
  res.once("finish", finish);
18345
18443
  res.once("close", finish);
@@ -18514,21 +18612,11 @@ __name(registerPermissionRoutes, "registerPermissionRoutes");
18514
18612
  // packages/cli/src/serve/routes/session.ts
18515
18613
  init_esbuild_shims();
18516
18614
  import * as crypto3 from "node:crypto";
18517
- import * as path11 from "node:path";
18615
+ import * as fs4 from "node:fs";
18616
+ import * as path10 from "node:path";
18518
18617
 
18519
18618
  // packages/cli/src/serve/server/prompt-deadline.ts
18520
18619
  init_esbuild_shims();
18521
- var PromptDeadlineExceededError = class extends Error {
18522
- static {
18523
- __name(this, "PromptDeadlineExceededError");
18524
- }
18525
- deadlineMs;
18526
- constructor(deadlineMs) {
18527
- super(`prompt exceeded the ${deadlineMs}ms deadline`);
18528
- this.name = "PromptDeadlineExceededError";
18529
- this.deadlineMs = deadlineMs;
18530
- }
18531
- };
18532
18620
  function resolvePromptDeadlineMs(serverMs, requestMs) {
18533
18621
  if (serverMs === void 0 || !Number.isFinite(serverMs) || serverMs <= 0) {
18534
18622
  return void 0;
@@ -18638,6 +18726,25 @@ function encodeMetadataSessionCursor(last, filter, archiveState) {
18638
18726
  ).toString("base64url");
18639
18727
  }
18640
18728
  __name(encodeMetadataSessionCursor, "encodeMetadataSessionCursor");
18729
+ async function enrichWorktreeSidecars(bySessionId, sessionService, archiveState = "active") {
18730
+ for (const [sessionId, summary] of bySessionId) {
18731
+ if (summary.worktree) continue;
18732
+ const sidecar = await readWorktreeSession(
18733
+ sessionService.getWorktreeSessionPathForArchiveState(
18734
+ sessionId,
18735
+ archiveState
18736
+ )
18737
+ ).catch(() => null);
18738
+ if (sidecar) {
18739
+ summary.worktree = {
18740
+ slug: sidecar.slug,
18741
+ path: sidecar.worktreePath,
18742
+ branch: sidecar.worktreeBranch
18743
+ };
18744
+ }
18745
+ }
18746
+ }
18747
+ __name(enrichWorktreeSidecars, "enrichWorktreeSidecars");
18641
18748
  function toSummary2(item) {
18642
18749
  return {
18643
18750
  sessionId: item.sessionId,
@@ -18783,6 +18890,7 @@ async function listOrganizedWorkspaceSessionsForResponse(bridge, workspaceCwd, o
18783
18890
  applyOrganization(session, snapshot.sessions.get(session.sessionId))
18784
18891
  );
18785
18892
  }
18893
+ await enrichWorktreeSidecars(bySessionId, sessionService, archiveState);
18786
18894
  if (readOptions.mergeLive !== false && archiveState !== "archived" && isFirstPage) {
18787
18895
  try {
18788
18896
  const liveSessions = bridge.listWorkspaceSessions(workspaceCwd);
@@ -18868,6 +18976,7 @@ async function listWorkspaceSessionsByMetadataForResponse(bridge, workspaceCwd,
18868
18976
  for (const session of persisted.sessions) {
18869
18977
  bySessionId.set(session.sessionId, session);
18870
18978
  }
18979
+ await enrichWorktreeSidecars(bySessionId, sessionService, archiveState);
18871
18980
  let liveMergeFailed = false;
18872
18981
  if (readOptions.mergeLive !== false && archiveState !== "archived") {
18873
18982
  try {
@@ -18970,6 +19079,7 @@ async function listWorkspaceSessionsForResponse(bridge, workspaceCwd, options, r
18970
19079
  for (const item of persisted.items) {
18971
19080
  bySessionId.set(item.sessionId, toSummary2(item));
18972
19081
  }
19082
+ await enrichWorktreeSidecars(bySessionId, sessionService, archiveState);
18973
19083
  if (archiveState === "archived" || readOptions.mergeLive === false) {
18974
19084
  const sessions2 = [...bySessionId.values()];
18975
19085
  const nextCursor2 = persisted.nextCursor != null ? String(persisted.nextCursor) : void 0;
@@ -19108,123 +19218,831 @@ async function exportSessionTranscript(params) {
19108
19218
  }
19109
19219
  __name(exportSessionTranscript, "exportSessionTranscript");
19110
19220
 
19111
- // packages/cli/src/serve/routes/session.ts
19112
- var WORKSPACE_TRANSCRIPT_RESPONSE_MAX_BYTES = 32 * 1024 * 1024;
19113
- var WORKSPACE_TRANSCRIPT_CURSOR_MAX_BYTES = 64 * 1024;
19114
- var TRANSCRIPT_CURSOR_TOO_LARGE_REPLAY_ERROR = "Transcript pagination state exceeds the safe limit";
19115
- var GENERATION_HEARTBEAT_MS = 15e3;
19116
- var PRIMARY_ONLY_LIVE_SESSION_ROUTES = [
19117
- "POST /session/:id/branch",
19118
- "POST /session/:id/fork",
19119
- "POST /session/:id/cd"
19120
- ];
19121
- function isPrimaryOnlyLiveSessionRoute(route) {
19122
- return PRIMARY_ONLY_LIVE_SESSION_ROUTES.includes(
19123
- route
19124
- );
19221
+ // packages/cli/src/serve/virtual-subagent-sessions.ts
19222
+ init_esbuild_shims();
19223
+ import * as fs3 from "node:fs/promises";
19224
+ import { createReadStream } from "node:fs";
19225
+ import readline from "node:readline";
19226
+ var PREFIX = "subagent.";
19227
+ var POLL_INTERVAL_MS = 250;
19228
+ var TARGET_RETENTION_MS = 6e4;
19229
+ async function readFirstUserText(filePath) {
19230
+ const stream = createReadStream(filePath);
19231
+ const lines = readline.createInterface({
19232
+ input: stream,
19233
+ crlfDelay: Infinity
19234
+ });
19235
+ try {
19236
+ for await (const line of lines) {
19237
+ const trimmed = line.trim();
19238
+ if (!trimmed) continue;
19239
+ for (const record of parseLineTolerant(trimmed, filePath)) {
19240
+ if (record.type !== "user") continue;
19241
+ return record.message?.parts?.find(
19242
+ (part) => typeof part.text === "string"
19243
+ )?.text;
19244
+ }
19245
+ }
19246
+ return void 0;
19247
+ } catch (error2) {
19248
+ if (error2.code === "ENOENT") return void 0;
19249
+ throw error2;
19250
+ } finally {
19251
+ lines.close();
19252
+ stream.destroy();
19253
+ }
19254
+ }
19255
+ __name(readFirstUserText, "readFirstUserText");
19256
+ function asRecord(value) {
19257
+ return typeof value === "object" && value !== null ? value : void 0;
19258
+ }
19259
+ __name(asRecord, "asRecord");
19260
+ function finiteNonNegative(value) {
19261
+ return typeof value === "number" && Number.isFinite(value) && value >= 0 ? value : void 0;
19262
+ }
19263
+ __name(finiteNonNegative, "finiteNonNegative");
19264
+ function normalizeTaskStatus(status) {
19265
+ if (typeof status !== "string") return void 0;
19266
+ if (status === "success") return "completed";
19267
+ if (status === "error") return "failed";
19268
+ if (status === "background") return "running";
19269
+ return status;
19270
+ }
19271
+ __name(normalizeTaskStatus, "normalizeTaskStatus");
19272
+ function durationBetween(start, end) {
19273
+ if (!end) return void 0;
19274
+ const startTime = Date.parse(start);
19275
+ const endTime = Date.parse(end);
19276
+ return Number.isFinite(startTime) && Number.isFinite(endTime) ? Math.max(0, endTime - startTime) : void 0;
19277
+ }
19278
+ __name(durationBetween, "durationBetween");
19279
+ function findToolCallMetrics(records, toolCallId) {
19280
+ const toolResult = records.find(
19281
+ (record) => record.toolCallResult?.callId === toolCallId
19282
+ )?.toolCallResult;
19283
+ const display = asRecord(toolResult?.resultDisplay);
19284
+ const summary = asRecord(display?.["executionSummary"]);
19285
+ return {
19286
+ status: normalizeTaskStatus(display?.["status"]) ?? normalizeTaskStatus(toolResult?.status),
19287
+ durationMs: finiteNonNegative(summary?.["totalDurationMs"]),
19288
+ totalTokens: finiteNonNegative(summary?.["totalTokens"]) ?? finiteNonNegative(display?.["tokenCount"]),
19289
+ inputTokens: finiteNonNegative(summary?.["inputTokens"]),
19290
+ outputTokens: finiteNonNegative(summary?.["outputTokens"]),
19291
+ cachedTokens: finiteNonNegative(summary?.["cachedTokens"])
19292
+ };
19125
19293
  }
19126
- __name(isPrimaryOnlyLiveSessionRoute, "isPrimaryOnlyLiveSessionRoute");
19127
- function formatGenerationSse(event, data) {
19128
- return `event: ${event}
19129
- data: ${JSON.stringify({ v: 1, ...data })}
19130
-
19131
- `;
19294
+ __name(findToolCallMetrics, "findToolCallMetrics");
19295
+ function encodePart(value) {
19296
+ return Buffer.from(value, "utf8").toString("base64url");
19132
19297
  }
19133
- __name(formatGenerationSse, "formatGenerationSse");
19134
- function writeGenerationSseChunk(res, chunk) {
19135
- if (res.destroyed) {
19136
- return Promise.reject(new Error("Generation SSE connection destroyed"));
19137
- }
19138
- const writable = res.write(chunk);
19139
- const flush = res.flush;
19140
- flush?.call(res);
19141
- if (writable) {
19142
- return res.destroyed ? Promise.reject(new Error("Generation SSE connection destroyed")) : Promise.resolve();
19298
+ __name(encodePart, "encodePart");
19299
+ function decodePart(value) {
19300
+ try {
19301
+ return Buffer.from(value, "base64url").toString("utf8");
19302
+ } catch {
19303
+ return void 0;
19143
19304
  }
19144
- return new Promise((resolve5, reject) => {
19145
- const cleanup = /* @__PURE__ */ __name(() => {
19146
- res.off("drain", onDrain);
19147
- res.off("close", onClose);
19148
- res.off("error", onError);
19149
- }, "cleanup");
19150
- const onDrain = /* @__PURE__ */ __name(() => {
19151
- cleanup();
19152
- resolve5();
19153
- }, "onDrain");
19154
- const onClose = /* @__PURE__ */ __name(() => {
19155
- cleanup();
19156
- reject(new Error("Generation SSE connection closed"));
19157
- }, "onClose");
19158
- const onError = /* @__PURE__ */ __name((error2) => {
19159
- cleanup();
19160
- reject(error2);
19161
- }, "onError");
19162
- res.once("drain", onDrain);
19163
- res.once("close", onClose);
19164
- res.once("error", onError);
19165
- if (res.destroyed) onClose();
19166
- });
19167
19305
  }
19168
- __name(writeGenerationSseChunk, "writeGenerationSseChunk");
19169
- function isReadOnlyWorkspaceInspection(runtime) {
19170
- return !runtime.primary && !runtime.trusted;
19171
- }
19172
- __name(isReadOnlyWorkspaceInspection, "isReadOnlyWorkspaceInspection");
19173
- function runWorkspaceInspectionWithLogPolicy(runtime, read) {
19174
- return isReadOnlyWorkspaceInspection(runtime) ? runWithoutDebugLogSession(read) : read();
19306
+ __name(decodePart, "decodePart");
19307
+ function isValidVirtualSessionPart(value) {
19308
+ return /^[a-zA-Z0-9_-]{1,500}$/.test(value);
19175
19309
  }
19176
- __name(runWorkspaceInspectionWithLogPolicy, "runWorkspaceInspectionWithLogPolicy");
19177
- function requireSessionArtifactClientId(clientId, res) {
19178
- if (clientId !== void 0) return true;
19179
- res.status(403).json({
19180
- error: "Session artifact access requires a session-bound client id",
19181
- code: "client_id_required",
19182
- errorKind: "client_id_required"
19183
- });
19184
- return false;
19310
+ __name(isValidVirtualSessionPart, "isValidVirtualSessionPart");
19311
+ function createVirtualSubagentSessionId(parentSessionId, agentId) {
19312
+ if (!isValidVirtualSessionPart(parentSessionId) || !isValidVirtualSessionPart(agentId)) {
19313
+ throw new Error("Virtual subagent session ids require valid id parts");
19314
+ }
19315
+ return `${PREFIX}${encodePart(parentSessionId)}.${encodePart(agentId)}`;
19185
19316
  }
19186
- __name(requireSessionArtifactClientId, "requireSessionArtifactClientId");
19187
- function sendArtifactValidationError(res, err) {
19188
- if (!(err instanceof SessionArtifactValidationError)) {
19189
- return false;
19317
+ __name(createVirtualSubagentSessionId, "createVirtualSubagentSessionId");
19318
+ function parseVirtualSubagentSessionId(sessionId) {
19319
+ if (!sessionId.startsWith(PREFIX) || sessionId.length > 2e3) {
19320
+ return void 0;
19190
19321
  }
19191
- res.status(400).json({
19322
+ const parts = sessionId.slice(PREFIX.length).split(".");
19323
+ if (parts.length !== 2) return void 0;
19324
+ const parentSessionId = decodePart(parts[0]);
19325
+ const agentId = decodePart(parts[1]);
19326
+ if (!parentSessionId || !agentId || !isValidVirtualSessionPart(parentSessionId) || !isValidVirtualSessionPart(agentId)) {
19327
+ return void 0;
19328
+ }
19329
+ return { parentSessionId, agentId };
19330
+ }
19331
+ __name(parseVirtualSubagentSessionId, "parseVirtualSubagentSessionId");
19332
+ function replayCursorState(sessionId, position, leafUuid, startTime, lastUpdated) {
19333
+ return {
19192
19334
  v: 1,
19193
- error: {
19194
- code: err.code,
19195
- message: err.message,
19196
- ...err.field ? { field: err.field } : {}
19197
- }
19198
- });
19199
- return true;
19335
+ sessionId,
19336
+ fileIdentity: { dev: 0, ino: 0 },
19337
+ snapshotSize: position,
19338
+ position,
19339
+ leafUuid,
19340
+ startTime,
19341
+ lastUpdated
19342
+ };
19200
19343
  }
19201
- __name(sendArtifactValidationError, "sendArtifactValidationError");
19202
- function sendSessionOrganizationError(res, err) {
19203
- if (!(err instanceof SessionOrganizationError)) {
19204
- return false;
19344
+ __name(replayCursorState, "replayCursorState");
19345
+ var VirtualSubagentTarget = class _VirtualSubagentTarget {
19346
+ constructor(sessionId, parentSessionId, task, workspaceCwd, onExpired) {
19347
+ this.sessionId = sessionId;
19348
+ this.parentSessionId = parentSessionId;
19349
+ this.task = task;
19350
+ this.workspaceCwd = workspaceCwd;
19351
+ this.onExpired = onExpired;
19205
19352
  }
19206
- const status = err.code === "group_name_conflict" ? 409 : err.code === "group_not_found" ? 404 : err.code === "session_organization_store_unreadable" ? 500 : 400;
19207
- res.status(status).json({
19208
- error: err.message,
19209
- code: err.code,
19210
- ...err.field !== void 0 ? { field: err.field } : {}
19211
- });
19212
- return true;
19213
- }
19214
- __name(sendSessionOrganizationError, "sendSessionOrganizationError");
19215
- function parseTranscriptLimitQuery(rawLimit, res) {
19216
- if (rawLimit === void 0) return void 0;
19217
- if (typeof rawLimit !== "string" || rawLimit.trim() === "") {
19218
- res.status(400).json({
19219
- error: "`limit` must be a positive integer",
19220
- code: "invalid_transcript_limit"
19221
- });
19222
- return null;
19353
+ static {
19354
+ __name(this, "VirtualSubagentTarget");
19355
+ }
19356
+ bus = new EventBus(1024, 8);
19357
+ events = [];
19358
+ snapshotDelivered = false;
19359
+ offset = 0;
19360
+ transcriptIdentity;
19361
+ streamOffset = 0;
19362
+ streamIdentity;
19363
+ streamReady = false;
19364
+ canonicalThroughTimestamp = 0;
19365
+ completedStreamRounds = /* @__PURE__ */ new Set();
19366
+ streamedRounds = /* @__PURE__ */ new Set();
19367
+ streamRunIds = /* @__PURE__ */ new Set();
19368
+ legacyStreamedSinceCanonical = false;
19369
+ replayState;
19370
+ initialized = false;
19371
+ refreshPromise = Promise.resolve();
19372
+ snapshotPromise = Promise.resolve();
19373
+ pollTimer;
19374
+ subscribers = 0;
19375
+ retentionTimer;
19376
+ updateStatus(status) {
19377
+ const wasRunning = this.task.status === "running";
19378
+ this.task.status = status;
19379
+ if (status !== "running" && this.pollTimer) {
19380
+ clearInterval(this.pollTimer);
19381
+ this.pollTimer = void 0;
19382
+ }
19383
+ if (wasRunning && status !== "running") {
19384
+ void this.refreshLive().catch(() => void 0);
19385
+ }
19386
+ }
19387
+ rememberEvent(event) {
19388
+ if (event && !this.snapshotDelivered) this.events.push(event);
19389
+ }
19390
+ resetCanonicalState() {
19391
+ this.offset = 0;
19392
+ this.replayState = void 0;
19393
+ this.canonicalThroughTimestamp = 0;
19394
+ this.completedStreamRounds.clear();
19395
+ this.streamRunIds.clear();
19396
+ this.streamedRounds.clear();
19397
+ this.legacyStreamedSinceCanonical = false;
19398
+ }
19399
+ resetStreamState() {
19400
+ this.streamOffset = 0;
19401
+ this.completedStreamRounds.clear();
19402
+ this.streamRunIds.clear();
19403
+ this.streamedRounds.clear();
19404
+ this.legacyStreamedSinceCanonical = false;
19405
+ }
19406
+ async readNewRecords(endOffset) {
19407
+ let handle;
19408
+ try {
19409
+ handle = await fs3.open(this.task.outputFile, "r");
19410
+ const stat3 = await handle.stat();
19411
+ const identity = `${stat3.dev}:${stat3.ino}`;
19412
+ if (this.transcriptIdentity !== void 0 && this.transcriptIdentity !== identity || stat3.size < this.offset) {
19413
+ this.resetCanonicalState();
19414
+ }
19415
+ this.transcriptIdentity = identity;
19416
+ const size = Math.min(stat3.size, endOffset ?? stat3.size);
19417
+ if (size <= this.offset) return [];
19418
+ const bytes = Buffer.alloc(size - this.offset);
19419
+ const { bytesRead } = await handle.read(
19420
+ bytes,
19421
+ 0,
19422
+ bytes.length,
19423
+ this.offset
19424
+ );
19425
+ const chunk = bytes.subarray(0, bytesRead);
19426
+ const lastNewline = chunk.lastIndexOf(10);
19427
+ if (lastNewline < 0) return [];
19428
+ const complete = chunk.subarray(0, lastNewline + 1);
19429
+ this.offset += complete.length;
19430
+ return complete.toString("utf8").split("\n").flatMap((line) => {
19431
+ const trimmed = line.trim();
19432
+ return trimmed ? parseLineTolerant(trimmed, this.task.outputFile) : [];
19433
+ });
19434
+ } catch (error2) {
19435
+ if (error2.code === "ENOENT") {
19436
+ if (this.transcriptIdentity !== void 0) {
19437
+ this.transcriptIdentity = void 0;
19438
+ this.resetCanonicalState();
19439
+ }
19440
+ return [];
19441
+ }
19442
+ throw error2;
19443
+ } finally {
19444
+ await handle?.close();
19445
+ }
19223
19446
  }
19224
- if (!/^\d+$/.test(rawLimit)) {
19225
- res.status(400).json({
19226
- error: "`limit` must be a positive integer",
19227
- code: "invalid_transcript_limit"
19447
+ async readStreamUpdates(endOffset) {
19448
+ const replayingExisting = !this.streamReady;
19449
+ this.streamReady = true;
19450
+ const filePath = `${this.task.outputFile}.stream`;
19451
+ let handle;
19452
+ try {
19453
+ handle = await fs3.open(filePath, "r");
19454
+ const stat3 = await handle.stat();
19455
+ const identity = `${stat3.dev}:${stat3.ino}`;
19456
+ if (this.streamIdentity !== void 0 && this.streamIdentity !== identity) {
19457
+ this.resetStreamState();
19458
+ }
19459
+ this.streamIdentity = identity;
19460
+ if (stat3.size < this.streamOffset) this.resetStreamState();
19461
+ const size = Math.min(stat3.size, endOffset ?? stat3.size);
19462
+ if (size <= this.streamOffset) return;
19463
+ const bytes = Buffer.alloc(size - this.streamOffset);
19464
+ const { bytesRead } = await handle.read(
19465
+ bytes,
19466
+ 0,
19467
+ bytes.length,
19468
+ this.streamOffset
19469
+ );
19470
+ const chunk = bytes.subarray(0, bytesRead);
19471
+ const lastNewline = chunk.lastIndexOf(10);
19472
+ if (lastNewline < 0) return;
19473
+ const complete = chunk.subarray(0, lastNewline + 1);
19474
+ this.streamOffset += complete.length;
19475
+ const records = complete.toString("utf8").split("\n").flatMap((line) => {
19476
+ const trimmed = line.trim();
19477
+ return trimmed ? parseLineTolerant(trimmed, filePath) : [];
19478
+ });
19479
+ for (const record of records) {
19480
+ if (record.v !== 1 || typeof record.text !== "string" || typeof record.timestamp !== "number") {
19481
+ continue;
19482
+ }
19483
+ const roundKey = typeof record.runId === "string" && typeof record.round === "number" ? `${record.runId}:${record.round}` : void 0;
19484
+ if (typeof record.runId === "string") {
19485
+ this.streamRunIds.add(record.runId);
19486
+ }
19487
+ if ((roundKey ? this.completedStreamRounds.has(roundKey) : record.timestamp <= this.canonicalThroughTimestamp) || replayingExisting && typeof record.round !== "number") {
19488
+ continue;
19489
+ }
19490
+ const event = this.bus.publish({
19491
+ type: "session_update",
19492
+ data: createTranscriptMessageUpdate({
19493
+ role: "assistant",
19494
+ text: record.text,
19495
+ timestamp: record.timestamp,
19496
+ ...record.thought ? { thought: true } : {}
19497
+ })
19498
+ });
19499
+ this.rememberEvent(event);
19500
+ if (roundKey) this.streamedRounds.add(roundKey);
19501
+ else this.legacyStreamedSinceCanonical = true;
19502
+ }
19503
+ for (const completed of this.completedStreamRounds) {
19504
+ const runId = completed.slice(0, completed.lastIndexOf(":"));
19505
+ if (!this.streamRunIds.has(runId)) {
19506
+ this.completedStreamRounds.delete(completed);
19507
+ }
19508
+ }
19509
+ } catch (error2) {
19510
+ if (error2.code !== "ENOENT") throw error2;
19511
+ this.streamIdentity = void 0;
19512
+ this.streamOffset = 0;
19513
+ this.streamRunIds.clear();
19514
+ this.streamedRounds.clear();
19515
+ this.legacyStreamedSinceCanonical = false;
19516
+ } finally {
19517
+ await handle?.close();
19518
+ }
19519
+ }
19520
+ refreshOnce = /* @__PURE__ */ __name(async (endOffset) => {
19521
+ let records = await this.readNewRecords(endOffset);
19522
+ if (records.length === 0) {
19523
+ this.initialized = true;
19524
+ return;
19525
+ }
19526
+ for (const record of records) {
19527
+ if (record.type === "assistant" && (record.usageMetadata !== void 0 || record.message?.parts?.some((part) => typeof part.text === "string"))) {
19528
+ if (typeof record.agentRunId === "string" && typeof record.agentRound === "number") {
19529
+ this.completedStreamRounds.add(
19530
+ `${record.agentRunId}:${record.agentRound}`
19531
+ );
19532
+ }
19533
+ const timestamp = Date.parse(record.timestamp);
19534
+ if (Number.isFinite(timestamp)) {
19535
+ this.canonicalThroughTimestamp = Math.max(
19536
+ this.canonicalThroughTimestamp,
19537
+ timestamp
19538
+ );
19539
+ }
19540
+ }
19541
+ }
19542
+ if (this.streamedRounds.size > 0 || this.legacyStreamedSinceCanonical) {
19543
+ records = records.filter((record) => {
19544
+ const roundKey = typeof record.agentRunId === "string" && typeof record.agentRound === "number" ? `${record.agentRunId}:${record.agentRound}` : void 0;
19545
+ if (roundKey && this.streamedRounds.delete(roundKey)) return false;
19546
+ if (!this.legacyStreamedSinceCanonical || record.type !== "assistant" || record.message?.parts?.some((part) => part.functionCall)) {
19547
+ return true;
19548
+ }
19549
+ this.legacyStreamedSinceCanonical = false;
19550
+ return false;
19551
+ });
19552
+ if (records.length === 0) {
19553
+ this.initialized = true;
19554
+ return;
19555
+ }
19556
+ }
19557
+ const startTime = records[0]?.timestamp ?? (/* @__PURE__ */ new Date()).toISOString();
19558
+ const lastUpdated = records[records.length - 1]?.timestamp ?? (/* @__PURE__ */ new Date()).toISOString();
19559
+ const page = {
19560
+ sessionId: this.sessionId,
19561
+ filePath: this.task.outputFile,
19562
+ records,
19563
+ gaps: [],
19564
+ hasMore: true,
19565
+ replay: this.replayState,
19566
+ startTime,
19567
+ lastUpdated,
19568
+ nextCursorState: replayCursorState(
19569
+ this.sessionId,
19570
+ this.offset,
19571
+ records[records.length - 1]?.uuid ?? "",
19572
+ startTime,
19573
+ lastUpdated
19574
+ )
19575
+ };
19576
+ let nextReplayState;
19577
+ const replay = await replayTranscriptRecordPage({
19578
+ sessionId: this.sessionId,
19579
+ page,
19580
+ encodeCursor: /* @__PURE__ */ __name((state) => {
19581
+ nextReplayState = state.replay;
19582
+ return "virtual-subagent-replay";
19583
+ }, "encodeCursor")
19584
+ });
19585
+ this.replayState = nextReplayState;
19586
+ const inputs = replay.updates.map((update) => ({
19587
+ type: "session_update",
19588
+ data: update
19589
+ }));
19590
+ const published = this.initialized ? inputs.flatMap((input) => {
19591
+ const event = this.bus.publish(input);
19592
+ return event ? [event] : [];
19593
+ }) : this.bus.seedReplayEvents(inputs);
19594
+ if (!this.snapshotDelivered) this.events.push(...published);
19595
+ this.initialized = true;
19596
+ }, "refreshOnce");
19597
+ refreshAt(bounds) {
19598
+ return this.refreshOnce(bounds?.transcript).then(async () => {
19599
+ if (this.task.status === "running") {
19600
+ await this.readStreamUpdates(bounds?.stream);
19601
+ }
19602
+ });
19603
+ }
19604
+ enqueueRefresh(work) {
19605
+ const result = this.refreshPromise.catch(() => void 0).then(work);
19606
+ this.refreshPromise = result.then(
19607
+ () => void 0,
19608
+ () => void 0
19609
+ );
19610
+ return result;
19611
+ }
19612
+ refreshLive() {
19613
+ return this.enqueueRefresh(() => this.refreshAt());
19614
+ }
19615
+ async captureReadBounds() {
19616
+ const size = /* @__PURE__ */ __name(async (filePath) => {
19617
+ try {
19618
+ return (await fs3.stat(filePath)).size;
19619
+ } catch (error2) {
19620
+ if (error2.code === "ENOENT") return 0;
19621
+ throw error2;
19622
+ }
19623
+ }, "size");
19624
+ const [transcript, stream] = await Promise.all([
19625
+ size(this.task.outputFile),
19626
+ size(`${this.task.outputFile}.stream`)
19627
+ ]);
19628
+ return { transcript, stream };
19629
+ }
19630
+ async createSnapshotOnce() {
19631
+ if (!this.snapshotDelivered) {
19632
+ await this.refreshLive();
19633
+ const snapshot = [...this.events];
19634
+ this.events.length = 0;
19635
+ this.snapshotDelivered = true;
19636
+ return { events: snapshot, lastEventId: this.bus.lastEventId };
19637
+ }
19638
+ return this.enqueueRefresh(async () => {
19639
+ const bounds = await this.captureReadBounds();
19640
+ const target = new _VirtualSubagentTarget(
19641
+ this.sessionId,
19642
+ this.parentSessionId,
19643
+ this.task,
19644
+ this.workspaceCwd,
19645
+ () => void 0
19646
+ );
19647
+ await target.refreshAt(bounds);
19648
+ await this.refreshAt(bounds);
19649
+ return {
19650
+ events: [...target.events],
19651
+ lastEventId: this.bus.lastEventId
19652
+ };
19653
+ });
19654
+ }
19655
+ createSnapshot() {
19656
+ const snapshot = this.snapshotPromise.then(() => this.createSnapshotOnce());
19657
+ this.snapshotPromise = snapshot.then(
19658
+ () => void 0,
19659
+ () => void 0
19660
+ );
19661
+ return snapshot;
19662
+ }
19663
+ async load(clientId) {
19664
+ const snapshot = await this.createSnapshot();
19665
+ if (this.subscribers === 0) this.scheduleRetention();
19666
+ return {
19667
+ sessionId: this.sessionId,
19668
+ workspaceCwd: this.workspaceCwd,
19669
+ attached: true,
19670
+ ...clientId ? { clientId } : {},
19671
+ createdAt: new Date(this.task.startTime).toISOString(),
19672
+ hasActivePrompt: this.task.status === "running",
19673
+ state: {},
19674
+ compactedReplay: snapshot.events,
19675
+ liveJournal: [],
19676
+ historyHasMore: false,
19677
+ lastEventId: snapshot.lastEventId
19678
+ };
19679
+ }
19680
+ async *iterate(opts) {
19681
+ if (this.retentionTimer) {
19682
+ clearTimeout(this.retentionTimer);
19683
+ this.retentionTimer = void 0;
19684
+ }
19685
+ this.subscribers++;
19686
+ try {
19687
+ await this.refreshLive();
19688
+ if (!this.snapshotDelivered) {
19689
+ this.events.length = 0;
19690
+ this.snapshotDelivered = true;
19691
+ }
19692
+ if (this.task.status === "running" && !this.pollTimer) {
19693
+ this.pollTimer = setInterval(() => {
19694
+ void this.refreshLive().catch(() => void 0);
19695
+ }, POLL_INTERVAL_MS);
19696
+ this.pollTimer.unref();
19697
+ }
19698
+ yield* this.bus.subscribe(opts);
19699
+ } finally {
19700
+ this.subscribers--;
19701
+ if (this.subscribers === 0) {
19702
+ if (this.pollTimer) clearInterval(this.pollTimer);
19703
+ this.pollTimer = void 0;
19704
+ this.scheduleRetention();
19705
+ }
19706
+ }
19707
+ }
19708
+ subscribe(opts) {
19709
+ return {
19710
+ [Symbol.asyncIterator]: () => this.iterate(opts)
19711
+ };
19712
+ }
19713
+ scheduleRetention() {
19714
+ if (this.retentionTimer) clearTimeout(this.retentionTimer);
19715
+ this.retentionTimer = setTimeout(this.onExpired, TARGET_RETENTION_MS);
19716
+ this.retentionTimer.unref();
19717
+ }
19718
+ };
19719
+ var VirtualSubagentSessions = class {
19720
+ static {
19721
+ __name(this, "VirtualSubagentSessions");
19722
+ }
19723
+ targets = /* @__PURE__ */ new Map();
19724
+ async findTask(runtime, parentSessionId, predicate) {
19725
+ const status = await runtime.bridge.getSessionTasksStatus(parentSessionId);
19726
+ const task = status.tasks.find(
19727
+ (candidate) => candidate.kind === "agent" && typeof candidate.outputFile === "string" && predicate(candidate)
19728
+ );
19729
+ if (task?.kind === "agent" && task.outputFile) {
19730
+ return {
19731
+ id: task.id,
19732
+ title: task.label,
19733
+ outputFile: task.outputFile,
19734
+ status: task.status,
19735
+ startTime: task.startTime,
19736
+ durationMs: task.stats?.durationMs ?? (task.endTime === void 0 ? void 0 : Math.max(0, task.endTime - task.startTime)),
19737
+ totalTokens: task.stats?.totalTokens
19738
+ };
19739
+ }
19740
+ const runtimeDir = runtime.env.effectiveEnv?.["QWEN_RUNTIME_DIR"];
19741
+ const projectDir = Storage.runWithRuntimeBaseDir(
19742
+ runtimeDir,
19743
+ runtime.workspaceCwd,
19744
+ () => new Storage(runtime.workspaceCwd).getProjectDir()
19745
+ );
19746
+ const sessionDir = getSubagentSessionDir(projectDir, parentSessionId);
19747
+ let names;
19748
+ try {
19749
+ names = await fs3.readdir(sessionDir);
19750
+ } catch (error2) {
19751
+ if (error2.code === "ENOENT") return void 0;
19752
+ throw error2;
19753
+ }
19754
+ for (const name of names) {
19755
+ if (!name.endsWith(".meta.json")) continue;
19756
+ const metaPath = `${sessionDir}/${name}`;
19757
+ const meta = readAgentMeta(metaPath);
19758
+ if (!meta || !predicate({
19759
+ kind: "agent",
19760
+ id: meta.agentId,
19761
+ toolUseId: meta.toolUseId,
19762
+ outputFile: metaPath.slice(0, -".meta.json".length) + ".jsonl"
19763
+ })) {
19764
+ continue;
19765
+ }
19766
+ return {
19767
+ id: meta.agentId,
19768
+ title: meta.description || meta.agentType,
19769
+ outputFile: metaPath.slice(0, -".meta.json".length) + ".jsonl",
19770
+ status: meta.status ?? "completed",
19771
+ startTime: Number.isFinite(Date.parse(meta.createdAt)) ? Date.parse(meta.createdAt) : Date.now(),
19772
+ durationMs: durationBetween(meta.createdAt, meta.lastUpdatedAt)
19773
+ };
19774
+ }
19775
+ return void 0;
19776
+ }
19777
+ async findLegacyTaskByToolCall(runtime, parentSessionId, toolCallId) {
19778
+ const runtimeDir = runtime.env.effectiveEnv?.["QWEN_RUNTIME_DIR"];
19779
+ const projectDir = Storage.runWithRuntimeBaseDir(
19780
+ runtimeDir,
19781
+ runtime.workspaceCwd,
19782
+ () => new Storage(runtime.workspaceCwd).getProjectDir()
19783
+ );
19784
+ const parentRecords = await read(
19785
+ `${projectDir}/chats/${parentSessionId}.jsonl`
19786
+ );
19787
+ let root;
19788
+ for (const record of parentRecords) {
19789
+ for (const part of record.message?.parts ?? []) {
19790
+ const call = part.functionCall;
19791
+ if (call?.id !== toolCallId || call.name !== "agent") continue;
19792
+ const args = call.args;
19793
+ root = {
19794
+ timestamp: Date.parse(record.timestamp),
19795
+ ...typeof args?.["description"] === "string" ? { description: args["description"] } : {},
19796
+ ...typeof args?.["prompt"] === "string" ? { prompt: args["prompt"] } : {},
19797
+ ...typeof args?.["subagent_type"] === "string" ? { agentType: args["subagent_type"] } : {}
19798
+ };
19799
+ break;
19800
+ }
19801
+ if (root) break;
19802
+ }
19803
+ if (!root) return void 0;
19804
+ const sessionDir = getSubagentSessionDir(projectDir, parentSessionId);
19805
+ let names;
19806
+ try {
19807
+ names = await fs3.readdir(sessionDir);
19808
+ } catch (error2) {
19809
+ if (error2.code === "ENOENT") return void 0;
19810
+ throw error2;
19811
+ }
19812
+ const candidates = [];
19813
+ for (const name of names) {
19814
+ if (!name.endsWith(".meta.json")) continue;
19815
+ const metaPath = `${sessionDir}/${name}`;
19816
+ const meta = readAgentMeta(metaPath);
19817
+ if (!meta) continue;
19818
+ const outputFile = metaPath.slice(0, -".meta.json".length) + ".jsonl";
19819
+ const launchPrompt = await readFirstUserText(outputFile);
19820
+ let score = 0;
19821
+ if (root.prompt && launchPrompt === root.prompt) score += 8;
19822
+ if (root.description && meta.description === root.description) score += 4;
19823
+ if (root.agentType && meta.agentType === root.agentType) score += 2;
19824
+ const startTime = Date.parse(meta.createdAt);
19825
+ const delta = Math.abs(startTime - root.timestamp);
19826
+ if (Number.isFinite(delta) && delta <= 6e4) score += 1;
19827
+ if (score === 0) continue;
19828
+ candidates.push({
19829
+ id: meta.agentId,
19830
+ title: meta.description || meta.agentType,
19831
+ outputFile,
19832
+ status: meta.status ?? "completed",
19833
+ startTime: Number.isFinite(startTime) ? startTime : Date.now(),
19834
+ durationMs: durationBetween(meta.createdAt, meta.lastUpdatedAt),
19835
+ score,
19836
+ delta
19837
+ });
19838
+ }
19839
+ candidates.sort((a, b) => b.score - a.score || a.delta - b.delta);
19840
+ const selected = candidates[0];
19841
+ if (!selected) return void 0;
19842
+ const metrics = findToolCallMetrics(parentRecords, toolCallId);
19843
+ return {
19844
+ ...selected,
19845
+ status: metrics.status ?? selected.status,
19846
+ durationMs: metrics.durationMs ?? selected.durationMs,
19847
+ totalTokens: metrics.totalTokens ?? selected.totalTokens,
19848
+ inputTokens: metrics.inputTokens ?? selected.inputTokens,
19849
+ outputTokens: metrics.outputTokens ?? selected.outputTokens,
19850
+ cachedTokens: metrics.cachedTokens ?? selected.cachedTokens
19851
+ };
19852
+ }
19853
+ async readParentToolCallMetrics(runtime, parentSessionId, toolCallId) {
19854
+ const runtimeDir = runtime.env.effectiveEnv?.["QWEN_RUNTIME_DIR"];
19855
+ const projectDir = Storage.runWithRuntimeBaseDir(
19856
+ runtimeDir,
19857
+ runtime.workspaceCwd,
19858
+ () => new Storage(runtime.workspaceCwd).getProjectDir()
19859
+ );
19860
+ const records = await read(
19861
+ `${projectDir}/chats/${parentSessionId}.jsonl`
19862
+ );
19863
+ return findToolCallMetrics(records, toolCallId);
19864
+ }
19865
+ async resolve(runtime, parentSessionId, toolCallId) {
19866
+ let task = await this.findTask(
19867
+ runtime,
19868
+ parentSessionId,
19869
+ (candidate) => candidate.toolUseId === toolCallId || candidate.id.endsWith(`-${toolCallId}`)
19870
+ );
19871
+ const metrics = task && task.status !== "running" ? await this.readParentToolCallMetrics(
19872
+ runtime,
19873
+ parentSessionId,
19874
+ toolCallId
19875
+ ) : void 0;
19876
+ task ??= await this.findLegacyTaskByToolCall(
19877
+ runtime,
19878
+ parentSessionId,
19879
+ toolCallId
19880
+ );
19881
+ if (!task) return void 0;
19882
+ const sessionId = createVirtualSubagentSessionId(parentSessionId, task.id);
19883
+ const status = task.status;
19884
+ this.targets.get(`${runtime.workspaceId}:${sessionId}`)?.updateStatus(status);
19885
+ return {
19886
+ sessionId,
19887
+ taskId: task.id,
19888
+ title: task.title,
19889
+ status,
19890
+ durationMs: metrics?.durationMs ?? task.durationMs,
19891
+ totalTokens: metrics?.totalTokens ?? task.totalTokens,
19892
+ inputTokens: metrics?.inputTokens ?? task.inputTokens,
19893
+ outputTokens: metrics?.outputTokens ?? task.outputTokens,
19894
+ cachedTokens: metrics?.cachedTokens ?? task.cachedTokens
19895
+ };
19896
+ }
19897
+ async getTarget(runtime, sessionId) {
19898
+ const targetKey = `${runtime.workspaceId}:${sessionId}`;
19899
+ const cached = this.targets.get(targetKey);
19900
+ if (cached) return cached;
19901
+ const key = parseVirtualSubagentSessionId(sessionId);
19902
+ if (!key) return void 0;
19903
+ const task = await this.findTask(
19904
+ runtime,
19905
+ key.parentSessionId,
19906
+ (candidate) => candidate.id === key.agentId
19907
+ );
19908
+ if (!task) return void 0;
19909
+ const existing = this.targets.get(targetKey);
19910
+ if (existing) return existing;
19911
+ const target = new VirtualSubagentTarget(
19912
+ sessionId,
19913
+ key.parentSessionId,
19914
+ task,
19915
+ runtime.workspaceCwd,
19916
+ () => this.targets.delete(targetKey)
19917
+ );
19918
+ this.targets.set(targetKey, target);
19919
+ return target;
19920
+ }
19921
+ async load(runtime, sessionId, clientId) {
19922
+ return (await this.getTarget(runtime, sessionId))?.load(clientId);
19923
+ }
19924
+ async subscribe(runtime, sessionId, opts) {
19925
+ return (await this.getTarget(runtime, sessionId))?.subscribe(opts);
19926
+ }
19927
+ };
19928
+
19929
+ // packages/cli/src/serve/routes/session.ts
19930
+ var WORKSPACE_TRANSCRIPT_RESPONSE_MAX_BYTES = 32 * 1024 * 1024;
19931
+ var WORKSPACE_TRANSCRIPT_CURSOR_MAX_BYTES = 64 * 1024;
19932
+ var TRANSCRIPT_CURSOR_TOO_LARGE_REPLAY_ERROR = "Transcript pagination state exceeds the safe limit";
19933
+ var GENERATION_HEARTBEAT_MS = 15e3;
19934
+ var PRIMARY_ONLY_LIVE_SESSION_ROUTES = [
19935
+ "POST /session/:id/branch",
19936
+ "POST /session/:id/fork",
19937
+ "POST /session/:id/cd"
19938
+ ];
19939
+ function isPrimaryOnlyLiveSessionRoute(route) {
19940
+ return PRIMARY_ONLY_LIVE_SESSION_ROUTES.includes(
19941
+ route
19942
+ );
19943
+ }
19944
+ __name(isPrimaryOnlyLiveSessionRoute, "isPrimaryOnlyLiveSessionRoute");
19945
+ function formatGenerationSse(event, data) {
19946
+ return `event: ${event}
19947
+ data: ${JSON.stringify({ v: 1, ...data })}
19948
+
19949
+ `;
19950
+ }
19951
+ __name(formatGenerationSse, "formatGenerationSse");
19952
+ function writeGenerationSseChunk(res, chunk) {
19953
+ if (res.destroyed) {
19954
+ return Promise.reject(new Error("Generation SSE connection destroyed"));
19955
+ }
19956
+ const writable = res.write(chunk);
19957
+ const flush = res.flush;
19958
+ flush?.call(res);
19959
+ if (writable) {
19960
+ return res.destroyed ? Promise.reject(new Error("Generation SSE connection destroyed")) : Promise.resolve();
19961
+ }
19962
+ return new Promise((resolve6, reject) => {
19963
+ const cleanup = /* @__PURE__ */ __name(() => {
19964
+ res.off("drain", onDrain);
19965
+ res.off("close", onClose);
19966
+ res.off("error", onError);
19967
+ }, "cleanup");
19968
+ const onDrain = /* @__PURE__ */ __name(() => {
19969
+ cleanup();
19970
+ resolve6();
19971
+ }, "onDrain");
19972
+ const onClose = /* @__PURE__ */ __name(() => {
19973
+ cleanup();
19974
+ reject(new Error("Generation SSE connection closed"));
19975
+ }, "onClose");
19976
+ const onError = /* @__PURE__ */ __name((error2) => {
19977
+ cleanup();
19978
+ reject(error2);
19979
+ }, "onError");
19980
+ res.once("drain", onDrain);
19981
+ res.once("close", onClose);
19982
+ res.once("error", onError);
19983
+ if (res.destroyed) onClose();
19984
+ });
19985
+ }
19986
+ __name(writeGenerationSseChunk, "writeGenerationSseChunk");
19987
+ function isReadOnlyWorkspaceInspection(runtime) {
19988
+ return !runtime.primary && !runtime.trusted;
19989
+ }
19990
+ __name(isReadOnlyWorkspaceInspection, "isReadOnlyWorkspaceInspection");
19991
+ function runWorkspaceInspectionWithLogPolicy(runtime, read2) {
19992
+ return isReadOnlyWorkspaceInspection(runtime) ? runWithoutDebugLogSession(read2) : read2();
19993
+ }
19994
+ __name(runWorkspaceInspectionWithLogPolicy, "runWorkspaceInspectionWithLogPolicy");
19995
+ function requireSessionArtifactClientId(clientId, res) {
19996
+ if (clientId !== void 0) return true;
19997
+ res.status(403).json({
19998
+ error: "Session artifact access requires a session-bound client id",
19999
+ code: "client_id_required",
20000
+ errorKind: "client_id_required"
20001
+ });
20002
+ return false;
20003
+ }
20004
+ __name(requireSessionArtifactClientId, "requireSessionArtifactClientId");
20005
+ function sendArtifactValidationError(res, err) {
20006
+ if (!(err instanceof SessionArtifactValidationError)) {
20007
+ return false;
20008
+ }
20009
+ res.status(400).json({
20010
+ v: 1,
20011
+ error: {
20012
+ code: err.code,
20013
+ message: err.message,
20014
+ ...err.field ? { field: err.field } : {}
20015
+ }
20016
+ });
20017
+ return true;
20018
+ }
20019
+ __name(sendArtifactValidationError, "sendArtifactValidationError");
20020
+ function sendSessionOrganizationError(res, err) {
20021
+ if (!(err instanceof SessionOrganizationError)) {
20022
+ return false;
20023
+ }
20024
+ const status = err.code === "group_name_conflict" ? 409 : err.code === "group_not_found" ? 404 : err.code === "session_organization_store_unreadable" ? 500 : 400;
20025
+ res.status(status).json({
20026
+ error: err.message,
20027
+ code: err.code,
20028
+ ...err.field !== void 0 ? { field: err.field } : {}
20029
+ });
20030
+ return true;
20031
+ }
20032
+ __name(sendSessionOrganizationError, "sendSessionOrganizationError");
20033
+ function parseTranscriptLimitQuery(rawLimit, res) {
20034
+ if (rawLimit === void 0) return void 0;
20035
+ if (typeof rawLimit !== "string" || rawLimit.trim() === "") {
20036
+ res.status(400).json({
20037
+ error: "`limit` must be a positive integer",
20038
+ code: "invalid_transcript_limit"
20039
+ });
20040
+ return null;
20041
+ }
20042
+ if (!/^\d+$/.test(rawLimit)) {
20043
+ res.status(400).json({
20044
+ error: "`limit` must be a positive integer",
20045
+ code: "invalid_transcript_limit"
19228
20046
  });
19229
20047
  return null;
19230
20048
  }
@@ -19334,7 +20152,8 @@ function registerSessionRoutes(app, deps) {
19334
20152
  sendBridgeError: sendBridgeError2,
19335
20153
  daemonLog,
19336
20154
  promptDeadlineMs,
19337
- sessionShellCommandEnabled
20155
+ sessionShellCommandEnabled,
20156
+ virtualSubagentSessions
19338
20157
  } = deps;
19339
20158
  const LANGUAGE_CODES = deps.languageCodes;
19340
20159
  const transcriptCursorMasterKey = crypto3.randomBytes(32);
@@ -19433,7 +20252,7 @@ function registerSessionRoutes(app, deps) {
19433
20252
  const workspaceParam = req.params[paramName] ?? "";
19434
20253
  const byId = workspaceRegistry.getByWorkspaceId(workspaceParam);
19435
20254
  if (byId) return byId;
19436
- if (!path11.isAbsolute(workspaceParam)) {
20255
+ if (!path10.isAbsolute(workspaceParam)) {
19437
20256
  res.status(400).json({
19438
20257
  error: `\`:${paramName}\` must decode to a workspace id or absolute path`
19439
20258
  });
@@ -19847,7 +20666,7 @@ function registerSessionRoutes(app, deps) {
19847
20666
  })), "serializeSessionErrors");
19848
20667
  const resolveWorkspaceParam = /* @__PURE__ */ __name((req, res) => {
19849
20668
  const workspaceCwd = req.params["id"] ?? "";
19850
- if (!path11.isAbsolute(workspaceCwd)) {
20669
+ if (!path10.isAbsolute(workspaceCwd)) {
19851
20670
  res.status(400).json({ error: "`:id` must decode to an absolute workspace path" });
19852
20671
  return null;
19853
20672
  }
@@ -19919,6 +20738,68 @@ function registerSessionRoutes(app, deps) {
19919
20738
  }
19920
20739
  const clientId = parseClientIdHeader(req, res);
19921
20740
  if (clientId === null) return;
20741
+ let worktreeMeta;
20742
+ const rawWorktree = body["worktree"];
20743
+ if (rawWorktree !== void 0 && rawWorktree !== null) {
20744
+ if (typeof rawWorktree !== "object" || Array.isArray(rawWorktree)) {
20745
+ res.status(400).json({
20746
+ error: '`worktree` must be an object (e.g. `{}` or `{"slug":"my-task"}`)',
20747
+ code: "invalid_worktree"
20748
+ });
20749
+ return;
20750
+ }
20751
+ const wtReq = rawWorktree;
20752
+ let wtService;
20753
+ try {
20754
+ wtService = new GitWorktreeService(workspaceCwd);
20755
+ } catch {
20756
+ res.status(500).json({
20757
+ error: "Failed to initialize worktree service",
20758
+ code: "worktree_init_failed"
20759
+ });
20760
+ return;
20761
+ }
20762
+ if (!await wtService.isGitRepository()) {
20763
+ res.status(400).json({
20764
+ error: "Worktree isolation requires a git repository",
20765
+ code: "worktree_not_git_repo"
20766
+ });
20767
+ return;
20768
+ }
20769
+ const rawSlug = wtReq["slug"];
20770
+ let slug;
20771
+ if (rawSlug === void 0 || rawSlug === null) {
20772
+ slug = GitWorktreeService.generateAutoSlug();
20773
+ } else if (typeof rawSlug !== "string" || rawSlug.length === 0) {
20774
+ res.status(400).json({
20775
+ error: "`worktree.slug` must be a non-empty string when provided",
20776
+ code: "worktree_invalid_slug"
20777
+ });
20778
+ return;
20779
+ } else {
20780
+ slug = rawSlug;
20781
+ }
20782
+ const slugError = GitWorktreeService.validateUserWorktreeSlug(slug);
20783
+ if (slugError) {
20784
+ res.status(400).json({ error: slugError, code: "worktree_invalid_slug" });
20785
+ return;
20786
+ }
20787
+ const baseBranch = await wtService.getCurrentBranch().catch(() => void 0);
20788
+ const wtResult = await wtService.createUserWorktree(slug, baseBranch);
20789
+ if (!wtResult.success || !wtResult.worktree) {
20790
+ res.status(500).json({
20791
+ error: wtResult.error ?? "Failed to create worktree",
20792
+ code: "worktree_create_failed"
20793
+ });
20794
+ return;
20795
+ }
20796
+ worktreeMeta = {
20797
+ slug,
20798
+ path: wtResult.worktree.path,
20799
+ branch: wtResult.worktree.branch
20800
+ };
20801
+ sessionScope = "thread";
20802
+ }
19922
20803
  try {
19923
20804
  const session = await runtime.bridge.spawnOrAttach({
19924
20805
  workspaceCwd,
@@ -19927,7 +20808,8 @@ function registerSessionRoutes(app, deps) {
19927
20808
  ...sessionScope !== void 0 ? { sessionScope } : {},
19928
20809
  ...approvalMode !== void 0 ? { approvalMode } : {},
19929
20810
  ...source.sourceType !== void 0 ? { sourceType: source.sourceType } : {},
19930
- ...source.sourceId !== void 0 ? { sourceId: source.sourceId } : {}
20811
+ ...source.sourceId !== void 0 ? { sourceId: source.sourceId } : {},
20812
+ ...worktreeMeta ? { worktree: worktreeMeta } : {}
19931
20813
  });
19932
20814
  if (daemonLog) {
19933
20815
  daemonLog.info(
@@ -19954,6 +20836,10 @@ function registerSessionRoutes(app, deps) {
19954
20836
  await new SessionService(runtime.workspaceCwd).removeSession(
19955
20837
  session.sessionId
19956
20838
  );
20839
+ if (worktreeMeta) {
20840
+ await new GitWorktreeService(workspaceCwd).removeUserWorktree(worktreeMeta.slug, { deleteBranch: true }).catch(() => {
20841
+ });
20842
+ }
19957
20843
  }
19958
20844
  } catch {
19959
20845
  }
@@ -19963,14 +20849,128 @@ function registerSessionRoutes(app, deps) {
19963
20849
  }
19964
20850
  return;
19965
20851
  }
20852
+ if (worktreeMeta) {
20853
+ try {
20854
+ const createAllowedRoots = [
20855
+ path10.join(workspaceCwd, ".qwen", "worktrees")
20856
+ ];
20857
+ let createRepoTop = null;
20858
+ try {
20859
+ createRepoTop = await new GitWorktreeService(
20860
+ workspaceCwd
20861
+ ).getRepoTopLevel();
20862
+ } catch {
20863
+ }
20864
+ if (createRepoTop && createRepoTop !== workspaceCwd) {
20865
+ createAllowedRoots.push(
20866
+ path10.join(createRepoTop, ".qwen", "worktrees")
20867
+ );
20868
+ }
20869
+ await runtime.bridge.changeSessionCwd(session.sessionId, {
20870
+ path: worktreeMeta.path,
20871
+ allowedRoots: createAllowedRoots
20872
+ });
20873
+ await writeWorktreeSessionMarker(
20874
+ worktreeMeta.path,
20875
+ session.sessionId
20876
+ ).catch(() => {
20877
+ });
20878
+ await writeWorktreeSession(
20879
+ new SessionService(workspaceCwd).getWorktreeSessionPath(
20880
+ session.sessionId
20881
+ ),
20882
+ {
20883
+ slug: worktreeMeta.slug,
20884
+ worktreePath: worktreeMeta.path,
20885
+ worktreeBranch: worktreeMeta.branch,
20886
+ originalCwd: workspaceCwd,
20887
+ originalBranch: "",
20888
+ originalHeadCommit: ""
20889
+ }
20890
+ ).catch(() => {
20891
+ });
20892
+ } catch (cdErr) {
20893
+ if (daemonLog) {
20894
+ daemonLog.warn("worktree cd failed, rolling back", {
20895
+ sessionId: session.sessionId,
20896
+ error: cdErr instanceof Error ? cdErr.message : String(cdErr)
20897
+ });
20898
+ }
20899
+ const killed = await runtime.bridge.killSession(session.sessionId, { requireZeroAttaches: true }).catch(() => false);
20900
+ if (killed) {
20901
+ await new SessionService(workspaceCwd).removeSession(session.sessionId).catch(() => {
20902
+ });
20903
+ }
20904
+ await new GitWorktreeService(workspaceCwd).removeUserWorktree(worktreeMeta.slug, { deleteBranch: true }).catch(() => {
20905
+ });
20906
+ res.status(500).json({
20907
+ error: "Failed to relocate session into worktree",
20908
+ code: "worktree_relocate_failed"
20909
+ });
20910
+ return;
20911
+ }
20912
+ }
19966
20913
  res.status(200).json(session);
19967
20914
  } catch (err) {
20915
+ if (worktreeMeta) {
20916
+ await new GitWorktreeService(workspaceCwd).removeUserWorktree(worktreeMeta.slug, { deleteBranch: true }).catch(() => {
20917
+ });
20918
+ }
19968
20919
  sendBridgeError2(res, err, { route: "POST /session" });
19969
20920
  }
19970
20921
  });
19971
20922
  const restoreSessionHandler = /* @__PURE__ */ __name((action) => async (req, res) => {
19972
20923
  const sessionId = requireSessionId(req, res);
19973
20924
  if (!sessionId) return;
20925
+ const virtualKey = parseVirtualSubagentSessionId(sessionId);
20926
+ if (virtualKey) {
20927
+ const route2 = `POST /session/:id/${action}`;
20928
+ if (action !== "load") {
20929
+ res.status(400).json({
20930
+ error: `Virtual subagent sessions do not support ${action}`,
20931
+ code: "unsupported_action",
20932
+ sessionId
20933
+ });
20934
+ return;
20935
+ }
20936
+ if (!virtualSubagentSessions) {
20937
+ res.status(404).json({
20938
+ error: `No session with id "${sessionId}"`,
20939
+ code: "session_not_found",
20940
+ sessionId
20941
+ });
20942
+ return;
20943
+ }
20944
+ const runtime2 = requireSessionRuntime({
20945
+ sessionId: virtualKey.parentSessionId,
20946
+ route: route2,
20947
+ res,
20948
+ workspaceRegistry,
20949
+ daemonLog
20950
+ });
20951
+ if (!runtime2) return;
20952
+ const clientId2 = parseClientIdHeader(req, res);
20953
+ if (clientId2 === null) return;
20954
+ try {
20955
+ const session = await virtualSubagentSessions.load(
20956
+ runtime2,
20957
+ sessionId,
20958
+ clientId2
20959
+ );
20960
+ if (!session) {
20961
+ res.status(404).json({
20962
+ error: "Subagent session not found",
20963
+ code: "session_not_found",
20964
+ sessionId
20965
+ });
20966
+ return;
20967
+ }
20968
+ res.status(200).json(session);
20969
+ } catch (err) {
20970
+ sendBridgeError2(res, err, { route: route2, sessionId });
20971
+ }
20972
+ return;
20973
+ }
19974
20974
  const body = safeBody(req);
19975
20975
  const route = `POST /session/:id/${action}`;
19976
20976
  let resolvedRuntime;
@@ -20050,6 +21050,72 @@ function registerSessionRoutes(app, deps) {
20050
21050
  }
20051
21051
  return;
20052
21052
  }
21053
+ if (!session.worktree) {
21054
+ const sidecar = await readWorktreeSession(
21055
+ new SessionService(workspaceCwd).getWorktreeSessionPath(sessionId)
21056
+ ).catch(() => null);
21057
+ if (sidecar) {
21058
+ let realTarget;
21059
+ const candidateRoots = [
21060
+ path10.join(workspaceCwd, ".qwen", "worktrees")
21061
+ ];
21062
+ try {
21063
+ realTarget = fs4.realpathSync(sidecar.worktreePath);
21064
+ let repoTop = null;
21065
+ try {
21066
+ repoTop = await new GitWorktreeService(
21067
+ workspaceCwd
21068
+ ).getRepoTopLevel();
21069
+ } catch {
21070
+ }
21071
+ if (repoTop && repoTop !== workspaceCwd) {
21072
+ candidateRoots.push(path10.join(repoTop, ".qwen", "worktrees"));
21073
+ }
21074
+ const contained = candidateRoots.some((root) => {
21075
+ try {
21076
+ const realRoot = fs4.realpathSync(root);
21077
+ const rel = path10.relative(realRoot, realTarget);
21078
+ return !rel.startsWith("..") && !path10.isAbsolute(rel);
21079
+ } catch {
21080
+ return false;
21081
+ }
21082
+ });
21083
+ if (!contained) {
21084
+ realTarget = void 0;
21085
+ }
21086
+ } catch {
21087
+ realTarget = void 0;
21088
+ }
21089
+ if (!realTarget) {
21090
+ daemonLog?.warn("worktree sidecar path failed containment", {
21091
+ sessionId,
21092
+ path: sidecar.worktreePath
21093
+ });
21094
+ } else {
21095
+ const wt = {
21096
+ slug: sidecar.slug,
21097
+ path: realTarget,
21098
+ branch: sidecar.worktreeBranch
21099
+ };
21100
+ try {
21101
+ if (!session.hasActivePrompt) {
21102
+ await runtime.bridge.changeSessionCwd(sessionId, {
21103
+ path: wt.path,
21104
+ allowedRoots: candidateRoots
21105
+ });
21106
+ }
21107
+ runtime.bridge.setSessionWorktree(sessionId, wt);
21108
+ session.worktree = wt;
21109
+ } catch (restoreErr) {
21110
+ daemonLog?.warn("worktree restore failed on load/resume", {
21111
+ sessionId,
21112
+ worktreePath: wt.path,
21113
+ error: restoreErr instanceof Error ? restoreErr.message : String(restoreErr)
21114
+ });
21115
+ }
21116
+ }
21117
+ }
21118
+ }
20053
21119
  res.status(200).json(session);
20054
21120
  } catch (err) {
20055
21121
  sendBridgeError2(res, err, {
@@ -20062,6 +21128,112 @@ function registerSessionRoutes(app, deps) {
20062
21128
  }, "restoreSessionHandler");
20063
21129
  app.post("/session/:id/load", mutate(), restoreSessionHandler("load"));
20064
21130
  app.post("/session/:id/resume", mutate(), restoreSessionHandler("resume"));
21131
+ app.get("/session/:id/subagents/:toolCallId", async (req, res) => {
21132
+ const route = "GET /session/:id/subagents/:toolCallId";
21133
+ const sessionId = requireSessionId(req, res);
21134
+ if (!sessionId) return;
21135
+ if (!virtualSubagentSessions) {
21136
+ res.status(404).json({
21137
+ error: `No session with id "${sessionId}"`,
21138
+ code: "session_not_found",
21139
+ sessionId
21140
+ });
21141
+ return;
21142
+ }
21143
+ const toolCallId = req.params["toolCallId"];
21144
+ if (!toolCallId || toolCallId.length > 500) {
21145
+ res.status(400).json({
21146
+ error: "`toolCallId` must be a non-empty tool call id",
21147
+ code: "invalid_tool_call_id"
21148
+ });
21149
+ return;
21150
+ }
21151
+ const runtime = requireSessionRuntime({
21152
+ sessionId,
21153
+ route,
21154
+ res,
21155
+ workspaceRegistry,
21156
+ daemonLog
21157
+ });
21158
+ if (!runtime) return;
21159
+ try {
21160
+ const resolved = await virtualSubagentSessions.resolve(
21161
+ runtime,
21162
+ sessionId,
21163
+ toolCallId
21164
+ );
21165
+ if (!resolved) {
21166
+ res.status(404).json({
21167
+ error: "Subagent session not found",
21168
+ code: "session_not_found",
21169
+ sessionId,
21170
+ toolCallId
21171
+ });
21172
+ return;
21173
+ }
21174
+ res.status(200).set("Cache-Control", "no-store").json(resolved);
21175
+ } catch (err) {
21176
+ sendBridgeError2(res, err, { route, sessionId });
21177
+ }
21178
+ });
21179
+ app.post(
21180
+ "/session/:id/subagents/:toolCallId/cancel",
21181
+ mutate(),
21182
+ async (req, res) => {
21183
+ const route = "POST /session/:id/subagents/:toolCallId/cancel";
21184
+ const sessionId = requireSessionId(req, res);
21185
+ if (!sessionId) return;
21186
+ if (!virtualSubagentSessions) {
21187
+ res.status(404).json({
21188
+ error: `No session with id "${sessionId}"`,
21189
+ code: "session_not_found",
21190
+ sessionId
21191
+ });
21192
+ return;
21193
+ }
21194
+ const toolCallId = req.params["toolCallId"];
21195
+ if (!toolCallId || toolCallId.length > 500) {
21196
+ res.status(400).json({
21197
+ error: "`toolCallId` must be a non-empty tool call id",
21198
+ code: "invalid_tool_call_id"
21199
+ });
21200
+ return;
21201
+ }
21202
+ const runtime = requireSessionRuntime({
21203
+ sessionId,
21204
+ route,
21205
+ res,
21206
+ workspaceRegistry,
21207
+ daemonLog
21208
+ });
21209
+ if (!runtime) return;
21210
+ try {
21211
+ const resolved = await virtualSubagentSessions.resolve(
21212
+ runtime,
21213
+ sessionId,
21214
+ toolCallId
21215
+ );
21216
+ if (!resolved) {
21217
+ res.status(404).json({
21218
+ error: "Subagent session not found",
21219
+ code: "session_not_found",
21220
+ sessionId,
21221
+ toolCallId
21222
+ });
21223
+ return;
21224
+ }
21225
+ res.status(200).json(
21226
+ await runtime.bridge.cancelSessionTask(
21227
+ sessionId,
21228
+ resolved.taskId,
21229
+ "agent"
21230
+ )
21231
+ );
21232
+ } catch (err) {
21233
+ sendBridgeError2(res, err, { route, sessionId });
21234
+ }
21235
+ }
21236
+ );
20065
21237
  app.post(
20066
21238
  "/session/:id/branch",
20067
21239
  mutate(),
@@ -20131,7 +21303,7 @@ function registerSessionRoutes(app, deps) {
20131
21303
  async (req, res, sessionId) => {
20132
21304
  const body = safeBody(req);
20133
21305
  const targetPath = body["path"];
20134
- if (typeof targetPath !== "string" || targetPath.length === 0 || !path11.isAbsolute(targetPath)) {
21306
+ if (typeof targetPath !== "string" || targetPath.length === 0 || !path10.isAbsolute(targetPath)) {
20135
21307
  res.status(400).json({
20136
21308
  error: "`path` is required and must be an absolute path",
20137
21309
  code: "invalid_path"
@@ -20361,6 +21533,28 @@ function registerSessionRoutes(app, deps) {
20361
21533
  });
20362
21534
  app.get(
20363
21535
  "/session/:id/context",
21536
+ (req, res, next) => {
21537
+ const sessionId = req.params["id"];
21538
+ const key = sessionId ? parseVirtualSubagentSessionId(sessionId) : void 0;
21539
+ if (!sessionId || !key) {
21540
+ next();
21541
+ return;
21542
+ }
21543
+ const runtime = requireSessionRuntime({
21544
+ sessionId: key.parentSessionId,
21545
+ route: "GET /session/:id/context",
21546
+ res,
21547
+ workspaceRegistry,
21548
+ daemonLog
21549
+ });
21550
+ if (!runtime) return;
21551
+ res.status(200).json({
21552
+ v: 1,
21553
+ sessionId,
21554
+ workspaceCwd: runtime.workspaceCwd,
21555
+ state: {}
21556
+ });
21557
+ },
20364
21558
  withOwnerReadSession(
20365
21559
  "GET /session/:id/context",
20366
21560
  async (_req, res, sessionId, runtime) => {
@@ -20392,6 +21586,28 @@ function registerSessionRoutes(app, deps) {
20392
21586
  );
20393
21587
  app.get(
20394
21588
  "/session/:id/supported-commands",
21589
+ (req, res, next) => {
21590
+ const sessionId = req.params["id"];
21591
+ const key = sessionId ? parseVirtualSubagentSessionId(sessionId) : void 0;
21592
+ if (!sessionId || !key) {
21593
+ next();
21594
+ return;
21595
+ }
21596
+ const runtime = requireSessionRuntime({
21597
+ sessionId: key.parentSessionId,
21598
+ route: "GET /session/:id/supported-commands",
21599
+ res,
21600
+ workspaceRegistry,
21601
+ daemonLog
21602
+ });
21603
+ if (!runtime) return;
21604
+ res.status(200).json({
21605
+ v: 1,
21606
+ sessionId,
21607
+ availableCommands: [],
21608
+ availableSkills: []
21609
+ });
21610
+ },
20395
21611
  withOwnerReadSession(
20396
21612
  "GET /session/:id/supported-commands",
20397
21613
  async (_req, res, sessionId, runtime) => {
@@ -20633,15 +21849,6 @@ function registerSessionRoutes(app, deps) {
20633
21849
  promptDeadlineMs,
20634
21850
  requestDeadlineMs
20635
21851
  );
20636
- let deadlineTimer;
20637
- if (effectiveDeadlineMs !== void 0) {
20638
- deadlineTimer = setTimeout(() => {
20639
- if (!abort.signal.aborted) {
20640
- abort.abort(new PromptDeadlineExceededError(effectiveDeadlineMs));
20641
- }
20642
- }, effectiveDeadlineMs);
20643
- deadlineTimer.unref();
20644
- }
20645
21852
  let promptPromise;
20646
21853
  try {
20647
21854
  promptPromise = ownerBridge.sendPrompt(
@@ -20654,11 +21861,11 @@ function registerSessionRoutes(app, deps) {
20654
21861
  abort.signal,
20655
21862
  {
20656
21863
  ...clientId !== void 0 ? { clientId } : {},
20657
- promptId
21864
+ promptId,
21865
+ ...effectiveDeadlineMs !== void 0 ? { deadlineMs: effectiveDeadlineMs } : {}
20658
21866
  }
20659
21867
  );
20660
21868
  } catch (err) {
20661
- if (deadlineTimer !== void 0) clearTimeout(deadlineTimer);
20662
21869
  res.off("close", onResClose);
20663
21870
  res.off("finish", onResFinish);
20664
21871
  if (daemonLog && err instanceof PromptQueueFullError) {
@@ -20703,9 +21910,7 @@ function registerSessionRoutes(app, deps) {
20703
21910
  );
20704
21911
  }
20705
21912
  }
20706
- ).finally(() => {
20707
- if (deadlineTimer !== void 0) clearTimeout(deadlineTimer);
20708
- }).catch(() => {
21913
+ ).catch(() => {
20709
21914
  });
20710
21915
  if (daemonLog) {
20711
21916
  daemonLog.info("prompt enqueued", { sessionId, promptId, clientId });
@@ -20799,6 +22004,29 @@ function registerSessionRoutes(app, deps) {
20799
22004
  app.post(
20800
22005
  "/session/:id/heartbeat",
20801
22006
  mutate(),
22007
+ (req, res, next) => {
22008
+ const sessionId = req.params["id"];
22009
+ const key = sessionId ? parseVirtualSubagentSessionId(sessionId) : void 0;
22010
+ if (!sessionId || !key) {
22011
+ next();
22012
+ return;
22013
+ }
22014
+ const runtime = requireSessionRuntime({
22015
+ sessionId: key.parentSessionId,
22016
+ route: "POST /session/:id/heartbeat",
22017
+ res,
22018
+ workspaceRegistry,
22019
+ daemonLog
22020
+ });
22021
+ if (!runtime) return;
22022
+ const clientId = parseClientIdHeader(req, res);
22023
+ if (clientId === null) return;
22024
+ res.status(200).json({
22025
+ sessionId,
22026
+ ...clientId ? { clientId } : {},
22027
+ lastSeenAt: Date.now()
22028
+ });
22029
+ },
20802
22030
  withOwnerMutableSession(
20803
22031
  "POST /session/:id/heartbeat",
20804
22032
  (req, res, sessionId, runtime) => {
@@ -20815,6 +22043,25 @@ function registerSessionRoutes(app, deps) {
20815
22043
  app.post(
20816
22044
  "/session/:id/detach",
20817
22045
  mutate(),
22046
+ (req, res, next) => {
22047
+ const sessionId = req.params["id"];
22048
+ const key = sessionId ? parseVirtualSubagentSessionId(sessionId) : void 0;
22049
+ if (!sessionId || !key) {
22050
+ next();
22051
+ return;
22052
+ }
22053
+ const runtime = requireSessionRuntime({
22054
+ sessionId: key.parentSessionId,
22055
+ route: "POST /session/:id/detach",
22056
+ res,
22057
+ workspaceRegistry,
22058
+ daemonLog
22059
+ });
22060
+ if (!runtime) return;
22061
+ const clientId = parseClientIdHeader(req, res);
22062
+ if (clientId === null) return;
22063
+ res.status(204).end();
22064
+ },
20818
22065
  withOwnerMutableSession(
20819
22066
  "POST /session/:id/detach",
20820
22067
  async (req, res, sessionId, runtime) => {
@@ -22578,7 +23825,7 @@ __name(registerUsageStatsRoutes, "registerUsageStatsRoutes");
22578
23825
  // packages/cli/src/serve/scheduled-task-keepalive.ts
22579
23826
  init_esbuild_shims();
22580
23827
  import * as fsSync from "node:fs";
22581
- import * as path12 from "node:path";
23828
+ import * as path11 from "node:path";
22582
23829
  var log = createDebugLogger("SCHED_KEEPALIVE");
22583
23830
  function collectBoundSessionIds(tasks) {
22584
23831
  const seen = /* @__PURE__ */ new Set();
@@ -22789,8 +24036,8 @@ function startScheduledTaskKeepalive(opts) {
22789
24036
  timer.unref?.();
22790
24037
  let bindDebounce;
22791
24038
  const cronFilePath = getCronFilePath(boundWorkspace);
22792
- const cronDir = path12.dirname(cronFilePath);
22793
- const cronFileName = path12.basename(cronFilePath);
24039
+ const cronDir = path11.dirname(cronFilePath);
24040
+ const cronFileName = path11.basename(cronFilePath);
22794
24041
  let fileWatcher;
22795
24042
  try {
22796
24043
  fsSync.mkdirSync(cronDir, { recursive: true });
@@ -22881,7 +24128,7 @@ async function rehydrateScheduledTaskSessions(deps) {
22881
24128
  }
22882
24129
  __name(rehydrateScheduledTaskSessions, "rehydrateScheduledTaskSessions");
22883
24130
  function withTimeout(p, ms, label) {
22884
- return new Promise((resolve5, reject) => {
24131
+ return new Promise((resolve6, reject) => {
22885
24132
  const timer = setTimeout(() => {
22886
24133
  reject(new Error(`${label} timed out after ${ms}ms`));
22887
24134
  }, ms);
@@ -22889,7 +24136,7 @@ function withTimeout(p, ms, label) {
22889
24136
  p.then(
22890
24137
  (v) => {
22891
24138
  clearTimeout(timer);
22892
- resolve5(v);
24139
+ resolve6(v);
22893
24140
  },
22894
24141
  (e) => {
22895
24142
  clearTimeout(timer);
@@ -22973,7 +24220,7 @@ function registerWorkspaceStatusRoutes(app, deps) {
22973
24220
  const ctx = buildWorkspaceCtx("POST /workspace/acp/preheat");
22974
24221
  const timeoutMsRaw = req.query["timeoutMs"];
22975
24222
  const timeoutMs = typeof timeoutMsRaw === "string" && timeoutMsRaw.trim() ? Number(timeoutMsRaw) : void 0;
22976
- if (timeoutMs !== void 0 && (!Number.isFinite(timeoutMs) || !Number.isInteger(timeoutMs) || timeoutMs <= 0 || timeoutMs > MAX_ACP_PREHEAT_TIMEOUT_MS)) {
24223
+ if (timeoutMsRaw !== void 0 && (timeoutMs === void 0 || !Number.isFinite(timeoutMs) || !Number.isInteger(timeoutMs) || timeoutMs <= 0 || timeoutMs > MAX_ACP_PREHEAT_TIMEOUT_MS)) {
22977
24224
  res.status(400).json({
22978
24225
  error: "`timeoutMs` must be a positive integer no greater than 60000",
22979
24226
  code: "invalid_timeout"
@@ -23203,7 +24450,9 @@ function createServeFeatures(deps) {
23203
24450
  channelControlAvailable,
23204
24451
  sessionShellCommandEnabled,
23205
24452
  multiWorkspaceSessionsEnabled,
24453
+ dynamicWorkspaceRegistrationAvailable,
23206
24454
  persistentWorkspaceRegistrationAvailable,
24455
+ scratchWorkspaceRegistrationAvailable,
23207
24456
  workspaceRuntimeRemovalAvailable
23208
24457
  } = deps;
23209
24458
  const env = deps.env ?? process.env;
@@ -23237,7 +24486,9 @@ function createServeFeatures(deps) {
23237
24486
  channelReloadAvailable: channelReloadAvailable(),
23238
24487
  channelControlAvailable,
23239
24488
  multiWorkspaceSessionsEnabled: multiWorkspaceSessionsEnabled(),
24489
+ dynamicWorkspaceRegistrationAvailable,
23240
24490
  persistentWorkspaceRegistrationAvailable,
24491
+ scratchWorkspaceRegistrationAvailable: scratchWorkspaceRegistrationAvailable(),
23241
24492
  workspaceRuntimeRemovalAvailable,
23242
24493
  acpHttpEnabled: resolveAcpHttpEnabled(),
23243
24494
  clientMcpOverWsEnabled: opts.clientMcpOverWs === true,
@@ -23307,6 +24558,7 @@ function registerCapabilitiesRoutes(app, deps) {
23307
24558
  workspaces: runtimes.map((runtime) => ({
23308
24559
  id: runtime.workspaceId,
23309
24560
  cwd: runtime.workspaceCwd,
24561
+ ...runtime.displayName !== void 0 ? { displayName: runtime.displayName } : {},
23310
24562
  primary: runtime.primary,
23311
24563
  trusted: runtime.trusted,
23312
24564
  ...runtimeRemoval ? { removable: runtime.removable === true } : {}
@@ -23979,6 +25231,12 @@ init_esbuild_shims();
23979
25231
 
23980
25232
  // packages/cli/src/serve/server/error-response.ts
23981
25233
  init_esbuild_shims();
25234
+ var SESSION_WRITER_ERROR_MESSAGES = {
25235
+ session_writer_conflict: "This session is already open in another Qwen process.",
25236
+ session_writer_lost: "Write ownership for this session was lost.",
25237
+ session_transcript_changed: "The session transcript changed outside its active writer.",
25238
+ session_writer_unavailable: "Session write ownership could not be verified."
25239
+ };
23982
25240
  function bridgeErrorExtraContext(ctx) {
23983
25241
  const extra = {};
23984
25242
  for (const [key, value] of Object.entries(ctx ?? {})) {
@@ -24031,6 +25289,14 @@ function sendPermissionVoteError(res, err, ctx, daemonLog) {
24031
25289
  }
24032
25290
  __name(sendPermissionVoteError, "sendPermissionVoteError");
24033
25291
  function sendBridgeError(res, err, ctx, daemonLog) {
25292
+ if (err instanceof SessionWriterError) {
25293
+ res.status(err.httpStatus).json({
25294
+ error: err.message,
25295
+ code: err.errorKind,
25296
+ errorKind: err.errorKind
25297
+ });
25298
+ return;
25299
+ }
24034
25300
  if (err instanceof WorkspaceSkillNotFoundError) {
24035
25301
  res.status(404).json({
24036
25302
  error: err.message,
@@ -24343,6 +25609,22 @@ function sendBridgeError(res, err, ctx, daemonLog) {
24343
25609
  const data = err.data;
24344
25610
  if (data && typeof data === "object") {
24345
25611
  const kind = data.errorKind;
25612
+ if (kind === "session_writer_conflict" || kind === "session_writer_lost" || kind === "session_transcript_changed") {
25613
+ res.status(409).json({
25614
+ error: SESSION_WRITER_ERROR_MESSAGES[kind],
25615
+ code: kind,
25616
+ errorKind: kind
25617
+ });
25618
+ return;
25619
+ }
25620
+ if (kind === "session_writer_unavailable") {
25621
+ res.status(503).json({
25622
+ error: SESSION_WRITER_ERROR_MESSAGES[kind],
25623
+ code: kind,
25624
+ errorKind: kind
25625
+ });
25626
+ return;
25627
+ }
24346
25628
  if (kind === "mcp_budget_would_exceed") {
24347
25629
  const d = data;
24348
25630
  res.status(409).json({
@@ -24544,7 +25826,7 @@ data: ${dataJson}
24544
25826
  __name(formatSseFrame, "formatSseFrame");
24545
25827
  function registerSseEventsRoutes(app, deps) {
24546
25828
  const { workspaceRegistry, daemonLog, sendBridgeError: sendBridgeError2, writerIdleTimeoutMs } = deps;
24547
- app.get("/session/:id/events", (req, res) => {
25829
+ app.get("/session/:id/events", async (req, res) => {
24548
25830
  const sessionId = req.params["id"];
24549
25831
  const lastEventId = parseLastEventId(req.headers["last-event-id"]);
24550
25832
  const maxQueued = parseMaxQueuedQuery(req.query["maxQueued"], res);
@@ -24552,8 +25834,9 @@ function registerSseEventsRoutes(app, deps) {
24552
25834
  let iter;
24553
25835
  const abort = new AbortController();
24554
25836
  try {
25837
+ const virtualKey = parseVirtualSubagentSessionId(sessionId);
24555
25838
  const runtime = requireSessionRuntime({
24556
- sessionId,
25839
+ sessionId: virtualKey?.parentSessionId ?? sessionId,
24557
25840
  route: "GET /session/:id/events",
24558
25841
  res,
24559
25842
  workspaceRegistry,
@@ -24561,12 +25844,24 @@ function registerSseEventsRoutes(app, deps) {
24561
25844
  });
24562
25845
  if (!runtime) return;
24563
25846
  const snapshot = req.query["snapshot"] === "1";
24564
- const iterable = runtime.bridge.subscribeEvents(sessionId, {
25847
+ const iterable = virtualKey ? await deps.virtualSubagentSessions?.subscribe(runtime, sessionId, {
25848
+ signal: abort.signal,
25849
+ lastEventId,
25850
+ ...maxQueued !== void 0 ? { maxQueued } : {}
25851
+ }) : runtime.bridge.subscribeEvents(sessionId, {
24565
25852
  signal: abort.signal,
24566
25853
  lastEventId,
24567
25854
  ...maxQueued !== void 0 ? { maxQueued } : {},
24568
25855
  ...snapshot ? { snapshot: true } : {}
24569
25856
  });
25857
+ if (!iterable) {
25858
+ res.status(404).json({
25859
+ error: "Subagent session not found",
25860
+ code: "session_not_found",
25861
+ sessionId
25862
+ });
25863
+ return;
25864
+ }
24570
25865
  iter = iterable[Symbol.asyncIterator]();
24571
25866
  } catch (err) {
24572
25867
  if (err instanceof SubscriberLimitExceededError) {
@@ -24619,9 +25914,9 @@ function registerSseEventsRoutes(app, deps) {
24619
25914
  let writeChain = Promise.resolve();
24620
25915
  const trackWriterIdle = writerIdleTimeoutMs !== void 0 && writerIdleTimeoutMs > 0;
24621
25916
  let lastWriteAt = trackWriterIdle ? Date.now() : 0;
24622
- const doWrite = /* @__PURE__ */ __name((chunk) => new Promise((resolve5, reject) => {
25917
+ const doWrite = /* @__PURE__ */ __name((chunk) => new Promise((resolve6, reject) => {
24623
25918
  if (res.writableEnded) {
24624
- resolve5();
25919
+ resolve6();
24625
25920
  return;
24626
25921
  }
24627
25922
  let ok;
@@ -24633,19 +25928,19 @@ function registerSseEventsRoutes(app, deps) {
24633
25928
  }
24634
25929
  if (ok) {
24635
25930
  if (trackWriterIdle) lastWriteAt = Date.now();
24636
- resolve5();
25931
+ resolve6();
24637
25932
  return;
24638
25933
  }
24639
25934
  const onDrain = /* @__PURE__ */ __name(() => {
24640
25935
  res.off("close", onClose);
24641
25936
  res.off("error", onError);
24642
25937
  if (trackWriterIdle) lastWriteAt = Date.now();
24643
- resolve5();
25938
+ resolve6();
24644
25939
  }, "onDrain");
24645
25940
  const onClose = /* @__PURE__ */ __name(() => {
24646
25941
  res.off("drain", onDrain);
24647
25942
  res.off("error", onError);
24648
- resolve5();
25943
+ resolve6();
24649
25944
  }, "onClose");
24650
25945
  const onError = /* @__PURE__ */ __name((err) => {
24651
25946
  res.off("drain", onDrain);
@@ -24974,7 +26269,7 @@ __name(registerWorkspaceModelsRoutes, "registerWorkspaceModelsRoutes");
24974
26269
  // packages/cli/src/serve/routes/a2ui-action.ts
24975
26270
  init_esbuild_shims();
24976
26271
  import * as fsp4 from "node:fs/promises";
24977
- import * as path13 from "node:path";
26272
+ import * as path12 from "node:path";
24978
26273
  var A2UI_MIME = "application/a2ui+json";
24979
26274
  var ACTION_TOOL = "action";
24980
26275
  var CALL_TIMEOUT_MS = 15e3;
@@ -24997,7 +26292,7 @@ __name(usableServerConfig, "usableServerConfig");
24997
26292
  async function findFromSettingsFile(workspaceCwd) {
24998
26293
  try {
24999
26294
  const raw = await fsp4.readFile(
25000
- path13.join(workspaceCwd, ".qwen", "settings.json"),
26295
+ path12.join(workspaceCwd, ".qwen", "settings.json"),
25001
26296
  "utf8"
25002
26297
  );
25003
26298
  const settings = JSON.parse(raw);
@@ -25134,7 +26429,7 @@ __name(registerA2uiActionRoutes, "registerA2uiActionRoutes");
25134
26429
 
25135
26430
  // packages/cli/src/serve/server/fs-factory.ts
25136
26431
  init_esbuild_shims();
25137
- import * as path14 from "node:path";
26432
+ import * as path13 from "node:path";
25138
26433
  var IDE_WORKSPACE_PATH_ENV_VAR = "QWEN_CODE_IDE_WORKSPACE_PATH";
25139
26434
  function createDefaultFsAuditEmit() {
25140
26435
  const WARN_EVERY = 100;
@@ -25208,14 +26503,14 @@ function parseIdeWorkspacePathEnv(value) {
25208
26503
  const parsed = JSON.parse(value);
25209
26504
  if (Array.isArray(parsed) && parsed.every((item) => typeof item === "string")) {
25210
26505
  return parsed.filter(
25211
- (workspace) => workspace.length > 0 && path14.isAbsolute(workspace)
26506
+ (workspace) => workspace.length > 0 && path13.isAbsolute(workspace)
25212
26507
  );
25213
26508
  }
25214
26509
  throw new Error("IDE workspace path JSON must be a string array");
25215
26510
  } catch {
25216
26511
  }
25217
26512
  }
25218
- return value.split(path14.delimiter).filter((workspace) => workspace.length > 0 && path14.isAbsolute(workspace));
26513
+ return value.split(path13.delimiter).filter((workspace) => workspace.length > 0 && path13.isAbsolute(workspace));
25219
26514
  }
25220
26515
  __name(parseIdeWorkspacePathEnv, "parseIdeWorkspacePathEnv");
25221
26516
  function dropNestedWorkspacesPreservingPrimary(workspaces) {
@@ -25714,45 +27009,201 @@ function registerWorkspaceQualifiedLifecycleRoutes(app, deps) {
25714
27009
  deps.sendBridgeError(res, err, { route });
25715
27010
  }
25716
27011
  }
25717
- );
25718
- }
25719
- __name(registerWorkspaceQualifiedLifecycleRoutes, "registerWorkspaceQualifiedLifecycleRoutes");
25720
-
25721
- // packages/cli/src/serve/routes/workspace-management.ts
25722
- init_esbuild_shims();
25723
- import { readdir, stat } from "node:fs/promises";
25724
- import { realpathSync } from "node:fs";
25725
- import { basename as basename4, dirname as dirname4, isAbsolute as isAbsolute7, join as join7, resolve as resolve4, sep as sep3 } from "node:path";
25726
- var MAX_PATH_SUGGESTIONS = 50;
25727
- function registerWorkspaceManagementRoutes(app, deps) {
25728
- const {
25729
- workspaceRegistry,
25730
- mutate,
25731
- safeBody: safeBody2,
25732
- createWorkspaceRuntime,
25733
- workspaceRegistrationStore,
25734
- getAcpHandle,
25735
- runtimeRemoval
25736
- } = deps;
25737
- const inFlight = /* @__PURE__ */ new Map();
25738
- let sealed = false;
25739
- let activeOperations = 0;
25740
- const idleWaiters = /* @__PURE__ */ new Set();
25741
- const operationStarted = /* @__PURE__ */ __name(() => {
25742
- activeOperations++;
25743
- }, "operationStarted");
25744
- const operationFinished = /* @__PURE__ */ __name(() => {
25745
- activeOperations--;
25746
- if (activeOperations !== 0) return;
25747
- for (const resolveIdle of idleWaiters) resolveIdle();
25748
- idleWaiters.clear();
25749
- }, "operationFinished");
25750
- const sendSealed = /* @__PURE__ */ __name((res) => {
25751
- res.status(503).json({
25752
- error: "Daemon is shutting down",
25753
- code: "daemon_shutting_down"
25754
- });
25755
- }, "sendSealed");
27012
+ );
27013
+ }
27014
+ __name(registerWorkspaceQualifiedLifecycleRoutes, "registerWorkspaceQualifiedLifecycleRoutes");
27015
+
27016
+ // packages/cli/src/serve/routes/workspace-management.ts
27017
+ init_esbuild_shims();
27018
+ import { readdir as readdir2, stat as stat2 } from "node:fs/promises";
27019
+ import { realpathSync as realpathSync2 } from "node:fs";
27020
+ import { basename as basename4, dirname as dirname4, isAbsolute as isAbsolute7, join as join8, resolve as resolve4, sep as sep3 } from "node:path";
27021
+ var MAX_PATH_SUGGESTIONS = 50;
27022
+ function registerWorkspaceManagementRoutes(app, deps) {
27023
+ const {
27024
+ workspaceRegistry,
27025
+ mutate,
27026
+ safeBody: safeBody2,
27027
+ createWorkspaceRuntime,
27028
+ managedScratchRoot,
27029
+ workspaceRegistrationStore,
27030
+ getAcpHandle,
27031
+ runtimeRemoval
27032
+ } = deps;
27033
+ const inFlight = /* @__PURE__ */ new Map();
27034
+ let sealed = false;
27035
+ let activeOperations = 0;
27036
+ let pendingScratchCreations = 0;
27037
+ const idleWaiters = /* @__PURE__ */ new Set();
27038
+ const operationStarted = /* @__PURE__ */ __name(() => {
27039
+ activeOperations++;
27040
+ }, "operationStarted");
27041
+ const operationFinished = /* @__PURE__ */ __name(() => {
27042
+ activeOperations--;
27043
+ if (activeOperations !== 0) return;
27044
+ for (const resolveIdle of idleWaiters) resolveIdle();
27045
+ idleWaiters.clear();
27046
+ }, "operationFinished");
27047
+ const sendSealed = /* @__PURE__ */ __name((res) => {
27048
+ res.status(503).json({
27049
+ error: "Daemon is shutting down",
27050
+ code: "daemon_shutting_down"
27051
+ });
27052
+ }, "sendSealed");
27053
+ const attachRegistrationIds = /* @__PURE__ */ __name((runtime, registrationIds) => {
27054
+ runtime.registrationIds ??= [];
27055
+ for (const registrationId of registrationIds) {
27056
+ if (!runtime.registrationIds.includes(registrationId)) {
27057
+ runtime.registrationIds.push(registrationId);
27058
+ }
27059
+ }
27060
+ }, "attachRegistrationIds");
27061
+ const restorePersistedDisplayName = /* @__PURE__ */ __name(async (runtime, canonical) => {
27062
+ const snapshot = await workspaceRegistrationStore.read();
27063
+ const storedWorkspace = snapshot.workspaces.find(
27064
+ (stored) => process.platform === "win32" ? stored.toLowerCase() === canonical.toLowerCase() : stored === canonical
27065
+ );
27066
+ const storedDisplayName = storedWorkspace ? snapshot.displayNames?.[workspaceRegistrationId(storedWorkspace)] : void 0;
27067
+ if (storedWorkspace) {
27068
+ attachRegistrationIds(runtime, [
27069
+ workspaceRegistrationId(storedWorkspace)
27070
+ ]);
27071
+ }
27072
+ if (storedDisplayName === void 0) {
27073
+ delete runtime.displayName;
27074
+ } else {
27075
+ runtime.displayName = storedDisplayName;
27076
+ }
27077
+ }, "restorePersistedDisplayName");
27078
+ const projectedWorkspaceCount = /* @__PURE__ */ __name(() => {
27079
+ const cwdSet = new Set(
27080
+ workspaceRegistry.listManaged().map((runtime) => runtime.workspaceCwd)
27081
+ );
27082
+ for (const [cwd, operation] of inFlight) {
27083
+ if (operation === "addition") cwdSet.add(cwd);
27084
+ }
27085
+ return cwdSet.size + pendingScratchCreations;
27086
+ }, "projectedWorkspaceCount");
27087
+ const createScratchWorkspace = /* @__PURE__ */ __name(async (res) => {
27088
+ if (!createWorkspaceRuntime || !managedScratchRoot || !runtimeRemoval) {
27089
+ res.status(501).json({
27090
+ error: "Scratch workspace registration is not available",
27091
+ code: "scratch_not_available"
27092
+ });
27093
+ return;
27094
+ }
27095
+ if (sealed) {
27096
+ sendSealed(res);
27097
+ return;
27098
+ }
27099
+ if (workspaceRegistry.listManaged().some(
27100
+ (runtime2) => !isScratchRootCompatible(
27101
+ runtime2.workspaceCwd,
27102
+ managedScratchRoot.canonicalRoot
27103
+ )
27104
+ ) || [...inFlight].some(
27105
+ ([cwd, operation]) => operation === "addition" && !isScratchRootCompatible(cwd, managedScratchRoot.canonicalRoot)
27106
+ )) {
27107
+ res.status(409).json({
27108
+ error: "Managed scratch root conflicts with a registered workspace",
27109
+ code: "scratch_root_conflict"
27110
+ });
27111
+ return;
27112
+ }
27113
+ if (projectedWorkspaceCount() >= MAX_REGISTERED_WORKSPACES) {
27114
+ res.status(409).json({
27115
+ error: "Workspace registration limit reached",
27116
+ code: "workspace_limit_reached"
27117
+ });
27118
+ return;
27119
+ }
27120
+ pendingScratchCreations++;
27121
+ operationStarted();
27122
+ let reservationHeld = true;
27123
+ let canonical;
27124
+ let runtime;
27125
+ let registered = false;
27126
+ try {
27127
+ canonical = await createManagedScratchDirectory(managedScratchRoot);
27128
+ if (sealed) {
27129
+ sendSealed(res);
27130
+ return;
27131
+ }
27132
+ pendingScratchCreations--;
27133
+ reservationHeld = false;
27134
+ inFlight.set(canonical, "addition");
27135
+ const boundCwds = workspaceRegistry.listManaged().map((entry) => entry.workspaceCwd);
27136
+ for (const [cwd, operation] of inFlight) {
27137
+ if (operation === "addition" && cwd !== canonical) boundCwds.push(cwd);
27138
+ }
27139
+ if (boundCwds.some(
27140
+ (cwd) => !isScratchRootCompatible(cwd, managedScratchRoot.canonicalRoot) || isWithinRoot(canonical, cwd) || isWithinRoot(cwd, canonical)
27141
+ )) {
27142
+ res.status(409).json({
27143
+ error: "Workspace path nests with an existing workspace",
27144
+ code: "workspace_nested"
27145
+ });
27146
+ return;
27147
+ }
27148
+ if (sealed) {
27149
+ sendSealed(res);
27150
+ return;
27151
+ }
27152
+ runtime = await createWorkspaceRuntime(canonical, {
27153
+ provenance: "managed-scratch"
27154
+ });
27155
+ if (runtime.workspaceCwd !== canonical || runtime.primary || !runtime.trusted) {
27156
+ throw new Error(
27157
+ "Scratch runtime violated the managed runtime contract"
27158
+ );
27159
+ }
27160
+ if (sealed) {
27161
+ sendSealed(res);
27162
+ return;
27163
+ }
27164
+ workspaceRegistry.add(runtime);
27165
+ registered = true;
27166
+ try {
27167
+ await runtimeRemoval.runtimeAdded?.(runtime);
27168
+ } catch (err) {
27169
+ try {
27170
+ writeStderrLine(
27171
+ `qwen serve: workspace runtime adapter notification failed after registry add: ${err instanceof Error ? err.message : String(err)}`
27172
+ );
27173
+ } catch {
27174
+ }
27175
+ }
27176
+ res.status(201).json({
27177
+ id: runtime.workspaceId,
27178
+ cwd: runtime.workspaceCwd,
27179
+ primary: false,
27180
+ trusted: true,
27181
+ persisted: false
27182
+ });
27183
+ } catch (err) {
27184
+ writeStderrLine(
27185
+ `qwen serve: scratch workspace registration failed: ${err instanceof Error ? err.message : String(err)}${canonical ? `; retained directory: ${canonical}` : ""}`
27186
+ );
27187
+ if (!res.headersSent) {
27188
+ res.status(500).json({
27189
+ error: "Failed to register scratch workspace",
27190
+ code: "runtime_creation_failed"
27191
+ });
27192
+ }
27193
+ } finally {
27194
+ if (runtime && !registered) {
27195
+ await runtimeRemoval.disposeRuntime(runtime, "workspace_removed").catch(() => {
27196
+ try {
27197
+ runtime?.bridge.killAllSync();
27198
+ } catch {
27199
+ }
27200
+ });
27201
+ }
27202
+ if (reservationHeld) pendingScratchCreations--;
27203
+ if (canonical) inFlight.delete(canonical);
27204
+ operationFinished();
27205
+ }
27206
+ }, "createScratchWorkspace");
25756
27207
  app.get(
25757
27208
  "/workspace-path-suggestions",
25758
27209
  async (req, res) => {
@@ -25780,13 +27231,13 @@ function registerWorkspaceManagementRoutes(app, deps) {
25780
27231
  return;
25781
27232
  }
25782
27233
  const endsWithSep = prefix.endsWith("/") || process.platform === "win32" && prefix.endsWith("\\");
25783
- const dir = endsWithSep ? join7(prefix, ".") : dirname4(prefix);
27234
+ const dir = endsWithSep ? join8(prefix, ".") : dirname4(prefix);
25784
27235
  const filter = endsWithSep ? "" : basename4(prefix);
25785
27236
  const filterLower = filter.toLowerCase();
25786
27237
  const suggestions = [];
25787
27238
  let truncated = false;
25788
27239
  try {
25789
- const entries = await readdir(dir, { withFileTypes: true });
27240
+ const entries = await readdir2(dir, { withFileTypes: true });
25790
27241
  entries.sort((a, b) => a.name.localeCompare(b.name));
25791
27242
  for (const entry of entries) {
25792
27243
  if (entry.name.startsWith(".") && !filter.startsWith(".")) continue;
@@ -25796,7 +27247,7 @@ function registerWorkspaceManagementRoutes(app, deps) {
25796
27247
  let isDir = entry.isDirectory();
25797
27248
  if (!isDir && entry.isSymbolicLink()) {
25798
27249
  try {
25799
- isDir = (await stat(join7(dir, entry.name))).isDirectory();
27250
+ isDir = (await stat2(join8(dir, entry.name))).isDirectory();
25800
27251
  } catch {
25801
27252
  continue;
25802
27253
  }
@@ -25806,7 +27257,7 @@ function registerWorkspaceManagementRoutes(app, deps) {
25806
27257
  truncated = true;
25807
27258
  break;
25808
27259
  }
25809
- suggestions.push({ name: entry.name, path: join7(dir, entry.name) });
27260
+ suggestions.push({ name: entry.name, path: join8(dir, entry.name) });
25810
27261
  }
25811
27262
  } catch {
25812
27263
  }
@@ -25824,8 +27275,33 @@ function registerWorkspaceManagementRoutes(app, deps) {
25824
27275
  mutate({ strict: true }),
25825
27276
  async (req, res) => {
25826
27277
  const body = safeBody2(req);
27278
+ if ("kind" in body) {
27279
+ if (body["kind"] !== "scratch" || "cwd" in body || "persist" in body || Object.keys(body).some((key) => key !== "kind")) {
27280
+ res.status(400).json({
27281
+ error: 'Scratch workspace requests must be exactly { kind: "scratch" }',
27282
+ code: "invalid_workspace_request"
27283
+ });
27284
+ return;
27285
+ }
27286
+ await createScratchWorkspace(res);
27287
+ return;
27288
+ }
25827
27289
  const cwd = body["cwd"];
25828
27290
  const persist = body["persist"] ?? false;
27291
+ const hasDisplayName = Object.hasOwn(body, "displayName");
27292
+ let displayName;
27293
+ if (hasDisplayName) {
27294
+ try {
27295
+ displayName = normalizeWorkspaceDisplayName(body["displayName"]);
27296
+ } catch (err) {
27297
+ if (!(err instanceof WorkspaceDisplayNameValidationError)) throw err;
27298
+ res.status(400).json({
27299
+ error: err.message,
27300
+ code: "invalid_display_name"
27301
+ });
27302
+ return;
27303
+ }
27304
+ }
25829
27305
  if (typeof cwd !== "string" || cwd.trim().length === 0) {
25830
27306
  res.status(400).json({
25831
27307
  error: "`cwd` must be a non-empty string",
@@ -25854,23 +27330,24 @@ function registerWorkspaceManagementRoutes(app, deps) {
25854
27330
  });
25855
27331
  return;
25856
27332
  }
25857
- if (!isAbsolute7(cwd)) {
27333
+ if (cwd.length > MAX_WORKSPACE_PATH_LENGTH) {
25858
27334
  res.status(400).json({
25859
- error: "`cwd` must be an absolute path",
27335
+ error: `\`cwd\` exceeds the ${MAX_WORKSPACE_PATH_LENGTH}-character limit`,
25860
27336
  code: "invalid_path"
25861
27337
  });
25862
27338
  return;
25863
27339
  }
25864
- if (cwd.length > MAX_WORKSPACE_PATH_LENGTH) {
27340
+ const sandboxCwd = translateAndCheckAbsoluteWorkspacePath(cwd);
27341
+ if (sandboxCwd === null) {
25865
27342
  res.status(400).json({
25866
- error: `\`cwd\` exceeds the ${MAX_WORKSPACE_PATH_LENGTH}-character limit`,
27343
+ error: "`cwd` must be an absolute path",
25867
27344
  code: "invalid_path"
25868
27345
  });
25869
27346
  return;
25870
27347
  }
25871
27348
  let canonical;
25872
27349
  try {
25873
- canonical = realpathSync.native(resolve4(cwd));
27350
+ canonical = realpathSync2.native(resolve4(sandboxCwd));
25874
27351
  } catch {
25875
27352
  res.status(400).json({
25876
27353
  error: "Path does not exist or is not accessible",
@@ -25878,12 +27355,19 @@ function registerWorkspaceManagementRoutes(app, deps) {
25878
27355
  });
25879
27356
  return;
25880
27357
  }
27358
+ if (managedScratchRoot && !isScratchRootCompatible(canonical, managedScratchRoot.canonicalRoot)) {
27359
+ res.status(409).json({
27360
+ error: "Workspace path conflicts with the managed scratch root",
27361
+ code: "scratch_root_conflict"
27362
+ });
27363
+ return;
27364
+ }
25881
27365
  if (sealed) {
25882
27366
  sendSealed(res);
25883
27367
  return;
25884
27368
  }
25885
27369
  try {
25886
- const s = await stat(canonical);
27370
+ const s = await stat2(canonical);
25887
27371
  if (!s.isDirectory()) {
25888
27372
  res.status(400).json({
25889
27373
  error: "Path is not a directory",
@@ -25945,11 +27429,12 @@ function registerWorkspaceManagementRoutes(app, deps) {
25945
27429
  operationStarted();
25946
27430
  try {
25947
27431
  const snapshot = await workspaceRegistrationStore.read();
25948
- const alreadyPersisted = snapshot.workspaces.some(
27432
+ const persistedWorkspaces = snapshot.workspaces.filter(
25949
27433
  (stored) => existingRuntime.registrationIds?.includes(
25950
27434
  workspaceRegistrationId(stored)
25951
27435
  ) === true || (process.platform === "win32" ? stored.toLowerCase() === canonical.toLowerCase() : stored === canonical)
25952
27436
  );
27437
+ const alreadyPersisted = persistedWorkspaces.length > 0;
25953
27438
  if (!alreadyPersisted && snapshot.workspaces.length >= MAX_REGISTERED_WORKSPACES - 1) {
25954
27439
  res.status(409).json({
25955
27440
  error: "Workspace registration limit reached",
@@ -25957,22 +27442,56 @@ function registerWorkspaceManagementRoutes(app, deps) {
25957
27442
  });
25958
27443
  return;
25959
27444
  }
25960
- if (!alreadyPersisted) {
27445
+ if (alreadyPersisted) {
27446
+ attachRegistrationIds(
27447
+ existingRuntime,
27448
+ persistedWorkspaces.map(workspaceRegistrationId)
27449
+ );
27450
+ const storedDisplayName = persistedWorkspaces.map(
27451
+ (stored) => snapshot.displayNames?.[workspaceRegistrationId(stored)]
27452
+ ).find((name) => name !== void 0);
27453
+ if (storedDisplayName === void 0) {
27454
+ delete existingRuntime.displayName;
27455
+ } else {
27456
+ existingRuntime.displayName = storedDisplayName;
27457
+ }
27458
+ } else {
27459
+ let added = false;
25961
27460
  try {
25962
- await workspaceRegistrationStore.add(canonical);
27461
+ const persistedDisplayName = hasDisplayName ? displayName : existingRuntime.displayName;
27462
+ added = persistedDisplayName === void 0 ? await workspaceRegistrationStore.add(canonical) : await workspaceRegistrationStore.add(
27463
+ canonical,
27464
+ persistedDisplayName
27465
+ );
25963
27466
  } catch (err) {
25964
27467
  if (!(err instanceof WorkspaceRegistrationStoreCommittedError)) {
25965
27468
  throw err;
25966
27469
  }
27470
+ added = true;
25967
27471
  try {
25968
27472
  writeStderrLine(`qwen serve: ${err.message}`);
25969
27473
  } catch {
25970
27474
  }
25971
27475
  }
27476
+ if (added) {
27477
+ attachRegistrationIds(existingRuntime, [
27478
+ workspaceRegistrationId(canonical)
27479
+ ]);
27480
+ }
27481
+ if (added && hasDisplayName) {
27482
+ if (displayName === void 0) {
27483
+ delete existingRuntime.displayName;
27484
+ } else {
27485
+ existingRuntime.displayName = displayName;
27486
+ }
27487
+ } else if (!added) {
27488
+ await restorePersistedDisplayName(existingRuntime, canonical);
27489
+ }
25972
27490
  }
25973
27491
  res.status(200).json({
25974
27492
  id: existingRuntime.workspaceId,
25975
27493
  cwd: existingRuntime.workspaceCwd,
27494
+ ...existingRuntime.displayName !== void 0 ? { displayName: existingRuntime.displayName } : {},
25976
27495
  primary: existingRuntime.primary,
25977
27496
  trusted: existingRuntime.trusted,
25978
27497
  persisted: true
@@ -26027,13 +27546,7 @@ function registerWorkspaceManagementRoutes(app, deps) {
26027
27546
  return;
26028
27547
  }
26029
27548
  }
26030
- const projectedWorkspaceCwds = new Set(
26031
- workspaceRegistry.listManaged().map((runtime) => runtime.workspaceCwd)
26032
- );
26033
- for (const [cwd2, operation] of inFlight) {
26034
- if (operation === "addition") projectedWorkspaceCwds.add(cwd2);
26035
- }
26036
- if (projectedWorkspaceCwds.size >= MAX_REGISTERED_WORKSPACES) {
27549
+ if (projectedWorkspaceCount() >= MAX_REGISTERED_WORKSPACES) {
26037
27550
  res.status(409).json({
26038
27551
  error: "Workspace registration limit reached",
26039
27552
  code: "workspace_limit_reached"
@@ -26044,13 +27557,21 @@ function registerWorkspaceManagementRoutes(app, deps) {
26044
27557
  operationStarted();
26045
27558
  let persistenceFailed = false;
26046
27559
  try {
26047
- const runtime = await createWorkspaceRuntime(canonical);
27560
+ const runtime = await createWorkspaceRuntime(canonical, {
27561
+ provenance: "existing"
27562
+ });
27563
+ if (!persist && displayName !== void 0) {
27564
+ runtime.displayName = displayName;
27565
+ }
26048
27566
  let persistedRecordAdded = false;
26049
27567
  try {
26050
27568
  if (persist) {
26051
27569
  try {
26052
27570
  try {
26053
- persistedRecordAdded = await workspaceRegistrationStore.add(canonical);
27571
+ persistedRecordAdded = displayName === void 0 ? await workspaceRegistrationStore.add(canonical) : await workspaceRegistrationStore.add(
27572
+ canonical,
27573
+ displayName
27574
+ );
26054
27575
  } catch (err) {
26055
27576
  if (!(err instanceof WorkspaceRegistrationStoreCommittedError)) {
26056
27577
  throw err;
@@ -26061,6 +27582,16 @@ function registerWorkspaceManagementRoutes(app, deps) {
26061
27582
  } catch {
26062
27583
  }
26063
27584
  }
27585
+ if (persistedRecordAdded) {
27586
+ attachRegistrationIds(runtime, [
27587
+ workspaceRegistrationId(canonical)
27588
+ ]);
27589
+ if (displayName !== void 0) {
27590
+ runtime.displayName = displayName;
27591
+ }
27592
+ } else {
27593
+ await restorePersistedDisplayName(runtime, canonical);
27594
+ }
26064
27595
  } catch (err) {
26065
27596
  persistenceFailed = true;
26066
27597
  throw err;
@@ -26104,6 +27635,7 @@ function registerWorkspaceManagementRoutes(app, deps) {
26104
27635
  res.status(201).json({
26105
27636
  id: runtime.workspaceId,
26106
27637
  cwd: runtime.workspaceCwd,
27638
+ ...runtime.displayName !== void 0 ? { displayName: runtime.displayName } : {},
26107
27639
  primary: runtime.primary,
26108
27640
  trusted: runtime.trusted,
26109
27641
  ...persist ? { persisted: true } : {}
@@ -26171,6 +27703,98 @@ function registerWorkspaceManagementRoutes(app, deps) {
26171
27703
  });
26172
27704
  return void 0;
26173
27705
  }, "resolveManagedRuntime");
27706
+ app.patch(
27707
+ "/workspaces/:workspace",
27708
+ mutate({ strict: true }),
27709
+ async (req, res) => {
27710
+ const body = safeBody2(req);
27711
+ const unsupportedField = Object.keys(body).find(
27712
+ (field) => field !== "displayName"
27713
+ );
27714
+ if (unsupportedField) {
27715
+ res.status(400).json({
27716
+ error: `\`${unsupportedField}\` is not an updatable workspace field`,
27717
+ code: "unsupported_field"
27718
+ });
27719
+ return;
27720
+ }
27721
+ if (!Object.hasOwn(body, "displayName")) {
27722
+ res.status(400).json({
27723
+ error: "No updatable fields provided",
27724
+ code: "empty_patch"
27725
+ });
27726
+ return;
27727
+ }
27728
+ let displayName;
27729
+ try {
27730
+ displayName = body["displayName"] === null ? void 0 : normalizeWorkspaceDisplayName(body["displayName"]);
27731
+ } catch (err) {
27732
+ if (!(err instanceof WorkspaceDisplayNameValidationError)) throw err;
27733
+ res.status(400).json({
27734
+ error: err.message,
27735
+ code: "invalid_display_name"
27736
+ });
27737
+ return;
27738
+ }
27739
+ if (sealed) {
27740
+ sendSealed(res);
27741
+ return;
27742
+ }
27743
+ const runtime = resolveManagedRuntime(req, res);
27744
+ if (!runtime) return;
27745
+ if (inFlight.has(runtime.workspaceCwd)) {
27746
+ res.status(409).json({
27747
+ error: "Workspace registration is in progress",
27748
+ code: "workspace_registration_in_progress"
27749
+ });
27750
+ return;
27751
+ }
27752
+ inFlight.set(runtime.workspaceCwd, "update");
27753
+ operationStarted();
27754
+ try {
27755
+ if (workspaceRegistrationStore && runtime.registrationIds !== void 0 && runtime.registrationIds.length > 0) {
27756
+ try {
27757
+ await workspaceRegistrationStore.setDisplayNameByIds(
27758
+ runtime.registrationIds,
27759
+ displayName
27760
+ );
27761
+ } catch (err) {
27762
+ if (!(err instanceof WorkspaceRegistrationStoreCommittedError)) {
27763
+ throw err;
27764
+ }
27765
+ try {
27766
+ writeStderrLine(`qwen serve: ${err.message}`);
27767
+ } catch {
27768
+ }
27769
+ }
27770
+ }
27771
+ if (displayName === void 0) {
27772
+ delete runtime.displayName;
27773
+ } else {
27774
+ runtime.displayName = displayName;
27775
+ }
27776
+ res.status(200).json({
27777
+ id: runtime.workspaceId,
27778
+ cwd: runtime.workspaceCwd,
27779
+ ...runtime.displayName !== void 0 ? { displayName: runtime.displayName } : {},
27780
+ primary: runtime.primary,
27781
+ trusted: runtime.trusted,
27782
+ ...runtimeRemoval ? { removable: runtime.removable === true } : {}
27783
+ });
27784
+ } catch (err) {
27785
+ writeStderrLine(
27786
+ `qwen serve: failed to persist workspace display name: ${err instanceof Error ? err.message : String(err)}`
27787
+ );
27788
+ res.status(500).json({
27789
+ error: "Failed to persist workspace display name",
27790
+ code: "workspace_registration_store_error"
27791
+ });
27792
+ } finally {
27793
+ inFlight.delete(runtime.workspaceCwd);
27794
+ operationFinished();
27795
+ }
27796
+ }
27797
+ );
26174
27798
  app.delete(
26175
27799
  "/workspaces/:workspace",
26176
27800
  mutate({ strict: true }),
@@ -26406,11 +28030,13 @@ function registerWorkspaceManagementRoutes(app, deps) {
26406
28030
  schemaVersion: snapshot.schemaVersion,
26407
28031
  primaryWorkspace: snapshot.primaryWorkspace,
26408
28032
  entries: snapshot.workspaces.map((cwd) => {
28033
+ const registrationId = workspaceRegistrationId(cwd);
26409
28034
  const runtime = workspaceRegistry.getByWorkspaceCwd(cwd);
26410
28035
  return {
26411
- id: workspaceRegistrationId(cwd),
28036
+ id: registrationId,
26412
28037
  cwd,
26413
- active: runtime !== void 0 || registrationIsActive(workspaceRegistrationId(cwd)),
28038
+ ...snapshot.displayNames?.[registrationId] !== void 0 ? { displayName: snapshot.displayNames[registrationId] } : {},
28039
+ active: runtime !== void 0 || registrationIsActive(registrationId),
26414
28040
  persisted: true
26415
28041
  };
26416
28042
  })
@@ -26468,7 +28094,7 @@ function registerWorkspaceManagementRoutes(app, deps) {
26468
28094
  }
26469
28095
  if (storedCwd) {
26470
28096
  try {
26471
- operationCwd = realpathSync.native(resolve4(storedCwd));
28097
+ operationCwd = realpathSync2.native(resolve4(storedCwd));
26472
28098
  } catch {
26473
28099
  operationCwd = resolve4(storedCwd);
26474
28100
  }
@@ -26508,6 +28134,11 @@ function registerWorkspaceManagementRoutes(app, deps) {
26508
28134
  });
26509
28135
  return;
26510
28136
  }
28137
+ if (runtime?.registrationIds) {
28138
+ runtime.registrationIds = runtime.registrationIds.filter(
28139
+ (id) => id !== registrationId
28140
+ );
28141
+ }
26511
28142
  res.json({
26512
28143
  removed: true,
26513
28144
  active,
@@ -26539,6 +28170,8 @@ __name(registerWorkspaceManagementRoutes, "registerWorkspaceManagementRoutes");
26539
28170
 
26540
28171
  // packages/cli/src/serve/routes/workspace-git.ts
26541
28172
  init_esbuild_shims();
28173
+ import * as fs5 from "node:fs";
28174
+ import * as path14 from "node:path";
26542
28175
  function registerWorkspaceGitRoutes(app, deps) {
26543
28176
  app.get("/workspace/git", async (_req, res) => {
26544
28177
  try {
@@ -26560,10 +28193,43 @@ function registerWorkspaceQualifiedGitRoutes(app, deps) {
26560
28193
  const runtime = resolveTrustedRuntime2(deps.workspaceRegistry, req, res);
26561
28194
  if (!runtime) return;
26562
28195
  const route = "GET /workspaces/:workspace/git";
28196
+ const rawCwd = req.query["cwd"];
28197
+ let gitCwd = runtime.workspaceCwd;
28198
+ if (typeof rawCwd === "string" && rawCwd.length > 0) {
28199
+ try {
28200
+ const resolved = fs5.realpathSync(path14.resolve(rawCwd));
28201
+ const root = fs5.realpathSync(runtime.workspaceCwd);
28202
+ const rel = path14.relative(root, resolved);
28203
+ if (!rel.startsWith("..") && !path14.isAbsolute(rel)) {
28204
+ gitCwd = resolved;
28205
+ }
28206
+ } catch {
28207
+ }
28208
+ }
26563
28209
  try {
26564
- res.status(200).json(
26565
- await deps.gitState.getStatus(runtime.workspaceCwd, runtime.bridge)
26566
- );
28210
+ if (gitCwd !== runtime.workspaceCwd) {
28211
+ const status = await getGitWorkingTreeStatus(gitCwd).catch(() => null);
28212
+ res.status(200).json(
28213
+ status ? {
28214
+ v: 2,
28215
+ workspaceCwd: gitCwd,
28216
+ branch: status.branch ?? null,
28217
+ detached: status.detached,
28218
+ staged: status.staged,
28219
+ unstaged: status.unstaged,
28220
+ untracked: status.untracked,
28221
+ conflicted: status.conflicted,
28222
+ hasUpstream: status.hasUpstream,
28223
+ ahead: status.ahead,
28224
+ behind: status.behind,
28225
+ stashCount: status.stashCount,
28226
+ ...status.operation ? { operation: status.operation } : {},
28227
+ computedAt: Date.now()
28228
+ } : { v: 2, workspaceCwd: gitCwd, branch: null }
28229
+ );
28230
+ } else {
28231
+ res.status(200).json(await deps.gitState.getStatus(gitCwd, runtime.bridge));
28232
+ }
26567
28233
  } catch (err) {
26568
28234
  deps.sendBridgeError(res, err, { route });
26569
28235
  }
@@ -26716,6 +28382,163 @@ function registerWorkspaceQualifiedGitDiffRoutes(app, deps) {
26716
28382
  }
26717
28383
  __name(registerWorkspaceQualifiedGitDiffRoutes, "registerWorkspaceQualifiedGitDiffRoutes");
26718
28384
 
28385
+ // packages/cli/src/serve/routes/workspace-git-log.ts
28386
+ init_esbuild_shims();
28387
+ function buildLogList(workspaceCwd, result) {
28388
+ if (!result) {
28389
+ return {
28390
+ v: 1,
28391
+ workspaceCwd,
28392
+ available: false,
28393
+ entries: [],
28394
+ hasMore: false
28395
+ };
28396
+ }
28397
+ return {
28398
+ v: 1,
28399
+ workspaceCwd,
28400
+ available: true,
28401
+ entries: result.entries.map((e) => ({
28402
+ sha: e.sha,
28403
+ shortSha: e.shortSha,
28404
+ authorName: e.authorName,
28405
+ authorEmail: e.authorEmail,
28406
+ authorDate: e.authorDate,
28407
+ subject: e.subject,
28408
+ ...e.refs ? { refs: e.refs } : {},
28409
+ parents: e.parents
28410
+ })),
28411
+ hasMore: result.hasMore
28412
+ };
28413
+ }
28414
+ __name(buildLogList, "buildLogList");
28415
+ function buildCommitDetail(workspaceCwd, result) {
28416
+ if (!result) {
28417
+ return { v: 1, workspaceCwd, available: false };
28418
+ }
28419
+ return {
28420
+ v: 1,
28421
+ workspaceCwd,
28422
+ available: true,
28423
+ sha: result.sha,
28424
+ shortSha: result.shortSha,
28425
+ authorName: result.authorName,
28426
+ authorEmail: result.authorEmail,
28427
+ authorDate: result.authorDate,
28428
+ subject: result.subject,
28429
+ body: result.body,
28430
+ ...result.refs ? { refs: result.refs } : {},
28431
+ parents: result.parents,
28432
+ files: result.files.map((f) => ({
28433
+ path: f.path,
28434
+ added: f.added,
28435
+ removed: f.removed,
28436
+ isBinary: f.isBinary
28437
+ })),
28438
+ filesCount: result.filesCount,
28439
+ linesAdded: result.linesAdded,
28440
+ linesRemoved: result.linesRemoved,
28441
+ hiddenCount: result.hiddenCount
28442
+ };
28443
+ }
28444
+ __name(buildCommitDetail, "buildCommitDetail");
28445
+ function parsePagination(req) {
28446
+ const rawLimit = req.query["limit"];
28447
+ const rawSkip = req.query["skip"];
28448
+ const parsedLimit = typeof rawLimit === "string" ? parseInt(rawLimit, 10) : NaN;
28449
+ const parsedSkip = typeof rawSkip === "string" ? parseInt(rawSkip, 10) : NaN;
28450
+ const limit = Math.min(
28451
+ Math.max(Number.isNaN(parsedLimit) ? DEFAULT_LOG_LIMIT : parsedLimit, 1),
28452
+ MAX_LOG_LIMIT
28453
+ );
28454
+ const skip = Math.max(Number.isNaN(parsedSkip) ? 0 : parsedSkip, 0);
28455
+ return { limit, skip };
28456
+ }
28457
+ __name(parsePagination, "parsePagination");
28458
+ async function handleLogList(req, res, workspaceCwd, sendBridgeError2, route) {
28459
+ try {
28460
+ applyReadHeaders(res);
28461
+ const { limit, skip } = parsePagination(req);
28462
+ const result = await fetchGitLog(workspaceCwd, { limit, skip });
28463
+ res.status(200).json(buildLogList(workspaceCwd, result));
28464
+ } catch (err) {
28465
+ sendBridgeError2(res, err, { route });
28466
+ }
28467
+ }
28468
+ __name(handleLogList, "handleLogList");
28469
+ async function handleCommitDetail(req, res, workspaceCwd, sendBridgeError2, route) {
28470
+ const sha = req.query["sha"];
28471
+ if (typeof sha !== "string" || sha.length === 0 || !/^[0-9a-f]{7,40}$/i.test(sha)) {
28472
+ applyReadHeaders(res);
28473
+ res.status(400).json({
28474
+ errorKind: "parse_error",
28475
+ error: "sha query parameter is required",
28476
+ status: 400
28477
+ });
28478
+ return;
28479
+ }
28480
+ try {
28481
+ applyReadHeaders(res);
28482
+ const result = await fetchGitCommitDetail(workspaceCwd, sha);
28483
+ res.status(200).json(buildCommitDetail(workspaceCwd, result));
28484
+ } catch (err) {
28485
+ sendBridgeError2(res, err, { route });
28486
+ }
28487
+ }
28488
+ __name(handleCommitDetail, "handleCommitDetail");
28489
+ function registerWorkspaceGitLogRoutes(app, deps) {
28490
+ app.get("/workspace/git/log", (req, res) => {
28491
+ void handleLogList(
28492
+ req,
28493
+ res,
28494
+ deps.boundWorkspace,
28495
+ deps.sendBridgeError,
28496
+ "GET /workspace/git/log"
28497
+ );
28498
+ });
28499
+ app.get("/workspace/git/log/commit", (req, res) => {
28500
+ void handleCommitDetail(
28501
+ req,
28502
+ res,
28503
+ deps.boundWorkspace,
28504
+ deps.sendBridgeError,
28505
+ "GET /workspace/git/log/commit"
28506
+ );
28507
+ });
28508
+ }
28509
+ __name(registerWorkspaceGitLogRoutes, "registerWorkspaceGitLogRoutes");
28510
+ function resolveTrustedRuntime4(registry, req, res) {
28511
+ const runtime = resolveWorkspaceRuntimeFromParam(registry, req, res);
28512
+ if (!runtime) return null;
28513
+ return requireTrustedWorkspaceRuntime(runtime, res) ? runtime : null;
28514
+ }
28515
+ __name(resolveTrustedRuntime4, "resolveTrustedRuntime");
28516
+ function registerWorkspaceQualifiedGitLogRoutes(app, deps) {
28517
+ app.get("/workspaces/:workspace/git/log", (req, res) => {
28518
+ const runtime = resolveTrustedRuntime4(deps.workspaceRegistry, req, res);
28519
+ if (!runtime) return;
28520
+ void handleLogList(
28521
+ req,
28522
+ res,
28523
+ runtime.workspaceCwd,
28524
+ deps.sendBridgeError,
28525
+ "GET /workspaces/:workspace/git/log"
28526
+ );
28527
+ });
28528
+ app.get("/workspaces/:workspace/git/log/commit", (req, res) => {
28529
+ const runtime = resolveTrustedRuntime4(deps.workspaceRegistry, req, res);
28530
+ if (!runtime) return;
28531
+ void handleCommitDetail(
28532
+ req,
28533
+ res,
28534
+ runtime.workspaceCwd,
28535
+ deps.sendBridgeError,
28536
+ "GET /workspaces/:workspace/git/log/commit"
28537
+ );
28538
+ });
28539
+ }
28540
+ __name(registerWorkspaceQualifiedGitLogRoutes, "registerWorkspaceQualifiedGitLogRoutes");
28541
+
26719
28542
  // packages/cli/src/serve/workspace-git-state.ts
26720
28543
  init_esbuild_shims();
26721
28544
  var WorkspaceGitState = class {
@@ -28423,7 +30246,16 @@ function createServeApp(opts, getPort = () => opts.port, deps = {}) {
28423
30246
  }, "channelReloadAvailable"),
28424
30247
  sessionShellCommandEnabled,
28425
30248
  multiWorkspaceSessionsEnabled: /* @__PURE__ */ __name(() => workspaceRegistry.list().length > 1, "multiWorkspaceSessionsEnabled"),
30249
+ dynamicWorkspaceRegistrationAvailable: deps.createWorkspaceRuntime !== void 0,
28426
30250
  persistentWorkspaceRegistrationAvailable: deps.workspaceRegistrationStore !== void 0,
30251
+ // Scratch creation is advertised only while every managed runtime still
30252
+ // respects the root boundary and a complete disposal owner is present.
30253
+ scratchWorkspaceRegistrationAvailable: /* @__PURE__ */ __name(() => deps.createWorkspaceRuntime !== void 0 && deps.managedScratchRoot !== void 0 && deps.workspaceRuntimeRemoval !== void 0 && workspaceRegistry.listManaged().every(
30254
+ (runtime) => isScratchRootCompatible(
30255
+ runtime.workspaceCwd,
30256
+ deps.managedScratchRoot.canonicalRoot
30257
+ )
30258
+ ), "scratchWorkspaceRegistrationAvailable"),
28427
30259
  workspaceRuntimeRemovalAvailable: deps.workspaceRuntimeRemoval !== void 0,
28428
30260
  ...primaryEffectiveEnv ? { env: primaryEffectiveEnv } : {}
28429
30261
  });
@@ -28446,6 +30278,7 @@ function createServeApp(opts, getPort = () => opts.port, deps = {}) {
28446
30278
  maxPendingPromptsPerSession: opts.maxPendingPromptsPerSession,
28447
30279
  eventRingSize: opts.eventRingSize,
28448
30280
  compactedReplayMaxBytes: opts.compactedReplayMaxBytes,
30281
+ initializeTimeoutMs: opts.initializeTimeoutMs,
28449
30282
  permissionResponseTimeoutMs: opts.permissionResponseTimeoutMs,
28450
30283
  boundWorkspace,
28451
30284
  sessionShellCommandEnabled,
@@ -28722,6 +30555,14 @@ function createServeApp(opts, getPort = () => opts.port, deps = {}) {
28722
30555
  workspaceRegistry,
28723
30556
  sendBridgeError: sendBridgeError2
28724
30557
  });
30558
+ registerWorkspaceGitLogRoutes(app, {
30559
+ boundWorkspace: primaryBoundWorkspace,
30560
+ sendBridgeError: sendBridgeError2
30561
+ });
30562
+ registerWorkspaceQualifiedGitLogRoutes(app, {
30563
+ workspaceRegistry,
30564
+ sendBridgeError: sendBridgeError2
30565
+ });
28725
30566
  mountWorkspaceMemoryRoutes(app, {
28726
30567
  bridge: primaryBridge,
28727
30568
  boundWorkspace: primaryBoundWorkspace,
@@ -28821,6 +30662,7 @@ function createServeApp(opts, getPort = () => opts.port, deps = {}) {
28821
30662
  mutate,
28822
30663
  safeBody,
28823
30664
  createWorkspaceRuntime: deps.createWorkspaceRuntime,
30665
+ managedScratchRoot: deps.managedScratchRoot,
28824
30666
  workspaceRegistrationStore: deps.workspaceRegistrationStore,
28825
30667
  getAcpHandle: /* @__PURE__ */ __name(() => acpHandleRef.current, "getAcpHandle"),
28826
30668
  runtimeRemoval: deps.workspaceRuntimeRemoval
@@ -28924,6 +30766,7 @@ function createServeApp(opts, getPort = () => opts.port, deps = {}) {
28924
30766
  allowPrivateAuthBaseUrl: opts.allowPrivateAuthBaseUrl === true,
28925
30767
  installAuthProvider: deps.installAuthProvider
28926
30768
  });
30769
+ const virtualSubagentSessions = new VirtualSubagentSessions();
28927
30770
  registerSessionRoutes(app, {
28928
30771
  boundWorkspace: primaryBoundWorkspace,
28929
30772
  bridge: primaryBridge,
@@ -28934,7 +30777,8 @@ function createServeApp(opts, getPort = () => opts.port, deps = {}) {
28934
30777
  daemonLog,
28935
30778
  promptDeadlineMs: opts.promptDeadlineMs,
28936
30779
  sessionShellCommandEnabled,
28937
- languageCodes
30780
+ languageCodes,
30781
+ virtualSubagentSessions
28938
30782
  });
28939
30783
  registerWorkspaceMcpControlRoutes(app, {
28940
30784
  boundWorkspace: primaryBoundWorkspace,
@@ -29100,7 +30944,8 @@ function createServeApp(opts, getPort = () => opts.port, deps = {}) {
29100
30944
  workspaceRegistry,
29101
30945
  daemonLog,
29102
30946
  writerIdleTimeoutMs: opts.writerIdleTimeoutMs,
29103
- sendBridgeError: sendBridgeError2
30947
+ sendBridgeError: sendBridgeError2,
30948
+ virtualSubagentSessions
29104
30949
  });
29105
30950
  acpHandleRef.current = mountAcpHttp(app, primaryBridge, {
29106
30951
  boundWorkspace: primaryBoundWorkspace,