@qwen-code/qwen-code 0.19.9 → 0.19.10

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 (310) hide show
  1. package/bundled/qc-helper/docs/configuration/settings.md +7 -0
  2. package/bundled/qc-helper/docs/features/channels/dingtalk.md +3 -0
  3. package/bundled/qc-helper/docs/features/channels/overview.md +11 -3
  4. package/bundled/qc-helper/docs/features/code-review.md +88 -44
  5. package/bundled/qc-helper/docs/features/commands.md +6 -6
  6. package/bundled/qc-helper/docs/features/hooks.md +29 -0
  7. package/bundled/qc-helper/docs/features/sub-agents.md +21 -0
  8. package/bundled/qc-helper/docs/qwen-serve.md +46 -20
  9. package/bundled/qc-helper/docs/reference/keyboard-shortcuts.md +1 -1
  10. package/bundled/review/DESIGN.md +219 -33
  11. package/bundled/review/SKILL.md +449 -153
  12. package/chunks/{MaxSizedBox-6HYJ3ZPJ.js → MaxSizedBox-67ODZ4SZ.js} +31 -31
  13. package/chunks/{StandaloneSessionPicker-WS4GXYOG.js → StandaloneSessionPicker-SIPBQT5Z.js} +51 -49
  14. package/chunks/{acpAgent-5FWSOZL5.js → acpAgent-VPZJXLFX.js} +528 -478
  15. package/chunks/{agent-HOLHB3RT.js → agent-Z7NWL6XL.js} +26 -26
  16. package/chunks/{agent-headless-SXL6H56A.js → agent-headless-73HZ6ROQ.js} +26 -26
  17. package/chunks/{anthropicContentGenerator-L73TO3DB.js → anthropicContentGenerator-56U3YCP2.js} +5 -5
  18. package/chunks/{artifact-tool-U7IRTLIV.js → artifact-tool-BWZZJ42H.js} +2 -2
  19. package/chunks/{askUserQuestion-2DLUUZZG.js → askUserQuestion-WU3S5A5T.js} +2 -2
  20. package/chunks/{bridge-BCJQ7BBB.js → bridge-XFKW6S7Q.js} +32 -32
  21. package/chunks/{ca-UJ6HC4H2.js → ca-C2JTT2N5.js} +4 -1
  22. package/chunks/channel-worker-group-K7QKH6IG.js +13 -0
  23. package/chunks/channel-worker-manager-5RWKSGEU.js +418 -0
  24. package/chunks/channel-worker-supervisor-PCDAZN4D.js +20 -0
  25. package/chunks/{chunk-LXNEJD34.js → chunk-2FO5GFKZ.js} +1 -1
  26. package/chunks/{chunk-B5ORX3FG.js → chunk-2UUAIFQO.js} +1 -1
  27. package/chunks/{chunk-L36P3NBD.js → chunk-2W3OOD4W.js} +2 -0
  28. package/chunks/{chunk-7R3CZA3Q.js → chunk-2Z5UX4KI.js} +1 -1
  29. package/chunks/chunk-3MX7D6QN.js +516 -0
  30. package/chunks/{chunk-E2IY465S.js → chunk-3XJFUTNM.js} +10 -10
  31. package/chunks/{chunk-JZETEN3Z.js → chunk-422XAKCK.js} +3 -3
  32. package/chunks/{chunk-N3EMS75V.js → chunk-4FMG7EDJ.js} +1268 -1233
  33. package/chunks/{chunk-HKMAENAO.js → chunk-4YWLED2A.js} +8 -6
  34. package/chunks/{chunk-SCGXUJBT.js → chunk-5EBKKSBX.js} +3 -3
  35. package/chunks/chunk-5HBA2Z7V.js +28 -0
  36. package/chunks/{chunk-XYQSMABS.js → chunk-5LROA5W4.js} +4 -4
  37. package/chunks/{chunk-ZJE7NSL3.js → chunk-5M6IDOMF.js} +34 -97
  38. package/chunks/{chunk-VA4KQY6V.js → chunk-65N2J6V2.js} +3 -3
  39. package/chunks/{chunk-4C5BQ2D2.js → chunk-6GETGQWP.js} +71 -12
  40. package/chunks/{chunk-PVZM22CK.js → chunk-6GKMJPOC.js} +5 -5
  41. package/chunks/{chunk-W2UIXQDL.js → chunk-6OATMEYN.js} +1 -1
  42. package/chunks/{chunk-GZRTYZ2R.js → chunk-6W6DI34P.js} +154 -1
  43. package/chunks/{chunk-EMDMPBJ4.js → chunk-7L4XBYVW.js} +3 -3
  44. package/chunks/{chunk-EAXLGSFP.js → chunk-7MJAZMXK.js} +8 -8
  45. package/chunks/{chunk-K434OPES.js → chunk-7NAWTFVY.js} +3 -3
  46. package/chunks/{chunk-J4TSQ5EQ.js → chunk-7NFB7LBQ.js} +8 -1
  47. package/chunks/{chunk-5SFOMFG4.js → chunk-7R4DPSRA.js} +36 -2
  48. package/chunks/{chunk-P67PFTUT.js → chunk-AAR5SGMD.js} +4 -4
  49. package/chunks/{chunk-RDJSGHZE.js → chunk-ALGGS7UH.js} +1 -38
  50. package/chunks/{chunk-GWHYEOV2.js → chunk-ARKANCNX.js} +2 -1
  51. package/chunks/{chunk-D2GFWEXB.js → chunk-B5I2IIWY.js} +6 -6
  52. package/chunks/{chunk-524RQP4Q.js → chunk-B7NUUEXC.js} +10 -4
  53. package/chunks/{chunk-CUMMSHH6.js → chunk-BBNVFRGD.js} +1 -1
  54. package/chunks/{chunk-5HOMWMCL.js → chunk-CEW4HDPK.js} +4166 -1338
  55. package/chunks/chunk-CJFNEBYB.js +91 -0
  56. package/chunks/{chunk-VWPVHAMO.js → chunk-CUUXANEQ.js} +5 -1
  57. package/chunks/{chunk-GWLSNBG4.js → chunk-DK33QJ3V.js} +30 -26
  58. package/chunks/{chunk-HPDUL5MF.js → chunk-DPFBNG72.js} +1 -1
  59. package/chunks/{chunk-KKNMOEZH.js → chunk-E2UVIFI2.js} +185 -398
  60. package/chunks/{chunk-MC23XKFE.js → chunk-E67NFMF4.js} +3 -3
  61. package/chunks/{chunk-OQ4DRIOA.js → chunk-EQY6POVO.js} +2 -2
  62. package/chunks/{chunk-XUOOWUZS.js → chunk-F7NXQH4Y.js} +1 -1
  63. package/chunks/{chunk-YLV3XXFB.js → chunk-FBU7WRZI.js} +17 -1
  64. package/chunks/{chunk-LK7KUE55.js → chunk-FSA7ERJ2.js} +1 -1
  65. package/chunks/{chunk-PDZ7MBDG.js → chunk-FXMC7SL2.js} +27 -6
  66. package/chunks/{chunk-SJHDYNHF.js → chunk-GDQQRV43.js} +3 -3
  67. package/chunks/{chunk-34MW4KTI.js → chunk-GGJII3FM.js} +2 -2
  68. package/chunks/{chunk-3BTRNWWD.js → chunk-GOXKNSDZ.js} +1 -64
  69. package/chunks/chunk-GYTKQYDB.js +23 -0
  70. package/chunks/{chunk-HVY356M2.js → chunk-H3FQOPPS.js} +3 -3
  71. package/chunks/{chunk-YVEDCAUE.js → chunk-HGT6JR3U.js} +19 -0
  72. package/chunks/{chunk-WQUQVGTF.js → chunk-HHEFI4RP.js} +183 -96
  73. package/chunks/chunk-IDS7MSUP.js +74 -0
  74. package/chunks/{chunk-6PESIEKJ.js → chunk-JSJFKYWT.js} +68 -6
  75. package/chunks/{chunk-CNEIYWSA.js → chunk-K4PZ5F5T.js} +5 -5
  76. package/chunks/{chunk-NVYTCB5Z.js → chunk-K7CRWKOE.js} +14534 -13980
  77. package/chunks/{chunk-ORBGV7NJ.js → chunk-KKRTYONM.js} +6 -4
  78. package/chunks/{chunk-IAVB3HM3.js → chunk-KSO42X3Z.js} +13 -0
  79. package/chunks/chunk-L37RC7MQ.js +493 -0
  80. package/chunks/{chunk-4QLQE5WJ.js → chunk-L5U3ELZX.js} +1 -1
  81. package/chunks/{chunk-3G7CIHVV.js → chunk-L62SEJWY.js} +4 -4
  82. package/chunks/{chunk-EGYZ275M.js → chunk-LNUXFLLJ.js} +4 -4
  83. package/chunks/{chunk-4ZVWQHEQ.js → chunk-LQIDP6K5.js} +1 -1
  84. package/chunks/{chunk-VTU57BWZ.js → chunk-LQU7EVFA.js} +1 -1
  85. package/chunks/{chunk-B4G2WOFA.js → chunk-LTNI523B.js} +2 -2
  86. package/chunks/{chunk-DC5Z3DU6.js → chunk-LXLTBIDP.js} +43 -6
  87. package/chunks/{chunk-KHUQZZJ6.js → chunk-MO7O5722.js} +370 -36
  88. package/chunks/chunk-MR3PXB6E.js +48 -0
  89. package/chunks/{chunk-5VXNZWGF.js → chunk-N6FXRR6P.js} +1 -1
  90. package/chunks/{chunk-WL4L7EZH.js → chunk-OA4JVLSA.js} +27 -1
  91. package/chunks/{chunk-TO6QE22P.js → chunk-OATTJGPJ.js} +26 -22
  92. package/chunks/{chunk-X6TJ3YZV.js → chunk-OFEVHGVU.js} +159 -57
  93. package/chunks/{chunk-X4NKFGFJ.js → chunk-OJAMDVF5.js} +0 -15
  94. package/chunks/{chunk-BZIFY5TF.js → chunk-OKAIGAYW.js} +3 -3
  95. package/chunks/{chunk-3VAGG5T5.js → chunk-P6LART6G.js} +116 -15
  96. package/chunks/{chunk-3SJSQXNS.js → chunk-PEJWA3QQ.js} +12 -8
  97. package/chunks/{chunk-BAPGSC7U.js → chunk-Q5GLXH5Q.js} +23 -9
  98. package/chunks/{chunk-MXL5UP4X.js → chunk-Q6TUALBE.js} +1 -1
  99. package/chunks/{chunk-QYMQSECS.js → chunk-QAW7PIHT.js} +2 -2
  100. package/chunks/{chunk-LUODI7WD.js → chunk-RCEEXIOO.js} +6 -4
  101. package/chunks/{chunk-YAUFFXDS.js → chunk-RDRVMDWV.js} +12 -11
  102. package/chunks/{chunk-CEA3E3JB.js → chunk-SPJQO2CE.js} +2 -2
  103. package/chunks/{chunk-U2NNEY4R.js → chunk-SPUYQB4T.js} +1 -1
  104. package/chunks/{chunk-34Z3U5RQ.js → chunk-SXU3KKNI.js} +514 -114
  105. package/chunks/{chunk-ECNYL4AA.js → chunk-TISZXPAX.js} +1 -1
  106. package/chunks/{chunk-JSG7ZSBC.js → chunk-TQBODCFD.js} +1 -1
  107. package/chunks/{chunk-AKIVHSJR.js → chunk-TTUO4DNG.js} +111 -93
  108. package/chunks/chunk-TV6K2FB4.js +224 -0
  109. package/chunks/{chunk-4GORAUCN.js → chunk-TXY2C3D2.js} +1 -1
  110. package/chunks/{chunk-5XUCZNSY.js → chunk-TYLOFD2U.js} +1 -1
  111. package/chunks/{chunk-CLFKOZEK.js → chunk-UFOKA4PR.js} +1 -1
  112. package/chunks/{channel-worker-supervisor-WSOAAYUO.js → chunk-URU5UEK6.js} +67 -35
  113. package/chunks/{chunk-D5SKC4YG.js → chunk-V7EQTZYR.js} +41 -13
  114. package/chunks/{chunk-L6P4KPHR.js → chunk-VBRRNQB7.js} +59 -39
  115. package/chunks/{chunk-BMGVRZN4.js → chunk-W34A5MJH.js} +1 -1
  116. package/chunks/{chunk-PODM4SZ4.js → chunk-WDW64OW3.js} +5 -5
  117. package/chunks/{chunk-W3JHSWRP.js → chunk-WDWJ4OQJ.js} +4 -4
  118. package/chunks/{chunk-Q4YQW46J.js → chunk-WIASPMLX.js} +31 -17
  119. package/chunks/{chunk-ZLXQN2QS.js → chunk-WIEO4CWB.js} +1 -1
  120. package/chunks/{chunk-A3XKDTSH.js → chunk-WLXYAKV7.js} +4 -4
  121. package/chunks/{chunk-Q6I5QHMH.js → chunk-WTSXKLG5.js} +1 -1
  122. package/chunks/{chunk-J3JA76CF.js → chunk-WX6SD4IQ.js} +1 -1
  123. package/chunks/{chunk-77XJ3SWN.js → chunk-X362TMXZ.js} +5 -5
  124. package/chunks/{chunk-CCDMCZPP.js → chunk-XLIRF7IK.js} +1 -1
  125. package/chunks/{chunk-AURZZYMD.js → chunk-XXJKGHZV.js} +4 -4
  126. package/chunks/{chunk-TDEXZKMT.js → chunk-Y66VOBRP.js} +2 -2
  127. package/chunks/{chunk-CC2ITGCF.js → chunk-YHN5SUIJ.js} +49 -6
  128. package/chunks/{chunk-3AHXV67U.js → chunk-YU56QGXX.js} +1 -1
  129. package/chunks/{chunk-5U27BZ72.js → chunk-YX4LLZ3D.js} +187 -75
  130. package/chunks/{chunk-ATAKVRIF.js → chunk-YYPXHMWO.js} +7 -7
  131. package/chunks/{chunk-XLA62MYB.js → chunk-ZKMGAFYV.js} +2 -2
  132. package/chunks/{chunk-UOZWKTQG.js → chunk-ZPAHLFZU.js} +2 -2
  133. package/chunks/{chunk-7PU4FYLG.js → chunk-ZQTZXVHP.js} +4 -4
  134. package/chunks/chunk-ZRKBI3DP.js +34 -0
  135. package/chunks/{computer-use-HM37RX6A.js → computer-use-IYTX45WA.js} +26 -26
  136. package/chunks/{config-utils-NV2SVGPB.js → config-utils-CFT33LTP.js} +3 -2
  137. package/chunks/{contextCommand-OF5SFGH2.js → contextCommand-272V77WU.js} +28 -28
  138. package/chunks/{create-sub-session-KPRT7ECJ.js → create-sub-session-CBJMQLYP.js} +26 -26
  139. package/chunks/{create-sub-session-INX7TXJI.js → create-sub-session-WNX2OQVX.js} +2 -2
  140. package/chunks/{cron-create-AMBKGZX6.js → cron-create-36TIFKRT.js} +4 -4
  141. package/chunks/{cron-delete-LRU4OJYG.js → cron-delete-OQD3WULU.js} +4 -4
  142. package/chunks/{cron-list-WVP2JXER.js → cron-list-4533T2FH.js} +4 -4
  143. package/chunks/{daemon-ARHTSTXP.js → daemon-RNGFPMAB.js} +575 -58
  144. package/chunks/{daemon-status-provider-B2UTZUJ2.js → daemon-status-provider-L4STG5VO.js} +36 -36
  145. package/chunks/{de-EBJN3OVN.js → de-2VCDRDGU.js} +4 -1
  146. package/chunks/{dist-VHV4EVHG.js → dist-3V3ZV6ML.js} +1 -1
  147. package/chunks/{dist-XKU3ABM5.js → dist-ERCPDVA6.js} +1 -1
  148. package/chunks/{dist-PNVLTKTL.js → dist-HNN7DR2L.js} +158 -4
  149. package/chunks/{dist-WKPOYU7O.js → dist-JZE7F6YR.js} +1 -1
  150. package/chunks/{dist-QYCAEZIT.js → dist-MOEC47TR.js} +5 -1
  151. package/chunks/{dist-R7LN5AZE.js → dist-PHEPJLXD.js} +2 -2
  152. package/chunks/{earlyInputCapture-3VTHRC4C.js → earlyInputCapture-EN4BRREQ.js} +27 -27
  153. package/chunks/{edit-VNI4NJ73.js → edit-OMAF2QDR.js} +27 -27
  154. package/chunks/{en-5A6LA7RK.js → en-NJCA3TAA.js} +5 -1
  155. package/chunks/{enter-worktree-IYYBKPZT.js → enter-worktree-BBZX52HG.js} +26 -26
  156. package/chunks/{enterPlanMode-GMC5FD5A.js → enterPlanMode-5NNFMBUY.js} +42 -27
  157. package/chunks/{environment-5HSSRMJ7.js → environment-7TEWMJYN.js} +30 -29
  158. package/chunks/{errors-HMFCJJ7P.js → errors-I4VKVX3F.js} +28 -28
  159. package/chunks/{exit-worktree-6BHCMP5G.js → exit-worktree-FUWRJI33.js} +26 -26
  160. package/chunks/{exitPlanMode-CJW7G74W.js → exitPlanMode-IHCJ5EEI.js} +26 -26
  161. package/chunks/{fast-path-FRDMDVHG.js → fast-path-ZA57TOH4.js} +3 -3
  162. package/chunks/{fast-path-settings-5QZE64HR.js → fast-path-settings-DAOVFADC.js} +6 -4
  163. package/chunks/{fr-YXRABLYZ.js → fr-5F3E7WKD.js} +4 -1
  164. package/chunks/{gemini-QYSEGHAX.js → gemini-UOAKVXBG.js} +139 -76
  165. package/chunks/{geminiContentGenerator-J7YNZDYP.js → geminiContentGenerator-G6UCE6MW.js} +4 -4
  166. package/chunks/{glob-BRCSGFOT.js → glob-4GJQ2UFF.js} +28 -27
  167. package/chunks/{grep-EE2DUOSY.js → grep-5QSYXF2E.js} +26 -26
  168. package/chunks/{handleAutoUpdate-5NWTLR67.js → handleAutoUpdate-ULHNWL6R.js} +30 -30
  169. package/chunks/{i18n-BASPENNQ.js → i18n-CYDUTF6F.js} +27 -27
  170. package/chunks/initializer-NRFKUGIO.js +73 -0
  171. package/chunks/{installationInfo-W6V4DT7W.js → installationInfo-WELKRHHE.js} +27 -27
  172. package/chunks/{ja-7VQOANVG.js → ja-66J6B53L.js} +5 -2
  173. package/chunks/{keychain-token-storage-VKUBNCP4.js → keychain-token-storage-AU22CQI6.js} +2 -2
  174. package/chunks/list-JVDXEG2E.js +76 -0
  175. package/chunks/loadedSettingsAdapter-WAM4VUTG.js +70 -0
  176. package/chunks/{loop-wakeup-WX7BLWWP.js → loop-wakeup-MVUKDVCP.js} +5 -5
  177. package/chunks/{ls-ZB2BDP6T.js → ls-RXNIAQDE.js} +4 -4
  178. package/chunks/{lsp-V5DN4YUJ.js → lsp-HB5LM5IL.js} +2 -2
  179. package/chunks/mcp-YHOZN3ZM.js +70 -0
  180. package/chunks/{monitor-X5Z3H4FY.js → monitor-R7XZPJHQ.js} +26 -26
  181. package/chunks/nonInteractiveCli-NSOB6D74.js +129 -0
  182. package/chunks/{notebook-edit-TRM2QIJK.js → notebook-edit-6RNKE2L2.js} +27 -27
  183. package/chunks/{openaiContentGenerator-AAYONPMF.js → openaiContentGenerator-XNS5S64I.js} +12 -12
  184. package/chunks/{pidfile-D4I4FTVA.js → pidfile-XE4RRR2P.js} +27 -27
  185. package/chunks/{pt-2C6YCSHL.js → pt-TFZO5Y6T.js} +4 -1
  186. package/chunks/{qwenContentGenerator-K3HZ2H76.js → qwenContentGenerator-APDPJ3VN.js} +28 -28
  187. package/chunks/{qwenOAuth2-PJQ27GSO.js → qwenOAuth2-LEYOU7RU.js} +5 -5
  188. package/chunks/{read-file-7SZSIZOL.js → read-file-XSUWXSR7.js} +8 -8
  189. package/chunks/{read-mcp-resource-SM5DA4RG.js → read-mcp-resource-6LRTZKXI.js} +2 -2
  190. package/chunks/{record-artifact-4XKZX3UW.js → record-artifact-PMDTY4OS.js} +2 -2
  191. package/chunks/{ripGrep-YNPFVCZP.js → ripGrep-APB3CDMU.js} +26 -26
  192. package/chunks/{ru-6BBHVZZV.js → ru-4L4LFHIT.js} +4 -1
  193. package/chunks/{run-qwen-serve-DMWV5N6L.js → run-qwen-serve-NWTGPERT.js} +1232 -371
  194. package/chunks/{runtime-57WWRVHN.js → runtime-EIO3NQKR.js} +42 -37
  195. package/chunks/{scheduler-YBLGWSIL.js → scheduler-JJDZBDRN.js} +26 -26
  196. package/chunks/{send-message-F36YD6KQ.js → send-message-SR4WSXP2.js} +3 -3
  197. package/chunks/{serve-R63NK3CV.js → serve-WTIPB3EI.js} +36 -34
  198. package/chunks/{server-Z22GCAXP.js → server-NJPHQHLH.js} +5238 -1328
  199. package/chunks/{session-HKAAI7BN.js → session-O4AO7FTS.js} +298 -98
  200. package/chunks/{settings-3EYN66GK.js → settings-HQNDK7TG.js} +34 -32
  201. package/chunks/{shell-6YXINTWJ.js → shell-UIXM6PWG.js} +26 -26
  202. package/chunks/{skill-OO57P4X6.js → skill-3XMB4ULV.js} +10 -10
  203. package/chunks/{spawnChannel-JD7G4VU6.js → spawnChannel-3R632QRM.js} +28 -28
  204. package/chunks/{src-G5UPLZSZ.js → src-USZKPUOC.js} +85 -27
  205. package/chunks/{standalone-update-OB7F4JPZ.js → standalone-update-L5XW3D7K.js} +28 -28
  206. package/chunks/{startInteractiveUI-73EGLIIH.js → startInteractiveUI-CPZOL2WB.js} +730 -397
  207. package/chunks/{syntheticOutput-34H7LGA7.js → syntheticOutput-YKFNUQZD.js} +3 -3
  208. package/chunks/{task-create-FRGOEIKY.js → task-create-NUFOHU53.js} +8 -7
  209. package/chunks/{task-list-OW766BXZ.js → task-list-Z2IKQY3S.js} +6 -5
  210. package/chunks/{task-stop-SIR5SNBN.js → task-stop-KQFIVQTJ.js} +2 -2
  211. package/chunks/{task-update-YRA532MT.js → task-update-HKADXSTD.js} +8 -7
  212. package/chunks/{team-create-PECAAPXK.js → team-create-XXPRF3IQ.js} +26 -26
  213. package/chunks/{team-delete-6OSECUZC.js → team-delete-SDNTGZLG.js} +6 -5
  214. package/chunks/{team-plan-approval-L6F434RY.js → team-plan-approval-EOTTKHDW.js} +26 -26
  215. package/chunks/{theme-manager-ZG4RY6GU.js → theme-manager-P6UITO2L.js} +27 -27
  216. package/chunks/{todoWrite-YDMFEV4G.js → todoWrite-YNXB27GB.js} +4 -4
  217. package/chunks/{tool-search-THVIWAPB.js → tool-search-DDNGK2LR.js} +9 -9
  218. package/chunks/{total-session-admission-JOKNRIIA.js → total-session-admission-PL5N7DNY.js} +33 -33
  219. package/chunks/tree-sitter-YJVE2ZUK.js +2980 -0
  220. package/chunks/{trustedFolders-EOGT3UVS.js → trustedFolders-C5LMF3UR.js} +29 -28
  221. package/chunks/types-ML3TRJQ5.js +16 -0
  222. package/chunks/{updateCheck-2KYEYVSB.js → updateCheck-QTVVISH7.js} +29 -29
  223. package/chunks/{validateNonInterActiveAuth-EN6ZQSR2.js → validateNonInterActiveAuth-RY4RKBQG.js} +75 -71
  224. package/chunks/{version-3UEA6ZIR.js → version-U45RYOSD.js} +1 -1
  225. package/chunks/{web-fetch-PAAEQKBW.js → web-fetch-ZSPR3PRR.js} +5 -5
  226. package/chunks/{workflow-QCCCMYP3.js → workflow-TCIAQYOA.js} +27 -27
  227. package/chunks/workspace-providers-status-I3G2HYLY.js +73 -0
  228. package/chunks/workspace-registration-store-IH5GLZ6Y.js +27 -0
  229. package/chunks/{workspace-registry-24QFLQYH.js → workspace-registry-QEKBELIX.js} +33 -33
  230. package/chunks/workspace-service-ORKHGLP3.js +86 -0
  231. package/chunks/workspace-skills-status-D7QCNDYY.js +72 -0
  232. package/chunks/{write-file-I3MUDRIE.js → write-file-JGRQR5VM.js} +27 -27
  233. package/chunks/{zh-RQE7I22T.js → zh-FSAH32JB.js} +6 -2
  234. package/chunks/{zh-TW-TBPQGHKH.js → zh-TW-D2YIE2LO.js} +6 -2
  235. package/cli.js +11 -11
  236. package/locales/ca.js +6 -0
  237. package/locales/de.js +6 -0
  238. package/locales/en.js +8 -0
  239. package/locales/fr.js +6 -0
  240. package/locales/ja.js +7 -1
  241. package/locales/pt.js +6 -0
  242. package/locales/ru.js +6 -0
  243. package/locales/zh-TW.js +9 -1
  244. package/locales/zh.js +9 -1
  245. package/package.json +3 -3
  246. package/web-shell/assets/{arc-C15hqnJe.js → arc-CUeDlxvE.js} +1 -1
  247. package/web-shell/assets/{architectureDiagram-3BPJPVTR-B-At37J_.js → architectureDiagram-3BPJPVTR-PiUszkQA.js} +1 -1
  248. package/web-shell/assets/{blockDiagram-GPEHLZMM-B51wjcU7.js → blockDiagram-GPEHLZMM-s2wYSO7e.js} +1 -1
  249. package/web-shell/assets/{c4Diagram-AAUBKEIU-xBK7BAwN.js → c4Diagram-AAUBKEIU-DyLxZoz9.js} +1 -1
  250. package/web-shell/assets/channel-DkuJJ0qd.js +1 -0
  251. package/web-shell/assets/{chunk-2J33WTMH-xKmLg7Yr.js → chunk-2J33WTMH-Dsdai7Tk.js} +1 -1
  252. package/web-shell/assets/{chunk-4BX2VUAB-BfkdKZCM.js → chunk-4BX2VUAB-DEosOjV7.js} +1 -1
  253. package/web-shell/assets/{chunk-55IACEB6-DT713sZf.js → chunk-55IACEB6-sNsRLTXf.js} +1 -1
  254. package/web-shell/assets/{chunk-727SXJPM-CYEeAamv.js → chunk-727SXJPM-DkRNZzmh.js} +1 -1
  255. package/web-shell/assets/{chunk-AQP2D5EJ-DBN-5CFd.js → chunk-AQP2D5EJ-BrsRNpzd.js} +1 -1
  256. package/web-shell/assets/{chunk-FMBD7UC4-CGZKk4PH.js → chunk-FMBD7UC4-CI039lpl.js} +1 -1
  257. package/web-shell/assets/{chunk-ND2GUHAM-qQbC2O-y.js → chunk-ND2GUHAM-M-pkeIfu.js} +1 -1
  258. package/web-shell/assets/{chunk-QZHKN3VN-B3zeXwsX.js → chunk-QZHKN3VN-C4ckGNbH.js} +1 -1
  259. package/web-shell/assets/classDiagram-4FO5ZUOK-CwqHc0TB.js +1 -0
  260. package/web-shell/assets/classDiagram-v2-Q7XG4LA2-CwqHc0TB.js +1 -0
  261. package/web-shell/assets/{cose-bilkent-S5V4N54A-BKsl1Wvy.js → cose-bilkent-S5V4N54A-BciKUAFq.js} +1 -1
  262. package/web-shell/assets/{dagre-BM42HDAG-CuuuLiBK.js → dagre-BM42HDAG-C1nTSgU6.js} +1 -1
  263. package/web-shell/assets/{diagram-2AECGRRQ-CG4_eKiV.js → diagram-2AECGRRQ-BDPNWr1m.js} +1 -1
  264. package/web-shell/assets/{diagram-5GNKFQAL-DSFTmZB1.js → diagram-5GNKFQAL-CNFhTszL.js} +1 -1
  265. package/web-shell/assets/{diagram-KO2AKTUF-BxwlEHn8.js → diagram-KO2AKTUF-CjPa4p5a.js} +1 -1
  266. package/web-shell/assets/{diagram-LMA3HP47-BUAg-jMG.js → diagram-LMA3HP47-ZzPykSyG.js} +1 -1
  267. package/web-shell/assets/{diagram-OG6HWLK6-BFM2jlO5.js → diagram-OG6HWLK6-0UVtZ9A4.js} +1 -1
  268. package/web-shell/assets/{erDiagram-TEJ5UH35-CerbFPa2.js → erDiagram-TEJ5UH35-CajDZCat.js} +1 -1
  269. package/web-shell/assets/{flowDiagram-I6XJVG4X-BNeZz5Zz.js → flowDiagram-I6XJVG4X-BRuFBIvL.js} +1 -1
  270. package/web-shell/assets/{ganttDiagram-6RSMTGT7-CTOogLaM.js → ganttDiagram-6RSMTGT7-BevGmJqG.js} +3 -3
  271. package/web-shell/assets/{gitGraphDiagram-PVQCEYII-yxSFkXPj.js → gitGraphDiagram-PVQCEYII-DvPMpBMb.js} +1 -1
  272. package/web-shell/assets/index-Cnvv4VcI.css +5 -0
  273. package/web-shell/assets/index-D1Uyklxa.js +1088 -0
  274. package/web-shell/assets/index-DzHwQkQq.js +3 -0
  275. package/web-shell/assets/{infoDiagram-5YYISTIA-DYdAUevm.js → infoDiagram-5YYISTIA-Oixn7tA9.js} +1 -1
  276. package/web-shell/assets/{ishikawaDiagram-YF4QCWOH-CNuijZ90.js → ishikawaDiagram-YF4QCWOH-BgKpeg-j.js} +1 -1
  277. package/web-shell/assets/{journeyDiagram-JHISSGLW-BTyiuonf.js → journeyDiagram-JHISSGLW-74mwxIaA.js} +1 -1
  278. package/web-shell/assets/{kanban-definition-UN3LZRKU-DPJo0Uow.js → kanban-definition-UN3LZRKU-D4D6cEqA.js} +1 -1
  279. package/web-shell/assets/{linear-C8wKCbIC.js → linear-atZRE_L2.js} +1 -1
  280. package/web-shell/assets/{mermaid.core-BV5o7nW5.js → mermaid.core-KKudX-JC.js} +5 -5
  281. package/web-shell/assets/{mindmap-definition-RKZ34NQL-BtLcBmSt.js → mindmap-definition-RKZ34NQL-CMCej9yG.js} +1 -1
  282. package/web-shell/assets/{pieDiagram-4H26LBE5-C22J7A9Q.js → pieDiagram-4H26LBE5-nhx40X7q.js} +1 -1
  283. package/web-shell/assets/{quadrantDiagram-W4KKPZXB-DSL10wiL.js → quadrantDiagram-W4KKPZXB-CUmVcN3M.js} +1 -1
  284. package/web-shell/assets/{requirementDiagram-4Y6WPE33-feqh0UpX.js → requirementDiagram-4Y6WPE33-C_vyEwyy.js} +1 -1
  285. package/web-shell/assets/{sankeyDiagram-5OEKKPKP-Z4OVaWaZ.js → sankeyDiagram-5OEKKPKP-DU6G4VWR.js} +1 -1
  286. package/web-shell/assets/{sequenceDiagram-3UESZ5HK-DIluIcb1.js → sequenceDiagram-3UESZ5HK-DdeRR_KJ.js} +1 -1
  287. package/web-shell/assets/{stateDiagram-AJRCARHV-hlhnuoYH.js → stateDiagram-AJRCARHV-C6iCI8ps.js} +1 -1
  288. package/web-shell/assets/stateDiagram-v2-BHNVJYJU-C0_6nR6C.js +1 -0
  289. package/web-shell/assets/{timeline-definition-PNZ67QCA-Dqf_CqgL.js → timeline-definition-PNZ67QCA-B_Ea8Cb7.js} +1 -1
  290. package/web-shell/assets/{vennDiagram-CIIHVFJN-DD2QhaTX.js → vennDiagram-CIIHVFJN-BPUVZEJA.js} +1 -1
  291. package/web-shell/assets/{wardley-L42UT6IY-B2uI85U_.js → wardley-L42UT6IY-BWEj0lKY.js} +1 -1
  292. package/web-shell/assets/{wardleyDiagram-YWT4CUSO-U1aJX71g.js → wardleyDiagram-YWT4CUSO-BvDsdIQw.js} +1 -1
  293. package/web-shell/assets/{xychartDiagram-2RQKCTM6-C0ODHUee.js → xychartDiagram-2RQKCTM6-crz0QhF_.js} +1 -1
  294. package/web-shell/index.html +2 -2
  295. package/chunks/chunk-CU3L64TP.js +0 -93
  296. package/chunks/initializer-UTQ7FB7G.js +0 -71
  297. package/chunks/list-DEICDL65.js +0 -74
  298. package/chunks/loadedSettingsAdapter-NOWEGDYJ.js +0 -68
  299. package/chunks/mcp-L5JXEEIA.js +0 -68
  300. package/chunks/nonInteractiveCli-LS2K4X6A.js +0 -124
  301. package/chunks/types-JNKGKUJT.js +0 -12
  302. package/chunks/workspace-providers-status-4KMGETOJ.js +0 -71
  303. package/chunks/workspace-service-RVLBMSMZ.js +0 -80
  304. package/chunks/workspace-skills-status-DS4ZVFTO.js +0 -70
  305. package/web-shell/assets/channel-CLiQD50f.js +0 -1
  306. package/web-shell/assets/classDiagram-4FO5ZUOK-D3sYqow5.js +0 -1
  307. package/web-shell/assets/classDiagram-v2-Q7XG4LA2-D3sYqow5.js +0 -1
  308. package/web-shell/assets/index-D5IWFVk1.css +0 -5
  309. package/web-shell/assets/index-KFJRDhX7.js +0 -783
  310. package/web-shell/assets/stateDiagram-v2-BHNVJYJU-BhQMwgpl.js +0 -1
