@qwen-code/qwen-code 0.20.1 → 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 (219) hide show
  1. package/bundled/qc-helper/docs/integration-github-action.md +9 -9
  2. package/chunks/{MaxSizedBox-4WZYPSRU.js → MaxSizedBox-KYNG7EN7.js} +10 -11
  3. package/chunks/{StandaloneSessionPicker-PE4JAIFA.js → StandaloneSessionPicker-7XN4WVVG.js} +25 -26
  4. package/chunks/{acpAgent-BVIKGJ2C.js → acpAgent-FTFFYP5G.js} +121 -80
  5. package/chunks/{agent-DHLFAOUV.js → agent-Y76LTTOT.js} +10 -11
  6. package/chunks/{agent-headless-ZP5WTNXZ.js → agent-headless-IVAEQPK6.js} +10 -11
  7. package/chunks/{anthropicContentGenerator-NMSS7IMV.js → anthropicContentGenerator-HGWAHO24.js} +6 -8
  8. package/chunks/{bridge-XAK7JKMD.js → bridge-4M77KUEV.js} +14 -15
  9. package/chunks/{channel-worker-group-LFBT7K64.js → channel-worker-group-QZV2SP5U.js} +3 -3
  10. package/chunks/{channel-worker-manager-3RUPERG2.js → channel-worker-manager-3GMAU45H.js} +3 -3
  11. package/chunks/{channel-worker-supervisor-A3KVATD3.js → channel-worker-supervisor-QCXSXCRY.js} +2 -2
  12. package/chunks/{chunk-TXRKCFWS.js → chunk-2HGTVAOW.js} +1 -1
  13. package/chunks/{chunk-7LH6CHKG.js → chunk-2P6CNEHB.js} +1 -1
  14. package/chunks/{chunk-CHXKGIMK.js → chunk-3IABAQR6.js} +1 -1
  15. package/chunks/chunk-3Z43GZUQ.js +32 -0
  16. package/chunks/{chunk-KDPIV6WC.js → chunk-4CTP6VR6.js} +1 -1
  17. package/chunks/{chunk-BKZEHVPV.js → chunk-5G3ZVADU.js} +148 -47
  18. package/chunks/{chunk-BZAEENUV.js → chunk-6GEJX3LE.js} +2 -2
  19. package/chunks/{chunk-JHFVJQRO.js → chunk-6HOCJNO5.js} +1 -1
  20. package/chunks/{chunk-5EA5NVXS.js → chunk-A3TAEAHX.js} +1 -1
  21. package/chunks/{chunk-KQQ757OQ.js → chunk-ACW3VNUE.js} +1 -1
  22. package/chunks/{chunk-3SXF4GMQ.js → chunk-AVQ6EX4J.js} +1 -1
  23. package/chunks/{chunk-4DSBFQMI.js → chunk-BK6UOUJ2.js} +2 -2
  24. package/chunks/{chunk-GEB2CGUV.js → chunk-BLAEKN6K.js} +1368 -984
  25. package/chunks/{chunk-M7WBGLYP.js → chunk-BULDBTYC.js} +2 -0
  26. package/chunks/{chunk-PPIHLGNE.js → chunk-C3EXYVFX.js} +1 -1
  27. package/chunks/{chunk-6PRNSLMB.js → chunk-C54UTDOC.js} +16 -17
  28. package/chunks/{chunk-JYS55H6Z.js → chunk-CBOQ3HY7.js} +400 -3
  29. package/chunks/{chunk-LPMBFOWH.js → chunk-CGZ5SV23.js} +33 -33
  30. package/chunks/{chunk-N5ARKAVE.js → chunk-COAARUPK.js} +6 -6
  31. package/chunks/{chunk-JO7FGOSY.js → chunk-E2ZK5M4P.js} +3 -3
  32. package/chunks/{chunk-766HLFAG.js → chunk-EEFRJ5CT.js} +3 -3
  33. package/chunks/{chunk-BWQRDISK.js → chunk-ESQHGKPJ.js} +1 -1
  34. package/chunks/{chunk-X7XWGRDT.js → chunk-FJ2IUWNQ.js} +3 -3
  35. package/chunks/{chunk-G6LRTI62.js → chunk-FQI7LT7T.js} +4 -4
  36. package/chunks/{chunk-Q2V2ADXF.js → chunk-FTNI3D7D.js} +4 -4
  37. package/chunks/{chunk-QD6BRERJ.js → chunk-GHRSKGHF.js} +1 -1
  38. package/chunks/{chunk-7SWFAKVH.js → chunk-GWM4PDYK.js} +10 -10
  39. package/chunks/{chunk-JTUAAVUT.js → chunk-HCJQORKC.js} +2 -2
  40. package/chunks/{chunk-QSJ6JIF5.js → chunk-HDATOR4J.js} +3 -3
  41. package/chunks/{chunk-JIBBZH37.js → chunk-HIYP7IR4.js} +23 -25
  42. package/chunks/{chunk-R3BCL5XW.js → chunk-HL6AKUGD.js} +3 -3
  43. package/chunks/{chunk-Q3GGJDYN.js → chunk-HPQFGWOD.js} +3 -3
  44. package/chunks/{chunk-76OFFG6L.js → chunk-IFUNDCQ6.js} +1 -1
  45. package/chunks/{chunk-KSZZBDVD.js → chunk-IFVECEIK.js} +25 -25
  46. package/chunks/{chunk-JKFHJK5U.js → chunk-IKP54WUL.js} +4 -4
  47. package/chunks/{chunk-27CLX4FV.js → chunk-ISMD2AB3.js} +1 -1
  48. package/chunks/{chunk-3KQSDUK3.js → chunk-KF6CTNTJ.js} +7 -8
  49. package/chunks/{chunk-PIHKWN7M.js → chunk-L5F3T6TQ.js} +1 -1
  50. package/chunks/{chunk-OUDZVU7H.js → chunk-L7ASZD66.js} +7 -5
  51. package/chunks/{chunk-JJEFX6U5.js → chunk-LESHKUWF.js} +2 -4
  52. package/chunks/{chunk-QUHJRRUA.js → chunk-LKB5YL5T.js} +29 -18
  53. package/chunks/{chunk-DPRMI6NU.js → chunk-LU3RXCM7.js} +1 -1
  54. package/chunks/{chunk-EFIOE2EH.js → chunk-M3EQ3GZC.js} +1 -1
  55. package/chunks/{chunk-TPR35HHZ.js → chunk-M4VFMLQK.js} +3 -3
  56. package/chunks/{chunk-6NHK6HS7.js → chunk-MDZTPSXO.js} +1 -1
  57. package/chunks/{chunk-D53NR4GO.js → chunk-MJPBB2GK.js} +66 -52
  58. package/chunks/{chunk-RYSMKY43.js → chunk-NAXEEGJU.js} +4 -4
  59. package/chunks/{chunk-D6ZOVZLF.js → chunk-O4OT3DM3.js} +1 -1
  60. package/chunks/{chunk-PBED7USE.js → chunk-OPDZT2VG.js} +1 -1
  61. package/chunks/{chunk-Y2DAH52F.js → chunk-P6PBZL3N.js} +4 -4
  62. package/chunks/{chunk-AZD6KAV7.js → chunk-PRAUGUNM.js} +3 -3
  63. package/chunks/{chunk-S3YQCNJE.js → chunk-PVT6E3ZI.js} +1 -1
  64. package/chunks/{chunk-4BRH6FP5.js → chunk-Q22WWVR6.js} +4 -4
  65. package/chunks/{chunk-EWXXMRMP.js → chunk-RC7A7SSL.js} +2 -2
  66. package/chunks/{chunk-IS2SBY6T.js → chunk-RCUEYZDE.js} +36 -2
  67. package/chunks/{chunk-R7MPKABX.js → chunk-RMY5SX7S.js} +70 -36
  68. package/chunks/{chunk-SP32MK6J.js → chunk-RTQSXHS7.js} +1 -1
  69. package/chunks/{chunk-PSVSP2OS.js → chunk-S333CBIA.js} +3 -3
  70. package/chunks/{chunk-WML6JOGQ.js → chunk-TA4S377U.js} +5 -7
  71. package/chunks/{chunk-5G2SK2OO.js → chunk-U6TQGUNB.js} +192 -105
  72. package/chunks/{chunk-MTSYH4MB.js → chunk-UKU3NGW6.js} +2 -2
  73. package/chunks/{chunk-3LH5Q2AR.js → chunk-UVFCANV5.js} +4 -4
  74. package/chunks/{chunk-NNFK277W.js → chunk-V4AKJQ26.js} +1 -1
  75. package/chunks/{chunk-EC2ET5ZZ.js → chunk-VJPRLNLR.js} +1 -1
  76. package/chunks/{chunk-7NDXG4MB.js → chunk-VTXX72XS.js} +7 -7
  77. package/chunks/{chunk-LYEKAAEH.js → chunk-WOWQQGGN.js} +3 -3
  78. package/chunks/{chunk-WCFTQD7H.js → chunk-YLSB23Y2.js} +1 -1
  79. package/chunks/{chunk-52T5UHAZ.js → chunk-YNWJAOPL.js} +1 -1
  80. package/chunks/{chunk-DRIXALGM.js → chunk-ZKFJKN23.js} +2 -2
  81. package/chunks/{computer-use-MV4K6WJM.js → computer-use-UKQBH7UM.js} +10 -11
  82. package/chunks/{config-utils-WYUQ7II4.js → config-utils-FYTBZLCJ.js} +1 -1
  83. package/chunks/{contextCommand-TQD36VNX.js → contextCommand-ESHGAVWX.js} +12 -13
  84. package/chunks/{create-sub-session-JOW4BKMC.js → create-sub-session-574EPZUU.js} +10 -11
  85. package/chunks/{daemon-KLPTQIE4.js → daemon-GJRFILYS.js} +185 -18
  86. package/chunks/{daemon-status-provider-TII4SMCZ.js → daemon-status-provider-GZXZP3NU.js} +18 -19
  87. package/chunks/{earlyInputCapture-2V57RG6H.js → earlyInputCapture-GI3HGQIT.js} +10 -11
  88. package/chunks/{edit-TTUH7PWR.js → edit-EBJK74B3.js} +10 -11
  89. package/chunks/{enter-worktree-D4IVCXYB.js → enter-worktree-2ETY5CSV.js} +10 -11
  90. package/chunks/{enterPlanMode-WRUJTVYN.js → enterPlanMode-NY4U2727.js} +10 -11
  91. package/chunks/{environment-SEPKXB2C.js → environment-33IR3NOU.js} +12 -13
  92. package/chunks/{errors-YSVGBLBU.js → errors-2OCY23IC.js} +12 -13
  93. package/chunks/{exit-worktree-MZ4JSSP6.js → exit-worktree-Y4ULJ45U.js} +10 -11
  94. package/chunks/{exitPlanMode-HAZLSSOJ.js → exitPlanMode-SECI2EQ6.js} +10 -11
  95. package/chunks/{fast-path-EVBVIE2U.js → fast-path-6Z7RW5J5.js} +3 -3
  96. package/chunks/{fast-path-settings-XB3CPUJT.js → fast-path-settings-DAOVFADC.js} +2 -2
  97. package/chunks/{gemini-APQ76464.js → gemini-XLGLUGSU.js} +53 -54
  98. package/chunks/{geminiContentGenerator-LB4MA2LI.js → geminiContentGenerator-NNZZDH24.js} +1 -1
  99. package/chunks/{glob-LABYMYKG.js → glob-KZA64SSV.js} +10 -11
  100. package/chunks/{grep-HKIKJCAS.js → grep-ONHQMY3V.js} +10 -11
  101. package/chunks/{handleAutoUpdate-RWAAL2UM.js → handleAutoUpdate-PRTJISXQ.js} +15 -16
  102. package/chunks/{i18n-ZUVDAJIJ.js → i18n-ZTKKG5R5.js} +11 -12
  103. package/chunks/{initializer-7YUHIC36.js → initializer-FPPZGBYN.js} +16 -17
  104. package/chunks/{installationInfo-DVEOMWDE.js → installationInfo-DV2C27HT.js} +11 -12
  105. package/chunks/{list-WHCZSIR2.js → list-KEHCNUAK.js} +19 -20
  106. package/chunks/{loadedSettingsAdapter-YCWN6AK3.js → loadedSettingsAdapter-7RZ6M3WH.js} +16 -17
  107. package/chunks/{managed-npm-update-PG3463CJ.js → managed-npm-update-EBKNOG37.js} +11 -12
  108. package/chunks/{mcp-VLHDCKAN.js → mcp-NHXKZRRP.js} +16 -17
  109. package/chunks/{monitor-GG4F4YM6.js → monitor-FMUAIFFH.js} +10 -11
  110. package/chunks/{nonInteractiveCli-UYXYV4YX.js → nonInteractiveCli-I2GPZNTP.js} +46 -47
  111. package/chunks/{notebook-edit-US4VLN6Q.js → notebook-edit-V7RNXKVL.js} +10 -11
  112. package/chunks/{openaiContentGenerator-CVEDTMDB.js → openaiContentGenerator-IBVUUZDH.js} +7 -8
  113. package/chunks/{pidfile-QQ45OIOY.js → pidfile-AMTGL2H2.js} +10 -11
  114. package/chunks/{processUtils-3WMHLQE5.js → processUtils-3ZT2JF6D.js} +2 -2
  115. package/chunks/{qwenContentGenerator-Y2GRNYZQ.js → qwenContentGenerator-E72VVWS3.js} +15 -16
  116. package/chunks/{qwenOAuth2-J2X6E5VO.js → qwenOAuth2-YCC3HP24.js} +7 -8
  117. package/chunks/{read-file-C7Z266CU.js → read-file-5EWNGUXN.js} +4 -4
  118. package/chunks/{resumeHistoryUtils-KBQWX77U.js → resumeHistoryUtils-IH4RNB76.js} +13 -14
  119. package/chunks/{ripGrep-RW26MTQ3.js → ripGrep-B6A6N7GI.js} +10 -11
  120. package/chunks/{run-qwen-serve-MXFMOMEL.js → run-qwen-serve-6PKSMF6Z.js} +67 -48
  121. package/chunks/{runtime-APNO3V6D.js → runtime-ASRANXO6.js} +18 -19
  122. package/chunks/{scheduler-L6FYCGVO.js → scheduler-IABM76UZ.js} +10 -11
  123. package/chunks/{sdk-exporters-http-IDGLRBGP.js → sdk-exporters-http-6MCQH335.js} +2 -2
  124. package/chunks/{sdk-impl-5ESZBGJQ.js → sdk-impl-HOLWAXC6.js} +9 -2
  125. package/chunks/{send-message-PYIJ2PZL.js → send-message-KBO6X4ZS.js} +1 -1
  126. package/chunks/{serve-6QBXDVWT.js → serve-A4DT5D32.js} +16 -17
  127. package/chunks/{server-5TJJEMVQ.js → server-DZ5ZSVRE.js} +1322 -178
  128. package/chunks/{session-BWEUHKQB.js → session-G2R3CYU6.js} +49 -50
  129. package/chunks/{settings-O7IUQNRR.js → settings-7TNSXUTO.js} +18 -19
  130. package/chunks/{shell-R5L4NQYY.js → shell-5BRFGEMK.js} +10 -11
  131. package/chunks/{skill-ITEOSNW6.js → skill-3SWYEK7M.js} +4 -4
  132. package/chunks/{spawnChannel-E7NTWSGW.js → spawnChannel-GGN2WVWW.js} +12 -13
  133. package/chunks/{src-FFXGUTNL.js → src-5BPBNQ5S.js} +45 -33
  134. package/chunks/{standalone-update-JCJOXW4P.js → standalone-update-AHOZ56LS.js} +13 -14
  135. package/chunks/{startInteractiveUI-IJSBLZFO.js → startInteractiveUI-TLGOQVV7.js} +150 -144
  136. package/chunks/{team-create-OVSZTJZO.js → team-create-XHDF7UKM.js} +10 -11
  137. package/chunks/{team-plan-approval-SLEVDLT5.js → team-plan-approval-XKSBXWMH.js} +10 -11
  138. package/chunks/{theme-manager-V6ZQISHM.js → theme-manager-6ZKLBFAN.js} +10 -11
  139. package/chunks/{tool-search-KYIF6C6E.js → tool-search-UDNJCXYS.js} +4 -4
  140. package/chunks/{total-session-admission-EU77XTL7.js → total-session-admission-VWRCCDYM.js} +14 -15
  141. package/chunks/{tree-sitter-4D7QS7F6.js → tree-sitter-L5BFT64K.js} +1 -1
  142. package/chunks/{tree-sitter-bash-VEJGF5XF.js → tree-sitter-bash-ZKDNQGID.js} +1 -1
  143. package/chunks/{trustedFolders-DDEF3ADH.js → trustedFolders-TJI6OLAN.js} +11 -12
  144. package/chunks/{chunk-5I5BM454.js → undici-3FJYTMOF.js} +24 -399
  145. package/chunks/{chunk-L573Z2QZ.js → undici-PYHBDDPN.js} +1 -5
  146. package/chunks/{update-relaunch-XEZTDP6K.js → update-relaunch-RS5GB74A.js} +5 -5
  147. package/chunks/{updateCheck-KZ5LZ545.js → updateCheck-T4EEA5YR.js} +13 -14
  148. package/chunks/{useAutoAcceptIndicator-47EZERGQ.js → useAutoAcceptIndicator-LLWMXC7F.js} +18 -19
  149. package/chunks/{validateNonInterActiveAuth-J2DM4LWZ.js → validateNonInterActiveAuth-OJ3KYXAR.js} +43 -44
  150. package/chunks/{version-PN7WYXHP.js → version-ZCEUV5DO.js} +1 -1
  151. package/chunks/{web-fetch-WRI5QRFR.js → web-fetch-KQF4YFCI.js} +6 -7
  152. package/chunks/{web-search-2HCXNAVX.js → web-search-QDDGFGKI.js} +13 -12
  153. package/chunks/{workflow-U5XBPGQZ.js → workflow-GIRKCX4P.js} +11 -12
  154. package/chunks/{workspace-providers-status-2T54GIJZ.js → workspace-providers-status-UTMAVTNE.js} +19 -20
  155. package/chunks/{workspace-registration-store-F3V4KBIW.js → workspace-registration-store-EYJMJFZU.js} +1 -1
  156. package/chunks/{workspace-registry-U6QVZ5BU.js → workspace-registry-4W4UW6MY.js} +14 -15
  157. package/chunks/{workspace-service-734D36QD.js → workspace-service-DJCPY6ZN.js} +21 -22
  158. package/chunks/{workspace-skills-status-5ABUKOAQ.js → workspace-skills-status-VQ2LKXXX.js} +17 -18
  159. package/chunks/{write-file-CIH4I4CS.js → write-file-PLK6RQ7M.js} +10 -11
  160. package/cli.js +12 -12
  161. package/package.json +3 -3
  162. package/web-shell/assets/{arc-ByltRugA.js → arc-DIQrcXXh.js} +1 -1
  163. package/web-shell/assets/{architectureDiagram-3BPJPVTR-CCRTto5d.js → architectureDiagram-3BPJPVTR-CbPd-DSw.js} +1 -1
  164. package/web-shell/assets/{blockDiagram-GPEHLZMM-Jfy36u1L.js → blockDiagram-GPEHLZMM-yzBIVhMX.js} +1 -1
  165. package/web-shell/assets/{c4Diagram-AAUBKEIU-4d5FfEZ0.js → c4Diagram-AAUBKEIU-B88Swcsu.js} +1 -1
  166. package/web-shell/assets/channel-BaTMUesZ.js +1 -0
  167. package/web-shell/assets/{chunk-2J33WTMH-BPwxCEro.js → chunk-2J33WTMH-BbOLo6NX.js} +1 -1
  168. package/web-shell/assets/{chunk-4BX2VUAB-jY7ZmJWY.js → chunk-4BX2VUAB-Bg6in0r0.js} +1 -1
  169. package/web-shell/assets/{chunk-55IACEB6-C98HgCsS.js → chunk-55IACEB6-Bv9QRyLI.js} +1 -1
  170. package/web-shell/assets/{chunk-727SXJPM-cDu-ge-q.js → chunk-727SXJPM-CFokiv61.js} +1 -1
  171. package/web-shell/assets/{chunk-AQP2D5EJ-BKdJwxXK.js → chunk-AQP2D5EJ-DS2Oxf6L.js} +1 -1
  172. package/web-shell/assets/{chunk-FMBD7UC4-DnuxqwMu.js → chunk-FMBD7UC4-D2NkHD3B.js} +1 -1
  173. package/web-shell/assets/{chunk-ND2GUHAM-C4fZNPv0.js → chunk-ND2GUHAM-BsT_UC5B.js} +1 -1
  174. package/web-shell/assets/{chunk-QZHKN3VN-Cf4XWOmz.js → chunk-QZHKN3VN-tnJo3zln.js} +1 -1
  175. package/web-shell/assets/classDiagram-4FO5ZUOK-CyBPzWud.js +1 -0
  176. package/web-shell/assets/classDiagram-v2-Q7XG4LA2-CyBPzWud.js +1 -0
  177. package/web-shell/assets/{cose-bilkent-S5V4N54A-C82mFiqj.js → cose-bilkent-S5V4N54A-BTMa6DAZ.js} +1 -1
  178. package/web-shell/assets/{dagre-BM42HDAG-Df8KACER.js → dagre-BM42HDAG-ujGX7Owg.js} +1 -1
  179. package/web-shell/assets/{diagram-2AECGRRQ-EzNs7s_2.js → diagram-2AECGRRQ-fU4-dbPa.js} +1 -1
  180. package/web-shell/assets/{diagram-5GNKFQAL-BRLNvreg.js → diagram-5GNKFQAL-Bdm-TYSA.js} +1 -1
  181. package/web-shell/assets/{diagram-KO2AKTUF-2HLYHRjC.js → diagram-KO2AKTUF-Bkhz85Z9.js} +1 -1
  182. package/web-shell/assets/{diagram-LMA3HP47-DeH0NzSp.js → diagram-LMA3HP47-Bzu3q26p.js} +1 -1
  183. package/web-shell/assets/{diagram-OG6HWLK6-k5Gn47-G.js → diagram-OG6HWLK6-CZrXbG5Q.js} +1 -1
  184. package/web-shell/assets/{erDiagram-TEJ5UH35-gPHFo79f.js → erDiagram-TEJ5UH35-BjozEAYu.js} +1 -1
  185. package/web-shell/assets/{flowDiagram-I6XJVG4X-DYBOiTRW.js → flowDiagram-I6XJVG4X-B3a2I8c-.js} +1 -1
  186. package/web-shell/assets/{ganttDiagram-6RSMTGT7-cxjAuic9.js → ganttDiagram-6RSMTGT7-CIMn9fNm.js} +1 -1
  187. package/web-shell/assets/{gitGraphDiagram-PVQCEYII-3nPqpmCP.js → gitGraphDiagram-PVQCEYII-DlFy9KRx.js} +1 -1
  188. package/web-shell/assets/{index-Cl8d-1bK.js → index-BODUAzQA.js} +1 -1
  189. package/web-shell/assets/index-C54DNMF7.js +1209 -0
  190. package/web-shell/assets/index-lWqBfc78.css +5 -0
  191. package/web-shell/assets/{infoDiagram-5YYISTIA-Dph21pR5.js → infoDiagram-5YYISTIA-BmKjQgCy.js} +1 -1
  192. package/web-shell/assets/{ishikawaDiagram-YF4QCWOH-Cjg1hSaG.js → ishikawaDiagram-YF4QCWOH-BrQEMZz2.js} +1 -1
  193. package/web-shell/assets/{journeyDiagram-JHISSGLW-CR-IzvnU.js → journeyDiagram-JHISSGLW-D-2r7Xrt.js} +1 -1
  194. package/web-shell/assets/{kanban-definition-UN3LZRKU-BYmuybuC.js → kanban-definition-UN3LZRKU-CndsFHCX.js} +1 -1
  195. package/web-shell/assets/{linear-CngEEoy8.js → linear-D-IwNnKx.js} +1 -1
  196. package/web-shell/assets/{mermaid.core-G6fbZRPf.js → mermaid.core-4ll09sri.js} +5 -5
  197. package/web-shell/assets/{mindmap-definition-RKZ34NQL-BtnqnUwJ.js → mindmap-definition-RKZ34NQL-maMRIxjo.js} +1 -1
  198. package/web-shell/assets/{pieDiagram-4H26LBE5-XTq6UHIA.js → pieDiagram-4H26LBE5-aunUDhrJ.js} +1 -1
  199. package/web-shell/assets/{quadrantDiagram-W4KKPZXB-D1J5PrsS.js → quadrantDiagram-W4KKPZXB-D3K0P1NZ.js} +1 -1
  200. package/web-shell/assets/{requirementDiagram-4Y6WPE33-CLcBUy3t.js → requirementDiagram-4Y6WPE33-CX2X9HRc.js} +1 -1
  201. package/web-shell/assets/{sankeyDiagram-5OEKKPKP-iwKV02_6.js → sankeyDiagram-5OEKKPKP-CDroWk7l.js} +1 -1
  202. package/web-shell/assets/{sequenceDiagram-3UESZ5HK-7NFYQcEX.js → sequenceDiagram-3UESZ5HK-DTk-2b16.js} +1 -1
  203. package/web-shell/assets/{stateDiagram-AJRCARHV-Bvm4Wih6.js → stateDiagram-AJRCARHV-Cud64hQr.js} +1 -1
  204. package/web-shell/assets/stateDiagram-v2-BHNVJYJU-g-uUpecT.js +1 -0
  205. package/web-shell/assets/{timeline-definition-PNZ67QCA-B4FZFE9O.js → timeline-definition-PNZ67QCA-DfD5okf_.js} +1 -1
  206. package/web-shell/assets/{vennDiagram-CIIHVFJN-CvMBpmtL.js → vennDiagram-CIIHVFJN-BYl8ay25.js} +1 -1
  207. package/web-shell/assets/{wardley-L42UT6IY-E3ag2327.js → wardley-L42UT6IY-BZFAt10J.js} +1 -1
  208. package/web-shell/assets/{wardleyDiagram-YWT4CUSO-BEXWlgxC.js → wardleyDiagram-YWT4CUSO-BIWn0GA7.js} +1 -1
  209. package/web-shell/assets/{xychartDiagram-2RQKCTM6-CICK05gI.js → xychartDiagram-2RQKCTM6-1_H4xblT.js} +1 -1
  210. package/web-shell/index.html +2 -2
  211. package/web-shell/assets/channel-4N2UIFcG.js +0 -1
  212. package/web-shell/assets/classDiagram-4FO5ZUOK-Q4dYOtsh.js +0 -1
  213. package/web-shell/assets/classDiagram-v2-Q7XG4LA2-Q4dYOtsh.js +0 -1
  214. package/web-shell/assets/index-B7jzUZ_s.css +0 -5
  215. package/web-shell/assets/index-gE8OWwj_.js +0 -1197
  216. package/web-shell/assets/stateDiagram-v2-BHNVJYJU-xXU_zO2Z.js +0 -1
  217. package/chunks/{chunk-D7WXIW7H.js → chunk-H24SOJIQ.js} +3 -3
  218. package/chunks/{chunk-QZJY47IE.js → chunk-PEJWA3QQ.js} +5 -5
  219. package/chunks/{dist-HMU6CYS4.js → dist-XBJVSWS2.js} +1 -1
