@qwen-code/qwen-code 0.20.0 → 0.20.1-nightly.20260724.7d17c44a3

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 (388) 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 +7 -5
  9. package/chunks/MaxSizedBox-LGRTXB47.js +84 -0
  10. package/chunks/{StandaloneSessionPicker-CEGO2AZX.js → StandaloneSessionPicker-H3TBU3C3.js} +68 -56
  11. package/chunks/{acp-startup-profiler-N3RHHXJ3.js → acp-startup-profiler-RV3IV562.js} +2 -2
  12. package/chunks/{acpAgent-YUR43TLG.js → acpAgent-5D7P4BB5.js} +2061 -556
  13. package/chunks/agent-W7UAHCCI.js +80 -0
  14. package/chunks/agent-headless-KTBMPRSC.js +74 -0
  15. package/chunks/{anthropicContentGenerator-HVKLXOOU.js → anthropicContentGenerator-ZLQ3X2HI.js} +112 -45
  16. package/chunks/{artifact-tool-WBCAMD3O.js → artifact-tool-OKMWONT6.js} +3 -3
  17. package/chunks/{askUserQuestion-6DZC4UV5.js → askUserQuestion-V6FUS23G.js} +3 -3
  18. package/chunks/bridge-FFC4C6VD.js +89 -0
  19. package/chunks/{build-SSCNEHZZ.js → build-RV63TIRH.js} +2 -3
  20. package/chunks/{ca-2SL2BXTK.js → ca-GKRQZ7AM.js} +612 -201
  21. package/chunks/{channel-worker-group-53CMOPFT.js → channel-worker-group-MA3WXWYX.js} +7 -6
  22. package/chunks/{channel-worker-manager-UTXILKC2.js → channel-worker-manager-TIYYYBCT.js} +189 -29
  23. package/chunks/{channel-worker-supervisor-ZGO2W2MD.js → channel-worker-supervisor-CXRCDA4Y.js} +6 -5
  24. package/chunks/{chunk-TYQMGACW.js → chunk-22C7BQ6D.js} +508 -10967
  25. package/chunks/{chunk-4EP2PYYL.js → chunk-2G6QIHYL.js} +5 -5
  26. package/chunks/{chunk-H2XVO6NE.js → chunk-2MIN6GRR.js} +1 -1
  27. package/chunks/chunk-2RFKHEXL.js +74 -0
  28. package/chunks/{chunk-7SXZC7ID.js → chunk-2WTVWAKT.js} +7 -6
  29. package/chunks/{chunk-TIH2ZTOC.js → chunk-32A4PI3E.js} +2 -2
  30. package/chunks/chunk-36HSVBBU.js +469 -0
  31. package/chunks/{chunk-IR46U7RB.js → chunk-3FB2Y2OE.js} +3 -3
  32. package/chunks/{chunk-QR6U5QPP.js → chunk-3SJ43L4W.js} +4 -0
  33. package/chunks/chunk-3Z43GZUQ.js +32 -0
  34. package/chunks/chunk-43T5WDQ7.js +127 -0
  35. package/chunks/chunk-46UV252V.js +128 -0
  36. package/chunks/{chunk-JD3MKVKL.js → chunk-4K56OJFJ.js} +1 -1
  37. package/chunks/{chunk-KTUQMDEP.js → chunk-4K7VDKAD.js} +1 -1
  38. package/chunks/{chunk-QKYTTBYW.js → chunk-4LVZNIDO.js} +1 -1
  39. package/chunks/{chunk-OWCALFEG.js → chunk-54R2CV2G.js} +1 -1
  40. package/chunks/{chunk-ZEOZL37W.js → chunk-57FIIFJN.js} +1 -1
  41. package/chunks/chunk-5BS3KLRP.js +6194 -0
  42. package/chunks/{chunk-NEEB7UEN.js → chunk-6GMVPFB2.js} +153 -72
  43. package/chunks/{chunk-GMGDLUC7.js → chunk-6IL7KRLE.js} +1 -1
  44. package/chunks/chunk-6PVPNMXU.js +29 -0
  45. package/chunks/chunk-6QHAUJUE.js +293 -0
  46. package/chunks/chunk-6VK3IRTX.js +10017 -0
  47. package/chunks/{chunk-BDBMYST4.js → chunk-6X4GWOPW.js} +1 -1
  48. package/chunks/{chunk-AYCDXHZB.js → chunk-7Z6JQEL6.js} +1 -1
  49. package/chunks/{chunk-FSL5W5TI.js → chunk-AFFGGOF6.js} +4 -4
  50. package/chunks/chunk-AMDSOFFV.js +10860 -0
  51. package/chunks/chunk-AXUW635Q.js +934 -0
  52. package/chunks/{chunk-A5LYNIW7.js → chunk-BJBUDCM3.js} +8 -8
  53. package/chunks/chunk-BK2UNYWD.js +29 -0
  54. package/chunks/{chunk-6RLROE6G.js → chunk-BLFVGB7D.js} +30 -4
  55. package/chunks/chunk-BPJSQIJX.js +100 -0
  56. package/chunks/{chunk-FLSVD6BS.js → chunk-BRTR7S7O.js} +3 -3
  57. package/chunks/{chunk-KG3XV6FH.js → chunk-BSNWBC33.js} +32 -2
  58. package/chunks/chunk-BULDBTYC.js +153 -0
  59. package/chunks/{chunk-PBWEWI4N.js → chunk-BW5Z5NOG.js} +83 -74
  60. package/chunks/{chunk-EIAK6Q2B.js → chunk-C3VHAXP2.js} +20 -3
  61. package/chunks/{chunk-6AFUCL3D.js → chunk-CEZB3XFD.js} +1 -1
  62. package/chunks/chunk-CHMENNJV.js +1832 -0
  63. package/chunks/{chunk-TMQ6XQCX.js → chunk-CK3IEEHR.js} +416 -291
  64. package/chunks/{chunk-OYZWQNWG.js → chunk-CK6UABV2.js} +2 -2
  65. package/chunks/{chunk-VZQUV7VK.js → chunk-CKTMY3EP.js} +1 -1
  66. package/chunks/{chunk-VDWBQ5AW.js → chunk-CUPAVLRY.js} +5 -2
  67. package/chunks/{chunk-I2PYAYFM.js → chunk-CXUFILV3.js} +3 -3
  68. package/chunks/chunk-DP3IHZGG.js +1498 -0
  69. package/chunks/{chunk-BMWMT5Y2.js → chunk-DP5GT2MW.js} +7 -375
  70. package/chunks/{chunk-D22SX43D.js → chunk-DWNZ6PVQ.js} +1 -1
  71. package/chunks/{chunk-5SCI6E3E.js → chunk-E4IMU4Y5.js} +1 -1
  72. package/chunks/{chunk-DP5GXXNZ.js → chunk-EL2IQ2S5.js} +5 -1
  73. package/chunks/{chunk-EZVDJFZ7.js → chunk-ERLGR7GI.js} +1 -1
  74. package/chunks/{chunk-IVPSS6EL.js → chunk-F5MBYZSU.js} +4 -4
  75. package/chunks/{chunk-AQIEINAY.js → chunk-F6IYL66A.js} +28 -1766
  76. package/chunks/{chunk-FEOZBUMT.js → chunk-FODK6UMO.js} +0 -27
  77. package/chunks/{chunk-PGEPSDJI.js → chunk-FWNZ7CVN.js} +24 -20
  78. package/chunks/{chunk-5JBR5XIK.js → chunk-G7EFBBVF.js} +220 -141
  79. package/chunks/chunk-GLNBDYUX.js +38 -0
  80. package/chunks/{chunk-ANPINBOF.js → chunk-H4YKEV2X.js} +5 -5
  81. package/chunks/{chunk-TDKQP3M6.js → chunk-HIJQF5B5.js} +1 -1
  82. package/chunks/{chunk-FQD7GFSV.js → chunk-HJJDKFL5.js} +3 -3
  83. package/chunks/{chunk-4N3KMAIL.js → chunk-HPWHDJID.js} +152 -35
  84. package/chunks/{chunk-KQNM4EO7.js → chunk-HQCSRJ3P.js} +138 -6
  85. package/chunks/chunk-HTR4WV6U.js +327 -0
  86. package/chunks/{chunk-YWEW33JY.js → chunk-HVO55LUD.js} +7 -7
  87. package/chunks/{chunk-MJ6S23WZ.js → chunk-HZEWYOVI.js} +5 -5
  88. package/chunks/chunk-IFG6TYJ2.js +16577 -0
  89. package/chunks/{chunk-B3KGZCQN.js → chunk-IJTOWOD7.js} +322 -202
  90. package/chunks/{chunk-RS7MT2QG.js → chunk-IPUUTYMV.js} +2 -4
  91. package/chunks/{chunk-4ILMYHEI.js → chunk-IRDZJSCL.js} +3 -3
  92. package/chunks/{chunk-XU457J4V.js → chunk-IRH27ZC2.js} +2 -2
  93. package/chunks/{chunk-33XUAINQ.js → chunk-J5UKQEFG.js} +69 -9
  94. package/chunks/{chunk-G45X5TRN.js → chunk-JCW2R7WC.js} +1 -72
  95. package/chunks/{chunk-S2XVRHDN.js → chunk-JDFBBGRD.js} +1 -1
  96. package/chunks/{chunk-4XNLIGVA.js → chunk-JKCALGYN.js} +1023 -383
  97. package/chunks/{chunk-TJTKSVIV.js → chunk-JLU636DO.js} +5 -1
  98. package/chunks/{chunk-VEXFOTEO.js → chunk-JYUSL2V4.js} +3 -3
  99. package/chunks/{chunk-S2PD3EZD.js → chunk-KJEMJWNH.js} +1 -1
  100. package/chunks/{chunk-E2UVIFI2.js → chunk-KRXPRVGL.js} +0 -1
  101. package/chunks/{chunk-CZF3E5GF.js → chunk-LA5H3LM5.js} +1 -1
  102. package/chunks/{chunk-NDMQLV4Y.js → chunk-LBAO2XRA.js} +4 -4
  103. package/chunks/{chunk-7RMOXZTC.js → chunk-LDPP5VTZ.js} +4 -4
  104. package/chunks/{chunk-KDC6GNQR.js → chunk-LEEWLFHW.js} +4 -4
  105. package/chunks/{chunk-KX6UK4VJ.js → chunk-LI4I37W4.js} +22152 -18007
  106. package/chunks/{chunk-OOCI5VVU.js → chunk-LIZRAKPB.js} +1 -1
  107. package/chunks/{chunk-AJSJ5TTU.js → chunk-LP2E4MQG.js} +1 -1
  108. package/chunks/chunk-LS77BEZP.js +405 -0
  109. package/chunks/{chunk-BRRF37CO.js → chunk-LYTBLSSW.js} +5 -5
  110. package/chunks/{chunk-DBE4QFZS.js → chunk-MB7ENXPR.js} +39 -37
  111. package/chunks/{chunk-GKY2OJ7R.js → chunk-MOHAWVLH.js} +4 -4
  112. package/chunks/chunk-NABLFI57.js +82 -0
  113. package/chunks/chunk-NBQDBANR.js +411 -0
  114. package/chunks/{chunk-EAUYY7SS.js → chunk-NOAAFNTJ.js} +43 -10
  115. package/chunks/chunk-NXS53EA7.js +1462 -0
  116. package/chunks/{chunk-C27BYUX6.js → chunk-OQB4EXO4.js} +14 -11
  117. package/chunks/{chunk-NHDKSOEY.js → chunk-P3QQPMQA.js} +5 -5
  118. package/chunks/{chunk-OP4MOGXF.js → chunk-P5RRUHL7.js} +23 -1
  119. package/chunks/{chunk-KOR3XKCA.js → chunk-PBII2NFX.js} +12 -6
  120. package/chunks/{chunk-O3OCNYY5.js → chunk-PDYB7HG2.js} +2 -2
  121. package/chunks/{chunk-2HOVDT7W.js → chunk-PFSUKTZH.js} +1 -1
  122. package/chunks/chunk-PKL3HGNZ.js +2299 -0
  123. package/chunks/{chunk-5DTTYNB7.js → chunk-PQNHRFJC.js} +16 -3
  124. package/chunks/{chunk-OLMETXLX.js → chunk-PXHK5ONM.js} +41 -9
  125. package/chunks/{chunk-PF4CHQOJ.js → chunk-Q6GU6TKM.js} +11 -10
  126. package/chunks/{chunk-4ODB7WIB.js → chunk-QAFKR7WR.js} +1 -1
  127. package/chunks/{chunk-PBATSWUQ.js → chunk-QBUDF33N.js} +1 -1
  128. package/chunks/{chunk-BVLROR2T.js → chunk-QLJUC7TG.js} +1 -1
  129. package/chunks/{chunk-UEY4AYUL.js → chunk-QNLNLENL.js} +2 -2
  130. package/chunks/{chunk-333CXMNJ.js → chunk-QXZTZJLX.js} +5 -5
  131. package/chunks/chunk-R6D2CTQR.js +289 -0
  132. package/chunks/{chunk-7PZ2ATFZ.js → chunk-R6SKHK3T.js} +54 -29
  133. package/chunks/{chunk-OONJNQ42.js → chunk-RGG6M2WF.js} +4 -4
  134. package/chunks/{chunk-RFIAR4YL.js → chunk-RV4C2ZFG.js} +1 -1
  135. package/chunks/{chunk-O3Z73NBP.js → chunk-RW2NEXYJ.js} +15 -11
  136. package/chunks/{chunk-HZPN55E5.js → chunk-SJEDL7DI.js} +1 -1
  137. package/chunks/{chunk-AKX4WPPP.js → chunk-SWBJRDYC.js} +866 -183
  138. package/chunks/{chunk-NBMIC7DR.js → chunk-SX4PK3FC.js} +145 -5
  139. package/chunks/chunk-T3452DP5.js +246 -0
  140. package/chunks/{chunk-TB6UDU4T.js → chunk-THJNPLI4.js} +16 -16
  141. package/chunks/{chunk-T4TZQJ7W.js → chunk-TWPJO254.js} +5 -16
  142. package/chunks/chunk-U7ZFW55U.js +2098 -0
  143. package/chunks/{chunk-JNWZQ27S.js → chunk-UCOJC6EB.js} +72 -23
  144. package/chunks/{chunk-W7H223ZZ.js → chunk-UGYMA4EI.js} +1 -1
  145. package/chunks/{chunk-X6YQWCIJ.js → chunk-UH3WSE5L.js} +13 -1
  146. package/chunks/{chunk-2LL7TXB4.js → chunk-UH7242DI.js} +3 -3
  147. package/chunks/{chunk-CB2HFGRV.js → chunk-UJV643E2.js} +31 -6
  148. package/chunks/chunk-UO7DCGEV.js +121 -0
  149. package/chunks/{chunk-Y2ENGUD6.js → chunk-UPF7PTBI.js} +79 -2
  150. package/chunks/chunk-UW5EOVUN.js +249 -0
  151. package/chunks/{chunk-SJMV7ZBK.js → chunk-VLVO52KC.js} +8 -8
  152. package/chunks/{chunk-R3VWUU2E.js → chunk-VYPFXUCB.js} +1 -1
  153. package/chunks/{chunk-S2W2LVDU.js → chunk-WHFK6G6U.js} +8 -9
  154. package/chunks/chunk-WI3KCKZ5.js +391 -0
  155. package/chunks/{chunk-NGFEPAE6.js → chunk-WLEFWSSC.js} +8 -6
  156. package/chunks/{chunk-XVVH63JG.js → chunk-WUJXJ34P.js} +3 -3
  157. package/chunks/{chunk-MAQQGNQ5.js → chunk-WYLPWQHJ.js} +56 -717
  158. package/chunks/{chunk-D2VIDMVM.js → chunk-X6N25LXS.js} +2 -2
  159. package/chunks/chunk-XAWJ2526.js +1049 -0
  160. package/chunks/{chunk-CV63PP6U.js → chunk-YCIM6O3I.js} +1 -1
  161. package/chunks/{chunk-OEO2ERWK.js → chunk-Z44CVEUF.js} +54 -33
  162. package/chunks/{chunk-TKLLK6XQ.js → chunk-ZT4POVWC.js} +11 -11
  163. package/chunks/{chunk-NIJEXGV6.js → chunk-ZXYUQXY5.js} +148 -10
  164. package/chunks/{computer-use-NIWQNUZF.js → computer-use-UJ5T34TE.js} +50 -37
  165. package/chunks/{config-utils-AHQ6YZ66.js → config-utils-XQRXHAN3.js} +3 -3
  166. package/chunks/contextCommand-CSCB4E5M.js +79 -0
  167. package/chunks/{create-sub-session-MGNX52P3.js → create-sub-session-55F3GOLK.js} +46 -33
  168. package/chunks/{create-sub-session-P26FE5GG.js → create-sub-session-JPCSYZAJ.js} +3 -3
  169. package/chunks/{cron-create-JWFHBDRQ.js → cron-create-CUMELMPL.js} +6 -6
  170. package/chunks/{cron-delete-GDX4E26G.js → cron-delete-QZFV6U3P.js} +5 -5
  171. package/chunks/{cron-list-USMAIWPT.js → cron-list-IDKO7ZO2.js} +5 -5
  172. package/chunks/{daemon-RG2MAI6T.js → daemon-7LP7R6IU.js} +500 -133
  173. package/chunks/daemon-status-provider-6YNZ3UAE.js +88 -0
  174. package/chunks/{de-I7ZIYXZC.js → de-4IBXM7CN.js} +5 -1
  175. package/chunks/{dist-WGTQO7F2.js → dist-376652EZ.js} +114 -28
  176. package/chunks/{dist-53PZYC5B.js → dist-3YCTE6HD.js} +2 -2
  177. package/chunks/{dist-2BHAYBKP.js → dist-D7Z3HOO7.js} +14 -2
  178. package/chunks/{dist-FUTEXY6A.js → dist-MEGJFGAI.js} +40 -9
  179. package/chunks/{dist-2MIU4UUH.js → dist-NQ436QEX.js} +1 -1
  180. package/chunks/{dist-AU7NQQRP.js → dist-NQNTOIEN.js} +26 -2
  181. package/chunks/earlyInputCapture-HPUVJ2KH.js +81 -0
  182. package/chunks/{edit-3QV3JZJL.js → edit-7CMAN3F4.js} +50 -39
  183. package/chunks/{en-XE34GKAA.js → en-SALLIJS7.js} +6 -1
  184. package/chunks/{enter-worktree-4GMMF7EG.js → enter-worktree-3PH4YTY2.js} +49 -36
  185. package/chunks/{enterPlanMode-L5UWBAUC.js → enterPlanMode-MSXLSWLI.js} +55 -37
  186. package/chunks/{environment-3OV7UQOT.js → environment-KS36ZHBE.js} +48 -35
  187. package/chunks/errors-LCPFS62A.js +87 -0
  188. package/chunks/{exit-worktree-DDP57JLV.js → exit-worktree-ARA4C3CK.js} +49 -36
  189. package/chunks/{exitPlanMode-CJBLGPIP.js → exitPlanMode-GCDIQPB7.js} +49 -36
  190. package/chunks/{fast-path-M6RP2ING.js → fast-path-IDHBVIT6.js} +3 -2
  191. package/chunks/{fr-X7KDVZIY.js → fr-WVHEBDDB.js} +5 -1
  192. package/chunks/{gemini-H4PHBJTL.js → gemini-2AFQJMX5.js} +141 -105
  193. package/chunks/{geminiContentGenerator-VURJYPWP.js → geminiContentGenerator-UDIH3YI6.js} +9 -8
  194. package/chunks/{getMachineId-bsd-EXV7SWPA.js → getMachineId-bsd-QFVLPUPT.js} +1 -1
  195. package/chunks/{getMachineId-darwin-IUOMFXU3.js → getMachineId-darwin-DGMQQE2E.js} +1 -1
  196. package/chunks/{getMachineId-linux-K7XJYFHL.js → getMachineId-linux-R4Z6CSWC.js} +1 -1
  197. package/chunks/{getMachineId-unsupported-EA5FDRJ6.js → getMachineId-unsupported-Z3SBVBUV.js} +1 -1
  198. package/chunks/{getMachineId-win-KBA6RAI5.js → getMachineId-win-SCK5UFDT.js} +1 -1
  199. package/chunks/{glob-2KUSRAVQ.js → glob-HCL7HZ67.js} +49 -36
  200. package/chunks/{grep-B5RXVESV.js → grep-CJLBSCTV.js} +49 -36
  201. package/chunks/handleAutoUpdate-Q572P3FL.js +80 -0
  202. package/chunks/i18n-OBB4R7SR.js +96 -0
  203. package/chunks/initializer-LXEY6V3C.js +85 -0
  204. package/chunks/installationInfo-XUAOVMEE.js +79 -0
  205. package/chunks/{ja-2ICT3KXF.js → ja-KY4ROZTE.js} +5 -1
  206. package/chunks/{keychain-token-storage-DWRJMNH3.js → keychain-token-storage-6ACJDYIB.js} +3 -3
  207. package/chunks/{kittyProtocolDetector-HCNNKJTI.js → kittyProtocolDetector-MBRTDRBK.js} +5 -3
  208. package/chunks/list-WAXY7QOU.js +88 -0
  209. package/chunks/list-agents-AH3P5NB7.js +80 -0
  210. package/chunks/loadedSettingsAdapter-OZFNBRHE.js +82 -0
  211. package/chunks/loggingContentGenerator-7WDTTE6G.js +1068 -0
  212. package/chunks/{loop-wakeup-5GLTUBHA.js → loop-wakeup-IHRW6TNB.js} +7 -7
  213. package/chunks/{ls-FHBY3Y7I.js → ls-ZAXZ2G2W.js} +5 -5
  214. package/chunks/{lsp-B6VMEW6Y.js → lsp-R4ZG3UGQ.js} +3 -3
  215. package/chunks/managed-npm-update-N42DO5QW.js +339 -0
  216. package/chunks/mcp-6SOORKTY.js +82 -0
  217. package/chunks/{monitor-GLJZDNPS.js → monitor-4PSVNVU4.js} +51 -37
  218. package/chunks/node-UUDY34IG.js +305 -0
  219. package/chunks/nonInteractiveCli-FBR5S7IZ.js +140 -0
  220. package/chunks/{notebook-edit-AVCIWS4F.js → notebook-edit-QK26632S.js} +50 -39
  221. package/chunks/{openaiContentGenerator-B7W24G3D.js → openaiContentGenerator-IXJS6C2U.js} +33 -20
  222. package/chunks/pidfile-UCFCJOAP.js +85 -0
  223. package/chunks/{processUtils-XZPY2PBB.js → processUtils-YL2LXON2.js} +2 -2
  224. package/chunks/{pt-JJ4XPIBP.js → pt-OK455PLH.js} +5 -1
  225. package/chunks/{qwenContentGenerator-6GUTWJIC.js → qwenContentGenerator-H6WZPJKC.js} +56 -36
  226. package/chunks/{qwenOAuth2-GASEEWGU.js → qwenOAuth2-HTROHKXO.js} +10 -23
  227. package/chunks/read-file-FOYTMUNL.js +31 -0
  228. package/chunks/{read-mcp-resource-AKCL7I43.js → read-mcp-resource-65BWNF3F.js} +3 -3
  229. package/chunks/{record-artifact-PEUB7727.js → record-artifact-2RLSOP6U.js} +3 -3
  230. package/chunks/resumeHistoryUtils-ZNHTWBXS.js +90 -0
  231. package/chunks/ripGrep-K4K4QLNJ.js +72 -0
  232. package/chunks/{ru-STR4KTW7.js → ru-7SPDGMGD.js} +5 -1
  233. package/chunks/{run-qwen-serve-OZGR3FQA.js → run-qwen-serve-XI4MCAFV.js} +343 -88
  234. package/chunks/runtime-4CTBU5WX.js +115 -0
  235. package/chunks/{scheduler-Z7QLMUWA.js → scheduler-TTEITHBF.js} +46 -33
  236. package/chunks/sdk-exporters-grpc-N3OLDF63.js +23214 -0
  237. package/chunks/sdk-exporters-http-AOHAEOMC.js +563 -0
  238. package/chunks/sdk-impl-TLQOC7P4.js +9193 -0
  239. package/chunks/{send-message-3RHE7HSM.js → send-message-GEY4CNPS.js} +47 -8
  240. package/chunks/serve-W7UKJTQT.js +88 -0
  241. package/chunks/{server-SO64U3X5.js → server-JD5PIE7A.js} +3069 -517
  242. package/chunks/{session-2KL2WQAH.js → session-R4BDHLYR.js} +112 -177
  243. package/chunks/{settings-KITVOUSV.js → settings-BXZHA6TZ.js} +50 -37
  244. package/chunks/shell-XYMFCGN5.js +82 -0
  245. package/chunks/{skill-SOQHY455.js → skill-YKXYEPOF.js} +25 -20
  246. package/chunks/spawnChannel-IO4HQLFS.js +81 -0
  247. package/chunks/{src-43LM7JLB.js → src-LKKTJ4NG.js} +382 -235
  248. package/chunks/standalone-update-76JG7DVN.js +91 -0
  249. package/chunks/{startInteractiveUI-3RGTGEX5.js → startInteractiveUI-BXWQUXAS.js} +1314 -958
  250. package/chunks/{syntheticOutput-FG5PQKIR.js → syntheticOutput-2WNMXEU5.js} +4 -4
  251. package/chunks/task-create-R5H74Y76.js +25 -0
  252. package/chunks/{task-list-QWSY4ZIU.js → task-list-WXAFDSRY.js} +7 -7
  253. package/chunks/{task-stop-GWC6UWAL.js → task-stop-CHFZP23W.js} +4 -4
  254. package/chunks/{task-update-NCTAB73Q.js → task-update-Z44A4GAR.js} +11 -9
  255. package/chunks/{team-create-FXN3PEBP.js → team-create-5Y3MCAIM.js} +49 -36
  256. package/chunks/{team-delete-KK37HTOG.js → team-delete-YDCMRSI4.js} +7 -7
  257. package/chunks/{team-plan-approval-GEIZ356Q.js → team-plan-approval-HYJJZ76T.js} +49 -36
  258. package/chunks/theme-manager-3YF2SUZL.js +76 -0
  259. package/chunks/{todoWrite-ERCAMLFS.js → todoWrite-ED2IVZJL.js} +5 -5
  260. package/chunks/{tool-search-XKK7DNOK.js → tool-search-3ZO2XMEP.js} +21 -17
  261. package/chunks/total-session-admission-NDF7EVG7.js +83 -0
  262. package/chunks/trustedFolders-Q7RALK4T.js +92 -0
  263. package/chunks/{chunk-6EFTQYW7.js → undici-3FJYTMOF.js} +24 -399
  264. package/chunks/{chunk-L573Z2QZ.js → undici-PYHBDDPN.js} +1 -5
  265. package/chunks/{update-relaunch-FMVZK6XF.js → update-relaunch-BTW5XGVT.js} +17 -17
  266. package/chunks/updateCheck-MXIU6DWQ.js +91 -0
  267. package/chunks/useAutoAcceptIndicator-BJXHJW77.js +92 -0
  268. package/chunks/{validateNonInterActiveAuth-PRVEB6GG.js → validateNonInterActiveAuth-FLEPF3QQ.js} +90 -76
  269. package/chunks/{version-AZMG6KWL.js → version-75VRONIL.js} +1 -1
  270. package/chunks/{web-fetch-EPGJ5OQQ.js → web-fetch-5X27LYHB.js} +101 -41
  271. package/chunks/web-search-IDMTBJUP.js +718 -0
  272. package/chunks/{workflow-UTNVPW22.js → workflow-JOD2OPFQ.js} +54 -40
  273. package/chunks/workspace-providers-status-WDLBDLPG.js +85 -0
  274. package/chunks/{workspace-registration-store-F3ZX3YHT.js → workspace-registration-store-26Z6J6P5.js} +9 -3
  275. package/chunks/workspace-registry-IABDATX3.js +87 -0
  276. package/chunks/workspace-service-BI4KDYPD.js +97 -0
  277. package/chunks/workspace-skills-status-OVB4LPHA.js +84 -0
  278. package/chunks/write-file-276AJ7KE.js +72 -0
  279. package/chunks/{zh-6ANG2HTL.js → zh-Q54GA5SV.js} +6 -1
  280. package/chunks/{zh-TW-4RR3YHNN.js → zh-TW-VOBNFOPU.js} +6 -1
  281. package/cli-entry.js +164 -12
  282. package/cli.js +19 -12
  283. package/locales/ca.js +773 -203
  284. package/locales/de.js +8 -2
  285. package/locales/en.js +9 -2
  286. package/locales/fr.js +8 -2
  287. package/locales/ja.js +8 -2
  288. package/locales/pt.js +8 -2
  289. package/locales/ru.js +8 -2
  290. package/locales/zh-TW.js +9 -2
  291. package/locales/zh.js +9 -2
  292. package/package.json +3 -3
  293. package/web-shell/assets/{arc-Buk1besA.js → arc-CMb7lr2P.js} +1 -1
  294. package/web-shell/assets/{architectureDiagram-3BPJPVTR-B1aUKYDC.js → architectureDiagram-3BPJPVTR-D6KQ5Kwm.js} +1 -1
  295. package/web-shell/assets/{blockDiagram-GPEHLZMM-CRTdg3Zx.js → blockDiagram-GPEHLZMM-Ce7YYSf8.js} +1 -1
  296. package/web-shell/assets/{c4Diagram-AAUBKEIU-DFdRMp5g.js → c4Diagram-AAUBKEIU-DaStHfor.js} +1 -1
  297. package/web-shell/assets/channel-Dg4f-Kry.js +1 -0
  298. package/web-shell/assets/{chunk-2J33WTMH-4rYQdkEI.js → chunk-2J33WTMH-CPaqadg9.js} +1 -1
  299. package/web-shell/assets/{chunk-4BX2VUAB-Coi-pQJy.js → chunk-4BX2VUAB-Veh9ZGKg.js} +1 -1
  300. package/web-shell/assets/{chunk-55IACEB6-BtBjz02t.js → chunk-55IACEB6-BPTX5n4q.js} +1 -1
  301. package/web-shell/assets/{chunk-727SXJPM-CGYOWorl.js → chunk-727SXJPM-CtXsE_ca.js} +1 -1
  302. package/web-shell/assets/{chunk-AQP2D5EJ-CH5AKhqx.js → chunk-AQP2D5EJ-D8DDCJ8h.js} +1 -1
  303. package/web-shell/assets/{chunk-FMBD7UC4-Cd50-w85.js → chunk-FMBD7UC4-cjMDGzHz.js} +1 -1
  304. package/web-shell/assets/{chunk-ND2GUHAM-C2wF3KCK.js → chunk-ND2GUHAM-BaZ1hNhV.js} +1 -1
  305. package/web-shell/assets/{chunk-QZHKN3VN-pCeRTaWi.js → chunk-QZHKN3VN-C7w-9w5-.js} +1 -1
  306. package/web-shell/assets/classDiagram-4FO5ZUOK-CT7Fo2aW.js +1 -0
  307. package/web-shell/assets/classDiagram-v2-Q7XG4LA2-CT7Fo2aW.js +1 -0
  308. package/web-shell/assets/{cose-bilkent-S5V4N54A-B-_fAB6D.js → cose-bilkent-S5V4N54A-DqvBEEIe.js} +1 -1
  309. package/web-shell/assets/{dagre-BM42HDAG-ChSPNHpL.js → dagre-BM42HDAG-RkPyoMAk.js} +1 -1
  310. package/web-shell/assets/{diagram-2AECGRRQ-BX7cFOF3.js → diagram-2AECGRRQ-D9b6nNyg.js} +1 -1
  311. package/web-shell/assets/{diagram-5GNKFQAL-BQUTW92n.js → diagram-5GNKFQAL-CiiNKUIy.js} +1 -1
  312. package/web-shell/assets/{diagram-KO2AKTUF-BkYPh3e4.js → diagram-KO2AKTUF-CP1qizXd.js} +1 -1
  313. package/web-shell/assets/{diagram-LMA3HP47-Cl6jsNyx.js → diagram-LMA3HP47-BGe30TWx.js} +1 -1
  314. package/web-shell/assets/{diagram-OG6HWLK6-DRWoHz8n.js → diagram-OG6HWLK6-CvoEPARH.js} +1 -1
  315. package/web-shell/assets/{erDiagram-TEJ5UH35-CGvFcZco.js → erDiagram-TEJ5UH35-DWfLzVkV.js} +1 -1
  316. package/web-shell/assets/{flowDiagram-I6XJVG4X-vms6oVdv.js → flowDiagram-I6XJVG4X-D-dTQmo6.js} +1 -1
  317. package/web-shell/assets/{ganttDiagram-6RSMTGT7-ukT_sfmi.js → ganttDiagram-6RSMTGT7-CYPHKaGY.js} +1 -1
  318. package/web-shell/assets/{gitGraphDiagram-PVQCEYII-Bn2ZE2Ut.js → gitGraphDiagram-PVQCEYII-DA7_aQYD.js} +1 -1
  319. package/web-shell/assets/index-B0i-TOYM.css +5 -0
  320. package/web-shell/assets/index-CgCHD46L.js +1225 -0
  321. package/web-shell/assets/{index-wFXp7W68.js → index-DqHNAB8C.js} +1 -1
  322. package/web-shell/assets/{infoDiagram-5YYISTIA-DHJdSi7x.js → infoDiagram-5YYISTIA-B87ljDPa.js} +1 -1
  323. package/web-shell/assets/{ishikawaDiagram-YF4QCWOH-DOvd2Wph.js → ishikawaDiagram-YF4QCWOH-CYSpyjaN.js} +1 -1
  324. package/web-shell/assets/{journeyDiagram-JHISSGLW-CH_urMCT.js → journeyDiagram-JHISSGLW-DAL6Js6f.js} +1 -1
  325. package/web-shell/assets/{kanban-definition-UN3LZRKU-FKiBdgbH.js → kanban-definition-UN3LZRKU-_zufKGJv.js} +1 -1
  326. package/web-shell/assets/{linear-0ZVQFVKf.js → linear-DidhMgku.js} +1 -1
  327. package/web-shell/assets/{mermaid.core-DJ05ZZIK.js → mermaid.core-DAkX3h3a.js} +5 -5
  328. package/web-shell/assets/{mindmap-definition-RKZ34NQL-BPuUhkUm.js → mindmap-definition-RKZ34NQL-DbZxUBEH.js} +1 -1
  329. package/web-shell/assets/{pieDiagram-4H26LBE5-yLFKcXyG.js → pieDiagram-4H26LBE5-Du9uoqrf.js} +1 -1
  330. package/web-shell/assets/{quadrantDiagram-W4KKPZXB-irWqc1pE.js → quadrantDiagram-W4KKPZXB-DwjELuKm.js} +1 -1
  331. package/web-shell/assets/{requirementDiagram-4Y6WPE33-B_4uMoIV.js → requirementDiagram-4Y6WPE33-BAqfVtBL.js} +1 -1
  332. package/web-shell/assets/{sankeyDiagram-5OEKKPKP-ciA4GPwk.js → sankeyDiagram-5OEKKPKP--hm2VpmK.js} +1 -1
  333. package/web-shell/assets/{sequenceDiagram-3UESZ5HK-CRdZvy0U.js → sequenceDiagram-3UESZ5HK-R5MUQaIt.js} +1 -1
  334. package/web-shell/assets/{stateDiagram-AJRCARHV-DaYIkCCn.js → stateDiagram-AJRCARHV-VsX032xQ.js} +1 -1
  335. package/web-shell/assets/stateDiagram-v2-BHNVJYJU-uPWLcSfy.js +1 -0
  336. package/web-shell/assets/{timeline-definition-PNZ67QCA-oBUKv6iH.js → timeline-definition-PNZ67QCA-BqjVRXzg.js} +1 -1
  337. package/web-shell/assets/{vennDiagram-CIIHVFJN-CGW9Sdmb.js → vennDiagram-CIIHVFJN-i2tkvlkg.js} +1 -1
  338. package/web-shell/assets/{wardley-L42UT6IY-CvwKJOCm.js → wardley-L42UT6IY-Ch8G49EM.js} +1 -1
  339. package/web-shell/assets/{wardleyDiagram-YWT4CUSO-Ipc260sN.js → wardleyDiagram-YWT4CUSO-bYpWeQNy.js} +1 -1
  340. package/web-shell/assets/{xychartDiagram-2RQKCTM6-D6-CM7pK.js → xychartDiagram-2RQKCTM6-C9NhuBqB.js} +1 -1
  341. package/web-shell/index.html +17 -13
  342. package/chunks/MaxSizedBox-B5YGZSYE.js +0 -72
  343. package/chunks/agent-H4JIDL7S.js +0 -67
  344. package/chunks/agent-headless-TTBEREQV.js +0 -61
  345. package/chunks/bridge-VL7ITBU5.js +0 -75
  346. package/chunks/chunk-542SK7KV.js +0 -8293
  347. package/chunks/chunk-CPCVCKKF.js +0 -358
  348. package/chunks/chunk-SEKHYHMS.js +0 -45
  349. package/chunks/chunk-W7FJ3N32.js +0 -49
  350. package/chunks/chunk-ZFKNWQGQ.js +0 -74639
  351. package/chunks/contextCommand-L2COEUHS.js +0 -66
  352. package/chunks/daemon-status-provider-NL4IAG7B.js +0 -74
  353. package/chunks/earlyInputCapture-L6I2A22T.js +0 -68
  354. package/chunks/errors-LEOF5QG4.js +0 -74
  355. package/chunks/handleAutoUpdate-QQVIWXKT.js +0 -67
  356. package/chunks/i18n-N6OBDORT.js +0 -83
  357. package/chunks/initializer-6WCFNDLL.js +0 -72
  358. package/chunks/installationInfo-6J3WPXNS.js +0 -64
  359. package/chunks/list-HOWQSWP6.js +0 -75
  360. package/chunks/loadedSettingsAdapter-AO4YBRXZ.js +0 -69
  361. package/chunks/mcp-QH7QNXOH.js +0 -69
  362. package/chunks/nonInteractiveCli-TI7EMPXD.js +0 -126
  363. package/chunks/pidfile-UEHAT6DH.js +0 -72
  364. package/chunks/read-file-SQJONF6A.js +0 -29
  365. package/chunks/resumeHistoryUtils-PFQ2A23X.js +0 -78
  366. package/chunks/ripGrep-QCK22GDU.js +0 -59
  367. package/chunks/runtime-SNVAP6EH.js +0 -100
  368. package/chunks/serve-BT7KS6SC.js +0 -75
  369. package/chunks/shell-BITUVH2R.js +0 -69
  370. package/chunks/spawnChannel-2BU3AULL.js +0 -68
  371. package/chunks/standalone-update-YG5JUYCM.js +0 -78
  372. package/chunks/task-create-HX32YXO7.js +0 -23
  373. package/chunks/theme-manager-IAETOI25.js +0 -63
  374. package/chunks/total-session-admission-BJLDHKJN.js +0 -69
  375. package/chunks/trustedFolders-5XCVNEUU.js +0 -79
  376. package/chunks/updateCheck-YZZB7YBU.js +0 -70
  377. package/chunks/useAutoAcceptIndicator-ZSQX4I2H.js +0 -80
  378. package/chunks/workspace-providers-status-EADV364W.js +0 -72
  379. package/chunks/workspace-registry-W6VMFYZU.js +0 -73
  380. package/chunks/workspace-service-F3KIN2UN.js +0 -84
  381. package/chunks/workspace-skills-status-YVICUR5Y.js +0 -71
  382. package/chunks/write-file-CVGF2OKV.js +0 -596
  383. package/web-shell/assets/channel-04R0vLbG.js +0 -1
  384. package/web-shell/assets/classDiagram-4FO5ZUOK-Bw9SOwAV.js +0 -1
  385. package/web-shell/assets/classDiagram-v2-Q7XG4LA2-Bw9SOwAV.js +0 -1
  386. package/web-shell/assets/index-DgkKrjw3.js +0 -1187
  387. package/web-shell/assets/index-Rv6mOAN9.css +0 -5
  388. package/web-shell/assets/stateDiagram-v2-BHNVJYJU-DWBoO4UY.js +0 -1