@@ -12,32 +12,6 @@ import {
12
12
  __name
13
13
  } from "./chunk-J2S4EL5Y.js";
14
14
 
15
- // packages/channels/base/dist/paths.js
16
- init_esbuild_shims();
17
- import * as path from "node:path";
18
- import * as os from "node:os";
19
- function resolvePath(dir) {
20
- let resolved = dir;
21
- if (resolved === "~" || resolved.startsWith("~/") || resolved.startsWith("~\\")) {
22
- const relativeSegments = resolved === "~" ? [] : resolved.slice(2).split(/[/\\]+/).filter(Boolean);
23
- resolved = path.join(os.homedir(), ...relativeSegments);
24
- }
25
- if (!path.isAbsolute(resolved)) {
26
- resolved = path.resolve(resolved);
27
- }
28
- return resolved;
29
- }
30
- __name(resolvePath, "resolvePath");
31
- function getGlobalQwenDir() {
32
- const envDir = process.env["QWEN_HOME"];
33
- if (envDir) {
34
- return resolvePath(envDir);
35
- }
36
- const homeDir = os.homedir();
37
- return homeDir ? path.join(homeDir, ".qwen") : path.join(os.tmpdir(), ".qwen");
38
- }
39
- __name(getGlobalQwenDir, "getGlobalQwenDir");
40
-
41
15
  // packages/channels/base/dist/sanitize.js
