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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (327) hide show
  1. package/bundled/qc-helper/docs/configuration/settings.md +1 -1
  2. package/bundled/qc-helper/docs/features/auto-mode.md +19 -16
  3. package/bundled/qc-helper/docs/features/commands.md +54 -0
  4. package/bundled/qc-helper/docs/features/sub-agents.md +16 -7
  5. package/bundled/qc-helper/docs/integration-github-action.md +1 -1
  6. package/bundled/qc-helper/docs/qwen-serve.md +2 -1
  7. package/bundled/review/DESIGN.md +2 -2
  8. package/bundled/review/SKILL.md +4 -4
  9. package/chunks/{MaxSizedBox-EH6G5AEH.js → MaxSizedBox-KYNG7EN7.js} +38 -35
  10. package/chunks/{StandaloneSessionPicker-264A3TEA.js → StandaloneSessionPicker-7XN4WVVG.js} +55 -52
  11. package/chunks/{acpAgent-6RBIJFDI.js → acpAgent-FTFFYP5G.js} +1536 -512
  12. package/chunks/{agent-QURXGAA3.js → agent-Y76LTTOT.js} +34 -31
  13. package/chunks/{agent-headless-CRGX4ICQ.js → agent-headless-IVAEQPK6.js} +34 -31
  14. package/chunks/{anthropicContentGenerator-BWBAZGTW.js → anthropicContentGenerator-HGWAHO24.js} +11 -13
  15. package/chunks/{artifact-tool-IUJ7QWCX.js → artifact-tool-56T5IMBP.js} +3 -3
  16. package/chunks/{askUserQuestion-IUMUUTDQ.js → askUserQuestion-E25OBIC2.js} +3 -3
  17. package/chunks/{bridge-MNFVKPMI.js → bridge-4M77KUEV.js} +39 -36
  18. package/chunks/{build-SSCNEHZZ.js → build-GHIZ4MSZ.js} +1 -1
  19. package/chunks/{ca-2SL2BXTK.js → ca-N6VVUFVB.js} +611 -201
  20. package/chunks/{channel-worker-group-53CMOPFT.js → channel-worker-group-QZV2SP5U.js} +4 -4
  21. package/chunks/{channel-worker-manager-UTXILKC2.js → channel-worker-manager-3GMAU45H.js} +4 -4
  22. package/chunks/{channel-worker-supervisor-ZGO2W2MD.js → channel-worker-supervisor-QCXSXCRY.js} +3 -3
  23. package/chunks/{chunk-UQES76OO.js → chunk-2HGTVAOW.js} +6 -6
  24. package/chunks/{chunk-2HOVDT7W.js → chunk-2LI23QA6.js} +1 -1
  25. package/chunks/{chunk-ANHT55MR.js → chunk-2P6CNEHB.js} +1 -1
  26. package/chunks/chunk-2RFKHEXL.js +74 -0
  27. package/chunks/{chunk-BF32GYSY.js → chunk-3IABAQR6.js} +1 -1
  28. package/chunks/chunk-3Z43GZUQ.js +32 -0
  29. package/chunks/chunk-43T5WDQ7.js +127 -0
  30. package/chunks/{chunk-DA7OOKVN.js → chunk-4CTP6VR6.js} +29 -2
  31. package/chunks/{chunk-JD3MKVKL.js → chunk-4K56OJFJ.js} +1 -1
  32. package/chunks/{chunk-KTUQMDEP.js → chunk-4K7VDKAD.js} +1 -1
  33. package/chunks/{chunk-QKYTTBYW.js → chunk-4LVZNIDO.js} +1 -1
  34. package/chunks/{chunk-ZEOZL37W.js → chunk-57FIIFJN.js} +1 -1
  35. package/chunks/{chunk-7YBZGNEC.js → chunk-5G3ZVADU.js} +308 -199
  36. package/chunks/{chunk-X4CGDBKA.js → chunk-6GEJX3LE.js} +3 -3
  37. package/chunks/{chunk-6GUTHAN7.js → chunk-6HOCJNO5.js} +1 -1
  38. package/chunks/{chunk-GMGDLUC7.js → chunk-6IL7KRLE.js} +1 -1
  39. package/chunks/chunk-6PVPNMXU.js +29 -0
  40. package/chunks/{chunk-BDBMYST4.js → chunk-6X4GWOPW.js} +1 -1
  41. package/chunks/{chunk-4ODB7WIB.js → chunk-6ZBPS62S.js} +1 -1
  42. package/chunks/{chunk-AYCDXHZB.js → chunk-7Z6JQEL6.js} +1 -1
  43. package/chunks/{chunk-WAX3ITOA.js → chunk-A3TAEAHX.js} +1 -1
  44. package/chunks/{chunk-OLMETXLX.js → chunk-ACW3VNUE.js} +2 -2
  45. package/chunks/{chunk-IB35C3IL.js → chunk-AVQ6EX4J.js} +1 -1
  46. package/chunks/{chunk-TTSKHF43.js → chunk-BK6UOUJ2.js} +2 -2
  47. package/chunks/{chunk-6OH6A5EX.js → chunk-BLAEKN6K.js} +20603 -17709
  48. package/chunks/chunk-BULDBTYC.js +153 -0
  49. package/chunks/{chunk-XNP57UDV.js → chunk-C3EXYVFX.js} +2 -2
  50. package/chunks/{chunk-FVS747N7.js → chunk-C54UTDOC.js} +23 -19
  51. package/chunks/{chunk-MAQQGNQ5.js → chunk-CBOQ3HY7.js} +466 -10
  52. package/chunks/{chunk-VFAE4AGH.js → chunk-CGZ5SV23.js} +72 -67
  53. package/chunks/{chunk-WKRXIHD6.js → chunk-COAARUPK.js} +8 -8
  54. package/chunks/{chunk-GA7VRJVN.js → chunk-E2ZK5M4P.js} +5 -5
  55. package/chunks/{chunk-5SCI6E3E.js → chunk-E4IMU4Y5.js} +1 -1
  56. package/chunks/{chunk-E5GIFWE3.js → chunk-EEFRJ5CT.js} +54 -33
  57. package/chunks/{chunk-WXAXH7IJ.js → chunk-ESQHGKPJ.js} +1 -1
  58. package/chunks/{chunk-NEEB7UEN.js → chunk-FFFM6NJV.js} +1 -2
  59. package/chunks/{chunk-Z5R4JMOL.js → chunk-FJ2IUWNQ.js} +4 -4
  60. package/chunks/{chunk-JVTCARQ6.js → chunk-FQI7LT7T.js} +4 -4
  61. package/chunks/{chunk-BRXIO5WY.js → chunk-FTNI3D7D.js} +7 -7
  62. package/chunks/{chunk-OMH3276Y.js → chunk-GHRSKGHF.js} +7 -7
  63. package/chunks/{chunk-OONJNQ42.js → chunk-GPSKDNEE.js} +3 -3
  64. package/chunks/{chunk-KPZNOZPC.js → chunk-GWM4PDYK.js} +19 -19
  65. package/chunks/{chunk-NBMIC7DR.js → chunk-H24SOJIQ.js} +2 -2
  66. package/chunks/{chunk-FNGK2Z5B.js → chunk-H4AR2JQF.js} +3 -3
  67. package/chunks/{chunk-WOT64EP2.js → chunk-HCJQORKC.js} +2 -2
  68. package/chunks/{chunk-7KDI2IB2.js → chunk-HDATOR4J.js} +4 -4
  69. package/chunks/{chunk-IE4JSQ5L.js → chunk-HIYP7IR4.js} +39 -37
  70. package/chunks/{chunk-N6YTEVLV.js → chunk-HL6AKUGD.js} +10 -4
  71. package/chunks/{chunk-BAIEQKR5.js → chunk-HPQFGWOD.js} +5 -5
  72. package/chunks/chunk-HTR4WV6U.js +327 -0
  73. package/chunks/{chunk-SDXIH6OA.js → chunk-IFUNDCQ6.js} +137 -5
  74. package/chunks/{chunk-Z6UEAQTP.js → chunk-IFVECEIK.js} +178 -61
  75. package/chunks/{chunk-QOK6RMIP.js → chunk-IKP54WUL.js} +4 -4
  76. package/chunks/{chunk-IUSNI6IX.js → chunk-ISMD2AB3.js} +1 -1
  77. package/chunks/{chunk-G45X5TRN.js → chunk-JCW2R7WC.js} +1 -72
  78. package/chunks/{chunk-LZYWWWCZ.js → chunk-KF6CTNTJ.js} +8 -9
  79. package/chunks/{chunk-EIAK6Q2B.js → chunk-KHOVYUHX.js} +2 -2
  80. package/chunks/chunk-KWK7UE6L.js +6194 -0
  81. package/chunks/{chunk-WBTZGWQ6.js → chunk-L5F3T6TQ.js} +1 -1
  82. package/chunks/{chunk-RELYEO3R.js → chunk-L7ASZD66.js} +244 -1607
  83. package/chunks/{chunk-UJEZQ562.js → chunk-LESHKUWF.js} +3 -5
  84. package/chunks/{chunk-OOCI5VVU.js → chunk-LIZRAKPB.js} +1 -1
  85. package/chunks/{chunk-Q3ZBFXK4.js → chunk-LKB5YL5T.js} +143 -36
  86. package/chunks/{chunk-MKLKHZAK.js → chunk-LU3RXCM7.js} +1 -1
  87. package/chunks/{chunk-B453NMZJ.js → chunk-M3EQ3GZC.js} +3 -3
  88. package/chunks/{chunk-TCKTNY66.js → chunk-M4VFMLQK.js} +6 -6
  89. package/chunks/{chunk-26LLB6FM.js → chunk-MDZTPSXO.js} +2 -2
  90. package/chunks/{chunk-4SLLEAQP.js → chunk-MJPBB2GK.js} +591 -316
  91. package/chunks/chunk-NABLFI57.js +82 -0
  92. package/chunks/{chunk-T7DDD7CZ.js → chunk-NAXEEGJU.js} +4 -4
  93. package/chunks/{chunk-467G3SV5.js → chunk-NPQDJGKU.js} +1 -1
  94. package/chunks/{chunk-FLTN6NRU.js → chunk-O4OT3DM3.js} +5 -1
  95. package/chunks/{chunk-3EUZWNWA.js → chunk-OPDZT2VG.js} +1 -1
  96. package/chunks/chunk-OQ5SYCPE.js +10017 -0
  97. package/chunks/{chunk-C27BYUX6.js → chunk-OQB4EXO4.js} +14 -11
  98. package/chunks/{chunk-V25Z5UUB.js → chunk-P6PBZL3N.js} +7 -6
  99. package/chunks/{chunk-5NWV4NFB.js → chunk-PRAUGUNM.js} +3 -3
  100. package/chunks/{chunk-MC2DOZS7.js → chunk-PVT6E3ZI.js} +3 -3
  101. package/chunks/{chunk-KXEGCGUG.js → chunk-Q22WWVR6.js} +31 -6
  102. package/chunks/{chunk-JDI67JFB.js → chunk-Q2YKNMLS.js} +3 -3
  103. package/chunks/{chunk-PBATSWUQ.js → chunk-QBUDF33N.js} +1 -1
  104. package/chunks/{chunk-Y2ENGUD6.js → chunk-QKTHJXCS.js} +1 -1
  105. package/chunks/{chunk-BVLROR2T.js → chunk-QLJUC7TG.js} +1 -1
  106. package/chunks/{chunk-UEY4AYUL.js → chunk-QNLNLENL.js} +2 -2
  107. package/chunks/{chunk-OKWRU4NO.js → chunk-RC7A7SSL.js} +3 -3
  108. package/chunks/chunk-RCUEYZDE.js +2290 -0
  109. package/chunks/{chunk-EVSTCA7S.js → chunk-RMY5SX7S.js} +368 -113
  110. package/chunks/{chunk-4WUAQ2DO.js → chunk-RTQSXHS7.js} +2 -2
  111. package/chunks/{chunk-RFIAR4YL.js → chunk-RV4C2ZFG.js} +1 -1
  112. package/chunks/{chunk-NIJEXGV6.js → chunk-RVLZCXEE.js} +79 -10
  113. package/chunks/{chunk-Q4RBU7WX.js → chunk-S333CBIA.js} +6 -6
  114. package/chunks/{chunk-JNWZQ27S.js → chunk-SP5WRGVG.js} +3 -3
  115. package/chunks/{chunk-FSL5W5TI.js → chunk-T2L47JJK.js} +3 -3
  116. package/chunks/{chunk-PWVTCGBP.js → chunk-TA4S377U.js} +30 -20
  117. package/chunks/{chunk-TB6UDU4T.js → chunk-THJNPLI4.js} +16 -16
  118. package/chunks/chunk-U6TQGUNB.js +20687 -0
  119. package/chunks/chunk-U7ZFW55U.js +2098 -0
  120. package/chunks/{chunk-W7H223ZZ.js → chunk-UGYMA4EI.js} +1 -1
  121. package/chunks/{chunk-X6YQWCIJ.js → chunk-UH3WSE5L.js} +13 -1
  122. package/chunks/{chunk-P2YAOGJD.js → chunk-UKU3NGW6.js} +3 -3
  123. package/chunks/{chunk-NOWTNYC7.js → chunk-UVFCANV5.js} +8 -8
  124. package/chunks/{chunk-CVDW42JT.js → chunk-V4AKJQ26.js} +1 -1
  125. package/chunks/{chunk-Z5Q65RVH.js → chunk-VJPRLNLR.js} +1 -1
  126. package/chunks/{chunk-Y4CRUWFZ.js → chunk-VTXX72XS.js} +60 -35
  127. package/chunks/{chunk-R3VWUU2E.js → chunk-VYPFXUCB.js} +1 -1
  128. package/chunks/chunk-WHGVTP7Q.js +1049 -0
  129. package/chunks/{chunk-IKP5DXZY.js → chunk-WOWQQGGN.js} +5 -5
  130. package/chunks/{chunk-D2VIDMVM.js → chunk-X6N25LXS.js} +2 -2
  131. package/chunks/chunk-XHATNRQA.js +1500 -0
  132. package/chunks/{chunk-2DXOIVUI.js → chunk-YLSB23Y2.js} +11 -11
  133. package/chunks/{chunk-S35ZDXOS.js → chunk-YM3SZTH4.js} +2 -1
  134. package/chunks/{chunk-OF2BBLYQ.js → chunk-YNWJAOPL.js} +2 -2
  135. package/chunks/{chunk-GKY2OJ7R.js → chunk-ZHERRXZJ.js} +1 -1
  136. package/chunks/{chunk-AR27OPIU.js → chunk-ZKFJKN23.js} +2 -2
  137. package/chunks/{computer-use-R7KA6UJ6.js → computer-use-UKQBH7UM.js} +39 -36
  138. package/chunks/{config-utils-6FXFJUYB.js → config-utils-FYTBZLCJ.js} +3 -3
  139. package/chunks/{contextCommand-KAQQPHZ4.js → contextCommand-ESHGAVWX.js} +36 -33
  140. package/chunks/{create-sub-session-TDPDBU4K.js → create-sub-session-574EPZUU.js} +34 -31
  141. package/chunks/{create-sub-session-X5RVIHCK.js → create-sub-session-AZ77LBL3.js} +3 -3
  142. package/chunks/{cron-create-AC5FFLN7.js → cron-create-KTWJM7QT.js} +5 -5
  143. package/chunks/{cron-delete-JEB3FAHA.js → cron-delete-2P3I5ULL.js} +5 -5
  144. package/chunks/{cron-list-NBYPCNIB.js → cron-list-PXDPGEDQ.js} +5 -5
  145. package/chunks/{daemon-RG2MAI6T.js → daemon-GJRFILYS.js} +323 -99
  146. package/chunks/daemon-status-provider-GZXZP3NU.js +80 -0
  147. package/chunks/{de-I7ZIYXZC.js → de-4IBXM7CN.js} +5 -1
  148. package/chunks/{dist-AU7NQQRP.js → dist-OAV7LJGJ.js} +1 -1
  149. package/chunks/{dist-FUTEXY6A.js → dist-OMW6WDEO.js} +1 -1
  150. package/chunks/{dist-2MIU4UUH.js → dist-PJLG2XYX.js} +1 -1
  151. package/chunks/{dist-53PZYC5B.js → dist-UIFWIFRO.js} +2 -2
  152. package/chunks/{dist-2BHAYBKP.js → dist-XBJVSWS2.js} +1 -1
  153. package/chunks/{dist-WGTQO7F2.js → dist-XRYV6TJP.js} +65 -25
  154. package/chunks/{earlyInputCapture-WC7RI5HV.js → earlyInputCapture-GI3HGQIT.js} +35 -32
  155. package/chunks/{edit-6MHKCJCM.js → edit-EBJK74B3.js} +42 -41
  156. package/chunks/{en-XE34GKAA.js → en-USMCCJAJ.js} +5 -1
  157. package/chunks/{enter-worktree-O7VJ2E7A.js → enter-worktree-2ETY5CSV.js} +39 -36
  158. package/chunks/{enterPlanMode-5XYAALIO.js → enterPlanMode-NY4U2727.js} +45 -37
  159. package/chunks/{environment-LSKFNLBU.js → environment-33IR3NOU.js} +36 -33
  160. package/chunks/{errors-ZFVCY6HG.js → errors-2OCY23IC.js} +36 -33
  161. package/chunks/{exit-worktree-MYIK66T7.js → exit-worktree-Y4ULJ45U.js} +39 -36
  162. package/chunks/{exitPlanMode-7MBNU76O.js → exitPlanMode-SECI2EQ6.js} +39 -36
  163. package/chunks/{fast-path-RNLIB64C.js → fast-path-6Z7RW5J5.js} +3 -2
  164. package/chunks/{fr-X7KDVZIY.js → fr-WVHEBDDB.js} +5 -1
  165. package/chunks/{gemini-WK5ISEAQ.js → gemini-XLGLUGSU.js} +93 -89
  166. package/chunks/{geminiContentGenerator-NUJQBZBW.js → geminiContentGenerator-NNZZDH24.js} +5 -5
  167. package/chunks/{getMachineId-bsd-EXV7SWPA.js → getMachineId-bsd-QFVLPUPT.js} +1 -1
  168. package/chunks/{getMachineId-darwin-IUOMFXU3.js → getMachineId-darwin-DGMQQE2E.js} +1 -1
  169. package/chunks/{getMachineId-linux-K7XJYFHL.js → getMachineId-linux-R4Z6CSWC.js} +1 -1
  170. package/chunks/{getMachineId-unsupported-EA5FDRJ6.js → getMachineId-unsupported-Z3SBVBUV.js} +1 -1
  171. package/chunks/{getMachineId-win-KBA6RAI5.js → getMachineId-win-SCK5UFDT.js} +1 -1
  172. package/chunks/{glob-7P6RYY4L.js → glob-KZA64SSV.js} +41 -38
  173. package/chunks/{grep-V3QHNP2J.js → grep-ONHQMY3V.js} +41 -38
  174. package/chunks/handleAutoUpdate-PRTJISXQ.js +73 -0
  175. package/chunks/{i18n-B7IO7WQT.js → i18n-ZTKKG5R5.js} +35 -32
  176. package/chunks/{initializer-E5TIC3CW.js → initializer-FPPZGBYN.js} +40 -37
  177. package/chunks/{installationInfo-XLPNAISK.js → installationInfo-DV2C27HT.js} +37 -32
  178. package/chunks/{ja-2ICT3KXF.js → ja-KY4ROZTE.js} +5 -1
  179. package/chunks/{keychain-token-storage-DWRJMNH3.js → keychain-token-storage-6ACJDYIB.js} +3 -3
  180. package/chunks/{list-3CZR5I42.js → list-KEHCNUAK.js} +42 -39
  181. package/chunks/{loadedSettingsAdapter-X5BSC6CE.js → loadedSettingsAdapter-7RZ6M3WH.js} +39 -36
  182. package/chunks/{loop-wakeup-HMHCT5GU.js → loop-wakeup-RNMRVA66.js} +6 -6
  183. package/chunks/{ls-IW5HYDG4.js → ls-J2ZI5XYK.js} +5 -5
  184. package/chunks/{lsp-4RL52YIZ.js → lsp-UMS3NUB5.js} +3 -3
  185. package/chunks/managed-npm-update-EBKNOG37.js +332 -0
  186. package/chunks/{mcp-4C4HWXAR.js → mcp-NHXKZRRP.js} +39 -36
  187. package/chunks/{monitor-3CJDNZB2.js → monitor-FMUAIFFH.js} +39 -36
  188. package/chunks/nonInteractiveCli-I2GPZNTP.js +132 -0
  189. package/chunks/{notebook-edit-MX366HCT.js → notebook-edit-V7RNXKVL.js} +43 -42
  190. package/chunks/{openaiContentGenerator-KRPNNJGZ.js → openaiContentGenerator-IBVUUZDH.js} +19 -18
  191. package/chunks/{pidfile-K7T2JLUJ.js → pidfile-AMTGL2H2.js} +35 -32
  192. package/chunks/{processUtils-YXL3VIBR.js → processUtils-3ZT2JF6D.js} +2 -2
  193. package/chunks/{pt-JJ4XPIBP.js → pt-OK455PLH.js} +5 -1
  194. package/chunks/{qwenContentGenerator-GJVXFZ3U.js → qwenContentGenerator-E72VVWS3.js} +41 -38
  195. package/chunks/{qwenOAuth2-UZTIBQLY.js → qwenOAuth2-YCC3HP24.js} +17 -16
  196. package/chunks/{read-file-S5XQSYOW.js → read-file-5EWNGUXN.js} +13 -11
  197. package/chunks/{read-mcp-resource-OIBCNIX7.js → read-mcp-resource-F6HYMDUY.js} +3 -3
  198. package/chunks/{record-artifact-HDMK4LHG.js → record-artifact-7GCFLDD7.js} +3 -3
  199. package/chunks/{resumeHistoryUtils-IKR6XD2S.js → resumeHistoryUtils-IH4RNB76.js} +41 -38
  200. package/chunks/{ripGrep-H65GRSQX.js → ripGrep-B6A6N7GI.js} +34 -31
  201. package/chunks/{ru-STR4KTW7.js → ru-7SPDGMGD.js} +5 -1
  202. package/chunks/{run-qwen-serve-7SKAQOAA.js → run-qwen-serve-6PKSMF6Z.js} +115 -74
  203. package/chunks/{runtime-I2STBGPR.js → runtime-ASRANXO6.js} +45 -40
  204. package/chunks/{scheduler-6F7HETNO.js → scheduler-IABM76UZ.js} +34 -31
  205. package/chunks/sdk-exporters-grpc-ETLH47EP.js +23214 -0
  206. package/chunks/sdk-exporters-http-6MCQH335.js +563 -0
  207. package/chunks/sdk-impl-HOLWAXC6.js +9193 -0
  208. package/chunks/{send-message-WXVVK4DB.js → send-message-KBO6X4ZS.js} +7 -5
  209. package/chunks/{serve-4ATEWSEA.js → serve-A4DT5D32.js} +39 -36
  210. package/chunks/{server-YPUPFV2O.js → server-DZ5ZSVRE.js} +2317 -472
  211. package/chunks/{session-AZFIERIY.js → session-G2R3CYU6.js} +87 -172
  212. package/chunks/{settings-EFQHLTM3.js → settings-7TNSXUTO.js} +43 -40
  213. package/chunks/{shell-FWXWBJ4Q.js → shell-5BRFGEMK.js} +34 -31
  214. package/chunks/{skill-A634MNCD.js → skill-3SWYEK7M.js} +24 -20
  215. package/chunks/{spawnChannel-KKBGGR47.js → spawnChannel-GGN2WVWW.js} +36 -33
  216. package/chunks/{src-BVROLD6N.js → src-5BPBNQ5S.js} +314 -236
  217. package/chunks/{standalone-update-ERLA3BDC.js → standalone-update-AHOZ56LS.js} +37 -34
  218. package/chunks/{startInteractiveUI-3VZ23WAY.js → startInteractiveUI-TLGOQVV7.js} +1105 -906
  219. package/chunks/{syntheticOutput-HCUFXSIA.js → syntheticOutput-H7RTI5KL.js} +4 -4
  220. package/chunks/{task-create-RIY5JTFC.js → task-create-7474AJJD.js} +10 -8
  221. package/chunks/{task-list-XBUCV3CO.js → task-list-633HGOIB.js} +6 -6
  222. package/chunks/{task-stop-QDFCCYR5.js → task-stop-MNUGHPIA.js} +3 -3
  223. package/chunks/{task-update-7PXKJQOI.js → task-update-66GQB5LI.js} +10 -8
  224. package/chunks/{team-create-ZZO7QFQ7.js → team-create-XHDF7UKM.js} +42 -39
  225. package/chunks/{team-delete-TNSSE2S5.js → team-delete-BB3CG3QF.js} +6 -6
  226. package/chunks/{team-plan-approval-3BZBJ46K.js → team-plan-approval-XKSBXWMH.js} +39 -36
  227. package/chunks/{theme-manager-FSFWNXFJ.js → theme-manager-6ZKLBFAN.js} +35 -32
  228. package/chunks/{todoWrite-OMAIGB6V.js → todoWrite-KRAUN54W.js} +5 -5
  229. package/chunks/{tool-search-VYXAAIDW.js → tool-search-UDNJCXYS.js} +21 -17
  230. package/chunks/{total-session-admission-PSMLQICS.js → total-session-admission-VWRCCDYM.js} +40 -37
  231. package/chunks/{tree-sitter-4D7QS7F6.js → tree-sitter-L5BFT64K.js} +1 -1
  232. package/chunks/{tree-sitter-bash-VEJGF5XF.js → tree-sitter-bash-ZKDNQGID.js} +1 -1
  233. package/chunks/{trustedFolders-QA3RK2NV.js → trustedFolders-TJI6OLAN.js} +35 -32
  234. package/chunks/{chunk-6EFTQYW7.js → undici-3FJYTMOF.js} +24 -399
  235. package/chunks/{chunk-L573Z2QZ.js → undici-PYHBDDPN.js} +1 -5
  236. package/chunks/{update-relaunch-LNLZFX3J.js → update-relaunch-RS5GB74A.js} +17 -17
  237. package/chunks/updateCheck-T4EEA5YR.js +88 -0
  238. package/chunks/{useAutoAcceptIndicator-DIWN27LT.js → useAutoAcceptIndicator-LLWMXC7F.js} +44 -41
  239. package/chunks/{validateNonInterActiveAuth-LOEOFCAF.js → validateNonInterActiveAuth-OJ3KYXAR.js} +74 -71
  240. package/chunks/{version-HBF2VBLE.js → version-ZCEUV5DO.js} +1 -1
  241. package/chunks/{web-fetch-BWGSD2BD.js → web-fetch-KQF4YFCI.js} +99 -42
  242. package/chunks/{web-search-OOHTCVR3.js → web-search-QDDGFGKI.js} +113 -61
  243. package/chunks/{workflow-LJAJBOR4.js → workflow-GIRKCX4P.js} +47 -43
  244. package/chunks/{workspace-providers-status-FYV7TTHA.js → workspace-providers-status-UTMAVTNE.js} +42 -39
  245. package/chunks/{workspace-registration-store-4EHGQW4Y.js → workspace-registration-store-EYJMJFZU.js} +8 -2
  246. package/chunks/{workspace-registry-BKD7VC4Y.js → workspace-registry-4W4UW6MY.js} +40 -37
  247. package/chunks/{workspace-service-75RHX6KR.js → workspace-service-DJCPY6ZN.js} +46 -43
  248. package/chunks/{workspace-skills-status-WBZBZI6A.js → workspace-skills-status-VQ2LKXXX.js} +40 -37
  249. package/chunks/write-file-PLK6RQ7M.js +65 -0
  250. package/chunks/{zh-TW-4RR3YHNN.js → zh-TW-BM47YBFH.js} +5 -1
  251. package/chunks/{zh-6ANG2HTL.js → zh-WY5DWYZD.js} +5 -1
  252. package/cli-entry.js +164 -12
  253. package/cli.js +18 -11
  254. package/locales/ca.js +772 -203
  255. package/locales/de.js +8 -2
  256. package/locales/en.js +8 -2
  257. package/locales/fr.js +8 -2
  258. package/locales/ja.js +8 -2
  259. package/locales/pt.js +8 -2
  260. package/locales/ru.js +8 -2
  261. package/locales/zh-TW.js +8 -2
  262. package/locales/zh.js +8 -2
  263. package/package.json +3 -3
  264. package/web-shell/assets/{arc-Buk1besA.js → arc-DIQrcXXh.js} +1 -1
  265. package/web-shell/assets/{architectureDiagram-3BPJPVTR-B1aUKYDC.js → architectureDiagram-3BPJPVTR-CbPd-DSw.js} +1 -1
  266. package/web-shell/assets/{blockDiagram-GPEHLZMM-CRTdg3Zx.js → blockDiagram-GPEHLZMM-yzBIVhMX.js} +1 -1
  267. package/web-shell/assets/{c4Diagram-AAUBKEIU-DFdRMp5g.js → c4Diagram-AAUBKEIU-B88Swcsu.js} +1 -1
  268. package/web-shell/assets/channel-BaTMUesZ.js +1 -0
  269. package/web-shell/assets/{chunk-2J33WTMH-4rYQdkEI.js → chunk-2J33WTMH-BbOLo6NX.js} +1 -1
  270. package/web-shell/assets/{chunk-4BX2VUAB-Coi-pQJy.js → chunk-4BX2VUAB-Bg6in0r0.js} +1 -1
  271. package/web-shell/assets/{chunk-55IACEB6-BtBjz02t.js → chunk-55IACEB6-Bv9QRyLI.js} +1 -1
  272. package/web-shell/assets/{chunk-727SXJPM-CGYOWorl.js → chunk-727SXJPM-CFokiv61.js} +1 -1
  273. package/web-shell/assets/{chunk-AQP2D5EJ-CH5AKhqx.js → chunk-AQP2D5EJ-DS2Oxf6L.js} +1 -1
  274. package/web-shell/assets/{chunk-FMBD7UC4-Cd50-w85.js → chunk-FMBD7UC4-D2NkHD3B.js} +1 -1
  275. package/web-shell/assets/{chunk-ND2GUHAM-C2wF3KCK.js → chunk-ND2GUHAM-BsT_UC5B.js} +1 -1
  276. package/web-shell/assets/{chunk-QZHKN3VN-pCeRTaWi.js → chunk-QZHKN3VN-tnJo3zln.js} +1 -1
  277. package/web-shell/assets/classDiagram-4FO5ZUOK-CyBPzWud.js +1 -0
  278. package/web-shell/assets/classDiagram-v2-Q7XG4LA2-CyBPzWud.js +1 -0
  279. package/web-shell/assets/{cose-bilkent-S5V4N54A-B-_fAB6D.js → cose-bilkent-S5V4N54A-BTMa6DAZ.js} +1 -1
  280. package/web-shell/assets/{dagre-BM42HDAG-ChSPNHpL.js → dagre-BM42HDAG-ujGX7Owg.js} +1 -1
  281. package/web-shell/assets/{diagram-2AECGRRQ-BX7cFOF3.js → diagram-2AECGRRQ-fU4-dbPa.js} +1 -1
  282. package/web-shell/assets/{diagram-5GNKFQAL-BQUTW92n.js → diagram-5GNKFQAL-Bdm-TYSA.js} +1 -1
  283. package/web-shell/assets/{diagram-KO2AKTUF-BkYPh3e4.js → diagram-KO2AKTUF-Bkhz85Z9.js} +1 -1
  284. package/web-shell/assets/{diagram-LMA3HP47-Cl6jsNyx.js → diagram-LMA3HP47-Bzu3q26p.js} +1 -1
  285. package/web-shell/assets/{diagram-OG6HWLK6-DRWoHz8n.js → diagram-OG6HWLK6-CZrXbG5Q.js} +1 -1
  286. package/web-shell/assets/{erDiagram-TEJ5UH35-CGvFcZco.js → erDiagram-TEJ5UH35-BjozEAYu.js} +1 -1
  287. package/web-shell/assets/{flowDiagram-I6XJVG4X-vms6oVdv.js → flowDiagram-I6XJVG4X-B3a2I8c-.js} +1 -1
  288. package/web-shell/assets/{ganttDiagram-6RSMTGT7-ukT_sfmi.js → ganttDiagram-6RSMTGT7-CIMn9fNm.js} +1 -1
  289. package/web-shell/assets/{gitGraphDiagram-PVQCEYII-Bn2ZE2Ut.js → gitGraphDiagram-PVQCEYII-DlFy9KRx.js} +1 -1
  290. package/web-shell/assets/{index-wFXp7W68.js → index-BODUAzQA.js} +1 -1
  291. package/web-shell/assets/index-C54DNMF7.js +1209 -0
  292. package/web-shell/assets/index-lWqBfc78.css +5 -0
  293. package/web-shell/assets/{infoDiagram-5YYISTIA-DHJdSi7x.js → infoDiagram-5YYISTIA-BmKjQgCy.js} +1 -1
  294. package/web-shell/assets/{ishikawaDiagram-YF4QCWOH-DOvd2Wph.js → ishikawaDiagram-YF4QCWOH-BrQEMZz2.js} +1 -1
  295. package/web-shell/assets/{journeyDiagram-JHISSGLW-CH_urMCT.js → journeyDiagram-JHISSGLW-D-2r7Xrt.js} +1 -1
  296. package/web-shell/assets/{kanban-definition-UN3LZRKU-FKiBdgbH.js → kanban-definition-UN3LZRKU-CndsFHCX.js} +1 -1
  297. package/web-shell/assets/{linear-0ZVQFVKf.js → linear-D-IwNnKx.js} +1 -1
  298. package/web-shell/assets/{mermaid.core-DJ05ZZIK.js → mermaid.core-4ll09sri.js} +5 -5
  299. package/web-shell/assets/{mindmap-definition-RKZ34NQL-BPuUhkUm.js → mindmap-definition-RKZ34NQL-maMRIxjo.js} +1 -1
  300. package/web-shell/assets/{pieDiagram-4H26LBE5-yLFKcXyG.js → pieDiagram-4H26LBE5-aunUDhrJ.js} +1 -1
  301. package/web-shell/assets/{quadrantDiagram-W4KKPZXB-irWqc1pE.js → quadrantDiagram-W4KKPZXB-D3K0P1NZ.js} +1 -1
  302. package/web-shell/assets/{requirementDiagram-4Y6WPE33-B_4uMoIV.js → requirementDiagram-4Y6WPE33-CX2X9HRc.js} +1 -1
  303. package/web-shell/assets/{sankeyDiagram-5OEKKPKP-ciA4GPwk.js → sankeyDiagram-5OEKKPKP-CDroWk7l.js} +1 -1
  304. package/web-shell/assets/{sequenceDiagram-3UESZ5HK-CRdZvy0U.js → sequenceDiagram-3UESZ5HK-DTk-2b16.js} +1 -1
  305. package/web-shell/assets/{stateDiagram-AJRCARHV-DaYIkCCn.js → stateDiagram-AJRCARHV-Cud64hQr.js} +1 -1
  306. package/web-shell/assets/stateDiagram-v2-BHNVJYJU-g-uUpecT.js +1 -0
  307. package/web-shell/assets/{timeline-definition-PNZ67QCA-oBUKv6iH.js → timeline-definition-PNZ67QCA-DfD5okf_.js} +1 -1
  308. package/web-shell/assets/{vennDiagram-CIIHVFJN-CGW9Sdmb.js → vennDiagram-CIIHVFJN-BYl8ay25.js} +1 -1
  309. package/web-shell/assets/{wardley-L42UT6IY-CvwKJOCm.js → wardley-L42UT6IY-BZFAt10J.js} +1 -1
  310. package/web-shell/assets/{wardleyDiagram-YWT4CUSO-Ipc260sN.js → wardleyDiagram-YWT4CUSO-BIWn0GA7.js} +1 -1
  311. package/web-shell/assets/{xychartDiagram-2RQKCTM6-D6-CM7pK.js → xychartDiagram-2RQKCTM6-1_H4xblT.js} +1 -1
  312. package/web-shell/index.html +2 -2
  313. package/chunks/chunk-ETD6K42I.js +0 -358
  314. package/chunks/chunk-I5NLVPZJ.js +0 -45
  315. package/chunks/chunk-ONWW74X6.js +0 -74639
  316. package/chunks/chunk-W7FJ3N32.js +0 -49
  317. package/chunks/daemon-status-provider-LVTVJGAD.js +0 -77
  318. package/chunks/handleAutoUpdate-AAQ6PL3E.js +0 -70
  319. package/chunks/nonInteractiveCli-QTEHDDFH.js +0 -129
  320. package/chunks/updateCheck-JJEUQ54U.js +0 -73
  321. package/chunks/write-file-M2DTFILF.js +0 -599
  322. package/web-shell/assets/channel-04R0vLbG.js +0 -1
  323. package/web-shell/assets/classDiagram-4FO5ZUOK-Bw9SOwAV.js +0 -1
  324. package/web-shell/assets/classDiagram-v2-Q7XG4LA2-Bw9SOwAV.js +0 -1
  325. package/web-shell/assets/index-DgkKrjw3.js +0 -1187
  326. package/web-shell/assets/index-Rv6mOAN9.css +0 -5
  327. package/web-shell/assets/stateDiagram-v2-BHNVJYJU-DWBoO4UY.js +0 -1
