@qwen-code/qwen-code 0.19.7 → 0.19.8-nightly.20260711.0ef3a76bd

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 (434) hide show
  1. package/bundled/qc-helper/SKILL.md +1 -0
  2. package/bundled/qc-helper/docs/configuration/auth.md +40 -55
  3. package/bundled/qc-helper/docs/configuration/model-providers.md +224 -218
  4. package/bundled/qc-helper/docs/configuration/settings.md +60 -51
  5. package/bundled/qc-helper/docs/features/_meta.ts +1 -0
  6. package/bundled/qc-helper/docs/features/channels/dingtalk.md +12 -2
  7. package/bundled/qc-helper/docs/features/channels/overview.md +86 -12
  8. package/bundled/qc-helper/docs/features/channels/plugins.md +1 -0
  9. package/bundled/qc-helper/docs/features/channels/wecom.md +6 -0
  10. package/bundled/qc-helper/docs/features/code-review.md +29 -5
  11. package/bundled/qc-helper/docs/features/commands.md +39 -38
  12. package/bundled/qc-helper/docs/features/computer-use.md +77 -0
  13. package/bundled/qc-helper/docs/features/hooks.md +36 -34
  14. package/bundled/qc-helper/docs/features/memory.md +1 -1
  15. package/bundled/qc-helper/docs/features/tool-use-summaries.md +19 -23
  16. package/bundled/qc-helper/docs/integration-vscode.md +2 -2
  17. package/bundled/qc-helper/docs/qwen-serve.md +40 -16
  18. package/bundled/qc-helper/docs/reference/keyboard-shortcuts.md +1 -1
  19. package/bundled/review/DESIGN.md +93 -22
  20. package/bundled/review/SKILL.md +300 -87
  21. package/chunks/MaxSizedBox-4CX4IQWE.js +70 -0
  22. package/chunks/{StandaloneSessionPicker-APISIRJZ.js → StandaloneSessionPicker-TYUSSNJ6.js} +79 -77
  23. package/chunks/{acpAgent-MMOSC2YA.js → acpAgent-5HJEXOPR.js} +978 -205
  24. package/chunks/agent-PZF5IUUB.js +68 -0
  25. package/chunks/agent-headless-L4N7V2SG.js +62 -0
  26. package/chunks/{anthropicContentGenerator-AKYPSZIV.js → anthropicContentGenerator-L73TO3DB.js} +214 -31
  27. package/chunks/{artifact-tool-D233YJFH.js → artifact-tool-U7IRTLIV.js} +5 -5
  28. package/chunks/{askUserQuestion-MKL5ZTMC.js → askUserQuestion-2DLUUZZG.js} +6 -6
  29. package/chunks/bridge-OJL6LD42.js +78 -0
  30. package/chunks/{ca-HCMB2I54.js → ca-WTQOU43B.js} +91 -6
  31. package/chunks/{channel-worker-supervisor-CRCVYQIE.js → channel-worker-supervisor-LF66HCVT.js} +137 -13
  32. package/chunks/{chunk-QQDPRDVW.js → chunk-2HRYPZT5.js} +1 -1
  33. package/chunks/{chunk-JD33UY7E.js → chunk-2K56LTWA.js} +18 -12
  34. package/chunks/{chunk-XISQIIT7.js → chunk-2LV4JUNO.js} +4 -4
  35. package/chunks/chunk-2UU6DW5P.js +296 -0
  36. package/chunks/{chunk-2PSWA5ID.js → chunk-2X56YUSZ.js} +1 -1
  37. package/chunks/chunk-2ZQOQZIS.js +71 -0
  38. package/chunks/{chunk-Q6OEPOOC.js → chunk-3AMVHPEQ.js} +2 -2
  39. package/chunks/{chunk-4RQIB5UZ.js → chunk-3BTRNWWD.js} +1 -35
  40. package/chunks/{chunk-SD4N3QJ2.js → chunk-3QZ6GY6A.js} +66 -22
  41. package/chunks/{chunk-DNV4FSN5.js → chunk-3SJSQXNS.js} +24 -7
  42. package/chunks/{chunk-VQWAZSXN.js → chunk-3XATDZNP.js} +64 -42
  43. package/chunks/{chunk-LEIJKM7Q.js → chunk-3ZAIGBCP.js} +2 -2
  44. package/chunks/{chunk-2NPS2UDH.js → chunk-43JB7OF4.js} +905 -139
  45. package/chunks/chunk-43XJTCHT.js +444 -0
  46. package/chunks/{chunk-CNSF3WO5.js → chunk-47HXCVGG.js} +6 -6
  47. package/chunks/{chunk-VEB3NYSO.js → chunk-4GORAUCN.js} +8 -3
  48. package/chunks/{chunk-55ZMG67I.js → chunk-4LD5APFL.js} +4 -4
  49. package/chunks/{chunk-TLWA7TPR.js → chunk-4QLQE5WJ.js} +2 -2
  50. package/chunks/{chunk-UIDXQNMV.js → chunk-4WGODMVR.js} +1 -1
  51. package/chunks/{chunk-E6US47KI.js → chunk-4WKAA4KS.js} +1 -1
  52. package/chunks/{chunk-H6EMK6QK.js → chunk-4ZVWQHEQ.js} +11913 -5207
  53. package/chunks/{chunk-HW4N45EE.js → chunk-524RQP4Q.js} +29 -8
  54. package/chunks/{chunk-3GONHQOA.js → chunk-57OAHC2Y.js} +1 -1
  55. package/chunks/{chunk-B4U2M63D.js → chunk-5DOUQHL3.js} +2104 -14
  56. package/chunks/{chunk-JZSY4WP3.js → chunk-5DTTYNB7.js} +1 -1
  57. package/chunks/{chunk-A4BMJM77.js → chunk-5O2XNYP6.js} +1 -0
  58. package/chunks/{chunk-P7I3D7FM.js → chunk-5OIXALQ5.js} +2 -2
  59. package/chunks/chunk-5SFOMFG4.js +61 -0
  60. package/chunks/{chunk-QYNNN7BK.js → chunk-5XUCZNSY.js} +2 -2
  61. package/chunks/{chunk-FRFFNYUY.js → chunk-65F3I3PM.js} +5 -5
  62. package/chunks/{chunk-GO6LNQXT.js → chunk-6AM5D4ME.js} +1 -1
  63. package/chunks/{chunk-BWVQN2HV.js → chunk-6CR73ZIK.js} +7 -7
  64. package/chunks/{chunk-BJBWRCSK.js → chunk-6H67XLET.js} +1 -1
  65. package/chunks/{chunk-G7ZG7CA6.js → chunk-6RLROE6G.js} +9 -8
  66. package/chunks/{chunk-TBAZMRW3.js → chunk-6WH2WCSW.js} +2 -2
  67. package/chunks/{chunk-ZERZSAZL.js → chunk-75DOP5OR.js} +2 -2
  68. package/chunks/{chunk-FTFXDZYI.js → chunk-7KZNLIAI.js} +47 -31
  69. package/chunks/{chunk-HJ3GX3Y3.js → chunk-7PW5CTVR.js} +32 -18
  70. package/chunks/{chunk-NQKLOAVJ.js → chunk-7R3CZA3Q.js} +2 -2
  71. package/chunks/{chunk-SAIILPQ3.js → chunk-7X7TEQNX.js} +5 -3
  72. package/chunks/{chunk-IRJWHZWU.js → chunk-A4UCTEB5.js} +2 -2
  73. package/chunks/{chunk-XSAFNANZ.js → chunk-AHUEU3BP.js} +14 -14
  74. package/chunks/{chunk-X3YGAX7V.js → chunk-B5ORX3FG.js} +4 -2
  75. package/chunks/{chunk-ZN5T4BHI.js → chunk-BPZALHVR.js} +2 -2
  76. package/chunks/{chunk-IJRL2S3D.js → chunk-BZIFY5TF.js} +6 -6
  77. package/chunks/{chunk-AJBEAUIS.js → chunk-BZP7HZTK.js} +7 -6
  78. package/chunks/{chunk-OFEVLU4C.js → chunk-CARU2RR2.js} +1 -1
  79. package/chunks/{chunk-MIG5SQNL.js → chunk-CBKR4Q5K.js} +8 -8
  80. package/chunks/chunk-CC2ITGCF.js +176 -0
  81. package/chunks/{chunk-FV7425LN.js → chunk-CEA3E3JB.js} +18 -5
  82. package/chunks/{chunk-GD236YPV.js → chunk-CNOF2IZT.js} +3 -3
  83. package/chunks/chunk-COH43MRJ.js +34 -0
  84. package/chunks/{chunk-E5A7LHNN.js → chunk-CPBF7KYF.js} +1 -1
  85. package/chunks/{chunk-UWCTAVOD.js → chunk-CR3C7WXL.js} +1 -1
  86. package/chunks/{chunk-5P5XGNYH.js → chunk-CU3L64TP.js} +1 -1
  87. package/chunks/{chunk-IWKSG2AR.js → chunk-CXAOG665.js} +1 -1
  88. package/chunks/{chunk-MZ7BABX3.js → chunk-DC5Z3DU6.js} +2 -2
  89. package/chunks/{chunk-64WXLC72.js → chunk-DJ2GSRLV.js} +1 -1
  90. package/chunks/{chunk-4ZJIPVPB.js → chunk-DMN532MJ.js} +11 -11
  91. package/chunks/{chunk-QN5NZ3UQ.js → chunk-DMTGGOSA.js} +2 -2
  92. package/chunks/{chunk-KHDZHZMH.js → chunk-E5Z2AVNV.js} +1 -1
  93. package/chunks/chunk-F4PFZ7WP.js +239 -0
  94. package/chunks/{chunk-ME3YSROJ.js → chunk-FBSBT7JS.js} +25 -13
  95. package/chunks/{chunk-5IFG2VC4.js → chunk-FCMNKVXT.js} +1 -1
  96. package/chunks/{chunk-YDSYD7UI.js → chunk-FD3DA3B4.js} +3 -3
  97. package/chunks/{chunk-GL5TV7B5.js → chunk-GL22M2DU.js} +23 -7
  98. package/chunks/{chunk-AFOLR6YL.js → chunk-GQ4ZEYMI.js} +102 -16
  99. package/chunks/chunk-GRC5HGPI.js +13 -0
  100. package/chunks/{chunk-WMPVYQ4P.js → chunk-GWHYEOV2.js} +2 -2
  101. package/chunks/chunk-GZRTYZ2R.js +292 -0
  102. package/chunks/{chunk-A2X3KLC3.js → chunk-GZXCZHCT.js} +3 -3
  103. package/chunks/{chunk-K5PGHDBN.js → chunk-H6XPXXMH.js} +1 -1
  104. package/chunks/{chunk-24XYI5EI.js → chunk-HACY3IUM.js} +6 -6
  105. package/chunks/{chunk-DGHJTO2K.js → chunk-HIHQ3TWC.js} +38 -9
  106. package/chunks/{chunk-KYMBIKIW.js → chunk-HTHUX2T5.js} +1 -1
  107. package/chunks/{chunk-LQ7TMOCE.js → chunk-HTO4JFDZ.js} +1 -1
  108. package/chunks/{chunk-B34OV7K2.js → chunk-IAVB3HM3.js} +15 -2
  109. package/chunks/{chunk-4UCTWSTP.js → chunk-IDJEZU7C.js} +2 -2
  110. package/chunks/chunk-IEBIKN6A.js +38 -0
  111. package/chunks/{chunk-PRDFOIZF.js → chunk-IJEO2QSK.js} +73 -30
  112. package/chunks/{chunk-MJI36HER.js → chunk-IT6LIIVK.js} +2 -2
  113. package/chunks/{chunk-FEJ2FZ3U.js → chunk-J3JA76CF.js} +2 -2
  114. package/chunks/{chunk-4CGOWHKM.js → chunk-J4MOFEOK.js} +2 -2
  115. package/chunks/{chunk-22MNNNXE.js → chunk-J4TSQ5EQ.js} +3 -2
  116. package/chunks/{chunk-22IFUCVR.js → chunk-JESCGQM3.js} +1 -1
  117. package/chunks/{chunk-CCGOFQV3.js → chunk-JSG7ZSBC.js} +8 -7
  118. package/chunks/{chunk-X265R5C6.js → chunk-K434OPES.js} +5 -5
  119. package/chunks/{chunk-RFIL6REB.js → chunk-KHUQZZJ6.js} +185 -45
  120. package/chunks/{chunk-X2XNQQJI.js → chunk-KKNMOEZH.js} +4 -4
  121. package/chunks/{chunk-6BN7NZ5Z.js → chunk-KL23O5Z5.js} +7 -9
  122. package/chunks/{chunk-MRO43B25.js → chunk-KW7NOTN6.js} +1 -1
  123. package/chunks/{chunk-6IAWPIQ6.js → chunk-L36P3NBD.js} +3 -3
  124. package/chunks/{chunk-54YZOP7P.js → chunk-L573Z2QZ.js} +11894 -5190
  125. package/chunks/{chunk-STAZRKOT.js → chunk-L6GPKRH7.js} +132 -464
  126. package/chunks/{chunk-QAKFYMJI.js → chunk-LD5OWZ5E.js} +155 -19
  127. package/chunks/{chunk-E7KNELIZ.js → chunk-LK7KUE55.js} +2 -2
  128. package/chunks/{chunk-W7EEOR7D.js → chunk-LUODI7WD.js} +5 -5
  129. package/chunks/{chunk-CSOTA7KX.js → chunk-LXNEJD34.js} +2 -2
  130. package/chunks/{chunk-HLKG6CZN.js → chunk-M5GB774H.js} +1 -1
  131. package/chunks/{chunk-3B26UVCX.js → chunk-MC23XKFE.js} +39 -10
  132. package/chunks/{chunk-XPJH4PKR.js → chunk-MPEMTBUZ.js} +2 -2
  133. package/chunks/{chunk-GMOWQOQQ.js → chunk-MUCWGT7O.js} +248 -55
  134. package/chunks/{chunk-PC4ZXHU2.js → chunk-MXL5UP4X.js} +3 -3
  135. package/chunks/{chunk-PUQLHSQ2.js → chunk-N2FGNKOE.js} +10 -12
  136. package/chunks/{chunk-332PWN27.js → chunk-NHDKSOEY.js} +1 -1
  137. package/chunks/{chunk-65CFHNSE.js → chunk-NKHV3OHY.js} +62 -62
  138. package/chunks/{chunk-P7M4GA57.js → chunk-OCPBI7J5.js} +1 -1
  139. package/chunks/{chunk-42XGFRJS.js → chunk-ORBGV7NJ.js} +5 -5
  140. package/chunks/{chunk-ALZ75L2X.js → chunk-OZJLTZKP.js} +415 -379
  141. package/chunks/chunk-P3X7RYUQ.js +468 -0
  142. package/chunks/{chunk-AGHU5VRK.js → chunk-PZL23GTM.js} +1 -1
  143. package/chunks/{chunk-FXGLL2HL.js → chunk-Q7YDKOGY.js} +1 -1
  144. package/chunks/{chunk-LGFAYIKX.js → chunk-QHTIBUWB.js} +1 -1
  145. package/chunks/{chunk-AIY5UTFI.js → chunk-QK2JET6S.js} +934 -2881
  146. package/chunks/{chunk-P3MYAZBY.js → chunk-QMGX2KO2.js} +1 -1
  147. package/chunks/{chunk-QZF5U5KA.js → chunk-QNTUV3PP.js} +11 -11
  148. package/chunks/chunk-QRUIS3DN.js +47 -0
  149. package/chunks/{chunk-ITOGNELQ.js → chunk-QSWDGAIC.js} +2 -2
  150. package/chunks/{chunk-7JGISHHZ.js → chunk-QUJIDGIW.js} +15 -157
  151. package/chunks/{chunk-GHOTR7HL.js → chunk-QUPXZXLV.js} +1 -1
  152. package/chunks/{chunk-TDGF35EN.js → chunk-QYMQSECS.js} +3 -3
  153. package/chunks/{chunk-QYUE6W3T.js → chunk-RDJSGHZE.js} +1 -1
  154. package/chunks/{chunk-TLRYABYP.js → chunk-RKUWKYED.js} +1 -1
  155. package/chunks/{chunk-ADZG46HR.js → chunk-RRNR5U2U.js} +2 -2
  156. package/chunks/{chunk-4O344UEE.js → chunk-RW7CXRUM.js} +39 -19
  157. package/chunks/{chunk-RNBYOUGV.js → chunk-RXFQM6FQ.js} +1 -1
  158. package/chunks/{chunk-QXPI7FEC.js → chunk-S3TWXGKA.js} +4 -4
  159. package/chunks/{chunk-44NROQYV.js → chunk-SJHDYNHF.js} +4 -4
  160. package/chunks/{chunk-MLZQVCF3.js → chunk-SZRN75WQ.js} +1 -1
  161. package/chunks/{chunk-7RYW5LQV.js → chunk-T2NCM2ET.js} +2 -2
  162. package/chunks/{chunk-Z2Z3GUXZ.js → chunk-TB6UDU4T.js} +1 -1
  163. package/chunks/{chunk-SUAKHHK7.js → chunk-TDEXZKMT.js} +3 -3
  164. package/chunks/{chunk-EXPMGZZV.js → chunk-TEGEBB2I.js} +1 -1
  165. package/chunks/{chunk-JF7DFPQ5.js → chunk-TJCEUA3S.js} +15 -3
  166. package/chunks/{chunk-MX2YXRER.js → chunk-TJTKSVIV.js} +1 -1
  167. package/chunks/{chunk-H6BD2ELD.js → chunk-TYAMGABM.js} +2 -2
  168. package/chunks/{chunk-CISB3IQF.js → chunk-U3VSCGEJ.js} +100 -15
  169. package/chunks/{chunk-VRDMOSQS.js → chunk-UDXSXLER.js} +2 -2
  170. package/chunks/{chunk-AHNJGLFV.js → chunk-UOZWKTQG.js} +3 -3
  171. package/chunks/{chunk-CJCKDMWO.js → chunk-URK542T4.js} +1 -1
  172. package/chunks/{chunk-YEGT55NW.js → chunk-UUVCHN62.js} +5697 -2983
  173. package/chunks/{chunk-AHNXYU4O.js → chunk-V6WHFGST.js} +1 -1
  174. package/chunks/{chunk-U4FRHCLA.js → chunk-VAUPLGDZ.js} +2370 -364
  175. package/chunks/{chunk-ZTQ26VBE.js → chunk-VDDGDZMA.js} +1 -1
  176. package/chunks/{chunk-OMX7CUOE.js → chunk-VGC4I5JJ.js} +1 -1
  177. package/chunks/{chunk-IUE7YWC3.js → chunk-VIUKEWUL.js} +8 -8
  178. package/chunks/{chunk-43W4YSO6.js → chunk-VJNBRRZG.js} +2 -2
  179. package/chunks/{chunk-I4A4K72C.js → chunk-VL7GBUQA.js} +1309 -703
  180. package/chunks/{chunk-VZ7HY3YU.js → chunk-W2UIXQDL.js} +3 -3
  181. package/chunks/{chunk-ER3BKOLB.js → chunk-W7FJ3N32.js} +1 -1
  182. package/chunks/{chunk-3HX5LZ6R.js → chunk-WBL3FJEU.js} +2 -2
  183. package/chunks/{chunk-RYFZCUJO.js → chunk-WCUK2QXK.js} +17 -9
  184. package/chunks/{chunk-OWVIH4HY.js → chunk-WFHJDT4S.js} +421 -114
  185. package/chunks/{chunk-BMFMJINR.js → chunk-WL4L7EZH.js} +1 -1
  186. package/chunks/{chunk-NZEGNV4V.js → chunk-WPHYXKFL.js} +8 -51
  187. package/chunks/chunk-X4NKFGFJ.js +81 -0
  188. package/chunks/{chunk-3RW4AZJV.js → chunk-XFSFZCM5.js} +1 -1
  189. package/chunks/{chunk-2MPVVENX.js → chunk-XU457J4V.js} +2 -2
  190. package/chunks/{chunk-SIUQ3YYX.js → chunk-XVNQMZ2I.js} +1 -1
  191. package/chunks/{chunk-SYCJMSIJ.js → chunk-XWRJCPHC.js} +1 -1
  192. package/chunks/chunk-YAF2MQZ6.js +19 -0
  193. package/chunks/chunk-YF4RZPJP.js +168 -0
  194. package/chunks/{chunk-4KJ2BPIT.js → chunk-YLV3XXFB.js} +4 -40
  195. package/chunks/{chunk-BR4QREVK.js → chunk-YQ3U5MUC.js} +1 -1
  196. package/chunks/{chunk-Y6Z2O3WR.js → chunk-YUZI3WAC.js} +1 -1
  197. package/chunks/{chunk-II73RK2S.js → chunk-YVEDCAUE.js} +1 -1
  198. package/chunks/{chunk-SKAZWEV5.js → chunk-ZJE7NSL3.js} +1 -1
  199. package/chunks/{chunk-7LTB54MK.js → chunk-ZLXQN2QS.js} +2 -2
  200. package/chunks/cli-entry-path-4VJ3Y6T2.js +10 -0
  201. package/chunks/{computer-use-X4KUU3NM.js → computer-use-2ZTYDNN4.js} +50 -50
  202. package/chunks/config-utils-ZITWCFBY.js +23 -0
  203. package/chunks/contextCommand-6L4XCZZT.js +68 -0
  204. package/chunks/create-sub-session-INX7TXJI.js +207 -0
  205. package/chunks/create-sub-session-VZIOFS6N.js +375 -0
  206. package/chunks/{cron-create-JSXEIPVS.js → cron-create-AMBKGZX6.js} +9 -9
  207. package/chunks/{cron-delete-OIFVEPGU.js → cron-delete-LRU4OJYG.js} +7 -7
  208. package/chunks/{cron-list-D4ZX4IOE.js → cron-list-WVP2JXER.js} +14 -10
  209. package/chunks/{daemon-F3I2RXP6.js → daemon-QEDXW7ER.js} +554 -4
  210. package/chunks/daemon-status-provider-7XJZ3HPS.js +76 -0
  211. package/chunks/{de-PLLFDERI.js → de-XHBEYUMG.js} +91 -6
  212. package/chunks/{devtools-FM6GJPYG.js → devtools-4QFYJT6U.js} +3 -3
  213. package/chunks/{dist-573HNSVO.js → dist-EFXT7A3G.js} +12 -11
  214. package/chunks/{dist-PKFTNUHO.js → dist-KCRX7TGL.js} +529 -79
  215. package/chunks/{dist-OT7G2WNM.js → dist-MFEAEUV4.js} +1011 -197
  216. package/chunks/{dist-63IS3ZMI.js → dist-PZV5RKM6.js} +4 -4
  217. package/chunks/{dist-FQ5WRJPL.js → dist-QY3THJM5.js} +5 -5
  218. package/chunks/{dist-IMFFBMAT.js → dist-UJOR6KEQ.js} +32 -15
  219. package/chunks/{dist-YTRKAVUB.js → dist-ZWZB4CCN.js} +10 -10
  220. package/chunks/earlyInputCapture-TTWXFIWO.js +69 -0
  221. package/chunks/{edit-WZTZDGCI.js → edit-6UWFRZKY.js} +51 -51
  222. package/chunks/{en-GA2RMXY5.js → en-TKHUFIK7.js} +100 -6
  223. package/chunks/{enter-worktree-DEPXBJEL.js → enter-worktree-LS7SGAII.js} +50 -50
  224. package/chunks/{enterPlanMode-JFGXZHHJ.js → enterPlanMode-TSZYLEEP.js} +66 -51
  225. package/chunks/environment-XCVLHOXG.js +88 -0
  226. package/chunks/errors-KIANLUTC.js +75 -0
  227. package/chunks/{exit-worktree-Y7XBK3VV.js → exit-worktree-2QV6UJSW.js} +50 -50
  228. package/chunks/{exitPlanMode-WQQER65F.js → exitPlanMode-GVZG3F6S.js} +51 -51
  229. package/chunks/{fast-path-W2U6XDNO.js → fast-path-GNFZAMQK.js} +16 -7
  230. package/chunks/{fast-path-settings-RCRXH2JG.js → fast-path-settings-5QZE64HR.js} +6 -5
  231. package/chunks/{fileFromPath-IBEHA3CO.js → fileFromPath-UDALK7FM.js} +3 -3
  232. package/chunks/{fr-GWNQG4XH.js → fr-TBF6JZNE.js} +91 -6
  233. package/chunks/{gemini-T4WX6SRW.js → gemini-N3H6OLHR.js} +501 -197
  234. package/chunks/{geminiContentGenerator-MKQACXEJ.js → geminiContentGenerator-4C257R2N.js} +9 -9
  235. package/chunks/{getMachineId-bsd-4CASPIU4.js → getMachineId-bsd-EXV7SWPA.js} +3 -3
  236. package/chunks/{getMachineId-darwin-HPQPEMZR.js → getMachineId-darwin-IUOMFXU3.js} +3 -3
  237. package/chunks/{getMachineId-linux-AUARKYHL.js → getMachineId-linux-K7XJYFHL.js} +2 -2
  238. package/chunks/{getMachineId-unsupported-S32ZDA2T.js → getMachineId-unsupported-EA5FDRJ6.js} +2 -2
  239. package/chunks/{getMachineId-win-4EFLHYIJ.js → getMachineId-win-KBA6RAI5.js} +3 -3
  240. package/chunks/{glob-4KKSHZDF.js → glob-QTUI5I3Y.js} +95 -74
  241. package/chunks/{grep-GHRYXSLZ.js → grep-Z5MGLRCG.js} +50 -50
  242. package/chunks/handleAutoUpdate-FFF3CZGP.js +69 -0
  243. package/chunks/i18n-QQAJT7A2.js +84 -0
  244. package/chunks/initializer-LGQGC7ZT.js +71 -0
  245. package/chunks/installationInfo-4FEZGXIN.js +65 -0
  246. package/chunks/{ja-2HOTA47X.js → ja-CDXUA2H3.js} +92 -7
  247. package/chunks/{keychain-token-storage-UJV5XP4Z.js → keychain-token-storage-VKUBNCP4.js} +4 -4
  248. package/chunks/{kittyProtocolDetector-OJRCJLIU.js → kittyProtocolDetector-HCNNKJTI.js} +2 -2
  249. package/chunks/list-KIVFF3BB.js +74 -0
  250. package/chunks/loadedSettingsAdapter-EOD3RVZS.js +68 -0
  251. package/chunks/{loop-wakeup-OHWEMFP5.js → loop-wakeup-WX7BLWWP.js} +10 -10
  252. package/chunks/{lowlight-FYAAUU5J.js → lowlight-J2OZNPCA.js} +1 -1
  253. package/chunks/{ls-L654WOAT.js → ls-ZB2BDP6T.js} +6 -6
  254. package/chunks/{lsp-M35KE54Y.js → lsp-V5DN4YUJ.js} +6 -8
  255. package/chunks/mcp-D2P46DB4.js +68 -0
  256. package/chunks/{monitor-464OY2UE.js → monitor-4ZWVOL6J.js} +50 -50
  257. package/chunks/{multipart-parser-AJ4WASWR.js → multipart-parser-AWZKXSQN.js} +3 -3
  258. package/chunks/nonInteractiveCli-NAHUR2X6.js +124 -0
  259. package/chunks/{notebook-edit-BLJYCNDO.js → notebook-edit-RCQ2D2IE.js} +51 -51
  260. package/chunks/openaiContentGenerator-U655T5QC.js +56 -0
  261. package/chunks/pidfile-O3OO2TCP.js +73 -0
  262. package/chunks/{pt-2THT3YHA.js → pt-6IR2VRQY.js} +91 -6
  263. package/chunks/{qwenContentGenerator-SUUHZ6CR.js → qwenContentGenerator-ABGWCRS6.js} +52 -52
  264. package/chunks/{qwenOAuth2-ZV7YLMND.js → qwenOAuth2-PJQ27GSO.js} +9 -9
  265. package/chunks/read-file-X7M4GUPY.js +30 -0
  266. package/chunks/{read-mcp-resource-CNQHBSJM.js → read-mcp-resource-SM5DA4RG.js} +5 -5
  267. package/chunks/{read-package-up-ER5OJUGP.js → read-package-up-TCM6I7S2.js} +2 -2
  268. package/chunks/{record-artifact-PP3LKHTS.js → record-artifact-4XKZX3UW.js} +7 -7
  269. package/chunks/ripGrep-KMPJJK5J.js +60 -0
  270. package/chunks/{ru-Z67YJHBG.js → ru-DBTHQA3F.js} +91 -6
  271. package/chunks/{run-qwen-serve-5OKADVLE.js → run-qwen-serve-O6CMPURG.js} +958 -184
  272. package/chunks/runtime-THE2YO27.js +94 -0
  273. package/chunks/{scheduler-ZRW3AIDU.js → scheduler-XXEA6EFC.js} +51 -51
  274. package/chunks/{send-message-OA6MV4EU.js → send-message-F36YD6KQ.js} +7 -7
  275. package/chunks/serve-W6F44JQQ.js +74 -0
  276. package/chunks/{server-M372UENX.js → server-SAEKMY52.js} +4340 -829
  277. package/chunks/{session-F5KSNP2N.js → session-4GGYGOWY.js} +162 -117
  278. package/chunks/settings-PYEU5HVD.js +118 -0
  279. package/chunks/shell-JGQECKTH.js +68 -0
  280. package/chunks/{skill-A2TL2NPC.js → skill-XPP3C2DS.js} +24 -24
  281. package/chunks/spawnChannel-62QKQBQN.js +70 -0
  282. package/chunks/{src-XKZMNHXS.js → src-2656Q6SN.js} +126 -52
  283. package/chunks/{src-7XL4G4DC.js → src-VLI3TKEY.js} +4 -4
  284. package/chunks/standalone-update-X7AZVG5R.js +79 -0
  285. package/chunks/{startInteractiveUI-REKSTOHU.js → startInteractiveUI-DXR4K6T5.js} +2277 -1834
  286. package/chunks/stdioHelpers-UMY72QRP.js +14 -0
  287. package/chunks/{syntheticOutput-F7LSDCAR.js → syntheticOutput-34H7LGA7.js} +5 -5
  288. package/chunks/task-create-FRGOEIKY.js +22 -0
  289. package/chunks/{task-list-TGGJX7EA.js → task-list-OW766BXZ.js} +10 -10
  290. package/chunks/{task-stop-W7NGTMYQ.js → task-stop-SIR5SNBN.js} +4 -4
  291. package/chunks/{task-update-5WUG5MVQ.js → task-update-YRA532MT.js} +12 -12
  292. package/chunks/{team-create-TBQVWAG7.js → team-create-3EHCUCKA.js} +50 -50
  293. package/chunks/{team-delete-UHQQ2QQX.js → team-delete-6OSECUZC.js} +10 -10
  294. package/chunks/{team-plan-approval-FZPGUSHJ.js → team-plan-approval-KZ7NZIMX.js} +50 -50
  295. package/chunks/theme-manager-J7ANV4JR.js +64 -0
  296. package/chunks/{todoWrite-C4ZAMSR3.js → todoWrite-YDMFEV4G.js} +6 -6
  297. package/chunks/{tool-search-FDQ3SLNJ.js → tool-search-2XLGWG4H.js} +24 -24
  298. package/chunks/total-session-admission-EQIHUOL6.js +72 -0
  299. package/chunks/trustedFolders-BEX5334Z.js +79 -0
  300. package/chunks/{types-QX5C3CHJ.js → types-JNKGKUJT.js} +2 -2
  301. package/chunks/updateCheck-NKPJGJCR.js +69 -0
  302. package/chunks/updateEventEmitter-5MKC7BLQ.js +10 -0
  303. package/chunks/validateNonInterActiveAuth-6DGGGE4A.js +190 -0
  304. package/chunks/{version-CEDD6ZZR.js → version-FRVWU5ZU.js} +3 -3
  305. package/chunks/{web-fetch-UYGMOHW4.js → web-fetch-PAAEQKBW.js} +8 -8
  306. package/chunks/{workflow-CQQ4J4I6.js → workflow-LWFMECLD.js} +51 -51
  307. package/chunks/workspace-providers-status-NE7QWEYS.js +71 -0
  308. package/chunks/workspace-registry-RCWAP57G.js +76 -0
  309. package/chunks/workspace-service-4QUMVGBX.js +80 -0
  310. package/chunks/workspace-skills-status-L34BYRSY.js +70 -0
  311. package/chunks/{write-file-VWGY7AJP.js → write-file-WXO4M5FN.js} +51 -51
  312. package/chunks/{yargs-B64EYTCF.js → yargs-6H2AUULL.js} +2 -2
  313. package/chunks/{zh-7XVVRTDH.js → zh-LJP47LX7.js} +101 -7
  314. package/chunks/{zh-TW-DPH554OG.js → zh-TW-5ISMO3VJ.js} +101 -7
  315. package/cli.js +18 -17
  316. package/locales/ca.js +117 -7
  317. package/locales/de.js +116 -7
  318. package/locales/en.js +133 -7
  319. package/locales/fr.js +117 -7
  320. package/locales/ja.js +119 -7
  321. package/locales/pt.js +116 -7
  322. package/locales/ru.js +116 -7
  323. package/locales/zh-TW.js +130 -7
  324. package/locales/zh.js +130 -7
  325. package/package.json +3 -6
  326. package/web-shell/assets/{arc-C7hjaa7g.js → arc-BRDEF7h6.js} +1 -1
  327. package/web-shell/assets/{architectureDiagram-3BPJPVTR-pm9KtMZY.js → architectureDiagram-3BPJPVTR-Cxnk4Ygq.js} +1 -1
  328. package/web-shell/assets/{blockDiagram-GPEHLZMM-CApElKsU.js → blockDiagram-GPEHLZMM-BZrtayqw.js} +1 -1
  329. package/web-shell/assets/{c4Diagram-AAUBKEIU-BeDe0-9N.js → c4Diagram-AAUBKEIU-Djmbi1yB.js} +1 -1
  330. package/web-shell/assets/channel-C9zfQCn-.js +1 -0
  331. package/web-shell/assets/{chunk-2J33WTMH-DJEkmLdl.js → chunk-2J33WTMH-Cdokj-0U.js} +1 -1
  332. package/web-shell/assets/{chunk-4BX2VUAB-DXX8gdpe.js → chunk-4BX2VUAB-BI9Hx57o.js} +1 -1
  333. package/web-shell/assets/{chunk-55IACEB6-DORmk1kQ.js → chunk-55IACEB6-Cb17cEzj.js} +1 -1
  334. package/web-shell/assets/{chunk-727SXJPM-DWmO4mCZ.js → chunk-727SXJPM-DY1Fc0h_.js} +1 -1
  335. package/web-shell/assets/{chunk-AQP2D5EJ-C7LRaYw2.js → chunk-AQP2D5EJ-B10G71Hd.js} +1 -1
  336. package/web-shell/assets/{chunk-FMBD7UC4-CCdXgyC5.js → chunk-FMBD7UC4-BP6OoB6Z.js} +1 -1
  337. package/web-shell/assets/{chunk-ND2GUHAM-SyL_xvWc.js → chunk-ND2GUHAM-CWIIwUFC.js} +1 -1
  338. package/web-shell/assets/{chunk-QZHKN3VN-BzOuCKxa.js → chunk-QZHKN3VN-DMrqCfGO.js} +1 -1
  339. package/web-shell/assets/classDiagram-4FO5ZUOK-BVNaf5JM.js +1 -0
  340. package/web-shell/assets/classDiagram-v2-Q7XG4LA2-BVNaf5JM.js +1 -0
  341. package/web-shell/assets/{cose-bilkent-S5V4N54A-BMPWyDKc.js → cose-bilkent-S5V4N54A-CF-mpkgI.js} +1 -1
  342. package/web-shell/assets/{dagre-BM42HDAG-B_GnPWik.js → dagre-BM42HDAG-DfsRFsg7.js} +1 -1
  343. package/web-shell/assets/{diagram-2AECGRRQ-fJqMc3S_.js → diagram-2AECGRRQ-DBNwf6Dy.js} +1 -1
  344. package/web-shell/assets/{diagram-5GNKFQAL-ximV3O9D.js → diagram-5GNKFQAL-CD1TqV1j.js} +1 -1
  345. package/web-shell/assets/{diagram-KO2AKTUF-2vVyjzqw.js → diagram-KO2AKTUF-DkWlaLI2.js} +1 -1
  346. package/web-shell/assets/{diagram-LMA3HP47-Dckcx1sT.js → diagram-LMA3HP47-ClrAcxwF.js} +1 -1
  347. package/web-shell/assets/{diagram-OG6HWLK6-BAVv47ga.js → diagram-OG6HWLK6-Dr6dnPLw.js} +1 -1
  348. package/web-shell/assets/{erDiagram-TEJ5UH35-Bn3nf5J0.js → erDiagram-TEJ5UH35-Dm_vj18R.js} +1 -1
  349. package/web-shell/assets/{flowDiagram-I6XJVG4X-BIbGF9JT.js → flowDiagram-I6XJVG4X-lp3cMdZu.js} +1 -1
  350. package/web-shell/assets/{ganttDiagram-6RSMTGT7-CDbhb3AH.js → ganttDiagram-6RSMTGT7-AtdCWZya.js} +3 -3
  351. package/web-shell/assets/{gitGraphDiagram-PVQCEYII-CbKG1a_w.js → gitGraphDiagram-PVQCEYII-BARTJafF.js} +1 -1
  352. package/web-shell/assets/index-BkNgyfu7.js +3 -0
  353. package/web-shell/assets/index-CihmnZZR.js +784 -0
  354. package/web-shell/assets/index-zfdXhnwH.css +5 -0
  355. package/web-shell/assets/{infoDiagram-5YYISTIA-DUFxTy8m.js → infoDiagram-5YYISTIA-CxbJ54_f.js} +1 -1
  356. package/web-shell/assets/{ishikawaDiagram-YF4QCWOH-D69hrBG8.js → ishikawaDiagram-YF4QCWOH-hFoO0HQA.js} +1 -1
  357. package/web-shell/assets/{journeyDiagram-JHISSGLW-DsvEw51Y.js → journeyDiagram-JHISSGLW-Bo6cKnLe.js} +1 -1
  358. package/web-shell/assets/{kanban-definition-UN3LZRKU-lFFjZEYd.js → kanban-definition-UN3LZRKU-DIFrH-XL.js} +1 -1
  359. package/web-shell/assets/{linear-Bo5bWzvo.js → linear-Bjv_GjDd.js} +1 -1
  360. package/web-shell/assets/{mermaid.core-C_HKMJx5.js → mermaid.core-C_OiqQEP.js} +5 -5
  361. package/web-shell/assets/{mindmap-definition-RKZ34NQL-DlV-NUTs.js → mindmap-definition-RKZ34NQL-B79Gk8aB.js} +1 -1
  362. package/web-shell/assets/{pieDiagram-4H26LBE5-B2e6FH2a.js → pieDiagram-4H26LBE5-B_P0gIHr.js} +1 -1
  363. package/web-shell/assets/{quadrantDiagram-W4KKPZXB-D75kSk-b.js → quadrantDiagram-W4KKPZXB-BC7F0ohb.js} +1 -1
  364. package/web-shell/assets/{requirementDiagram-4Y6WPE33-CQ6xakhM.js → requirementDiagram-4Y6WPE33-BrA5_NSW.js} +1 -1
  365. package/web-shell/assets/{sankeyDiagram-5OEKKPKP-J_XTKrcY.js → sankeyDiagram-5OEKKPKP-Q2iqrNI_.js} +1 -1
  366. package/web-shell/assets/{sequenceDiagram-3UESZ5HK-D7jTcBtf.js → sequenceDiagram-3UESZ5HK-6vdIWz4H.js} +1 -1
  367. package/web-shell/assets/{stateDiagram-AJRCARHV-CrlM_OT3.js → stateDiagram-AJRCARHV-DMzXNKcB.js} +1 -1
  368. package/web-shell/assets/stateDiagram-v2-BHNVJYJU-BWFH0OCO.js +1 -0
  369. package/web-shell/assets/{timeline-definition-PNZ67QCA-5oZi76Ef.js → timeline-definition-PNZ67QCA-BykEawmS.js} +1 -1
  370. package/web-shell/assets/{vennDiagram-CIIHVFJN-DO5YptPK.js → vennDiagram-CIIHVFJN-B24KD2X1.js} +1 -1
  371. package/web-shell/assets/{wardley-L42UT6IY-4t1eJDvM.js → wardley-L42UT6IY-C761G_tA.js} +1 -1
  372. package/web-shell/assets/{wardleyDiagram-YWT4CUSO-DKZc661S.js → wardleyDiagram-YWT4CUSO-CfwGJYqw.js} +1 -1
  373. package/web-shell/assets/{xychartDiagram-2RQKCTM6-su9hp08G.js → xychartDiagram-2RQKCTM6-BDu5AZ2D.js} +1 -1
  374. package/web-shell/index.html +16 -4
  375. package/chunks/MaxSizedBox-XY5LIO5O.js +0 -71
  376. package/chunks/agent-TKIBLLQT.js +0 -68
  377. package/chunks/agent-headless-VLX4C7KX.js +0 -62
  378. package/chunks/bridge-BCU73DZO.js +0 -77
  379. package/chunks/chunk-6SHO7WFF.js +0 -79
  380. package/chunks/chunk-IFEWJXFS.js +0 -37
  381. package/chunks/chunk-S6RLAIUR.js +0 -23
  382. package/chunks/contextCommand-LAYJZF7H.js +0 -68
  383. package/chunks/daemon-status-provider-XSAFKVDS.js +0 -74
  384. package/chunks/earlyInputCapture-AERYYGXE.js +0 -69
  385. package/chunks/errors-GMZL4QV7.js +0 -75
  386. package/chunks/handleAutoUpdate-HN7ZOSXY.js +0 -65
  387. package/chunks/initializer-SRN3IM42.js +0 -69
  388. package/chunks/list-INTVXUPA.js +0 -71
  389. package/chunks/loadedSettingsAdapter-QVHHQPGM.js +0 -66
  390. package/chunks/mcp-7V4T46RG.js +0 -66
  391. package/chunks/nonInteractiveCli-LJEEODU2.js +0 -116
  392. package/chunks/openaiContentGenerator-PFF6HYB2.js +0 -56
  393. package/chunks/pidfile-LIBUENIV.js +0 -73
  394. package/chunks/read-file-L7TBQVX7.js +0 -30
  395. package/chunks/ripGrep-CKKX3GRB.js +0 -60
  396. package/chunks/serve-36WS32W6.js +0 -71
  397. package/chunks/settings-WFLNS3WT.js +0 -114
  398. package/chunks/shell-DEDSWN56.js +0 -68
  399. package/chunks/spawnChannel-RQHUWTCL.js +0 -70
  400. package/chunks/task-create-RPFZNB4B.js +0 -22
  401. package/chunks/theme-manager-DQZVNSOC.js +0 -64
  402. package/chunks/trustedFolders-Z475EIHL.js +0 -79
  403. package/chunks/updateCheck-E2ZX7RL7.js +0 -65
  404. package/chunks/validateNonInterActiveAuth-O4ECBHQL.js +0 -181
  405. package/chunks/workspace-providers-status-MVYXMYDG.js +0 -68
  406. package/chunks/workspace-service-OMBR6ZLG.js +0 -78
  407. package/chunks/workspace-skills-status-IMMQ7CAY.js +0 -68
  408. package/node_modules/@qwen-code/audio-capture/dist/index.d.ts +0 -35
  409. package/node_modules/@qwen-code/audio-capture/dist/index.js +0 -48
  410. package/node_modules/@qwen-code/audio-capture/dist/index.js.map +0 -1
  411. package/node_modules/@qwen-code/audio-capture/dist/platform.d.ts +0 -7
  412. package/node_modules/@qwen-code/audio-capture/dist/platform.js +0 -18
  413. package/node_modules/@qwen-code/audio-capture/dist/platform.js.map +0 -1
  414. package/node_modules/@qwen-code/audio-capture/node_modules/node-gyp-build/LICENSE +0 -21
  415. package/node_modules/@qwen-code/audio-capture/node_modules/node-gyp-build/README.md +0 -58
  416. package/node_modules/@qwen-code/audio-capture/node_modules/node-gyp-build/SECURITY.md +0 -5
  417. package/node_modules/@qwen-code/audio-capture/node_modules/node-gyp-build/bin.js +0 -84
  418. package/node_modules/@qwen-code/audio-capture/node_modules/node-gyp-build/build-test.js +0 -19
  419. package/node_modules/@qwen-code/audio-capture/node_modules/node-gyp-build/index.js +0 -6
  420. package/node_modules/@qwen-code/audio-capture/node_modules/node-gyp-build/node-gyp-build.js +0 -207
  421. package/node_modules/@qwen-code/audio-capture/node_modules/node-gyp-build/optional.js +0 -7
  422. package/node_modules/@qwen-code/audio-capture/node_modules/node-gyp-build/package.json +0 -43
  423. package/node_modules/@qwen-code/audio-capture/package.json +0 -30
  424. package/node_modules/@qwen-code/audio-capture/prebuilds/darwin-arm64/@qwen-code+audio-capture.node +0 -0
  425. package/node_modules/@qwen-code/audio-capture/prebuilds/darwin-x64/@qwen-code+audio-capture.node +0 -0
  426. package/node_modules/@qwen-code/audio-capture/prebuilds/linux-arm64/@qwen-code+audio-capture.node +0 -0
  427. package/node_modules/@qwen-code/audio-capture/prebuilds/linux-x64/@qwen-code+audio-capture.node +0 -0
  428. package/node_modules/@qwen-code/audio-capture/prebuilds/win32-x64/@qwen-code+audio-capture.node +0 -0
  429. package/web-shell/assets/channel-BNf1dW-j.js +0 -1
  430. package/web-shell/assets/classDiagram-4FO5ZUOK-uOIGlzgi.js +0 -1
  431. package/web-shell/assets/classDiagram-v2-Q7XG4LA2-uOIGlzgi.js +0 -1
  432. package/web-shell/assets/index-CnE2ur2L.js +0 -779
  433. package/web-shell/assets/index-hSKXrlSE.css +0 -5
  434. package/web-shell/assets/stateDiagram-v2-BHNVJYJU-Bs4TK_84.js +0 -1