42
16
  init_esbuild_shims();
43
17
  var PROMPT_UNSAFE_INVISIBLES = new RegExp("[\\u0080-\\u009f\\p{Cf}\\u2028\\u2029]|\\p{Variation_Selector}", "gu");
@@ -74,6 +48,32 @@ __name(sanitizeLogText, "sanitizeLogText");
74
48
  // packages/channels/base/dist/index.js
75
49
  init_esbuild_shims();
76
50
 
51
+ // packages/channels/base/dist/paths.js
52
+ init_esbuild_shims();
53
+ import * as path from "node:path";
54
+ import * as os from "node:os";
55
+ function resolvePath(dir) {
56
+ let resolved = dir;
57
+ if (resolved === "~" || resolved.startsWith("~/") || resolved.startsWith("~\\")) {
58
+ const relativeSegments = resolved === "~" ? [] : resolved.slice(2).split(/[/\\]+/).filter(Boolean);
59
+ resolved = path.join(os.homedir(), ...relativeSegments);
60
+ }
61
+ if (!path.isAbsolute(resolved)) {
62
+ resolved = path.resolve(resolved);
63
+ }
64
+ return resolved;
65
+ }
66
+ __name(resolvePath, "resolvePath");
67
+ function getGlobalQwenDir() {
68
+ const envDir = process.env["QWEN_HOME"];
69
+ if (envDir) {
70
+ return resolvePath(envDir);
71
+ }
72
+ const homeDir = os.homedir();
73
+ return homeDir ? path.join(homeDir, ".qwen") : path.join(os.tmpdir(), ".qwen");
74
+ }
75
+ __name(getGlobalQwenDir, "getGlobalQwenDir");
76
+
77
77
  // packages/channels/base/dist/AcpBridge.js