@@ -1,5 +1,8 @@
1
1
  // Force strict mode and setup for ESM
2
2
  "use strict";
3
+ import {
4
+ recomputeMcpGating
5
+ } from "./chunk-E2ZK5M4P.js";
3
6
  import {
4
7
  classifyApiError
5
8
  } from "./chunk-V7RNNPGC.js";
@@ -12,42 +15,37 @@ import {
12
15
  matchMcpServerByRef,
13
16
  parseExtensionRef,
14
17
  parseMcpServerRef
15
- } from "./chunk-Z5R4JMOL.js";
18
+ } from "./chunk-FJ2IUWNQ.js";
16
19
  import {
17
20
  getAvailableCommands,
18
21
  handleSlashCommand,
19
22
  insertAfterFunctionResponses,
20
23
  isSlashCommand,
21
24
  normalizePartList
22
- } from "./chunk-VFAE4AGH.js";
23
- import {
24
- recomputeMcpGating
25
- } from "./chunk-GA7VRJVN.js";
25
+ } from "./chunk-CGZ5SV23.js";
26
26
  import {
27
27
  appEvents,
28
28
  buildDisabledSkillNamesProvider,
29
29
  loadCliConfig,
30
30
  normalizeDisabledToolList
31
- } from "./chunk-4SLLEAQP.js";
31
+ } from "./chunk-MJPBB2GK.js";
32
32
  import {
33
33
  getCommandSubcommandNames
34
- } from "./chunk-3EUZWNWA.js";
34
+ } from "./chunk-OPDZT2VG.js";
35
35
  import {
36
36
  getEffectiveSupportedModes
37
- } from "./chunk-WOT64EP2.js";
37
+ } from "./chunk-HCJQORKC.js";
38
38
  import "./chunk-5DTTYNB7.js";
39
- import "./chunk-QKYTTBYW.js";
39
+ import "./chunk-4LVZNIDO.js";
40
40
  import {
41
41
  collectContextData,
42
42
  formatContextUsageText
43
- } from "./chunk-NOWTNYC7.js";
43
+ } from "./chunk-UVFCANV5.js";
44
44
  import "./chunk-4WGODMVR.js";
45
- import "./chunk-AYCDXHZB.js";
46
- import "./chunk-QOK6RMIP.js";
47
- import "./chunk-P2YAOGJD.js";
48
- import "./chunk-DA7OOKVN.js";
49
- import "./chunk-LZYWWWCZ.js";
45
+ import "./chunk-IKP54WUL.js";
46
+ import "./chunk-KF6CTNTJ.js";
50
47
  import "./chunk-YAF2MQZ6.js";
48
+ import "./chunk-7Z6JQEL6.js";
51
49
  import {
52
50
  GENERATION_MAX_PROMPT_BYTES,
53
51
  GENERATION_TIMEOUT_MS,
@@ -66,7 +64,7 @@ import {
66
64
  shouldSuppressRememberErrorDetails,
67
65
  workspaceMemoryFailureCode,
68
66
  workspaceMemoryFailureDiagnostics
69
- } from "./chunk-TTSKHF43.js";
67
+ } from "./chunk-BK6UOUJ2.js";
70
68
  import {
71
69
  HistoryReplayer,
72
70
  MessageEmitter,
@@ -76,21 +74,21 @@ import {
76
74
  goalTerminalEventToHistoryItem,
77
75
  recordGoalStatusItem,
78
76
  restoreGoalFromHistory
79
- } from "./chunk-FVS747N7.js";
80
- import "./chunk-KTUQMDEP.js";
77
+ } from "./chunk-C54UTDOC.js";
78
+ import "./chunk-4K7VDKAD.js";
79
+ import "./chunk-V4AKJQ26.js";
81
80
  import "./chunk-RS7MT2QG.js";
82
- import "./chunk-CVDW42JT.js";
83
81
  import "./chunk-H2XVO6NE.js";
82
+ import "./chunk-QHTIBUWB.js";
84
83
  import {
85
84
  isTerminalGoalStatusKind
86
85
  } from "./chunk-QTERJVPZ.js";
87
- import "./chunk-QHTIBUWB.js";
88
- import "./chunk-L573Z2QZ.js";
86
+ import "./chunk-3Z43GZUQ.js";
89
87
  import {
90
88
  computeCpuPercent
91
89
  } from "./chunk-HGT6JR3U.js";
92
90
  import "./chunk-RXFQM6FQ.js";
93
- import "./chunk-N6YTEVLV.js";
91
+ import "./chunk-HL6AKUGD.js";
94
92
  import "./chunk-6H67XLET.js";
95
93
  import {
96
94
  beginAcpBootstrapConfigProfiling,
@@ -98,32 +96,10 @@ import {
98
96
  endAcpBootstrapConfigProfiling,
99
97
  markAcpStartup
100
98
  } from "./chunk-TDKQP3M6.js";
101
- import {
102
- createLoadedSettingsAdapter
103
- } from "./chunk-Z5Q65RVH.js";
99
+ import "./chunk-UKU3NGW6.js";
104
100
  import "./chunk-LXXMOYPL.js";
105
- import "./chunk-7KDI2IB2.js";
101
+ import "./chunk-HDATOR4J.js";
106
102
  import "./chunk-E5Z2AVNV.js";
107
- import {
108
- parseSessionSource
109
- } from "./chunk-EVSTCA7S.js";
110
- import "./chunk-6RLROE6G.js";
111
- import "./chunk-COH43MRJ.js";
112
- import {
113
- CHANNEL_STARTUP_PROFILE_META_KEY,
114
- CHANNEL_STARTUP_PROFILE_VERSION,
115
- CLIENT_MCP_OVER_WS_CONFIG_FLAG,
116
- LOAD_REPLAY_BULK_MODE,
117
- LOAD_REPLAY_META_KEY,
118
- LOAD_REPLAY_MODE_META_KEY,
119
- LOAD_REPLAY_PAGE_SIZE_META_KEY,
120
- LOAD_REPLAY_VERSION,
121
- MID_TURN_QUEUE_DRAIN_METHOD,
122
- TODO_STOP_GUARD_QUEUE_RELEASE_METHOD
123
- } from "./chunk-QR6U5QPP.js";
124
- import {
125
- ndJsonStream
126
- } from "./chunk-6GUTHAN7.js";
127
103
  import {
128
104
  ACP_ROUTE_ID_PREFIX,
129
105
  buildAcpModelOptions,
@@ -132,7 +108,7 @@ import {
132
108
  parseAcpModelOption,
133
109
  resolveAcpModelOption,
134
110
  sanitizeProviderBaseUrl
135
- } from "./chunk-TCKTNY66.js";
111
+ } from "./chunk-M4VFMLQK.js";
136
112
  import {
137
113
  mapSkillConfigToStatus
138
114
  } from "./chunk-2W3OOD4W.js";
@@ -142,19 +118,48 @@ import {
142
118
  buildPermissionSettings,
143
119
  normalizePermissionRules,
144
120
  readPermissionRuleSet
145
- } from "./chunk-WAX3ITOA.js";
121
+ } from "./chunk-A3TAEAHX.js";
146
122
  import {
147
123
  MAX_AUDIO_BYTES,
148
124
  sanitizeVoiceErrorMessage,
149
125
  transcribeVoiceAudio
150
- } from "./chunk-B453NMZJ.js";
126
+ } from "./chunk-M3EQ3GZC.js";
151
127
  import {
152
128
  readVoiceModel
153
- } from "./chunk-IB35C3IL.js";
154
- import "./chunk-BVLROR2T.js";
129
+ } from "./chunk-AVQ6EX4J.js";
130
+ import "./chunk-QLJUC7TG.js";
131
+ import {
132
+ parseSessionSource
133
+ } from "./chunk-RMY5SX7S.js";
134
+ import "./chunk-6RLROE6G.js";
135
+ import "./chunk-COH43MRJ.js";
136
+ import {
137
+ CHANNEL_STARTUP_PROFILE_META_KEY,
138
+ CHANNEL_STARTUP_PROFILE_VERSION,
139
+ CLIENT_MCP_OVER_WS_CONFIG_FLAG,
140
+ LOAD_REPLAY_BULK_MODE,
141
+ LOAD_REPLAY_META_KEY,
142
+ LOAD_REPLAY_MODE_META_KEY,
143
+ LOAD_REPLAY_PAGE_SIZE_META_KEY,
144
+ LOAD_REPLAY_VERSION,
145
+ MID_TURN_QUEUE_DRAIN_METHOD,
146
+ TODO_STOP_GUARD_QUEUE_RELEASE_METHOD
147
+ } from "./chunk-QR6U5QPP.js";
155
148
  import {
156
149
  NOT_CURRENTLY_GENERATING_CANCEL_MESSAGE
157
- } from "./chunk-X6YQWCIJ.js";
150
+ } from "./chunk-UH3WSE5L.js";
151
+ import "./chunk-Q22WWVR6.js";
152
+ import "./chunk-FQI7LT7T.js";
153
+ import "./chunk-57OAHC2Y.js";
154
+ import "./chunk-GHRSKGHF.js";
155
+ import "./chunk-6ZBPS62S.js";
156
+ import "./chunk-V6WHFGST.js";
157
+ import {
158
+ createLoadedSettingsAdapter
159
+ } from "./chunk-VJPRLNLR.js";
160
+ import {
161
+ ndJsonStream
162
+ } from "./chunk-6HOCJNO5.js";
158
163
  import {
159
164
  ACP_PREFLIGHT_KINDS,
160
165
  IDLE_HOOK_EVENTS,
@@ -162,29 +167,23 @@ import {
162
167
  SERVE_STATUS_EXT_METHODS,
163
168
  STATUS_SCHEMA_VERSION,
164
169
  mapDomainErrorToErrorKind
165
- } from "./chunk-WXAXH7IJ.js";
166
- import "./chunk-KXEGCGUG.js";
167
- import "./chunk-JVTCARQ6.js";
168
- import "./chunk-57OAHC2Y.js";
169
- import "./chunk-OMH3276Y.js";
170
- import "./chunk-4ODB7WIB.js";
171
- import "./chunk-V6WHFGST.js";
172
- import {
173
- assembleMcpServers,
174
- loadMcpApprovals
175
- } from "./chunk-V25Z5UUB.js";
176
- import "./chunk-W7FJ3N32.js";
177
- import "./chunk-Y2ENGUD6.js";
170
+ } from "./chunk-ESQHGKPJ.js";
171
+ import "./chunk-2RFKHEXL.js";
172
+ import "./chunk-QKTHJXCS.js";
178
173
  import "./chunk-TJTKSVIV.js";
179
174
  import "./chunk-M5GB774H.js";
180
- import "./chunk-RFIAR4YL.js";
181
- import "./chunk-2HOVDT7W.js";
182
- import "./chunk-NIJEXGV6.js";
175
+ import "./chunk-RV4C2ZFG.js";
176
+ import "./chunk-2LI23QA6.js";
177
+ import "./chunk-RVLZCXEE.js";
183
178
  import {
184
179
  AgentSideConnection,
185
180
  PROTOCOL_VERSION,
186
181
  RequestError
187
182
  } from "./chunk-UDXSXLER.js";
183
+ import {
184
+ assembleMcpServers,
185
+ loadMcpApprovals
186
+ } from "./chunk-P6PBZL3N.js";
188
187
  import {
189
188
  getOutputLanguageFilePath,
190
189
  getPersistScopeForModelSelection,
@@ -193,38 +192,39 @@ import {
193
192
  resolveOutputLanguageOrPreserveAuto,
194
193
  updateOutputLanguageFile,
195
194
  writeOutputLanguageAndRegisterPath
196
- } from "./chunk-KPZNOZPC.js";
195
+ } from "./chunk-GWM4PDYK.js";
197
196
  import "./chunk-RKUWKYED.js";