@@ -12,40 +12,46 @@ import {
12
12
  matchMcpServerByRef,
13
13
  parseExtensionRef,
14
14
  parseMcpServerRef
15
- } from "./chunk-IVPSS6EL.js";
15
+ } from "./chunk-F5MBYZSU.js";
16
16
  import {
17
17
  getAvailableCommands,
18
18
  handleSlashCommand,
19
19
  insertAfterFunctionResponses,
20
20
  isSlashCommand,
21
21
  normalizePartList
22
- } from "./chunk-PBWEWI4N.js";
22
+ } from "./chunk-BW5Z5NOG.js";
23
+ import {
24
+ collectContextData,
25
+ formatContextUsageText
26
+ } from "./chunk-BJBUDCM3.js";
23
27
  import {
24
28
  recomputeMcpGating
25
- } from "./chunk-333CXMNJ.js";
29
+ } from "./chunk-QXZTZJLX.js";
26
30
  import {
27
31
  appEvents,
28
32
  buildDisabledSkillNamesProvider,
29
33
  loadCliConfig,
30
34
  normalizeDisabledToolList
31
- } from "./chunk-4XNLIGVA.js";
35
+ } from "./chunk-JKCALGYN.js";
32
36
  import {
33
37
  getCommandSubcommandNames
34
- } from "./chunk-HZPN55E5.js";
38
+ } from "./chunk-SJEDL7DI.js";
35
39
  import {
36
40
  getEffectiveSupportedModes
37
- } from "./chunk-2LL7TXB4.js";
38
- import "./chunk-5DTTYNB7.js";
39
- import "./chunk-QKYTTBYW.js";
40
- import {
41
- collectContextData,
42
- formatContextUsageText
43
- } from "./chunk-A5LYNIW7.js";
41
+ } from "./chunk-UH7242DI.js";
44
42
  import "./chunk-4WGODMVR.js";
45
- import "./chunk-AYCDXHZB.js";
46
- import "./chunk-KDC6GNQR.js";
47
- import "./chunk-KG3XV6FH.js";
48
- import "./chunk-S2W2LVDU.js";
43
+ import "./chunk-PQNHRFJC.js";
44
+ import "./chunk-4LVZNIDO.js";
45
+ import "./chunk-7Z6JQEL6.js";
46
+ import {
47
+ beginAcpBootstrapConfigProfiling,
48
+ buildAndFreezeAcpStartupProfile,
49
+ endAcpBootstrapConfigProfiling,
50
+ markAcpStartup
51
+ } from "./chunk-HIJQF5B5.js";
52
+ import "./chunk-LEEWLFHW.js";
53
+ import "./chunk-JYUSL2V4.js";
54
+ import "./chunk-WHFK6G6U.js";
49
55
  import "./chunk-YAF2MQZ6.js";
50
56
  import {
51
57
  GENERATION_MAX_PROMPT_BYTES,
@@ -59,13 +65,14 @@ import {
59
65
  executeGeneration,
60
66
  formatWorkspaceMemoryForgetSummary,
61
67
  isValidServerName,
68
+ normalizeChannelDeliveryText,
62
69
  redactMcpServerSecrets,
63
70
  replayTranscriptRecordPage,
64
71
  restoreRedactedMcpSecrets,
65
72
  shouldSuppressRememberErrorDetails,
66
73
  workspaceMemoryFailureCode,
67
74
  workspaceMemoryFailureDiagnostics
68
- } from "./chunk-5JBR5XIK.js";
75
+ } from "./chunk-G7EFBBVF.js";
69
76
  import {
70
77
  HistoryReplayer,
71
78
  MessageEmitter,
@@ -75,83 +82,81 @@ import {
75
82
  goalTerminalEventToHistoryItem,
76
83
  recordGoalStatusItem,
77
84
  restoreGoalFromHistory
78
- } from "./chunk-PGEPSDJI.js";
79
- import "./chunk-KTUQMDEP.js";
80
- import "./chunk-D22SX43D.js";
81
- import "./chunk-RS7MT2QG.js";
82
- import "./chunk-H2XVO6NE.js";
85
+ } from "./chunk-FWNZ7CVN.js";
86
+ import "./chunk-4K7VDKAD.js";
87
+ import "./chunk-IPUUTYMV.js";
88
+ import "./chunk-DWNZ6PVQ.js";
89
+ import "./chunk-2MIN6GRR.js";
83
90
  import "./chunk-QHTIBUWB.js";
84
91
  import {
85
92
  isTerminalGoalStatusKind
86
93
  } from "./chunk-QTERJVPZ.js";
87
- import "./chunk-L573Z2QZ.js";
88
- import {
89
- computeCpuPercent
90
- } from "./chunk-HGT6JR3U.js";
91
- import "./chunk-RXFQM6FQ.js";
92
- import "./chunk-KOR3XKCA.js";
93
- import "./chunk-6H67XLET.js";
94
- import {
95
- beginAcpBootstrapConfigProfiling,
96
- buildAndFreezeAcpStartupProfile,
97
- endAcpBootstrapConfigProfiling,
98
- markAcpStartup
99
- } from "./chunk-TDKQP3M6.js";
100
- import "./chunk-VEXFOTEO.js";
101
- import "./chunk-LXXMOYPL.js";
102
- import "./chunk-NDMQLV4Y.js";
103
- import "./chunk-E5Z2AVNV.js";
104
- import {
105
- ACP_ROUTE_ID_PREFIX,
106
- buildAcpModelOptions,
107
- getCurrentAcpModelId,
108
- parseAcpBaseModelId,
109
- parseAcpModelOption,
110
- resolveAcpModelOption,
111
- sanitizeProviderBaseUrl
112
- } from "./chunk-NGFEPAE6.js";
113
- import {
114
- mapSkillConfigToStatus
115
- } from "./chunk-2W3OOD4W.js";
94
+ import "./chunk-3Z43GZUQ.js";
116
95
  import {
117
96
  PERMISSION_RULE_TYPES,
118
97
  PermissionRulesValidationError,
119
98
  buildPermissionSettings,
120
99
  normalizePermissionRules,
121
100
  readPermissionRuleSet
122
- } from "./chunk-S2XVRHDN.js";
101
+ } from "./chunk-JDFBBGRD.js";
123
102
  import {
124
103
  MAX_AUDIO_BYTES,
125
104
  sanitizeVoiceErrorMessage,
126
105
  transcribeVoiceAudio
127
- } from "./chunk-IR46U7RB.js";
106
+ } from "./chunk-3FB2Y2OE.js";
128
107
  import {
129
108
  readVoiceModel
130
- } from "./chunk-S2PD3EZD.js";
131
- import "./chunk-BVLROR2T.js";
109
+ } from "./chunk-KJEMJWNH.js";
110
+ import "./chunk-QLJUC7TG.js";
111
+ import {
112
+ computeCpuPercent
113
+ } from "./chunk-HGT6JR3U.js";
114
+ import "./chunk-RXFQM6FQ.js";
115
+ import "./chunk-PBII2NFX.js";
116
+ import "./chunk-6H67XLET.js";
117
+ import {
118
+ createLoadedSettingsAdapter
119
+ } from "./chunk-LA5H3LM5.js";
120
+ import "./chunk-LXXMOYPL.js";
121
+ import "./chunk-LBAO2XRA.js";
122
+ import "./chunk-E5Z2AVNV.js";
132
123
  import {
133
124
  parseSessionSource
134
- } from "./chunk-AKX4WPPP.js";
135
- import "./chunk-6RLROE6G.js";
136
- import "./chunk-COH43MRJ.js";
125
+ } from "./chunk-SWBJRDYC.js";
126
+ import {
127
+ NOT_CURRENTLY_GENERATING_CANCEL_MESSAGE
128
+ } from "./chunk-UH3WSE5L.js";
137
129
  import {
138
130
  CHANNEL_STARTUP_PROFILE_META_KEY,
139
131
  CHANNEL_STARTUP_PROFILE_VERSION,
140
132
  CLIENT_MCP_OVER_WS_CONFIG_FLAG,
133
+ DAEMON_CHANNEL_DELIVERY_META_KEY,
141
134
  LOAD_REPLAY_BULK_MODE,
142
135
  LOAD_REPLAY_META_KEY,
143
136
  LOAD_REPLAY_MODE_META_KEY,
144
137
  LOAD_REPLAY_PAGE_SIZE_META_KEY,
145
138
  LOAD_REPLAY_VERSION,
146
139
  MID_TURN_QUEUE_DRAIN_METHOD,
140
+ PROMPT_CANCEL_METHOD,
147
141
  TODO_STOP_GUARD_QUEUE_RELEASE_METHOD
148
- } from "./chunk-QR6U5QPP.js";
142
+ } from "./chunk-3SJ43L4W.js";
143
+ import "./chunk-BLFVGB7D.js";
144
+ import "./chunk-COH43MRJ.js";
149
145
  import {
150
146
  ndJsonStream
151
- } from "./chunk-CV63PP6U.js";
147
+ } from "./chunk-YCIM6O3I.js";
152
148
  import {
153
- NOT_CURRENTLY_GENERATING_CANCEL_MESSAGE
154
- } from "./chunk-X6YQWCIJ.js";
149
+ ACP_ROUTE_ID_PREFIX,
150
+ buildAcpModelOptions,
151
+ getCurrentAcpModelId,
152
+ parseAcpBaseModelId,
153
+ parseAcpModelOption,
154
+ resolveAcpModelOption,
155
+ sanitizeProviderBaseUrl
156
+ } from "./chunk-WLEFWSSC.js";
157
+ import {
158
+ mapSkillConfigToStatus
159
+ } from "./chunk-2W3OOD4W.js";
155
160
  import {
156
161
  ACP_PREFLIGHT_KINDS,
157
162
  IDLE_HOOK_EVENTS,
@@ -159,23 +164,22 @@ import {
159
164
  SERVE_STATUS_EXT_METHODS,
160
165
  STATUS_SCHEMA_VERSION,
161
166
  mapDomainErrorToErrorKind
162
- } from "./chunk-VDWBQ5AW.js";
163
- import "./chunk-CB2HFGRV.js";
164
- import "./chunk-MJ6S23WZ.js";
167
+ } from "./chunk-CUPAVLRY.js";
168
+ import "./chunk-PFSUKTZH.js";
169
+ import "./chunk-UJV643E2.js";
170
+ import "./chunk-HZEWYOVI.js";
165
171
  import "./chunk-57OAHC2Y.js";
166
- import "./chunk-YWEW33JY.js";
167
- import "./chunk-4ODB7WIB.js";
172
+ import "./chunk-HVO55LUD.js";
173
+ import "./chunk-QAFKR7WR.js";
168
174
  import "./chunk-V6WHFGST.js";
169
- import {
170
- createLoadedSettingsAdapter
171
- } from "./chunk-CZF3E5GF.js";
172
- import "./chunk-W7FJ3N32.js";
173
- import "./chunk-Y2ENGUD6.js";
174
- import "./chunk-TJTKSVIV.js";
175
+ import "./chunk-BSNWBC33.js";
176
+ import "./chunk-2RFKHEXL.js";
177
+ import "./chunk-UPF7PTBI.js";
178
+ import "./chunk-JLU636DO.js";
179
+ import "./chunk-BK2UNYWD.js";
175
180
  import "./chunk-M5GB774H.js";
176
- import "./chunk-RFIAR4YL.js";
177
- import "./chunk-2HOVDT7W.js";
178
- import "./chunk-NIJEXGV6.js";
181
+ import "./chunk-RV4C2ZFG.js";
182
+ import "./chunk-ZXYUQXY5.js";
179
183
  import {
180
184
  AgentSideConnection,
181
185
  PROTOCOL_VERSION,
@@ -184,7 +188,7 @@ import {
184
188
  import {
185
189
  assembleMcpServers,
186
190
  loadMcpApprovals
187
- } from "./chunk-7SXZC7ID.js";
191
+ } from "./chunk-2WTVWAKT.js";
188
192
  import {
189
193
  getOutputLanguageFilePath,
190
194
  getPersistScopeForModelSelection,
@@ -193,7 +197,7 @@ import {
193
197
  resolveOutputLanguageOrPreserveAuto,
194
198
  updateOutputLanguageFile,
195
199
  writeOutputLanguageAndRegisterPath
196
- } from "./chunk-33XUAINQ.js";
200
+ } from "./chunk-J5UKQEFG.js";
197
201
  import "./chunk-RKUWKYED.js";
198
202
  import "./chunk-GOXKNSDZ.js";
199
203
  import {
@@ -204,20 +208,20 @@ import {
204
208
  SUPPORTED_LANGUAGES,
205
209
  getCurrentLanguage,
206
210
  setLanguageAsync
207
- } from "./chunk-TKLLK6XQ.js";
211
+ } from "./chunk-ZT4POVWC.js";
208
212
  import {
209
213
  findEnvFiles,
210
214
  preResolveHomeEnvOverrides,
211
215
  reloadEnvironment
212
- } from "./chunk-TIH2ZTOC.js";
216
+ } from "./chunk-32A4PI3E.js";
213
217
  import "./chunk-QRUIS3DN.js";
214
- import "./chunk-OWCALFEG.js";
218
+ import "./chunk-54R2CV2G.js";
215
219
  import "./chunk-VJNBRRZG.js";
216
220
  import {
217
221
  isFolderTrustEnabled,
218
222
  isWorkspaceTrusted,
219
223
  loadTrustedFolders
220
- } from "./chunk-I2PYAYFM.js";
224
+ } from "./chunk-CXUFILV3.js";
221
225
  import "./chunk-ALGGS7UH.js";
222
226
  import "./chunk-MR3PXB6E.js";
223
227
  import {
@@ -243,16 +247,20 @@ import {
243
247
  McpServerSpawnFailedError,
244
248
  McpTransportPool,
245
249
  MessageDisplayDispatcher,
250
+ PLAN_MODE_ENTRY_SIBLING_SKIP_MESSAGE,
246
251
  POOLED_TRANSPORTS_DEFAULT,
247
252
  SESSION_ARTIFACT_PERSISTENCE_VERSION,
248
253
  SESSION_TITLE_MAX_LENGTH,
249
254
  SESSION_TRANSCRIPT_MAX_LIMIT,
250
255
  SESSION_TRANSCRIPT_MAX_PAGE_BYTES,
256
+ SESSION_WRITER_RPC_CODES,
251
257
  SessionService,
252
258
  SessionTranscriptPageTooLargeError,
253
259
  SessionTranscriptReader,
254
260
  SessionTranscriptSnapshotUnavailableError,
255
261
  SessionTranscriptTooLargeError,
262
+ SessionWriterError,
263
+ SessionWriterUnavailableError,
256
264
  TURN_INTERRUPTION_HISTORY_TAIL_COUNT,
257
265
  WorkspaceMcpBudget,
258
266
  abortGoalForStopHookCap,
@@ -272,13 +280,18 @@ import {
272
280
  convertToFunctionErrorResponse,
273
281
  convertToFunctionResponse,
274
282
  createDuplicateProviderToolCallResponse,
283
+ decorateClassifierUnavailableConfirmation,
284
+ decoratePlanModeShellConfirmation,
275
285
  dedupeToolCallsById,
276
286
  detectAutonomousSentinel,
277
287
  detectLoopSentinel,
278
288
  encodeSessionTranscriptCursor,
279
289
  evaluateAutoMode,
280
290
  evaluatePermissionFlow,
291
+ evaluatePlanModeShellPolicy,
292
+ finalizeToolResponses,
281
293
  findExistingProviderModels,
294
+ findPlanModeEntryBatchBoundaryIndex,
282
295
  findProviderById,
283
296
  findRepeatedDuplicateProviderToolCall,
284
297
  fireNotificationHook,
@@ -301,21 +314,19 @@ import {
301
314
  getPlanModeSystemReminder,
302
315
  getProviderToolCallId,
303
316
  getScopedEnvContents,
304
- getStartupContextLength,
317
+ getStopHookContinuationReason,
305
318
  ideContextStore,
306
319
  injectPermissionRulesIfMissing,
307
320
  isApproveOutcome,
308
321
  isDenialFallbackReason,
309
322
  isGatedMcpScope,
310
323
  isPlanModeBlocked,
311
- isSystemReminderContent,
312
324
  markDuplicateProviderToolCallResponseSent,
313
325
  matchesAnyServerPattern,
314
326
  mcpServerRequiresOAuth,
315
327
  needsConfirmation,
316
328
  normalizeEventPayload,
317
329
  normalizeSnapshotPayload,
318
- parsePositiveIntegerEnv,
319
330
  persistPermissionOutcome,
320
331
  readManyFiles,
321
332
  recordAllow,
@@ -337,53 +348,79 @@ import {
337
348
  shouldRunAutoModeForCall,
338
349
  subagentGenerator,
339
350
  unregisterGoalHook,
340
- updateSetting
341
- } from "./chunk-KX6UK4VJ.js";
351
+ updateSetting,
352
+ validatePlanModeShellApproval,
353
+ validatePlanModeShellContext
354
+ } from "./chunk-LI4I37W4.js";
342
355
  import "./chunk-5M6IDOMF.js";
343
- import "./chunk-T4TZQJ7W.js";
356
+ import "./chunk-TWPJO254.js";
344
357
  import {
345
358
  external_exports
346
359
  } from "./chunk-H6XPXXMH.js";
347
- import "./chunk-EAUYY7SS.js";
348
- import "./chunk-FSL5W5TI.js";
349
- import "./chunk-OONJNQ42.js";
350
- import "./chunk-D2VIDMVM.js";
351
- import "./chunk-E2UVIFI2.js";
352
- import "./chunk-XU457J4V.js";
360
+ import "./chunk-NOAAFNTJ.js";
361
+ import "./chunk-AFFGGOF6.js";
362
+ import "./chunk-RGG6M2WF.js";
363
+ import "./chunk-X6N25LXS.js";
364
+ import "./chunk-KRXPRVGL.js";
365
+ import {
366
+ parsePositiveIntegerEnv
367
+ } from "./chunk-6PVPNMXU.js";
368
+ import "./chunk-UO7DCGEV.js";
369
+ import "./chunk-IRH27ZC2.js";
353
370
  import "./chunk-VDDGDZMA.js";
354
- import "./chunk-EIAK6Q2B.js";
371
+ import "./chunk-C3VHAXP2.js";
355
372
  import "./chunk-SZRN75WQ.js";
356
373
  import "./chunk-HTO4JFDZ.js";
357
374
  import "./chunk-CPBF7KYF.js";
358
375
  import {
359
376
  APPROVAL_MODES,
360
377
  FORK_SUBAGENT_TYPE,
378
+ getStartupContextLength,
379
+ isSystemReminderContent,
361
380
  runWithRuntimeContentGenerator
362
- } from "./chunk-CPCVCKKF.js";
381
+ } from "./chunk-XAWJ2526.js";
363
382
  import "./chunk-6AM5D4ME.js";
364
- import "./chunk-G45X5TRN.js";
383
+ import "./chunk-NABLFI57.js";
365
384
  import {
366
385
  HookEventName,
367
386
  createHookOutput
368
- } from "./chunk-PBATSWUQ.js";
369
- import "./chunk-ZEOZL37W.js";
370
- import "./chunk-OOCI5VVU.js";
387
+ } from "./chunk-QBUDF33N.js";
388
+ import "./chunk-JCW2R7WC.js";
389
+ import "./chunk-57FIIFJN.js";
390
+ import "./chunk-LIZRAKPB.js";
371
391
  import {
372
392
  clearCachedCredentialFile,
373
393
  qwenOAuth2Events
374
- } from "./chunk-BRRF37CO.js";
375
- import "./chunk-BMWMT5Y2.js";
394
+ } from "./chunk-LYTBLSSW.js";
395
+ import "./chunk-WI3KCKZ5.js";
396
+ import "./chunk-DP5GT2MW.js";
376
397
  import "./chunk-JESCGQM3.js";