78
78
  init_esbuild_shims();
79
79
  import { spawn } from "node:child_process";
@@ -361,15 +361,23 @@ var AcpBridge = class extends EventEmitter {
361
361
  async prompt(sessionId, text, options) {
362
362
  const conn = this.ensureConnection();
363
363
  const chunks = [];
364
+ let slashCommandOutput = "";
364
365
  const onChunk = /* @__PURE__ */ __name((sid, chunk) => {
365
366
  if (sid === sessionId)
366
367
  chunks.push(chunk);
367
368
  }, "onChunk");
368
- const clearChunks = /* @__PURE__ */ __name((sid) => {
369
+ const onSlashCommandOutput = /* @__PURE__ */ __name((sid, chunk) => {
369
370
  if (sid === sessionId)
371
+ slashCommandOutput = chunk;
372
+ }, "onSlashCommandOutput");
373
+ const clearChunks = /* @__PURE__ */ __name((sid) => {
374
+ if (sid === sessionId) {
370
375
  chunks.length = 0;
376
+ slashCommandOutput = "";
377
+ }
371
378
  }, "clearChunks");
372
379
  this.on("textChunk", onChunk);
380
+ this.on("slashCommandOutput", onSlashCommandOutput);
373
381
  this.on("responseBoundary", clearChunks);
374
382
  const prompt = [];
375
383
  if (options?.imageBase64 && options.imageMimeType) {
@@ -387,9 +395,10 @@ var AcpBridge = class extends EventEmitter {
387
395
  });
388
396
  } finally {
389
397
  this.off("textChunk", onChunk);
398
+ this.off("slashCommandOutput", onSlashCommandOutput);
390
399
  this.off("responseBoundary", clearChunks);
391
400
  }
392
- return chunks.join("");
401
+ return chunks.join("") || slashCommandOutput;
393
402
  }
394
403
  async cancelSession(sessionId) {
395
404
  const conn = this.ensureConnection();
@@ -432,9 +441,13 @@ var AcpBridge = class extends EventEmitter {
432
441
  const type = update["sessionUpdate"];
433
442
  switch (type) {
434
443
  case "agent_message_chunk": {
444
+ const meta = update["_meta"];
445
+ if (typeof meta?.["parentToolCallId"] === "string") {
446
+ break;
447
+ }
435
448
  const content = update["content"];
436
449
  if (content?.type === "text" && content.text) {
437
- this.emit("textChunk", sessionId, content.text);
450
+ this.emit(meta?.["source"] === "slash_command" ? "slashCommandOutput" : "textChunk", sessionId, content.text);
438
451
  }
439
452
  break;
440
453
  }
@@ -707,6 +720,7 @@ var DaemonChannelBridge = class extends EventEmitter2 {
707
720
  }
708
721
  options;
709
722
  sessions = /* @__PURE__ */ new Map();
723
+ sessionBindingTokens = /* @__PURE__ */ new Map();
710
724
  eventControllers = /* @__PURE__ */ new Map();
711
725
  requestToSession = /* @__PURE__ */ new Map();
712
726
  respondedRequestToSession = /* @__PURE__ */ new Map();
@@ -715,6 +729,7 @@ var DaemonChannelBridge = class extends EventEmitter2 {
715
729
  availableCommandsBySession = /* @__PURE__ */ new Map();
716
730
  turnBarriers = /* @__PURE__ */ new Map();
717
731
  connected = false;
732
+ lifecycleGeneration = 0;
718
733
  latestAvailableCommandsSessionId;
719
734
  lastError;
720
735
  constructor(options) {
@@ -750,17 +765,22 @@ var DaemonChannelBridge = class extends EventEmitter2 {
750
765
  async start() {
751
766
  this.connected = true;
752
767
  }
753
- async newSession(cwd, options) {
768
+ async newSession(cwd, options, bindingToken) {
769
+ const lifecycleGeneration = this.lifecycleGeneration;
754
770
  const session = await this.options.sessionFactory({
755
771
  workspaceCwd: cwd || this.options.cwd,
756
772
  modelServiceId: this.options.modelServiceId,
757
773
  sessionScope: this.options.sessionScope ?? "thread",
758
774
  ...options?.approvalMode ? { approvalMode: options.approvalMode } : {}
759
775
  });
760
- this.attachSession(session);
776
+ if (lifecycleGeneration !== this.lifecycleGeneration) {
777
+ await this.rejectStaleSession(session);
778
+ }
779
+ this.attachSession(session, bindingToken);
761
780
  return session.sessionId;
762
781
  }
763
- async loadSession(sessionId, cwd, options) {
782
+ async loadSession(sessionId, cwd, options, bindingToken) {
783
+ const lifecycleGeneration = this.lifecycleGeneration;
764
784
  const session = await this.options.sessionFactory({
765
785
  workspaceCwd: cwd || this.options.cwd,
766
786
  modelServiceId: this.options.modelServiceId,
@@ -768,10 +788,16 @@ var DaemonChannelBridge = class extends EventEmitter2 {
768
788
  sessionScope: this.options.sessionScope ?? "thread",
769
789
  ...options?.approvalMode ? { approvalMode: options.approvalMode } : {}
770
790
  });
791
+ if (lifecycleGeneration !== this.lifecycleGeneration) {
792
+ await this.rejectStaleSession(session);
793
+ }
771
794
  if (session.sessionId !== sessionId) {
795
+ void this.releaseSessionClient(session).catch((error) => {
796
+ this.lastError = error;
797
+ });
772
798
  throw new Error(`Daemon returned session ${session.sessionId} while loading ${sessionId}`);
773
799
  }
774
- this.attachSession(session);
800
+ this.attachSession(session, bindingToken);
775
801
  return session.sessionId;
776
802
  }
777
803
  async prompt(sessionId, text, options) {
@@ -788,14 +814,21 @@ var DaemonChannelBridge = class extends EventEmitter2 {
788
814
  }
789
815
  controllers.add(controller);
790
816
  const chunks = [];
817
+ let slashCommandOutput = "";
791
818
  const onChunk = /* @__PURE__ */ __name((sid, chunk) => {
792
819
  if (sid === sessionId) {
793
820
  chunks.push(chunk);
794
821
  }
795
822
  }, "onChunk");
823
+ const onSlashCommandOutput = /* @__PURE__ */ __name((sid, chunk) => {
824
+ if (sid === sessionId) {
825
+ slashCommandOutput = chunk;
826
+ }
827
+ }, "onSlashCommandOutput");
796
828
  const clearChunks = /* @__PURE__ */ __name((sid) => {
797
829
  if (sid === sessionId) {
798
830
  chunks.length = 0;
831
+ slashCommandOutput = "";
799
832
  }
800
833
  }, "clearChunks");
801
834
  const onSessionDied = /* @__PURE__ */ __name((info) => {
@@ -804,6 +837,7 @@ var DaemonChannelBridge = class extends EventEmitter2 {
804
837
  }
805
838
  }, "onSessionDied");
806
839
  this.on("textChunk", onChunk);
840
+ this.on("slashCommandOutput", onSlashCommandOutput);
807
841
  this.on("responseBoundary", clearChunks);
808
842
  this.on("sessionDied", onSessionDied);
809
843
  const turnBarrier = this.createTurnBarrier(sessionId);
@@ -822,7 +856,7 @@ var DaemonChannelBridge = class extends EventEmitter2 {
822
856
  turnBarrier,
823
857
  new Promise((resolve2) => setTimeout(resolve2, 0))
824
858
  ]);
825
- const textResult = chunks.join("");
859
+ const textResult = chunks.join("") || slashCommandOutput;
826
860
  this.emit("promptComplete", {
827
861
  sessionId,
828
862
  text: textResult,
@@ -832,6 +866,7 @@ var DaemonChannelBridge = class extends EventEmitter2 {
832
866
  } finally {
833
867
  this.clearTurnBarrier(sessionId);
834
868
  this.off("textChunk", onChunk);
869
+ this.off("slashCommandOutput", onSlashCommandOutput);
835
870
  this.off("responseBoundary", clearChunks);
836
871
  this.off("sessionDied", onSessionDied);
837
872
  this.activePrompts.delete(sessionId);
@@ -855,6 +890,25 @@ var DaemonChannelBridge = class extends EventEmitter2 {
855
890
  this.activePrompts.delete(sessionId);
856
891
  await session.cancel();
857
892
  }
893
+ async discardSession(sessionId, expectedBindingToken) {
894
+ if (expectedBindingToken !== void 0 && this.sessionBindingTokens.get(sessionId) !== expectedBindingToken) {
895
+ return;
896
+ }
897
+ const session = this.removeSessionBinding(sessionId);
898
+ if (!session)
899
+ return;
900
+ await this.releaseSessionClient(session);
901
+ }
902
+ async releaseSessionClient(session) {
903
+ if (session.detach) {
904
+ try {
905
+ await session.detach();
906
+ return;
907
+ } catch {
908
+ }
909
+ }
910
+ await session.cancel();
911
+ }
858
912
  async setSessionModel(sessionId, modelId) {
859
913
  return await this.ensureSession(sessionId).setModel(modelId);
860
914
  }
@@ -885,6 +939,7 @@ var DaemonChannelBridge = class extends EventEmitter2 {
885
939
  }
886
940
  }
887
941
  stop() {
942
+ this.lifecycleGeneration++;
888
943
  for (const sessionId of Array.from(this.sessions.keys())) {
889
944
  const session = this.sessions.get(sessionId);
890
945
  if (session) {
@@ -892,7 +947,7 @@ var DaemonChannelBridge = class extends EventEmitter2 {
892
947
  this.lastError = error;
893
948
  });
894
949
  }
895
- this.dropSession(sessionId, "bridge_stopped");
950
+ this.dropSession(sessionId, "bridge_stopped", false);
896
951
  }
897
952
  this.latestAvailableCommandsSessionId = void 0;
898
953
  this.connected = false;
@@ -900,15 +955,29 @@ var DaemonChannelBridge = class extends EventEmitter2 {
900
955
  get isConnected() {
901
956
  return this.connected;
902
957
  }
903
- attachSession(session) {
904
- if (this.sessions.has(session.sessionId)) {
905
- this.dropSession(session.sessionId, "session_replaced");
958
+ attachSession(session, bindingToken) {
959
+ const replacedSession = this.removeSessionBinding(session.sessionId);
960
+ if (replacedSession) {
961
+ void this.releaseSessionClient(replacedSession).catch((error) => {
962
+ this.lastError = error;
963
+ });
964
+ this.emit("sessionDied", {
965
+ sessionId: session.sessionId,
966
+ reason: "session_replaced"
967
+ });
906
968
  }
907
969
  this.sessions.set(session.sessionId, session);
970
+ this.sessionBindingTokens.set(session.sessionId, bindingToken);
908
971
  const controller = new AbortController();
909
972
  this.eventControllers.set(session.sessionId, controller);
910
973
  void this.pumpEvents(session, controller.signal);
911
974
  }
975
+ async rejectStaleSession(session) {
976
+ void this.releaseSessionClient(session).catch((error) => {
977
+ this.lastError = error;
978
+ });
979
+ throw new Error("Daemon channel bridge stopped during session creation");
980
+ }
912
981
  ensureSession(sessionId) {
913
982
  const session = this.sessions.get(sessionId);
914
983
  if (!session) {
@@ -944,6 +1013,9 @@ var DaemonChannelBridge = class extends EventEmitter2 {
944
1013
  handleEvent(session, event) {
945
1014
  switch (event.type) {
946
1015
  case "session_update":
1016
+ if (isRecord(event.data) && typeof event.data["sessionId"] === "string" && event.data["sessionId"] !== session.sessionId) {
1017
+ break;
1018
+ }
947
1019
  this.handleSessionUpdate(session.sessionId, event.data);
948
1020
  break;
949
1021
  case "permission_request":
@@ -987,9 +1059,13 @@ var DaemonChannelBridge = class extends EventEmitter2 {
987
1059
  const type = getString(update["sessionUpdate"]);
988
1060
  switch (type) {
989
1061
  case "agent_message_chunk": {
1062
+ const meta = isRecord(update["_meta"]) ? update["_meta"] : void 0;
1063
+ if (typeof meta?.["parentToolCallId"] === "string") {
1064
+ break;
1065
+ }
990
1066
  const text = getTextContent(update["content"]);
991
1067
  if (text) {
992
- this.emit("textChunk", sessionId, text);
1068
+ this.emit(meta?.["source"] === "slash_command" ? "slashCommandOutput" : "textChunk", sessionId, text);
993
1069
  }
994
1070
  break;
995
1071
  }
@@ -1123,14 +1199,26 @@ var DaemonChannelBridge = class extends EventEmitter2 {
1123
1199
  handleSessionDied(sessionId, data) {
1124
1200
  this.dropSession(sessionId, this.getStringField(data, "reason", "session_died"));
1125
1201
  }
1126
- dropSession(sessionId, reason) {
1127
- if (!this.sessions.has(sessionId)) {
1202
+ dropSession(sessionId, reason, releaseClient = true) {
1203
+ const session = this.removeSessionBinding(sessionId);
1204
+ if (!session)
1128
1205
  return;
1206
+ if (releaseClient) {
1207
+ void this.releaseSessionClient(session).catch((error) => {
1208
+ this.lastError = error;
1209
+ });
1129
1210
  }
1211
+ this.emit("sessionDied", { sessionId, reason });
1212
+ }
1213
+ removeSessionBinding(sessionId) {
1214
+ const session = this.sessions.get(sessionId);
1215
+ if (!session)
1216
+ return void 0;
1130
1217
  this.resolveTurnBarrier(sessionId);
1131
1218
  this.eventControllers.get(sessionId)?.abort();
1132
1219
  this.eventControllers.delete(sessionId);
1133
1220
  this.sessions.delete(sessionId);
1221
+ this.sessionBindingTokens.delete(sessionId);
1134
1222
  this.abortActivePrompts(sessionId);
1135
1223
  this.activePrompts.delete(sessionId);
1136
1224
  this.availableCommandsBySession.delete(sessionId);
@@ -1147,7 +1235,7 @@ var DaemonChannelBridge = class extends EventEmitter2 {
1147
1235
  this.respondedRequestToSession.delete(requestId);
1148
1236
  }
1149
1237
  }
1150
- this.emit("sessionDied", { sessionId, reason });
1238
+ return session;
1151
1239
  }
1152
1240
  getStringField(data, field, fallback) {
1153
1241
  return isRecord(data) && typeof data[field] === "string" ? data[field] : fallback;
@@ -1295,7 +1383,7 @@ var BlockStreamer = class {
1295
1383
 
1296
1384
  // packages/channels/base/dist/ChannelBase.js
1297
1385
  init_esbuild_shims();
1298
- import { basename, join as join4 } from "node:path";
1386
+ import { basename, join as join5 } from "node:path";
1299
1387
 
1300
1388
  // packages/channels/base/dist/GroupGate.js
1301
1389
  init_esbuild_shims();
@@ -1770,7 +1858,8 @@ __name(generateCode, "generateCode");
1770
1858
 
1771
1859
  // packages/channels/base/dist/SessionRouter.js
1772
1860
  init_esbuild_shims();
1773
- import { existsSync as existsSync3, readFileSync as readFileSync3, writeFileSync as writeFileSync3, unlinkSync } from "node:fs";
1861
+ import { chmodSync as chmodSync2, existsSync as existsSync3, mkdirSync as mkdirSync3, readFileSync as readFileSync3, renameSync as renameSync2, rmSync, unlinkSync, writeFileSync as writeFileSync3 } from "node:fs";
1862
+ import { dirname as dirname2, join as join4 } from "node:path";
1774
1863
  import process2 from "node:process";
1775
1864
  var SessionRouter = class {
1776
1865
  static {
@@ -1784,17 +1873,22 @@ var SessionRouter = class {
1784
1873
  // session ID → cwd
1785
1874
  creatingSessions = /* @__PURE__ */ new Map();
1786
1875
  sessionLoadWindows = /* @__PURE__ */ new Set();
1876
+ liveSessionIds = /* @__PURE__ */ new Set();
1877
+ routeTokens = /* @__PURE__ */ new Map();
1878
+ lifecycleGeneration = 0;
1787
1879
  bridge;
1788
1880
  defaultCwd;
1789
1881
  defaultScope;
1790
1882
  channelScopes = /* @__PURE__ */ new Map();
1791
1883
  channelApprovalModes = /* @__PURE__ */ new Map();
1792
1884
  persistPath;
1793
- constructor(bridge, defaultCwd, scope = "user", persistPath) {
1885
+ recoveryMode;
1886
+ constructor(bridge, defaultCwd, scope = "user", persistPath, options = {}) {
1794
1887
  this.bridge = bridge;
1795
1888
  this.defaultCwd = defaultCwd;
1796
1889
  this.defaultScope = scope;
1797
1890
  this.persistPath = persistPath;
1891
+ this.recoveryMode = options.recoveryMode ?? "eager";
1798
1892
  }
1799
1893
  /** Replace the bridge instance (used after crash recovery restart). */
1800
1894
  setBridge(bridge) {
@@ -1829,60 +1923,168 @@ var SessionRouter = class {
1829
1923
  }
1830
1924
  async resolve(channelName, senderId, chatId, threadId, cwd, isGroup, options) {
1831
1925
  const key = this.routingKey(channelName, senderId, chatId, options?.routingThreadId ?? threadId);
1832
- let failedCreateWaits = 0;
1926
+ const input = {
1927
+ channelName,
1928
+ senderId,
1929
+ chatId,
1930
+ threadId,
1931
+ cwd: cwd || this.defaultCwd,
1932
+ isGroup
1933
+ };
1934
+ let failedWaits = 0;
1833
1935
  for (; ; ) {
1834
1936
  const existing = this.toSession.get(key);
1835
- if (existing) {
1937
+ if (existing && this.isLive(existing)) {
1836
1938
  this.promoteTargetToGroup(existing, isGroup);
1837
1939
  return existing;
1838
1940
  }
1839
1941
  const creating = this.creatingSessions.get(key);
1840
1942
  if (creating) {
1841
1943
  try {
1842
- const sessionId = await creating;
1944
+ const sessionId = await creating.promise;
1945
+ try {
1946
+ this.assertOperationResultCurrent(key, sessionId, creating);
1947
+ } catch (error) {
1948
+ this.scheduleDiscardInvalidatedSession(sessionId, creating);
1949
+ throw error;
1950
+ }
1843
1951
  this.promoteTargetToGroup(sessionId, isGroup);
1844
1952
  return sessionId;
1845
- } catch (err) {
1953
+ } catch (error) {
1954
+ if (creating.invalidationError) {
1955
+ throw creating.invalidationError;
1956
+ }
1846
1957
  if (this.creatingSessions.get(key) === creating) {
1847
1958
  this.creatingSessions.delete(key);
1848
1959
  }
1849
- failedCreateWaits++;
1850
- if (failedCreateWaits > 3) {
1851
- throw err;
1852
- }
1960
+ this.releaseRouteToken(key, creating);
1961
+ failedWaits++;
1962
+ if (failedWaits > 3)
1963
+ throw error;
1853
1964
  continue;
1854
1965
  }
1855
1966
  }
1856
- const created = Promise.resolve().then(async () => {
1857
- const sessionCwd = cwd || this.defaultCwd;
1858
- const loadWindow = this.beginSessionLoad();
1967
+ const operation = this.createSessionOperation(key, {
1968
+ channelName: input.channelName,
1969
+ senderId: input.senderId,
1970
+ chatId: input.chatId,
1971
+ threadId: input.threadId,
1972
+ isGroup: input.isGroup
1973
+ }, (currentOperation) => existing ? this.loadOrReplaceSession(key, existing, input, currentOperation) : this.createAndStoreSession(key, input, currentOperation));
1974
+ this.creatingSessions.set(key, operation);
1975
+ try {
1976
+ const sessionId = await operation.promise;
1859
1977
  try {
1860
- const sessionId = await this.createLiveSession(sessionCwd, loadWindow, key, this.sessionOptions(channelName));
1861
- this.toSession.set(key, sessionId);
1862
- this.toTarget.set(sessionId, {
1863
- channelName,
1864
- senderId,
1865
- chatId,
1866
- threadId,
1867
- isGroup
1868
- });
1869
- this.toCwd.set(sessionId, sessionCwd);
1870
- this.persist();
1871
- return sessionId;
1872
- } finally {
1873
- this.endSessionLoad(loadWindow);
1978
+ this.assertOperationResultCurrent(key, sessionId, operation);
1979
+ } catch (error) {
1980
+ this.scheduleDiscardInvalidatedSession(sessionId, operation);
1981
+ throw error;
1874
1982
  }
1875
- });
1876
- this.creatingSessions.set(key, created);
1877
- try {
1878
- return await created;
1983
+ this.promoteTargetToGroup(sessionId, isGroup);
1984
+ return sessionId;
1879
1985
  } finally {
1880
- if (this.creatingSessions.get(key) === created) {
1986
+ if (this.creatingSessions.get(key) === operation) {
1881
1987
  this.creatingSessions.delete(key);
1882
1988
  }
1989
+ this.releaseRouteToken(key, operation);
1883
1990
  }
1884
1991
  }
1885
1992
  }
1993
+ isLive(sessionId) {
1994
+ return this.recoveryMode === "eager" || this.liveSessionIds.has(sessionId);
1995
+ }
1996
+ async createAndStoreSession(key, input, operation) {
1997
+ const loadWindow = this.beginSessionLoad();
1998
+ try {
1999
+ const sessionId = await this.createLiveSession(input.cwd, loadWindow, key, this.sessionOptions(input.channelName), operation);
2000
+ try {
2001
+ this.assertOperationCurrent(operation);
2002
+ } catch (error) {
2003
+ this.scheduleDiscardInvalidatedSession(sessionId, operation);
2004
+ throw error;
2005
+ }
2006
+ this.toSession.set(key, sessionId);
2007
+ this.toTarget.set(sessionId, {
2008
+ channelName: input.channelName,
2009
+ senderId: input.senderId,
2010
+ chatId: input.chatId,
2011
+ threadId: input.threadId,
2012
+ isGroup: input.isGroup
2013
+ });
2014
+ this.toCwd.set(sessionId, input.cwd);
2015
+ this.liveSessionIds.add(sessionId);
2016
+ this.persist();
2017
+ return sessionId;
2018
+ } finally {
2019
+ this.endSessionLoad(loadWindow);
2020
+ }
2021
+ }
2022
+ async loadOrReplaceSession(key, savedSessionId, input, operation) {
2023
+ const savedCwd = this.toCwd.get(savedSessionId) ?? input.cwd;
2024
+ const loadWindow = this.beginSessionLoad();
2025
+ try {
2026
+ try {
2027
+ const loadedSessionId = await this.bridge.loadSession(savedSessionId, savedCwd, this.sessionOptions(input.channelName), operation);
2028
+ try {
2029
+ this.assertOperationCurrent(operation);
2030
+ if (this.toSession.get(key) !== savedSessionId) {
2031
+ this.invalidateOperation(operation);
2032
+ this.assertOperationCurrent(operation);
2033
+ }
2034
+ } catch (error) {
2035
+ this.scheduleDiscardInvalidatedSession(loadedSessionId, operation);
2036
+ throw error;
2037
+ }
2038
+ if (typeof loadedSessionId !== "string" || loadedSessionId.length === 0 || loadWindow.delete(loadedSessionId)) {
2039
+ throw new Error("Invalid or dead restored session ID");
2040
+ }
2041
+ if (loadedSessionId !== savedSessionId) {
2042
+ const target = this.toTarget.get(savedSessionId);
2043
+ this.deleteByKey(key);
2044
+ this.toSession.set(key, loadedSessionId);
2045
+ if (target)
2046
+ this.toTarget.set(loadedSessionId, target);
2047
+ this.toCwd.set(loadedSessionId, savedCwd);
2048
+ this.persist();
2049
+ }
2050
+ this.liveSessionIds.add(loadedSessionId);
2051
+ return loadedSessionId;
2052
+ } catch (loadError) {
2053
+ this.assertOperationCurrent(operation);
2054
+ try {
2055
+ const replacement = await this.createLiveSession(input.cwd, loadWindow, key, this.sessionOptions(input.channelName), operation);
2056
+ try {
2057
+ this.assertOperationCurrent(operation);
2058
+ } catch (error) {
2059
+ this.scheduleDiscardInvalidatedSession(replacement, operation);
2060
+ throw error;
2061
+ }
2062
+ this.deleteByKey(key);
2063
+ this.toSession.set(key, replacement);
2064
+ this.toTarget.set(replacement, {
2065
+ channelName: input.channelName,
2066
+ senderId: input.senderId,
2067
+ chatId: input.chatId,
2068
+ threadId: input.threadId,
2069
+ isGroup: input.isGroup
2070
+ });
2071
+ this.toCwd.set(replacement, input.cwd);
2072
+ this.liveSessionIds.add(replacement);
2073
+ this.persist();
2074
+ process2.stderr.write(`[SessionRouter] Replaced unavailable session ${sanitizeLogText(savedSessionId, 128)} for key ${sanitizeLogText(key, 256)} after load failed: ${sanitizeLogText(loadError instanceof Error ? loadError.message : String(loadError), 512)}
2075
+ `);
2076
+ return replacement;
2077
+ } catch (createError) {
2078
+ this.assertOperationCurrent(operation);
2079
+ process2.stderr.write(`[SessionRouter] Failed to load session ${sanitizeLogText(savedSessionId, 128)} for key ${sanitizeLogText(key, 256)} (${sanitizeLogText(loadError instanceof Error ? loadError.message : String(loadError), 512)}) and failed to create a replacement (${sanitizeLogText(createError instanceof Error ? createError.message : String(createError), 512)})
2080
+ `);
2081
+ throw createError;
2082
+ }
2083
+ }
2084
+ } finally {
2085
+ this.endSessionLoad(loadWindow);
2086
+ }
2087
+ }
1886
2088
  getTarget(sessionId) {
1887
2089
  return this.toTarget.get(sessionId);
1888
2090
  }
@@ -1912,6 +2114,7 @@ var SessionRouter = class {
1912
2114
  const scope = this.channelScopes.get(channelName) || this.defaultScope;
1913
2115
  if (chatId) {
1914
2116
  const key = this.routingKey(channelName, senderId, chatId, threadId);
2117
+ this.invalidateRouteOperation(key);
1915
2118
  const sessionId = this.deleteByKey(key);
1916
2119
  if (sessionId)
1917
2120
  removedIds.push(sessionId);
@@ -1921,11 +2124,17 @@ var SessionRouter = class {
1921
2124
  for (const [k, mappedSessionId] of [...this.toSession.entries()]) {
1922
2125
  const target = this.toTarget.get(mappedSessionId);
1923
2126
  if (target?.channelName === channelName && target.senderId === senderId) {
2127
+ this.invalidateRouteOperation(k);
1924
2128
  const sessionId = this.deleteByKey(k);
1925
2129
  if (sessionId)
1926
2130
  removedIds.push(sessionId);
1927
2131
  }
1928
2132
  }
2133
+ for (const [key, operation] of [...this.creatingSessions]) {
2134
+ if (operation.target.channelName === channelName && operation.target.senderId === senderId) {
2135
+ this.invalidateRouteOperation(key);
2136
+ }
2137
+ }
1929
2138
  }
1930
2139
  if (removedIds.length > 0)
1931
2140
  this.persist();
@@ -1936,6 +2145,7 @@ var SessionRouter = class {
1936
2145
  let removed = false;
1937
2146
  for (const [key, mappedSessionId] of [...this.toSession.entries()]) {
1938
2147
  if (mappedSessionId === sessionId) {
2148
+ this.invalidateRouteOperation(key);
1939
2149
  this.toSession.delete(key);
1940
2150
  removed = true;
1941
2151
  }
@@ -1946,6 +2156,7 @@ var SessionRouter = class {
1946
2156
  if (this.toCwd.delete(sessionId)) {
1947
2157
  removed = true;
1948
2158
  }
2159
+ this.liveSessionIds.delete(sessionId);
1949
2160
  if (!removed && this.sessionLoadWindows.size > 0) {
1950
2161
  for (const loadWindow of this.sessionLoadWindows) {
1951
2162
  loadWindow.add(sessionId);
@@ -1956,6 +2167,17 @@ var SessionRouter = class {
1956
2167
  }
1957
2168
  return removed;
1958
2169
  }
2170
+ handleSessionDied(sessionId) {
2171
+ if (this.recoveryMode === "eager") {
2172
+ return this.removeSessionId(sessionId);
2173
+ }
2174
+ const known = this.toTarget.has(sessionId);
2175
+ this.liveSessionIds.delete(sessionId);
2176
+ for (const loadWindow of this.sessionLoadWindows) {
2177
+ loadWindow.add(sessionId);
2178
+ }
2179
+ return known;
2180
+ }
1959
2181
  deleteByKey(key) {
1960
2182
  const sessionId = this.toSession.get(key);
1961
2183
  if (!sessionId)
@@ -1963,6 +2185,7 @@ var SessionRouter = class {
1963
2185
  this.toSession.delete(key);
1964
2186
  this.toTarget.delete(sessionId);
1965
2187
  this.toCwd.delete(sessionId);
2188
+ this.liveSessionIds.delete(sessionId);
1966
2189
  return sessionId;
1967
2190
  }
1968
2191
  promoteTargetToGroup(sessionId, isGroup) {
@@ -1985,45 +2208,69 @@ var SessionRouter = class {
1985
2208
  }
1986
2209
  return entries;
1987
2210
  }
2211
+ restoreRoutes() {
2212
+ if (this.recoveryMode !== "lazy") {
2213
+ throw new Error("restoreRoutes requires lazy recovery mode");
2214
+ }
2215
+ const persisted = this.readPersistedEntries();
2216
+ if (!persisted)
2217
+ return { restored: 0, dropped: 0 };
2218
+ this.dispose();
2219
+ let restored = 0;
2220
+ for (const [key, entry] of Object.entries(persisted.entries)) {
2221
+ this.toSession.set(key, entry.sessionId);
2222
+ this.toTarget.set(entry.sessionId, entry.target);
2223
+ this.toCwd.set(entry.sessionId, entry.cwd);
2224
+ restored++;
2225
+ }
2226
+ if (persisted.dropped > 0)
2227
+ this.persist();
2228
+ return { restored, dropped: persisted.dropped };
2229
+ }
1988
2230
  /**
1989
2231
  * Restore session mappings from a previous bridge.
1990
2232
  * Called after bridge restart — attempts loadSession for each saved mapping.
1991
2233
  * Failed loads are dropped (new session on next message).
1992
2234
  */
1993
2235
  async restoreSessions() {
1994
- const persistPath = this.persistPath;
1995
- if (!persistPath || !existsSync3(persistPath)) {
1996
- return { restored: 0, failed: 0 };
1997
- }
1998
- let entries;
1999
- try {
2000
- entries = JSON.parse(readFileSync3(persistPath, "utf-8"));
2001
- } catch (err) {
2002
- const reason = err instanceof Error ? err.message : String(err);
2003
- process2.stderr.write(`[SessionRouter] Corrupted persist file at ${sanitizeLogText(persistPath, 1024)}: ${sanitizeLogText(reason, 512)}
2004
- `);
2236
+ const persisted = this.readPersistedEntries();
2237
+ if (!persisted)
2005
2238
  return { restored: 0, failed: 0 };
2006
- }
2239
+ const entries = persisted.entries;
2240
+ const restoreGeneration = this.lifecycleGeneration;
2007
2241
  let restored = 0;
2008
2242
  let failed = 0;
2009
- let changed = false;
2243
+ let changed = persisted.dropped > 0;
2010
2244
  const reservations = /* @__PURE__ */ new Map();
2245
+ for (const key of persisted.droppedKeys) {
2246
+ this.deleteByKey(key);
2247
+ }
2011
2248
  for (const key of Object.keys(entries)) {
2012
2249
  this.deleteByKey(key);
2013
2250
  const reservation = this.createSessionReservation();
2014
2251
  reservation.promise.catch(() => void 0);
2015
- this.creatingSessions.set(key, reservation.promise);
2016
- reservations.set(key, reservation);
2252
+ const operation = this.createSessionOperation(key, entries[key].target, () => reservation.promise);
2253
+ operation.promise.catch(() => void 0);
2254
+ this.creatingSessions.set(key, operation);
2255
+ reservations.set(key, { reservation, operation });
2017
2256
  }
2018
2257
  const loadWindow = this.beginSessionLoad();
2019
2258
  try {
2020
2259
  for (const [key, entry] of Object.entries(entries)) {
2021
- const reservation = reservations.get(key);
2022
- if (!reservation)
2260
+ const reserved = reservations.get(key);
2261
+ if (!reserved)
2023
2262
  continue;
2263
+ const { reservation, operation } = reserved;
2024
2264
  try {
2265
+ this.assertOperationCurrent(operation);
2025
2266
  const options = this.sessionOptions(entry.target.channelName);
2026
- const sessionId = options ? await this.bridge.loadSession(entry.sessionId, entry.cwd, options) : await this.bridge.loadSession(entry.sessionId, entry.cwd);
2267
+ const sessionId = await this.bridge.loadSession(entry.sessionId, entry.cwd, options, operation);
2268
+ try {
2269
+ this.assertOperationCurrent(operation);
2270
+ } catch (error) {
2271
+ this.scheduleDiscardInvalidatedSession(sessionId, operation);
2272
+ throw error;
2273
+ }
2027
2274
  if (typeof sessionId !== "string" || sessionId.length === 0) {
2028
2275
  throw new Error("Invalid restored session ID");
2029
2276
  }
@@ -2046,26 +2293,36 @@ var SessionRouter = class {
2046
2293
  failed++;
2047
2294
  changed = true;
2048
2295
  } finally {
2049
- if (this.creatingSessions.get(key) === reservation.promise) {
2296
+ if (this.creatingSessions.get(key) === operation) {
2050
2297
  this.creatingSessions.delete(key);
2051
2298
  }
2299
+ this.releaseRouteToken(key, operation);
2052
2300
  }
2053
2301
  }
2054
2302
  } finally {
2055
2303
  this.endSessionLoad(loadWindow);
2056
2304
  }
2057
- if (changed) {
2305
+ if (changed && restoreGeneration === this.lifecycleGeneration) {
2058
2306
  this.persist();
2059
2307
  }
2060
2308
  return { restored, failed };
2061
2309
  }
2062
- /** Clear in-memory state and delete persist file. Used on clean shutdown. */
2063
- clearAll() {
2310
+ dispose() {
2311
+ this.lifecycleGeneration++;
2312
+ for (const operation of this.creatingSessions.values()) {
2313
+ this.invalidateOperation(operation);
2314
+ }
2064
2315
  this.toSession.clear();
2065
2316
  this.toTarget.clear();
2066
2317
  this.toCwd.clear();
2067
2318
  this.creatingSessions.clear();
2068
2319
  this.sessionLoadWindows.clear();
2320
+ this.liveSessionIds.clear();
2321
+ this.routeTokens.clear();
2322
+ }
2323
+ /** Clear in-memory state and delete persist file. Used on clean shutdown. */
2324
+ clearAll() {
2325
+ this.dispose();
2069
2326
  if (this.persistPath && existsSync3(this.persistPath)) {
2070
2327
  try {
2071
2328
  unlinkSync(this.persistPath);
@@ -2073,30 +2330,105 @@ var SessionRouter = class {
2073
2330
  }
2074
2331
  }
2075
2332
  }
2333
+ readPersistedEntries() {
2334
+ const persistPath = this.persistPath;
2335
+ if (!persistPath || !existsSync3(persistPath))
2336
+ return void 0;
2337
+ let parsed;
2338
+ try {
2339
+ parsed = JSON.parse(readFileSync3(persistPath, "utf-8"));
2340
+ } catch (error) {
2341
+ const quarantinePath = `${persistPath}.corrupt-${Date.now()}`;
2342
+ try {
2343
+ renameSync2(persistPath, quarantinePath);
2344
+ } catch {
2345
+ }
2346
+ process2.stderr.write(`[SessionRouter] Corrupted persist file at ${sanitizeLogText(persistPath, 1024)}: ${sanitizeLogText(error instanceof Error ? error.message : String(error), 512)}
2347
+ `);
2348
+ return void 0;
2349
+ }
2350
+ if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) {
2351
+ const quarantinePath = `${persistPath}.corrupt-${Date.now()}`;
2352
+ try {
2353
+ renameSync2(persistPath, quarantinePath);
2354
+ } catch {
2355
+ }
2356
+ process2.stderr.write(`[SessionRouter] Invalid route store at ${sanitizeLogText(persistPath, 1024)}: expected an object
2357
+ `);
2358
+ return void 0;
2359
+ }
2360
+ const entries = {};
2361
+ const droppedKeys = [];
2362
+ for (const [key, value] of Object.entries(parsed)) {
2363
+ if (this.isPersistedEntry(value))
2364
+ entries[key] = value;
2365
+ else
2366
+ droppedKeys.push(key);
2367
+ }
2368
+ return { entries, dropped: droppedKeys.length, droppedKeys };
2369
+ }
2370
+ isPersistedEntry(value) {
2371
+ if (typeof value !== "object" || value === null)
2372
+ return false;
2373
+ const entry = value;
2374
+ const target = entry["target"];
2375
+ if (typeof target !== "object" || target === null)
2376
+ return false;
2377
+ const typedTarget = target;
2378
+ return typeof entry["sessionId"] === "string" && entry["sessionId"].length > 0 && typeof entry["cwd"] === "string" && entry["cwd"].length > 0 && typeof typedTarget["channelName"] === "string" && typeof typedTarget["senderId"] === "string" && typeof typedTarget["chatId"] === "string" && (typedTarget["threadId"] === void 0 || typeof typedTarget["threadId"] === "string") && (typedTarget["isGroup"] === void 0 || typeof typedTarget["isGroup"] === "boolean");
2379
+ }
2076
2380
  persist() {
2077
2381
  if (!this.persistPath)
2078
2382
  return;
2079
2383
  const data = {};
2080
2384
  for (const [key, sessionId] of this.toSession) {
2081
2385
  const target = this.toTarget.get(sessionId);
2082
- if (target) {
2083
- data[key] = {
2084
- sessionId,
2085
- target,
2086
- cwd: this.toCwd.get(sessionId) || this.defaultCwd
2087
- };
2088
- }
2386
+ if (!target)
2387
+ continue;
2388
+ data[key] = {
2389
+ sessionId,
2390
+ target,
2391
+ cwd: this.toCwd.get(sessionId) ?? this.defaultCwd
2392
+ };
2089
2393
  }
2394
+ const dir = dirname2(this.persistPath);
2395
+ const tempPath = join4(dir, `${Date.now()}-${process2.pid}-${Math.random().toString(16).slice(2)}.tmp`);
2090
2396
  try {
2091
- writeFileSync3(this.persistPath, JSON.stringify(data, null, 2), "utf-8");
2092
- } catch {
2397
+ mkdirSync3(dir, { recursive: true, mode: 448 });
2398
+ try {
2399
+ chmodSync2(dir, 448);
2400
+ } catch {
2401
+ }
2402
+ writeFileSync3(tempPath, JSON.stringify(data, null, 2), {
2403
+ encoding: "utf-8",
2404
+ mode: 384
2405
+ });
2406
+ renameSync2(tempPath, this.persistPath);
2407
+ try {
2408
+ chmodSync2(this.persistPath, 384);
2409
+ } catch {
2410
+ }
2411
+ } catch (error) {
2412
+ process2.stderr.write(`[SessionRouter] Failed to persist routes at ${sanitizeLogText(this.persistPath, 1024)}: ${sanitizeLogText(error instanceof Error ? error.message : String(error), 512)}
2413
+ `);
2414
+ } finally {
2415
+ try {
2416
+ rmSync(tempPath, { force: true });
2417
+ } catch {
2418
+ }
2093
2419
  }
2094
2420
  }
2095
- async createLiveSession(cwd, loadWindow, routingKey, options) {
2421
+ async createLiveSession(cwd, loadWindow, routingKey, options, operation) {
2096
2422
  const maxAttempts = 2;
2097
2423
  let lastDeadSessionId;
2098
2424
  for (let attempt = 0; attempt < maxAttempts; attempt++) {
2099
- const sessionId = options ? await this.bridge.newSession(cwd, options) : await this.bridge.newSession(cwd);
2425
+ const sessionId = await this.bridge.newSession(cwd, options, operation);
2426
+ try {
2427
+ this.assertOperationCurrent(operation);
2428
+ } catch (error) {
2429
+ this.scheduleDiscardInvalidatedSession(sessionId, operation);
2430
+ throw error;
2431
+ }
2100
2432
  if (typeof sessionId !== "string" || sessionId.length === 0) {
2101
2433
  throw new Error("Invalid session ID from bridge");
2102
2434
  }
@@ -2112,6 +2444,65 @@ var SessionRouter = class {
2112
2444
  this.sessionLoadWindows.add(loadWindow);
2113
2445
  return loadWindow;
2114
2446
  }
2447
+ createSessionOperation(key, target, run) {
2448
+ let routeToken = this.routeTokens.get(key);
2449
+ if (!routeToken) {
2450
+ routeToken = {};
2451
+ this.routeTokens.set(key, routeToken);
2452
+ }
2453
+ const operation = {
2454
+ promise: Promise.resolve(""),
2455
+ target,
2456
+ lifecycleGeneration: this.lifecycleGeneration,
2457
+ routeToken
2458
+ };
2459
+ operation.promise = Promise.resolve().then(() => run(operation)).catch((error) => {
2460
+ this.assertOperationCurrent(operation);
2461
+ throw error;
2462
+ });
2463
+ return operation;
2464
+ }
2465
+ invalidateRouteOperation(key) {
2466
+ this.routeTokens.delete(key);
2467
+ const operation = this.creatingSessions.get(key);
2468
+ if (!operation)
2469
+ return;
2470
+ this.invalidateOperation(operation);
2471
+ this.creatingSessions.delete(key);
2472
+ }
2473
+ invalidateOperation(operation) {
2474
+ operation.invalidationError ??= new Error("Session route operation was invalidated");
2475
+ }
2476
+ assertOperationCurrent(operation) {
2477
+ if (operation.lifecycleGeneration !== this.lifecycleGeneration) {
2478
+ this.invalidateOperation(operation);
2479
+ }
2480
+ if (operation.invalidationError) {
2481
+ throw operation.invalidationError;
2482
+ }
2483
+ }
2484
+ assertOperationResultCurrent(key, sessionId, operation) {
2485
+ if (operation.routeToken !== this.routeTokens.get(key)) {
2486
+ this.invalidateOperation(operation);
2487
+ }
2488
+ if (this.toSession.get(key) !== sessionId) {
2489
+ this.invalidateOperation(operation);
2490
+ }
2491
+ this.assertOperationCurrent(operation);
2492
+ }
2493
+ releaseRouteToken(key, operation) {
2494
+ if (this.routeTokens.get(key) === operation.routeToken && !this.toSession.has(key) && !this.creatingSessions.has(key)) {
2495
+ this.routeTokens.delete(key);
2496
+ }
2497
+ }
2498
+ scheduleDiscardInvalidatedSession(sessionId, operation) {
2499
+ if ([...this.toSession.values()].includes(sessionId))
2500
+ return;
2501
+ try {
2502
+ void this.bridge.discardSession?.(sessionId, operation).catch(() => void 0);
2503
+ } catch {
2504
+ }
2505
+ }
2115
2506
  createSessionReservation() {
2116
2507
  let resolveReservation;
2117
2508
  let rejectReservation;
@@ -2750,7 +3141,7 @@ var ChannelBase = class {
2750
3141
  this.memoryScope = Object.freeze(this.resolveMemoryScope(name, config));
2751
3142
  this.channelMemory = options?.channelMemory;
2752
3143
  this.memoryIntentClassifier = options?.memoryIntentClassifier;
2753
- this.groupHistory = new GroupHistoryStore(options?.groupHistoryPath ?? join4(getGlobalQwenDir(), "channels", `${encodeURIComponent(name)}-group-history.jsonl`));
3144
+ this.groupHistory = new GroupHistoryStore(options?.groupHistoryPath ?? join5(getGlobalQwenDir(), "channels", `${encodeURIComponent(name)}-group-history.jsonl`));
2754
3145
  this.loopController = options?.loopController;
2755
3146
  this.groupGate = new GroupGate(config.groupPolicy, config.groups);
2756
3147
  this.dmGate = new DmGate(config.dmPolicy);
@@ -3444,7 +3835,7 @@ ${sanitizePromptText(job.prompt)}`;
3444
3835
  onToolCall(_chatId, _event) {
3445
3836
  }
3446
3837
  onSessionDied(sessionId) {
3447
- this.router.removeSessionId(sessionId);
3838
+ this.router.handleSessionDied(sessionId);
3448
3839
  this.instructedSessions.delete(sessionId);
3449
3840
  this.removePendingPermissionsForSession(sessionId);
3450
3841
  }
@@ -3492,13 +3883,16 @@ ${sanitizePromptText(job.prompt)}`;
3492
3883
  */
3493
3884
  onResponseBoundary(_chatId, _sessionId) {
3494
3885
  }
3886
+ async sendResponseMessage(chatId, text, _sessionId) {
3887
+ await this.sendMessage(chatId, text);
3888
+ }
3495
3889
  /**
3496
3890
  * Called when the agent's full response is ready.
3497
3891
  * Override to customize delivery (e.g., finalize an AI card).
3498
- * Default: calls sendMessage() with the full response text.
3892
+ * Default: sends the full response text.
3499
3893
  */
3500
- async onResponseComplete(chatId, fullText, _sessionId) {
3501
- await this.sendMessage(chatId, fullText);
3894
+ async onResponseComplete(chatId, fullText, sessionId) {
3895
+ await this.sendResponseMessage(chatId, fullText, sessionId);
3502
3896
  }
3503
3897
  /**
3504
3898
  * Register a slash command handler. Subclasses can call this to add
@@ -4909,12 +5303,14 @@ ${promptToSend}`;
4909
5303
  minChars: this.config.blockStreamingChunk?.minChars ?? 400,
4910
5304
  maxChars: this.config.blockStreamingChunk?.maxChars ?? 1e3,
4911
5305
  idleMs: this.config.blockStreamingCoalesce?.idleMs ?? 1500,
4912
- send: /* @__PURE__ */ __name((text) => this.sendMessage(envelope.chatId, text), "send")
5306
+ send: /* @__PURE__ */ __name((text) => this.sendResponseMessage(envelope.chatId, text, sessionId), "send")
4913
5307
  }) : null;
4914
5308
  promptState.stopStreaming = () => streamer?.stop();
4915
5309
  const heldChunks = [];
5310
+ let hasStreamedText = false;
4916
5311
  const releaseHeldChunks = /* @__PURE__ */ __name(() => {
4917
5312
  for (const held of heldChunks.splice(0)) {
5313
+ hasStreamedText = true;
4918
5314
  this.emitTaskLifecycle({
4919
5315
  ...this.lifecycleBase(envelope.chatId, sessionId, envelope.messageId),
4920
5316
  type: "text_chunk",
@@ -4938,6 +5334,7 @@ ${promptToSend}`;
4938
5334
  return;
4939
5335
  }
4940
5336
  heldChunks.length = 0;
5337
+ hasStreamedText = false;
4941
5338
  this.onResponseBoundary(envelope.chatId, sessionId);
4942
5339
  streamer?.stop();
4943
5340
  }, "onResponseBoundary");
@@ -4956,6 +5353,9 @@ ${promptToSend}`;
4956
5353
  if (!promptState.cancelled && response) {
4957
5354
  promptState.deliveryStarted = true;
4958
5355
  if (streamer) {
5356
+ if (!hasStreamedText) {
5357
+ streamer.push(response);
5358
+ }
4959
5359
  await streamer.flush();
4960
5360
  } else {
4961
5361
  await this.onResponseComplete(envelope.chatId, response, sessionId);