@@ -14,7 +14,7 @@ import {
14
14
  shouldSuppressRememberErrorDetails,
15
15
  workspaceMemoryFailureCode,
16
16
  workspaceMemoryFailureDiagnostics
17
- } from "./chunk-4DSBFQMI.js";
17
+ } from "./chunk-BK6UOUJ2.js";
18
18
  import {
19
19
  openQwenAsrRealtimeStream,
20
20
  openVoiceStream,
@@ -23,6 +23,7 @@ import {
23
23
  import {
24
24
  SetupGithubError,
25
25
  collectSessionData,
26
+ createTranscriptMessageUpdate,
26
27
  generateExportFilename,
27
28
  normalizeSessionData,
28
29
  setupGithub,
@@ -30,17 +31,21 @@ import {
30
31
  toJson,
31
32
  toJsonl,
32
33
  toMarkdown
33
- } from "./chunk-6PRNSLMB.js";
34
+ } from "./chunk-C54UTDOC.js";
34
35
  import {
35
36
  OBSERVED_CONTACT_MAX_FRESH_WITHIN_SECONDS,
36
37
  ObservedChannelContactStore
37
38
  } from "./chunk-4K7VDKAD.js";
39
+ import "./chunk-V4AKJQ26.js";
38
40
  import "./chunk-RS7MT2QG.js";
39
- import "./chunk-NNFK277W.js";
40
41
  import "./chunk-H2XVO6NE.js";
41
42
  import "./chunk-QHTIBUWB.js";
42
43
  import "./chunk-QTERJVPZ.js";
43
- import "./chunk-L573Z2QZ.js";
44
+ import "./chunk-3Z43GZUQ.js";
45
+ import {
46
+ createSingleWorkspaceRegistry,
47
+ createWorkspaceSessionOwnerIndex
48
+ } from "./chunk-UGYMA4EI.js";
44
49
  import {
45
50
  CAPABILITIES_SCHEMA_VERSION,
46
51
  CLIENT_ID_HEADER,
@@ -65,6 +70,7 @@ import {
65
70
  createBridgeFileSystemAdapter,
66
71
  createBuildWorkspaceCtx,
67
72
  createClientMcpServerProvider,
73
+ createManagedScratchDirectory,
68
74
  createMutationGate,
69
75
  createRateLimiter,
70
76
  denyBrowserOriginCors,
@@ -76,6 +82,7 @@ import {
76
82
  installAccessLogMiddleware,
77
83
  isBrowserAutomationMcpAvailable,
78
84
  isDeepHealthQuery,
85
+ isScratchRootCompatible,
79
86
  parseAllowOriginPatterns,
80
87
  parseAndValidateWorkspaceClientId,
81
88
  parseClientIdHeader,
@@ -96,29 +103,29 @@ import {
96
103
  setRateLimiter,
97
104
  unsafeRevealSecret,
98
105
  validateMcpRuntimeServerName
99
- } from "./chunk-BKZEHVPV.js";
106
+ } from "./chunk-5G3ZVADU.js";
100
107
  import {
101
108
  isLoopbackBind
102
109
  } from "./chunk-RXFQM6FQ.js";
103
110
  import {
104
111
  createDaemonStatusProvider
105
- } from "./chunk-RYSMKY43.js";
112
+ } from "./chunk-NAXEEGJU.js";
106
113
  import "./chunk-LXXMOYPL.js";
107
- import "./chunk-QSJ6JIF5.js";
114
+ import "./chunk-HDATOR4J.js";
108
115
  import "./chunk-E5Z2AVNV.js";
109
116
  import {
110
117
  createWorkspaceProvidersStatusProvider
111
- } from "./chunk-N5ARKAVE.js";
118
+ } from "./chunk-COAARUPK.js";
112
119
  import {
113
120
  getAuthTypeFromEnv,
114
121
  resolveCliGenerationConfig
115
- } from "./chunk-TPR35HHZ.js";
122
+ } from "./chunk-M4VFMLQK.js";
116
123
  import {
117
124
  snapshotProcessEnv
118
- } from "./chunk-DRIXALGM.js";
125
+ } from "./chunk-ZKFJKN23.js";
119
126
  import {
120
127
  createWorkspaceSkillsStatusProvider
121
- } from "./chunk-AZD6KAV7.js";
128
+ } from "./chunk-PRAUGUNM.js";
122
129
  import "./chunk-2W3OOD4W.js";