398
+ import "./chunk-XVNQMZ2I.js";
399
+ import "./chunk-FODK6UMO.js";
400
+ import "./chunk-GLNBDYUX.js";
401
+ import "./chunk-DJ2GSRLV.js";
402
+ import "./chunk-R6D2CTQR.js";
403
+ import {
404
+ extractDaemonTraceContext,
405
+ registerAcpEventLoopLagGauge,
406
+ startEventLoopLagMonitor,
407
+ withDaemonSpan
408
+ } from "./chunk-AXUW635Q.js";
409
+ import "./chunk-BPJSQIJX.js";
410
+ import "./chunk-P3QQPMQA.js";
411
+ import "./chunk-6QHAUJUE.js";
412
+ import {
413
+ getToolCallPreparations
414
+ } from "./chunk-LS77BEZP.js";
377
415
  import {
378
- AuthType,
379
416
  ConversationFinishedEvent,
380
417
  DiscoveredMCPTool,
418
+ INVOCATION_CONTEXT_META_KEY,
381
419
  LoopDetectedEvent,
420
+ PRIVATE_ACP_CAPABILITY_ENV,
421
+ PRIVATE_PARENT_CAPABILITY_META_KEY,
382
422
  PromptSuggestionEvent,
383
423
  UserPromptEvent,
384
- endToolExecutionSpan,
385
- endToolSpan,
386
- extractDaemonTraceContext,
387
424
  formatFullTurnVisionNotice,
388
425
  formatVisionBridgeNotice,
389
426
  getAllGeminiMdFilenames,
@@ -397,63 +434,66 @@ import {
397
434
  logToolCall,
398
435
  logUserPrompt,
399
436
  normalizeParts,
400
- registerAcpEventLoopLagGauge,
401
- runInToolSpanContext,
437
+ parseInvocationContext,
402
438
  runSideQuery,
403
439
  runVisionBridge,
440
+ runWithInvocationContext,
404
441
  shouldRunVisionBridge,
405
442
  splitImageParts,
406
- startEventLoopLagMonitor,
407
- startToolExecutionSpan,
408
- startToolSpan,
409
- uiTelemetryService,
410
- withDaemonSpan,
411
- withInteractionSpan
412
- } from "./chunk-ZFKNWQGQ.js";
413
- import "./chunk-4WKAA4KS.js";
414
- import "./chunk-CR3C7WXL.js";
443
+ uiTelemetryService
444
+ } from "./chunk-IFG6TYJ2.js";
415
445
  import "./chunk-VGC4I5JJ.js";
416
446
  import {
417
447
  getAutoMemoryRoot,
418
448
  getUserAutoMemoryRoot
419
- } from "./chunk-JD3MKVKL.js";
420
- import "./chunk-UEY4AYUL.js";
421
- import "./chunk-BDBMYST4.js";
422
- import "./chunk-EZVDJFZ7.js";
449
+ } from "./chunk-4K56OJFJ.js";
423
450
  import {
424
- ToolConfirmationOutcome,
425
- ToolNames,
426
- isShellProgressData
427
- } from "./chunk-OP4MOGXF.js";
428
- import "./chunk-XVNQMZ2I.js";
429
- import "./chunk-FEOZBUMT.js";
430
- import "./chunk-DJ2GSRLV.js";
431
- import "./chunk-6EFTQYW7.js";
451
+ AuthType
452
+ } from "./chunk-36HSVBBU.js";
453
+ import "./chunk-46UV252V.js";
454
+ import "./chunk-A4UCTEB5.js";
455
+ import "./chunk-XWRJCPHC.js";
432
456
  import {
433
457
  DEFAULT_TOKEN_LIMIT,
434
- getToolCallPreparations,
435
458
  tokenLimit
436
- } from "./chunk-MAQQGNQ5.js";
437
- import "./chunk-A4UCTEB5.js";
438
- import "./chunk-XWRJCPHC.js";
439
- import "./chunk-TYQMGACW.js";
440
- import "./chunk-TYAMGABM.js";
441
- import "./chunk-FCMNKVXT.js";
459
+ } from "./chunk-UW5EOVUN.js";
460
+ import "./chunk-NBQDBANR.js";
461
+ import "./chunk-QNLNLENL.js";
462
+ import "./chunk-6X4GWOPW.js";
463
+ import {
464
+ endToolExecutionSpan,
465
+ endToolSpan,
466
+ initializeTelemetry,
467
+ runInToolSpanContext,
468
+ startToolExecutionSpan,
469
+ startToolSpan,
470
+ withInteractionSpan
471
+ } from "./chunk-PKL3HGNZ.js";
472
+ import "./chunk-HTR4WV6U.js";
473
+ import "./chunk-BULDBTYC.js";
474
+ import "./chunk-U7ZFW55U.js";
475
+ import "./chunk-ERLGR7GI.js";
476
+ import {
477
+ ToolConfirmationOutcome,
478
+ ToolNames,
479
+ isShellProgressData
480
+ } from "./chunk-P5RRUHL7.js";
442
481
  import {
443
482
  Storage,
444
483
  createDebugLogger,
445
484
  getErrorMessage,
446
485
  getErrorStatus,
447
486
  isSubpath
448
- } from "./chunk-C27BYUX6.js";
449
- import "./chunk-VZQUV7VK.js";
487
+ } from "./chunk-OQB4EXO4.js";
488
+ import "./chunk-CKTMY3EP.js";
450
489
  import {
451
490
  runExitCleanup
452
- } from "./chunk-DP5GXXNZ.js";
491
+ } from "./chunk-EL2IQ2S5.js";
453
492
  import "./chunk-75DOP5OR.js";
454
493
  import "./chunk-DMTGGOSA.js";
455
494
  import "./chunk-YQ3U5MUC.js";
456
- import "./chunk-TB6UDU4T.js";
495
+ import "./chunk-AMDSOFFV.js";
496
+ import "./chunk-THJNPLI4.js";
457
497
  import {
458
498
  init_esbuild_shims
459
499
  } from "./chunk-5O2XNYP6.js";
@@ -463,7 +503,7 @@ import {
463
503
 
464
504
  // packages/cli/src/acp-integration/acpAgent.ts
465
505
  init_esbuild_shims();
466
- import { randomUUID } from "node:crypto";
506
+ import { randomUUID as randomUUID2, timingSafeEqual } from "node:crypto";
467
507
  import { performance } from "node:perf_hooks";
468
508
 
469
509
  // packages/cli/src/acp-integration/authMethods.ts
@@ -841,6 +881,7 @@ __name(isInactiveExtensionSkill, "isInactiveExtensionSkill");
841
881
  // packages/cli/src/acp-integration/session/Session.ts
842
882
  init_esbuild_shims();
843
883
  import { Buffer as Buffer2 } from "node:buffer";
884
+ import { randomUUID } from "node:crypto";
844
885
  import { existsSync as existsSync2, statSync as statSync2 } from "node:fs";
845
886
  import * as os2 from "node:os";
846
887
  import * as path3 from "node:path";
@@ -965,8 +1006,23 @@ function supportsHideAlwaysAllow(confirmation) {
965
1006
  }
966
1007
  __name(supportsHideAlwaysAllow, "supportsHideAlwaysAllow");
967
1008
  function filterAlwaysAllowOptions(confirmation, options, forceHideAlwaysAllow = false) {
968
- const hideAlwaysAllow = forceHideAlwaysAllow || supportsHideAlwaysAllow(confirmation) && confirmation.hideAlwaysAllow === true;
969
- return hideAlwaysAllow ? options.filter((option) => option.kind !== "allow_always") : options;
1009
+ const hideAlwaysAllow = forceHideAlwaysAllow || confirmation.autoModeFallback !== void 0 || supportsHideAlwaysAllow(confirmation) && confirmation.hideAlwaysAllow === true;
1010
+ const visibleOptions = hideAlwaysAllow ? options.filter((option) => option.kind !== "allow_always") : options;
1011
+ if (!confirmation.autoModeFallback) return visibleOptions;
1012
+ const switchOption = {
1013
+ optionId: "proceed_once_and_switch_to_default" /* ProceedOnceAndSwitchToDefault */,
1014
+ name: "Switch to Default Mode and allow once (recommended)",
1015
+ kind: "allow_once"
1016
+ };
1017
+ const rejectIndex = visibleOptions.findIndex(
1018
+ (option) => option.kind === "reject_once"
1019
+ );
1020
+ if (rejectIndex === -1) return [...visibleOptions, switchOption];
1021
+ return [
1022
+ ...visibleOptions.slice(0, rejectIndex),
1023
+ switchOption,
1024
+ ...visibleOptions.slice(rejectIndex)
1025
+ ];
970
1026
  }
971
1027
  __name(filterAlwaysAllowOptions, "filterAlwaysAllowOptions");
972
1028
  function formatExecPermissionScopeLabel(confirmation) {
@@ -994,6 +1050,22 @@ function interactionMetaFields(confirmation) {
994
1050
  __name(interactionMetaFields, "interactionMetaFields");
995
1051
  function buildPermissionRequestContent(confirmation) {
996
1052
  const content = [];
1053
+ if (confirmation.autoModeFallback) {
1054
+ content.push({
1055
+ type: "content",
1056
+ content: {
1057
+ type: "text",
1058
+ text: confirmation.autoModeFallback.message
1059
+ }
1060
+ });
1061
+ }
1062
+ const warnings = confirmation.type === "exec" || confirmation.type === "edit" ? confirmation.warnings ?? [] : [];
1063
+ for (const warning of warnings) {
1064
+ content.push({
1065
+ type: "content",
1066
+ content: { type: "text", text: warning }
1067
+ });
1068
+ }
997
1069
  if (confirmation.type === "edit") {
998
1070
  content.push({
999
1071
  type: "diff",
@@ -1014,6 +1086,56 @@ function buildPermissionRequestContent(confirmation) {
1014
1086
  return content;
1015
1087
  }
1016
1088
  __name(buildPermissionRequestContent, "buildPermissionRequestContent");
1089
+ function permissionAbortError(signal) {
1090
+ return signal.reason instanceof Error ? signal.reason : new Error("Permission request was aborted.");
1091
+ }
1092
+ __name(permissionAbortError, "permissionAbortError");
1093
+ function requestPermissionWithAbort(client, params, signal) {
1094
+ if (signal.aborted) {
1095
+ return Promise.reject(permissionAbortError(signal));
1096
+ }
1097
+ return new Promise((resolve5, reject) => {
1098
+ let settled = false;
1099
+ const finish = /* @__PURE__ */ __name((callback) => {
1100
+ if (settled) return;
1101
+ settled = true;
1102
+ signal.removeEventListener("abort", onAbort);
1103
+ callback();
1104
+ }, "finish");
1105
+ const onAbort = /* @__PURE__ */ __name(() => finish(() => reject(permissionAbortError(signal))), "onAbort");
1106
+ signal.addEventListener("abort", onAbort, { once: true });
1107
+ let request;
1108
+ try {
1109
+ request = client.requestPermission(params);
1110
+ } catch (error) {
1111
+ finish(() => reject(error));
1112
+ return;
1113
+ }
1114
+ request.then(
1115
+ (response) => finish(() => resolve5(response)),
1116
+ (error) => finish(() => reject(error))
1117
+ );
1118
+ });
1119
+ }
1120
+ __name(requestPermissionWithAbort, "requestPermissionWithAbort");
1121
+ function resolvePermissionOutcome(response, offeredOptions) {
1122
+ if (response.outcome.outcome === "cancelled") {
1123
+ return "cancel" /* Cancel */;
1124
+ }
1125
+ const optionId = response.outcome.optionId;
1126
+ if (!offeredOptions.some((option) => option.optionId === optionId)) {
1127
+ throw new Error(
1128
+ `Permission response selected unoffered option: ${optionId}`
1129
+ );
1130
+ }
1131
+ if (!Object.values(ToolConfirmationOutcome).includes(
1132
+ optionId
1133
+ )) {
1134
+ throw new Error(`Permission response selected invalid option: ${optionId}`);
1135
+ }
1136
+ return optionId;
1137
+ }
1138
+ __name(resolvePermissionOutcome, "resolvePermissionOutcome");
1017
1139
  function toPermissionOptions(confirmation, forceHideAlwaysAllow = false) {
1018
1140
  switch (confirmation.type) {
1019
1141
  case "edit":
@@ -1240,9 +1362,13 @@ var SubAgentTracker = class {
1240
1362
  }, "onConfirm")
1241
1363
  };
1242
1364
  const { title, locations, kind } = this.toolCallEmitter.resolveToolMetadata(event.name, state?.args);
1365
+ const permissionOptions = toPermissionOptions(fullConfirmationDetails);
1366
+ const offeredPermissionOptions = permissionOptions.map((option) => ({
1367
+ ...option
1368
+ }));
1243
1369
  const params = {
1244
1370
  sessionId: this.ctx.sessionId,
1245
- options: toPermissionOptions(fullConfirmationDetails),
1371
+ options: permissionOptions,
1246
1372
  toolCall: {
1247
1373
  toolCallId: event.callId,
1248
1374
  status: "pending",
@@ -1263,8 +1389,15 @@ var SubAgentTracker = class {
1263
1389
  }
1264
1390
  };
1265
1391
  try {
1266
- const output = await this.client.requestPermission(params);
1267
- const outcome = output.outcome.outcome === "cancelled" ? "cancel" /* Cancel */ : external_exports.nativeEnum(ToolConfirmationOutcome).parse(output.outcome.optionId);
1392
+ const output = await requestPermissionWithAbort(
1393
+ this.client,
1394
+ params,
1395
+ abortSignal
1396
+ );
1397
+ const outcome = resolvePermissionOutcome(
1398
+ output,
1399
+ offeredPermissionOptions
1400
+ );
1268
1401
  await event.respond(outcome, {
1269
1402
  answers: "answers" in output ? output.answers : void 0
1270
1403
  });
@@ -1856,6 +1989,10 @@ function maskApiKeyForDisplay(apiKey) {
1856
1989
  return `${trimmed.slice(0, 3)}...${trimmed.slice(-4)}`;
1857
1990
  }
1858
1991
  __name(maskApiKeyForDisplay, "maskApiKeyForDisplay");
1992
+ function getAbortAwareEndTurnStopReason(signal) {
1993
+ return signal.aborted ? "cancelled" : "end_turn";
1994
+ }
1995
+ __name(getAbortAwareEndTurnStopReason, "getAbortAwareEndTurnStopReason");
1859
1996
  var DAEMON_INVALID_TOOL_PARAMS_THRESHOLD = 3;
1860
1997
  var PERMISSION_CANCEL_SKIP_MESSAGE = "Skipped because a permission request was cancelled before the user answered; user input is required before continuing.";
1861
1998
  var LOOP_DETECTED_SKIP_MESSAGE = "Skipped because loop detection stopped the current turn before this tool call could run.";
@@ -2091,6 +2228,43 @@ var MidTurnDrainTimeoutError = class extends Error {
2091
2228
  );
2092
2229
  }
2093
2230
  };
2231
+ function beginChannelDeliveryResponseBlock(capture) {
2232
+ if (!capture) return void 0;
2233
+ capture.finalText = "";
2234
+ return [];
2235
+ }
2236
+ __name(beginChannelDeliveryResponseBlock, "beginChannelDeliveryResponseBlock");
2237
+ function commitChannelDeliveryResponseBlock(capture, responseBlock, hasFunctionCalls) {
2238
+ if (capture && responseBlock && !hasFunctionCalls) {
2239
+ capture.finalText = responseBlock.join("");
2240
+ }
2241
+ }
2242
+ __name(commitChannelDeliveryResponseBlock, "commitChannelDeliveryResponseBlock");
2243
+ function parsePromptChannelDelivery(params) {
2244
+ const meta = params._meta;
2245
+ const value = meta?.[DAEMON_CHANNEL_DELIVERY_META_KEY];
2246
+ if (typeof value !== "object" || value === null || Array.isArray(value)) {
2247
+ return void 0;
2248
+ }
2249
+ const delivery = value;
2250
+ const target = delivery["target"];
2251
+ if (typeof delivery["deliveryId"] !== "string" || delivery["deliveryId"].length === 0 || typeof target !== "object" || target === null || Array.isArray(target)) {
2252
+ return void 0;
2253
+ }
2254
+ const targetRecord = target;
2255
+ if (typeof targetRecord["channelName"] !== "string" || targetRecord["channelName"].length === 0 || targetRecord["type"] !== "user" && targetRecord["type"] !== "chat" || typeof targetRecord["id"] !== "string" || targetRecord["id"].length === 0) {
2256
+ return void 0;
2257
+ }
2258
+ return {
2259
+ deliveryId: delivery["deliveryId"],
2260
+ target: {
2261
+ channelName: targetRecord["channelName"],
2262
+ type: targetRecord["type"],
2263
+ id: targetRecord["id"]
2264
+ }
2265
+ };
2266
+ }
2267
+ __name(parsePromptChannelDelivery, "parsePromptChannelDelivery");
2094
2268
  var MAX_NOTIFICATION_QUEUE = 20;
2095
2269
  var MAX_DEFERRED_UNRELATED_CRON_QUEUE = 20;
2096
2270
  function isExistingFile(resolved, fileExists = existsSync2, statFile = statSync2) {
@@ -2307,7 +2481,7 @@ var Session = class {
2307
2481
  this.client = client;
2308
2482
  this.settings = settings;
2309
2483
  this.sessionId = id;
2310
- this.runtimeBaseDir = Storage.getRuntimeBaseDir();
2484
+ this.runtimeBaseDir = config.storage.getRuntimeBaseDir();
2311
2485
  const todoStopGuardEnabled = this.settings.merged.experimental?.todoStopGuard === true && !this.config.getBareMode() && !this.config.isSafeMode();
2312
2486
  this.todoStopGuard = new DaemonTodoStopGuard(todoStopGuardEnabled);
2313
2487
  this.todoStopGuardBackgroundBaseline = todoStopGuardEnabled ? this.#captureTodoStopGuardBackgroundBaseline() : {
@@ -2338,6 +2512,7 @@ var Session = class {
2338
2512
  * process termination is slow.
2339
2513
  */
2340
2514
  pendingPromptCompletion = null;
2515
+ automaticDrainRetry = null;
2341
2516
  /**
2342
2517
  * Per-turn AbortController for the fire-and-forget follow-up suggestion
2343
2518
  * generation. Aborted on the top of the next `prompt()` and on
@@ -2400,6 +2575,9 @@ var Session = class {
2400
2575
  // or session reload), which would otherwise execute orphaned cron prompts
2401
2576
  // on a session whose registries are already unregistered.
2402
2577
  disposed = false;
2578
+ closing = false;
2579
+ closeGateCompletion = null;
2580
+ resolveCloseGate = null;
2403
2581
  unsubscribeChatRecordingFailure;
2404
2582
  // Modular components
2405
2583
  historyReplayer;
@@ -2422,6 +2600,8 @@ var Session = class {
2422
2600
  * that produces this string.
2423
2601
  */
2424
2602
  pendingWorktreeNotice = null;
2603
+ /** One-shot model notice for background agents restored with the session. */
2604
+ pendingRecoveredAgentsNotice = null;
2425
2605
  // Implement SessionContext interface
2426
2606
  sessionId;
2427
2607
  #prepareTodoStopGuardForPrompt(params) {
@@ -2634,7 +2814,7 @@ var Session = class {
2634
2814
  * mount.
2635
2815
  */
2636
2816
  startCronScheduler() {
2637
- this.#startCronSchedulerIfNeeded().catch((error) => {
2817
+ this.#startCronSchedulerInRuntime().catch((error) => {
2638
2818
  debugLogger6.warn(
2639
2819
  `Cron scheduler startup failed [session ${this.sessionId}]: ${error}`
2640
2820
  );
@@ -2643,8 +2823,95 @@ var Session = class {
2643
2823
  getConfig() {
2644
2824
  return this.config;
2645
2825
  }
2826
+ async assertCanStartTurn() {
2827
+ if (this.closing) {
2828
+ throw RequestError.invalidParams(void 0, "Session is closing");
2829
+ }
2830
+ try {
2831
+ await this.config.assertCanStartTurn();
2832
+ } catch (error) {
2833
+ if (error instanceof SessionWriterError) {
2834
+ throw new RequestError(error.rpcCode, error.message, {
2835
+ errorKind: error.errorKind
2836
+ });
2837
+ }
2838
+ throw error;
2839
+ }
2840
+ if (this.closing) {
2841
+ throw RequestError.invalidParams(void 0, "Session is closing");
2842
+ }
2843
+ }
2646
2844
  isIdle() {
2647
- return !this.pendingPrompt && !this.pendingPromptCompletion && !this.cronProcessing && !this.cronAbortController && !this.notificationProcessing && !this.notificationAbortController;
2845
+ return !this.closing && !this.#hasActiveTurn();
2846
+ }
2847
+ #hasActiveTurn() {
2848
+ return Boolean(
2849
+ this.pendingPrompt || this.pendingPromptCompletion || this.cronProcessing || this.cronAbortController || this.cronCompletion || this.notificationProcessing || this.notificationAbortController || this.notificationCompletion
2850
+ );
2851
+ }
2852
+ beginClose() {
2853
+ if (this.closing) {
2854
+ throw RequestError.invalidParams(
2855
+ void 0,
2856
+ "Session close is already in progress"
2857
+ );
2858
+ }
2859
+ this.closing = true;
2860
+ let resolveGate;
2861
+ const completion = new Promise((resolve5) => {
2862
+ resolveGate = resolve5;
2863
+ });
2864
+ this.closeGateCompletion = completion;
2865
+ this.resolveCloseGate = resolveGate;
2866
+ let released = false;
2867
+ return () => {
2868
+ if (released) return;
2869
+ released = true;
2870
+ if (this.closeGateCompletion === completion) {
2871
+ this.closeGateCompletion = null;
2872
+ this.resolveCloseGate = null;
2873
+ }
2874
+ resolveGate();
2875
+ if (this.disposed) return;
2876
+ this.closing = false;
2877
+ void this.#drainCronQueue();
2878
+ void this.#drainNotificationQueue();
2879
+ };
2880
+ }
2881
+ beginCloseIfAvailable() {
2882
+ if (this.disposed) {
2883
+ throw RequestError.invalidParams(void 0, "Session has been disposed");
2884
+ }
2885
+ return this.closing ? null : this.beginClose();
2886
+ }
2887
+ waitForCloseGateToRelease() {
2888
+ return this.closeGateCompletion ?? Promise.resolve();
2889
+ }
2890
+ async waitForActiveTurnsToSettle() {
2891
+ const pending = [
2892
+ this.pendingPromptCompletion,
2893
+ this.cronCompletion,
2894
+ this.notificationCompletion
2895
+ ].filter((completion) => completion !== null);
2896
+ await Promise.allSettled(pending);
2897
+ }
2898
+ #deferAutomaticQueueDrainUntilTurnsSettle() {
2899
+ const completions = [
2900
+ this.pendingPromptCompletion,
2901
+ this.cronCompletion,
2902
+ this.notificationCompletion
2903
+ ].filter((completion) => completion !== null);
2904
+ if (completions.length === 0) return false;
2905
+ if (this.automaticDrainRetry) return true;
2906
+ const retry = Promise.allSettled(completions).then(() => {
2907
+ if (this.automaticDrainRetry !== retry) return;
2908
+ this.automaticDrainRetry = null;
2909
+ if (this.disposed) return;
2910
+ void this.#drainCronQueue();
2911
+ void this.#drainNotificationQueue();
2912
+ });
2913
+ this.automaticDrainRetry = retry;
2914
+ return true;
2648
2915
  }
2649
2916
  getTurnCount() {
2650
2917
  return this.turn;
@@ -2654,6 +2921,10 @@ var Session = class {
2654
2921
  }
2655
2922
  dispose() {
2656
2923
  this.disposed = true;
2924
+ this.closing = true;
2925
+ this.resolveCloseGate?.();
2926
+ this.resolveCloseGate = null;
2927
+ this.closeGateCompletion = null;
2657
2928
  this.todoStopGuardQueuedPromptPriority = false;
2658
2929
  this.todoStopGuardDrainAutomaticQueuesWhenIdle = false;
2659
2930
  this.todoStopGuard.clearTrust();
@@ -2670,8 +2941,9 @@ var Session = class {
2670
2941
  this.cronProcessing = false;
2671
2942
  this.cronCompletion = null;
2672
2943
  if (this.config.isCronEnabled()) {
2673
- this.config.getCronScheduler().stop();
2944
+ this.#stopCronSchedulerInRuntime();
2674
2945
  }
2946
+ this.config.getBackgroundTaskRegistry().abortAll({ notify: false });
2675
2947
  this.config.getBackgroundTaskRegistry().setNotificationCallback(void 0);
2676
2948
  this.config.getMonitorRegistry().setNotificationCallback(void 0);
2677
2949
  this.config.getBackgroundShellRegistry().setNotificationCallback(void 0);
@@ -2754,7 +3026,7 @@ var Session = class {
2754
3026
  "targetTurnIndex must be a non-negative integer"
2755
3027
  );
2756
3028
  }
2757
- if (this.pendingPrompt || this.cronProcessing || this.cronAbortController || this.notificationProcessing || this.notificationAbortController) {
3029
+ if (this.closing || this.#hasActiveTurn()) {
2758
3030
  throw RequestError.invalidParams(
2759
3031
  void 0,
2760
3032
  "Cannot rewind while a prompt is running"
@@ -2811,7 +3083,7 @@ var Session = class {
2811
3083
  return count;
2812
3084
  }
2813
3085
  restoreHistory(history) {
2814
- if (this.pendingPrompt || this.cronProcessing || this.cronAbortController || this.notificationProcessing || this.notificationAbortController) {
3086
+ if (this.closing || this.#hasActiveTurn()) {
2815
3087
  throw RequestError.invalidParams(
2816
3088
  void 0,
2817
3089
  "Cannot restore history while a prompt is running"
@@ -2885,17 +3157,37 @@ var Session = class {
2885
3157
  const scheduler = this.config.isCronEnabled() ? this.config.getCronScheduler() : null;
2886
3158
  if (scheduler) {
2887
3159
  const summary = scheduler.getExitSummary();
2888
- scheduler.stop();
3160
+ this.#stopCronSchedulerInRuntime();
2889
3161
  if (summary) {
2890
3162
  await this.messageEmitter.emitAgentMessage(summary);
2891
3163
  }
2892
3164
  }
2893
3165
  }
2894
- async prompt(params) {
3166
+ async prompt(params, invocationContext, admissionCancellation) {
3167
+ if (this.closing) {
3168
+ throw RequestError.invalidParams(void 0, "Session is closing");
3169
+ }
3170
+ await this.assertCanStartTurn();
3171
+ if (admissionCancellation?.aborted) {
3172
+ return { stopReason: "cancelled" };
3173
+ }
2895
3174
  const todoStopGuardPreparation = this.#prepareTodoStopGuardForPrompt(params);
2896
3175
  this.pendingPrompt?.abort();
2897
3176
  const pendingSend = new AbortController();
3177
+ const cancelPendingSend = /* @__PURE__ */ __name(() => pendingSend.abort(USER_CANCEL_ABORT_REASON), "cancelPendingSend");
3178
+ if (admissionCancellation) {
3179
+ admissionCancellation.addEventListener("abort", cancelPendingSend, {
3180
+ once: true
3181
+ });
3182
+ if (admissionCancellation.aborted) cancelPendingSend();
3183
+ }
2898
3184
  this.pendingPrompt = pendingSend;
3185
+ const releasePendingSend = /* @__PURE__ */ __name(() => {
3186
+ admissionCancellation?.removeEventListener("abort", cancelPendingSend);
3187
+ if (this.pendingPrompt === pendingSend) {
3188
+ this.pendingPrompt = null;
3189
+ }
3190
+ }, "releasePendingSend");
2899
3191
  if (this.followupAbort) {
2900
3192
  this.followupAbort.abort();
2901
3193
  this.followupAbort = null;
@@ -2932,6 +3224,8 @@ var Session = class {
2932
3224
  }
2933
3225
  }
2934
3226
  if (pendingSend.signal.aborted) {
3227
+ releasePendingSend();
3228
+ this.todoStopGuard.suspend();
2935
3229
  return { stopReason: "cancelled" };
2936
3230
  }
2937
3231
  if (todoStopGuardPreparation.startsWorkChain) {
@@ -2940,26 +3234,52 @@ var Session = class {
2940
3234
  this.todoStopGuardBackgroundBaseline = this.#captureTodoStopGuardBackgroundBaseline();
2941
3235
  }
2942
3236
  this.duplicateProviderToolCallResponseIds.clear();
3237
+ const channelDelivery = parsePromptChannelDelivery(params);
3238
+ const channelDeliveryCapture = channelDelivery ? { finalText: "" } : void 0;
2943
3239
  let resolveCompletion;
2944
3240
  this.pendingPromptCompletion = new Promise((resolve5) => {
2945
3241
  resolveCompletion = resolve5;
2946
3242
  });
2947
3243
  try {
2948
- const result = await this.#executePrompt(params, pendingSend);
2949
- this.pendingPrompt = null;
3244
+ const result = await this.#executePrompt(
3245
+ params,
3246
+ pendingSend,
3247
+ channelDeliveryCapture,
3248
+ invocationContext
3249
+ );
3250
+ releasePendingSend();
2950
3251
  void this.#drainCronQueue();
2951
3252
  void this.#drainNotificationQueue();
2952
3253
  this.#maybeEmitFollowupSuggestion(result);
3254
+ if (channelDelivery && result.stopReason === "end_turn") {
3255
+ this.#scheduleChannelDelivery({
3256
+ sessionId: this.sessionId,
3257
+ deliveryId: channelDelivery.deliveryId,
3258
+ source: "prompt",
3259
+ target: channelDelivery.target,
3260
+ text: normalizeChannelDeliveryText(
3261
+ channelDeliveryCapture?.finalText ?? ""
3262
+ ),
3263
+ promptId: channelDelivery.deliveryId
3264
+ });
3265
+ }
2953
3266
  return result;
3267
+ } catch (error) {
3268
+ if (error instanceof SessionWriterError) {
3269
+ throw new RequestError(error.rpcCode, error.message, {
3270
+ errorKind: error.errorKind
3271
+ });
3272
+ }
3273
+ throw error;
2954
3274
  } finally {
2955
- this.pendingPrompt = null;
3275
+ releasePendingSend();
2956
3276
  const shouldDrainAutomaticQueues = todoStopGuardPreparation.drainSupersededAutomaticQueues || this.todoStopGuardDrainAutomaticQueuesWhenIdle || this.todoStopGuard.blocksUnrelatedAutomaticTurns || this.todoStopGuard.hasCommittedContinuation || this.todoStopGuardQueuedPromptPriority;
2957
3277
  this.todoStopGuardDrainAutomaticQueuesWhenIdle = false;
2958
3278
  if (shouldDrainAutomaticQueues) {
2959
3279
  void this.#drainCronQueue();
2960
3280
  void this.#drainNotificationQueue();
2961
3281
  }
2962
- void this.#startCronSchedulerIfNeeded();
3282
+ void this.#startCronSchedulerInRuntime();
2963
3283
  resolveCompletion();
2964
3284
  this.pendingPromptCompletion = null;
2965
3285
  }
@@ -3082,17 +3402,31 @@ var Session = class {
3082
3402
  }
3083
3403
  })();
3084
3404
  }
3085
- async #executePrompt(params, pendingSend) {
3086
- return sessionIdContext.run(
3087
- this.config.getSessionId(),
3088
- () => this.#executePromptInner(params, pendingSend)
3405
+ async #executePrompt(params, pendingSend, channelDeliveryCapture, invocationContext) {
3406
+ const sessionId = this.config.getSessionId();
3407
+ if (invocationContext !== void 0 && invocationContext.sessionId !== sessionId) {
3408
+ throw RequestError.invalidParams(
3409
+ void 0,
3410
+ "Invocation context session does not match the active session"
3411
+ );
3412
+ }
3413
+ return runWithInvocationContext(
3414
+ invocationContext,
3415
+ () => sessionIdContext.run(
3416
+ sessionId,
3417
+ () => this.#executePromptInner(params, pendingSend, channelDeliveryCapture)
3418
+ )
3089
3419
  );
3090
3420
  }
3091
- async #executePromptInner(params, pendingSend) {
3421
+ async #executePromptInner(params, pendingSend, channelDeliveryCapture) {
3092
3422
  return Storage.runWithRuntimeBaseDir(
3093
3423
  this.runtimeBaseDir,
3094
3424
  this.config.getWorkingDir(),
3095
3425
  async () => {
3426
+ await this.assertCanStartTurn();
3427
+ if (pendingSend.signal.aborted) {
3428
+ return { stopReason: "cancelled" };
3429
+ }
3096
3430
  this.turn += 1;
3097
3431
  const promptId = this.config.getSessionId() + "########" + this.turn;
3098
3432
  const parentContext = extractDaemonTraceContext(params);
@@ -3156,6 +3490,7 @@ var Session = class {
3156
3490
  (block) => block.type === "text"
3157
3491
  );
3158
3492
  const inputText = firstTextBlock?.text || "";
3493
+ const isSlashInput = !isContinue && isSlashCommand(inputText);
3159
3494
  let parts;
3160
3495
  let fullTurnModelOverride;
3161
3496
  const onFullTurnModel = /* @__PURE__ */ __name((model) => {
@@ -3167,7 +3502,7 @@ var Session = class {
3167
3502
  }, "onFullTurnModel");
3168
3503
  if (isContinue) {
3169
3504
  parts = continuationParts;
3170
- } else if (isSlashCommand(inputText)) {
3505
+ } else if (isSlashInput) {
3171
3506
  const slashCommandResult = await handleSlashCommand(
3172
3507
  inputText,
3173
3508
  pendingSend,
@@ -3251,6 +3586,17 @@ ${this.pendingWorktreeNotice}
3251
3586
  parts = insertAfterFunctionResponses(parts, [noticePart]);
3252
3587
  this.pendingWorktreeNotice = null;
3253
3588
  }
3589
+ if (this.pendingRecoveredAgentsNotice && !isContinue && !isSlashInput) {
3590
+ const noticePart = {
3591
+ text: `<system-reminder>
3592
+ ${this.pendingRecoveredAgentsNotice}
3593
+ </system-reminder>
3594
+
3595
+ `
3596
+ };
3597
+ parts = insertAfterFunctionResponses(parts, [noticePart]);
3598
+ this.pendingRecoveredAgentsNotice = null;
3599
+ }
3254
3600
  let nextMessage = { role: "user", parts };
3255
3601
  let turnCount = 0;
3256
3602
  const toolLoopState = createDaemonToolLoopState();
@@ -3271,6 +3617,7 @@ ${this.pendingWorktreeNotice}
3271
3617
  const messageDisplay = this.#createMessageDisplayDispatcher(
3272
3618
  pendingSend.signal
3273
3619
  );
3620
+ let channelDeliveryResponseBlock;
3274
3621
  try {
3275
3622
  const sendResult = await this.#sendMessageStreamWithAutoCompression(
3276
3623
  promptId,
@@ -3288,6 +3635,8 @@ ${this.pendingWorktreeNotice}
3288
3635
  }
3289
3636
  const responseStream = sendResult.responseStream;
3290
3637
  nextMessage = null;
3638
+ channelDeliveryResponseBlock = beginChannelDeliveryResponseBlock(channelDeliveryCapture);
3639
+ const channelDeliveryCheckpoint = channelDeliveryResponseBlock?.length ?? 0;
3291
3640
  let streamFailed = false;
3292
3641
  try {
3293
3642
  for await (const resp of responseStream) {
@@ -3307,6 +3656,7 @@ ${this.pendingWorktreeNotice}
3307
3656
  part.thought
3308
3657
  );
3309
3658
  if (!part.thought) {
3659
+ channelDeliveryResponseBlock?.push(part.text);
3310
3660
  messageDisplay?.addChunk(part.text);
3311
3661
  }
3312
3662
  }
@@ -3322,6 +3672,11 @@ ${this.pendingWorktreeNotice}
3322
3672
  }
3323
3673
  }
3324
3674
  if (resp.type === "retry" /* RETRY */ || resp.type === "model_fallback" /* MODEL_FALLBACK */) {
3675
+ if (resp.type === "model_fallback" /* MODEL_FALLBACK */ || !resp.isContinuation) {
3676
+ if (channelDeliveryResponseBlock) {
3677
+ channelDeliveryResponseBlock.length = channelDeliveryCheckpoint;
3678
+ }
3679
+ }
3325
3680
  await finalizeToolCallPreparations(
3326
3681
  preparationTracker,
3327
3682
  true,
@@ -3375,6 +3730,11 @@ ${this.pendingWorktreeNotice}
3375
3730
  } finally {
3376
3731
  await messageDisplay?.finish();
3377
3732
  }
3733
+ commitChannelDeliveryResponseBlock(
3734
+ channelDeliveryCapture,
3735
+ channelDeliveryResponseBlock,
3736
+ functionCalls.length > 0
3737
+ );
3378
3738
  if (usageMetadata) {
3379
3739
  this.#recordPromptTokenCount(usageMetadata);
3380
3740
  if (this.messageRewriter) {
@@ -3403,7 +3763,11 @@ ${this.pendingWorktreeNotice}
3403
3763
  toolRun,
3404
3764
  pendingSend.signal
3405
3765
  );
3406
- return { stopReason: "end_turn" };
3766
+ return {
3767
+ stopReason: getAbortAwareEndTurnStopReason(
3768
+ pendingSend.signal
3769
+ )
3770
+ };
3407
3771
  }
3408
3772
  const nextAfterTools = await this.#buildNextMessageAfterToolRun(
3409
3773
  toolRun,
@@ -3417,7 +3781,11 @@ ${this.pendingWorktreeNotice}
3417
3781
  toolRun,
3418
3782
  pendingSend.signal
3419
3783
  );
3420
- return { stopReason: "end_turn" };
3784
+ return {
3785
+ stopReason: getAbortAwareEndTurnStopReason(
3786
+ pendingSend.signal
3787
+ )
3788
+ };
3421
3789
  }
3422
3790
  }
3423
3791
  }
@@ -3430,7 +3798,8 @@ ${this.pendingWorktreeNotice}
3430
3798
  hooksEnabled,
3431
3799
  messageBus,
3432
3800
  true,
3433
- fullTurnModelOverride
3801
+ fullTurnModelOverride,
3802
+ channelDeliveryCapture
3434
3803
  );
3435
3804
  } finally {
3436
3805
  logConversationFinishedEvent(
@@ -3447,7 +3816,7 @@ ${this.pendingWorktreeNotice}
3447
3816
  }
3448
3817
  );
3449
3818
  }
3450
- async #handleStopHookLoop(pendingSend, promptId, hooksEnabled, messageBus, allowExternalHooks = true, modelOverride) {
3819
+ async #handleStopHookLoop(pendingSend, promptId, hooksEnabled, messageBus, allowExternalHooks = true, modelOverride, channelDeliveryCapture) {
3451
3820
  const stopHookBlockingCap = this.config.getStopHookBlockingCap();
3452
3821
  let stopHookIterationCount = 0;
3453
3822
  let stopHookReasons = [];
@@ -3462,7 +3831,7 @@ ${this.pendingWorktreeNotice}
3462
3831
  while (true) {
3463
3832
  if (pendingSend.signal.aborted) {
3464
3833
  this.todoStopGuard.suspend();
3465
- return { stopReason: "end_turn" };
3834
+ return { stopReason: "cancelled" };
3466
3835
  }
3467
3836
  if (this.config.getApprovalMode() === "plan" /* PLAN */) {
3468
3837
  this.#clearTodoStopGuardTrustAndDrainAutomaticQueues();
@@ -3489,7 +3858,8 @@ ${this.pendingWorktreeNotice}
3489
3858
  false,
3490
3859
  {
3491
3860
  onFullTurnModel,
3492
- getModelOverride: /* @__PURE__ */ __name(() => modelOverride, "getModelOverride")
3861
+ getModelOverride: /* @__PURE__ */ __name(() => modelOverride, "getModelOverride"),
3862
+ channelDeliveryCapture
3493
3863
  }
3494
3864
  );
3495
3865
  if (continuation2.kind === "terminal") {
@@ -3551,7 +3921,8 @@ ${this.pendingWorktreeNotice}
3551
3921
  false,
3552
3922
  {
3553
3923
  onFullTurnModel,
3554
- getModelOverride: /* @__PURE__ */ __name(() => modelOverride, "getModelOverride")
3924
+ getModelOverride: /* @__PURE__ */ __name(() => modelOverride, "getModelOverride"),
3925
+ channelDeliveryCapture
3555
3926
  }
3556
3927
  );
3557
3928
  if (continuation2.kind === "terminal") {
@@ -3565,7 +3936,7 @@ ${this.pendingWorktreeNotice}
3565
3936
  await this.messageEmitter.emitAgentMessage(stopOutput.systemMessage);
3566
3937
  }
3567
3938
  if (stopOutput?.isBlockingDecision() || stopOutput?.shouldStopExecution()) {
3568
- externalReason = stopOutput.getEffectiveReason();
3939
+ externalReason = getStopHookContinuationReason(stopOutput);
3569
3940
  stopHookIterationCount++;
3570
3941
  stopHookReasons = [...stopHookReasons, externalReason];
3571
3942
  stopHookCount = response.stopHookCount ?? 1;
@@ -3632,7 +4003,8 @@ ${this.pendingWorktreeNotice}
3632
4003
  ), "onAutomaticContinuationValidated")
3633
4004
  } : {},
3634
4005
  onFullTurnModel,
3635
- getModelOverride: /* @__PURE__ */ __name(() => modelOverride, "getModelOverride")
4006
+ getModelOverride: /* @__PURE__ */ __name(() => modelOverride, "getModelOverride"),
4007
+ channelDeliveryCapture
3636
4008
  }
3637
4009
  );
3638
4010
  if (continuation.supersededAutomaticContinuation && externalReason) {
@@ -3675,6 +4047,7 @@ ${this.pendingWorktreeNotice}
3675
4047
  const messageDisplay = this.#createMessageDisplayDispatcher(
3676
4048
  pendingSend.signal
3677
4049
  );
4050
+ let channelDeliveryResponseBlock;
3678
4051
  try {
3679
4052
  const sendResult = await this.#sendMessageStreamWithAutoCompression(
3680
4053
  promptIdForSend,
@@ -3806,6 +4179,10 @@ ${this.pendingWorktreeNotice}
3806
4179
  }
3807
4180
  const responseStream = sendResult.responseStream;
3808
4181
  nextMessage = null;
4182
+ channelDeliveryResponseBlock = beginChannelDeliveryResponseBlock(
4183
+ options.channelDeliveryCapture
4184
+ );
4185
+ const channelDeliveryCheckpoint = channelDeliveryResponseBlock?.length ?? 0;
3809
4186
  initialSend = false;
3810
4187
  if (guardForThisSend) {
3811
4188
  const guardCommitted = this.todoStopGuard.commitContinuation(
@@ -3836,7 +4213,10 @@ ${this.pendingWorktreeNotice}
3836
4213
  "assistant",
3837
4214
  part.thought
3838
4215
  );
3839
- if (!part.thought) messageDisplay?.addChunk(part.text);
4216
+ if (!part.thought) {
4217
+ channelDeliveryResponseBlock?.push(part.text);
4218
+ messageDisplay?.addChunk(part.text);
4219
+ }
3840
4220
  }
3841
4221
  }
3842
4222
  if (response.type === "chunk" /* CHUNK */ && response.value.usageMetadata) {
@@ -3850,6 +4230,11 @@ ${this.pendingWorktreeNotice}
3850
4230
  }
3851
4231
  }
3852
4232
  if (response.type === "retry" /* RETRY */ || response.type === "model_fallback" /* MODEL_FALLBACK */) {
4233
+ if (response.type === "model_fallback" /* MODEL_FALLBACK */ || !response.isContinuation) {
4234
+ if (channelDeliveryResponseBlock) {
4235
+ channelDeliveryResponseBlock.length = channelDeliveryCheckpoint;
4236
+ }
4237
+ }
3853
4238
  await finalizeToolCallPreparations(
3854
4239
  preparationTracker,
3855
4240
  true,
@@ -3888,6 +4273,11 @@ ${this.pendingWorktreeNotice}
3888
4273
  await messageDisplay?.finish();
3889
4274
  }
3890
4275
  }
4276
+ commitChannelDeliveryResponseBlock(
4277
+ options.channelDeliveryCapture,
4278
+ channelDeliveryResponseBlock,
4279
+ functionCalls.length > 0
4280
+ );
3891
4281
  if (usageMetadata) {
3892
4282
  this.#recordPromptTokenCount(usageMetadata);
3893
4283
  const durationMs = Date.now() - streamStartTime;
@@ -3912,7 +4302,7 @@ ${this.pendingWorktreeNotice}
3912
4302
  await this.#preserveStoppedToolRun(toolRun, pendingSend.signal);
3913
4303
  return {
3914
4304
  kind: "terminal",
3915
- stopReason: "end_turn",
4305
+ stopReason: getAbortAwareEndTurnStopReason(pendingSend.signal),
3916
4306
  ...supersededAutomaticContinuation ? { supersededAutomaticContinuation: true } : {}
3917
4307
  };
3918
4308
  }
@@ -4007,6 +4397,19 @@ ${this.pendingWorktreeNotice}
4007
4397
  };
4008
4398
  await this.client.sessionUpdate(params);
4009
4399
  }
4400
+ #scheduleChannelDelivery(params) {
4401
+ const timer = setTimeout(() => {
4402
+ void this.client.extMethod(SERVE_CONTROL_EXT_METHODS.channelDelivery, params).catch((error) => {
4403
+ try {
4404
+ debugLogger6.warn(
4405
+ `Channel delivery submission failed: ${error instanceof Error ? error.message : String(error)}`
4406
+ );
4407
+ } catch {
4408
+ }
4409
+ });
4410
+ }, 0);
4411
+ timer.unref();
4412
+ }
4010
4413
  #getCurrentChat() {
4011
4414
  return this.config.getGeminiClient().getChat();
4012
4415
  }
@@ -4161,13 +4564,18 @@ ${this.pendingWorktreeNotice}
4161
4564
  }
4162
4565
  }
4163
4566
  async #preserveStoppedToolRun(toolRun, abortSignal) {
4567
+ const midTurnParts = abortSignal.aborted ? await this.#buildMidTurnParts(
4568
+ this.#takeRecoveredMidTurnMessages(),
4569
+ abortSignal,
4570
+ { preserveFallbackOnAbort: true }
4571
+ ) : await this.#drainMidTurnUserMessages(abortSignal);
4164
4572
  this.#preserveUnsentMessageHistory(