198
- import "./chunk-GOXKNSDZ.js";
199
- import {
200
- getSystemDefaultsPath,
201
- getSystemSettingsPath
202
- } from "./chunk-IDS7MSUP.js";
203
197
  import {
204
198
  SUPPORTED_LANGUAGES,
205
199
  getCurrentLanguage,
206
200
  setLanguageAsync
207
- } from "./chunk-2DXOIVUI.js";
201
+ } from "./chunk-YLSB23Y2.js";
208
202
  import {
209
203
  findEnvFiles,
210
204
  preResolveHomeEnvOverrides,
211
205
  reloadEnvironment
212
- } from "./chunk-OF2BBLYQ.js";
206
+ } from "./chunk-YNWJAOPL.js";
207
+ import "./chunk-4CTP6VR6.js";
208
+ import "./chunk-GOXKNSDZ.js";
209
+ import {
210
+ getSystemDefaultsPath,
211
+ getSystemSettingsPath
212
+ } from "./chunk-IDS7MSUP.js";
213
213
  import "./chunk-QRUIS3DN.js";
214
- import "./chunk-IUSNI6IX.js";
214
+ import "./chunk-XFSFZCM5.js";
215
+ import "./chunk-ISMD2AB3.js";
215
216
  import "./chunk-VJNBRRZG.js";
216
217
  import {
217
218
  isFolderTrustEnabled,
218
219
  isWorkspaceTrusted,
219
220
  loadTrustedFolders
220
- } from "./chunk-MC2DOZS7.js";
221
+ } from "./chunk-PVT6E3ZI.js";
221
222
  import "./chunk-ALGGS7UH.js";
222
223
  import "./chunk-MR3PXB6E.js";
223
224
  import {
224
225
  writeStderrLine,
225
226
  writeStderrLineSafe
226
227
  } from "./chunk-OWAK7LMW.js";
227
- import "./chunk-XFSFZCM5.js";
228
228
  import {
229
229
  ALL_PROVIDERS,
230
230
  APPROVAL_MODE_INFO,
@@ -243,16 +243,20 @@ import {
243
243
  McpServerSpawnFailedError,
244
244
  McpTransportPool,
245
245
  MessageDisplayDispatcher,
246
+ PLAN_MODE_ENTRY_SIBLING_SKIP_MESSAGE,
246
247
  POOLED_TRANSPORTS_DEFAULT,
247
248
  SESSION_ARTIFACT_PERSISTENCE_VERSION,
248
249
  SESSION_TITLE_MAX_LENGTH,
249
250
  SESSION_TRANSCRIPT_MAX_LIMIT,
250
251
  SESSION_TRANSCRIPT_MAX_PAGE_BYTES,
252
+ SESSION_WRITER_RPC_CODES,
251
253
  SessionService,
252
254
  SessionTranscriptPageTooLargeError,
253
255
  SessionTranscriptReader,
254
256
  SessionTranscriptSnapshotUnavailableError,
255
257
  SessionTranscriptTooLargeError,
258
+ SessionWriterError,
259
+ SessionWriterUnavailableError,
256
260
  TURN_INTERRUPTION_HISTORY_TAIL_COUNT,
257
261
  WorkspaceMcpBudget,
258
262
  abortGoalForStopHookCap,
@@ -260,6 +264,7 @@ import {
260
264
  applyAutoModeDecision,
261
265
  applyProviderInstallPlan,
262
266
  approxBase64Bytes,
267
+ bridgeToolResultImages,
263
268
  buildBackgroundEntryLabel,
264
269
  buildBtwCacheSafeParams,
265
270
  buildBtwPrompt,
@@ -272,13 +277,18 @@ import {
272
277
  convertToFunctionErrorResponse,
273
278
  convertToFunctionResponse,
274
279
  createDuplicateProviderToolCallResponse,
280
+ decorateClassifierUnavailableConfirmation,
281
+ decoratePlanModeShellConfirmation,
275
282
  dedupeToolCallsById,
276
283
  detectAutonomousSentinel,
277
284
  detectLoopSentinel,
278
285
  encodeSessionTranscriptCursor,
279
286
  evaluateAutoMode,
280
287
  evaluatePermissionFlow,
288
+ evaluatePlanModeShellPolicy,
289
+ finalizeToolResponses,
281
290
  findExistingProviderModels,
291
+ findPlanModeEntryBatchBoundaryIndex,
282
292
  findProviderById,
283
293
  findRepeatedDuplicateProviderToolCall,
284
294
  fireNotificationHook,
@@ -301,21 +311,19 @@ import {
301
311
  getPlanModeSystemReminder,
302
312
  getProviderToolCallId,
303
313
  getScopedEnvContents,
304
- getStartupContextLength,
314
+ getStopHookContinuationReason,
305
315
  ideContextStore,
306
316
  injectPermissionRulesIfMissing,
307
317
  isApproveOutcome,
308
318
  isDenialFallbackReason,
309
319
  isGatedMcpScope,
310
320
  isPlanModeBlocked,
311
- isSystemReminderContent,
312
321
  markDuplicateProviderToolCallResponseSent,
313
322
  matchesAnyServerPattern,
314
323
  mcpServerRequiresOAuth,
315
324
  needsConfirmation,
316
325
  normalizeEventPayload,
317
326
  normalizeSnapshotPayload,
318
- parsePositiveIntegerEnv,
319
327
  persistPermissionOutcome,
320
328
  readManyFiles,
321
329
  recordAllow,
@@ -337,45 +345,57 @@ import {
337
345
  shouldRunAutoModeForCall,
338
346
  subagentGenerator,
339
347
  unregisterGoalHook,
340
- updateSetting
341
- } from "./chunk-6OH6A5EX.js";
342
- import "./chunk-5M6IDOMF.js";
348
+ updateSetting,
349
+ validatePlanModeShellApproval,
350
+ validatePlanModeShellContext
351
+ } from "./chunk-BLAEKN6K.js";
343
352
  import "./chunk-T4TZQJ7W.js";
344
353
  import {
345
354
  external_exports
346
355
  } from "./chunk-H6XPXXMH.js";
347
- import "./chunk-OONJNQ42.js";
348
- import "./chunk-JDI67JFB.js";
356
+ import "./chunk-5M6IDOMF.js";
357
+ import "./chunk-T2L47JJK.js";
358
+ import "./chunk-GPSKDNEE.js";
359
+ import "./chunk-X6N25LXS.js";
360
+ import "./chunk-E2UVIFI2.js";
361
+ import "./chunk-L5F3T6TQ.js";
362
+ import "./chunk-Q2YKNMLS.js";
349
363
  import "./chunk-XU457J4V.js";
350
364
  import "./chunk-VDDGDZMA.js";
351
- import "./chunk-EIAK6Q2B.js";
352
- import "./chunk-FSL5W5TI.js";
353
- import "./chunk-D2VIDMVM.js";
354
- import "./chunk-E2UVIFI2.js";
355
- import "./chunk-WBTZGWQ6.js";
365
+ import "./chunk-KHOVYUHX.js";
356
366
  import "./chunk-SZRN75WQ.js";
357
- import "./chunk-HTO4JFDZ.js";
367
+ import {
368
+ parsePositiveIntegerEnv
369
+ } from "./chunk-6PVPNMXU.js";
358
370
  import "./chunk-CPBF7KYF.js";
371
+ import "./chunk-NABLFI57.js";
372
+ import {
373
+ HookEventName,
374
+ createHookOutput
375
+ } from "./chunk-QBUDF33N.js";
376
+ import "./chunk-LIZRAKPB.js";
359
377
  import {
360
378
  APPROVAL_MODES,
361
379
  FORK_SUBAGENT_TYPE,
380
+ getStartupContextLength,
381
+ isSystemReminderContent,
362
382
  runWithRuntimeContentGenerator
363
- } from "./chunk-ETD6K42I.js";
383
+ } from "./chunk-WHGVTP7Q.js";
364
384
  import "./chunk-6AM5D4ME.js";
365
- import "./chunk-G45X5TRN.js";
366
- import {
367
- HookEventName,
368
- createHookOutput
369
- } from "./chunk-PBATSWUQ.js";
370
- import "./chunk-ZEOZL37W.js";
371
- import "./chunk-OOCI5VVU.js";
385
+ import "./chunk-JCW2R7WC.js";
386
+ import "./chunk-57FIIFJN.js";
387
+ import "./chunk-HTO4JFDZ.js";
372
388
  import {
373
389
  clearCachedCredentialFile,
374
390
  qwenOAuth2Events
375
- } from "./chunk-UQES76OO.js";
376
- import "./chunk-OKWRU4NO.js";
377
- import "./chunk-XNP57UDV.js";
391
+ } from "./chunk-2HGTVAOW.js";
378
392
  import "./chunk-JESCGQM3.js";
393
+ import "./chunk-RC7A7SSL.js";
394
+ import "./chunk-C3EXYVFX.js";
395
+ import "./chunk-XVNQMZ2I.js";
396
+ import "./chunk-FODK6UMO.js";
397
+ import "./chunk-GLNBDYUX.js";
398
+ import "./chunk-DJ2GSRLV.js";
379
399
  import {
380
400
  AuthType,
381
401
  ConversationFinishedEvent,
@@ -383,8 +403,6 @@ import {
383
403
  LoopDetectedEvent,
384
404
  PromptSuggestionEvent,
385
405
  UserPromptEvent,
386
- endToolExecutionSpan,
387
- endToolSpan,
388
406
  extractDaemonTraceContext,
389
407
  formatFullTurnVisionNotice,
390
408
  formatVisionBridgeNotice,
@@ -400,63 +418,63 @@ import {
400
418
  logUserPrompt,
401
419
  normalizeParts,
402
420
  registerAcpEventLoopLagGauge,
403
- runInToolSpanContext,
404
421
  runSideQuery,
405
422
  runVisionBridge,
406
423
  shouldRunVisionBridge,
407
424
  splitImageParts,
408
425
  startEventLoopLagMonitor,
409
- startToolExecutionSpan,
410
- startToolSpan,
411
426
  uiTelemetryService,
412
- withDaemonSpan,
413
- withInteractionSpan
414
- } from "./chunk-ONWW74X6.js";
415
- import "./chunk-4WKAA4KS.js";
416
- import "./chunk-CR3C7WXL.js";
427
+ withDaemonSpan
428
+ } from "./chunk-U6TQGUNB.js";
417
429
  import "./chunk-VGC4I5JJ.js";
418
430
  import {
419
431
  getAutoMemoryRoot,
420
432
  getUserAutoMemoryRoot
421
- } from "./chunk-JD3MKVKL.js";
422
- import "./chunk-UEY4AYUL.js";
423
- import "./chunk-BDBMYST4.js";
424
- import "./chunk-467G3SV5.js";
425
- import {
426
- ToolConfirmationOutcome,
427
- ToolNames,
428
- isShellProgressData
429
- } from "./chunk-S35ZDXOS.js";
430
- import "./chunk-XVNQMZ2I.js";
431
- import "./chunk-FODK6UMO.js";
432
- import "./chunk-GLNBDYUX.js";
433
- import "./chunk-DJ2GSRLV.js";
434
- import "./chunk-6EFTQYW7.js";
433
+ } from "./chunk-4K56OJFJ.js";
435
434
  import {
436
435
  DEFAULT_TOKEN_LIMIT,
437
436
  getToolCallPreparations,
438
437
  tokenLimit
439
- } from "./chunk-MAQQGNQ5.js";
438
+ } from "./chunk-CBOQ3HY7.js";
440
439
  import "./chunk-A4UCTEB5.js";
441
440
  import "./chunk-XWRJCPHC.js";
441
+ import "./chunk-QNLNLENL.js";
442
+ import "./chunk-6X4GWOPW.js";
442
443
  import "./chunk-TYQMGACW.js";
443
444
  import "./chunk-TYAMGABM.js";
444
445
  import "./chunk-FCMNKVXT.js";
446
+ import {
447
+ endToolExecutionSpan,
448
+ endToolSpan,
449
+ runInToolSpanContext,
450
+ startToolExecutionSpan,
451
+ startToolSpan,
452
+ withInteractionSpan
453
+ } from "./chunk-RCUEYZDE.js";
454
+ import "./chunk-HTR4WV6U.js";
455
+ import "./chunk-BULDBTYC.js";
456
+ import "./chunk-U7ZFW55U.js";
457
+ import "./chunk-NPQDJGKU.js";
458
+ import {
459
+ ToolConfirmationOutcome,
460
+ ToolNames,
461
+ isShellProgressData
462
+ } from "./chunk-YM3SZTH4.js";
445
463
  import {
446
464
  Storage,
447
465
  createDebugLogger,
448
466
  getErrorMessage,
449
467
  getErrorStatus,
450
468
  isSubpath
451
- } from "./chunk-C27BYUX6.js";
452
- import "./chunk-MKLKHZAK.js";
469
+ } from "./chunk-OQB4EXO4.js";
470
+ import "./chunk-LU3RXCM7.js";
453
471
  import {
454
472
  runExitCleanup
455
- } from "./chunk-FLTN6NRU.js";
473
+ } from "./chunk-O4OT3DM3.js";
456
474
  import "./chunk-75DOP5OR.js";
457
475
  import "./chunk-DMTGGOSA.js";
458
476
  import "./chunk-YQ3U5MUC.js";
459
- import "./chunk-TB6UDU4T.js";
477
+ import "./chunk-THJNPLI4.js";
460
478
  import {
461
479
  init_esbuild_shims
462
480
  } from "./chunk-5O2XNYP6.js";
