@qwen-code/qwen-code 0.19.8 → 0.19.9-preview.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (451) 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 +68 -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 +82 -7
  8. package/bundled/qc-helper/docs/features/channels/wecom.md +6 -0
  9. package/bundled/qc-helper/docs/features/code-review.md +109 -41
  10. package/bundled/qc-helper/docs/features/commands.md +45 -44
  11. package/bundled/qc-helper/docs/features/computer-use.md +77 -0
  12. package/bundled/qc-helper/docs/features/hooks.md +29 -0
  13. package/bundled/qc-helper/docs/features/sub-agents.md +21 -0
  14. package/bundled/qc-helper/docs/features/tool-use-summaries.md +19 -23
  15. package/bundled/qc-helper/docs/integration-vscode.md +2 -2
  16. package/bundled/qc-helper/docs/qwen-serve.md +66 -23
  17. package/bundled/qc-helper/docs/reference/keyboard-shortcuts.md +2 -2
  18. package/bundled/review/DESIGN.md +303 -46
  19. package/bundled/review/SKILL.md +670 -165
  20. package/chunks/MaxSizedBox-BEVSAWZ6.js +70 -0
  21. package/chunks/{StandaloneSessionPicker-EYRGH6PJ.js → StandaloneSessionPicker-2DA2MDDE.js} +81 -79
  22. package/chunks/{acpAgent-GRFTTRHW.js → acpAgent-G3WJU3PS.js} +1318 -465
  23. package/chunks/agent-DD3WSHXE.js +68 -0
  24. package/chunks/agent-headless-MHI7U2CU.js +62 -0
  25. package/chunks/{anthropicContentGenerator-CPF22MA7.js → anthropicContentGenerator-56U3YCP2.js} +187 -31
  26. package/chunks/{artifact-tool-D233YJFH.js → artifact-tool-MIZLXBLF.js} +5 -5
  27. package/chunks/{askUserQuestion-MKL5ZTMC.js → askUserQuestion-XMJVPNWM.js} +6 -6
  28. package/chunks/bridge-HKEWPNB5.js +78 -0
  29. package/chunks/{ca-MKD32FQL.js → ca-C2JTT2N5.js} +68 -6
  30. package/chunks/channel-worker-group-K7QKH6IG.js +13 -0
  31. package/chunks/channel-worker-manager-YSFB4HUU.js +418 -0
  32. package/chunks/channel-worker-supervisor-QCKIOYZD.js +20 -0
  33. package/chunks/chunk-2FMQQXMM.js +38 -0
  34. package/chunks/{chunk-CSOTA7KX.js → chunk-2FO5GFKZ.js} +2 -2
  35. package/chunks/{chunk-QQDPRDVW.js → chunk-2HRYPZT5.js} +1 -1
  36. package/chunks/{chunk-UXEW557D.js → chunk-2J4ZWME4.js} +3 -3
  37. package/chunks/{chunk-P3XEEI3X.js → chunk-2TQXXQMI.js} +36 -7
  38. package/chunks/{chunk-GSHQYYIV.js → chunk-2UW5RFRP.js} +6 -26
  39. package/chunks/{chunk-6IAWPIQ6.js → chunk-2W3OOD4W.js} +5 -3
  40. package/chunks/{chunk-2PSWA5ID.js → chunk-2X56YUSZ.js} +1 -1
  41. package/chunks/{chunk-NQKLOAVJ.js → chunk-2Z5UX4KI.js} +2 -2
  42. package/chunks/chunk-3MX7D6QN.js +516 -0
  43. package/chunks/{chunk-EEN2TKST.js → chunk-43RXPU5Q.js} +2 -2
  44. package/chunks/{chunk-55ZMG67I.js → chunk-4LD5APFL.js} +4 -4
  45. package/chunks/{chunk-WF4FAXDL.js → chunk-4QZ3XHWE.js} +62 -62
  46. package/chunks/chunk-4QZADKJS.js +34 -0
  47. package/chunks/{chunk-UIDXQNMV.js → chunk-4WGODMVR.js} +1 -1
  48. package/chunks/{chunk-E6US47KI.js → chunk-4WKAA4KS.js} +1 -1
  49. package/chunks/{chunk-TI3BWD4D.js → chunk-54UZQ57N.js} +39 -19
  50. package/chunks/{chunk-3GONHQOA.js → chunk-57OAHC2Y.js} +1 -1
  51. package/chunks/{chunk-JZSY4WP3.js → chunk-5DTTYNB7.js} +1 -1
  52. package/chunks/chunk-5HBA2Z7V.js +28 -0
  53. package/chunks/{chunk-SKAZWEV5.js → chunk-5M6IDOMF.js} +35 -98
  54. package/chunks/{chunk-A4BMJM77.js → chunk-5O2XNYP6.js} +1 -0
  55. package/chunks/{chunk-FQNC62B2.js → chunk-5VHASII5.js} +11 -11
  56. package/chunks/{chunk-GO6LNQXT.js → chunk-6AM5D4ME.js} +1 -1
  57. package/chunks/{chunk-BJBWRCSK.js → chunk-6H67XLET.js} +1 -1
  58. package/chunks/{chunk-O7FIRWJV.js → chunk-6JPDCEDB.js} +3 -3
  59. package/chunks/{chunk-3UP777ZS.js → chunk-6RLROE6G.js} +1 -1
  60. package/chunks/{chunk-GN3F6PIU.js → chunk-6WPJRYLZ.js} +5 -5
  61. package/chunks/{chunk-ZERZSAZL.js → chunk-75DOP5OR.js} +2 -2
  62. package/chunks/chunk-7DKX4A5Z.js +91 -0
  63. package/chunks/{chunk-M7S4GK5Z.js → chunk-7IDCQ35Q.js} +147 -30
  64. package/chunks/{chunk-22MNNNXE.js → chunk-7NFB7LBQ.js} +11 -3
  65. package/chunks/{chunk-ZL5HN75Q.js → chunk-7R4DPSRA.js} +37 -3
  66. package/chunks/{chunk-VZ7HY3YU.js → chunk-7STBROEV.js} +3 -3
  67. package/chunks/{chunk-SAIILPQ3.js → chunk-7X7TEQNX.js} +5 -3
  68. package/chunks/{chunk-RMLZAUWH.js → chunk-A3U2TQUL.js} +10 -12
  69. package/chunks/{chunk-IRJWHZWU.js → chunk-A4UCTEB5.js} +2 -2
  70. package/chunks/{chunk-BOBRZZKD.js → chunk-A7W4GQRW.js} +5 -5
  71. package/chunks/{chunk-O33TBKDC.js → chunk-AAUZBE5Y.js} +155 -19
  72. package/chunks/{chunk-SQ2UATK7.js → chunk-ADLYZJYZ.js} +11 -11
  73. package/chunks/{chunk-QYUE6W3T.js → chunk-ALGGS7UH.js} +2 -39
  74. package/chunks/{chunk-WMPVYQ4P.js → chunk-ARKANCNX.js} +3 -2
  75. package/chunks/{chunk-IBY3Q3HG.js → chunk-AU4R7ACM.js} +967 -181
  76. package/chunks/{channel-worker-supervisor-NZQUOEFJ.js → chunk-B7MFJBKE.js} +190 -34
  77. package/chunks/{chunk-HW4N45EE.js → chunk-B7NUUEXC.js} +38 -11
  78. package/chunks/{chunk-3B26UVCX.js → chunk-BLPMRN4B.js} +39 -10
  79. package/chunks/{chunk-ZN5T4BHI.js → chunk-BPZALHVR.js} +2 -2
  80. package/chunks/{chunk-BVYU3ZTI.js → chunk-BXT6PQ73.js} +1020 -942
  81. package/chunks/{chunk-OFEVLU4C.js → chunk-CARU2RR2.js} +1 -1
  82. package/chunks/{chunk-HDOH3QYE.js → chunk-CEGKYZDB.js} +2 -2
  83. package/chunks/{chunk-GLE2YUPU.js → chunk-COH43MRJ.js} +1 -1
  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-IWKSG2AR.js → chunk-CXAOG665.js} +1 -1
  87. package/chunks/{chunk-64WXLC72.js → chunk-DJ2GSRLV.js} +1 -1
  88. package/chunks/{chunk-QN5NZ3UQ.js → chunk-DMTGGOSA.js} +2 -2
  89. package/chunks/{chunk-27BHARDE.js → chunk-DMVA55W5.js} +2124 -30
  90. package/chunks/{chunk-JPALE3PA.js → chunk-DQCCLVQK.js} +6 -6
  91. package/chunks/{chunk-X2XNQQJI.js → chunk-E2UVIFI2.js} +186 -399
  92. package/chunks/{chunk-KHDZHZMH.js → chunk-E5Z2AVNV.js} +1 -1
  93. package/chunks/{chunk-E7EMCSUG.js → chunk-EAHMOXLL.js} +64 -42
  94. package/chunks/{chunk-VGGOPZUL.js → chunk-EJ3KGYWL.js} +36 -8
  95. package/chunks/{chunk-DIWVZ3VM.js → chunk-ERTHKDKN.js} +5 -5
  96. package/chunks/{chunk-UX6OTBVD.js → chunk-EX5OULP3.js} +2 -2
  97. package/chunks/{chunk-5MBO76SL.js → chunk-F333XEAU.js} +3 -3
  98. package/chunks/{chunk-OACJLMLD.js → chunk-FBU7WRZI.js} +18 -2
  99. package/chunks/{chunk-5IFG2VC4.js → chunk-FCMNKVXT.js} +1 -1
  100. package/chunks/chunk-FEOBU3FA.js +253 -0
  101. package/chunks/{chunk-LAXNEOBG.js → chunk-FI2WSOWX.js} +19 -3
  102. package/chunks/{chunk-E7KNELIZ.js → chunk-FSA7ERJ2.js} +2 -2
  103. package/chunks/{chunk-44NROQYV.js → chunk-GDQQRV43.js} +4 -4
  104. package/chunks/{chunk-ZE6E424U.js → chunk-GN5HJJBO.js} +2 -2
  105. package/chunks/{chunk-O2YT7VB4.js → chunk-GOXKNSDZ.js} +2 -65
  106. package/chunks/{chunk-V35MD7KN.js → chunk-GRC5HGPI.js} +1 -1
  107. package/chunks/{chunk-ON3JA3RU.js → chunk-GTENQOEJ.js} +7 -9
  108. package/chunks/{chunk-S6RLAIUR.js → chunk-GYTKQYDB.js} +1 -1
  109. package/chunks/{chunk-A2X3KLC3.js → chunk-GZXCZHCT.js} +3 -3
  110. package/chunks/{chunk-K5PGHDBN.js → chunk-H6XPXXMH.js} +1 -1
  111. package/chunks/{chunk-PMFULMLX.js → chunk-HCJTURZD.js} +2262 -384
  112. package/chunks/chunk-HGG2RRXD.js +445 -0
  113. package/chunks/{chunk-II73RK2S.js → chunk-HGT6JR3U.js} +20 -1
  114. package/chunks/{chunk-DICGXFAI.js → chunk-HJCVNZLQ.js} +11 -9
  115. package/chunks/{chunk-3GNOQZDC.js → chunk-HJUDVNCO.js} +17663 -14877
  116. package/chunks/{chunk-AYNCLGTW.js → chunk-HRUGYOJN.js} +8 -51
  117. package/chunks/{chunk-KYMBIKIW.js → chunk-HTHUX2T5.js} +1 -1
  118. package/chunks/{chunk-LQ7TMOCE.js → chunk-HTO4JFDZ.js} +1 -1
  119. package/chunks/{chunk-BUZ6HGL4.js → chunk-HWTL6MPR.js} +357 -59
  120. package/chunks/chunk-IDS7MSUP.js +74 -0
  121. package/chunks/{chunk-4CGOWHKM.js → chunk-J4MOFEOK.js} +2 -2
  122. package/chunks/chunk-JCD4FM7K.js +296 -0
  123. package/chunks/{chunk-22IFUCVR.js → chunk-JESCGQM3.js} +1 -1
  124. package/chunks/{chunk-JZHIQJOE.js → chunk-JGO6RFI2.js} +6 -6
  125. package/chunks/{chunk-X3YGAX7V.js → chunk-JGUT3LWZ.js} +9 -2
  126. package/chunks/{chunk-JRQ7EVGE.js → chunk-JW7OOJC6.js} +2 -2
  127. package/chunks/{chunk-OQXDAMKY.js → chunk-KF5MMGG4.js} +8 -8
  128. package/chunks/{chunk-42XGFRJS.js → chunk-KKRTYONM.js} +8 -6
  129. package/chunks/{chunk-GGQQA4JW.js → chunk-KSO42X3Z.js} +15 -2
  130. package/chunks/{chunk-MRO43B25.js → chunk-KW7NOTN6.js} +1 -1
  131. package/chunks/{chunk-54YZOP7P.js → chunk-L573Z2QZ.js} +11894 -5190
  132. package/chunks/{chunk-TLWA7TPR.js → chunk-L5U3ELZX.js} +2 -2
  133. package/chunks/{chunk-YHKAK72D.js → chunk-LHEOLOXU.js} +251 -63
  134. package/chunks/{chunk-H6EMK6QK.js → chunk-LQIDP6K5.js} +11913 -5207
  135. package/chunks/{chunk-I6WGFJJ3.js → chunk-LSEJG6AM.js} +73 -19
  136. package/chunks/{chunk-MZ7BABX3.js → chunk-LXLTBIDP.js} +44 -7
  137. package/chunks/{chunk-HLKG6CZN.js → chunk-M5GB774H.js} +1 -1
  138. package/chunks/{chunk-JCH35JB3.js → chunk-MKK4XGLF.js} +2 -2
  139. package/chunks/{chunk-YKZIAK7C.js → chunk-MO7O5722.js} +424 -40
  140. package/chunks/chunk-MR3PXB6E.js +48 -0
  141. package/chunks/{chunk-A5JOJ77H.js → chunk-MRYWYBQ4.js} +38 -15
  142. package/chunks/{chunk-332PWN27.js → chunk-NHDKSOEY.js} +1 -1
  143. package/chunks/{chunk-TSPB77TG.js → chunk-NRAFASYX.js} +1016 -2967
  144. package/chunks/{chunk-BMFMJINR.js → chunk-OA4JVLSA.js} +28 -2
  145. package/chunks/{chunk-P7M4GA57.js → chunk-OCPBI7J5.js} +1 -1
  146. package/chunks/chunk-OJAMDVF5.js +66 -0
  147. package/chunks/{chunk-IJRL2S3D.js → chunk-OKAIGAYW.js} +6 -6
  148. package/chunks/{chunk-FBET5XZ2.js → chunk-PEJWA3QQ.js} +29 -10
  149. package/chunks/{chunk-L4AMBVQG.js → chunk-PMKW35AT.js} +54 -22
  150. package/chunks/{chunk-AGHU5VRK.js → chunk-PZL23GTM.js} +1 -1
  151. package/chunks/{chunk-PC4ZXHU2.js → chunk-Q6TUALBE.js} +3 -3
  152. package/chunks/{chunk-FXGLL2HL.js → chunk-Q7YDKOGY.js} +1 -1
  153. package/chunks/{chunk-XOHNA2S6.js → chunk-QAW7PIHT.js} +3 -3
  154. package/chunks/{chunk-XYR5RUA5.js → chunk-QE2WJ7FS.js} +10 -3
  155. package/chunks/{chunk-LGFAYIKX.js → chunk-QHTIBUWB.js} +1 -1
  156. package/chunks/{chunk-P3MYAZBY.js → chunk-QMGX2KO2.js} +1 -1
  157. package/chunks/{chunk-Z3I3QJK3.js → chunk-QRUIS3DN.js} +1 -1
  158. package/chunks/{chunk-ITOGNELQ.js → chunk-QSWDGAIC.js} +2 -2
  159. package/chunks/{chunk-PUVCVELY.js → chunk-QUJOI7SR.js} +70 -8
  160. package/chunks/{chunk-GHOTR7HL.js → chunk-QUPXZXLV.js} +1 -1
  161. package/chunks/{chunk-6VK6FIMQ.js → chunk-R5D5JOAM.js} +415 -379
  162. package/chunks/{chunk-CD6USWHZ.js → chunk-R5XLNDE2.js} +2 -2
  163. package/chunks/{chunk-W7EEOR7D.js → chunk-RCEEXIOO.js} +8 -6
  164. package/chunks/{chunk-TLRYABYP.js → chunk-RKUWKYED.js} +1 -1
  165. package/chunks/{chunk-RNBYOUGV.js → chunk-RXFQM6FQ.js} +1 -1
  166. package/chunks/{chunk-QXPI7FEC.js → chunk-S3TWXGKA.js} +4 -4
  167. package/chunks/{chunk-2EM7ECZD.js → chunk-SMSFWUFY.js} +309 -80
  168. package/chunks/{chunk-FV7425LN.js → chunk-SPJQO2CE.js} +18 -5
  169. package/chunks/{chunk-MLZQVCF3.js → chunk-SZRN75WQ.js} +1 -1
  170. package/chunks/{chunk-7RYW5LQV.js → chunk-T2NCM2ET.js} +2 -2
  171. package/chunks/{chunk-Z2Z3GUXZ.js → chunk-TB6UDU4T.js} +1 -1
  172. package/chunks/{chunk-EXPMGZZV.js → chunk-TEGEBB2I.js} +1 -1
  173. package/chunks/{chunk-MX2YXRER.js → chunk-TJTKSVIV.js} +1 -1
  174. package/chunks/{chunk-CCGOFQV3.js → chunk-TQBODCFD.js} +8 -7
  175. package/chunks/chunk-TV6K2FB4.js +224 -0
  176. package/chunks/{chunk-H6BD2ELD.js → chunk-TYAMGABM.js} +2 -2
  177. package/chunks/{chunk-QYNNN7BK.js → chunk-TYLOFD2U.js} +2 -2
  178. package/chunks/{chunk-VRDMOSQS.js → chunk-UDXSXLER.js} +2 -2
  179. package/chunks/{chunk-DHOLNQLC.js → chunk-UFDX27PL.js} +60 -40
  180. package/chunks/{chunk-WHJQ3JUS.js → chunk-UGN6CTNZ.js} +10 -10
  181. package/chunks/{chunk-CHB5SLZZ.js → chunk-UNLRKDMW.js} +4 -4
  182. package/chunks/{chunk-CJCKDMWO.js → chunk-URK542T4.js} +1 -1
  183. package/chunks/{chunk-AHNXYU4O.js → chunk-V6WHFGST.js} +1 -1
  184. package/chunks/{chunk-ZTQ26VBE.js → chunk-VDDGDZMA.js} +1 -1
  185. package/chunks/{chunk-BOBOCR5H.js → chunk-VEETSXYX.js} +4 -4
  186. package/chunks/{chunk-OMX7CUOE.js → chunk-VGC4I5JJ.js} +1 -1
  187. package/chunks/{chunk-43W4YSO6.js → chunk-VJNBRRZG.js} +2 -2
  188. package/chunks/{chunk-WQTHLB5T.js → chunk-VKS7EIOA.js} +7 -7
  189. package/chunks/{chunk-J7RCB6N5.js → chunk-VVDNGM6X.js} +2 -2
  190. package/chunks/{chunk-ER3BKOLB.js → chunk-W7FJ3N32.js} +1 -1
  191. package/chunks/{chunk-3HX5LZ6R.js → chunk-WBL3FJEU.js} +2 -2
  192. package/chunks/{chunk-7LTB54MK.js → chunk-WIEO4CWB.js} +2 -2
  193. package/chunks/chunk-WMC6HH7Y.js +493 -0
  194. package/chunks/{chunk-FEJ2FZ3U.js → chunk-WTNZ6DXB.js} +2 -2
  195. package/chunks/{chunk-L46XKEGM.js → chunk-X6ODDESK.js} +5 -8
  196. package/chunks/chunk-XDPYM5DE.js +71 -0
  197. package/chunks/{chunk-3RW4AZJV.js → chunk-XFSFZCM5.js} +1 -1
  198. package/chunks/{chunk-2MPVVENX.js → chunk-XU457J4V.js} +2 -2
  199. package/chunks/{chunk-SIUQ3YYX.js → chunk-XVNQMZ2I.js} +1 -1
  200. package/chunks/{chunk-SYCJMSIJ.js → chunk-XWRJCPHC.js} +1 -1
  201. package/chunks/{chunk-SUAKHHK7.js → chunk-Y66VOBRP.js} +3 -3
  202. package/chunks/chunk-YAF2MQZ6.js +19 -0
  203. package/chunks/chunk-YHN5SUIJ.js +219 -0
  204. package/chunks/{chunk-BR4QREVK.js → chunk-YQ3U5MUC.js} +1 -1
  205. package/chunks/{chunk-Y6Z2O3WR.js → chunk-YUZI3WAC.js} +1 -1
  206. package/chunks/{chunk-YDOXPLYL.js → chunk-ZA74ZTQU.js} +4564 -1326
  207. package/chunks/{chunk-DCZWC4PF.js → chunk-ZGE3222J.js} +5 -5
  208. package/chunks/chunk-ZP4ZZJJG.js +448 -0
  209. package/chunks/{chunk-AHNJGLFV.js → chunk-ZPAHLFZU.js} +3 -3
  210. package/chunks/cli-entry-path-4VJ3Y6T2.js +10 -0
  211. package/chunks/{computer-use-WMY3UOBX.js → computer-use-SHA6C3ES.js} +50 -50
  212. package/chunks/config-utils-XSHOMMK4.js +24 -0
  213. package/chunks/contextCommand-HOAF5LUC.js +68 -0
  214. package/chunks/create-sub-session-EAB2U5XW.js +207 -0
  215. package/chunks/create-sub-session-WJOWBFEP.js +375 -0
  216. package/chunks/{cron-create-JSXEIPVS.js → cron-create-GMVKSXZT.js} +9 -9
  217. package/chunks/{cron-delete-OIFVEPGU.js → cron-delete-VDZKUAVK.js} +7 -7
  218. package/chunks/{cron-list-D4ZX4IOE.js → cron-list-UG7C7RAR.js} +14 -10
  219. package/chunks/{daemon-WPAENEBW.js → daemon-MI5HF26N.js} +1074 -61
  220. package/chunks/daemon-status-provider-KFL3LRTP.js +76 -0
  221. package/chunks/{de-ZFPPQVSF.js → de-2VCDRDGU.js} +68 -6
  222. package/chunks/{devtools-FM6GJPYG.js → devtools-4QFYJT6U.js} +3 -3
  223. package/chunks/{dist-O2IRTRPP.js → dist-IEXZC5ZR.js} +10 -10
  224. package/chunks/{dist-SCFLLYMK.js → dist-PQK4GCKA.js} +12 -11
  225. package/chunks/{dist-63IS3ZMI.js → dist-PZV5RKM6.js} +4 -4
  226. package/chunks/{dist-E6UANPIM.js → dist-U75JK3PF.js} +1011 -197
  227. package/chunks/{dist-H2AEJCZ5.js → dist-VXO7QBON.js} +5 -5
  228. package/chunks/{dist-Z34QPAQW.js → dist-WH4TZSH3.js} +529 -79
  229. package/chunks/{dist-BEXOZXLQ.js → dist-X2ABIW5R.js} +36 -15
  230. package/chunks/earlyInputCapture-PKAQJMIP.js +69 -0
  231. package/chunks/{edit-OTYWAXGP.js → edit-6TXLYHJ2.js} +51 -51
  232. package/chunks/{en-N4EPZAQI.js → en-NJCA3TAA.js} +78 -6
  233. package/chunks/{enter-worktree-HNYBDVCX.js → enter-worktree-ZTILGPJX.js} +50 -50
  234. package/chunks/{enterPlanMode-CJCNGT63.js → enterPlanMode-62HRAMCH.js} +66 -51
  235. package/chunks/environment-OYA3ZVEL.js +89 -0
  236. package/chunks/errors-BFXOUUUR.js +75 -0
  237. package/chunks/{exit-worktree-DUUKOE3X.js → exit-worktree-HHJ5M6MV.js} +50 -50
  238. package/chunks/{exitPlanMode-AMMSXOAJ.js → exitPlanMode-M3SWHCL7.js} +51 -51
  239. package/chunks/{fast-path-OV6NIP3K.js → fast-path-3VMPLM74.js} +8 -8
  240. package/chunks/{fast-path-settings-7RIFI3PK.js → fast-path-settings-DAOVFADC.js} +8 -6
  241. package/chunks/{fileFromPath-IBEHA3CO.js → fileFromPath-UDALK7FM.js} +3 -3
  242. package/chunks/{fr-5WWMY53B.js → fr-5F3E7WKD.js} +68 -6
  243. package/chunks/{gemini-NQ3WWBKB.js → gemini-ZCGVYOJL.js} +181 -110
  244. package/chunks/{geminiContentGenerator-CDUNEJQE.js → geminiContentGenerator-XBYBAIDQ.js} +9 -9
  245. package/chunks/{getMachineId-bsd-4CASPIU4.js → getMachineId-bsd-EXV7SWPA.js} +3 -3
  246. package/chunks/{getMachineId-darwin-HPQPEMZR.js → getMachineId-darwin-IUOMFXU3.js} +3 -3
  247. package/chunks/{getMachineId-linux-AUARKYHL.js → getMachineId-linux-K7XJYFHL.js} +2 -2
  248. package/chunks/{getMachineId-unsupported-S32ZDA2T.js → getMachineId-unsupported-EA5FDRJ6.js} +2 -2
  249. package/chunks/{getMachineId-win-4EFLHYIJ.js → getMachineId-win-KBA6RAI5.js} +3 -3
  250. package/chunks/{glob-ROV3YS4R.js → glob-UOEYQNHN.js} +97 -75
  251. package/chunks/{grep-NRITKDCD.js → grep-OQM3CH7W.js} +50 -50
  252. package/chunks/handleAutoUpdate-ORBYVJHZ.js +69 -0
  253. package/chunks/i18n-NBP574CO.js +84 -0
  254. package/chunks/initializer-CWD7TCCD.js +73 -0
  255. package/chunks/installationInfo-CHPDUPWC.js +65 -0
  256. package/chunks/{ja-CUHZOLEJ.js → ja-66J6B53L.js} +69 -7
  257. package/chunks/{keychain-token-storage-UJV5XP4Z.js → keychain-token-storage-AU22CQI6.js} +4 -4
  258. package/chunks/{kittyProtocolDetector-OJRCJLIU.js → kittyProtocolDetector-HCNNKJTI.js} +2 -2
  259. package/chunks/list-ZTTO362W.js +76 -0
  260. package/chunks/loadedSettingsAdapter-V4ZTRKUO.js +70 -0
  261. package/chunks/{loop-wakeup-OHWEMFP5.js → loop-wakeup-C4EXLYVA.js} +10 -10
  262. package/chunks/{lowlight-FYAAUU5J.js → lowlight-J2OZNPCA.js} +1 -1
  263. package/chunks/{ls-7MFU2QYW.js → ls-2OUTG3IZ.js} +6 -6
  264. package/chunks/{lsp-XHDTPTGV.js → lsp-4VMNXZW6.js} +4 -4
  265. package/chunks/mcp-UH5PSGIK.js +70 -0
  266. package/chunks/{monitor-FL2ZO33W.js → monitor-F4NYEU5J.js} +50 -50
  267. package/chunks/{multipart-parser-AJ4WASWR.js → multipart-parser-AWZKXSQN.js} +3 -3
  268. package/chunks/nonInteractiveCli-7IHPXVNH.js +129 -0
  269. package/chunks/{notebook-edit-6PULTHL5.js → notebook-edit-HPDXNGQH.js} +51 -51
  270. package/chunks/openaiContentGenerator-OBDNNOE2.js +56 -0
  271. package/chunks/pidfile-AUMGYIOK.js +73 -0
  272. package/chunks/{pt-OLYN42DS.js → pt-TFZO5Y6T.js} +68 -6
  273. package/chunks/{qwenContentGenerator-NX2E7PB7.js → qwenContentGenerator-LH2U2YRG.js} +52 -52
  274. package/chunks/{qwenOAuth2-ZV7YLMND.js → qwenOAuth2-LEYOU7RU.js} +9 -9
  275. package/chunks/read-file-HUUFBLEO.js +30 -0
  276. package/chunks/{read-mcp-resource-CNQHBSJM.js → read-mcp-resource-JUFHCKSC.js} +5 -5
  277. package/chunks/{read-package-up-ER5OJUGP.js → read-package-up-TCM6I7S2.js} +2 -2
  278. package/chunks/{record-artifact-SQ2OKRJW.js → record-artifact-DWSMBXYY.js} +4 -4
  279. package/chunks/ripGrep-C7X33LU6.js +60 -0
  280. package/chunks/{ru-LDM3GWVQ.js → ru-4L4LFHIT.js} +68 -6
  281. package/chunks/{run-qwen-serve-JK2DL7PI.js → run-qwen-serve-DGW5AFDJ.js} +1465 -283
  282. package/chunks/runtime-NYUSLBEZ.js +99 -0
  283. package/chunks/{scheduler-O4IGVZKK.js → scheduler-5VKDXULT.js} +51 -51
  284. package/chunks/{send-message-76GT3JMC.js → send-message-JZ752NWD.js} +7 -7
  285. package/chunks/serve-UTAHSFXH.js +76 -0
  286. package/chunks/{server-SGNPKX2O.js → server-VUHSYSUV.js} +9088 -1817
  287. package/chunks/{session-5BNM25EZ.js → session-QSGSSNFB.js} +340 -135
  288. package/chunks/settings-X24RYEED.js +120 -0
  289. package/chunks/shell-4MSI2R4O.js +70 -0
  290. package/chunks/{skill-I22QK5XS.js → skill-JR3GTNVZ.js} +24 -24
  291. package/chunks/spawnChannel-RFAAO44J.js +70 -0
  292. package/chunks/{src-7XL4G4DC.js → src-VLI3TKEY.js} +4 -4
  293. package/chunks/{src-BBQSM46M.js → src-YDBNMIIM.js} +183 -53
  294. package/chunks/standalone-update-4CY4HKGC.js +79 -0
  295. package/chunks/{startInteractiveUI-JII36UGN.js → startInteractiveUI-FOD7MMVB.js} +2368 -1923
  296. package/chunks/stdioHelpers-UMY72QRP.js +14 -0
  297. package/chunks/{syntheticOutput-F7LSDCAR.js → syntheticOutput-LELY6HAI.js} +5 -5
  298. package/chunks/task-create-QY3BIMNM.js +23 -0
  299. package/chunks/{task-list-TGGJX7EA.js → task-list-D2U47WBJ.js} +11 -10
  300. package/chunks/{task-stop-W7NGTMYQ.js → task-stop-N6E5IYLH.js} +4 -4
  301. package/chunks/{task-update-XYWMHJGJ.js → task-update-HJCQILLB.js} +13 -12
  302. package/chunks/{team-create-A7NUU5AQ.js → team-create-ZLQSU2E3.js} +50 -50
  303. package/chunks/{team-delete-UHQQ2QQX.js → team-delete-RCWYDRF4.js} +11 -10
  304. package/chunks/{team-plan-approval-TOQRJ2KI.js → team-plan-approval-YUAYBYLS.js} +50 -50
  305. package/chunks/theme-manager-SKNEBMOG.js +64 -0
  306. package/chunks/{todoWrite-C4ZAMSR3.js → todoWrite-FKCGATPJ.js} +6 -6
  307. package/chunks/{tool-search-SZ4EFS2T.js → tool-search-V5J3TGWY.js} +24 -24
  308. package/chunks/total-session-admission-2WIH72I3.js +72 -0
  309. package/chunks/tree-sitter-YJVE2ZUK.js +2980 -0
  310. package/chunks/trustedFolders-JF265CRI.js +80 -0
  311. package/chunks/types-ML3TRJQ5.js +16 -0
  312. package/chunks/updateCheck-AMXNPBP6.js +69 -0
  313. package/chunks/updateEventEmitter-5MKC7BLQ.js +10 -0
  314. package/chunks/validateNonInterActiveAuth-6YHQO7PD.js +194 -0
  315. package/chunks/{version-NO2XSNNP.js → version-UEJJK7PE.js} +3 -3
  316. package/chunks/{web-fetch-UYGMOHW4.js → web-fetch-QGODBB6S.js} +8 -8
  317. package/chunks/{workflow-WO2H6NRI.js → workflow-5YFA5V4M.js} +51 -51
  318. package/chunks/workspace-providers-status-LMBLBNR7.js +73 -0
  319. package/chunks/workspace-registration-store-VV2S4MSV.js +27 -0
  320. package/chunks/workspace-registry-BVMPYRLN.js +76 -0
  321. package/chunks/workspace-service-PUYIZ3J4.js +86 -0
  322. package/chunks/workspace-skills-status-CJ7J2KPP.js +72 -0
  323. package/chunks/{write-file-PX2Z7IBE.js → write-file-OV77M6X7.js} +51 -51
  324. package/chunks/{yargs-B64EYTCF.js → yargs-6H2AUULL.js} +2 -2
  325. package/chunks/{zh-J4F6QWQV.js → zh-FSAH32JB.js} +79 -7
  326. package/chunks/{zh-TW-XVDWOLSW.js → zh-TW-D2YIE2LO.js} +79 -7
  327. package/cli.js +18 -17
  328. package/locales/ca.js +91 -7
  329. package/locales/de.js +90 -7
  330. package/locales/en.js +109 -7
  331. package/locales/fr.js +91 -7
  332. package/locales/ja.js +93 -7
  333. package/locales/pt.js +90 -7
  334. package/locales/ru.js +90 -7
  335. package/locales/zh-TW.js +106 -7
  336. package/locales/zh.js +106 -7
  337. package/package.json +3 -6
  338. package/web-shell/assets/{arc-BWyoJpY2.js → arc-CObt_TK9.js} +1 -1
  339. package/web-shell/assets/{architectureDiagram-3BPJPVTR-BT0mGrz2.js → architectureDiagram-3BPJPVTR-B7aiJ6CK.js} +1 -1
  340. package/web-shell/assets/{blockDiagram-GPEHLZMM-BLgUWvyf.js → blockDiagram-GPEHLZMM-BSK2CrID.js} +1 -1
  341. package/web-shell/assets/{c4Diagram-AAUBKEIU-DYx9M7oU.js → c4Diagram-AAUBKEIU-Bhx2p7T_.js} +1 -1
  342. package/web-shell/assets/channel-BBaLq8MV.js +1 -0
  343. package/web-shell/assets/{chunk-2J33WTMH-CfMHWbuZ.js → chunk-2J33WTMH-c3Hzv0Ni.js} +1 -1
  344. package/web-shell/assets/{chunk-4BX2VUAB-B1URoqEV.js → chunk-4BX2VUAB-DNXaK7ZF.js} +1 -1
  345. package/web-shell/assets/{chunk-55IACEB6-DAIaM4QF.js → chunk-55IACEB6-BXjvDj_i.js} +1 -1
  346. package/web-shell/assets/{chunk-727SXJPM-B2X34knw.js → chunk-727SXJPM-B6CaKFp-.js} +1 -1
  347. package/web-shell/assets/{chunk-AQP2D5EJ-Cif-zLTQ.js → chunk-AQP2D5EJ-tij6Mz9B.js} +1 -1
  348. package/web-shell/assets/{chunk-FMBD7UC4-H18WCXdY.js → chunk-FMBD7UC4-DdlsGk2h.js} +1 -1
  349. package/web-shell/assets/{chunk-ND2GUHAM-YFtetHi0.js → chunk-ND2GUHAM-CdgGZSHE.js} +1 -1
  350. package/web-shell/assets/{chunk-QZHKN3VN-By2hiH3r.js → chunk-QZHKN3VN-D8oJn1C0.js} +1 -1
  351. package/web-shell/assets/classDiagram-4FO5ZUOK-B2ZK6sWE.js +1 -0
  352. package/web-shell/assets/classDiagram-v2-Q7XG4LA2-B2ZK6sWE.js +1 -0
  353. package/web-shell/assets/{cose-bilkent-S5V4N54A-VrcnnLZu.js → cose-bilkent-S5V4N54A-BUVmNp1Y.js} +1 -1
  354. package/web-shell/assets/{dagre-BM42HDAG-CGo-IaVV.js → dagre-BM42HDAG-CO4q310O.js} +1 -1
  355. package/web-shell/assets/{diagram-2AECGRRQ-Dl4QjzIB.js → diagram-2AECGRRQ-C6gFvWkg.js} +1 -1
  356. package/web-shell/assets/{diagram-5GNKFQAL-qMLmsO0u.js → diagram-5GNKFQAL-NG2I_c0h.js} +1 -1
  357. package/web-shell/assets/{diagram-KO2AKTUF-CHlmuxPI.js → diagram-KO2AKTUF-DFKMS6I9.js} +1 -1
  358. package/web-shell/assets/{diagram-LMA3HP47-BUwU3GwT.js → diagram-LMA3HP47-BiElfsfP.js} +1 -1
  359. package/web-shell/assets/{diagram-OG6HWLK6-HEhwPDUM.js → diagram-OG6HWLK6-zLWDYUqu.js} +1 -1
  360. package/web-shell/assets/{erDiagram-TEJ5UH35-1n0llBmM.js → erDiagram-TEJ5UH35-DoVaazhK.js} +1 -1
  361. package/web-shell/assets/{flowDiagram-I6XJVG4X-BN74uMnt.js → flowDiagram-I6XJVG4X-0RLz-mXg.js} +1 -1
  362. package/web-shell/assets/{ganttDiagram-6RSMTGT7-BoOq78i3.js → ganttDiagram-6RSMTGT7-C-eX1A39.js} +3 -3
  363. package/web-shell/assets/{gitGraphDiagram-PVQCEYII-CN8b00c8.js → gitGraphDiagram-PVQCEYII-BauQu1Bu.js} +1 -1
  364. package/web-shell/assets/index-3uAT3ehO.css +5 -0
  365. package/web-shell/assets/index-CVHa2QH7.js +3 -0
  366. package/web-shell/assets/index-D1KigWat.js +1128 -0
  367. package/web-shell/assets/{infoDiagram-5YYISTIA-CCurnIna.js → infoDiagram-5YYISTIA-C800cFvZ.js} +1 -1
  368. package/web-shell/assets/{ishikawaDiagram-YF4QCWOH-AwuRqdUP.js → ishikawaDiagram-YF4QCWOH-CFK1Jk6e.js} +1 -1
  369. package/web-shell/assets/{journeyDiagram-JHISSGLW-B7IICk-E.js → journeyDiagram-JHISSGLW-Cjx0WAC4.js} +1 -1
  370. package/web-shell/assets/{kanban-definition-UN3LZRKU-BYF0OKhx.js → kanban-definition-UN3LZRKU-DWMDHbiv.js} +1 -1
  371. package/web-shell/assets/{linear-GWWguGfD.js → linear-vpW4FrZs.js} +1 -1
  372. package/web-shell/assets/{mermaid.core-JqtkxvCl.js → mermaid.core-DsHRUnDd.js} +5 -5
  373. package/web-shell/assets/{mindmap-definition-RKZ34NQL-B0MmHsZ6.js → mindmap-definition-RKZ34NQL-D3Eb1cAK.js} +1 -1
  374. package/web-shell/assets/{pieDiagram-4H26LBE5-DhImUZLQ.js → pieDiagram-4H26LBE5-Cr2-6sWt.js} +1 -1
  375. package/web-shell/assets/{quadrantDiagram-W4KKPZXB-DGeSC3DT.js → quadrantDiagram-W4KKPZXB-Yd7yUgVp.js} +1 -1
  376. package/web-shell/assets/{requirementDiagram-4Y6WPE33-DkspY6Re.js → requirementDiagram-4Y6WPE33-BE6SprL8.js} +1 -1
  377. package/web-shell/assets/{sankeyDiagram-5OEKKPKP-CaOofS2x.js → sankeyDiagram-5OEKKPKP-DzkuMK8d.js} +1 -1
  378. package/web-shell/assets/{sequenceDiagram-3UESZ5HK-DFQ_kFnN.js → sequenceDiagram-3UESZ5HK-wD9A3Dhi.js} +1 -1
  379. package/web-shell/assets/{stateDiagram-AJRCARHV-D3snw0Tz.js → stateDiagram-AJRCARHV-BOp5q1Nm.js} +1 -1
  380. package/web-shell/assets/stateDiagram-v2-BHNVJYJU-BDsWUmPG.js +1 -0
  381. package/web-shell/assets/{timeline-definition-PNZ67QCA-l4zH8nLM.js → timeline-definition-PNZ67QCA-Btc08sUA.js} +1 -1
  382. package/web-shell/assets/{vennDiagram-CIIHVFJN-BnRlA98M.js → vennDiagram-CIIHVFJN-Bv6upsOA.js} +1 -1
  383. package/web-shell/assets/{wardley-L42UT6IY-BS0xUdmd.js → wardley-L42UT6IY-D-XamnCK.js} +1 -1
  384. package/web-shell/assets/{wardleyDiagram-YWT4CUSO-DKGBUWyQ.js → wardleyDiagram-YWT4CUSO-BbP_5Wfp.js} +1 -1
  385. package/web-shell/assets/{xychartDiagram-2RQKCTM6-DVb2HuOB.js → xychartDiagram-2RQKCTM6-CO5Hh28b.js} +1 -1
  386. package/web-shell/index.html +16 -4
  387. package/chunks/MaxSizedBox-5DT2SD7B.js +0 -71
  388. package/chunks/agent-H2DGKS77.js +0 -68
  389. package/chunks/agent-headless-KFMFIT6J.js +0 -62
  390. package/chunks/bridge-NA3ZQQKJ.js +0 -78
  391. package/chunks/chunk-5P5XGNYH.js +0 -93
  392. package/chunks/chunk-6SHO7WFF.js +0 -79
  393. package/chunks/chunk-IFEWJXFS.js +0 -37
  394. package/chunks/chunk-XNXVCNAT.js +0 -88
  395. package/chunks/contextCommand-LXFZRP4L.js +0 -68
  396. package/chunks/daemon-status-provider-GJRXY5EN.js +0 -76
  397. package/chunks/earlyInputCapture-KNOYZ4MJ.js +0 -69
  398. package/chunks/environment-ATFTYMLZ.js +0 -88
  399. package/chunks/errors-A54HAADA.js +0 -75
  400. package/chunks/handleAutoUpdate-CEZJAARW.js +0 -65
  401. package/chunks/initializer-BRFJKRRX.js +0 -71
  402. package/chunks/list-KVHF7O4X.js +0 -73
  403. package/chunks/loadedSettingsAdapter-LL5PSFKX.js +0 -68
  404. package/chunks/mcp-3GCXRTOQ.js +0 -68
  405. package/chunks/nonInteractiveCli-PTQI3DV6.js +0 -119
  406. package/chunks/openaiContentGenerator-YE42PKCY.js +0 -56
  407. package/chunks/pidfile-NZYSCFRK.js +0 -73
  408. package/chunks/read-file-33XGP5HF.js +0 -30
  409. package/chunks/ripGrep-QWZLGTAN.js +0 -60
  410. package/chunks/serve-JTMIGANH.js +0 -74
  411. package/chunks/settings-3MI4XXP6.js +0 -118
  412. package/chunks/shell-YJKBE67T.js +0 -68
  413. package/chunks/spawnChannel-UNV6W4DU.js +0 -70
  414. package/chunks/task-create-WCHTB435.js +0 -22
  415. package/chunks/theme-manager-WZ4RRMMB.js +0 -64
  416. package/chunks/total-session-admission-ULXJWXFV.js +0 -72
  417. package/chunks/trustedFolders-LAZZPZ3D.js +0 -79
  418. package/chunks/types-QX5C3CHJ.js +0 -12
  419. package/chunks/updateCheck-KONLM73X.js +0 -65
  420. package/chunks/validateNonInterActiveAuth-MPKSRCXD.js +0 -184
  421. package/chunks/workspace-providers-status-3W7E7DFW.js +0 -71
  422. package/chunks/workspace-registry-SXJZNN3O.js +0 -74
  423. package/chunks/workspace-service-CZRQZ4Q4.js +0 -80
  424. package/chunks/workspace-skills-status-K7WFREPD.js +0 -70
  425. package/node_modules/@qwen-code/audio-capture/dist/index.d.ts +0 -35
  426. package/node_modules/@qwen-code/audio-capture/dist/index.js +0 -48
  427. package/node_modules/@qwen-code/audio-capture/dist/index.js.map +0 -1
  428. package/node_modules/@qwen-code/audio-capture/dist/platform.d.ts +0 -7
  429. package/node_modules/@qwen-code/audio-capture/dist/platform.js +0 -18
  430. package/node_modules/@qwen-code/audio-capture/dist/platform.js.map +0 -1
  431. package/node_modules/@qwen-code/audio-capture/node_modules/node-gyp-build/LICENSE +0 -21
  432. package/node_modules/@qwen-code/audio-capture/node_modules/node-gyp-build/README.md +0 -58
  433. package/node_modules/@qwen-code/audio-capture/node_modules/node-gyp-build/SECURITY.md +0 -5
  434. package/node_modules/@qwen-code/audio-capture/node_modules/node-gyp-build/bin.js +0 -84
  435. package/node_modules/@qwen-code/audio-capture/node_modules/node-gyp-build/build-test.js +0 -19
  436. package/node_modules/@qwen-code/audio-capture/node_modules/node-gyp-build/index.js +0 -6
  437. package/node_modules/@qwen-code/audio-capture/node_modules/node-gyp-build/node-gyp-build.js +0 -207
  438. package/node_modules/@qwen-code/audio-capture/node_modules/node-gyp-build/optional.js +0 -7
  439. package/node_modules/@qwen-code/audio-capture/node_modules/node-gyp-build/package.json +0 -43
  440. package/node_modules/@qwen-code/audio-capture/package.json +0 -30
  441. package/node_modules/@qwen-code/audio-capture/prebuilds/darwin-arm64/@qwen-code+audio-capture.node +0 -0
  442. package/node_modules/@qwen-code/audio-capture/prebuilds/darwin-x64/@qwen-code+audio-capture.node +0 -0
  443. package/node_modules/@qwen-code/audio-capture/prebuilds/linux-arm64/@qwen-code+audio-capture.node +0 -0
  444. package/node_modules/@qwen-code/audio-capture/prebuilds/linux-x64/@qwen-code+audio-capture.node +0 -0
  445. package/node_modules/@qwen-code/audio-capture/prebuilds/win32-x64/@qwen-code+audio-capture.node +0 -0
  446. package/web-shell/assets/channel-wmPUGHtg.js +0 -1
  447. package/web-shell/assets/classDiagram-4FO5ZUOK-BA2ljEjW.js +0 -1
  448. package/web-shell/assets/classDiagram-v2-Q7XG4LA2-BA2ljEjW.js +0 -1
  449. package/web-shell/assets/index-CNwoO1Cn.js +0 -783
  450. package/web-shell/assets/index-CWQ0z6kZ.css +0 -5
  451. package/web-shell/assets/stateDiagram-v2-BHNVJYJU-BbSm_9d0.js +0 -1