4165
4573
  {
4166
4574
  role: "user",
4167
4575
  parts: [
4168
4576
  ...toolRun.parts,
4169
4577
  ...toolRun.loopDetected ? [{ text: LOOP_DETECTED_CONTEXT_MESSAGE }] : [],
4170
- ...await this.#drainMidTurnUserMessages(abortSignal)
4578
+ ...midTurnParts
4171
4579
  ]
4172
4580
  },
4173
4581
  true
@@ -4282,11 +4690,7 @@ ${this.pendingWorktreeNotice}
4282
4690
  const recovered = this.#takeRecoveredMidTurnMessages();
4283
4691
  if (this.midTurnDrainUnavailable) {
4284
4692
  return {
4285
- parts: await this.#buildMidTurnParts(
4286
- recovered,
4287
- abortSignal,
4288
- options.onFullTurnModel
4289
- ),
4693
+ parts: await this.#buildMidTurnParts(recovered, abortSignal, options),
4290
4694
  hasQueuedPrompt: false
4291
4695
  };
4292
4696
  }
@@ -4314,7 +4718,7 @@ ${this.pendingWorktreeNotice}
4314
4718
  parts: await this.#buildMidTurnParts(
4315
4719
  [...recovered, ...parseMidTurnDrainResponse(response)],
4316
4720
  abortSignal,
4317
- options.onFullTurnModel
4721
+ options
4318
4722
  ),
4319
4723
  hasQueuedPrompt: isRecord2(response) && response["hasQueuedPrompt"] === true
4320
4724
  };
@@ -4334,11 +4738,7 @@ ${this.pendingWorktreeNotice}
4334
4738
  `Mid-turn queue drain ${isPermanentError ? "permanently " : ""}unavailable [session ${this.sessionId}]: ${errorMessage}`
4335
4739
  );
4336
4740
  return {
4337
- parts: await this.#buildMidTurnParts(
4338
- recovered,
4339
- abortSignal,
4340
- options.onFullTurnModel
4341
- ),
4741
+ parts: await this.#buildMidTurnParts(recovered, abortSignal, options),
4342
4742
  hasQueuedPrompt: false
4343
4743
  };
4344
4744
  }
@@ -4398,7 +4798,7 @@ ${this.pendingWorktreeNotice}
4398
4798
  * happens on injection (here), so a message recovered from an earlier
4399
4799
  * timed-out drain is still recorded exactly once.
4400
4800
  */
4401
- async #buildMidTurnParts(messages, abortSignal, onFullTurnModel) {
4801
+ async #buildMidTurnParts(messages, abortSignal, options = {}) {
4402
4802
  const parts = [];
4403
4803
  for (const message of messages) {
4404
4804
  const displayText = message.kind === "text" ? message.message : message.displayText;
@@ -4408,13 +4808,19 @@ ${this.pendingWorktreeNotice}
4408
4808
  abortSignal,
4409
4809
  MID_TURN_QUEUE_RESOLVE_TIMEOUT_MS,
4410
4810
  (signal) => this.#resolvePrompt(message.content, signal, {
4411
- onFullTurnModel
4811
+ onFullTurnModel: options.onFullTurnModel
4412
4812
  })
4413
4813
  );
4414
4814
  } catch (messageError) {
4415
- if (abortSignal.aborted) return parts;
4416
- const errorMessage = this.#formatError(messageError);
4417
- debugLogger6.warn(`Failed to resolve mid-turn message: ${errorMessage}`);
4815
+ if (abortSignal.aborted && !options.preserveFallbackOnAbort) {
4816
+ return parts;
4817
+ }
4818
+ if (!abortSignal.aborted) {
4819
+ const errorMessage = this.#formatError(messageError);
4820
+ debugLogger6.warn(
4821
+ `Failed to resolve mid-turn message: ${errorMessage}`
4822
+ );
4823
+ }
4418
4824
  rawParts = [{ text: displayText }];
4419
4825
  if (message.kind === "structured" && hasInlineMediaContentBlock(message.content)) {
4420
4826
  rawParts.push({ text: MID_TURN_ATTACHMENT_PROCESSING_FAILURE_TEXT });
@@ -4451,11 +4857,27 @@ ${this.pendingWorktreeNotice}
4451
4857
  this.#enqueueCronPrompt({
4452
4858
  prompt: job.prompt,
4453
4859
  source: job.cronExpr === "@wakeup" ? "loop" : "cron",
4454
- ...job.id ? { taskId: job.id } : {}
4860
+ ...job.id ? { taskId: job.id } : {},
4861
+ ...job.lastFiredAt !== void 0 ? { firedAt: job.lastFiredAt } : {},
4862
+ ...job.delivery ? { delivery: job.delivery } : {}
4455
4863
  });
4456
4864
  void this.#drainCronQueue();
4457
4865
  });
4458
4866
  }
4867
+ #startCronSchedulerInRuntime() {
4868
+ return Storage.runWithRuntimeBaseDir(
4869
+ this.runtimeBaseDir,
4870
+ this.config.getWorkingDir(),
4871
+ () => this.#startCronSchedulerIfNeeded()
4872
+ );
4873
+ }
4874
+ #stopCronSchedulerInRuntime() {
4875
+ Storage.runWithRuntimeBaseDir(
4876
+ this.runtimeBaseDir,
4877
+ this.config.getWorkingDir(),
4878
+ () => this.config.getCronScheduler().stop()
4879
+ );
4880
+ }
4459
4881
  #enqueueCronPrompt(item) {
4460
4882
  if ((this.todoStopGuard.blocksUnrelatedAutomaticTurns || this.todoStopGuardQueuedPromptPriority) && !this.#cronContinuesTodoStopGuardWorkChain(item)) {
4461
4883
  if (item.taskId) {
@@ -4486,17 +4908,31 @@ ${this.pendingWorktreeNotice}
4486
4908
  */
4487
4909
  async #drainCronQueue() {
4488
4910
  if (this.disposed) return;
4911
+ if (this.closing) return;
4489
4912
  if (this.cronProcessing) return;
4490
4913
  if (this.pendingPrompt) return;
4491
4914
  if (this.notificationProcessing) return;
4915
+ if (this.#deferAutomaticQueueDrainUntilTurnsSettle()) return;
4492
4916
  if (this.#nextCronQueueIndex() < 0) return;
4493
- this.cronProcessing = true;
4494
- let resolveCompletion;
4495
- this.cronCompletion = new Promise((resolve5) => {
4496
- resolveCompletion = resolve5;
4497
- });
4498
4917
  try {
4499
- while (this.cronQueue.length > 0) {
4918
+ await this.assertCanStartTurn();
4919
+ } catch (error) {
4920
+ debugLogger6.warn(
4921
+ `Cron turn rejected [session ${this.sessionId}]: ${error instanceof Error ? error.message : String(error)}`
4922
+ );
4923
+ return;
4924
+ }
4925
+ if (this.disposed || this.closing || this.cronProcessing || this.pendingPrompt || this.notificationProcessing || this.#nextCronQueueIndex() < 0) {
4926
+ return;
4927
+ }
4928
+ if (this.#deferAutomaticQueueDrainUntilTurnsSettle()) return;
4929
+ this.cronProcessing = true;
4930
+ let resolveCompletion;
4931
+ this.cronCompletion = new Promise((resolve5) => {
4932
+ resolveCompletion = resolve5;
4933
+ });
4934
+ try {
4935
+ while (this.cronQueue.length > 0) {
4500
4936
  const nextIndex = this.#nextCronQueueIndex();
4501
4937
  if (nextIndex < 0) break;
4502
4938
  const [item] = this.cronQueue.splice(nextIndex, 1);
@@ -4511,7 +4947,7 @@ ${this.pendingWorktreeNotice}
4511
4947
  if (this.config.isCronEnabled()) {
4512
4948
  const scheduler = this.config.getCronScheduler();
4513
4949
  if (!scheduler.hasPendingWork) {
4514
- scheduler.stop();
4950
+ this.#stopCronSchedulerInRuntime();
4515
4951
  }
4516
4952
  }
4517
4953
  }
@@ -4550,9 +4986,12 @@ ${this.pendingWorktreeNotice}
4550
4986
  * `_meta.source='cron'`, streams the model response, and handles tool calls.
4551
4987
  */
4552
4988
  async #executeCronPrompt(item) {
4553
- return sessionIdContext.run(
4554
- this.config.getSessionId(),
4555
- () => this.#executeCronPromptInner(item)
4989
+ return runWithInvocationContext(
4990
+ void 0,
4991
+ () => sessionIdContext.run(
4992
+ this.config.getSessionId(),
4993
+ () => this.#executeCronPromptInner(item)
4994
+ )
4556
4995
  );
4557
4996
  }
4558
4997
  async #executeCronPromptInner(item) {
@@ -4568,6 +5007,8 @@ ${this.pendingWorktreeNotice}
4568
5007
  );
4569
5008
  const promptId = this.config.getSessionId() + "########cron" + Date.now();
4570
5009
  let cronHadError = false;
5010
+ let cronCompleted = false;
5011
+ const channelDeliveryCapture = item.delivery ? { finalText: "" } : void 0;
4571
5012
  await withInteractionSpan(
4572
5013
  this.config,
4573
5014
  {
@@ -4578,6 +5019,8 @@ ${this.pendingWorktreeNotice}
4578
5019
  async () => {
4579
5020
  let turnCount = 0;
4580
5021
  try {
5022
+ await this.assertCanStartTurn();
5023
+ if (ac.signal.aborted) return;
4581
5024
  const loopMode = detectLoopSentinel(prompt);
4582
5025
  const autonomousMode = loopMode ? null : detectAutonomousSentinel(prompt);
4583
5026
  let loopTick = null;
@@ -4666,6 +5109,8 @@ ${this.pendingWorktreeNotice}
4666
5109
  return;
4667
5110
  }
4668
5111
  const responseStream = sendResult.responseStream;
5112
+ const channelDeliveryResponseBlock = beginChannelDeliveryResponseBlock(channelDeliveryCapture);
5113
+ const channelDeliveryCheckpoint = channelDeliveryResponseBlock?.length ?? 0;
4669
5114
  if (loopTick && turnCount === 1) {
4670
5115
  this.loopTickResolver?.markDelivered();
4671
5116
  }
@@ -4690,6 +5135,7 @@ ${this.pendingWorktreeNotice}
4690
5135
  part.thought
4691
5136
  );
4692
5137
  if (!part.thought) {
5138
+ channelDeliveryResponseBlock?.push(part.text);
4693
5139
  messageDisplay?.addChunk(part.text);
4694
5140
  }
4695
5141
  }
@@ -4705,6 +5151,11 @@ ${this.pendingWorktreeNotice}
4705
5151
  }
4706
5152
  }
4707
5153
  if (resp.type === "retry" /* RETRY */ || resp.type === "model_fallback" /* MODEL_FALLBACK */) {
5154
+ if (resp.type === "model_fallback" /* MODEL_FALLBACK */ || !resp.isContinuation) {
5155
+ if (channelDeliveryResponseBlock) {
5156
+ channelDeliveryResponseBlock.length = channelDeliveryCheckpoint;
5157
+ }
5158
+ }
4708
5159
  await finalizeToolCallPreparations(
4709
5160
  preparationTracker,
4710
5161
  true,
@@ -4727,6 +5178,11 @@ ${this.pendingWorktreeNotice}
4727
5178
  await messageDisplay?.finish();
4728
5179
  }
4729
5180
  }
5181
+ commitChannelDeliveryResponseBlock(
5182
+ channelDeliveryCapture,
5183
+ channelDeliveryResponseBlock,
5184
+ functionCalls.length > 0
5185
+ );
4730
5186
  if (usageMetadata) {
4731
5187
  this.#recordPromptTokenCount(usageMetadata);
4732
5188
  if (this.messageRewriter) {
@@ -4763,18 +5219,23 @@ ${this.pendingWorktreeNotice}
4763
5219
  }
4764
5220
  }
4765
5221
  }
5222
+ let stopReason = "end_turn";
4766
5223
  if (this.todoStopGuard.needsStopInspection) {
4767
5224
  const guardStop = await this.#handleStopHookLoop(
4768
5225
  ac,
4769
5226
  promptId,
4770
5227
  false,
4771
5228
  void 0,
4772
- false
5229
+ false,
5230
+ void 0,
5231
+ channelDeliveryCapture
4773
5232
  );
5233
+ stopReason = guardStop.stopReason;
4774
5234
  if (guardStop.stopReason === "max_tokens") {
4775
5235
  this.#stopCronAfterTokenLimit();
4776
5236
  }
4777
5237
  }
5238
+ cronCompleted = stopReason === "end_turn" && !ac.signal.aborted;
4778
5239
  } catch (error) {
4779
5240
  if (ac.signal.aborted) {
4780
5241
  this.todoStopGuard.suspend();
@@ -4802,6 +5263,19 @@ ${this.pendingWorktreeNotice}
4802
5263
  },
4803
5264
  () => ac.signal.aborted ? "cancelled" : cronHadError ? "error" : "ok"
4804
5265
  );
5266
+ if (cronCompleted && item.delivery && item.taskId && item.firedAt !== void 0) {
5267
+ this.#scheduleChannelDelivery({
5268
+ sessionId: this.sessionId,
5269
+ deliveryId: `${item.taskId}:${item.firedAt}`,
5270
+ source: "scheduled",
5271
+ target: item.delivery.target,
5272
+ text: normalizeChannelDeliveryText(
5273
+ channelDeliveryCapture?.finalText ?? ""
5274
+ ),
5275
+ taskId: item.taskId,
5276
+ firedAt: item.firedAt
5277
+ });
5278
+ }
4805
5279
  }
4806
5280
  );
4807
5281
  }
@@ -4907,12 +5381,26 @@ ${this.pendingWorktreeNotice}
4907
5381
  }
4908
5382
  async #drainNotificationQueue() {
4909
5383
  if (this.disposed) return;
5384
+ if (this.closing) return;
4910
5385
  if (this.notificationProcessing) return;
4911
5386
  if (this.pendingPrompt || this.cronProcessing || this.cronAbortController) {
4912
5387
  return;
4913
5388
  }
