@qwen-code/qwen-code 0.19.8 → 0.19.9-nightly.20260714.9dd8389eb

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 (449) 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 +61 -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/tool-use-summaries.md +19 -23
  14. package/bundled/qc-helper/docs/integration-vscode.md +2 -2
  15. package/bundled/qc-helper/docs/qwen-serve.md +60 -22
  16. package/bundled/qc-helper/docs/reference/keyboard-shortcuts.md +2 -2
  17. package/bundled/review/DESIGN.md +303 -46
  18. package/bundled/review/SKILL.md +658 -165
  19. package/chunks/MaxSizedBox-QAYHOC4F.js +71 -0
  20. package/chunks/{StandaloneSessionPicker-EYRGH6PJ.js → StandaloneSessionPicker-D3R6YYX3.js} +82 -79
  21. package/chunks/{acpAgent-GRFTTRHW.js → acpAgent-ENHBW72A.js} +1178 -421
  22. package/chunks/agent-57LX4KMG.js +69 -0
  23. package/chunks/agent-headless-AC6EVNAP.js +63 -0
  24. package/chunks/{anthropicContentGenerator-CPF22MA7.js → anthropicContentGenerator-56U3YCP2.js} +187 -31
  25. package/chunks/{artifact-tool-D233YJFH.js → artifact-tool-BWZZJ42H.js} +5 -5
  26. package/chunks/{askUserQuestion-MKL5ZTMC.js → askUserQuestion-WU3S5A5T.js} +6 -6
  27. package/chunks/bridge-4OZH44MK.js +79 -0
  28. package/chunks/{ca-MKD32FQL.js → ca-C2JTT2N5.js} +68 -6
  29. package/chunks/channel-worker-group-K7QKH6IG.js +13 -0
  30. package/chunks/channel-worker-manager-5RWKSGEU.js +418 -0
  31. package/chunks/channel-worker-supervisor-PCDAZN4D.js +20 -0
  32. package/chunks/{chunk-CSOTA7KX.js → chunk-2FO5GFKZ.js} +2 -2
  33. package/chunks/{chunk-QQDPRDVW.js → chunk-2HRYPZT5.js} +1 -1
  34. package/chunks/{chunk-I6WGFJJ3.js → chunk-2MF6ICOL.js} +38 -12
  35. package/chunks/{chunk-X3YGAX7V.js → chunk-2UUAIFQO.js} +4 -2
  36. package/chunks/{chunk-2PSWA5ID.js → chunk-2X56YUSZ.js} +1 -1
  37. package/chunks/{chunk-NQKLOAVJ.js → chunk-2Z5UX4KI.js} +2 -2
  38. package/chunks/chunk-3MX7D6QN.js +516 -0
  39. package/chunks/{chunk-YDOXPLYL.js → chunk-4DYYRLIE.js} +3890 -975
  40. package/chunks/{chunk-OQXDAMKY.js → chunk-4FPUAYTT.js} +8 -8
  41. package/chunks/{chunk-55ZMG67I.js → chunk-4LD5APFL.js} +4 -4
  42. package/chunks/{chunk-YKZIAK7C.js → chunk-4LJNI7MU.js} +166 -37
  43. package/chunks/{chunk-BOBOCR5H.js → chunk-4QOPEEL2.js} +4 -4
  44. package/chunks/{chunk-UIDXQNMV.js → chunk-4WGODMVR.js} +1 -1
  45. package/chunks/{chunk-E6US47KI.js → chunk-4WKAA4KS.js} +1 -1
  46. package/chunks/{chunk-3GONHQOA.js → chunk-57OAHC2Y.js} +1 -1
  47. package/chunks/{chunk-JZSY4WP3.js → chunk-5DTTYNB7.js} +1 -1
  48. package/chunks/chunk-5HBA2Z7V.js +28 -0
  49. package/chunks/{chunk-SKAZWEV5.js → chunk-5M6IDOMF.js} +35 -98
  50. package/chunks/{chunk-A4BMJM77.js → chunk-5O2XNYP6.js} +1 -0
  51. package/chunks/{chunk-GO6LNQXT.js → chunk-6AM5D4ME.js} +1 -1
  52. package/chunks/{chunk-BJBWRCSK.js → chunk-6H67XLET.js} +1 -1
  53. package/chunks/{chunk-AYNCLGTW.js → chunk-6HHAADP2.js} +8 -51
  54. package/chunks/{chunk-VZ7HY3YU.js → chunk-6OATMEYN.js} +3 -3
  55. package/chunks/{chunk-3UP777ZS.js → chunk-6RLROE6G.js} +1 -1
  56. package/chunks/{chunk-ZERZSAZL.js → chunk-75DOP5OR.js} +2 -2
  57. package/chunks/{chunk-RMLZAUWH.js → chunk-7BIZARI2.js} +10 -12
  58. package/chunks/{chunk-GN3F6PIU.js → chunk-7NAWTFVY.js} +5 -5
  59. package/chunks/{chunk-22MNNNXE.js → chunk-7NFB7LBQ.js} +11 -3
  60. package/chunks/{chunk-ZL5HN75Q.js → chunk-7R4DPSRA.js} +37 -3
  61. package/chunks/{chunk-BVYU3ZTI.js → chunk-7U7UIO5W.js} +1005 -942
  62. package/chunks/{chunk-SAIILPQ3.js → chunk-7X7TEQNX.js} +5 -3
  63. package/chunks/{chunk-IRJWHZWU.js → chunk-A4UCTEB5.js} +2 -2
  64. package/chunks/{chunk-WF4FAXDL.js → chunk-AAS2Q2TV.js} +62 -62
  65. package/chunks/{chunk-O7FIRWJV.js → chunk-AAWKZ5R7.js} +3 -3
  66. package/chunks/{chunk-JCH35JB3.js → chunk-AGBFWLA5.js} +2 -2
  67. package/chunks/{chunk-QYUE6W3T.js → chunk-ALGGS7UH.js} +2 -39
  68. package/chunks/{chunk-WMPVYQ4P.js → chunk-ARKANCNX.js} +3 -2
  69. package/chunks/{chunk-HDOH3QYE.js → chunk-ASVORVFT.js} +2 -2
  70. package/chunks/{chunk-CHB5SLZZ.js → chunk-AUGSSJX3.js} +3 -3
  71. package/chunks/{chunk-PUVCVELY.js → chunk-B6ABUBYY.js} +4 -4
  72. package/chunks/{chunk-L4AMBVQG.js → chunk-B6KHOCU7.js} +49 -21
  73. package/chunks/{chunk-HW4N45EE.js → chunk-B7NUUEXC.js} +38 -11
  74. package/chunks/{chunk-CD6USWHZ.js → chunk-BBNVFRGD.js} +2 -2
  75. package/chunks/{chunk-ZN5T4BHI.js → chunk-BPZALHVR.js} +2 -2
  76. package/chunks/{chunk-VGGOPZUL.js → chunk-C4CXFRKY.js} +12 -5
  77. package/chunks/{chunk-OFEVLU4C.js → chunk-CARU2RR2.js} +1 -1
  78. package/chunks/{chunk-SQ2UATK7.js → chunk-CLTWL6HD.js} +11 -11
  79. package/chunks/{chunk-GLE2YUPU.js → chunk-COH43MRJ.js} +1 -1
  80. package/chunks/{chunk-E5A7LHNN.js → chunk-CPBF7KYF.js} +1 -1
  81. package/chunks/{chunk-UWCTAVOD.js → chunk-CR3C7WXL.js} +1 -1
  82. package/chunks/{chunk-DIWVZ3VM.js → chunk-CSACSGAW.js} +5 -5
  83. package/chunks/{chunk-5P5XGNYH.js → chunk-CU3L64TP.js} +1 -1
  84. package/chunks/{chunk-IWKSG2AR.js → chunk-CXAOG665.js} +1 -1
  85. package/chunks/{chunk-64WXLC72.js → chunk-DJ2GSRLV.js} +1 -1
  86. package/chunks/chunk-DKXW66XA.js +38 -0
  87. package/chunks/{chunk-QN5NZ3UQ.js → chunk-DMTGGOSA.js} +2 -2
  88. package/chunks/{chunk-JZHIQJOE.js → chunk-DMTQY5GY.js} +6 -6
  89. package/chunks/{chunk-GSHQYYIV.js → chunk-DNKX35GS.js} +6 -26
  90. package/chunks/{chunk-6IAWPIQ6.js → chunk-DPSWJWZI.js} +4 -3
  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-3B26UVCX.js → chunk-E67NFMF4.js} +39 -10
  94. package/chunks/{chunk-ON3JA3RU.js → chunk-EU3U7USF.js} +7 -9
  95. package/chunks/{chunk-L46XKEGM.js → chunk-EUNRLYJG.js} +5 -8
  96. package/chunks/{chunk-OACJLMLD.js → chunk-FBU7WRZI.js} +18 -2
  97. package/chunks/{chunk-5IFG2VC4.js → chunk-FCMNKVXT.js} +1 -1
  98. package/chunks/{chunk-A5JOJ77H.js → chunk-FDL4PB5H.js} +38 -15
  99. package/chunks/{chunk-E7KNELIZ.js → chunk-FSA7ERJ2.js} +2 -2
  100. package/chunks/{chunk-TI3BWD4D.js → chunk-G6QTKQN4.js} +39 -19
  101. package/chunks/{chunk-44NROQYV.js → chunk-GDQQRV43.js} +4 -4
  102. package/chunks/{chunk-O2YT7VB4.js → chunk-GOXKNSDZ.js} +2 -65
  103. package/chunks/{chunk-V35MD7KN.js → chunk-GRC5HGPI.js} +1 -1
  104. package/chunks/chunk-GYGGUR4Q.js +253 -0
  105. package/chunks/{chunk-S6RLAIUR.js → chunk-GYTKQYDB.js} +1 -1
  106. package/chunks/{chunk-A2X3KLC3.js → chunk-GZXCZHCT.js} +3 -3
  107. package/chunks/{chunk-K5PGHDBN.js → chunk-H6XPXXMH.js} +1 -1
  108. package/chunks/{chunk-E7EMCSUG.js → chunk-HE54PGVI.js} +64 -42
  109. package/chunks/{chunk-KYMBIKIW.js → chunk-HTHUX2T5.js} +1 -1
  110. package/chunks/{chunk-LQ7TMOCE.js → chunk-HTO4JFDZ.js} +1 -1
  111. package/chunks/chunk-HZYUNZDQ.js +296 -0
  112. package/chunks/chunk-IDS7MSUP.js +74 -0
  113. package/chunks/chunk-J2TDDOSM.js +493 -0
  114. package/chunks/{chunk-4CGOWHKM.js → chunk-J4MOFEOK.js} +2 -2
  115. package/chunks/{chunk-22IFUCVR.js → chunk-JESCGQM3.js} +1 -1
  116. package/chunks/chunk-JR63TOV4.js +91 -0
  117. package/chunks/chunk-K3PPUB46.js +445 -0
  118. package/chunks/{chunk-42XGFRJS.js → chunk-KKRTYONM.js} +8 -6
  119. package/chunks/{chunk-GGQQA4JW.js → chunk-KSO42X3Z.js} +15 -2
  120. package/chunks/{chunk-MRO43B25.js → chunk-KW7NOTN6.js} +1 -1
  121. package/chunks/{chunk-54YZOP7P.js → chunk-L573Z2QZ.js} +11894 -5190
  122. package/chunks/{chunk-TLWA7TPR.js → chunk-L5U3ELZX.js} +2 -2
  123. package/chunks/{chunk-WHJQ3JUS.js → chunk-LAM6CGP5.js} +10 -10
  124. package/chunks/{chunk-H6EMK6QK.js → chunk-LQIDP6K5.js} +11913 -5207
  125. package/chunks/{chunk-MZ7BABX3.js → chunk-LXLTBIDP.js} +44 -7
  126. package/chunks/{chunk-HLKG6CZN.js → chunk-M5GB774H.js} +1 -1
  127. package/chunks/{chunk-EEN2TKST.js → chunk-MBJ3D6SF.js} +2 -2
  128. package/chunks/{chunk-PMFULMLX.js → chunk-MBP3K324.js} +2234 -377
  129. package/chunks/chunk-MR3PXB6E.js +48 -0
  130. package/chunks/{chunk-ZE6E424U.js → chunk-N7FCSERB.js} +2 -2
  131. package/chunks/{chunk-332PWN27.js → chunk-NHDKSOEY.js} +1 -1
  132. package/chunks/chunk-OATTJGPJ.js +448 -0
  133. package/chunks/{chunk-UX6OTBVD.js → chunk-OCC3UTWA.js} +2 -2
  134. package/chunks/{chunk-P7M4GA57.js → chunk-OCPBI7J5.js} +1 -1
  135. package/chunks/chunk-OJAMDVF5.js +66 -0
  136. package/chunks/{chunk-IJRL2S3D.js → chunk-OKAIGAYW.js} +6 -6
  137. package/chunks/{chunk-WQTHLB5T.js → chunk-P3S67A5R.js} +7 -7
  138. package/chunks/{chunk-FBET5XZ2.js → chunk-PEJWA3QQ.js} +29 -10
  139. package/chunks/{chunk-J7RCB6N5.js → chunk-PHYCWSDG.js} +2 -2
  140. package/chunks/{chunk-LAXNEOBG.js → chunk-PMRH4YYW.js} +18 -3
  141. package/chunks/{chunk-AGHU5VRK.js → chunk-PZL23GTM.js} +1 -1
  142. package/chunks/{chunk-PC4ZXHU2.js → chunk-Q6TUALBE.js} +3 -3
  143. package/chunks/{chunk-FXGLL2HL.js → chunk-Q7YDKOGY.js} +1 -1
  144. package/chunks/{chunk-P3XEEI3X.js → chunk-QABSSDQH.js} +36 -7
  145. package/chunks/{chunk-XOHNA2S6.js → chunk-QAW7PIHT.js} +3 -3
  146. package/chunks/{chunk-LGFAYIKX.js → chunk-QHTIBUWB.js} +1 -1
  147. package/chunks/{chunk-P3MYAZBY.js → chunk-QMGX2KO2.js} +1 -1
  148. package/chunks/{chunk-Z3I3QJK3.js → chunk-QRUIS3DN.js} +1 -1
  149. package/chunks/{chunk-ITOGNELQ.js → chunk-QSWDGAIC.js} +2 -2
  150. package/chunks/{chunk-GHOTR7HL.js → chunk-QUPXZXLV.js} +1 -1
  151. package/chunks/{chunk-W7EEOR7D.js → chunk-RCEEXIOO.js} +8 -6
  152. package/chunks/{chunk-2EM7ECZD.js → chunk-RJL5T4WJ.js} +281 -65
  153. package/chunks/{chunk-TLRYABYP.js → chunk-RKUWKYED.js} +1 -1
  154. package/chunks/{chunk-RNBYOUGV.js → chunk-RXFQM6FQ.js} +1 -1
  155. package/chunks/{chunk-JRQ7EVGE.js → chunk-S2QXYLUB.js} +2 -2
  156. package/chunks/{chunk-QXPI7FEC.js → chunk-S3TWXGKA.js} +4 -4
  157. package/chunks/{chunk-O33TBKDC.js → chunk-SE74CIZD.js} +155 -19
  158. package/chunks/{chunk-FV7425LN.js → chunk-SPJQO2CE.js} +18 -5
  159. package/chunks/{chunk-3GNOQZDC.js → chunk-SSFDPGFN.js} +11866 -11542
  160. package/chunks/{chunk-DCZWC4PF.js → chunk-SUWGUGAD.js} +5 -5
  161. package/chunks/{chunk-IBY3Q3HG.js → chunk-SXU3KKNI.js} +963 -181
  162. package/chunks/{chunk-MLZQVCF3.js → chunk-SZRN75WQ.js} +1 -1
  163. package/chunks/{chunk-M7S4GK5Z.js → chunk-T2L6SGQY.js} +115 -29
  164. package/chunks/{chunk-7RYW5LQV.js → chunk-T2NCM2ET.js} +2 -2
  165. package/chunks/{chunk-JPALE3PA.js → chunk-T5C2OUCI.js} +6 -6
  166. package/chunks/{chunk-BUZ6HGL4.js → chunk-T7FSRWQ5.js} +248 -55
  167. package/chunks/{chunk-Z2Z3GUXZ.js → chunk-TB6UDU4T.js} +1 -1
  168. package/chunks/{chunk-EXPMGZZV.js → chunk-TEGEBB2I.js} +1 -1
  169. package/chunks/{chunk-MX2YXRER.js → chunk-TJTKSVIV.js} +1 -1
  170. package/chunks/{chunk-CCGOFQV3.js → chunk-TQBODCFD.js} +8 -7
  171. package/chunks/chunk-TV6K2FB4.js +224 -0
  172. package/chunks/{chunk-5MBO76SL.js → chunk-TXY2C3D2.js} +3 -3
  173. package/chunks/{chunk-H6BD2ELD.js → chunk-TYAMGABM.js} +2 -2
  174. package/chunks/{chunk-QYNNN7BK.js → chunk-TYLOFD2U.js} +2 -2
  175. package/chunks/{chunk-VRDMOSQS.js → chunk-UDXSXLER.js} +2 -2
  176. package/chunks/{chunk-UXEW557D.js → chunk-UI3W56WF.js} +3 -3
  177. package/chunks/{chunk-CJCKDMWO.js → chunk-URK542T4.js} +1 -1
  178. package/chunks/{channel-worker-supervisor-NZQUOEFJ.js → chunk-URU5UEK6.js} +190 -34
  179. package/chunks/{chunk-AHNXYU4O.js → chunk-V6WHFGST.js} +1 -1
  180. package/chunks/chunk-V75IOTWF.js +71 -0
  181. package/chunks/{chunk-ZTQ26VBE.js → chunk-VDDGDZMA.js} +1 -1
  182. package/chunks/{chunk-OMX7CUOE.js → chunk-VGC4I5JJ.js} +1 -1
  183. package/chunks/{chunk-43W4YSO6.js → chunk-VJNBRRZG.js} +2 -2
  184. package/chunks/{chunk-ER3BKOLB.js → chunk-W7FJ3N32.js} +1 -1
  185. package/chunks/{chunk-3HX5LZ6R.js → chunk-WBL3FJEU.js} +2 -2
  186. package/chunks/{chunk-7LTB54MK.js → chunk-WIEO4CWB.js} +2 -2
  187. package/chunks/{chunk-BMFMJINR.js → chunk-WL4L7EZH.js} +1 -1
  188. package/chunks/{chunk-6VK6FIMQ.js → chunk-WM5HY72H.js} +415 -379
  189. package/chunks/{chunk-BOBRZZKD.js → chunk-WN4D7YCI.js} +5 -5
  190. package/chunks/{chunk-DHOLNQLC.js → chunk-WWQ3QIJS.js} +60 -40
  191. package/chunks/{chunk-FEJ2FZ3U.js → chunk-WX6SD4IQ.js} +2 -2
  192. package/chunks/{chunk-DICGXFAI.js → chunk-X7EBAABW.js} +11 -9
  193. package/chunks/{chunk-3RW4AZJV.js → chunk-XFSFZCM5.js} +1 -1
  194. package/chunks/{chunk-YHKAK72D.js → chunk-XHW5VUIQ.js} +102 -16
  195. package/chunks/{chunk-2MPVVENX.js → chunk-XU457J4V.js} +2 -2
  196. package/chunks/{chunk-SIUQ3YYX.js → chunk-XVNQMZ2I.js} +1 -1
  197. package/chunks/{chunk-SYCJMSIJ.js → chunk-XWRJCPHC.js} +1 -1
  198. package/chunks/{chunk-SUAKHHK7.js → chunk-Y66VOBRP.js} +3 -3
  199. package/chunks/chunk-YAF2MQZ6.js +19 -0
  200. package/chunks/{chunk-FQNC62B2.js → chunk-YH4J5XI3.js} +11 -11
  201. package/chunks/chunk-YHN5SUIJ.js +219 -0
  202. package/chunks/{chunk-BR4QREVK.js → chunk-YQ3U5MUC.js} +1 -1
  203. package/chunks/{chunk-Y6Z2O3WR.js → chunk-YUZI3WAC.js} +1 -1
  204. package/chunks/{chunk-II73RK2S.js → chunk-YVEDCAUE.js} +1 -1
  205. package/chunks/{chunk-XYR5RUA5.js → chunk-YWUK7OS7.js} +10 -3
  206. package/chunks/{chunk-27BHARDE.js → chunk-Z56JO4JZ.js} +2124 -30
  207. package/chunks/{chunk-TSPB77TG.js → chunk-ZLM3KXBT.js} +1015 -2967
  208. package/chunks/{chunk-AHNJGLFV.js → chunk-ZPAHLFZU.js} +3 -3
  209. package/chunks/chunk-ZRKBI3DP.js +34 -0
  210. package/chunks/cli-entry-path-4VJ3Y6T2.js +10 -0
  211. package/chunks/{computer-use-WMY3UOBX.js → computer-use-DIP5BWXP.js} +51 -50
  212. package/chunks/config-utils-CFT33LTP.js +24 -0
  213. package/chunks/contextCommand-QU4GJWWD.js +69 -0
  214. package/chunks/create-sub-session-TCLIYVGR.js +376 -0
  215. package/chunks/create-sub-session-WNX2OQVX.js +207 -0
  216. package/chunks/{cron-create-JSXEIPVS.js → cron-create-36TIFKRT.js} +9 -9
  217. package/chunks/{cron-delete-OIFVEPGU.js → cron-delete-OQD3WULU.js} +7 -7
  218. package/chunks/{cron-list-D4ZX4IOE.js → cron-list-4533T2FH.js} +14 -10
  219. package/chunks/{daemon-WPAENEBW.js → daemon-CEZ27OH4.js} +734 -24
  220. package/chunks/daemon-status-provider-SIBFMLBQ.js +77 -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-E6UANPIM.js → dist-3V3ZV6ML.js} +1011 -197
  224. package/chunks/{dist-SCFLLYMK.js → dist-ERCPDVA6.js} +12 -11
  225. package/chunks/{dist-Z34QPAQW.js → dist-HNN7DR2L.js} +529 -79
  226. package/chunks/{dist-O2IRTRPP.js → dist-JZE7F6YR.js} +10 -10
  227. package/chunks/{dist-BEXOZXLQ.js → dist-MOEC47TR.js} +36 -15
  228. package/chunks/{dist-H2AEJCZ5.js → dist-PHEPJLXD.js} +5 -5
  229. package/chunks/{dist-63IS3ZMI.js → dist-PZV5RKM6.js} +4 -4
  230. package/chunks/earlyInputCapture-L66BEG2C.js +70 -0
  231. package/chunks/{edit-OTYWAXGP.js → edit-Y5LAJSST.js} +52 -51
  232. package/chunks/{en-N4EPZAQI.js → en-NJCA3TAA.js} +78 -6
  233. package/chunks/{enter-worktree-HNYBDVCX.js → enter-worktree-X5LML7T4.js} +51 -50
  234. package/chunks/{enterPlanMode-CJCNGT63.js → enterPlanMode-XWF32QOW.js} +67 -51
  235. package/chunks/environment-YVMA5F4I.js +90 -0
  236. package/chunks/errors-4Y5SUAOC.js +76 -0
  237. package/chunks/{exit-worktree-DUUKOE3X.js → exit-worktree-SFHU7XYC.js} +51 -50
  238. package/chunks/{exitPlanMode-AMMSXOAJ.js → exitPlanMode-FP3NAN6E.js} +52 -51
  239. package/chunks/{fast-path-OV6NIP3K.js → fast-path-ZJNFFCBM.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-5CAB22BI.js} +122 -109
  244. package/chunks/{geminiContentGenerator-CDUNEJQE.js → geminiContentGenerator-GE3HPIFB.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-YPACZAEL.js} +98 -75
  251. package/chunks/{grep-NRITKDCD.js → grep-IPR4XW37.js} +51 -50
  252. package/chunks/handleAutoUpdate-P2KEP56V.js +70 -0
  253. package/chunks/i18n-BRCT66AA.js +85 -0
  254. package/chunks/initializer-34HXSK3A.js +74 -0
  255. package/chunks/installationInfo-WOTDQMSC.js +66 -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-XOGP7UPP.js +77 -0
  260. package/chunks/loadedSettingsAdapter-L4YKGU6F.js +71 -0
  261. package/chunks/{loop-wakeup-OHWEMFP5.js → loop-wakeup-MVUKDVCP.js} +10 -10
  262. package/chunks/{lowlight-FYAAUU5J.js → lowlight-J2OZNPCA.js} +1 -1
  263. package/chunks/{ls-7MFU2QYW.js → ls-RXNIAQDE.js} +6 -6
  264. package/chunks/{lsp-XHDTPTGV.js → lsp-HB5LM5IL.js} +4 -4
  265. package/chunks/mcp-HH7DIP7Y.js +71 -0
  266. package/chunks/{monitor-FL2ZO33W.js → monitor-25DEBT6U.js} +51 -50
  267. package/chunks/{multipart-parser-AJ4WASWR.js → multipart-parser-AWZKXSQN.js} +3 -3
  268. package/chunks/nonInteractiveCli-CT3VSSLK.js +130 -0
  269. package/chunks/{notebook-edit-6PULTHL5.js → notebook-edit-TAVXSWQ6.js} +52 -51
  270. package/chunks/openaiContentGenerator-6I7DKUAN.js +56 -0
  271. package/chunks/pidfile-SIQGCFLZ.js +74 -0
  272. package/chunks/{pt-OLYN42DS.js → pt-TFZO5Y6T.js} +68 -6
  273. package/chunks/{qwenContentGenerator-NX2E7PB7.js → qwenContentGenerator-5DDIXI2N.js} +53 -52
  274. package/chunks/{qwenOAuth2-ZV7YLMND.js → qwenOAuth2-LEYOU7RU.js} +9 -9
  275. package/chunks/read-file-WDOAYRFU.js +30 -0
  276. package/chunks/{read-mcp-resource-CNQHBSJM.js → read-mcp-resource-6LRTZKXI.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-PMDTY4OS.js} +4 -4
  279. package/chunks/ripGrep-MI7PHN3Q.js +61 -0
  280. package/chunks/{ru-LDM3GWVQ.js → ru-4L4LFHIT.js} +68 -6
  281. package/chunks/{run-qwen-serve-JK2DL7PI.js → run-qwen-serve-PNTYF3RE.js} +1289 -256
  282. package/chunks/runtime-V3FBMUTG.js +100 -0
  283. package/chunks/{scheduler-O4IGVZKK.js → scheduler-4TAUIJBM.js} +52 -51
  284. package/chunks/{send-message-76GT3JMC.js → send-message-SR4WSXP2.js} +7 -7
  285. package/chunks/serve-WB2TR7XM.js +77 -0
  286. package/chunks/{server-SGNPKX2O.js → server-AF6LNFPK.js} +8094 -2800
  287. package/chunks/{session-5BNM25EZ.js → session-BIGK4NRW.js} +341 -135
  288. package/chunks/settings-IXF5FIQO.js +121 -0
  289. package/chunks/shell-5VWJ2PPG.js +69 -0
  290. package/chunks/{skill-I22QK5XS.js → skill-SI667Y3B.js} +24 -24
  291. package/chunks/spawnChannel-IKX6DD7J.js +71 -0
  292. package/chunks/{src-BBQSM46M.js → src-55DZWDAK.js} +151 -52
  293. package/chunks/{src-7XL4G4DC.js → src-VLI3TKEY.js} +4 -4
  294. package/chunks/standalone-update-MHLSFHE6.js +80 -0
  295. package/chunks/{startInteractiveUI-JII36UGN.js → startInteractiveUI-V2EDWLAX.js} +2239 -1846
  296. package/chunks/stdioHelpers-UMY72QRP.js +14 -0
  297. package/chunks/{syntheticOutput-F7LSDCAR.js → syntheticOutput-YKFNUQZD.js} +5 -5
  298. package/chunks/task-create-NUFOHU53.js +23 -0
  299. package/chunks/{task-list-TGGJX7EA.js → task-list-Z2IKQY3S.js} +11 -10
  300. package/chunks/{task-stop-W7NGTMYQ.js → task-stop-KQFIVQTJ.js} +4 -4
  301. package/chunks/{task-update-XYWMHJGJ.js → task-update-HKADXSTD.js} +13 -12
  302. package/chunks/{team-create-A7NUU5AQ.js → team-create-IZAMLBJS.js} +51 -50
  303. package/chunks/{team-delete-UHQQ2QQX.js → team-delete-SDNTGZLG.js} +11 -10
  304. package/chunks/{team-plan-approval-TOQRJ2KI.js → team-plan-approval-3R4RCKCP.js} +51 -50
  305. package/chunks/theme-manager-LCOXZ5DO.js +65 -0
  306. package/chunks/{todoWrite-C4ZAMSR3.js → todoWrite-YNXB27GB.js} +6 -6
  307. package/chunks/{tool-search-SZ4EFS2T.js → tool-search-NYNCD5LF.js} +24 -24
  308. package/chunks/total-session-admission-PJWGOMQE.js +73 -0
  309. package/chunks/tree-sitter-YJVE2ZUK.js +2980 -0
  310. package/chunks/trustedFolders-DOJDHNYP.js +81 -0
  311. package/chunks/{types-QX5C3CHJ.js → types-JNKGKUJT.js} +2 -2
  312. package/chunks/updateCheck-ZXL66KIG.js +70 -0
  313. package/chunks/updateEventEmitter-5MKC7BLQ.js +10 -0
  314. package/chunks/validateNonInterActiveAuth-JSNJZCYY.js +195 -0
  315. package/chunks/{version-NO2XSNNP.js → version-3NLBENG5.js} +3 -3
  316. package/chunks/{web-fetch-UYGMOHW4.js → web-fetch-ZSPR3PRR.js} +8 -8
  317. package/chunks/{workflow-WO2H6NRI.js → workflow-BQYLF7XP.js} +52 -51
  318. package/chunks/workspace-providers-status-FA2DGEZW.js +74 -0
  319. package/chunks/workspace-registration-store-TARTAGMI.js +27 -0
  320. package/chunks/workspace-registry-AGE7WAXX.js +77 -0
  321. package/chunks/workspace-service-ERC5VR2B.js +83 -0
  322. package/chunks/workspace-skills-status-FKYWGNCN.js +73 -0
  323. package/chunks/{write-file-PX2Z7IBE.js → write-file-S47KSK7Z.js} +52 -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-Zj4EkBUY.js} +1 -1
  339. package/web-shell/assets/{architectureDiagram-3BPJPVTR-BT0mGrz2.js → architectureDiagram-3BPJPVTR-DAk1Ua3Y.js} +1 -1
  340. package/web-shell/assets/{blockDiagram-GPEHLZMM-BLgUWvyf.js → blockDiagram-GPEHLZMM-DBNqUthM.js} +1 -1
  341. package/web-shell/assets/{c4Diagram-AAUBKEIU-DYx9M7oU.js → c4Diagram-AAUBKEIU-Dq5QGJ53.js} +1 -1
  342. package/web-shell/assets/channel-DWfYijFS.js +1 -0
  343. package/web-shell/assets/{chunk-2J33WTMH-CfMHWbuZ.js → chunk-2J33WTMH-DY0AeGru.js} +1 -1
  344. package/web-shell/assets/{chunk-4BX2VUAB-B1URoqEV.js → chunk-4BX2VUAB-COX3OyIi.js} +1 -1
  345. package/web-shell/assets/{chunk-55IACEB6-DAIaM4QF.js → chunk-55IACEB6-Csoyddbh.js} +1 -1
  346. package/web-shell/assets/{chunk-727SXJPM-B2X34knw.js → chunk-727SXJPM-BJPONdxX.js} +1 -1
  347. package/web-shell/assets/{chunk-AQP2D5EJ-Cif-zLTQ.js → chunk-AQP2D5EJ-syLVH6fg.js} +1 -1
  348. package/web-shell/assets/{chunk-FMBD7UC4-H18WCXdY.js → chunk-FMBD7UC4-Cfm59Nhw.js} +1 -1
  349. package/web-shell/assets/{chunk-ND2GUHAM-YFtetHi0.js → chunk-ND2GUHAM-DZf6tAqS.js} +1 -1
  350. package/web-shell/assets/{chunk-QZHKN3VN-By2hiH3r.js → chunk-QZHKN3VN-DKBp_v5q.js} +1 -1
  351. package/web-shell/assets/classDiagram-4FO5ZUOK-DDht-78J.js +1 -0
  352. package/web-shell/assets/classDiagram-v2-Q7XG4LA2-DDht-78J.js +1 -0
  353. package/web-shell/assets/{cose-bilkent-S5V4N54A-VrcnnLZu.js → cose-bilkent-S5V4N54A-DUU3mMQ5.js} +1 -1
  354. package/web-shell/assets/{dagre-BM42HDAG-CGo-IaVV.js → dagre-BM42HDAG-BUgNfbh-.js} +1 -1
  355. package/web-shell/assets/{diagram-2AECGRRQ-Dl4QjzIB.js → diagram-2AECGRRQ-DT7MVfAg.js} +1 -1
  356. package/web-shell/assets/{diagram-5GNKFQAL-qMLmsO0u.js → diagram-5GNKFQAL-Cv4YG-ec.js} +1 -1
  357. package/web-shell/assets/{diagram-KO2AKTUF-CHlmuxPI.js → diagram-KO2AKTUF-BAe9LLkn.js} +1 -1
  358. package/web-shell/assets/{diagram-LMA3HP47-BUwU3GwT.js → diagram-LMA3HP47-DW8wqTIP.js} +1 -1
  359. package/web-shell/assets/{diagram-OG6HWLK6-HEhwPDUM.js → diagram-OG6HWLK6-CmkuWbaK.js} +1 -1
  360. package/web-shell/assets/{erDiagram-TEJ5UH35-1n0llBmM.js → erDiagram-TEJ5UH35-DwvdHjZ9.js} +1 -1
  361. package/web-shell/assets/{flowDiagram-I6XJVG4X-BN74uMnt.js → flowDiagram-I6XJVG4X-CSsXrhW_.js} +1 -1
  362. package/web-shell/assets/{ganttDiagram-6RSMTGT7-BoOq78i3.js → ganttDiagram-6RSMTGT7-BtuznCdi.js} +3 -3
  363. package/web-shell/assets/{gitGraphDiagram-PVQCEYII-CN8b00c8.js → gitGraphDiagram-PVQCEYII-DGmAm06g.js} +1 -1
  364. package/web-shell/assets/index-B9Xwf4OS.css +5 -0
  365. package/web-shell/assets/index-BEtz1cvN.js +3 -0
  366. package/web-shell/assets/index-BUkM4ZXX.js +1088 -0
  367. package/web-shell/assets/{infoDiagram-5YYISTIA-CCurnIna.js → infoDiagram-5YYISTIA-OAiZ1q0K.js} +1 -1
  368. package/web-shell/assets/{ishikawaDiagram-YF4QCWOH-AwuRqdUP.js → ishikawaDiagram-YF4QCWOH-DyK0KTIT.js} +1 -1
  369. package/web-shell/assets/{journeyDiagram-JHISSGLW-B7IICk-E.js → journeyDiagram-JHISSGLW-DzYJlwfO.js} +1 -1
  370. package/web-shell/assets/{kanban-definition-UN3LZRKU-BYF0OKhx.js → kanban-definition-UN3LZRKU-CU_tcDwi.js} +1 -1
  371. package/web-shell/assets/{linear-GWWguGfD.js → linear-DvZXjF17.js} +1 -1
  372. package/web-shell/assets/{mermaid.core-JqtkxvCl.js → mermaid.core-_ZFEQlOl.js} +5 -5
  373. package/web-shell/assets/{mindmap-definition-RKZ34NQL-B0MmHsZ6.js → mindmap-definition-RKZ34NQL-Or4p64HB.js} +1 -1
  374. package/web-shell/assets/{pieDiagram-4H26LBE5-DhImUZLQ.js → pieDiagram-4H26LBE5-lXE-zZ6b.js} +1 -1
  375. package/web-shell/assets/{quadrantDiagram-W4KKPZXB-DGeSC3DT.js → quadrantDiagram-W4KKPZXB-DUXb9mUV.js} +1 -1
  376. package/web-shell/assets/{requirementDiagram-4Y6WPE33-DkspY6Re.js → requirementDiagram-4Y6WPE33-D_10uHfo.js} +1 -1
  377. package/web-shell/assets/{sankeyDiagram-5OEKKPKP-CaOofS2x.js → sankeyDiagram-5OEKKPKP-E8c0fPqe.js} +1 -1
  378. package/web-shell/assets/{sequenceDiagram-3UESZ5HK-DFQ_kFnN.js → sequenceDiagram-3UESZ5HK-CJMtFttK.js} +1 -1
  379. package/web-shell/assets/{stateDiagram-AJRCARHV-D3snw0Tz.js → stateDiagram-AJRCARHV-DhbviRbB.js} +1 -1
  380. package/web-shell/assets/stateDiagram-v2-BHNVJYJU-CntljfwW.js +1 -0
  381. package/web-shell/assets/{timeline-definition-PNZ67QCA-l4zH8nLM.js → timeline-definition-PNZ67QCA-CM5yMkFK.js} +1 -1
  382. package/web-shell/assets/{vennDiagram-CIIHVFJN-BnRlA98M.js → vennDiagram-CIIHVFJN-BCi-zWNN.js} +1 -1
  383. package/web-shell/assets/{wardley-L42UT6IY-BS0xUdmd.js → wardley-L42UT6IY-BJ_yJNjJ.js} +1 -1
  384. package/web-shell/assets/{wardleyDiagram-YWT4CUSO-DKGBUWyQ.js → wardleyDiagram-YWT4CUSO-TjtLk-qN.js} +1 -1
  385. package/web-shell/assets/{xychartDiagram-2RQKCTM6-DVb2HuOB.js → xychartDiagram-2RQKCTM6-D1TjyoQ3.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-6SHO7WFF.js +0 -79
  392. package/chunks/chunk-IFEWJXFS.js +0 -37
  393. package/chunks/chunk-XNXVCNAT.js +0 -88
  394. package/chunks/contextCommand-LXFZRP4L.js +0 -68
  395. package/chunks/daemon-status-provider-GJRXY5EN.js +0 -76
  396. package/chunks/earlyInputCapture-KNOYZ4MJ.js +0 -69
  397. package/chunks/environment-ATFTYMLZ.js +0 -88
  398. package/chunks/errors-A54HAADA.js +0 -75
  399. package/chunks/handleAutoUpdate-CEZJAARW.js +0 -65
  400. package/chunks/initializer-BRFJKRRX.js +0 -71
  401. package/chunks/list-KVHF7O4X.js +0 -73
  402. package/chunks/loadedSettingsAdapter-LL5PSFKX.js +0 -68
  403. package/chunks/mcp-3GCXRTOQ.js +0 -68
  404. package/chunks/nonInteractiveCli-PTQI3DV6.js +0 -119
  405. package/chunks/openaiContentGenerator-YE42PKCY.js +0 -56
  406. package/chunks/pidfile-NZYSCFRK.js +0 -73
  407. package/chunks/read-file-33XGP5HF.js +0 -30
  408. package/chunks/ripGrep-QWZLGTAN.js +0 -60
  409. package/chunks/serve-JTMIGANH.js +0 -74
  410. package/chunks/settings-3MI4XXP6.js +0 -118
  411. package/chunks/shell-YJKBE67T.js +0 -68
  412. package/chunks/spawnChannel-UNV6W4DU.js +0 -70
  413. package/chunks/task-create-WCHTB435.js +0 -22
  414. package/chunks/theme-manager-WZ4RRMMB.js +0 -64
  415. package/chunks/total-session-admission-ULXJWXFV.js +0 -72
  416. package/chunks/trustedFolders-LAZZPZ3D.js +0 -79
  417. package/chunks/updateCheck-KONLM73X.js +0 -65
  418. package/chunks/validateNonInterActiveAuth-MPKSRCXD.js +0 -184
  419. package/chunks/workspace-providers-status-3W7E7DFW.js +0 -71
  420. package/chunks/workspace-registry-SXJZNN3O.js +0 -74
  421. package/chunks/workspace-service-CZRQZ4Q4.js +0 -80
  422. package/chunks/workspace-skills-status-K7WFREPD.js +0 -70
  423. package/node_modules/@qwen-code/audio-capture/dist/index.d.ts +0 -35
  424. package/node_modules/@qwen-code/audio-capture/dist/index.js +0 -48
  425. package/node_modules/@qwen-code/audio-capture/dist/index.js.map +0 -1
  426. package/node_modules/@qwen-code/audio-capture/dist/platform.d.ts +0 -7
  427. package/node_modules/@qwen-code/audio-capture/dist/platform.js +0 -18
  428. package/node_modules/@qwen-code/audio-capture/dist/platform.js.map +0 -1
  429. package/node_modules/@qwen-code/audio-capture/node_modules/node-gyp-build/LICENSE +0 -21
  430. package/node_modules/@qwen-code/audio-capture/node_modules/node-gyp-build/README.md +0 -58
  431. package/node_modules/@qwen-code/audio-capture/node_modules/node-gyp-build/SECURITY.md +0 -5
  432. package/node_modules/@qwen-code/audio-capture/node_modules/node-gyp-build/bin.js +0 -84
  433. package/node_modules/@qwen-code/audio-capture/node_modules/node-gyp-build/build-test.js +0 -19
  434. package/node_modules/@qwen-code/audio-capture/node_modules/node-gyp-build/index.js +0 -6
  435. package/node_modules/@qwen-code/audio-capture/node_modules/node-gyp-build/node-gyp-build.js +0 -207
  436. package/node_modules/@qwen-code/audio-capture/node_modules/node-gyp-build/optional.js +0 -7
  437. package/node_modules/@qwen-code/audio-capture/node_modules/node-gyp-build/package.json +0 -43
  438. package/node_modules/@qwen-code/audio-capture/package.json +0 -30
  439. package/node_modules/@qwen-code/audio-capture/prebuilds/darwin-arm64/@qwen-code+audio-capture.node +0 -0
  440. package/node_modules/@qwen-code/audio-capture/prebuilds/darwin-x64/@qwen-code+audio-capture.node +0 -0
  441. package/node_modules/@qwen-code/audio-capture/prebuilds/linux-arm64/@qwen-code+audio-capture.node +0 -0
  442. package/node_modules/@qwen-code/audio-capture/prebuilds/linux-x64/@qwen-code+audio-capture.node +0 -0
  443. package/node_modules/@qwen-code/audio-capture/prebuilds/win32-x64/@qwen-code+audio-capture.node +0 -0
  444. package/web-shell/assets/channel-wmPUGHtg.js +0 -1
  445. package/web-shell/assets/classDiagram-4FO5ZUOK-BA2ljEjW.js +0 -1
  446. package/web-shell/assets/classDiagram-v2-Q7XG4LA2-BA2ljEjW.js +0 -1
  447. package/web-shell/assets/index-CNwoO1Cn.js +0 -783
  448. package/web-shell/assets/index-CWQ0z6kZ.css +0 -5
  449. package/web-shell/assets/stateDiagram-v2-BHNVJYJU-BbSm_9d0.js +0 -1
@@ -1,137 +1,579 @@
1
1
  // Force strict mode and setup for ESM
2
2
  "use strict";
3
+ import {
4
+ formatHistoryGapNotice,
5
+ indexGapsByChild
6
+ } from "./chunk-DKXW66XA.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-SSFDPGFN.js";
12
16
  import {
13
17
  ToolNames
14
- } from "./chunk-X3YGAX7V.js";
18
+ } from "./chunk-2UUAIFQO.js";
15
19
  import {
16
20
  createDebugLogger
17
- } from "./chunk-22MNNNXE.js";
21
+ } from "./chunk-7NFB7LBQ.js";
18
22
  import {
19
23
  init_esbuild_shims
20
- } from "./chunk-A4BMJM77.js";
24
+ } from "./chunk-5O2XNYP6.js";
21
25
  import {
22
26
  __name,
23
27
  __toESM
24
28
  } from "./chunk-J2S4EL5Y.js";