123
130
  import {
124
131
  EMPTY_WORKSPACE_VOICE_UPDATE_ERROR,
@@ -133,14 +140,14 @@ import {
133
140
  validateWorkspaceSkillName,
134
141
  validateWorkspaceVoiceState,
135
142
  voiceSettingsScopeToWire
136
- } from "./chunk-7NDXG4MB.js";
143
+ } from "./chunk-VTXX72XS.js";
137
144
  import {
138
145
  PermissionRulesValidationError,
139
146
  buildPermissionSettings,
140
147
  isPermissionRuleType,
141
148
  normalizePermissionRules,
142
149
  readPermissionRuleSet
143
- } from "./chunk-5EA5NVXS.js";
150
+ } from "./chunk-A3TAEAHX.js";
144
151
  import {
145
152
  assertVoiceBaseUrlNetworkAllowed,
146
153
  isStreamingVoiceModel,
@@ -148,12 +155,12 @@ import {
148
155
  resolveVoiceTranscriptionConfig,
149
156
  sanitizeVoiceErrorMessage,
150
157
  transcribeVoiceAudio
151
- } from "./chunk-EFIOE2EH.js";
158
+ } from "./chunk-M3EQ3GZC.js";
152
159
  import {
153
160
  isVoiceEnabled,
154
161
  isVoiceMode,
155
162
  readVoiceModel
156
- } from "./chunk-3SXF4GMQ.js";
163
+ } from "./chunk-AVQ6EX4J.js";
157
164
  import "./chunk-QLJUC7TG.js";