5389
+ if (this.#deferAutomaticQueueDrainUntilTurnsSettle()) return;
4914
5390
  if (this.notificationQueue.length === 0) return;
4915
5391
  if (this.#nextNotificationQueueIndex() < 0) return;
5392
+ try {
5393
+ await this.assertCanStartTurn();
5394
+ } catch (error) {
5395
+ debugLogger6.warn(
5396
+ `Notification turn rejected [session ${this.sessionId}]: ${error instanceof Error ? error.message : String(error)}`
5397
+ );
5398
+ return;
5399
+ }
5400
+ if (this.disposed || this.closing || this.notificationProcessing || this.pendingPrompt || this.cronProcessing || this.cronAbortController || this.#nextNotificationQueueIndex() < 0) {
5401
+ return;
5402
+ }
5403
+ if (this.#deferAutomaticQueueDrainUntilTurnsSettle()) return;
4916
5404
  this.notificationProcessing = true;
4917
5405
  let resolveCompletion;
4918
5406
  this.notificationCompletion = new Promise((resolve5) => {
@@ -4927,9 +5415,12 @@ ${this.pendingWorktreeNotice}
4927
5415
  if (nextIndex < 0) break;
4928
5416
  const [item] = this.notificationQueue.splice(nextIndex, 1);
4929
5417
  if (!item) break;
4930
- await sessionIdContext.run(
4931
- this.config.getSessionId(),
4932
- () => this.#executeBackgroundNotificationPromptInner(item)
5418
+ await runWithInvocationContext(
5419
+ void 0,
5420
+ () => sessionIdContext.run(
5421
+ this.config.getSessionId(),
5422
+ () => this.#executeBackgroundNotificationPromptInner(item)
5423
+ )
4933
5424
  );
4934
5425
  }
4935
5426
  } finally {
@@ -4962,6 +5453,8 @@ ${this.pendingWorktreeNotice}
4962
5453
  );
4963
5454
  const promptId = this.config.getSessionId() + "########notification" + Date.now();
4964
5455
  try {
5456
+ await this.assertCanStartTurn();
5457
+ if (ac.signal.aborted) return;
4965
5458
  await this.#emitBackgroundNotificationDisplay(item);
4966
5459
  const notificationParts = [{ text: item.modelText }];
4967
5460
  this.config.getChatRecordingService()?.recordNotification(notificationParts, item.displayText);
@@ -5091,7 +5584,9 @@ ${this.pendingWorktreeNotice}
5091
5584
  if (toolRun.stopAfterPermissionCancel) {
5092
5585
  this.todoStopGuard.suspend();
5093
5586
  await this.#preserveStoppedToolRun(toolRun, ac.signal);
5094
- await this.#emitBackgroundNotificationEndTurn("end_turn");
5587
+ await this.#emitBackgroundNotificationEndTurn(
5588
+ getAbortAwareEndTurnStopReason(ac.signal)
5589
+ );
5095
5590
  return;
5096
5591
  }
5097
5592
  const nextAfterTools = await this.#buildNextMessageAfterToolRun(
@@ -5102,7 +5597,9 @@ ${this.pendingWorktreeNotice}
5102
5597
  if (toolRun.loopDetected) {
5103
5598
  this.todoStopGuard.suspend();
5104
5599
  await this.#preserveStoppedToolRun(toolRun, ac.signal);
5105
- await this.#emitBackgroundNotificationEndTurn("end_turn");
5600
+ await this.#emitBackgroundNotificationEndTurn(
5601
+ getAbortAwareEndTurnStopReason(ac.signal)
5602
+ );
5106
5603
  return;
5107
5604
  }
5108
5605
  }
@@ -5120,7 +5617,9 @@ ${this.pendingWorktreeNotice}
5120
5617
  false
5121
5618
  )).stopReason;
5122
5619
  }
