@qwen-code/qwen-code 0.19.9 → 0.19.10-nightly.20260715.c538bd70d

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 +8 -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-LOOBDOTZ.js} +31 -31
  13. package/chunks/{StandaloneSessionPicker-WS4GXYOG.js → StandaloneSessionPicker-76CLZSH2.js} +51 -49
  14. package/chunks/{acpAgent-5FWSOZL5.js → acpAgent-DFJOK7EB.js} +567 -482
  15. package/chunks/{agent-HOLHB3RT.js → agent-OJQWXNHP.js} +26 -26
  16. package/chunks/{agent-headless-SXL6H56A.js → agent-headless-ND7GOORY.js} +26 -26
  17. package/chunks/{anthropicContentGenerator-L73TO3DB.js → anthropicContentGenerator-56U3YCP2.js} +5 -5
  18. package/chunks/{artifact-tool-U7IRTLIV.js → artifact-tool-MIZLXBLF.js} +2 -2
  19. package/chunks/{askUserQuestion-2DLUUZZG.js → askUserQuestion-XMJVPNWM.js} +2 -2
  20. package/chunks/{bridge-BCJQ7BBB.js → bridge-SNJK2JLK.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-YSFB4HUU.js +418 -0
  24. package/chunks/channel-worker-supervisor-QCKIOYZD.js +20 -0
  25. package/chunks/{chunk-CCDMCZPP.js → chunk-26UABK2C.js} +1 -1
  26. package/chunks/{chunk-LXNEJD34.js → chunk-2FO5GFKZ.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-CLFKOZEK.js → chunk-3XULHBC7.js} +1 -1
  31. package/chunks/chunk-4QZADKJS.js +34 -0
  32. package/chunks/{chunk-E2IY465S.js → chunk-4UDHAJFV.js} +10 -10
  33. package/chunks/{chunk-5U27BZ72.js → chunk-55SAYASQ.js} +190 -77
  34. package/chunks/chunk-5HBA2Z7V.js +28 -0
  35. package/chunks/{chunk-ZJE7NSL3.js → chunk-5M6IDOMF.js} +34 -97
  36. package/chunks/{chunk-HVY356M2.js → chunk-5SQ55XJZ.js} +3 -3
  37. package/chunks/{chunk-EAXLGSFP.js → chunk-6GRAQNTY.js} +8 -8
  38. package/chunks/{chunk-K434OPES.js → chunk-6WPJRYLZ.js} +3 -3
  39. package/chunks/{chunk-VWPVHAMO.js → chunk-7DXHIMXL.js} +5 -1
  40. package/chunks/{chunk-J4TSQ5EQ.js → chunk-7NFB7LBQ.js} +8 -1
  41. package/chunks/{chunk-5SFOMFG4.js → chunk-7R4DPSRA.js} +36 -2
  42. package/chunks/{chunk-W2UIXQDL.js → chunk-7STBROEV.js} +1 -1
  43. package/chunks/{chunk-BMGVRZN4.js → chunk-AETEZU4U.js} +1 -1
  44. package/chunks/{chunk-HPDUL5MF.js → chunk-AGZWN4WV.js} +1 -1
  45. package/chunks/{chunk-RDJSGHZE.js → chunk-ALGGS7UH.js} +1 -38
  46. package/chunks/{chunk-GWHYEOV2.js → chunk-ARKANCNX.js} +2 -1
  47. package/chunks/{chunk-34Z3U5RQ.js → chunk-AU4R7ACM.js} +518 -114
  48. package/chunks/{channel-worker-supervisor-WSOAAYUO.js → chunk-B7MFJBKE.js} +67 -35
  49. package/chunks/{chunk-524RQP4Q.js → chunk-B7NUUEXC.js} +10 -4
  50. package/chunks/{chunk-MC23XKFE.js → chunk-BLPMRN4B.js} +3 -3
  51. package/chunks/{chunk-A3XKDTSH.js → chunk-BRRKAUGR.js} +4 -4
  52. package/chunks/{chunk-W3JHSWRP.js → chunk-BUPLOPUA.js} +4 -4
  53. package/chunks/{chunk-3VAGG5T5.js → chunk-BYOOK22F.js} +121 -16
  54. package/chunks/{chunk-EMDMPBJ4.js → chunk-C47ENMZJ.js} +3 -3
  55. package/chunks/{chunk-3AHXV67U.js → chunk-C5TVXLJZ.js} +1 -1
  56. package/chunks/{chunk-X6TJ3YZV.js → chunk-CGT5TQIZ.js} +159 -57
  57. package/chunks/{chunk-4C5BQ2D2.js → chunk-CQQD7MDG.js} +82 -12
  58. package/chunks/{chunk-KKNMOEZH.js → chunk-E2UVIFI2.js} +185 -398
  59. package/chunks/{chunk-P67PFTUT.js → chunk-EPY4ZEU6.js} +4 -4
  60. package/chunks/{chunk-6PESIEKJ.js → chunk-EZSRHWGS.js} +68 -6
  61. package/chunks/{chunk-4GORAUCN.js → chunk-F333XEAU.js} +1 -1
  62. package/chunks/{chunk-YLV3XXFB.js → chunk-FBU7WRZI.js} +17 -1
  63. package/chunks/{chunk-Q6I5QHMH.js → chunk-FGTCZJOD.js} +1 -1
  64. package/chunks/{chunk-LK7KUE55.js → chunk-FSA7ERJ2.js} +1 -1
  65. package/chunks/{chunk-B4G2WOFA.js → chunk-FTU55ZZ7.js} +3 -3
  66. package/chunks/{chunk-EGYZ275M.js → chunk-GCD7PEDZ.js} +4 -4
  67. package/chunks/{chunk-SJHDYNHF.js → chunk-GDQQRV43.js} +3 -3
  68. package/chunks/{chunk-3BTRNWWD.js → chunk-GOXKNSDZ.js} +1 -64
  69. package/chunks/{chunk-GZRTYZ2R.js → chunk-GQKWT45X.js} +154 -1
  70. package/chunks/chunk-GYTKQYDB.js +23 -0
  71. package/chunks/{chunk-YVEDCAUE.js → chunk-HGT6JR3U.js} +19 -0
  72. package/chunks/{chunk-N3EMS75V.js → chunk-HKM2TEF7.js} +1268 -1233
  73. package/chunks/chunk-IDS7MSUP.js +74 -0
  74. package/chunks/{chunk-PVZM22CK.js → chunk-INKAZNYC.js} +5 -5
  75. package/chunks/{chunk-3G7CIHVV.js → chunk-IOQ75R4R.js} +4 -4
  76. package/chunks/{chunk-AURZZYMD.js → chunk-IQOOJSPR.js} +4 -4
  77. package/chunks/{chunk-AKIVHSJR.js → chunk-J4UQXGVL.js} +111 -93
  78. package/chunks/{chunk-VTU57BWZ.js → chunk-JEKOCLRN.js} +1 -1
  79. package/chunks/{chunk-B5ORX3FG.js → chunk-JGUT3LWZ.js} +6 -1
  80. package/chunks/{chunk-PDZ7MBDG.js → chunk-JIQHT2O6.js} +27 -6
  81. package/chunks/{chunk-XUOOWUZS.js → chunk-JPAH76WA.js} +1 -1
  82. package/chunks/{chunk-BAPGSC7U.js → chunk-K4LG6TVJ.js} +23 -9
  83. package/chunks/chunk-KET3M4K4.js +493 -0
  84. package/chunks/{chunk-ORBGV7NJ.js → chunk-KKRTYONM.js} +6 -4
  85. package/chunks/{chunk-SCGXUJBT.js → chunk-KPA5QGN2.js} +3 -3
  86. package/chunks/{chunk-IAVB3HM3.js → chunk-KSO42X3Z.js} +13 -0
  87. package/chunks/{chunk-4QLQE5WJ.js → chunk-L5U3ELZX.js} +1 -1
  88. package/chunks/{chunk-77XJ3SWN.js → chunk-LIUEXYPL.js} +5 -5
  89. package/chunks/{chunk-4ZVWQHEQ.js → chunk-LQIDP6K5.js} +1 -1
  90. package/chunks/{chunk-34MW4KTI.js → chunk-LT5CRUA5.js} +2 -2
  91. package/chunks/{chunk-DC5Z3DU6.js → chunk-LXLTBIDP.js} +43 -6
  92. package/chunks/{chunk-VA4KQY6V.js → chunk-MEK7CQJR.js} +3 -3
  93. package/chunks/{chunk-KHUQZZJ6.js → chunk-MO7O5722.js} +370 -36
  94. package/chunks/chunk-MR3PXB6E.js +48 -0
  95. package/chunks/{chunk-PODM4SZ4.js → chunk-MV52C5MA.js} +5 -5
  96. package/chunks/{chunk-WL4L7EZH.js → chunk-OA4JVLSA.js} +27 -1
  97. package/chunks/{chunk-X4NKFGFJ.js → chunk-OJAMDVF5.js} +0 -15
  98. package/chunks/{chunk-BZIFY5TF.js → chunk-OKAIGAYW.js} +3 -3
  99. package/chunks/{chunk-ECNYL4AA.js → chunk-OPNPGO6D.js} +1 -1
  100. package/chunks/{chunk-3SJSQXNS.js → chunk-PEJWA3QQ.js} +12 -8
  101. package/chunks/{chunk-MXL5UP4X.js → chunk-Q6TUALBE.js} +1 -1
  102. package/chunks/{chunk-QYMQSECS.js → chunk-QAW7PIHT.js} +2 -2
  103. package/chunks/{chunk-5HOMWMCL.js → chunk-QEDYXCLG.js} +4167 -1338
  104. package/chunks/chunk-QNNTA7IX.js +91 -0
  105. package/chunks/{chunk-D2GFWEXB.js → chunk-QNT5T4Q2.js} +6 -6
  106. package/chunks/{chunk-CUMMSHH6.js → chunk-R5XLNDE2.js} +1 -1
  107. package/chunks/{chunk-LUODI7WD.js → chunk-RCEEXIOO.js} +6 -4
  108. package/chunks/{chunk-WQUQVGTF.js → chunk-RQWDLG6Z.js} +183 -96
  109. package/chunks/{chunk-XYQSMABS.js → chunk-SLCVZX6F.js} +4 -4
  110. package/chunks/{chunk-CEA3E3JB.js → chunk-SPJQO2CE.js} +2 -2
  111. package/chunks/{chunk-JSG7ZSBC.js → chunk-TQBODCFD.js} +1 -1
  112. package/chunks/chunk-TV6K2FB4.js +224 -0
  113. package/chunks/{chunk-5XUCZNSY.js → chunk-TYLOFD2U.js} +1 -1
  114. package/chunks/{chunk-CNEIYWSA.js → chunk-UKWAQ7AV.js} +5 -5
  115. package/chunks/{chunk-7PU4FYLG.js → chunk-US4YQT62.js} +4 -4
  116. package/chunks/{chunk-Q4YQW46J.js → chunk-UYPPCIJQ.js} +36 -18
  117. package/chunks/{chunk-YAUFFXDS.js → chunk-UZKG7HFG.js} +12 -11
  118. package/chunks/{chunk-GWLSNBG4.js → chunk-VQLRHJKL.js} +30 -26
  119. package/chunks/{chunk-L6P4KPHR.js → chunk-VRUHAVZS.js} +59 -39
  120. package/chunks/{chunk-HKMAENAO.js → chunk-W2U4RJJU.js} +8 -6
  121. package/chunks/{chunk-ATAKVRIF.js → chunk-WDSCTLAB.js} +7 -7
  122. package/chunks/{chunk-ZLXQN2QS.js → chunk-WIEO4CWB.js} +1 -1
  123. package/chunks/{chunk-OQ4DRIOA.js → chunk-WJOC24IW.js} +2 -2
  124. package/chunks/{chunk-J3JA76CF.js → chunk-WTNZ6DXB.js} +1 -1
  125. package/chunks/{chunk-NVYTCB5Z.js → chunk-XCR44EEA.js} +14589 -13980
  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-D5SKC4YG.js → chunk-ZBAROUR6.js} +41 -13
  129. package/chunks/{chunk-U2NNEY4R.js → chunk-ZEEVKDO7.js} +1 -1
  130. package/chunks/{chunk-5VXNZWGF.js → chunk-ZLOHB76C.js} +1 -1
  131. package/chunks/{chunk-JZETEN3Z.js → chunk-ZNCLTRNU.js} +3 -3
  132. package/chunks/{chunk-TO6QE22P.js → chunk-ZP4ZZJJG.js} +26 -22
  133. package/chunks/{chunk-UOZWKTQG.js → chunk-ZPAHLFZU.js} +2 -2
  134. package/chunks/{chunk-XLA62MYB.js → chunk-ZTXZ7FM4.js} +2 -2
  135. package/chunks/{computer-use-HM37RX6A.js → computer-use-DRETHEQF.js} +26 -26
  136. package/chunks/{config-utils-NV2SVGPB.js → config-utils-XSHOMMK4.js} +3 -2
  137. package/chunks/{contextCommand-OF5SFGH2.js → contextCommand-7YJUW23J.js} +28 -28
  138. package/chunks/{create-sub-session-INX7TXJI.js → create-sub-session-EAB2U5XW.js} +2 -2
  139. package/chunks/{create-sub-session-KPRT7ECJ.js → create-sub-session-L5HOZAEL.js} +26 -26
  140. package/chunks/{cron-create-AMBKGZX6.js → cron-create-GMVKSXZT.js} +4 -4
  141. package/chunks/{cron-delete-LRU4OJYG.js → cron-delete-VDZKUAVK.js} +4 -4
  142. package/chunks/{cron-list-WVP2JXER.js → cron-list-UG7C7RAR.js} +4 -4
  143. package/chunks/{daemon-ARHTSTXP.js → daemon-MI5HF26N.js} +603 -62
  144. package/chunks/{daemon-status-provider-B2UTZUJ2.js → daemon-status-provider-2D47GOJT.js} +36 -36
  145. package/chunks/{de-EBJN3OVN.js → de-2VCDRDGU.js} +4 -1
  146. package/chunks/{dist-WKPOYU7O.js → dist-IEXZC5ZR.js} +1 -1
  147. package/chunks/{dist-XKU3ABM5.js → dist-PQK4GCKA.js} +1 -1
  148. package/chunks/{dist-VHV4EVHG.js → dist-U75JK3PF.js} +1 -1
  149. package/chunks/{dist-R7LN5AZE.js → dist-VXO7QBON.js} +2 -2
  150. package/chunks/{dist-PNVLTKTL.js → dist-WH4TZSH3.js} +158 -4
  151. package/chunks/{dist-QYCAEZIT.js → dist-X2ABIW5R.js} +5 -1
  152. package/chunks/{earlyInputCapture-3VTHRC4C.js → earlyInputCapture-OJQPGCSX.js} +27 -27
  153. package/chunks/{edit-VNI4NJ73.js → edit-LZOAFLT2.js} +27 -27
  154. package/chunks/{en-5A6LA7RK.js → en-NJCA3TAA.js} +5 -1
  155. package/chunks/{enter-worktree-IYYBKPZT.js → enter-worktree-VL2TCGI5.js} +26 -26
  156. package/chunks/{enterPlanMode-GMC5FD5A.js → enterPlanMode-QGHBHZWI.js} +42 -27
  157. package/chunks/{environment-5HSSRMJ7.js → environment-2G5IC2EU.js} +30 -29
  158. package/chunks/{errors-HMFCJJ7P.js → errors-7QNQDNI2.js} +28 -28
  159. package/chunks/{exit-worktree-6BHCMP5G.js → exit-worktree-5V3X2MRH.js} +26 -26
  160. package/chunks/{exitPlanMode-CJW7G74W.js → exitPlanMode-XDPNQB4H.js} +26 -26
  161. package/chunks/{fast-path-FRDMDVHG.js → fast-path-NNSD4BVZ.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-RKDUWGXJ.js} +139 -76
  165. package/chunks/{geminiContentGenerator-J7YNZDYP.js → geminiContentGenerator-V7QGHXVF.js} +4 -4
  166. package/chunks/{glob-BRCSGFOT.js → glob-ZNQUUOTS.js} +28 -27
  167. package/chunks/{grep-EE2DUOSY.js → grep-NYIGLM7R.js} +26 -26
  168. package/chunks/{handleAutoUpdate-5NWTLR67.js → handleAutoUpdate-UBQ4IQXY.js} +30 -30
  169. package/chunks/{i18n-BASPENNQ.js → i18n-5T3S6SGP.js} +27 -27
  170. package/chunks/initializer-TJED246Q.js +73 -0
  171. package/chunks/{installationInfo-W6V4DT7W.js → installationInfo-OTEU7FKR.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-6OHS7MFJ.js +76 -0
  175. package/chunks/loadedSettingsAdapter-5456XIYG.js +70 -0
  176. package/chunks/{loop-wakeup-WX7BLWWP.js → loop-wakeup-C4EXLYVA.js} +5 -5
  177. package/chunks/{ls-ZB2BDP6T.js → ls-2OUTG3IZ.js} +4 -4
  178. package/chunks/{lsp-V5DN4YUJ.js → lsp-4VMNXZW6.js} +2 -2
  179. package/chunks/mcp-NOWRPFKY.js +70 -0
  180. package/chunks/{monitor-X5Z3H4FY.js → monitor-CVDZO3IZ.js} +26 -26
  181. package/chunks/nonInteractiveCli-UGI7Y43E.js +129 -0
  182. package/chunks/{notebook-edit-TRM2QIJK.js → notebook-edit-NWIA5TEJ.js} +27 -27
  183. package/chunks/{openaiContentGenerator-AAYONPMF.js → openaiContentGenerator-KJONBBJO.js} +12 -12
  184. package/chunks/{pidfile-D4I4FTVA.js → pidfile-L3TGXMTF.js} +27 -27
  185. package/chunks/{pt-2C6YCSHL.js → pt-TFZO5Y6T.js} +4 -1
  186. package/chunks/{qwenContentGenerator-K3HZ2H76.js → qwenContentGenerator-GXUZB5SJ.js} +28 -28
  187. package/chunks/{qwenOAuth2-PJQ27GSO.js → qwenOAuth2-LEYOU7RU.js} +5 -5
  188. package/chunks/{read-file-7SZSIZOL.js → read-file-I4OUZXTA.js} +8 -8
  189. package/chunks/{read-mcp-resource-SM5DA4RG.js → read-mcp-resource-JUFHCKSC.js} +2 -2
  190. package/chunks/{record-artifact-4XKZX3UW.js → record-artifact-DWSMBXYY.js} +2 -2
  191. package/chunks/{ripGrep-YNPFVCZP.js → ripGrep-XLCXANIO.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-R6SBP6YS.js} +1232 -371
  194. package/chunks/{runtime-57WWRVHN.js → runtime-U3S33YUQ.js} +42 -37
  195. package/chunks/{scheduler-YBLGWSIL.js → scheduler-65QCIELP.js} +26 -26
  196. package/chunks/{send-message-F36YD6KQ.js → send-message-JZ752NWD.js} +3 -3
  197. package/chunks/{serve-R63NK3CV.js → serve-PSPOFCOD.js} +36 -34
  198. package/chunks/{server-Z22GCAXP.js → server-6P5ZB56O.js} +5561 -1377
  199. package/chunks/{session-HKAAI7BN.js → session-ILLOYW75.js} +298 -98
  200. package/chunks/{settings-3EYN66GK.js → settings-RMUJGYIK.js} +34 -32
  201. package/chunks/{shell-6YXINTWJ.js → shell-65GTAN5Q.js} +28 -26
  202. package/chunks/{skill-OO57P4X6.js → skill-L76U3YCX.js} +10 -10
  203. package/chunks/{spawnChannel-JD7G4VU6.js → spawnChannel-LXIGZ4EM.js} +28 -28
  204. package/chunks/{src-G5UPLZSZ.js → src-DWZT2X3Z.js} +87 -27
  205. package/chunks/{standalone-update-OB7F4JPZ.js → standalone-update-F6SRKPSD.js} +28 -28
  206. package/chunks/{startInteractiveUI-73EGLIIH.js → startInteractiveUI-UEJQP7S3.js} +730 -397
  207. package/chunks/{syntheticOutput-34H7LGA7.js → syntheticOutput-LELY6HAI.js} +3 -3
  208. package/chunks/{task-create-FRGOEIKY.js → task-create-QY3BIMNM.js} +8 -7
  209. package/chunks/{task-list-OW766BXZ.js → task-list-D2U47WBJ.js} +6 -5
  210. package/chunks/{task-stop-SIR5SNBN.js → task-stop-N6E5IYLH.js} +2 -2
  211. package/chunks/{task-update-YRA532MT.js → task-update-HJCQILLB.js} +8 -7
  212. package/chunks/{team-create-PECAAPXK.js → team-create-4QBZVOGN.js} +26 -26
  213. package/chunks/{team-delete-6OSECUZC.js → team-delete-RCWYDRF4.js} +6 -5
  214. package/chunks/{team-plan-approval-L6F434RY.js → team-plan-approval-BK4CIOFV.js} +26 -26
  215. package/chunks/{theme-manager-ZG4RY6GU.js → theme-manager-5F2IGW6E.js} +27 -27
  216. package/chunks/{todoWrite-YDMFEV4G.js → todoWrite-FKCGATPJ.js} +4 -4
  217. package/chunks/{tool-search-THVIWAPB.js → tool-search-J2ESO33H.js} +9 -9
  218. package/chunks/{total-session-admission-JOKNRIIA.js → total-session-admission-U4LZ5QTQ.js} +33 -33
  219. package/chunks/tree-sitter-YJVE2ZUK.js +2980 -0
  220. package/chunks/{trustedFolders-EOGT3UVS.js → trustedFolders-TIDOXCJA.js} +29 -28
  221. package/chunks/types-ML3TRJQ5.js +16 -0
  222. package/chunks/{updateCheck-2KYEYVSB.js → updateCheck-VRVR26FI.js} +29 -29
  223. package/chunks/{validateNonInterActiveAuth-EN6ZQSR2.js → validateNonInterActiveAuth-UGKYAVLG.js} +75 -71
  224. package/chunks/{version-3UEA6ZIR.js → version-7HR6VZAT.js} +1 -1
  225. package/chunks/{web-fetch-PAAEQKBW.js → web-fetch-QGODBB6S.js} +5 -5
  226. package/chunks/{workflow-QCCCMYP3.js → workflow-EDQAITEW.js} +27 -27
  227. package/chunks/workspace-providers-status-27UGAK77.js +73 -0
  228. package/chunks/workspace-registration-store-5H7577YQ.js +27 -0
  229. package/chunks/{workspace-registry-24QFLQYH.js → workspace-registry-F3THGAXC.js} +33 -33
  230. package/chunks/workspace-service-4JSAQAHP.js +86 -0
  231. package/chunks/workspace-skills-status-5JTWZHZU.js +72 -0
  232. package/chunks/{write-file-I3MUDRIE.js → write-file-UY6XCZZM.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-CObt_TK9.js} +1 -1
  247. package/web-shell/assets/{architectureDiagram-3BPJPVTR-B-At37J_.js → architectureDiagram-3BPJPVTR-B7aiJ6CK.js} +1 -1
  248. package/web-shell/assets/{blockDiagram-GPEHLZMM-B51wjcU7.js → blockDiagram-GPEHLZMM-BSK2CrID.js} +1 -1
  249. package/web-shell/assets/{c4Diagram-AAUBKEIU-xBK7BAwN.js → c4Diagram-AAUBKEIU-Bhx2p7T_.js} +1 -1
  250. package/web-shell/assets/channel-BBaLq8MV.js +1 -0
  251. package/web-shell/assets/{chunk-2J33WTMH-xKmLg7Yr.js → chunk-2J33WTMH-c3Hzv0Ni.js} +1 -1
  252. package/web-shell/assets/{chunk-4BX2VUAB-BfkdKZCM.js → chunk-4BX2VUAB-DNXaK7ZF.js} +1 -1
  253. package/web-shell/assets/{chunk-55IACEB6-DT713sZf.js → chunk-55IACEB6-BXjvDj_i.js} +1 -1
  254. package/web-shell/assets/{chunk-727SXJPM-CYEeAamv.js → chunk-727SXJPM-B6CaKFp-.js} +1 -1
  255. package/web-shell/assets/{chunk-AQP2D5EJ-DBN-5CFd.js → chunk-AQP2D5EJ-tij6Mz9B.js} +1 -1
  256. package/web-shell/assets/{chunk-FMBD7UC4-CGZKk4PH.js → chunk-FMBD7UC4-DdlsGk2h.js} +1 -1
  257. package/web-shell/assets/{chunk-ND2GUHAM-qQbC2O-y.js → chunk-ND2GUHAM-CdgGZSHE.js} +1 -1
  258. package/web-shell/assets/{chunk-QZHKN3VN-B3zeXwsX.js → chunk-QZHKN3VN-D8oJn1C0.js} +1 -1
  259. package/web-shell/assets/classDiagram-4FO5ZUOK-B2ZK6sWE.js +1 -0
  260. package/web-shell/assets/classDiagram-v2-Q7XG4LA2-B2ZK6sWE.js +1 -0
  261. package/web-shell/assets/{cose-bilkent-S5V4N54A-BKsl1Wvy.js → cose-bilkent-S5V4N54A-BUVmNp1Y.js} +1 -1
  262. package/web-shell/assets/{dagre-BM42HDAG-CuuuLiBK.js → dagre-BM42HDAG-CO4q310O.js} +1 -1
  263. package/web-shell/assets/{diagram-2AECGRRQ-CG4_eKiV.js → diagram-2AECGRRQ-C6gFvWkg.js} +1 -1
  264. package/web-shell/assets/{diagram-5GNKFQAL-DSFTmZB1.js → diagram-5GNKFQAL-NG2I_c0h.js} +1 -1
  265. package/web-shell/assets/{diagram-KO2AKTUF-BxwlEHn8.js → diagram-KO2AKTUF-DFKMS6I9.js} +1 -1
  266. package/web-shell/assets/{diagram-LMA3HP47-BUAg-jMG.js → diagram-LMA3HP47-BiElfsfP.js} +1 -1
  267. package/web-shell/assets/{diagram-OG6HWLK6-BFM2jlO5.js → diagram-OG6HWLK6-zLWDYUqu.js} +1 -1
  268. package/web-shell/assets/{erDiagram-TEJ5UH35-CerbFPa2.js → erDiagram-TEJ5UH35-DoVaazhK.js} +1 -1
  269. package/web-shell/assets/{flowDiagram-I6XJVG4X-BNeZz5Zz.js → flowDiagram-I6XJVG4X-0RLz-mXg.js} +1 -1
  270. package/web-shell/assets/{ganttDiagram-6RSMTGT7-CTOogLaM.js → ganttDiagram-6RSMTGT7-C-eX1A39.js} +3 -3
  271. package/web-shell/assets/{gitGraphDiagram-PVQCEYII-yxSFkXPj.js → gitGraphDiagram-PVQCEYII-BauQu1Bu.js} +1 -1
  272. package/web-shell/assets/index-3uAT3ehO.css +5 -0
  273. package/web-shell/assets/index-CVHa2QH7.js +3 -0
  274. package/web-shell/assets/index-D1KigWat.js +1128 -0
  275. package/web-shell/assets/{infoDiagram-5YYISTIA-DYdAUevm.js → infoDiagram-5YYISTIA-C800cFvZ.js} +1 -1
  276. package/web-shell/assets/{ishikawaDiagram-YF4QCWOH-CNuijZ90.js → ishikawaDiagram-YF4QCWOH-CFK1Jk6e.js} +1 -1
  277. package/web-shell/assets/{journeyDiagram-JHISSGLW-BTyiuonf.js → journeyDiagram-JHISSGLW-Cjx0WAC4.js} +1 -1
  278. package/web-shell/assets/{kanban-definition-UN3LZRKU-DPJo0Uow.js → kanban-definition-UN3LZRKU-DWMDHbiv.js} +1 -1
  279. package/web-shell/assets/{linear-C8wKCbIC.js → linear-vpW4FrZs.js} +1 -1
  280. package/web-shell/assets/{mermaid.core-BV5o7nW5.js → mermaid.core-DsHRUnDd.js} +5 -5
  281. package/web-shell/assets/{mindmap-definition-RKZ34NQL-BtLcBmSt.js → mindmap-definition-RKZ34NQL-D3Eb1cAK.js} +1 -1
  282. package/web-shell/assets/{pieDiagram-4H26LBE5-C22J7A9Q.js → pieDiagram-4H26LBE5-Cr2-6sWt.js} +1 -1
  283. package/web-shell/assets/{quadrantDiagram-W4KKPZXB-DSL10wiL.js → quadrantDiagram-W4KKPZXB-Yd7yUgVp.js} +1 -1
  284. package/web-shell/assets/{requirementDiagram-4Y6WPE33-feqh0UpX.js → requirementDiagram-4Y6WPE33-BE6SprL8.js} +1 -1
  285. package/web-shell/assets/{sankeyDiagram-5OEKKPKP-Z4OVaWaZ.js → sankeyDiagram-5OEKKPKP-DzkuMK8d.js} +1 -1
  286. package/web-shell/assets/{sequenceDiagram-3UESZ5HK-DIluIcb1.js → sequenceDiagram-3UESZ5HK-wD9A3Dhi.js} +1 -1
  287. package/web-shell/assets/{stateDiagram-AJRCARHV-hlhnuoYH.js → stateDiagram-AJRCARHV-BOp5q1Nm.js} +1 -1
  288. package/web-shell/assets/stateDiagram-v2-BHNVJYJU-BDsWUmPG.js +1 -0
  289. package/web-shell/assets/{timeline-definition-PNZ67QCA-Dqf_CqgL.js → timeline-definition-PNZ67QCA-Btc08sUA.js} +1 -1
  290. package/web-shell/assets/{vennDiagram-CIIHVFJN-DD2QhaTX.js → vennDiagram-CIIHVFJN-Bv6upsOA.js} +1 -1
  291. package/web-shell/assets/{wardley-L42UT6IY-B2uI85U_.js → wardley-L42UT6IY-D-XamnCK.js} +1 -1
  292. package/web-shell/assets/{wardleyDiagram-YWT4CUSO-U1aJX71g.js → wardleyDiagram-YWT4CUSO-BbP_5Wfp.js} +1 -1
  293. package/web-shell/assets/{xychartDiagram-2RQKCTM6-C0ODHUee.js → xychartDiagram-2RQKCTM6-CO5Hh28b.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
  }
@@ -1004,6 +1080,10 @@ var DaemonChannelBridge = class extends EventEmitter2 {
1004
1080
  case "tool_call_update": {
1005
1081
  const toolCallId = getString(update["toolCallId"]);
1006
1082
  const kind = getString(update["kind"]);
1083
+ const meta = isRecord(update["_meta"]) ? update["_meta"] : void 0;
1084
+ if (!kind && toolCallId && getString(update["status"]) === "in_progress" && meta?.["shellProgress"] !== void 0) {
1085
+ break;
1086
+ }
1007
1087
  if (!toolCallId || !kind) {
1008
1088
  this.emitProtocolError(`Malformed daemon ${type} event`, update);
1009
1089
  break;
@@ -1123,14 +1203,26 @@ var DaemonChannelBridge = class extends EventEmitter2 {
1123
1203
  handleSessionDied(sessionId, data) {
1124
1204
  this.dropSession(sessionId, this.getStringField(data, "reason", "session_died"));
1125
1205
  }
1126
- dropSession(sessionId, reason) {
1127
- if (!this.sessions.has(sessionId)) {
1206
+ dropSession(sessionId, reason, releaseClient = true) {
1207
+ const session = this.removeSessionBinding(sessionId);
1208
+ if (!session)
1128
1209
  return;
1210
+ if (releaseClient) {
1211
+ void this.releaseSessionClient(session).catch((error) => {
1212
+ this.lastError = error;
1213
+ });
1129
1214
  }
1215
+ this.emit("sessionDied", { sessionId, reason });
1216
+ }
1217
+ removeSessionBinding(sessionId) {
1218
+ const session = this.sessions.get(sessionId);
1219
+ if (!session)
1220
+ return void 0;
1130
1221
  this.resolveTurnBarrier(sessionId);
1131
1222
  this.eventControllers.get(sessionId)?.abort();
1132
1223
  this.eventControllers.delete(sessionId);
1133
1224
  this.sessions.delete(sessionId);
1225
+ this.sessionBindingTokens.delete(sessionId);
1134
1226
  this.abortActivePrompts(sessionId);
1135
1227
  this.activePrompts.delete(sessionId);
1136
1228
  this.availableCommandsBySession.delete(sessionId);
@@ -1147,7 +1239,7 @@ var DaemonChannelBridge = class extends EventEmitter2 {
1147
1239
  this.respondedRequestToSession.delete(requestId);
1148
1240
  }
1149
1241
  }
1150
- this.emit("sessionDied", { sessionId, reason });
1242
+ return session;
1151
1243
  }
1152
1244
  getStringField(data, field, fallback) {
1153
1245
  return isRecord(data) && typeof data[field] === "string" ? data[field] : fallback;
@@ -1295,7 +1387,7 @@ var BlockStreamer = class {
1295
1387
 
1296
1388
  // packages/channels/base/dist/ChannelBase.js
1297
1389
  init_esbuild_shims();
1298
- import { basename, join as join4 } from "node:path";
1390
+ import { basename, join as join5 } from "node:path";
1299
1391
 
1300
1392
  // packages/channels/base/dist/GroupGate.js
1301
1393
  init_esbuild_shims();
@@ -1770,7 +1862,8 @@ __name(generateCode, "generateCode");
1770
1862
 
1771
1863
  // packages/channels/base/dist/SessionRouter.js
1772
1864
  init_esbuild_shims();
1773
- import { existsSync as existsSync3, readFileSync as readFileSync3, writeFileSync as writeFileSync3, unlinkSync } from "node:fs";
1865
+ import { chmodSync as chmodSync2, existsSync as existsSync3, mkdirSync as mkdirSync3, readFileSync as readFileSync3, renameSync as renameSync2, rmSync, unlinkSync, writeFileSync as writeFileSync3 } from "node:fs";
1866
+ import { dirname as dirname2, join as join4 } from "node:path";
1774
1867
  import process2 from "node:process";
1775
1868
  var SessionRouter = class {
1776
1869
  static {
@@ -1784,17 +1877,22 @@ var SessionRouter = class {
1784
1877
  // session ID → cwd
1785
1878
  creatingSessions = /* @__PURE__ */ new Map();
1786
1879
  sessionLoadWindows = /* @__PURE__ */ new Set();
1880
+ liveSessionIds = /* @__PURE__ */ new Set();
1881
+ routeTokens = /* @__PURE__ */ new Map();
1882
+ lifecycleGeneration = 0;
1787
1883
  bridge;
1788
1884
  defaultCwd;
1789
1885
  defaultScope;
1790
1886
  channelScopes = /* @__PURE__ */ new Map();
1791
1887
  channelApprovalModes = /* @__PURE__ */ new Map();
1792
1888
  persistPath;
1793
- constructor(bridge, defaultCwd, scope = "user", persistPath) {
1889
+ recoveryMode;
1890
+ constructor(bridge, defaultCwd, scope = "user", persistPath, options = {}) {
1794
1891
  this.bridge = bridge;
1795
1892
  this.defaultCwd = defaultCwd;
1796
1893
  this.defaultScope = scope;
1797
1894
  this.persistPath = persistPath;
1895
+ this.recoveryMode = options.recoveryMode ?? "eager";
1798
1896
  }
1799
1897
  /** Replace the bridge instance (used after crash recovery restart). */
1800
1898
  setBridge(bridge) {
@@ -1829,60 +1927,168 @@ var SessionRouter = class {
1829
1927
  }
1830
1928
  async resolve(channelName, senderId, chatId, threadId, cwd, isGroup, options) {
1831
1929
  const key = this.routingKey(channelName, senderId, chatId, options?.routingThreadId ?? threadId);
1832
- let failedCreateWaits = 0;
1930
+ const input = {
1931
+ channelName,
1932
+ senderId,
1933
+ chatId,
1934
+ threadId,
1935
+ cwd: cwd || this.defaultCwd,
1936
+ isGroup
1937
+ };
1938
+ let failedWaits = 0;
1833
1939
  for (; ; ) {
1834
1940
  const existing = this.toSession.get(key);
1835
- if (existing) {
1941
+ if (existing && this.isLive(existing)) {
1836
1942
  this.promoteTargetToGroup(existing, isGroup);
1837
1943
  return existing;
1838
1944
  }
1839
1945
  const creating = this.creatingSessions.get(key);
1840
1946
  if (creating) {
1841
1947
  try {
1842
- const sessionId = await creating;
1948
+ const sessionId = await creating.promise;
1949
+ try {
1950
+ this.assertOperationResultCurrent(key, sessionId, creating);
1951
+ } catch (error) {
1952
+ this.scheduleDiscardInvalidatedSession(sessionId, creating);
1953
+ throw error;
1954
+ }
1843
1955
  this.promoteTargetToGroup(sessionId, isGroup);
1844
1956
  return sessionId;
1845
- } catch (err) {
1957
+ } catch (error) {
1958
+ if (creating.invalidationError) {
1959
+ throw creating.invalidationError;
1960
+ }
1846
1961
  if (this.creatingSessions.get(key) === creating) {
1847
1962
  this.creatingSessions.delete(key);
1848
1963
  }
1849
- failedCreateWaits++;
1850
- if (failedCreateWaits > 3) {
1851
- throw err;
1852
- }
1964
+ this.releaseRouteToken(key, creating);
1965
+ failedWaits++;
1966
+ if (failedWaits > 3)
1967
+ throw error;
1853
1968
  continue;
1854
1969
  }
1855
1970
  }
1856
- const created = Promise.resolve().then(async () => {
1857
- const sessionCwd = cwd || this.defaultCwd;
1858
- const loadWindow = this.beginSessionLoad();
1971
+ const operation = this.createSessionOperation(key, {
1972
+ channelName: input.channelName,
1973
+ senderId: input.senderId,
1974
+ chatId: input.chatId,
1975
+ threadId: input.threadId,
1976
+ isGroup: input.isGroup
1977
+ }, (currentOperation) => existing ? this.loadOrReplaceSession(key, existing, input, currentOperation) : this.createAndStoreSession(key, input, currentOperation));
1978
+ this.creatingSessions.set(key, operation);
1979
+ try {
1980
+ const sessionId = await operation.promise;
1859
1981
  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);
1982
+ this.assertOperationResultCurrent(key, sessionId, operation);
1983
+ } catch (error) {
1984
+ this.scheduleDiscardInvalidatedSession(sessionId, operation);
1985
+ throw error;
1874
1986
  }
1875
- });
1876
- this.creatingSessions.set(key, created);
1877
- try {
1878
- return await created;
1987
+ this.promoteTargetToGroup(sessionId, isGroup);
1988
+ return sessionId;
1879
1989
  } finally {
1880
- if (this.creatingSessions.get(key) === created) {
1990
+ if (this.creatingSessions.get(key) === operation) {
1881
1991
  this.creatingSessions.delete(key);
1882
1992
  }
1993
+ this.releaseRouteToken(key, operation);
1883
1994
  }
1884
1995
  }
1885
1996
  }
1997
+ isLive(sessionId) {
1998
+ return this.recoveryMode === "eager" || this.liveSessionIds.has(sessionId);
1999
+ }
2000
+ async createAndStoreSession(key, input, operation) {
2001
+ const loadWindow = this.beginSessionLoad();
2002
+ try {
2003
+ const sessionId = await this.createLiveSession(input.cwd, loadWindow, key, this.sessionOptions(input.channelName), operation);
2004
+ try {
2005
+ this.assertOperationCurrent(operation);
2006
+ } catch (error) {
2007
+ this.scheduleDiscardInvalidatedSession(sessionId, operation);
2008
+ throw error;
2009
+ }
2010
+ this.toSession.set(key, sessionId);
2011
+ this.toTarget.set(sessionId, {
2012
+ channelName: input.channelName,
2013
+ senderId: input.senderId,
2014
+ chatId: input.chatId,
2015
+ threadId: input.threadId,
2016
+ isGroup: input.isGroup
2017
+ });
2018
+ this.toCwd.set(sessionId, input.cwd);
2019
+ this.liveSessionIds.add(sessionId);
2020
+ this.persist();
2021
+ return sessionId;
2022
+ } finally {
2023
+ this.endSessionLoad(loadWindow);
2024
+ }
2025
+ }
2026
+ async loadOrReplaceSession(key, savedSessionId, input, operation) {
2027
+ const savedCwd = this.toCwd.get(savedSessionId) ?? input.cwd;
2028
+ const loadWindow = this.beginSessionLoad();
2029
+ try {
2030
+ try {
2031
+ const loadedSessionId = await this.bridge.loadSession(savedSessionId, savedCwd, this.sessionOptions(input.channelName), operation);
2032
+ try {
2033
+ this.assertOperationCurrent(operation);
2034
+ if (this.toSession.get(key) !== savedSessionId) {
2035
+ this.invalidateOperation(operation);
2036
+ this.assertOperationCurrent(operation);
2037
+ }
2038
+ } catch (error) {
2039
+ this.scheduleDiscardInvalidatedSession(loadedSessionId, operation);
2040
+ throw error;
2041
+ }
2042
+ if (typeof loadedSessionId !== "string" || loadedSessionId.length === 0 || loadWindow.delete(loadedSessionId)) {
2043
+ throw new Error("Invalid or dead restored session ID");
2044
+ }
2045
+ if (loadedSessionId !== savedSessionId) {
2046
+ const target = this.toTarget.get(savedSessionId);
2047
+ this.deleteByKey(key);
2048
+ this.toSession.set(key, loadedSessionId);
2049
+ if (target)
2050
+ this.toTarget.set(loadedSessionId, target);
2051
+ this.toCwd.set(loadedSessionId, savedCwd);
2052
+ this.persist();
2053
+ }
2054
+ this.liveSessionIds.add(loadedSessionId);
2055
+ return loadedSessionId;
2056
+ } catch (loadError) {
2057
+ this.assertOperationCurrent(operation);
2058
+ try {
2059
+ const replacement = await this.createLiveSession(input.cwd, loadWindow, key, this.sessionOptions(input.channelName), operation);
2060
+ try {
2061
+ this.assertOperationCurrent(operation);
2062
+ } catch (error) {
2063
+ this.scheduleDiscardInvalidatedSession(replacement, operation);
2064
+ throw error;
2065
+ }
2066
+ this.deleteByKey(key);
2067
+ this.toSession.set(key, replacement);
2068
+ this.toTarget.set(replacement, {
2069
+ channelName: input.channelName,
2070
+ senderId: input.senderId,
2071
+ chatId: input.chatId,
2072
+ threadId: input.threadId,
2073
+ isGroup: input.isGroup
2074
+ });
2075
+ this.toCwd.set(replacement, input.cwd);
2076
+ this.liveSessionIds.add(replacement);
2077
+ this.persist();
2078
+ 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)}
2079
+ `);
2080
+ return replacement;
2081
+ } catch (createError) {
2082
+ this.assertOperationCurrent(operation);
2083
+ 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)})
2084
+ `);
2085
+ throw createError;
2086
+ }
2087
+ }
2088
+ } finally {
2089
+ this.endSessionLoad(loadWindow);
2090
+ }
2091
+ }
1886
2092
  getTarget(sessionId) {
1887
2093
  return this.toTarget.get(sessionId);
1888
2094
  }
@@ -1912,6 +2118,7 @@ var SessionRouter = class {
1912
2118
  const scope = this.channelScopes.get(channelName) || this.defaultScope;
1913
2119
  if (chatId) {
1914
2120
  const key = this.routingKey(channelName, senderId, chatId, threadId);
2121
+ this.invalidateRouteOperation(key);
1915
2122
  const sessionId = this.deleteByKey(key);
1916
2123
  if (sessionId)
1917
2124
  removedIds.push(sessionId);
@@ -1921,11 +2128,17 @@ var SessionRouter = class {
1921
2128
  for (const [k, mappedSessionId] of [...this.toSession.entries()]) {
1922
2129
  const target = this.toTarget.get(mappedSessionId);
1923
2130
  if (target?.channelName === channelName && target.senderId === senderId) {
2131
+ this.invalidateRouteOperation(k);
1924
2132
  const sessionId = this.deleteByKey(k);
1925
2133
  if (sessionId)
1926
2134
  removedIds.push(sessionId);
1927
2135
  }
1928
2136
  }
2137
+ for (const [key, operation] of [...this.creatingSessions]) {
2138
+ if (operation.target.channelName === channelName && operation.target.senderId === senderId) {
2139
+ this.invalidateRouteOperation(key);
2140
+ }
2141
+ }
1929
2142
  }
1930
2143
  if (removedIds.length > 0)
1931
2144
  this.persist();
@@ -1936,6 +2149,7 @@ var SessionRouter = class {
1936
2149
  let removed = false;
1937
2150
  for (const [key, mappedSessionId] of [...this.toSession.entries()]) {
1938
2151
  if (mappedSessionId === sessionId) {
2152
+ this.invalidateRouteOperation(key);
1939
2153
  this.toSession.delete(key);
1940
2154
  removed = true;
1941
2155
  }
@@ -1946,6 +2160,7 @@ var SessionRouter = class {
1946
2160
  if (this.toCwd.delete(sessionId)) {
1947
2161
  removed = true;
1948
2162
  }
2163
+ this.liveSessionIds.delete(sessionId);
1949
2164
  if (!removed && this.sessionLoadWindows.size > 0) {
1950
2165
  for (const loadWindow of this.sessionLoadWindows) {
1951
2166
  loadWindow.add(sessionId);
@@ -1956,6 +2171,17 @@ var SessionRouter = class {
1956
2171
  }
1957
2172
  return removed;
1958
2173
  }
2174
+ handleSessionDied(sessionId) {
2175
+ if (this.recoveryMode === "eager") {
2176
+ return this.removeSessionId(sessionId);
2177
+ }
2178
+ const known = this.toTarget.has(sessionId);
2179
+ this.liveSessionIds.delete(sessionId);
2180
+ for (const loadWindow of this.sessionLoadWindows) {
2181
+ loadWindow.add(sessionId);
2182
+ }
2183
+ return known;
2184
+ }
1959
2185
  deleteByKey(key) {
1960
2186
  const sessionId = this.toSession.get(key);
1961
2187
  if (!sessionId)
@@ -1963,6 +2189,7 @@ var SessionRouter = class {
1963
2189
  this.toSession.delete(key);
1964
2190
  this.toTarget.delete(sessionId);
1965
2191
  this.toCwd.delete(sessionId);
2192
+ this.liveSessionIds.delete(sessionId);
1966
2193
  return sessionId;
1967
2194
  }
1968
2195
  promoteTargetToGroup(sessionId, isGroup) {
@@ -1985,45 +2212,69 @@ var SessionRouter = class {
1985
2212
  }
1986
2213
  return entries;
1987
2214
  }
2215
+ restoreRoutes() {
2216
+ if (this.recoveryMode !== "lazy") {
2217
+ throw new Error("restoreRoutes requires lazy recovery mode");
2218
+ }
2219
+ const persisted = this.readPersistedEntries();
2220
+ if (!persisted)
2221
+ return { restored: 0, dropped: 0 };
2222
+ this.dispose();
2223
+ let restored = 0;
2224
+ for (const [key, entry] of Object.entries(persisted.entries)) {
2225
+ this.toSession.set(key, entry.sessionId);
2226
+ this.toTarget.set(entry.sessionId, entry.target);
2227
+ this.toCwd.set(entry.sessionId, entry.cwd);
2228
+ restored++;
2229
+ }
2230
+ if (persisted.dropped > 0)
2231
+ this.persist();
2232
+ return { restored, dropped: persisted.dropped };
2233
+ }
1988
2234
  /**
1989
2235
  * Restore session mappings from a previous bridge.
1990
2236
  * Called after bridge restart — attempts loadSession for each saved mapping.
1991
2237
  * Failed loads are dropped (new session on next message).
1992
2238
  */
1993
2239
  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
- `);
2240
+ const persisted = this.readPersistedEntries();
2241
+ if (!persisted)
2005
2242
  return { restored: 0, failed: 0 };
2006
- }
2243
+ const entries = persisted.entries;
2244
+ const restoreGeneration = this.lifecycleGeneration;
2007
2245
  let restored = 0;
2008
2246
  let failed = 0;
2009
- let changed = false;
2247
+ let changed = persisted.dropped > 0;
2010
2248
  const reservations = /* @__PURE__ */ new Map();
2249
+ for (const key of persisted.droppedKeys) {
2250
+ this.deleteByKey(key);
2251
+ }
2011
2252
  for (const key of Object.keys(entries)) {
2012
2253
  this.deleteByKey(key);
2013
2254
  const reservation = this.createSessionReservation();
2014
2255
  reservation.promise.catch(() => void 0);
2015
- this.creatingSessions.set(key, reservation.promise);
2016
- reservations.set(key, reservation);
2256
+ const operation = this.createSessionOperation(key, entries[key].target, () => reservation.promise);
2257
+ operation.promise.catch(() => void 0);
2258
+ this.creatingSessions.set(key, operation);
2259
+ reservations.set(key, { reservation, operation });
2017
2260
  }
2018
2261
  const loadWindow = this.beginSessionLoad();
2019
2262
  try {
2020
2263
  for (const [key, entry] of Object.entries(entries)) {
2021
- const reservation = reservations.get(key);
2022
- if (!reservation)
2264
+ const reserved = reservations.get(key);
2265
+ if (!reserved)
2023
2266
  continue;
2267
+ const { reservation, operation } = reserved;
2024
2268
  try {
2269
+ this.assertOperationCurrent(operation);
2025
2270
  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);
2271
+ const sessionId = await this.bridge.loadSession(entry.sessionId, entry.cwd, options, operation);
2272
+ try {
2273
+ this.assertOperationCurrent(operation);
2274
+ } catch (error) {
2275
+ this.scheduleDiscardInvalidatedSession(sessionId, operation);
2276
+ throw error;
2277
+ }
2027
2278
  if (typeof sessionId !== "string" || sessionId.length === 0) {
2028
2279
  throw new Error("Invalid restored session ID");
2029
2280
  }
@@ -2046,26 +2297,36 @@ var SessionRouter = class {
2046
2297
  failed++;
2047
2298
  changed = true;
2048
2299
  } finally {
2049
- if (this.creatingSessions.get(key) === reservation.promise) {
2300
+ if (this.creatingSessions.get(key) === operation) {
2050
2301
  this.creatingSessions.delete(key);
2051
2302
  }
2303
+ this.releaseRouteToken(key, operation);
2052
2304
  }
2053
2305
  }
2054
2306
  } finally {
2055
2307
  this.endSessionLoad(loadWindow);
2056
2308
  }
2057
- if (changed) {
2309
+ if (changed && restoreGeneration === this.lifecycleGeneration) {
2058
2310
  this.persist();
2059
2311
  }
2060
2312
  return { restored, failed };
2061
2313
  }
2062
- /** Clear in-memory state and delete persist file. Used on clean shutdown. */
2063
- clearAll() {
2314
+ dispose() {
2315
+ this.lifecycleGeneration++;
2316
+ for (const operation of this.creatingSessions.values()) {
2317
+ this.invalidateOperation(operation);
2318
+ }
2064
2319
  this.toSession.clear();
2065
2320
  this.toTarget.clear();
2066
2321
  this.toCwd.clear();
2067
2322
  this.creatingSessions.clear();
2068
2323
  this.sessionLoadWindows.clear();
2324
+ this.liveSessionIds.clear();
2325
+ this.routeTokens.clear();
2326
+ }
2327
+ /** Clear in-memory state and delete persist file. Used on clean shutdown. */
2328
+ clearAll() {
2329
+ this.dispose();
2069
2330
  if (this.persistPath && existsSync3(this.persistPath)) {
2070
2331
  try {
2071
2332
  unlinkSync(this.persistPath);
@@ -2073,30 +2334,105 @@ var SessionRouter = class {
2073
2334
  }
2074
2335
  }
2075
2336
  }
2337
+ readPersistedEntries() {
2338
+ const persistPath = this.persistPath;
2339
+ if (!persistPath || !existsSync3(persistPath))
2340
+ return void 0;
2341
+ let parsed;
2342
+ try {
2343
+ parsed = JSON.parse(readFileSync3(persistPath, "utf-8"));
2344
+ } catch (error) {
2345
+ const quarantinePath = `${persistPath}.corrupt-${Date.now()}`;
2346
+ try {
2347
+ renameSync2(persistPath, quarantinePath);
2348
+ } catch {
2349
+ }
2350
+ process2.stderr.write(`[SessionRouter] Corrupted persist file at ${sanitizeLogText(persistPath, 1024)}: ${sanitizeLogText(error instanceof Error ? error.message : String(error), 512)}
2351
+ `);
2352
+ return void 0;
2353
+ }
2354
+ if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) {
2355
+ const quarantinePath = `${persistPath}.corrupt-${Date.now()}`;
2356
+ try {
2357
+ renameSync2(persistPath, quarantinePath);
2358
+ } catch {
2359
+ }
2360
+ process2.stderr.write(`[SessionRouter] Invalid route store at ${sanitizeLogText(persistPath, 1024)}: expected an object
2361
+ `);
2362
+ return void 0;
2363
+ }
2364
+ const entries = {};
2365
+ const droppedKeys = [];
2366
+ for (const [key, value] of Object.entries(parsed)) {
2367
+ if (this.isPersistedEntry(value))
2368
+ entries[key] = value;
2369
+ else
2370
+ droppedKeys.push(key);
2371
+ }
2372
+ return { entries, dropped: droppedKeys.length, droppedKeys };
2373
+ }
2374
+ isPersistedEntry(value) {
2375
+ if (typeof value !== "object" || value === null)
2376
+ return false;
2377
+ const entry = value;
2378
+ const target = entry["target"];
2379
+ if (typeof target !== "object" || target === null)
2380
+ return false;
2381
+ const typedTarget = target;
2382
+ 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");
2383
+ }
2076
2384
  persist() {
2077
2385
  if (!this.persistPath)
2078
2386
  return;
2079
2387
  const data = {};
2080
2388
  for (const [key, sessionId] of this.toSession) {
2081
2389
  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
- }
2390
+ if (!target)
2391
+ continue;
2392
+ data[key] = {
2393
+ sessionId,
2394
+ target,
2395
+ cwd: this.toCwd.get(sessionId) ?? this.defaultCwd
2396
+ };
2089
2397
  }
2398
+ const dir = dirname2(this.persistPath);
2399
+ const tempPath = join4(dir, `${Date.now()}-${process2.pid}-${Math.random().toString(16).slice(2)}.tmp`);
2090
2400
  try {
2091
- writeFileSync3(this.persistPath, JSON.stringify(data, null, 2), "utf-8");
2092
- } catch {
2401
+ mkdirSync3(dir, { recursive: true, mode: 448 });
2402
+ try {
2403
+ chmodSync2(dir, 448);
2404
+ } catch {
2405
+ }
2406
+ writeFileSync3(tempPath, JSON.stringify(data, null, 2), {
2407
+ encoding: "utf-8",
2408
+ mode: 384
2409
+ });
2410
+ renameSync2(tempPath, this.persistPath);
2411
+ try {
2412
+ chmodSync2(this.persistPath, 384);
2413
+ } catch {
2414
+ }
2415
+ } catch (error) {
2416
+ process2.stderr.write(`[SessionRouter] Failed to persist routes at ${sanitizeLogText(this.persistPath, 1024)}: ${sanitizeLogText(error instanceof Error ? error.message : String(error), 512)}
2417
+ `);
2418
+ } finally {
2419
+ try {
2420
+ rmSync(tempPath, { force: true });
2421
+ } catch {
2422
+ }
2093
2423
  }
2094
2424
  }
2095
- async createLiveSession(cwd, loadWindow, routingKey, options) {
2425
+ async createLiveSession(cwd, loadWindow, routingKey, options, operation) {
2096
2426
  const maxAttempts = 2;
2097
2427
  let lastDeadSessionId;
2098
2428
  for (let attempt = 0; attempt < maxAttempts; attempt++) {
2099
- const sessionId = options ? await this.bridge.newSession(cwd, options) : await this.bridge.newSession(cwd);
2429
+ const sessionId = await this.bridge.newSession(cwd, options, operation);
2430
+ try {
2431
+ this.assertOperationCurrent(operation);
2432
+ } catch (error) {
2433
+ this.scheduleDiscardInvalidatedSession(sessionId, operation);
2434
+ throw error;
2435
+ }
2100
2436
  if (typeof sessionId !== "string" || sessionId.length === 0) {
2101
2437
  throw new Error("Invalid session ID from bridge");
2102
2438
  }
@@ -2112,6 +2448,65 @@ var SessionRouter = class {
2112
2448
  this.sessionLoadWindows.add(loadWindow);
2113
2449
  return loadWindow;
2114
2450
  }
2451
+ createSessionOperation(key, target, run) {
2452
+ let routeToken = this.routeTokens.get(key);
2453
+ if (!routeToken) {
2454
+ routeToken = {};
2455
+ this.routeTokens.set(key, routeToken);
2456
+ }
2457
+ const operation = {
2458
+ promise: Promise.resolve(""),
2459
+ target,
2460
+ lifecycleGeneration: this.lifecycleGeneration,
2461
+ routeToken
2462
+ };
2463
+ operation.promise = Promise.resolve().then(() => run(operation)).catch((error) => {
2464
+ this.assertOperationCurrent(operation);
2465
+ throw error;
2466
+ });
2467
+ return operation;
2468
+ }
2469
+ invalidateRouteOperation(key) {
2470
+ this.routeTokens.delete(key);
2471
+ const operation = this.creatingSessions.get(key);
2472
+ if (!operation)
2473
+ return;
2474
+ this.invalidateOperation(operation);
2475
+ this.creatingSessions.delete(key);
2476
+ }
2477
+ invalidateOperation(operation) {
2478
+ operation.invalidationError ??= new Error("Session route operation was invalidated");
2479
+ }
2480
+ assertOperationCurrent(operation) {
2481
+ if (operation.lifecycleGeneration !== this.lifecycleGeneration) {
2482
+ this.invalidateOperation(operation);
2483
+ }
2484
+ if (operation.invalidationError) {
2485
+ throw operation.invalidationError;
2486
+ }
2487
+ }
2488
+ assertOperationResultCurrent(key, sessionId, operation) {
2489
+ if (operation.routeToken !== this.routeTokens.get(key)) {
2490
+ this.invalidateOperation(operation);
2491
+ }
2492
+ if (this.toSession.get(key) !== sessionId) {
2493
+ this.invalidateOperation(operation);
2494
+ }
2495
+ this.assertOperationCurrent(operation);
2496
+ }
2497
+ releaseRouteToken(key, operation) {
2498
+ if (this.routeTokens.get(key) === operation.routeToken && !this.toSession.has(key) && !this.creatingSessions.has(key)) {
2499
+ this.routeTokens.delete(key);
2500
+ }
2501
+ }
2502
+ scheduleDiscardInvalidatedSession(sessionId, operation) {
2503
+ if ([...this.toSession.values()].includes(sessionId))
2504
+ return;
2505
+ try {
2506
+ void this.bridge.discardSession?.(sessionId, operation).catch(() => void 0);
2507
+ } catch {
2508
+ }
2509
+ }
2115
2510
  createSessionReservation() {
2116
2511
  let resolveReservation;
2117
2512
  let rejectReservation;
@@ -2750,7 +3145,7 @@ var ChannelBase = class {
2750
3145
  this.memoryScope = Object.freeze(this.resolveMemoryScope(name, config));
2751
3146
  this.channelMemory = options?.channelMemory;
2752
3147
  this.memoryIntentClassifier = options?.memoryIntentClassifier;
2753
- this.groupHistory = new GroupHistoryStore(options?.groupHistoryPath ?? join4(getGlobalQwenDir(), "channels", `${encodeURIComponent(name)}-group-history.jsonl`));
3148
+ this.groupHistory = new GroupHistoryStore(options?.groupHistoryPath ?? join5(getGlobalQwenDir(), "channels", `${encodeURIComponent(name)}-group-history.jsonl`));
2754
3149
  this.loopController = options?.loopController;
2755
3150
  this.groupGate = new GroupGate(config.groupPolicy, config.groups);
2756
3151
  this.dmGate = new DmGate(config.dmPolicy);
@@ -3444,7 +3839,7 @@ ${sanitizePromptText(job.prompt)}`;
3444
3839
  onToolCall(_chatId, _event) {
3445
3840
  }
3446
3841
  onSessionDied(sessionId) {
3447
- this.router.removeSessionId(sessionId);
3842
+ this.router.handleSessionDied(sessionId);
3448
3843
  this.instructedSessions.delete(sessionId);
3449
3844
  this.removePendingPermissionsForSession(sessionId);
3450
3845
  }
@@ -3492,13 +3887,16 @@ ${sanitizePromptText(job.prompt)}`;
3492
3887
  */
3493
3888
  onResponseBoundary(_chatId, _sessionId) {
3494
3889
  }
3890
+ async sendResponseMessage(chatId, text, _sessionId) {
3891
+ await this.sendMessage(chatId, text);
3892
+ }
3495
3893
  /**
3496
3894
  * Called when the agent's full response is ready.
3497
3895
  * Override to customize delivery (e.g., finalize an AI card).
3498
- * Default: calls sendMessage() with the full response text.
3896
+ * Default: sends the full response text.
3499
3897
  */
3500
- async onResponseComplete(chatId, fullText, _sessionId) {
3501
- await this.sendMessage(chatId, fullText);
3898
+ async onResponseComplete(chatId, fullText, sessionId) {
3899
+ await this.sendResponseMessage(chatId, fullText, sessionId);
3502
3900
  }
3503
3901
  /**
3504
3902
  * Register a slash command handler. Subclasses can call this to add
@@ -4909,12 +5307,14 @@ ${promptToSend}`;
4909
5307
  minChars: this.config.blockStreamingChunk?.minChars ?? 400,
4910
5308
  maxChars: this.config.blockStreamingChunk?.maxChars ?? 1e3,
4911
5309
  idleMs: this.config.blockStreamingCoalesce?.idleMs ?? 1500,
4912
- send: /* @__PURE__ */ __name((text) => this.sendMessage(envelope.chatId, text), "send")
5310
+ send: /* @__PURE__ */ __name((text) => this.sendResponseMessage(envelope.chatId, text, sessionId), "send")
4913
5311
  }) : null;
4914
5312
  promptState.stopStreaming = () => streamer?.stop();
4915
5313
  const heldChunks = [];
5314
+ let hasStreamedText = false;
4916
5315
  const releaseHeldChunks = /* @__PURE__ */ __name(() => {
4917
5316
  for (const held of heldChunks.splice(0)) {
5317
+ hasStreamedText = true;
4918
5318
  this.emitTaskLifecycle({
4919
5319
  ...this.lifecycleBase(envelope.chatId, sessionId, envelope.messageId),
4920
5320
  type: "text_chunk",
@@ -4938,6 +5338,7 @@ ${promptToSend}`;
4938
5338
  return;
4939
5339
  }
4940
5340
  heldChunks.length = 0;
5341
+ hasStreamedText = false;
4941
5342
  this.onResponseBoundary(envelope.chatId, sessionId);
4942
5343
  streamer?.stop();
4943
5344
  }, "onResponseBoundary");
@@ -4956,6 +5357,9 @@ ${promptToSend}`;
4956
5357
  if (!promptState.cancelled && response) {
4957
5358
  promptState.deliveryStarted = true;
4958
5359
  if (streamer) {
5360
+ if (!hasStreamedText) {
5361
+ streamer.push(response);
5362
+ }
4959
5363
  await streamer.flush();
4960
5364
  } else {
4961
5365
  await this.onResponseComplete(envelope.chatId, response, sessionId);