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