158
165
  import {
159
166
  WorkspacePermissionRulesSessionRequiredError,
@@ -164,30 +171,16 @@ import {
164
171
  import {
165
172
  createTotalSessionAdmissionController
166
173
  } from "./chunk-VYPFXUCB.js";
167
- import {
168
- createSingleWorkspaceRegistry,
169
- createWorkspaceSessionOwnerIndex
170
- } from "./chunk-UGYMA4EI.js";
171
174
  import "./chunk-GRC5HGPI.js";
172
- import {
173
- daemonObservedContactsPath,
174
- loadChannelsConfig
175
- } from "./chunk-4BRH6FP5.js";
176
- import "./chunk-G6LRTI62.js";
177
- import "./chunk-57OAHC2Y.js";
178
- import {
179
- parseChannelWebhookConfigLenient
180
- } from "./chunk-QD6BRERJ.js";
181
- import "./chunk-6ZBPS62S.js";
182
- import "./chunk-V6WHFGST.js";
183
175
  import {
184
176
  SessionArtifactAuthorizationError,
185
177
  SessionArtifactValidationError,
186
178
  createAcpSessionBridge,
187
179
  parseSessionSource
188
- } from "./chunk-R7MPKABX.js";
180
+ } from "./chunk-RMY5SX7S.js";
189
181
  import {
190
182
  EVENT_SCHEMA_VERSION,
183
+ EventBus,
191
184
  SubscriberLimitExceededError
192
185
  } from "./chunk-6RLROE6G.js";
193
186
  import "./chunk-COH43MRJ.js";
@@ -225,12 +218,38 @@ import {
225
218
  WorkspaceInitSymlinkError,
226
219
  WorkspaceMismatchError
227
220
  } from "./chunk-UH3WSE5L.js";
228
- import "./chunk-JHFVJQRO.js";
221
+ import "./chunk-WBL3FJEU.js";
222
+ import {
223
+ daemonObservedContactsPath,
224
+ loadChannelsConfig
225
+ } from "./chunk-Q22WWVR6.js";
226
+ import "./chunk-FQI7LT7T.js";
227
+ import "./chunk-57OAHC2Y.js";
228
+ import {
229
+ parseChannelWebhookConfigLenient
230
+ } from "./chunk-GHRSKGHF.js";
231
+ import "./chunk-6ZBPS62S.js";
232
+ import "./chunk-V6WHFGST.js";
233
+ import "./chunk-6HOCJNO5.js";
229
234
  import {
230
235
  STATUS_SCHEMA_VERSION,
231
236
  createIdleWorkspaceMemoryStatus,
232
237
  mapDomainErrorToErrorKind
233
- } from "./chunk-BWQRDISK.js";
238
+ } from "./chunk-ESQHGKPJ.js";
239
+ import {
240
+ MAX_REGISTERED_WORKSPACES,
241
+ WorkspaceDisplayNameValidationError,
242
+ WorkspaceRegistrationStoreCommittedError,
243
+ WorkspaceRegistrationStoreLimitError,
244
+ normalizeWorkspaceDisplayName,
245
+ workspaceRegistrationId
246
+ } from "./chunk-IFUNDCQ6.js";
247
+ import {
248
+ MAX_WORKSPACE_PATH_LENGTH,
249
+ canonicalizeWorkspace,
250
+ canonicalizeWorkspaces,
251
+ translateAndCheckAbsoluteWorkspacePath
252
+ } from "./chunk-2RFKHEXL.js";
234
253
  import {
235
254
  MAX_CHANNEL_STARTUP_FAILURES,
236
255
  MAX_CHANNEL_STARTUP_FAILURE_CHANNEL_LENGTH,
@@ -246,7 +265,7 @@ import {
246
265
  import {
247
266
  redactLogCredentials
248
267
  } from "./chunk-M5GB774H.js";
249
- import "./chunk-WBL3FJEU.js";
268
+ import "./chunk-5HBA2Z7V.js";
250
269
  import "./chunk-T2NCM2ET.js";
251
270
  import {
252
271
  sanitizeLogText
@@ -261,38 +280,23 @@ import {
261
280
  getWritableScopes,
262
281
  loadSettings,
263
282
  validateSettingValue
264
- } from "./chunk-7SWFAKVH.js";
283
+ } from "./chunk-GWM4PDYK.js";
265
284
  import "./chunk-RKUWKYED.js";
266
285
  import {
267
286
  SUPPORTED_LANGUAGES,
268
287
  detectSystemLanguage,
269
288
  resolveLanguageSetting,
270
289
  resolveSupportedLanguage
271
- } from "./chunk-WCFTQD7H.js";
272
- import "./chunk-52T5UHAZ.js";
290
+ } from "./chunk-YLSB23Y2.js";
291
+ import "./chunk-YNWJAOPL.js";
273
292
  import "./chunk-GOXKNSDZ.js";
274
- import "./chunk-QRUIS3DN.js";
275
- import {
276
- MAX_REGISTERED_WORKSPACES,
277
- WorkspaceDisplayNameValidationError,
278
- WorkspaceRegistrationStoreCommittedError,
279
- WorkspaceRegistrationStoreLimitError,
280
- normalizeWorkspaceDisplayName,
281
- workspaceRegistrationId
282
- } from "./chunk-76OFFG6L.js";
283
- import {
284
- MAX_WORKSPACE_PATH_LENGTH,
285
- canonicalizeWorkspace,
286
- canonicalizeWorkspaces,
287
- translateAndCheckAbsoluteWorkspacePath
288
- } from "./chunk-2RFKHEXL.js";
289
- import "./chunk-5HBA2Z7V.js";
290
293
  import "./chunk-IDS7MSUP.js";
291
- import "./chunk-27CLX4FV.js";
294
+ import "./chunk-QRUIS3DN.js";
295
+ import "./chunk-ISMD2AB3.js";
292
296
  import "./chunk-VJNBRRZG.js";
293
297
  import {
294
298
  getWorkspaceTrustStatus
295
- } from "./chunk-S3YQCNJE.js";
299
+ } from "./chunk-PVT6E3ZI.js";
296
300
  import "./chunk-ALGGS7UH.js";