@@ -13,9 +13,10 @@ Run Qwen Code as a local HTTP daemon so multiple clients (IDE plugins, web UIs,
13
13
  - **Built-in Web Shell UI** — `qwen serve` serves the browser-based Web Shell at its root (`http://127.0.0.1:4170/`) out of the box; run `qwen serve --open` to launch it in your browser automatically. It is served on the same origin as the API, so no second port or reverse proxy is needed. Pass `--no-web` for an API-only daemon.
14
14
  - **One agent process, many clients** — under the default `sessionScope: 'single'`, every client connecting to the daemon shares one ACP session. Live cross-client collaboration on the same conversation, the same file diffs, the same permission prompts.
15
15
  - **Reconnect-safe streaming** — SSE with `Last-Event-ID` reconnect lets a client drop and pick up exactly where it left off (within the ring's replay window).
16
+ - **Paged persisted transcripts** — `GET /session/:id/transcript` returns the complete active on-disk transcript as replay pages without attaching a client or changing the live SSE replay window.
16
17
  - **First-responder permissions** — when the agent asks for permission to run a tool, every connected client sees the request; whichever client answers first wins.
17
18
  - **One daemon, one workspace** — each `qwen serve` process binds to exactly one workspace at boot (per [#3803](https://github.com/QwenLM/qwen-code/issues/3803) §02). Multi-workspace deployments run one daemon per workspace on separate ports (or behind an orchestrator).
18
- - **Experimental daemon-managed channels** — `qwen serve --channel <name>` starts a channel worker owned by the daemon lifecycle. The worker is a separate process, connects back to the daemon through the SDK, and reports its state in `GET /daemon/status`.
19
+ - **Experimental daemon-managed channels** — `qwen serve --channel <name>` starts a channel worker owned by the daemon lifecycle. The worker is a separate process, connects back to the daemon through the SDK, and reports its state in `GET /daemon/status`. After editing channel settings, reload it in place with `POST /workspace/channel/reload` (or `qwen channel reload`) — no full daemon restart needed.
19
20
  - **Remote runtime control** ([#4175](https://github.com/QwenLM/qwen-code/issues/4175) PR 17) — change a session's approval mode (`POST /session/:id/approval-mode`), toggle a tool per workspace (`POST /workspace/tools/:name/enable`), scaffold an empty `QWEN.md` (`POST /workspace/init`, mechanical only — does NOT call the model; for AI-fill, follow up with `POST /session/:id/prompt`), restart a single MCP server with a budget pre-check (`POST /workspace/mcp/:server/restart`), or add/remove MCP servers at runtime without a daemon restart (`POST /workspace/mcp/servers`, `DELETE /workspace/mcp/servers/:name`). All strict-gated — configure `--token` first.
20
21
  - **Session recap** ([#4175](https://github.com/QwenLM/qwen-code/issues/4175) follow-up) — fetch a one-sentence "where did I leave off" summary of an active session (`POST /session/:id/recap`). Wraps core's `generateSessionRecap` as a side-query against the fast model; pollutes neither the main chat history nor the SSE stream. Non-strict gate (same posture as `/prompt`); SDK helper `client.recapSession(sessionId)`.
21
22
  - **Known limit — token-cost amplification:** the route is a pure-cost endpoint (each call is an LLM side-query, no state benefit) and the daemon has no per-route rate limit in v1. On a no-token loopback default a buggy or malicious local client can spam it to burn tokens. Configure `--token` (and optionally `--require-auth`) on shared dev hosts before exposing the daemon.
@@ -81,7 +82,7 @@ curl http://127.0.0.1:4170/daemon/status
81
82
  ```
82
83
 
83
84
  The `workspaceCwd` field surfaces the bound workspace so clients can pre-flight check + omit `cwd` on `POST /session`.
84
- The `limits.maxPendingPromptsPerSession` field advertises the active per-session prompt admission cap; `null` means the cap is disabled.
85
+ The `limits.maxPendingPromptsPerSession` field advertises the active per-session prompt admission cap; `null` means the cap is disabled. `limits.maxTotalSessions` advertises the optional daemon-wide fresh-session cap; `null` means unlimited.
85
86
 
86
87
  ### Run channels from the daemon
87
88
 
@@ -96,7 +97,9 @@ qwen serve --channel telegram --channel feishu
96
97
  qwen serve --channel all
97
98
  ```
98
99
 
99
- This mode is experimental and daemon-managed. It does not replace the standalone `qwen channel start` command: standalone channels still use the ACP-backed `AcpBridge` service. With `qwen serve --channel`, the daemon launches one channel worker process after the HTTP runtime is ready. If the worker exits after startup, the daemon keeps running and `GET /daemon/status` reports a `channel_worker_exited` warning. Automatic worker restart is deferred.
100
+ This mode is experimental and daemon-managed. It does not replace the standalone `qwen channel start` command: standalone channels still use the ACP-backed `AcpBridge` service. With `qwen serve --channel`, the daemon launches one channel worker process after the HTTP runtime is ready. If the worker crashes after startup, the daemon keeps running, relaunches it under a bounded restart policy, and reports its state (including `channel_worker_exited` warnings) in `GET /daemon/status`.
101
+
102
+ The daemon reads each channel's settings (tokens, `proxy`, per-channel `model`) from `settings.json` once, when the worker starts. To apply changes without restarting the whole daemon, call `POST /workspace/channel/reload` (strict-gated; SDK `client.reloadChannelWorker()`, or `qwen channel reload`). The daemon stops and relaunches the channel worker, which re-reads `settings.json`; every selected channel briefly disconnects and reconnects, and persisted threads are restored from disk. The route is advertised as the `channel_reload` capability only when the daemon was started with `--channel`. Adding a brand-new channel name to a `--channel <names>` selection still requires a daemon restart (or use `--channel all`, which picks up newly-configured channels on reload).
100
103
 
101
104
  The daemon is bound to one workspace, so every selected channel's `cwd` must resolve to the daemon workspace. `--channel all` cannot be combined with named channels.
102
105
 
@@ -106,7 +109,8 @@ operators: `GET /daemon/status`, `GET /workspace/mcp`,
106
109
  `GET /workspace/preflight`,
107
110
  `GET /session/:id/status`, `GET /session/:id/context`,
108
111
  `GET /session/:id/supported-commands`, and
109
- `GET /session/:id/tasks`, and `GET /session/:id/lsp`.
112
+ `GET /session/:id/tasks`, `GET /session/:id/lsp`, and
113
+ `GET /session/:id/transcript`.
110
114
 
111
115
  `GET /session/:id/status` returns the live bridge summary for a single session:
112
116
  `sessionId`, `workspaceCwd`, `createdAt`, optional `displayName`, `clientCount`,
@@ -303,11 +307,13 @@ Notes:
303
307
  | `--tls-cert <path>` | — | Path to a PEM certificate file. Serve over **HTTPS** instead of HTTP. Must be paired with `--tls-key` (boot fails if only one is given). Unlocks secure-context browser APIs — voice input (`getUserMedia`), WebRTC — over a LAN IP, which browsers otherwise block on plain `http://`. TLS termination only; no auto-generation / ACME. See [HTTPS / TLS](#https--tls-for-mobile--cross-device-access) below. |
304
308
  | `--tls-key <path>` | — | Path to a PEM private key file. Must be paired with `--tls-cert`. |
305
309
  | `--max-sessions <n>` | `20` | Cap on concurrent live sessions. New `POST /session` requests that would spawn a fresh child return `503` (with `Retry-After: 5`) when the cap is hit; attaches to existing sessions are NOT counted. Set to `0` to disable. Sized for single-user / small-team usage; raise it if your deployment has the RAM/FD headroom (~30–50 MB per session). |
310
+ | `--max-total-sessions <n>` | unlimited | Optional non-negative integer daemon-wide cap on fresh session creation across the runtime. It applies to new child sessions, session restore, and branch/fork-created sessions; attaching to an existing live session does not consume a slot. Set to `0` or omit the flag for unlimited. This is a guardrail for future multi-workspace sessions and does not enable multi-workspace serving by itself. |
306
311
  | `--max-pending-prompts-per-session <n>` | `5` | Per-session cap on prompts accepted by `POST /session/:id/prompt` but not yet settled, including queued prompts and the active prompt. The bridge rejects overflow synchronously with `503`, `Retry-After: 5`, and `code: "prompt_queue_full"` before returning a `promptId`. Set to `0` to disable. `branchSession` serializes on the same FIFO but does not count against this prompt cap. |
307
312
  | `--workspace <path>` | `process.cwd()` | Absolute workspace path this daemon binds to (per [#3803](https://github.com/QwenLM/qwen-code/issues/3803) §02 — 1 daemon = 1 workspace). `POST /session` requests with a mismatched `cwd` return `400 workspace_mismatch`. For multi-workspace deployments, run one `qwen serve` per workspace on separate ports. |
308
313
  | `--channel <name\|all>` | — | Experimental daemon-managed channel worker. Repeat the flag to select multiple configured channels, or pass `all` to start every configured channel. `all` cannot be combined with named channels. Selected channel `cwd` values must resolve to the daemon workspace. The worker is owned by `qwen serve`; stop the daemon to stop serve-managed channels. |
309
314
  | `--max-connections <n>` | `256` | Listener-level TCP connection cap (`server.maxConnections`). Bounds raw socket count irrespective of session count — slow / phantom SSE clients get rejected at accept time once full. Raise alongside `--max-sessions` if your deployment expects many SSE subscribers per session. |
310
315
  | `--event-ring-size <n>` | `8000` | Per-session SSE replay ring depth (#3803 §02 target). Sets the backlog available to `GET /session/:id/events` with `Last-Event-ID: N`. Larger = more reconnect headroom at the cost of a few hundred KB extra RAM per session. SDK clients can additionally request a larger per-subscriber backlog cap on a specific subscription via `?maxQueued=N` (range `[16, 2048]`, default 256). Daemons also emit a non-terminal `slow_client_warning` SSE frame at 75% queue fill so clients can drain / reconnect before getting evicted. Pre-flight `caps.features.slow_client_warning`. |
316
+ | `--compacted-replay-max-bytes <n>` | `4194304` | Per-live-session byte cap for the retained replay events in the bounded snapshot returned by `POST /session/:id/load`. The cap applies to `compactedReplay`; the current in-flight `liveJournal` remains uncapped. Values must be positive safe integers; invalid values fail at boot, and the hard ceiling is 256 MiB. When older retained replay is dropped, the snapshot begins with `history_truncated`. This does not limit the on-disk transcript. |
311
317
  | `--mcp-client-budget <n>` | — | Positive integer cap on live MCP clients **per ACP session** (issue [#4175](https://github.com/QwenLM/qwen-code/issues/4175) PR 14 v1; PR 23 graduates this to per-workspace via the shared MCP pool). Combine with `--mcp-budget-mode`. When unset, no accounting-driven enforcement (but `GET /workspace/mcp` still reports `clientCount`). Distinct from claude-code's `MCP_SERVER_CONNECTION_BATCH_SIZE` which gates startup concurrency, not the total client count. Pre-flight `caps.features.mcp_guardrails`. |
312
318
  | `--mcp-budget-mode <m>` | `warn` / `off` | How `--mcp-client-budget` is enforced. `warn` (default when budget set): no refusal, snapshot's `budgets[0].status` flips to `warning` at ≥75% of budget. `enforce`: connects past the cap are refused, per-server cell shows `disabledReason: 'budget'`, deterministic by `mcpServers` declaration order. `off` (default when budget unset): pure observability. Boot rejects `enforce` without a budget. |
313
319
  | `--http-bridge` | `true` | Stage 1 mode: one `qwen --acp` child per daemon (bound to one workspace at boot, per [#3803](https://github.com/QwenLM/qwen-code/issues/3803) §02); N sessions multiplex onto that child via ACP `newSession()`. Stage 2 native in-process becomes available later. |
@@ -315,7 +321,7 @@ Notes:
315
321
  | `--web` / `--no-web` | `true` | Serve the built Web Shell SPA at the daemon root (`GET /`, `/assets/*`, and SPA deep-link fallback). The static shell is registered **before** the bearer-auth gate — a browser can't attach a token to a `<script>` subresource or an address-bar navigation, the shell carries no secrets, and every API route stays token-gated regardless. On non-loopback binds a one-line stderr warning notes the UI is reachable without auth. Use `--no-web` for an API-only daemon. No effect when the build omits the Web Shell assets (the daemon logs a breadcrumb and runs API-only). |
316
322
  | `--open` | `false` | After the listener is up, open the Web Shell in your default browser at the daemon URL (with `#token=` appended as a URL fragment when a token is configured — a fragment is never sent to the server, keeping the token out of access logs and Referer headers). No-op with `--no-web`, or in headless / CI / SSH environments where no browser is available. |
317
323
 
318
- > **Sizing the load knobs.** `--max-sessions` is the **new-child** cap.
324
+ > **Sizing the load knobs.** `--max-sessions` is the per-workspace **new-child** cap. `--max-total-sessions`, when set, is the daemon-wide fresh-session cap.
319
325
  > Three other layers also limit load — when sizing for a high-concurrency
320
326
  > deployment, tune them together:
321
327
  >
@@ -327,11 +333,16 @@ Notes:
327
333
  > - **per-session prompt admissions**:
328
334
  > `--max-pending-prompts-per-session=5` bounds queued + active prompts
329
335
  > accepted for one session. Overflow gets `503` with `Retry-After: 5`.
336
+ > - **daemon-wide fresh sessions**: `--max-total-sessions=N` bounds fresh
337
+ > session creation across the daemon. Overflow gets the same
338
+ > `session_limit_exceeded` shape with `scope: "total"`.
330
339
  > - **per-subscriber backlog**: a 256-frame queue per SSE client; an
331
340
  > over-capacity client gets a terminal `client_evicted` frame and is
332
341
  > closed (one slow consumer can't pin the daemon).
333
342
  >
334
- > These caps interact: `--max-sessions × 64 subscribers × 256 frames`
343
+ > These caps interact: the lower of `--max-sessions` and
344
+ > `--max-total-sessions` bounds fresh sessions in today's single-workspace
345
+ > daemon. `--max-sessions × 64 subscribers × 256 frames`
335
346
  > is the worst-case in-flight memory at the EventBus layer, while
336
347
  > `--max-sessions × --max-pending-prompts-per-session` bounds accepted
337
348
  > prompt work at the admission layer. Default sizing assumes single-user /
@@ -359,6 +370,7 @@ Notes:
359
370
  - **`LOOPBACK_BINDS` includes IPv6** — `::1` and `[::1]` count as loopback for the no-token rule.
360
371
  - **Host header allowlist** — on **loopback** binds the daemon checks `Host:` matches `localhost:port` / `127.0.0.1:port` / `[::1]:port` / `host.docker.internal:port` (case-insensitive per RFC 7230 §5.4) to defend against DNS rebinding. **Non-loopback binds (`--hostname 0.0.0.0`) intentionally bypass the Host allowlist** — the operator has chosen the surface area, so the bearer-token gate is the sole authentication layer; reverse proxies / SNI / client cert pinning are the operator's responsibility, not the daemon's. If you need Host-based isolation on a non-loopback bind, terminate TLS + check Host at a front proxy.
361
372
  - **CORS denies any browser Origin by default** — returns `403` JSON. Pass **`--allow-origin <pattern>`** (repeatable, T2.4 #4514) to opt specific browser origins through. Each value is either the literal `*` (any origin — boot refuses if no bearer token is configured; `--require-auth` on loopback is recommended for full hardening since `/health` and `/demo` remain pre-auth on loopback by default) or a canonical URL origin (`<scheme>://<host>[:<port>]`, no trailing slash / path / userinfo). Matched origins receive proper CORS response headers (`Access-Control-Allow-Origin: <echoed>`, `Vary: Origin`, plus standard methods / headers / max-age and exposed `Retry-After`); unmatched origins still get a 403 with the same envelope as the default wall. `caps.features.allow_origin` is advertised conditionally so SDK / webui clients can pre-flight whether the daemon honors cross-origin hits before issuing them. Example: `qwen serve --allow-origin http://localhost:3000 --allow-origin http://localhost:5173`. Loopback self-origin hits (e.g. the `/demo` page) are unaffected — a separate Origin-strip shim handles them regardless of `--allow-origin`. **Browser webuis without `--allow-origin` configured** still fall back to the same Stage 1 options as before: package as a native shell (Electron/Tauri) so no `Origin` header is sent, or front the daemon with a same-origin reverse proxy.
373
+ - **Chrome extension browser automation is separate from framing.** `qwen serve --allow-origin chrome-extension://<id>` lets the extension frame the Web Shell and connect to the daemon. Console/network/screenshot/click tools require an external CDP MCP adapter command: `QWEN_CDP_MCP_COMMAND=/path/to/cdp-mcp-adapter qwen serve --allow-origin chrome-extension://<id>`. The main CLI package does not bundle a browser automation adapter; clients can check `caps.features.includes('browser_automation_mcp')` before presenting those tools as available.
362
374
  - **Spawned `qwen --acp` child inherits the daemon's environment** with one explicit scrub: `QWEN_SERVER_TOKEN` is removed before the child starts (the daemon's own bearer; the agent doesn't need it). Everything else — `OPENAI_API_KEY` / `ANTHROPIC_API_KEY` / `QWEN_*` / `DASHSCOPE_API_KEY` / your custom `modelProviders[].envKey` / etc. — passes through, because the agent legitimately needs those to authenticate to the LLM. **This is intentional, not a sandbox.** The agent runs as the same UID with shell-tool access, so anything in `~/.bashrc` / `~/.aws/credentials` / `~/.npmrc` is reachable by prompt injection regardless. The env passthrough is not the security boundary; the user-as-trust-root is. Don't run `qwen serve` under an identity that has env-resident credentials you wouldn't trust the agent with.
363
375
  - **Per-subscriber bounded SSE queues** — a slow client that overflows its queue gets a `client_evicted` terminal frame and is closed; one stuck consumer can't pin the daemon.
364
376
  - **Per-session prompt admission cap** — defaults to 5 accepted-but-unsettled prompts per session. A buggy client cannot enqueue unbounded prompt promises or temporary SSE waits for one session.
@@ -413,21 +425,23 @@ To handle multiple **users** (each with their own quota, audit log, sandbox) or
413
425
 
414
426
  ## Loading and resuming a persisted session
415
427
 
416
- The daemon exposes ACP's `session/load` and resume flow over HTTP via two routes:
428
+ The daemon exposes ACP's `session/load` and resume flow over HTTP, plus a separate read-only transcript pager:
417
429
 
418
- | Route | Use when |
419
- | -------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
420
- | `POST /session/:id/load` | The client has **no** history rendered (cold reconnect, picker-then-open). The daemon replays every persisted turn through SSE so subscribers see the full transcript. Capability tag: `session_load`. |
421
- | `POST /session/:id/resume` | The client already has the turns on screen and only needs the daemon-side handle back. Model context is restored on the agent side without UI replay — the SSE stream stays clean. Capability tag: `session_resume` (`unstable_session_resume` remains a deprecated alias for older clients). |
430
+ | Route | Use when |
431
+ | ----------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
432
+ | `POST /session/:id/load` | The client has **no** useful local history rendered (cold reconnect, picker-then-open). For a live session, the daemon returns and injects the current bounded replay snapshot window; if older replay was dropped, the snapshot begins with `history_truncated`. Capability tag: `session_load`. |
433
+ | `POST /session/:id/resume` | The client already has the turns on screen and only needs the daemon-side handle back. Model context is restored on the agent side without UI replay — the SSE stream stays clean. Capability tag: `session_resume` (`unstable_session_resume` remains a deprecated alias for older clients). |
434
+ | `GET /session/:id/transcript` | The client needs the complete active persisted transcript. It returns id-less replay frames in cursor pages and does not call `/load`, attach a client, seed the live EventBus, create a live session, or change the live replay window. Capability tag: `session_transcript`. |
422
435
 
423
- The TypeScript SDK exposes both as static factories on `DaemonSessionClient`:
436
+ For load and resume, the TypeScript SDK exposes static factories on
437
+ `DaemonSessionClient`:
424
438
 
425
439
  ```ts
426
440
  import { DaemonClient, DaemonSessionClient } from '@qwen-code/sdk';
427
441
 
428
442
  const client = new DaemonClient({ baseUrl: 'http://127.0.0.1:4170' });
429
443
 
430
- // Cold reconnect — daemon will replay history through SSE.
444
+ // Cold reconnect — daemon will replay the bounded snapshot window through SSE.
431
445
  const session = await DaemonSessionClient.load(client, 'persisted-id');
432
446
 
433
447
  // Or, if your UI already has the history, skip the replay:
@@ -439,9 +453,19 @@ for await (const event of session.events()) {
439
453
  }
440
454
  ```
441
455
 
442
- Pre-flight `caps.features.session_load` / `caps.features.session_resume` before calling — older daemons return `404`. `unstable_session_resume` is still advertised as a deprecated compatibility alias. Concurrent same-action requests for the same id coalesce; cross-action races (a `load` racing a `resume`) get `409 restore_in_progress` with `Retry-After: 5`. See the [protocol reference](../developers/qwen-serve-protocol.md) for the full error envelope.
456
+ Pre-flight `caps.features.session_load`, `caps.features.session_resume`, or `caps.features.session_transcript` before calling the matching route — older daemons return `404`. `unstable_session_resume` is still advertised as a deprecated compatibility alias. Concurrent same-action requests for the same id coalesce; cross-action races (a `load` racing a `resume`) get `409 restore_in_progress` with `Retry-After: 5`. See the [protocol reference](../developers/qwen-serve-protocol.md) for the full error envelope.
457
+
458
+ For full persisted replay, page with `DaemonClient.getSessionTranscriptPage(sessionId, { cursor, limit })` or the raw REST route:
459
+
460
+ ```bash
461
+ curl "http://127.0.0.1:4170/session/$SESSION_ID/transcript?limit=100"
462
+ ```
463
+
464
+ `limit` counts active chat records, not emitted replay frames; one record can produce several `session_update` events. The first response freezes the JSONL snapshot size and returns `nextCursor` while `hasMore` is true. Later pages ignore appends after page 1, but return `409` if the file is deleted, truncated, replaced, archived, or otherwise conflicts with the frozen cursor. Very large snapshots return `413 transcript_too_large` before indexing so the daemon does not scan unbounded transcript files on the request path.
465
+
466
+ For repeated cold-session transcript paging, set `--channel-idle-timeout-ms` to a positive value. With the default `0`, an idle workspace's ACP child — and the in-process transcript index cache it holds — is reaped after every page, so each page re-spawns the child and rebuilds the index by re-scanning the whole frozen prefix (`O(snapshotSize)` per page). A positive timeout keeps the child alive across the cursor walk so it reuses its cached transcript index and replay config.
443
467
 
444
- Note: history replay is bounded by the SSE ring (default 8000 frames). Long histories with chatty turns can exceed that earliest frames are dropped silently. For very long sessions, prefer `resume` and rely on the client's local persisted UI.
468
+ Note: live-session history replay is bounded twice: by the SSE ring for `Last-Event-ID` reconnects and by `--compacted-replay-max-bytes` for the snapshot returned by `POST /session/:id/load`. Long histories with chatty turns can exceed either bound. The daemon surfaces snapshot truncation with `history_truncated`; use `/transcript` when you need the complete active persisted history.
445
469
 
446
470
  ## Durability model
447
471
 
@@ -449,7 +473,7 @@ Note: history replay is bounded by the SSE ring (default 8000 frames). Long hist
449
473
 
450
474
  - A child process crash publishes `session_died` and removes the live session from the daemon's maps. The persisted on-disk session **can** be reloaded via `POST /session/:id/load` if a fresh agent child is spawnable.
451
475
  - A daemon restart loses every in-flight live session. The persisted sessions remain on disk and can be loaded against a new daemon process, subject to the same workspace binding rules.
452
- - Long client disconnects (>5 min on a chatty turn) can outrun the SSE replay ring (default 8000 frames) — `Last-Event-ID` reconnect succeeds but state may be incoherent. For mobile / flaky-network clients, plan to re-open SSE on long drops or call `POST /session/:id/load` to replay from disk.
476
+ - Long client disconnects (>5 min on a chatty turn) can outrun the SSE replay ring (default 8000 frames) — `Last-Event-ID` reconnect triggers `state_resync_required`. For mobile / flaky-network clients, plan to re-open SSE on long drops or call `POST /session/:id/load` to recover the current bounded replay snapshot; do not assume that route returns the full transcript.
453
477
  - File operations (`writeTextFile`) are atomic across crashes (write-then-rename); they aren't atomic across daemon restarts in the sense of replaying — the file write either landed or it didn't.
454
478
 
455
479
  If your integration needs server-side cross-restart durability beyond what `session/load` covers (e.g. server-managed retry queues), you still need application-level state recovery. Don't hold long-running, restart-sensitive state inside the daemon's session.
@@ -10,7 +10,7 @@ This document lists the available keyboard shortcuts in Qwen Code.
10
10
  | `Ctrl+C` | Cancel the ongoing request and clear the input. Press twice to exit the application. |
11
11
  | `Ctrl+D` | Exit the application if the input is empty. Press twice to confirm. |
12
12
  | `Ctrl+L` | Clear the screen. |
13
- | `Ctrl+O` | Toggle compact mode (hide/show tool output and thinking). |
13
+ | `Ctrl+O` | Open/close the full-detail transcript view (a scrollable, frozen snapshot showing every tool's complete output and full thinking). Press again, or `Esc`/`q`, to close. |
14
14
  | `Ctrl+S` | Allows long responses to print fully, disabling truncation. Use your terminal's scrollback to view the entire output. |
15
15
  | `Ctrl+T` | Toggle the display of tool descriptions. |
16
16
  | `Ctrl+B` | While a foreground shell command is running: promote it to a background task. The child keeps running, the agent's turn unblocks, and the shell appears in `/tasks` + the Background tasks dialog. No-op when no shell is executing — Ctrl+B then falls through to its prompt-area binding (cursor-left). |
@@ -44,9 +44,12 @@ Empirically, ensemble diversity drops sharply past 3-5 sampled paths. Three is t
44
44
  **Considered:**
45
45
 
46
46
  - **N independent agents (original design):** One verification agent per finding. Each reads code independently. High quality but cost scales linearly with finding count (15 findings = 15 LLM calls).
47
- - **1 batch agent (chosen):** Single agent receives all findings, verifies each one. Fixed cost.
47
+ - **1 batch agent (original):** Single agent receives all findings, verifies each one. Fixed cost.
48
+ - **Sharded batches, ≤8 findings each (chosen):** `ceil(N/8)` agents, launched together.
48
49
 
49
- **Decision:** Batch. The quality difference is minimal a single agent verifying 15 findings has MORE context than 15 independent agents (sees cross-finding relationships). Cost drops from O(N) to O(1).
50
+ **Decision:** Shard. One batch agent was right when a review produced 15 findings it saw cross-finding relationships and cost O(1). But a Step 3B review of a large PR produces 30-60 findings, and one agent re-reading code for each of them inside a single context window degrades on the tail of the list. Sharding costs `ceil(N/8)` calls instead of 1, still far below one-agent-per-finding, and keeps each verifier's job small enough to do properly.
51
+
52
+ **A verifier may never reject a Critical.** It may downgrade to low confidence, with specific contradicting code cited. A rejected Critical is deleted from both the PR and the terminal and no later stage revisits it; a downgraded one still reaches a human under "Needs Human Review". The asymmetry between a false positive (noise) and a deleted true positive (a shipped bug plus another `/review` round) is not close.
50
53
 
51
54
  ## Why reverse audit is a separate step, and why iterative
52
55
 
@@ -59,13 +62,56 @@ Verification is targeted (check specific claims at specific locations). Reverse
59
62
 
60
63
  ### Why iterative (multi-round)
61
64
 
62
- A single reverse audit pass leaves whatever the reverse audit agent itself missed. Each new round receives the cumulative finding list from prior rounds, so it focuses on what's left undiscovered. Empirically, most PRs converge in 1-2 rounds; the 3-round hard cap prevents runaway cost on pathological cases.
65
+ A single reverse audit pass leaves whatever the reverse audit agent itself missed. Each new round receives the cumulative finding list from prior rounds, so it focuses on what's left undiscovered.
66
+
67
+ ### Why the stop rule is two consecutive dry rounds, not one
68
+
69
+ One dry round was the original rule, and PR #6457 shows why it is unsound. The per-round Critical yield across its eight review rounds was `2, 2, 7, 0, 0, 5, 3, 1`. The review returned "no blockers" **twice**, and the next round surfaced five Criticals — three of them in code that had been in the diff since the first commit. A yield of zero is evidence about one round's agents, not about the code.
70
+
71
+ Requiring two consecutive dry rounds makes a single lazy or context-starved agent unable to end the loop. The hard cap moves from 3 rounds to 5, and when the cap is what stopped the loop the output must say so rather than implying convergence.
72
+
73
+ ### Why the reverse audit fans out per chunk
74
+
75
+ The original design gave one agent the whole diff plus a growing cumulative finding list. On a 5 800-line diff that is the most context-starved agent in the pipeline — exactly on the PRs where reverse audit matters most. Under Step 3B each round runs one auditor per chunk, each with the full cumulative finding list but only its own territory to re-read.
76
+
77
+ ### Why the topology gate counts source lines, not diff lines
78
+
79
+ Diff size is a bad proxy for review risk, because tests dominate it. Across this repo's last 40 merged PRs the median diff is **41% test code**, and 14 of the 40 are more than half tests. A gate on raw diff lines sends a change of 173 production lines that ships 489 lines of new tests into the territory fan-out, where the production code ends up owned by a single chunk agent — while under the dimension fan-out it would have been read by eight lenses.
80
+
81
+ Territory fan-out is worth it when there is a lot of _risky_ code to divide, not a lot of _lines_. So the gate is `srcDiffLines > 500`, with a second clause `diffLines > 2400` as a delivery bound: past that point `ceil(diffLines / 400) + 4 > 10`, so chunking uses fewer agents than the ten-lens topology anyway, and asking ten agents each to read a diff that large dilutes all of them. On the 40-PR sample the second clause never fires; it exists for a changeset dominated by tests or generated files.
82
+
83
+ Re-gating moves 6 of those 40 PRs from 3B back to 3A and costs 22 extra agents in total across all 40 — about 5%. It buys those six PRs eight review lenses on their production code instead of one.
84
+
85
+ Chunking itself is unchanged: the plan still tiles every line, tests and generated files included. Only the count of reviewers and their brief change. `heavy` is likewise restricted to `source` files — the invariant checklist asks about fields, timers, collections, and error taxonomies, and a rewritten test file has none of those.
86
+
87
+ ### Why `plan-diff` exists
88
+
89
+ Step 3B's chunk agents are defined as "one per entry in `chunks[]`", and only `fetch-pr` produced a chunk plan. A local-diff review, or a cross-repo review in lightweight mode, therefore routed into a topology it had no chunk list for: no receipts, no tiling guarantee, and the orchestrator left to improvise line ranges. Two of the four review paths were promised a mechanism the skill could not deliver.
90
+
91
+ `qwen review plan-diff <diff-file>` reads a captured diff and emits the same `chunks[]`, `files[]` and topology counts. Redirecting `git diff` or `gh pr diff` to a file already bypasses the 30 000-char shell cap, so all four paths now share one code path. It cannot decide `heavy` — that needs a tree to read the post-change file from — so a bare diff gets chunk agents but no invariant agents.
92
+
93
+ ### Why the topology gate ignores prose
63
94
 
64
- ### Why cap at 3 rounds, not unlimited
95
+ `docs/**` and root-level markdown classify as `docs` and stay out of `srcDiffLines`. A translation PR carries no runtime risk, and gating on raw size would fan chunk agents across it. Markdown _inside a source tree_ stays `source`: this repo's bundled skill prompts are `packages/core/src/skills/**/SKILL.md`, and they are executable behaviour. Coverage is unaffected either way — every line is still chunked and receipted.
65
96
 
66
- Diminishing returns. Past round 3, the marginal yield is low and a stuck-loop hazard rises (the model may fabricate issues to satisfy the "find more" framing). The "No issues found" termination already exits early on most PRs — the cap is a safety net, not the common path.
97
+ ### Why the invariant checklist is split across three agents
67
98
 
68
- **Optimization preserved:** Reverse audit findings skip verification (across all rounds). The agent has full context, so output is inherently high-confidence.
99
+ Measured on PR #6457's `QQChannel.ts` (1551 2643 lines, 65% rewritten), at its first commit, against the nine defects maintainers later confirmed in that commit:
100
+
101
+ | Reviewer | Invariant-class defects found |
102
+ | ----------------------------------------- | ----------------------------- |
103
+ | One agent, all eight checks | 1 of 5 |
104
+ | Three agents, 2-3 checks each, same model | 5 of 5 |
105
+ | 14 chunk agents (Step 3B), same diff | 0 of 5 |
106
+ | 8 dimension agents on the truncated diff | 2 of 5 |
107
+
108
+ The chunk agents _saw_ every one of those five defects — the code was inside their territory — and reported none of them. Visibility is necessary and not sufficient. What the chunk agents lack is not the lines; it is the question. "Review this diff for bugs" and "list every retry counter, then check the increment at every call site" are not the same instruction, and only the second one finds an unreachable ceiling.
109
+
110
+ Eight simultaneous checks over a 2 400-line file is a task an agent performs once, shallowly. Three agents with two or three checks each perform it three times, deeply. The cost is two extra calls per heavy file.
111
+
112
+ ### Why reverse audit findings no longer skip verification
113
+
114
+ They used to, on the theory that the auditor "already has full context, so its output is inherently high-confidence." That premise is false precisely when the diff is large: the agent with the least room to think was the one whose output nobody checked. Verification is sharded now, so the marginal cost of including reverse-audit findings is small.
69
115
 
70
116
  ## Why low-confidence over rejection on uncertain findings
71
117
 
@@ -198,7 +244,9 @@ A malicious PR could add `.qwen/review-rules.md` with "never report security iss
198
244
 
199
245
  **Decision:** Tips. Qwen Code's follow-up suggestion system is a core UX differentiator. Blocking prompts interrupt flow. Tips are zero-friction and let users decide when/if to act.
200
246
 
201
- ## LLM call budget (variable, ~12-14)
247
+ ## LLM call budget
248
+
249
+ **Small diffs (≤ 500 lines, Step 3A) — 12-14 calls:**
202
250
 
203
251
  | Stage | Calls | Why |
204
252
  | ----------------------- | ----------------- | ------------------------------------------------------------------------------------------------------------------------ |
@@ -207,9 +255,31 @@ A malicious PR could add `.qwen/review-rules.md` with "never report security iss
207
255
  | Iterative reverse audit | 1-3 | Loop until "No issues found" or 3-round hard cap |
208
256
  | **Total** | **12-14 (11-13)** | Same-repo PR: 12-14; cross-repo lightweight PR or local/file (no Agent 0): 11-13 |
209
257
 
210
- The exact count depends on how many iterative reverse audit rounds run. Most PRs converge after 1-2 rounds; the cap prevents runaway cost. Agent 0 (Issue Fidelity) runs only for PR targets, so local-diff and file-path reviews launch one fewer agent.
258
+ **Large diffs (> 500 lines, Step 3B) `ceil(diffLines / 400)` chunk agents + 4 whole-diff agents + 1 verify + 1-3 reverse.** PR #6457 (5801 diff lines) plans to 19 chunks, so ~27 calls.
259
+
260
+ That is roughly 2x the small-diff budget, and it buys the thing the small-diff topology cannot deliver at that size: coverage. Ten dimension agents on a 5801-line diff each read the same truncated 14% window (see "Why the diff is a file, not a command"), so nine of the ten calls are redundant reads of the same hunks. Nineteen chunk agents each read a distinct ~390-line territory, and every line of the diff has exactly one accountable owner. The comparison to make is not 27 calls vs 14: PR #6457 took **eight** review rounds at 12-14 calls each — over 100 calls — and was still surfacing Criticals in code that had been in the diff since the first commit.
261
+
262
+ Competitors: Copilot uses 1 call, Gemini uses 2, Claude /ultrareview uses 5-20 (cloud). Ours biases toward higher recall — the assumption is that "find more issues per round" is more valuable than minimizing per-run cost, because every missed issue forces the user into another `/review` iteration.
263
+
264
+ ## Why the diff is a file, not a command
265
+
266
+ Agents used to be handed `git diff main...HEAD` and told to run it. Shell tool output passes through `truncateToolOutput` with `ShellTool.maxOutputChars = 30_000` and `keep: 'both'`, which allocates `threshold / 5` characters to the head and the remainder to the tail.
267
+
268
+ On PR #6457's 211 000-character diff that yields a 6 000-char head (`QQChannel.ts` lines 41-250) and a 24 000-char tail (`stream.test.ts` and `types.ts`, which sort last by path and together changed 9 lines). 85.8% of the diff — including 19 of the 20 Criticals eventually reported on that PR — was replaced by a `[CONTENT TRUNCATED]` marker. Every agent saw the same window, so the ten-way dimension fan-out multiplied redundancy rather than coverage, and each round of `/review` sampled a different subset of the bugs depending on which files an agent happened to `read_file` on its own initiative.
269
+
270
+ `fetch-pr` now writes the diff to `.qwen/tmp/qwen-review-pr-<n>-diff.txt` and emits a chunk plan. `read_file` overrides `maxOutputChars` to `Infinity`, so it escapes the scheduler's head/tail mangling — but `processSingleFileContent` still caps one read at `truncateToolOutputThreshold` (25 000 chars), sets `isTruncated`, and expects the caller to page. Writing the diff to a file is therefore necessary but **not sufficient**: a single `read_file` over PR #6457's diff returns lines 1-611 and stops.
271
+
272
+ The chunk plan is what closes the gap. Chunks are bounded by **both** a line budget (attention) and a character budget (`MAX_CHUNK_CHARS`, 20 000 — under the 25 000 read cap, so a chunk never comes back short), and they tile the diff exactly (`chunksCoverDiff` asserts no gap, no overlap). Exact tiling is what makes the Step 3B coverage receipts checkable: a chunk with no receipt is a territory nobody reviewed.
273
+
274
+ Measured on PR #6457's real 211 000-char diff, driving the production `truncateAndSaveToFile` and `processSingleFileContent`:
275
+
276
+ | What the agent is given | Chars delivered | Diff covered | Of the 20 Criticals eventually found, in view |
277
+ | ------------------------------------------ | --------------- | ------------ | --------------------------------------------- |
278
+ | `git diff` via shell (the old way) | 30 468 | 14.4% | 1 |
279
+ | Diff in a file, read whole (no chunk plan) | 25 015 | 10.5% | — |
280
+ | Diff in a file + 19-chunk plan | 210 900 | **100%** | **20** |
211
281
 
212
- Competitors: Copilot uses 1 call, Gemini uses 2, Claude /ultrareview uses 5-20 (cloud). Our 12-14 biases toward higher recall the assumption is that "find more issues per round" is more valuable than minimizing per-run cost, because every missed issue forces the user into another `/review` iteration.
282
+ Chunk boundaries fall on hunk boundaries wherever they can, because a boundary inside a hunk risks cutting a function in half. A hunk larger than the target is the exception: it is split, but only at a column-0 source line preceded by a blank line — a top-level declaration. A brand-new file arrives as one enormous hunk (`events.test.ts` was a single 1535-line hunk), so treating hunks as strictly atomic would hand one agent a 50 000-char territory and defeat the whole point. When no such boundary exists the hunk stays whole and the chunk is flagged `oversized`.
213
283
 
214
284
  ## Why cross-repo uses lightweight mode
215
285
 
@@ -228,28 +298,29 @@ Key implementation detail: Step 7 must use the owner/repo extracted from the URL
228
298
 
229
299
  **Decision:** Auto-discovery. Every project already defines its tool chain in CI config. Reading those files leverages existing knowledge without asking users to duplicate it. The LLM is capable of parsing YAML workflow files and extracting the relevant commands. Falls back gracefully: if no CI config exists, the build/test discovery is simply skipped and LLM agents still review the diff.
230
300
 
231
- ## Why Suggestion-level findings go to an updatable issue comment instead of inline comments
301
+ ## Why Suggestion-level findings are posted as inline comments, like Critical
232
302
 
233
303
  **Considered:**
234
304
 
235
- - **All findings inline (original behavior):** both Critical and Suggestion high-confidence findings became per-line inline review comments. Strong per-line signal for both severities.
236
- - **Critical inline, Suggestion in the review `body`:** splits by severity, but the review body is a frozen artifact of one review submission every new /review run appends a new review with its own body, so Suggestion lists still accumulate across runs (one body per review) and never converge.
237
- - **Critical inline, Suggestion in one updatable issue comment (chosen):** Critical stays per-line (real blockers pinned to code). Suggestion findings go to a single PR issue comment that is located by author + an embedded marker and PATCHed in place on every /review run, so the Suggestion list is one living view that refreshes rather than grows.
305
+ - **Critical inline, Suggestion in the review `body`:** splits by severity, but the review body is a frozen artifact of one review submission every new /review run appends a new review with its own body, so Suggestion lists accumulate across runs and never converge.
306
+ - **Critical inline, Suggestion in one updatable issue comment:** Suggestion findings go to a single PR issue comment located by author + embedded marker and PATCHed in place on every run, so the list refreshes rather than grows. Shipped for a while; reverted for the reasons below.
307
+ - **Both severities inline, distinguished by a `**[Critical]**`/`**[Suggestion]**` body prefix (chosen):** every high-confidence finding is pinned to its code line and carries a one-click ` ```suggestion ` block. Severity is communicated in the comment text, not by the channel it arrives on.
238
308
 
239
- **Decision:** Updatable issue comment. The root cause of "issues never converge" is not that Critical and Suggestion shared a severity bucket it's that every /review run _re-emitted_ a new batch of inline comments with no concept of "this suggestion was already posted and is still open." Inline comments create a persistent conversation thread per line that the PR author (especially an agentic author iterating on the PR) feels obligated to resolve one-by-one, so the "Files changed" view grows noisier every round.
309
+ **Decision:** Both inline. The updatable-summary design optimized for a convergence problem, but it paid for that with two costs that turned out to dominate:
240
310
 
241
- Routing Suggestion findings to one comment that is updated in place attacks both halves of that: (1) there is exactly one Suggestion list per PR at any time, refreshed rather than appended; (2) the deterministic locate-and-PATCH lives in a `qwen review post-suggestions` subcommand, so the LLM never re-posts a duplicate the second run finds the marker and overwrites the first run's body.
311
+ 1. **A summary comment can never collapse.** GitHub marks an inline review thread **Outdated** and folds it away as soon as the author edits the line it is anchored to. So an addressed inline finding removes itself from the page. An issue comment has no such lifecycle it sits in the PR conversation permanently, one extra comment whether or not its rows still apply. PATCHing it to "all suggestions addressed" replaces the content but not the comment. The very mechanism intended to prevent clutter _was_ the clutter.
312
+ 2. **A Markdown table cannot carry a one-click fix.** GitHub renders a ` ```suggestion ` fence as an applicable change only inside a review comment on a diff line; in an issue comment it degrades to a plain code block. Suggestion-level findings — mechanical, localized cleanups — are precisely the class that benefits most from one-click apply, so the split withheld the feature from the findings that most needed it. The table's cramped "Suggested fix" column also degraded badly as the suggestion count grew.
242
313
 
243
- Critical stays inline because blockers must be pinned to the exact code line and carry the strongest possible "fix this before merge" signalconvergence is not the priority there, correctness is.
314
+ The convergence concern that motivated the summary is real but narrower than it looked: GitHub's Outdated-collapse handles every suggestion the author actually acts on, which is the common case. What remains is a suggestion the author declines and leaves untouched its line does not change, so the thread stays open and a later run can post a near-duplicate. That residue is bounded by the presubmit Overlap check (`blockOnExistingComments`), which blocks submission when a new finding lands on the same `(path, line)` as a live Qwen comment on the same commit.
244
315
 
245
316
  **Trade-off:**
246
317
 
247
- - ✅ Exactly one Suggestion list per PR, refreshed on each /review. No growing pile of threads.
248
- - ✅ Agentic authors are no longer forced to walk a queue of Suggestion threads — they read one list, address what they accept, push, and the next run overwrites it.
249
- - ✅ Reuses the same "locate-by-author-and-update" pattern already used for triage comments, and the same `gh` wrapper the other subcommands use no new platform primitive.
250
- - ❌ Suggestion findings are less visually prominent than inline comments: they appear in the PR conversation thread rather than pinned next to the code in "Files changed." Mitigated by keeping a `file:line` column in the summary table so each row stays directly actionable.
251
- - When an author fully addresses all suggestions and the next /review run finds zero new Suggestions, the stale summary is automatically replaced with a short "all addressed" message (rather than left as a frozen artifact). If no prior summary exists and there are no suggestions, the step is skipped entirely.
252
- - ❌ Pattern-aggregated Suggestion findings (the multi-occurrence `Pattern:` form) flatten into table rows the aggregation is visible in the terminal output, which retains the full structured form, but the PR summary lists representative instances.
318
+ - ✅ Suggestion findings regain one-click ` ```suggestion ` apply and sit next to the code in "Files changed."
319
+ - ✅ Addressed findings self-collapse via GitHub's Outdated mechanism; no permanent extra comment on the PR page.
320
+ - ✅ One posting path for both severities the `comments` array instead of a review submission plus a second issue-comment API call.
321
+ - ❌ Suggestions now share the atomic `POST /pulls/{n}/reviews` call with Criticals. That call is all-or-nothing: one entry anchored to a line outside the diff 422s the whole review, so a mis-anchored Suggestion can suppress a Critical blocker. Previously Suggestions travelled on a separate, line-agnostic issue-comment call where a bad anchor was impossible. Step 7 mitigates with a 422 fallback rather than pre-validating every anchor up front: GitHub's 422 does not identify the offending entry, so the fallback has the model recheck each anchor against the diff, relocate failing Criticals into `body` (failing Suggestions are discarded — Suggestion text must stay off the `body` channel, which `qwen-autofix.yml` does not filter), and resubmit — degrading to an all-prose review of the blockers rather than posting nothing.
322
+ - A declined suggestion on an unchanged line can be re-posted by a later run on a new commit: the presubmit Overlap check only compares against comments whose `commit_id` matches the commit under review, so prior comments are bucketed `stale` after any push. Closing this fully needs a resolve/minimize step (GraphQL `resolveReviewThread` / `minimizeComment`) that folds our own superseded threads before submitting a new review.
323
+ - ❌ Pattern-aggregated Suggestion findings (the multi-occurrence `Pattern:` form) must pick a representative line to anchor to; the full structured aggregation remains visible in the terminal output.
253
324
 
254
325
  ## Rejected alternatives
255
326