@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.
- package/bundled/qc-helper/SKILL.md +1 -0
- package/bundled/qc-helper/docs/configuration/auth.md +40 -55
- package/bundled/qc-helper/docs/configuration/model-providers.md +224 -218
- package/bundled/qc-helper/docs/configuration/settings.md +61 -51
- package/bundled/qc-helper/docs/features/_meta.ts +1 -0
- package/bundled/qc-helper/docs/features/channels/dingtalk.md +12 -2
- package/bundled/qc-helper/docs/features/channels/overview.md +82 -7
- package/bundled/qc-helper/docs/features/channels/wecom.md +6 -0
- package/bundled/qc-helper/docs/features/code-review.md +109 -41
- package/bundled/qc-helper/docs/features/commands.md +45 -44
- package/bundled/qc-helper/docs/features/computer-use.md +77 -0
- package/bundled/qc-helper/docs/features/hooks.md +29 -0
- package/bundled/qc-helper/docs/features/tool-use-summaries.md +19 -23
- package/bundled/qc-helper/docs/integration-vscode.md +2 -2
- package/bundled/qc-helper/docs/qwen-serve.md +60 -22
- package/bundled/qc-helper/docs/reference/keyboard-shortcuts.md +2 -2
- package/bundled/review/DESIGN.md +303 -46
- package/bundled/review/SKILL.md +658 -165
- package/chunks/MaxSizedBox-QAYHOC4F.js +71 -0
- package/chunks/{StandaloneSessionPicker-EYRGH6PJ.js → StandaloneSessionPicker-D3R6YYX3.js} +82 -79
- package/chunks/{acpAgent-GRFTTRHW.js → acpAgent-ENHBW72A.js} +1178 -421
- package/chunks/agent-57LX4KMG.js +69 -0
- package/chunks/agent-headless-AC6EVNAP.js +63 -0
- package/chunks/{anthropicContentGenerator-CPF22MA7.js → anthropicContentGenerator-56U3YCP2.js} +187 -31
- package/chunks/{artifact-tool-D233YJFH.js → artifact-tool-BWZZJ42H.js} +5 -5
- package/chunks/{askUserQuestion-MKL5ZTMC.js → askUserQuestion-WU3S5A5T.js} +6 -6
- package/chunks/bridge-4OZH44MK.js +79 -0
- package/chunks/{ca-MKD32FQL.js → ca-C2JTT2N5.js} +68 -6
- package/chunks/channel-worker-group-K7QKH6IG.js +13 -0
- package/chunks/channel-worker-manager-5RWKSGEU.js +418 -0
- package/chunks/channel-worker-supervisor-PCDAZN4D.js +20 -0
- package/chunks/{chunk-CSOTA7KX.js → chunk-2FO5GFKZ.js} +2 -2
- package/chunks/{chunk-QQDPRDVW.js → chunk-2HRYPZT5.js} +1 -1
- package/chunks/{chunk-I6WGFJJ3.js → chunk-2MF6ICOL.js} +38 -12
- package/chunks/{chunk-X3YGAX7V.js → chunk-2UUAIFQO.js} +4 -2
- package/chunks/{chunk-2PSWA5ID.js → chunk-2X56YUSZ.js} +1 -1
- package/chunks/{chunk-NQKLOAVJ.js → chunk-2Z5UX4KI.js} +2 -2
- package/chunks/chunk-3MX7D6QN.js +516 -0
- package/chunks/{chunk-YDOXPLYL.js → chunk-4DYYRLIE.js} +3890 -975
- package/chunks/{chunk-OQXDAMKY.js → chunk-4FPUAYTT.js} +8 -8
- package/chunks/{chunk-55ZMG67I.js → chunk-4LD5APFL.js} +4 -4
- package/chunks/{chunk-YKZIAK7C.js → chunk-4LJNI7MU.js} +166 -37
- package/chunks/{chunk-BOBOCR5H.js → chunk-4QOPEEL2.js} +4 -4
- package/chunks/{chunk-UIDXQNMV.js → chunk-4WGODMVR.js} +1 -1
- package/chunks/{chunk-E6US47KI.js → chunk-4WKAA4KS.js} +1 -1
- package/chunks/{chunk-3GONHQOA.js → chunk-57OAHC2Y.js} +1 -1
- package/chunks/{chunk-JZSY4WP3.js → chunk-5DTTYNB7.js} +1 -1
- package/chunks/chunk-5HBA2Z7V.js +28 -0
- package/chunks/{chunk-SKAZWEV5.js → chunk-5M6IDOMF.js} +35 -98
- package/chunks/{chunk-A4BMJM77.js → chunk-5O2XNYP6.js} +1 -0
- package/chunks/{chunk-GO6LNQXT.js → chunk-6AM5D4ME.js} +1 -1
- package/chunks/{chunk-BJBWRCSK.js → chunk-6H67XLET.js} +1 -1
- package/chunks/{chunk-AYNCLGTW.js → chunk-6HHAADP2.js} +8 -51
- package/chunks/{chunk-VZ7HY3YU.js → chunk-6OATMEYN.js} +3 -3
- package/chunks/{chunk-3UP777ZS.js → chunk-6RLROE6G.js} +1 -1
- package/chunks/{chunk-ZERZSAZL.js → chunk-75DOP5OR.js} +2 -2
- package/chunks/{chunk-RMLZAUWH.js → chunk-7BIZARI2.js} +10 -12
- package/chunks/{chunk-GN3F6PIU.js → chunk-7NAWTFVY.js} +5 -5
- package/chunks/{chunk-22MNNNXE.js → chunk-7NFB7LBQ.js} +11 -3
- package/chunks/{chunk-ZL5HN75Q.js → chunk-7R4DPSRA.js} +37 -3
- package/chunks/{chunk-BVYU3ZTI.js → chunk-7U7UIO5W.js} +1005 -942
- package/chunks/{chunk-SAIILPQ3.js → chunk-7X7TEQNX.js} +5 -3
- package/chunks/{chunk-IRJWHZWU.js → chunk-A4UCTEB5.js} +2 -2
- package/chunks/{chunk-WF4FAXDL.js → chunk-AAS2Q2TV.js} +62 -62
- package/chunks/{chunk-O7FIRWJV.js → chunk-AAWKZ5R7.js} +3 -3
- package/chunks/{chunk-JCH35JB3.js → chunk-AGBFWLA5.js} +2 -2
- package/chunks/{chunk-QYUE6W3T.js → chunk-ALGGS7UH.js} +2 -39
- package/chunks/{chunk-WMPVYQ4P.js → chunk-ARKANCNX.js} +3 -2
- package/chunks/{chunk-HDOH3QYE.js → chunk-ASVORVFT.js} +2 -2
- package/chunks/{chunk-CHB5SLZZ.js → chunk-AUGSSJX3.js} +3 -3
- package/chunks/{chunk-PUVCVELY.js → chunk-B6ABUBYY.js} +4 -4
- package/chunks/{chunk-L4AMBVQG.js → chunk-B6KHOCU7.js} +49 -21
- package/chunks/{chunk-HW4N45EE.js → chunk-B7NUUEXC.js} +38 -11
- package/chunks/{chunk-CD6USWHZ.js → chunk-BBNVFRGD.js} +2 -2
- package/chunks/{chunk-ZN5T4BHI.js → chunk-BPZALHVR.js} +2 -2
- package/chunks/{chunk-VGGOPZUL.js → chunk-C4CXFRKY.js} +12 -5
- package/chunks/{chunk-OFEVLU4C.js → chunk-CARU2RR2.js} +1 -1
- package/chunks/{chunk-SQ2UATK7.js → chunk-CLTWL6HD.js} +11 -11
- package/chunks/{chunk-GLE2YUPU.js → chunk-COH43MRJ.js} +1 -1
- package/chunks/{chunk-E5A7LHNN.js → chunk-CPBF7KYF.js} +1 -1
- package/chunks/{chunk-UWCTAVOD.js → chunk-CR3C7WXL.js} +1 -1
- package/chunks/{chunk-DIWVZ3VM.js → chunk-CSACSGAW.js} +5 -5
- package/chunks/{chunk-5P5XGNYH.js → chunk-CU3L64TP.js} +1 -1
- package/chunks/{chunk-IWKSG2AR.js → chunk-CXAOG665.js} +1 -1
- package/chunks/{chunk-64WXLC72.js → chunk-DJ2GSRLV.js} +1 -1
- package/chunks/chunk-DKXW66XA.js +38 -0
- package/chunks/{chunk-QN5NZ3UQ.js → chunk-DMTGGOSA.js} +2 -2
- package/chunks/{chunk-JZHIQJOE.js → chunk-DMTQY5GY.js} +6 -6
- package/chunks/{chunk-GSHQYYIV.js → chunk-DNKX35GS.js} +6 -26
- package/chunks/{chunk-6IAWPIQ6.js → chunk-DPSWJWZI.js} +4 -3
- package/chunks/{chunk-X2XNQQJI.js → chunk-E2UVIFI2.js} +186 -399
- package/chunks/{chunk-KHDZHZMH.js → chunk-E5Z2AVNV.js} +1 -1
- package/chunks/{chunk-3B26UVCX.js → chunk-E67NFMF4.js} +39 -10
- package/chunks/{chunk-ON3JA3RU.js → chunk-EU3U7USF.js} +7 -9
- package/chunks/{chunk-L46XKEGM.js → chunk-EUNRLYJG.js} +5 -8
- package/chunks/{chunk-OACJLMLD.js → chunk-FBU7WRZI.js} +18 -2
- package/chunks/{chunk-5IFG2VC4.js → chunk-FCMNKVXT.js} +1 -1
- package/chunks/{chunk-A5JOJ77H.js → chunk-FDL4PB5H.js} +38 -15
- package/chunks/{chunk-E7KNELIZ.js → chunk-FSA7ERJ2.js} +2 -2
- package/chunks/{chunk-TI3BWD4D.js → chunk-G6QTKQN4.js} +39 -19
- package/chunks/{chunk-44NROQYV.js → chunk-GDQQRV43.js} +4 -4
- package/chunks/{chunk-O2YT7VB4.js → chunk-GOXKNSDZ.js} +2 -65
- package/chunks/{chunk-V35MD7KN.js → chunk-GRC5HGPI.js} +1 -1
- package/chunks/chunk-GYGGUR4Q.js +253 -0
- package/chunks/{chunk-S6RLAIUR.js → chunk-GYTKQYDB.js} +1 -1
- package/chunks/{chunk-A2X3KLC3.js → chunk-GZXCZHCT.js} +3 -3
- package/chunks/{chunk-K5PGHDBN.js → chunk-H6XPXXMH.js} +1 -1
- package/chunks/{chunk-E7EMCSUG.js → chunk-HE54PGVI.js} +64 -42
- package/chunks/{chunk-KYMBIKIW.js → chunk-HTHUX2T5.js} +1 -1
- package/chunks/{chunk-LQ7TMOCE.js → chunk-HTO4JFDZ.js} +1 -1
- package/chunks/chunk-HZYUNZDQ.js +296 -0
- package/chunks/chunk-IDS7MSUP.js +74 -0
- package/chunks/chunk-J2TDDOSM.js +493 -0
- package/chunks/{chunk-4CGOWHKM.js → chunk-J4MOFEOK.js} +2 -2
- package/chunks/{chunk-22IFUCVR.js → chunk-JESCGQM3.js} +1 -1
- package/chunks/chunk-JR63TOV4.js +91 -0
- package/chunks/chunk-K3PPUB46.js +445 -0
- package/chunks/{chunk-42XGFRJS.js → chunk-KKRTYONM.js} +8 -6
- package/chunks/{chunk-GGQQA4JW.js → chunk-KSO42X3Z.js} +15 -2
- package/chunks/{chunk-MRO43B25.js → chunk-KW7NOTN6.js} +1 -1
- package/chunks/{chunk-54YZOP7P.js → chunk-L573Z2QZ.js} +11894 -5190
- package/chunks/{chunk-TLWA7TPR.js → chunk-L5U3ELZX.js} +2 -2
- package/chunks/{chunk-WHJQ3JUS.js → chunk-LAM6CGP5.js} +10 -10
- package/chunks/{chunk-H6EMK6QK.js → chunk-LQIDP6K5.js} +11913 -5207
- package/chunks/{chunk-MZ7BABX3.js → chunk-LXLTBIDP.js} +44 -7
- package/chunks/{chunk-HLKG6CZN.js → chunk-M5GB774H.js} +1 -1
- package/chunks/{chunk-EEN2TKST.js → chunk-MBJ3D6SF.js} +2 -2
- package/chunks/{chunk-PMFULMLX.js → chunk-MBP3K324.js} +2234 -377
- package/chunks/chunk-MR3PXB6E.js +48 -0
- package/chunks/{chunk-ZE6E424U.js → chunk-N7FCSERB.js} +2 -2
- package/chunks/{chunk-332PWN27.js → chunk-NHDKSOEY.js} +1 -1
- package/chunks/chunk-OATTJGPJ.js +448 -0
- package/chunks/{chunk-UX6OTBVD.js → chunk-OCC3UTWA.js} +2 -2
- package/chunks/{chunk-P7M4GA57.js → chunk-OCPBI7J5.js} +1 -1
- package/chunks/chunk-OJAMDVF5.js +66 -0
- package/chunks/{chunk-IJRL2S3D.js → chunk-OKAIGAYW.js} +6 -6
- package/chunks/{chunk-WQTHLB5T.js → chunk-P3S67A5R.js} +7 -7
- package/chunks/{chunk-FBET5XZ2.js → chunk-PEJWA3QQ.js} +29 -10
- package/chunks/{chunk-J7RCB6N5.js → chunk-PHYCWSDG.js} +2 -2
- package/chunks/{chunk-LAXNEOBG.js → chunk-PMRH4YYW.js} +18 -3
- package/chunks/{chunk-AGHU5VRK.js → chunk-PZL23GTM.js} +1 -1
- package/chunks/{chunk-PC4ZXHU2.js → chunk-Q6TUALBE.js} +3 -3
- package/chunks/{chunk-FXGLL2HL.js → chunk-Q7YDKOGY.js} +1 -1
- package/chunks/{chunk-P3XEEI3X.js → chunk-QABSSDQH.js} +36 -7
- package/chunks/{chunk-XOHNA2S6.js → chunk-QAW7PIHT.js} +3 -3
- package/chunks/{chunk-LGFAYIKX.js → chunk-QHTIBUWB.js} +1 -1
- package/chunks/{chunk-P3MYAZBY.js → chunk-QMGX2KO2.js} +1 -1
- package/chunks/{chunk-Z3I3QJK3.js → chunk-QRUIS3DN.js} +1 -1
- package/chunks/{chunk-ITOGNELQ.js → chunk-QSWDGAIC.js} +2 -2
- package/chunks/{chunk-GHOTR7HL.js → chunk-QUPXZXLV.js} +1 -1
- package/chunks/{chunk-W7EEOR7D.js → chunk-RCEEXIOO.js} +8 -6
- package/chunks/{chunk-2EM7ECZD.js → chunk-RJL5T4WJ.js} +281 -65
- package/chunks/{chunk-TLRYABYP.js → chunk-RKUWKYED.js} +1 -1
- package/chunks/{chunk-RNBYOUGV.js → chunk-RXFQM6FQ.js} +1 -1
- package/chunks/{chunk-JRQ7EVGE.js → chunk-S2QXYLUB.js} +2 -2
- package/chunks/{chunk-QXPI7FEC.js → chunk-S3TWXGKA.js} +4 -4
- package/chunks/{chunk-O33TBKDC.js → chunk-SE74CIZD.js} +155 -19
- package/chunks/{chunk-FV7425LN.js → chunk-SPJQO2CE.js} +18 -5
- package/chunks/{chunk-3GNOQZDC.js → chunk-SSFDPGFN.js} +11866 -11542
- package/chunks/{chunk-DCZWC4PF.js → chunk-SUWGUGAD.js} +5 -5
- package/chunks/{chunk-IBY3Q3HG.js → chunk-SXU3KKNI.js} +963 -181
- package/chunks/{chunk-MLZQVCF3.js → chunk-SZRN75WQ.js} +1 -1
- package/chunks/{chunk-M7S4GK5Z.js → chunk-T2L6SGQY.js} +115 -29
- package/chunks/{chunk-7RYW5LQV.js → chunk-T2NCM2ET.js} +2 -2
- package/chunks/{chunk-JPALE3PA.js → chunk-T5C2OUCI.js} +6 -6
- package/chunks/{chunk-BUZ6HGL4.js → chunk-T7FSRWQ5.js} +248 -55
- package/chunks/{chunk-Z2Z3GUXZ.js → chunk-TB6UDU4T.js} +1 -1
- package/chunks/{chunk-EXPMGZZV.js → chunk-TEGEBB2I.js} +1 -1
- package/chunks/{chunk-MX2YXRER.js → chunk-TJTKSVIV.js} +1 -1
- package/chunks/{chunk-CCGOFQV3.js → chunk-TQBODCFD.js} +8 -7
- package/chunks/chunk-TV6K2FB4.js +224 -0
- package/chunks/{chunk-5MBO76SL.js → chunk-TXY2C3D2.js} +3 -3
- package/chunks/{chunk-H6BD2ELD.js → chunk-TYAMGABM.js} +2 -2
- package/chunks/{chunk-QYNNN7BK.js → chunk-TYLOFD2U.js} +2 -2
- package/chunks/{chunk-VRDMOSQS.js → chunk-UDXSXLER.js} +2 -2
- package/chunks/{chunk-UXEW557D.js → chunk-UI3W56WF.js} +3 -3
- package/chunks/{chunk-CJCKDMWO.js → chunk-URK542T4.js} +1 -1
- package/chunks/{channel-worker-supervisor-NZQUOEFJ.js → chunk-URU5UEK6.js} +190 -34
- package/chunks/{chunk-AHNXYU4O.js → chunk-V6WHFGST.js} +1 -1
- package/chunks/chunk-V75IOTWF.js +71 -0
- package/chunks/{chunk-ZTQ26VBE.js → chunk-VDDGDZMA.js} +1 -1
- package/chunks/{chunk-OMX7CUOE.js → chunk-VGC4I5JJ.js} +1 -1
- package/chunks/{chunk-43W4YSO6.js → chunk-VJNBRRZG.js} +2 -2
- package/chunks/{chunk-ER3BKOLB.js → chunk-W7FJ3N32.js} +1 -1
- package/chunks/{chunk-3HX5LZ6R.js → chunk-WBL3FJEU.js} +2 -2
- package/chunks/{chunk-7LTB54MK.js → chunk-WIEO4CWB.js} +2 -2
- package/chunks/{chunk-BMFMJINR.js → chunk-WL4L7EZH.js} +1 -1
- package/chunks/{chunk-6VK6FIMQ.js → chunk-WM5HY72H.js} +415 -379
- package/chunks/{chunk-BOBRZZKD.js → chunk-WN4D7YCI.js} +5 -5
- package/chunks/{chunk-DHOLNQLC.js → chunk-WWQ3QIJS.js} +60 -40
- package/chunks/{chunk-FEJ2FZ3U.js → chunk-WX6SD4IQ.js} +2 -2
- package/chunks/{chunk-DICGXFAI.js → chunk-X7EBAABW.js} +11 -9
- package/chunks/{chunk-3RW4AZJV.js → chunk-XFSFZCM5.js} +1 -1
- package/chunks/{chunk-YHKAK72D.js → chunk-XHW5VUIQ.js} +102 -16
- package/chunks/{chunk-2MPVVENX.js → chunk-XU457J4V.js} +2 -2
- package/chunks/{chunk-SIUQ3YYX.js → chunk-XVNQMZ2I.js} +1 -1
- package/chunks/{chunk-SYCJMSIJ.js → chunk-XWRJCPHC.js} +1 -1
- package/chunks/{chunk-SUAKHHK7.js → chunk-Y66VOBRP.js} +3 -3
- package/chunks/chunk-YAF2MQZ6.js +19 -0
- package/chunks/{chunk-FQNC62B2.js → chunk-YH4J5XI3.js} +11 -11
- package/chunks/chunk-YHN5SUIJ.js +219 -0
- package/chunks/{chunk-BR4QREVK.js → chunk-YQ3U5MUC.js} +1 -1
- package/chunks/{chunk-Y6Z2O3WR.js → chunk-YUZI3WAC.js} +1 -1
- package/chunks/{chunk-II73RK2S.js → chunk-YVEDCAUE.js} +1 -1
- package/chunks/{chunk-XYR5RUA5.js → chunk-YWUK7OS7.js} +10 -3
- package/chunks/{chunk-27BHARDE.js → chunk-Z56JO4JZ.js} +2124 -30
- package/chunks/{chunk-TSPB77TG.js → chunk-ZLM3KXBT.js} +1015 -2967
- package/chunks/{chunk-AHNJGLFV.js → chunk-ZPAHLFZU.js} +3 -3
- package/chunks/chunk-ZRKBI3DP.js +34 -0
- package/chunks/cli-entry-path-4VJ3Y6T2.js +10 -0
- package/chunks/{computer-use-WMY3UOBX.js → computer-use-DIP5BWXP.js} +51 -50
- package/chunks/config-utils-CFT33LTP.js +24 -0
- package/chunks/contextCommand-QU4GJWWD.js +69 -0
- package/chunks/create-sub-session-TCLIYVGR.js +376 -0
- package/chunks/create-sub-session-WNX2OQVX.js +207 -0
- package/chunks/{cron-create-JSXEIPVS.js → cron-create-36TIFKRT.js} +9 -9
- package/chunks/{cron-delete-OIFVEPGU.js → cron-delete-OQD3WULU.js} +7 -7
- package/chunks/{cron-list-D4ZX4IOE.js → cron-list-4533T2FH.js} +14 -10
- package/chunks/{daemon-WPAENEBW.js → daemon-CEZ27OH4.js} +734 -24
- package/chunks/daemon-status-provider-SIBFMLBQ.js +77 -0
- package/chunks/{de-ZFPPQVSF.js → de-2VCDRDGU.js} +68 -6
- package/chunks/{devtools-FM6GJPYG.js → devtools-4QFYJT6U.js} +3 -3
- package/chunks/{dist-E6UANPIM.js → dist-3V3ZV6ML.js} +1011 -197
- package/chunks/{dist-SCFLLYMK.js → dist-ERCPDVA6.js} +12 -11
- package/chunks/{dist-Z34QPAQW.js → dist-HNN7DR2L.js} +529 -79
- package/chunks/{dist-O2IRTRPP.js → dist-JZE7F6YR.js} +10 -10
- package/chunks/{dist-BEXOZXLQ.js → dist-MOEC47TR.js} +36 -15
- package/chunks/{dist-H2AEJCZ5.js → dist-PHEPJLXD.js} +5 -5
- package/chunks/{dist-63IS3ZMI.js → dist-PZV5RKM6.js} +4 -4
- package/chunks/earlyInputCapture-L66BEG2C.js +70 -0
- package/chunks/{edit-OTYWAXGP.js → edit-Y5LAJSST.js} +52 -51
- package/chunks/{en-N4EPZAQI.js → en-NJCA3TAA.js} +78 -6
- package/chunks/{enter-worktree-HNYBDVCX.js → enter-worktree-X5LML7T4.js} +51 -50
- package/chunks/{enterPlanMode-CJCNGT63.js → enterPlanMode-XWF32QOW.js} +67 -51
- package/chunks/environment-YVMA5F4I.js +90 -0
- package/chunks/errors-4Y5SUAOC.js +76 -0
- package/chunks/{exit-worktree-DUUKOE3X.js → exit-worktree-SFHU7XYC.js} +51 -50
- package/chunks/{exitPlanMode-AMMSXOAJ.js → exitPlanMode-FP3NAN6E.js} +52 -51
- package/chunks/{fast-path-OV6NIP3K.js → fast-path-ZJNFFCBM.js} +8 -8
- package/chunks/{fast-path-settings-7RIFI3PK.js → fast-path-settings-DAOVFADC.js} +8 -6
- package/chunks/{fileFromPath-IBEHA3CO.js → fileFromPath-UDALK7FM.js} +3 -3
- package/chunks/{fr-5WWMY53B.js → fr-5F3E7WKD.js} +68 -6
- package/chunks/{gemini-NQ3WWBKB.js → gemini-5CAB22BI.js} +122 -109
- package/chunks/{geminiContentGenerator-CDUNEJQE.js → geminiContentGenerator-GE3HPIFB.js} +9 -9
- package/chunks/{getMachineId-bsd-4CASPIU4.js → getMachineId-bsd-EXV7SWPA.js} +3 -3
- package/chunks/{getMachineId-darwin-HPQPEMZR.js → getMachineId-darwin-IUOMFXU3.js} +3 -3
- package/chunks/{getMachineId-linux-AUARKYHL.js → getMachineId-linux-K7XJYFHL.js} +2 -2
- package/chunks/{getMachineId-unsupported-S32ZDA2T.js → getMachineId-unsupported-EA5FDRJ6.js} +2 -2
- package/chunks/{getMachineId-win-4EFLHYIJ.js → getMachineId-win-KBA6RAI5.js} +3 -3
- package/chunks/{glob-ROV3YS4R.js → glob-YPACZAEL.js} +98 -75
- package/chunks/{grep-NRITKDCD.js → grep-IPR4XW37.js} +51 -50
- package/chunks/handleAutoUpdate-P2KEP56V.js +70 -0
- package/chunks/i18n-BRCT66AA.js +85 -0
- package/chunks/initializer-34HXSK3A.js +74 -0
- package/chunks/installationInfo-WOTDQMSC.js +66 -0
- package/chunks/{ja-CUHZOLEJ.js → ja-66J6B53L.js} +69 -7
- package/chunks/{keychain-token-storage-UJV5XP4Z.js → keychain-token-storage-AU22CQI6.js} +4 -4
- package/chunks/{kittyProtocolDetector-OJRCJLIU.js → kittyProtocolDetector-HCNNKJTI.js} +2 -2
- package/chunks/list-XOGP7UPP.js +77 -0
- package/chunks/loadedSettingsAdapter-L4YKGU6F.js +71 -0
- package/chunks/{loop-wakeup-OHWEMFP5.js → loop-wakeup-MVUKDVCP.js} +10 -10
- package/chunks/{lowlight-FYAAUU5J.js → lowlight-J2OZNPCA.js} +1 -1
- package/chunks/{ls-7MFU2QYW.js → ls-RXNIAQDE.js} +6 -6
- package/chunks/{lsp-XHDTPTGV.js → lsp-HB5LM5IL.js} +4 -4
- package/chunks/mcp-HH7DIP7Y.js +71 -0
- package/chunks/{monitor-FL2ZO33W.js → monitor-25DEBT6U.js} +51 -50
- package/chunks/{multipart-parser-AJ4WASWR.js → multipart-parser-AWZKXSQN.js} +3 -3
- package/chunks/nonInteractiveCli-CT3VSSLK.js +130 -0
- package/chunks/{notebook-edit-6PULTHL5.js → notebook-edit-TAVXSWQ6.js} +52 -51
- package/chunks/openaiContentGenerator-6I7DKUAN.js +56 -0
- package/chunks/pidfile-SIQGCFLZ.js +74 -0
- package/chunks/{pt-OLYN42DS.js → pt-TFZO5Y6T.js} +68 -6
- package/chunks/{qwenContentGenerator-NX2E7PB7.js → qwenContentGenerator-5DDIXI2N.js} +53 -52
- package/chunks/{qwenOAuth2-ZV7YLMND.js → qwenOAuth2-LEYOU7RU.js} +9 -9
- package/chunks/read-file-WDOAYRFU.js +30 -0
- package/chunks/{read-mcp-resource-CNQHBSJM.js → read-mcp-resource-6LRTZKXI.js} +5 -5
- package/chunks/{read-package-up-ER5OJUGP.js → read-package-up-TCM6I7S2.js} +2 -2
- package/chunks/{record-artifact-SQ2OKRJW.js → record-artifact-PMDTY4OS.js} +4 -4
- package/chunks/ripGrep-MI7PHN3Q.js +61 -0
- package/chunks/{ru-LDM3GWVQ.js → ru-4L4LFHIT.js} +68 -6
- package/chunks/{run-qwen-serve-JK2DL7PI.js → run-qwen-serve-PNTYF3RE.js} +1289 -256
- package/chunks/runtime-V3FBMUTG.js +100 -0
- package/chunks/{scheduler-O4IGVZKK.js → scheduler-4TAUIJBM.js} +52 -51
- package/chunks/{send-message-76GT3JMC.js → send-message-SR4WSXP2.js} +7 -7
- package/chunks/serve-WB2TR7XM.js +77 -0
- package/chunks/{server-SGNPKX2O.js → server-AF6LNFPK.js} +8094 -2800
- package/chunks/{session-5BNM25EZ.js → session-BIGK4NRW.js} +341 -135
- package/chunks/settings-IXF5FIQO.js +121 -0
- package/chunks/shell-5VWJ2PPG.js +69 -0
- package/chunks/{skill-I22QK5XS.js → skill-SI667Y3B.js} +24 -24
- package/chunks/spawnChannel-IKX6DD7J.js +71 -0
- package/chunks/{src-BBQSM46M.js → src-55DZWDAK.js} +151 -52
- package/chunks/{src-7XL4G4DC.js → src-VLI3TKEY.js} +4 -4
- package/chunks/standalone-update-MHLSFHE6.js +80 -0
- package/chunks/{startInteractiveUI-JII36UGN.js → startInteractiveUI-V2EDWLAX.js} +2239 -1846
- package/chunks/stdioHelpers-UMY72QRP.js +14 -0
- package/chunks/{syntheticOutput-F7LSDCAR.js → syntheticOutput-YKFNUQZD.js} +5 -5
- package/chunks/task-create-NUFOHU53.js +23 -0
- package/chunks/{task-list-TGGJX7EA.js → task-list-Z2IKQY3S.js} +11 -10
- package/chunks/{task-stop-W7NGTMYQ.js → task-stop-KQFIVQTJ.js} +4 -4
- package/chunks/{task-update-XYWMHJGJ.js → task-update-HKADXSTD.js} +13 -12
- package/chunks/{team-create-A7NUU5AQ.js → team-create-IZAMLBJS.js} +51 -50
- package/chunks/{team-delete-UHQQ2QQX.js → team-delete-SDNTGZLG.js} +11 -10
- package/chunks/{team-plan-approval-TOQRJ2KI.js → team-plan-approval-3R4RCKCP.js} +51 -50
- package/chunks/theme-manager-LCOXZ5DO.js +65 -0
- package/chunks/{todoWrite-C4ZAMSR3.js → todoWrite-YNXB27GB.js} +6 -6
- package/chunks/{tool-search-SZ4EFS2T.js → tool-search-NYNCD5LF.js} +24 -24
- package/chunks/total-session-admission-PJWGOMQE.js +73 -0
- package/chunks/tree-sitter-YJVE2ZUK.js +2980 -0
- package/chunks/trustedFolders-DOJDHNYP.js +81 -0
- package/chunks/{types-QX5C3CHJ.js → types-JNKGKUJT.js} +2 -2
- package/chunks/updateCheck-ZXL66KIG.js +70 -0
- package/chunks/updateEventEmitter-5MKC7BLQ.js +10 -0
- package/chunks/validateNonInterActiveAuth-JSNJZCYY.js +195 -0
- package/chunks/{version-NO2XSNNP.js → version-3NLBENG5.js} +3 -3
- package/chunks/{web-fetch-UYGMOHW4.js → web-fetch-ZSPR3PRR.js} +8 -8
- package/chunks/{workflow-WO2H6NRI.js → workflow-BQYLF7XP.js} +52 -51
- package/chunks/workspace-providers-status-FA2DGEZW.js +74 -0
- package/chunks/workspace-registration-store-TARTAGMI.js +27 -0
- package/chunks/workspace-registry-AGE7WAXX.js +77 -0
- package/chunks/workspace-service-ERC5VR2B.js +83 -0
- package/chunks/workspace-skills-status-FKYWGNCN.js +73 -0
- package/chunks/{write-file-PX2Z7IBE.js → write-file-S47KSK7Z.js} +52 -51
- package/chunks/{yargs-B64EYTCF.js → yargs-6H2AUULL.js} +2 -2
- package/chunks/{zh-J4F6QWQV.js → zh-FSAH32JB.js} +79 -7
- package/chunks/{zh-TW-XVDWOLSW.js → zh-TW-D2YIE2LO.js} +79 -7
- package/cli.js +18 -17
- package/locales/ca.js +91 -7
- package/locales/de.js +90 -7
- package/locales/en.js +109 -7
- package/locales/fr.js +91 -7
- package/locales/ja.js +93 -7
- package/locales/pt.js +90 -7
- package/locales/ru.js +90 -7
- package/locales/zh-TW.js +106 -7
- package/locales/zh.js +106 -7
- package/package.json +3 -6
- package/web-shell/assets/{arc-BWyoJpY2.js → arc-Zj4EkBUY.js} +1 -1
- package/web-shell/assets/{architectureDiagram-3BPJPVTR-BT0mGrz2.js → architectureDiagram-3BPJPVTR-DAk1Ua3Y.js} +1 -1
- package/web-shell/assets/{blockDiagram-GPEHLZMM-BLgUWvyf.js → blockDiagram-GPEHLZMM-DBNqUthM.js} +1 -1
- package/web-shell/assets/{c4Diagram-AAUBKEIU-DYx9M7oU.js → c4Diagram-AAUBKEIU-Dq5QGJ53.js} +1 -1
- package/web-shell/assets/channel-DWfYijFS.js +1 -0
- package/web-shell/assets/{chunk-2J33WTMH-CfMHWbuZ.js → chunk-2J33WTMH-DY0AeGru.js} +1 -1
- package/web-shell/assets/{chunk-4BX2VUAB-B1URoqEV.js → chunk-4BX2VUAB-COX3OyIi.js} +1 -1
- package/web-shell/assets/{chunk-55IACEB6-DAIaM4QF.js → chunk-55IACEB6-Csoyddbh.js} +1 -1
- package/web-shell/assets/{chunk-727SXJPM-B2X34knw.js → chunk-727SXJPM-BJPONdxX.js} +1 -1
- package/web-shell/assets/{chunk-AQP2D5EJ-Cif-zLTQ.js → chunk-AQP2D5EJ-syLVH6fg.js} +1 -1
- package/web-shell/assets/{chunk-FMBD7UC4-H18WCXdY.js → chunk-FMBD7UC4-Cfm59Nhw.js} +1 -1
- package/web-shell/assets/{chunk-ND2GUHAM-YFtetHi0.js → chunk-ND2GUHAM-DZf6tAqS.js} +1 -1
- package/web-shell/assets/{chunk-QZHKN3VN-By2hiH3r.js → chunk-QZHKN3VN-DKBp_v5q.js} +1 -1
- package/web-shell/assets/classDiagram-4FO5ZUOK-DDht-78J.js +1 -0
- package/web-shell/assets/classDiagram-v2-Q7XG4LA2-DDht-78J.js +1 -0
- package/web-shell/assets/{cose-bilkent-S5V4N54A-VrcnnLZu.js → cose-bilkent-S5V4N54A-DUU3mMQ5.js} +1 -1
- package/web-shell/assets/{dagre-BM42HDAG-CGo-IaVV.js → dagre-BM42HDAG-BUgNfbh-.js} +1 -1
- package/web-shell/assets/{diagram-2AECGRRQ-Dl4QjzIB.js → diagram-2AECGRRQ-DT7MVfAg.js} +1 -1
- package/web-shell/assets/{diagram-5GNKFQAL-qMLmsO0u.js → diagram-5GNKFQAL-Cv4YG-ec.js} +1 -1
- package/web-shell/assets/{diagram-KO2AKTUF-CHlmuxPI.js → diagram-KO2AKTUF-BAe9LLkn.js} +1 -1
- package/web-shell/assets/{diagram-LMA3HP47-BUwU3GwT.js → diagram-LMA3HP47-DW8wqTIP.js} +1 -1
- package/web-shell/assets/{diagram-OG6HWLK6-HEhwPDUM.js → diagram-OG6HWLK6-CmkuWbaK.js} +1 -1
- package/web-shell/assets/{erDiagram-TEJ5UH35-1n0llBmM.js → erDiagram-TEJ5UH35-DwvdHjZ9.js} +1 -1
- package/web-shell/assets/{flowDiagram-I6XJVG4X-BN74uMnt.js → flowDiagram-I6XJVG4X-CSsXrhW_.js} +1 -1
- package/web-shell/assets/{ganttDiagram-6RSMTGT7-BoOq78i3.js → ganttDiagram-6RSMTGT7-BtuznCdi.js} +3 -3
- package/web-shell/assets/{gitGraphDiagram-PVQCEYII-CN8b00c8.js → gitGraphDiagram-PVQCEYII-DGmAm06g.js} +1 -1
- package/web-shell/assets/index-B9Xwf4OS.css +5 -0
- package/web-shell/assets/index-BEtz1cvN.js +3 -0
- package/web-shell/assets/index-BUkM4ZXX.js +1088 -0
- package/web-shell/assets/{infoDiagram-5YYISTIA-CCurnIna.js → infoDiagram-5YYISTIA-OAiZ1q0K.js} +1 -1
- package/web-shell/assets/{ishikawaDiagram-YF4QCWOH-AwuRqdUP.js → ishikawaDiagram-YF4QCWOH-DyK0KTIT.js} +1 -1
- package/web-shell/assets/{journeyDiagram-JHISSGLW-B7IICk-E.js → journeyDiagram-JHISSGLW-DzYJlwfO.js} +1 -1
- package/web-shell/assets/{kanban-definition-UN3LZRKU-BYF0OKhx.js → kanban-definition-UN3LZRKU-CU_tcDwi.js} +1 -1
- package/web-shell/assets/{linear-GWWguGfD.js → linear-DvZXjF17.js} +1 -1
- package/web-shell/assets/{mermaid.core-JqtkxvCl.js → mermaid.core-_ZFEQlOl.js} +5 -5
- package/web-shell/assets/{mindmap-definition-RKZ34NQL-B0MmHsZ6.js → mindmap-definition-RKZ34NQL-Or4p64HB.js} +1 -1
- package/web-shell/assets/{pieDiagram-4H26LBE5-DhImUZLQ.js → pieDiagram-4H26LBE5-lXE-zZ6b.js} +1 -1
- package/web-shell/assets/{quadrantDiagram-W4KKPZXB-DGeSC3DT.js → quadrantDiagram-W4KKPZXB-DUXb9mUV.js} +1 -1
- package/web-shell/assets/{requirementDiagram-4Y6WPE33-DkspY6Re.js → requirementDiagram-4Y6WPE33-D_10uHfo.js} +1 -1
- package/web-shell/assets/{sankeyDiagram-5OEKKPKP-CaOofS2x.js → sankeyDiagram-5OEKKPKP-E8c0fPqe.js} +1 -1
- package/web-shell/assets/{sequenceDiagram-3UESZ5HK-DFQ_kFnN.js → sequenceDiagram-3UESZ5HK-CJMtFttK.js} +1 -1
- package/web-shell/assets/{stateDiagram-AJRCARHV-D3snw0Tz.js → stateDiagram-AJRCARHV-DhbviRbB.js} +1 -1
- package/web-shell/assets/stateDiagram-v2-BHNVJYJU-CntljfwW.js +1 -0
- package/web-shell/assets/{timeline-definition-PNZ67QCA-l4zH8nLM.js → timeline-definition-PNZ67QCA-CM5yMkFK.js} +1 -1
- package/web-shell/assets/{vennDiagram-CIIHVFJN-BnRlA98M.js → vennDiagram-CIIHVFJN-BCi-zWNN.js} +1 -1
- package/web-shell/assets/{wardley-L42UT6IY-BS0xUdmd.js → wardley-L42UT6IY-BJ_yJNjJ.js} +1 -1
- package/web-shell/assets/{wardleyDiagram-YWT4CUSO-DKGBUWyQ.js → wardleyDiagram-YWT4CUSO-TjtLk-qN.js} +1 -1
- package/web-shell/assets/{xychartDiagram-2RQKCTM6-DVb2HuOB.js → xychartDiagram-2RQKCTM6-D1TjyoQ3.js} +1 -1
- package/web-shell/index.html +16 -4
- package/chunks/MaxSizedBox-5DT2SD7B.js +0 -71
- package/chunks/agent-H2DGKS77.js +0 -68
- package/chunks/agent-headless-KFMFIT6J.js +0 -62
- package/chunks/bridge-NA3ZQQKJ.js +0 -78
- package/chunks/chunk-6SHO7WFF.js +0 -79
- package/chunks/chunk-IFEWJXFS.js +0 -37
- package/chunks/chunk-XNXVCNAT.js +0 -88
- package/chunks/contextCommand-LXFZRP4L.js +0 -68
- package/chunks/daemon-status-provider-GJRXY5EN.js +0 -76
- package/chunks/earlyInputCapture-KNOYZ4MJ.js +0 -69
- package/chunks/environment-ATFTYMLZ.js +0 -88
- package/chunks/errors-A54HAADA.js +0 -75
- package/chunks/handleAutoUpdate-CEZJAARW.js +0 -65
- package/chunks/initializer-BRFJKRRX.js +0 -71
- package/chunks/list-KVHF7O4X.js +0 -73
- package/chunks/loadedSettingsAdapter-LL5PSFKX.js +0 -68
- package/chunks/mcp-3GCXRTOQ.js +0 -68
- package/chunks/nonInteractiveCli-PTQI3DV6.js +0 -119
- package/chunks/openaiContentGenerator-YE42PKCY.js +0 -56
- package/chunks/pidfile-NZYSCFRK.js +0 -73
- package/chunks/read-file-33XGP5HF.js +0 -30
- package/chunks/ripGrep-QWZLGTAN.js +0 -60
- package/chunks/serve-JTMIGANH.js +0 -74
- package/chunks/settings-3MI4XXP6.js +0 -118
- package/chunks/shell-YJKBE67T.js +0 -68
- package/chunks/spawnChannel-UNV6W4DU.js +0 -70
- package/chunks/task-create-WCHTB435.js +0 -22
- package/chunks/theme-manager-WZ4RRMMB.js +0 -64
- package/chunks/total-session-admission-ULXJWXFV.js +0 -72
- package/chunks/trustedFolders-LAZZPZ3D.js +0 -79
- package/chunks/updateCheck-KONLM73X.js +0 -65
- package/chunks/validateNonInterActiveAuth-MPKSRCXD.js +0 -184
- package/chunks/workspace-providers-status-3W7E7DFW.js +0 -71
- package/chunks/workspace-registry-SXJZNN3O.js +0 -74
- package/chunks/workspace-service-CZRQZ4Q4.js +0 -80
- package/chunks/workspace-skills-status-K7WFREPD.js +0 -70
- package/node_modules/@qwen-code/audio-capture/dist/index.d.ts +0 -35
- package/node_modules/@qwen-code/audio-capture/dist/index.js +0 -48
- package/node_modules/@qwen-code/audio-capture/dist/index.js.map +0 -1
- package/node_modules/@qwen-code/audio-capture/dist/platform.d.ts +0 -7
- package/node_modules/@qwen-code/audio-capture/dist/platform.js +0 -18
- package/node_modules/@qwen-code/audio-capture/dist/platform.js.map +0 -1
- package/node_modules/@qwen-code/audio-capture/node_modules/node-gyp-build/LICENSE +0 -21
- package/node_modules/@qwen-code/audio-capture/node_modules/node-gyp-build/README.md +0 -58
- package/node_modules/@qwen-code/audio-capture/node_modules/node-gyp-build/SECURITY.md +0 -5
- package/node_modules/@qwen-code/audio-capture/node_modules/node-gyp-build/bin.js +0 -84
- package/node_modules/@qwen-code/audio-capture/node_modules/node-gyp-build/build-test.js +0 -19
- package/node_modules/@qwen-code/audio-capture/node_modules/node-gyp-build/index.js +0 -6
- package/node_modules/@qwen-code/audio-capture/node_modules/node-gyp-build/node-gyp-build.js +0 -207
- package/node_modules/@qwen-code/audio-capture/node_modules/node-gyp-build/optional.js +0 -7
- package/node_modules/@qwen-code/audio-capture/node_modules/node-gyp-build/package.json +0 -43
- package/node_modules/@qwen-code/audio-capture/package.json +0 -30
- package/node_modules/@qwen-code/audio-capture/prebuilds/darwin-arm64/@qwen-code+audio-capture.node +0 -0
- package/node_modules/@qwen-code/audio-capture/prebuilds/darwin-x64/@qwen-code+audio-capture.node +0 -0
- package/node_modules/@qwen-code/audio-capture/prebuilds/linux-arm64/@qwen-code+audio-capture.node +0 -0
- package/node_modules/@qwen-code/audio-capture/prebuilds/linux-x64/@qwen-code+audio-capture.node +0 -0
- package/node_modules/@qwen-code/audio-capture/prebuilds/win32-x64/@qwen-code+audio-capture.node +0 -0
- package/web-shell/assets/channel-wmPUGHtg.js +0 -1
- package/web-shell/assets/classDiagram-4FO5ZUOK-BA2ljEjW.js +0 -1
- package/web-shell/assets/classDiagram-v2-Q7XG4LA2-BA2ljEjW.js +0 -1
- package/web-shell/assets/index-CNwoO1Cn.js +0 -783
- package/web-shell/assets/index-CWQ0z6kZ.css +0 -5
- 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-
|
|
9
|
+
} from "./chunk-L573Z2QZ.js";
|
|
6
10
|
import {
|
|
7
11
|
writeStderrLine
|
|
8
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-YUZI3WAC.js";
|
|
9
13
|
import {
|
|
10
14
|
getActiveGoal
|
|
11
|
-
} from "./chunk-
|
|
15
|
+
} from "./chunk-SSFDPGFN.js";
|
|
12
16
|
import {
|
|
13
17
|
ToolNames
|
|
14
|
-
} from "./chunk-
|
|
18
|
+
} from "./chunk-2UUAIFQO.js";
|
|
15
19
|
import {
|
|
16
20
|
createDebugLogger
|
|
17
|
-
} from "./chunk-
|
|
21
|
+
} from "./chunk-7NFB7LBQ.js";
|
|
18
22
|
import {
|
|
19
23
|
init_esbuild_shims
|
|
20
|
-
} from "./chunk-
|
|
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/
|
|
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/
|
|
36
|
+
// packages/cli/src/utils/gitUtils.ts
|
|
33
37
|
init_esbuild_shims();
|
|
34
|
-
var
|
|
35
|
-
|
|
36
|
-
|
|
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
|
-
|
|
39
|
-
|
|
72
|
+
}, "isGitHubRepositoryAsync");
|
|
73
|
+
function isGitHubRemoteUrl(remoteUrl) {
|
|
74
|
+
if (remoteUrl.startsWith("git@github.com:")) {
|
|
75
|
+
return true;
|
|
40
76
|
}
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
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
|
-
|
|
50
|
-
|
|
51
|
-
|
|
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
|
|
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
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
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
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
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
|
-
|
|
74
|
-
|
|
75
|
-
|
|
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/
|
|
81
|
-
var
|
|
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, "
|
|
179
|
+
__name(this, "SetupGithubError");
|
|
84
180
|
}
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
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
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
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
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
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
|
-
|
|
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/
|
|
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
|
-
*
|
|
963
|
+
* Static + pure so it can be unit-tested without an emitter
|
|
964
|
+
* instance. Exported via `ToolCallEmitter.resolveToolProvenance`.
|
|
693
965
|
*/
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
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
|
-
*
|
|
980
|
+
* Checks if a tool name is the TodoWriteTool.
|
|
981
|
+
* Exposed for external use in components that need to check this.
|
|
730
982
|
*/
|
|
731
|
-
|
|
732
|
-
|
|
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
|
-
*
|
|
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
|
-
|
|
810
|
-
|
|
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
|
-
*
|
|
844
|
-
* @param usageMetadata - The usage metadata to replay
|
|
993
|
+
* Checks if a tool name is the EnterPlanModeTool.
|
|
845
994
|
*/
|
|
846
|
-
|
|
847
|
-
|
|
995
|
+
isEnterPlanModeTool(toolName) {
|
|
996
|
+
return toolName === ToolNames.ENTER_PLAN_MODE;
|
|
848
997
|
}
|
|
849
998
|
/**
|
|
850
|
-
*
|
|
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
|
-
|
|
853
|
-
if (!
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
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
|
-
|
|
879
|
-
let
|
|
880
|
-
|
|
881
|
-
|
|
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
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
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
|
-
|
|
898
|
-
throw firstError;
|
|
899
|
-
}
|
|
1037
|
+
return { title, locations, kind };
|
|
900
1038
|
}
|
|
901
1039
|
/**
|
|
902
|
-
*
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
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
|
-
*
|
|
931
|
-
*
|
|
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
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
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
|
-
*
|
|
1084
|
+
* Transforms Part[] to ToolCallContent[].
|
|
1085
|
+
* Extracts text from functionResponse parts and text parts.
|
|
951
1086
|
*/
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
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/
|
|
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/
|
|
1117
|
+
// packages/cli/src/utils/chat-record-tool-call-id.ts
|
|
977
1118
|
init_esbuild_shims();
|
|
978
|
-
|
|
979
|
-
|
|
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(
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
return
|
|
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(
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
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
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
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
|
|
1141
|
+
return void 0;
|
|
1103
1142
|
}
|
|
1104
|
-
__name(
|
|
1143
|
+
__name(extractFunctionResponseId, "extractFunctionResponseId");
|
|
1105
1144
|
|
|
1106
|
-
// packages/cli/src/
|
|
1107
|
-
var
|
|
1108
|
-
var
|
|
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, "
|
|
1149
|
+
__name(this, "HistoryReplayer");
|
|
1120
1150
|
}
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
constructor(
|
|
1126
|
-
|
|
1127
|
-
this.
|
|
1128
|
-
this.
|
|
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
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
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
|
-
|
|
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
|
-
|
|
1152
|
-
|
|
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
|
-
|
|
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
|
-
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
|
|
1184
|
-
|
|
1185
|
-
|
|
1186
|
-
"
|
|
1187
|
-
|
|
1188
|
-
|
|
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
|
-
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
|
|
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
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
|
|
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
|
-
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
|
|
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
|
-
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
|
-
|
|
1247
|
-
|
|
1248
|
-
|
|
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
|
-
|
|
1255
|
-
|
|
1256
|
-
|
|
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
|
-
|
|
1270
|
-
|
|
1271
|
-
|
|
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
|
-
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
async
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
|
|
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
|
|
1297
|
-
|
|
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
|
-
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
|
-
|
|
1308
|
-
|
|
1309
|
-
|
|
1310
|
-
|
|
1311
|
-
|
|
1312
|
-
|
|
1313
|
-
|
|
1314
|
-
|
|
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
|
-
|
|
1369
|
-
|
|
1370
|
-
|
|
1371
|
-
|
|
1372
|
-
|
|
1373
|
-
|
|
1374
|
-
|
|
1375
|
-
|
|
1376
|
-
|
|
1377
|
-
|
|
1378
|
-
|
|
1379
|
-
|
|
1380
|
-
|
|
1381
|
-
|
|
1382
|
-
|
|
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
|
-
|
|
1397
|
-
|
|
1398
|
-
|
|
1399
|
-
|
|
1400
|
-
|
|
1401
|
-
|
|
1402
|
-
|
|
1403
|
-
|
|
1404
|
-
|
|
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
|
-
|
|
1408
|
-
|
|
1409
|
-
|
|
1410
|
-
|
|
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-
|
|
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
|
|
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
|
|
2524
|
+
* Copyright 2025 Qwen
|
|
2462
2525
|
* SPDX-License-Identifier: Apache-2.0
|
|
2463
2526
|
*/
|
|
2464
2527
|
/**
|