5123
- await this.#emitBackgroundNotificationEndTurn(stopReason);
5620
+ await this.#emitBackgroundNotificationEndTurn(
5621
+ ac.signal.aborted ? "cancelled" : stopReason
5622
+ );
5124
5623
  } catch (error) {
5125
5624
  if (ac.signal.aborted) {
5126
5625
  this.todoStopGuard.suspend();
@@ -5413,8 +5912,46 @@ ${this.pendingWorktreeNotice}
5413
5912
  */
5414
5913
  async runToolCalls(abortSignal, promptId, functionCalls, toolLoopState) {
5415
5914
  const dedupedFunctionCalls = dedupeToolCallsById(functionCalls);
5915
+ const generatedCallIdBase = randomUUID();
5916
+ const executionCallIds = new Map(
5917
+ dedupedFunctionCalls.map((functionCall, index) => [
5918
+ functionCall,
5919
+ functionCall.id ?? `${functionCall.name ?? "tool"}-${generatedCallIdBase}-${index}`
5920
+ ])
5921
+ );
5922
+ const pendingToolResultRecords = [];
5923
+ let toolResultRecordSequence = 0;
5924
+ const queueToolResultRecord = /* @__PURE__ */ __name((fc, record) => {
5925
+ pendingToolResultRecords.push({
5926
+ ...record,
5927
+ ordinal: dedupedFunctionCalls.indexOf(fc),
5928
+ sequence: toolResultRecordSequence++
5929
+ });
5930
+ }, "queueToolResultRecord");
5931
+ const finalizeRunToolResult = /* @__PURE__ */ __name(async (result) => {
5932
+ if (pendingToolResultRecords.length === 0) return result;
5933
+ const orderedRecords = [...pendingToolResultRecords].sort(
5934
+ (left, right) => left.ordinal - right.ordinal || left.sequence - right.sequence
5935
+ );
5936
+ const finalized = await finalizeToolResponses(
5937
+ this.config,
5938
+ orderedRecords.map((record) => ({
5939
+ callId: record.callId,
5940
+ toolName: record.toolName,
5941
+ responseParts: record.responseParts,
5942
+ persistedOutputFiles: record.persistedOutputFiles
5943
+ }))
5944
+ );
5945
+ orderedRecords.forEach((record, index) => {
5946
+ this.config.getChatRecordingService()?.recordToolResult(finalized[index].responseParts, record.metadata);
5947
+ });
5948
+ return {
5949
+ ...result,
5950
+ parts: finalized.flatMap((entry) => entry.responseParts)
5951
+ };
5952
+ }, "finalizeRunToolResult");
5416
5953
  let skippedToolCallCounter = 0;
5417
- const recordSkippedToolCall = /* @__PURE__ */ __name(async (fc, message = PERMISSION_CANCEL_SKIP_MESSAGE, emitStart = true) => {
5954
+ const recordSkippedToolCall = /* @__PURE__ */ __name(async (fc, message = PERMISSION_CANCEL_SKIP_MESSAGE, emitStart = true, errorType) => {
5418
5955
  const toolName = fc.name ?? "unknown_tool";
5419
5956
  const callId = fc.id ?? `${toolName}-skip-${++skippedToolCallCounter}`;
5420
5957
  const part = {
@@ -5426,12 +5963,17 @@ ${this.pendingWorktreeNotice}
5426
5963
  };
5427
5964
  const error = new Error(message);
5428
5965
  try {
5429
- this.config.getChatRecordingService()?.recordToolResult([part], {
5966
+ queueToolResultRecord(fc, {
5430
5967
  callId,
5431
- status: "error",
5432
- resultDisplay: void 0,
5433
- error,
5434
- errorType: void 0
5968
+ toolName,
5969
+ responseParts: [part],
5970
+ metadata: {
5971
+ callId,
5972
+ status: "error",
5973
+ resultDisplay: void 0,
5974
+ error,
5975
+ errorType
5976
+ }
5435
5977
  });
5436
5978
  if (emitStart) {
5437
5979
  await this.toolCallEmitter.emitStart({
@@ -5453,7 +5995,7 @@ ${this.pendingWorktreeNotice}
5453
5995
  toolLoopState,
5454
5996
  dedupedFunctionCalls.length
5455
5997
  )) {
5456
- return {
5998
+ return await finalizeRunToolResult({
5457
5999
  parts: await Promise.all(
5458
6000
  dedupedFunctionCalls.map(
5459
6001
  (fc) => recordSkippedToolCall(fc, LOOP_DETECTED_SKIP_MESSAGE, false)
@@ -5461,7 +6003,7 @@ ${this.pendingWorktreeNotice}
5461
6003
  ),
5462
6004
  stopAfterPermissionCancel: false,
5463
6005
  loopDetected: true
5464
- };
6006
+ });
5465
6007
  }
5466
6008
  const batches = [];
5467
6009
  const handledProviderToolCallIds = new Set(
@@ -5478,13 +6020,13 @@ ${this.pendingWorktreeNotice}
5478
6020
  debugLogger6.debug(
5479
6021
  `[Session.runToolCalls] Dropping batch after repeated duplicate provider tool-call id: ${providerCallId} (tool: ${repeatedDuplicateCall.name ?? "unknown_tool"})`
5480
6022
  );
5481
- return {
6023
+ return await finalizeRunToolResult({
5482
6024
  parts: [],
5483
6025
  stopAfterPermissionCancel: false,
5484
6026
  repeatedDuplicateProviderToolCall: true
5485
- };
6027
+ });
5486
6028
  }
5487
- const pushDuplicateBatch = /* @__PURE__ */ __name((request) => {
6029
+ const pushDuplicateBatch = /* @__PURE__ */ __name((fc, request) => {
5488
6030
  const providerCallId = request.providerCallId ?? request.callId;
5489
6031
  markDuplicateProviderToolCallResponseSent(
5490
6032
  providerCallId,
@@ -5494,7 +6036,7 @@ ${this.pendingWorktreeNotice}
5494
6036
  debugLogger6.debug(
5495
6037
  `[Session.runToolCalls] Suppressing duplicate provider tool-call id: ${providerCallId} (tool: ${request.name})`
5496
6038
  );
5497
- batches.push({ kind: "duplicate", request, response });
6039
+ batches.push({ kind: "duplicate", fc, request, response });
5498
6040
  }, "pushDuplicateBatch");
5499
6041
  const emitDuplicateBatch = /* @__PURE__ */ __name(async (batch) => {
5500
6042
  const { request, response } = batch;
@@ -5531,20 +6073,26 @@ ${this.pendingWorktreeNotice}
5531
6073
  success: false
5532
6074
  });
5533
6075
  }
5534
- this.config.getChatRecordingService()?.recordToolResult(response.responseParts, {
6076
+ queueToolResultRecord(batch.fc, {
5535
6077
  callId: response.callId,
5536
- status: "error",
5537
- resultDisplay: response.resultDisplay,
5538
- error: response.error,
5539
- errorType: response.errorType
6078
+ toolName: request.name,
6079
+ responseParts: response.responseParts,
6080
+ persistedOutputFiles: response.persistedOutputFiles,
6081
+ metadata: {
6082
+ callId: response.callId,
6083
+ status: "error",
6084
+ resultDisplay: response.resultDisplay,
6085
+ error: response.error,
6086
+ errorType: response.errorType
6087
+ }
5540
6088
  });
5541
6089
  }, "emitDuplicateBatch");
5542
6090
  for (const fc of dedupedFunctionCalls) {
5543
6091
  const providerCallId = getProviderToolCallId(fc) ?? fc.id;
5544
6092
  if (providerCallId) {
5545
6093
  if (handledProviderToolCallIds.has(providerCallId)) {
5546
- const callId = fc.id ?? `${fc.name}-${Date.now()}`;
5547
- pushDuplicateBatch({
6094
+ const callId = executionCallIds.get(fc);
6095
+ pushDuplicateBatch(fc, {
5548
6096
  callId,
5549
6097
  providerCallId,
5550
6098
  name: fc.name ?? "unknown_tool",
@@ -5564,6 +6112,13 @@ ${this.pendingWorktreeNotice}
5564
6112
  batches.push({ kind: "execute", concurrent: isAgent, calls: [fc] });
5565
6113
  }
5566
6114
  }
6115
+ const executableCalls = batches.flatMap(
6116
+ (batch) => batch.kind === "execute" ? batch.calls : []
6117
+ );
6118
+ const planModeEntryBoundaryIndex = findPlanModeEntryBatchBoundaryIndex(
6119
+ executableCalls.map((call) => call.name)
6120
+ );
6121
+ const planModeEntryBoundary = planModeEntryBoundaryIndex === void 0 ? void 0 : executableCalls[planModeEntryBoundaryIndex];
5567
6122
  const appendSkippedAfter = /* @__PURE__ */ __name(async (parts2, fc, message = PERMISSION_CANCEL_SKIP_MESSAGE) => {
5568
6123
  const startIndex = dedupedFunctionCalls.indexOf(fc) + 1;
5569
6124
  for (const remainingCall of dedupedFunctionCalls.slice(startIndex)) {
@@ -5630,7 +6185,9 @@ ${this.pendingWorktreeNotice}
5630
6185
  calls[i],
5631
6186
  onStopAfterPermissionCancel,
5632
6187
  toolLoopState,
5633
- recordSkippedToolCall
6188
+ recordSkippedToolCall,
6189
+ queueToolResultRecord,
6190
+ executionCallIds.get(calls[i])
5634
6191
  );
5635
6192
  results[i] = r;
5636
6193
  if (r.loopDetected) {
@@ -5662,7 +6219,9 @@ ${this.pendingWorktreeNotice}
5662
6219
  calls[idx],
5663
6220
  onStopAfterPermissionCancel,
5664
6221
  toolLoopState,
5665
- recordSkippedToolCall
6222
+ recordSkippedToolCall,
6223
+ queueToolResultRecord,
6224
+ executionCallIds.get(calls[idx])
5666
6225
  ).then((r) => {
5667
6226
  results[idx] = r;
5668
6227
  }).finally(() => {
@@ -5701,6 +6260,19 @@ ${this.pendingWorktreeNotice}
5701
6260
  parts.push(...batch.response.responseParts);
5702
6261
  continue;
5703
6262
  }
6263
+ if (planModeEntryBoundary && !batch.calls.includes(planModeEntryBoundary)) {
6264
+ for (const fc of batch.calls) {
6265
+ parts.push(
6266
+ await recordSkippedToolCall(
6267
+ fc,
6268
+ PLAN_MODE_ENTRY_SIBLING_SKIP_MESSAGE,
6269
+ true,
6270
+ "execution_denied" /* EXECUTION_DENIED */
6271
+ )
6272
+ );
6273
+ }
6274
+ continue;
6275
+ }
5704
6276
  if (batch.concurrent && batch.calls.length > 1) {
5705
6277
  const batchAbortController = new AbortController();
5706
6278
  let batchStopAfterPermissionCancel = false;
@@ -5744,24 +6316,24 @@ ${this.pendingWorktreeNotice}
5744
6316
  batch.calls[batch.calls.length - 1],
5745
6317
  LOOP_DETECTED_SKIP_MESSAGE
5746
6318
  );
5747
- return {
6319
+ return await finalizeRunToolResult({
5748
6320
  parts,
5749
6321
  stopAfterPermissionCancel: false,
5750
6322
  loopDetected: true,
5751
6323
  memoryWriteCandidates
5752
- };
6324
+ });
5753
6325
  }
5754
6326
  if (shouldStop) {
5755
6327
  await appendSkippedAfter(
5756
6328
  parts,
5757
6329
  batch.calls[batch.calls.length - 1]
5758
6330
  );
5759
- return {
6331
+ return await finalizeRunToolResult({
5760
6332
  parts,
5761
6333
  stopAfterPermissionCancel: true,
5762
6334
  repeatedDuplicateProviderToolCall: false,
5763
6335
  memoryWriteCandidates
5764
- };
6336
+ });
5765
6337
  }
5766
6338
  } else {
5767
6339
  for (const fc of batch.calls) {
@@ -5771,37 +6343,39 @@ ${this.pendingWorktreeNotice}
5771
6343
  fc,
5772
6344
  void 0,
5773
6345
  toolLoopState,
5774
- recordSkippedToolCall
6346
+ recordSkippedToolCall,
6347
+ queueToolResultRecord,
6348
+ executionCallIds.get(fc)
5775
6349
  );
5776
6350
  parts.push(...r.parts);
5777
6351
  collectMemoryWriteCandidates(r);
5778
6352
  if (r.loopDetected) {
5779
6353
  await appendSkippedAfter(parts, fc, LOOP_DETECTED_SKIP_MESSAGE);
5780
- return {
6354
+ return await finalizeRunToolResult({
5781
6355
  parts,
5782
6356
  stopAfterPermissionCancel: false,
5783
6357
  loopDetected: true,
5784
6358
  memoryWriteCandidates
5785
- };
6359
+ });
5786
6360
  }
5787
6361
  if (r.stopAfterPermissionCancel) {
5788
6362
  await appendSkippedAfter(parts, fc);
5789
- return {
6363
+ return await finalizeRunToolResult({
5790
6364
  parts,
5791
6365
  stopAfterPermissionCancel: true,
5792
6366
  repeatedDuplicateProviderToolCall: false,
5793
6367
  memoryWriteCandidates
5794
- };
6368
+ });
5795
6369
  }
5796
6370
  }
5797
6371
  }
5798
6372
  }
5799
- return {
6373
+ return await finalizeRunToolResult({
5800
6374
  parts,
5801
6375
  stopAfterPermissionCancel: false,
5802
6376
  repeatedDuplicateProviderToolCall: false,
5803
6377
  memoryWriteCandidates
5804
- };
6378
+ });
5805
6379
  } finally {
5806
6380
  await refreshMemoryIfNeeded();
5807
6381
  }
@@ -5836,8 +6410,8 @@ ${this.pendingWorktreeNotice}
5836
6410
  }
5837
6411
  return reminders;
5838
6412
  }
5839
- async runTool(abortSignal, promptId, fc, onStopAfterPermissionCancel, toolLoopState, recordSkippedToolCall) {
5840
- const callId = fc.id ?? `${fc.name}-${Date.now()}`;
6413
+ async runTool(abortSignal, promptId, fc, onStopAfterPermissionCancel, toolLoopState, recordSkippedToolCall, queueToolResultRecord, generatedCallId) {
6414
+ const callId = fc.id ?? generatedCallId ?? `${fc.name}-${Date.now()}`;
5841
6415
  let args = fc.args ?? {};
5842
6416
  if (toolLoopState?.loopDetected) {
5843
6417
  return {
@@ -5899,12 +6473,17 @@ ${this.pendingWorktreeNotice}
5899
6473
  await this.toolCallEmitter.emitError(callId, toolName2, error);
5900
6474
  }
5901
6475
  const errorParts = errorResponse(error);
5902
- this.config.getChatRecordingService()?.recordToolResult(errorParts, {
6476
+ queueToolResultRecord?.(fc, {
5903
6477
  callId,
5904
- status: "error",
5905
- resultDisplay: void 0,
5906
- error,
5907
- errorType: void 0
6478
+ toolName: toolName2,
6479
+ responseParts: errorParts,
6480
+ metadata: {
6481
+ callId,
6482
+ status: "error",
6483
+ resultDisplay: void 0,
6484
+ error,
6485
+ errorType: void 0
6486
+ }
5908
6487
  });
5909
6488
  const loopDetected = opts?.recordInvalidToolParams === true && !activeToolAbortSignal.aborted && !opts?.stopAfterPermissionCancel && recordDaemonInvalidToolParams(
5910
6489
  this.config,
@@ -5934,19 +6513,22 @@ ${this.pendingWorktreeNotice}
5934
6513
  { recordInvalidToolParams: true }
5935
6514
  );
5936
6515
  }
5937
- const toolSpan = startToolSpan(toolName, {
6516
+ const policyToolName = tool.name;
6517
+ const originalPolicyRequestArgs = policyToolName === ToolNames.SHELL || policyToolName === ToolNames.MONITOR ? structuredClone(args) : args;
6518
+ const toolSpan = startToolSpan(policyToolName, {
5938
6519
  "tool.call_id": callId,
6520
+ "gen_ai.tool.call.id": getProviderToolCallId(fc) ?? callId,
5939
6521
  // Dual-emit the legacy call_id/tool_name aliases like CoreToolScheduler
5940
6522
  // (coreToolScheduler.ts) so pre-Phase-2 dashboards keyed off call_id keep
5941
6523
  // matching daemon/ACP tool spans during the migration window.
5942
6524
  call_id: callId,
5943
- tool_name: toolName
6525
+ tool_name: policyToolName
5944
6526
  });
5945
6527
  let spanSuccess = false;
5946
6528
  try {
5947
6529
  return await runInToolSpanContext(toolSpan, async () => {
5948
6530
  const pm = this.config.getPermissionManager?.();
5949
- if (pm && !await pm.isToolEnabled(toolName)) {
6531
+ if (pm && !await pm.isToolEnabled(policyToolName)) {
5950
6532
  return earlyErrorResponse(
5951
6533
  new Error(`Tool "${toolName}" is disabled.`),
5952
6534
  toolName
@@ -5975,7 +6557,7 @@ ${this.pendingWorktreeNotice}
5975
6557
  }
5976
6558
  }
5977
6559
  const toolUseId = generateToolUseId();
5978
- const approvalMode = this.config.getApprovalMode();
6560
+ let approvalMode = this.config.getApprovalMode();
5979
6561
  let toolBuildSucceeded = false;
5980
6562
  try {
5981
6563
  const invocation = tool.build(args);
@@ -6000,12 +6582,12 @@ ${this.pendingWorktreeNotice}
6000
6582
  activeToolAbortSignal
6001
6583
  );
6002
6584
  }
6003
- const isAskUserQuestionTool = toolName === ToolNames.ASK_USER_QUESTION;
6004
- const toolParams = invocation.params;
6585
+ const isAskUserQuestionTool = policyToolName === ToolNames.ASK_USER_QUESTION;
6586
+ let toolParams = invocation.params;
6005
6587
  const flowResult = await evaluatePermissionFlow(
6006
6588
  this.config,
6007
6589
  invocation,
6008
- toolName,
6590
+ policyToolName,
6009
6591
  toolParams
6010
6592
  );
6011
6593
  const {
@@ -6015,31 +6597,75 @@ ${this.pendingWorktreeNotice}
6015
6597
  denyMessage,
6016
6598
  requiresUserInteraction
6017
6599
  } = flowResult;
6600
+ approvalMode = this.config.getApprovalMode();
6018
6601
  const isPlanMode = approvalMode === "plan" /* PLAN */;
6602
+ const isPlanShellCall = isPlanMode && (policyToolName === ToolNames.SHELL || policyToolName === ToolNames.MONITOR);
6019
6603
  if (finalPermission === "deny") {
6020
6604
  return earlyErrorResponse(
6021
6605
  new Error(denyMessage ?? `Tool "${toolName}" is denied.`),
6022
6606
  toolName
6023
6607
  );
6024
6608
  }
6025
- const forceAutoReviewForAllow = approvalMode === "auto" /* AUTO */ && (shouldForceAutoModeReviewForAllow(pmCtx, this.config.getCwd()) || shouldClassifyAllShellForAutoMode(toolName, this.config));
6609
+ let planShellAmbientWorkingDirectory;
6610
+ if (isPlanShellCall) {
6611
+ const directory = toolParams["directory"];
6612
+ planShellAmbientWorkingDirectory = typeof directory === "string" && directory.length > 0 ? void 0 : this.config.getTargetDir();
6613
+ invocation.params = {
6614
+ ...structuredClone(invocation.params),
6615
+ directory: typeof directory === "string" && directory.length > 0 ? directory : planShellAmbientWorkingDirectory
6616
+ };
6617
+ toolParams = invocation.params;
6618
+ }
6619
+ const planShellDecision = isPlanShellCall ? await evaluatePlanModeShellPolicy({
6620
+ config: this.config,
6621
+ toolName: policyToolName,
6622
+ requestArgs: originalPolicyRequestArgs,
6623
+ invocationParams: toolParams,
6624
+ permissionContext: pmCtx,
6625
+ ambientWorkingDirectory: planShellAmbientWorkingDirectory,
6626
+ signal: activeToolAbortSignal
6627
+ }) : { classification: "not-applicable" };
6628
+ if (planShellDecision.classification !== "not-applicable") {
6629
+ const initialPlanShellError = await validatePlanModeShellContext({
6630
+ config: this.config,
6631
+ decision: planShellDecision,
6632
+ requestArgs: args,
6633
+ invocationParams: invocation.params,
6634
+ signal: activeToolAbortSignal
6635
+ });
6636
+ if (initialPlanShellError) {
6637
+ return earlyErrorResponse(
6638
+ new Error(initialPlanShellError),
6639
+ toolName
6640
+ );
6641
+ }
6642
+ }
6643
+ if (planShellDecision.classification === "write") {
6644
+ return earlyErrorResponse(
6645
+ new Error(planShellDecision.writeBlockMessage),
6646
+ toolName
6647
+ );
6648
+ }
6649
+ const planShellRequiresConfirmation = planShellDecision.classification === "unknown";
6650
+ const forceAutoReviewForAllow = approvalMode === "auto" /* AUTO */ && (shouldForceAutoModeReviewForAllow(pmCtx, this.config.getCwd()) || shouldClassifyAllShellForAutoMode(policyToolName, this.config));
6026
6651
  const confirmationPermission = getEffectivePermissionForConfirmation(
6027
6652
  finalPermission,
6028
6653
  forceAutoReviewForAllow
6029
6654
  );
6030
6655
  if (finalPermission === "allow" && forceAutoReviewForAllow) {
6031
6656
  debugLogger6.info(
6032
- `Auto mode: L4 allow overridden by protected-write guard for ${toolName}`
6657
+ `Auto mode: L4 allow overridden by protected-write guard for ${policyToolName}`
6033
6658
  );
6034
6659
  }
6035
- let autoModeAllowed = finalPermission === "allow" && !forceAutoReviewForAllow;
6660
+ let autoModeAllowed = finalPermission === "allow" && !forceAutoReviewForAllow && !planShellRequiresConfirmation;
6036
6661
  if (autoModeAllowed && approvalMode === "auto" /* AUTO */) {
6037
6662
  this.config.setAutoModeDenialState(
6038
6663
  recordAllow(this.config.getAutoModeDenialState())
6039
6664
  );
6040
6665
  }
6041
- let wasAutoModeDenialFallback = false;
6042
- if (!autoModeAllowed && !requiresUserInteraction && shouldRunAutoModeForCall(approvalMode, toolName)) {
6666
+ let wasAutoModeManualFallback = false;
6667
+ let autoModeFallbackMessage;
6668
+ if (!autoModeAllowed && !requiresUserInteraction && shouldRunAutoModeForCall(approvalMode, policyToolName)) {
6043
6669
  const denialState = this.config.getAutoModeDenialState();
6044
6670
  const fallback = shouldFallback(denialState);
6045
6671
  const messages = this.config.getGeminiClient?.()?.getHistoryTail(MAX_TRANSCRIPT_MESSAGES, false) ?? [];
@@ -6061,7 +6687,7 @@ ${this.pendingWorktreeNotice}
6061
6687
  this.config,
6062
6688
  decision,
6063
6689
  outcome,
6064
- toolName,
6690
+ policyToolName,
6065
6691
  toolParams,
6066
6692
  callId,
6067
6693
  abortSignal
@@ -6072,17 +6698,16 @@ ${this.pendingWorktreeNotice}
6072
6698
  break;
6073
6699
  case "blocked":
6074
6700
  debugLogger6.warn(
6075
- `Auto mode blocked (${outcome.reason}): tool=${toolName}, ` + formatDenialStateLog(denialState)
6701
+ `Auto mode blocked (${outcome.reason}): tool=${policyToolName}, ` + formatDenialStateLog(denialState)
6076
6702
  );
6077
6703
  return earlyErrorResponse(
6078
6704
  new Error(outcome.errorMessage),
6079
6705
  toolName
6080
6706
  );
6081
6707
  case "fallback":
6082
- wasAutoModeDenialFallback = isDenialFallbackReason(
6083
- outcome.reason
6084
- );
6085
- if (wasAutoModeDenialFallback) {
6708
+ wasAutoModeManualFallback = isDenialFallbackReason(outcome.reason) || outcome.reason === "classifier_unavailable";
6709
+ autoModeFallbackMessage = outcome.message;
6710
+ if (wasAutoModeManualFallback) {
6086
6711
  debugLogger6.warn(
6087
6712
  `Auto mode fallback to manual approval (${outcome.reason}): ` + formatDenialStateLog(denialState)
6088
6713
  );
@@ -6097,7 +6722,7 @@ ${this.pendingWorktreeNotice}
6097
6722
  let didRequestPermission = false;
6098
6723
  let confirmationDetails;
6099
6724
  const recordAutoModeFallbackResolution = /* @__PURE__ */ __name((outcome) => {
6100
- if (approvalMode === "auto" /* AUTO */ && wasAutoModeDenialFallback && isApproveOutcome(outcome)) {
6725
+ if (approvalMode === "auto" /* AUTO */ && wasAutoModeManualFallback && isApproveOutcome(outcome)) {
6101
6726
  const before = this.config.getAutoModeDenialState();
6102
6727
  const after = recordFallbackApprove(before);
6103
6728
  if (after === before) {
@@ -6113,14 +6738,51 @@ ${this.pendingWorktreeNotice}
6113
6738
  }
6114
6739
  }, "recordAutoModeFallbackResolution");
6115
6740
  if (!autoModeAllowed && needsConfirmation(
6116
- confirmationPermission,
6741
+ planShellRequiresConfirmation ? "ask" : confirmationPermission,
6117
6742
  approvalMode,
6118
- toolName,
6743
+ policyToolName,
6119
6744
  requiresUserInteraction
6120
6745
  )) {
6121
- confirmationDetails = await invocation.getConfirmationDetails(abortSignal);
6746
+ confirmationDetails = await invocation.getConfirmationDetails(
6747
+ activeToolAbortSignal
6748
+ );
6749
+ if (autoModeFallbackMessage) {
6750
+ confirmationDetails = decorateClassifierUnavailableConfirmation(
6751
+ confirmationDetails,
6752
+ autoModeFallbackMessage
6753
+ );
6754
+ }
6755
+ if (planShellDecision.classification !== "not-applicable") {
6756
+ const preDisplayPlanShellError = await validatePlanModeShellContext({
6757
+ config: this.config,
6758
+ decision: planShellDecision,
6759
+ requestArgs: args,
6760
+ invocationParams: invocation.params,
6761
+ signal: activeToolAbortSignal
6762
+ });
6763
+ if (preDisplayPlanShellError) {
6764
+ return earlyErrorResponse(
6765
+ new Error(preDisplayPlanShellError),
6766
+ toolName
6767
+ );
6768
+ }
6769
+ }
6770
+ try {
6771
+ confirmationDetails = decoratePlanModeShellConfirmation(
6772
+ planShellDecision,
6773
+ confirmationDetails
6774
+ );
6775
+ } catch {
6776
+ if (planShellDecision.classification === "unknown") {
6777
+ return earlyErrorResponse(
6778
+ new Error(planShellDecision.noApprovalMessage),
6779
+ toolName
6780
+ );
6781
+ }
6782
+ throw new Error("Unable to prepare shell confirmation.");
6783
+ }
6122
6784
  injectPermissionRulesIfMissing(confirmationDetails, pmCtx);
6123
- if (isPlanModeBlocked(
6785
+ if (planShellDecision.classification === "not-applicable" && isPlanModeBlocked(
6124
6786
  isPlanMode,
6125
6787
  isExitPlanModeTool,
6126
6788
  isAskUserQuestionTool,
@@ -6140,23 +6802,50 @@ ${this.pendingWorktreeNotice}
6140
6802
  if (hooksEnabled && messageBus) {
6141
6803
  const hookResult = await firePermissionRequestHook(
6142
6804
  messageBus,
6143
- toolName,
6805
+ policyToolName,
6144
6806
  args,
6145
- String(approvalMode)
6807
+ String(approvalMode),
6808
+ void 0,
6809
+ activeToolAbortSignal
6146
6810
  );
6147
6811
  if (hookResult.hasDecision && (!hookResult.shouldAllow || !requiresUserInteraction)) {
6148
6812
  hookHandled = true;
6149
6813
  if (hookResult.shouldAllow) {
6150
- if (hookResult.updatedInput) {
6151
- args = hookResult.updatedInput;
6152
- invocation.params = hookResult.updatedInput;
6814
+ if (planShellDecision.classification !== "not-applicable") {
6815
+ const approval = await validatePlanModeShellApproval({
6816
+ config: this.config,
6817
+ decision: planShellDecision,
6818
+ requestArgs: args,
6819
+ invocationParams: invocation.params,
6820
+ signal: activeToolAbortSignal,
6821
+ outcome: "proceed_once" /* ProceedOnce */,
6822
+ payload: hookResult.updatedInput ? { updatedInput: hookResult.updatedInput } : void 0
6823
+ });
6824
+ await confirmationDetails.onConfirm(
6825
+ approval.outcome,
6826
+ approval.payload
6827
+ );
6828
+ if (approval.outcome === "cancel" /* Cancel */) {
6829
+ return earlyErrorResponse(
6830
+ new Error(
6831
+ approval.payload?.cancelMessage ?? planShellDecision.noApprovalMessage
6832
+ ),
6833
+ toolName
6834
+ );
6835
+ }
6836
+ recordAutoModeFallbackResolution(approval.outcome);
6837
+ } else {
6838
+ if (hookResult.updatedInput) {
6839
+ args = hookResult.updatedInput;
6840
+ invocation.params = hookResult.updatedInput;
6841
+ }
6842
+ await confirmationDetails.onConfirm(
6843
+ "proceed_once" /* ProceedOnce */
6844
+ );
6845
+ recordAutoModeFallbackResolution(
6846
+ "proceed_once" /* ProceedOnce */
6847
+ );
6153
6848
  }
6154
- await confirmationDetails.onConfirm(
6155
- "proceed_once" /* ProceedOnce */
6156
- );
6157
- recordAutoModeFallbackResolution(
6158
- "proceed_once" /* ProceedOnce */
6159
- );
6160
6849
  } else {
6161
6850
  return earlyErrorResponse(
6162
6851
  new Error(
@@ -6169,11 +6858,26 @@ ${this.pendingWorktreeNotice}
6169
6858
  }
6170
6859
  if (!requiresUserInteraction && approvalMode === "auto-edit" /* AUTO_EDIT */ && (confirmationDetails.type === "edit" || confirmationDetails.type === "info")) {
6171
6860
  } else if (!hookHandled) {
6861
+ if (planShellDecision.classification !== "not-applicable") {
6862
+ const finalPreDisplayPlanShellError = await validatePlanModeShellContext({
6863
+ config: this.config,
6864
+ decision: planShellDecision,
6865
+ requestArgs: args,
6866
+ invocationParams: invocation.params,
6867
+ signal: activeToolAbortSignal
6868
+ });
6869
+ if (finalPreDisplayPlanShellError) {
6870
+ return earlyErrorResponse(
6871
+ new Error(finalPreDisplayPlanShellError),
6872
+ toolName
6873
+ );
6874
+ }
6875
+ }
6172
6876
  didRequestPermission = true;
6173
6877
  const content = buildPermissionRequestContent(confirmationDetails);
6174
6878
  const mappedKind = this.toolCallEmitter.mapToolKind(
6175
6879
  tool.kind,
6176
- toolName
6880
+ policyToolName
6177
6881
  );
6178
6882
  if (hooksEnabled && messageBus) {
6179
6883
  this.fireNotificationHookWithTerminalSequence(
@@ -6183,9 +6887,16 @@ ${this.pendingWorktreeNotice}
6183
6887
  "Permission needed"
6184
6888
  );
6185
6889
  }
6890
+ const permissionOptions = toPermissionOptions(
6891
+ confirmationDetails,
6892
+ pmForcedAsk
6893
+ );
6894
+ const offeredPermissionOptions = permissionOptions.map(
6895
+ (option) => ({ ...option })
6896
+ );
6186
6897
  const params = {
6187
6898
  sessionId: this.sessionId,
6188
- options: toPermissionOptions(confirmationDetails, pmForcedAsk),
6899
+ options: permissionOptions,
6189
6900
  toolCall: {
6190
6901
  toolCallId: callId,
6191
6902
  status: "pending",
@@ -6204,10 +6915,12 @@ ${this.pendingWorktreeNotice}
6204
6915
  }
6205
6916
  }
6206
6917
  };
6207
- const stopAfterPermissionCancel = /* @__PURE__ */ __name(() => {
6918
+ const stopAfterPermissionCancel = /* @__PURE__ */ __name((message) => {
6208
6919
  onStopAfterPermissionCancel?.();
6209
6920
  return earlyErrorResponse(
6210
- new Error(`Tool "${toolName}" was canceled by the user.`),
6921
+ new Error(
6922
+ message ?? `Tool "${toolName}" was canceled by the user.`
6923
+ ),
6211
6924
  toolName,
6212
6925
  { stopAfterPermissionCancel: true }
6213
6926
  );
@@ -6215,10 +6928,15 @@ ${this.pendingWorktreeNotice}
6215
6928
  let output;
6216
6929
  let outcome;
6217
6930
  try {
6218
- output = await this.client.requestPermission(
6219
- params
6931
+ output = await requestPermissionWithAbort(
6932
+ this.client,
6933
+ params,
6934
+ activeToolAbortSignal
6935
+ );
6936
+ outcome = resolvePermissionOutcome(
6937
+ output,
6938
+ offeredPermissionOptions
6220
6939
  );
6221
- outcome = output.outcome.outcome === "cancelled" ? "cancel" /* Cancel */ : external_exports.nativeEnum(ToolConfirmationOutcome).parse(output.outcome.optionId);
6222
6940
  } catch (error) {
6223
6941
  debugLogger6.error(
6224
6942
  `Permission request failed for tool ${toolName}:`,
@@ -6235,7 +6953,9 @@ ${this.pendingWorktreeNotice}
6235
6953
  );
6236
6954
  }
6237
6955
  onStopAfterPermissionCancel?.();
6238
- 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(
6956
+ 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(
6957
+ error
6958
+ )}. The command was not run; Plan mode remains active.` : `Permission request failed for "${toolName}": ${this.#formatError(
6239
6959
  error
6240
6960
  )}`;
6241
6961
  return earlyErrorResponse(
@@ -6244,11 +6964,32 @@ ${this.pendingWorktreeNotice}
6244
6964
  { stopAfterPermissionCancel: true }
6245
6965
  );
6246
6966
  }
6967
+ let confirmationPayload = {
6968
+ answers: output.answers
6969
+ };
6970
+ if (planShellDecision.classification !== "not-applicable") {
6971
+ const approval = await validatePlanModeShellApproval({
6972
+ config: this.config,
6973
+ decision: planShellDecision,
6974
+ requestArgs: args,
6975
+ invocationParams: invocation.params,
6976
+ signal: activeToolAbortSignal,
6977
+ outcome,
6978
+ payload: confirmationPayload
6979
+ });
6980
+ outcome = approval.outcome;
6981
+ confirmationPayload = approval.payload;
6982
+ }
6983
+ const shouldSwitchToDefault = outcome === "proceed_once_and_switch_to_default" /* ProceedOnceAndSwitchToDefault */;
6984
+ if (shouldSwitchToDefault) {
6985
+ outcome = "proceed_once" /* ProceedOnce */;
6986
+ }
6247
6987
  recordAutoModeFallbackResolution(outcome);
6248
6988
  try {
6249
- await confirmationDetails.onConfirm(outcome, {
6250
- answers: output.answers
6251
- });
6989
+ await confirmationDetails.onConfirm(
6990
+ outcome,
6991
+ confirmationPayload
6992
+ );
6252
6993
  } catch (error) {
6253
6994
  if (outcome !== "cancel" /* Cancel */) {
6254
6995
  throw error;
@@ -6259,21 +7000,31 @@ ${this.pendingWorktreeNotice}
6259
7000
  );
6260
7001
  return stopAfterPermissionCancel();
6261
7002
  }
7003
+ if (shouldSwitchToDefault) {
7004
+ this.config.setApprovalMode("default" /* DEFAULT */);
7005
+ await this.sendCurrentModeUpdateNotification();
7006
+ }
6262
7007
  if (outcome === "proceed_always" /* ProceedAlways */ || outcome === "proceed_always_project" /* ProceedAlwaysProject */ || outcome === "proceed_always_user" /* ProceedAlwaysUser */) {
6263
7008
  await persistPermissionOutcome(
6264
7009
  outcome,
6265
7010
  confirmationDetails,
6266
7011
  this.config.getOnPersistPermissionRule?.(),
6267
7012
  this.config.getPermissionManager?.(),
6268
- { answers: output.answers }
7013
+ confirmationPayload
6269
7014
  );
6270
7015
  }
6271
7016
  if (confirmationDetails.type === "edit" && outcome === "proceed_always" /* ProceedAlways */) {
6272
7017
  await this.sendCurrentModeUpdateNotification();
6273
7018
  }
6274
7019
  switch (outcome) {
7020
+ case "proceed_once_and_switch_to_default" /* ProceedOnceAndSwitchToDefault */:
7021
+ throw new Error(
7022
+ "Switch-to-Default outcome must be normalized before execution."
7023
+ );
6275
7024
  case "cancel" /* Cancel */:
6276
- return stopAfterPermissionCancel();
7025
+ return stopAfterPermissionCancel(
7026
+ confirmationPayload?.cancelMessage
7027
+ );
6277
7028
  case "proceed_once" /* ProceedOnce */:
6278
7029
  case "proceed_always" /* ProceedAlways */:
6279
7030
  case "proceed_always_project" /* ProceedAlwaysProject */:
@@ -6305,7 +7056,7 @@ ${this.pendingWorktreeNotice}
6305
7056
  if (hooksEnabledForTool && messageBusForTool) {
6306
7057
  const preHookResult = await firePreToolUseHook(
6307
7058
  messageBusForTool,
6308
- toolName,
7059
+ policyToolName,
6309
7060
  args,
6310
7061
  toolUseId,
6311
7062
  permissionMode,
@@ -6422,7 +7173,7 @@ ${this.pendingWorktreeNotice}
6422
7173
  };
6423
7174
  const postHookResult = await firePostToolUseHook(
6424
7175
  messageBusForTool,
6425
- toolName,
7176
+ policyToolName,
6426
7177
  args,
6427
7178
  toolResponse,
6428
7179
  toolUseId,
@@ -6453,7 +7204,7 @@ ${this.pendingWorktreeNotice}
6453
7204
  const failureHookResult = await firePostToolUseFailureHook(
6454
7205
  messageBusForTool,
6455
7206
  toolUseId,
6456
- toolName,
7207
+ policyToolName,
6457
7208
  args,
6458
7209
  toolResult.error?.message ?? "Tool execution was cancelled",
6459
7210
  isInterrupt,
@@ -6507,12 +7258,18 @@ ${this.pendingWorktreeNotice}
6507
7258
  prompt_id: promptId,
6508
7259
  tool_type: typeof tool !== "undefined" && tool instanceof DiscoveredMCPTool ? "mcp" : "native"
6509
7260
  });
6510
- this.config.getChatRecordingService()?.recordToolResult(responseParts, {
7261
+ queueToolResultRecord?.(fc, {
6511
7262
  callId,
6512
- status,
6513
- resultDisplay: toolResult.returnDisplay,
6514
- error: toolResult.error ? new Error(toolResult.error.message) : void 0,
6515
- errorType: toolResult.error?.type
7263
+ toolName,
7264
+ responseParts,
7265
+ persistedOutputFiles: toolResult.persistedOutputFiles,
7266
+ metadata: {
7267
+ callId,
7268
+ status,
7269
+ resultDisplay: toolResult.returnDisplay,
7270
+ error: toolResult.error ? new Error(toolResult.error.message) : void 0,
7271
+ errorType: toolResult.error?.type
7272
+ }
6516
7273
  });
6517
7274
  spanSuccess = succeeded;
6518
7275
  if (toolResult.error) {
@@ -6542,7 +7299,7 @@ ${this.pendingWorktreeNotice}
6542
7299
  const failureHookResult = await firePostToolUseFailureHook(
6543
7300
  messageBusForError,
6544
7301
  toolUseId,
6545
- toolName,
7302
+ policyToolName,
6546
7303
  args,
6547
7304
  error.message,
6548
7305
  isInterrupt,
@@ -6563,24 +7320,6 @@ ${this.pendingWorktreeNotice}
6563
7320
  });
6564
7321
  }
6565
7322
  await this.toolCallEmitter.emitError(callId, toolName, error);
6566
- const errorParts = [
6567
- {
6568
- functionResponse: {
6569
- id: callId,
6570
- name: toolName,
6571
- response: { error: error.message }
6572
- }
6573
- }
6574
- ];
6575
- this.config.getChatRecordingService()?.recordToolResult(errorParts, {
6576
- callId,
6577
- // A throw caused by abort (e.g. AbortError) is a cancellation, not
6578
- // a genuine tool error — keep it consistent with the success path.
6579
- status: activeToolAbortSignal.aborted ? "cancelled" : "error",
6580
- resultDisplay: void 0,
6581
- error,
6582
- errorType: void 0
6583
- });
6584
7323
  const loopDetected = !activeToolAbortSignal.aborted && !toolBuildSucceeded && recordDaemonInvalidToolParams(
6585
7324
  this.config,
6586
7325
  promptId,
@@ -6589,6 +7328,18 @@ ${this.pendingWorktreeNotice}
6589
7328
  error
6590
7329
  );
6591
7330
  const responseParts = errorResponse(error);
7331
+ queueToolResultRecord?.(fc, {
7332
+ callId,
7333
+ toolName,
7334
+ responseParts,
7335
+ metadata: {
7336
+ callId,
7337
+ status: activeToolAbortSignal.aborted ? "cancelled" : "error",
7338
+ resultDisplay: void 0,
7339
+ error,
7340
+ errorType: void 0
7341
+ }
7342
+ });
6592
7343
  return {
6593
7344
  parts: responseParts,
6594
7345
  stopAfterPermissionCancel: nestedPermissionCancelled,
@@ -7149,7 +7900,8 @@ function serializeAgentTask(entry, now) {
7149
7900
  at: a.at
7150
7901
  }))
7151
7902
  } : {},
7152
- ...optionalField("prompt", entry.prompt)
7903
+ ...optionalField("prompt", entry.prompt),
7904
+ ...optionalField("toolUseId", entry.toolUseId)
7153
7905
  };
7154
7906
  }
7155
7907
  __name(serializeAgentTask, "serializeAgentTask");
@@ -7225,6 +7977,7 @@ var QWEN_ACP_LOCAL_READ_ROOTS_ENV = "QWEN_ACP_LOCAL_READ_ROOTS";
7225
7977
  var POSIX_TMP_LOCAL_READ_ROOT = "/tmp";
7226
7978
  var BTW_CHILD_TIMEOUT_MS = 55e3;
7227
7979
  var MCP_OAUTH_START_TIMEOUT_MS = 3e4;
7980
+ var SESSION_DRAIN_TIMEOUT_MS = 3e4;
7228
7981
  var WORKSPACE_MEMORY_REMEMBER_CHILD_TIMEOUT_MS = 295e3;
7229
7982
  function createAcpSessionStartProfiler(span) {
7230
7983
  let failedStage;
@@ -7283,6 +8036,77 @@ function workspaceMemoryErrorData(code, diagnostics) {
7283
8036
  };
7284
8037
  }
7285
8038
  __name(workspaceMemoryErrorData, "workspaceMemoryErrorData");
8039
+ var SESSION_WRITER_MESSAGES = {
8040
+ session_writer_conflict: "This session is already open in another Qwen process.",
8041
+ session_writer_lost: "Write ownership for this session was lost.",
8042
+ session_transcript_changed: "The session transcript changed outside its active writer.",
8043
+ session_writer_unavailable: "Session write ownership could not be verified."
8044
+ };
8045
+ function getSessionWriterError(error) {
8046
+ if (!error || typeof error !== "object") return void 0;
8047
+ const candidate = error;
8048
+ const errorKind = candidate["errorKind"];
8049
+ if (typeof errorKind !== "string" || !(errorKind in SESSION_WRITER_RPC_CODES)) {
8050
+ return void 0;
8051
+ }
8052
+ const typedKind = errorKind;
8053
+ if (candidate["rpcCode"] !== SESSION_WRITER_RPC_CODES[typedKind]) {
8054
+ return void 0;
8055
+ }
8056
+ return {
8057
+ rpcCode: SESSION_WRITER_RPC_CODES[typedKind],
8058
+ errorKind: typedKind,
8059
+ message: SESSION_WRITER_MESSAGES[typedKind]
8060
+ };
8061
+ }
8062
+ __name(getSessionWriterError, "getSessionWriterError");
8063
+ function mapSessionWriterRequestError(error) {
8064
+ const writerError = getSessionWriterError(error);
8065
+ return writerError ? new RequestError(writerError.rpcCode, writerError.message, {
8066
+ errorKind: writerError.errorKind
8067
+ }) : error;
8068
+ }
8069
+ __name(mapSessionWriterRequestError, "mapSessionWriterRequestError");
8070
+ async function shutdownSessionConfig(config) {
8071
+ await config.shutdown({ shutdownTelemetry: false });
8072
+ if (config.hasSessionWriteOwnership()) {
8073
+ throw new SessionWriterUnavailableError();
8074
+ }
8075
+ }
8076
+ __name(shutdownSessionConfig, "shutdownSessionConfig");
8077
+ async function waitForSessionDrain(operation, timeoutMs, kind) {
8078
+ let timer;
8079
+ const timeout = new Promise((_, reject) => {
8080
+ timer = setTimeout(
8081
+ () => reject(new Error(`Session ${kind} timed out after ${timeoutMs}ms`)),
8082
+ timeoutMs
8083
+ );
8084
+ timer.unref();
8085
+ });
8086
+ try {
8087
+ await Promise.race([operation, timeout]);
8088
+ } finally {
8089
+ if (timer) clearTimeout(timer);
8090
+ }
8091
+ }
8092
+ __name(waitForSessionDrain, "waitForSessionDrain");
8093
+ async function beginSessionCloseAfterCurrentGate(session, timeoutMs) {
8094
+ const deadline = Date.now() + timeoutMs;
8095
+ while (true) {
8096
+ const releaseGate = session.beginCloseIfAvailable();
8097
+ if (releaseGate) return releaseGate;
8098
+ const remainingMs = deadline - Date.now();
8099
+ if (remainingMs <= 0) {
8100
+ throw new Error(`Session close timed out after ${timeoutMs}ms`);
8101
+ }
8102
+ await waitForSessionDrain(
8103
+ session.waitForCloseGateToRelease(),
8104
+ remainingMs,
8105
+ "close"
8106
+ );
8107
+ }
8108
+ }
8109
+ __name(beginSessionCloseAfterCurrentGate, "beginSessionCloseAfterCurrentGate");
7286
8110
  var logWorkspaceMemoryExtractionError = createWorkspaceMemoryExtractionErrorLogger(debugLogger7);
7287
8111
  function parseAcpLocalReadRootsEnv(raw = process.env[QWEN_ACP_LOCAL_READ_ROOTS_ENV]) {
7288
8112
  if (!raw) return [];
@@ -7300,7 +8124,7 @@ function buildAcpLocalReadRoots(config) {
7300
8124
  // local read fallback, not read_file's default permission.
7301
8125
  config.storage.getProjectTempDir(),
7302
8126
  path4.join(config.storage.getProjectDir(), "subagents"),
7303
- Storage.getGlobalTempDir(),
8127
+ path4.join(config.getSessionRuntimeBaseDir(), "tmp"),
7304
8128
  getAutoMemoryRoot(config.getTargetDir()),
7305
8129
  getUserAutoMemoryRoot(),
7306
8130
  ...config.storage.getUserSkillsDirs(),
@@ -8785,7 +9609,9 @@ async function deliverClientMcpMessage(connection, serverName, message, sessionI
8785
9609
  return payload;
8786
9610
  }
8787
9611
  __name(deliverClientMcpMessage, "deliverClientMcpMessage");
8788
- async function runAcpAgent(config, settings, argv) {
9612
+ async function runAcpAgent(config, settings, argv, options) {
9613
+ const privateParentCapability = options === void 0 ? process.env[PRIVATE_ACP_CAPABILITY_ENV] : options.privateParentCapability;
9614
+ delete process.env[PRIVATE_ACP_CAPABILITY_ENV];
8789
9615
  let acpConnection;
8790
9616
  const bootstrapClientMcpSender = /* @__PURE__ */ __name((serverName, message) => deliverClientMcpMessage(acpConnection, serverName, message), "bootstrapClientMcpSender");
8791
9617
  beginAcpBootstrapConfigProfiling();
@@ -8803,6 +9629,11 @@ async function runAcpAgent(config, settings, argv) {
8803
9629
  } finally {
8804
9630
  endAcpBootstrapConfigProfiling();
8805
9631
  }
9632
+ const startupWarnings = typeof config.getWarnings === "function" ? config.getWarnings() : [];
9633
+ for (const warning of startupWarnings) {
9634
+ process.stderr.write(`${warning}
9635
+ `);
9636
+ }
8806
9637
  const eventLoopMonitor = startEventLoopLagMonitor({
8807
9638
  onNewMaxStall: /* @__PURE__ */ __name((maxMs) => {
8808
9639
  console.error(`[perf] acp agent event loop stall: max=${maxMs}ms`);
@@ -8817,10 +9648,33 @@ async function runAcpAgent(config, settings, argv) {
8817
9648
  console.log = console.error;
8818
9649
  console.info = console.error;
8819
9650
  console.debug = console.error;
8820
- const stream = ndJsonStream(stdout, stdin);
9651
+ let initializeRequestId;
9652
+ const stream = ndJsonStream(stdout, stdin, {
9653
+ onMessageObserved: /* @__PURE__ */ __name(({ direction, message }) => {
9654
+ if (direction === "received" && "id" in message && "method" in message && message.method === "initialize") {
9655
+ initializeRequestId = message.id;
9656
+ return;
9657
+ }
9658
+ if (direction !== "sent" || initializeRequestId === void 0 || !("id" in message) || "method" in message || message.id !== initializeRequestId) {
9659
+ return;
9660
+ }
9661
+ initializeRequestId = void 0;
9662
+ if ("result" in message) {
9663
+ void initializeTelemetry(config).then(() => {
9664
+ registerAcpEventLoopLagGauge(() => eventLoopMonitor.snapshot());
9665
+ });
9666
+ }
9667
+ }, "onMessageObserved")
9668
+ });
8821
9669
  connection = new AgentSideConnection((conn) => {
8822
9670
  acpConnection = conn;
8823
- agentInstance = new QwenAgent(config, settings, argv, conn);
9671
+ agentInstance = new QwenAgent(
9672
+ config,
9673
+ settings,
9674
+ argv,
9675
+ conn,
9676
+ privateParentCapability
9677
+ );
8824
9678
  return agentInstance;
8825
9679
  }, stream);
8826
9680
  markAcpStartup("transportSetupEnd");
@@ -8828,7 +9682,6 @@ async function runAcpAgent(config, settings, argv) {
8828
9682
  eventLoopMonitor.dispose();
8829
9683
  throw err;
8830
9684
  }
8831
- registerAcpEventLoopLagGauge(() => eventLoopMonitor.snapshot());
8832
9685
  const drainPoolBeforeExit = /* @__PURE__ */ __name(async (label) => {
8833
9686
  if (!agentInstance) return;
8834
9687
  try {
@@ -8873,7 +9726,7 @@ async function runAcpAgent(config, settings, argv) {
8873
9726
  debugLogger7.debug("[ACP] Shutdown signal received, closing streams");
8874
9727
  try {
8875
9728
  await fireSessionEndOnce("other" /* Other */);
8876
- agentInstance?.disposeSessions();
9729
+ await agentInstance?.disposeSessions();
8877
9730
  try {
8878
9731
  process.stdin.destroy();
8879
9732
  } catch {
@@ -8900,7 +9753,7 @@ async function runAcpAgent(config, settings, argv) {
8900
9753
  await connection.closed;
8901
9754
  await fireSessionEndOnce("prompt_input_exit" /* PromptInputExit */);
8902
9755
  await drainPoolBeforeExit("ide_close");
8903
- agentInstance?.disposeSessions();
9756
+ await agentInstance?.disposeSessions();
8904
9757
  } finally {
8905
9758
  process.off("SIGTERM", shutdownHandler);
8906
9759
  process.off("SIGINT", shutdownHandler);
@@ -9017,11 +9870,12 @@ function parseAcpSessionListCursor(value) {
9017
9870
  }
9018
9871
  __name(parseAcpSessionListCursor, "parseAcpSessionListCursor");
9019
9872
  var QwenAgent = class {
9020
- constructor(config, settings, argv, connection) {
9873
+ constructor(config, settings, argv, connection, expectedPrivateParentCapability) {
9021
9874
  this.config = config;
9022
9875
  this.settings = settings;
9023
9876
  this.argv = argv;
9024
9877
  this.connection = connection;
9878
+ this.expectedPrivateParentCapability = expectedPrivateParentCapability;
9025
9879
  if (process.env["QWEN_SERVE_NO_MCP_POOL"] === "1") {
9026
9880
  this.mcpPool = void 0;
9027
9881
  this.workspaceMcpBudget = void 0;
@@ -9052,14 +9906,18 @@ var QwenAgent = class {
9052
9906
  __name(this, "QwenAgent");
9053
9907
  }
9054
9908
  sessions = /* @__PURE__ */ new Map();
9909
+ activePromptCalls = /* @__PURE__ */ new Map();
9055
9910
  workspaceMcpDiscoveryConfig;
9056
9911
  workspaceMcpDiscoveryPromise;
9057
9912
  workspaceMcpDiscoveryError;
9058
9913
  pendingMcpAuthentications = /* @__PURE__ */ new Map();
9059
9914
  mcpAuthenticationResults = /* @__PURE__ */ new Map();
9060
9915
  generationControllers = /* @__PURE__ */ new Map();
9916
+ workspaceGenerationControllers = /* @__PURE__ */ new Map();
9061
9917
  transcriptReplayConfigCache = /* @__PURE__ */ new Map();
9918
+ pendingConfigCleanup = /* @__PURE__ */ new Map();
9062
9919
  clientCapabilities;
9920
+ privateParentState = "uninitialized";
9063
9921
  // CPU-usage delta baseline for the daemon's `workspaceResource` extMethod
9064
9922
  // (Daemon Status child-resource chart). The daemon polls this at a fixed
9065
9923
  // cadence, so successive calls form a clean delta window independent of tool
@@ -9161,21 +10019,26 @@ var QwenAgent = class {
9161
10019
  async createWorkspaceMcpDiscoveryConfig(settings) {
9162
10020
  if (this.workspaceMcpDiscoveryConfig) return;
9163
10021
  const cwd = this.config.getTargetDir();
9164
- const config = await loadCliConfig(
9165
- settings.merged,
9166
- {
9167
- ...this.argv,
9168
- sessionId: "workspace-mcp-discovery",
9169
- resume: void 0,
9170
- continue: false
9171
- },
10022
+ const config = await this.runWithPinnedRuntimeBaseDir(
10023
+ settings,
9172
10024
  cwd,
9173
- void 0,
9174
- {
9175
- userHooks: settings.getUserHooks(),
9176
- projectHooks: settings.getProjectHooks()
9177
- },
9178
- buildDisabledSkillNamesProvider(settings)
10025
+ () => loadCliConfig(
10026
+ settings.merged,
10027
+ {
10028
+ ...this.argv,
10029
+ sessionId: "workspace-mcp-discovery",
10030
+ resume: void 0,
10031
+ continue: false,
10032
+ chatRecording: false
10033
+ },
10034
+ cwd,
10035
+ void 0,
10036
+ {
10037
+ userHooks: settings.getUserHooks(),
10038
+ projectHooks: settings.getProjectHooks()
10039
+ },
10040
+ buildDisabledSkillNamesProvider(settings)
10041
+ )
9179
10042
  );
9180
10043
  config.setMcpTransportPool(this.mcpPool);
9181
10044
  try {
@@ -9215,7 +10078,7 @@ var QwenAgent = class {
9215
10078
  await this.createWorkspaceMcpDiscoveryConfig(settings);
9216
10079
  });
9217
10080
  }
9218
- reloadWorkspaceMcpDiscovery() {
10081
+ reloadWorkspaceMcpDiscovery(options = {}) {
9219
10082
  return this.enqueueWorkspaceMcpDiscovery("reload", async () => {
9220
10083
  const settings = loadSettings(this.config.getTargetDir());
9221
10084
  const discoveryConfig = this.workspaceMcpDiscoveryConfig;
@@ -9261,8 +10124,62 @@ var QwenAgent = class {
9261
10124
  "Failed to synchronize MCP settings with live sessions"
9262
10125
  );
9263
10126
  }
10127
+ if (options.forceReconnectAll === true || options.forceReconnectWhich !== void 0) {
10128
+ await this.forceReconnectWorkspaceMcp(options.forceReconnectWhich);
10129
+ }
9264
10130
  });
9265
10131
  }
10132
+ async forceReconnectWorkspaceMcp(requestedServerNames) {
10133
+ const serverNames = /* @__PURE__ */ new Set();
10134
+ for (const config of [
10135
+ this.workspaceMcpDiscoveryConfig,
10136
+ this.config,
10137
+ ...this.getActiveSessions().map((session) => session.getConfig())
10138
+ ]) {
10139
+ for (const name of Object.keys(config?.getMcpServers() ?? {})) {
10140
+ serverNames.add(name);
10141
+ }
10142
+ }
10143
+ const selectedServerNames = requestedServerNames ? [...new Set(requestedServerNames)].filter(
10144
+ (name) => serverNames.has(name)
10145
+ ) : [...serverNames];
10146
+ const errors = [];
10147
+ for (const serverName of selectedServerNames) {
10148
+ try {
10149
+ const poolHasEntries = (this.mcpPool?.getSnapshot().byName[serverName]?.entryCount ?? 0) > 0;
10150
+ if (this.mcpPool && poolHasEntries) {
10151
+ const results = await this.mcpPool.restartByName(serverName);
10152
+ const failed = results.find((result) => !result.restarted);
10153
+ if (failed) {
10154
+ throw new Error(
10155
+ `MCP server ${JSON.stringify(serverName)} failed to reconnect: ${failed.reason ?? "unknown error"}`
10156
+ );
10157
+ }
10158
+ await Promise.all(
10159
+ this.getLiveMcpConfigs(serverName).map(async (config) => {
10160
+ const geminiClient = config.getGeminiClient?.();
10161
+ if (geminiClient?.isInitialized?.()) {
10162
+ await geminiClient.setTools?.();
10163
+ }
10164
+ })
10165
+ );
10166
+ } else {
10167
+ await this.reconcileMcpServerAcrossLiveConfigs(
10168
+ serverName,
10169
+ "discover"
10170
+ );
10171
+ }
10172
+ } catch (error) {
10173
+ errors.push(error);
10174
+ }
10175
+ }
10176
+ if (errors.length > 0) {
10177
+ throw new AggregateError(
10178
+ errors,
10179
+ "Failed to force reconnect one or more MCP servers"
10180
+ );
10181
+ }
10182
+ }
9266
10183
  /**
9267
10184
  * Drain the workspace MCP transport pool. Called on shutdown so all
9268
10185
  * pool entries get a coordinated SIGTERM before process.exit. No-op
@@ -9283,100 +10200,229 @@ var QwenAgent = class {
9283
10200
  );
9284
10201
  }
9285
10202
  }
9286
- async closeStoredSession(sessionId, opts) {
9287
- for (const [requestId, generation] of this.generationControllers) {
9288
- if (generation.sessionId !== sessionId) continue;
9289
- generation.controller.abort();
9290
- this.generationControllers.delete(requestId);
9291
- }
9292
- const session = this.sessions.get(sessionId);
9293
- if (!session) {
9294
- this.mcpPool?.releaseSession(sessionId);
9295
- return;
10203
+ async removeStoredSessionEntry(sessionId, session, cleanupErrors = [], options = {}) {
10204
+ if (this.sessions.get(sessionId) !== session) return;
10205
+ try {
10206
+ session.dispose();
10207
+ } catch (error) {
10208
+ cleanupErrors.push(error);
9296
10209
  }
9297
- const requireFlush = opts?.requireFlush === true;
9298
- const flushRecording = /* @__PURE__ */ __name(async () => {
10210
+ if (options.shutdownConfig !== false) {
9299
10211
  try {
9300
- await session.getConfig().getChatRecordingService()?.flush();
9301
- return void 0;
9302
- } catch (err) {
9303
- debugLogger7.debug(
9304
- `Session ${sessionId} chat recording flush during close failed: ${err instanceof Error ? err.message : String(err)}`
9305
- );
9306
- return err;
9307
- }
9308
- }, "flushRecording");
9309
- if (requireFlush) {
9310
- const preCancelFlushError = await flushRecording();
9311
- if (preCancelFlushError !== void 0) {
9312
- throw preCancelFlushError;
10212
+ await session.getConfig().shutdown({ shutdownTelemetry: false });
10213
+ } catch (error) {
10214
+ cleanupErrors.push(error);
9313
10215
  }
9314
10216
  }
9315
10217
  try {
9316
- await session.cancelPendingPrompt();
9317
- } catch (err) {
9318
- debugLogger7.debug(
9319
- `Session ${sessionId} cancel during close failed: ${err instanceof Error ? err.message : String(err)}`
9320
- );
10218
+ unregisterGoalHook(session.getConfig(), sessionId);
10219
+ } catch (error) {
10220
+ cleanupErrors.push(error);
9321
10221
  }
9322
- const flushError = await flushRecording();
9323
- if (flushError !== void 0 && requireFlush) {
9324
- throw flushError;
10222
+ try {
10223
+ this.mcpPool?.releaseSession(sessionId);
10224
+ } catch (error) {
10225
+ cleanupErrors.push(error);
9325
10226
  }
9326
10227
  try {
9327
- await session.getConfig().getToolRegistry()?.stop();
9328
- } catch (err) {
9329
- debugLogger7.debug(
9330
- `Session ${sessionId} tool registry stop during close failed: ${err instanceof Error ? err.message : String(err)}`
9331
- );
10228
+ uiTelemetryService.removeSession(sessionId);
10229
+ } catch (error) {
10230
+ cleanupErrors.push(error);
9332
10231
  }
9333
- unregisterGoalHook(session.getConfig(), sessionId);
9334
- this.mcpPool?.releaseSession(sessionId);
9335
- uiTelemetryService.removeSession(sessionId);
9336
10232
  this.sessions.delete(sessionId);
9337
- }
9338
- discardStoredSessionIfCurrent(sessionId, session) {
9339
- if (this.sessions.get(sessionId) !== session) {
9340
- return;
9341
- }
9342
- const logCleanupFailure = /* @__PURE__ */ __name((action, err) => {
9343
- debugLogger7.debug(
9344
- `Session ${sessionId} ${action} during failed restore cleanup failed: ${err instanceof Error ? err.message : String(err)}`
10233
+ if (cleanupErrors.length > 0) {
10234
+ debugLogger7.warn(
10235
+ `Session ${sessionId} closed after ${cleanupErrors.length} cleanup failure(s): ${cleanupErrors.map(
10236
+ (error) => error instanceof Error ? error.message : String(error)
10237
+ ).join("; ")}`
9345
10238
  );
9346
- }, "logCleanupFailure");
10239
+ }
10240
+ }
10241
+ async withLiveSessionRestore(sessionId, session, operation) {
10242
+ await session.assertCanStartTurn();
10243
+ const config = session.getConfig();
10244
+ const releaseGate = session.beginClose();
9347
10245
  try {
9348
- session.dispose();
9349
- } catch (err) {
9350
- logCleanupFailure("dispose", err);
10246
+ await waitForSessionDrain(
10247
+ session.waitForActiveTurnsToSettle(),
10248
+ SESSION_DRAIN_TIMEOUT_MS,
10249
+ "restore"
10250
+ );
10251
+ const recorder = config.getChatRecordingService();
10252
+ const loadAuthoritative = /* @__PURE__ */ __name(() => config.getSessionService().loadSession(sessionId), "loadAuthoritative");
10253
+ const data = recorder ? await recorder.runWithWriteBarrier(loadAuthoritative) : await loadAuthoritative();
10254
+ if (!data) throw new SessionWriterUnavailableError();
10255
+ return await operation(config, data);
10256
+ } catch (error) {
10257
+ throw mapSessionWriterRequestError(error);
10258
+ } finally {
10259
+ releaseGate();
9351
10260
  }
10261
+ }
10262
+ async cleanupUnstoredConfig(config) {
10263
+ const sessionId = config.getSessionId();
10264
+ const cleanupKey = this.pendingConfigCleanupKey(
10265
+ config.getSessionRuntimeBaseDir(),
10266
+ sessionId
10267
+ );
9352
10268
  try {
9353
- unregisterGoalHook(session.getConfig(), sessionId);
9354
- } catch (err) {
9355
- logCleanupFailure("goal hook unregister", err);
10269
+ await shutdownSessionConfig(config);
10270
+ } catch (error) {
10271
+ const pending2 = this.pendingConfigCleanup.get(cleanupKey) ?? /* @__PURE__ */ new Set();
10272
+ pending2.add(config);
10273
+ this.pendingConfigCleanup.set(cleanupKey, pending2);
10274
+ throw mapSessionWriterRequestError(error);
10275
+ }
10276
+ const pending = this.pendingConfigCleanup.get(cleanupKey);
10277
+ pending?.delete(config);
10278
+ if (pending?.size === 0) {
10279
+ this.pendingConfigCleanup.delete(cleanupKey);
9356
10280
  }
10281
+ }
10282
+ async cleanupAfterRequestFailure(error, cleanup) {
9357
10283
  try {
10284
+ await cleanup();
10285
+ } catch (cleanupError) {
10286
+ debugLogger7.warn(
10287
+ `Session cleanup failed while preserving the original request error: ${cleanupError instanceof Error ? cleanupError.message : String(cleanupError)}`
10288
+ );
10289
+ }
10290
+ throw error;
10291
+ }
10292
+ pendingConfigCleanupKey(runtimeBaseDir, sessionId) {
10293
+ return `${path4.resolve(runtimeBaseDir)}\0${sessionId}`;
10294
+ }
10295
+ async retryPendingConfigCleanup(runtimeBaseDir, requiredSessionId) {
10296
+ const resolvedRuntimeBaseDir = path4.resolve(runtimeBaseDir);
10297
+ const configs = /* @__PURE__ */ new Set();
10298
+ for (const pending of this.pendingConfigCleanup.values()) {
10299
+ for (const config of pending) {
10300
+ if (path4.resolve(config.getSessionRuntimeBaseDir()) === resolvedRuntimeBaseDir) {
10301
+ configs.add(config);
10302
+ }
10303
+ }
10304
+ }
10305
+ for (const config of configs) {
10306
+ try {
10307
+ await this.cleanupUnstoredConfig(config);
10308
+ } catch (error) {
10309
+ if (config.getSessionId() === requiredSessionId) throw error;
10310
+ debugLogger7.warn(
10311
+ `Deferred Config cleanup retry failed for session ${config.getSessionId()}: ${error instanceof Error ? error.message : String(error)}`
10312
+ );
10313
+ }
10314
+ }
10315
+ }
10316
+ async closeStoredSession(sessionId, opts) {
10317
+ const session = this.sessions.get(sessionId);
10318
+ if (!session) {
9358
10319
  this.mcpPool?.releaseSession(sessionId);
9359
- } catch (err) {
9360
- logCleanupFailure("MCP pool release", err);
10320
+ return;
10321
+ }
10322
+ const recorder = session.getConfig().getChatRecordingService();
10323
+ const requireFlush = opts?.requireFlush === true;
10324
+ if (requireFlush) {
10325
+ await recorder?.flush();
10326
+ }
10327
+ const drainTimeoutMs = opts?.drainTimeoutMs ?? SESSION_DRAIN_TIMEOUT_MS;
10328
+ const cancelClose = opts?.waitForCloseGate ? await beginSessionCloseAfterCurrentGate(session, drainTimeoutMs) : session.beginClose();
10329
+ for (const [requestId, generation] of this.generationControllers) {
10330
+ if (generation.sessionId !== sessionId) continue;
10331
+ generation.controller.abort();
10332
+ this.generationControllers.delete(requestId);
9361
10333
  }
10334
+ let removedFromStore = false;
9362
10335
  try {
9363
- uiTelemetryService.removeSession(sessionId);
9364
- } catch (err) {
9365
- logCleanupFailure("telemetry removal", err);
10336
+ await waitForSessionDrain(
10337
+ (async () => {
10338
+ try {
10339
+ await session.cancelPendingPrompt();
10340
+ } catch (err) {
10341
+ debugLogger7.debug(
10342
+ `Session ${sessionId} cancel during close failed: ${err instanceof Error ? err.message : String(err)}`
10343
+ );
10344
+ }
10345
+ await session.waitForActiveTurnsToSettle();
10346
+ })(),
10347
+ drainTimeoutMs,
10348
+ "close"
10349
+ );
10350
+ recorder?.finalize();
10351
+ let flushError;
10352
+ try {
10353
+ await recorder?.flush();
10354
+ } catch (error) {
10355
+ flushError = error;
10356
+ }
10357
+ if (flushError !== void 0 && requireFlush) {
10358
+ throw flushError;
10359
+ }
10360
+ let closeError;
10361
+ try {
10362
+ await recorder?.close();
10363
+ } catch (error) {
10364
+ closeError = error;
10365
+ }
10366
+ if (recorder?.hasWriteOwnership()) {
10367
+ throw closeError ?? new SessionWriterUnavailableError();
10368
+ }
10369
+ const cleanupErrors = [];
10370
+ if (flushError !== void 0) cleanupErrors.push(flushError);
10371
+ if (closeError !== void 0) cleanupErrors.push(closeError);
10372
+ await this.removeStoredSessionEntry(sessionId, session, cleanupErrors, {
10373
+ shutdownConfig: opts?.shutdownConfig
10374
+ });
10375
+ removedFromStore = true;
10376
+ } finally {
10377
+ if (!removedFromStore) cancelClose();
9366
10378
  }
9367
- this.sessions.delete(sessionId);
9368
10379
  }
9369
- disposeSessions() {
10380
+ async discardStoredSessionIfCurrent(sessionId, session, opts) {
10381
+ if (this.sessions.get(sessionId) !== session) {
10382
+ return;
10383
+ }
10384
+ await this.closeStoredSession(sessionId, opts);
10385
+ }
10386
+ async disposeSessions() {
9370
10387
  for (const generation of this.generationControllers.values()) {
9371
10388
  generation.controller.abort();
9372
10389
  }
9373
10390
  this.generationControllers.clear();
9374
- for (const session of this.sessions.values()) {
9375
- session.dispose();
9376
- }
9377
- this.sessions.clear();
10391
+ for (const controller of this.workspaceGenerationControllers.values()) {
10392
+ controller.abort();
10393
+ }
10394
+ this.workspaceGenerationControllers.clear();
10395
+ await Promise.allSettled(
10396
+ [...this.sessions.entries()].map(
10397
+ ([sessionId, session]) => this.discardStoredSessionIfCurrent(sessionId, session, {
10398
+ waitForCloseGate: true
10399
+ })
10400
+ )
10401
+ );
10402
+ await Promise.allSettled(
10403
+ [...this.pendingConfigCleanup.values()].flatMap((configs) => [...configs]).map((config) => this.cleanupUnstoredConfig(config))
10404
+ );
9378
10405
  this.disposeTranscriptReplayConfigs();
9379
10406
  }
10407
+ runWithPinnedRuntimeBaseDir(settings, cwd, operation) {
10408
+ return runWithAcpRuntimeOutputDir(settings, cwd, operation);
10409
+ }
10410
+ async assertLiveSessionScope(config, settings, cwd) {
10411
+ if (path4.resolve(config.storage.getProjectRoot()) !== path4.resolve(cwd)) {
10412
+ throw RequestError.invalidParams(
10413
+ void 0,
10414
+ "The live session belongs to another workspace."
10415
+ );
10416
+ }
10417
+ const requestedRuntimeBaseDir = await this.runWithPinnedRuntimeBaseDir(
10418
+ settings,
10419
+ cwd,
10420
+ () => Storage.getRuntimeBaseDir()
10421
+ );
10422
+ if (path4.resolve(config.getSessionRuntimeBaseDir()) !== path4.resolve(requestedRuntimeBaseDir)) {
10423
+ throw mapSessionWriterRequestError(new SessionWriterUnavailableError());
10424
+ }
10425
+ }
9380
10426
  /** Expose the pool's workspace-scoped budget controller for snapshot builders. */
9381
10427
  getWorkspaceMcpBudget() {
9382
10428
  return this.workspaceMcpBudget;
@@ -9404,9 +10450,34 @@ var QwenAgent = class {
9404
10450
  }
9405
10451
  async initialize(args) {
9406
10452
  markAcpStartup("initializeHandlerStart");
10453
+ if (this.privateParentState === "rejected") {
10454
+ throw RequestError.invalidParams(
10455
+ void 0,
10456
+ "Invalid private ACP parent capability"
10457
+ );
10458
+ }
10459
+ if (this.privateParentState === "uninitialized") {
10460
+ const expectedCapability = this.expectedPrivateParentCapability;
10461
+ if (expectedCapability === void 0) {
10462
+ this.privateParentState = "untrusted";
10463
+ } else {
10464
+ const suppliedCapability = args._meta?.[PRIVATE_PARENT_CAPABILITY_META_KEY];
10465
+ const suppliedBuffer = typeof suppliedCapability === "string" ? Buffer.from(suppliedCapability) : void 0;
10466
+ const expectedBuffer = Buffer.from(expectedCapability);
10467
+ if (suppliedBuffer !== void 0 && suppliedBuffer.length === expectedBuffer.length && timingSafeEqual(suppliedBuffer, expectedBuffer)) {
10468
+ this.privateParentState = "trusted";
10469
+ } else {
10470
+ this.privateParentState = "rejected";
10471
+ throw RequestError.invalidParams(
10472
+ void 0,
10473
+ "Invalid private ACP parent capability"
10474
+ );
10475
+ }
10476
+ }
10477
+ }
9407
10478
  this.clientCapabilities = args.clientCapabilities;
9408
10479
  const authMethods = buildAuthMethods();
9409
- const version = "0.20.0";
10480
+ const version = "0.20.1-nightly.20260724.7d17c44a3";
9410
10481
  const response = {
9411
10482
  protocolVersion: PROTOCOL_VERSION,
9412
10483
  agentInfo: {
@@ -9495,15 +10566,24 @@ var QwenAgent = class {
9495
10566
  "config_setup",
9496
10567
  () => this.newSessionConfig(cwd, mcpServers, settings)
9497
10568
  );
9498
- await profiler.time("auth", () => this.ensureAuthenticated(config));
9499
- profiler.timeSync(
9500
- "file_system_setup",
9501
- () => this.setupFileSystem(config)
9502
- );
9503
- const session = await profiler.time(
9504
- "session_register",
9505
- () => this.createAndStoreSession(config, settings)
9506
- );
10569
+ let session;
10570
+ try {
10571
+ await profiler.time("auth", () => this.ensureAuthenticated(config));
10572
+ profiler.timeSync(
10573
+ "file_system_setup",
10574
+ () => this.setupFileSystem(config)
10575
+ );
10576
+ session = await profiler.time(
10577
+ "session_register",
10578
+ () => this.createAndStoreSession(config, settings)
10579
+ );
10580
+ } catch (error) {
10581
+ return this.cleanupAfterRequestFailure(error, async () => {
10582
+ if (this.sessions.get(config.getSessionId())?.getConfig() !== config) {
10583
+ await this.cleanupUnstoredConfig(config);
10584
+ }
10585
+ });
10586
+ }
9507
10587
  profiler.setSessionId(session.getId());
9508
10588
  return profiler.timeSync("response_build", () => ({
9509
10589
  sessionId: session.getId(),
@@ -9517,7 +10597,56 @@ var QwenAgent = class {
9517
10597
  }
9518
10598
  async loadSession(params) {
9519
10599
  const settings = loadSettingsCached(params.cwd);
9520
- const exists = await runWithAcpRuntimeOutputDir(
10600
+ const liveSession = this.sessions.get(params.sessionId);
10601
+ if (liveSession) {
10602
+ const liveConfig = liveSession.getConfig();
10603
+ await this.assertLiveSessionScope(liveConfig, settings, params.cwd);
10604
+ return this.withLiveSessionRestore(
10605
+ params.sessionId,
10606
+ liveSession,
10607
+ async (config2, sessionData2) => {
10608
+ const response2 = {
10609
+ modes: this.buildModesData(config2),
10610
+ models: this.buildAvailableModels(config2),
10611
+ configOptions: this.buildConfigOptions(config2),
10612
+ ...sessionData2.artifactSnapshot ? { artifactSnapshot: sessionData2.artifactSnapshot } : {}
10613
+ };
10614
+ const records = sessionData2.conversation.messages;
10615
+ if (records.length === 0) return response2;
10616
+ const bulkReplay2 = isBulkLoadReplayRequest(params);
10617
+ const replayPage = bulkReplay2 ? selectRecentHistoryRecords(records, getLoadReplayPageSize(params)) : { records, hasMore: false };
10618
+ const replay = await collectHistoryReplayUpdates({
10619
+ sessionId: params.sessionId,
10620
+ config: config2,
10621
+ records: replayPage.records,
10622
+ gaps: sessionData2.historyGaps,
10623
+ cumulativeUsage: createReplayCumulativeUsage(),
10624
+ logger: debugLogger7
10625
+ });
10626
+ if (!bulkReplay2) {
10627
+ for (const update of replay.updates) {
10628
+ await liveSession.sendUpdate(update);
10629
+ }
10630
+ if (replay.replayError !== void 0) {
10631
+ throw RequestError.internalError(void 0, replay.replayError);
10632
+ }
10633
+ return response2;
10634
+ }
10635
+ return {
10636
+ ...response2,
10637
+ _meta: {
10638
+ [LOAD_REPLAY_META_KEY]: {
10639
+ v: LOAD_REPLAY_VERSION,
10640
+ updates: replay.updates,
10641
+ ...replay.replayError !== void 0 ? { partial: true, replayError: replay.replayError } : {},
10642
+ ...replayPage.hasMore ? { hasMore: true } : {}
10643
+ }
10644
+ }
10645
+ };
10646
+ }
10647
+ );
10648
+ }
10649
+ const exists = await this.runWithPinnedRuntimeBaseDir(
9521
10650
  settings,
9522
10651
  params.cwd,
9523
10652
  async () => {
@@ -9540,17 +10669,26 @@ var QwenAgent = class {
9540
10669
  params.sessionId,
9541
10670
  true
9542
10671
  );
9543
- await this.ensureAuthenticated(config);
9544
- this.setupFileSystem(config);
9545
10672
  const sessionData = config.getResumedSessionData();
9546
10673
  const bulkReplay = isBulkLoadReplayRequest(params);
9547
10674
  const replayPageSize = bulkReplay ? getLoadReplayPageSize(params) : void 0;
9548
- const session = await this.createAndStoreSession(
9549
- config,
9550
- settings,
9551
- sessionData,
9552
- bulkReplay ? { replayHistory: false, startPostReplayServices: false } : {}
9553
- );
10675
+ let session;
10676
+ try {
10677
+ await this.ensureAuthenticated(config);
10678
+ this.setupFileSystem(config);
10679
+ session = await this.createAndStoreSession(
10680
+ config,
10681
+ settings,
10682
+ sessionData,
10683
+ bulkReplay ? { replayHistory: false, startPostReplayServices: false } : {}
10684
+ );
10685
+ } catch (error) {
10686
+ return this.cleanupAfterRequestFailure(error, async () => {
10687
+ if (this.sessions.get(config.getSessionId())?.getConfig() !== config) {
10688
+ await this.cleanupUnstoredConfig(config);
10689
+ }
10690
+ });
10691
+ }
9554
10692
  let replayEnvelope;
9555
10693
  if (bulkReplay) {
9556
10694
  try {
@@ -9597,11 +10735,25 @@ var QwenAgent = class {
9597
10735
  session.installRewriter();
9598
10736
  session.startCronScheduler();
9599
10737
  } catch (err) {
9600
- this.discardStoredSessionIfCurrent(params.sessionId, session);
9601
- throw err;
10738
+ return this.cleanupAfterRequestFailure(err, async () => {
10739
+ try {
10740
+ await this.discardStoredSessionIfCurrent(params.sessionId, session);
10741
+ } catch (cleanupError) {
10742
+ await this.removeStoredSessionEntry(
10743
+ params.sessionId,
10744
+ session,
10745
+ [cleanupError],
10746
+ {
10747
+ shutdownConfig: false
10748
+ }
10749
+ );
10750
+ await this.cleanupUnstoredConfig(config);
10751
+ }
10752
+ });
9602
10753
  }
9603
10754
  }
9604
10755
  await this.#restoreWorktreeOnResume(config, session);
10756
+ await this.#restoreBackgroundAgentsOnResume(config, session);
9605
10757
  this.#restoreGoalOnResume(config, session);
9606
10758
  const modesData = this.buildModesData(config);
9607
10759
  const availableModels = this.buildAvailableModels(config);
@@ -9624,7 +10776,22 @@ var QwenAgent = class {
9624
10776
  }
9625
10777
  async unstable_resumeSession(params) {
9626
10778
  const settings = loadSettingsCached(params.cwd);
9627
- const exists = await runWithAcpRuntimeOutputDir(
10779
+ const liveSession = this.sessions.get(params.sessionId);
10780
+ if (liveSession) {
10781
+ const liveConfig = liveSession.getConfig();
10782
+ await this.assertLiveSessionScope(liveConfig, settings, params.cwd);
10783
+ return this.withLiveSessionRestore(
10784
+ params.sessionId,
10785
+ liveSession,
10786
+ async (config2, sessionData2) => ({
10787
+ modes: this.buildModesData(config2),
10788
+ models: this.buildAvailableModels(config2),
10789
+ configOptions: this.buildConfigOptions(config2),
10790
+ ...sessionData2.artifactSnapshot ? { artifactSnapshot: sessionData2.artifactSnapshot } : {}
10791
+ })
10792
+ );
10793
+ }
10794
+ const exists = await this.runWithPinnedRuntimeBaseDir(
9628
10795
  settings,
9629
10796
  params.cwd,
9630
10797
  async () => {
@@ -9643,15 +10810,25 @@ var QwenAgent = class {
9643
10810
  params.sessionId,
9644
10811
  true
9645
10812
  );
9646
- await this.ensureAuthenticated(config);
9647
- this.setupFileSystem(config);
9648
- const session = await this.createAndStoreSession(
9649
- config,
9650
- settings,
9651
- config.getResumedSessionData(),
9652
- { replayHistory: false }
9653
- );
10813
+ let session;
10814
+ try {
10815
+ await this.ensureAuthenticated(config);
10816
+ this.setupFileSystem(config);
10817
+ session = await this.createAndStoreSession(
10818
+ config,
10819
+ settings,
10820
+ config.getResumedSessionData(),
10821
+ { replayHistory: false }
10822
+ );
10823
+ } catch (error) {
10824
+ return this.cleanupAfterRequestFailure(error, async () => {
10825
+ if (this.sessions.get(config.getSessionId())?.getConfig() !== config) {
10826
+ await this.cleanupUnstoredConfig(config);
10827
+ }
10828
+ });
10829
+ }
9654
10830
  await this.#restoreWorktreeOnResume(config, session);
10831
+ await this.#restoreBackgroundAgentsOnResume(config, session);
9655
10832
  this.#restoreGoalOnResume(config, session);
9656
10833
  const modesData = this.buildModesData(config);
9657
10834
  const availableModels = this.buildAvailableModels(config);
@@ -9681,6 +10858,10 @@ var QwenAgent = class {
9681
10858
  debugLogger7.warn(`ACP worktree restore failed: ${error}`);
9682
10859
  }
9683
10860
  }
10861
+ async #restoreBackgroundAgentsOnResume(config, session) {
10862
+ await config.loadPausedBackgroundAgents(config.getSessionId());
10863
+ session.pendingRecoveredAgentsNotice = config.consumePendingRecoveredAgentsNotice();
10864
+ }
9684
10865
  /**
9685
10866
  * Re-registers the `/goal` Stop hook when a resumed transcript ends on an
9686
10867
  * unsatisfied goal — the daemon counterpart of the TUI's resume restore.
@@ -9814,7 +10995,50 @@ var QwenAgent = class {
9814
10995
  if (!session) {
9815
10996
  throw new Error(`Session not found: ${params.sessionId}`);
9816
10997
  }
9817
- return session.prompt(params);
10998
+ const sanitizedParams = { ...params };
10999
+ const meta = params._meta && typeof params._meta === "object" ? { ...params._meta } : {};
11000
+ const suppliedContext = meta[INVOCATION_CONTEXT_META_KEY];
11001
+ delete meta[INVOCATION_CONTEXT_META_KEY];
11002
+ delete meta[PRIVATE_PARENT_CAPABILITY_META_KEY];
11003
+ if (Object.keys(meta).length > 0) {
11004
+ sanitizedParams._meta = meta;
11005
+ } else {
11006
+ delete sanitizedParams._meta;
11007
+ }
11008
+ const invocationContext = this.privateParentState === "trusted" && suppliedContext !== void 0 ? parseInvocationContext(suppliedContext) : void 0;
11009
+ if (this.privateParentState === "trusted" && suppliedContext !== void 0 && invocationContext === void 0) {
11010
+ throw RequestError.invalidParams(
11011
+ void 0,
11012
+ "Invalid trusted ACP invocation context"
11013
+ );
11014
+ }
11015
+ let settleCall = /* @__PURE__ */ __name(() => {
11016
+ }, "settleCall");
11017
+ const call = {
11018
+ controller: new AbortController(),
11019
+ settled: new Promise((resolve5) => {
11020
+ settleCall = resolve5;
11021
+ })
11022
+ };
11023
+ let calls = this.activePromptCalls.get(params.sessionId);
11024
+ if (!calls) {
11025
+ calls = /* @__PURE__ */ new Set();
11026
+ this.activePromptCalls.set(params.sessionId, calls);
11027
+ }
11028
+ calls.add(call);
11029
+ try {
11030
+ return await session.prompt(
11031
+ sanitizedParams,
11032
+ invocationContext,
11033
+ call.controller.signal
11034
+ );
11035
+ } finally {
11036
+ calls.delete(call);
11037
+ if (calls.size === 0) {
11038
+ this.activePromptCalls.delete(params.sessionId);
11039
+ }
11040
+ settleCall();
11041
+ }
9818
11042
  }
9819
11043
  async cancel(params) {
9820
11044
  const session = this.sessions.get(params.sessionId);
@@ -11564,10 +12788,48 @@ var QwenAgent = class {
11564
12788
  };
11565
12789
  }
11566
12790
  async extMethod(method, params) {
12791
+ try {
12792
+ return await this.extMethodInternal(method, params);
12793
+ } catch (error) {
12794
+ const writerError = getSessionWriterError(error);
12795
+ if (writerError) {
12796
+ throw new RequestError(writerError.rpcCode, writerError.message, {
12797
+ errorKind: writerError.errorKind
12798
+ });
12799
+ }
12800
+ throw error;
12801
+ }
12802
+ }
12803
+ async extMethodInternal(method, params) {
11567
12804
  const requestedCwd = typeof params["cwd"] === "string" ? params["cwd"] : void 0;
11568
12805
  const cwd = requestedCwd || process.cwd();
11569
12806
  const SESSION_ID_RE = /^[0-9a-fA-F-]{32,36}$/;
11570
12807
  switch (method) {
12808
+ case PROMPT_CANCEL_METHOD: {
12809
+ const sessionId = params["sessionId"];
12810
+ if (typeof sessionId !== "string" || sessionId.length === 0) {
12811
+ throw RequestError.invalidParams(
12812
+ void 0,
12813
+ "Invalid or missing sessionId"
12814
+ );
12815
+ }
12816
+ const session = this.sessions.get(sessionId);
12817
+ if (!session) {
12818
+ throw RequestError.invalidParams(
12819
+ void 0,
12820
+ `Session not found for id: ${sessionId}`
12821
+ );
12822
+ }
12823
+ const targetedCalls = new Set(
12824
+ this.activePromptCalls.get(sessionId) ?? []
12825
+ );
12826
+ if (targetedCalls.size === 0) {
12827
+ return { cancelled: false };
12828
+ }
12829
+ targetedCalls.forEach((call) => call.controller.abort());
12830
+ await Promise.all(Array.from(targetedCalls, (call) => call.settled));
12831
+ return { cancelled: true };
12832
+ }
11571
12833
  case TODO_STOP_GUARD_QUEUE_RELEASE_METHOD: {
11572
12834
  const sessionId = params["sessionId"];
11573
12835
  if (typeof sessionId !== "string" || sessionId.length === 0) {
@@ -11837,6 +13099,25 @@ var QwenAgent = class {
11837
13099
  "Transcript cursor and record boundary are mutually exclusive"
11838
13100
  );
11839
13101
  }
13102
+ const rawDirection = params["direction"];
13103
+ if (rawDirection !== void 0 && rawDirection !== "backward") {
13104
+ throw RequestError.invalidParams(
13105
+ void 0,
13106
+ "Invalid transcript direction"
13107
+ );
13108
+ }
13109
+ if (rawCursor !== void 0 && rawDirection !== void 0) {
13110
+ throw RequestError.invalidParams(
13111
+ void 0,
13112
+ "Transcript cursor and direction are mutually exclusive"
13113
+ );
13114
+ }
13115
+ if (rawBeforeRecordId !== void 0 && rawDirection !== void 0) {
13116
+ throw RequestError.invalidParams(
13117
+ void 0,
13118
+ "Transcript record boundary and direction are mutually exclusive"
13119
+ );
13120
+ }
11840
13121
  const rawLimit = params["limit"];
11841
13122
  if (rawLimit !== void 0 && (!Number.isSafeInteger(rawLimit) || rawLimit < 1 || rawLimit > SESSION_TRANSCRIPT_MAX_LIMIT)) {
11842
13123
  throw RequestError.invalidParams(
@@ -11847,10 +13128,14 @@ var QwenAgent = class {
11847
13128
  try {
11848
13129
  const settings = loadSettingsCached(cwd);
11849
13130
  return await runWithAcpRuntimeOutputDir(settings, cwd, async () => {
13131
+ if (rawDirection === "backward") {
13132
+ await this.sessions.get(sessionId)?.getConfig().getChatRecordingService()?.flush();
13133
+ }
11850
13134
  const reader = new SessionTranscriptReader(cwd);
11851
13135
  const page = await reader.readPage(sessionId, {
11852
13136
  ...typeof rawCursor === "string" ? { cursor: rawCursor } : {},
11853
13137
  ...typeof rawBeforeRecordId === "string" ? { beforeRecordId: rawBeforeRecordId } : {},
13138
+ ...rawDirection === "backward" ? { direction: rawDirection } : {},
11854
13139
  ...typeof rawLimit === "number" ? { limit: rawLimit } : {},
11855
13140
  maxBytes: SESSION_TRANSCRIPT_MAX_PAGE_BYTES
11856
13141
  });
@@ -12396,8 +13681,34 @@ var QwenAgent = class {
12396
13681
  }
12397
13682
  case SERVE_CONTROL_EXT_METHODS.workspaceMcpInitialize:
12398
13683
  return this.initializeWorkspaceMcpDiscovery();
12399
- case SERVE_CONTROL_EXT_METHODS.workspaceMcpReload:
12400
- return this.reloadWorkspaceMcpDiscovery();
13684
+ case SERVE_CONTROL_EXT_METHODS.workspaceMcpReload: {
13685
+ const forceReconnectAll = params["forceReconnectAll"];
13686
+ const forceReconnectWhich = params["forceReconnectWhich"];
13687
+ if (forceReconnectAll !== void 0 && typeof forceReconnectAll !== "boolean") {
13688
+ throw RequestError.invalidParams(
13689
+ void 0,
13690
+ "forceReconnectAll must be a boolean"
13691
+ );
13692
+ }
13693
+ if (forceReconnectWhich !== void 0 && (!Array.isArray(forceReconnectWhich) || forceReconnectWhich.some(
13694
+ (serverName) => typeof serverName !== "string" || serverName.length === 0
13695
+ ))) {
13696
+ throw RequestError.invalidParams(
13697
+ void 0,
13698
+ "forceReconnectWhich must be an array of server names"
13699
+ );
13700
+ }
13701
+ if (forceReconnectAll === true && forceReconnectWhich !== void 0) {
13702
+ throw RequestError.invalidParams(
13703
+ void 0,
13704
+ "forceReconnectAll and forceReconnectWhich cannot be used together"
13705
+ );
13706
+ }
13707
+ return this.reloadWorkspaceMcpDiscovery({
13708
+ forceReconnectAll: forceReconnectAll === true,
13709
+ forceReconnectWhich
13710
+ });
13711
+ }
12401
13712
  case SERVE_CONTROL_EXT_METHODS.workspaceMcpManage: {
12402
13713
  const serverName = params["serverName"];
12403
13714
  const action = params["action"];
@@ -12649,6 +13960,52 @@ var QwenAgent = class {
12649
13960
  authUrl
12650
13961
  };
12651
13962
  }
13963
+ case SERVE_CONTROL_EXT_METHODS.workspaceGenerationStart: {
13964
+ const requestId = params["requestId"];
13965
+ const prompt = params["prompt"];
13966
+ if (typeof requestId !== "string" || requestId.length === 0) {
13967
+ throw RequestError.invalidParams(
13968
+ void 0,
13969
+ "Invalid or missing requestId"
13970
+ );
13971
+ }
13972
+ if (typeof prompt !== "string" || !prompt.trim() || Buffer.byteLength(prompt, "utf8") > GENERATION_MAX_PROMPT_BYTES || params["purpose"] !== "text") {
13973
+ throw RequestError.invalidParams(
13974
+ void 0,
13975
+ "Invalid workspace generation request"
13976
+ );
13977
+ }
13978
+ if (this.workspaceGenerationControllers.has(requestId)) {
13979
+ throw RequestError.invalidParams(
13980
+ void 0,
13981
+ "Duplicate workspace generation requestId"
13982
+ );
13983
+ }
13984
+ const controller = new AbortController();
13985
+ this.workspaceGenerationControllers.set(requestId, controller);
13986
+ const signal = AbortSignal.any([
13987
+ controller.signal,
13988
+ AbortSignal.timeout(GENERATION_TIMEOUT_MS)
13989
+ ]);
13990
+ try {
13991
+ const emit = /* @__PURE__ */ __name(async (event) => {
13992
+ await this.connection.extNotification(
13993
+ "qwen/notify/workspace/generation/event",
13994
+ { v: 1, requestId, event }
13995
+ );
13996
+ }, "emit");
13997
+ const result = await executeGeneration(
13998
+ this.config,
13999
+ requestId,
14000
+ prompt.trim(),
14001
+ signal,
14002
+ emit
14003
+ );
14004
+ return { requestId, ...result };
14005
+ } finally {
14006
+ this.workspaceGenerationControllers.delete(requestId);
14007
+ }
14008
+ }
12652
14009
  case SERVE_CONTROL_EXT_METHODS.workspaceAgentGenerate: {
12653
14010
  const description = params["description"];
12654
14011
  if (typeof description !== "string" || !description.trim() || description.length > 4096) {
@@ -12663,6 +14020,22 @@ var QwenAgent = class {
12663
14020
  AbortSignal.timeout(5 * 6e4)
12664
14021
  );
12665
14022
  }
14023
+ case SERVE_CONTROL_EXT_METHODS.workspaceGenerationCancel: {
14024
+ const requestId = params["requestId"];
14025
+ if (typeof requestId !== "string" || requestId.length === 0) {
14026
+ throw RequestError.invalidParams(
14027
+ void 0,
14028
+ "Invalid or missing requestId"
14029
+ );
14030
+ }
14031
+ const controller = this.workspaceGenerationControllers.get(requestId);
14032
+ const cancelled = controller !== void 0;
14033
+ if (cancelled) {
14034
+ controller.abort();
14035
+ this.workspaceGenerationControllers.delete(requestId);
14036
+ }
14037
+ return { requestId, cancelled };
14038
+ }
12666
14039
  case SERVE_CONTROL_EXT_METHODS.sessionArtifactsPersist: {
12667
14040
  const sessionId = params["sessionId"];
12668
14041
  if (typeof sessionId !== "string" || sessionId.length === 0) {
@@ -12704,6 +14077,34 @@ var QwenAgent = class {
12704
14077
  }
12705
14078
  return { sessionId, persisted: true, kind };
12706
14079
  }
14080
+ case "qwen/session/recordTextElements": {
14081
+ const sessionId = params["sessionId"];
14082
+ const content = params["content"];
14083
+ const textElements = params["textElements"];
14084
+ if (typeof sessionId !== "string" || sessionId.length === 0) {
14085
+ throw RequestError.invalidParams(
14086
+ void 0,
14087
+ "Invalid or missing sessionId"
14088
+ );
14089
+ }
14090
+ if (typeof content !== "string" || !Array.isArray(textElements)) {
14091
+ throw RequestError.invalidParams(
14092
+ void 0,
14093
+ "Invalid user text elements payload"
14094
+ );
14095
+ }
14096
+ const session = this.sessionOrThrow(sessionId);
14097
+ await session.assertCanStartTurn();
14098
+ const recording = session.getConfig().getChatRecordingService();
14099
+ if (!recording) {
14100
+ throw RequestError.internalError(
14101
+ void 0,
14102
+ "Chat recording service unavailable"
14103
+ );
14104
+ }
14105
+ await recording.recordUserTextElements({ content, textElements });
14106
+ return { sessionId, persisted: true };
14107
+ }
12707
14108
  case SERVE_CONTROL_EXT_METHODS.sessionTitle: {
12708
14109
  const sessionId = params["sessionId"];
12709
14110
  const displayName = params["displayName"];
@@ -12799,8 +14200,16 @@ var QwenAgent = class {
12799
14200
  "Invalid or missing sessionId"
12800
14201
  );
12801
14202
  }
14203
+ const rawDrainTimeoutMs = params["drainTimeoutMs"];
14204
+ if (rawDrainTimeoutMs !== void 0 && (typeof rawDrainTimeoutMs !== "number" || !Number.isSafeInteger(rawDrainTimeoutMs) || rawDrainTimeoutMs < 1 || rawDrainTimeoutMs > 2147483647)) {
14205
+ throw RequestError.invalidParams(
14206
+ void 0,
14207
+ "Invalid session close drain timeout"
14208
+ );
14209
+ }
12802
14210
  await this.closeStoredSession(sessionId, {
12803
- requireFlush: params["requireFlush"] === true
14211
+ requireFlush: params["requireFlush"] === true,
14212
+ ...typeof rawDrainTimeoutMs === "number" ? { drainTimeoutMs: rawDrainTimeoutMs } : {}
12804
14213
  });
12805
14214
  return { sessionId, closed: true };
12806
14215
  }
@@ -12842,6 +14251,21 @@ var QwenAgent = class {
12842
14251
  });
12843
14252
  }
12844
14253
  const canonicalPath = await fs2.realpath(targetPath);
14254
+ const allowedRoots = params["allowedRoots"];
14255
+ if (Array.isArray(allowedRoots) && allowedRoots.length > 0) {
14256
+ const contained = allowedRoots.some((root) => {
14257
+ if (typeof root !== "string") return false;
14258
+ const rel = path4.relative(root, canonicalPath);
14259
+ return !rel.startsWith("..") && !path4.isAbsolute(rel);
14260
+ });
14261
+ if (!contained) {
14262
+ throw new RequestError(
14263
+ -32004,
14264
+ `Path outside allowed roots: ${canonicalPath}`,
14265
+ { errorKind: "containment_violation", path: canonicalPath }
14266
+ );
14267
+ }
14268
+ }
12845
14269
  const previousCwd = config.getTargetDir();
12846
14270
  if (canonicalPath === previousCwd) {
12847
14271
  return { previousCwd, newCwd: canonicalPath, warnings: [] };
@@ -13723,16 +15147,11 @@ ${outputText}
13723
15147
  let artifactSnapshot;
13724
15148
  let artifactSnapshotUnavailable;
13725
15149
  try {
13726
- await session.getConfig().getChatRecordingService()?.flush();
13727
- const cwd2 = session.getConfig().getProjectRoot();
13728
- const sessionData = await runWithAcpRuntimeOutputDir(
13729
- this.settings,
13730
- cwd2,
13731
- async () => {
13732
- const sessionService = new SessionService(cwd2);
13733
- return sessionService.loadSession(sessionId);
13734
- }
13735
- );
15150
+ const config = session.getConfig();
15151
+ const recording = config.getChatRecordingService();
15152
+ await recording?.flush();
15153
+ const loadAuthoritative = /* @__PURE__ */ __name(() => config.getSessionService().loadSession(sessionId), "loadAuthoritative");
15154
+ const sessionData = recording ? await recording.runWithWriteBarrier(loadAuthoritative) : await loadAuthoritative();
13736
15155
  if (sessionData === void 0) {
13737
15156
  artifactSnapshotUnavailable = "session data unavailable after rewind";
13738
15157
  } else if (sessionData.artifactSnapshot) {
@@ -13773,20 +15192,37 @@ ${outputText}
13773
15192
  "Invalid or missing sessionId"
13774
15193
  );
13775
15194
  }
13776
- const sessionData = await runWithAcpRuntimeOutputDir(
13777
- this.settings,
13778
- cwd,
13779
- async () => {
13780
- const sessionService = new SessionService(cwd);
13781
- return sessionService.loadSession(sessionId);
13782
- }
13783
- );
15195
+ const liveSession = this.sessions.get(sessionId);
15196
+ let replayConfig = this.config;
15197
+ let sessionData;
15198
+ if (liveSession) {
15199
+ const config = liveSession.getConfig();
15200
+ await this.assertLiveSessionScope(
15201
+ config,
15202
+ loadSettingsCached(cwd),
15203
+ cwd
15204
+ );
15205
+ const recording = config.getChatRecordingService();
15206
+ const loadAuthoritative = /* @__PURE__ */ __name(() => config.getSessionService().loadSession(sessionId), "loadAuthoritative");
15207
+ sessionData = recording ? await recording.runWithWriteBarrier(loadAuthoritative) : await loadAuthoritative();
15208
+ replayConfig = config;
15209
+ } else {
15210
+ const settings = loadSettingsCached(cwd);
15211
+ sessionData = await this.runWithPinnedRuntimeBaseDir(
15212
+ settings,
15213
+ cwd,
15214
+ async () => {
15215
+ const sessionService = new SessionService(cwd);
15216
+ return sessionService.loadSession(sessionId);
15217
+ }
15218
+ );
15219
+ }
13784
15220
  if (!sessionData?.conversation) {
13785
15221
  return { updates: [] };
13786
15222
  }
13787
15223
  const replay = await collectHistoryReplayUpdates({
13788
15224
  sessionId,
13789
- config: this.config,
15225
+ config: replayConfig,
13790
15226
  records: sessionData.conversation.messages,
13791
15227
  gaps: sessionData.historyGaps,
13792
15228
  cumulativeUsage: createReplayCumulativeUsage(),
@@ -13854,56 +15290,51 @@ ${outputText}
13854
15290
  sessionId
13855
15291
  });
13856
15292
  }
13857
- const recording = sourceSession.getConfig().getChatRecordingService();
15293
+ const sourceConfig = sourceSession.getConfig();
15294
+ const recording = sourceConfig.getChatRecordingService();
13858
15295
  if (recording) {
13859
15296
  await recording.flush();
13860
15297
  }
13861
- const newSessionId = randomUUID();
13862
- return await runWithAcpRuntimeOutputDir(
13863
- this.settings,
13864
- cwd,
13865
- async () => {
13866
- const sessionService = new SessionService(cwd);
13867
- await sessionService.forkSession(sessionId, newSessionId);
13868
- let title;
13869
- try {
13870
- let baseName;
13871
- if (typeof name === "string" && name.trim().length > 0) {
13872
- baseName = name.trim();
13873
- } else {
13874
- const existingTitle = recording?.getCurrentCustomTitle();
13875
- const stripped = existingTitle?.replace(/\s*\(Branch(?:\s+\d+)?\)\s*$/, "").trim();
13876
- if (stripped && stripped.length > 0) {
13877
- baseName = stripped;
13878
- } else {
13879
- baseName = sessionId.slice(0, 8);
13880
- }
13881
- }
13882
- title = await computeUniqueBranchTitle(baseName, sessionService);
13883
- const renamed = await sessionService.renameSession(
13884
- newSessionId,
13885
- title,
13886
- "manual"
13887
- );
13888
- if (!renamed) {
13889
- throw new RequestError(
13890
- -32603,
13891
- `Failed to set title on forked session ${newSessionId}`,
13892
- { errorKind: "internal", sessionId: newSessionId }
13893
- );
13894
- }
13895
- } catch (err) {
13896
- sessionService.removeSession(newSessionId).catch((rmErr) => {
13897
- process.stderr.write(
13898
- `qwen serve: failed to clean up orphan session ${newSessionId}: ${rmErr instanceof Error ? rmErr.message : rmErr}
13899
- `
13900
- );
13901
- });
13902
- throw err;
15298
+ const newSessionId = randomUUID2();
15299
+ const sessionService = sourceConfig.getSessionService();
15300
+ await sessionService.forkSession(sessionId, newSessionId);
15301
+ let title;
15302
+ try {
15303
+ let baseName;
15304
+ if (typeof name === "string" && name.trim().length > 0) {
15305
+ baseName = name.trim();
15306
+ } else {
15307
+ const existingTitle = recording?.getCurrentCustomTitle();
15308
+ const stripped = existingTitle?.replace(/\s*\(Branch(?:\s+\d+)?\)\s*$/, "").trim();
15309
+ if (stripped && stripped.length > 0) {
15310
+ baseName = stripped;
15311
+ } else {
15312
+ baseName = sessionId.slice(0, 8);
13903
15313
  }
13904
- return { newSessionId, title, displayName: title };
13905
15314
  }
13906
- );
15315
+ title = await computeUniqueBranchTitle(baseName, sessionService);
15316
+ const renamed = await sessionService.renameSession(
15317
+ newSessionId,
15318
+ title,
15319
+ "manual"
15320
+ );
15321
+ if (!renamed) {
15322
+ throw new RequestError(
15323
+ -32603,
15324
+ `Failed to set title on forked session ${newSessionId}`,
15325
+ { errorKind: "internal", sessionId: newSessionId }
15326
+ );
15327
+ }
15328
+ } catch (err) {
15329
+ sessionService.removeSession(newSessionId).catch((rmErr) => {
15330
+ process.stderr.write(
15331
+ `qwen serve: failed to clean up orphan session ${newSessionId}: ${rmErr instanceof Error ? rmErr.message : rmErr}
15332
+ `
15333
+ );
15334
+ });
15335
+ throw err;
15336
+ }
15337
+ return { newSessionId, title, displayName: title };
13907
15338
  }
13908
15339
  case "qwen/settings/getCore": {
13909
15340
  const settings = loadSettings(cwd);
@@ -14292,17 +15723,25 @@ ${outputText}
14292
15723
  this.disposeTranscriptReplayConfig(cached.config);
14293
15724
  }
14294
15725
  const entry = { settings };
14295
- const pending = this.newSessionConfig(cwd, [], settings, void 0, false, {
14296
- skipMcpDiscovery: true,
14297
- skipHooks: true,
14298
- skipSkillManager: true,
14299
- skipFileCheckpointing: true,
14300
- // Read-only replay: tolerate tools that cannot construct without the
14301
- // subsystems skipped above (e.g. SkillTool needs the SkillManager). The
14302
- // registry is only consulted for optional tool_call metadata during
14303
- // replay, and ToolCallEmitter falls back to the recorded tool name.
14304
- lenientToolWarmup: true
14305
- });
15726
+ const pending = this.newSessionConfig(
15727
+ cwd,
15728
+ [],
15729
+ settings,
15730
+ void 0,
15731
+ false,
15732
+ {
15733
+ skipMcpDiscovery: true,
15734
+ skipHooks: true,
15735
+ skipSkillManager: true,
15736
+ skipFileCheckpointing: true,
15737
+ // Read-only replay: tolerate tools that cannot construct without the
15738
+ // subsystems skipped above (e.g. SkillTool needs the SkillManager). The
15739
+ // registry is only consulted for optional tool_call metadata during
15740
+ // replay, and ToolCallEmitter falls back to the recorded tool name.
15741
+ lenientToolWarmup: true
15742
+ },
15743
+ false
15744
+ );
14306
15745
  entry.pending = pending;
14307
15746
  this.transcriptReplayConfigCache.set(key, entry);
14308
15747
  try {
@@ -14330,7 +15769,34 @@ ${outputText}
14330
15769
  throw error;
14331
15770
  }
14332
15771
  }
14333
- async newSessionConfig(cwd, mcpServers, settings, sessionId, resume, initializeOptions = {}) {
15772
+ async newSessionConfig(cwd, mcpServers, settings, sessionId, resume, initializeOptions = {}, chatRecording) {
15773
+ try {
15774
+ return await this.runWithPinnedRuntimeBaseDir(settings, cwd, async () => {
15775
+ await this.retryPendingConfigCleanup(
15776
+ Storage.getRuntimeBaseDir(),
15777
+ sessionId
15778
+ );
15779
+ return this.newSessionConfigInRuntimeContext(
15780
+ cwd,
15781
+ mcpServers,
15782
+ settings,
15783
+ sessionId,
15784
+ resume,
15785
+ initializeOptions,
15786
+ chatRecording
15787
+ );
15788
+ });
15789
+ } catch (error) {
15790
+ const writerError = getSessionWriterError(error);
15791
+ if (writerError) {
15792
+ throw new RequestError(writerError.rpcCode, writerError.message, {
15793
+ errorKind: writerError.errorKind
15794
+ });
15795
+ }
15796
+ throw error;
15797
+ }
15798
+ }
15799
+ async newSessionConfigInRuntimeContext(cwd, mcpServers, settings, sessionId, resume, initializeOptions = {}, chatRecording) {
14334
15800
  const sessionMcpServers = {};
14335
15801
  for (const server of mcpServers) {
14336
15802
  const stdioServer = toStdioServer(server);
@@ -14386,8 +15852,14 @@ ${outputText}
14386
15852
  const sessionArg = resume === true ? { resume: sessionId, sessionId: void 0 } : { sessionId, resume: void 0 };
14387
15853
  const argvForSession = {
14388
15854
  ...this.argv,
15855
+ // Docker sandbox relaunch injects a fixed --sandbox-session-id into
15856
+ // the ACP process argv. Without clearing it, every newSession()
15857
+ // inherits the same ID and the second session collides with the
15858
+ // first's writer lease (#7435).
15859
+ sandboxSessionId: void 0,
14389
15860
  ...sessionArg,
14390
- continue: false
15861
+ continue: false,
15862
+ ...chatRecording !== void 0 ? { chatRecording } : {}
14391
15863
  };
14392
15864
  const config = await loadCliConfig(
14393
15865
  mergedSettings,
@@ -14441,15 +15913,22 @@ ${outputText}
14441
15913
  });
14442
15914
  });
14443
15915
  }
14444
- await config.initialize({
14445
- ...initializeOptions,
14446
- // Reverse tool channel (issue #5626, Phase 2): bind the session
14447
- // manager's SDK MCP callback to the `client_mcp/message` ext-method so a
14448
- // client-hosted (extension) MCP server added at runtime reaches the
14449
- // daemon WS. Servers that aren't client-hosted never use this callback
14450
- // (the daemon only adds SDK-type runtime servers for client MCP).
14451
- sendSdkMcpMessage: this.buildClientMcpSender(wiredSessionId)
14452
- });
15916
+ try {
15917
+ await config.initialize({
15918
+ ...initializeOptions,
15919
+ // Reverse tool channel (issue #5626, Phase 2): bind the session
15920
+ // manager's SDK MCP callback to the `client_mcp/message` ext-method so a
15921
+ // client-hosted (extension) MCP server added at runtime reaches the
15922
+ // daemon WS. Servers that aren't client-hosted never use this callback
15923
+ // (the daemon only adds SDK-type runtime servers for client MCP).
15924
+ sendSdkMcpMessage: this.buildClientMcpSender(wiredSessionId)
15925
+ });
15926
+ } catch (error) {
15927
+ return this.cleanupAfterRequestFailure(
15928
+ error,
15929
+ () => this.cleanupUnstoredConfig(config)
15930
+ );
15931
+ }
14453
15932
  void this.surfaceMcpFailuresWhenReady(config);
14454
15933
  return config;
14455
15934
  }
@@ -14510,34 +15989,52 @@ ${outputText}
14510
15989
  if (needsInitialize) {
14511
15990
  await geminiClient.initialize();
14512
15991
  }
14513
- this.sessions.get(sessionId)?.dispose();
15992
+ if (this.sessions.has(sessionId)) {
15993
+ throw new Error(`Session ${sessionId} is already active.`);
15994
+ }
14514
15995
  const session = new Session(sessionId, config, this.connection, settings);
14515
15996
  this.sessions.set(sessionId, session);
14516
- setTimeout(async () => {
14517
- await session.sendAvailableCommandsUpdate();
14518
- }, 0);
14519
- if (sessionData?.fileHistorySnapshots?.length) {
14520
- config.getFileHistoryService().restoreFromSnapshots(sessionData.fileHistorySnapshots);
14521
- }
14522
- if (sessionData?.conversation.messages) {
14523
- config.getChatRecordingService()?.rebuildTurnBoundaries(sessionData.conversation.messages);
14524
- }
14525
- if (options.replayHistory !== false && sessionData?.conversation.messages) {
14526
- await session.replayHistory(
14527
- sessionData.conversation.messages,
14528
- sessionData.historyGaps
14529
- );
14530
- }
14531
- if (options.startPostReplayServices !== false) {
14532
- session.installRewriter();
14533
- session.startCronScheduler();
15997
+ try {
15998
+ if (sessionData?.fileHistorySnapshots?.length) {
15999
+ config.getFileHistoryService().restoreFromSnapshots(sessionData.fileHistorySnapshots);
16000
+ }
16001
+ if (sessionData?.conversation.messages) {
16002
+ config.getChatRecordingService()?.rebuildTurnBoundaries(sessionData.conversation.messages);
16003
+ }
16004
+ if (options.replayHistory !== false && sessionData?.conversation.messages) {
16005
+ await session.replayHistory(
16006
+ sessionData.conversation.messages,
16007
+ sessionData.historyGaps
16008
+ );
16009
+ }
16010
+ if (options.startPostReplayServices !== false) {
16011
+ session.installRewriter();
16012
+ session.startCronScheduler();
16013
+ }
16014
+ setTimeout(() => {
16015
+ void session.sendAvailableCommandsUpdate();
16016
+ }, 0);
16017
+ return session;
16018
+ } catch (error) {
16019
+ try {
16020
+ await this.discardStoredSessionIfCurrent(sessionId, session, {
16021
+ shutdownConfig: false
16022
+ });
16023
+ } catch (cleanupError) {
16024
+ await this.removeStoredSessionEntry(
16025
+ sessionId,
16026
+ session,
16027
+ [cleanupError],
16028
+ { shutdownConfig: false }
16029
+ );
16030
+ }
16031
+ throw error;
14534
16032
  }
14535
- return session;
14536
16033
  }
14537
16034
  buildAvailableModels(config) {
14538
16035
  const rawCurrentModelId = (config.getModel() || this.config.getModel() || "").trim();
14539
16036
  const currentAuthType = config.getAuthType();
14540
- const modelOptions = buildAcpModelOptions(config.getAllConfiguredModels());
16037
+ const modelOptions = this.buildSelectableModelOptions(config);
14541
16038
  const activeRuntimeSnapshot = config.getActiveRuntimeModelSnapshot?.();
14542
16039
  const currentModelId = getCurrentAcpModelId(
14543
16040
  modelOptions,
@@ -14572,7 +16069,7 @@ ${outputText}
14572
16069
  }
14573
16070
  buildConfigOptions(config) {
14574
16071
  const currentApprovalMode = config.getApprovalMode();
14575
- const modelOptions = buildAcpModelOptions(config.getAllConfiguredModels());
16072
+ const modelOptions = this.buildSelectableModelOptions(config);
14576
16073
  const rawCurrentModelId = (config.getModel() || "").trim();
14577
16074
  const currentAuthType = config.getAuthType?.();
14578
16075
  const activeRuntimeSnapshot = config.getActiveRuntimeModelSnapshot?.();
@@ -14612,6 +16109,14 @@ ${outputText}
14612
16109
  };
14613
16110
  return [modeConfigOption, modelConfigOption];
14614
16111
  }
16112
+ buildSelectableModelOptions(config) {
16113
+ const currentAuthType = config.getAuthType();
16114
+ return buildAcpModelOptions(
16115
+ config.getAllConfiguredModels().filter(
16116
+ (model) => model.authType !== "qwen-oauth" /* QWEN_OAUTH */ || currentAuthType === "qwen-oauth" /* QWEN_OAUTH */
16117
+ )
16118
+ );
16119
+ }
14615
16120
  };
14616
16121
  function diffSettingsKeys(oldMerged, newMerged) {
14617
16122
  const changed = /* @__PURE__ */ new Set();