@@ -1,136 +1,581 @@
1
1
  // Force strict mode and setup for ESM
2
2
  "use strict";
3
+ import {
4
+ formatHistoryGapNotice,
5
+ indexGapsByChild
6
+ } from "./chunk-2FMQQXMM.js";
3
7
  import {
4
8
  require_undici
5
- } from "./chunk-54YZOP7P.js";
9
+ } from "./chunk-L573Z2QZ.js";
6
10
  import {
7
11
  writeStderrLine
8
- } from "./chunk-Y6Z2O3WR.js";
12
+ } from "./chunk-YUZI3WAC.js";
9
13
  import {
10
14
  getActiveGoal
11
- } from "./chunk-3GNOQZDC.js";
15
+ } from "./chunk-HJUDVNCO.js";
16
+ import {
17
+ apiActivityTracker
18
+ } from "./chunk-HWTL6MPR.js";
12
19
  import {
13
20
  ToolNames
14
- } from "./chunk-X3YGAX7V.js";
21
+ } from "./chunk-JGUT3LWZ.js";
15
22
  import {
16
23
  createDebugLogger
17
- } from "./chunk-22MNNNXE.js";
24
+ } from "./chunk-7NFB7LBQ.js";
18
25
  import {
19
26
  init_esbuild_shims
20
- } from "./chunk-A4BMJM77.js";
27
+ } from "./chunk-5O2XNYP6.js";
21
28
  import {
22
29
  __name,
23
30
  __toESM
24
31
  } from "./chunk-J2S4EL5Y.js";