25
29
 
26
- // packages/cli/src/acp-integration/session/HistoryReplayer.ts
27
- init_esbuild_shims();
28
-
29
- // packages/cli/src/acp-integration/session/emitters/MessageEmitter.ts
30
+ // packages/cli/src/services/setup-github.ts
30
31
  init_esbuild_shims();
32
+ var import_undici2 = __toESM(require_undici(), 1);
33
+ import { promises as fsp } from "node:fs";
34
+ import * as path from "node:path";
31
35
 
32
- // packages/cli/src/acp-integration/session/emitters/BaseEmitter.ts
36
+ // packages/cli/src/utils/gitUtils.ts
33
37
  init_esbuild_shims();
34
- var BaseEmitter = class {
35
- constructor(ctx) {
36
- this.ctx = ctx;
38
+ var import_undici = __toESM(require_undici(), 1);
39
+ import * as childProcess from "node:child_process";
40
+ var debugLogger = createDebugLogger("GIT");
41
+ async function runGit(args, opts = {}) {
42
+ return await new Promise((resolve2, reject) => {
43
+ childProcess.execFile(
44
+ "git",
45
+ args,
46
+ {
47
+ encoding: "utf-8",
48
+ ...opts.cwd ? { cwd: opts.cwd } : {}
49
+ },
50
+ (err, stdout) => {
51
+ if (err) {
52
+ reject(err);
53
+ return;
54
+ }
55
+ resolve2(String(stdout ?? "").trim());
56
+ }
57
+ );
58
+ });
59
+ }
60
+ __name(runGit, "runGit");
61
+ var isGitHubRepositoryAsync = /* @__PURE__ */ __name(async (opts = {}) => {
62
+ try {
63
+ const remotes = await runGit(["remote", "-v"], opts);
64
+ return remotes.split("\n").some((line) => {
65
+ const remoteUrl = line.trim().split(/\s+/)[1];
66
+ return remoteUrl ? isGitHubRemoteUrl(remoteUrl) : false;
67
+ });
68
+ } catch (_error) {
69
+ debugLogger.debug(`Failed to get git remote:`, _error);
70
+ return false;
37
71
  }
38
- static {
39
- __name(this, "BaseEmitter");
72
+ }, "isGitHubRepositoryAsync");
73
+ function isGitHubRemoteUrl(remoteUrl) {
74
+ if (remoteUrl.startsWith("git@github.com:")) {
75
+ return true;
40
76
  }
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;
77
+ if (remoteUrl.startsWith("git@")) {
78
+ return false;
79
+ }
80
+ try {
81
+ return new URL(remoteUrl).hostname === "github.com";
82
+ } catch {
83
+ return false;
84
+ }
85
+ }
86
+ __name(isGitHubRemoteUrl, "isGitHubRemoteUrl");
87
+ var getGitRepoRootAsync = /* @__PURE__ */ __name(async (opts = {}) => {
88
+ const gitRepoRoot = await runGit(["rev-parse", "--show-toplevel"], opts);
89
+ if (!gitRepoRoot) {
90
+ throw new Error(`Git repo returned empty value`);
91
+ }
92
+ return gitRepoRoot;
93
+ }, "getGitRepoRootAsync");
94
+ var getLatestGitHubRelease = /* @__PURE__ */ __name(async (proxy) => {
95
+ try {
96
+ const controller = new AbortController();
97
+ const endpoint = `https://api.github.com/repos/QwenLM/qwen-code-action/releases/latest`;
98
+ const response = await fetch(endpoint, {
99
+ method: "GET",
100
+ headers: {
101
+ Accept: "application/vnd.github+json",
102
+ "Content-Type": "application/json",
103
+ "X-GitHub-Api-Version": "2022-11-28"
104
+ },
105
+ dispatcher: proxy ? new import_undici.ProxyAgent(proxy) : void 0,
106
+ signal: AbortSignal.any([AbortSignal.timeout(3e4), controller.signal])
107
+ });
108
+ if (!response.ok) {
109
+ throw new Error(
110
+ `Invalid response code: ${response.status} - ${response.statusText}`
111
+ );
48
112
  }
49
- if (typeof ts === "string") {
50
- const ms = new Date(ts).getTime();
51
- return Number.isFinite(ms) ? ms : void 0;
113
+ const releaseTag = (await response.json()).tag_name;
114
+ if (!releaseTag) {
115
+ throw new Error(`Response did not include tag_name field`);
52
116
  }
53
- return void 0;
117
+ return releaseTag;
118
+ } catch (_error) {
119
+ debugLogger.debug(
120
+ `Failed to determine latest qwen-code-action release:`,
121
+ _error
122
+ );
123
+ throw new Error(
124
+ `Unable to determine the latest qwen-code-action release on GitHub.`
125
+ );
54
126
  }
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);
127
+ }, "getLatestGitHubRelease");
128
+ async function getGitHubRepoInfoAsync(opts = {}) {
129
+ return parseGitHubRepoInfo(
130
+ await runGit(["remote", "get-url", "origin"], opts)
131
+ );
132
+ }
133
+ __name(getGitHubRepoInfoAsync, "getGitHubRepoInfoAsync");
134
+ function parseGitHubRepoInfo(remoteUrl) {
135
+ let urlToParse = remoteUrl;
136
+ if (remoteUrl.startsWith("git@github.com:")) {
137
+ urlToParse = remoteUrl.replace("git@github.com:", "");
138
+ } else if (remoteUrl.startsWith("git@")) {
139
+ throw new Error(
140
+ `Owner & repo could not be extracted from remote URL: ${remoteUrl}`
141
+ );
65
142
  }
66
- /**
67
- * Gets the session configuration.
68
- */
69
- get config() {
70
- return this.ctx.config;
143
+ let parsedUrl;
144
+ try {
145
+ parsedUrl = new URL(urlToParse, "https://github.com");
146
+ } catch {
147
+ throw new Error(
148
+ `Owner & repo could not be extracted from remote URL: ${remoteUrl}`
149
+ );
71
150
  }
72
- /**
73
- * Gets the session ID.
74
- */
75
- get sessionId() {
76
- return this.ctx.sessionId;
151
+ if (parsedUrl.hostname !== "github.com") {
152
+ throw new Error(
153
+ `Owner & repo could not be extracted from remote URL: ${remoteUrl}`
154
+ );
77
155
  }
78
- };
156
+ const parts = parsedUrl.pathname.split("/").filter((part) => part !== "");
157
+ if (parts.length !== 2 || !parts[0] || !parts[1]) {
158
+ throw new Error(
159
+ `Owner & repo could not be extracted from remote URL: ${remoteUrl}`
160
+ );
161
+ }
162
+ return { owner: parts[0], repo: parts[1].replace(/\.git$/, "") };
163
+ }
164
+ __name(parseGitHubRepoInfo, "parseGitHubRepoInfo");
79
165
 
80
- // packages/cli/src/acp-integration/session/emitters/MessageEmitter.ts
81
- var MessageEmitter = class extends BaseEmitter {
166
+ // packages/cli/src/services/setup-github.ts
167
+ var debugLogger2 = createDebugLogger("SETUP_GITHUB");
168
+ var GITHUB_WORKFLOW_PATHS = [
169
+ "qwen-dispatch/qwen-dispatch.yml",
170
+ "qwen-assistant/qwen-invoke.yml",
171
+ "issue-triage/qwen-triage.yml",
172
+ "issue-triage/qwen-scheduled-triage.yml",
173
+ "pr-review/qwen-review.yml"
174
+ ];
175
+ var GITIGNORE_ENTRIES = [".qwen/", "gha-creds-*.json"];
176
+ var MAX_WORKFLOW_DOWNLOAD_BYTES = 5 * 1024 * 1024;
177
+ var SetupGithubError = class extends Error {
82
178
  static {
83
- __name(this, "MessageEmitter");
179
+ __name(this, "SetupGithubError");
84
180
  }
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
- });
181
+ code;
182
+ status;
183
+ partial;
184
+ partialResult;
185
+ constructor(code, message, status, partialResult) {
186
+ super(message);
187
+ this.name = "SetupGithubError";
188
+ this.code = code;
189
+ this.status = status;
190
+ this.partial = partialResult !== void 0;
191
+ this.partialResult = partialResult;
114
192
  }
115
- async emitGoalTerminal(event) {
116
- await this.sendUpdate({
117
- sessionUpdate: "agent_message_chunk",
118
- content: { type: "text", text: "" },
119
- _meta: {
120
- goalTerminal: event
121
- }
193
+ };
194
+ var nodeFileOps = {
195
+ assertCanWrite() {
196
+ },
197
+ async ensureWorkflowDirectory(gitRepoRoot) {
198
+ await fsp.mkdir(path.join(gitRepoRoot, ".github", "workflows"), {
199
+ recursive: true
122
200
  });
123
- }
124
- async emitGoalStatus(status) {
125
- await this.sendUpdate({
126
- sessionUpdate: "agent_message_chunk",
127
- content: { type: "text", text: "" },
128
- _meta: {
129
- goalStatus: status
201
+ },
202
+ async writeTextFile(gitRepoRoot, relativePath, content) {
203
+ const target = path.join(gitRepoRoot, relativePath);
204
+ await fsp.writeFile(target, content, { mode: 420 });
205
+ return { sizeBytes: Buffer.byteLength(content, "utf8") };
206
+ },
207
+ async readTextFile(gitRepoRoot, relativePath) {
208
+ try {
209
+ return await fsp.readFile(path.join(gitRepoRoot, relativePath), "utf8");
210
+ } catch (error) {
211
+ if (error.code === "ENOENT") {
212
+ return void 0;
130
213
  }
131
- });
214
+ throw error;
215
+ }
132
216
  }
133
- /**
134
- * Emits a user message chunk.
217
+ };
218
+ async function setupGithub(options = {}) {
219
+ const cwd = options.cwd ?? process.cwd();
220
+ const fileOps = options.fileOps ?? nodeFileOps;
221
+ if (!await isGitHubRepositoryAsync({ cwd })) {
222
+ throw new SetupGithubError(
223
+ "github_repository_not_found",
224
+ "Unable to determine the GitHub repository. /setup-github must be run from a git repository.",
225
+ 400
226
+ );
227
+ }
228
+ let gitRepoRoot;
229
+ try {
230
+ gitRepoRoot = await getGitRepoRootAsync({ cwd });
231
+ } catch (error) {
232
+ debugLogger2.debug("Failed to get git repo root:", error);
233
+ throw new SetupGithubError(
234
+ "github_repository_not_found",
235
+ "Unable to determine the GitHub repository. /setup-github must be run from a git repository.",
236
+ 400
237
+ );
238
+ }
239
+ if (options.workspaceRoot) {
240
+ const [gitRootReal, workspaceReal] = await Promise.all([
241
+ realpathOrResolve(gitRepoRoot),
242
+ realpathOrResolve(options.workspaceRoot)
243
+ ]);
244
+ if (gitRootReal !== workspaceReal) {
245
+ throw new SetupGithubError(
246
+ "github_git_root_mismatch",
247
+ "The Git repository root must match the daemon workspace root.",
248
+ 400
249
+ );
250
+ }
251
+ }
252
+ fileOps.assertCanWrite?.();
253
+ let releaseTag;
254
+ try {
255
+ releaseTag = await getLatestGitHubRelease(options.proxy);
256
+ } catch (error) {
257
+ writeStderrLine(
258
+ `qwen setup-github: failed to determine latest qwen-code-action release: ${error instanceof Error ? error.message : String(error)}`
259
+ );
260
+ debugLogger2.debug(
261
+ "Failed to determine latest qwen-code-action release:",
262
+ error
263
+ );
264
+ throw new SetupGithubError(
265
+ "github_release_lookup_failed",
266
+ "Unable to determine the latest qwen-code-action release on GitHub.",
267
+ 502
268
+ );
269
+ }
270
+ const readmeUrl = `https://github.com/QwenLM/qwen-code-action/blob/${releaseTag}/README.md#quick-start`;
271
+ const secretsUrl = await resolveSecretsUrl(cwd);
272
+ const downloads = await downloadWorkflows({
273
+ releaseTag,
274
+ proxy: options.proxy,
275
+ abortSignal: options.abortSignal,
276
+ fetchImpl: options.fetchImpl ?? fetch
277
+ });
278
+ const result = {
279
+ kind: "github_setup",
280
+ workspaceCwd: options.workspaceRoot ?? gitRepoRoot,
281
+ gitRepoRoot,
282
+ releaseTag,
283
+ readmeUrl,
284
+ ...secretsUrl ? { secretsUrl } : {},
285
+ workflows: [],
286
+ gitignore: { path: ".gitignore", status: "skipped" },
287
+ warnings: []
288
+ };
289
+ result.gitignore = await updateGitignore(gitRepoRoot, fileOps);
290
+ if (result.gitignore.status === "failed") {
291
+ result.warnings.push("Failed to update .gitignore.");
292
+ }
293
+ try {
294
+ await fileOps.ensureWorkflowDirectory(gitRepoRoot);
295
+ for (const workflow of downloads) {
296
+ const relativePath = path.posix.join(
297
+ ".github",
298
+ "workflows",
299
+ path.posix.basename(workflow.sourcePath)
300
+ );
301
+ try {
302
+ const write = await fileOps.writeTextFile(
303
+ gitRepoRoot,
304
+ relativePath,
305
+ workflow.content
306
+ );
307
+ result.workflows.push({
308
+ sourcePath: workflow.sourcePath,
309
+ path: relativePath,
310
+ status: "written",
311
+ sizeBytes: write.sizeBytes
312
+ });
313
+ } catch (error) {
314
+ result.partial = true;
315
+ result.workflows.push({
316
+ sourcePath: workflow.sourcePath,
317
+ path: relativePath,
318
+ status: "failed",
319
+ error: error instanceof Error ? error.message : String(error)
320
+ });
321
+ throw new SetupGithubError(
322
+ "github_workflow_write_failed",
323
+ `Unable to write ${relativePath}.`,
324
+ 500,
325
+ result
326
+ );
327
+ }
328
+ }
329
+ } catch (error) {
330
+ if (error instanceof SetupGithubError) throw error;
331
+ throw new SetupGithubError(
332
+ "github_workflow_write_failed",
333
+ "Unable to create .github/workflows.",
334
+ 500,
335
+ result
336
+ );
337
+ }
338
+ return result;
339
+ }
340
+ __name(setupGithub, "setupGithub");
341
+ async function updateGitignore(gitRepoRoot, fileOps = nodeFileOps) {
342
+ try {
343
+ const existingContent = await fileOps.readTextFile(
344
+ gitRepoRoot,
345
+ ".gitignore"
346
+ );
347
+ if (existingContent === void 0) {
348
+ const content = GITIGNORE_ENTRIES.join("\n") + "\n";
349
+ await fileOps.writeTextFile(gitRepoRoot, ".gitignore", content);
350
+ return {
351
+ path: ".gitignore",
352
+ status: "created",
353
+ added: [...GITIGNORE_ENTRIES]
354
+ };
355
+ }
356
+ const missingEntries = GITIGNORE_ENTRIES.filter(
357
+ (entry) => !existingContent.split(/\r?\n/).some((line) => line.split("#")[0].trim() === entry)
358
+ );
359
+ if (missingEntries.length === 0) {
360
+ return { path: ".gitignore", status: "unchanged" };
361
+ }
362
+ const nextContent = existingContent + "\n" + missingEntries.join("\n") + "\n";
363
+ await fileOps.writeTextFile(gitRepoRoot, ".gitignore", nextContent);
364
+ return {
365
+ path: ".gitignore",
366
+ status: "updated",
367
+ added: missingEntries
368
+ };
369
+ } catch (error) {
370
+ debugLogger2.debug("Failed to update .gitignore:", error);
371
+ return {
372
+ path: ".gitignore",
373
+ status: "failed",
374
+ error: error instanceof Error ? error.message : String(error)
375
+ };
376
+ }
377
+ }
378
+ __name(updateGitignore, "updateGitignore");
379
+ async function downloadWorkflows(options) {
380
+ const internalAbort = new AbortController();
381
+ try {
382
+ const dispatcher = options.proxy ? new import_undici2.ProxyAgent(options.proxy) : void 0;
383
+ return await Promise.all(
384
+ GITHUB_WORKFLOW_PATHS.map(async (workflow) => {
385
+ const endpoint = `https://raw.githubusercontent.com/QwenLM/qwen-code-action/refs/tags/${options.releaseTag}/examples/workflows/${workflow}`;
386
+ const response = await options.fetchImpl(endpoint, {
387
+ method: "GET",
388
+ dispatcher,
389
+ signal: AbortSignal.any([
390
+ AbortSignal.timeout(3e4),
391
+ internalAbort.signal,
392
+ ...options.abortSignal ? [options.abortSignal] : []
393
+ ])
394
+ });
395
+ if (!response.ok) {
396
+ throw new Error(
397
+ `Invalid response code downloading ${endpoint}: ${response.status} - ${response.statusText}`
398
+ );
399
+ }
400
+ return {
401
+ sourcePath: workflow,
402
+ content: await readResponseTextWithLimit(response, workflow)
403
+ };
404
+ })
405
+ );
406
+ } catch (error) {
407
+ internalAbort.abort();
408
+ const message = error instanceof Error ? error.message : String(error);
409
+ debugLogger2.debug("Failed to download qwen-code-action workflows:", error);
410
+ throw new SetupGithubError(
411
+ "github_workflow_download_failed",
412
+ `Unable to download qwen-code-action workflows from GitHub. ${message}`,
413
+ 502
414
+ );
415
+ }
416
+ }
417
+ __name(downloadWorkflows, "downloadWorkflows");
418
+ async function readResponseTextWithLimit(response, sourcePath) {
419
+ const contentLength = response.headers.get("content-length");
420
+ if (contentLength !== null) {
421
+ const parsedLength = Number(contentLength);
422
+ if (Number.isFinite(parsedLength) && parsedLength > MAX_WORKFLOW_DOWNLOAD_BYTES) {
423
+ throw new Error(
424
+ `${sourcePath} exceeds download limit of ${MAX_WORKFLOW_DOWNLOAD_BYTES} bytes`
425
+ );
426
+ }
427
+ }
428
+ if (!response.body) return "";
429
+ const reader = response.body.getReader();
430
+ const chunks = [];
431
+ let totalBytes = 0;
432
+ try {
433
+ while (true) {
434
+ const { done, value } = await reader.read();
435
+ if (done) break;
436
+ if (!value) continue;
437
+ totalBytes += value.byteLength;
438
+ if (totalBytes > MAX_WORKFLOW_DOWNLOAD_BYTES) {
439
+ await reader.cancel().catch(() => {
440
+ });
441
+ throw new Error(
442
+ `${sourcePath} exceeds download limit of ${MAX_WORKFLOW_DOWNLOAD_BYTES} bytes`
443
+ );
444
+ }
445
+ chunks.push(value);
446
+ }
447
+ } finally {
448
+ reader.releaseLock();
449
+ }
450
+ const body = new Uint8Array(totalBytes);
451
+ let offset = 0;
452
+ for (const chunk of chunks) {
453
+ body.set(chunk, offset);
454
+ offset += chunk.byteLength;
455
+ }
456
+ return new TextDecoder().decode(body);
457
+ }
458
+ __name(readResponseTextWithLimit, "readResponseTextWithLimit");
459
+ async function resolveSecretsUrl(cwd) {
460
+ try {
461
+ const repoInfo = await getGitHubRepoInfoAsync({ cwd });
462
+ return `https://github.com/${repoInfo.owner}/${repoInfo.repo}/settings/secrets/actions`;
463
+ } catch {
464
+ return void 0;
465
+ }
466
+ }
467
+ __name(resolveSecretsUrl, "resolveSecretsUrl");
468
+ async function realpathOrResolve(input) {
469
+ try {
470
+ return await fsp.realpath(input);
471
+ } catch {
472
+ return path.resolve(input);
473
+ }
474
+ }
475
+ __name(realpathOrResolve, "realpathOrResolve");
476
+
477
+ // packages/cli/src/acp-integration/session/emitters/MessageEmitter.ts
478
+ init_esbuild_shims();
479
+
480
+ // packages/cli/src/acp-integration/session/emitters/base-emitter.ts
481
+ init_esbuild_shims();
482
+ var BaseEmitter = class {
483
+ constructor(ctx) {
484
+ this.ctx = ctx;
485
+ }
486
+ static {
487
+ __name(this, "BaseEmitter");
488
+ }
489
+ /**
490
+ * Converts an ISO timestamp string or epoch ms to epoch ms number.
491
+ * Returns undefined if the input is not a valid timestamp.
492
+ */
493
+ static toEpochMs(ts) {
494
+ if (typeof ts === "number") {
495
+ return Number.isFinite(ts) ? ts : void 0;
496
+ }
497
+ if (typeof ts === "string") {
498
+ const ms = new Date(ts).getTime();
499
+ return Number.isFinite(ms) ? ms : void 0;
500
+ }
501
+ return void 0;
502
+ }
503
+ /**
504
+ * Sends a session update to the ACP client.
505
+ * If a message rewriter is configured, updates pass through it first
506
+ * (original messages are sent as-is, rewritten versions are appended).
507
+ */
508
+ async sendUpdate(update) {
509
+ if (this.ctx.messageRewriter) {
510
+ return this.ctx.messageRewriter.interceptUpdate(update);
511
+ }
512
+ return this.ctx.sendUpdate(update);
513
+ }
514
+ /**
515
+ * Gets the session ID.
516
+ */
517
+ get sessionId() {
518
+ return this.ctx.sessionId;
519
+ }
520
+ };
521
+
522
+ // packages/cli/src/acp-integration/session/emitters/MessageEmitter.ts
523
+ var MessageEmitter = class extends BaseEmitter {
524
+ static {
525
+ __name(this, "MessageEmitter");
526
+ }
527
+ /**
528
+ * Emits a StopHookLoop event when Stop hooks create a loop.
529
+ * This informs the client that Stop hooks have been executed multiple times.
530
+ *
531
+ * @param iterationCount - The current iteration count
532
+ * @param reasons - Array of reasons from each Stop hook execution
533
+ * @param stopHookCount - Number of Stop hooks that were executed
534
+ */
535
+ async emitStopHookLoop(iterationCount, reasons, stopHookCount) {
536
+ const activeGoal = getActiveGoal(this.sessionId);
537
+ await this.sendUpdate({
538
+ sessionUpdate: "agent_message_chunk",
539
+ content: { type: "text", text: "" },
540
+ _meta: {
541
+ stopHookLoop: {
542
+ iterationCount,
543
+ reasons,
544
+ stopHookCount,
545
+ ...activeGoal ? {
546
+ goal: {
547
+ condition: activeGoal.condition,
548
+ iterations: activeGoal.iterations,
549
+ setAt: activeGoal.setAt,
550
+ lastReason: activeGoal.lastReason
551
+ }
552
+ } : {}
553
+ }
554
+ }
555
+ });
556
+ }
557
+ async emitGoalTerminal(event) {
558
+ await this.sendUpdate({
559
+ sessionUpdate: "agent_message_chunk",
560
+ content: { type: "text", text: "" },
561
+ _meta: {
562
+ goalTerminal: event
563
+ }
564
+ });
565
+ }
566
+ async emitGoalStatus(status) {
567
+ await this.sendUpdate({
568
+ sessionUpdate: "agent_message_chunk",
569
+ content: { type: "text", text: "" },
570
+ _meta: {
571
+ goalStatus: status
572
+ }
573
+ });
574
+ }
575
+ /**
576
+ * Emits a user message chunk.
135
577
  *
136
578
  * @param text - The user message text content
137
579
  * @param timestamp - Optional server-side timestamp (ISO string or ms) for message ordering
@@ -182,6 +624,17 @@ var MessageEmitter = class extends BaseEmitter {
182
624
  ..._meta ? { _meta } : {}
183
625
  });
184
626
  }
627
+ async emitSlashCommandOutput(text, timestamp) {
628
+ const epochMs = BaseEmitter.toEpochMs(timestamp);
629
+ await this.sendUpdate({
630
+ sessionUpdate: "agent_message_chunk",
631
+ content: { type: "text", text },
632
+ _meta: {
633
+ source: "slash_command",
634
+ ...epochMs != null ? { timestamp: epochMs } : {}
635
+ }
636
+ });
637
+ }
185
638
  /**
186
639
  * Emits usage metadata.
187
640
  */
@@ -242,9 +695,6 @@ var MessageEmitter = class extends BaseEmitter {
242
695
  }
243
696
  };
244
697
 
245
- // packages/cli/src/acp-integration/session/emitters/ToolCallEmitter.ts
246
- init_esbuild_shims();
247
-
248
698
  // packages/cli/src/acp-integration/session/emitters/PlanEmitter.ts
249
699
  init_esbuild_shims();
250
700
  var PlanEmitter = class extends BaseEmitter {
@@ -314,6 +764,16 @@ var PlanEmitter = class extends BaseEmitter {
314
764
  }
315
765
  };
316
766
 
767
+ // packages/cli/src/acp-integration/session/emitters/tool-call-emitter.ts
768
+ init_esbuild_shims();
769
+
770
+ // packages/cli/src/acp-integration/session/types.ts
771
+ init_esbuild_shims();
772
+ function hasFullSessionContext(context) {
773
+ return "config" in context;
774
+ }
775
+ __name(hasFullSessionContext, "hasFullSessionContext");
776
+
317
777
  // packages/cli/src/utils/truncatedDiffPreview.ts
318
778
  init_esbuild_shims();
319
779
  function buildTruncatedDiffPreviewText(display) {
@@ -326,7 +786,7 @@ function buildTruncatedDiffPreviewText(display) {
326
786
  }
327
787
  __name(buildTruncatedDiffPreviewText, "buildTruncatedDiffPreviewText");
328
788
 
329
- // packages/cli/src/acp-integration/session/emitters/ToolCallEmitter.ts
789
+ // packages/cli/src/acp-integration/session/emitters/tool-call-emitter.ts
330
790
  var KIND_MAP = {
331
791
  ["read" /* Read */]: "read",
332
792
  ["edit" /* Edit */]: "edit",
@@ -496,923 +956,526 @@ var ToolCallEmitter = class _ToolCallEmitter extends BaseEmitter {
496
956
  * `serverId: <server>`. Naming convention from
497
957
  * `packages/core/src/tools/mcp-tool.ts` in the
498
958
  * `@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.
959
+ * heuristic fallback so SDK consumers stay consistent with
960
+ * daemon classification.
961
+ * - everything else → `'builtin'`
691
962
  *
692
- * @param records - Array of chat records to replay
963
+ * Static + pure so it can be unit-tested without an emitter
964
+ * instance. Exported via `ToolCallEmitter.resolveToolProvenance`.
693
965
  */
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;
966
+ static resolveToolProvenance(toolName, subagentMeta) {
967
+ if (subagentMeta !== void 0) {
968
+ return { provenance: "subagent" };
969
+ }
970
+ if (toolName.startsWith("mcp__")) {
971
+ const parts = toolName.split("__");
972
+ if (parts.length >= 3 && parts[1] && parts[1].length > 0) {
973
+ return { provenance: "mcp", serverId: parts[1] };
722
974
  }
723
- } finally {
724
- this.pendingReplayToolCalls.clear();
725
- this.setActiveRecordId(null);
726
975
  }
976
+ return { provenance: "builtin" };
727
977
  }
978
+ // ==================== Public Utilities ====================
728
979
  /**
729
- * Replays a single chat record.
980
+ * Checks if a tool name is the TodoWriteTool.
981
+ * Exposed for external use in components that need to check this.
730
982
  */
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
- }
983
+ isTodoWriteTool(toolName) {
984
+ return toolName === ToolNames.TODO_WRITE;
800
985
  }
801
986
  /**
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
987
+ * Checks if a tool name is the ExitPlanModeTool.
808
988
  */
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
- }
989
+ isExitPlanModeTool(toolName) {
990
+ return toolName === ToolNames.EXIT_PLAN_MODE;
841
991
  }
842
992
  /**
843
- * Replays usage metadata.
844
- * @param usageMetadata - The usage metadata to replay
993
+ * Checks if a tool name is the EnterPlanModeTool.
845
994
  */
846
- async replayUsageMetadata(usageMetadata) {
847
- await this.messageEmitter.emitUsageMetadata(usageMetadata);
995
+ isEnterPlanModeTool(toolName) {
996
+ return toolName === ToolNames.ENTER_PLAN_MODE;
848
997
  }
849
998
  /**
850
- * Replays a tool result record.
999
+ * Resolves tool metadata from the registry.
1000
+ * Falls back to defaults if tool not found or build fails.
1001
+ *
1002
+ * @param toolName - Name of the tool
1003
+ * @param args - Tool call arguments (used to build invocation)
851
1004
  */
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
- );
1005
+ resolveToolMetadata(toolName, args) {
1006
+ if (!hasFullSessionContext(this.ctx)) {
1007
+ const description = typeof args?.["description"] === "string" ? args["description"].trim() : "";
1008
+ return {
1009
+ title: description ? `${toolName}: ${description}` : toolName,
1010
+ locations: [],
1011
+ kind: "other"
1012
+ };
876
1013
  }
877
- }
878
- async failDanglingToolCalls() {
879
- let firstError;
880
- for (const pending of this.pendingReplayToolCalls.values()) {
881
- this.setActiveRecordId(pending.recordId, pending.timestamp);
1014
+ const toolRegistry = this.ctx.config.getToolRegistry();
1015
+ const tool = toolRegistry.getTool(toolName);
1016
+ let title = tool?.displayName ?? toolName;
1017
+ let locations = [];
1018
+ let kind = "other";
1019
+ if (tool && args) {
882
1020
  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);
1021
+ const invocation = tool.build(args);
1022
+ title = `${title}: ${invocation.getDescription()}`;
1023
+ locations = invocation.toolLocations().map((loc) => ({
1024
+ path: loc.path,
1025
+ line: loc.line ?? null
1026
+ }));
1027
+ kind = this.mapToolKind(tool.kind, toolName);
1028
+ } catch {
1029
+ if (typeof args["description"] === "string") {
1030
+ title = `${title}: ${args["description"]}`;
1031
+ }
1032
+ if (tool.kind) {
1033
+ kind = this.mapToolKind(tool.kind, toolName);
1034
+ }
895
1035
  }
896
1036
  }
897
- if (firstError) {
898
- throw firstError;
899
- }
1037
+ return { title, locations, kind };
900
1038
  }
901
1039
  /**
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);
1040
+ * Maps core Tool Kind enum to ACP ToolKind string literals.
1041
+ *
1042
+ * @param kind - The core Kind enum value
1043
+ * @param toolName - Optional tool name to handle special cases like exit_plan_mode
1044
+ */
1045
+ mapToolKind(kind, toolName) {
1046
+ if (toolName && (this.isExitPlanModeTool(toolName) || this.isEnterPlanModeTool(toolName))) {
1047
+ return "switch_mode";
927
1048
  }
1049
+ return KIND_MAP[kind] ?? "other";
928
1050
  }
1051
+ // ==================== Private Helpers ====================
929
1052
  /**
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.
1053
+ * Extracts diff content from resultDisplay if it's a diff type (edit tool result).
1054
+ * Returns null if not a diff.
933
1055
  */
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
- );
1056
+ extractDiffContent(resultDisplay) {
1057
+ if (!resultDisplay || typeof resultDisplay !== "object") return null;
1058
+ const obj = resultDisplay;
1059
+ if ("fileName" in obj && "newContent" in obj) {
1060
+ if (this.isTruncatedSessionDiffDisplay(resultDisplay)) {
1061
+ return {
1062
+ type: "content",
1063
+ content: {
1064
+ type: "text",
1065
+ text: buildTruncatedDiffPreviewText(obj)
1066
+ }
1067
+ };
946
1068
  }
1069
+ return {
1070
+ type: "diff",
1071
+ path: obj["fileName"],
1072
+ oldText: obj["originalContent"] ?? "",
1073
+ newText: obj["newContent"]
1074
+ };
947
1075
  }
1076
+ return null;
1077
+ }
1078
+ isTruncatedSessionDiffDisplay(resultDisplay) {
1079
+ if (!resultDisplay || typeof resultDisplay !== "object") return false;
1080
+ const obj = resultDisplay;
1081
+ return obj["truncatedForSession"] === true && "fileName" in obj && "newContent" in obj;
948
1082
  }
949
1083
  /**
950
- * Extracts tool name from a chat record's function response.
1084
+ * Transforms Part[] to ToolCallContent[].
1085
+ * Extracts text from functionResponse parts and text parts.
951
1086
  */
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;
1087
+ transformPartsToToolCallContent(parts) {
1088
+ const result = [];
1089
+ for (const part of parts) {
1090
+ if ("text" in part && part.text) {
1091
+ result.push({
1092
+ type: "content",
1093
+ content: { type: "text", text: part.text }
1094
+ });
1095
+ }
1096
+ if ("functionResponse" in part && part.functionResponse) {
1097
+ try {
1098
+ const resp = part.functionResponse.response;
1099
+ const outputField = resp["output"];
1100
+ const errorField = resp["error"];
1101
+ const responseText = typeof outputField === "string" ? outputField : typeof errorField === "string" ? errorField : JSON.stringify(resp);
1102
+ result.push({
1103
+ type: "content",
1104
+ content: { type: "text", text: responseText }
1105
+ });
1106
+ } catch {
957
1107
  }
958
1108
  }
959
1109
  }
960
- return "";
961
- }
962
- setActiveRecordId(recordId, timestamp) {
963
- const context = this.ctx;
964
- if (typeof context.setActiveRecordId === "function") {
965
- context.setActiveRecordId(recordId, timestamp);
966
- }
1110
+ return result;
967
1111
  }
968
1112
  };
969
1113
 
970
- // packages/cli/src/services/setup-github.ts
1114
+ // packages/cli/src/acp-integration/session/history-replayer.ts
971
1115
  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
1116
 
976
- // packages/cli/src/utils/gitUtils.ts
1117
+ // packages/cli/src/utils/chat-record-tool-call-id.ts
977
1118
  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
- });
1119
+ function getToolResultCallId(record) {
1120
+ return getExplicitToolResultCallId(record) ?? record.uuid;
999
1121
  }
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;
1122
+ __name(getToolResultCallId, "getToolResultCallId");
1123
+ function getExplicitToolResultCallId(record) {
1124
+ const resultCallId = record.toolCallResult?.callId;
1125
+ if (typeof resultCallId === "string" && resultCallId.length > 0) {
1126
+ return resultCallId;
1024
1127
  }
1128
+ return extractFunctionResponseId(record);
1025
1129
  }
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`);
1130
+ __name(getExplicitToolResultCallId, "getExplicitToolResultCallId");
1131
+ function extractFunctionResponseId(record) {
1132
+ if (!record.message?.parts) {
1133
+ return void 0;
1031
1134
  }
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`);
1135
+ for (const part of record.message.parts) {
1136
+ const id = "functionResponse" in part ? part.functionResponse?.id : void 0;
1137
+ if (typeof id === "string" && id.length > 0) {
1138
+ return id;
1056
1139
  }
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
1140
  }
1102
- return { owner: parts[0], repo: parts[1].replace(/\.git$/, "") };
1141
+ return void 0;
1103
1142
  }
1104
- __name(parseGitHubRepoInfo, "parseGitHubRepoInfo");
1143
+ __name(extractFunctionResponseId, "extractFunctionResponseId");
1105
1144
 
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 {
1145
+ // packages/cli/src/acp-integration/session/history-replayer.ts
1146
+ var MISSING_TOOL_RESULT_MESSAGE = "Tool result missing from saved history; the previous run likely ended before this tool completed.";
1147
+ var HistoryReplayer = class {
1118
1148
  static {
1119
- __name(this, "SetupGithubError");
1149
+ __name(this, "HistoryReplayer");
1120
1150
  }
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;
1151
+ ctx;
1152
+ messageEmitter;
1153
+ toolCallEmitter;
1154
+ pendingReplayToolCalls = /* @__PURE__ */ new Map();
1155
+ constructor(ctx) {
1156
+ this.ctx = ctx;
1157
+ this.messageEmitter = new MessageEmitter(ctx);
1158
+ this.toolCallEmitter = new ToolCallEmitter(ctx);
1132
1159
  }
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) {
1160
+ /**
1161
+ * Replays all chat records from a loaded session.
1162
+ *
1163
+ * @param records - Array of chat records to replay
1164
+ * @param gaps - Optional detected history gaps; a visible notice is emitted
1165
+ * immediately before each gap's child record so the user sees that an
1166
+ * earlier segment was lost rather than assuming the halves are contiguous.
1167
+ */
1168
+ async replay(records, gaps) {
1148
1169
  try {
1149
- return await fsp.readFile(path.join(gitRepoRoot, relativePath), "utf8");
1170
+ await this.replayPage(records, { finalizeDangling: true, gaps });
1171
+ } finally {
1172
+ this.pendingReplayToolCalls.clear();
1173
+ this.setActiveRecordId(null);
1174
+ }
1175
+ }
1176
+ async replayPage(records, options = {}) {
1177
+ this.pendingReplayToolCalls.clear();
1178
+ for (const pending of options.pendingToolCalls ?? []) {
1179
+ this.pendingReplayToolCalls.set(pending.callId, pending);
1180
+ }
1181
+ const gapByChildUuid = indexGapsByChild(options.gaps);
1182
+ let replayError;
1183
+ try {
1184
+ for (const record of records) {
1185
+ const gap = gapByChildUuid.get(record.uuid);
1186
+ if (gap) {
1187
+ await this.emitHistoryGapNotice(gap, record.timestamp);
1188
+ }
1189
+ await this.replayRecord(record);
1190
+ }
1150
1191
  } catch (error) {
1151
- if (error.code === "ENOENT") {
1152
- return void 0;
1192
+ replayError = error;
1193
+ }
1194
+ let danglingError;
1195
+ if (options.finalizeDangling === true) {
1196
+ try {
1197
+ await this.failDanglingToolCalls();
1198
+ } catch (error) {
1199
+ danglingError = error;
1153
1200
  }
1154
- throw error;
1155
1201
  }
1202
+ const state = {
1203
+ pendingToolCalls: options.finalizeDangling === true ? [] : Array.from(this.pendingReplayToolCalls.values())
1204
+ };
1205
+ this.setActiveRecordId(null);
1206
+ if (replayError && danglingError) {
1207
+ throw new AggregateError(
1208
+ [replayError, danglingError],
1209
+ "Replay and dangling-cleanup both failed"
1210
+ );
1211
+ }
1212
+ if (replayError) {
1213
+ throw replayError;
1214
+ }
1215
+ if (danglingError) {
1216
+ throw danglingError;
1217
+ }
1218
+ return state;
1156
1219
  }
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
- );
1220
+ getPendingToolCalls() {
1221
+ return Array.from(this.pendingReplayToolCalls.values());
1178
1222
  }
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
- );
1223
+ /**
1224
+ * Replays a single chat record.
1225
+ */
1226
+ async replayRecord(record) {
1227
+ this.setActiveRecordId(record.uuid, record.timestamp);
1228
+ try {
1229
+ switch (record.type) {
1230
+ case "user":
1231
+ if (record.subtype === "notification" || record.subtype === "cron") {
1232
+ const displayText = record.systemPayload?.displayText;
1233
+ if (displayText) {
1234
+ await this.messageEmitter.emitUserMessage(
1235
+ displayText,
1236
+ record.timestamp,
1237
+ record.subtype === "cron" ? { source: "cron" } : void 0
1238
+ );
1239
+ }
1240
+ break;
1241
+ }
1242
+ if (record.subtype === "mid_turn_user_message") {
1243
+ const displayText = record.systemPayload?.displayText;
1244
+ if (displayText) {
1245
+ await this.messageEmitter.emitUserMessage(
1246
+ displayText,
1247
+ record.timestamp
1248
+ );
1249
+ } else if (record.message) {
1250
+ await this.replayContent(
1251
+ record.message,
1252
+ "user",
1253
+ record.timestamp,
1254
+ record.uuid
1255
+ );
1256
+ }
1257
+ break;
1258
+ }
1259
+ if (record.message) {
1260
+ await this.replayContent(
1261
+ record.message,
1262
+ "user",
1263
+ record.timestamp,
1264
+ record.uuid
1265
+ );
1266
+ }
1267
+ break;
1268
+ case "assistant":
1269
+ if (record.message) {
1270
+ await this.replayContent(
1271
+ record.message,
1272
+ "assistant",
1273
+ record.timestamp,
1274
+ record.uuid
1275
+ );
1276
+ }
1277
+ if (record.usageMetadata) {
1278
+ await this.replayUsageMetadata(record.usageMetadata);
1279
+ }
1280
+ break;
1281
+ case "tool_result":
1282
+ await this.replayToolResult(record);
1283
+ break;
1284
+ case "system":
1285
+ if (record.subtype === "slash_command") {
1286
+ await this.replaySlashCommandResult(record);
1287
+ }
1288
+ break;
1289
+ default:
1290
+ break;
1291
+ }
1292
+ } finally {
1293
+ this.setActiveRecordId(null);
1190
1294
  }
1191
1295
  }
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
1296
+ /**
1297
+ * Emits a visible notice marking a break in the persisted history chain: an
1298
+ * earlier segment was physically lost (storage interruption) and could not be
1299
+ * recovered, so the surviving turns below must not be read as contiguous with
1300
+ * whatever came before the gap. Uses the agent message channel — the same one
1301
+ * used for other system notices (see MessageEmitter.emitStopHookLoop) — so no
1302
+ * new session-update kind is needed.
1303
+ */
1304
+ async emitHistoryGapNotice(gap, timestamp) {
1305
+ await this.messageEmitter.emitAgentMessage(
1306
+ formatHistoryGapNotice(gap),
1307
+ timestamp
1208
1308
  );
1209
1309
  }
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.");
1310
+ /**
1311
+ * Replays content from a message (user or assistant).
1312
+ * Handles text parts, thought parts, and function calls.
1313
+ *
1314
+ * @param content - The content to replay
1315
+ * @param role - The role (user or assistant)
1316
+ * @param timestamp - Optional server-side timestamp from the JSONL record
1317
+ */
1318
+ async replayContent(content, role, timestamp, recordId) {
1319
+ for (const part of content.parts ?? []) {
1320
+ if ("text" in part && part.text) {
1321
+ const isThought = part.thought ?? false;
1322
+ await this.messageEmitter.emitMessage(
1323
+ part.text,
1324
+ role,
1325
+ isThought,
1326
+ timestamp
1327
+ );
1328
+ }
1329
+ if ("functionCall" in part && part.functionCall) {
1330
+ const functionName = part.functionCall.name ?? "";
1331
+ const sourceCallId = part.functionCall.id;
1332
+ const callId = sourceCallId ?? `${functionName}-${Date.now()}`;
1333
+ const emitted = await this.toolCallEmitter.emitStart({
1334
+ toolName: functionName,
1335
+ callId,
1336
+ args: part.functionCall.args,
1337
+ status: "in_progress",
1338
+ timestamp
1339
+ });
1340
+ if (emitted && role === "assistant" && recordId && sourceCallId) {
1341
+ this.pendingReplayToolCalls.set(callId, {
1342
+ callId,
1343
+ toolName: functionName,
1344
+ timestamp,
1345
+ recordId
1346
+ });
1347
+ }
1348
+ }
1349
+ }
1232
1350
  }
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)
1351
+ /**
1352
+ * Replays usage metadata.
1353
+ * @param usageMetadata - The usage metadata to replay
1354
+ */
1355
+ async replayUsageMetadata(usageMetadata) {
1356
+ await this.messageEmitter.emitUsageMetadata(usageMetadata);
1357
+ }
1358
+ /**
1359
+ * Replays a tool result record.
1360
+ */
1361
+ async replayToolResult(record) {
1362
+ if (!record.message?.parts) {
1363
+ return;
1364
+ }
1365
+ const result = record.toolCallResult;
1366
+ const callId = getToolResultCallId(record);
1367
+ this.pendingReplayToolCalls.delete(callId);
1368
+ const toolName = this.extractToolNameFromRecord(record);
1369
+ await this.toolCallEmitter.emitResult({
1370
+ toolName,
1371
+ callId,
1372
+ success: !result?.error,
1373
+ message: record.message.parts,
1374
+ resultDisplay: result?.resultDisplay,
1375
+ artifacts: result?.artifacts,
1376
+ // For TodoWriteTool fallback, try to extract args from the record
1377
+ // Note: args aren't stored in tool_result records by default
1378
+ args: void 0,
1379
+ timestamp: record.timestamp
1380
+ });
1381
+ const { resultDisplay } = result ?? {};
1382
+ if (!!resultDisplay && typeof resultDisplay === "object" && "type" in resultDisplay && resultDisplay.type === "task_execution") {
1383
+ await this.emitTaskUsageFromResultDisplay(
1384
+ resultDisplay
1240
1385
  );
1386
+ }
1387
+ }
1388
+ async failDanglingToolCalls() {
1389
+ let firstError;
1390
+ for (const pending of this.pendingReplayToolCalls.values()) {
1391
+ this.setActiveRecordId(pending.recordId, pending.timestamp);
1241
1392
  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
1393
+ await this.toolCallEmitter.emitResult({
1394
+ toolName: pending.toolName,
1395
+ callId: pending.callId,
1396
+ success: false,
1397
+ message: [],
1398
+ error: new Error(MISSING_TOOL_RESULT_MESSAGE),
1399
+ timestamp: pending.timestamp
1252
1400
  });
1253
1401
  } 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
- );
1402
+ firstError ??= error;
1403
+ } finally {
1404
+ this.setActiveRecordId(null);
1267
1405
  }
1268
1406
  }
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
- );
1407
+ if (firstError) {
1408
+ throw firstError;
1409
+ }
1277
1410
  }
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
- };
1411
+ /**
1412
+ * Emits token usage from a AgentResultDisplay execution summary, if present.
1413
+ */
1414
+ async emitTaskUsageFromResultDisplay(resultDisplay) {
1415
+ const summary = resultDisplay.executionSummary;
1416
+ if (!summary) {
1417
+ return;
1295
1418
  }
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" };
1419
+ const usageMetadata = {};
1420
+ if (Number.isFinite(summary.inputTokens)) {
1421
+ usageMetadata.promptTokenCount = summary.inputTokens;
1301
1422
  }
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
- );
1423
+ if (Number.isFinite(summary.outputTokens)) {
1424
+ usageMetadata.candidatesTokenCount = summary.outputTokens;
1425
+ }
1426
+ if (Number.isFinite(summary.thoughtTokens)) {
1427
+ usageMetadata.thoughtsTokenCount = summary.thoughtTokens;
1428
+ }
1429
+ if (Number.isFinite(summary.cachedTokens)) {
1430
+ usageMetadata.cachedContentTokenCount = summary.cachedTokens;
1431
+ }
1432
+ if (Number.isFinite(summary.totalTokens)) {
1433
+ usageMetadata.totalTokenCount = summary.totalTokens;
1434
+ }
1435
+ if (Object.keys(usageMetadata).length > 0) {
1436
+ await this.messageEmitter.emitUsageMetadata(usageMetadata);
1366
1437
  }
1367
1438
  }
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`
1439
+ /**
1440
+ * Replays a slash_command system record by re-emitting its output as an
1441
+ * agent message chunk. This allows Zed to reconstruct the correct turn
1442
+ * structure (user → agent) on session resume without polluting model context.
1443
+ */
1444
+ async replaySlashCommandResult(record) {
1445
+ const payload = record.systemPayload;
1446
+ if (payload?.phase !== "result" || !payload.outputHistoryItems?.length) {
1447
+ return;
1448
+ }
1449
+ for (const item of payload.outputHistoryItems) {
1450
+ const text = typeof item["text"] === "string" ? item["text"] : "";
1451
+ if (text) {
1452
+ await this.messageEmitter.emitSlashCommandOutput(
1453
+ text.replace(/\n/g, " \n"),
1454
+ record.timestamp
1383
1455
  );
1384
1456
  }
1385
- chunks.push(value);
1386
1457
  }
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
1458
  }
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;
1459
+ /**
1460
+ * Extracts tool name from a chat record's function response.
1461
+ */
1462
+ extractToolNameFromRecord(record) {
1463
+ if (record.message?.parts) {
1464
+ for (const part of record.message.parts) {
1465
+ if ("functionResponse" in part && part.functionResponse?.name) {
1466
+ return part.functionResponse.name;
1467
+ }
1468
+ }
1469
+ }
1470
+ return "";
1405
1471
  }
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);
1472
+ setActiveRecordId(recordId, timestamp) {
1473
+ const context = this.ctx;
1474
+ if (typeof context.setActiveRecordId === "function") {
1475
+ context.setActiveRecordId(recordId, timestamp);
1476
+ }
1413
1477
  }
1414
- }
1415
- __name(realpathOrResolve, "realpathOrResolve");
1478
+ };
1416
1479
 
1417
1480
  // packages/cli/src/ui/utils/export/collect.ts
1418
1481
  init_esbuild_shims();
@@ -1603,7 +1666,7 @@ async function extractMetadata(conversation, config) {
1603
1666
  const gitBranch = firstRecord?.gitBranch;
1604
1667
  let gitRepo;
1605
1668
  if (cwd) {
1606
- const { getGitRepoName } = await import("./src-BBQSM46M.js");
1669
+ const { getGitRepoName } = await import("./src-55DZWDAK.js");
1607
1670
  gitRepo = getGitRepoName(cwd);
1608
1671
  }
1609
1672
  let model;
@@ -2448,7 +2511,7 @@ export {
2448
2511
  };
2449
2512
  /**
2450
2513
  * @license
2451
- * Copyright 2025 Qwen
2514
+ * Copyright 2025 Google LLC
2452
2515
  * SPDX-License-Identifier: Apache-2.0
2453
2516
  */
2454
2517
  /**
@@ -2458,7 +2521,7 @@ export {
2458
2521
  */
2459
2522
  /**
2460
2523
  * @license
2461
- * Copyright 2025 Google LLC
2524
+ * Copyright 2025 Qwen
2462
2525
  * SPDX-License-Identifier: Apache-2.0
2463
2526
  */
2464
2527
  /**