297
301
  import {
298
302
  isWithinRoot as isWithinRoot2
@@ -343,10 +347,12 @@ import {
343
347
  fetchGitDiffHunksForFile,
344
348
  fetchGitLog,
345
349
  getGitWorkingTreeStatus,
350
+ getSubagentSessionDir,
346
351
  glob,
347
352
  loadIgnoreRules,
348
353
  loadUsageHistoryWithLive,
349
354
  parseInstallSource,
355
+ readAgentMeta,
350
356
  readWorktreeSession,
351
357
  redactUrlCredentials,
352
358
  resolveBranchName,
@@ -358,7 +364,7 @@ import {
358
364
  writeWorkspaceContextFile,
359
365
  writeWorktreeSession,
360
366
  writeWorktreeSessionMarker
361
- } from "./chunk-GEB2CGUV.js";
367
+ } from "./chunk-BLAEKN6K.js";
362
368
  import "./chunk-T4TZQJ7W.js";
363
369
  import "./chunk-H6XPXXMH.js";
364
370
  import "./chunk-5M6IDOMF.js";
@@ -366,6 +372,7 @@ import "./chunk-T2L47JJK.js";
366
372
  import "./chunk-GPSKDNEE.js";
367
373
  import "./chunk-X6N25LXS.js";
368
374
  import "./chunk-E2UVIFI2.js";
375
+ import "./chunk-L5F3T6TQ.js";
369
376
  import {
370
377
  MAX_JOBS,
371
378
  nextDurableFireMs
@@ -385,7 +392,6 @@ import {
385
392
  } from "./chunk-KHOVYUHX.js";
386
393
  import "./chunk-SZRN75WQ.js";
387
394
  import "./chunk-6PVPNMXU.js";
388
- import "./chunk-PIHKWN7M.js";
389
395
  import "./chunk-CPBF7KYF.js";
390
396
  import "./chunk-NABLFI57.js";
391
397
  import "./chunk-QBUDF33N.js";
@@ -399,10 +405,6 @@ import "./chunk-6AM5D4ME.js";
399
405
  import "./chunk-JCW2R7WC.js";
400
406
  import "./chunk-57FIIFJN.js";
401
407
  import "./chunk-HTO4JFDZ.js";
402
- import "./chunk-XVNQMZ2I.js";
403
- import "./chunk-CR3C7WXL.js";
404
- import "./chunk-FODK6UMO.js";
405
- import "./chunk-GLNBDYUX.js";
406
408
  import {
407
409
  QwenOAuth2Client,
408
410
  QwenOAuthPollError,
@@ -411,12 +413,15 @@ import {
411
413
  isDeviceAuthorizationSuccess,
412
414
  isDeviceTokenPending,
413
415
  isDeviceTokenSuccess
414
- } from "./chunk-TXRKCFWS.js";
416
+ } from "./chunk-2HGTVAOW.js";
415
417
  import "./chunk-JESCGQM3.js";
416
- import "./chunk-EWXXMRMP.js";
417
- import "./chunk-PPIHLGNE.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";
418
424
  import "./chunk-DJ2GSRLV.js";
419
- import "./chunk-5I5BM454.js";
420
425
  import {
421
426
  addDaemonRequestAttribute,
422
427
  decodeBufferWithEncodingInfo,
@@ -425,15 +430,17 @@ import {
425
430
  hashDaemonWorkspace,
426
431
  isBinaryFile,
427
432
  isWithinRoot,
433
+ parseLineTolerant,
434
+ read,
428
435
  recordDaemonBridgeError,
429
436
  recordDaemonError,
430
437
  recordDaemonHttpRequest,
431
438
  recordDaemonHttpResponse,
432
439
  withDaemonRequestSpan
433
- } from "./chunk-5G2SK2OO.js";
440
+ } from "./chunk-U6TQGUNB.js";
434
441
  import "./chunk-VGC4I5JJ.js";
435
442
  import "./chunk-4K56OJFJ.js";
436
- import "./chunk-JYS55H6Z.js";
443
+ import "./chunk-CBOQ3HY7.js";
437
444
  import "./chunk-A4UCTEB5.js";
438
445
  import "./chunk-XWRJCPHC.js";
439
446
  import "./chunk-QNLNLENL.js";
@@ -443,9 +450,9 @@ import {
443
450
  import_websocket_server
444
451
  } from "./chunk-TYAMGABM.js";
445
452
  import "./chunk-FCMNKVXT.js";
446
- import "./chunk-IS2SBY6T.js";
453
+ import "./chunk-RCUEYZDE.js";
447
454
  import "./chunk-HTR4WV6U.js";
448
- import "./chunk-M7WBGLYP.js";
455
+ import "./chunk-BULDBTYC.js";
449
456
  import "./chunk-U7ZFW55U.js";
450
457
  import "./chunk-NPQDJGKU.js";
451
458
  import "./chunk-YM3SZTH4.js";
@@ -650,9 +657,9 @@ async function findExistingAncestor(absolute) {
650
657
  let current = absolute;
651
658
  const tailParts = [];
652
659
  for (let i = 0; i < MAX_ANCESTOR_HOPS; i++) {
653
- let stat2 = null;
660
+ let stat3 = null;
654
661
  try {
655
- stat2 = await fsp.stat(current);
662
+ stat3 = await fsp.stat(current);
656
663
  } catch (err) {
657
664
  const code = err?.code;
658
665
  if (code === "ENOENT" || code === "ENOTDIR") {
@@ -660,8 +667,8 @@ async function findExistingAncestor(absolute) {
660
667
  throw err;
661
668
  }
662
669
  }
663
- if (stat2) {
664
- if (tailParts.length > 0 && !stat2.isDirectory()) {
670
+ if (stat3) {
671
+ if (tailParts.length > 0 && !stat3.isDirectory()) {
665
672
  throw new FsError(
666
673
  "parse_error",
667
674
  `path component is not a directory: ${absolute}`,
@@ -734,7 +741,7 @@ async function resolveWithinWorkspace(input, boundWorkspaces, intent) {
734
741
  boundCanonicals
735
742
  );
736
743
  if (boundCanonical !== void 0) {
737
- 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) => {
738
745
  if (lstatErr.code === "ENOENT" || lstatErr.code === "ENOTDIR") {
739
746
  return false;
740
747
  }
@@ -1225,8 +1232,8 @@ var WorkspaceFileSystemImpl = class {
1225
1232
  const toRead = Math.min(maxBytes, available);
1226
1233
  buf = Buffer.allocUnsafe(toRead);
1227
1234
  if (toRead > 0) {
1228
- const read = await fh.read(buf, 0, toRead, offset);
1229
- 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);
1230
1237
  }
1231
1238
  const afterRead = await fh.stat();
1232
1239
  assertSameFile(st, afterRead, p, "read");
@@ -1767,17 +1774,17 @@ var WorkspaceFileSystemImpl = class {
1767
1774
  * for their `sendFsError` serializer.
1768
1775
  */
1769
1776
  recordAndWrap(err, intent, input) {
1770
- const fs5 = wrapAsFsError(err);
1777
+ const fs6 = wrapAsFsError(err);
1771
1778
  this.deps.audit.recordDenied(this.deps.ctx, {
1772
1779
  intent,
1773
1780
  input,
1774
- errorKind: fs5.kind,
1775
- hint: fs5.hint,
1781
+ errorKind: fs6.kind,
1782
+ hint: fs6.hint,
1776
1783
  // Quote the underlying OS / FsError message so audit
1777
1784
  // consumers debugging a production incident can see the
1778
1785
  // actual cause (errno text, byte counts, glob pattern,
1779
1786
  // etc.) rather than just `errorKind` + `hint`.
1780
- message: fs5.message,
1787
+ message: fs6.message,
1781
1788
  // For glob denials (parse_error pattern rejection,
1782
1789
  // catastrophic walk failures) the input IS the pattern
1783
1790
  // already; surfacing it on the dedicated `pattern` field
@@ -1786,7 +1793,7 @@ var WorkspaceFileSystemImpl = class {
1786
1793
  // branching on intent.
1787
1794
  pattern: intent === "glob" ? input : void 0
1788
1795
  });
1789
- return fs5;
1796
+ return fs6;
1790
1797
  }
1791
1798
  };
1792
1799
  var CONTENT_HASH_RE = /^sha256:[0-9a-f]{64}$/;
@@ -1894,9 +1901,9 @@ async function readStableRegularFileBuffer(p, pre) {
1894
1901
  const out = Buffer.alloc(opened.size);
1895
1902
  let offset = 0;
1896
1903
  while (offset < opened.size) {
1897
- const read = await fh.read(out, offset, opened.size - offset, offset);
1898
- if (read.bytesRead === 0) break;
1899
- 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;
1900
1907
  }
1901
1908
  const afterRead = await fh.stat();
1902
1909
  assertSameFile(opened, afterRead, p, "read");
@@ -2151,15 +2158,15 @@ async function hashRegularFileAtPath(p, pre) {
2151
2158
  const buf = Buffer.allocUnsafe(64 * 1024);
2152
2159
  let offset = 0;
2153
2160
  while (offset < opened.size) {
2154
- const read = await fh.read(
2161
+ const read2 = await fh.read(
2155
2162
  buf,
2156
2163
  0,
2157
2164
  Math.min(buf.length, opened.size - offset),
2158
2165
  offset
2159
2166
  );
2160
- if (read.bytesRead === 0) break;
2161
- hash.update(buf.subarray(0, read.bytesRead));
2162
- offset += read.bytesRead;
2167
+ if (read2.bytesRead === 0) break;
2168
+ hash.update(buf.subarray(0, read2.bytesRead));
2169
+ offset += read2.bytesRead;
2163
2170
  }
2164
2171
  } finally {
2165
2172
  await fh.close();
@@ -2523,12 +2530,12 @@ __name(applyReadHeaders, "applyReadHeaders");
2523
2530
  function sendFsError(res, err, route) {
2524
2531
  applyReadHeaders(res);
2525
2532
  if (isFsError(err)) {
2526
- const fs5 = err;
2527
- res.status(fs5.status).json({
2528
- errorKind: fs5.kind,
2529
- error: fs5.message,
2530
- hint: fs5.hint,
2531
- status: fs5.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
2532
2539
  });
2533
2540
  return;
2534
2541
  }
@@ -2630,13 +2637,13 @@ async function handleGetFile(req, res, deps) {
2630
2637
  });
2631
2638
  return;
2632
2639
  }
2633
- const fs5 = factory.forRequest({
2640
+ const fs6 = factory.forRequest({
2634
2641
  originatorClientId: clientId ?? void 0,
2635
2642
  route: ROUTE2
2636
2643
  });
2637
2644
  try {
2638
- const resolved = await fs5.resolve(queryPath, "read");
2639
- const out = await fs5.readText(resolved, { maxBytes, line, limit });
2645
+ const resolved = await fs6.resolve(queryPath, "read");
2646
+ const out = await fs6.readText(resolved, { maxBytes, line, limit });
2640
2647
  const returnedBytes = Buffer.byteLength(out.content, "utf-8");
2641
2648
  applyReadHeaders(res);
2642
2649
  res.status(200).json({
@@ -2690,13 +2697,13 @@ async function handleGetFileBytes(req, res, deps) {
2690
2697
  });
2691
2698
  return;
2692
2699
  }
2693
- const fs5 = factory.forRequest({
2700
+ const fs6 = factory.forRequest({
2694
2701
  originatorClientId: clientId ?? void 0,
2695
2702
  route: ROUTE2
2696
2703
  });
2697
2704
  try {
2698
- const resolved = await fs5.resolve(queryPath, "read");
2699
- const out = await fs5.readBytesWindow(resolved, {
2705
+ const resolved = await fs6.resolve(queryPath, "read");
2706
+ const out = await fs6.readBytesWindow(resolved, {
2700
2707
  offset: offset ?? 0,
2701
2708
  maxBytes: maxBytes ?? DEFAULT_FILE_BYTES_MAX_BYTES
2702
2709
  });
@@ -2724,13 +2731,13 @@ async function handleGetStat(req, res, deps) {
2724
2731
  if (clientId === null) return;
2725
2732
  const queryPath = requireStringQuery(res, req.query["path"], "path", ROUTE2);
2726
2733
  if (queryPath === null) return;
2727
- const fs5 = factory.forRequest({
2734
+ const fs6 = factory.forRequest({
2728
2735
  originatorClientId: clientId ?? void 0,
2729
2736
  route: ROUTE2
2730
2737
  });
2731
2738
  try {
2732
- const resolved = await fs5.resolve(queryPath, "stat");
2733
- const st = await fs5.stat(resolved);
2739
+ const resolved = await fs6.resolve(queryPath, "stat");
2740
+ const st = await fs6.stat(resolved);
2734
2741
  applyReadHeaders(res);
2735
2742
  res.status(200).json({
2736
2743
  kind: "stat",
@@ -2753,13 +2760,13 @@ async function handleGetList(req, res, deps) {
2753
2760
  const queryPath = requireStringQuery(res, req.query["path"], "path", ROUTE2);
2754
2761
  if (queryPath === null) return;
2755
2762
  const includeIgnored = parseBoolFlag(req.query["includeIgnored"]);
2756
- const fs5 = factory.forRequest({
2763
+ const fs6 = factory.forRequest({
2757
2764
  originatorClientId: clientId ?? void 0,
2758
2765
  route: ROUTE2
2759
2766
  });
2760
2767
  try {
2761
- const resolved = await fs5.resolve(queryPath, "list");
2762
- const entries = await fs5.list(resolved, {
2768
+ const resolved = await fs6.resolve(queryPath, "list");
2769
+ const entries = await fs6.list(resolved, {
2763
2770
  includeIgnored,
2764
2771
  maxEntries: MAX_LIST_ENTRIES + 1
2765
2772
  });
@@ -2812,15 +2819,15 @@ async function handleGetGlob(req, res, deps) {
2812
2819
  }
2813
2820
  const cwdRaw = req.query["cwd"];
2814
2821
  const cwdString = typeof cwdRaw === "string" && cwdRaw.length > 0 ? cwdRaw : void 0;
2815
- const fs5 = factory.forRequest({
2822
+ const fs6 = factory.forRequest({
2816
2823
  originatorClientId: clientId ?? void 0,
2817
2824
  route: ROUTE2
2818
2825
  });
2819
2826
  const start = performance.now();
2820
2827
  try {
2821
- const cwdResolved = cwdString ? await fs5.resolve(cwdString, "list") : void 0;
2828
+ const cwdResolved = cwdString ? await fs6.resolve(cwdString, "list") : void 0;
2822
2829
  const cap = maxResults ?? DEFAULT_GLOB_MAX_RESULTS;
2823
- const probe = await fs5.glob(pattern, {
2830
+ const probe = await fs6.glob(pattern, {
2824
2831
  cwd: cwdResolved,
2825
2832
  includeIgnored,
2826
2833
  maxResults: cap + 1
@@ -2994,7 +3001,7 @@ function validateClientId(clientId, deps, res) {
2994
3001
  }
2995
3002
  __name(validateClientId, "validateClientId");
2996
3003
  function createSetupGithubFileOps(factory, route, originatorClientId) {
2997
- const fs5 = factory.forRequest({
3004
+ const fs6 = factory.forRequest({
2998
3005
  route,
2999
3006
  ...originatorClientId ? { originatorClientId } : {}
3000
3007
  });
@@ -3017,14 +3024,14 @@ function createSetupGithubFileOps(factory, route, originatorClientId) {
3017
3024
  ]);
3018
3025
  },
3019
3026
  async writeTextFile(_gitRepoRoot, relativePath, content) {
3020
- const resolved = await fs5.resolve(relativePath, "write");
3021
- const out = await fs5.writeTextOverwrite(resolved, content);
3027
+ const resolved = await fs6.resolve(relativePath, "write");
3028
+ const out = await fs6.writeTextOverwrite(resolved, content);
3022
3029
  return { sizeBytes: out.sizeBytes };
3023
3030
  },
3024
3031
  async readTextFile(_gitRepoRoot, relativePath) {
3025
3032
  try {
3026
- const resolved = await fs5.resolve(relativePath, "read");
3027
- const out = await fs5.readText(resolved);
3033
+ const resolved = await fs6.resolve(relativePath, "read");
3034
+ const out = await fs6.readText(resolved);
3028
3035
  return out.content;
3029
3036
  } catch (error2) {
3030
3037
  if (isFsError(error2) && error2.kind === "path_not_found") {
@@ -3045,15 +3052,15 @@ async function ensureDirectoryWithoutSymlink(root, segments) {
3045
3052
  checkedSegments.push(segment);
3046
3053
  const label = `Workspace path "${checkedSegments.join("/")}"`;
3047
3054
  try {
3048
- const stat2 = await fsp3.lstat(current);
3049
- if (stat2.isSymbolicLink()) {
3055
+ const stat3 = await fsp3.lstat(current);
3056
+ if (stat3.isSymbolicLink()) {
3050
3057
  throw new SetupGithubError(
3051
3058
  "github_setup_invalid_workspace",
3052
3059
  `${label} must not be a symlink.`,
3053
3060
  400
3054
3061
  );
3055
3062
  }
3056
- if (!stat2.isDirectory()) {
3063
+ if (!stat3.isDirectory()) {
3057
3064
  throw new SetupGithubError(
3058
3065
  "github_setup_invalid_workspace",
3059
3066
  `${label} must be a directory.`,
@@ -3090,15 +3097,15 @@ async function ensureDirectoryWithoutSymlink(root, segments) {
3090
3097
  }
3091
3098
  __name(ensureDirectoryWithoutSymlink, "ensureDirectoryWithoutSymlink");
3092
3099
  async function assertDirectoryWithoutSymlink(target, label) {
3093
- const stat2 = await fsp3.lstat(target);
3094
- if (stat2.isSymbolicLink()) {
3100
+ const stat3 = await fsp3.lstat(target);
3101
+ if (stat3.isSymbolicLink()) {
3095
3102
  throw new SetupGithubError(
3096
3103
  "github_setup_invalid_workspace",
3097
3104
  `${label} must not be a symlink.`,
3098
3105
  400
3099
3106
  );
3100
3107
  }
3101
- if (!stat2.isDirectory()) {
3108
+ if (!stat3.isDirectory()) {
3102
3109
  throw new SetupGithubError(
3103
3110
  "github_setup_invalid_workspace",
3104
3111
  `${label} must be a directory.`,
@@ -4739,12 +4746,12 @@ async function collectWorkspaceMemoryStatus(boundWorkspace) {
4739
4746
  for (const filename of filenames) {
4740
4747
  const candidate = path8.join(globalDir, filename);
4741
4748
  try {
4742
- const stat2 = await fs.stat(candidate);
4743
- if (stat2.isFile()) {
4749
+ const stat3 = await fs.stat(candidate);
4750
+ if (stat3.isFile()) {
4744
4751
  files.push({
4745
4752
  absolutePath: candidate,
4746
4753
  scope: "global",
4747
- bytes: stat2.size
4754
+ bytes: stat3.size
4748
4755
  });
4749
4756
  }
4750
4757
  } catch (err) {
@@ -4788,12 +4795,12 @@ async function walkWorkspaceForMemory(start, filenames, errors) {
4788
4795
  for (const filename of filenames) {
4789
4796
  const candidate = path8.join(start, filename);
4790
4797
  try {
4791
- const stat2 = await fs.stat(candidate);
4792
- if (stat2.isFile()) {
4798
+ const stat3 = await fs.stat(candidate);
4799
+ if (stat3.isFile()) {
4793
4800
  out.push({
4794
4801
  absolutePath: candidate,
4795
4802
  scope: "workspace",
4796
- bytes: stat2.size
4803
+ bytes: stat3.size
4797
4804
  });
4798
4805
  }
4799
4806
  } catch (err) {
@@ -9045,7 +9052,7 @@ var AcpDispatcher = class {
9045
9052
  );
9046
9053
  return;
9047
9054
  }
9048
- const fs5 = this.fsFactory.forRequest({
9055
+ const fs6 = this.fsFactory.forRequest({
9049
9056
  originatorClientId: conn.clientId,
9050
9057
  route: `ACP ${method}`
9051
9058
  });
@@ -9097,8 +9104,8 @@ var AcpDispatcher = class {
9097
9104
  );
9098
9105
  return;
9099
9106
  }
9100
- const resolved = await fs5.resolve(p, "read");
9101
- const out = await fs5.readText(resolved, { maxBytes, line, limit });
9107
+ const resolved = await fs6.resolve(p, "read");
9108
+ const out = await fs6.readText(resolved, { maxBytes, line, limit });
9102
9109
  this.replyConn(conn, id, {
9103
9110
  path: p,
9104
9111
  content: out.content,
@@ -9120,7 +9127,7 @@ var AcpDispatcher = class {
9120
9127
  conn.sendConn(error(id, RPC.INVALID_PARAMS, "`path` required"));
9121
9128
  return;
9122
9129
  }
9123
- const fs5 = this.fsFactory.forRequest({
9130
+ const fs6 = this.fsFactory.forRequest({
9124
9131
  originatorClientId: conn.clientId,
9125
9132
  route: `ACP ${method}`
9126
9133
  });
@@ -9156,8 +9163,8 @@ var AcpDispatcher = class {
9156
9163
  );
9157
9164
  return;
9158
9165
  }
9159
- const resolved = await fs5.resolve(p, "read");
9160
- const buf = await fs5.readBytesWindow(resolved, { offset, maxBytes });
9166
+ const resolved = await fs6.resolve(p, "read");
9167
+ const buf = await fs6.readBytesWindow(resolved, { offset, maxBytes });
9161
9168
  this.replyConn(conn, id, { path: p, ...buf });
9162
9169
  return;
9163
9170
  }
@@ -9175,12 +9182,12 @@ var AcpDispatcher = class {
9175
9182
  conn.sendConn(error(id, RPC.INVALID_PARAMS, "`path` required"));
9176
9183
  return;
9177
9184
  }
9178
- const fs5 = this.fsFactory.forRequest({
9185
+ const fs6 = this.fsFactory.forRequest({
9179
9186
  originatorClientId: conn.clientId,
9180
9187
  route: `ACP ${method}`
9181
9188
  });
9182
- const resolved = await fs5.resolve(p, "read");
9183
- const result = await fs5.stat(resolved);
9189
+ const resolved = await fs6.resolve(p, "read");
9190
+ const result = await fs6.stat(resolved);
9184
9191
  this.replyConn(conn, id, { path: p, ...result });
9185
9192
  return;
9186
9193
  }
@@ -9198,13 +9205,13 @@ var AcpDispatcher = class {
9198
9205
  conn.sendConn(error(id, RPC.INVALID_PARAMS, "`path` required"));
9199
9206
  return;
9200
9207
  }
9201
- const fs5 = this.fsFactory.forRequest({
9208
+ const fs6 = this.fsFactory.forRequest({
9202
9209
  originatorClientId: conn.clientId,
9203
9210
  route: `ACP ${method}`
9204
9211
  });
9205
- const resolved = await fs5.resolve(p, "read");
9212
+ const resolved = await fs6.resolve(p, "read");
9206
9213
  const MAX_LIST = 2e3;
9207
- const entries = await fs5.list(resolved, { maxEntries: MAX_LIST + 1 });
9214
+ const entries = await fs6.list(resolved, { maxEntries: MAX_LIST + 1 });
9208
9215
  const truncated = entries.length > MAX_LIST;
9209
9216
  this.replyConn(conn, id, {
9210
9217
  path: p,
@@ -9229,7 +9236,7 @@ var AcpDispatcher = class {
9229
9236
  );
9230
9237
  return;
9231
9238
  }
9232
- const fs5 = this.fsFactory.forRequest({
9239
+ const fs6 = this.fsFactory.forRequest({
9233
9240
  originatorClientId: conn.clientId,
9234
9241
  route: `ACP ${method}`
9235
9242
  });
@@ -9249,7 +9256,7 @@ var AcpDispatcher = class {
9249
9256
  );
9250
9257
  return;
9251
9258
  }
9252
- const matches = await fs5.glob(pattern, {
9259
+ const matches = await fs6.glob(pattern, {
9253
9260
  maxResults: maxResults + 1
9254
9261
  });
9255
9262
  const truncated = matches.length > maxResults;
@@ -9281,11 +9288,11 @@ var AcpDispatcher = class {
9281
9288
  );
9282
9289
  return;
9283
9290
  }
9284
- const fs5 = this.fsFactory.forRequest({
9291
+ const fs6 = this.fsFactory.forRequest({
9285
9292
  originatorClientId: conn.clientId,
9286
9293
  route: `ACP ${method}`
9287
9294
  });
9288
- const resolved = await fs5.resolve(p, "write");
9295
+ const resolved = await fs6.resolve(p, "write");
9289
9296
  if (Buffer.byteLength(params["content"], "utf8") > 10 * 1024 * 1024) {
9290
9297
  if (id !== void 0)
9291
9298
  conn.sendConn(
@@ -9293,7 +9300,7 @@ var AcpDispatcher = class {
9293
9300
  );
9294
9301
  return;
9295
9302
  }
9296
- await fs5.writeTextOverwrite(resolved, params["content"]);
9303
+ await fs6.writeTextOverwrite(resolved, params["content"]);
9297
9304
  this.replyConn(conn, id, { ok: true, path: p });
9298
9305
  return;
9299
9306
  }
@@ -9322,12 +9329,12 @@ var AcpDispatcher = class {
9322
9329
  );
9323
9330
  return;
9324
9331
  }
9325
- const fs5 = this.fsFactory.forRequest({
9332
+ const fs6 = this.fsFactory.forRequest({
9326
9333
  originatorClientId: conn.clientId,
9327
9334
  route: `ACP ${method}`
9328
9335
  });
9329
- const resolved = await fs5.resolve(p, "write");
9330
- const result = await fs5.edit(
9336
+ const resolved = await fs6.resolve(p, "write");
9337
+ const result = await fs6.edit(
9331
9338
  resolved,
9332
9339
  params["oldText"],
9333
9340
  params["newText"]
@@ -17518,13 +17525,13 @@ async function handlePostFileWrite(req, res, deps) {
17518
17525
  req
17519
17526
  );
17520
17527
  if (originatorClientId === null) return;
17521
- const fs5 = factory.forRequest({
17528
+ const fs6 = factory.forRequest({
17522
17529
  originatorClientId,
17523
17530
  route: ROUTE2
17524
17531
  });
17525
17532
  try {
17526
- const resolved = await fs5.resolve(queryPath, "write");
17527
- const out = await fs5.writeTextAtomic(resolved, content, {
17533
+ const resolved = await fs6.resolve(queryPath, "write");
17534
+ const out = await fs6.writeTextAtomic(resolved, content, {
17528
17535
  mode,
17529
17536
  ...expectedHash ? { expectedHash } : {},
17530
17537
  ...bom !== void 0 ? { bom } : {},
@@ -17577,13 +17584,13 @@ async function handlePostFileEdit(req, res, deps) {
17577
17584
  req
17578
17585
  );
17579
17586
  if (originatorClientId === null) return;
17580
- const fs5 = factory.forRequest({
17587
+ const fs6 = factory.forRequest({
17581
17588
  originatorClientId,
17582
17589
  route: ROUTE2
17583
17590
  });
17584
17591
  try {
17585
- const resolved = await fs5.resolve(queryPath, "edit");
17586
- const out = await fs5.editAtomic(resolved, oldText, newText, {
17592
+ const resolved = await fs6.resolve(queryPath, "edit");
17593
+ const out = await fs6.editAtomic(resolved, oldText, newText, {
17587
17594
  expectedHash
17588
17595
  });
17589
17596
  applyReadHeaders(res);
@@ -17911,6 +17918,18 @@ var legacySessionTelemetryRoutes = [
17911
17918
  attribution: "handler_resolved",
17912
17919
  route: "GET /session/:id/tasks"
17913
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
+ },
17914
17933
  {
17915
17934
  method: "GET",
17916
17935
  path: "/session/:id/lsp",
@@ -18593,7 +18612,7 @@ __name(registerPermissionRoutes, "registerPermissionRoutes");
18593
18612
  // packages/cli/src/serve/routes/session.ts
18594
18613
  init_esbuild_shims();
18595
18614
  import * as crypto3 from "node:crypto";
18596
- import * as fs3 from "node:fs";
18615
+ import * as fs4 from "node:fs";
18597
18616
  import * as path10 from "node:path";
18598
18617
 
18599
18618
  // packages/cli/src/serve/server/prompt-deadline.ts
@@ -19199,6 +19218,714 @@ async function exportSessionTranscript(params) {
19199
19218
  }
19200
19219
  __name(exportSessionTranscript, "exportSessionTranscript");
19201
19220
 
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
+ };
19293
+ }
19294
+ __name(findToolCallMetrics, "findToolCallMetrics");
19295
+ function encodePart(value) {
19296
+ return Buffer.from(value, "utf8").toString("base64url");
19297
+ }
19298
+ __name(encodePart, "encodePart");
19299
+ function decodePart(value) {
19300
+ try {
19301
+ return Buffer.from(value, "base64url").toString("utf8");
19302
+ } catch {
19303
+ return void 0;
19304
+ }
19305
+ }
19306
+ __name(decodePart, "decodePart");
19307
+ function isValidVirtualSessionPart(value) {
19308
+ return /^[a-zA-Z0-9_-]{1,500}$/.test(value);
19309
+ }
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)}`;
19316
+ }
19317
+ __name(createVirtualSubagentSessionId, "createVirtualSubagentSessionId");
19318
+ function parseVirtualSubagentSessionId(sessionId) {
19319
+ if (!sessionId.startsWith(PREFIX) || sessionId.length > 2e3) {
19320
+ return void 0;
19321
+ }
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 {
19334
+ v: 1,
19335
+ sessionId,
19336
+ fileIdentity: { dev: 0, ino: 0 },
19337
+ snapshotSize: position,
19338
+ position,
19339
+ leafUuid,
19340
+ startTime,
19341
+ lastUpdated
19342
+ };
19343
+ }
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;
19352
+ }
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
+ }
19446
+ }
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
+
19202
19929
  // packages/cli/src/serve/routes/session.ts
19203
19930
  var WORKSPACE_TRANSCRIPT_RESPONSE_MAX_BYTES = 32 * 1024 * 1024;
19204
19931
  var WORKSPACE_TRANSCRIPT_CURSOR_MAX_BYTES = 64 * 1024;
@@ -19261,8 +19988,8 @@ function isReadOnlyWorkspaceInspection(runtime) {
19261
19988
  return !runtime.primary && !runtime.trusted;
19262
19989
  }
19263
19990
  __name(isReadOnlyWorkspaceInspection, "isReadOnlyWorkspaceInspection");
19264
- function runWorkspaceInspectionWithLogPolicy(runtime, read) {
19265
- return isReadOnlyWorkspaceInspection(runtime) ? runWithoutDebugLogSession(read) : read();
19991
+ function runWorkspaceInspectionWithLogPolicy(runtime, read2) {
19992
+ return isReadOnlyWorkspaceInspection(runtime) ? runWithoutDebugLogSession(read2) : read2();
19266
19993
  }
19267
19994
  __name(runWorkspaceInspectionWithLogPolicy, "runWorkspaceInspectionWithLogPolicy");
19268
19995
  function requireSessionArtifactClientId(clientId, res) {
@@ -19425,7 +20152,8 @@ function registerSessionRoutes(app, deps) {
19425
20152
  sendBridgeError: sendBridgeError2,
19426
20153
  daemonLog,
19427
20154
  promptDeadlineMs,
19428
- sessionShellCommandEnabled
20155
+ sessionShellCommandEnabled,
20156
+ virtualSubagentSessions
19429
20157
  } = deps;
19430
20158
  const LANGUAGE_CODES = deps.languageCodes;
19431
20159
  const transcriptCursorMasterKey = crypto3.randomBytes(32);
@@ -20194,6 +20922,55 @@ function registerSessionRoutes(app, deps) {
20194
20922
  const restoreSessionHandler = /* @__PURE__ */ __name((action) => async (req, res) => {
20195
20923
  const sessionId = requireSessionId(req, res);
20196
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
+ }
20197
20974
  const body = safeBody(req);
20198
20975
  const route = `POST /session/:id/${action}`;
20199
20976
  let resolvedRuntime;
@@ -20283,7 +21060,7 @@ function registerSessionRoutes(app, deps) {
20283
21060
  path10.join(workspaceCwd, ".qwen", "worktrees")
20284
21061
  ];
20285
21062
  try {
20286
- realTarget = fs3.realpathSync(sidecar.worktreePath);
21063
+ realTarget = fs4.realpathSync(sidecar.worktreePath);
20287
21064
  let repoTop = null;
20288
21065
  try {
20289
21066
  repoTop = await new GitWorktreeService(
@@ -20296,7 +21073,7 @@ function registerSessionRoutes(app, deps) {
20296
21073
  }
20297
21074
  const contained = candidateRoots.some((root) => {
20298
21075
  try {
20299
- const realRoot = fs3.realpathSync(root);
21076
+ const realRoot = fs4.realpathSync(root);
20300
21077
  const rel = path10.relative(realRoot, realTarget);
20301
21078
  return !rel.startsWith("..") && !path10.isAbsolute(rel);
20302
21079
  } catch {
@@ -20351,6 +21128,112 @@ function registerSessionRoutes(app, deps) {
20351
21128
  }, "restoreSessionHandler");
20352
21129
  app.post("/session/:id/load", mutate(), restoreSessionHandler("load"));
20353
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
+ );
20354
21237
  app.post(
20355
21238
  "/session/:id/branch",
20356
21239
  mutate(),
@@ -20650,6 +21533,28 @@ function registerSessionRoutes(app, deps) {
20650
21533
  });
20651
21534
  app.get(
20652
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
+ },
20653
21558
  withOwnerReadSession(
20654
21559
  "GET /session/:id/context",
20655
21560
  async (_req, res, sessionId, runtime) => {
@@ -20681,6 +21586,28 @@ function registerSessionRoutes(app, deps) {
20681
21586
  );
20682
21587
  app.get(
20683
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
+ },
20684
21611
  withOwnerReadSession(
20685
21612
  "GET /session/:id/supported-commands",
20686
21613
  async (_req, res, sessionId, runtime) => {
@@ -21077,6 +22004,29 @@ function registerSessionRoutes(app, deps) {
21077
22004
  app.post(
21078
22005
  "/session/:id/heartbeat",
21079
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
+ },
21080
22030
  withOwnerMutableSession(
21081
22031
  "POST /session/:id/heartbeat",
21082
22032
  (req, res, sessionId, runtime) => {
@@ -21093,6 +22043,25 @@ function registerSessionRoutes(app, deps) {
21093
22043
  app.post(
21094
22044
  "/session/:id/detach",
21095
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
+ },
21096
22065
  withOwnerMutableSession(
21097
22066
  "POST /session/:id/detach",
21098
22067
  async (req, res, sessionId, runtime) => {
@@ -23481,7 +24450,9 @@ function createServeFeatures(deps) {
23481
24450
  channelControlAvailable,
23482
24451
  sessionShellCommandEnabled,
23483
24452
  multiWorkspaceSessionsEnabled,
24453
+ dynamicWorkspaceRegistrationAvailable,
23484
24454
  persistentWorkspaceRegistrationAvailable,
24455
+ scratchWorkspaceRegistrationAvailable,
23485
24456
  workspaceRuntimeRemovalAvailable
23486
24457
  } = deps;
23487
24458
  const env = deps.env ?? process.env;
@@ -23515,7 +24486,9 @@ function createServeFeatures(deps) {
23515
24486
  channelReloadAvailable: channelReloadAvailable(),
23516
24487
  channelControlAvailable,
23517
24488
  multiWorkspaceSessionsEnabled: multiWorkspaceSessionsEnabled(),
24489
+ dynamicWorkspaceRegistrationAvailable,
23518
24490
  persistentWorkspaceRegistrationAvailable,
24491
+ scratchWorkspaceRegistrationAvailable: scratchWorkspaceRegistrationAvailable(),
23519
24492
  workspaceRuntimeRemovalAvailable,
23520
24493
  acpHttpEnabled: resolveAcpHttpEnabled(),
23521
24494
  clientMcpOverWsEnabled: opts.clientMcpOverWs === true,
@@ -24853,7 +25826,7 @@ data: ${dataJson}
24853
25826
  __name(formatSseFrame, "formatSseFrame");
24854
25827
  function registerSseEventsRoutes(app, deps) {
24855
25828
  const { workspaceRegistry, daemonLog, sendBridgeError: sendBridgeError2, writerIdleTimeoutMs } = deps;
24856
- app.get("/session/:id/events", (req, res) => {
25829
+ app.get("/session/:id/events", async (req, res) => {
24857
25830
  const sessionId = req.params["id"];
24858
25831
  const lastEventId = parseLastEventId(req.headers["last-event-id"]);
24859
25832
  const maxQueued = parseMaxQueuedQuery(req.query["maxQueued"], res);
@@ -24861,8 +25834,9 @@ function registerSseEventsRoutes(app, deps) {
24861
25834
  let iter;
24862
25835
  const abort = new AbortController();
24863
25836
  try {
25837
+ const virtualKey = parseVirtualSubagentSessionId(sessionId);
24864
25838
  const runtime = requireSessionRuntime({
24865
- sessionId,
25839
+ sessionId: virtualKey?.parentSessionId ?? sessionId,
24866
25840
  route: "GET /session/:id/events",
24867
25841
  res,
24868
25842
  workspaceRegistry,
@@ -24870,12 +25844,24 @@ function registerSseEventsRoutes(app, deps) {
24870
25844
  });
24871
25845
  if (!runtime) return;
24872
25846
  const snapshot = req.query["snapshot"] === "1";
24873
- 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, {
24874
25852
  signal: abort.signal,
24875
25853
  lastEventId,
24876
25854
  ...maxQueued !== void 0 ? { maxQueued } : {},
24877
25855
  ...snapshot ? { snapshot: true } : {}
24878
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
+ }
24879
25865
  iter = iterable[Symbol.asyncIterator]();
24880
25866
  } catch (err) {
24881
25867
  if (err instanceof SubscriberLimitExceededError) {
@@ -26029,7 +27015,7 @@ __name(registerWorkspaceQualifiedLifecycleRoutes, "registerWorkspaceQualifiedLif
26029
27015
 
26030
27016
  // packages/cli/src/serve/routes/workspace-management.ts
26031
27017
  init_esbuild_shims();
26032
- import { readdir, stat } from "node:fs/promises";
27018
+ import { readdir as readdir2, stat as stat2 } from "node:fs/promises";
26033
27019
  import { realpathSync as realpathSync2 } from "node:fs";
26034
27020
  import { basename as basename4, dirname as dirname4, isAbsolute as isAbsolute7, join as join8, resolve as resolve4, sep as sep3 } from "node:path";
26035
27021
  var MAX_PATH_SUGGESTIONS = 50;
@@ -26039,6 +27025,7 @@ function registerWorkspaceManagementRoutes(app, deps) {
26039
27025
  mutate,
26040
27026
  safeBody: safeBody2,
26041
27027
  createWorkspaceRuntime,
27028
+ managedScratchRoot,
26042
27029
  workspaceRegistrationStore,
26043
27030
  getAcpHandle,
26044
27031
  runtimeRemoval
@@ -26046,6 +27033,7 @@ function registerWorkspaceManagementRoutes(app, deps) {
26046
27033
  const inFlight = /* @__PURE__ */ new Map();
26047
27034
  let sealed = false;
26048
27035
  let activeOperations = 0;
27036
+ let pendingScratchCreations = 0;
26049
27037
  const idleWaiters = /* @__PURE__ */ new Set();
26050
27038
  const operationStarted = /* @__PURE__ */ __name(() => {
26051
27039
  activeOperations++;
@@ -26087,6 +27075,135 @@ function registerWorkspaceManagementRoutes(app, deps) {
26087
27075
  runtime.displayName = storedDisplayName;
26088
27076
  }
26089
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");
26090
27207
  app.get(
26091
27208
  "/workspace-path-suggestions",
26092
27209
  async (req, res) => {
@@ -26120,7 +27237,7 @@ function registerWorkspaceManagementRoutes(app, deps) {
26120
27237
  const suggestions = [];
26121
27238
  let truncated = false;
26122
27239
  try {
26123
- const entries = await readdir(dir, { withFileTypes: true });
27240
+ const entries = await readdir2(dir, { withFileTypes: true });
26124
27241
  entries.sort((a, b) => a.name.localeCompare(b.name));
26125
27242
  for (const entry of entries) {
26126
27243
  if (entry.name.startsWith(".") && !filter.startsWith(".")) continue;
@@ -26130,7 +27247,7 @@ function registerWorkspaceManagementRoutes(app, deps) {
26130
27247
  let isDir = entry.isDirectory();
26131
27248
  if (!isDir && entry.isSymbolicLink()) {
26132
27249
  try {
26133
- isDir = (await stat(join8(dir, entry.name))).isDirectory();
27250
+ isDir = (await stat2(join8(dir, entry.name))).isDirectory();
26134
27251
  } catch {
26135
27252
  continue;
26136
27253
  }
@@ -26158,6 +27275,17 @@ function registerWorkspaceManagementRoutes(app, deps) {
26158
27275
  mutate({ strict: true }),
26159
27276
  async (req, res) => {
26160
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
+ }
26161
27289
  const cwd = body["cwd"];
26162
27290
  const persist = body["persist"] ?? false;
26163
27291
  const hasDisplayName = Object.hasOwn(body, "displayName");
@@ -26227,12 +27355,19 @@ function registerWorkspaceManagementRoutes(app, deps) {
26227
27355
  });
26228
27356
  return;
26229
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
+ }
26230
27365
  if (sealed) {
26231
27366
  sendSealed(res);
26232
27367
  return;
26233
27368
  }
26234
27369
  try {
26235
- const s = await stat(canonical);
27370
+ const s = await stat2(canonical);
26236
27371
  if (!s.isDirectory()) {
26237
27372
  res.status(400).json({
26238
27373
  error: "Path is not a directory",
@@ -26411,13 +27546,7 @@ function registerWorkspaceManagementRoutes(app, deps) {
26411
27546
  return;
26412
27547
  }
26413
27548
  }
26414
- const projectedWorkspaceCwds = new Set(
26415
- workspaceRegistry.listManaged().map((runtime) => runtime.workspaceCwd)
26416
- );
26417
- for (const [cwd2, operation] of inFlight) {
26418
- if (operation === "addition") projectedWorkspaceCwds.add(cwd2);
26419
- }
26420
- if (projectedWorkspaceCwds.size >= MAX_REGISTERED_WORKSPACES) {
27549
+ if (projectedWorkspaceCount() >= MAX_REGISTERED_WORKSPACES) {
26421
27550
  res.status(409).json({
26422
27551
  error: "Workspace registration limit reached",
26423
27552
  code: "workspace_limit_reached"
@@ -26428,7 +27557,9 @@ function registerWorkspaceManagementRoutes(app, deps) {
26428
27557
  operationStarted();
26429
27558
  let persistenceFailed = false;
26430
27559
  try {
26431
- const runtime = await createWorkspaceRuntime(canonical);
27560
+ const runtime = await createWorkspaceRuntime(canonical, {
27561
+ provenance: "existing"
27562
+ });
26432
27563
  if (!persist && displayName !== void 0) {
26433
27564
  runtime.displayName = displayName;
26434
27565
  }
@@ -27039,7 +28170,7 @@ __name(registerWorkspaceManagementRoutes, "registerWorkspaceManagementRoutes");
27039
28170
 
27040
28171
  // packages/cli/src/serve/routes/workspace-git.ts
27041
28172
  init_esbuild_shims();
27042
- import * as fs4 from "node:fs";
28173
+ import * as fs5 from "node:fs";
27043
28174
  import * as path14 from "node:path";
27044
28175
  function registerWorkspaceGitRoutes(app, deps) {
27045
28176
  app.get("/workspace/git", async (_req, res) => {
@@ -27066,8 +28197,8 @@ function registerWorkspaceQualifiedGitRoutes(app, deps) {
27066
28197
  let gitCwd = runtime.workspaceCwd;
27067
28198
  if (typeof rawCwd === "string" && rawCwd.length > 0) {
27068
28199
  try {
27069
- const resolved = fs4.realpathSync(path14.resolve(rawCwd));
27070
- const root = fs4.realpathSync(runtime.workspaceCwd);
28200
+ const resolved = fs5.realpathSync(path14.resolve(rawCwd));
28201
+ const root = fs5.realpathSync(runtime.workspaceCwd);
27071
28202
  const rel = path14.relative(root, resolved);
27072
28203
  if (!rel.startsWith("..") && !path14.isAbsolute(rel)) {
27073
28204
  gitCwd = resolved;
@@ -29115,7 +30246,16 @@ function createServeApp(opts, getPort = () => opts.port, deps = {}) {
29115
30246
  }, "channelReloadAvailable"),
29116
30247
  sessionShellCommandEnabled,
29117
30248
  multiWorkspaceSessionsEnabled: /* @__PURE__ */ __name(() => workspaceRegistry.list().length > 1, "multiWorkspaceSessionsEnabled"),
30249
+ dynamicWorkspaceRegistrationAvailable: deps.createWorkspaceRuntime !== void 0,
29118
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"),
29119
30259
  workspaceRuntimeRemovalAvailable: deps.workspaceRuntimeRemoval !== void 0,
29120
30260
  ...primaryEffectiveEnv ? { env: primaryEffectiveEnv } : {}
29121
30261
  });
@@ -29522,6 +30662,7 @@ function createServeApp(opts, getPort = () => opts.port, deps = {}) {
29522
30662
  mutate,
29523
30663
  safeBody,
29524
30664
  createWorkspaceRuntime: deps.createWorkspaceRuntime,
30665
+ managedScratchRoot: deps.managedScratchRoot,
29525
30666
  workspaceRegistrationStore: deps.workspaceRegistrationStore,
29526
30667
  getAcpHandle: /* @__PURE__ */ __name(() => acpHandleRef.current, "getAcpHandle"),
29527
30668
  runtimeRemoval: deps.workspaceRuntimeRemoval
@@ -29625,6 +30766,7 @@ function createServeApp(opts, getPort = () => opts.port, deps = {}) {
29625
30766
  allowPrivateAuthBaseUrl: opts.allowPrivateAuthBaseUrl === true,
29626
30767
  installAuthProvider: deps.installAuthProvider
29627
30768
  });
30769
+ const virtualSubagentSessions = new VirtualSubagentSessions();
29628
30770
  registerSessionRoutes(app, {
29629
30771
  boundWorkspace: primaryBoundWorkspace,
29630
30772
  bridge: primaryBridge,
@@ -29635,7 +30777,8 @@ function createServeApp(opts, getPort = () => opts.port, deps = {}) {
29635
30777
  daemonLog,
29636
30778
  promptDeadlineMs: opts.promptDeadlineMs,
29637
30779
  sessionShellCommandEnabled,
29638
- languageCodes
30780
+ languageCodes,
30781
+ virtualSubagentSessions
29639
30782
  });
29640
30783
  registerWorkspaceMcpControlRoutes(app, {
29641
30784
  boundWorkspace: primaryBoundWorkspace,
@@ -29801,7 +30944,8 @@ function createServeApp(opts, getPort = () => opts.port, deps = {}) {
29801
30944
  workspaceRegistry,
29802
30945
  daemonLog,
29803
30946
  writerIdleTimeoutMs: opts.writerIdleTimeoutMs,
29804
- sendBridgeError: sendBridgeError2
30947
+ sendBridgeError: sendBridgeError2,
30948
+ virtualSubagentSessions
29805
30949
  });
29806
30950
  acpHandleRef.current = mountAcpHttp(app, primaryBridge, {
29807
30951
  boundWorkspace: primaryBoundWorkspace,