@@ -466,7 +484,7 @@ import {
466
484
 
467
485
  // packages/cli/src/acp-integration/acpAgent.ts
468
486
  init_esbuild_shims();
469
- import { randomUUID } from "node:crypto";
487
+ import { randomUUID as randomUUID2 } from "node:crypto";
470
488
  import { performance } from "node:perf_hooks";
471
489
 
472
490
  // packages/cli/src/acp-integration/authMethods.ts
@@ -844,6 +862,7 @@ __name(isInactiveExtensionSkill, "isInactiveExtensionSkill");
844
862
  // packages/cli/src/acp-integration/session/Session.ts
845
863
  init_esbuild_shims();
846
864
  import { Buffer as Buffer2 } from "node:buffer";
865
+ import { randomUUID } from "node:crypto";
847
866
  import { existsSync as existsSync2, statSync as statSync2 } from "node:fs";
848
867
  import * as os2 from "node:os";
849
868
  import * as path3 from "node:path";
@@ -968,8 +987,23 @@ function supportsHideAlwaysAllow(confirmation) {
968
987
  }
969
988
  __name(supportsHideAlwaysAllow, "supportsHideAlwaysAllow");
970
989
  function filterAlwaysAllowOptions(confirmation, options, forceHideAlwaysAllow = false) {
971
- const hideAlwaysAllow = forceHideAlwaysAllow || supportsHideAlwaysAllow(confirmation) && confirmation.hideAlwaysAllow === true;
972
- return hideAlwaysAllow ? options.filter((option) => option.kind !== "allow_always") : options;
990
+ const hideAlwaysAllow = forceHideAlwaysAllow || confirmation.autoModeFallback !== void 0 || supportsHideAlwaysAllow(confirmation) && confirmation.hideAlwaysAllow === true;
991
+ const visibleOptions = hideAlwaysAllow ? options.filter((option) => option.kind !== "allow_always") : options;
992
+ if (!confirmation.autoModeFallback) return visibleOptions;
993
+ const switchOption = {
994
+ optionId: "proceed_once_and_switch_to_default" /* ProceedOnceAndSwitchToDefault */,
995
+ name: "Switch to Default Mode and allow once (recommended)",
996
+ kind: "allow_once"
997
+ };
998
+ const rejectIndex = visibleOptions.findIndex(
999
+ (option) => option.kind === "reject_once"
1000
+ );
1001
+ if (rejectIndex === -1) return [...visibleOptions, switchOption];
1002
+ return [
1003
+ ...visibleOptions.slice(0, rejectIndex),
1004
+ switchOption,
1005
+ ...visibleOptions.slice(rejectIndex)
1006
+ ];
973
1007
  }
974
1008
  __name(filterAlwaysAllowOptions, "filterAlwaysAllowOptions");
975
1009
  function formatExecPermissionScopeLabel(confirmation) {
@@ -997,6 +1031,22 @@ function interactionMetaFields(confirmation) {
997
1031
  __name(interactionMetaFields, "interactionMetaFields");
998
1032
  function buildPermissionRequestContent(confirmation) {
999
1033
  const content = [];
1034
+ if (confirmation.autoModeFallback) {
1035
+ content.push({
1036
+ type: "content",
1037
+ content: {
1038
+ type: "text",
1039
+ text: confirmation.autoModeFallback.message
1040
+ }
1041
+ });
1042
+ }
1043
+ const warnings = confirmation.type === "exec" || confirmation.type === "edit" ? confirmation.warnings ?? [] : [];
1044
+ for (const warning of warnings) {
1045
+ content.push({
1046
+ type: "content",
1047
+ content: { type: "text", text: warning }
1048
+ });
1049
+ }
1000
1050
  if (confirmation.type === "edit") {
1001
1051
  content.push({
1002
1052
  type: "diff",
@@ -1017,6 +1067,56 @@ function buildPermissionRequestContent(confirmation) {
1017
1067
  return content;
1018
1068
  }
1019
1069
  __name(buildPermissionRequestContent, "buildPermissionRequestContent");
1070
+ function permissionAbortError(signal) {
1071
+ return signal.reason instanceof Error ? signal.reason : new Error("Permission request was aborted.");
1072
+ }
1073
+ __name(permissionAbortError, "permissionAbortError");
1074
+ function requestPermissionWithAbort(client, params, signal) {
1075
+ if (signal.aborted) {
1076
+ return Promise.reject(permissionAbortError(signal));
1077
+ }
1078
+ return new Promise((resolve5, reject) => {
1079
+ let settled = false;
1080
+ const finish = /* @__PURE__ */ __name((callback) => {
1081
+ if (settled) return;
1082
+ settled = true;
1083
+ signal.removeEventListener("abort", onAbort);
1084
+ callback();
1085
+ }, "finish");
1086
+ const onAbort = /* @__PURE__ */ __name(() => finish(() => reject(permissionAbortError(signal))), "onAbort");
1087
+ signal.addEventListener("abort", onAbort, { once: true });
1088
+ let request;
1089
+ try {
1090
+ request = client.requestPermission(params);
1091
+ } catch (error) {
1092
+ finish(() => reject(error));
1093
+ return;
1094
+ }
1095
+ request.then(
1096
+ (response) => finish(() => resolve5(response)),
1097
+ (error) => finish(() => reject(error))
1098
+ );
1099
+ });
1100
+ }
1101
+ __name(requestPermissionWithAbort, "requestPermissionWithAbort");
1102
+ function resolvePermissionOutcome(response, offeredOptions) {
1103
+ if (response.outcome.outcome === "cancelled") {
1104
+ return "cancel" /* Cancel */;
1105
+ }
1106
+ const optionId = response.outcome.optionId;
1107
+ if (!offeredOptions.some((option) => option.optionId === optionId)) {
1108
+ throw new Error(
1109
+ `Permission response selected unoffered option: ${optionId}`
1110
+ );
1111
+ }
1112
+ if (!Object.values(ToolConfirmationOutcome).includes(
1113
+ optionId
1114
+ )) {
1115
+ throw new Error(`Permission response selected invalid option: ${optionId}`);
1116
+ }
1117
+ return optionId;
1118
+ }
1119
+ __name(resolvePermissionOutcome, "resolvePermissionOutcome");
1020
1120
  function toPermissionOptions(confirmation, forceHideAlwaysAllow = false) {
1021
1121
  switch (confirmation.type) {
1022
1122
  case "edit":
@@ -1243,9 +1343,13 @@ var SubAgentTracker = class {
1243
1343
  }, "onConfirm")
1244
1344
  };
1245
1345
  const { title, locations, kind } = this.toolCallEmitter.resolveToolMetadata(event.name, state?.args);
1346
+ const permissionOptions = toPermissionOptions(fullConfirmationDetails);
1347
+ const offeredPermissionOptions = permissionOptions.map((option) => ({
1348
+ ...option
1349
+ }));
1246
1350
  const params = {
1247
1351
  sessionId: this.ctx.sessionId,
1248
- options: toPermissionOptions(fullConfirmationDetails),
1352
+ options: permissionOptions,
1249
1353
  toolCall: {
1250
1354
  toolCallId: event.callId,
1251
1355
  status: "pending",
@@ -1266,8 +1370,15 @@ var SubAgentTracker = class {
1266
1370
  }
1267
1371
  };
1268
1372
  try {
1269
- const output = await this.client.requestPermission(params);
1270
- const outcome = output.outcome.outcome === "cancelled" ? "cancel" /* Cancel */ : external_exports.nativeEnum(ToolConfirmationOutcome).parse(output.outcome.optionId);
1373
+ const output = await requestPermissionWithAbort(
1374
+ this.client,
1375
+ params,
1376
+ abortSignal
1377
+ );
1378
+ const outcome = resolvePermissionOutcome(
1379
+ output,
1380
+ offeredPermissionOptions
1381
+ );
1271
1382
  await event.respond(outcome, {
1272
1383
  answers: "answers" in output ? output.answers : void 0
1273
1384
  });
@@ -1859,6 +1970,10 @@ function maskApiKeyForDisplay(apiKey) {
1859
1970
  return `${trimmed.slice(0, 3)}...${trimmed.slice(-4)}`;
1860
1971
  }
1861
1972
  __name(maskApiKeyForDisplay, "maskApiKeyForDisplay");
1973
+ function getAbortAwareEndTurnStopReason(signal) {
1974
+ return signal.aborted ? "cancelled" : "end_turn";
1975
+ }
1976
+ __name(getAbortAwareEndTurnStopReason, "getAbortAwareEndTurnStopReason");
1862
1977
  var DAEMON_INVALID_TOOL_PARAMS_THRESHOLD = 3;
1863
1978
  var PERMISSION_CANCEL_SKIP_MESSAGE = "Skipped because a permission request was cancelled before the user answered; user input is required before continuing.";
1864
1979
  var LOOP_DETECTED_SKIP_MESSAGE = "Skipped because loop detection stopped the current turn before this tool call could run.";
@@ -2310,7 +2425,7 @@ var Session = class {
2310
2425
  this.client = client;
2311
2426
  this.settings = settings;
2312
2427
  this.sessionId = id;
2313
- this.runtimeBaseDir = Storage.getRuntimeBaseDir();
2428
+ this.runtimeBaseDir = config.storage.getRuntimeBaseDir();
2314
2429
  const todoStopGuardEnabled = this.settings.merged.experimental?.todoStopGuard === true && !this.config.getBareMode() && !this.config.isSafeMode();
2315
2430
  this.todoStopGuard = new DaemonTodoStopGuard(todoStopGuardEnabled);
2316
2431
  this.todoStopGuardBackgroundBaseline = todoStopGuardEnabled ? this.#captureTodoStopGuardBackgroundBaseline() : {
@@ -2341,6 +2456,7 @@ var Session = class {
2341
2456
  * process termination is slow.
2342
2457
  */
2343
2458
  pendingPromptCompletion = null;
2459
+ automaticDrainRetry = null;
2344
2460
  /**
2345
2461
  * Per-turn AbortController for the fire-and-forget follow-up suggestion
2346
2462
  * generation. Aborted on the top of the next `prompt()` and on
@@ -2403,6 +2519,9 @@ var Session = class {
2403
2519
  // or session reload), which would otherwise execute orphaned cron prompts
2404
2520
  // on a session whose registries are already unregistered.
2405
2521
  disposed = false;
2522
+ closing = false;
2523
+ closeGateCompletion = null;
2524
+ resolveCloseGate = null;
2406
2525
  unsubscribeChatRecordingFailure;
2407
2526
  // Modular components
2408
2527
  historyReplayer;
@@ -2637,7 +2756,7 @@ var Session = class {
2637
2756
  * mount.
2638
2757
  */
2639
2758
  startCronScheduler() {
2640
- this.#startCronSchedulerIfNeeded().catch((error) => {
2759
+ this.#startCronSchedulerInRuntime().catch((error) => {
2641
2760
  debugLogger6.warn(
2642
2761
  `Cron scheduler startup failed [session ${this.sessionId}]: ${error}`
2643
2762
  );
@@ -2646,8 +2765,95 @@ var Session = class {
2646
2765
  getConfig() {
2647
2766
  return this.config;
2648
2767
  }
2768
+ async assertCanStartTurn() {
2769
+ if (this.closing) {
2770
+ throw RequestError.invalidParams(void 0, "Session is closing");
2771
+ }
2772
+ try {
2773
+ await this.config.assertCanStartTurn();
2774
+ } catch (error) {
2775
+ if (error instanceof SessionWriterError) {
2776
+ throw new RequestError(error.rpcCode, error.message, {
2777
+ errorKind: error.errorKind
2778
+ });
2779
+ }
2780
+ throw error;
2781
+ }
2782
+ if (this.closing) {
2783
+ throw RequestError.invalidParams(void 0, "Session is closing");
2784
+ }
2785
+ }
2649
2786
  isIdle() {
2650
- return !this.pendingPrompt && !this.pendingPromptCompletion && !this.cronProcessing && !this.cronAbortController && !this.notificationProcessing && !this.notificationAbortController;
2787
+ return !this.closing && !this.#hasActiveTurn();
2788
+ }
2789
+ #hasActiveTurn() {
2790
+ return Boolean(
2791
+ this.pendingPrompt || this.pendingPromptCompletion || this.cronProcessing || this.cronAbortController || this.cronCompletion || this.notificationProcessing || this.notificationAbortController || this.notificationCompletion
2792
+ );
2793
+ }
2794
+ beginClose() {
2795
+ if (this.closing) {
2796
+ throw RequestError.invalidParams(
2797
+ void 0,
2798
+ "Session close is already in progress"
2799
+ );
2800
+ }
2801
+ this.closing = true;
2802
+ let resolveGate;
2803
+ const completion = new Promise((resolve5) => {
2804
+ resolveGate = resolve5;
2805
+ });
2806
+ this.closeGateCompletion = completion;
2807
+ this.resolveCloseGate = resolveGate;
2808
+ let released = false;
2809
+ return () => {
2810
+ if (released) return;
2811
+ released = true;
2812
+ if (this.closeGateCompletion === completion) {
2813
+ this.closeGateCompletion = null;
2814
+ this.resolveCloseGate = null;
2815
+ }
2816
+ resolveGate();
2817
+ if (this.disposed) return;
2818
+ this.closing = false;
2819
+ void this.#drainCronQueue();
2820
+ void this.#drainNotificationQueue();
2821
+ };
2822
+ }
2823
+ beginCloseIfAvailable() {
2824
+ if (this.disposed) {
2825
+ throw RequestError.invalidParams(void 0, "Session has been disposed");
2826
+ }
2827
+ return this.closing ? null : this.beginClose();
2828
+ }
2829
+ waitForCloseGateToRelease() {
2830
+ return this.closeGateCompletion ?? Promise.resolve();
2831
+ }
2832
+ async waitForActiveTurnsToSettle() {
2833
+ const pending = [
2834
+ this.pendingPromptCompletion,
2835
+ this.cronCompletion,
2836
+ this.notificationCompletion
2837
+ ].filter((completion) => completion !== null);
2838
+ await Promise.allSettled(pending);
2839
+ }
2840
+ #deferAutomaticQueueDrainUntilTurnsSettle() {
2841
+ const completions = [
2842
+ this.pendingPromptCompletion,
2843
+ this.cronCompletion,
2844
+ this.notificationCompletion
2845
+ ].filter((completion) => completion !== null);
2846
+ if (completions.length === 0) return false;
2847
+ if (this.automaticDrainRetry) return true;
2848
+ const retry = Promise.allSettled(completions).then(() => {
2849
+ if (this.automaticDrainRetry !== retry) return;
2850
+ this.automaticDrainRetry = null;
2851
+ if (this.disposed) return;
2852
+ void this.#drainCronQueue();
2853
+ void this.#drainNotificationQueue();
2854
+ });
2855
+ this.automaticDrainRetry = retry;
2856
+ return true;
2651
2857
  }
2652
2858
  getTurnCount() {
2653
2859
  return this.turn;
@@ -2657,6 +2863,10 @@ var Session = class {
2657
2863
  }
2658
2864
  dispose() {
2659
2865
  this.disposed = true;
2866
+ this.closing = true;
2867
+ this.resolveCloseGate?.();
2868
+ this.resolveCloseGate = null;
2869
+ this.closeGateCompletion = null;
2660
2870
  this.todoStopGuardQueuedPromptPriority = false;
2661
2871
  this.todoStopGuardDrainAutomaticQueuesWhenIdle = false;
2662
2872
  this.todoStopGuard.clearTrust();
@@ -2673,7 +2883,7 @@ var Session = class {
2673
2883
  this.cronProcessing = false;
2674
2884
  this.cronCompletion = null;
2675
2885
  if (this.config.isCronEnabled()) {
2676
- this.config.getCronScheduler().stop();
2886
+ this.#stopCronSchedulerInRuntime();
2677
2887
  }
2678
2888
  this.config.getBackgroundTaskRegistry().setNotificationCallback(void 0);
2679
2889
  this.config.getMonitorRegistry().setNotificationCallback(void 0);
@@ -2757,7 +2967,7 @@ var Session = class {
2757
2967
  "targetTurnIndex must be a non-negative integer"
2758
2968
  );
2759
2969
  }
2760
- if (this.pendingPrompt || this.cronProcessing || this.cronAbortController || this.notificationProcessing || this.notificationAbortController) {
2970
+ if (this.closing || this.#hasActiveTurn()) {
2761
2971
  throw RequestError.invalidParams(
2762
2972
  void 0,
2763
2973
  "Cannot rewind while a prompt is running"
@@ -2814,7 +3024,7 @@ var Session = class {
2814
3024
  return count;
2815
3025
  }
2816
3026
  restoreHistory(history) {
2817
- if (this.pendingPrompt || this.cronProcessing || this.cronAbortController || this.notificationProcessing || this.notificationAbortController) {
3027
+ if (this.closing || this.#hasActiveTurn()) {
2818
3028
  throw RequestError.invalidParams(
2819
3029
  void 0,
2820
3030
  "Cannot restore history while a prompt is running"
@@ -2888,13 +3098,17 @@ var Session = class {
2888
3098
  const scheduler = this.config.isCronEnabled() ? this.config.getCronScheduler() : null;
2889
3099
  if (scheduler) {
2890
3100
  const summary = scheduler.getExitSummary();
2891
- scheduler.stop();
3101
+ this.#stopCronSchedulerInRuntime();
2892
3102
  if (summary) {
2893
3103
  await this.messageEmitter.emitAgentMessage(summary);
2894
3104
  }
2895
3105
  }
2896
3106
  }
2897
3107
  async prompt(params) {
3108
+ if (this.closing) {
3109
+ throw RequestError.invalidParams(void 0, "Session is closing");
3110
+ }
3111
+ await this.assertCanStartTurn();
2898
3112
  const todoStopGuardPreparation = this.#prepareTodoStopGuardForPrompt(params);
2899
3113
  this.pendingPrompt?.abort();
2900
3114
  const pendingSend = new AbortController();
@@ -2954,6 +3168,13 @@ var Session = class {
2954
3168
  void this.#drainNotificationQueue();
2955
3169
  this.#maybeEmitFollowupSuggestion(result);
2956
3170
  return result;
3171
+ } catch (error) {
3172
+ if (error instanceof SessionWriterError) {
3173
+ throw new RequestError(error.rpcCode, error.message, {
3174
+ errorKind: error.errorKind
3175
+ });
3176
+ }
3177
+ throw error;
2957
3178
  } finally {
2958
3179
  this.pendingPrompt = null;
2959
3180
  const shouldDrainAutomaticQueues = todoStopGuardPreparation.drainSupersededAutomaticQueues || this.todoStopGuardDrainAutomaticQueuesWhenIdle || this.todoStopGuard.blocksUnrelatedAutomaticTurns || this.todoStopGuard.hasCommittedContinuation || this.todoStopGuardQueuedPromptPriority;
@@ -2962,7 +3183,7 @@ var Session = class {
2962
3183
  void this.#drainCronQueue();
2963
3184
  void this.#drainNotificationQueue();
2964
3185
  }
2965
- void this.#startCronSchedulerIfNeeded();
3186
+ void this.#startCronSchedulerInRuntime();
2966
3187
  resolveCompletion();
2967
3188
  this.pendingPromptCompletion = null;
2968
3189
  }
@@ -3096,6 +3317,10 @@ var Session = class {
3096
3317
  this.runtimeBaseDir,
3097
3318
  this.config.getWorkingDir(),
3098
3319
  async () => {
3320
+ await this.assertCanStartTurn();
3321
+ if (pendingSend.signal.aborted) {
3322
+ return { stopReason: "cancelled" };
3323
+ }
3099
3324
  this.turn += 1;
3100
3325
  const promptId = this.config.getSessionId() + "########" + this.turn;
3101
3326
  const parentContext = extractDaemonTraceContext(params);
@@ -3162,6 +3387,9 @@ var Session = class {
3162
3387
  let parts;
3163
3388
  let fullTurnModelOverride;
3164
3389
  const onFullTurnModel = /* @__PURE__ */ __name((model) => {
3390
+ if (fullTurnModelOverride === model) {
3391
+ return true;
3392
+ }
3165
3393
  if (fullTurnModelOverride) {
3166
3394
  return false;
3167
3395
  }
@@ -3397,7 +3625,8 @@ ${this.pendingWorktreeNotice}
3397
3625
  pendingSend.signal,
3398
3626
  promptId,
3399
3627
  functionCalls,
3400
- toolLoopState
3628
+ toolLoopState,
3629
+ onFullTurnModel
3401
3630
  )
3402
3631
  );
3403
3632
  if (toolRun.stopAfterPermissionCancel) {
@@ -3406,7 +3635,11 @@ ${this.pendingWorktreeNotice}
3406
3635
  toolRun,
3407
3636
  pendingSend.signal
3408
3637
  );
3409
- return { stopReason: "end_turn" };
3638
+ return {
3639
+ stopReason: getAbortAwareEndTurnStopReason(
3640
+ pendingSend.signal
3641
+ )
3642
+ };
3410
3643
  }
3411
3644
  const nextAfterTools = await this.#buildNextMessageAfterToolRun(
3412
3645
  toolRun,
@@ -3420,7 +3653,11 @@ ${this.pendingWorktreeNotice}
3420
3653
  toolRun,
3421
3654
  pendingSend.signal
3422
3655
  );
3423
- return { stopReason: "end_turn" };
3656
+ return {
3657
+ stopReason: getAbortAwareEndTurnStopReason(
3658
+ pendingSend.signal
3659
+ )
3660
+ };
3424
3661
  }
3425
3662
  }
3426
3663
  }
@@ -3455,6 +3692,9 @@ ${this.pendingWorktreeNotice}
3455
3692
  let stopHookIterationCount = 0;
3456
3693
  let stopHookReasons = [];
3457
3694
  const onFullTurnModel = /* @__PURE__ */ __name((model) => {
3695
+ if (modelOverride === model) {
3696
+ return true;
3697
+ }
3458
3698
  if (modelOverride) {
3459
3699
  return false;
3460
3700
  }
@@ -3465,7 +3705,7 @@ ${this.pendingWorktreeNotice}
3465
3705
  while (true) {
3466
3706
  if (pendingSend.signal.aborted) {
3467
3707
  this.todoStopGuard.suspend();
3468
- return { stopReason: "end_turn" };
3708
+ return { stopReason: "cancelled" };
3469
3709
  }
3470
3710
  if (this.config.getApprovalMode() === "plan" /* PLAN */) {
3471
3711
  this.#clearTodoStopGuardTrustAndDrainAutomaticQueues();
@@ -3568,7 +3808,7 @@ ${this.pendingWorktreeNotice}
3568
3808
  await this.messageEmitter.emitAgentMessage(stopOutput.systemMessage);
3569
3809
  }
3570
3810
  if (stopOutput?.isBlockingDecision() || stopOutput?.shouldStopExecution()) {
3571
- externalReason = stopOutput.getEffectiveReason();
3811
+ externalReason = getStopHookContinuationReason(stopOutput);
3572
3812
  stopHookIterationCount++;
3573
3813
  stopHookReasons = [...stopHookReasons, externalReason];
3574
3814
  stopHookCount = response.stopHookCount ?? 1;
@@ -3907,7 +4147,8 @@ ${this.pendingWorktreeNotice}
3907
4147
  pendingSend.signal,
3908
4148
  toolPromptId,
3909
4149
  functionCalls,
3910
- toolLoopState
4150
+ toolLoopState,
4151
+ options.onFullTurnModel
3911
4152
  )
3912
4153
  );
3913
4154
  if (toolRun.stopAfterPermissionCancel || toolRun.loopDetected) {
@@ -3915,7 +4156,7 @@ ${this.pendingWorktreeNotice}
3915
4156
  await this.#preserveStoppedToolRun(toolRun, pendingSend.signal);
3916
4157
  return {
3917
4158
  kind: "terminal",
3918
- stopReason: "end_turn",
4159
+ stopReason: getAbortAwareEndTurnStopReason(pendingSend.signal),
3919
4160
  ...supersededAutomaticContinuation ? { supersededAutomaticContinuation: true } : {}
3920
4161
  };
3921
4162
  }
@@ -4164,13 +4405,18 @@ ${this.pendingWorktreeNotice}
4164
4405
  }
4165
4406
  }
4166
4407
  async #preserveStoppedToolRun(toolRun, abortSignal) {
4408
+ const midTurnParts = abortSignal.aborted ? await this.#buildMidTurnParts(
4409
+ this.#takeRecoveredMidTurnMessages(),
4410
+ abortSignal,
4411
+ { preserveFallbackOnAbort: true }
4412
+ ) : await this.#drainMidTurnUserMessages(abortSignal);
4167
4413
  this.#preserveUnsentMessageHistory(
4168
4414
  {
4169
4415
  role: "user",
4170
4416
  parts: [
4171
4417
  ...toolRun.parts,
4172
4418
  ...toolRun.loopDetected ? [{ text: LOOP_DETECTED_CONTEXT_MESSAGE }] : [],
4173
- ...await this.#drainMidTurnUserMessages(abortSignal)
4419
+ ...midTurnParts
4174
4420
  ]
4175
4421
  },
4176
4422
  true
@@ -4285,11 +4531,7 @@ ${this.pendingWorktreeNotice}
4285
4531
  const recovered = this.#takeRecoveredMidTurnMessages();
4286
4532
  if (this.midTurnDrainUnavailable) {
4287
4533
  return {
4288
- parts: await this.#buildMidTurnParts(
4289
- recovered,
4290
- abortSignal,
4291
- options.onFullTurnModel
4292
- ),
4534
+ parts: await this.#buildMidTurnParts(recovered, abortSignal, options),
4293
4535
  hasQueuedPrompt: false
4294
4536
  };
4295
4537
  }
@@ -4317,7 +4559,7 @@ ${this.pendingWorktreeNotice}
4317
4559
  parts: await this.#buildMidTurnParts(
4318
4560
  [...recovered, ...parseMidTurnDrainResponse(response)],
4319
4561
  abortSignal,
4320
- options.onFullTurnModel
4562
+ options
4321
4563
  ),
4322
4564
  hasQueuedPrompt: isRecord2(response) && response["hasQueuedPrompt"] === true
4323
4565
  };
@@ -4337,11 +4579,7 @@ ${this.pendingWorktreeNotice}
4337
4579
  `Mid-turn queue drain ${isPermanentError ? "permanently " : ""}unavailable [session ${this.sessionId}]: ${errorMessage}`
4338
4580
  );
4339
4581
  return {
4340
- parts: await this.#buildMidTurnParts(
4341
- recovered,
4342
- abortSignal,
4343
- options.onFullTurnModel
4344
- ),
4582
+ parts: await this.#buildMidTurnParts(recovered, abortSignal, options),
4345
4583
  hasQueuedPrompt: false
4346
4584
  };
4347
4585
  }
@@ -4401,7 +4639,7 @@ ${this.pendingWorktreeNotice}
4401
4639
  * happens on injection (here), so a message recovered from an earlier
4402
4640
  * timed-out drain is still recorded exactly once.
4403
4641
  */
4404
- async #buildMidTurnParts(messages, abortSignal, onFullTurnModel) {
4642
+ async #buildMidTurnParts(messages, abortSignal, options = {}) {
4405
4643
  const parts = [];
4406
4644
  for (const message of messages) {
4407
4645
  const displayText = message.kind === "text" ? message.message : message.displayText;
@@ -4411,13 +4649,19 @@ ${this.pendingWorktreeNotice}
4411
4649
  abortSignal,
4412
4650
  MID_TURN_QUEUE_RESOLVE_TIMEOUT_MS,
4413
4651
  (signal) => this.#resolvePrompt(message.content, signal, {
4414
- onFullTurnModel
4652
+ onFullTurnModel: options.onFullTurnModel
4415
4653
  })
4416
4654
  );
4417
4655
  } catch (messageError) {
4418
- if (abortSignal.aborted) return parts;
4419
- const errorMessage = this.#formatError(messageError);
4420
- debugLogger6.warn(`Failed to resolve mid-turn message: ${errorMessage}`);
4656
+ if (abortSignal.aborted && !options.preserveFallbackOnAbort) {
4657
+ return parts;
4658
+ }
4659
+ if (!abortSignal.aborted) {
4660
+ const errorMessage = this.#formatError(messageError);
4661
+ debugLogger6.warn(
4662
+ `Failed to resolve mid-turn message: ${errorMessage}`
4663
+ );
4664
+ }
4421
4665
  rawParts = [{ text: displayText }];
4422
4666
  if (message.kind === "structured" && hasInlineMediaContentBlock(message.content)) {
4423
4667
  rawParts.push({ text: MID_TURN_ATTACHMENT_PROCESSING_FAILURE_TEXT });
@@ -4459,6 +4703,20 @@ ${this.pendingWorktreeNotice}
4459
4703
  void this.#drainCronQueue();
4460
4704
  });
4461
4705
  }
4706
+ #startCronSchedulerInRuntime() {
4707
+ return Storage.runWithRuntimeBaseDir(
4708
+ this.runtimeBaseDir,
4709
+ this.config.getWorkingDir(),
4710
+ () => this.#startCronSchedulerIfNeeded()
4711
+ );
4712
+ }
4713
+ #stopCronSchedulerInRuntime() {
4714
+ Storage.runWithRuntimeBaseDir(
4715
+ this.runtimeBaseDir,
4716
+ this.config.getWorkingDir(),
4717
+ () => this.config.getCronScheduler().stop()
4718
+ );
4719
+ }
4462
4720
  #enqueueCronPrompt(item) {
4463
4721
  if ((this.todoStopGuard.blocksUnrelatedAutomaticTurns || this.todoStopGuardQueuedPromptPriority) && !this.#cronContinuesTodoStopGuardWorkChain(item)) {
4464
4722
  if (item.taskId) {
@@ -4489,10 +4747,24 @@ ${this.pendingWorktreeNotice}
4489
4747
  */
4490
4748
  async #drainCronQueue() {
4491
4749
  if (this.disposed) return;
4750
+ if (this.closing) return;
4492
4751
  if (this.cronProcessing) return;
4493
4752
  if (this.pendingPrompt) return;
4494
4753
  if (this.notificationProcessing) return;
4754
+ if (this.#deferAutomaticQueueDrainUntilTurnsSettle()) return;
4495
4755
  if (this.#nextCronQueueIndex() < 0) return;
4756
+ try {
4757
+ await this.assertCanStartTurn();
4758
+ } catch (error) {
4759
+ debugLogger6.warn(
4760
+ `Cron turn rejected [session ${this.sessionId}]: ${error instanceof Error ? error.message : String(error)}`
4761
+ );
4762
+ return;
4763
+ }
4764
+ if (this.disposed || this.closing || this.cronProcessing || this.pendingPrompt || this.notificationProcessing || this.#nextCronQueueIndex() < 0) {
4765
+ return;
4766
+ }
4767
+ if (this.#deferAutomaticQueueDrainUntilTurnsSettle()) return;
4496
4768
  this.cronProcessing = true;
4497
4769
  let resolveCompletion;
4498
4770
  this.cronCompletion = new Promise((resolve5) => {
@@ -4514,7 +4786,7 @@ ${this.pendingWorktreeNotice}
4514
4786
  if (this.config.isCronEnabled()) {
4515
4787
  const scheduler = this.config.getCronScheduler();
4516
4788
  if (!scheduler.hasPendingWork) {
4517
- scheduler.stop();
4789
+ this.#stopCronSchedulerInRuntime();
4518
4790
  }
4519
4791
  }
4520
4792
  }
@@ -4581,6 +4853,8 @@ ${this.pendingWorktreeNotice}
4581
4853
  async () => {
4582
4854
  let turnCount = 0;
4583
4855
  try {
4856
+ await this.assertCanStartTurn();
4857
+ if (ac.signal.aborted) return;
4584
4858
  const loopMode = detectLoopSentinel(prompt);
4585
4859
  const autonomousMode = loopMode ? null : detectAutonomousSentinel(prompt);
4586
4860
  let loopTick = null;
@@ -4910,12 +5184,26 @@ ${this.pendingWorktreeNotice}
4910
5184
  }
4911
5185
  async #drainNotificationQueue() {
4912
5186
  if (this.disposed) return;
5187
+ if (this.closing) return;
4913
5188
  if (this.notificationProcessing) return;
4914
5189
  if (this.pendingPrompt || this.cronProcessing || this.cronAbortController) {
4915
5190
  return;
4916
5191
  }
5192
+ if (this.#deferAutomaticQueueDrainUntilTurnsSettle()) return;
4917
5193
  if (this.notificationQueue.length === 0) return;
4918
5194
  if (this.#nextNotificationQueueIndex() < 0) return;
5195
+ try {
5196
+ await this.assertCanStartTurn();
5197
+ } catch (error) {
5198
+ debugLogger6.warn(
5199
+ `Notification turn rejected [session ${this.sessionId}]: ${error instanceof Error ? error.message : String(error)}`
5200
+ );
5201
+ return;
5202
+ }
5203
+ if (this.disposed || this.closing || this.notificationProcessing || this.pendingPrompt || this.cronProcessing || this.cronAbortController || this.#nextNotificationQueueIndex() < 0) {
5204
+ return;
5205
+ }
5206
+ if (this.#deferAutomaticQueueDrainUntilTurnsSettle()) return;
4919
5207
  this.notificationProcessing = true;
4920
5208
  let resolveCompletion;
4921
5209
  this.notificationCompletion = new Promise((resolve5) => {
@@ -4965,6 +5253,8 @@ ${this.pendingWorktreeNotice}
4965
5253
  );
4966
5254
  const promptId = this.config.getSessionId() + "########notification" + Date.now();
4967
5255
  try {
5256
+ await this.assertCanStartTurn();
5257
+ if (ac.signal.aborted) return;
4968
5258
  await this.#emitBackgroundNotificationDisplay(item);
4969
5259
  const notificationParts = [{ text: item.modelText }];
4970
5260
  this.config.getChatRecordingService()?.recordNotification(notificationParts, item.displayText);
@@ -5094,7 +5384,9 @@ ${this.pendingWorktreeNotice}
5094
5384
  if (toolRun.stopAfterPermissionCancel) {
5095
5385
  this.todoStopGuard.suspend();
5096
5386
  await this.#preserveStoppedToolRun(toolRun, ac.signal);
5097
- await this.#emitBackgroundNotificationEndTurn("end_turn");
5387
+ await this.#emitBackgroundNotificationEndTurn(
5388
+ getAbortAwareEndTurnStopReason(ac.signal)
5389
+ );
5098
5390
  return;
5099
5391
  }
5100
5392
  const nextAfterTools = await this.#buildNextMessageAfterToolRun(
@@ -5105,7 +5397,9 @@ ${this.pendingWorktreeNotice}
5105
5397
  if (toolRun.loopDetected) {
5106
5398
  this.todoStopGuard.suspend();
5107
5399
  await this.#preserveStoppedToolRun(toolRun, ac.signal);
5108
- await this.#emitBackgroundNotificationEndTurn("end_turn");
5400
+ await this.#emitBackgroundNotificationEndTurn(
5401
+ getAbortAwareEndTurnStopReason(ac.signal)
5402
+ );
5109
5403
  return;
5110
5404
  }
5111
5405
  }
@@ -5123,7 +5417,9 @@ ${this.pendingWorktreeNotice}
5123
5417
  false
5124
5418
  )).stopReason;
5125
5419
  }
5126
- await this.#emitBackgroundNotificationEndTurn(stopReason);
5420
+ await this.#emitBackgroundNotificationEndTurn(
5421
+ ac.signal.aborted ? "cancelled" : stopReason
5422
+ );
5127
5423
  } catch (error) {
5128
5424
  if (ac.signal.aborted) {
5129
5425
  this.todoStopGuard.suspend();
@@ -5414,10 +5710,48 @@ ${this.pendingWorktreeNotice}
5414
5710
  * sequential batch to preserve the implicit ordering the model may rely
5415
5711
  * on. Response-part ordering matches the original `functionCalls` order.
5416
5712
  */
5417
- async runToolCalls(abortSignal, promptId, functionCalls, toolLoopState) {
5713
+ async runToolCalls(abortSignal, promptId, functionCalls, toolLoopState, onFullTurnModel) {
5418
5714
  const dedupedFunctionCalls = dedupeToolCallsById(functionCalls);
5715
+ const generatedCallIdBase = randomUUID();
5716
+ const executionCallIds = new Map(
5717
+ dedupedFunctionCalls.map((functionCall, index) => [
5718
+ functionCall,
5719
+ functionCall.id ?? `${functionCall.name ?? "tool"}-${generatedCallIdBase}-${index}`
5720
+ ])
5721
+ );
5722
+ const pendingToolResultRecords = [];
5723
+ let toolResultRecordSequence = 0;
5724
+ const queueToolResultRecord = /* @__PURE__ */ __name((fc, record) => {
5725
+ pendingToolResultRecords.push({
5726
+ ...record,
5727
+ ordinal: dedupedFunctionCalls.indexOf(fc),
5728
+ sequence: toolResultRecordSequence++
5729
+ });
5730
+ }, "queueToolResultRecord");
5731
+ const finalizeRunToolResult = /* @__PURE__ */ __name(async (result) => {
5732
+ if (pendingToolResultRecords.length === 0) return result;
5733
+ const orderedRecords = [...pendingToolResultRecords].sort(
5734
+ (left, right) => left.ordinal - right.ordinal || left.sequence - right.sequence
5735
+ );
5736
+ const finalized = await finalizeToolResponses(
5737
+ this.config,
5738
+ orderedRecords.map((record) => ({
5739
+ callId: record.callId,
5740
+ toolName: record.toolName,
5741
+ responseParts: record.responseParts,
5742
+ persistedOutputFiles: record.persistedOutputFiles
5743
+ }))
5744
+ );
5745
+ orderedRecords.forEach((record, index) => {
5746
+ this.config.getChatRecordingService()?.recordToolResult(finalized[index].responseParts, record.metadata);
5747
+ });
5748
+ return {
5749
+ ...result,
5750
+ parts: finalized.flatMap((entry) => entry.responseParts)
5751
+ };
5752
+ }, "finalizeRunToolResult");
5419
5753
  let skippedToolCallCounter = 0;
5420
- const recordSkippedToolCall = /* @__PURE__ */ __name(async (fc, message = PERMISSION_CANCEL_SKIP_MESSAGE, emitStart = true) => {
5754
+ const recordSkippedToolCall = /* @__PURE__ */ __name(async (fc, message = PERMISSION_CANCEL_SKIP_MESSAGE, emitStart = true, errorType) => {
5421
5755
  const toolName = fc.name ?? "unknown_tool";
5422
5756
  const callId = fc.id ?? `${toolName}-skip-${++skippedToolCallCounter}`;
5423
5757
  const part = {
@@ -5429,12 +5763,17 @@ ${this.pendingWorktreeNotice}
5429
5763
  };
5430
5764
  const error = new Error(message);
5431
5765
  try {
5432
- this.config.getChatRecordingService()?.recordToolResult([part], {
5766
+ queueToolResultRecord(fc, {
5433
5767
  callId,
5434
- status: "error",
5435
- resultDisplay: void 0,
5436
- error,
5437
- errorType: void 0
5768
+ toolName,
5769
+ responseParts: [part],
5770
+ metadata: {
5771
+ callId,
5772
+ status: "error",
5773
+ resultDisplay: void 0,
5774
+ error,
5775
+ errorType
5776
+ }
5438
5777
  });
5439
5778
  if (emitStart) {
5440
5779
  await this.toolCallEmitter.emitStart({
@@ -5456,7 +5795,7 @@ ${this.pendingWorktreeNotice}
5456
5795
  toolLoopState,
5457
5796
  dedupedFunctionCalls.length
5458
5797
  )) {
5459
- return {
5798
+ return await finalizeRunToolResult({
5460
5799
  parts: await Promise.all(
5461
5800
  dedupedFunctionCalls.map(
5462
5801
  (fc) => recordSkippedToolCall(fc, LOOP_DETECTED_SKIP_MESSAGE, false)
@@ -5464,7 +5803,7 @@ ${this.pendingWorktreeNotice}
5464
5803
  ),
5465
5804
  stopAfterPermissionCancel: false,
5466
5805
  loopDetected: true
5467
- };
5806
+ });
5468
5807
  }
5469
5808
  const batches = [];
5470
5809
  const handledProviderToolCallIds = new Set(
@@ -5481,13 +5820,13 @@ ${this.pendingWorktreeNotice}
5481
5820
  debugLogger6.debug(
5482
5821
  `[Session.runToolCalls] Dropping batch after repeated duplicate provider tool-call id: ${providerCallId} (tool: ${repeatedDuplicateCall.name ?? "unknown_tool"})`
5483
5822
  );
5484
- return {
5823
+ return await finalizeRunToolResult({
5485
5824
  parts: [],
5486
5825
  stopAfterPermissionCancel: false,
5487
5826
  repeatedDuplicateProviderToolCall: true
5488
- };
5827
+ });
5489
5828
  }
5490
- const pushDuplicateBatch = /* @__PURE__ */ __name((request) => {
5829
+ const pushDuplicateBatch = /* @__PURE__ */ __name((fc, request) => {
5491
5830
  const providerCallId = request.providerCallId ?? request.callId;
5492
5831
  markDuplicateProviderToolCallResponseSent(
5493
5832
  providerCallId,
@@ -5497,7 +5836,7 @@ ${this.pendingWorktreeNotice}
5497
5836
  debugLogger6.debug(
5498
5837
  `[Session.runToolCalls] Suppressing duplicate provider tool-call id: ${providerCallId} (tool: ${request.name})`
5499
5838
  );
5500
- batches.push({ kind: "duplicate", request, response });
5839
+ batches.push({ kind: "duplicate", fc, request, response });
5501
5840
  }, "pushDuplicateBatch");
5502
5841
  const emitDuplicateBatch = /* @__PURE__ */ __name(async (batch) => {
5503
5842
  const { request, response } = batch;
@@ -5534,20 +5873,26 @@ ${this.pendingWorktreeNotice}
5534
5873
  success: false
5535
5874
  });
5536
5875
  }
5537
- this.config.getChatRecordingService()?.recordToolResult(response.responseParts, {
5876
+ queueToolResultRecord(batch.fc, {
5538
5877
  callId: response.callId,
5539
- status: "error",
5540
- resultDisplay: response.resultDisplay,
5541
- error: response.error,
5542
- errorType: response.errorType
5878
+ toolName: request.name,
5879
+ responseParts: response.responseParts,
5880
+ persistedOutputFiles: response.persistedOutputFiles,
5881
+ metadata: {
5882
+ callId: response.callId,
5883
+ status: "error",
5884
+ resultDisplay: response.resultDisplay,
5885
+ error: response.error,
5886
+ errorType: response.errorType
5887
+ }
5543
5888
  });
5544
5889
  }, "emitDuplicateBatch");
5545
5890
  for (const fc of dedupedFunctionCalls) {
5546
5891
  const providerCallId = getProviderToolCallId(fc) ?? fc.id;
5547
5892
  if (providerCallId) {
5548
5893
  if (handledProviderToolCallIds.has(providerCallId)) {
5549
- const callId = fc.id ?? `${fc.name}-${Date.now()}`;
5550
- pushDuplicateBatch({
5894
+ const callId = executionCallIds.get(fc);
5895
+ pushDuplicateBatch(fc, {
5551
5896
  callId,
5552
5897
  providerCallId,
5553
5898
  name: fc.name ?? "unknown_tool",
@@ -5567,6 +5912,13 @@ ${this.pendingWorktreeNotice}
5567
5912
  batches.push({ kind: "execute", concurrent: isAgent, calls: [fc] });
5568
5913
  }
5569
5914
  }
5915
+ const executableCalls = batches.flatMap(
5916
+ (batch) => batch.kind === "execute" ? batch.calls : []
5917
+ );
5918
+ const planModeEntryBoundaryIndex = findPlanModeEntryBatchBoundaryIndex(
5919
+ executableCalls.map((call) => call.name)
5920
+ );
5921
+ const planModeEntryBoundary = planModeEntryBoundaryIndex === void 0 ? void 0 : executableCalls[planModeEntryBoundaryIndex];
5570
5922
  const appendSkippedAfter = /* @__PURE__ */ __name(async (parts2, fc, message = PERMISSION_CANCEL_SKIP_MESSAGE) => {
5571
5923
  const startIndex = dedupedFunctionCalls.indexOf(fc) + 1;
5572
5924
  for (const remainingCall of dedupedFunctionCalls.slice(startIndex)) {
@@ -5633,7 +5985,10 @@ ${this.pendingWorktreeNotice}
5633
5985
  calls[i],
5634
5986
  onStopAfterPermissionCancel,
5635
5987
  toolLoopState,
5636
- recordSkippedToolCall
5988
+ recordSkippedToolCall,
5989
+ queueToolResultRecord,
5990
+ executionCallIds.get(calls[i]),
5991
+ onFullTurnModel
5637
5992
  );
5638
5993
  results[i] = r;
5639
5994
  if (r.loopDetected) {
@@ -5665,7 +6020,10 @@ ${this.pendingWorktreeNotice}
5665
6020
  calls[idx],
5666
6021
  onStopAfterPermissionCancel,
5667
6022
  toolLoopState,
5668
- recordSkippedToolCall
6023
+ recordSkippedToolCall,
6024
+ queueToolResultRecord,
6025
+ executionCallIds.get(calls[idx]),
6026
+ onFullTurnModel
5669
6027
  ).then((r) => {
5670
6028
  results[idx] = r;
5671
6029
  }).finally(() => {
@@ -5704,6 +6062,19 @@ ${this.pendingWorktreeNotice}
5704
6062
  parts.push(...batch.response.responseParts);
5705
6063
  continue;
5706
6064
  }
6065
+ if (planModeEntryBoundary && !batch.calls.includes(planModeEntryBoundary)) {
6066
+ for (const fc of batch.calls) {
6067
+ parts.push(
6068
+ await recordSkippedToolCall(
6069
+ fc,
6070
+ PLAN_MODE_ENTRY_SIBLING_SKIP_MESSAGE,
6071
+ true,
6072
+ "execution_denied" /* EXECUTION_DENIED */
6073
+ )
6074
+ );
6075
+ }
6076
+ continue;
6077
+ }
5707
6078
  if (batch.concurrent && batch.calls.length > 1) {
5708
6079
  const batchAbortController = new AbortController();
5709
6080
  let batchStopAfterPermissionCancel = false;
@@ -5747,24 +6118,24 @@ ${this.pendingWorktreeNotice}
5747
6118
  batch.calls[batch.calls.length - 1],
5748
6119
  LOOP_DETECTED_SKIP_MESSAGE
5749
6120
  );
5750
- return {
6121
+ return await finalizeRunToolResult({
5751
6122
  parts,
5752
6123
  stopAfterPermissionCancel: false,
5753
6124
  loopDetected: true,
5754
6125
  memoryWriteCandidates
5755
- };
6126
+ });
5756
6127
  }
5757
6128
  if (shouldStop) {
5758
6129
  await appendSkippedAfter(
5759
6130
  parts,
5760
6131
  batch.calls[batch.calls.length - 1]
5761
6132
  );
5762
- return {
6133
+ return await finalizeRunToolResult({
5763
6134
  parts,
5764
6135
  stopAfterPermissionCancel: true,
5765
6136
  repeatedDuplicateProviderToolCall: false,
5766
6137
  memoryWriteCandidates
5767
- };
6138
+ });
5768
6139
  }
5769
6140
  } else {
5770
6141
  for (const fc of batch.calls) {
@@ -5774,37 +6145,40 @@ ${this.pendingWorktreeNotice}
5774
6145
  fc,
5775
6146
  void 0,
5776
6147
  toolLoopState,
5777
- recordSkippedToolCall
6148
+ recordSkippedToolCall,
6149
+ queueToolResultRecord,
6150
+ executionCallIds.get(fc),
6151
+ onFullTurnModel
5778
6152
  );
5779
6153
  parts.push(...r.parts);
5780
6154
  collectMemoryWriteCandidates(r);
5781
6155
  if (r.loopDetected) {
5782
6156
  await appendSkippedAfter(parts, fc, LOOP_DETECTED_SKIP_MESSAGE);
5783
- return {
6157
+ return await finalizeRunToolResult({
5784
6158
  parts,
5785
6159
  stopAfterPermissionCancel: false,
5786
6160
  loopDetected: true,
5787
6161
  memoryWriteCandidates
5788
- };
6162
+ });
5789
6163
  }
5790
6164
  if (r.stopAfterPermissionCancel) {
5791
6165
  await appendSkippedAfter(parts, fc);
5792
- return {
6166
+ return await finalizeRunToolResult({
5793
6167
  parts,
5794
6168
  stopAfterPermissionCancel: true,
5795
6169
  repeatedDuplicateProviderToolCall: false,
5796
6170
  memoryWriteCandidates
5797
- };
6171
+ });
5798
6172
  }
5799
6173
  }
5800
6174
  }
5801
6175
  }
5802
- return {
6176
+ return await finalizeRunToolResult({
5803
6177
  parts,
5804
6178
  stopAfterPermissionCancel: false,
5805
6179
  repeatedDuplicateProviderToolCall: false,
5806
6180
  memoryWriteCandidates
5807
- };
6181
+ });
5808
6182
  } finally {
5809
6183
  await refreshMemoryIfNeeded();
5810
6184
  }
@@ -5839,8 +6213,8 @@ ${this.pendingWorktreeNotice}
5839
6213
  }
5840
6214
  return reminders;
5841
6215
  }
5842
- async runTool(abortSignal, promptId, fc, onStopAfterPermissionCancel, toolLoopState, recordSkippedToolCall) {
5843
- const callId = fc.id ?? `${fc.name}-${Date.now()}`;
6216
+ async runTool(abortSignal, promptId, fc, onStopAfterPermissionCancel, toolLoopState, recordSkippedToolCall, queueToolResultRecord, generatedCallId, onFullTurnModel) {
6217
+ const callId = fc.id ?? generatedCallId ?? `${fc.name}-${Date.now()}`;
5844
6218
  let args = fc.args ?? {};
5845
6219
  if (toolLoopState?.loopDetected) {
5846
6220
  return {
@@ -5902,12 +6276,17 @@ ${this.pendingWorktreeNotice}
5902
6276
  await this.toolCallEmitter.emitError(callId, toolName2, error);
5903
6277
  }
5904
6278
  const errorParts = errorResponse(error);
5905
- this.config.getChatRecordingService()?.recordToolResult(errorParts, {
6279
+ queueToolResultRecord?.(fc, {
5906
6280
  callId,
5907
- status: "error",
5908
- resultDisplay: void 0,
5909
- error,
5910
- errorType: void 0
6281
+ toolName: toolName2,
6282
+ responseParts: errorParts,
6283
+ metadata: {
6284
+ callId,
6285
+ status: "error",
6286
+ resultDisplay: void 0,
6287
+ error,
6288
+ errorType: void 0
6289
+ }
5911
6290
  });
5912
6291
  const loopDetected = opts?.recordInvalidToolParams === true && !activeToolAbortSignal.aborted && !opts?.stopAfterPermissionCancel && recordDaemonInvalidToolParams(
5913
6292
  this.config,
@@ -5937,19 +6316,21 @@ ${this.pendingWorktreeNotice}
5937
6316
  { recordInvalidToolParams: true }
5938
6317
  );
5939
6318
  }
5940
- const toolSpan = startToolSpan(toolName, {
6319
+ const policyToolName = tool.name;
6320
+ const originalPolicyRequestArgs = policyToolName === ToolNames.SHELL || policyToolName === ToolNames.MONITOR ? structuredClone(args) : args;
6321
+ const toolSpan = startToolSpan(policyToolName, {
5941
6322
  "tool.call_id": callId,
5942
6323
  // Dual-emit the legacy call_id/tool_name aliases like CoreToolScheduler
5943
6324
  // (coreToolScheduler.ts) so pre-Phase-2 dashboards keyed off call_id keep
5944
6325
  // matching daemon/ACP tool spans during the migration window.
5945
6326
  call_id: callId,
5946
- tool_name: toolName
6327
+ tool_name: policyToolName
5947
6328
  });
5948
6329
  let spanSuccess = false;
5949
6330
  try {
5950
6331
  return await runInToolSpanContext(toolSpan, async () => {
5951
6332
  const pm = this.config.getPermissionManager?.();
5952
- if (pm && !await pm.isToolEnabled(toolName)) {
6333
+ if (pm && !await pm.isToolEnabled(policyToolName)) {
5953
6334
  return earlyErrorResponse(
5954
6335
  new Error(`Tool "${toolName}" is disabled.`),
5955
6336
  toolName
@@ -5978,7 +6359,7 @@ ${this.pendingWorktreeNotice}
5978
6359
  }
5979
6360
  }
5980
6361
  const toolUseId = generateToolUseId();
5981
- const approvalMode = this.config.getApprovalMode();
6362
+ let approvalMode = this.config.getApprovalMode();
5982
6363
  let toolBuildSucceeded = false;
5983
6364
  try {
5984
6365
  const invocation = tool.build(args);
@@ -6003,12 +6384,12 @@ ${this.pendingWorktreeNotice}
6003
6384
  activeToolAbortSignal
6004
6385
  );
6005
6386
  }
6006
- const isAskUserQuestionTool = toolName === ToolNames.ASK_USER_QUESTION;
6007
- const toolParams = invocation.params;
6387
+ const isAskUserQuestionTool = policyToolName === ToolNames.ASK_USER_QUESTION;
6388
+ let toolParams = invocation.params;
6008
6389
  const flowResult = await evaluatePermissionFlow(
6009
6390
  this.config,
6010
6391
  invocation,
6011
- toolName,
6392
+ policyToolName,
6012
6393
  toolParams
6013
6394
  );
6014
6395
  const {
@@ -6018,31 +6399,75 @@ ${this.pendingWorktreeNotice}
6018
6399
  denyMessage,
6019
6400
  requiresUserInteraction
6020
6401
  } = flowResult;
6402
+ approvalMode = this.config.getApprovalMode();
6021
6403
  const isPlanMode = approvalMode === "plan" /* PLAN */;
6404
+ const isPlanShellCall = isPlanMode && (policyToolName === ToolNames.SHELL || policyToolName === ToolNames.MONITOR);
6022
6405
  if (finalPermission === "deny") {
6023
6406
  return earlyErrorResponse(
6024
6407
  new Error(denyMessage ?? `Tool "${toolName}" is denied.`),
6025
6408
  toolName
6026
6409
  );
6027
6410
  }
6028
- const forceAutoReviewForAllow = approvalMode === "auto" /* AUTO */ && (shouldForceAutoModeReviewForAllow(pmCtx, this.config.getCwd()) || shouldClassifyAllShellForAutoMode(toolName, this.config));
6411
+ let planShellAmbientWorkingDirectory;
6412
+ if (isPlanShellCall) {
6413
+ const directory = toolParams["directory"];
6414
+ planShellAmbientWorkingDirectory = typeof directory === "string" && directory.length > 0 ? void 0 : this.config.getTargetDir();
6415
+ invocation.params = {
6416
+ ...structuredClone(invocation.params),
6417
+ directory: typeof directory === "string" && directory.length > 0 ? directory : planShellAmbientWorkingDirectory
6418
+ };
6419
+ toolParams = invocation.params;
6420
+ }
6421
+ const planShellDecision = isPlanShellCall ? await evaluatePlanModeShellPolicy({
6422
+ config: this.config,
6423
+ toolName: policyToolName,
6424
+ requestArgs: originalPolicyRequestArgs,
6425
+ invocationParams: toolParams,
6426
+ permissionContext: pmCtx,
6427
+ ambientWorkingDirectory: planShellAmbientWorkingDirectory,
6428
+ signal: activeToolAbortSignal
6429
+ }) : { classification: "not-applicable" };
6430
+ if (planShellDecision.classification !== "not-applicable") {
6431
+ const initialPlanShellError = await validatePlanModeShellContext({
6432
+ config: this.config,
6433
+ decision: planShellDecision,
6434
+ requestArgs: args,
6435
+ invocationParams: invocation.params,
6436
+ signal: activeToolAbortSignal
6437
+ });
6438
+ if (initialPlanShellError) {
6439
+ return earlyErrorResponse(
6440
+ new Error(initialPlanShellError),
6441
+ toolName
6442
+ );
6443
+ }
6444
+ }
6445
+ if (planShellDecision.classification === "write") {
6446
+ return earlyErrorResponse(
6447
+ new Error(planShellDecision.writeBlockMessage),
6448
+ toolName
6449
+ );
6450
+ }
6451
+ const planShellRequiresConfirmation = planShellDecision.classification === "unknown";
6452
+ const forceAutoReviewForAllow = approvalMode === "auto" /* AUTO */ && (shouldForceAutoModeReviewForAllow(pmCtx, this.config.getCwd()) || shouldClassifyAllShellForAutoMode(policyToolName, this.config));
6029
6453
  const confirmationPermission = getEffectivePermissionForConfirmation(
6030
6454
  finalPermission,
6031
6455
  forceAutoReviewForAllow
6032
6456
  );
6033
6457
  if (finalPermission === "allow" && forceAutoReviewForAllow) {
6034
6458
  debugLogger6.info(
6035
- `Auto mode: L4 allow overridden by protected-write guard for ${toolName}`
6459
+ `Auto mode: L4 allow overridden by protected-write guard for ${policyToolName}`
6036
6460
  );
6037
6461
  }
6038
- let autoModeAllowed = finalPermission === "allow" && !forceAutoReviewForAllow;
6462
+ let autoModeAllowed = finalPermission === "allow" && !forceAutoReviewForAllow && !planShellRequiresConfirmation;
6039
6463
  if (autoModeAllowed && approvalMode === "auto" /* AUTO */) {
6040
6464
  this.config.setAutoModeDenialState(
6041
6465
  recordAllow(this.config.getAutoModeDenialState())
6042
6466
  );
6043
6467
  }
6044
- let wasAutoModeDenialFallback = false;
6045
- if (!autoModeAllowed && !requiresUserInteraction && shouldRunAutoModeForCall(approvalMode, toolName)) {
6468
+ let wasAutoModeManualFallback = false;
6469
+ let autoModeFallbackMessage;
6470
+ if (!autoModeAllowed && !requiresUserInteraction && shouldRunAutoModeForCall(approvalMode, policyToolName)) {
6046
6471
  const denialState = this.config.getAutoModeDenialState();
6047
6472
  const fallback = shouldFallback(denialState);
6048
6473
  const messages = this.config.getGeminiClient?.()?.getHistoryTail(MAX_TRANSCRIPT_MESSAGES, false) ?? [];
@@ -6064,7 +6489,7 @@ ${this.pendingWorktreeNotice}
6064
6489
  this.config,
6065
6490
  decision,
6066
6491
  outcome,
6067
- toolName,
6492
+ policyToolName,
6068
6493
  toolParams,
6069
6494
  callId,
6070
6495
  abortSignal
@@ -6075,17 +6500,16 @@ ${this.pendingWorktreeNotice}
6075
6500
  break;
6076
6501
  case "blocked":
6077
6502
  debugLogger6.warn(
6078
- `Auto mode blocked (${outcome.reason}): tool=${toolName}, ` + formatDenialStateLog(denialState)
6503
+ `Auto mode blocked (${outcome.reason}): tool=${policyToolName}, ` + formatDenialStateLog(denialState)
6079
6504
  );
6080
6505
  return earlyErrorResponse(
6081
6506
  new Error(outcome.errorMessage),
6082
6507
  toolName
6083
6508
  );
6084
6509
  case "fallback":
6085
- wasAutoModeDenialFallback = isDenialFallbackReason(
6086
- outcome.reason
6087
- );
6088
- if (wasAutoModeDenialFallback) {
6510
+ wasAutoModeManualFallback = isDenialFallbackReason(outcome.reason) || outcome.reason === "classifier_unavailable";
6511
+ autoModeFallbackMessage = outcome.message;
6512
+ if (wasAutoModeManualFallback) {
6089
6513
  debugLogger6.warn(
6090
6514
  `Auto mode fallback to manual approval (${outcome.reason}): ` + formatDenialStateLog(denialState)
6091
6515
  );
@@ -6100,7 +6524,7 @@ ${this.pendingWorktreeNotice}
6100
6524
  let didRequestPermission = false;
6101
6525
  let confirmationDetails;
6102
6526
  const recordAutoModeFallbackResolution = /* @__PURE__ */ __name((outcome) => {
6103
- if (approvalMode === "auto" /* AUTO */ && wasAutoModeDenialFallback && isApproveOutcome(outcome)) {
6527
+ if (approvalMode === "auto" /* AUTO */ && wasAutoModeManualFallback && isApproveOutcome(outcome)) {
6104
6528
  const before = this.config.getAutoModeDenialState();
6105
6529
  const after = recordFallbackApprove(before);
6106
6530
  if (after === before) {
@@ -6116,14 +6540,51 @@ ${this.pendingWorktreeNotice}
6116
6540
  }
6117
6541
  }, "recordAutoModeFallbackResolution");
6118
6542
  if (!autoModeAllowed && needsConfirmation(
6119
- confirmationPermission,
6543
+ planShellRequiresConfirmation ? "ask" : confirmationPermission,
6120
6544
  approvalMode,
6121
- toolName,
6545
+ policyToolName,
6122
6546
  requiresUserInteraction
6123
6547
  )) {
6124
- confirmationDetails = await invocation.getConfirmationDetails(abortSignal);
6548
+ confirmationDetails = await invocation.getConfirmationDetails(
6549
+ activeToolAbortSignal
6550
+ );
6551
+ if (autoModeFallbackMessage) {
6552
+ confirmationDetails = decorateClassifierUnavailableConfirmation(
6553
+ confirmationDetails,
6554
+ autoModeFallbackMessage
6555
+ );
6556
+ }
6557
+ if (planShellDecision.classification !== "not-applicable") {
6558
+ const preDisplayPlanShellError = await validatePlanModeShellContext({
6559
+ config: this.config,
6560
+ decision: planShellDecision,
6561
+ requestArgs: args,
6562
+ invocationParams: invocation.params,
6563
+ signal: activeToolAbortSignal
6564
+ });
6565
+ if (preDisplayPlanShellError) {
6566
+ return earlyErrorResponse(
6567
+ new Error(preDisplayPlanShellError),
6568
+ toolName
6569
+ );
6570
+ }
6571
+ }
6572
+ try {
6573
+ confirmationDetails = decoratePlanModeShellConfirmation(
6574
+ planShellDecision,
6575
+ confirmationDetails
6576
+ );
6577
+ } catch {
6578
+ if (planShellDecision.classification === "unknown") {
6579
+ return earlyErrorResponse(
6580
+ new Error(planShellDecision.noApprovalMessage),
6581
+ toolName
6582
+ );
6583
+ }
6584
+ throw new Error("Unable to prepare shell confirmation.");
6585
+ }
6125
6586
  injectPermissionRulesIfMissing(confirmationDetails, pmCtx);
6126
- if (isPlanModeBlocked(
6587
+ if (planShellDecision.classification === "not-applicable" && isPlanModeBlocked(
6127
6588
  isPlanMode,
6128
6589
  isExitPlanModeTool,
6129
6590
  isAskUserQuestionTool,
@@ -6143,23 +6604,50 @@ ${this.pendingWorktreeNotice}
6143
6604
  if (hooksEnabled && messageBus) {
6144
6605
  const hookResult = await firePermissionRequestHook(
6145
6606
  messageBus,
6146
- toolName,
6607
+ policyToolName,
6147
6608
  args,
6148
- String(approvalMode)
6609
+ String(approvalMode),
6610
+ void 0,
6611
+ activeToolAbortSignal
6149
6612
  );
6150
6613
  if (hookResult.hasDecision && (!hookResult.shouldAllow || !requiresUserInteraction)) {
6151
6614
  hookHandled = true;
6152
6615
  if (hookResult.shouldAllow) {
6153
- if (hookResult.updatedInput) {
6154
- args = hookResult.updatedInput;
6155
- invocation.params = hookResult.updatedInput;
6616
+ if (planShellDecision.classification !== "not-applicable") {
6617
+ const approval = await validatePlanModeShellApproval({
6618
+ config: this.config,
6619
+ decision: planShellDecision,
6620
+ requestArgs: args,
6621
+ invocationParams: invocation.params,
6622
+ signal: activeToolAbortSignal,
6623
+ outcome: "proceed_once" /* ProceedOnce */,
6624
+ payload: hookResult.updatedInput ? { updatedInput: hookResult.updatedInput } : void 0
6625
+ });
6626
+ await confirmationDetails.onConfirm(
6627
+ approval.outcome,
6628
+ approval.payload
6629
+ );
6630
+ if (approval.outcome === "cancel" /* Cancel */) {
6631
+ return earlyErrorResponse(
6632
+ new Error(
6633
+ approval.payload?.cancelMessage ?? planShellDecision.noApprovalMessage
6634
+ ),
6635
+ toolName
6636
+ );
6637
+ }
6638
+ recordAutoModeFallbackResolution(approval.outcome);
6639
+ } else {
6640
+ if (hookResult.updatedInput) {
6641
+ args = hookResult.updatedInput;
6642
+ invocation.params = hookResult.updatedInput;
6643
+ }
6644
+ await confirmationDetails.onConfirm(
6645
+ "proceed_once" /* ProceedOnce */
6646
+ );
6647
+ recordAutoModeFallbackResolution(
6648
+ "proceed_once" /* ProceedOnce */
6649
+ );
6156
6650
  }
6157
- await confirmationDetails.onConfirm(
6158
- "proceed_once" /* ProceedOnce */
6159
- );
6160
- recordAutoModeFallbackResolution(
6161
- "proceed_once" /* ProceedOnce */
6162
- );
6163
6651
  } else {
6164
6652
  return earlyErrorResponse(
6165
6653
  new Error(
@@ -6172,11 +6660,26 @@ ${this.pendingWorktreeNotice}
6172
6660
  }
6173
6661
  if (!requiresUserInteraction && approvalMode === "auto-edit" /* AUTO_EDIT */ && (confirmationDetails.type === "edit" || confirmationDetails.type === "info")) {
6174
6662
  } else if (!hookHandled) {
6663
+ if (planShellDecision.classification !== "not-applicable") {
6664
+ const finalPreDisplayPlanShellError = await validatePlanModeShellContext({
6665
+ config: this.config,
6666
+ decision: planShellDecision,
6667
+ requestArgs: args,
6668
+ invocationParams: invocation.params,
6669
+ signal: activeToolAbortSignal
6670
+ });
6671
+ if (finalPreDisplayPlanShellError) {
6672
+ return earlyErrorResponse(
6673
+ new Error(finalPreDisplayPlanShellError),
6674
+ toolName
6675
+ );
6676
+ }
6677
+ }
6175
6678
  didRequestPermission = true;
6176
6679
  const content = buildPermissionRequestContent(confirmationDetails);
6177
6680
  const mappedKind = this.toolCallEmitter.mapToolKind(
6178
6681
  tool.kind,
6179
- toolName
6682
+ policyToolName
6180
6683
  );
6181
6684
  if (hooksEnabled && messageBus) {
6182
6685
  this.fireNotificationHookWithTerminalSequence(
@@ -6186,9 +6689,16 @@ ${this.pendingWorktreeNotice}
6186
6689
  "Permission needed"
6187
6690
  );
6188
6691
  }
6692
+ const permissionOptions = toPermissionOptions(
6693
+ confirmationDetails,
6694
+ pmForcedAsk
6695
+ );
6696
+ const offeredPermissionOptions = permissionOptions.map(
6697
+ (option) => ({ ...option })
6698
+ );
6189
6699
  const params = {
6190
6700
  sessionId: this.sessionId,
6191
- options: toPermissionOptions(confirmationDetails, pmForcedAsk),
6701
+ options: permissionOptions,
6192
6702
  toolCall: {
6193
6703
  toolCallId: callId,
6194
6704
  status: "pending",
@@ -6207,10 +6717,12 @@ ${this.pendingWorktreeNotice}
6207
6717
  }
6208
6718
  }
6209
6719
  };
6210
- const stopAfterPermissionCancel = /* @__PURE__ */ __name(() => {
6720
+ const stopAfterPermissionCancel = /* @__PURE__ */ __name((message) => {
6211
6721
  onStopAfterPermissionCancel?.();
6212
6722
  return earlyErrorResponse(
6213
- new Error(`Tool "${toolName}" was canceled by the user.`),
6723
+ new Error(
6724
+ message ?? `Tool "${toolName}" was canceled by the user.`
6725
+ ),
6214
6726
  toolName,
6215
6727
  { stopAfterPermissionCancel: true }
6216
6728
  );
@@ -6218,10 +6730,15 @@ ${this.pendingWorktreeNotice}
6218
6730
  let output;
6219
6731
  let outcome;
6220
6732
  try {
6221
- output = await this.client.requestPermission(
6222
- params
6733
+ output = await requestPermissionWithAbort(
6734
+ this.client,
6735
+ params,
6736
+ activeToolAbortSignal
6737
+ );
6738
+ outcome = resolvePermissionOutcome(
6739
+ output,
6740
+ offeredPermissionOptions
6223
6741
  );
6224
- outcome = output.outcome.outcome === "cancelled" ? "cancel" /* Cancel */ : external_exports.nativeEnum(ToolConfirmationOutcome).parse(output.outcome.optionId);
6225
6742
  } catch (error) {
6226
6743
  debugLogger6.error(
6227
6744
  `Permission request failed for tool ${toolName}:`,
@@ -6238,7 +6755,9 @@ ${this.pendingWorktreeNotice}
6238
6755
  );
6239
6756
  }
6240
6757
  onStopAfterPermissionCancel?.();
6241
- const permissionFailureMessage = isExitPlanModeTool ? "The host could not present plan-exit approval. Plan mode remains active; use the host mode selector or /plan exit to leave plan mode." : `Permission request failed for "${toolName}": ${this.#formatError(
6758
+ const permissionFailureMessage = isExitPlanModeTool ? "The host could not present plan-exit approval. Plan mode remains active; use the host mode selector or /plan exit to leave plan mode." : planShellDecision.classification === "unknown" ? `Plan mode could not complete approval for this shell command: ${this.#formatError(
6759
+ error
6760
+ )}. The command was not run; Plan mode remains active.` : `Permission request failed for "${toolName}": ${this.#formatError(
6242
6761
  error
6243
6762
  )}`;
6244
6763
  return earlyErrorResponse(
@@ -6247,11 +6766,32 @@ ${this.pendingWorktreeNotice}
6247
6766
  { stopAfterPermissionCancel: true }
6248
6767
  );
6249
6768
  }
6769
+ let confirmationPayload = {
6770
+ answers: output.answers
6771
+ };
6772
+ if (planShellDecision.classification !== "not-applicable") {
6773
+ const approval = await validatePlanModeShellApproval({
6774
+ config: this.config,
6775
+ decision: planShellDecision,
6776
+ requestArgs: args,
6777
+ invocationParams: invocation.params,
6778
+ signal: activeToolAbortSignal,
6779
+ outcome,
6780
+ payload: confirmationPayload
6781
+ });
6782
+ outcome = approval.outcome;
6783
+ confirmationPayload = approval.payload;
6784
+ }
6785
+ const shouldSwitchToDefault = outcome === "proceed_once_and_switch_to_default" /* ProceedOnceAndSwitchToDefault */;
6786
+ if (shouldSwitchToDefault) {
6787
+ outcome = "proceed_once" /* ProceedOnce */;
6788
+ }
6250
6789
  recordAutoModeFallbackResolution(outcome);
6251
6790
  try {
6252
- await confirmationDetails.onConfirm(outcome, {
6253
- answers: output.answers
6254
- });
6791
+ await confirmationDetails.onConfirm(
6792
+ outcome,
6793
+ confirmationPayload
6794
+ );
6255
6795
  } catch (error) {
6256
6796
  if (outcome !== "cancel" /* Cancel */) {
6257
6797
  throw error;
@@ -6262,21 +6802,31 @@ ${this.pendingWorktreeNotice}
6262
6802
  );
6263
6803
  return stopAfterPermissionCancel();
6264
6804
  }
6805
+ if (shouldSwitchToDefault) {
6806
+ this.config.setApprovalMode("default" /* DEFAULT */);
6807
+ await this.sendCurrentModeUpdateNotification();
6808
+ }
6265
6809
  if (outcome === "proceed_always" /* ProceedAlways */ || outcome === "proceed_always_project" /* ProceedAlwaysProject */ || outcome === "proceed_always_user" /* ProceedAlwaysUser */) {
6266
6810
  await persistPermissionOutcome(
6267
6811
  outcome,
6268
6812
  confirmationDetails,
6269
6813
  this.config.getOnPersistPermissionRule?.(),
6270
6814
  this.config.getPermissionManager?.(),
6271
- { answers: output.answers }
6815
+ confirmationPayload
6272
6816
  );
6273
6817
  }
6274
6818
  if (confirmationDetails.type === "edit" && outcome === "proceed_always" /* ProceedAlways */) {
6275
6819
  await this.sendCurrentModeUpdateNotification();
6276
6820
  }
6277
6821
  switch (outcome) {
6822
+ case "proceed_once_and_switch_to_default" /* ProceedOnceAndSwitchToDefault */:
6823
+ throw new Error(
6824
+ "Switch-to-Default outcome must be normalized before execution."
6825
+ );
6278
6826
  case "cancel" /* Cancel */:
6279
- return stopAfterPermissionCancel();
6827
+ return stopAfterPermissionCancel(
6828
+ confirmationPayload?.cancelMessage
6829
+ );
6280
6830
  case "proceed_once" /* ProceedOnce */:
6281
6831
  case "proceed_always" /* ProceedAlways */:
6282
6832
  case "proceed_always_project" /* ProceedAlwaysProject */:
@@ -6308,7 +6858,7 @@ ${this.pendingWorktreeNotice}
6308
6858
  if (hooksEnabledForTool && messageBusForTool) {
6309
6859
  const preHookResult = await firePreToolUseHook(
6310
6860
  messageBusForTool,
6311
- toolName,
6861
+ policyToolName,
6312
6862
  args,
6313
6863
  toolUseId,
6314
6864
  permissionMode,
@@ -6398,7 +6948,7 @@ ${this.pendingWorktreeNotice}
6398
6948
  this.#clearTodoStopGuardTrustAndDrainAutomaticQueues();
6399
6949
  }
6400
6950
  }
6401
- const responseParts = toolResult.error ? convertToFunctionErrorResponse(
6951
+ let responseParts = toolResult.error ? convertToFunctionErrorResponse(
6402
6952
  toolName,
6403
6953
  callId,
6404
6954
  toolResult.llmContent,
@@ -6425,7 +6975,7 @@ ${this.pendingWorktreeNotice}
6425
6975
  };
6426
6976
  const postHookResult = await firePostToolUseHook(
6427
6977
  messageBusForTool,
6428
- toolName,
6978
+ policyToolName,
6429
6979
  args,
6430
6980
  toolResponse,
6431
6981
  toolUseId,
@@ -6456,7 +7006,7 @@ ${this.pendingWorktreeNotice}
6456
7006
  const failureHookResult = await firePostToolUseFailureHook(
6457
7007
  messageBusForTool,
6458
7008
  toolUseId,
6459
- toolName,
7009
+ policyToolName,
6460
7010
  args,
6461
7011
  toolResult.error?.message ?? "Tool execution was cancelled",
6462
7012
  isInterrupt,
@@ -6476,6 +7026,12 @@ ${this.pendingWorktreeNotice}
6476
7026
  artifacts: failureHookResult.artifacts
6477
7027
  });
6478
7028
  }
7029
+ responseParts = await bridgeToolResultImages({
7030
+ config: this.config,
7031
+ responseParts,
7032
+ signal: activeToolAbortSignal,
7033
+ onFullTurnModel
7034
+ });
6479
7035
  if (isTodoWriteTool) {
6480
7036
  const todos = this.planEmitter.extractTodos(
6481
7037
  toolResult.returnDisplay,
@@ -6510,12 +7066,18 @@ ${this.pendingWorktreeNotice}
6510
7066
  prompt_id: promptId,
6511
7067
  tool_type: typeof tool !== "undefined" && tool instanceof DiscoveredMCPTool ? "mcp" : "native"
6512
7068
  });
6513
- this.config.getChatRecordingService()?.recordToolResult(responseParts, {
7069
+ queueToolResultRecord?.(fc, {
6514
7070
  callId,
6515
- status,
6516
- resultDisplay: toolResult.returnDisplay,
6517
- error: toolResult.error ? new Error(toolResult.error.message) : void 0,
6518
- errorType: toolResult.error?.type
7071
+ toolName,
7072
+ responseParts,
7073
+ persistedOutputFiles: toolResult.persistedOutputFiles,
7074
+ metadata: {
7075
+ callId,
7076
+ status,
7077
+ resultDisplay: toolResult.returnDisplay,
7078
+ error: toolResult.error ? new Error(toolResult.error.message) : void 0,
7079
+ errorType: toolResult.error?.type
7080
+ }
6519
7081
  });
6520
7082
  spanSuccess = succeeded;
6521
7083
  if (toolResult.error) {
@@ -6545,7 +7107,7 @@ ${this.pendingWorktreeNotice}
6545
7107
  const failureHookResult = await firePostToolUseFailureHook(
6546
7108
  messageBusForError,
6547
7109
  toolUseId,
6548
- toolName,
7110
+ policyToolName,
6549
7111
  args,
6550
7112
  error.message,
6551
7113
  isInterrupt,
@@ -6566,24 +7128,6 @@ ${this.pendingWorktreeNotice}
6566
7128
  });
6567
7129
  }
6568
7130
  await this.toolCallEmitter.emitError(callId, toolName, error);
6569
- const errorParts = [
6570
- {
6571
- functionResponse: {
6572
- id: callId,
6573
- name: toolName,
6574
- response: { error: error.message }
6575
- }
6576
- }
6577
- ];
6578
- this.config.getChatRecordingService()?.recordToolResult(errorParts, {
6579
- callId,
6580
- // A throw caused by abort (e.g. AbortError) is a cancellation, not
6581
- // a genuine tool error — keep it consistent with the success path.
6582
- status: activeToolAbortSignal.aborted ? "cancelled" : "error",
6583
- resultDisplay: void 0,
6584
- error,
6585
- errorType: void 0
6586
- });
6587
7131
  const loopDetected = !activeToolAbortSignal.aborted && !toolBuildSucceeded && recordDaemonInvalidToolParams(
6588
7132
  this.config,
6589
7133
  promptId,
@@ -6592,6 +7136,18 @@ ${this.pendingWorktreeNotice}
6592
7136
  error
6593
7137
  );
6594
7138
  const responseParts = errorResponse(error);
7139
+ queueToolResultRecord?.(fc, {
7140
+ callId,
7141
+ toolName,
7142
+ responseParts,
7143
+ metadata: {
7144
+ callId,
7145
+ status: activeToolAbortSignal.aborted ? "cancelled" : "error",
7146
+ resultDisplay: void 0,
7147
+ error,
7148
+ errorType: void 0
7149
+ }
7150
+ });
6595
7151
  return {
6596
7152
  parts: responseParts,
6597
7153
  stopAfterPermissionCancel: nestedPermissionCancelled,
@@ -7152,7 +7708,8 @@ function serializeAgentTask(entry, now) {
7152
7708
  at: a.at
7153
7709
  }))
7154
7710
  } : {},
7155
- ...optionalField("prompt", entry.prompt)
7711
+ ...optionalField("prompt", entry.prompt),
7712
+ ...optionalField("toolUseId", entry.toolUseId)
7156
7713
  };
7157
7714
  }
7158
7715
  __name(serializeAgentTask, "serializeAgentTask");
@@ -7228,6 +7785,7 @@ var QWEN_ACP_LOCAL_READ_ROOTS_ENV = "QWEN_ACP_LOCAL_READ_ROOTS";
7228
7785
  var POSIX_TMP_LOCAL_READ_ROOT = "/tmp";
7229
7786
  var BTW_CHILD_TIMEOUT_MS = 55e3;
7230
7787
  var MCP_OAUTH_START_TIMEOUT_MS = 3e4;
7788
+ var SESSION_DRAIN_TIMEOUT_MS = 3e4;
7231
7789
  var WORKSPACE_MEMORY_REMEMBER_CHILD_TIMEOUT_MS = 295e3;
7232
7790
  function createAcpSessionStartProfiler(span) {
7233
7791
  let failedStage;
@@ -7286,6 +7844,77 @@ function workspaceMemoryErrorData(code, diagnostics) {
7286
7844
  };
7287
7845
  }
7288
7846
  __name(workspaceMemoryErrorData, "workspaceMemoryErrorData");
7847
+ var SESSION_WRITER_MESSAGES = {
7848
+ session_writer_conflict: "This session is already open in another Qwen process.",
7849
+ session_writer_lost: "Write ownership for this session was lost.",
7850
+ session_transcript_changed: "The session transcript changed outside its active writer.",
7851
+ session_writer_unavailable: "Session write ownership could not be verified."
7852
+ };
7853
+ function getSessionWriterError(error) {
7854
+ if (!error || typeof error !== "object") return void 0;
7855
+ const candidate = error;
7856
+ const errorKind = candidate["errorKind"];
7857
+ if (typeof errorKind !== "string" || !(errorKind in SESSION_WRITER_RPC_CODES)) {
7858
+ return void 0;
7859
+ }
7860
+ const typedKind = errorKind;
7861
+ if (candidate["rpcCode"] !== SESSION_WRITER_RPC_CODES[typedKind]) {
7862
+ return void 0;
7863
+ }
7864
+ return {
7865
+ rpcCode: SESSION_WRITER_RPC_CODES[typedKind],
7866
+ errorKind: typedKind,
7867
+ message: SESSION_WRITER_MESSAGES[typedKind]
7868
+ };
7869
+ }
7870
+ __name(getSessionWriterError, "getSessionWriterError");
7871
+ function mapSessionWriterRequestError(error) {
7872
+ const writerError = getSessionWriterError(error);
7873
+ return writerError ? new RequestError(writerError.rpcCode, writerError.message, {
7874
+ errorKind: writerError.errorKind
7875
+ }) : error;
7876
+ }
7877
+ __name(mapSessionWriterRequestError, "mapSessionWriterRequestError");
7878
+ async function shutdownSessionConfig(config) {
7879
+ await config.shutdown({ shutdownTelemetry: false });
7880
+ if (config.hasSessionWriteOwnership()) {
7881
+ throw new SessionWriterUnavailableError();
7882
+ }
7883
+ }
7884
+ __name(shutdownSessionConfig, "shutdownSessionConfig");
7885
+ async function waitForSessionDrain(operation, timeoutMs, kind) {
7886
+ let timer;
7887
+ const timeout = new Promise((_, reject) => {
7888
+ timer = setTimeout(
7889
+ () => reject(new Error(`Session ${kind} timed out after ${timeoutMs}ms`)),
7890
+ timeoutMs
7891
+ );
7892
+ timer.unref();
7893
+ });
7894
+ try {
7895
+ await Promise.race([operation, timeout]);
7896
+ } finally {
7897
+ if (timer) clearTimeout(timer);
7898
+ }
7899
+ }
7900
+ __name(waitForSessionDrain, "waitForSessionDrain");
7901
+ async function beginSessionCloseAfterCurrentGate(session, timeoutMs) {
7902
+ const deadline = Date.now() + timeoutMs;
7903
+ while (true) {
7904
+ const releaseGate = session.beginCloseIfAvailable();
7905
+ if (releaseGate) return releaseGate;
7906
+ const remainingMs = deadline - Date.now();
7907
+ if (remainingMs <= 0) {
7908
+ throw new Error(`Session close timed out after ${timeoutMs}ms`);
7909
+ }
7910
+ await waitForSessionDrain(
7911
+ session.waitForCloseGateToRelease(),
7912
+ remainingMs,
7913
+ "close"
7914
+ );
7915
+ }
7916
+ }
7917
+ __name(beginSessionCloseAfterCurrentGate, "beginSessionCloseAfterCurrentGate");
7289
7918
  var logWorkspaceMemoryExtractionError = createWorkspaceMemoryExtractionErrorLogger(debugLogger7);
7290
7919
  function parseAcpLocalReadRootsEnv(raw = process.env[QWEN_ACP_LOCAL_READ_ROOTS_ENV]) {
7291
7920
  if (!raw) return [];
@@ -7303,7 +7932,7 @@ function buildAcpLocalReadRoots(config) {
7303
7932
  // local read fallback, not read_file's default permission.
7304
7933
  config.storage.getProjectTempDir(),
7305
7934
  path4.join(config.storage.getProjectDir(), "subagents"),
7306
- Storage.getGlobalTempDir(),
7935
+ path4.join(config.getSessionRuntimeBaseDir(), "tmp"),
7307
7936
  getAutoMemoryRoot(config.getTargetDir()),
7308
7937
  getUserAutoMemoryRoot(),
7309
7938
  ...config.storage.getUserSkillsDirs(),
@@ -8881,7 +9510,7 @@ async function runAcpAgent(config, settings, argv) {
8881
9510
  debugLogger7.debug("[ACP] Shutdown signal received, closing streams");
8882
9511
  try {
8883
9512
  await fireSessionEndOnce("other" /* Other */);
8884
- agentInstance?.disposeSessions();
9513
+ await agentInstance?.disposeSessions();
8885
9514
  try {
8886
9515
  process.stdin.destroy();
8887
9516
  } catch {
@@ -8908,7 +9537,7 @@ async function runAcpAgent(config, settings, argv) {
8908
9537
  await connection.closed;
8909
9538
  await fireSessionEndOnce("prompt_input_exit" /* PromptInputExit */);
8910
9539
  await drainPoolBeforeExit("ide_close");
8911
- agentInstance?.disposeSessions();
9540
+ await agentInstance?.disposeSessions();
8912
9541
  } finally {
8913
9542
  process.off("SIGTERM", shutdownHandler);
8914
9543
  process.off("SIGINT", shutdownHandler);
@@ -9067,6 +9696,7 @@ var QwenAgent = class {
9067
9696
  mcpAuthenticationResults = /* @__PURE__ */ new Map();
9068
9697
  generationControllers = /* @__PURE__ */ new Map();
9069
9698
  transcriptReplayConfigCache = /* @__PURE__ */ new Map();
9699
+ pendingConfigCleanup = /* @__PURE__ */ new Map();
9070
9700
  clientCapabilities;
9071
9701
  // CPU-usage delta baseline for the daemon's `workspaceResource` extMethod
9072
9702
  // (Daemon Status child-resource chart). The daemon polls this at a fixed
@@ -9169,21 +9799,26 @@ var QwenAgent = class {
9169
9799
  async createWorkspaceMcpDiscoveryConfig(settings) {
9170
9800
  if (this.workspaceMcpDiscoveryConfig) return;
9171
9801
  const cwd = this.config.getTargetDir();
9172
- const config = await loadCliConfig(
9173
- settings.merged,
9174
- {
9175
- ...this.argv,
9176
- sessionId: "workspace-mcp-discovery",
9177
- resume: void 0,
9178
- continue: false
9179
- },
9802
+ const config = await this.runWithPinnedRuntimeBaseDir(
9803
+ settings,
9180
9804
  cwd,
9181
- void 0,
9182
- {
9183
- userHooks: settings.getUserHooks(),
9184
- projectHooks: settings.getProjectHooks()
9185
- },
9186
- buildDisabledSkillNamesProvider(settings)
9805
+ () => loadCliConfig(
9806
+ settings.merged,
9807
+ {
9808
+ ...this.argv,
9809
+ sessionId: "workspace-mcp-discovery",
9810
+ resume: void 0,
9811
+ continue: false,
9812
+ chatRecording: false
9813
+ },
9814
+ cwd,
9815
+ void 0,
9816
+ {
9817
+ userHooks: settings.getUserHooks(),
9818
+ projectHooks: settings.getProjectHooks()
9819
+ },
9820
+ buildDisabledSkillNamesProvider(settings)
9821
+ )
9187
9822
  );
9188
9823
  config.setMcpTransportPool(this.mcpPool);
9189
9824
  try {
@@ -9291,100 +9926,225 @@ var QwenAgent = class {
9291
9926
  );
9292
9927
  }
9293
9928
  }
9294
- async closeStoredSession(sessionId, opts) {
9295
- for (const [requestId, generation] of this.generationControllers) {
9296
- if (generation.sessionId !== sessionId) continue;
9297
- generation.controller.abort();
9298
- this.generationControllers.delete(requestId);
9299
- }
9300
- const session = this.sessions.get(sessionId);
9301
- if (!session) {
9302
- this.mcpPool?.releaseSession(sessionId);
9303
- return;
9929
+ async removeStoredSessionEntry(sessionId, session, cleanupErrors = [], options = {}) {
9930
+ if (this.sessions.get(sessionId) !== session) return;
9931
+ try {
9932
+ session.dispose();
9933
+ } catch (error) {
9934
+ cleanupErrors.push(error);
9304
9935
  }
9305
- const requireFlush = opts?.requireFlush === true;
9306
- const flushRecording = /* @__PURE__ */ __name(async () => {
9936
+ if (options.shutdownConfig !== false) {
9307
9937
  try {
9308
- await session.getConfig().getChatRecordingService()?.flush();
9309
- return void 0;
9310
- } catch (err) {
9311
- debugLogger7.debug(
9312
- `Session ${sessionId} chat recording flush during close failed: ${err instanceof Error ? err.message : String(err)}`
9313
- );
9314
- return err;
9315
- }
9316
- }, "flushRecording");
9317
- if (requireFlush) {
9318
- const preCancelFlushError = await flushRecording();
9319
- if (preCancelFlushError !== void 0) {
9320
- throw preCancelFlushError;
9938
+ await session.getConfig().shutdown({ shutdownTelemetry: false });
9939
+ } catch (error) {
9940
+ cleanupErrors.push(error);
9321
9941
  }
9322
9942
  }
9323
9943
  try {
9324
- await session.cancelPendingPrompt();
9325
- } catch (err) {
9326
- debugLogger7.debug(
9327
- `Session ${sessionId} cancel during close failed: ${err instanceof Error ? err.message : String(err)}`
9328
- );
9944
+ unregisterGoalHook(session.getConfig(), sessionId);
9945
+ } catch (error) {
9946
+ cleanupErrors.push(error);
9329
9947
  }
9330
- const flushError = await flushRecording();
9331
- if (flushError !== void 0 && requireFlush) {
9332
- throw flushError;
9948
+ try {
9949
+ this.mcpPool?.releaseSession(sessionId);
9950
+ } catch (error) {
9951
+ cleanupErrors.push(error);
9333
9952
  }
9334
9953
  try {
9335
- await session.getConfig().getToolRegistry()?.stop();
9336
- } catch (err) {
9337
- debugLogger7.debug(
9338
- `Session ${sessionId} tool registry stop during close failed: ${err instanceof Error ? err.message : String(err)}`
9339
- );
9954
+ uiTelemetryService.removeSession(sessionId);
9955
+ } catch (error) {
9956
+ cleanupErrors.push(error);
9340
9957
  }
9341
- unregisterGoalHook(session.getConfig(), sessionId);
9342
- this.mcpPool?.releaseSession(sessionId);
9343
- uiTelemetryService.removeSession(sessionId);
9344
9958
  this.sessions.delete(sessionId);
9345
- }
9346
- discardStoredSessionIfCurrent(sessionId, session) {
9347
- if (this.sessions.get(sessionId) !== session) {
9348
- return;
9349
- }
9350
- const logCleanupFailure = /* @__PURE__ */ __name((action, err) => {
9351
- debugLogger7.debug(
9352
- `Session ${sessionId} ${action} during failed restore cleanup failed: ${err instanceof Error ? err.message : String(err)}`
9959
+ if (cleanupErrors.length > 0) {
9960
+ debugLogger7.warn(
9961
+ `Session ${sessionId} closed after ${cleanupErrors.length} cleanup failure(s): ${cleanupErrors.map(
9962
+ (error) => error instanceof Error ? error.message : String(error)
9963
+ ).join("; ")}`
9353
9964
  );
9354
- }, "logCleanupFailure");
9965
+ }
9966
+ }
9967
+ async withLiveSessionRestore(sessionId, session, operation) {
9968
+ await session.assertCanStartTurn();
9969
+ const config = session.getConfig();
9970
+ const releaseGate = session.beginClose();
9355
9971
  try {
9356
- session.dispose();
9357
- } catch (err) {
9358
- logCleanupFailure("dispose", err);
9972
+ await waitForSessionDrain(
9973
+ session.waitForActiveTurnsToSettle(),
9974
+ SESSION_DRAIN_TIMEOUT_MS,
9975
+ "restore"
9976
+ );
9977
+ const recorder = config.getChatRecordingService();
9978
+ const loadAuthoritative = /* @__PURE__ */ __name(() => config.getSessionService().loadSession(sessionId), "loadAuthoritative");
9979
+ const data = recorder ? await recorder.runWithWriteBarrier(loadAuthoritative) : await loadAuthoritative();
9980
+ if (!data) throw new SessionWriterUnavailableError();
9981
+ return await operation(config, data);
9982
+ } catch (error) {
9983
+ throw mapSessionWriterRequestError(error);
9984
+ } finally {
9985
+ releaseGate();
9359
9986
  }
9987
+ }
9988
+ async cleanupUnstoredConfig(config) {
9989
+ const sessionId = config.getSessionId();
9990
+ const cleanupKey = this.pendingConfigCleanupKey(
9991
+ config.getSessionRuntimeBaseDir(),
9992
+ sessionId
9993
+ );
9360
9994
  try {
9361
- unregisterGoalHook(session.getConfig(), sessionId);
9362
- } catch (err) {
9363
- logCleanupFailure("goal hook unregister", err);
9995
+ await shutdownSessionConfig(config);
9996
+ } catch (error) {
9997
+ const pending2 = this.pendingConfigCleanup.get(cleanupKey) ?? /* @__PURE__ */ new Set();
9998
+ pending2.add(config);
9999
+ this.pendingConfigCleanup.set(cleanupKey, pending2);
10000
+ throw mapSessionWriterRequestError(error);
10001
+ }
10002
+ const pending = this.pendingConfigCleanup.get(cleanupKey);
10003
+ pending?.delete(config);
10004
+ if (pending?.size === 0) {
10005
+ this.pendingConfigCleanup.delete(cleanupKey);
9364
10006
  }
10007
+ }
10008
+ async cleanupAfterRequestFailure(error, cleanup) {
9365
10009
  try {
10010
+ await cleanup();
10011
+ } catch (cleanupError) {
10012
+ debugLogger7.warn(
10013
+ `Session cleanup failed while preserving the original request error: ${cleanupError instanceof Error ? cleanupError.message : String(cleanupError)}`
10014
+ );
10015
+ }
10016
+ throw error;
10017
+ }
10018
+ pendingConfigCleanupKey(runtimeBaseDir, sessionId) {
10019
+ return `${path4.resolve(runtimeBaseDir)}\0${sessionId}`;
10020
+ }
10021
+ async retryPendingConfigCleanup(runtimeBaseDir, requiredSessionId) {
10022
+ const resolvedRuntimeBaseDir = path4.resolve(runtimeBaseDir);
10023
+ const configs = /* @__PURE__ */ new Set();
10024
+ for (const pending of this.pendingConfigCleanup.values()) {
10025
+ for (const config of pending) {
10026
+ if (path4.resolve(config.getSessionRuntimeBaseDir()) === resolvedRuntimeBaseDir) {
10027
+ configs.add(config);
10028
+ }
10029
+ }
10030
+ }
10031
+ for (const config of configs) {
10032
+ try {
10033
+ await this.cleanupUnstoredConfig(config);
10034
+ } catch (error) {
10035
+ if (config.getSessionId() === requiredSessionId) throw error;
10036
+ debugLogger7.warn(
10037
+ `Deferred Config cleanup retry failed for session ${config.getSessionId()}: ${error instanceof Error ? error.message : String(error)}`
10038
+ );
10039
+ }
10040
+ }
10041
+ }
10042
+ async closeStoredSession(sessionId, opts) {
10043
+ const session = this.sessions.get(sessionId);
10044
+ if (!session) {
9366
10045
  this.mcpPool?.releaseSession(sessionId);
9367
- } catch (err) {
9368
- logCleanupFailure("MCP pool release", err);
10046
+ return;
10047
+ }
10048
+ const recorder = session.getConfig().getChatRecordingService();
10049
+ const requireFlush = opts?.requireFlush === true;
10050
+ if (requireFlush) {
10051
+ await recorder?.flush();
10052
+ }
10053
+ const drainTimeoutMs = opts?.drainTimeoutMs ?? SESSION_DRAIN_TIMEOUT_MS;
10054
+ const cancelClose = opts?.waitForCloseGate ? await beginSessionCloseAfterCurrentGate(session, drainTimeoutMs) : session.beginClose();
10055
+ for (const [requestId, generation] of this.generationControllers) {
10056
+ if (generation.sessionId !== sessionId) continue;
10057
+ generation.controller.abort();
10058
+ this.generationControllers.delete(requestId);
9369
10059
  }
10060
+ let removedFromStore = false;
9370
10061
  try {
9371
- uiTelemetryService.removeSession(sessionId);
9372
- } catch (err) {
9373
- logCleanupFailure("telemetry removal", err);
10062
+ await waitForSessionDrain(
10063
+ (async () => {
10064
+ try {
10065
+ await session.cancelPendingPrompt();
10066
+ } catch (err) {
10067
+ debugLogger7.debug(
10068
+ `Session ${sessionId} cancel during close failed: ${err instanceof Error ? err.message : String(err)}`
10069
+ );
10070
+ }
10071
+ await session.waitForActiveTurnsToSettle();
10072
+ })(),
10073
+ drainTimeoutMs,
10074
+ "close"
10075
+ );
10076
+ recorder?.finalize();
10077
+ let flushError;
10078
+ try {
10079
+ await recorder?.flush();
10080
+ } catch (error) {
10081
+ flushError = error;
10082
+ }
10083
+ if (flushError !== void 0 && requireFlush) {
10084
+ throw flushError;
10085
+ }
10086
+ let closeError;
10087
+ try {
10088
+ await recorder?.close();
10089
+ } catch (error) {
10090
+ closeError = error;
10091
+ }
10092
+ if (recorder?.hasWriteOwnership()) {
10093
+ throw closeError ?? new SessionWriterUnavailableError();
10094
+ }
10095
+ const cleanupErrors = [];
10096
+ if (flushError !== void 0) cleanupErrors.push(flushError);
10097
+ if (closeError !== void 0) cleanupErrors.push(closeError);
10098
+ await this.removeStoredSessionEntry(sessionId, session, cleanupErrors, {
10099
+ shutdownConfig: opts?.shutdownConfig
10100
+ });
10101
+ removedFromStore = true;
10102
+ } finally {
10103
+ if (!removedFromStore) cancelClose();
9374
10104
  }
9375
- this.sessions.delete(sessionId);
9376
10105
  }
9377
- disposeSessions() {
10106
+ async discardStoredSessionIfCurrent(sessionId, session, opts) {
10107
+ if (this.sessions.get(sessionId) !== session) {
10108
+ return;
10109
+ }
10110
+ await this.closeStoredSession(sessionId, opts);
10111
+ }
10112
+ async disposeSessions() {
9378
10113
  for (const generation of this.generationControllers.values()) {
9379
10114
  generation.controller.abort();
9380
10115
  }
9381
10116
  this.generationControllers.clear();
9382
- for (const session of this.sessions.values()) {
9383
- session.dispose();
9384
- }
9385
- this.sessions.clear();
10117
+ await Promise.allSettled(
10118
+ [...this.sessions.entries()].map(
10119
+ ([sessionId, session]) => this.discardStoredSessionIfCurrent(sessionId, session, {
10120
+ waitForCloseGate: true
10121
+ })
10122
+ )
10123
+ );
10124
+ await Promise.allSettled(
10125
+ [...this.pendingConfigCleanup.values()].flatMap((configs) => [...configs]).map((config) => this.cleanupUnstoredConfig(config))
10126
+ );
9386
10127
  this.disposeTranscriptReplayConfigs();
9387
10128
  }
10129
+ runWithPinnedRuntimeBaseDir(settings, cwd, operation) {
10130
+ return runWithAcpRuntimeOutputDir(settings, cwd, operation);
10131
+ }
10132
+ async assertLiveSessionScope(config, settings, cwd) {
10133
+ if (path4.resolve(config.storage.getProjectRoot()) !== path4.resolve(cwd)) {
10134
+ throw RequestError.invalidParams(
10135
+ void 0,
10136
+ "The live session belongs to another workspace."
10137
+ );
10138
+ }
10139
+ const requestedRuntimeBaseDir = await this.runWithPinnedRuntimeBaseDir(
10140
+ settings,
10141
+ cwd,
10142
+ () => Storage.getRuntimeBaseDir()
10143
+ );
10144
+ if (path4.resolve(config.getSessionRuntimeBaseDir()) !== path4.resolve(requestedRuntimeBaseDir)) {
10145
+ throw mapSessionWriterRequestError(new SessionWriterUnavailableError());
10146
+ }
10147
+ }
9388
10148
  /** Expose the pool's workspace-scoped budget controller for snapshot builders. */
9389
10149
  getWorkspaceMcpBudget() {
9390
10150
  return this.workspaceMcpBudget;
@@ -9414,7 +10174,7 @@ var QwenAgent = class {
9414
10174
  markAcpStartup("initializeHandlerStart");
9415
10175
  this.clientCapabilities = args.clientCapabilities;
9416
10176
  const authMethods = buildAuthMethods();
9417
- const version = "0.20.1-preview.7215";
10177
+ const version = "0.20.2-gdpval-vl-agent.0";
9418
10178
  const response = {
9419
10179
  protocolVersion: PROTOCOL_VERSION,
9420
10180
  agentInfo: {
@@ -9503,15 +10263,24 @@ var QwenAgent = class {
9503
10263
  "config_setup",
9504
10264
  () => this.newSessionConfig(cwd, mcpServers, settings)
9505
10265
  );
9506
- await profiler.time("auth", () => this.ensureAuthenticated(config));
9507
- profiler.timeSync(
9508
- "file_system_setup",
9509
- () => this.setupFileSystem(config)
9510
- );
9511
- const session = await profiler.time(
9512
- "session_register",
9513
- () => this.createAndStoreSession(config, settings)
9514
- );
10266
+ let session;
10267
+ try {
10268
+ await profiler.time("auth", () => this.ensureAuthenticated(config));
10269
+ profiler.timeSync(
10270
+ "file_system_setup",
10271
+ () => this.setupFileSystem(config)
10272
+ );
10273
+ session = await profiler.time(
10274
+ "session_register",
10275
+ () => this.createAndStoreSession(config, settings)
10276
+ );
10277
+ } catch (error) {
10278
+ return this.cleanupAfterRequestFailure(error, async () => {
10279
+ if (this.sessions.get(config.getSessionId())?.getConfig() !== config) {
10280
+ await this.cleanupUnstoredConfig(config);
10281
+ }
10282
+ });
10283
+ }
9515
10284
  profiler.setSessionId(session.getId());
9516
10285
  return profiler.timeSync("response_build", () => ({
9517
10286
  sessionId: session.getId(),
@@ -9525,7 +10294,56 @@ var QwenAgent = class {
9525
10294
  }
9526
10295
  async loadSession(params) {
9527
10296
  const settings = loadSettingsCached(params.cwd);
9528
- const exists = await runWithAcpRuntimeOutputDir(
10297
+ const liveSession = this.sessions.get(params.sessionId);
10298
+ if (liveSession) {
10299
+ const liveConfig = liveSession.getConfig();
10300
+ await this.assertLiveSessionScope(liveConfig, settings, params.cwd);
10301
+ return this.withLiveSessionRestore(
10302
+ params.sessionId,
10303
+ liveSession,
10304
+ async (config2, sessionData2) => {
10305
+ const response2 = {
10306
+ modes: this.buildModesData(config2),
10307
+ models: this.buildAvailableModels(config2),
10308
+ configOptions: this.buildConfigOptions(config2),
10309
+ ...sessionData2.artifactSnapshot ? { artifactSnapshot: sessionData2.artifactSnapshot } : {}
10310
+ };
10311
+ const records = sessionData2.conversation.messages;
10312
+ if (records.length === 0) return response2;
10313
+ const bulkReplay2 = isBulkLoadReplayRequest(params);
10314
+ const replayPage = bulkReplay2 ? selectRecentHistoryRecords(records, getLoadReplayPageSize(params)) : { records, hasMore: false };
10315
+ const replay = await collectHistoryReplayUpdates({
10316
+ sessionId: params.sessionId,
10317
+ config: config2,
10318
+ records: replayPage.records,
10319
+ gaps: sessionData2.historyGaps,
10320
+ cumulativeUsage: createReplayCumulativeUsage(),
10321
+ logger: debugLogger7
10322
+ });
10323
+ if (!bulkReplay2) {
10324
+ for (const update of replay.updates) {
10325
+ await liveSession.sendUpdate(update);
10326
+ }
10327
+ if (replay.replayError !== void 0) {
10328
+ throw RequestError.internalError(void 0, replay.replayError);
10329
+ }
10330
+ return response2;
10331
+ }
10332
+ return {
10333
+ ...response2,
10334
+ _meta: {
10335
+ [LOAD_REPLAY_META_KEY]: {
10336
+ v: LOAD_REPLAY_VERSION,
10337
+ updates: replay.updates,
10338
+ ...replay.replayError !== void 0 ? { partial: true, replayError: replay.replayError } : {},
10339
+ ...replayPage.hasMore ? { hasMore: true } : {}
10340
+ }
10341
+ }
10342
+ };
10343
+ }
10344
+ );
10345
+ }
10346
+ const exists = await this.runWithPinnedRuntimeBaseDir(
9529
10347
  settings,
9530
10348
  params.cwd,
9531
10349
  async () => {
@@ -9548,17 +10366,26 @@ var QwenAgent = class {
9548
10366
  params.sessionId,
9549
10367
  true
9550
10368
  );
9551
- await this.ensureAuthenticated(config);
9552
- this.setupFileSystem(config);
9553
10369
  const sessionData = config.getResumedSessionData();
9554
10370
  const bulkReplay = isBulkLoadReplayRequest(params);
9555
10371
  const replayPageSize = bulkReplay ? getLoadReplayPageSize(params) : void 0;
9556
- const session = await this.createAndStoreSession(
9557
- config,
9558
- settings,
9559
- sessionData,
9560
- bulkReplay ? { replayHistory: false, startPostReplayServices: false } : {}
9561
- );
10372
+ let session;
10373
+ try {
10374
+ await this.ensureAuthenticated(config);
10375
+ this.setupFileSystem(config);
10376
+ session = await this.createAndStoreSession(
10377
+ config,
10378
+ settings,
10379
+ sessionData,
10380
+ bulkReplay ? { replayHistory: false, startPostReplayServices: false } : {}
10381
+ );
10382
+ } catch (error) {
10383
+ return this.cleanupAfterRequestFailure(error, async () => {
10384
+ if (this.sessions.get(config.getSessionId())?.getConfig() !== config) {
10385
+ await this.cleanupUnstoredConfig(config);
10386
+ }
10387
+ });
10388
+ }
9562
10389
  let replayEnvelope;
9563
10390
  if (bulkReplay) {
9564
10391
  try {
@@ -9605,8 +10432,21 @@ var QwenAgent = class {
9605
10432
  session.installRewriter();
9606
10433
  session.startCronScheduler();
9607
10434
  } catch (err) {
9608
- this.discardStoredSessionIfCurrent(params.sessionId, session);
9609
- throw err;
10435
+ return this.cleanupAfterRequestFailure(err, async () => {
10436
+ try {
10437
+ await this.discardStoredSessionIfCurrent(params.sessionId, session);
10438
+ } catch (cleanupError) {
10439
+ await this.removeStoredSessionEntry(
10440
+ params.sessionId,
10441
+ session,
10442
+ [cleanupError],
10443
+ {
10444
+ shutdownConfig: false
10445
+ }
10446
+ );
10447
+ await this.cleanupUnstoredConfig(config);
10448
+ }
10449
+ });
9610
10450
  }
9611
10451
  }
9612
10452
  await this.#restoreWorktreeOnResume(config, session);
@@ -9632,7 +10472,22 @@ var QwenAgent = class {
9632
10472
  }
9633
10473
  async unstable_resumeSession(params) {
9634
10474
  const settings = loadSettingsCached(params.cwd);
9635
- const exists = await runWithAcpRuntimeOutputDir(
10475
+ const liveSession = this.sessions.get(params.sessionId);
10476
+ if (liveSession) {
10477
+ const liveConfig = liveSession.getConfig();
10478
+ await this.assertLiveSessionScope(liveConfig, settings, params.cwd);
10479
+ return this.withLiveSessionRestore(
10480
+ params.sessionId,
10481
+ liveSession,
10482
+ async (config2, sessionData2) => ({
10483
+ modes: this.buildModesData(config2),
10484
+ models: this.buildAvailableModels(config2),
10485
+ configOptions: this.buildConfigOptions(config2),
10486
+ ...sessionData2.artifactSnapshot ? { artifactSnapshot: sessionData2.artifactSnapshot } : {}
10487
+ })
10488
+ );
10489
+ }
10490
+ const exists = await this.runWithPinnedRuntimeBaseDir(
9636
10491
  settings,
9637
10492
  params.cwd,
9638
10493
  async () => {
@@ -9651,14 +10506,23 @@ var QwenAgent = class {
9651
10506
  params.sessionId,
9652
10507
  true
9653
10508
  );
9654
- await this.ensureAuthenticated(config);
9655
- this.setupFileSystem(config);
9656
- const session = await this.createAndStoreSession(
9657
- config,
9658
- settings,
9659
- config.getResumedSessionData(),
9660
- { replayHistory: false }
9661
- );
10509
+ let session;
10510
+ try {
10511
+ await this.ensureAuthenticated(config);
10512
+ this.setupFileSystem(config);
10513
+ session = await this.createAndStoreSession(
10514
+ config,
10515
+ settings,
10516
+ config.getResumedSessionData(),
10517
+ { replayHistory: false }
10518
+ );
10519
+ } catch (error) {
10520
+ return this.cleanupAfterRequestFailure(error, async () => {
10521
+ if (this.sessions.get(config.getSessionId())?.getConfig() !== config) {
10522
+ await this.cleanupUnstoredConfig(config);
10523
+ }
10524
+ });
10525
+ }
9662
10526
  await this.#restoreWorktreeOnResume(config, session);
9663
10527
  this.#restoreGoalOnResume(config, session);
9664
10528
  const modesData = this.buildModesData(config);
@@ -11572,6 +12436,19 @@ var QwenAgent = class {
11572
12436
  };
11573
12437
  }
11574
12438
  async extMethod(method, params) {
12439
+ try {
12440
+ return await this.extMethodInternal(method, params);
12441
+ } catch (error) {
12442
+ const writerError = getSessionWriterError(error);
12443
+ if (writerError) {
12444
+ throw new RequestError(writerError.rpcCode, writerError.message, {
12445
+ errorKind: writerError.errorKind
12446
+ });
12447
+ }
12448
+ throw error;
12449
+ }
12450
+ }
12451
+ async extMethodInternal(method, params) {
11575
12452
  const requestedCwd = typeof params["cwd"] === "string" ? params["cwd"] : void 0;
11576
12453
  const cwd = requestedCwd || process.cwd();
11577
12454
  const SESSION_ID_RE = /^[0-9a-fA-F-]{32,36}$/;
@@ -11845,6 +12722,25 @@ var QwenAgent = class {
11845
12722
  "Transcript cursor and record boundary are mutually exclusive"
11846
12723
  );
11847
12724
  }
12725
+ const rawDirection = params["direction"];
12726
+ if (rawDirection !== void 0 && rawDirection !== "backward") {
12727
+ throw RequestError.invalidParams(
12728
+ void 0,
12729
+ "Invalid transcript direction"
12730
+ );
12731
+ }
12732
+ if (rawCursor !== void 0 && rawDirection !== void 0) {
12733
+ throw RequestError.invalidParams(
12734
+ void 0,
12735
+ "Transcript cursor and direction are mutually exclusive"
12736
+ );
12737
+ }
12738
+ if (rawBeforeRecordId !== void 0 && rawDirection !== void 0) {
12739
+ throw RequestError.invalidParams(
12740
+ void 0,
12741
+ "Transcript record boundary and direction are mutually exclusive"
12742
+ );
12743
+ }
11848
12744
  const rawLimit = params["limit"];
11849
12745
  if (rawLimit !== void 0 && (!Number.isSafeInteger(rawLimit) || rawLimit < 1 || rawLimit > SESSION_TRANSCRIPT_MAX_LIMIT)) {
11850
12746
  throw RequestError.invalidParams(
@@ -11855,10 +12751,14 @@ var QwenAgent = class {
11855
12751
  try {
11856
12752
  const settings = loadSettingsCached(cwd);
11857
12753
  return await runWithAcpRuntimeOutputDir(settings, cwd, async () => {
12754
+ if (rawDirection === "backward") {
12755
+ await this.sessions.get(sessionId)?.getConfig().getChatRecordingService()?.flush();
12756
+ }
11858
12757
  const reader = new SessionTranscriptReader(cwd);
11859
12758
  const page = await reader.readPage(sessionId, {
11860
12759
  ...typeof rawCursor === "string" ? { cursor: rawCursor } : {},
11861
12760
  ...typeof rawBeforeRecordId === "string" ? { beforeRecordId: rawBeforeRecordId } : {},
12761
+ ...rawDirection === "backward" ? { direction: rawDirection } : {},
11862
12762
  ...typeof rawLimit === "number" ? { limit: rawLimit } : {},
11863
12763
  maxBytes: SESSION_TRANSCRIPT_MAX_PAGE_BYTES
11864
12764
  });
@@ -12712,6 +13612,34 @@ var QwenAgent = class {
12712
13612
  }
12713
13613
  return { sessionId, persisted: true, kind };
12714
13614
  }
13615
+ case "qwen/session/recordTextElements": {
13616
+ const sessionId = params["sessionId"];
13617
+ const content = params["content"];
13618
+ const textElements = params["textElements"];
13619
+ if (typeof sessionId !== "string" || sessionId.length === 0) {
13620
+ throw RequestError.invalidParams(
13621
+ void 0,
13622
+ "Invalid or missing sessionId"
13623
+ );
13624
+ }
13625
+ if (typeof content !== "string" || !Array.isArray(textElements)) {
13626
+ throw RequestError.invalidParams(
13627
+ void 0,
13628
+ "Invalid user text elements payload"
13629
+ );
13630
+ }
13631
+ const session = this.sessionOrThrow(sessionId);
13632
+ await session.assertCanStartTurn();
13633
+ const recording = session.getConfig().getChatRecordingService();
13634
+ if (!recording) {
13635
+ throw RequestError.internalError(
13636
+ void 0,
13637
+ "Chat recording service unavailable"
13638
+ );
13639
+ }
13640
+ await recording.recordUserTextElements({ content, textElements });
13641
+ return { sessionId, persisted: true };
13642
+ }
12715
13643
  case SERVE_CONTROL_EXT_METHODS.sessionTitle: {
12716
13644
  const sessionId = params["sessionId"];
12717
13645
  const displayName = params["displayName"];
@@ -12807,8 +13735,16 @@ var QwenAgent = class {
12807
13735
  "Invalid or missing sessionId"
12808
13736
  );
12809
13737
  }
13738
+ const rawDrainTimeoutMs = params["drainTimeoutMs"];
13739
+ if (rawDrainTimeoutMs !== void 0 && (typeof rawDrainTimeoutMs !== "number" || !Number.isSafeInteger(rawDrainTimeoutMs) || rawDrainTimeoutMs < 1 || rawDrainTimeoutMs > 2147483647)) {
13740
+ throw RequestError.invalidParams(
13741
+ void 0,
13742
+ "Invalid session close drain timeout"
13743
+ );
13744
+ }
12810
13745
  await this.closeStoredSession(sessionId, {
12811
- requireFlush: params["requireFlush"] === true
13746
+ requireFlush: params["requireFlush"] === true,
13747
+ ...typeof rawDrainTimeoutMs === "number" ? { drainTimeoutMs: rawDrainTimeoutMs } : {}
12812
13748
  });
12813
13749
  return { sessionId, closed: true };
12814
13750
  }
@@ -12850,6 +13786,21 @@ var QwenAgent = class {
12850
13786
  });
12851
13787
  }
12852
13788
  const canonicalPath = await fs2.realpath(targetPath);
13789
+ const allowedRoots = params["allowedRoots"];
13790
+ if (Array.isArray(allowedRoots) && allowedRoots.length > 0) {
13791
+ const contained = allowedRoots.some((root) => {
13792
+ if (typeof root !== "string") return false;
13793
+ const rel = path4.relative(root, canonicalPath);
13794
+ return !rel.startsWith("..") && !path4.isAbsolute(rel);
13795
+ });
13796
+ if (!contained) {
13797
+ throw new RequestError(
13798
+ -32004,
13799
+ `Path outside allowed roots: ${canonicalPath}`,
13800
+ { errorKind: "containment_violation", path: canonicalPath }
13801
+ );
13802
+ }
13803
+ }
12853
13804
  const previousCwd = config.getTargetDir();
12854
13805
  if (canonicalPath === previousCwd) {
12855
13806
  return { previousCwd, newCwd: canonicalPath, warnings: [] };
@@ -13731,16 +14682,11 @@ ${outputText}
13731
14682
  let artifactSnapshot;
13732
14683
  let artifactSnapshotUnavailable;
13733
14684
  try {
13734
- await session.getConfig().getChatRecordingService()?.flush();
13735
- const cwd2 = session.getConfig().getProjectRoot();
13736
- const sessionData = await runWithAcpRuntimeOutputDir(
13737
- this.settings,
13738
- cwd2,
13739
- async () => {
13740
- const sessionService = new SessionService(cwd2);
13741
- return sessionService.loadSession(sessionId);
13742
- }
13743
- );
14685
+ const config = session.getConfig();
14686
+ const recording = config.getChatRecordingService();
14687
+ await recording?.flush();
14688
+ const loadAuthoritative = /* @__PURE__ */ __name(() => config.getSessionService().loadSession(sessionId), "loadAuthoritative");
14689
+ const sessionData = recording ? await recording.runWithWriteBarrier(loadAuthoritative) : await loadAuthoritative();
13744
14690
  if (sessionData === void 0) {
13745
14691
  artifactSnapshotUnavailable = "session data unavailable after rewind";
13746
14692
  } else if (sessionData.artifactSnapshot) {
@@ -13781,20 +14727,37 @@ ${outputText}
13781
14727
  "Invalid or missing sessionId"
13782
14728
  );
13783
14729
  }
13784
- const sessionData = await runWithAcpRuntimeOutputDir(
13785
- this.settings,
13786
- cwd,
13787
- async () => {
13788
- const sessionService = new SessionService(cwd);
13789
- return sessionService.loadSession(sessionId);
13790
- }
13791
- );
14730
+ const liveSession = this.sessions.get(sessionId);
14731
+ let replayConfig = this.config;
14732
+ let sessionData;
14733
+ if (liveSession) {
14734
+ const config = liveSession.getConfig();
14735
+ await this.assertLiveSessionScope(
14736
+ config,
14737
+ loadSettingsCached(cwd),
14738
+ cwd
14739
+ );
14740
+ const recording = config.getChatRecordingService();
14741
+ const loadAuthoritative = /* @__PURE__ */ __name(() => config.getSessionService().loadSession(sessionId), "loadAuthoritative");
14742
+ sessionData = recording ? await recording.runWithWriteBarrier(loadAuthoritative) : await loadAuthoritative();
14743
+ replayConfig = config;
14744
+ } else {
14745
+ const settings = loadSettingsCached(cwd);
14746
+ sessionData = await this.runWithPinnedRuntimeBaseDir(
14747
+ settings,
14748
+ cwd,
14749
+ async () => {
14750
+ const sessionService = new SessionService(cwd);
14751
+ return sessionService.loadSession(sessionId);
14752
+ }
14753
+ );
14754
+ }
13792
14755
  if (!sessionData?.conversation) {
13793
14756
  return { updates: [] };
13794
14757
  }
13795
14758
  const replay = await collectHistoryReplayUpdates({
13796
14759
  sessionId,
13797
- config: this.config,
14760
+ config: replayConfig,
13798
14761
  records: sessionData.conversation.messages,
13799
14762
  gaps: sessionData.historyGaps,
13800
14763
  cumulativeUsage: createReplayCumulativeUsage(),
@@ -13862,56 +14825,51 @@ ${outputText}
13862
14825
  sessionId
13863
14826
  });
13864
14827
  }
13865
- const recording = sourceSession.getConfig().getChatRecordingService();
14828
+ const sourceConfig = sourceSession.getConfig();
14829
+ const recording = sourceConfig.getChatRecordingService();
13866
14830
  if (recording) {
13867
14831
  await recording.flush();
13868
14832
  }
13869
- const newSessionId = randomUUID();
13870
- return await runWithAcpRuntimeOutputDir(
13871
- this.settings,
13872
- cwd,
13873
- async () => {
13874
- const sessionService = new SessionService(cwd);
13875
- await sessionService.forkSession(sessionId, newSessionId);
13876
- let title;
13877
- try {
13878
- let baseName;
13879
- if (typeof name === "string" && name.trim().length > 0) {
13880
- baseName = name.trim();
13881
- } else {
13882
- const existingTitle = recording?.getCurrentCustomTitle();
13883
- const stripped = existingTitle?.replace(/\s*\(Branch(?:\s+\d+)?\)\s*$/, "").trim();
13884
- if (stripped && stripped.length > 0) {
13885
- baseName = stripped;
13886
- } else {
13887
- baseName = sessionId.slice(0, 8);
13888
- }
13889
- }
13890
- title = await computeUniqueBranchTitle(baseName, sessionService);
13891
- const renamed = await sessionService.renameSession(
13892
- newSessionId,
13893
- title,
13894
- "manual"
13895
- );
13896
- if (!renamed) {
13897
- throw new RequestError(
13898
- -32603,
13899
- `Failed to set title on forked session ${newSessionId}`,
13900
- { errorKind: "internal", sessionId: newSessionId }
13901
- );
13902
- }
13903
- } catch (err) {
13904
- sessionService.removeSession(newSessionId).catch((rmErr) => {
13905
- process.stderr.write(
13906
- `qwen serve: failed to clean up orphan session ${newSessionId}: ${rmErr instanceof Error ? rmErr.message : rmErr}
13907
- `
13908
- );
13909
- });
13910
- throw err;
14833
+ const newSessionId = randomUUID2();
14834
+ const sessionService = sourceConfig.getSessionService();
14835
+ await sessionService.forkSession(sessionId, newSessionId);
14836
+ let title;
14837
+ try {
14838
+ let baseName;
14839
+ if (typeof name === "string" && name.trim().length > 0) {
14840
+ baseName = name.trim();
14841
+ } else {
14842
+ const existingTitle = recording?.getCurrentCustomTitle();
14843
+ const stripped = existingTitle?.replace(/\s*\(Branch(?:\s+\d+)?\)\s*$/, "").trim();
14844
+ if (stripped && stripped.length > 0) {
14845
+ baseName = stripped;
14846
+ } else {
14847
+ baseName = sessionId.slice(0, 8);
13911
14848
  }
13912
- return { newSessionId, title, displayName: title };
13913
14849
  }
13914
- );
14850
+ title = await computeUniqueBranchTitle(baseName, sessionService);
14851
+ const renamed = await sessionService.renameSession(
14852
+ newSessionId,
14853
+ title,
14854
+ "manual"
14855
+ );
14856
+ if (!renamed) {
14857
+ throw new RequestError(
14858
+ -32603,
14859
+ `Failed to set title on forked session ${newSessionId}`,
14860
+ { errorKind: "internal", sessionId: newSessionId }
14861
+ );
14862
+ }
14863
+ } catch (err) {
14864
+ sessionService.removeSession(newSessionId).catch((rmErr) => {
14865
+ process.stderr.write(
14866
+ `qwen serve: failed to clean up orphan session ${newSessionId}: ${rmErr instanceof Error ? rmErr.message : rmErr}
14867
+ `
14868
+ );
14869
+ });
14870
+ throw err;
14871
+ }
14872
+ return { newSessionId, title, displayName: title };
13915
14873
  }
13916
14874
  case "qwen/settings/getCore": {
13917
14875
  const settings = loadSettings(cwd);
@@ -14300,17 +15258,25 @@ ${outputText}
14300
15258
  this.disposeTranscriptReplayConfig(cached.config);
14301
15259
  }
14302
15260
  const entry = { settings };
14303
- const pending = this.newSessionConfig(cwd, [], settings, void 0, false, {
14304
- skipMcpDiscovery: true,
14305
- skipHooks: true,
14306
- skipSkillManager: true,
14307
- skipFileCheckpointing: true,
14308
- // Read-only replay: tolerate tools that cannot construct without the
14309
- // subsystems skipped above (e.g. SkillTool needs the SkillManager). The
14310
- // registry is only consulted for optional tool_call metadata during
14311
- // replay, and ToolCallEmitter falls back to the recorded tool name.
14312
- lenientToolWarmup: true
14313
- });
15261
+ const pending = this.newSessionConfig(
15262
+ cwd,
15263
+ [],
15264
+ settings,
15265
+ void 0,
15266
+ false,
15267
+ {
15268
+ skipMcpDiscovery: true,
15269
+ skipHooks: true,
15270
+ skipSkillManager: true,
15271
+ skipFileCheckpointing: true,
15272
+ // Read-only replay: tolerate tools that cannot construct without the
15273
+ // subsystems skipped above (e.g. SkillTool needs the SkillManager). The
15274
+ // registry is only consulted for optional tool_call metadata during
15275
+ // replay, and ToolCallEmitter falls back to the recorded tool name.
15276
+ lenientToolWarmup: true
15277
+ },
15278
+ false
15279
+ );
14314
15280
  entry.pending = pending;
14315
15281
  this.transcriptReplayConfigCache.set(key, entry);
14316
15282
  try {
@@ -14338,7 +15304,34 @@ ${outputText}
14338
15304
  throw error;
14339
15305
  }
14340
15306
  }
14341
- async newSessionConfig(cwd, mcpServers, settings, sessionId, resume, initializeOptions = {}) {
15307
+ async newSessionConfig(cwd, mcpServers, settings, sessionId, resume, initializeOptions = {}, chatRecording) {
15308
+ try {
15309
+ return await this.runWithPinnedRuntimeBaseDir(settings, cwd, async () => {
15310
+ await this.retryPendingConfigCleanup(
15311
+ Storage.getRuntimeBaseDir(),
15312
+ sessionId
15313
+ );
15314
+ return this.newSessionConfigInRuntimeContext(
15315
+ cwd,
15316
+ mcpServers,
15317
+ settings,
15318
+ sessionId,
15319
+ resume,
15320
+ initializeOptions,
15321
+ chatRecording
15322
+ );
15323
+ });
15324
+ } catch (error) {
15325
+ const writerError = getSessionWriterError(error);
15326
+ if (writerError) {
15327
+ throw new RequestError(writerError.rpcCode, writerError.message, {
15328
+ errorKind: writerError.errorKind
15329
+ });
15330
+ }
15331
+ throw error;
15332
+ }
15333
+ }
15334
+ async newSessionConfigInRuntimeContext(cwd, mcpServers, settings, sessionId, resume, initializeOptions = {}, chatRecording) {
14342
15335
  const sessionMcpServers = {};
14343
15336
  for (const server of mcpServers) {
14344
15337
  const stdioServer = toStdioServer(server);
@@ -14394,8 +15387,14 @@ ${outputText}
14394
15387
  const sessionArg = resume === true ? { resume: sessionId, sessionId: void 0 } : { sessionId, resume: void 0 };
14395
15388
  const argvForSession = {
14396
15389
  ...this.argv,
15390
+ // Docker sandbox relaunch injects a fixed --sandbox-session-id into
15391
+ // the ACP process argv. Without clearing it, every newSession()
15392
+ // inherits the same ID and the second session collides with the
15393
+ // first's writer lease (#7435).
15394
+ sandboxSessionId: void 0,
14397
15395
  ...sessionArg,
14398
- continue: false
15396
+ continue: false,
15397
+ ...chatRecording !== void 0 ? { chatRecording } : {}
14399
15398
  };
14400
15399
  const config = await loadCliConfig(
14401
15400
  mergedSettings,
@@ -14449,15 +15448,22 @@ ${outputText}
14449
15448
  });
14450
15449
  });
14451
15450
  }
14452
- await config.initialize({
14453
- ...initializeOptions,
14454
- // Reverse tool channel (issue #5626, Phase 2): bind the session
14455
- // manager's SDK MCP callback to the `client_mcp/message` ext-method so a
14456
- // client-hosted (extension) MCP server added at runtime reaches the
14457
- // daemon WS. Servers that aren't client-hosted never use this callback
14458
- // (the daemon only adds SDK-type runtime servers for client MCP).
14459
- sendSdkMcpMessage: this.buildClientMcpSender(wiredSessionId)
14460
- });
15451
+ try {
15452
+ await config.initialize({
15453
+ ...initializeOptions,
15454
+ // Reverse tool channel (issue #5626, Phase 2): bind the session
15455
+ // manager's SDK MCP callback to the `client_mcp/message` ext-method so a
15456
+ // client-hosted (extension) MCP server added at runtime reaches the
15457
+ // daemon WS. Servers that aren't client-hosted never use this callback
15458
+ // (the daemon only adds SDK-type runtime servers for client MCP).
15459
+ sendSdkMcpMessage: this.buildClientMcpSender(wiredSessionId)
15460
+ });
15461
+ } catch (error) {
15462
+ return this.cleanupAfterRequestFailure(
15463
+ error,
15464
+ () => this.cleanupUnstoredConfig(config)
15465
+ );
15466
+ }
14461
15467
  void this.surfaceMcpFailuresWhenReady(config);
14462
15468
  return config;
14463
15469
  }
@@ -14518,29 +15524,47 @@ ${outputText}
14518
15524
  if (needsInitialize) {
14519
15525
  await geminiClient.initialize();
14520
15526
  }
14521
- this.sessions.get(sessionId)?.dispose();
15527
+ if (this.sessions.has(sessionId)) {
15528
+ throw new Error(`Session ${sessionId} is already active.`);
15529
+ }
14522
15530
  const session = new Session(sessionId, config, this.connection, settings);
14523
15531
  this.sessions.set(sessionId, session);
14524
- setTimeout(async () => {
14525
- await session.sendAvailableCommandsUpdate();
14526
- }, 0);
14527
- if (sessionData?.fileHistorySnapshots?.length) {
14528
- config.getFileHistoryService().restoreFromSnapshots(sessionData.fileHistorySnapshots);
14529
- }
14530
- if (sessionData?.conversation.messages) {
14531
- config.getChatRecordingService()?.rebuildTurnBoundaries(sessionData.conversation.messages);
14532
- }
14533
- if (options.replayHistory !== false && sessionData?.conversation.messages) {
14534
- await session.replayHistory(
14535
- sessionData.conversation.messages,
14536
- sessionData.historyGaps
14537
- );
14538
- }
14539
- if (options.startPostReplayServices !== false) {
14540
- session.installRewriter();
14541
- session.startCronScheduler();
15532
+ try {
15533
+ if (sessionData?.fileHistorySnapshots?.length) {
15534
+ config.getFileHistoryService().restoreFromSnapshots(sessionData.fileHistorySnapshots);
15535
+ }
15536
+ if (sessionData?.conversation.messages) {
15537
+ config.getChatRecordingService()?.rebuildTurnBoundaries(sessionData.conversation.messages);
15538
+ }
15539
+ if (options.replayHistory !== false && sessionData?.conversation.messages) {
15540
+ await session.replayHistory(
15541
+ sessionData.conversation.messages,
15542
+ sessionData.historyGaps
15543
+ );
15544
+ }
15545
+ if (options.startPostReplayServices !== false) {
15546
+ session.installRewriter();
15547
+ session.startCronScheduler();
15548
+ }
15549
+ setTimeout(() => {
15550
+ void session.sendAvailableCommandsUpdate();
15551
+ }, 0);
15552
+ return session;
15553
+ } catch (error) {
15554
+ try {
15555
+ await this.discardStoredSessionIfCurrent(sessionId, session, {
15556
+ shutdownConfig: false
15557
+ });
15558
+ } catch (cleanupError) {
15559
+ await this.removeStoredSessionEntry(
15560
+ sessionId,
15561
+ session,
15562
+ [cleanupError],
15563
+ { shutdownConfig: false }
15564
+ );
15565
+ }
15566
+ throw error;
14542
15567
  }
14543
- return session;
14544
15568
  }
14545
15569
  buildAvailableModels(config) {
14546
15570
  const rawCurrentModelId = (config.getModel() || this.config.getModel() || "").trim();