25
32
 
26
- // packages/cli/src/acp-integration/session/HistoryReplayer.ts
27
- init_esbuild_shims();
28
-
29
- // packages/cli/src/acp-integration/session/emitters/MessageEmitter.ts
33
+ // packages/cli/src/services/setup-github.ts
30
34
  init_esbuild_shims();
35
+ var import_undici2 = __toESM(require_undici(), 1);
36
+ import { promises as fsp } from "node:fs";
37
+ import * as path from "node:path";
31
38
 
32
- // packages/cli/src/acp-integration/session/emitters/BaseEmitter.ts
39
+ // packages/cli/src/utils/gitUtils.ts
33
40
  init_esbuild_shims();
34
- var BaseEmitter = class {
35
- constructor(ctx) {
36
- this.ctx = ctx;
41
+ var import_undici = __toESM(require_undici(), 1);
42
+ import * as childProcess from "node:child_process";
43
+ var debugLogger = createDebugLogger("GIT");
44
+ async function runGit(args, opts = {}) {
45
+ return await new Promise((resolve2, reject) => {
46
+ childProcess.execFile(
47
+ "git",
48
+ args,
49
+ {
50
+ encoding: "utf-8",
51
+ ...opts.cwd ? { cwd: opts.cwd } : {}
52
+ },
53
+ (err, stdout) => {
54
+ if (err) {
55
+ reject(err);
56
+ return;
57
+ }
58
+ resolve2(String(stdout ?? "").trim());
59
+ }
60
+ );
61
+ });
62
+ }
63
+ __name(runGit, "runGit");
64
+ var isGitHubRepositoryAsync = /* @__PURE__ */ __name(async (opts = {}) => {
65
+ try {
66
+ const remotes = await runGit(["remote", "-v"], opts);
67
+ return remotes.split("\n").some((line) => {
68
+ const remoteUrl = line.trim().split(/\s+/)[1];
69
+ return remoteUrl ? isGitHubRemoteUrl(remoteUrl) : false;
70
+ });
71
+ } catch (_error) {
72
+ debugLogger.debug(`Failed to get git remote:`, _error);
73
+ return false;
37
74
  }
38
- static {
39
- __name(this, "BaseEmitter");
75
+ }, "isGitHubRepositoryAsync");
76
+ function isGitHubRemoteUrl(remoteUrl) {
77
+ if (remoteUrl.startsWith("git@github.com:")) {
78
+ return true;
40
79
  }
41
- /**
42
- * Converts an ISO timestamp string or epoch ms to epoch ms number.
43
- * Returns undefined if the input is not a valid timestamp.
44
- */
45
- static toEpochMs(ts) {
46
- if (typeof ts === "number") {
47
- return Number.isFinite(ts) ? ts : void 0;
80
+ if (remoteUrl.startsWith("git@")) {
81
+ return false;
82
+ }
83
+ try {
84
+ return new URL(remoteUrl).hostname === "github.com";
85
+ } catch {
86
+ return false;
87
+ }
88
+ }
89
+ __name(isGitHubRemoteUrl, "isGitHubRemoteUrl");
90
+ var getGitRepoRootAsync = /* @__PURE__ */ __name(async (opts = {}) => {
91
+ const gitRepoRoot = await runGit(["rev-parse", "--show-toplevel"], opts);
92
+ if (!gitRepoRoot) {
93
+ throw new Error(`Git repo returned empty value`);
94
+ }
95
+ return gitRepoRoot;
96
+ }, "getGitRepoRootAsync");
97
+ var getLatestGitHubRelease = /* @__PURE__ */ __name(async (proxy) => {
98
+ try {
99
+ const controller = new AbortController();
100
+ const endpoint = `https://api.github.com/repos/QwenLM/qwen-code-action/releases/latest`;
101
+ const response = await fetch(endpoint, {
102
+ method: "GET",
103
+ headers: {
104
+ Accept: "application/vnd.github+json",
105
+ "Content-Type": "application/json",
106
+ "X-GitHub-Api-Version": "2022-11-28"
107
+ },
108
+ dispatcher: proxy ? new import_undici.ProxyAgent(proxy) : void 0,
109
+ signal: AbortSignal.any([AbortSignal.timeout(3e4), controller.signal])
110
+ });
111
+ if (!response.ok) {
112
+ throw new Error(
113
+ `Invalid response code: ${response.status} - ${response.statusText}`
114
+ );
48
115
  }
49
- if (typeof ts === "string") {
50
- const ms = new Date(ts).getTime();
51
- return Number.isFinite(ms) ? ms : void 0;
116
+ const releaseTag = (await response.json()).tag_name;
117
+ if (!releaseTag) {
118
+ throw new Error(`Response did not include tag_name field`);
52
119
  }
53
- return void 0;
120
+ return releaseTag;
121
+ } catch (_error) {
122
+ debugLogger.debug(
123
+ `Failed to determine latest qwen-code-action release:`,
124
+ _error
125
+ );
126
+ throw new Error(
127
+ `Unable to determine the latest qwen-code-action release on GitHub.`
128
+ );
54
129
  }
55
- /**
56
- * Sends a session update to the ACP client.
57
- * If a message rewriter is configured, updates pass through it first
58
- * (original messages are sent as-is, rewritten versions are appended).
59
- */
60
- async sendUpdate(update) {
61
- if (this.ctx.messageRewriter) {
62
- return this.ctx.messageRewriter.interceptUpdate(update);
63
- }
64
- return this.ctx.sendUpdate(update);
130
+ }, "getLatestGitHubRelease");
131
+ async function getGitHubRepoInfoAsync(opts = {}) {
132
+ return parseGitHubRepoInfo(
133
+ await runGit(["remote", "get-url", "origin"], opts)
134
+ );
135
+ }
136
+ __name(getGitHubRepoInfoAsync, "getGitHubRepoInfoAsync");
137
+ function parseGitHubRepoInfo(remoteUrl) {
138
+ let urlToParse = remoteUrl;
139
+ if (remoteUrl.startsWith("git@github.com:")) {
140
+ urlToParse = remoteUrl.replace("git@github.com:", "");
141
+ } else if (remoteUrl.startsWith("git@")) {
142
+ throw new Error(
143
+ `Owner & repo could not be extracted from remote URL: ${remoteUrl}`
144
+ );
65
145
  }
66
- /**
67
- * Gets the session configuration.
68
- */
69
- get config() {
70
- return this.ctx.config;
146
+ let parsedUrl;
147
+ try {
148
+ parsedUrl = new URL(urlToParse, "https://github.com");
149
+ } catch {
150
+ throw new Error(
151
+ `Owner & repo could not be extracted from remote URL: ${remoteUrl}`
152
+ );
71
153
  }
72
- /**
73
- * Gets the session ID.
74
- */
75
- get sessionId() {
76
- return this.ctx.sessionId;
154
+ if (parsedUrl.hostname !== "github.com") {
155
+ throw new Error(
156
+ `Owner & repo could not be extracted from remote URL: ${remoteUrl}`
157
+ );
77
158
  }
78
- };
159
+ const parts = parsedUrl.pathname.split("/").filter((part) => part !== "");
160
+ if (parts.length !== 2 || !parts[0] || !parts[1]) {
161
+ throw new Error(
162
+ `Owner & repo could not be extracted from remote URL: ${remoteUrl}`
163
+ );
164
+ }
165
+ return { owner: parts[0], repo: parts[1].replace(/\.git$/, "") };
166
+ }
167
+ __name(parseGitHubRepoInfo, "parseGitHubRepoInfo");
79
168
 
80
- // packages/cli/src/acp-integration/session/emitters/MessageEmitter.ts
81
- var MessageEmitter = class extends BaseEmitter {
169
+ // packages/cli/src/services/setup-github.ts
170
+ var debugLogger2 = createDebugLogger("SETUP_GITHUB");
171
+ var GITHUB_WORKFLOW_PATHS = [
172
+ "qwen-dispatch/qwen-dispatch.yml",
173
+ "qwen-assistant/qwen-invoke.yml",
174
+ "issue-triage/qwen-triage.yml",
175
+ "issue-triage/qwen-scheduled-triage.yml",
176
+ "pr-review/qwen-review.yml"
177
+ ];
178
+ var GITIGNORE_ENTRIES = [".qwen/", "gha-creds-*.json"];
179
+ var MAX_WORKFLOW_DOWNLOAD_BYTES = 5 * 1024 * 1024;
180
+ var SetupGithubError = class extends Error {
82
181
  static {
83
- __name(this, "MessageEmitter");
182
+ __name(this, "SetupGithubError");
84
183
  }
85
- /**
86
- * Emits a StopHookLoop event when Stop hooks create a loop.
87
- * This informs the client that Stop hooks have been executed multiple times.
88
- *
89
- * @param iterationCount - The current iteration count
90
- * @param reasons - Array of reasons from each Stop hook execution
91
- * @param stopHookCount - Number of Stop hooks that were executed
92
- */
93
- async emitStopHookLoop(iterationCount, reasons, stopHookCount) {
94
- const activeGoal = getActiveGoal(this.sessionId);
95
- await this.sendUpdate({
96
- sessionUpdate: "agent_message_chunk",
97
- content: { type: "text", text: "" },
98
- _meta: {
99
- stopHookLoop: {
100
- iterationCount,
101
- reasons,
102
- stopHookCount,
103
- ...activeGoal ? {
104
- goal: {
105
- condition: activeGoal.condition,
106
- iterations: activeGoal.iterations,
107
- setAt: activeGoal.setAt,
108
- lastReason: activeGoal.lastReason
109
- }
110
- } : {}
111
- }
112
- }
113
- });
184
+ code;
185
+ status;
186
+ partial;
187
+ partialResult;
188
+ constructor(code, message, status, partialResult) {
189
+ super(message);
190
+ this.name = "SetupGithubError";
191
+ this.code = code;
192
+ this.status = status;
193
+ this.partial = partialResult !== void 0;
194
+ this.partialResult = partialResult;
114
195
  }
115
- async emitGoalTerminal(event) {
116
- await this.sendUpdate({
117
- sessionUpdate: "agent_message_chunk",
118
- content: { type: "text", text: "" },
119
- _meta: {
120
- goalTerminal: event
121
- }
196
+ };
197
+ var nodeFileOps = {
198
+ assertCanWrite() {
199
+ },
200
+ async ensureWorkflowDirectory(gitRepoRoot) {
201
+ await fsp.mkdir(path.join(gitRepoRoot, ".github", "workflows"), {
202
+ recursive: true
122
203
  });
123
- }
124
- async emitGoalStatus(status) {
125
- await this.sendUpdate({
126
- sessionUpdate: "agent_message_chunk",
127
- content: { type: "text", text: "" },
128
- _meta: {
129
- goalStatus: status
204
+ },
205
+ async writeTextFile(gitRepoRoot, relativePath, content) {
206
+ const target = path.join(gitRepoRoot, relativePath);
207
+ await fsp.writeFile(target, content, { mode: 420 });
208
+ return { sizeBytes: Buffer.byteLength(content, "utf8") };
209
+ },
210
+ async readTextFile(gitRepoRoot, relativePath) {
211
+ try {
212
+ return await fsp.readFile(path.join(gitRepoRoot, relativePath), "utf8");
213
+ } catch (error) {
214
+ if (error.code === "ENOENT") {
215
+ return void 0;
130
216
  }
131
- });
217
+ throw error;
218
+ }
132
219
  }
133
- /**
220
+ };
221
+ async function setupGithub(options = {}) {
222
+ const cwd = options.cwd ?? process.cwd();
223
+ const fileOps = options.fileOps ?? nodeFileOps;
224
+ if (!await isGitHubRepositoryAsync({ cwd })) {
225
+ throw new SetupGithubError(
226
+ "github_repository_not_found",
227
+ "Unable to determine the GitHub repository. /setup-github must be run from a git repository.",
228
+ 400
229
+ );
230
+ }
231
+ let gitRepoRoot;
232
+ try {
233
+ gitRepoRoot = await getGitRepoRootAsync({ cwd });
234
+ } catch (error) {
235
+ debugLogger2.debug("Failed to get git repo root:", error);
236
+ throw new SetupGithubError(
237
+ "github_repository_not_found",
238
+ "Unable to determine the GitHub repository. /setup-github must be run from a git repository.",
239
+ 400
240
+ );
241
+ }
242
+ if (options.workspaceRoot) {
243
+ const [gitRootReal, workspaceReal] = await Promise.all([
244
+ realpathOrResolve(gitRepoRoot),
245
+ realpathOrResolve(options.workspaceRoot)
246
+ ]);
247
+ if (gitRootReal !== workspaceReal) {
248
+ throw new SetupGithubError(
249
+ "github_git_root_mismatch",
250
+ "The Git repository root must match the daemon workspace root.",
251
+ 400
252
+ );
253
+ }
254
+ }
255
+ fileOps.assertCanWrite?.();
256
+ let releaseTag;
257
+ try {
258
+ releaseTag = await getLatestGitHubRelease(options.proxy);
259
+ } catch (error) {
260
+ writeStderrLine(
261
+ `qwen setup-github: failed to determine latest qwen-code-action release: ${error instanceof Error ? error.message : String(error)}`
262
+ );
263
+ debugLogger2.debug(
264
+ "Failed to determine latest qwen-code-action release:",
265
+ error
266
+ );
267
+ throw new SetupGithubError(
268
+ "github_release_lookup_failed",
269
+ "Unable to determine the latest qwen-code-action release on GitHub.",
270
+ 502
271
+ );
272
+ }
273
+ const readmeUrl = `https://github.com/QwenLM/qwen-code-action/blob/${releaseTag}/README.md#quick-start`;
274
+ const secretsUrl = await resolveSecretsUrl(cwd);
275
+ const downloads = await downloadWorkflows({
276
+ releaseTag,
277
+ proxy: options.proxy,
278
+ abortSignal: options.abortSignal,
279
+ fetchImpl: options.fetchImpl ?? fetch
280
+ });
281
+ const result = {
282
+ kind: "github_setup",
283
+ workspaceCwd: options.workspaceRoot ?? gitRepoRoot,
284
+ gitRepoRoot,
285
+ releaseTag,
286
+ readmeUrl,
287
+ ...secretsUrl ? { secretsUrl } : {},
288
+ workflows: [],
289
+ gitignore: { path: ".gitignore", status: "skipped" },
290
+ warnings: []
291
+ };
292
+ result.gitignore = await updateGitignore(gitRepoRoot, fileOps);
293
+ if (result.gitignore.status === "failed") {
294
+ result.warnings.push("Failed to update .gitignore.");
295
+ }
296
+ try {
297
+ await fileOps.ensureWorkflowDirectory(gitRepoRoot);
298
+ for (const workflow of downloads) {
299
+ const relativePath = path.posix.join(
300
+ ".github",
301
+ "workflows",
302
+ path.posix.basename(workflow.sourcePath)
303
+ );
304
+ try {
305
+ const write = await fileOps.writeTextFile(
306
+ gitRepoRoot,
307
+ relativePath,
308
+ workflow.content
309
+ );
310
+ result.workflows.push({
311
+ sourcePath: workflow.sourcePath,
312
+ path: relativePath,
313
+ status: "written",
314
+ sizeBytes: write.sizeBytes
315
+ });
316
+ } catch (error) {
317
+ result.partial = true;
318
+ result.workflows.push({
319
+ sourcePath: workflow.sourcePath,
320
+ path: relativePath,
321
+ status: "failed",
322
+ error: error instanceof Error ? error.message : String(error)
323
+ });
324
+ throw new SetupGithubError(
325
+ "github_workflow_write_failed",
326
+ `Unable to write ${relativePath}.`,
327
+ 500,
328
+ result
329
+ );
330
+ }
331
+ }
332
+ } catch (error) {
333
+ if (error instanceof SetupGithubError) throw error;
334
+ throw new SetupGithubError(
335
+ "github_workflow_write_failed",
336
+ "Unable to create .github/workflows.",
337
+ 500,
338
+ result
339
+ );
340
+ }
341
+ return result;
342
+ }
343
+ __name(setupGithub, "setupGithub");
344
+ async function updateGitignore(gitRepoRoot, fileOps = nodeFileOps) {
345
+ try {
346
+ const existingContent = await fileOps.readTextFile(
347
+ gitRepoRoot,
348
+ ".gitignore"
349
+ );
350
+ if (existingContent === void 0) {
351
+ const content = GITIGNORE_ENTRIES.join("\n") + "\n";
352
+ await fileOps.writeTextFile(gitRepoRoot, ".gitignore", content);
353
+ return {
354
+ path: ".gitignore",
355
+ status: "created",
356
+ added: [...GITIGNORE_ENTRIES]
357
+ };
358
+ }
359
+ const missingEntries = GITIGNORE_ENTRIES.filter(
360
+ (entry) => !existingContent.split(/\r?\n/).some((line) => line.split("#")[0].trim() === entry)
361
+ );
362
+ if (missingEntries.length === 0) {
363
+ return { path: ".gitignore", status: "unchanged" };
364
+ }
365
+ const nextContent = existingContent + "\n" + missingEntries.join("\n") + "\n";
366
+ await fileOps.writeTextFile(gitRepoRoot, ".gitignore", nextContent);
367
+ return {
368
+ path: ".gitignore",
369
+ status: "updated",
370
+ added: missingEntries
371
+ };
372
+ } catch (error) {
373
+ debugLogger2.debug("Failed to update .gitignore:", error);
374
+ return {
375
+ path: ".gitignore",
376
+ status: "failed",
377
+ error: error instanceof Error ? error.message : String(error)
378
+ };
379
+ }
380
+ }
381
+ __name(updateGitignore, "updateGitignore");
382
+ async function downloadWorkflows(options) {
383
+ const internalAbort = new AbortController();
384
+ try {
385
+ const dispatcher = options.proxy ? new import_undici2.ProxyAgent(options.proxy) : void 0;
386
+ return await Promise.all(
387
+ GITHUB_WORKFLOW_PATHS.map(async (workflow) => {
388
+ const endpoint = `https://raw.githubusercontent.com/QwenLM/qwen-code-action/refs/tags/${options.releaseTag}/examples/workflows/${workflow}`;
389
+ const response = await options.fetchImpl(endpoint, {
390
+ method: "GET",
391
+ dispatcher,
392
+ signal: AbortSignal.any([
393
+ AbortSignal.timeout(3e4),
394
+ internalAbort.signal,
395
+ ...options.abortSignal ? [options.abortSignal] : []
396
+ ])
397
+ });
398
+ if (!response.ok) {
399
+ throw new Error(
400
+ `Invalid response code downloading ${endpoint}: ${response.status} - ${response.statusText}`
401
+ );
402
+ }
403
+ return {
404
+ sourcePath: workflow,
405
+ content: await readResponseTextWithLimit(response, workflow)
406
+ };
407
+ })
408
+ );
409
+ } catch (error) {
410
+ internalAbort.abort();
411
+ const message = error instanceof Error ? error.message : String(error);
412
+ debugLogger2.debug("Failed to download qwen-code-action workflows:", error);
413
+ throw new SetupGithubError(
414
+ "github_workflow_download_failed",
415
+ `Unable to download qwen-code-action workflows from GitHub. ${message}`,
416
+ 502
417
+ );
418
+ }
419
+ }
420
+ __name(downloadWorkflows, "downloadWorkflows");
421
+ async function readResponseTextWithLimit(response, sourcePath) {
422
+ const contentLength = response.headers.get("content-length");
423
+ if (contentLength !== null) {
424
+ const parsedLength = Number(contentLength);
425
+ if (Number.isFinite(parsedLength) && parsedLength > MAX_WORKFLOW_DOWNLOAD_BYTES) {
426
+ throw new Error(
427
+ `${sourcePath} exceeds download limit of ${MAX_WORKFLOW_DOWNLOAD_BYTES} bytes`
428
+ );
429
+ }
430
+ }
431
+ if (!response.body) return "";
432
+ const reader = response.body.getReader();
433
+ const chunks = [];
434
+ let totalBytes = 0;
435
+ try {
436
+ while (true) {
437
+ const { done, value } = await reader.read();
438
+ if (done) break;
439
+ if (!value) continue;
440
+ totalBytes += value.byteLength;
441
+ if (totalBytes > MAX_WORKFLOW_DOWNLOAD_BYTES) {
442
+ await reader.cancel().catch(() => {
443
+ });
444
+ throw new Error(
445
+ `${sourcePath} exceeds download limit of ${MAX_WORKFLOW_DOWNLOAD_BYTES} bytes`
446
+ );
447
+ }
448
+ chunks.push(value);
449
+ }
450
+ } finally {
451
+ reader.releaseLock();
452
+ }
453
+ const body = new Uint8Array(totalBytes);
454
+ let offset = 0;
455
+ for (const chunk of chunks) {
456
+ body.set(chunk, offset);
457
+ offset += chunk.byteLength;
458
+ }
459
+ return new TextDecoder().decode(body);
460
+ }
461
+ __name(readResponseTextWithLimit, "readResponseTextWithLimit");
462
+ async function resolveSecretsUrl(cwd) {
463
+ try {
464
+ const repoInfo = await getGitHubRepoInfoAsync({ cwd });
465
+ return `https://github.com/${repoInfo.owner}/${repoInfo.repo}/settings/secrets/actions`;
466
+ } catch {
467
+ return void 0;
468
+ }
469
+ }
470
+ __name(resolveSecretsUrl, "resolveSecretsUrl");
471
+ async function realpathOrResolve(input) {
472
+ try {
473
+ return await fsp.realpath(input);
474
+ } catch {
475
+ return path.resolve(input);
476
+ }
477
+ }
478
+ __name(realpathOrResolve, "realpathOrResolve");
479
+
480
+ // packages/cli/src/acp-integration/session/emitters/MessageEmitter.ts
481
+ init_esbuild_shims();
482
+
483
+ // packages/cli/src/acp-integration/session/emitters/base-emitter.ts
484
+ init_esbuild_shims();
485
+ var BaseEmitter = class {
486
+ constructor(ctx) {
487
+ this.ctx = ctx;
488
+ }
489
+ static {
490
+ __name(this, "BaseEmitter");
491
+ }
492
+ /**
493
+ * Converts an ISO timestamp string or epoch ms to epoch ms number.
494
+ * Returns undefined if the input is not a valid timestamp.
495
+ */
496
+ static toEpochMs(ts) {
497
+ if (typeof ts === "number") {
498
+ return Number.isFinite(ts) ? ts : void 0;
499
+ }
500
+ if (typeof ts === "string") {
501
+ const ms = new Date(ts).getTime();
502
+ return Number.isFinite(ms) ? ms : void 0;
503
+ }
504
+ return void 0;
505
+ }
506
+ /**
507
+ * Sends a session update to the ACP client.
508
+ * If a message rewriter is configured, updates pass through it first
509
+ * (original messages are sent as-is, rewritten versions are appended).
510
+ */
511
+ async sendUpdate(update) {
512
+ if (this.ctx.messageRewriter) {
513
+ return this.ctx.messageRewriter.interceptUpdate(update);
514
+ }
515
+ return this.ctx.sendUpdate(update);
516
+ }
517
+ /**
518
+ * Gets the session ID.
519
+ */
520
+ get sessionId() {
521
+ return this.ctx.sessionId;
522
+ }
523
+ };
524
+
525
+ // packages/cli/src/acp-integration/session/emitters/MessageEmitter.ts
526
+ var MessageEmitter = class extends BaseEmitter {
527
+ static {
528
+ __name(this, "MessageEmitter");
529
+ }
530
+ /**
531
+ * Emits a StopHookLoop event when Stop hooks create a loop.
532
+ * This informs the client that Stop hooks have been executed multiple times.
533
+ *
534
+ * @param iterationCount - The current iteration count
535
+ * @param reasons - Array of reasons from each Stop hook execution
536
+ * @param stopHookCount - Number of Stop hooks that were executed
537
+ */
538
+ async emitStopHookLoop(iterationCount, reasons, stopHookCount) {
539
+ const activeGoal = getActiveGoal(this.sessionId);
540
+ await this.sendUpdate({
541
+ sessionUpdate: "agent_message_chunk",
542
+ content: { type: "text", text: "" },
543
+ _meta: {
544
+ stopHookLoop: {
545
+ iterationCount,
546
+ reasons,
547
+ stopHookCount,
548
+ ...activeGoal ? {
549
+ goal: {
550
+ condition: activeGoal.condition,
551
+ iterations: activeGoal.iterations,
552
+ setAt: activeGoal.setAt,
553
+ lastReason: activeGoal.lastReason
554
+ }
555
+ } : {}
556
+ }
557
+ }
558
+ });
559
+ }
560
+ async emitGoalTerminal(event) {
561
+ await this.sendUpdate({
562
+ sessionUpdate: "agent_message_chunk",
563
+ content: { type: "text", text: "" },
564
+ _meta: {
565
+ goalTerminal: event
566
+ }
567
+ });
568
+ }
569
+ async emitGoalStatus(status) {
570
+ await this.sendUpdate({
571
+ sessionUpdate: "agent_message_chunk",
572
+ content: { type: "text", text: "" },
573
+ _meta: {
574
+ goalStatus: status
575
+ }
576
+ });
577
+ }
578
+ /**
134
579
  * Emits a user message chunk.
135
580
  *
136
581
  * @param text - The user message text content
@@ -182,6 +627,17 @@ var MessageEmitter = class extends BaseEmitter {
182
627
  ..._meta ? { _meta } : {}
183
628
  });
184
629
  }
630
+ async emitSlashCommandOutput(text, timestamp) {
631
+ const epochMs = BaseEmitter.toEpochMs(timestamp);
632
+ await this.sendUpdate({
633
+ sessionUpdate: "agent_message_chunk",
634
+ content: { type: "text", text },
635
+ _meta: {
636
+ source: "slash_command",
637
+ ...epochMs != null ? { timestamp: epochMs } : {}
638
+ }
639
+ });
640
+ }
185
641
  /**
186
642
  * Emits usage metadata.
187
643
  */
@@ -210,7 +666,19 @@ var MessageEmitter = class extends BaseEmitter {
210
666
  );
211
667
  cumulative.apiTimeMs = addFinite(cumulative.apiTimeMs, durationMs);
212
668
  }
213
- const meta = typeof durationMs === "number" ? { usage, durationMs, ...subagentMeta } : { usage, ...subagentMeta };
669
+ let meta;
670
+ if (typeof durationMs === "number") {
671
+ const activity = apiActivityTracker.drain();
672
+ meta = {
673
+ usage,
674
+ durationMs,
675
+ ...activity.errors > 0 ? { apiErrors: activity.errors } : {},
676
+ ...activity.retries > 0 ? { apiRetries: activity.retries } : {},
677
+ ...subagentMeta
678
+ };
679
+ } else {
680
+ meta = { usage, ...subagentMeta };
681
+ }
214
682
  await this.sendUpdate({
215
683
  sessionUpdate: "agent_message_chunk",
216
684
  content: { type: "text", text },
@@ -242,9 +710,6 @@ var MessageEmitter = class extends BaseEmitter {
242
710
  }
243
711
  };
244
712
 
245
- // packages/cli/src/acp-integration/session/emitters/ToolCallEmitter.ts
246
- init_esbuild_shims();
247
-
248
713
  // packages/cli/src/acp-integration/session/emitters/PlanEmitter.ts
249
714
  init_esbuild_shims();
250
715
  var PlanEmitter = class extends BaseEmitter {
@@ -314,6 +779,16 @@ var PlanEmitter = class extends BaseEmitter {
314
779
  }
315
780
  };
316
781
 
782
+ // packages/cli/src/acp-integration/session/emitters/tool-call-emitter.ts
783
+ init_esbuild_shims();
784
+
785
+ // packages/cli/src/acp-integration/session/types.ts
786
+ init_esbuild_shims();
787
+ function hasFullSessionContext(context) {
788
+ return "config" in context;
789
+ }
790
+ __name(hasFullSessionContext, "hasFullSessionContext");
791
+
317
792
  // packages/cli/src/utils/truncatedDiffPreview.ts
318
793
  init_esbuild_shims();
319
794
  function buildTruncatedDiffPreviewText(display) {
@@ -326,7 +801,7 @@ function buildTruncatedDiffPreviewText(display) {
326
801
  }
327
802
  __name(buildTruncatedDiffPreviewText, "buildTruncatedDiffPreviewText");
328
803
 
329
- // packages/cli/src/acp-integration/session/emitters/ToolCallEmitter.ts
804
+ // packages/cli/src/acp-integration/session/emitters/tool-call-emitter.ts
330
805
  var KIND_MAP = {
331
806
  ["read" /* Read */]: "read",
332
807
  ["edit" /* Edit */]: "edit",
@@ -496,923 +971,526 @@ var ToolCallEmitter = class _ToolCallEmitter extends BaseEmitter {
496
971
  * `serverId: <server>`. Naming convention from
497
972
  * `packages/core/src/tools/mcp-tool.ts` in the
498
973
  * `@qwen-code/qwen-code-core` package — mirrors the SDK's same
499
- * heuristic fallback so SDK consumers stay consistent with
500
- * daemon classification.
501
- * - everything else → `'builtin'`
502
- *
503
- * Static + pure so it can be unit-tested without an emitter
504
- * instance. Exported via `ToolCallEmitter.resolveToolProvenance`.
505
- */
506
- static resolveToolProvenance(toolName, subagentMeta) {
507
- if (subagentMeta !== void 0) {
508
- return { provenance: "subagent" };
509
- }
510
- if (toolName.startsWith("mcp__")) {
511
- const parts = toolName.split("__");
512
- if (parts.length >= 3 && parts[1] && parts[1].length > 0) {
513
- return { provenance: "mcp", serverId: parts[1] };
514
- }
515
- }
516
- return { provenance: "builtin" };
517
- }
518
- // ==================== Public Utilities ====================
519
- /**
520
- * Checks if a tool name is the TodoWriteTool.
521
- * Exposed for external use in components that need to check this.
522
- */
523
- isTodoWriteTool(toolName) {
524
- return toolName === ToolNames.TODO_WRITE;
525
- }
526
- /**
527
- * Checks if a tool name is the ExitPlanModeTool.
528
- */
529
- isExitPlanModeTool(toolName) {
530
- return toolName === ToolNames.EXIT_PLAN_MODE;
531
- }
532
- /**
533
- * Checks if a tool name is the EnterPlanModeTool.
534
- */
535
- isEnterPlanModeTool(toolName) {
536
- return toolName === ToolNames.ENTER_PLAN_MODE;
537
- }
538
- /**
539
- * Resolves tool metadata from the registry.
540
- * Falls back to defaults if tool not found or build fails.
541
- *
542
- * @param toolName - Name of the tool
543
- * @param args - Tool call arguments (used to build invocation)
544
- */
545
- resolveToolMetadata(toolName, args) {
546
- const toolRegistry = this.config.getToolRegistry();
547
- const tool = toolRegistry.getTool(toolName);
548
- let title = tool?.displayName ?? toolName;
549
- let locations = [];
550
- let kind = "other";
551
- if (tool && args) {
552
- try {
553
- const invocation = tool.build(args);
554
- title = `${title}: ${invocation.getDescription()}`;
555
- locations = invocation.toolLocations().map((loc) => ({
556
- path: loc.path,
557
- line: loc.line ?? null
558
- }));
559
- kind = this.mapToolKind(tool.kind, toolName);
560
- } catch {
561
- if (typeof args["description"] === "string") {
562
- title = `${title}: ${args["description"]}`;
563
- }
564
- if (tool.kind) {
565
- kind = this.mapToolKind(tool.kind, toolName);
566
- }
567
- }
568
- }
569
- return { title, locations, kind };
570
- }
571
- /**
572
- * Maps core Tool Kind enum to ACP ToolKind string literals.
573
- *
574
- * @param kind - The core Kind enum value
575
- * @param toolName - Optional tool name to handle special cases like exit_plan_mode
576
- */
577
- mapToolKind(kind, toolName) {
578
- if (toolName && (this.isExitPlanModeTool(toolName) || this.isEnterPlanModeTool(toolName))) {
579
- return "switch_mode";
580
- }
581
- return KIND_MAP[kind] ?? "other";
582
- }
583
- // ==================== Private Helpers ====================
584
- /**
585
- * Extracts diff content from resultDisplay if it's a diff type (edit tool result).
586
- * Returns null if not a diff.
587
- */
588
- extractDiffContent(resultDisplay) {
589
- if (!resultDisplay || typeof resultDisplay !== "object") return null;
590
- const obj = resultDisplay;
591
- if ("fileName" in obj && "newContent" in obj) {
592
- if (this.isTruncatedSessionDiffDisplay(resultDisplay)) {
593
- return {
594
- type: "content",
595
- content: {
596
- type: "text",
597
- text: buildTruncatedDiffPreviewText(obj)
598
- }
599
- };
600
- }
601
- return {
602
- type: "diff",
603
- path: obj["fileName"],
604
- oldText: obj["originalContent"] ?? "",
605
- newText: obj["newContent"]
606
- };
607
- }
608
- return null;
609
- }
610
- isTruncatedSessionDiffDisplay(resultDisplay) {
611
- if (!resultDisplay || typeof resultDisplay !== "object") return false;
612
- const obj = resultDisplay;
613
- return obj["truncatedForSession"] === true && "fileName" in obj && "newContent" in obj;
614
- }
615
- /**
616
- * Transforms Part[] to ToolCallContent[].
617
- * Extracts text from functionResponse parts and text parts.
618
- */
619
- transformPartsToToolCallContent(parts) {
620
- const result = [];
621
- for (const part of parts) {
622
- if ("text" in part && part.text) {
623
- result.push({
624
- type: "content",
625
- content: { type: "text", text: part.text }
626
- });
627
- }
628
- if ("functionResponse" in part && part.functionResponse) {
629
- try {
630
- const resp = part.functionResponse.response;
631
- const outputField = resp["output"];
632
- const errorField = resp["error"];
633
- const responseText = typeof outputField === "string" ? outputField : typeof errorField === "string" ? errorField : JSON.stringify(resp);
634
- result.push({
635
- type: "content",
636
- content: { type: "text", text: responseText }
637
- });
638
- } catch {
639
- }
640
- }
641
- }
642
- return result;
643
- }
644
- };
645
-
646
- // packages/cli/src/utils/chat-record-tool-call-id.ts
647
- init_esbuild_shims();
648
- function getToolResultCallId(record) {
649
- return getExplicitToolResultCallId(record) ?? record.uuid;
650
- }
651
- __name(getToolResultCallId, "getToolResultCallId");
652
- function getExplicitToolResultCallId(record) {
653
- const resultCallId = record.toolCallResult?.callId;
654
- if (typeof resultCallId === "string" && resultCallId.length > 0) {
655
- return resultCallId;
656
- }
657
- return extractFunctionResponseId(record);
658
- }
659
- __name(getExplicitToolResultCallId, "getExplicitToolResultCallId");
660
- function extractFunctionResponseId(record) {
661
- if (!record.message?.parts) {
662
- return void 0;
663
- }
664
- for (const part of record.message.parts) {
665
- const id = "functionResponse" in part ? part.functionResponse?.id : void 0;
666
- if (typeof id === "string" && id.length > 0) {
667
- return id;
668
- }
669
- }
670
- return void 0;
671
- }
672
- __name(extractFunctionResponseId, "extractFunctionResponseId");
673
-
674
- // packages/cli/src/acp-integration/session/HistoryReplayer.ts
675
- var MISSING_TOOL_RESULT_MESSAGE = "Tool result missing from saved history; the previous run likely ended before this tool completed.";
676
- var HistoryReplayer = class {
677
- static {
678
- __name(this, "HistoryReplayer");
679
- }
680
- ctx;
681
- messageEmitter;
682
- toolCallEmitter;
683
- pendingReplayToolCalls = /* @__PURE__ */ new Map();
684
- constructor(ctx) {
685
- this.ctx = ctx;
686
- this.messageEmitter = new MessageEmitter(ctx);
687
- this.toolCallEmitter = new ToolCallEmitter(ctx);
688
- }
689
- /**
690
- * Replays all chat records from a loaded session.
974
+ * heuristic fallback so SDK consumers stay consistent with
975
+ * daemon classification.
976
+ * - everything else → `'builtin'`
691
977
  *
692
- * @param records - Array of chat records to replay
978
+ * Static + pure so it can be unit-tested without an emitter
979
+ * instance. Exported via `ToolCallEmitter.resolveToolProvenance`.
693
980
  */
694
- async replay(records) {
695
- this.pendingReplayToolCalls.clear();
696
- try {
697
- let replayError;
698
- try {
699
- for (const record of records) {
700
- await this.replayRecord(record);
701
- }
702
- } catch (error) {
703
- replayError = error;
704
- }
705
- let danglingError;
706
- try {
707
- await this.failDanglingToolCalls();
708
- } catch (error) {
709
- danglingError = error;
710
- }
711
- if (replayError && danglingError) {
712
- throw new AggregateError(
713
- [replayError, danglingError],
714
- "Replay and dangling-cleanup both failed"
715
- );
716
- }
717
- if (replayError) {
718
- throw replayError;
719
- }
720
- if (danglingError) {
721
- throw danglingError;
981
+ static resolveToolProvenance(toolName, subagentMeta) {
982
+ if (subagentMeta !== void 0) {
983
+ return { provenance: "subagent" };
984
+ }
985
+ if (toolName.startsWith("mcp__")) {
986
+ const parts = toolName.split("__");
987
+ if (parts.length >= 3 && parts[1] && parts[1].length > 0) {
988
+ return { provenance: "mcp", serverId: parts[1] };
722
989
  }
723
- } finally {
724
- this.pendingReplayToolCalls.clear();
725
- this.setActiveRecordId(null);
726
990
  }
991
+ return { provenance: "builtin" };
727
992
  }
993
+ // ==================== Public Utilities ====================
728
994
  /**
729
- * Replays a single chat record.
995
+ * Checks if a tool name is the TodoWriteTool.
996
+ * Exposed for external use in components that need to check this.
730
997
  */
731
- async replayRecord(record) {
732
- this.setActiveRecordId(record.uuid, record.timestamp);
733
- try {
734
- switch (record.type) {
735
- case "user":
736
- if (record.subtype === "notification" || record.subtype === "cron") {
737
- const displayText = record.systemPayload?.displayText;
738
- if (displayText) {
739
- await this.messageEmitter.emitUserMessage(
740
- displayText,
741
- record.timestamp,
742
- record.subtype === "cron" ? { source: "cron" } : void 0
743
- );
744
- }
745
- break;
746
- }
747
- if (record.subtype === "mid_turn_user_message") {
748
- const displayText = record.systemPayload?.displayText;
749
- if (displayText) {
750
- await this.messageEmitter.emitUserMessage(
751
- displayText,
752
- record.timestamp
753
- );
754
- } else if (record.message) {
755
- await this.replayContent(
756
- record.message,
757
- "user",
758
- record.timestamp,
759
- record.uuid
760
- );
761
- }
762
- break;
763
- }
764
- if (record.message) {
765
- await this.replayContent(
766
- record.message,
767
- "user",
768
- record.timestamp,
769
- record.uuid
770
- );
771
- }
772
- break;
773
- case "assistant":
774
- if (record.message) {
775
- await this.replayContent(
776
- record.message,
777
- "assistant",
778
- record.timestamp,
779
- record.uuid
780
- );
781
- }
782
- if (record.usageMetadata) {
783
- await this.replayUsageMetadata(record.usageMetadata);
784
- }
785
- break;
786
- case "tool_result":
787
- await this.replayToolResult(record);
788
- break;
789
- case "system":
790
- if (record.subtype === "slash_command") {
791
- await this.replaySlashCommandResult(record);
792
- }
793
- break;
794
- default:
795
- break;
796
- }
797
- } finally {
798
- this.setActiveRecordId(null);
799
- }
998
+ isTodoWriteTool(toolName) {
999
+ return toolName === ToolNames.TODO_WRITE;
800
1000
  }
801
1001
  /**
802
- * Replays content from a message (user or assistant).
803
- * Handles text parts, thought parts, and function calls.
804
- *
805
- * @param content - The content to replay
806
- * @param role - The role (user or assistant)
807
- * @param timestamp - Optional server-side timestamp from the JSONL record
1002
+ * Checks if a tool name is the ExitPlanModeTool.
808
1003
  */
809
- async replayContent(content, role, timestamp, recordId) {
810
- for (const part of content.parts ?? []) {
811
- if ("text" in part && part.text) {
812
- const isThought = part.thought ?? false;
813
- await this.messageEmitter.emitMessage(
814
- part.text,
815
- role,
816
- isThought,
817
- timestamp
818
- );
819
- }
820
- if ("functionCall" in part && part.functionCall) {
821
- const functionName = part.functionCall.name ?? "";
822
- const sourceCallId = part.functionCall.id;
823
- const callId = sourceCallId ?? `${functionName}-${Date.now()}`;
824
- const emitted = await this.toolCallEmitter.emitStart({
825
- toolName: functionName,
826
- callId,
827
- args: part.functionCall.args,
828
- status: "in_progress",
829
- timestamp
830
- });
831
- if (emitted && role === "assistant" && recordId && sourceCallId) {
832
- this.pendingReplayToolCalls.set(callId, {
833
- callId,
834
- toolName: functionName,
835
- timestamp,
836
- recordId
837
- });
838
- }
839
- }
840
- }
1004
+ isExitPlanModeTool(toolName) {
1005
+ return toolName === ToolNames.EXIT_PLAN_MODE;
841
1006
  }
842
1007
  /**
843
- * Replays usage metadata.
844
- * @param usageMetadata - The usage metadata to replay
1008
+ * Checks if a tool name is the EnterPlanModeTool.
845
1009
  */
846
- async replayUsageMetadata(usageMetadata) {
847
- await this.messageEmitter.emitUsageMetadata(usageMetadata);
1010
+ isEnterPlanModeTool(toolName) {
1011
+ return toolName === ToolNames.ENTER_PLAN_MODE;
848
1012
  }
849
1013
  /**
850
- * Replays a tool result record.
1014
+ * Resolves tool metadata from the registry.
1015
+ * Falls back to defaults if tool not found or build fails.
1016
+ *
1017
+ * @param toolName - Name of the tool
1018
+ * @param args - Tool call arguments (used to build invocation)
851
1019
  */
852
- async replayToolResult(record) {
853
- if (!record.message?.parts) {
854
- return;
855
- }
856
- const result = record.toolCallResult;
857
- const callId = getToolResultCallId(record);
858
- this.pendingReplayToolCalls.delete(callId);
859
- const toolName = this.extractToolNameFromRecord(record);
860
- await this.toolCallEmitter.emitResult({
861
- toolName,
862
- callId,
863
- success: !result?.error,
864
- message: record.message.parts,
865
- resultDisplay: result?.resultDisplay,
866
- // For TodoWriteTool fallback, try to extract args from the record
867
- // Note: args aren't stored in tool_result records by default
868
- args: void 0,
869
- timestamp: record.timestamp
870
- });
871
- const { resultDisplay } = result ?? {};
872
- if (!!resultDisplay && typeof resultDisplay === "object" && "type" in resultDisplay && resultDisplay.type === "task_execution") {
873
- await this.emitTaskUsageFromResultDisplay(
874
- resultDisplay
875
- );
1020
+ resolveToolMetadata(toolName, args) {
1021
+ if (!hasFullSessionContext(this.ctx)) {
1022
+ const description = typeof args?.["description"] === "string" ? args["description"].trim() : "";
1023
+ return {
1024
+ title: description ? `${toolName}: ${description}` : toolName,
1025
+ locations: [],
1026
+ kind: "other"
1027
+ };
876
1028
  }
877
- }
878
- async failDanglingToolCalls() {
879
- let firstError;
880
- for (const pending of this.pendingReplayToolCalls.values()) {
881
- this.setActiveRecordId(pending.recordId, pending.timestamp);
1029
+ const toolRegistry = this.ctx.config.getToolRegistry();
1030
+ const tool = toolRegistry.getTool(toolName);
1031
+ let title = tool?.displayName ?? toolName;
1032
+ let locations = [];
1033
+ let kind = "other";
1034
+ if (tool && args) {
882
1035
  try {
883
- await this.toolCallEmitter.emitResult({
884
- toolName: pending.toolName,
885
- callId: pending.callId,
886
- success: false,
887
- message: [],
888
- error: new Error(MISSING_TOOL_RESULT_MESSAGE),
889
- timestamp: pending.timestamp
890
- });
891
- } catch (error) {
892
- firstError ??= error;
893
- } finally {
894
- this.setActiveRecordId(null);
1036
+ const invocation = tool.build(args);
1037
+ title = `${title}: ${invocation.getDescription()}`;
1038
+ locations = invocation.toolLocations().map((loc) => ({
1039
+ path: loc.path,
1040
+ line: loc.line ?? null
1041
+ }));
1042
+ kind = this.mapToolKind(tool.kind, toolName);
1043
+ } catch {
1044
+ if (typeof args["description"] === "string") {
1045
+ title = `${title}: ${args["description"]}`;
1046
+ }
1047
+ if (tool.kind) {
1048
+ kind = this.mapToolKind(tool.kind, toolName);
1049
+ }
895
1050
  }
896
1051
  }
897
- if (firstError) {
898
- throw firstError;
899
- }
1052
+ return { title, locations, kind };
900
1053
  }
901
1054
  /**
902
- * Emits token usage from a AgentResultDisplay execution summary, if present.
903
- */
904
- async emitTaskUsageFromResultDisplay(resultDisplay) {
905
- const summary = resultDisplay.executionSummary;
906
- if (!summary) {
907
- return;
908
- }
909
- const usageMetadata = {};
910
- if (Number.isFinite(summary.inputTokens)) {
911
- usageMetadata.promptTokenCount = summary.inputTokens;
912
- }
913
- if (Number.isFinite(summary.outputTokens)) {
914
- usageMetadata.candidatesTokenCount = summary.outputTokens;
915
- }
916
- if (Number.isFinite(summary.thoughtTokens)) {
917
- usageMetadata.thoughtsTokenCount = summary.thoughtTokens;
918
- }
919
- if (Number.isFinite(summary.cachedTokens)) {
920
- usageMetadata.cachedContentTokenCount = summary.cachedTokens;
921
- }
922
- if (Number.isFinite(summary.totalTokens)) {
923
- usageMetadata.totalTokenCount = summary.totalTokens;
924
- }
925
- if (Object.keys(usageMetadata).length > 0) {
926
- await this.messageEmitter.emitUsageMetadata(usageMetadata);
1055
+ * Maps core Tool Kind enum to ACP ToolKind string literals.
1056
+ *
1057
+ * @param kind - The core Kind enum value
1058
+ * @param toolName - Optional tool name to handle special cases like exit_plan_mode
1059
+ */
1060
+ mapToolKind(kind, toolName) {
1061
+ if (toolName && (this.isExitPlanModeTool(toolName) || this.isEnterPlanModeTool(toolName))) {
1062
+ return "switch_mode";
927
1063
  }
1064
+ return KIND_MAP[kind] ?? "other";
928
1065
  }
1066
+ // ==================== Private Helpers ====================
929
1067
  /**
930
- * Replays a slash_command system record by re-emitting its output as an
931
- * agent message chunk. This allows Zed to reconstruct the correct turn
932
- * structure (user → agent) on session resume without polluting model context.
1068
+ * Extracts diff content from resultDisplay if it's a diff type (edit tool result).
1069
+ * Returns null if not a diff.
933
1070
  */
934
- async replaySlashCommandResult(record) {
935
- const payload = record.systemPayload;
936
- if (payload?.phase !== "result" || !payload.outputHistoryItems?.length) {
937
- return;
938
- }
939
- for (const item of payload.outputHistoryItems) {
940
- const text = typeof item["text"] === "string" ? item["text"] : "";
941
- if (text) {
942
- await this.messageEmitter.emitAgentMessage(
943
- text.replace(/\n/g, " \n"),
944
- record.timestamp
945
- );
1071
+ extractDiffContent(resultDisplay) {
1072
+ if (!resultDisplay || typeof resultDisplay !== "object") return null;
1073
+ const obj = resultDisplay;
1074
+ if ("fileName" in obj && "newContent" in obj) {
1075
+ if (this.isTruncatedSessionDiffDisplay(resultDisplay)) {
1076
+ return {
1077
+ type: "content",
1078
+ content: {
1079
+ type: "text",
1080
+ text: buildTruncatedDiffPreviewText(obj)
1081
+ }
1082
+ };
946
1083
  }
1084
+ return {
1085
+ type: "diff",
1086
+ path: obj["fileName"],
1087
+ oldText: obj["originalContent"] ?? "",
1088
+ newText: obj["newContent"]
1089
+ };
947
1090
  }
1091
+ return null;
1092
+ }
1093
+ isTruncatedSessionDiffDisplay(resultDisplay) {
1094
+ if (!resultDisplay || typeof resultDisplay !== "object") return false;
1095
+ const obj = resultDisplay;
1096
+ return obj["truncatedForSession"] === true && "fileName" in obj && "newContent" in obj;
948
1097
  }
949
1098
  /**
950
- * Extracts tool name from a chat record's function response.
1099
+ * Transforms Part[] to ToolCallContent[].
1100
+ * Extracts text from functionResponse parts and text parts.
951
1101
  */
952
- extractToolNameFromRecord(record) {
953
- if (record.message?.parts) {
954
- for (const part of record.message.parts) {
955
- if ("functionResponse" in part && part.functionResponse?.name) {
956
- return part.functionResponse.name;
1102
+ transformPartsToToolCallContent(parts) {
1103
+ const result = [];
1104
+ for (const part of parts) {
1105
+ if ("text" in part && part.text) {
1106
+ result.push({
1107
+ type: "content",
1108
+ content: { type: "text", text: part.text }
1109
+ });
1110
+ }
1111
+ if ("functionResponse" in part && part.functionResponse) {
1112
+ try {
1113
+ const resp = part.functionResponse.response;
1114
+ const outputField = resp["output"];
1115
+ const errorField = resp["error"];
1116
+ const responseText = typeof outputField === "string" ? outputField : typeof errorField === "string" ? errorField : JSON.stringify(resp);
1117
+ result.push({
1118
+ type: "content",
1119
+ content: { type: "text", text: responseText }
1120
+ });
1121
+ } catch {
957
1122
  }
958
1123
  }
959
1124
  }
960
- return "";
961
- }
962
- setActiveRecordId(recordId, timestamp) {
963
- const context = this.ctx;
964
- if (typeof context.setActiveRecordId === "function") {
965
- context.setActiveRecordId(recordId, timestamp);
966
- }
1125
+ return result;
967
1126
  }
968
1127
  };
969
1128
 
970
- // packages/cli/src/services/setup-github.ts
1129
+ // packages/cli/src/acp-integration/session/history-replayer.ts
971
1130
  init_esbuild_shims();
972
- var import_undici2 = __toESM(require_undici(), 1);
973
- import { promises as fsp } from "node:fs";
974
- import * as path from "node:path";
975
1131
 
976
- // packages/cli/src/utils/gitUtils.ts
1132
+ // packages/cli/src/utils/chat-record-tool-call-id.ts
977
1133
  init_esbuild_shims();
978
- var import_undici = __toESM(require_undici(), 1);
979
- import * as childProcess from "node:child_process";
980
- var debugLogger = createDebugLogger("GIT");
981
- async function runGit(args, opts = {}) {
982
- return await new Promise((resolve2, reject) => {
983
- childProcess.execFile(
984
- "git",
985
- args,
986
- {
987
- encoding: "utf-8",
988
- ...opts.cwd ? { cwd: opts.cwd } : {}
989
- },
990
- (err, stdout) => {
991
- if (err) {
992
- reject(err);
993
- return;
994
- }
995
- resolve2(String(stdout ?? "").trim());
996
- }
997
- );
998
- });
1134
+ function getToolResultCallId(record) {
1135
+ return getExplicitToolResultCallId(record) ?? record.uuid;
999
1136
  }
1000
- __name(runGit, "runGit");
1001
- var isGitHubRepositoryAsync = /* @__PURE__ */ __name(async (opts = {}) => {
1002
- try {
1003
- const remotes = await runGit(["remote", "-v"], opts);
1004
- return remotes.split("\n").some((line) => {
1005
- const remoteUrl = line.trim().split(/\s+/)[1];
1006
- return remoteUrl ? isGitHubRemoteUrl(remoteUrl) : false;
1007
- });
1008
- } catch (_error) {
1009
- debugLogger.debug(`Failed to get git remote:`, _error);
1010
- return false;
1011
- }
1012
- }, "isGitHubRepositoryAsync");
1013
- function isGitHubRemoteUrl(remoteUrl) {
1014
- if (remoteUrl.startsWith("git@github.com:")) {
1015
- return true;
1016
- }
1017
- if (remoteUrl.startsWith("git@")) {
1018
- return false;
1019
- }
1020
- try {
1021
- return new URL(remoteUrl).hostname === "github.com";
1022
- } catch {
1023
- return false;
1137
+ __name(getToolResultCallId, "getToolResultCallId");
1138
+ function getExplicitToolResultCallId(record) {
1139
+ const resultCallId = record.toolCallResult?.callId;
1140
+ if (typeof resultCallId === "string" && resultCallId.length > 0) {
1141
+ return resultCallId;
1024
1142
  }
1143
+ return extractFunctionResponseId(record);
1025
1144
  }
1026
- __name(isGitHubRemoteUrl, "isGitHubRemoteUrl");
1027
- var getGitRepoRootAsync = /* @__PURE__ */ __name(async (opts = {}) => {
1028
- const gitRepoRoot = await runGit(["rev-parse", "--show-toplevel"], opts);
1029
- if (!gitRepoRoot) {
1030
- throw new Error(`Git repo returned empty value`);
1145
+ __name(getExplicitToolResultCallId, "getExplicitToolResultCallId");
1146
+ function extractFunctionResponseId(record) {
1147
+ if (!record.message?.parts) {
1148
+ return void 0;
1031
1149
  }
1032
- return gitRepoRoot;
1033
- }, "getGitRepoRootAsync");
1034
- var getLatestGitHubRelease = /* @__PURE__ */ __name(async (proxy) => {
1035
- try {
1036
- const controller = new AbortController();
1037
- const endpoint = `https://api.github.com/repos/QwenLM/qwen-code-action/releases/latest`;
1038
- const response = await fetch(endpoint, {
1039
- method: "GET",
1040
- headers: {
1041
- Accept: "application/vnd.github+json",
1042
- "Content-Type": "application/json",
1043
- "X-GitHub-Api-Version": "2022-11-28"
1044
- },
1045
- dispatcher: proxy ? new import_undici.ProxyAgent(proxy) : void 0,
1046
- signal: AbortSignal.any([AbortSignal.timeout(3e4), controller.signal])
1047
- });
1048
- if (!response.ok) {
1049
- throw new Error(
1050
- `Invalid response code: ${response.status} - ${response.statusText}`
1051
- );
1052
- }
1053
- const releaseTag = (await response.json()).tag_name;
1054
- if (!releaseTag) {
1055
- throw new Error(`Response did not include tag_name field`);
1150
+ for (const part of record.message.parts) {
1151
+ const id = "functionResponse" in part ? part.functionResponse?.id : void 0;
1152
+ if (typeof id === "string" && id.length > 0) {
1153
+ return id;
1056
1154
  }
1057
- return releaseTag;
1058
- } catch (_error) {
1059
- debugLogger.debug(
1060
- `Failed to determine latest qwen-code-action release:`,
1061
- _error
1062
- );
1063
- throw new Error(
1064
- `Unable to determine the latest qwen-code-action release on GitHub.`
1065
- );
1066
- }
1067
- }, "getLatestGitHubRelease");
1068
- async function getGitHubRepoInfoAsync(opts = {}) {
1069
- return parseGitHubRepoInfo(
1070
- await runGit(["remote", "get-url", "origin"], opts)
1071
- );
1072
- }
1073
- __name(getGitHubRepoInfoAsync, "getGitHubRepoInfoAsync");
1074
- function parseGitHubRepoInfo(remoteUrl) {
1075
- let urlToParse = remoteUrl;
1076
- if (remoteUrl.startsWith("git@github.com:")) {
1077
- urlToParse = remoteUrl.replace("git@github.com:", "");
1078
- } else if (remoteUrl.startsWith("git@")) {
1079
- throw new Error(
1080
- `Owner & repo could not be extracted from remote URL: ${remoteUrl}`
1081
- );
1082
- }
1083
- let parsedUrl;
1084
- try {
1085
- parsedUrl = new URL(urlToParse, "https://github.com");
1086
- } catch {
1087
- throw new Error(
1088
- `Owner & repo could not be extracted from remote URL: ${remoteUrl}`
1089
- );
1090
- }
1091
- if (parsedUrl.hostname !== "github.com") {
1092
- throw new Error(
1093
- `Owner & repo could not be extracted from remote URL: ${remoteUrl}`
1094
- );
1095
- }
1096
- const parts = parsedUrl.pathname.split("/").filter((part) => part !== "");
1097
- if (parts.length !== 2 || !parts[0] || !parts[1]) {
1098
- throw new Error(
1099
- `Owner & repo could not be extracted from remote URL: ${remoteUrl}`
1100
- );
1101
1155
  }
1102
- return { owner: parts[0], repo: parts[1].replace(/\.git$/, "") };
1156
+ return void 0;
1103
1157
  }
1104
- __name(parseGitHubRepoInfo, "parseGitHubRepoInfo");
1158
+ __name(extractFunctionResponseId, "extractFunctionResponseId");
1105
1159
 
1106
- // packages/cli/src/services/setup-github.ts
1107
- var debugLogger2 = createDebugLogger("SETUP_GITHUB");
1108
- var GITHUB_WORKFLOW_PATHS = [
1109
- "qwen-dispatch/qwen-dispatch.yml",
1110
- "qwen-assistant/qwen-invoke.yml",
1111
- "issue-triage/qwen-triage.yml",
1112
- "issue-triage/qwen-scheduled-triage.yml",
1113
- "pr-review/qwen-review.yml"
1114
- ];
1115
- var GITIGNORE_ENTRIES = [".qwen/", "gha-creds-*.json"];
1116
- var MAX_WORKFLOW_DOWNLOAD_BYTES = 5 * 1024 * 1024;
1117
- var SetupGithubError = class extends Error {
1160
+ // packages/cli/src/acp-integration/session/history-replayer.ts
1161
+ var MISSING_TOOL_RESULT_MESSAGE = "Tool result missing from saved history; the previous run likely ended before this tool completed.";
1162
+ var HistoryReplayer = class {
1118
1163
  static {
1119
- __name(this, "SetupGithubError");
1164
+ __name(this, "HistoryReplayer");
1120
1165
  }
1121
- code;
1122
- status;
1123
- partial;
1124
- partialResult;
1125
- constructor(code, message, status, partialResult) {
1126
- super(message);
1127
- this.name = "SetupGithubError";
1128
- this.code = code;
1129
- this.status = status;
1130
- this.partial = partialResult !== void 0;
1131
- this.partialResult = partialResult;
1166
+ ctx;
1167
+ messageEmitter;
1168
+ toolCallEmitter;
1169
+ pendingReplayToolCalls = /* @__PURE__ */ new Map();
1170
+ constructor(ctx) {
1171
+ this.ctx = ctx;
1172
+ this.messageEmitter = new MessageEmitter(ctx);
1173
+ this.toolCallEmitter = new ToolCallEmitter(ctx);
1132
1174
  }
1133
- };
1134
- var nodeFileOps = {
1135
- assertCanWrite() {
1136
- },
1137
- async ensureWorkflowDirectory(gitRepoRoot) {
1138
- await fsp.mkdir(path.join(gitRepoRoot, ".github", "workflows"), {
1139
- recursive: true
1140
- });
1141
- },
1142
- async writeTextFile(gitRepoRoot, relativePath, content) {
1143
- const target = path.join(gitRepoRoot, relativePath);
1144
- await fsp.writeFile(target, content, { mode: 420 });
1145
- return { sizeBytes: Buffer.byteLength(content, "utf8") };
1146
- },
1147
- async readTextFile(gitRepoRoot, relativePath) {
1175
+ /**
1176
+ * Replays all chat records from a loaded session.
1177
+ *
1178
+ * @param records - Array of chat records to replay
1179
+ * @param gaps - Optional detected history gaps; a visible notice is emitted
1180
+ * immediately before each gap's child record so the user sees that an
1181
+ * earlier segment was lost rather than assuming the halves are contiguous.
1182
+ */
1183
+ async replay(records, gaps) {
1148
1184
  try {
1149
- return await fsp.readFile(path.join(gitRepoRoot, relativePath), "utf8");
1185
+ await this.replayPage(records, { finalizeDangling: true, gaps });
1186
+ } finally {
1187
+ this.pendingReplayToolCalls.clear();
1188
+ this.setActiveRecordId(null);
1189
+ }
1190
+ }
1191
+ async replayPage(records, options = {}) {
1192
+ this.pendingReplayToolCalls.clear();
1193
+ for (const pending of options.pendingToolCalls ?? []) {
1194
+ this.pendingReplayToolCalls.set(pending.callId, pending);
1195
+ }
1196
+ const gapByChildUuid = indexGapsByChild(options.gaps);
1197
+ let replayError;
1198
+ try {
1199
+ for (const record of records) {
1200
+ const gap = gapByChildUuid.get(record.uuid);
1201
+ if (gap) {
1202
+ await this.emitHistoryGapNotice(gap, record.timestamp);
1203
+ }
1204
+ await this.replayRecord(record);
1205
+ }
1150
1206
  } catch (error) {
1151
- if (error.code === "ENOENT") {
1152
- return void 0;
1207
+ replayError = error;
1208
+ }
1209
+ let danglingError;
1210
+ if (options.finalizeDangling === true) {
1211
+ try {
1212
+ await this.failDanglingToolCalls();
1213
+ } catch (error) {
1214
+ danglingError = error;
1153
1215
  }
1154
- throw error;
1155
1216
  }
1217
+ const state = {
1218
+ pendingToolCalls: options.finalizeDangling === true ? [] : Array.from(this.pendingReplayToolCalls.values())
1219
+ };
1220
+ this.setActiveRecordId(null);
1221
+ if (replayError && danglingError) {
1222
+ throw new AggregateError(
1223
+ [replayError, danglingError],
1224
+ "Replay and dangling-cleanup both failed"
1225
+ );
1226
+ }
1227
+ if (replayError) {
1228
+ throw replayError;
1229
+ }
1230
+ if (danglingError) {
1231
+ throw danglingError;
1232
+ }
1233
+ return state;
1156
1234
  }
1157
- };
1158
- async function setupGithub(options = {}) {
1159
- const cwd = options.cwd ?? process.cwd();
1160
- const fileOps = options.fileOps ?? nodeFileOps;
1161
- if (!await isGitHubRepositoryAsync({ cwd })) {
1162
- throw new SetupGithubError(
1163
- "github_repository_not_found",
1164
- "Unable to determine the GitHub repository. /setup-github must be run from a git repository.",
1165
- 400
1166
- );
1167
- }
1168
- let gitRepoRoot;
1169
- try {
1170
- gitRepoRoot = await getGitRepoRootAsync({ cwd });
1171
- } catch (error) {
1172
- debugLogger2.debug("Failed to get git repo root:", error);
1173
- throw new SetupGithubError(
1174
- "github_repository_not_found",
1175
- "Unable to determine the GitHub repository. /setup-github must be run from a git repository.",
1176
- 400
1177
- );
1235
+ getPendingToolCalls() {
1236
+ return Array.from(this.pendingReplayToolCalls.values());
1178
1237
  }
1179
- if (options.workspaceRoot) {
1180
- const [gitRootReal, workspaceReal] = await Promise.all([
1181
- realpathOrResolve(gitRepoRoot),
1182
- realpathOrResolve(options.workspaceRoot)
1183
- ]);
1184
- if (gitRootReal !== workspaceReal) {
1185
- throw new SetupGithubError(
1186
- "github_git_root_mismatch",
1187
- "The Git repository root must match the daemon workspace root.",
1188
- 400
1189
- );
1238
+ /**
1239
+ * Replays a single chat record.
1240
+ */
1241
+ async replayRecord(record) {
1242
+ this.setActiveRecordId(record.uuid, record.timestamp);
1243
+ try {
1244
+ switch (record.type) {
1245
+ case "user":
1246
+ if (record.subtype === "notification" || record.subtype === "cron") {
1247
+ const displayText = record.systemPayload?.displayText;
1248
+ if (displayText) {
1249
+ await this.messageEmitter.emitUserMessage(
1250
+ displayText,
1251
+ record.timestamp,
1252
+ record.subtype === "cron" ? { source: "cron" } : void 0
1253
+ );
1254
+ }
1255
+ break;
1256
+ }
1257
+ if (record.subtype === "mid_turn_user_message") {
1258
+ const displayText = record.systemPayload?.displayText;
1259
+ if (displayText) {
1260
+ await this.messageEmitter.emitUserMessage(
1261
+ displayText,
1262
+ record.timestamp
1263
+ );
1264
+ } else if (record.message) {
1265
+ await this.replayContent(
1266
+ record.message,
1267
+ "user",
1268
+ record.timestamp,
1269
+ record.uuid
1270
+ );
1271
+ }
1272
+ break;
1273
+ }
1274
+ if (record.message) {
1275
+ await this.replayContent(
1276
+ record.message,
1277
+ "user",
1278
+ record.timestamp,
1279
+ record.uuid
1280
+ );
1281
+ }
1282
+ break;
1283
+ case "assistant":
1284
+ if (record.message) {
1285
+ await this.replayContent(
1286
+ record.message,
1287
+ "assistant",
1288
+ record.timestamp,
1289
+ record.uuid
1290
+ );
1291
+ }
1292
+ if (record.usageMetadata) {
1293
+ await this.replayUsageMetadata(record.usageMetadata);
1294
+ }
1295
+ break;
1296
+ case "tool_result":
1297
+ await this.replayToolResult(record);
1298
+ break;
1299
+ case "system":
1300
+ if (record.subtype === "slash_command") {
1301
+ await this.replaySlashCommandResult(record);
1302
+ }
1303
+ break;
1304
+ default:
1305
+ break;
1306
+ }
1307
+ } finally {
1308
+ this.setActiveRecordId(null);
1190
1309
  }
1191
1310
  }
1192
- fileOps.assertCanWrite?.();
1193
- let releaseTag;
1194
- try {
1195
- releaseTag = await getLatestGitHubRelease(options.proxy);
1196
- } catch (error) {
1197
- writeStderrLine(
1198
- `qwen setup-github: failed to determine latest qwen-code-action release: ${error instanceof Error ? error.message : String(error)}`
1199
- );
1200
- debugLogger2.debug(
1201
- "Failed to determine latest qwen-code-action release:",
1202
- error
1203
- );
1204
- throw new SetupGithubError(
1205
- "github_release_lookup_failed",
1206
- "Unable to determine the latest qwen-code-action release on GitHub.",
1207
- 502
1311
+ /**
1312
+ * Emits a visible notice marking a break in the persisted history chain: an
1313
+ * earlier segment was physically lost (storage interruption) and could not be
1314
+ * recovered, so the surviving turns below must not be read as contiguous with
1315
+ * whatever came before the gap. Uses the agent message channel — the same one
1316
+ * used for other system notices (see MessageEmitter.emitStopHookLoop) — so no
1317
+ * new session-update kind is needed.
1318
+ */
1319
+ async emitHistoryGapNotice(gap, timestamp) {
1320
+ await this.messageEmitter.emitAgentMessage(
1321
+ formatHistoryGapNotice(gap),
1322
+ timestamp
1208
1323
  );
1209
1324
  }
1210
- const readmeUrl = `https://github.com/QwenLM/qwen-code-action/blob/${releaseTag}/README.md#quick-start`;
1211
- const secretsUrl = await resolveSecretsUrl(cwd);
1212
- const downloads = await downloadWorkflows({
1213
- releaseTag,
1214
- proxy: options.proxy,
1215
- abortSignal: options.abortSignal,
1216
- fetchImpl: options.fetchImpl ?? fetch
1217
- });
1218
- const result = {
1219
- kind: "github_setup",
1220
- workspaceCwd: options.workspaceRoot ?? gitRepoRoot,
1221
- gitRepoRoot,
1222
- releaseTag,
1223
- readmeUrl,
1224
- ...secretsUrl ? { secretsUrl } : {},
1225
- workflows: [],
1226
- gitignore: { path: ".gitignore", status: "skipped" },
1227
- warnings: []
1228
- };
1229
- result.gitignore = await updateGitignore(gitRepoRoot, fileOps);
1230
- if (result.gitignore.status === "failed") {
1231
- result.warnings.push("Failed to update .gitignore.");
1325
+ /**
1326
+ * Replays content from a message (user or assistant).
1327
+ * Handles text parts, thought parts, and function calls.
1328
+ *
1329
+ * @param content - The content to replay
1330
+ * @param role - The role (user or assistant)
1331
+ * @param timestamp - Optional server-side timestamp from the JSONL record
1332
+ */
1333
+ async replayContent(content, role, timestamp, recordId) {
1334
+ for (const part of content.parts ?? []) {
1335
+ if ("text" in part && part.text) {
1336
+ const isThought = part.thought ?? false;
1337
+ await this.messageEmitter.emitMessage(
1338
+ part.text,
1339
+ role,
1340
+ isThought,
1341
+ timestamp
1342
+ );
1343
+ }
1344
+ if ("functionCall" in part && part.functionCall) {
1345
+ const functionName = part.functionCall.name ?? "";
1346
+ const sourceCallId = part.functionCall.id;
1347
+ const callId = sourceCallId ?? `${functionName}-${Date.now()}`;
1348
+ const emitted = await this.toolCallEmitter.emitStart({
1349
+ toolName: functionName,
1350
+ callId,
1351
+ args: part.functionCall.args,
1352
+ status: "in_progress",
1353
+ timestamp
1354
+ });
1355
+ if (emitted && role === "assistant" && recordId && sourceCallId) {
1356
+ this.pendingReplayToolCalls.set(callId, {
1357
+ callId,
1358
+ toolName: functionName,
1359
+ timestamp,
1360
+ recordId
1361
+ });
1362
+ }
1363
+ }
1364
+ }
1232
1365
  }
1233
- try {
1234
- await fileOps.ensureWorkflowDirectory(gitRepoRoot);
1235
- for (const workflow of downloads) {
1236
- const relativePath = path.posix.join(
1237
- ".github",
1238
- "workflows",
1239
- path.posix.basename(workflow.sourcePath)
1366
+ /**
1367
+ * Replays usage metadata.
1368
+ * @param usageMetadata - The usage metadata to replay
1369
+ */
1370
+ async replayUsageMetadata(usageMetadata) {
1371
+ await this.messageEmitter.emitUsageMetadata(usageMetadata);
1372
+ }
1373
+ /**
1374
+ * Replays a tool result record.
1375
+ */
1376
+ async replayToolResult(record) {
1377
+ if (!record.message?.parts) {
1378
+ return;
1379
+ }
1380
+ const result = record.toolCallResult;
1381
+ const callId = getToolResultCallId(record);
1382
+ this.pendingReplayToolCalls.delete(callId);
1383
+ const toolName = this.extractToolNameFromRecord(record);
1384
+ await this.toolCallEmitter.emitResult({
1385
+ toolName,
1386
+ callId,
1387
+ success: !result?.error,
1388
+ message: record.message.parts,
1389
+ resultDisplay: result?.resultDisplay,
1390
+ artifacts: result?.artifacts,
1391
+ // For TodoWriteTool fallback, try to extract args from the record
1392
+ // Note: args aren't stored in tool_result records by default
1393
+ args: void 0,
1394
+ timestamp: record.timestamp
1395
+ });
1396
+ const { resultDisplay } = result ?? {};
1397
+ if (!!resultDisplay && typeof resultDisplay === "object" && "type" in resultDisplay && resultDisplay.type === "task_execution") {
1398
+ await this.emitTaskUsageFromResultDisplay(
1399
+ resultDisplay
1240
1400
  );
1401
+ }
1402
+ }
1403
+ async failDanglingToolCalls() {
1404
+ let firstError;
1405
+ for (const pending of this.pendingReplayToolCalls.values()) {
1406
+ this.setActiveRecordId(pending.recordId, pending.timestamp);
1241
1407
  try {
1242
- const write = await fileOps.writeTextFile(
1243
- gitRepoRoot,
1244
- relativePath,
1245
- workflow.content
1246
- );
1247
- result.workflows.push({
1248
- sourcePath: workflow.sourcePath,
1249
- path: relativePath,
1250
- status: "written",
1251
- sizeBytes: write.sizeBytes
1408
+ await this.toolCallEmitter.emitResult({
1409
+ toolName: pending.toolName,
1410
+ callId: pending.callId,
1411
+ success: false,
1412
+ message: [],
1413
+ error: new Error(MISSING_TOOL_RESULT_MESSAGE),
1414
+ timestamp: pending.timestamp
1252
1415
  });
1253
1416
  } catch (error) {
1254
- result.partial = true;
1255
- result.workflows.push({
1256
- sourcePath: workflow.sourcePath,
1257
- path: relativePath,
1258
- status: "failed",
1259
- error: error instanceof Error ? error.message : String(error)
1260
- });
1261
- throw new SetupGithubError(
1262
- "github_workflow_write_failed",
1263
- `Unable to write ${relativePath}.`,
1264
- 500,
1265
- result
1266
- );
1417
+ firstError ??= error;
1418
+ } finally {
1419
+ this.setActiveRecordId(null);
1267
1420
  }
1268
1421
  }
1269
- } catch (error) {
1270
- if (error instanceof SetupGithubError) throw error;
1271
- throw new SetupGithubError(
1272
- "github_workflow_write_failed",
1273
- "Unable to create .github/workflows.",
1274
- 500,
1275
- result
1276
- );
1422
+ if (firstError) {
1423
+ throw firstError;
1424
+ }
1277
1425
  }
1278
- return result;
1279
- }
1280
- __name(setupGithub, "setupGithub");
1281
- async function updateGitignore(gitRepoRoot, fileOps = nodeFileOps) {
1282
- try {
1283
- const existingContent = await fileOps.readTextFile(
1284
- gitRepoRoot,
1285
- ".gitignore"
1286
- );
1287
- if (existingContent === void 0) {
1288
- const content = GITIGNORE_ENTRIES.join("\n") + "\n";
1289
- await fileOps.writeTextFile(gitRepoRoot, ".gitignore", content);
1290
- return {
1291
- path: ".gitignore",
1292
- status: "created",
1293
- added: [...GITIGNORE_ENTRIES]
1294
- };
1426
+ /**
1427
+ * Emits token usage from a AgentResultDisplay execution summary, if present.
1428
+ */
1429
+ async emitTaskUsageFromResultDisplay(resultDisplay) {
1430
+ const summary = resultDisplay.executionSummary;
1431
+ if (!summary) {
1432
+ return;
1295
1433
  }
1296
- const missingEntries = GITIGNORE_ENTRIES.filter(
1297
- (entry) => !existingContent.split(/\r?\n/).some((line) => line.split("#")[0].trim() === entry)
1298
- );
1299
- if (missingEntries.length === 0) {
1300
- return { path: ".gitignore", status: "unchanged" };
1434
+ const usageMetadata = {};
1435
+ if (Number.isFinite(summary.inputTokens)) {
1436
+ usageMetadata.promptTokenCount = summary.inputTokens;
1301
1437
  }
1302
- const nextContent = existingContent + "\n" + missingEntries.join("\n") + "\n";
1303
- await fileOps.writeTextFile(gitRepoRoot, ".gitignore", nextContent);
1304
- return {
1305
- path: ".gitignore",
1306
- status: "updated",
1307
- added: missingEntries
1308
- };
1309
- } catch (error) {
1310
- debugLogger2.debug("Failed to update .gitignore:", error);
1311
- return {
1312
- path: ".gitignore",
1313
- status: "failed",
1314
- error: error instanceof Error ? error.message : String(error)
1315
- };
1316
- }
1317
- }
1318
- __name(updateGitignore, "updateGitignore");
1319
- async function downloadWorkflows(options) {
1320
- const internalAbort = new AbortController();
1321
- try {
1322
- const dispatcher = options.proxy ? new import_undici2.ProxyAgent(options.proxy) : void 0;
1323
- return await Promise.all(
1324
- GITHUB_WORKFLOW_PATHS.map(async (workflow) => {
1325
- const endpoint = `https://raw.githubusercontent.com/QwenLM/qwen-code-action/refs/tags/${options.releaseTag}/examples/workflows/${workflow}`;
1326
- const response = await options.fetchImpl(endpoint, {
1327
- method: "GET",
1328
- dispatcher,
1329
- signal: AbortSignal.any([
1330
- AbortSignal.timeout(3e4),
1331
- internalAbort.signal,
1332
- ...options.abortSignal ? [options.abortSignal] : []
1333
- ])
1334
- });
1335
- if (!response.ok) {
1336
- throw new Error(
1337
- `Invalid response code downloading ${endpoint}: ${response.status} - ${response.statusText}`
1338
- );
1339
- }
1340
- return {
1341
- sourcePath: workflow,
1342
- content: await readResponseTextWithLimit(response, workflow)
1343
- };
1344
- })
1345
- );
1346
- } catch (error) {
1347
- internalAbort.abort();
1348
- const message = error instanceof Error ? error.message : String(error);
1349
- debugLogger2.debug("Failed to download qwen-code-action workflows:", error);
1350
- throw new SetupGithubError(
1351
- "github_workflow_download_failed",
1352
- `Unable to download qwen-code-action workflows from GitHub. ${message}`,
1353
- 502
1354
- );
1355
- }
1356
- }
1357
- __name(downloadWorkflows, "downloadWorkflows");
1358
- async function readResponseTextWithLimit(response, sourcePath) {
1359
- const contentLength = response.headers.get("content-length");
1360
- if (contentLength !== null) {
1361
- const parsedLength = Number(contentLength);
1362
- if (Number.isFinite(parsedLength) && parsedLength > MAX_WORKFLOW_DOWNLOAD_BYTES) {
1363
- throw new Error(
1364
- `${sourcePath} exceeds download limit of ${MAX_WORKFLOW_DOWNLOAD_BYTES} bytes`
1365
- );
1438
+ if (Number.isFinite(summary.outputTokens)) {
1439
+ usageMetadata.candidatesTokenCount = summary.outputTokens;
1440
+ }
1441
+ if (Number.isFinite(summary.thoughtTokens)) {
1442
+ usageMetadata.thoughtsTokenCount = summary.thoughtTokens;
1443
+ }
1444
+ if (Number.isFinite(summary.cachedTokens)) {
1445
+ usageMetadata.cachedContentTokenCount = summary.cachedTokens;
1446
+ }
1447
+ if (Number.isFinite(summary.totalTokens)) {
1448
+ usageMetadata.totalTokenCount = summary.totalTokens;
1449
+ }
1450
+ if (Object.keys(usageMetadata).length > 0) {
1451
+ await this.messageEmitter.emitUsageMetadata(usageMetadata);
1366
1452
  }
1367
1453
  }
1368
- if (!response.body) return "";
1369
- const reader = response.body.getReader();
1370
- const chunks = [];
1371
- let totalBytes = 0;
1372
- try {
1373
- while (true) {
1374
- const { done, value } = await reader.read();
1375
- if (done) break;
1376
- if (!value) continue;
1377
- totalBytes += value.byteLength;
1378
- if (totalBytes > MAX_WORKFLOW_DOWNLOAD_BYTES) {
1379
- await reader.cancel().catch(() => {
1380
- });
1381
- throw new Error(
1382
- `${sourcePath} exceeds download limit of ${MAX_WORKFLOW_DOWNLOAD_BYTES} bytes`
1454
+ /**
1455
+ * Replays a slash_command system record by re-emitting its output as an
1456
+ * agent message chunk. This allows Zed to reconstruct the correct turn
1457
+ * structure (user → agent) on session resume without polluting model context.
1458
+ */
1459
+ async replaySlashCommandResult(record) {
1460
+ const payload = record.systemPayload;
1461
+ if (payload?.phase !== "result" || !payload.outputHistoryItems?.length) {
1462
+ return;
1463
+ }
1464
+ for (const item of payload.outputHistoryItems) {
1465
+ const text = typeof item["text"] === "string" ? item["text"] : "";
1466
+ if (text) {
1467
+ await this.messageEmitter.emitSlashCommandOutput(
1468
+ text.replace(/\n/g, " \n"),
1469
+ record.timestamp
1383
1470
  );
1384
1471
  }
1385
- chunks.push(value);
1386
1472
  }
1387
- } finally {
1388
- reader.releaseLock();
1389
- }
1390
- const body = new Uint8Array(totalBytes);
1391
- let offset = 0;
1392
- for (const chunk of chunks) {
1393
- body.set(chunk, offset);
1394
- offset += chunk.byteLength;
1395
1473
  }
1396
- return new TextDecoder().decode(body);
1397
- }
1398
- __name(readResponseTextWithLimit, "readResponseTextWithLimit");
1399
- async function resolveSecretsUrl(cwd) {
1400
- try {
1401
- const repoInfo = await getGitHubRepoInfoAsync({ cwd });
1402
- return `https://github.com/${repoInfo.owner}/${repoInfo.repo}/settings/secrets/actions`;
1403
- } catch {
1404
- return void 0;
1474
+ /**
1475
+ * Extracts tool name from a chat record's function response.
1476
+ */
1477
+ extractToolNameFromRecord(record) {
1478
+ if (record.message?.parts) {
1479
+ for (const part of record.message.parts) {
1480
+ if ("functionResponse" in part && part.functionResponse?.name) {
1481
+ return part.functionResponse.name;
1482
+ }
1483
+ }
1484
+ }
1485
+ return "";
1405
1486
  }
1406
- }
1407
- __name(resolveSecretsUrl, "resolveSecretsUrl");
1408
- async function realpathOrResolve(input) {
1409
- try {
1410
- return await fsp.realpath(input);
1411
- } catch {
1412
- return path.resolve(input);
1487
+ setActiveRecordId(recordId, timestamp) {
1488
+ const context = this.ctx;
1489
+ if (typeof context.setActiveRecordId === "function") {
1490
+ context.setActiveRecordId(recordId, timestamp);
1491
+ }
1413
1492
  }
1414
- }
1415
- __name(realpathOrResolve, "realpathOrResolve");
1493
+ };
1416
1494
 
1417
1495
  // packages/cli/src/ui/utils/export/collect.ts
1418
1496
  init_esbuild_shims();
@@ -1603,7 +1681,7 @@ async function extractMetadata(conversation, config) {
1603
1681
  const gitBranch = firstRecord?.gitBranch;
1604
1682
  let gitRepo;
1605
1683
  if (cwd) {
1606
- const { getGitRepoName } = await import("./src-BBQSM46M.js");
1684
+ const { getGitRepoName } = await import("./src-YDBNMIIM.js");
1607
1685
  gitRepo = getGitRepoName(cwd);
1608
1686
  }
1609
1687
  let model;
@@ -2448,7 +2526,7 @@ export {
2448
2526
  };
2449
2527
  /**
2450
2528
  * @license
2451
- * Copyright 2025 Qwen
2529
+ * Copyright 2025 Google LLC
2452
2530
  * SPDX-License-Identifier: Apache-2.0
2453
2531
  */
2454
2532
  /**
@@ -2458,7 +2536,7 @@ export {
2458
2536
  */
2459
2537
  /**
2460
2538
  * @license
2461
- * Copyright 2025 Google LLC
2539
+ * Copyright 2025 Qwen
2462
2540
  * SPDX-License-Identifier: Apache-2.0
2463
2541
  */
2464
2542
  /**