@qwen-code/qwen-code 0.21.12-preview.3 → 0.21.12-preview.4
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/docs/configuration/settings.md +10 -0
- package/bundled/qc-helper/docs/features/code-review.md +1 -1
- package/bundled/qc-helper/docs/qwen-serve.md +34 -34
- package/bundled/review/SKILL.md +55 -36
- package/chunks/{MaxSizedBox-EIK4BHBQ.js → MaxSizedBox-GFI5RYXH.js} +41 -41
- package/chunks/{StandaloneSessionPicker-NHVJDRYD.js → StandaloneSessionPicker-JFWRY4V2.js} +60 -60
- package/chunks/{acp-startup-profiler-JMJBZDVO.js → acp-startup-profiler-TVI2OVUN.js} +2 -2
- package/chunks/{acpAgent-37UDZP64.js → acpAgent-7YC6SNIS.js} +672 -428
- package/chunks/{agent-FAWBG7PP.js → agent-43KVQSB5.js} +38 -38
- package/chunks/{agent-headless-SHK4PCCH.js → agent-headless-P2N7PDGQ.js} +38 -38
- package/chunks/{anthropicContentGenerator-4JSC3ZFL.js → anthropicContentGenerator-ZBBX5VMY.js} +6 -6
- package/chunks/{artifact-tool-FRMBPDPB.js → artifact-tool-RWJAKYBZ.js} +2 -2
- package/chunks/{askUserQuestion-7G3LI3IZ.js → askUserQuestion-IQCA2SOX.js} +2 -2
- package/chunks/{bridge-DEAYNDCI.js → bridge-ZBMNALLA.js} +44 -44
- package/chunks/{channel-management-service-SKAN6NOB.js → channel-management-service-5ZYX4ROW.js} +4 -4
- package/chunks/{channel-settings-store-UIGYER6R.js → channel-settings-store-ZJWM7EDP.js} +45 -45
- package/chunks/{channel-worker-group-YPTB5ASD.js → channel-worker-group-QFJKXO7R.js} +5 -5
- package/chunks/{channel-worker-manager-4EHJSPRH.js → channel-worker-manager-PWD2UURZ.js} +5 -5
- package/chunks/{channel-worker-supervisor-DZKHYFHV.js → channel-worker-supervisor-XQJBGFCM.js} +3 -3
- package/chunks/{chunk-GZGDJ4E6.js → chunk-2ASWIM4A.js} +1 -1
- package/chunks/{chunk-DP3IHZGG.js → chunk-2AUM35J5.js} +59 -7
- package/chunks/{chunk-T4FTABSW.js → chunk-2N6CV4PW.js} +1 -1
- package/chunks/{chunk-5PWLQ7SK.js → chunk-2RTRFLWH.js} +11 -4
- package/chunks/{chunk-TYGKUOEG.js → chunk-2U3UCXZ3.js} +2 -1
- package/chunks/{chunk-QZ5G26ZE.js → chunk-32SNBMNP.js} +12 -12
- package/chunks/{chunk-NPE3STIW.js → chunk-3JI5D6RU.js} +3 -3
- package/chunks/{chunk-E5BWLU5J.js → chunk-3MJ44LNC.js} +59 -23
- package/chunks/{chunk-QUESTNOP.js → chunk-4JS2QK7P.js} +1 -1
- package/chunks/{chunk-L7T742G2.js → chunk-4X5J3V2I.js} +47 -3
- package/chunks/{chunk-IQFYO5BF.js → chunk-5KZNWF2M.js} +1 -1
- package/chunks/{chunk-EXG2R5UR.js → chunk-62TIEFNN.js} +8 -8
- package/chunks/{chunk-T6W4KACQ.js → chunk-67F2BEYW.js} +1 -1
- package/chunks/{chunk-NELCY6JT.js → chunk-6LDLDK6E.js} +1 -1
- package/chunks/{chunk-5I5NMQCU.js → chunk-6NQWER7D.js} +3 -3
- package/chunks/{chunk-732MOPEM.js → chunk-6OJDN5ZT.js} +1 -1
- package/chunks/{chunk-GLWWPFTW.js → chunk-6SU6OW5Z.js} +1 -1
- package/chunks/{chunk-TEKFBSMY.js → chunk-6T5HCY34.js} +3 -3
- package/chunks/{chunk-AQHNAA7E.js → chunk-7JL5YBSA.js} +1 -1
- package/chunks/{chunk-NWPO6I7V.js → chunk-7WUMS2UA.js} +1 -1
- package/chunks/{chunk-O5G7IQGM.js → chunk-A2QIWDFO.js} +347 -85
- package/chunks/{chunk-KT4OWAAZ.js → chunk-A4BAHMJF.js} +3 -3
- package/chunks/{chunk-N7NBMAMW.js → chunk-A6GQUQ7I.js} +2 -2
- package/chunks/{chunk-XLQS3VI6.js → chunk-AAZWJAPQ.js} +2 -2
- package/chunks/{chunk-LT532KF4.js → chunk-ADJDLEVO.js} +1 -1
- package/chunks/{chunk-VWD7SNNN.js → chunk-APQTLUZ3.js} +2120 -2085
- package/chunks/{chunk-AJX4ITUG.js → chunk-ARL4UGRW.js} +3 -3
- package/chunks/{chunk-ZQSNP4TG.js → chunk-B2BKFWJK.js} +2 -2
- package/chunks/{chunk-SAQHDAUJ.js → chunk-B66LYK4B.js} +452 -57
- package/chunks/{chunk-6ZIIHBNV.js → chunk-B7IBCWDW.js} +3 -3
- package/chunks/{chunk-5UPJ774B.js → chunk-BGIKUE5J.js} +1 -1
- package/chunks/{chunk-2J53A6MV.js → chunk-BNRIQWXW.js} +3 -3
- package/chunks/{chunk-CZXQ4UZA.js → chunk-BXAGPCYH.js} +1 -1
- package/chunks/{chunk-IEP44U2R.js → chunk-C2DR57L6.js} +1 -1
- package/chunks/{chunk-TBVNYG5B.js → chunk-CDDLHCC2.js} +3 -3
- package/chunks/{chunk-CG3OQDNY.js → chunk-CJNKGZLC.js} +6 -6
- package/chunks/{chunk-UZPWH6SP.js → chunk-CTEGMF77.js} +285 -125
- package/chunks/{chunk-3TT6MZHJ.js → chunk-DUFZ3OW6.js} +35 -35
- package/chunks/{chunk-ZWPWQEF5.js → chunk-E74YSVIN.js} +1 -1
- package/chunks/{chunk-RQVVXDHS.js → chunk-ECDXUCEO.js} +4 -4
- package/chunks/{chunk-47FQVRCO.js → chunk-EGB2PIYM.js} +1 -1
- package/chunks/{chunk-JL3LC3CQ.js → chunk-FB5CQZMK.js} +1 -1
- package/chunks/{chunk-U6PTKAOW.js → chunk-FNVF5RR4.js} +1 -1
- package/chunks/{chunk-O4BBDP2G.js → chunk-FTGU6G45.js} +2 -2
- package/chunks/{chunk-ZGWY4YUB.js → chunk-FVHLDSQS.js} +2 -2
- package/chunks/{chunk-RRQJPCRQ.js → chunk-FXWGMPAP.js} +2 -2
- package/chunks/{chunk-P64FPV3G.js → chunk-GDNDZJSG.js} +2 -2
- package/chunks/{chunk-M6HXP2SG.js → chunk-GHOUZ5X4.js} +1892 -622
- package/chunks/{chunk-M6SXIXBV.js → chunk-H2U4FK62.js} +6 -6
- package/chunks/{chunk-EFIMD5VA.js → chunk-H6BFLALJ.js} +1 -1
- package/chunks/{chunk-TYCXSMZU.js → chunk-HOJZ2QQA.js} +3 -3
- package/chunks/{chunk-Y66OOMKS.js → chunk-HWCHDINS.js} +21 -21
- package/chunks/{chunk-4GLFFNP3.js → chunk-HY5OHJEC.js} +5 -5
- package/chunks/{chunk-P2UCMHDT.js → chunk-IJCZP2MA.js} +2 -2
- package/chunks/{chunk-I4XSOFH2.js → chunk-JBZYGFIB.js} +1 -1
- package/chunks/{chunk-HBZUU4AE.js → chunk-JGD35ZSJ.js} +4 -4
- package/chunks/{chunk-DAX3G67A.js → chunk-JOVJCXN4.js} +1 -1
- package/chunks/{chunk-YI6UGZF5.js → chunk-JRMUA53D.js} +12 -12
- package/chunks/{chunk-CTQE2NB2.js → chunk-JRTJEGSP.js} +1 -1
- package/chunks/{chunk-MZSJ43WV.js → chunk-JVY7FHUZ.js} +15 -2
- package/chunks/{chunk-K7JW6V5O.js → chunk-JW5UEE3V.js} +1 -1
- package/chunks/{chunk-GYBDYWMV.js → chunk-JXS2JNMZ.js} +2 -2
- package/chunks/{chunk-L2GTEEEU.js → chunk-K5IDV3PC.js} +44 -1
- package/chunks/{chunk-N3FJOQX7.js → chunk-KB4ISUT3.js} +4 -4
- package/chunks/{chunk-GJJQV4PY.js → chunk-KK3FEHPJ.js} +1 -1
- package/chunks/{chunk-2AZMF6G5.js → chunk-KTWUFHS4.js} +2 -2
- package/chunks/{chunk-7D4KEFOT.js → chunk-L3YACXS2.js} +3 -3
- package/chunks/{chunk-575MI5K3.js → chunk-LIBTBTHP.js} +4 -4
- package/chunks/{chunk-JS4Q5NG5.js → chunk-LSMCI42W.js} +3 -3
- package/chunks/{chunk-YZJVVQD3.js → chunk-MTV5W6WN.js} +7 -7
- package/chunks/{chunk-UOMZKPI5.js → chunk-MUN34TTF.js} +7 -7
- package/chunks/{chunk-LHY6HBRA.js → chunk-N3J3CO35.js} +4 -4
- package/chunks/{chunk-TRYJ3BVE.js → chunk-N56NYJWY.js} +7 -7
- package/chunks/{chunk-3ZYX7AUR.js → chunk-NAOHSM56.js} +1 -1
- package/chunks/{chunk-URK542T4.js → chunk-NF5J2WFA.js} +15 -2
- package/chunks/{chunk-OPBATTFQ.js → chunk-NHZF4VCD.js} +1 -1
- package/chunks/{chunk-QTI7SRXI.js → chunk-NM33GGOM.js} +3 -3
- package/chunks/{chunk-F6AOBFUN.js → chunk-NW7SPXVG.js} +1 -1
- package/chunks/{chunk-J7DNMZFO.js → chunk-NX5QZVRS.js} +1 -1
- package/chunks/{chunk-WFRHWDBT.js → chunk-O4MVJKSX.js} +5 -5
- package/chunks/{chunk-NC4O6UE6.js → chunk-O6SLWH4X.js} +2 -2
- package/chunks/{chunk-V4MJ56RS.js → chunk-OIZWCOYC.js} +5 -5
- package/chunks/{chunk-JXK3WAP7.js → chunk-ORR5EFCL.js} +4 -4
- package/chunks/{chunk-EYY4IBPV.js → chunk-OSA2TFDI.js} +2 -2
- package/chunks/{chunk-KPVVWKF3.js → chunk-PSTHNTHF.js} +1 -1
- package/chunks/{chunk-4M2F7OG7.js → chunk-PYLVQ6RT.js} +6 -6
- package/chunks/{chunk-6AECVSVX.js → chunk-Q7ALOKK7.js} +3 -3
- package/chunks/{chunk-EYW54TBD.js → chunk-QEWAHAW2.js} +3 -3
- package/chunks/{chunk-N5ULBHP3.js → chunk-QSDPJROT.js} +2 -2
- package/chunks/{chunk-DYVCDQW2.js → chunk-QSMZHJ62.js} +1 -1
- package/chunks/{chunk-MDFUBQAQ.js → chunk-QWAI7FNT.js} +17 -17
- package/chunks/{chunk-M4OYAR6J.js → chunk-QXFAQDBV.js} +2 -2
- package/chunks/{chunk-ILVATFYJ.js → chunk-SFBRH5RY.js} +19 -15
- package/chunks/{chunk-EYS3GGM3.js → chunk-SKRHR6N2.js} +1 -1
- package/chunks/{chunk-6LYDH7VT.js → chunk-SNHBRO4C.js} +2 -2
- package/chunks/{chunk-5TXOGH4I.js → chunk-T4G33L3W.js} +3 -3
- package/chunks/{chunk-32VOOMEF.js → chunk-TB6DPBE4.js} +4 -4
- package/chunks/{chunk-DEG7R6Z6.js → chunk-TN3REXN4.js} +8 -8
- package/chunks/{chunk-MWZYNOCG.js → chunk-TNETSI2A.js} +3 -3
- package/chunks/{chunk-ZV4XVYL3.js → chunk-TROB4PZY.js} +4 -4
- package/chunks/{chunk-O5AZPHYZ.js → chunk-U5C2GIN2.js} +24 -16
- package/chunks/{chunk-3GCU5O2E.js → chunk-U7ROFHSH.js} +1 -1
- package/chunks/{chunk-HB6QW4LM.js → chunk-UAAWNTOC.js} +15 -12
- package/chunks/{chunk-HHGQGTJQ.js → chunk-UFHPAMAV.js} +4 -0
- package/chunks/{chunk-V3LXMASR.js → chunk-UHF5VBKO.js} +1 -1
- package/chunks/{chunk-FRH4SSGX.js → chunk-UPUAGRKY.js} +2 -2
- package/chunks/{chunk-6S52N6PG.js → chunk-UQPLUR4A.js} +2 -2
- package/chunks/{chunk-KIFRFCCB.js → chunk-UWIJU22K.js} +66 -19
- package/chunks/{chunk-HGCQ5SE7.js → chunk-UXEO7E3V.js} +21 -0
- package/chunks/{chunk-M2PY7CNK.js → chunk-V2U6FOJB.js} +2 -2
- package/chunks/{chunk-7SUQZ7QH.js → chunk-V3NMFQD2.js} +2 -2
- package/chunks/{chunk-6XZERB6P.js → chunk-VPZMLGD3.js} +3 -3
- package/chunks/{chunk-UNCIELQJ.js → chunk-VRQD5D7R.js} +1 -1
- package/chunks/{chunk-YTYPRVIZ.js → chunk-VUTOV2HG.js} +2 -2
- package/chunks/{chunk-7LZ7DK4D.js → chunk-VYDQD5J4.js} +1 -1
- package/chunks/{chunk-XCGIMOLN.js → chunk-WCCLLK7X.js} +14 -1
- package/chunks/{chunk-JEMR2FTD.js → chunk-WIHSDI6U.js} +4 -4
- package/chunks/{chunk-VJNBRRZG.js → chunk-WZMH7II3.js} +1 -1
- package/chunks/{chunk-XWUQ4IH5.js → chunk-XJ6IMYUS.js} +7 -7
- package/chunks/{chunk-3XZYK76R.js → chunk-XL6GYJL2.js} +1 -1
- package/chunks/{chunk-KNXA5XXK.js → chunk-XUBM2A4F.js} +7 -7
- package/chunks/{chunk-ENEEQMGM.js → chunk-XY7DGTIC.js} +1 -1
- package/chunks/{chunk-SSAOTDK7.js → chunk-Y2EOB7WZ.js} +1 -1
- package/chunks/{chunk-VQZXRLEX.js → chunk-Y2HK3ELT.js} +3 -3
- package/chunks/{chunk-FDWH6CBK.js → chunk-Y5C24BUY.js} +5 -5
- package/chunks/{chunk-5HBFERG5.js → chunk-YI5G32RU.js} +3 -3
- package/chunks/{chunk-MPBRV3UU.js → chunk-YMB77M76.js} +15 -0
- package/chunks/{chunk-KNQZXSLW.js → chunk-YY23TR4M.js} +23 -9
- package/chunks/{chunk-4ETA3KRC.js → chunk-ZA2JN5IZ.js} +3 -3
- package/chunks/{chunk-IX7CFQGA.js → chunk-ZPZANKVP.js} +3 -3
- package/chunks/{chunk-XTH2OMDS.js → chunk-ZRT36RSF.js} +1 -1
- package/chunks/{chunk-M2NMFAFR.js → chunk-ZZ7RUTJ4.js} +1 -1
- package/chunks/{computer-use-S4JEU5P7.js → computer-use-J5VUY257.js} +38 -38
- package/chunks/{config-utils-TXVKR27S.js → config-utils-7JZQN6L2.js} +4 -4
- package/chunks/{contextCommand-2H5OH2HW.js → contextCommand-RCTGC36R.js} +40 -40
- package/chunks/{core-runtime-IAQ4DD4Y.js → core-runtime-REBZ5ZYE.js} +38 -38
- package/chunks/{create-sub-session-Y4WYDZGC.js → create-sub-session-23ULO5PO.js} +2 -2
- package/chunks/{create-sub-session-EKHKXJAA.js → create-sub-session-TEEUROAZ.js} +38 -38
- package/chunks/{cron-create-ZOVA3CC2.js → cron-create-5WUTNKNF.js} +4 -4
- package/chunks/{cron-delete-7Z3H4LJY.js → cron-delete-JEQ27YPS.js} +4 -4
- package/chunks/{cron-list-UHGX3IQG.js → cron-list-IXGCA7UR.js} +4 -4
- package/chunks/{daemon-PXIC4ZDK.js → daemon-UBVOQMWY.js} +2 -1
- package/chunks/{daemon-status-provider-LPYR2GXY.js → daemon-status-provider-SV7KRLJ4.js} +49 -49
- package/chunks/{daemon-trust-policy-7JOBVFH3.js → daemon-trust-policy-LFUJ4NGF.js} +44 -44
- package/chunks/{daemon-trust-policy-monitor-OU3NRHAR.js → daemon-trust-policy-monitor-BQZ77NDD.js} +44 -44
- package/chunks/{deferred-core-runtime-SFT3KI2C.js → deferred-core-runtime-F4XOQJQL.js} +38 -38
- package/chunks/{dispatch-B53LNEO4.js → dispatch-FW7DX2CR.js} +7 -1
- package/chunks/{display-image-ZE3GZNIK.js → display-image-CAD7RAUM.js} +4 -4
- package/chunks/{dist-BNWP6IZL.js → dist-362MN6CP.js} +2 -2
- package/chunks/{dist-EFJILGIS.js → dist-5VDE7U3A.js} +1 -1
- package/chunks/{dist-AVUYBK7L.js → dist-6RK4U6VU.js} +1 -1
- package/chunks/{dist-KTYDJNYM.js → dist-B3ODKYEB.js} +1 -1
- package/chunks/{dist-NPS52B2V.js → dist-CCUH2Z4C.js} +1 -1
- package/chunks/{dist-BW2LDPV3.js → dist-DANKRAB3.js} +1 -1
- package/chunks/{dist-PKSRQAR2.js → dist-EZHCZSW6.js} +1 -1
- package/chunks/{dist-ZWDH5HLS.js → dist-M3XMEIP2.js} +1 -1
- package/chunks/{earlyInputCapture-27RPWE2D.js → earlyInputCapture-JAJXDT2N.js} +39 -39
- package/chunks/{edit-WXVZ7FHS.js → edit-OXBMFY5B.js} +38 -38
- package/chunks/{enter-worktree-TYMVXFLA.js → enter-worktree-XS4JX4PO.js} +38 -38
- package/chunks/{enterPlanMode-FT4MRU5N.js → enterPlanMode-J6PDPFFT.js} +38 -38
- package/chunks/{environment-Z6OMA34I.js → environment-BQW6FAZL.js} +40 -40
- package/chunks/{errors-YMXK2GG3.js → errors-TMSN7AZN.js} +40 -40
- package/chunks/{exit-worktree-ODZUQLGJ.js → exit-worktree-2RIE6DAO.js} +38 -38
- package/chunks/{exitPlanMode-MBPAPBBV.js → exitPlanMode-QQL27HU4.js} +38 -38
- package/chunks/{fast-path-ZU5T6XSN.js → fast-path-TSGUVE5K.js} +4 -4
- package/chunks/{gemini-OZK6AIMC.js → gemini-RLTFENFV.js} +86 -86
- package/chunks/{geminiContentGenerator-MC6ZKWZG.js → geminiContentGenerator-B6W6PSO7.js} +6 -6
- package/chunks/{glob-KJ4A4ZOM.js → glob-JKVAHWL5.js} +38 -38
- package/chunks/{goal-tools-JDK2SNMV.js → goal-tools-LQFO4BRY.js} +4 -4
- package/chunks/{grep-QWBLG564.js → grep-6CN23ZPS.js} +38 -38
- package/chunks/{handleAutoUpdate-M3ACKDKF.js → handleAutoUpdate-Y6BUNMBG.js} +42 -42
- package/chunks/{i18n-FPW7XZL5.js → i18n-Y5PM6L5V.js} +39 -39
- package/chunks/{image-gen-OTFC2S7L.js → image-gen-DC2IQZ73.js} +10 -10
- package/chunks/{initializer-5HKUXXBT.js → initializer-OYKKBNHO.js} +45 -45
- package/chunks/{installationInfo-4OA6UW7V.js → installationInfo-63AFHLWA.js} +39 -39
- package/chunks/{keychain-token-storage-JTWUYFU7.js → keychain-token-storage-GU75J2T2.js} +2 -2
- package/chunks/{list-3TKZ264A.js → list-KA63R3R6.js} +47 -47
- package/chunks/{list-agents-4GQ2XNEU.js → list-agents-5PNMK2AM.js} +2 -2
- package/chunks/{loadedSettingsAdapter-IRUANLS2.js → loadedSettingsAdapter-IGBJN7C5.js} +44 -44
- package/chunks/{loggingContentGenerator-D4URLH2A.js → loggingContentGenerator-Z3NADCTQ.js} +115 -93
- package/chunks/{loop-wakeup-HOQI3K5D.js → loop-wakeup-OV65FEGR.js} +5 -5
- package/chunks/{ls-FSHISLLA.js → ls-RPRSX26R.js} +4 -4
- package/chunks/{lsp-APQJ5ZEZ.js → lsp-IWTJWFLT.js} +2 -2
- package/chunks/{managed-npm-update-2O7XSAWJ.js → managed-npm-update-HA262PFM.js} +41 -41
- package/chunks/{mcp-AFVHCHKT.js → mcp-T5ZUOKT3.js} +44 -44
- package/chunks/{monitor-PY4WDSX3.js → monitor-SLGY7CYB.js} +38 -38
- package/chunks/nonInteractiveCli-R5PK5B5G.js +166 -0
- package/chunks/{notebook-edit-GEPL33NO.js → notebook-edit-STSSB5KQ.js} +38 -38
- package/chunks/{openaiContentGenerator-ACYSXQ6R.js → openaiContentGenerator-OQED57JE.js} +24 -24
- package/chunks/{opentui-entry-SBAOWW7M.js → opentui-entry-UTJ6MHDI.js} +116 -97
- package/chunks/{pidfile-SUNYCAA4.js → pidfile-GES3MIHH.js} +39 -39
- package/chunks/{processUtils-F7LP7YUV.js → processUtils-FU6VMUOL.js} +2 -2
- package/chunks/{qwenContentGenerator-BB6IPELF.js → qwenContentGenerator-HWJSEGUL.js} +43 -43
- package/chunks/{qwenOAuth2-OU3WGDOI.js → qwenOAuth2-PAIR7XEW.js} +9 -9
- package/chunks/{read-file-GORBXJTS.js → read-file-IYEBTQT5.js} +12 -12
- package/chunks/{read-mcp-resource-TJSJRH4F.js → read-mcp-resource-THCSZHXO.js} +2 -2
- package/chunks/{read-package-up-TCM6I7S2.js → read-package-up-K6RKTL5D.js} +1 -1
- package/chunks/{record-artifact-FXF5LHPE.js → record-artifact-76YYQA5F.js} +3 -3
- package/chunks/{resumeHistoryUtils-FOAJJJWK.js → resumeHistoryUtils-WP446RP5.js} +44 -44
- package/chunks/{ripGrep-RNLIZGCY.js → ripGrep-VV2CRCL2.js} +38 -38
- package/chunks/{run-qwen-serve-GVMMX3IU.js → run-qwen-serve-AHQCTALV.js} +160 -71
- package/chunks/{runtime-RNBZ5FDD.js → runtime-AUUZGDK6.js} +49 -49
- package/chunks/{scheduler-NTRFSPIP.js → scheduler-Y4UPEURR.js} +40 -40
- package/chunks/{sdk-exporters-http-2VPMAPFI.js → sdk-exporters-http-A7XLKZO7.js} +11 -7
- package/chunks/{sdk-impl-5W3JUCWF.js → sdk-impl-XO4UF6PR.js} +11 -8
- package/chunks/{send-message-RBYLV5NY.js → send-message-P5SLP57G.js} +6 -6
- package/chunks/{serve-H3PGA26U.js → serve-WI3SE4MY.js} +47 -47
- package/chunks/{server-SUXD2F3C.js → server-G6JU6UWL.js} +264 -159
- package/chunks/{session-MTFVUWWM.js → session-2AO2UACB.js} +85 -85
- package/chunks/{settings-GUJ3TN2J.js → settings-3HRWSH66.js} +43 -43
- package/chunks/{shell-C2UP5FF2.js → shell-AR7XFLHA.js} +38 -38
- package/chunks/{skill-4XCNK55E.js → skill-K6NOUUYM.js} +16 -16
- package/chunks/{skill-settings-Y2BU27XM.js → skill-settings-IOXQYS6X.js} +43 -43
- package/chunks/{spawnChannel-UUUUK734.js → spawnChannel-V6P6HF4V.js} +40 -40
- package/chunks/{standalone-update-MJ722XZ4.js → standalone-update-K5G3L2OJ.js} +40 -40
- package/chunks/{startInteractiveUI-TCPIPNGN.js → startInteractiveUI-TRRP52QX.js} +125 -115
- package/chunks/{syntheticOutput-D3Z64LJC.js → syntheticOutput-SEW4NA47.js} +3 -3
- package/chunks/{task-create-URFZ5EUX.js → task-create-247EAVF7.js} +10 -10
- package/chunks/{task-list-6JDFMPUW.js → task-list-ZJN4QHLK.js} +5 -5
- package/chunks/{task-stop-HHUGCD25.js → task-stop-MAYQJ42I.js} +2 -2
- package/chunks/{task-update-DVV6CUGI.js → task-update-SU5TMZGG.js} +10 -10
- package/chunks/{team-create-WZWH2NJI.js → team-create-IEEEBLE2.js} +38 -38
- package/chunks/{team-delete-PZGGBQLM.js → team-delete-3XVRPQBP.js} +5 -5
- package/chunks/{team-plan-approval-SUZQJCWJ.js → team-plan-approval-SJGNS5JL.js} +38 -38
- package/chunks/{terminal-image-renderer-BCUN3Z3W.js → terminal-image-renderer-C4RQMC67.js} +40 -40
- package/chunks/{theme-manager-UGMFDREN.js → theme-manager-IKZQJQ6C.js} +39 -39
- package/chunks/{todoWrite-WINAZSZI.js → todoWrite-IE2YTCK7.js} +4 -4
- package/chunks/{tool-search-B6F3MPUZ.js → tool-search-4UVNFYWU.js} +16 -16
- package/chunks/{total-session-admission-MQLBJ5WL.js → total-session-admission-DIN6FTZP.js} +44 -44
- package/chunks/{trustedFolders-2XST7U5C.js → trustedFolders-IAHOLV6A.js} +39 -39
- package/chunks/{update-relaunch-OVC7YNGD.js → update-relaunch-5QSJ5CWP.js} +5 -5
- package/chunks/{updateCheck-YAKM36WQ.js → updateCheck-N4RT7HOZ.js} +44 -44
- package/chunks/{useAutoAcceptIndicator-RF6FVX3S.js → useAutoAcceptIndicator-25T26VZS.js} +46 -46
- package/chunks/{validateNonInterActiveAuth-IPPXFNQH.js → validateNonInterActiveAuth-MCTVPLFE.js} +81 -81
- package/chunks/{version-4IDFEXOU.js → version-6PLZ7PCV.js} +2 -2
- package/chunks/{web-fetch-NUOLHXPN.js → web-fetch-5ANX6FSM.js} +16 -16
- package/chunks/{web-search-LVOOV4XZ.js → web-search-KQJWWRHW.js} +9 -9
- package/chunks/{workflow-JSTYTG3K.js → workflow-C57ZKFUF.js} +111 -46
- package/chunks/{workspace-providers-status-U4EYXA4K.js → workspace-providers-status-3QAE4G4Y.js} +47 -47
- package/chunks/{workspace-registration-store-OG66U3CB.js → workspace-registration-store-Q3J5LV6T.js} +1 -1
- package/chunks/{workspace-registry-WSHWQRQQ.js → workspace-registry-DSJ5NAII.js} +44 -44
- package/chunks/{workspace-service-QZXQHX2F.js → workspace-service-QW5LH7FA.js} +49 -49
- package/chunks/{workspace-skills-status-VRBHEX5O.js → workspace-skills-status-N34ALJPZ.js} +45 -45
- package/chunks/{workspace-trust-reconciler-FCRIUIOF.js → workspace-trust-reconciler-YTOL7QEV.js} +50 -50
- package/chunks/{write-file-PYL3JCCD.js → write-file-MSFRVUZB.js} +38 -38
- package/chunks/{zoom-image-RS6MU26F.js → zoom-image-4TQA5GHG.js} +12 -12
- package/cli.js +13 -13
- package/package.json +4 -4
- package/web-shell/assets/{arc-CgGUyHWd.js → arc-lZ04kynw.js} +1 -1
- package/web-shell/assets/{architectureDiagram-3BPJPVTR-BR0Qv-1Y.js → architectureDiagram-3BPJPVTR-B1wZVhzD.js} +1 -1
- package/web-shell/assets/{blockDiagram-GPEHLZMM-DIoaceaI.js → blockDiagram-GPEHLZMM-CO0e0yJt.js} +1 -1
- package/web-shell/assets/{c4Diagram-AAUBKEIU-Bc5k6BbI.js → c4Diagram-AAUBKEIU-Dfpo6Qie.js} +1 -1
- package/web-shell/assets/channel-BxvRq3pV.js +1 -0
- package/web-shell/assets/{chunk-2J33WTMH-DtPEz2WX.js → chunk-2J33WTMH-BvxArftT.js} +1 -1
- package/web-shell/assets/{chunk-4BX2VUAB-Dydo6ydE.js → chunk-4BX2VUAB-BS2XXjGY.js} +1 -1
- package/web-shell/assets/{chunk-55IACEB6-DD9_VWXm.js → chunk-55IACEB6-CYL6h3Ph.js} +1 -1
- package/web-shell/assets/{chunk-727SXJPM-DVI2m59k.js → chunk-727SXJPM-C-cWPX30.js} +1 -1
- package/web-shell/assets/{chunk-AQP2D5EJ-luatmaTN.js → chunk-AQP2D5EJ-CJLxNbVV.js} +1 -1
- package/web-shell/assets/{chunk-FMBD7UC4-Duy8NTIi.js → chunk-FMBD7UC4-DwfzKywA.js} +1 -1
- package/web-shell/assets/{chunk-ND2GUHAM-CrL1yhms.js → chunk-ND2GUHAM-BI5raYHQ.js} +1 -1
- package/web-shell/assets/{chunk-QZHKN3VN-C7BX6bu1.js → chunk-QZHKN3VN-_GkNI90J.js} +1 -1
- package/web-shell/assets/classDiagram-4FO5ZUOK-tL8nAxYf.js +1 -0
- package/web-shell/assets/classDiagram-v2-Q7XG4LA2-tL8nAxYf.js +1 -0
- package/web-shell/assets/{cose-bilkent-S5V4N54A-BTzs7mIi.js → cose-bilkent-S5V4N54A-BAVLNxh9.js} +1 -1
- package/web-shell/assets/{dagre-BM42HDAG-3VTUmWts.js → dagre-BM42HDAG-BD4XNLqp.js} +1 -1
- package/web-shell/assets/{diagram-2AECGRRQ-Ehdp75GN.js → diagram-2AECGRRQ-WO567p8w.js} +1 -1
- package/web-shell/assets/{diagram-5GNKFQAL-B3wu3teE.js → diagram-5GNKFQAL-mAk23VWO.js} +1 -1
- package/web-shell/assets/{diagram-KO2AKTUF-DjgTSf2S.js → diagram-KO2AKTUF-YQEeHKze.js} +1 -1
- package/web-shell/assets/{diagram-LMA3HP47-Br9mwjY3.js → diagram-LMA3HP47-CMVjxAjv.js} +1 -1
- package/web-shell/assets/{diagram-OG6HWLK6-D4xz5M-z.js → diagram-OG6HWLK6-42hPvbM-.js} +1 -1
- package/web-shell/assets/{erDiagram-TEJ5UH35-CXayWlG_.js → erDiagram-TEJ5UH35-CXU_cPfu.js} +1 -1
- package/web-shell/assets/{flowDiagram-I6XJVG4X-CLonjQTi.js → flowDiagram-I6XJVG4X-D-3TdhMT.js} +1 -1
- package/web-shell/assets/{ganttDiagram-6RSMTGT7-BTySFT-1.js → ganttDiagram-6RSMTGT7-CsgkXolz.js} +1 -1
- package/web-shell/assets/{gitGraphDiagram-PVQCEYII--2WcUjOe.js → gitGraphDiagram-PVQCEYII-B6Q3PBLD.js} +1 -1
- package/web-shell/assets/{index-DPJHkFOG.js → index-BFrkGj2B.js} +1 -1
- package/web-shell/assets/index-BgjULKyF.css +5 -0
- package/web-shell/assets/index-CxXlPYfl.js +1789 -0
- package/web-shell/assets/{infoDiagram-5YYISTIA-9vpgAf1m.js → infoDiagram-5YYISTIA-jiAfSXp8.js} +1 -1
- package/web-shell/assets/{ishikawaDiagram-YF4QCWOH-DcRpHnAW.js → ishikawaDiagram-YF4QCWOH-BWif5KeJ.js} +1 -1
- package/web-shell/assets/{journeyDiagram-JHISSGLW-C2TKorRm.js → journeyDiagram-JHISSGLW-B-GAZthS.js} +1 -1
- package/web-shell/assets/{kanban-definition-UN3LZRKU-DdsFwB8b.js → kanban-definition-UN3LZRKU-9TEuATdL.js} +1 -1
- package/web-shell/assets/{linear-7PjRvJrf.js → linear-dy_QPfyE.js} +1 -1
- package/web-shell/assets/{mermaid.core-raDXa11C.js → mermaid.core-DB2uLAnq.js} +5 -5
- package/web-shell/assets/{mindmap-definition-RKZ34NQL-DLHc-PRN.js → mindmap-definition-RKZ34NQL-ey_dyxi-.js} +1 -1
- package/web-shell/assets/{pieDiagram-4H26LBE5-BftYpeTW.js → pieDiagram-4H26LBE5-_6BuMdDj.js} +1 -1
- package/web-shell/assets/{quadrantDiagram-W4KKPZXB-O-6ygOYn.js → quadrantDiagram-W4KKPZXB-B2rM19W2.js} +1 -1
- package/web-shell/assets/{requirementDiagram-4Y6WPE33-BmZWVufJ.js → requirementDiagram-4Y6WPE33-DWj8b7vW.js} +1 -1
- package/web-shell/assets/{sankeyDiagram-5OEKKPKP-2x5beiWt.js → sankeyDiagram-5OEKKPKP-D5dtYh0N.js} +1 -1
- package/web-shell/assets/{sequenceDiagram-3UESZ5HK-BH8uKokQ.js → sequenceDiagram-3UESZ5HK-DVkdn_qW.js} +1 -1
- package/web-shell/assets/{stateDiagram-AJRCARHV-Dq1MFgX_.js → stateDiagram-AJRCARHV-DgwD_fi6.js} +1 -1
- package/web-shell/assets/stateDiagram-v2-BHNVJYJU-BWGkVGVB.js +1 -0
- package/web-shell/assets/{timeline-definition-PNZ67QCA-Cl2WKbv9.js → timeline-definition-PNZ67QCA-vNr_1UNX.js} +1 -1
- package/web-shell/assets/{vennDiagram-CIIHVFJN-BqoRo_Q-.js → vennDiagram-CIIHVFJN-ChFcGAcu.js} +1 -1
- package/web-shell/assets/{wardley-L42UT6IY-BTxp-Yot.js → wardley-L42UT6IY-C8PXoSWk.js} +1 -1
- package/web-shell/assets/{wardleyDiagram-YWT4CUSO-DFXVCSH2.js → wardleyDiagram-YWT4CUSO-C2nqOV6i.js} +1 -1
- package/web-shell/assets/{xychartDiagram-2RQKCTM6-qQhWx0aE.js → xychartDiagram-2RQKCTM6-BntaqhSB.js} +1 -1
- package/web-shell/index.html +2 -2
- package/chunks/nonInteractiveCli-ZHW6F76F.js +0 -166
- package/web-shell/assets/channel-D2b9IYpS.js +0 -1
- package/web-shell/assets/classDiagram-4FO5ZUOK-DHatTCmD.js +0 -1
- package/web-shell/assets/classDiagram-v2-Q7XG4LA2-DHatTCmD.js +0 -1
- package/web-shell/assets/index-CIFO52Wx.css +0 -5
- package/web-shell/assets/index-bhq3CUUF.js +0 -1789
- package/web-shell/assets/stateDiagram-v2-BHNVJYJU-spuAYji6.js +0 -1
|
@@ -5,23 +5,28 @@ import {
|
|
|
5
5
|
} from "./chunk-4NFY2S7N.js";
|
|
6
6
|
import {
|
|
7
7
|
formatHistoryGapNotice
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-FNVF5RR4.js";
|
|
9
9
|
import {
|
|
10
10
|
loadUndici
|
|
11
11
|
} from "./chunk-3Z43GZUQ.js";
|
|
12
12
|
import {
|
|
13
|
+
projectGoalStateToLegacy
|
|
14
|
+
} from "./chunk-GHOUZ5X4.js";
|
|
15
|
+
import {
|
|
16
|
+
parseGoalSnapshotV2,
|
|
17
|
+
parseGoalStateCause,
|
|
13
18
|
projectUserTranscriptForDisplay
|
|
14
|
-
} from "./chunk-
|
|
19
|
+
} from "./chunk-B66LYK4B.js";
|
|
15
20
|
import {
|
|
16
21
|
formatVisionBridgeNoticeDisplay,
|
|
17
22
|
isVisionBridgeNoticeDisplay
|
|
18
|
-
} from "./chunk-
|
|
23
|
+
} from "./chunk-UAAWNTOC.js";
|
|
19
24
|
import {
|
|
20
25
|
ToolNames
|
|
21
|
-
} from "./chunk-
|
|
26
|
+
} from "./chunk-ZRT36RSF.js";
|
|
22
27
|
import {
|
|
23
28
|
createDebugLogger
|
|
24
|
-
} from "./chunk-
|
|
29
|
+
} from "./chunk-YMB77M76.js";
|
|
25
30
|
import {
|
|
26
31
|
writeStderrLine,
|
|
27
32
|
writeStderrLineSafe
|
|
@@ -33,2265 +38,2295 @@ import {
|
|
|
33
38
|
__name
|
|
34
39
|
} from "./chunk-J2S4EL5Y.js";
|
|
35
40
|
|
|
36
|
-
// packages/cli/src/
|
|
41
|
+
// packages/cli/src/acp-integration/session/history-replayer.ts
|
|
37
42
|
init_esbuild_shims();
|
|
38
|
-
import { promises as fsp } from "node:fs";
|
|
39
|
-
import * as path from "node:path";
|
|
40
43
|
|
|
41
|
-
// packages/
|
|
44
|
+
// packages/acp-bridge/src/transcript-replay.ts
|
|
42
45
|
init_esbuild_shims();
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
reject(err);
|
|
57
|
-
return;
|
|
58
|
-
}
|
|
59
|
-
resolve2(String(stdout ?? "").trim());
|
|
60
|
-
}
|
|
61
|
-
);
|
|
62
|
-
});
|
|
46
|
+
|
|
47
|
+
// packages/core/dist/src/goals/goal-wire.js
|
|
48
|
+
init_esbuild_shims();
|
|
49
|
+
|
|
50
|
+
// packages/core/dist/src/goals/goal-protocol.js
|
|
51
|
+
init_esbuild_shims();
|
|
52
|
+
var GOAL_STATE_VERSION = 2;
|
|
53
|
+
var GOAL_CHECKPOINT_CLAIM_LIMIT = 32;
|
|
54
|
+
var GOAL_CHECKPOINT_CLAIM_MAX_CHARACTERS = 2e3;
|
|
55
|
+
var GOAL_CHECKPOINT_CLAIM_MAX_BYTES = 16e3;
|
|
56
|
+
var GOAL_CHECKPOINT_SOURCE_REFERENCE_LIMIT = 32;
|
|
57
|
+
function isGoalEvidenceProofKind(value) {
|
|
58
|
+
return value === "user_input" || value === "delivered_output" || value === "external_fact";
|
|
63
59
|
}
|
|
64
|
-
__name(
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
if (remoteUrl.startsWith("git@github.com:")) {
|
|
79
|
-
return true;
|
|
80
|
-
}
|
|
81
|
-
if (remoteUrl.startsWith("git@")) {
|
|
82
|
-
return false;
|
|
60
|
+
__name(isGoalEvidenceProofKind, "isGoalEvidenceProofKind");
|
|
61
|
+
|
|
62
|
+
// packages/core/dist/src/goals/goal-reducer.js
|
|
63
|
+
init_esbuild_shims();
|
|
64
|
+
var MAX_BLOCKED_AUDIT_COUNT = 3;
|
|
65
|
+
function parseGoalStateRecordPayloadV2(value) {
|
|
66
|
+
if (!isRecord(value) || !hasOnlyKeys(value, [
|
|
67
|
+
"v",
|
|
68
|
+
"cause",
|
|
69
|
+
"snapshot",
|
|
70
|
+
"checkpointPending",
|
|
71
|
+
"blockedAudit"
|
|
72
|
+
]) || value["v"] !== GOAL_STATE_VERSION || !isGoalStateCause(value["cause"]) || !isCheckpointPending(value["checkpointPending"]) || !isBlockedAudit(value["blockedAudit"])) {
|
|
73
|
+
return void 0;
|
|
83
74
|
}
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
75
|
+
const parsedSnapshot = parseGoalSnapshotV22(value["snapshot"]);
|
|
76
|
+
if (parsedSnapshot?.activity !== "idle")
|
|
77
|
+
return void 0;
|
|
78
|
+
const checkpointPending = value["checkpointPending"];
|
|
79
|
+
if (checkpointPending && (parsedSnapshot.goal?.status !== "active" || checkpointPending.permit.goalId !== parsedSnapshot.goal.goalId || checkpointPending.permit.revision !== parsedSnapshot.goal.revision || checkpointPending.recordUuid === parsedSnapshot.goal.evidenceCursor.recordId || value["cause"] !== "turn_finished" && value["cause"] !== "verifier_reject")) {
|
|
80
|
+
return void 0;
|
|
88
81
|
}
|
|
82
|
+
return {
|
|
83
|
+
v: GOAL_STATE_VERSION,
|
|
84
|
+
cause: value["cause"],
|
|
85
|
+
snapshot: parsedSnapshot,
|
|
86
|
+
...checkpointPending ? { checkpointPending: structuredClone(checkpointPending) } : {},
|
|
87
|
+
...value["blockedAudit"] ? { blockedAudit: structuredClone(value["blockedAudit"]) } : {}
|
|
88
|
+
};
|
|
89
89
|
}
|
|
90
|
-
__name(
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
throw new Error(`Git repo returned empty value`);
|
|
90
|
+
__name(parseGoalStateRecordPayloadV2, "parseGoalStateRecordPayloadV2");
|
|
91
|
+
function parseGoalSnapshotV22(value) {
|
|
92
|
+
if (!isRecord(value) || !hasOnlyKeys(value, ["v", "goal", "activity"]) || value["v"] !== GOAL_STATE_VERSION || !isGoalActivity(value["activity"])) {
|
|
93
|
+
return void 0;
|
|
95
94
|
}
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
const dispatcher = proxy ? new (await loadUndici()).ProxyAgent(proxy) : void 0;
|
|
103
|
-
const response = await fetch(endpoint, {
|
|
104
|
-
method: "GET",
|
|
105
|
-
headers: {
|
|
106
|
-
Accept: "application/vnd.github+json",
|
|
107
|
-
"Content-Type": "application/json",
|
|
108
|
-
"X-GitHub-Api-Version": "2022-11-28"
|
|
109
|
-
},
|
|
110
|
-
dispatcher,
|
|
111
|
-
signal: AbortSignal.any([AbortSignal.timeout(3e4), controller.signal])
|
|
112
|
-
});
|
|
113
|
-
if (!response.ok) {
|
|
114
|
-
throw new Error(
|
|
115
|
-
`Invalid response code: ${response.status} - ${response.statusText}`
|
|
116
|
-
);
|
|
117
|
-
}
|
|
118
|
-
const releaseTag = (await response.json()).tag_name;
|
|
119
|
-
if (!releaseTag) {
|
|
120
|
-
throw new Error(`Response did not include tag_name field`);
|
|
121
|
-
}
|
|
122
|
-
return releaseTag;
|
|
123
|
-
} catch (_error) {
|
|
124
|
-
debugLogger.debug(
|
|
125
|
-
`Failed to determine latest qwen-code-action release:`,
|
|
126
|
-
_error
|
|
127
|
-
);
|
|
128
|
-
throw new Error(
|
|
129
|
-
`Unable to determine the latest qwen-code-action release on GitHub.`
|
|
130
|
-
);
|
|
95
|
+
if (value["goal"] === null) {
|
|
96
|
+
return {
|
|
97
|
+
v: GOAL_STATE_VERSION,
|
|
98
|
+
goal: null,
|
|
99
|
+
activity: value["activity"]
|
|
100
|
+
};
|
|
131
101
|
}
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
return parseGitHubRepoInfo(
|
|
135
|
-
await runGit(["remote", "get-url", "origin"], opts)
|
|
136
|
-
);
|
|
102
|
+
const goal = parseGoalRecord(value["goal"]);
|
|
103
|
+
return goal ? { v: GOAL_STATE_VERSION, goal, activity: value["activity"] } : void 0;
|
|
137
104
|
}
|
|
138
|
-
__name(
|
|
139
|
-
function
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
105
|
+
__name(parseGoalSnapshotV22, "parseGoalSnapshotV2");
|
|
106
|
+
function parseGoalStateCause2(value) {
|
|
107
|
+
return isGoalStateCause(value) ? value : void 0;
|
|
108
|
+
}
|
|
109
|
+
__name(parseGoalStateCause2, "parseGoalStateCause");
|
|
110
|
+
function copyCursor(cursor) {
|
|
111
|
+
return { recordId: cursor.recordId };
|
|
112
|
+
}
|
|
113
|
+
__name(copyCursor, "copyCursor");
|
|
114
|
+
function parseGoalRecord(value) {
|
|
115
|
+
if (!isRecord(value) || !hasOnlyKeys(value, [
|
|
116
|
+
"goalId",
|
|
117
|
+
"revision",
|
|
118
|
+
"objective",
|
|
119
|
+
"status",
|
|
120
|
+
"evidenceCursor",
|
|
121
|
+
"turnCount",
|
|
122
|
+
"activeTimeMs",
|
|
123
|
+
"createdAt",
|
|
124
|
+
"updatedAt",
|
|
125
|
+
"evidenceCheckpoint",
|
|
126
|
+
"lastReason"
|
|
127
|
+
]) || typeof value["goalId"] !== "string" || !value["goalId"] || !isNonNegativeInteger(value["revision"]) || value["revision"] === 0 || typeof value["objective"] !== "string" || !value["objective"].trim() || !isGoalStatus(value["status"]) || !isTranscriptCursor(value["evidenceCursor"]) || !isNonNegativeInteger(value["turnCount"]) || !isNonNegativeNumber(value["activeTimeMs"]) || !isFiniteNumber(value["createdAt"]) || !isFiniteNumber(value["updatedAt"]) || !isGoalEvidenceCheckpoint(value["evidenceCheckpoint"]) || value["lastReason"] !== void 0 && typeof value["lastReason"] !== "string") {
|
|
128
|
+
return void 0;
|
|
147
129
|
}
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
parsedUrl = new URL(urlToParse, "https://github.com");
|
|
151
|
-
} catch {
|
|
152
|
-
throw new Error(
|
|
153
|
-
`Owner & repo could not be extracted from remote URL: ${remoteUrl}`
|
|
154
|
-
);
|
|
130
|
+
if (value["evidenceCheckpoint"] && value["evidenceCursor"].recordId !== value["evidenceCheckpoint"].checkpointId) {
|
|
131
|
+
return void 0;
|
|
155
132
|
}
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
133
|
+
return {
|
|
134
|
+
goalId: value["goalId"],
|
|
135
|
+
revision: value["revision"],
|
|
136
|
+
objective: value["objective"],
|
|
137
|
+
status: value["status"],
|
|
138
|
+
evidenceCursor: copyCursor(value["evidenceCursor"]),
|
|
139
|
+
turnCount: value["turnCount"],
|
|
140
|
+
activeTimeMs: value["activeTimeMs"],
|
|
141
|
+
createdAt: value["createdAt"],
|
|
142
|
+
updatedAt: value["updatedAt"],
|
|
143
|
+
...value["evidenceCheckpoint"] === void 0 ? {} : {
|
|
144
|
+
evidenceCheckpoint: structuredClone(value["evidenceCheckpoint"])
|
|
145
|
+
},
|
|
146
|
+
...value["lastReason"] === void 0 ? {} : { lastReason: value["lastReason"] }
|
|
147
|
+
};
|
|
148
|
+
}
|
|
149
|
+
__name(parseGoalRecord, "parseGoalRecord");
|
|
150
|
+
function isTranscriptCursor(value) {
|
|
151
|
+
return isRecord(value) && hasOnlyKeys(value, ["recordId"]) && (typeof value["recordId"] === "string" || value["recordId"] === null);
|
|
152
|
+
}
|
|
153
|
+
__name(isTranscriptCursor, "isTranscriptCursor");
|
|
154
|
+
function isGoalStatus(value) {
|
|
155
|
+
return value === "active" || value === "paused" || value === "blocked" || value === "usage_limited" || value === "complete";
|
|
156
|
+
}
|
|
157
|
+
__name(isGoalStatus, "isGoalStatus");
|
|
158
|
+
function isGoalActivity(value) {
|
|
159
|
+
return value === "idle" || value === "running" || value === "verifying";
|
|
160
|
+
}
|
|
161
|
+
__name(isGoalActivity, "isGoalActivity");
|
|
162
|
+
function isGoalStateCause(value) {
|
|
163
|
+
return value === "create" || value === "replace" || value === "edit" || value === "pause" || value === "resume" || value === "turn_finished" || value === "checkpoint" || value === "verifier_accept" || value === "verifier_reject" || value === "complete" || value === "blocked" || value === "usage_limited" || value === "clear" || value === "migrated";
|
|
164
|
+
}
|
|
165
|
+
__name(isGoalStateCause, "isGoalStateCause");
|
|
166
|
+
function isGoalEvidenceCheckpoint(value) {
|
|
167
|
+
if (value === void 0)
|
|
168
|
+
return true;
|
|
169
|
+
if (!isRecord(value) || !hasOnlyKeys(value, ["checkpointId", "createdAt", "claims"]) || typeof value["checkpointId"] !== "string" || value["checkpointId"].length === 0 || !isFiniteNumber(value["createdAt"]) || !Array.isArray(value["claims"]) || value["claims"].length === 0 || value["claims"].length > GOAL_CHECKPOINT_CLAIM_LIMIT) {
|
|
170
|
+
return false;
|
|
160
171
|
}
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
172
|
+
let checkpointBytes = 0;
|
|
173
|
+
for (const [index, claim] of value["claims"].entries()) {
|
|
174
|
+
if (!isRecord(claim) || !hasOnlyKeys(claim, ["id", "proofKind", "claim", "sourceRefs"]) || claim["id"] !== `${value["checkpointId"]}:${index + 1}` || !isGoalEvidenceProofKind(claim["proofKind"]) || typeof claim["claim"] !== "string" || claim["claim"].trim().length === 0 || [...claim["claim"]].length > GOAL_CHECKPOINT_CLAIM_MAX_CHARACTERS || !Array.isArray(claim["sourceRefs"]) || claim["sourceRefs"].length === 0 || claim["sourceRefs"].length > GOAL_CHECKPOINT_SOURCE_REFERENCE_LIMIT || new Set(claim["sourceRefs"]).size !== claim["sourceRefs"].length || claim["sourceRefs"].some((reference) => typeof reference !== "string" || reference.length === 0)) {
|
|
175
|
+
return false;
|
|
176
|
+
}
|
|
177
|
+
checkpointBytes += new TextEncoder().encode(claim["claim"]).byteLength;
|
|
178
|
+
if (checkpointBytes > GOAL_CHECKPOINT_CLAIM_MAX_BYTES)
|
|
179
|
+
return false;
|
|
166
180
|
}
|
|
167
|
-
return
|
|
181
|
+
return true;
|
|
168
182
|
}
|
|
169
|
-
__name(
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
"
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
];
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
183
|
+
__name(isGoalEvidenceCheckpoint, "isGoalEvidenceCheckpoint");
|
|
184
|
+
function isCheckpointPending(value) {
|
|
185
|
+
return value === void 0 || isRecord(value) && hasOnlyKeys(value, ["permit", "recordUuid"]) && isGoalTurnPermit(value["permit"]) && typeof value["recordUuid"] === "string" && value["recordUuid"].length > 0;
|
|
186
|
+
}
|
|
187
|
+
__name(isCheckpointPending, "isCheckpointPending");
|
|
188
|
+
function isGoalTurnPermit(value) {
|
|
189
|
+
return isRecord(value) && hasOnlyKeys(value, ["goalId", "revision", "turnId"]) && typeof value["goalId"] === "string" && value["goalId"].length > 0 && isNonNegativeInteger(value["revision"]) && value["revision"] > 0 && typeof value["turnId"] === "string" && value["turnId"].length > 0;
|
|
190
|
+
}
|
|
191
|
+
__name(isGoalTurnPermit, "isGoalTurnPermit");
|
|
192
|
+
function isBlockedAudit(value) {
|
|
193
|
+
return value === void 0 || isRecord(value) && hasOnlyKeys(value, ["fingerprint", "count", "turnIds"]) && typeof value["fingerprint"] === "string" && value["fingerprint"].length > 0 && isNonNegativeInteger(value["count"]) && value["count"] > 0 && value["count"] <= MAX_BLOCKED_AUDIT_COUNT && Array.isArray(value["turnIds"]) && value["turnIds"].length === value["count"] && value["turnIds"].every((turnId) => typeof turnId === "string" && turnId.length > 0);
|
|
194
|
+
}
|
|
195
|
+
__name(isBlockedAudit, "isBlockedAudit");
|
|
196
|
+
function isRecord(value) {
|
|
197
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
198
|
+
}
|
|
199
|
+
__name(isRecord, "isRecord");
|
|
200
|
+
function hasOnlyKeys(value, keys) {
|
|
201
|
+
return Object.keys(value).every((key) => keys.includes(key));
|
|
202
|
+
}
|
|
203
|
+
__name(hasOnlyKeys, "hasOnlyKeys");
|
|
204
|
+
function isNonNegativeInteger(value) {
|
|
205
|
+
return typeof value === "number" && Number.isInteger(value) && value >= 0;
|
|
206
|
+
}
|
|
207
|
+
__name(isNonNegativeInteger, "isNonNegativeInteger");
|
|
208
|
+
function isNonNegativeNumber(value) {
|
|
209
|
+
return typeof value === "number" && Number.isFinite(value) && value >= 0;
|
|
210
|
+
}
|
|
211
|
+
__name(isNonNegativeNumber, "isNonNegativeNumber");
|
|
212
|
+
function isFiniteNumber(value) {
|
|
213
|
+
return typeof value === "number" && Number.isFinite(value);
|
|
214
|
+
}
|
|
215
|
+
__name(isFiniteNumber, "isFiniteNumber");
|
|
216
|
+
|
|
217
|
+
// packages/core/dist/src/goals/goal-legacy-projection.js
|
|
218
|
+
init_esbuild_shims();
|
|
219
|
+
function projectGoalStateToLegacy2(payload, previousGoal = null) {
|
|
220
|
+
const snapshotGoal = payload.snapshot.goal;
|
|
221
|
+
const displayGoal = snapshotGoal ?? previousGoal;
|
|
222
|
+
const kind = legacyStatusKind(payload);
|
|
223
|
+
const goalStatus = {
|
|
224
|
+
type: "goal_status",
|
|
225
|
+
kind,
|
|
226
|
+
condition: displayGoal?.objective ?? "",
|
|
227
|
+
...displayGoal ? { iterations: displayGoal.turnCount } : {},
|
|
228
|
+
...displayGoal ? { setAt: displayGoal.createdAt } : {},
|
|
229
|
+
...displayGoal ? { durationMs: displayGoal.activeTimeMs } : {},
|
|
230
|
+
...displayGoal?.lastReason === void 0 ? {} : { lastReason: displayGoal.lastReason }
|
|
231
|
+
};
|
|
232
|
+
const terminalKind = kind === "achieved" || kind === "failed" || kind === "aborted" ? kind : void 0;
|
|
233
|
+
return {
|
|
234
|
+
activeGoal: snapshotGoal?.status === "active" ? {
|
|
235
|
+
condition: snapshotGoal.objective,
|
|
236
|
+
iterations: snapshotGoal.turnCount,
|
|
237
|
+
setAt: snapshotGoal.createdAt,
|
|
238
|
+
...snapshotGoal.lastReason === void 0 ? {} : { lastReason: snapshotGoal.lastReason }
|
|
239
|
+
} : null,
|
|
240
|
+
goalStatus,
|
|
241
|
+
goalTerminal: terminalKind && displayGoal ? {
|
|
242
|
+
kind: terminalKind,
|
|
243
|
+
condition: displayGoal.objective,
|
|
244
|
+
iterations: displayGoal.turnCount,
|
|
245
|
+
durationMs: displayGoal.activeTimeMs,
|
|
246
|
+
...displayGoal.lastReason === void 0 ? {} : { lastReason: displayGoal.lastReason }
|
|
247
|
+
} : null
|
|
248
|
+
};
|
|
249
|
+
}
|
|
250
|
+
__name(projectGoalStateToLegacy2, "projectGoalStateToLegacy");
|
|
251
|
+
function isGoalCheckpointBookkeepingTransition(previous, next) {
|
|
252
|
+
const previousGoal = previous?.goal;
|
|
253
|
+
const nextGoal = next.goal;
|
|
254
|
+
if (!previousGoal || !nextGoal)
|
|
255
|
+
return false;
|
|
256
|
+
return previousGoal.goalId === nextGoal.goalId && previousGoal.revision === nextGoal.revision && previousGoal.objective === nextGoal.objective && previousGoal.status === nextGoal.status && previousGoal.turnCount === nextGoal.turnCount && previousGoal.createdAt === nextGoal.createdAt && previousGoal.lastReason === nextGoal.lastReason;
|
|
257
|
+
}
|
|
258
|
+
__name(isGoalCheckpointBookkeepingTransition, "isGoalCheckpointBookkeepingTransition");
|
|
259
|
+
function isGoalCheckpointBookkeepingCause(cause, previousCause) {
|
|
260
|
+
if (cause === "checkpoint")
|
|
261
|
+
return true;
|
|
262
|
+
return cause === "verifier_reject" && (previousCause === "verifier_reject" || previousCause === "checkpoint");
|
|
263
|
+
}
|
|
264
|
+
__name(isGoalCheckpointBookkeepingCause, "isGoalCheckpointBookkeepingCause");
|
|
265
|
+
function isGoalCheckpointBookkeepingRecord(input) {
|
|
266
|
+
return isGoalCheckpointBookkeepingTransition(input.previous, input.next) && isGoalCheckpointBookkeepingCause(input.cause, input.previousCause);
|
|
267
|
+
}
|
|
268
|
+
__name(isGoalCheckpointBookkeepingRecord, "isGoalCheckpointBookkeepingRecord");
|
|
269
|
+
function legacyStatusKind(payload) {
|
|
270
|
+
switch (payload.cause) {
|
|
271
|
+
case "create":
|
|
272
|
+
case "replace":
|
|
273
|
+
case "edit":
|
|
274
|
+
case "resume":
|
|
275
|
+
return "set";
|
|
276
|
+
case "complete":
|
|
277
|
+
return "achieved";
|
|
278
|
+
case "clear":
|
|
279
|
+
return "cleared";
|
|
280
|
+
// A migrated goal is always persisted `paused` (`createMigratedGoalState`),
|
|
281
|
+
// and nothing drives a paused goal. Projecting it as `set` would re-assert
|
|
282
|
+
// "active" to every client that derives the live goal from the newest card,
|
|
283
|
+
// leaving a phantom running goal behind a resumed pre-v2 transcript.
|
|
284
|
+
case "migrated":
|
|
285
|
+
case "pause":
|
|
286
|
+
return "paused";
|
|
287
|
+
case "blocked":
|
|
288
|
+
case "usage_limited":
|
|
289
|
+
return "aborted";
|
|
290
|
+
case "turn_finished":
|
|
291
|
+
case "checkpoint":
|
|
292
|
+
case "verifier_accept":
|
|
293
|
+
case "verifier_reject":
|
|
294
|
+
return payload.snapshot.goal?.status === "complete" ? "achieved" : payload.snapshot.goal?.status === "blocked" || payload.snapshot.goal?.status === "usage_limited" ? "aborted" : "checking";
|
|
295
|
+
default:
|
|
296
|
+
return assertNever(payload.cause);
|
|
197
297
|
}
|
|
198
|
-
};
|
|
199
|
-
function isWorkspaceGenerationClosed(error) {
|
|
200
|
-
return Boolean(
|
|
201
|
-
error && typeof error === "object" && "code" in error && error.code === "workspace_generation_closed"
|
|
202
|
-
);
|
|
203
298
|
}
|
|
204
|
-
__name(
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
299
|
+
__name(legacyStatusKind, "legacyStatusKind");
|
|
300
|
+
function assertNever(value) {
|
|
301
|
+
throw new Error(`Unsupported Goal state cause: ${String(value)}`);
|
|
302
|
+
}
|
|
303
|
+
__name(assertNever, "assertNever");
|
|
304
|
+
|
|
305
|
+
// packages/acp-bridge/src/transcript-replay.ts
|
|
306
|
+
var MISSING_TRANSCRIPT_TOOL_RESULT_MESSAGE = "Tool result missing from saved history; the previous run likely ended before this tool completed.";
|
|
307
|
+
var TRANSCRIPT_GOAL_STATUS_KINDS = /* @__PURE__ */ new Set([
|
|
308
|
+
"set",
|
|
309
|
+
"achieved",
|
|
310
|
+
"cleared",
|
|
311
|
+
"failed",
|
|
312
|
+
"aborted",
|
|
313
|
+
// A paused goal is not running, and dropping the card here is not neutral:
|
|
314
|
+
// the replay stream is what feeds the goal renderer, so the older `set` card
|
|
315
|
+
// stays newest and every surface keeps claiming autonomous work is under way.
|
|
316
|
+
// Kept in step with `GOAL_STATUS_KINDS`, which the daemon-side reader
|
|
317
|
+
// (`parseGoalStatusItem`) validates the same on-disk cards against.
|
|
318
|
+
"paused",
|
|
319
|
+
"checking"
|
|
320
|
+
]);
|
|
321
|
+
function isObjectRecord(value) {
|
|
322
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
323
|
+
}
|
|
324
|
+
__name(isObjectRecord, "isObjectRecord");
|
|
325
|
+
function replaceTextPartsForDisplay(parts, displayText) {
|
|
326
|
+
const projected = [];
|
|
327
|
+
let replacedText = false;
|
|
328
|
+
for (const part of parts ?? []) {
|
|
329
|
+
if (isObjectRecord(part) && typeof part["text"] === "string") {
|
|
330
|
+
if (!replacedText && displayText.length > 0) {
|
|
331
|
+
projected.push({ text: displayText });
|
|
224
332
|
}
|
|
225
|
-
|
|
333
|
+
replacedText = true;
|
|
334
|
+
} else {
|
|
335
|
+
projected.push(part);
|
|
226
336
|
}
|
|
227
337
|
}
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
const cwd = options.cwd ?? process.cwd();
|
|
231
|
-
const fileOps = options.fileOps ?? nodeFileOps;
|
|
232
|
-
if (!await isGitHubRepositoryAsync({ cwd })) {
|
|
233
|
-
throw new SetupGithubError(
|
|
234
|
-
"github_repository_not_found",
|
|
235
|
-
"Unable to determine the GitHub repository. /setup-github must be run from a git repository.",
|
|
236
|
-
400
|
|
237
|
-
);
|
|
238
|
-
}
|
|
239
|
-
let gitRepoRoot;
|
|
240
|
-
try {
|
|
241
|
-
gitRepoRoot = await getGitRepoRootAsync({ cwd });
|
|
242
|
-
} catch (error) {
|
|
243
|
-
debugLogger2.debug("Failed to get git repo root:", error);
|
|
244
|
-
throw new SetupGithubError(
|
|
245
|
-
"github_repository_not_found",
|
|
246
|
-
"Unable to determine the GitHub repository. /setup-github must be run from a git repository.",
|
|
247
|
-
400
|
|
248
|
-
);
|
|
249
|
-
}
|
|
250
|
-
if (options.workspaceRoot) {
|
|
251
|
-
const [gitRootReal, workspaceReal] = await Promise.all([
|
|
252
|
-
realpathOrResolve(gitRepoRoot),
|
|
253
|
-
realpathOrResolve(options.workspaceRoot)
|
|
254
|
-
]);
|
|
255
|
-
if (gitRootReal !== workspaceReal) {
|
|
256
|
-
throw new SetupGithubError(
|
|
257
|
-
"github_git_root_mismatch",
|
|
258
|
-
"The Git repository root must match the daemon workspace root.",
|
|
259
|
-
400
|
|
260
|
-
);
|
|
261
|
-
}
|
|
338
|
+
if (!replacedText && displayText.length > 0) {
|
|
339
|
+
projected.push({ text: displayText });
|
|
262
340
|
}
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
`qwen setup-github: failed to determine latest qwen-code-action release: ${error instanceof Error ? error.message : String(error)}`
|
|
270
|
-
);
|
|
271
|
-
debugLogger2.debug(
|
|
272
|
-
"Failed to determine latest qwen-code-action release:",
|
|
273
|
-
error
|
|
274
|
-
);
|
|
275
|
-
throw new SetupGithubError(
|
|
276
|
-
"github_release_lookup_failed",
|
|
277
|
-
"Unable to determine the latest qwen-code-action release on GitHub.",
|
|
278
|
-
502
|
|
279
|
-
);
|
|
341
|
+
return projected;
|
|
342
|
+
}
|
|
343
|
+
__name(replaceTextPartsForDisplay, "replaceTextPartsForDisplay");
|
|
344
|
+
function toTranscriptEpochMs(timestamp) {
|
|
345
|
+
if (typeof timestamp === "number") {
|
|
346
|
+
return Number.isFinite(timestamp) ? timestamp : void 0;
|
|
280
347
|
}
|
|
281
|
-
|
|
282
|
-
const
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
const
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
gitRepoRoot,
|
|
293
|
-
releaseTag,
|
|
294
|
-
readmeUrl,
|
|
295
|
-
...secretsUrl ? { secretsUrl } : {},
|
|
296
|
-
workflows: [],
|
|
297
|
-
gitignore: { path: ".gitignore", status: "skipped" },
|
|
298
|
-
warnings: []
|
|
348
|
+
if (typeof timestamp !== "string") return void 0;
|
|
349
|
+
const epochMs = new Date(timestamp).getTime();
|
|
350
|
+
return Number.isFinite(epochMs) ? epochMs : void 0;
|
|
351
|
+
}
|
|
352
|
+
__name(toTranscriptEpochMs, "toTranscriptEpochMs");
|
|
353
|
+
function buildUpdateMeta(options) {
|
|
354
|
+
const timestamp = toTranscriptEpochMs(options.timestamp);
|
|
355
|
+
const sourceRecordIds = dedupeStrings(options.sourceRecordIds ?? []);
|
|
356
|
+
const qwenTranscript = {
|
|
357
|
+
...sourceRecordIds.length > 0 ? { sourceRecordIds } : {},
|
|
358
|
+
...options.planToolCallId ? { planToolCallId: options.planToolCallId } : {}
|
|
299
359
|
};
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
360
|
+
const meta = {
|
|
361
|
+
...options.extra ?? {},
|
|
362
|
+
...timestamp !== void 0 ? { timestamp } : {},
|
|
363
|
+
...Object.keys(qwenTranscript).length > 0 ? { qwenTranscript } : {}
|
|
364
|
+
};
|
|
365
|
+
return Object.keys(meta).length > 0 ? meta : void 0;
|
|
366
|
+
}
|
|
367
|
+
__name(buildUpdateMeta, "buildUpdateMeta");
|
|
368
|
+
function createTranscriptMessageUpdate(options) {
|
|
369
|
+
const meta = buildUpdateMeta(options);
|
|
370
|
+
return {
|
|
371
|
+
sessionUpdate: options.role === "user" ? "user_message_chunk" : options.thought ? "agent_thought_chunk" : "agent_message_chunk",
|
|
372
|
+
content: { type: "text", text: options.text },
|
|
373
|
+
...meta ? { _meta: meta } : {}
|
|
374
|
+
};
|
|
375
|
+
}
|
|
376
|
+
__name(createTranscriptMessageUpdate, "createTranscriptMessageUpdate");
|
|
377
|
+
function createTranscriptImageUpdate(options) {
|
|
378
|
+
const meta = buildUpdateMeta(options);
|
|
379
|
+
return {
|
|
380
|
+
sessionUpdate: "user_message_chunk",
|
|
381
|
+
content: { type: "image", data: options.data, mimeType: options.mimeType },
|
|
382
|
+
...meta ? { _meta: meta } : {}
|
|
383
|
+
};
|
|
384
|
+
}
|
|
385
|
+
__name(createTranscriptImageUpdate, "createTranscriptImageUpdate");
|
|
386
|
+
function createTranscriptUsageUpdate(usageMetadata, options = {}) {
|
|
387
|
+
const usage = {
|
|
388
|
+
inputTokens: finiteNumber(usageMetadata.promptTokenCount) ?? 0,
|
|
389
|
+
outputTokens: finiteNumber(usageMetadata.candidatesTokenCount) ?? 0,
|
|
390
|
+
totalTokens: finiteNumber(usageMetadata.totalTokenCount) ?? 0,
|
|
391
|
+
...finiteNumber(usageMetadata.thoughtsTokenCount) !== void 0 ? { thoughtTokens: finiteNumber(usageMetadata.thoughtsTokenCount) } : {},
|
|
392
|
+
...finiteNumber(usageMetadata.cachedContentTokenCount) !== void 0 ? {
|
|
393
|
+
cachedReadTokens: finiteNumber(usageMetadata.cachedContentTokenCount)
|
|
394
|
+
} : {}
|
|
395
|
+
};
|
|
396
|
+
const meta = buildUpdateMeta({
|
|
397
|
+
...options,
|
|
398
|
+
extra: { usage, ...options.extra ?? {} }
|
|
399
|
+
});
|
|
400
|
+
return {
|
|
401
|
+
sessionUpdate: "agent_message_chunk",
|
|
402
|
+
content: { type: "text", text: options.text ?? "" },
|
|
403
|
+
_meta: meta
|
|
404
|
+
};
|
|
405
|
+
}
|
|
406
|
+
__name(createTranscriptUsageUpdate, "createTranscriptUsageUpdate");
|
|
407
|
+
function createTranscriptToolCallStartUpdate(options) {
|
|
408
|
+
const provenance = resolveToolProvenance(options.toolName);
|
|
409
|
+
return {
|
|
410
|
+
sessionUpdate: options.asUpdate ? "tool_call_update" : "tool_call",
|
|
411
|
+
toolCallId: options.callId,
|
|
412
|
+
status: options.status ?? "pending",
|
|
413
|
+
title: options.metadata.title,
|
|
414
|
+
content: [],
|
|
415
|
+
locations: [...options.metadata.locations],
|
|
416
|
+
kind: options.metadata.kind,
|
|
417
|
+
rawInput: options.args ?? {},
|
|
418
|
+
_meta: buildUpdateMeta({
|
|
419
|
+
...options,
|
|
420
|
+
extra: {
|
|
421
|
+
toolName: options.toolName,
|
|
422
|
+
provenance: provenance.provenance,
|
|
423
|
+
...provenance.serverId ? { serverId: provenance.serverId } : {},
|
|
424
|
+
...options.extra ?? {}
|
|
339
425
|
}
|
|
340
|
-
}
|
|
341
|
-
}
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
426
|
+
})
|
|
427
|
+
};
|
|
428
|
+
}
|
|
429
|
+
__name(createTranscriptToolCallStartUpdate, "createTranscriptToolCallStartUpdate");
|
|
430
|
+
function createTranscriptToolCallResultUpdate(options) {
|
|
431
|
+
const provenance = resolveToolProvenance(options.toolName);
|
|
432
|
+
const content = buildToolResultContent(options);
|
|
433
|
+
const update = {
|
|
434
|
+
sessionUpdate: "tool_call_update",
|
|
435
|
+
toolCallId: options.callId,
|
|
436
|
+
status: options.success ? "completed" : "failed",
|
|
437
|
+
content,
|
|
438
|
+
_meta: buildUpdateMeta({
|
|
439
|
+
...options,
|
|
440
|
+
extra: {
|
|
441
|
+
toolName: options.toolName,
|
|
442
|
+
provenance: provenance.provenance,
|
|
443
|
+
...provenance.serverId ? { serverId: provenance.serverId } : {},
|
|
444
|
+
...options.artifacts && options.artifacts.length > 0 ? { artifacts: options.artifacts } : {},
|
|
445
|
+
...options.extra ?? {}
|
|
446
|
+
}
|
|
447
|
+
})
|
|
448
|
+
};
|
|
449
|
+
if (options.resultDisplay !== void 0 && !isTruncatedSessionDiffDisplay(options.resultDisplay)) {
|
|
450
|
+
update["rawOutput"] = options.resultDisplay;
|
|
350
451
|
}
|
|
351
|
-
return
|
|
452
|
+
return update;
|
|
352
453
|
}
|
|
353
|
-
__name(
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
const content = GITIGNORE_ENTRIES.join("\n") + "\n";
|
|
362
|
-
await fileOps.writeTextFile(gitRepoRoot, ".gitignore", content);
|
|
363
|
-
return {
|
|
364
|
-
path: ".gitignore",
|
|
365
|
-
status: "created",
|
|
366
|
-
added: [...GITIGNORE_ENTRIES]
|
|
367
|
-
};
|
|
454
|
+
__name(createTranscriptToolCallResultUpdate, "createTranscriptToolCallResultUpdate");
|
|
455
|
+
function createTranscriptPlanUpdate(todos, cumulativeUsage, options = {}) {
|
|
456
|
+
const meta = buildUpdateMeta({
|
|
457
|
+
...options,
|
|
458
|
+
extra: {
|
|
459
|
+
...cumulativeUsage ? { stats: { ...cumulativeUsage } } : {},
|
|
460
|
+
...options.todoPlanId ? { qwenTodoPlan: { id: options.todoPlanId } } : {},
|
|
461
|
+
...options.extra ?? {}
|
|
368
462
|
}
|
|
369
|
-
|
|
370
|
-
|
|
463
|
+
});
|
|
464
|
+
return {
|
|
465
|
+
sessionUpdate: "plan",
|
|
466
|
+
entries: todos.map((todo) => ({
|
|
467
|
+
content: todo.content,
|
|
468
|
+
priority: "medium",
|
|
469
|
+
status: todo.status,
|
|
470
|
+
...todo.id || todo.blockedBy ? {
|
|
471
|
+
_meta: {
|
|
472
|
+
qwenTodo: {
|
|
473
|
+
...todo.id ? { id: todo.id } : {},
|
|
474
|
+
...todo.blockedBy ? { blockedBy: [...todo.blockedBy] } : {}
|
|
475
|
+
}
|
|
476
|
+
}
|
|
477
|
+
} : {}
|
|
478
|
+
})),
|
|
479
|
+
...meta ? { _meta: meta } : {}
|
|
480
|
+
};
|
|
481
|
+
}
|
|
482
|
+
__name(createTranscriptPlanUpdate, "createTranscriptPlanUpdate");
|
|
483
|
+
function extractTranscriptTodoPlan(resultDisplay, args) {
|
|
484
|
+
const fromDisplay = extractTodoPlanFromDisplay(resultDisplay);
|
|
485
|
+
if (fromDisplay) return fromDisplay;
|
|
486
|
+
if (resultDisplay !== null && resultDisplay !== void 0) return null;
|
|
487
|
+
return args && Array.isArray(args["todos"]) ? { todos: normalizeTodos(args["todos"]) } : null;
|
|
488
|
+
}
|
|
489
|
+
__name(extractTranscriptTodoPlan, "extractTranscriptTodoPlan");
|
|
490
|
+
function createTranscriptReplayMachine(options = {}) {
|
|
491
|
+
return new DefaultTranscriptReplayMachine(options);
|
|
492
|
+
}
|
|
493
|
+
__name(createTranscriptReplayMachine, "createTranscriptReplayMachine");
|
|
494
|
+
var DefaultTranscriptReplayMachine = class {
|
|
495
|
+
constructor(options) {
|
|
496
|
+
this.options = options;
|
|
497
|
+
const initialState = parseInitialState(
|
|
498
|
+
options.initialState,
|
|
499
|
+
options.onDiagnostic
|
|
371
500
|
);
|
|
372
|
-
|
|
373
|
-
|
|
501
|
+
this.usage = { ...initialState.cumulativeUsage };
|
|
502
|
+
this.goalState = initialState.goalState;
|
|
503
|
+
this.goalCause = initialState.goalCause;
|
|
504
|
+
for (const pending of initialState.pendingToolCalls) {
|
|
505
|
+
this.pendingToolCalls.set(pending.callId, pending);
|
|
506
|
+
this.usedToolCallIds.add(pending.callId);
|
|
507
|
+
}
|
|
508
|
+
for (const gap of options.gaps ?? []) {
|
|
509
|
+
if (!this.gapByChild.has(gap.childUuid)) {
|
|
510
|
+
this.gapByChild.set(gap.childUuid, gap);
|
|
511
|
+
}
|
|
374
512
|
}
|
|
375
|
-
const nextContent = existingContent + "\n" + missingEntries.join("\n") + "\n";
|
|
376
|
-
await fileOps.writeTextFile(gitRepoRoot, ".gitignore", nextContent);
|
|
377
|
-
return {
|
|
378
|
-
path: ".gitignore",
|
|
379
|
-
status: "updated",
|
|
380
|
-
added: missingEntries
|
|
381
|
-
};
|
|
382
|
-
} catch (error) {
|
|
383
|
-
if (isWorkspaceGenerationClosed(error)) throw error;
|
|
384
|
-
debugLogger2.debug("Failed to update .gitignore:", error);
|
|
385
|
-
return {
|
|
386
|
-
path: ".gitignore",
|
|
387
|
-
status: "failed",
|
|
388
|
-
error: error instanceof Error ? error.message : String(error)
|
|
389
|
-
};
|
|
390
513
|
}
|
|
391
|
-
|
|
392
|
-
__name(
|
|
393
|
-
async function downloadWorkflows(options) {
|
|
394
|
-
const internalAbort = new AbortController();
|
|
395
|
-
try {
|
|
396
|
-
const dispatcher = options.proxy ? new (await loadUndici()).ProxyAgent(options.proxy) : void 0;
|
|
397
|
-
return await Promise.all(
|
|
398
|
-
GITHUB_WORKFLOW_PATHS.map(async (workflow) => {
|
|
399
|
-
const endpoint = `https://raw.githubusercontent.com/QwenLM/qwen-code-action/refs/tags/${options.releaseTag}/examples/workflows/${workflow}`;
|
|
400
|
-
const response = await options.fetchImpl(endpoint, {
|
|
401
|
-
method: "GET",
|
|
402
|
-
dispatcher,
|
|
403
|
-
signal: AbortSignal.any([
|
|
404
|
-
AbortSignal.timeout(3e4),
|
|
405
|
-
internalAbort.signal,
|
|
406
|
-
...options.abortSignal ? [options.abortSignal] : []
|
|
407
|
-
])
|
|
408
|
-
});
|
|
409
|
-
if (!response.ok) {
|
|
410
|
-
throw new Error(
|
|
411
|
-
`Invalid response code downloading ${endpoint}: ${response.status} - ${response.statusText}`
|
|
412
|
-
);
|
|
413
|
-
}
|
|
414
|
-
return {
|
|
415
|
-
sourcePath: workflow,
|
|
416
|
-
content: await readResponseTextWithLimit(response, workflow)
|
|
417
|
-
};
|
|
418
|
-
})
|
|
419
|
-
);
|
|
420
|
-
} catch (error) {
|
|
421
|
-
internalAbort.abort();
|
|
422
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
423
|
-
debugLogger2.debug("Failed to download qwen-code-action workflows:", error);
|
|
424
|
-
throw new SetupGithubError(
|
|
425
|
-
"github_workflow_download_failed",
|
|
426
|
-
`Unable to download qwen-code-action workflows from GitHub. ${message}`,
|
|
427
|
-
502
|
|
428
|
-
);
|
|
514
|
+
static {
|
|
515
|
+
__name(this, "DefaultTranscriptReplayMachine");
|
|
429
516
|
}
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
517
|
+
pendingToolCalls = /* @__PURE__ */ new Map();
|
|
518
|
+
usedToolCallIds = /* @__PURE__ */ new Set();
|
|
519
|
+
gapByChild = /* @__PURE__ */ new Map();
|
|
520
|
+
usage;
|
|
521
|
+
finalized = false;
|
|
522
|
+
goalState;
|
|
523
|
+
goalCause;
|
|
524
|
+
*project(record) {
|
|
525
|
+
if (this.finalized) {
|
|
437
526
|
throw new Error(
|
|
438
|
-
|
|
527
|
+
"Cannot project records after transcript replay finalize."
|
|
439
528
|
);
|
|
440
529
|
}
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
530
|
+
let ordinal = 0;
|
|
531
|
+
const emit = /* @__PURE__ */ __name((update) => ({
|
|
532
|
+
sourceRecordId: record.uuid,
|
|
533
|
+
...record.timestamp ? { sourceTimestamp: record.timestamp } : {},
|
|
534
|
+
emissionOrdinal: ordinal++,
|
|
535
|
+
update
|
|
536
|
+
}), "emit");
|
|
537
|
+
const meta = {
|
|
538
|
+
timestamp: record.timestamp,
|
|
539
|
+
sourceRecordIds: [record.uuid],
|
|
540
|
+
...record.subtype === "realtime_message" ? {
|
|
541
|
+
extra: {
|
|
542
|
+
source: "realtime_voice",
|
|
543
|
+
qwenDiscreteMessage: true
|
|
544
|
+
}
|
|
545
|
+
} : {}
|
|
546
|
+
};
|
|
547
|
+
const gap = this.gapByChild.get(record.uuid);
|
|
548
|
+
if (gap) {
|
|
549
|
+
yield emit(
|
|
550
|
+
createTranscriptMessageUpdate({
|
|
551
|
+
role: "assistant",
|
|
552
|
+
text: this.formatGap(gap),
|
|
553
|
+
...meta,
|
|
554
|
+
extra: { qwenDiscreteMessage: true }
|
|
555
|
+
})
|
|
556
|
+
);
|
|
557
|
+
}
|
|
558
|
+
switch (record.type) {
|
|
559
|
+
case "user":
|
|
560
|
+
yield* this.projectUserRecord(record, emit, meta);
|
|
561
|
+
break;
|
|
562
|
+
case "assistant":
|
|
563
|
+
yield* this.projectAssistantRecord(record, emit, meta);
|
|
564
|
+
break;
|
|
565
|
+
case "tool_result":
|
|
566
|
+
yield* this.projectToolResult(record, emit, meta);
|
|
567
|
+
break;
|
|
568
|
+
case "system":
|
|
569
|
+
yield* this.projectSystemRecord(record, emit, meta);
|
|
570
|
+
break;
|
|
571
|
+
default:
|
|
572
|
+
this.report(
|
|
573
|
+
"unknown_record_or_part",
|
|
574
|
+
"Skipped an unknown transcript record type.",
|
|
575
|
+
record.uuid
|
|
457
576
|
);
|
|
458
|
-
}
|
|
459
|
-
chunks.push(value);
|
|
460
577
|
}
|
|
461
|
-
} finally {
|
|
462
|
-
reader.releaseLock();
|
|
463
|
-
}
|
|
464
|
-
const body = new Uint8Array(totalBytes);
|
|
465
|
-
let offset = 0;
|
|
466
|
-
for (const chunk of chunks) {
|
|
467
|
-
body.set(chunk, offset);
|
|
468
|
-
offset += chunk.byteLength;
|
|
469
|
-
}
|
|
470
|
-
return new TextDecoder().decode(body);
|
|
471
|
-
}
|
|
472
|
-
__name(readResponseTextWithLimit, "readResponseTextWithLimit");
|
|
473
|
-
async function resolveSecretsUrl(cwd) {
|
|
474
|
-
try {
|
|
475
|
-
const repoInfo = await getGitHubRepoInfoAsync({ cwd });
|
|
476
|
-
return `https://github.com/${repoInfo.owner}/${repoInfo.repo}/settings/secrets/actions`;
|
|
477
|
-
} catch {
|
|
478
|
-
return void 0;
|
|
479
|
-
}
|
|
480
|
-
}
|
|
481
|
-
__name(resolveSecretsUrl, "resolveSecretsUrl");
|
|
482
|
-
async function realpathOrResolve(input) {
|
|
483
|
-
try {
|
|
484
|
-
return await fsp.realpath(input);
|
|
485
|
-
} catch {
|
|
486
|
-
return path.resolve(input);
|
|
487
|
-
}
|
|
488
|
-
}
|
|
489
|
-
__name(realpathOrResolve, "realpathOrResolve");
|
|
490
|
-
|
|
491
|
-
// packages/acp-bridge/src/transcript-replay.ts
|
|
492
|
-
init_esbuild_shims();
|
|
493
|
-
|
|
494
|
-
// packages/core/dist/src/goals/goal-wire.js
|
|
495
|
-
init_esbuild_shims();
|
|
496
|
-
|
|
497
|
-
// packages/core/dist/src/goals/goal-protocol.js
|
|
498
|
-
init_esbuild_shims();
|
|
499
|
-
var GOAL_STATE_VERSION = 2;
|
|
500
|
-
var GOAL_CHECKPOINT_CLAIM_LIMIT = 32;
|
|
501
|
-
var GOAL_CHECKPOINT_CLAIM_MAX_CHARACTERS = 2e3;
|
|
502
|
-
var GOAL_CHECKPOINT_CLAIM_MAX_BYTES = 16e3;
|
|
503
|
-
var GOAL_CHECKPOINT_SOURCE_REFERENCE_LIMIT = 32;
|
|
504
|
-
function isGoalEvidenceProofKind(value) {
|
|
505
|
-
return value === "user_input" || value === "delivered_output" || value === "external_fact";
|
|
506
|
-
}
|
|
507
|
-
__name(isGoalEvidenceProofKind, "isGoalEvidenceProofKind");
|
|
508
|
-
|
|
509
|
-
// packages/core/dist/src/goals/goal-reducer.js
|
|
510
|
-
init_esbuild_shims();
|
|
511
|
-
var MAX_BLOCKED_AUDIT_COUNT = 3;
|
|
512
|
-
function parseGoalStateRecordPayloadV2(value) {
|
|
513
|
-
if (!isRecord(value) || !hasOnlyKeys(value, [
|
|
514
|
-
"v",
|
|
515
|
-
"cause",
|
|
516
|
-
"snapshot",
|
|
517
|
-
"checkpointPending",
|
|
518
|
-
"blockedAudit"
|
|
519
|
-
]) || value["v"] !== GOAL_STATE_VERSION || !isGoalStateCause(value["cause"]) || !isCheckpointPending(value["checkpointPending"]) || !isBlockedAudit(value["blockedAudit"])) {
|
|
520
|
-
return void 0;
|
|
521
578
|
}
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
579
|
+
*finalize() {
|
|
580
|
+
if (this.finalized) return;
|
|
581
|
+
this.finalized = true;
|
|
582
|
+
let ordinal = 0;
|
|
583
|
+
for (const pending of [...this.pendingToolCalls.values()]) {
|
|
584
|
+
this.pendingToolCalls.delete(pending.callId);
|
|
585
|
+
this.report(
|
|
586
|
+
"missing_tool_result",
|
|
587
|
+
"A transcript tool call has no persisted result.",
|
|
588
|
+
pending.sourceRecordId
|
|
589
|
+
);
|
|
590
|
+
yield {
|
|
591
|
+
sourceRecordId: pending.sourceRecordId,
|
|
592
|
+
...pending.sourceTimestamp ? { sourceTimestamp: pending.sourceTimestamp } : {},
|
|
593
|
+
emissionOrdinal: ordinal++,
|
|
594
|
+
update: createTranscriptToolCallResultUpdate({
|
|
595
|
+
toolName: pending.toolName,
|
|
596
|
+
callId: pending.callId,
|
|
597
|
+
success: false,
|
|
598
|
+
errorMessage: MISSING_TRANSCRIPT_TOOL_RESULT_MESSAGE,
|
|
599
|
+
timestamp: pending.sourceTimestamp,
|
|
600
|
+
sourceRecordIds: [pending.sourceRecordId]
|
|
601
|
+
})
|
|
602
|
+
};
|
|
603
|
+
}
|
|
541
604
|
}
|
|
542
|
-
|
|
605
|
+
snapshot() {
|
|
543
606
|
return {
|
|
544
|
-
v:
|
|
545
|
-
|
|
546
|
-
|
|
607
|
+
v: 1,
|
|
608
|
+
pendingToolCalls: [...this.pendingToolCalls.values()].map((pending) => ({
|
|
609
|
+
...pending
|
|
610
|
+
})),
|
|
611
|
+
cumulativeUsage: { ...this.usage },
|
|
612
|
+
...this.goalState ? { goalState: this.goalState } : {},
|
|
613
|
+
...this.goalCause ? { goalCause: this.goalCause } : {}
|
|
547
614
|
};
|
|
548
615
|
}
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
"lastReason"
|
|
574
|
-
]) || typeof value["goalId"] !== "string" || !value["goalId"] || !isNonNegativeInteger(value["revision"]) || value["revision"] === 0 || typeof value["objective"] !== "string" || !value["objective"].trim() || !isGoalStatus(value["status"]) || !isTranscriptCursor(value["evidenceCursor"]) || !isNonNegativeInteger(value["turnCount"]) || !isNonNegativeNumber(value["activeTimeMs"]) || !isFiniteNumber(value["createdAt"]) || !isFiniteNumber(value["updatedAt"]) || !isGoalEvidenceCheckpoint(value["evidenceCheckpoint"]) || value["lastReason"] !== void 0 && typeof value["lastReason"] !== "string") {
|
|
575
|
-
return void 0;
|
|
576
|
-
}
|
|
577
|
-
if (value["evidenceCheckpoint"] && value["evidenceCursor"].recordId !== value["evidenceCheckpoint"].checkpointId) {
|
|
578
|
-
return void 0;
|
|
579
|
-
}
|
|
580
|
-
return {
|
|
581
|
-
goalId: value["goalId"],
|
|
582
|
-
revision: value["revision"],
|
|
583
|
-
objective: value["objective"],
|
|
584
|
-
status: value["status"],
|
|
585
|
-
evidenceCursor: copyCursor(value["evidenceCursor"]),
|
|
586
|
-
turnCount: value["turnCount"],
|
|
587
|
-
activeTimeMs: value["activeTimeMs"],
|
|
588
|
-
createdAt: value["createdAt"],
|
|
589
|
-
updatedAt: value["updatedAt"],
|
|
590
|
-
...value["evidenceCheckpoint"] === void 0 ? {} : {
|
|
591
|
-
evidenceCheckpoint: structuredClone(value["evidenceCheckpoint"])
|
|
592
|
-
},
|
|
593
|
-
...value["lastReason"] === void 0 ? {} : { lastReason: value["lastReason"] }
|
|
594
|
-
};
|
|
595
|
-
}
|
|
596
|
-
__name(parseGoalRecord, "parseGoalRecord");
|
|
597
|
-
function isTranscriptCursor(value) {
|
|
598
|
-
return isRecord(value) && hasOnlyKeys(value, ["recordId"]) && (typeof value["recordId"] === "string" || value["recordId"] === null);
|
|
599
|
-
}
|
|
600
|
-
__name(isTranscriptCursor, "isTranscriptCursor");
|
|
601
|
-
function isGoalStatus(value) {
|
|
602
|
-
return value === "active" || value === "paused" || value === "blocked" || value === "usage_limited" || value === "complete";
|
|
603
|
-
}
|
|
604
|
-
__name(isGoalStatus, "isGoalStatus");
|
|
605
|
-
function isGoalActivity(value) {
|
|
606
|
-
return value === "idle" || value === "running" || value === "verifying";
|
|
607
|
-
}
|
|
608
|
-
__name(isGoalActivity, "isGoalActivity");
|
|
609
|
-
function isGoalStateCause(value) {
|
|
610
|
-
return value === "create" || value === "replace" || value === "edit" || value === "pause" || value === "resume" || value === "turn_finished" || value === "checkpoint" || value === "verifier_accept" || value === "verifier_reject" || value === "complete" || value === "blocked" || value === "usage_limited" || value === "clear" || value === "migrated";
|
|
611
|
-
}
|
|
612
|
-
__name(isGoalStateCause, "isGoalStateCause");
|
|
613
|
-
function isGoalEvidenceCheckpoint(value) {
|
|
614
|
-
if (value === void 0)
|
|
615
|
-
return true;
|
|
616
|
-
if (!isRecord(value) || !hasOnlyKeys(value, ["checkpointId", "createdAt", "claims"]) || typeof value["checkpointId"] !== "string" || value["checkpointId"].length === 0 || !isFiniteNumber(value["createdAt"]) || !Array.isArray(value["claims"]) || value["claims"].length === 0 || value["claims"].length > GOAL_CHECKPOINT_CLAIM_LIMIT) {
|
|
617
|
-
return false;
|
|
618
|
-
}
|
|
619
|
-
let checkpointBytes = 0;
|
|
620
|
-
for (const [index, claim] of value["claims"].entries()) {
|
|
621
|
-
if (!isRecord(claim) || !hasOnlyKeys(claim, ["id", "proofKind", "claim", "sourceRefs"]) || claim["id"] !== `${value["checkpointId"]}:${index + 1}` || !isGoalEvidenceProofKind(claim["proofKind"]) || typeof claim["claim"] !== "string" || claim["claim"].trim().length === 0 || [...claim["claim"]].length > GOAL_CHECKPOINT_CLAIM_MAX_CHARACTERS || !Array.isArray(claim["sourceRefs"]) || claim["sourceRefs"].length === 0 || claim["sourceRefs"].length > GOAL_CHECKPOINT_SOURCE_REFERENCE_LIMIT || new Set(claim["sourceRefs"]).size !== claim["sourceRefs"].length || claim["sourceRefs"].some((reference) => typeof reference !== "string" || reference.length === 0)) {
|
|
622
|
-
return false;
|
|
616
|
+
*projectUserRecord(record, emit, meta) {
|
|
617
|
+
const payload = isObjectRecord(record.systemPayload) ? record.systemPayload : void 0;
|
|
618
|
+
if (record.subtype === "goal_runtime" || record.subtype === "notification" || record.subtype === "cron" || record.subtype === "mid_turn_user_message") {
|
|
619
|
+
const displayText = payload && typeof payload["displayText"] === "string" ? payload["displayText"] : void 0;
|
|
620
|
+
if (displayText) {
|
|
621
|
+
const isNotification = record.subtype === "notification";
|
|
622
|
+
const backgroundTask = payload && isObjectRecord(payload["backgroundTask"]) ? payload["backgroundTask"] : void 0;
|
|
623
|
+
yield emit(
|
|
624
|
+
createTranscriptMessageUpdate({
|
|
625
|
+
role: "user",
|
|
626
|
+
text: displayText,
|
|
627
|
+
...meta,
|
|
628
|
+
...isNotification ? {
|
|
629
|
+
extra: {
|
|
630
|
+
source: "background_notification",
|
|
631
|
+
qwenDiscreteMessage: true,
|
|
632
|
+
...backgroundTask ? { backgroundTask } : {}
|
|
633
|
+
}
|
|
634
|
+
} : record.subtype === "cron" ? { extra: { source: "cron" } } : {}
|
|
635
|
+
})
|
|
636
|
+
);
|
|
637
|
+
return;
|
|
638
|
+
}
|
|
639
|
+
if (record.subtype !== "mid_turn_user_message") return;
|
|
623
640
|
}
|
|
624
|
-
|
|
625
|
-
if (
|
|
626
|
-
|
|
641
|
+
const projection = projectUserTranscriptForDisplay(record);
|
|
642
|
+
if (projection.displayText !== void 0) {
|
|
643
|
+
yield* this.projectMessageParts(
|
|
644
|
+
record,
|
|
645
|
+
"user",
|
|
646
|
+
emit,
|
|
647
|
+
meta,
|
|
648
|
+
void 0,
|
|
649
|
+
replaceTextPartsForDisplay(
|
|
650
|
+
record.message?.parts,
|
|
651
|
+
projection.displayText
|
|
652
|
+
)
|
|
653
|
+
);
|
|
654
|
+
return;
|
|
655
|
+
}
|
|
656
|
+
yield* this.projectMessageParts(
|
|
657
|
+
record,
|
|
658
|
+
"user",
|
|
659
|
+
emit,
|
|
660
|
+
meta,
|
|
661
|
+
void 0,
|
|
662
|
+
projection.parts
|
|
663
|
+
);
|
|
627
664
|
}
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
__name(isRecord, "isRecord");
|
|
647
|
-
function hasOnlyKeys(value, keys) {
|
|
648
|
-
return Object.keys(value).every((key) => keys.includes(key));
|
|
649
|
-
}
|
|
650
|
-
__name(hasOnlyKeys, "hasOnlyKeys");
|
|
651
|
-
function isNonNegativeInteger(value) {
|
|
652
|
-
return typeof value === "number" && Number.isInteger(value) && value >= 0;
|
|
653
|
-
}
|
|
654
|
-
__name(isNonNegativeInteger, "isNonNegativeInteger");
|
|
655
|
-
function isNonNegativeNumber(value) {
|
|
656
|
-
return typeof value === "number" && Number.isFinite(value) && value >= 0;
|
|
657
|
-
}
|
|
658
|
-
__name(isNonNegativeNumber, "isNonNegativeNumber");
|
|
659
|
-
function isFiniteNumber(value) {
|
|
660
|
-
return typeof value === "number" && Number.isFinite(value);
|
|
661
|
-
}
|
|
662
|
-
__name(isFiniteNumber, "isFiniteNumber");
|
|
663
|
-
|
|
664
|
-
// packages/core/dist/src/goals/goal-legacy-projection.js
|
|
665
|
-
init_esbuild_shims();
|
|
666
|
-
function projectGoalStateToLegacy(payload, previousGoal = null) {
|
|
667
|
-
const snapshotGoal = payload.snapshot.goal;
|
|
668
|
-
const displayGoal = snapshotGoal ?? previousGoal;
|
|
669
|
-
const kind = legacyStatusKind(payload);
|
|
670
|
-
const goalStatus = {
|
|
671
|
-
type: "goal_status",
|
|
672
|
-
kind,
|
|
673
|
-
condition: displayGoal?.objective ?? "",
|
|
674
|
-
...displayGoal ? { iterations: displayGoal.turnCount } : {},
|
|
675
|
-
...displayGoal ? { setAt: displayGoal.createdAt } : {},
|
|
676
|
-
...displayGoal ? { durationMs: displayGoal.activeTimeMs } : {},
|
|
677
|
-
...displayGoal?.lastReason === void 0 ? {} : { lastReason: displayGoal.lastReason }
|
|
678
|
-
};
|
|
679
|
-
const terminalKind = kind === "achieved" || kind === "failed" || kind === "aborted" ? kind : void 0;
|
|
680
|
-
return {
|
|
681
|
-
activeGoal: snapshotGoal?.status === "active" ? {
|
|
682
|
-
condition: snapshotGoal.objective,
|
|
683
|
-
iterations: snapshotGoal.turnCount,
|
|
684
|
-
setAt: snapshotGoal.createdAt,
|
|
685
|
-
...snapshotGoal.lastReason === void 0 ? {} : { lastReason: snapshotGoal.lastReason }
|
|
686
|
-
} : null,
|
|
687
|
-
goalStatus,
|
|
688
|
-
goalTerminal: terminalKind && displayGoal ? {
|
|
689
|
-
kind: terminalKind,
|
|
690
|
-
condition: displayGoal.objective,
|
|
691
|
-
iterations: displayGoal.turnCount,
|
|
692
|
-
durationMs: displayGoal.activeTimeMs,
|
|
693
|
-
...displayGoal.lastReason === void 0 ? {} : { lastReason: displayGoal.lastReason }
|
|
694
|
-
} : null
|
|
695
|
-
};
|
|
696
|
-
}
|
|
697
|
-
__name(projectGoalStateToLegacy, "projectGoalStateToLegacy");
|
|
698
|
-
function isGoalCheckpointBookkeepingTransition(previous, next) {
|
|
699
|
-
const previousGoal = previous?.goal;
|
|
700
|
-
const nextGoal = next.goal;
|
|
701
|
-
if (!previousGoal || !nextGoal)
|
|
702
|
-
return false;
|
|
703
|
-
return previousGoal.goalId === nextGoal.goalId && previousGoal.revision === nextGoal.revision && previousGoal.objective === nextGoal.objective && previousGoal.status === nextGoal.status && previousGoal.turnCount === nextGoal.turnCount && previousGoal.createdAt === nextGoal.createdAt && previousGoal.lastReason === nextGoal.lastReason;
|
|
704
|
-
}
|
|
705
|
-
__name(isGoalCheckpointBookkeepingTransition, "isGoalCheckpointBookkeepingTransition");
|
|
706
|
-
function isGoalCheckpointBookkeepingCause(cause, previousCause) {
|
|
707
|
-
if (cause === "checkpoint")
|
|
708
|
-
return true;
|
|
709
|
-
return cause === "verifier_reject" && (previousCause === "verifier_reject" || previousCause === "checkpoint");
|
|
710
|
-
}
|
|
711
|
-
__name(isGoalCheckpointBookkeepingCause, "isGoalCheckpointBookkeepingCause");
|
|
712
|
-
function isGoalCheckpointBookkeepingRecord(input) {
|
|
713
|
-
return isGoalCheckpointBookkeepingTransition(input.previous, input.next) && isGoalCheckpointBookkeepingCause(input.cause, input.previousCause);
|
|
714
|
-
}
|
|
715
|
-
__name(isGoalCheckpointBookkeepingRecord, "isGoalCheckpointBookkeepingRecord");
|
|
716
|
-
function legacyStatusKind(payload) {
|
|
717
|
-
switch (payload.cause) {
|
|
718
|
-
case "create":
|
|
719
|
-
case "replace":
|
|
720
|
-
case "edit":
|
|
721
|
-
case "resume":
|
|
722
|
-
return "set";
|
|
723
|
-
case "complete":
|
|
724
|
-
return "achieved";
|
|
725
|
-
case "clear":
|
|
726
|
-
return "cleared";
|
|
727
|
-
// A migrated goal is always persisted `paused` (`createMigratedGoalState`),
|
|
728
|
-
// and nothing drives a paused goal. Projecting it as `set` would re-assert
|
|
729
|
-
// "active" to every client that derives the live goal from the newest card,
|
|
730
|
-
// leaving a phantom running goal behind a resumed pre-v2 transcript.
|
|
731
|
-
case "migrated":
|
|
732
|
-
case "pause":
|
|
733
|
-
return "paused";
|
|
734
|
-
case "blocked":
|
|
735
|
-
case "usage_limited":
|
|
736
|
-
return "aborted";
|
|
737
|
-
case "turn_finished":
|
|
738
|
-
case "checkpoint":
|
|
739
|
-
case "verifier_accept":
|
|
740
|
-
case "verifier_reject":
|
|
741
|
-
return payload.snapshot.goal?.status === "complete" ? "achieved" : payload.snapshot.goal?.status === "blocked" || payload.snapshot.goal?.status === "usage_limited" ? "aborted" : "checking";
|
|
742
|
-
default:
|
|
743
|
-
return assertNever(payload.cause);
|
|
665
|
+
*projectAssistantRecord(record, emit, meta) {
|
|
666
|
+
const usageMetadata = isObjectRecord(record.usageMetadata) ? record.usageMetadata : void 0;
|
|
667
|
+
let usageEmitted = false;
|
|
668
|
+
const takeUsageUpdate = /* @__PURE__ */ __name(() => {
|
|
669
|
+
if (!usageMetadata || usageEmitted) return void 0;
|
|
670
|
+
usageEmitted = true;
|
|
671
|
+
this.addUsage(usageMetadata);
|
|
672
|
+
return createTranscriptUsageUpdate(usageMetadata, meta);
|
|
673
|
+
}, "takeUsageUpdate");
|
|
674
|
+
yield* this.projectMessageParts(
|
|
675
|
+
record,
|
|
676
|
+
"assistant",
|
|
677
|
+
emit,
|
|
678
|
+
meta,
|
|
679
|
+
takeUsageUpdate
|
|
680
|
+
);
|
|
681
|
+
const trailingUsage = takeUsageUpdate();
|
|
682
|
+
if (trailingUsage) yield emit(trailingUsage);
|
|
744
683
|
}
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
}
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
684
|
+
*projectMessageParts(record, role, emit, meta, beforeToolCall, partsOverride) {
|
|
685
|
+
const parts = partsOverride ?? record.message?.parts;
|
|
686
|
+
if (!parts) return;
|
|
687
|
+
for (let partIndex = 0; partIndex < parts.length; partIndex += 1) {
|
|
688
|
+
const part = parts[partIndex];
|
|
689
|
+
if (!isObjectRecord(part)) {
|
|
690
|
+
this.report(
|
|
691
|
+
"malformed_part",
|
|
692
|
+
"Skipped a malformed transcript message part.",
|
|
693
|
+
record.uuid,
|
|
694
|
+
`message.parts[${partIndex}]`
|
|
695
|
+
);
|
|
696
|
+
continue;
|
|
697
|
+
}
|
|
698
|
+
let recognized = false;
|
|
699
|
+
if (typeof part["text"] === "string" && part["text"].length > 0) {
|
|
700
|
+
recognized = true;
|
|
701
|
+
yield emit(
|
|
702
|
+
createTranscriptMessageUpdate({
|
|
703
|
+
role,
|
|
704
|
+
text: part["text"],
|
|
705
|
+
thought: role === "assistant" && part["thought"] === true,
|
|
706
|
+
...meta
|
|
707
|
+
})
|
|
708
|
+
);
|
|
709
|
+
}
|
|
710
|
+
const inlineData = isObjectRecord(part["inlineData"]) ? part["inlineData"] : void 0;
|
|
711
|
+
if (inlineData) {
|
|
712
|
+
recognized = true;
|
|
713
|
+
const data = inlineData["data"];
|
|
714
|
+
const mimeType = inlineData["mimeType"];
|
|
715
|
+
if (role === "user" && typeof data === "string" && typeof mimeType === "string" && mimeType.startsWith("image/")) {
|
|
716
|
+
yield emit(createTranscriptImageUpdate({ data, mimeType, ...meta }));
|
|
717
|
+
} else {
|
|
718
|
+
this.report(
|
|
719
|
+
"malformed_part",
|
|
720
|
+
"Skipped an unsupported or malformed inline transcript part.",
|
|
721
|
+
record.uuid,
|
|
722
|
+
`message.parts[${partIndex}].inlineData`
|
|
723
|
+
);
|
|
724
|
+
}
|
|
779
725
|
}
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
sessionUpdate: options.role === "user" ? "user_message_chunk" : options.thought ? "agent_thought_chunk" : "agent_message_chunk",
|
|
819
|
-
content: { type: "text", text: options.text },
|
|
820
|
-
...meta ? { _meta: meta } : {}
|
|
821
|
-
};
|
|
822
|
-
}
|
|
823
|
-
__name(createTranscriptMessageUpdate, "createTranscriptMessageUpdate");
|
|
824
|
-
function createTranscriptImageUpdate(options) {
|
|
825
|
-
const meta = buildUpdateMeta(options);
|
|
826
|
-
return {
|
|
827
|
-
sessionUpdate: "user_message_chunk",
|
|
828
|
-
content: { type: "image", data: options.data, mimeType: options.mimeType },
|
|
829
|
-
...meta ? { _meta: meta } : {}
|
|
830
|
-
};
|
|
831
|
-
}
|
|
832
|
-
__name(createTranscriptImageUpdate, "createTranscriptImageUpdate");
|
|
833
|
-
function createTranscriptUsageUpdate(usageMetadata, options = {}) {
|
|
834
|
-
const usage = {
|
|
835
|
-
inputTokens: finiteNumber(usageMetadata.promptTokenCount) ?? 0,
|
|
836
|
-
outputTokens: finiteNumber(usageMetadata.candidatesTokenCount) ?? 0,
|
|
837
|
-
totalTokens: finiteNumber(usageMetadata.totalTokenCount) ?? 0,
|
|
838
|
-
...finiteNumber(usageMetadata.thoughtsTokenCount) !== void 0 ? { thoughtTokens: finiteNumber(usageMetadata.thoughtsTokenCount) } : {},
|
|
839
|
-
...finiteNumber(usageMetadata.cachedContentTokenCount) !== void 0 ? {
|
|
840
|
-
cachedReadTokens: finiteNumber(usageMetadata.cachedContentTokenCount)
|
|
841
|
-
} : {}
|
|
842
|
-
};
|
|
843
|
-
const meta = buildUpdateMeta({
|
|
844
|
-
...options,
|
|
845
|
-
extra: { usage, ...options.extra ?? {} }
|
|
846
|
-
});
|
|
847
|
-
return {
|
|
848
|
-
sessionUpdate: "agent_message_chunk",
|
|
849
|
-
content: { type: "text", text: options.text ?? "" },
|
|
850
|
-
_meta: meta
|
|
851
|
-
};
|
|
852
|
-
}
|
|
853
|
-
__name(createTranscriptUsageUpdate, "createTranscriptUsageUpdate");
|
|
854
|
-
function createTranscriptToolCallStartUpdate(options) {
|
|
855
|
-
const provenance = resolveToolProvenance(options.toolName);
|
|
856
|
-
return {
|
|
857
|
-
sessionUpdate: options.asUpdate ? "tool_call_update" : "tool_call",
|
|
858
|
-
toolCallId: options.callId,
|
|
859
|
-
status: options.status ?? "pending",
|
|
860
|
-
title: options.metadata.title,
|
|
861
|
-
content: [],
|
|
862
|
-
locations: [...options.metadata.locations],
|
|
863
|
-
kind: options.metadata.kind,
|
|
864
|
-
rawInput: options.args ?? {},
|
|
865
|
-
_meta: buildUpdateMeta({
|
|
866
|
-
...options,
|
|
867
|
-
extra: {
|
|
868
|
-
toolName: options.toolName,
|
|
869
|
-
provenance: provenance.provenance,
|
|
870
|
-
...provenance.serverId ? { serverId: provenance.serverId } : {},
|
|
871
|
-
...options.extra ?? {}
|
|
726
|
+
const functionCall = isObjectRecord(part["functionCall"]) ? part["functionCall"] : void 0;
|
|
727
|
+
if (functionCall) {
|
|
728
|
+
recognized = true;
|
|
729
|
+
const toolName = typeof functionCall["name"] === "string" ? functionCall["name"] : "";
|
|
730
|
+
const args = isObjectRecord(functionCall["args"]) ? functionCall["args"] : {};
|
|
731
|
+
if (!toolName) {
|
|
732
|
+
this.report(
|
|
733
|
+
"malformed_part",
|
|
734
|
+
"Skipped a tool call without a tool name.",
|
|
735
|
+
record.uuid,
|
|
736
|
+
`message.parts[${partIndex}].functionCall`
|
|
737
|
+
);
|
|
738
|
+
continue;
|
|
739
|
+
}
|
|
740
|
+
const preToolUpdate = beforeToolCall?.();
|
|
741
|
+
if (preToolUpdate) yield emit(preToolUpdate);
|
|
742
|
+
if (toolName === "todo_write") continue;
|
|
743
|
+
const explicitId = typeof functionCall["id"] === "string" && functionCall["id"].length > 0 ? functionCall["id"] : void 0;
|
|
744
|
+
const callId = this.allocateToolCallId(
|
|
745
|
+
explicitId ?? `qwen-replay-tool:${record.uuid}:${partIndex}`
|
|
746
|
+
);
|
|
747
|
+
const update = createTranscriptToolCallStartUpdate({
|
|
748
|
+
toolName,
|
|
749
|
+
callId,
|
|
750
|
+
args,
|
|
751
|
+
status: "in_progress",
|
|
752
|
+
metadata: this.resolveToolMetadata(toolName, args, record.uuid),
|
|
753
|
+
...meta
|
|
754
|
+
});
|
|
755
|
+
yield emit(update);
|
|
756
|
+
if (role === "assistant") {
|
|
757
|
+
this.pendingToolCalls.set(callId, {
|
|
758
|
+
callId,
|
|
759
|
+
toolName,
|
|
760
|
+
sourceRecordId: record.uuid,
|
|
761
|
+
...record.timestamp ? { sourceTimestamp: record.timestamp } : {}
|
|
762
|
+
});
|
|
763
|
+
}
|
|
872
764
|
}
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
const update = {
|
|
881
|
-
sessionUpdate: "tool_call_update",
|
|
882
|
-
toolCallId: options.callId,
|
|
883
|
-
status: options.success ? "completed" : "failed",
|
|
884
|
-
content,
|
|
885
|
-
_meta: buildUpdateMeta({
|
|
886
|
-
...options,
|
|
887
|
-
extra: {
|
|
888
|
-
toolName: options.toolName,
|
|
889
|
-
provenance: provenance.provenance,
|
|
890
|
-
...provenance.serverId ? { serverId: provenance.serverId } : {},
|
|
891
|
-
...options.artifacts && options.artifacts.length > 0 ? { artifacts: options.artifacts } : {},
|
|
892
|
-
...options.extra ?? {}
|
|
765
|
+
if (!recognized && !("functionResponse" in part)) {
|
|
766
|
+
this.report(
|
|
767
|
+
"unknown_record_or_part",
|
|
768
|
+
"Skipped an unknown transcript message part.",
|
|
769
|
+
record.uuid,
|
|
770
|
+
`message.parts[${partIndex}]`
|
|
771
|
+
);
|
|
893
772
|
}
|
|
894
|
-
}
|
|
895
|
-
};
|
|
896
|
-
if (options.resultDisplay !== void 0 && !isTruncatedSessionDiffDisplay(options.resultDisplay)) {
|
|
897
|
-
update["rawOutput"] = options.resultDisplay;
|
|
773
|
+
}
|
|
898
774
|
}
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
775
|
+
*projectToolResult(record, emit, meta) {
|
|
776
|
+
const result = isObjectRecord(record.toolCallResult) ? record.toolCallResult : void 0;
|
|
777
|
+
const toolName = extractToolName(record);
|
|
778
|
+
if (!toolName) {
|
|
779
|
+
this.report(
|
|
780
|
+
"malformed_part",
|
|
781
|
+
"A transcript tool result has no tool name.",
|
|
782
|
+
record.uuid,
|
|
783
|
+
"message.parts"
|
|
784
|
+
);
|
|
909
785
|
}
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
}
|
|
923
|
-
|
|
924
|
-
}
|
|
925
|
-
|
|
926
|
-
...meta ? { _meta: meta } : {}
|
|
927
|
-
};
|
|
928
|
-
}
|
|
929
|
-
__name(createTranscriptPlanUpdate, "createTranscriptPlanUpdate");
|
|
930
|
-
function extractTranscriptTodoPlan(resultDisplay, args) {
|
|
931
|
-
const fromDisplay = extractTodoPlanFromDisplay(resultDisplay);
|
|
932
|
-
if (fromDisplay) return fromDisplay;
|
|
933
|
-
if (resultDisplay !== null && resultDisplay !== void 0) return null;
|
|
934
|
-
return args && Array.isArray(args["todos"]) ? { todos: normalizeTodos(args["todos"]) } : null;
|
|
935
|
-
}
|
|
936
|
-
__name(extractTranscriptTodoPlan, "extractTranscriptTodoPlan");
|
|
937
|
-
function createTranscriptReplayMachine(options = {}) {
|
|
938
|
-
return new DefaultTranscriptReplayMachine(options);
|
|
939
|
-
}
|
|
940
|
-
__name(createTranscriptReplayMachine, "createTranscriptReplayMachine");
|
|
941
|
-
var DefaultTranscriptReplayMachine = class {
|
|
942
|
-
constructor(options) {
|
|
943
|
-
this.options = options;
|
|
944
|
-
const initialState = parseInitialState(
|
|
945
|
-
options.initialState,
|
|
946
|
-
options.onDiagnostic
|
|
947
|
-
);
|
|
948
|
-
this.usage = { ...initialState.cumulativeUsage };
|
|
949
|
-
this.goalState = initialState.goalState;
|
|
950
|
-
this.goalCause = initialState.goalCause;
|
|
951
|
-
for (const pending of initialState.pendingToolCalls) {
|
|
952
|
-
this.pendingToolCalls.set(pending.callId, pending);
|
|
953
|
-
this.usedToolCallIds.add(pending.callId);
|
|
786
|
+
const explicitCallId = extractToolResultCallId(record, result);
|
|
787
|
+
const callId = explicitCallId ? this.allocateToolCallId(explicitCallId, true) : this.correlateResultCallId(toolName, record.uuid);
|
|
788
|
+
this.pendingToolCalls.delete(callId);
|
|
789
|
+
const resultDisplay = result?.["resultDisplay"];
|
|
790
|
+
if (toolName === "todo_write") {
|
|
791
|
+
const plan = extractTranscriptTodoPlan(resultDisplay);
|
|
792
|
+
if (plan) {
|
|
793
|
+
yield emit(
|
|
794
|
+
createTranscriptPlanUpdate(plan.todos, this.usage, {
|
|
795
|
+
...meta,
|
|
796
|
+
planToolCallId: callId,
|
|
797
|
+
todoPlanId: plan.planId
|
|
798
|
+
})
|
|
799
|
+
);
|
|
800
|
+
}
|
|
801
|
+
return;
|
|
954
802
|
}
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
803
|
+
yield emit(
|
|
804
|
+
createTranscriptToolCallResultUpdate({
|
|
805
|
+
toolName,
|
|
806
|
+
callId,
|
|
807
|
+
success: result?.["status"] === void 0 ? !result?.["error"] : result["status"] === "success" && !result["error"],
|
|
808
|
+
errorMessage: extractErrorMessage(result?.["error"]),
|
|
809
|
+
message: record.message?.parts,
|
|
810
|
+
resultDisplay,
|
|
811
|
+
artifacts: Array.isArray(result?.["artifacts"]) ? result["artifacts"] : void 0,
|
|
812
|
+
contentPrefix: this.buildToolResultContentPrefix(
|
|
813
|
+
resultDisplay,
|
|
814
|
+
record.uuid
|
|
815
|
+
),
|
|
816
|
+
...meta
|
|
817
|
+
})
|
|
818
|
+
);
|
|
819
|
+
if (isTaskExecutionDisplay(resultDisplay)) {
|
|
820
|
+
const usage = usageFromTaskExecution(resultDisplay);
|
|
821
|
+
if (Object.keys(usage).length > 0) {
|
|
822
|
+
this.addUsage(usage);
|
|
823
|
+
yield emit(createTranscriptUsageUpdate(usage, meta));
|
|
958
824
|
}
|
|
959
825
|
}
|
|
960
826
|
}
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
827
|
+
*projectSystemRecord(record, emit, meta) {
|
|
828
|
+
if (record.subtype === "goal_state") {
|
|
829
|
+
const payload2 = parseGoalStateRecordPayloadV2(record.systemPayload);
|
|
830
|
+
if (!payload2) {
|
|
831
|
+
this.report(
|
|
832
|
+
"malformed_goal_state",
|
|
833
|
+
"Skipped a malformed Goal state transcript record.",
|
|
834
|
+
record.uuid,
|
|
835
|
+
"systemPayload"
|
|
836
|
+
);
|
|
837
|
+
return;
|
|
838
|
+
}
|
|
839
|
+
const bookkeepingOnly = isGoalCheckpointBookkeepingRecord({
|
|
840
|
+
cause: payload2.cause,
|
|
841
|
+
previousCause: this.goalCause,
|
|
842
|
+
previous: this.goalState,
|
|
843
|
+
next: payload2.snapshot
|
|
844
|
+
});
|
|
845
|
+
const projection = projectGoalStateToLegacy2(
|
|
846
|
+
payload2,
|
|
847
|
+
this.goalState?.goal ?? null
|
|
848
|
+
);
|
|
849
|
+
this.goalState = payload2.snapshot;
|
|
850
|
+
this.goalCause = payload2.cause;
|
|
851
|
+
if (bookkeepingOnly) return;
|
|
852
|
+
const { type: _type, ...goalStatus } = projection.goalStatus;
|
|
853
|
+
yield emit(
|
|
854
|
+
createTranscriptMessageUpdate({
|
|
855
|
+
role: "assistant",
|
|
856
|
+
text: "",
|
|
857
|
+
...meta,
|
|
858
|
+
extra: {
|
|
859
|
+
goalState: payload2.snapshot,
|
|
860
|
+
goalStatus,
|
|
861
|
+
...projection.goalTerminal ? { goalTerminal: projection.goalTerminal } : {},
|
|
862
|
+
"qwen.session.recordId": record.uuid
|
|
863
|
+
}
|
|
864
|
+
})
|
|
975
865
|
);
|
|
866
|
+
return;
|
|
976
867
|
}
|
|
977
|
-
|
|
978
|
-
const
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
868
|
+
if (record.subtype !== "slash_command") return;
|
|
869
|
+
const payload = isObjectRecord(record.systemPayload) ? record.systemPayload : void 0;
|
|
870
|
+
if (payload?.["phase"] !== "result") return;
|
|
871
|
+
const items = Array.isArray(payload["outputHistoryItems"]) ? payload["outputHistoryItems"] : [];
|
|
872
|
+
for (const item of items) {
|
|
873
|
+
const goalStatus = parseTranscriptGoalStatus(item);
|
|
874
|
+
if (goalStatus) {
|
|
875
|
+
if (goalStatus.condition.length === 0) {
|
|
876
|
+
this.report(
|
|
877
|
+
"malformed_part",
|
|
878
|
+
"Skipped replay of a goal card whose condition is empty.",
|
|
879
|
+
record.uuid,
|
|
880
|
+
"systemPayload.outputHistoryItems.goalStatus.condition"
|
|
881
|
+
);
|
|
882
|
+
} else if (goalStatus.kind !== "checking") {
|
|
883
|
+
yield emit(
|
|
884
|
+
createTranscriptMessageUpdate({
|
|
885
|
+
role: "assistant",
|
|
886
|
+
text: "",
|
|
887
|
+
...meta,
|
|
888
|
+
extra: { goalStatus }
|
|
889
|
+
})
|
|
890
|
+
);
|
|
991
891
|
}
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
if (gap) {
|
|
892
|
+
continue;
|
|
893
|
+
}
|
|
894
|
+
if (!isObjectRecord(item) || typeof item["text"] !== "string") continue;
|
|
996
895
|
yield emit(
|
|
997
896
|
createTranscriptMessageUpdate({
|
|
998
897
|
role: "assistant",
|
|
999
|
-
text:
|
|
898
|
+
text: item["text"].replace(/\n/g, " \n"),
|
|
1000
899
|
...meta,
|
|
1001
|
-
extra: {
|
|
900
|
+
extra: { source: "slash_command" }
|
|
1002
901
|
})
|
|
1003
902
|
);
|
|
1004
903
|
}
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
904
|
+
}
|
|
905
|
+
addUsage(metadata) {
|
|
906
|
+
this.usage.promptTokens += finiteNumber(metadata["promptTokenCount"]) ?? 0;
|
|
907
|
+
this.usage.candidateTokens += finiteNumber(metadata["candidatesTokenCount"]) ?? 0;
|
|
908
|
+
this.usage.cachedTokens += finiteNumber(metadata["cachedContentTokenCount"]) ?? 0;
|
|
909
|
+
}
|
|
910
|
+
correlateResultCallId(toolName, recordId) {
|
|
911
|
+
const candidates = [...this.pendingToolCalls.values()].filter(
|
|
912
|
+
(pending) => pending.toolName === toolName
|
|
913
|
+
);
|
|
914
|
+
if (candidates.length === 1) return candidates[0].callId;
|
|
915
|
+
this.report(
|
|
916
|
+
"ambiguous_tool_call_correlation",
|
|
917
|
+
"A tool result could not be matched to exactly one pending tool call.",
|
|
918
|
+
recordId
|
|
919
|
+
);
|
|
920
|
+
return this.allocateToolCallId(`qwen-replay-tool:${recordId}:result`);
|
|
921
|
+
}
|
|
922
|
+
allocateToolCallId(candidate, reuse = false) {
|
|
923
|
+
if (reuse && this.pendingToolCalls.has(candidate)) {
|
|
924
|
+
this.usedToolCallIds.add(candidate);
|
|
925
|
+
return candidate;
|
|
926
|
+
}
|
|
927
|
+
if (!this.usedToolCallIds.has(candidate)) {
|
|
928
|
+
this.usedToolCallIds.add(candidate);
|
|
929
|
+
return candidate;
|
|
930
|
+
}
|
|
931
|
+
let occurrence = 2;
|
|
932
|
+
while (this.usedToolCallIds.has(`${candidate}:${occurrence}`)) {
|
|
933
|
+
occurrence += 1;
|
|
1024
934
|
}
|
|
935
|
+
const id = `${candidate}:${occurrence}`;
|
|
936
|
+
this.usedToolCallIds.add(id);
|
|
937
|
+
return id;
|
|
1025
938
|
}
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
for (const pending of [...this.pendingToolCalls.values()]) {
|
|
1031
|
-
this.pendingToolCalls.delete(pending.callId);
|
|
939
|
+
resolveToolMetadata(toolName, args, recordId) {
|
|
940
|
+
try {
|
|
941
|
+
return this.options.presentation?.resolveToolMetadata(toolName, args) ?? fallbackToolMetadata(toolName, args);
|
|
942
|
+
} catch {
|
|
1032
943
|
this.report(
|
|
1033
|
-
"
|
|
1034
|
-
"
|
|
1035
|
-
|
|
944
|
+
"presentation_fallback",
|
|
945
|
+
"Tool presentation metadata fell back to deterministic defaults.",
|
|
946
|
+
recordId,
|
|
947
|
+
void 0,
|
|
948
|
+
false
|
|
1036
949
|
);
|
|
1037
|
-
|
|
1038
|
-
sourceRecordId: pending.sourceRecordId,
|
|
1039
|
-
...pending.sourceTimestamp ? { sourceTimestamp: pending.sourceTimestamp } : {},
|
|
1040
|
-
emissionOrdinal: ordinal++,
|
|
1041
|
-
update: createTranscriptToolCallResultUpdate({
|
|
1042
|
-
toolName: pending.toolName,
|
|
1043
|
-
callId: pending.callId,
|
|
1044
|
-
success: false,
|
|
1045
|
-
errorMessage: MISSING_TRANSCRIPT_TOOL_RESULT_MESSAGE,
|
|
1046
|
-
timestamp: pending.sourceTimestamp,
|
|
1047
|
-
sourceRecordIds: [pending.sourceRecordId]
|
|
1048
|
-
})
|
|
1049
|
-
};
|
|
950
|
+
return fallbackToolMetadata(toolName, args);
|
|
1050
951
|
}
|
|
1051
952
|
}
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
const payload = isObjectRecord(record.systemPayload) ? record.systemPayload : void 0;
|
|
1065
|
-
if (record.subtype === "goal_runtime" || record.subtype === "notification" || record.subtype === "cron" || record.subtype === "mid_turn_user_message") {
|
|
1066
|
-
const displayText = payload && typeof payload["displayText"] === "string" ? payload["displayText"] : void 0;
|
|
1067
|
-
if (displayText) {
|
|
1068
|
-
const isNotification = record.subtype === "notification";
|
|
1069
|
-
const backgroundTask = payload && isObjectRecord(payload["backgroundTask"]) ? payload["backgroundTask"] : void 0;
|
|
1070
|
-
yield emit(
|
|
1071
|
-
createTranscriptMessageUpdate({
|
|
1072
|
-
role: "user",
|
|
1073
|
-
text: displayText,
|
|
1074
|
-
...meta,
|
|
1075
|
-
...isNotification ? {
|
|
1076
|
-
extra: {
|
|
1077
|
-
source: "background_notification",
|
|
1078
|
-
qwenDiscreteMessage: true,
|
|
1079
|
-
...backgroundTask ? { backgroundTask } : {}
|
|
1080
|
-
}
|
|
1081
|
-
} : record.subtype === "cron" ? { extra: { source: "cron" } } : {}
|
|
1082
|
-
})
|
|
1083
|
-
);
|
|
1084
|
-
return;
|
|
1085
|
-
}
|
|
1086
|
-
if (record.subtype !== "mid_turn_user_message") return;
|
|
953
|
+
formatGap(gap) {
|
|
954
|
+
try {
|
|
955
|
+
return this.options.presentation?.formatHistoryGap(gap) ?? "Some earlier messages are unavailable because the saved history is incomplete.";
|
|
956
|
+
} catch {
|
|
957
|
+
this.report(
|
|
958
|
+
"presentation_fallback",
|
|
959
|
+
"History gap presentation fell back to deterministic defaults.",
|
|
960
|
+
gap.childUuid,
|
|
961
|
+
void 0,
|
|
962
|
+
false
|
|
963
|
+
);
|
|
964
|
+
return "Some earlier messages are unavailable because the saved history is incomplete.";
|
|
1087
965
|
}
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
966
|
+
}
|
|
967
|
+
buildToolResultContentPrefix(resultDisplay, recordId) {
|
|
968
|
+
try {
|
|
969
|
+
return this.options.presentation?.buildToolResultContentPrefix?.(
|
|
970
|
+
resultDisplay
|
|
971
|
+
) ?? defaultToolResultContentPrefix(resultDisplay);
|
|
972
|
+
} catch {
|
|
973
|
+
this.report(
|
|
974
|
+
"presentation_fallback",
|
|
975
|
+
"Tool result content presentation fell back to deterministic defaults.",
|
|
976
|
+
recordId,
|
|
1095
977
|
void 0,
|
|
1096
|
-
|
|
1097
|
-
record.message?.parts,
|
|
1098
|
-
projection.displayText
|
|
1099
|
-
)
|
|
978
|
+
false
|
|
1100
979
|
);
|
|
1101
|
-
return;
|
|
980
|
+
return defaultToolResultContentPrefix(resultDisplay);
|
|
1102
981
|
}
|
|
1103
|
-
yield* this.projectMessageParts(
|
|
1104
|
-
record,
|
|
1105
|
-
"user",
|
|
1106
|
-
emit,
|
|
1107
|
-
meta,
|
|
1108
|
-
void 0,
|
|
1109
|
-
projection.parts
|
|
1110
|
-
);
|
|
1111
982
|
}
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
}
|
|
1121
|
-
yield* this.projectMessageParts(
|
|
1122
|
-
record,
|
|
1123
|
-
"assistant",
|
|
1124
|
-
emit,
|
|
1125
|
-
meta,
|
|
1126
|
-
takeUsageUpdate
|
|
1127
|
-
);
|
|
1128
|
-
const trailingUsage = takeUsageUpdate();
|
|
1129
|
-
if (trailingUsage) yield emit(trailingUsage);
|
|
983
|
+
report(code, message, recordId, path2, affectsCompleteness = true) {
|
|
984
|
+
this.options.onDiagnostic?.({
|
|
985
|
+
code,
|
|
986
|
+
severity: affectsCompleteness ? "warning" : "info",
|
|
987
|
+
message,
|
|
988
|
+
affectsCompleteness,
|
|
989
|
+
...recordId ? { recordId } : {},
|
|
990
|
+
...path2 ? { path: path2 } : {}
|
|
991
|
+
});
|
|
1130
992
|
}
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
"malformed_part",
|
|
1167
|
-
"Skipped an unsupported or malformed inline transcript part.",
|
|
1168
|
-
record.uuid,
|
|
1169
|
-
`message.parts[${partIndex}].inlineData`
|
|
1170
|
-
);
|
|
1171
|
-
}
|
|
993
|
+
};
|
|
994
|
+
function parseTranscriptGoalStatus(value) {
|
|
995
|
+
if (!isObjectRecord(value) || value["type"] !== "goal_status") {
|
|
996
|
+
return void 0;
|
|
997
|
+
}
|
|
998
|
+
const kind = value["kind"];
|
|
999
|
+
const condition = value["condition"];
|
|
1000
|
+
if (typeof kind !== "string" || !TRANSCRIPT_GOAL_STATUS_KINDS.has(kind) || typeof condition !== "string") {
|
|
1001
|
+
return void 0;
|
|
1002
|
+
}
|
|
1003
|
+
const iterations = finiteNumber(value["iterations"]);
|
|
1004
|
+
const setAt = finiteNumber(value["setAt"]);
|
|
1005
|
+
const durationMs = finiteNumber(value["durationMs"]);
|
|
1006
|
+
const lastReason = typeof value["lastReason"] === "string" ? value["lastReason"] : void 0;
|
|
1007
|
+
return {
|
|
1008
|
+
kind,
|
|
1009
|
+
condition,
|
|
1010
|
+
...iterations !== void 0 ? { iterations } : {},
|
|
1011
|
+
...setAt !== void 0 ? { setAt } : {},
|
|
1012
|
+
...durationMs !== void 0 ? { durationMs } : {},
|
|
1013
|
+
...lastReason !== void 0 ? { lastReason } : {}
|
|
1014
|
+
};
|
|
1015
|
+
}
|
|
1016
|
+
__name(parseTranscriptGoalStatus, "parseTranscriptGoalStatus");
|
|
1017
|
+
function defaultToolResultContentPrefix(resultDisplay) {
|
|
1018
|
+
if (!isObjectRecord(resultDisplay) || resultDisplay["type"] !== "vision_bridge_notice" || typeof resultDisplay["summary"] !== "string" || typeof resultDisplay["notice"] !== "string") {
|
|
1019
|
+
return [];
|
|
1020
|
+
}
|
|
1021
|
+
return [
|
|
1022
|
+
{
|
|
1023
|
+
type: "content",
|
|
1024
|
+
content: {
|
|
1025
|
+
type: "text",
|
|
1026
|
+
text: `${resultDisplay["summary"]}
|
|
1027
|
+
${resultDisplay["notice"]}`
|
|
1172
1028
|
}
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
|
|
1184
|
-
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
metadata: this.resolveToolMetadata(toolName, args, record.uuid),
|
|
1200
|
-
...meta
|
|
1029
|
+
}
|
|
1030
|
+
];
|
|
1031
|
+
}
|
|
1032
|
+
__name(defaultToolResultContentPrefix, "defaultToolResultContentPrefix");
|
|
1033
|
+
function parseInitialState(value, onDiagnostic) {
|
|
1034
|
+
const empty = {
|
|
1035
|
+
v: 1,
|
|
1036
|
+
pendingToolCalls: [],
|
|
1037
|
+
cumulativeUsage: emptyUsage()
|
|
1038
|
+
};
|
|
1039
|
+
if (value === void 0) return empty;
|
|
1040
|
+
if (!isObjectRecord(value)) {
|
|
1041
|
+
throw new TypeError("Invalid transcript replay state.");
|
|
1042
|
+
}
|
|
1043
|
+
if ("v" in value && value["v"] !== 1) {
|
|
1044
|
+
throw new TypeError("Unsupported transcript replay state version.");
|
|
1045
|
+
}
|
|
1046
|
+
const rawPending = Array.isArray(value["pendingToolCalls"]) ? value["pendingToolCalls"] : [];
|
|
1047
|
+
const pendingToolCalls = rawPending.flatMap(
|
|
1048
|
+
(pending) => {
|
|
1049
|
+
if (!isObjectRecord(pending) || typeof pending["callId"] !== "string" || typeof pending["toolName"] !== "string" || typeof pending["sourceRecordId"] !== "string") {
|
|
1050
|
+
onDiagnostic?.({
|
|
1051
|
+
code: "invalid_replay_state",
|
|
1052
|
+
severity: "warning",
|
|
1053
|
+
message: "Dropped a malformed pending tool call from replay state.",
|
|
1054
|
+
affectsCompleteness: true
|
|
1201
1055
|
});
|
|
1202
|
-
|
|
1203
|
-
if (role === "assistant") {
|
|
1204
|
-
this.pendingToolCalls.set(callId, {
|
|
1205
|
-
callId,
|
|
1206
|
-
toolName,
|
|
1207
|
-
sourceRecordId: record.uuid,
|
|
1208
|
-
...record.timestamp ? { sourceTimestamp: record.timestamp } : {}
|
|
1209
|
-
});
|
|
1210
|
-
}
|
|
1211
|
-
}
|
|
1212
|
-
if (!recognized && !("functionResponse" in part)) {
|
|
1213
|
-
this.report(
|
|
1214
|
-
"unknown_record_or_part",
|
|
1215
|
-
"Skipped an unknown transcript message part.",
|
|
1216
|
-
record.uuid,
|
|
1217
|
-
`message.parts[${partIndex}]`
|
|
1218
|
-
);
|
|
1056
|
+
return [];
|
|
1219
1057
|
}
|
|
1058
|
+
return [
|
|
1059
|
+
{
|
|
1060
|
+
callId: pending["callId"],
|
|
1061
|
+
toolName: pending["toolName"],
|
|
1062
|
+
sourceRecordId: pending["sourceRecordId"],
|
|
1063
|
+
...typeof pending["sourceTimestamp"] === "string" ? { sourceTimestamp: pending["sourceTimestamp"] } : {}
|
|
1064
|
+
}
|
|
1065
|
+
];
|
|
1066
|
+
}
|
|
1067
|
+
);
|
|
1068
|
+
const rawUsage = value.cumulativeUsage;
|
|
1069
|
+
const usage = isObjectRecord(rawUsage) ? rawUsage : {};
|
|
1070
|
+
const validUsage = finiteNumber(usage["promptTokens"]) !== void 0 && finiteNumber(usage["cachedTokens"]) !== void 0 && finiteNumber(usage["candidateTokens"]) !== void 0 && finiteNumber(usage["apiTimeMs"]) !== void 0;
|
|
1071
|
+
if (!validUsage) {
|
|
1072
|
+
onDiagnostic?.({
|
|
1073
|
+
code: "invalid_replay_state",
|
|
1074
|
+
severity: "warning",
|
|
1075
|
+
message: "Reset invalid cumulative usage in transcript replay state.",
|
|
1076
|
+
affectsCompleteness: true
|
|
1077
|
+
});
|
|
1078
|
+
}
|
|
1079
|
+
const rawGoalState = value["goalState"];
|
|
1080
|
+
const goalState = rawGoalState === void 0 ? void 0 : parseGoalSnapshotV22(rawGoalState);
|
|
1081
|
+
if (rawGoalState !== void 0 && !goalState) {
|
|
1082
|
+
onDiagnostic?.({
|
|
1083
|
+
code: "invalid_replay_state",
|
|
1084
|
+
severity: "warning",
|
|
1085
|
+
message: "Dropped a malformed Goal state from replay state.",
|
|
1086
|
+
affectsCompleteness: true
|
|
1087
|
+
});
|
|
1088
|
+
}
|
|
1089
|
+
const rawGoalCause = value["goalCause"];
|
|
1090
|
+
const goalCause = rawGoalCause === void 0 ? void 0 : parseGoalStateCause2(rawGoalCause);
|
|
1091
|
+
if (rawGoalCause !== void 0 && !goalCause) {
|
|
1092
|
+
onDiagnostic?.({
|
|
1093
|
+
code: "invalid_replay_state",
|
|
1094
|
+
severity: "warning",
|
|
1095
|
+
message: "Dropped a malformed Goal cause from replay state.",
|
|
1096
|
+
affectsCompleteness: true
|
|
1097
|
+
});
|
|
1098
|
+
}
|
|
1099
|
+
return {
|
|
1100
|
+
v: 1,
|
|
1101
|
+
pendingToolCalls,
|
|
1102
|
+
cumulativeUsage: validUsage ? {
|
|
1103
|
+
promptTokens: usage["promptTokens"],
|
|
1104
|
+
cachedTokens: usage["cachedTokens"],
|
|
1105
|
+
candidateTokens: usage["candidateTokens"],
|
|
1106
|
+
apiTimeMs: usage["apiTimeMs"]
|
|
1107
|
+
} : emptyUsage(),
|
|
1108
|
+
...goalState ? { goalState } : {},
|
|
1109
|
+
...goalCause ? { goalCause } : {}
|
|
1110
|
+
};
|
|
1111
|
+
}
|
|
1112
|
+
__name(parseInitialState, "parseInitialState");
|
|
1113
|
+
function emptyUsage() {
|
|
1114
|
+
return {
|
|
1115
|
+
promptTokens: 0,
|
|
1116
|
+
cachedTokens: 0,
|
|
1117
|
+
candidateTokens: 0,
|
|
1118
|
+
apiTimeMs: 0
|
|
1119
|
+
};
|
|
1120
|
+
}
|
|
1121
|
+
__name(emptyUsage, "emptyUsage");
|
|
1122
|
+
function fallbackToolMetadata(toolName, args) {
|
|
1123
|
+
const description = typeof args["description"] === "string" ? args["description"].trim() : "";
|
|
1124
|
+
return {
|
|
1125
|
+
title: description ? `${toolName}: ${description}` : toolName,
|
|
1126
|
+
locations: [],
|
|
1127
|
+
kind: "other"
|
|
1128
|
+
};
|
|
1129
|
+
}
|
|
1130
|
+
__name(fallbackToolMetadata, "fallbackToolMetadata");
|
|
1131
|
+
function resolveToolProvenance(toolName) {
|
|
1132
|
+
if (toolName.startsWith("mcp__")) {
|
|
1133
|
+
const parts = toolName.split("__");
|
|
1134
|
+
if (parts.length >= 3 && parts[1]) {
|
|
1135
|
+
return { provenance: "mcp", serverId: parts[1] };
|
|
1220
1136
|
}
|
|
1221
1137
|
}
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
this.pendingToolCalls.delete(callId);
|
|
1236
|
-
const resultDisplay = result?.["resultDisplay"];
|
|
1237
|
-
if (toolName === "todo_write") {
|
|
1238
|
-
const plan = extractTranscriptTodoPlan(resultDisplay);
|
|
1239
|
-
if (plan) {
|
|
1240
|
-
yield emit(
|
|
1241
|
-
createTranscriptPlanUpdate(plan.todos, this.usage, {
|
|
1242
|
-
...meta,
|
|
1243
|
-
planToolCallId: callId,
|
|
1244
|
-
todoPlanId: plan.planId
|
|
1245
|
-
})
|
|
1246
|
-
);
|
|
1247
|
-
}
|
|
1248
|
-
return;
|
|
1249
|
-
}
|
|
1250
|
-
yield emit(
|
|
1251
|
-
createTranscriptToolCallResultUpdate({
|
|
1252
|
-
toolName,
|
|
1253
|
-
callId,
|
|
1254
|
-
success: result?.["status"] === void 0 ? !result?.["error"] : result["status"] === "success" && !result["error"],
|
|
1255
|
-
errorMessage: extractErrorMessage(result?.["error"]),
|
|
1256
|
-
message: record.message?.parts,
|
|
1257
|
-
resultDisplay,
|
|
1258
|
-
artifacts: Array.isArray(result?.["artifacts"]) ? result["artifacts"] : void 0,
|
|
1259
|
-
contentPrefix: this.buildToolResultContentPrefix(
|
|
1260
|
-
resultDisplay,
|
|
1261
|
-
record.uuid
|
|
1262
|
-
),
|
|
1263
|
-
...meta
|
|
1264
|
-
})
|
|
1265
|
-
);
|
|
1266
|
-
if (isTaskExecutionDisplay(resultDisplay)) {
|
|
1267
|
-
const usage = usageFromTaskExecution(resultDisplay);
|
|
1268
|
-
if (Object.keys(usage).length > 0) {
|
|
1269
|
-
this.addUsage(usage);
|
|
1270
|
-
yield emit(createTranscriptUsageUpdate(usage, meta));
|
|
1138
|
+
return { provenance: "builtin" };
|
|
1139
|
+
}
|
|
1140
|
+
__name(resolveToolProvenance, "resolveToolProvenance");
|
|
1141
|
+
function buildToolResultContent(options) {
|
|
1142
|
+
const prefix = [...options.contentPrefix ?? []];
|
|
1143
|
+
const diff = extractDiffContent(options.resultDisplay);
|
|
1144
|
+
if (diff) return [...prefix, diff];
|
|
1145
|
+
if (options.errorMessage) {
|
|
1146
|
+
return [
|
|
1147
|
+
...prefix,
|
|
1148
|
+
{
|
|
1149
|
+
type: "content",
|
|
1150
|
+
content: { type: "text", text: options.errorMessage }
|
|
1271
1151
|
}
|
|
1272
|
-
|
|
1152
|
+
];
|
|
1273
1153
|
}
|
|
1274
|
-
|
|
1275
|
-
|
|
1276
|
-
|
|
1277
|
-
|
|
1278
|
-
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
record.uuid,
|
|
1282
|
-
"systemPayload"
|
|
1283
|
-
);
|
|
1284
|
-
return;
|
|
1285
|
-
}
|
|
1286
|
-
const bookkeepingOnly = isGoalCheckpointBookkeepingRecord({
|
|
1287
|
-
cause: payload2.cause,
|
|
1288
|
-
previousCause: this.goalCause,
|
|
1289
|
-
previous: this.goalState,
|
|
1290
|
-
next: payload2.snapshot
|
|
1154
|
+
const content = [...prefix];
|
|
1155
|
+
for (const part of options.message ?? []) {
|
|
1156
|
+
if (!isObjectRecord(part)) continue;
|
|
1157
|
+
if (typeof part["text"] === "string" && part["text"]) {
|
|
1158
|
+
content.push({
|
|
1159
|
+
type: "content",
|
|
1160
|
+
content: { type: "text", text: part["text"] }
|
|
1291
1161
|
});
|
|
1292
|
-
const projection = projectGoalStateToLegacy(
|
|
1293
|
-
payload2,
|
|
1294
|
-
this.goalState?.goal ?? null
|
|
1295
|
-
);
|
|
1296
|
-
this.goalState = payload2.snapshot;
|
|
1297
|
-
this.goalCause = payload2.cause;
|
|
1298
|
-
if (bookkeepingOnly) return;
|
|
1299
|
-
const { type: _type, ...goalStatus } = projection.goalStatus;
|
|
1300
|
-
yield emit(
|
|
1301
|
-
createTranscriptMessageUpdate({
|
|
1302
|
-
role: "assistant",
|
|
1303
|
-
text: "",
|
|
1304
|
-
...meta,
|
|
1305
|
-
extra: {
|
|
1306
|
-
goalState: payload2.snapshot,
|
|
1307
|
-
goalStatus,
|
|
1308
|
-
...projection.goalTerminal ? { goalTerminal: projection.goalTerminal } : {},
|
|
1309
|
-
"qwen.session.recordId": record.uuid
|
|
1310
|
-
}
|
|
1311
|
-
})
|
|
1312
|
-
);
|
|
1313
|
-
return;
|
|
1314
1162
|
}
|
|
1315
|
-
|
|
1316
|
-
const payload = isObjectRecord(
|
|
1317
|
-
if (payload
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
const
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
|
-
|
|
1327
|
-
"systemPayload.outputHistoryItems.goalStatus.condition"
|
|
1328
|
-
);
|
|
1329
|
-
} else if (goalStatus.kind !== "checking") {
|
|
1330
|
-
yield emit(
|
|
1331
|
-
createTranscriptMessageUpdate({
|
|
1332
|
-
role: "assistant",
|
|
1333
|
-
text: "",
|
|
1334
|
-
...meta,
|
|
1335
|
-
extra: { goalStatus }
|
|
1336
|
-
})
|
|
1337
|
-
);
|
|
1338
|
-
}
|
|
1339
|
-
continue;
|
|
1340
|
-
}
|
|
1341
|
-
if (!isObjectRecord(item) || typeof item["text"] !== "string") continue;
|
|
1342
|
-
yield emit(
|
|
1343
|
-
createTranscriptMessageUpdate({
|
|
1344
|
-
role: "assistant",
|
|
1345
|
-
text: item["text"].replace(/\n/g, " \n"),
|
|
1346
|
-
...meta,
|
|
1347
|
-
extra: { source: "slash_command" }
|
|
1348
|
-
})
|
|
1349
|
-
);
|
|
1163
|
+
const response = isObjectRecord(part["functionResponse"]) ? part["functionResponse"] : void 0;
|
|
1164
|
+
const payload = response && isObjectRecord(response["response"]) ? response["response"] : void 0;
|
|
1165
|
+
if (!payload) continue;
|
|
1166
|
+
try {
|
|
1167
|
+
const output = payload["output"];
|
|
1168
|
+
const error = payload["error"];
|
|
1169
|
+
const text = typeof output === "string" ? output : typeof error === "string" ? error : JSON.stringify(payload);
|
|
1170
|
+
content.push({
|
|
1171
|
+
type: "content",
|
|
1172
|
+
content: { type: "text", text }
|
|
1173
|
+
});
|
|
1174
|
+
} catch {
|
|
1350
1175
|
}
|
|
1351
1176
|
}
|
|
1352
|
-
|
|
1353
|
-
|
|
1354
|
-
|
|
1355
|
-
|
|
1177
|
+
return content;
|
|
1178
|
+
}
|
|
1179
|
+
__name(buildToolResultContent, "buildToolResultContent");
|
|
1180
|
+
function extractDiffContent(resultDisplay) {
|
|
1181
|
+
if (!isObjectRecord(resultDisplay)) return null;
|
|
1182
|
+
if (!("fileName" in resultDisplay) || !("newContent" in resultDisplay)) {
|
|
1183
|
+
return null;
|
|
1356
1184
|
}
|
|
1357
|
-
|
|
1358
|
-
|
|
1359
|
-
|
|
1360
|
-
|
|
1361
|
-
|
|
1362
|
-
|
|
1363
|
-
|
|
1364
|
-
|
|
1365
|
-
recordId
|
|
1366
|
-
);
|
|
1367
|
-
return this.allocateToolCallId(`qwen-replay-tool:${recordId}:result`);
|
|
1185
|
+
if (isTruncatedSessionDiffDisplay(resultDisplay)) {
|
|
1186
|
+
return {
|
|
1187
|
+
type: "content",
|
|
1188
|
+
content: {
|
|
1189
|
+
type: "text",
|
|
1190
|
+
text: buildTruncatedDiffPreviewText(resultDisplay)
|
|
1191
|
+
}
|
|
1192
|
+
};
|
|
1368
1193
|
}
|
|
1369
|
-
|
|
1370
|
-
|
|
1371
|
-
|
|
1372
|
-
|
|
1373
|
-
|
|
1374
|
-
|
|
1375
|
-
|
|
1376
|
-
|
|
1194
|
+
return {
|
|
1195
|
+
type: "diff",
|
|
1196
|
+
path: typeof resultDisplay["fileName"] === "string" ? resultDisplay["fileName"] : "",
|
|
1197
|
+
oldText: typeof resultDisplay["originalContent"] === "string" ? resultDisplay["originalContent"] : "",
|
|
1198
|
+
newText: typeof resultDisplay["newContent"] === "string" ? resultDisplay["newContent"] : ""
|
|
1199
|
+
};
|
|
1200
|
+
}
|
|
1201
|
+
__name(extractDiffContent, "extractDiffContent");
|
|
1202
|
+
function isTruncatedSessionDiffDisplay(value) {
|
|
1203
|
+
return isObjectRecord(value) && value["truncatedForSession"] === true && "fileName" in value && "newContent" in value;
|
|
1204
|
+
}
|
|
1205
|
+
__name(isTruncatedSessionDiffDisplay, "isTruncatedSessionDiffDisplay");
|
|
1206
|
+
function buildTruncatedDiffPreviewText(display) {
|
|
1207
|
+
const fileName = typeof display["fileName"] === "string" ? display["fileName"] : "the edited file";
|
|
1208
|
+
const fileDiffLength = typeof display["fileDiffLength"] === "number" ? ` Original fileDiff length: ${display["fileDiffLength"]} chars.` : "";
|
|
1209
|
+
return display["fileDiffTruncated"] === true ? `Full diff omitted from saved session history for ${fileName}.${fileDiffLength}` : `Saved session preview only for ${fileName}; full original and new file contents are unavailable.`;
|
|
1210
|
+
}
|
|
1211
|
+
__name(buildTruncatedDiffPreviewText, "buildTruncatedDiffPreviewText");
|
|
1212
|
+
function extractToolName(record) {
|
|
1213
|
+
for (const part of record.message?.parts ?? []) {
|
|
1214
|
+
if (!isObjectRecord(part) || !isObjectRecord(part["functionResponse"])) {
|
|
1215
|
+
continue;
|
|
1377
1216
|
}
|
|
1378
|
-
|
|
1379
|
-
|
|
1380
|
-
|
|
1217
|
+
const name = part["functionResponse"]["name"];
|
|
1218
|
+
if (typeof name === "string") return name;
|
|
1219
|
+
}
|
|
1220
|
+
return "";
|
|
1221
|
+
}
|
|
1222
|
+
__name(extractToolName, "extractToolName");
|
|
1223
|
+
function extractToolResultCallId(record, result) {
|
|
1224
|
+
if (typeof result?.["callId"] === "string" && result["callId"].length > 0) {
|
|
1225
|
+
return result["callId"];
|
|
1226
|
+
}
|
|
1227
|
+
for (const part of record.message?.parts ?? []) {
|
|
1228
|
+
if (!isObjectRecord(part) || !isObjectRecord(part["functionResponse"])) {
|
|
1229
|
+
continue;
|
|
1381
1230
|
}
|
|
1382
|
-
const id =
|
|
1383
|
-
|
|
1384
|
-
|
|
1231
|
+
const id = part["functionResponse"]["id"];
|
|
1232
|
+
if (typeof id === "string" && id.length > 0) return id;
|
|
1233
|
+
}
|
|
1234
|
+
return void 0;
|
|
1235
|
+
}
|
|
1236
|
+
__name(extractToolResultCallId, "extractToolResultCallId");
|
|
1237
|
+
function extractTodoPlanFromDisplay(value) {
|
|
1238
|
+
if (isObjectRecord(value) && value["type"] === "todo_list") {
|
|
1239
|
+
return Array.isArray(value["todos"]) ? {
|
|
1240
|
+
...typeof value["planId"] === "string" ? { planId: value["planId"] } : {},
|
|
1241
|
+
todos: normalizeTodos(value["todos"])
|
|
1242
|
+
} : null;
|
|
1385
1243
|
}
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
|
|
1390
|
-
|
|
1391
|
-
|
|
1392
|
-
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
|
|
1396
|
-
|
|
1397
|
-
|
|
1244
|
+
if (typeof value !== "string") return null;
|
|
1245
|
+
try {
|
|
1246
|
+
const parsed = JSON.parse(value);
|
|
1247
|
+
return isObjectRecord(parsed) && parsed["type"] === "todo_list" && Array.isArray(parsed["todos"]) ? {
|
|
1248
|
+
...typeof parsed["planId"] === "string" ? { planId: parsed["planId"] } : {},
|
|
1249
|
+
todos: normalizeTodos(parsed["todos"])
|
|
1250
|
+
} : null;
|
|
1251
|
+
} catch {
|
|
1252
|
+
return null;
|
|
1253
|
+
}
|
|
1254
|
+
}
|
|
1255
|
+
__name(extractTodoPlanFromDisplay, "extractTodoPlanFromDisplay");
|
|
1256
|
+
function normalizeTodos(values) {
|
|
1257
|
+
return values.flatMap((value) => {
|
|
1258
|
+
if (!isObjectRecord(value) || typeof value["content"] !== "string")
|
|
1259
|
+
return [];
|
|
1260
|
+
const status = value["status"];
|
|
1261
|
+
if (status !== "pending" && status !== "in_progress" && status !== "completed") {
|
|
1262
|
+
return [];
|
|
1398
1263
|
}
|
|
1264
|
+
return [
|
|
1265
|
+
{
|
|
1266
|
+
...typeof value["id"] === "string" ? { id: value["id"] } : {},
|
|
1267
|
+
content: value["content"],
|
|
1268
|
+
status,
|
|
1269
|
+
...Array.isArray(value["blockedBy"]) && value["blockedBy"].every((dependency) => typeof dependency === "string") ? { blockedBy: value["blockedBy"] } : {}
|
|
1270
|
+
}
|
|
1271
|
+
];
|
|
1272
|
+
});
|
|
1273
|
+
}
|
|
1274
|
+
__name(normalizeTodos, "normalizeTodos");
|
|
1275
|
+
function isTaskExecutionDisplay(value) {
|
|
1276
|
+
return isObjectRecord(value) && value["type"] === "task_execution";
|
|
1277
|
+
}
|
|
1278
|
+
__name(isTaskExecutionDisplay, "isTaskExecutionDisplay");
|
|
1279
|
+
function usageFromTaskExecution(display) {
|
|
1280
|
+
const summary = isObjectRecord(display["executionSummary"]) ? display["executionSummary"] : void 0;
|
|
1281
|
+
if (!summary) return {};
|
|
1282
|
+
return {
|
|
1283
|
+
...finiteNumber(summary["inputTokens"]) !== void 0 ? { promptTokenCount: summary["inputTokens"] } : {},
|
|
1284
|
+
...finiteNumber(summary["outputTokens"]) !== void 0 ? { candidatesTokenCount: summary["outputTokens"] } : {},
|
|
1285
|
+
...finiteNumber(summary["thoughtTokens"]) !== void 0 ? { thoughtsTokenCount: summary["thoughtTokens"] } : {},
|
|
1286
|
+
...finiteNumber(summary["cachedTokens"]) !== void 0 ? { cachedContentTokenCount: summary["cachedTokens"] } : {},
|
|
1287
|
+
...finiteNumber(summary["totalTokens"]) !== void 0 ? { totalTokenCount: summary["totalTokens"] } : {}
|
|
1288
|
+
};
|
|
1289
|
+
}
|
|
1290
|
+
__name(usageFromTaskExecution, "usageFromTaskExecution");
|
|
1291
|
+
function finiteNumber(value) {
|
|
1292
|
+
return typeof value === "number" && Number.isFinite(value) ? value : void 0;
|
|
1293
|
+
}
|
|
1294
|
+
__name(finiteNumber, "finiteNumber");
|
|
1295
|
+
function extractErrorMessage(value) {
|
|
1296
|
+
if (value instanceof Error) return value.message;
|
|
1297
|
+
if (!isObjectRecord(value)) return void 0;
|
|
1298
|
+
return typeof value["message"] === "string" ? value["message"] : void 0;
|
|
1299
|
+
}
|
|
1300
|
+
__name(extractErrorMessage, "extractErrorMessage");
|
|
1301
|
+
function dedupeStrings(values) {
|
|
1302
|
+
return [...new Set(values.filter((value) => value.length > 0))];
|
|
1303
|
+
}
|
|
1304
|
+
__name(dedupeStrings, "dedupeStrings");
|
|
1305
|
+
|
|
1306
|
+
// packages/cli/src/acp-integration/session/emitters/tool-call-emitter.ts
|
|
1307
|
+
init_esbuild_shims();
|
|
1308
|
+
|
|
1309
|
+
// packages/cli/src/acp-integration/session/emitters/base-emitter.ts
|
|
1310
|
+
init_esbuild_shims();
|
|
1311
|
+
var BaseEmitter = class {
|
|
1312
|
+
constructor(ctx) {
|
|
1313
|
+
this.ctx = ctx;
|
|
1399
1314
|
}
|
|
1400
|
-
|
|
1401
|
-
|
|
1402
|
-
|
|
1403
|
-
|
|
1404
|
-
|
|
1405
|
-
|
|
1406
|
-
|
|
1407
|
-
|
|
1408
|
-
|
|
1409
|
-
|
|
1410
|
-
|
|
1411
|
-
|
|
1315
|
+
static {
|
|
1316
|
+
__name(this, "BaseEmitter");
|
|
1317
|
+
}
|
|
1318
|
+
/**
|
|
1319
|
+
* Converts an ISO timestamp string or epoch ms to epoch ms number.
|
|
1320
|
+
* Returns undefined if the input is not a valid timestamp.
|
|
1321
|
+
*/
|
|
1322
|
+
static toEpochMs(ts) {
|
|
1323
|
+
if (typeof ts === "number") {
|
|
1324
|
+
return Number.isFinite(ts) ? ts : void 0;
|
|
1325
|
+
}
|
|
1326
|
+
if (typeof ts === "string") {
|
|
1327
|
+
const ms = new Date(ts).getTime();
|
|
1328
|
+
return Number.isFinite(ms) ? ms : void 0;
|
|
1412
1329
|
}
|
|
1330
|
+
return void 0;
|
|
1413
1331
|
}
|
|
1414
|
-
|
|
1415
|
-
|
|
1416
|
-
|
|
1417
|
-
|
|
1418
|
-
|
|
1419
|
-
|
|
1420
|
-
|
|
1421
|
-
|
|
1422
|
-
"Tool result content presentation fell back to deterministic defaults.",
|
|
1423
|
-
recordId,
|
|
1424
|
-
void 0,
|
|
1425
|
-
false
|
|
1426
|
-
);
|
|
1427
|
-
return defaultToolResultContentPrefix(resultDisplay);
|
|
1332
|
+
/**
|
|
1333
|
+
* Sends a session update to the ACP client.
|
|
1334
|
+
* If a message rewriter is configured, updates pass through it first
|
|
1335
|
+
* (original messages are sent as-is, rewritten versions are appended).
|
|
1336
|
+
*/
|
|
1337
|
+
async sendUpdate(update) {
|
|
1338
|
+
if (this.ctx.messageRewriter) {
|
|
1339
|
+
return this.ctx.messageRewriter.interceptUpdate(update);
|
|
1428
1340
|
}
|
|
1341
|
+
return this.ctx.sendUpdate(update);
|
|
1429
1342
|
}
|
|
1430
|
-
|
|
1431
|
-
|
|
1432
|
-
|
|
1433
|
-
|
|
1434
|
-
|
|
1435
|
-
affectsCompleteness,
|
|
1436
|
-
...recordId ? { recordId } : {},
|
|
1437
|
-
...path2 ? { path: path2 } : {}
|
|
1438
|
-
});
|
|
1343
|
+
/**
|
|
1344
|
+
* Gets the session ID.
|
|
1345
|
+
*/
|
|
1346
|
+
get sessionId() {
|
|
1347
|
+
return this.ctx.sessionId;
|
|
1439
1348
|
}
|
|
1440
1349
|
};
|
|
1441
|
-
|
|
1442
|
-
|
|
1443
|
-
|
|
1350
|
+
|
|
1351
|
+
// packages/cli/src/acp-integration/session/emitters/PlanEmitter.ts
|
|
1352
|
+
init_esbuild_shims();
|
|
1353
|
+
var PlanEmitter = class extends BaseEmitter {
|
|
1354
|
+
static {
|
|
1355
|
+
__name(this, "PlanEmitter");
|
|
1444
1356
|
}
|
|
1445
|
-
|
|
1446
|
-
|
|
1447
|
-
|
|
1448
|
-
|
|
1357
|
+
/**
|
|
1358
|
+
* Emits a plan update with the given todo items.
|
|
1359
|
+
*
|
|
1360
|
+
* @param plan - Plan identity and todo items to send as plan entries
|
|
1361
|
+
*/
|
|
1362
|
+
async emitPlan(plan, sourceCallId) {
|
|
1363
|
+
const cumulative = this.ctx.cumulativeUsage;
|
|
1364
|
+
await this.sendUpdate(
|
|
1365
|
+
createTranscriptPlanUpdate(plan.todos, cumulative, {
|
|
1366
|
+
planToolCallId: sourceCallId,
|
|
1367
|
+
todoPlanId: plan.planId
|
|
1368
|
+
})
|
|
1369
|
+
);
|
|
1449
1370
|
}
|
|
1450
|
-
|
|
1451
|
-
|
|
1452
|
-
|
|
1453
|
-
|
|
1454
|
-
|
|
1455
|
-
|
|
1456
|
-
|
|
1457
|
-
|
|
1458
|
-
|
|
1459
|
-
|
|
1460
|
-
|
|
1461
|
-
|
|
1462
|
-
|
|
1463
|
-
|
|
1464
|
-
|
|
1465
|
-
|
|
1466
|
-
|
|
1371
|
+
/**
|
|
1372
|
+
* Extracts todos from tool result display or args.
|
|
1373
|
+
* Tries multiple sources in priority order:
|
|
1374
|
+
* 1. Result display object with type 'todo_list'
|
|
1375
|
+
* 2. Result display as JSON string
|
|
1376
|
+
* 3. Args with 'todos' array when no result display is available
|
|
1377
|
+
*
|
|
1378
|
+
* @param resultDisplay - The tool result display (object, string, or undefined)
|
|
1379
|
+
* @param args - The tool call arguments (fallback source)
|
|
1380
|
+
* @returns Plan snapshot if found, null otherwise
|
|
1381
|
+
*/
|
|
1382
|
+
extractPlan(resultDisplay, args) {
|
|
1383
|
+
const plan = extractTranscriptTodoPlan(resultDisplay, args);
|
|
1384
|
+
if (!plan) return null;
|
|
1385
|
+
return {
|
|
1386
|
+
...plan.planId ? { planId: plan.planId } : {},
|
|
1387
|
+
todos: plan.todos.map((todo, index) => ({
|
|
1388
|
+
id: todo.id ?? String(index),
|
|
1389
|
+
content: todo.content,
|
|
1390
|
+
status: todo.status,
|
|
1391
|
+
...todo.blockedBy ? { blockedBy: [...todo.blockedBy] } : {}
|
|
1392
|
+
}))
|
|
1393
|
+
};
|
|
1467
1394
|
}
|
|
1468
|
-
|
|
1469
|
-
|
|
1470
|
-
|
|
1471
|
-
|
|
1472
|
-
|
|
1473
|
-
|
|
1474
|
-
${resultDisplay["notice"]}`
|
|
1475
|
-
}
|
|
1476
|
-
}
|
|
1477
|
-
];
|
|
1395
|
+
};
|
|
1396
|
+
|
|
1397
|
+
// packages/cli/src/acp-integration/session/types.ts
|
|
1398
|
+
init_esbuild_shims();
|
|
1399
|
+
function hasFullSessionContext(context) {
|
|
1400
|
+
return "config" in context;
|
|
1478
1401
|
}
|
|
1479
|
-
__name(
|
|
1480
|
-
|
|
1481
|
-
|
|
1482
|
-
|
|
1483
|
-
|
|
1484
|
-
|
|
1485
|
-
|
|
1486
|
-
|
|
1487
|
-
|
|
1488
|
-
|
|
1402
|
+
__name(hasFullSessionContext, "hasFullSessionContext");
|
|
1403
|
+
|
|
1404
|
+
// packages/cli/src/acp-integration/session/emitters/tool-call-emitter.ts
|
|
1405
|
+
var KIND_MAP = {
|
|
1406
|
+
["read" /* Read */]: "read",
|
|
1407
|
+
["edit" /* Edit */]: "edit",
|
|
1408
|
+
["delete" /* Delete */]: "delete",
|
|
1409
|
+
["move" /* Move */]: "move",
|
|
1410
|
+
["search" /* Search */]: "search",
|
|
1411
|
+
["execute" /* Execute */]: "execute",
|
|
1412
|
+
["think" /* Think */]: "think",
|
|
1413
|
+
["fetch" /* Fetch */]: "fetch",
|
|
1414
|
+
// ACP defines no 'agent' ToolKind (verified through @agentclientprotocol/sdk
|
|
1415
|
+
// 0.25.1). The daemon's ClientSideConnection Zod-validates every session/update
|
|
1416
|
+
// and session/request_permission from the `qwen --acp` child before fanning out
|
|
1417
|
+
// to SSE clients, so emitting 'agent' is rejected at that hop and the frame is
|
|
1418
|
+
// dropped. Map the internal Kind.Agent to 'other' on the wire to stay
|
|
1419
|
+
// protocol-valid; dedicated agent UI is delivered out-of-band (via _meta.toolName)
|
|
1420
|
+
// in a follow-up rather than via a kind the protocol can't carry.
|
|
1421
|
+
["agent" /* Agent */]: "other",
|
|
1422
|
+
["other" /* Other */]: "other"
|
|
1423
|
+
};
|
|
1424
|
+
var ToolCallEmitter = class _ToolCallEmitter extends BaseEmitter {
|
|
1425
|
+
static {
|
|
1426
|
+
__name(this, "ToolCallEmitter");
|
|
1489
1427
|
}
|
|
1490
|
-
|
|
1491
|
-
|
|
1428
|
+
planEmitter;
|
|
1429
|
+
preparedCallIds = /* @__PURE__ */ new Set();
|
|
1430
|
+
constructor(ctx) {
|
|
1431
|
+
super(ctx);
|
|
1432
|
+
this.planEmitter = new PlanEmitter(ctx);
|
|
1492
1433
|
}
|
|
1493
|
-
|
|
1494
|
-
|
|
1495
|
-
|
|
1496
|
-
|
|
1497
|
-
|
|
1498
|
-
|
|
1499
|
-
|
|
1500
|
-
|
|
1501
|
-
|
|
1502
|
-
|
|
1503
|
-
|
|
1504
|
-
|
|
1505
|
-
|
|
1506
|
-
|
|
1507
|
-
|
|
1508
|
-
|
|
1509
|
-
|
|
1510
|
-
|
|
1434
|
+
/**
|
|
1435
|
+
* Emits a tool call start event.
|
|
1436
|
+
*
|
|
1437
|
+
* @param params - Tool call start parameters
|
|
1438
|
+
* @returns true if event was emitted, false if skipped (e.g., TodoWriteTool)
|
|
1439
|
+
*/
|
|
1440
|
+
async emitStart(params) {
|
|
1441
|
+
if (this.isTodoWriteTool(params.toolName)) {
|
|
1442
|
+
return false;
|
|
1443
|
+
}
|
|
1444
|
+
if (params.phase === "preparing" && this.preparedCallIds.has(params.callId)) {
|
|
1445
|
+
return false;
|
|
1446
|
+
}
|
|
1447
|
+
const { title, locations, kind } = this.resolveToolMetadata(
|
|
1448
|
+
params.toolName,
|
|
1449
|
+
params.args
|
|
1450
|
+
);
|
|
1451
|
+
const provenance = _ToolCallEmitter.resolveToolProvenance(
|
|
1452
|
+
params.toolName,
|
|
1453
|
+
params.subagentMeta
|
|
1454
|
+
);
|
|
1455
|
+
const updatesPreparedCall = params.phase !== "preparing" && this.preparedCallIds.delete(params.callId);
|
|
1456
|
+
await this.sendUpdate(
|
|
1457
|
+
createTranscriptToolCallStartUpdate({
|
|
1458
|
+
toolName: params.toolName,
|
|
1459
|
+
callId: params.callId,
|
|
1460
|
+
status: params.status || "pending",
|
|
1461
|
+
args: params.args,
|
|
1462
|
+
metadata: { title, locations, kind },
|
|
1463
|
+
timestamp: params.timestamp,
|
|
1464
|
+
asUpdate: updatesPreparedCall,
|
|
1465
|
+
extra: {
|
|
1466
|
+
...params.phase ? { phase: params.phase } : {},
|
|
1467
|
+
...params.subagentMeta,
|
|
1468
|
+
provenance: provenance.provenance,
|
|
1469
|
+
...provenance.serverId ? { serverId: provenance.serverId } : {}
|
|
1511
1470
|
}
|
|
1512
|
-
|
|
1471
|
+
})
|
|
1472
|
+
);
|
|
1473
|
+
if (params.phase === "preparing") {
|
|
1474
|
+
this.preparedCallIds.add(params.callId);
|
|
1513
1475
|
}
|
|
1514
|
-
|
|
1515
|
-
const rawUsage = value.cumulativeUsage;
|
|
1516
|
-
const usage = isObjectRecord(rawUsage) ? rawUsage : {};
|
|
1517
|
-
const validUsage = finiteNumber(usage["promptTokens"]) !== void 0 && finiteNumber(usage["cachedTokens"]) !== void 0 && finiteNumber(usage["candidateTokens"]) !== void 0 && finiteNumber(usage["apiTimeMs"]) !== void 0;
|
|
1518
|
-
if (!validUsage) {
|
|
1519
|
-
onDiagnostic?.({
|
|
1520
|
-
code: "invalid_replay_state",
|
|
1521
|
-
severity: "warning",
|
|
1522
|
-
message: "Reset invalid cumulative usage in transcript replay state.",
|
|
1523
|
-
affectsCompleteness: true
|
|
1524
|
-
});
|
|
1476
|
+
return true;
|
|
1525
1477
|
}
|
|
1526
|
-
|
|
1527
|
-
|
|
1528
|
-
|
|
1529
|
-
|
|
1530
|
-
|
|
1531
|
-
|
|
1532
|
-
|
|
1533
|
-
|
|
1478
|
+
/**
|
|
1479
|
+
* Emits a terminal frame when a prepared tool call is discarded before
|
|
1480
|
+
* execution. TodoWrite remains represented exclusively by plan updates.
|
|
1481
|
+
*
|
|
1482
|
+
* @param callId - ID of the prepared tool call
|
|
1483
|
+
* @param toolName - Name of the prepared tool
|
|
1484
|
+
*/
|
|
1485
|
+
async emitPreparationDiscarded(callId, toolName) {
|
|
1486
|
+
if (this.isTodoWriteTool(toolName)) return;
|
|
1487
|
+
this.preparedCallIds.delete(callId);
|
|
1488
|
+
const provenance = _ToolCallEmitter.resolveToolProvenance(toolName);
|
|
1489
|
+
await this.sendUpdate({
|
|
1490
|
+
sessionUpdate: "tool_call_update",
|
|
1491
|
+
toolCallId: callId,
|
|
1492
|
+
status: "failed",
|
|
1493
|
+
content: [],
|
|
1494
|
+
_meta: {
|
|
1495
|
+
toolName,
|
|
1496
|
+
phase: "preparing",
|
|
1497
|
+
preparationDiscarded: true,
|
|
1498
|
+
provenance: provenance.provenance,
|
|
1499
|
+
...provenance.serverId ? { serverId: provenance.serverId } : {}
|
|
1500
|
+
}
|
|
1534
1501
|
});
|
|
1535
1502
|
}
|
|
1536
|
-
|
|
1537
|
-
|
|
1538
|
-
|
|
1539
|
-
|
|
1540
|
-
|
|
1541
|
-
|
|
1542
|
-
|
|
1543
|
-
|
|
1544
|
-
|
|
1503
|
+
/**
|
|
1504
|
+
* Emits a tool call result event.
|
|
1505
|
+
* Handles TodoWriteTool specially by routing to plan updates.
|
|
1506
|
+
*
|
|
1507
|
+
* @param params - Tool call result parameters
|
|
1508
|
+
*/
|
|
1509
|
+
async emitResult(params) {
|
|
1510
|
+
if (this.isTodoWriteTool(params.toolName)) {
|
|
1511
|
+
if (params.subagentMeta) return;
|
|
1512
|
+
if (!params.success) return;
|
|
1513
|
+
const plan = this.planEmitter.extractPlan(
|
|
1514
|
+
params.resultDisplay,
|
|
1515
|
+
params.args
|
|
1516
|
+
);
|
|
1517
|
+
if (plan && (plan.todos.length > 0 || params.args && Array.isArray(params.args["todos"]))) {
|
|
1518
|
+
await this.planEmitter.emitPlan(plan, params.callId);
|
|
1519
|
+
}
|
|
1520
|
+
return;
|
|
1521
|
+
}
|
|
1522
|
+
this.preparedCallIds.delete(params.callId);
|
|
1523
|
+
const provenance = _ToolCallEmitter.resolveToolProvenance(
|
|
1524
|
+
params.toolName,
|
|
1525
|
+
params.subagentMeta
|
|
1526
|
+
);
|
|
1527
|
+
await this.sendUpdate(
|
|
1528
|
+
createTranscriptToolCallResultUpdate({
|
|
1529
|
+
toolName: params.toolName,
|
|
1530
|
+
callId: params.callId,
|
|
1531
|
+
success: params.success,
|
|
1532
|
+
message: params.message,
|
|
1533
|
+
resultDisplay: params.resultDisplay,
|
|
1534
|
+
errorMessage: params.error?.message,
|
|
1535
|
+
artifacts: params.artifacts,
|
|
1536
|
+
contentPrefix: buildToolResultContentPrefix(params.resultDisplay),
|
|
1537
|
+
timestamp: params.timestamp,
|
|
1538
|
+
extra: {
|
|
1539
|
+
...params.subagentMeta,
|
|
1540
|
+
provenance: provenance.provenance,
|
|
1541
|
+
...provenance.serverId ? { serverId: provenance.serverId } : {}
|
|
1542
|
+
}
|
|
1543
|
+
})
|
|
1544
|
+
);
|
|
1545
1545
|
}
|
|
1546
|
-
|
|
1547
|
-
|
|
1548
|
-
|
|
1549
|
-
|
|
1550
|
-
|
|
1551
|
-
|
|
1552
|
-
|
|
1553
|
-
|
|
1554
|
-
|
|
1555
|
-
|
|
1556
|
-
|
|
1557
|
-
|
|
1558
|
-
|
|
1559
|
-
|
|
1560
|
-
|
|
1561
|
-
|
|
1562
|
-
|
|
1563
|
-
|
|
1564
|
-
|
|
1565
|
-
|
|
1566
|
-
|
|
1567
|
-
|
|
1568
|
-
|
|
1569
|
-
|
|
1570
|
-
|
|
1571
|
-
|
|
1572
|
-
|
|
1573
|
-
|
|
1574
|
-
|
|
1575
|
-
|
|
1576
|
-
|
|
1577
|
-
|
|
1578
|
-
|
|
1579
|
-
|
|
1580
|
-
|
|
1581
|
-
|
|
1582
|
-
|
|
1546
|
+
/**
|
|
1547
|
+
* Emits a tool call error event.
|
|
1548
|
+
* Use this for explicit error handling when not using emitResult.
|
|
1549
|
+
*
|
|
1550
|
+
* @param callId - The tool call ID
|
|
1551
|
+
* @param toolName - The tool name
|
|
1552
|
+
* @param error - The error that occurred
|
|
1553
|
+
* @param subagentMeta - Optional subagent metadata
|
|
1554
|
+
*/
|
|
1555
|
+
async emitError(callId, toolName, error, subagentMeta) {
|
|
1556
|
+
this.preparedCallIds.delete(callId);
|
|
1557
|
+
const provenance = _ToolCallEmitter.resolveToolProvenance(
|
|
1558
|
+
toolName,
|
|
1559
|
+
subagentMeta
|
|
1560
|
+
);
|
|
1561
|
+
await this.sendUpdate(
|
|
1562
|
+
createTranscriptToolCallResultUpdate({
|
|
1563
|
+
toolName,
|
|
1564
|
+
callId,
|
|
1565
|
+
success: false,
|
|
1566
|
+
errorMessage: error.message,
|
|
1567
|
+
extra: {
|
|
1568
|
+
...subagentMeta,
|
|
1569
|
+
provenance: provenance.provenance,
|
|
1570
|
+
...provenance.serverId ? { serverId: provenance.serverId } : {}
|
|
1571
|
+
}
|
|
1572
|
+
})
|
|
1573
|
+
);
|
|
1574
|
+
}
|
|
1575
|
+
/**
|
|
1576
|
+
* Resolve a tool's provenance for UI dispatch on tool_call events.
|
|
1577
|
+
* The SDK reads `_meta.
|
|
1578
|
+
* provenance` + `_meta.serverId` to render builtin / MCP-server-badge /
|
|
1579
|
+
* subagent-block differently. Without this stamping, the SDK falls
|
|
1580
|
+
* back to string-matching the toolName which can't reliably
|
|
1581
|
+
* distinguish builtin from subagent.
|
|
1582
|
+
*
|
|
1583
|
+
* Resolution rules:
|
|
1584
|
+
* - `subagentMeta` present → `'subagent'` (a Task tool / Codex
|
|
1585
|
+
* subagent / etc. wrapping its own tool calls)
|
|
1586
|
+
* - toolName matches `mcp__<server>__<tool>` → `'mcp'` with
|
|
1587
|
+
* `serverId: <server>`. Naming convention from
|
|
1588
|
+
* `packages/core/src/tools/mcp-tool.ts` in the
|
|
1589
|
+
* `@qwen-code/qwen-code-core` package — mirrors the SDK's same
|
|
1590
|
+
* heuristic fallback so SDK consumers stay consistent with
|
|
1591
|
+
* daemon classification.
|
|
1592
|
+
* - everything else → `'builtin'`
|
|
1593
|
+
*
|
|
1594
|
+
* Static + pure so it can be unit-tested without an emitter
|
|
1595
|
+
* instance. Exported via `ToolCallEmitter.resolveToolProvenance`.
|
|
1596
|
+
*/
|
|
1597
|
+
static resolveToolProvenance(toolName, subagentMeta) {
|
|
1598
|
+
if (subagentMeta !== void 0) {
|
|
1599
|
+
return { provenance: "subagent" };
|
|
1583
1600
|
}
|
|
1584
|
-
|
|
1585
|
-
|
|
1586
|
-
|
|
1587
|
-
|
|
1588
|
-
function buildToolResultContent(options) {
|
|
1589
|
-
const prefix = [...options.contentPrefix ?? []];
|
|
1590
|
-
const diff = extractDiffContent(options.resultDisplay);
|
|
1591
|
-
if (diff) return [...prefix, diff];
|
|
1592
|
-
if (options.errorMessage) {
|
|
1593
|
-
return [
|
|
1594
|
-
...prefix,
|
|
1595
|
-
{
|
|
1596
|
-
type: "content",
|
|
1597
|
-
content: { type: "text", text: options.errorMessage }
|
|
1601
|
+
if (toolName.startsWith("mcp__")) {
|
|
1602
|
+
const parts = toolName.split("__");
|
|
1603
|
+
if (parts.length >= 3 && parts[1] && parts[1].length > 0) {
|
|
1604
|
+
return { provenance: "mcp", serverId: parts[1] };
|
|
1598
1605
|
}
|
|
1599
|
-
|
|
1606
|
+
}
|
|
1607
|
+
return { provenance: "builtin" };
|
|
1600
1608
|
}
|
|
1601
|
-
|
|
1602
|
-
|
|
1603
|
-
|
|
1604
|
-
|
|
1605
|
-
|
|
1606
|
-
|
|
1607
|
-
|
|
1608
|
-
|
|
1609
|
+
// ==================== Public Utilities ====================
|
|
1610
|
+
/**
|
|
1611
|
+
* Checks if a tool name is the TodoWriteTool.
|
|
1612
|
+
* Exposed for external use in components that need to check this.
|
|
1613
|
+
*/
|
|
1614
|
+
isTodoWriteTool(toolName) {
|
|
1615
|
+
return toolName === ToolNames.TODO_WRITE;
|
|
1616
|
+
}
|
|
1617
|
+
/**
|
|
1618
|
+
* Checks if a tool name is the ExitPlanModeTool.
|
|
1619
|
+
*/
|
|
1620
|
+
isExitPlanModeTool(toolName) {
|
|
1621
|
+
return toolName === ToolNames.EXIT_PLAN_MODE;
|
|
1622
|
+
}
|
|
1623
|
+
/**
|
|
1624
|
+
* Checks if a tool name is the EnterPlanModeTool.
|
|
1625
|
+
*/
|
|
1626
|
+
isEnterPlanModeTool(toolName) {
|
|
1627
|
+
return toolName === ToolNames.ENTER_PLAN_MODE;
|
|
1628
|
+
}
|
|
1629
|
+
/**
|
|
1630
|
+
* Resolves tool metadata from the registry.
|
|
1631
|
+
* Falls back to defaults if tool not found or build fails.
|
|
1632
|
+
*
|
|
1633
|
+
* @param toolName - Name of the tool
|
|
1634
|
+
* @param args - Tool call arguments (used to build invocation)
|
|
1635
|
+
*/
|
|
1636
|
+
resolveToolMetadata(toolName, args) {
|
|
1637
|
+
if (!hasFullSessionContext(this.ctx)) {
|
|
1638
|
+
const description = typeof args?.["description"] === "string" ? args["description"].trim() : "";
|
|
1639
|
+
return {
|
|
1640
|
+
title: description ? `${toolName}: ${description}` : toolName,
|
|
1641
|
+
locations: [],
|
|
1642
|
+
kind: "other"
|
|
1643
|
+
};
|
|
1609
1644
|
}
|
|
1610
|
-
const
|
|
1611
|
-
const
|
|
1612
|
-
|
|
1613
|
-
|
|
1614
|
-
|
|
1615
|
-
|
|
1616
|
-
|
|
1617
|
-
|
|
1618
|
-
|
|
1619
|
-
|
|
1620
|
-
|
|
1621
|
-
|
|
1645
|
+
const toolRegistry = this.ctx.config.getToolRegistry();
|
|
1646
|
+
const tool = toolRegistry.getTool(toolName);
|
|
1647
|
+
let title = tool?.displayName ?? toolName;
|
|
1648
|
+
let locations = [];
|
|
1649
|
+
let kind = "other";
|
|
1650
|
+
if (tool && args) {
|
|
1651
|
+
try {
|
|
1652
|
+
const invocation = tool.build(args);
|
|
1653
|
+
title = `${title}: ${invocation.getDescription()}`;
|
|
1654
|
+
locations = invocation.toolLocations().map((loc) => ({
|
|
1655
|
+
path: loc.path,
|
|
1656
|
+
line: loc.line ?? null
|
|
1657
|
+
}));
|
|
1658
|
+
kind = this.mapToolKind(tool.kind, toolName);
|
|
1659
|
+
} catch {
|
|
1660
|
+
if (typeof args["description"] === "string") {
|
|
1661
|
+
title = `${title}: ${args["description"]}`;
|
|
1662
|
+
}
|
|
1663
|
+
if (tool.kind) {
|
|
1664
|
+
kind = this.mapToolKind(tool.kind, toolName);
|
|
1665
|
+
}
|
|
1666
|
+
}
|
|
1622
1667
|
}
|
|
1668
|
+
return { title, locations, kind };
|
|
1623
1669
|
}
|
|
1624
|
-
|
|
1625
|
-
|
|
1626
|
-
|
|
1627
|
-
|
|
1628
|
-
|
|
1629
|
-
|
|
1630
|
-
|
|
1670
|
+
/**
|
|
1671
|
+
* Maps core Tool Kind enum to ACP ToolKind string literals.
|
|
1672
|
+
*
|
|
1673
|
+
* @param kind - The core Kind enum value
|
|
1674
|
+
* @param toolName - Optional tool name to handle special cases like exit_plan_mode
|
|
1675
|
+
*/
|
|
1676
|
+
mapToolKind(kind, toolName) {
|
|
1677
|
+
if (toolName && (this.isExitPlanModeTool(toolName) || this.isEnterPlanModeTool(toolName))) {
|
|
1678
|
+
return "switch_mode";
|
|
1679
|
+
}
|
|
1680
|
+
return KIND_MAP[kind] ?? "other";
|
|
1631
1681
|
}
|
|
1632
|
-
|
|
1633
|
-
|
|
1682
|
+
};
|
|
1683
|
+
function buildToolResultContentPrefix(resultDisplay) {
|
|
1684
|
+
if (!isVisionBridgeNoticeDisplay(resultDisplay)) return [];
|
|
1685
|
+
return [
|
|
1686
|
+
{
|
|
1634
1687
|
type: "content",
|
|
1635
1688
|
content: {
|
|
1636
1689
|
type: "text",
|
|
1637
|
-
text:
|
|
1690
|
+
text: sanitizeTerminalText(
|
|
1691
|
+
formatVisionBridgeNoticeDisplay(resultDisplay)
|
|
1692
|
+
)
|
|
1638
1693
|
}
|
|
1639
|
-
};
|
|
1640
|
-
}
|
|
1641
|
-
return {
|
|
1642
|
-
type: "diff",
|
|
1643
|
-
path: typeof resultDisplay["fileName"] === "string" ? resultDisplay["fileName"] : "",
|
|
1644
|
-
oldText: typeof resultDisplay["originalContent"] === "string" ? resultDisplay["originalContent"] : "",
|
|
1645
|
-
newText: typeof resultDisplay["newContent"] === "string" ? resultDisplay["newContent"] : ""
|
|
1646
|
-
};
|
|
1647
|
-
}
|
|
1648
|
-
__name(extractDiffContent, "extractDiffContent");
|
|
1649
|
-
function isTruncatedSessionDiffDisplay(value) {
|
|
1650
|
-
return isObjectRecord(value) && value["truncatedForSession"] === true && "fileName" in value && "newContent" in value;
|
|
1651
|
-
}
|
|
1652
|
-
__name(isTruncatedSessionDiffDisplay, "isTruncatedSessionDiffDisplay");
|
|
1653
|
-
function buildTruncatedDiffPreviewText(display) {
|
|
1654
|
-
const fileName = typeof display["fileName"] === "string" ? display["fileName"] : "the edited file";
|
|
1655
|
-
const fileDiffLength = typeof display["fileDiffLength"] === "number" ? ` Original fileDiff length: ${display["fileDiffLength"]} chars.` : "";
|
|
1656
|
-
return display["fileDiffTruncated"] === true ? `Full diff omitted from saved session history for ${fileName}.${fileDiffLength}` : `Saved session preview only for ${fileName}; full original and new file contents are unavailable.`;
|
|
1657
|
-
}
|
|
1658
|
-
__name(buildTruncatedDiffPreviewText, "buildTruncatedDiffPreviewText");
|
|
1659
|
-
function extractToolName(record) {
|
|
1660
|
-
for (const part of record.message?.parts ?? []) {
|
|
1661
|
-
if (!isObjectRecord(part) || !isObjectRecord(part["functionResponse"])) {
|
|
1662
|
-
continue;
|
|
1663
|
-
}
|
|
1664
|
-
const name = part["functionResponse"]["name"];
|
|
1665
|
-
if (typeof name === "string") return name;
|
|
1666
|
-
}
|
|
1667
|
-
return "";
|
|
1668
|
-
}
|
|
1669
|
-
__name(extractToolName, "extractToolName");
|
|
1670
|
-
function extractToolResultCallId(record, result) {
|
|
1671
|
-
if (typeof result?.["callId"] === "string" && result["callId"].length > 0) {
|
|
1672
|
-
return result["callId"];
|
|
1673
|
-
}
|
|
1674
|
-
for (const part of record.message?.parts ?? []) {
|
|
1675
|
-
if (!isObjectRecord(part) || !isObjectRecord(part["functionResponse"])) {
|
|
1676
|
-
continue;
|
|
1677
|
-
}
|
|
1678
|
-
const id = part["functionResponse"]["id"];
|
|
1679
|
-
if (typeof id === "string" && id.length > 0) return id;
|
|
1680
|
-
}
|
|
1681
|
-
return void 0;
|
|
1682
|
-
}
|
|
1683
|
-
__name(extractToolResultCallId, "extractToolResultCallId");
|
|
1684
|
-
function extractTodoPlanFromDisplay(value) {
|
|
1685
|
-
if (isObjectRecord(value) && value["type"] === "todo_list") {
|
|
1686
|
-
return Array.isArray(value["todos"]) ? {
|
|
1687
|
-
...typeof value["planId"] === "string" ? { planId: value["planId"] } : {},
|
|
1688
|
-
todos: normalizeTodos(value["todos"])
|
|
1689
|
-
} : null;
|
|
1690
|
-
}
|
|
1691
|
-
if (typeof value !== "string") return null;
|
|
1692
|
-
try {
|
|
1693
|
-
const parsed = JSON.parse(value);
|
|
1694
|
-
return isObjectRecord(parsed) && parsed["type"] === "todo_list" && Array.isArray(parsed["todos"]) ? {
|
|
1695
|
-
...typeof parsed["planId"] === "string" ? { planId: parsed["planId"] } : {},
|
|
1696
|
-
todos: normalizeTodos(parsed["todos"])
|
|
1697
|
-
} : null;
|
|
1698
|
-
} catch {
|
|
1699
|
-
return null;
|
|
1700
|
-
}
|
|
1701
|
-
}
|
|
1702
|
-
__name(extractTodoPlanFromDisplay, "extractTodoPlanFromDisplay");
|
|
1703
|
-
function normalizeTodos(values) {
|
|
1704
|
-
return values.flatMap((value) => {
|
|
1705
|
-
if (!isObjectRecord(value) || typeof value["content"] !== "string")
|
|
1706
|
-
return [];
|
|
1707
|
-
const status = value["status"];
|
|
1708
|
-
if (status !== "pending" && status !== "in_progress" && status !== "completed") {
|
|
1709
|
-
return [];
|
|
1710
1694
|
}
|
|
1711
|
-
|
|
1712
|
-
{
|
|
1713
|
-
...typeof value["id"] === "string" ? { id: value["id"] } : {},
|
|
1714
|
-
content: value["content"],
|
|
1715
|
-
status,
|
|
1716
|
-
...Array.isArray(value["blockedBy"]) && value["blockedBy"].every((dependency) => typeof dependency === "string") ? { blockedBy: value["blockedBy"] } : {}
|
|
1717
|
-
}
|
|
1718
|
-
];
|
|
1719
|
-
});
|
|
1720
|
-
}
|
|
1721
|
-
__name(normalizeTodos, "normalizeTodos");
|
|
1722
|
-
function isTaskExecutionDisplay(value) {
|
|
1723
|
-
return isObjectRecord(value) && value["type"] === "task_execution";
|
|
1724
|
-
}
|
|
1725
|
-
__name(isTaskExecutionDisplay, "isTaskExecutionDisplay");
|
|
1726
|
-
function usageFromTaskExecution(display) {
|
|
1727
|
-
const summary = isObjectRecord(display["executionSummary"]) ? display["executionSummary"] : void 0;
|
|
1728
|
-
if (!summary) return {};
|
|
1729
|
-
return {
|
|
1730
|
-
...finiteNumber(summary["inputTokens"]) !== void 0 ? { promptTokenCount: summary["inputTokens"] } : {},
|
|
1731
|
-
...finiteNumber(summary["outputTokens"]) !== void 0 ? { candidatesTokenCount: summary["outputTokens"] } : {},
|
|
1732
|
-
...finiteNumber(summary["thoughtTokens"]) !== void 0 ? { thoughtsTokenCount: summary["thoughtTokens"] } : {},
|
|
1733
|
-
...finiteNumber(summary["cachedTokens"]) !== void 0 ? { cachedContentTokenCount: summary["cachedTokens"] } : {},
|
|
1734
|
-
...finiteNumber(summary["totalTokens"]) !== void 0 ? { totalTokenCount: summary["totalTokens"] } : {}
|
|
1735
|
-
};
|
|
1736
|
-
}
|
|
1737
|
-
__name(usageFromTaskExecution, "usageFromTaskExecution");
|
|
1738
|
-
function finiteNumber(value) {
|
|
1739
|
-
return typeof value === "number" && Number.isFinite(value) ? value : void 0;
|
|
1740
|
-
}
|
|
1741
|
-
__name(finiteNumber, "finiteNumber");
|
|
1742
|
-
function extractErrorMessage(value) {
|
|
1743
|
-
if (value instanceof Error) return value.message;
|
|
1744
|
-
if (!isObjectRecord(value)) return void 0;
|
|
1745
|
-
return typeof value["message"] === "string" ? value["message"] : void 0;
|
|
1746
|
-
}
|
|
1747
|
-
__name(extractErrorMessage, "extractErrorMessage");
|
|
1748
|
-
function dedupeStrings(values) {
|
|
1749
|
-
return [...new Set(values.filter((value) => value.length > 0))];
|
|
1695
|
+
];
|
|
1750
1696
|
}
|
|
1751
|
-
__name(
|
|
1752
|
-
|
|
1753
|
-
// packages/cli/src/acp-integration/session/emitters/PlanEmitter.ts
|
|
1754
|
-
init_esbuild_shims();
|
|
1697
|
+
__name(buildToolResultContentPrefix, "buildToolResultContentPrefix");
|
|
1755
1698
|
|
|
1756
|
-
// packages/cli/src/acp-integration/session/
|
|
1757
|
-
|
|
1758
|
-
var BaseEmitter = class {
|
|
1699
|
+
// packages/cli/src/acp-integration/session/history-replayer.ts
|
|
1700
|
+
var HistoryReplayer = class {
|
|
1759
1701
|
constructor(ctx) {
|
|
1760
1702
|
this.ctx = ctx;
|
|
1703
|
+
this.toolCallEmitter = new ToolCallEmitter(ctx);
|
|
1704
|
+
this.machine = this.createMachine();
|
|
1761
1705
|
}
|
|
1762
1706
|
static {
|
|
1763
|
-
__name(this, "
|
|
1707
|
+
__name(this, "HistoryReplayer");
|
|
1764
1708
|
}
|
|
1765
|
-
|
|
1766
|
-
|
|
1767
|
-
|
|
1768
|
-
|
|
1769
|
-
|
|
1770
|
-
|
|
1771
|
-
|
|
1709
|
+
toolCallEmitter;
|
|
1710
|
+
machine;
|
|
1711
|
+
async replay(records, gaps, options = {}) {
|
|
1712
|
+
try {
|
|
1713
|
+
if (options.goalBootstrap) {
|
|
1714
|
+
const update = {
|
|
1715
|
+
sessionUpdate: "agent_message_chunk",
|
|
1716
|
+
content: { type: "text", text: "" },
|
|
1717
|
+
_meta: {
|
|
1718
|
+
...options.goalBootstrap.goalState ? { goalState: options.goalBootstrap.goalState } : {},
|
|
1719
|
+
goalStatus: options.goalBootstrap.goalStatus
|
|
1720
|
+
}
|
|
1721
|
+
};
|
|
1722
|
+
await this.sendUpdate(update);
|
|
1723
|
+
}
|
|
1724
|
+
await this.replayPage(records, {
|
|
1725
|
+
finalizeDangling: true,
|
|
1726
|
+
gaps,
|
|
1727
|
+
...options.initialGoalState ? { goalState: options.initialGoalState } : {},
|
|
1728
|
+
...options.initialGoalCause ? { goalCause: options.initialGoalCause } : {}
|
|
1729
|
+
});
|
|
1730
|
+
} finally {
|
|
1731
|
+
this.setActiveRecordId(null);
|
|
1772
1732
|
}
|
|
1773
|
-
|
|
1774
|
-
|
|
1775
|
-
|
|
1733
|
+
}
|
|
1734
|
+
static v2GoalBootstrap(rawGoalState, rawGoalCause) {
|
|
1735
|
+
const goalState = parseGoalSnapshotV2(rawGoalState);
|
|
1736
|
+
const goalCause = parseGoalStateCause(rawGoalCause);
|
|
1737
|
+
if (!goalState?.goal || goalState.goal.status !== "active" || !goalCause) {
|
|
1738
|
+
return void 0;
|
|
1776
1739
|
}
|
|
1777
|
-
|
|
1740
|
+
const projection = projectGoalStateToLegacy({
|
|
1741
|
+
v: 2,
|
|
1742
|
+
cause: goalCause,
|
|
1743
|
+
snapshot: goalState
|
|
1744
|
+
});
|
|
1745
|
+
const { type: _type, kind, ...goalStatus } = projection.goalStatus;
|
|
1746
|
+
if (kind !== "set" && kind !== "checking") {
|
|
1747
|
+
return void 0;
|
|
1748
|
+
}
|
|
1749
|
+
return { goalStatus: { ...goalStatus, kind }, goalState };
|
|
1778
1750
|
}
|
|
1779
|
-
|
|
1780
|
-
|
|
1781
|
-
|
|
1782
|
-
|
|
1783
|
-
|
|
1784
|
-
|
|
1785
|
-
|
|
1786
|
-
|
|
1751
|
+
async replayPage(records, options = {}) {
|
|
1752
|
+
this.machine = this.createMachine(options);
|
|
1753
|
+
let replayError;
|
|
1754
|
+
try {
|
|
1755
|
+
for (const record of records) {
|
|
1756
|
+
for (const emission of this.machine.project(record)) {
|
|
1757
|
+
this.setActiveRecordId(
|
|
1758
|
+
emission.sourceRecordId,
|
|
1759
|
+
emission.sourceTimestamp
|
|
1760
|
+
);
|
|
1761
|
+
await this.sendUpdate(emission.update);
|
|
1762
|
+
}
|
|
1763
|
+
}
|
|
1764
|
+
} catch (error) {
|
|
1765
|
+
replayError = error;
|
|
1787
1766
|
}
|
|
1788
|
-
|
|
1767
|
+
let danglingError;
|
|
1768
|
+
if (options.finalizeDangling === true) {
|
|
1769
|
+
for (const emission of this.machine.finalize()) {
|
|
1770
|
+
this.setActiveRecordId(
|
|
1771
|
+
emission.sourceRecordId,
|
|
1772
|
+
emission.sourceTimestamp
|
|
1773
|
+
);
|
|
1774
|
+
try {
|
|
1775
|
+
await this.sendUpdate(emission.update);
|
|
1776
|
+
} catch (error) {
|
|
1777
|
+
danglingError ??= error;
|
|
1778
|
+
}
|
|
1779
|
+
}
|
|
1780
|
+
}
|
|
1781
|
+
const replay = this.machine.snapshot();
|
|
1782
|
+
this.copyCumulativeUsage(replay);
|
|
1783
|
+
const state = {
|
|
1784
|
+
pendingToolCalls: options.finalizeDangling === true ? [] : replay.pendingToolCalls.map(toLegacyPendingToolCall),
|
|
1785
|
+
replay
|
|
1786
|
+
};
|
|
1787
|
+
this.setActiveRecordId(null);
|
|
1788
|
+
if (replayError && danglingError) {
|
|
1789
|
+
throw new AggregateError(
|
|
1790
|
+
[replayError, danglingError],
|
|
1791
|
+
"Replay and dangling-cleanup both failed"
|
|
1792
|
+
);
|
|
1793
|
+
}
|
|
1794
|
+
if (replayError) throw replayError;
|
|
1795
|
+
if (danglingError) throw danglingError;
|
|
1796
|
+
return state;
|
|
1789
1797
|
}
|
|
1790
|
-
|
|
1791
|
-
|
|
1792
|
-
*/
|
|
1793
|
-
get sessionId() {
|
|
1794
|
-
return this.ctx.sessionId;
|
|
1798
|
+
getPendingToolCalls() {
|
|
1799
|
+
return this.machine.snapshot().pendingToolCalls.map(toLegacyPendingToolCall);
|
|
1795
1800
|
}
|
|
1796
|
-
|
|
1797
|
-
|
|
1798
|
-
// packages/cli/src/acp-integration/session/emitters/PlanEmitter.ts
|
|
1799
|
-
var PlanEmitter = class extends BaseEmitter {
|
|
1800
|
-
static {
|
|
1801
|
-
__name(this, "PlanEmitter");
|
|
1801
|
+
getReplayState() {
|
|
1802
|
+
return this.machine.snapshot();
|
|
1802
1803
|
}
|
|
1803
|
-
|
|
1804
|
-
* Emits a plan update with the given todo items.
|
|
1805
|
-
*
|
|
1806
|
-
* @param plan - Plan identity and todo items to send as plan entries
|
|
1807
|
-
*/
|
|
1808
|
-
async emitPlan(plan, sourceCallId) {
|
|
1804
|
+
createMachine(options = {}) {
|
|
1809
1805
|
const cumulative = this.ctx.cumulativeUsage;
|
|
1810
|
-
|
|
1811
|
-
|
|
1812
|
-
|
|
1813
|
-
|
|
1814
|
-
|
|
1815
|
-
|
|
1806
|
+
const initialState = {
|
|
1807
|
+
v: 1,
|
|
1808
|
+
pendingToolCalls: (options.pendingToolCalls ?? []).map(
|
|
1809
|
+
toPendingTranscriptToolCall
|
|
1810
|
+
),
|
|
1811
|
+
cumulativeUsage: cumulative ? { ...cumulative } : {
|
|
1812
|
+
promptTokens: 0,
|
|
1813
|
+
cachedTokens: 0,
|
|
1814
|
+
candidateTokens: 0,
|
|
1815
|
+
apiTimeMs: 0
|
|
1816
|
+
},
|
|
1817
|
+
...options.goalState ? { goalState: options.goalState } : {},
|
|
1818
|
+
...options.goalCause ? { goalCause: options.goalCause } : {}
|
|
1819
|
+
};
|
|
1820
|
+
return createTranscriptReplayMachine({
|
|
1821
|
+
initialState,
|
|
1822
|
+
gaps: options.gaps,
|
|
1823
|
+
presentation: this.presentationAdapter(),
|
|
1824
|
+
onDiagnostic: /* @__PURE__ */ __name((diagnostic) => {
|
|
1825
|
+
if (diagnostic.code === "malformed_part" && diagnostic.path === "systemPayload.outputHistoryItems.goalStatus.condition") {
|
|
1826
|
+
writeStderrLineSafe(`qwen: ${diagnostic.message}`);
|
|
1827
|
+
}
|
|
1828
|
+
}, "onDiagnostic")
|
|
1829
|
+
});
|
|
1816
1830
|
}
|
|
1817
|
-
|
|
1818
|
-
* Extracts todos from tool result display or args.
|
|
1819
|
-
* Tries multiple sources in priority order:
|
|
1820
|
-
* 1. Result display object with type 'todo_list'
|
|
1821
|
-
* 2. Result display as JSON string
|
|
1822
|
-
* 3. Args with 'todos' array when no result display is available
|
|
1823
|
-
*
|
|
1824
|
-
* @param resultDisplay - The tool result display (object, string, or undefined)
|
|
1825
|
-
* @param args - The tool call arguments (fallback source)
|
|
1826
|
-
* @returns Plan snapshot if found, null otherwise
|
|
1827
|
-
*/
|
|
1828
|
-
extractPlan(resultDisplay, args) {
|
|
1829
|
-
const plan = extractTranscriptTodoPlan(resultDisplay, args);
|
|
1830
|
-
if (!plan) return null;
|
|
1831
|
+
presentationAdapter() {
|
|
1831
1832
|
return {
|
|
1832
|
-
|
|
1833
|
-
|
|
1834
|
-
|
|
1835
|
-
content: todo.content,
|
|
1836
|
-
status: todo.status,
|
|
1837
|
-
...todo.blockedBy ? { blockedBy: [...todo.blockedBy] } : {}
|
|
1838
|
-
}))
|
|
1833
|
+
resolveToolMetadata: /* @__PURE__ */ __name((toolName, args) => this.toolCallEmitter.resolveToolMetadata(toolName, { ...args }), "resolveToolMetadata"),
|
|
1834
|
+
formatHistoryGap: /* @__PURE__ */ __name((gap) => formatHistoryGapNotice(gap), "formatHistoryGap"),
|
|
1835
|
+
buildToolResultContentPrefix
|
|
1839
1836
|
};
|
|
1840
1837
|
}
|
|
1841
|
-
|
|
1842
|
-
|
|
1843
|
-
|
|
1844
|
-
|
|
1845
|
-
|
|
1846
|
-
|
|
1847
|
-
init_esbuild_shims();
|
|
1848
|
-
function hasFullSessionContext(context) {
|
|
1849
|
-
return "config" in context;
|
|
1850
|
-
}
|
|
1851
|
-
__name(hasFullSessionContext, "hasFullSessionContext");
|
|
1852
|
-
|
|
1853
|
-
// packages/cli/src/acp-integration/session/emitters/tool-call-emitter.ts
|
|
1854
|
-
var KIND_MAP = {
|
|
1855
|
-
["read" /* Read */]: "read",
|
|
1856
|
-
["edit" /* Edit */]: "edit",
|
|
1857
|
-
["delete" /* Delete */]: "delete",
|
|
1858
|
-
["move" /* Move */]: "move",
|
|
1859
|
-
["search" /* Search */]: "search",
|
|
1860
|
-
["execute" /* Execute */]: "execute",
|
|
1861
|
-
["think" /* Think */]: "think",
|
|
1862
|
-
["fetch" /* Fetch */]: "fetch",
|
|
1863
|
-
// ACP defines no 'agent' ToolKind (verified through @agentclientprotocol/sdk
|
|
1864
|
-
// 0.25.1). The daemon's ClientSideConnection Zod-validates every session/update
|
|
1865
|
-
// and session/request_permission from the `qwen --acp` child before fanning out
|
|
1866
|
-
// to SSE clients, so emitting 'agent' is rejected at that hop and the frame is
|
|
1867
|
-
// dropped. Map the internal Kind.Agent to 'other' on the wire to stay
|
|
1868
|
-
// protocol-valid; dedicated agent UI is delivered out-of-band (via _meta.toolName)
|
|
1869
|
-
// in a follow-up rather than via a kind the protocol can't carry.
|
|
1870
|
-
["agent" /* Agent */]: "other",
|
|
1871
|
-
["other" /* Other */]: "other"
|
|
1872
|
-
};
|
|
1873
|
-
var ToolCallEmitter = class _ToolCallEmitter extends BaseEmitter {
|
|
1874
|
-
static {
|
|
1875
|
-
__name(this, "ToolCallEmitter");
|
|
1838
|
+
async sendUpdate(update) {
|
|
1839
|
+
if (this.ctx.messageRewriter) {
|
|
1840
|
+
await this.ctx.messageRewriter.interceptUpdate(update);
|
|
1841
|
+
return;
|
|
1842
|
+
}
|
|
1843
|
+
await this.ctx.sendUpdate(update);
|
|
1876
1844
|
}
|
|
1877
|
-
|
|
1878
|
-
|
|
1879
|
-
|
|
1880
|
-
|
|
1881
|
-
|
|
1845
|
+
copyCumulativeUsage(state) {
|
|
1846
|
+
const cumulative = this.ctx.cumulativeUsage;
|
|
1847
|
+
if (!cumulative) return;
|
|
1848
|
+
cumulative.promptTokens = state.cumulativeUsage.promptTokens;
|
|
1849
|
+
cumulative.cachedTokens = state.cumulativeUsage.cachedTokens;
|
|
1850
|
+
cumulative.candidateTokens = state.cumulativeUsage.candidateTokens;
|
|
1851
|
+
cumulative.apiTimeMs = state.cumulativeUsage.apiTimeMs;
|
|
1882
1852
|
}
|
|
1883
|
-
|
|
1884
|
-
|
|
1885
|
-
|
|
1886
|
-
|
|
1887
|
-
|
|
1888
|
-
|
|
1889
|
-
|
|
1890
|
-
|
|
1891
|
-
|
|
1892
|
-
}
|
|
1893
|
-
|
|
1894
|
-
|
|
1895
|
-
|
|
1896
|
-
|
|
1897
|
-
|
|
1898
|
-
|
|
1899
|
-
|
|
1900
|
-
|
|
1901
|
-
|
|
1902
|
-
|
|
1903
|
-
|
|
1904
|
-
|
|
1905
|
-
|
|
1906
|
-
|
|
1907
|
-
|
|
1908
|
-
|
|
1909
|
-
|
|
1910
|
-
|
|
1911
|
-
|
|
1912
|
-
|
|
1913
|
-
|
|
1914
|
-
|
|
1915
|
-
|
|
1916
|
-
|
|
1917
|
-
|
|
1918
|
-
|
|
1853
|
+
setActiveRecordId(recordId, timestamp) {
|
|
1854
|
+
this.ctx.setActiveRecordId?.(recordId, timestamp);
|
|
1855
|
+
}
|
|
1856
|
+
};
|
|
1857
|
+
function toPendingTranscriptToolCall(pending) {
|
|
1858
|
+
return {
|
|
1859
|
+
callId: pending.callId,
|
|
1860
|
+
toolName: pending.toolName,
|
|
1861
|
+
sourceRecordId: pending.recordId,
|
|
1862
|
+
...pending.timestamp ? { sourceTimestamp: pending.timestamp } : {}
|
|
1863
|
+
};
|
|
1864
|
+
}
|
|
1865
|
+
__name(toPendingTranscriptToolCall, "toPendingTranscriptToolCall");
|
|
1866
|
+
function toLegacyPendingToolCall(pending) {
|
|
1867
|
+
return {
|
|
1868
|
+
callId: pending.callId,
|
|
1869
|
+
toolName: pending.toolName,
|
|
1870
|
+
recordId: pending.sourceRecordId,
|
|
1871
|
+
...pending.sourceTimestamp ? { timestamp: pending.sourceTimestamp } : {}
|
|
1872
|
+
};
|
|
1873
|
+
}
|
|
1874
|
+
__name(toLegacyPendingToolCall, "toLegacyPendingToolCall");
|
|
1875
|
+
|
|
1876
|
+
// packages/cli/src/services/setup-github.ts
|
|
1877
|
+
init_esbuild_shims();
|
|
1878
|
+
import { promises as fsp } from "node:fs";
|
|
1879
|
+
import * as path from "node:path";
|
|
1880
|
+
|
|
1881
|
+
// packages/cli/src/utils/gitUtils.ts
|
|
1882
|
+
init_esbuild_shims();
|
|
1883
|
+
import * as childProcess from "node:child_process";
|
|
1884
|
+
var debugLogger = createDebugLogger("GIT");
|
|
1885
|
+
async function runGit(args, opts = {}) {
|
|
1886
|
+
return await new Promise((resolve2, reject) => {
|
|
1887
|
+
childProcess.execFile(
|
|
1888
|
+
"git",
|
|
1889
|
+
args,
|
|
1890
|
+
{
|
|
1891
|
+
encoding: "utf-8",
|
|
1892
|
+
...opts.cwd ? { cwd: opts.cwd } : {}
|
|
1893
|
+
},
|
|
1894
|
+
(err, stdout) => {
|
|
1895
|
+
if (err) {
|
|
1896
|
+
reject(err);
|
|
1897
|
+
return;
|
|
1919
1898
|
}
|
|
1920
|
-
|
|
1899
|
+
resolve2(String(stdout ?? "").trim());
|
|
1900
|
+
}
|
|
1921
1901
|
);
|
|
1922
|
-
|
|
1923
|
-
|
|
1924
|
-
|
|
1902
|
+
});
|
|
1903
|
+
}
|
|
1904
|
+
__name(runGit, "runGit");
|
|
1905
|
+
var isGitHubRepositoryAsync = /* @__PURE__ */ __name(async (opts = {}) => {
|
|
1906
|
+
try {
|
|
1907
|
+
const remotes = await runGit(["remote", "-v"], opts);
|
|
1908
|
+
return remotes.split("\n").some((line) => {
|
|
1909
|
+
const remoteUrl = line.trim().split(/\s+/)[1];
|
|
1910
|
+
return remoteUrl ? isGitHubRemoteUrl(remoteUrl) : false;
|
|
1911
|
+
});
|
|
1912
|
+
} catch (_error) {
|
|
1913
|
+
debugLogger.debug(`Failed to get git remote:`, _error);
|
|
1914
|
+
return false;
|
|
1915
|
+
}
|
|
1916
|
+
}, "isGitHubRepositoryAsync");
|
|
1917
|
+
function isGitHubRemoteUrl(remoteUrl) {
|
|
1918
|
+
if (remoteUrl.startsWith("git@github.com:")) {
|
|
1925
1919
|
return true;
|
|
1926
1920
|
}
|
|
1927
|
-
|
|
1928
|
-
|
|
1929
|
-
* execution. TodoWrite remains represented exclusively by plan updates.
|
|
1930
|
-
*
|
|
1931
|
-
* @param callId - ID of the prepared tool call
|
|
1932
|
-
* @param toolName - Name of the prepared tool
|
|
1933
|
-
*/
|
|
1934
|
-
async emitPreparationDiscarded(callId, toolName) {
|
|
1935
|
-
if (this.isTodoWriteTool(toolName)) return;
|
|
1936
|
-
this.preparedCallIds.delete(callId);
|
|
1937
|
-
const provenance = _ToolCallEmitter.resolveToolProvenance(toolName);
|
|
1938
|
-
await this.sendUpdate({
|
|
1939
|
-
sessionUpdate: "tool_call_update",
|
|
1940
|
-
toolCallId: callId,
|
|
1941
|
-
status: "failed",
|
|
1942
|
-
content: [],
|
|
1943
|
-
_meta: {
|
|
1944
|
-
toolName,
|
|
1945
|
-
phase: "preparing",
|
|
1946
|
-
preparationDiscarded: true,
|
|
1947
|
-
provenance: provenance.provenance,
|
|
1948
|
-
...provenance.serverId ? { serverId: provenance.serverId } : {}
|
|
1949
|
-
}
|
|
1950
|
-
});
|
|
1921
|
+
if (remoteUrl.startsWith("git@")) {
|
|
1922
|
+
return false;
|
|
1951
1923
|
}
|
|
1952
|
-
|
|
1953
|
-
|
|
1954
|
-
|
|
1955
|
-
|
|
1956
|
-
|
|
1957
|
-
|
|
1958
|
-
|
|
1959
|
-
|
|
1960
|
-
|
|
1961
|
-
|
|
1962
|
-
|
|
1963
|
-
|
|
1964
|
-
|
|
1924
|
+
try {
|
|
1925
|
+
return new URL(remoteUrl).hostname === "github.com";
|
|
1926
|
+
} catch {
|
|
1927
|
+
return false;
|
|
1928
|
+
}
|
|
1929
|
+
}
|
|
1930
|
+
__name(isGitHubRemoteUrl, "isGitHubRemoteUrl");
|
|
1931
|
+
var getGitRepoRootAsync = /* @__PURE__ */ __name(async (opts = {}) => {
|
|
1932
|
+
const gitRepoRoot = await runGit(["rev-parse", "--show-toplevel"], opts);
|
|
1933
|
+
if (!gitRepoRoot) {
|
|
1934
|
+
throw new Error(`Git repo returned empty value`);
|
|
1935
|
+
}
|
|
1936
|
+
return gitRepoRoot;
|
|
1937
|
+
}, "getGitRepoRootAsync");
|
|
1938
|
+
var getLatestGitHubRelease = /* @__PURE__ */ __name(async (proxy) => {
|
|
1939
|
+
try {
|
|
1940
|
+
const controller = new AbortController();
|
|
1941
|
+
const endpoint = `https://api.github.com/repos/QwenLM/qwen-code-action/releases/latest`;
|
|
1942
|
+
const dispatcher = proxy ? new (await loadUndici()).ProxyAgent(proxy) : void 0;
|
|
1943
|
+
const response = await fetch(endpoint, {
|
|
1944
|
+
method: "GET",
|
|
1945
|
+
headers: {
|
|
1946
|
+
Accept: "application/vnd.github+json",
|
|
1947
|
+
"Content-Type": "application/json",
|
|
1948
|
+
"X-GitHub-Api-Version": "2022-11-28"
|
|
1949
|
+
},
|
|
1950
|
+
dispatcher,
|
|
1951
|
+
signal: AbortSignal.any([AbortSignal.timeout(3e4), controller.signal])
|
|
1952
|
+
});
|
|
1953
|
+
if (!response.ok) {
|
|
1954
|
+
throw new Error(
|
|
1955
|
+
`Invalid response code: ${response.status} - ${response.statusText}`
|
|
1965
1956
|
);
|
|
1966
|
-
if (plan && (plan.todos.length > 0 || params.args && Array.isArray(params.args["todos"]))) {
|
|
1967
|
-
await this.planEmitter.emitPlan(plan, params.callId);
|
|
1968
|
-
}
|
|
1969
|
-
return;
|
|
1970
1957
|
}
|
|
1971
|
-
|
|
1972
|
-
|
|
1973
|
-
|
|
1974
|
-
|
|
1958
|
+
const releaseTag = (await response.json()).tag_name;
|
|
1959
|
+
if (!releaseTag) {
|
|
1960
|
+
throw new Error(`Response did not include tag_name field`);
|
|
1961
|
+
}
|
|
1962
|
+
return releaseTag;
|
|
1963
|
+
} catch (_error) {
|
|
1964
|
+
debugLogger.debug(
|
|
1965
|
+
`Failed to determine latest qwen-code-action release:`,
|
|
1966
|
+
_error
|
|
1975
1967
|
);
|
|
1976
|
-
|
|
1977
|
-
|
|
1978
|
-
toolName: params.toolName,
|
|
1979
|
-
callId: params.callId,
|
|
1980
|
-
success: params.success,
|
|
1981
|
-
message: params.message,
|
|
1982
|
-
resultDisplay: params.resultDisplay,
|
|
1983
|
-
errorMessage: params.error?.message,
|
|
1984
|
-
artifacts: params.artifacts,
|
|
1985
|
-
contentPrefix: buildToolResultContentPrefix(params.resultDisplay),
|
|
1986
|
-
timestamp: params.timestamp,
|
|
1987
|
-
extra: {
|
|
1988
|
-
...params.subagentMeta,
|
|
1989
|
-
provenance: provenance.provenance,
|
|
1990
|
-
...provenance.serverId ? { serverId: provenance.serverId } : {}
|
|
1991
|
-
}
|
|
1992
|
-
})
|
|
1968
|
+
throw new Error(
|
|
1969
|
+
`Unable to determine the latest qwen-code-action release on GitHub.`
|
|
1993
1970
|
);
|
|
1994
1971
|
}
|
|
1995
|
-
|
|
1996
|
-
|
|
1997
|
-
|
|
1998
|
-
|
|
1999
|
-
|
|
2000
|
-
|
|
2001
|
-
|
|
2002
|
-
|
|
2003
|
-
|
|
2004
|
-
|
|
2005
|
-
|
|
2006
|
-
|
|
2007
|
-
|
|
2008
|
-
|
|
1972
|
+
}, "getLatestGitHubRelease");
|
|
1973
|
+
async function getGitHubRepoInfoAsync(opts = {}) {
|
|
1974
|
+
return parseGitHubRepoInfo(
|
|
1975
|
+
await runGit(["remote", "get-url", "origin"], opts)
|
|
1976
|
+
);
|
|
1977
|
+
}
|
|
1978
|
+
__name(getGitHubRepoInfoAsync, "getGitHubRepoInfoAsync");
|
|
1979
|
+
function parseGitHubRepoInfo(remoteUrl) {
|
|
1980
|
+
let urlToParse = remoteUrl;
|
|
1981
|
+
if (remoteUrl.startsWith("git@github.com:")) {
|
|
1982
|
+
urlToParse = remoteUrl.replace("git@github.com:", "");
|
|
1983
|
+
} else if (remoteUrl.startsWith("git@")) {
|
|
1984
|
+
throw new Error(
|
|
1985
|
+
`Owner & repo could not be extracted from remote URL: ${remoteUrl}`
|
|
2009
1986
|
);
|
|
2010
|
-
|
|
2011
|
-
|
|
2012
|
-
|
|
2013
|
-
|
|
2014
|
-
|
|
2015
|
-
|
|
2016
|
-
|
|
2017
|
-
...subagentMeta,
|
|
2018
|
-
provenance: provenance.provenance,
|
|
2019
|
-
...provenance.serverId ? { serverId: provenance.serverId } : {}
|
|
2020
|
-
}
|
|
2021
|
-
})
|
|
1987
|
+
}
|
|
1988
|
+
let parsedUrl;
|
|
1989
|
+
try {
|
|
1990
|
+
parsedUrl = new URL(urlToParse, "https://github.com");
|
|
1991
|
+
} catch {
|
|
1992
|
+
throw new Error(
|
|
1993
|
+
`Owner & repo could not be extracted from remote URL: ${remoteUrl}`
|
|
2022
1994
|
);
|
|
2023
1995
|
}
|
|
2024
|
-
|
|
2025
|
-
|
|
2026
|
-
|
|
2027
|
-
|
|
2028
|
-
* subagent-block differently. Without this stamping, the SDK falls
|
|
2029
|
-
* back to string-matching the toolName which can't reliably
|
|
2030
|
-
* distinguish builtin from subagent.
|
|
2031
|
-
*
|
|
2032
|
-
* Resolution rules:
|
|
2033
|
-
* - `subagentMeta` present → `'subagent'` (a Task tool / Codex
|
|
2034
|
-
* subagent / etc. wrapping its own tool calls)
|
|
2035
|
-
* - toolName matches `mcp__<server>__<tool>` → `'mcp'` with
|
|
2036
|
-
* `serverId: <server>`. Naming convention from
|
|
2037
|
-
* `packages/core/src/tools/mcp-tool.ts` in the
|
|
2038
|
-
* `@qwen-code/qwen-code-core` package — mirrors the SDK's same
|
|
2039
|
-
* heuristic fallback so SDK consumers stay consistent with
|
|
2040
|
-
* daemon classification.
|
|
2041
|
-
* - everything else → `'builtin'`
|
|
2042
|
-
*
|
|
2043
|
-
* Static + pure so it can be unit-tested without an emitter
|
|
2044
|
-
* instance. Exported via `ToolCallEmitter.resolveToolProvenance`.
|
|
2045
|
-
*/
|
|
2046
|
-
static resolveToolProvenance(toolName, subagentMeta) {
|
|
2047
|
-
if (subagentMeta !== void 0) {
|
|
2048
|
-
return { provenance: "subagent" };
|
|
2049
|
-
}
|
|
2050
|
-
if (toolName.startsWith("mcp__")) {
|
|
2051
|
-
const parts = toolName.split("__");
|
|
2052
|
-
if (parts.length >= 3 && parts[1] && parts[1].length > 0) {
|
|
2053
|
-
return { provenance: "mcp", serverId: parts[1] };
|
|
2054
|
-
}
|
|
2055
|
-
}
|
|
2056
|
-
return { provenance: "builtin" };
|
|
1996
|
+
if (parsedUrl.hostname !== "github.com") {
|
|
1997
|
+
throw new Error(
|
|
1998
|
+
`Owner & repo could not be extracted from remote URL: ${remoteUrl}`
|
|
1999
|
+
);
|
|
2057
2000
|
}
|
|
2058
|
-
|
|
2059
|
-
|
|
2060
|
-
|
|
2061
|
-
|
|
2062
|
-
|
|
2063
|
-
isTodoWriteTool(toolName) {
|
|
2064
|
-
return toolName === ToolNames.TODO_WRITE;
|
|
2001
|
+
const parts = parsedUrl.pathname.split("/").filter((part) => part !== "");
|
|
2002
|
+
if (parts.length !== 2 || !parts[0] || !parts[1]) {
|
|
2003
|
+
throw new Error(
|
|
2004
|
+
`Owner & repo could not be extracted from remote URL: ${remoteUrl}`
|
|
2005
|
+
);
|
|
2065
2006
|
}
|
|
2066
|
-
|
|
2067
|
-
|
|
2068
|
-
|
|
2069
|
-
|
|
2070
|
-
|
|
2007
|
+
return { owner: parts[0], repo: parts[1].replace(/\.git$/, "") };
|
|
2008
|
+
}
|
|
2009
|
+
__name(parseGitHubRepoInfo, "parseGitHubRepoInfo");
|
|
2010
|
+
|
|
2011
|
+
// packages/cli/src/services/setup-github.ts
|
|
2012
|
+
var debugLogger2 = createDebugLogger("SETUP_GITHUB");
|
|
2013
|
+
var GITHUB_WORKFLOW_PATHS = [
|
|
2014
|
+
"qwen-dispatch/qwen-dispatch.yml",
|
|
2015
|
+
"qwen-assistant/qwen-invoke.yml",
|
|
2016
|
+
"issue-triage/qwen-triage.yml",
|
|
2017
|
+
"issue-triage/qwen-scheduled-triage.yml",
|
|
2018
|
+
"pr-review/qwen-review.yml"
|
|
2019
|
+
];
|
|
2020
|
+
var GITIGNORE_ENTRIES = [".qwen/", "gha-creds-*.json"];
|
|
2021
|
+
var MAX_WORKFLOW_DOWNLOAD_BYTES = 5 * 1024 * 1024;
|
|
2022
|
+
var SetupGithubError = class extends Error {
|
|
2023
|
+
static {
|
|
2024
|
+
__name(this, "SetupGithubError");
|
|
2071
2025
|
}
|
|
2072
|
-
|
|
2073
|
-
|
|
2074
|
-
|
|
2075
|
-
|
|
2076
|
-
|
|
2026
|
+
code;
|
|
2027
|
+
status;
|
|
2028
|
+
partial;
|
|
2029
|
+
partialResult;
|
|
2030
|
+
constructor(code, message, status, partialResult) {
|
|
2031
|
+
super(message);
|
|
2032
|
+
this.name = "SetupGithubError";
|
|
2033
|
+
this.code = code;
|
|
2034
|
+
this.status = status;
|
|
2035
|
+
this.partial = partialResult !== void 0;
|
|
2036
|
+
this.partialResult = partialResult;
|
|
2077
2037
|
}
|
|
2078
|
-
|
|
2079
|
-
|
|
2080
|
-
|
|
2081
|
-
|
|
2082
|
-
|
|
2083
|
-
|
|
2084
|
-
|
|
2085
|
-
|
|
2086
|
-
|
|
2087
|
-
|
|
2088
|
-
|
|
2089
|
-
|
|
2090
|
-
|
|
2091
|
-
|
|
2092
|
-
|
|
2093
|
-
|
|
2094
|
-
const
|
|
2095
|
-
|
|
2096
|
-
|
|
2097
|
-
|
|
2098
|
-
|
|
2099
|
-
|
|
2100
|
-
|
|
2101
|
-
|
|
2102
|
-
|
|
2103
|
-
|
|
2104
|
-
path: loc.path,
|
|
2105
|
-
line: loc.line ?? null
|
|
2106
|
-
}));
|
|
2107
|
-
kind = this.mapToolKind(tool.kind, toolName);
|
|
2108
|
-
} catch {
|
|
2109
|
-
if (typeof args["description"] === "string") {
|
|
2110
|
-
title = `${title}: ${args["description"]}`;
|
|
2111
|
-
}
|
|
2112
|
-
if (tool.kind) {
|
|
2113
|
-
kind = this.mapToolKind(tool.kind, toolName);
|
|
2114
|
-
}
|
|
2038
|
+
};
|
|
2039
|
+
function isWorkspaceGenerationClosed(error) {
|
|
2040
|
+
return Boolean(
|
|
2041
|
+
error && typeof error === "object" && "code" in error && error.code === "workspace_generation_closed"
|
|
2042
|
+
);
|
|
2043
|
+
}
|
|
2044
|
+
__name(isWorkspaceGenerationClosed, "isWorkspaceGenerationClosed");
|
|
2045
|
+
var nodeFileOps = {
|
|
2046
|
+
assertCanWrite() {
|
|
2047
|
+
},
|
|
2048
|
+
async ensureWorkflowDirectory(gitRepoRoot) {
|
|
2049
|
+
await fsp.mkdir(path.join(gitRepoRoot, ".github", "workflows"), {
|
|
2050
|
+
recursive: true
|
|
2051
|
+
});
|
|
2052
|
+
},
|
|
2053
|
+
async writeTextFile(gitRepoRoot, relativePath, content) {
|
|
2054
|
+
const target = path.join(gitRepoRoot, relativePath);
|
|
2055
|
+
await fsp.writeFile(target, content, { mode: 420 });
|
|
2056
|
+
return { sizeBytes: Buffer.byteLength(content, "utf8") };
|
|
2057
|
+
},
|
|
2058
|
+
async readTextFile(gitRepoRoot, relativePath) {
|
|
2059
|
+
try {
|
|
2060
|
+
return await fsp.readFile(path.join(gitRepoRoot, relativePath), "utf8");
|
|
2061
|
+
} catch (error) {
|
|
2062
|
+
if (error.code === "ENOENT") {
|
|
2063
|
+
return void 0;
|
|
2115
2064
|
}
|
|
2065
|
+
throw error;
|
|
2116
2066
|
}
|
|
2117
|
-
return { title, locations, kind };
|
|
2118
|
-
}
|
|
2119
|
-
/**
|
|
2120
|
-
* Maps core Tool Kind enum to ACP ToolKind string literals.
|
|
2121
|
-
*
|
|
2122
|
-
* @param kind - The core Kind enum value
|
|
2123
|
-
* @param toolName - Optional tool name to handle special cases like exit_plan_mode
|
|
2124
|
-
*/
|
|
2125
|
-
mapToolKind(kind, toolName) {
|
|
2126
|
-
if (toolName && (this.isExitPlanModeTool(toolName) || this.isEnterPlanModeTool(toolName))) {
|
|
2127
|
-
return "switch_mode";
|
|
2128
|
-
}
|
|
2129
|
-
return KIND_MAP[kind] ?? "other";
|
|
2130
2067
|
}
|
|
2131
2068
|
};
|
|
2132
|
-
function
|
|
2133
|
-
|
|
2134
|
-
|
|
2135
|
-
|
|
2136
|
-
|
|
2137
|
-
|
|
2138
|
-
|
|
2139
|
-
|
|
2140
|
-
|
|
2141
|
-
|
|
2142
|
-
|
|
2069
|
+
async function setupGithub(options = {}) {
|
|
2070
|
+
const cwd = options.cwd ?? process.cwd();
|
|
2071
|
+
const fileOps = options.fileOps ?? nodeFileOps;
|
|
2072
|
+
if (!await isGitHubRepositoryAsync({ cwd })) {
|
|
2073
|
+
throw new SetupGithubError(
|
|
2074
|
+
"github_repository_not_found",
|
|
2075
|
+
"Unable to determine the GitHub repository. /setup-github must be run from a git repository.",
|
|
2076
|
+
400
|
|
2077
|
+
);
|
|
2078
|
+
}
|
|
2079
|
+
let gitRepoRoot;
|
|
2080
|
+
try {
|
|
2081
|
+
gitRepoRoot = await getGitRepoRootAsync({ cwd });
|
|
2082
|
+
} catch (error) {
|
|
2083
|
+
debugLogger2.debug("Failed to get git repo root:", error);
|
|
2084
|
+
throw new SetupGithubError(
|
|
2085
|
+
"github_repository_not_found",
|
|
2086
|
+
"Unable to determine the GitHub repository. /setup-github must be run from a git repository.",
|
|
2087
|
+
400
|
|
2088
|
+
);
|
|
2089
|
+
}
|
|
2090
|
+
if (options.workspaceRoot) {
|
|
2091
|
+
const [gitRootReal, workspaceReal] = await Promise.all([
|
|
2092
|
+
realpathOrResolve(gitRepoRoot),
|
|
2093
|
+
realpathOrResolve(options.workspaceRoot)
|
|
2094
|
+
]);
|
|
2095
|
+
if (gitRootReal !== workspaceReal) {
|
|
2096
|
+
throw new SetupGithubError(
|
|
2097
|
+
"github_git_root_mismatch",
|
|
2098
|
+
"The Git repository root must match the daemon workspace root.",
|
|
2099
|
+
400
|
|
2100
|
+
);
|
|
2143
2101
|
}
|
|
2144
|
-
];
|
|
2145
|
-
}
|
|
2146
|
-
__name(buildToolResultContentPrefix, "buildToolResultContentPrefix");
|
|
2147
|
-
|
|
2148
|
-
// packages/cli/src/acp-integration/session/history-replayer.ts
|
|
2149
|
-
init_esbuild_shims();
|
|
2150
|
-
var HistoryReplayer = class {
|
|
2151
|
-
constructor(ctx) {
|
|
2152
|
-
this.ctx = ctx;
|
|
2153
|
-
this.toolCallEmitter = new ToolCallEmitter(ctx);
|
|
2154
|
-
this.machine = this.createMachine();
|
|
2155
2102
|
}
|
|
2156
|
-
|
|
2157
|
-
|
|
2103
|
+
fileOps.assertCanWrite?.();
|
|
2104
|
+
let releaseTag;
|
|
2105
|
+
try {
|
|
2106
|
+
releaseTag = await getLatestGitHubRelease(options.proxy);
|
|
2107
|
+
} catch (error) {
|
|
2108
|
+
writeStderrLine(
|
|
2109
|
+
`qwen setup-github: failed to determine latest qwen-code-action release: ${error instanceof Error ? error.message : String(error)}`
|
|
2110
|
+
);
|
|
2111
|
+
debugLogger2.debug(
|
|
2112
|
+
"Failed to determine latest qwen-code-action release:",
|
|
2113
|
+
error
|
|
2114
|
+
);
|
|
2115
|
+
throw new SetupGithubError(
|
|
2116
|
+
"github_release_lookup_failed",
|
|
2117
|
+
"Unable to determine the latest qwen-code-action release on GitHub.",
|
|
2118
|
+
502
|
|
2119
|
+
);
|
|
2158
2120
|
}
|
|
2159
|
-
|
|
2160
|
-
|
|
2161
|
-
|
|
2162
|
-
|
|
2163
|
-
|
|
2164
|
-
|
|
2165
|
-
|
|
2166
|
-
|
|
2167
|
-
|
|
2168
|
-
|
|
2121
|
+
const readmeUrl = `https://github.com/QwenLM/qwen-code-action/blob/${releaseTag}/README.md#quick-start`;
|
|
2122
|
+
const secretsUrl = await resolveSecretsUrl(cwd);
|
|
2123
|
+
const downloads = await downloadWorkflows({
|
|
2124
|
+
releaseTag,
|
|
2125
|
+
proxy: options.proxy,
|
|
2126
|
+
abortSignal: options.abortSignal,
|
|
2127
|
+
fetchImpl: options.fetchImpl ?? fetch
|
|
2128
|
+
});
|
|
2129
|
+
const result = {
|
|
2130
|
+
kind: "github_setup",
|
|
2131
|
+
workspaceCwd: options.workspaceRoot ?? gitRepoRoot,
|
|
2132
|
+
gitRepoRoot,
|
|
2133
|
+
releaseTag,
|
|
2134
|
+
readmeUrl,
|
|
2135
|
+
...secretsUrl ? { secretsUrl } : {},
|
|
2136
|
+
workflows: [],
|
|
2137
|
+
gitignore: { path: ".gitignore", status: "skipped" },
|
|
2138
|
+
warnings: []
|
|
2139
|
+
};
|
|
2140
|
+
result.gitignore = await updateGitignore(gitRepoRoot, fileOps);
|
|
2141
|
+
if (result.gitignore.status === "failed") {
|
|
2142
|
+
result.warnings.push("Failed to update .gitignore.");
|
|
2143
|
+
}
|
|
2144
|
+
try {
|
|
2145
|
+
await fileOps.ensureWorkflowDirectory(gitRepoRoot);
|
|
2146
|
+
for (const workflow of downloads) {
|
|
2147
|
+
const relativePath = path.posix.join(
|
|
2148
|
+
".github",
|
|
2149
|
+
"workflows",
|
|
2150
|
+
path.posix.basename(workflow.sourcePath)
|
|
2151
|
+
);
|
|
2152
|
+
try {
|
|
2153
|
+
const write = await fileOps.writeTextFile(
|
|
2154
|
+
gitRepoRoot,
|
|
2155
|
+
relativePath,
|
|
2156
|
+
workflow.content
|
|
2157
|
+
);
|
|
2158
|
+
result.workflows.push({
|
|
2159
|
+
sourcePath: workflow.sourcePath,
|
|
2160
|
+
path: relativePath,
|
|
2161
|
+
status: "written",
|
|
2162
|
+
sizeBytes: write.sizeBytes
|
|
2163
|
+
});
|
|
2164
|
+
} catch (error) {
|
|
2165
|
+
if (isWorkspaceGenerationClosed(error)) throw error;
|
|
2166
|
+
result.partial = true;
|
|
2167
|
+
result.workflows.push({
|
|
2168
|
+
sourcePath: workflow.sourcePath,
|
|
2169
|
+
path: relativePath,
|
|
2170
|
+
status: "failed",
|
|
2171
|
+
error: error instanceof Error ? error.message : String(error)
|
|
2172
|
+
});
|
|
2173
|
+
throw new SetupGithubError(
|
|
2174
|
+
"github_workflow_write_failed",
|
|
2175
|
+
`Unable to write ${relativePath}.`,
|
|
2176
|
+
500,
|
|
2177
|
+
result
|
|
2178
|
+
);
|
|
2179
|
+
}
|
|
2169
2180
|
}
|
|
2181
|
+
} catch (error) {
|
|
2182
|
+
if (isWorkspaceGenerationClosed(error)) throw error;
|
|
2183
|
+
if (error instanceof SetupGithubError) throw error;
|
|
2184
|
+
throw new SetupGithubError(
|
|
2185
|
+
"github_workflow_write_failed",
|
|
2186
|
+
"Unable to create .github/workflows.",
|
|
2187
|
+
500,
|
|
2188
|
+
result
|
|
2189
|
+
);
|
|
2170
2190
|
}
|
|
2171
|
-
|
|
2172
|
-
|
|
2173
|
-
|
|
2174
|
-
|
|
2175
|
-
|
|
2176
|
-
|
|
2177
|
-
|
|
2178
|
-
|
|
2179
|
-
|
|
2180
|
-
|
|
2181
|
-
|
|
2182
|
-
|
|
2183
|
-
|
|
2184
|
-
|
|
2185
|
-
|
|
2191
|
+
return result;
|
|
2192
|
+
}
|
|
2193
|
+
__name(setupGithub, "setupGithub");
|
|
2194
|
+
async function updateGitignore(gitRepoRoot, fileOps = nodeFileOps) {
|
|
2195
|
+
try {
|
|
2196
|
+
const existingContent = await fileOps.readTextFile(
|
|
2197
|
+
gitRepoRoot,
|
|
2198
|
+
".gitignore"
|
|
2199
|
+
);
|
|
2200
|
+
if (existingContent === void 0) {
|
|
2201
|
+
const content = GITIGNORE_ENTRIES.join("\n") + "\n";
|
|
2202
|
+
await fileOps.writeTextFile(gitRepoRoot, ".gitignore", content);
|
|
2203
|
+
return {
|
|
2204
|
+
path: ".gitignore",
|
|
2205
|
+
status: "created",
|
|
2206
|
+
added: [...GITIGNORE_ENTRIES]
|
|
2207
|
+
};
|
|
2186
2208
|
}
|
|
2187
|
-
|
|
2188
|
-
|
|
2189
|
-
|
|
2190
|
-
|
|
2191
|
-
|
|
2192
|
-
emission.sourceTimestamp
|
|
2193
|
-
);
|
|
2194
|
-
try {
|
|
2195
|
-
await this.sendUpdate(emission.update);
|
|
2196
|
-
} catch (error) {
|
|
2197
|
-
danglingError ??= error;
|
|
2198
|
-
}
|
|
2199
|
-
}
|
|
2209
|
+
const missingEntries = GITIGNORE_ENTRIES.filter(
|
|
2210
|
+
(entry) => !existingContent.split(/\r?\n/).some((line) => line.split("#")[0].trim() === entry)
|
|
2211
|
+
);
|
|
2212
|
+
if (missingEntries.length === 0) {
|
|
2213
|
+
return { path: ".gitignore", status: "unchanged" };
|
|
2200
2214
|
}
|
|
2201
|
-
const
|
|
2202
|
-
|
|
2203
|
-
|
|
2204
|
-
|
|
2205
|
-
|
|
2215
|
+
const nextContent = existingContent + "\n" + missingEntries.join("\n") + "\n";
|
|
2216
|
+
await fileOps.writeTextFile(gitRepoRoot, ".gitignore", nextContent);
|
|
2217
|
+
return {
|
|
2218
|
+
path: ".gitignore",
|
|
2219
|
+
status: "updated",
|
|
2220
|
+
added: missingEntries
|
|
2206
2221
|
};
|
|
2207
|
-
|
|
2208
|
-
if (
|
|
2209
|
-
|
|
2210
|
-
|
|
2211
|
-
|
|
2212
|
-
|
|
2213
|
-
|
|
2214
|
-
if (replayError) throw replayError;
|
|
2215
|
-
if (danglingError) throw danglingError;
|
|
2216
|
-
return state;
|
|
2217
|
-
}
|
|
2218
|
-
getPendingToolCalls() {
|
|
2219
|
-
return this.machine.snapshot().pendingToolCalls.map(toLegacyPendingToolCall);
|
|
2220
|
-
}
|
|
2221
|
-
getReplayState() {
|
|
2222
|
-
return this.machine.snapshot();
|
|
2223
|
-
}
|
|
2224
|
-
createMachine(options = {}) {
|
|
2225
|
-
const cumulative = this.ctx.cumulativeUsage;
|
|
2226
|
-
const initialState = {
|
|
2227
|
-
v: 1,
|
|
2228
|
-
pendingToolCalls: (options.pendingToolCalls ?? []).map(
|
|
2229
|
-
toPendingTranscriptToolCall
|
|
2230
|
-
),
|
|
2231
|
-
cumulativeUsage: cumulative ? { ...cumulative } : {
|
|
2232
|
-
promptTokens: 0,
|
|
2233
|
-
cachedTokens: 0,
|
|
2234
|
-
candidateTokens: 0,
|
|
2235
|
-
apiTimeMs: 0
|
|
2236
|
-
},
|
|
2237
|
-
...options.goalState ? { goalState: options.goalState } : {},
|
|
2238
|
-
...options.goalCause ? { goalCause: options.goalCause } : {}
|
|
2222
|
+
} catch (error) {
|
|
2223
|
+
if (isWorkspaceGenerationClosed(error)) throw error;
|
|
2224
|
+
debugLogger2.debug("Failed to update .gitignore:", error);
|
|
2225
|
+
return {
|
|
2226
|
+
path: ".gitignore",
|
|
2227
|
+
status: "failed",
|
|
2228
|
+
error: error instanceof Error ? error.message : String(error)
|
|
2239
2229
|
};
|
|
2240
|
-
|
|
2241
|
-
|
|
2242
|
-
|
|
2243
|
-
|
|
2244
|
-
|
|
2245
|
-
|
|
2246
|
-
|
|
2230
|
+
}
|
|
2231
|
+
}
|
|
2232
|
+
__name(updateGitignore, "updateGitignore");
|
|
2233
|
+
async function downloadWorkflows(options) {
|
|
2234
|
+
const internalAbort = new AbortController();
|
|
2235
|
+
try {
|
|
2236
|
+
const dispatcher = options.proxy ? new (await loadUndici()).ProxyAgent(options.proxy) : void 0;
|
|
2237
|
+
return await Promise.all(
|
|
2238
|
+
GITHUB_WORKFLOW_PATHS.map(async (workflow) => {
|
|
2239
|
+
const endpoint = `https://raw.githubusercontent.com/QwenLM/qwen-code-action/refs/tags/${options.releaseTag}/examples/workflows/${workflow}`;
|
|
2240
|
+
const response = await options.fetchImpl(endpoint, {
|
|
2241
|
+
method: "GET",
|
|
2242
|
+
dispatcher,
|
|
2243
|
+
signal: AbortSignal.any([
|
|
2244
|
+
AbortSignal.timeout(3e4),
|
|
2245
|
+
internalAbort.signal,
|
|
2246
|
+
...options.abortSignal ? [options.abortSignal] : []
|
|
2247
|
+
])
|
|
2248
|
+
});
|
|
2249
|
+
if (!response.ok) {
|
|
2250
|
+
throw new Error(
|
|
2251
|
+
`Invalid response code downloading ${endpoint}: ${response.status} - ${response.statusText}`
|
|
2252
|
+
);
|
|
2247
2253
|
}
|
|
2248
|
-
|
|
2249
|
-
|
|
2254
|
+
return {
|
|
2255
|
+
sourcePath: workflow,
|
|
2256
|
+
content: await readResponseTextWithLimit(response, workflow)
|
|
2257
|
+
};
|
|
2258
|
+
})
|
|
2259
|
+
);
|
|
2260
|
+
} catch (error) {
|
|
2261
|
+
internalAbort.abort();
|
|
2262
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
2263
|
+
debugLogger2.debug("Failed to download qwen-code-action workflows:", error);
|
|
2264
|
+
throw new SetupGithubError(
|
|
2265
|
+
"github_workflow_download_failed",
|
|
2266
|
+
`Unable to download qwen-code-action workflows from GitHub. ${message}`,
|
|
2267
|
+
502
|
|
2268
|
+
);
|
|
2250
2269
|
}
|
|
2251
|
-
|
|
2252
|
-
|
|
2253
|
-
|
|
2254
|
-
|
|
2255
|
-
|
|
2256
|
-
|
|
2270
|
+
}
|
|
2271
|
+
__name(downloadWorkflows, "downloadWorkflows");
|
|
2272
|
+
async function readResponseTextWithLimit(response, sourcePath) {
|
|
2273
|
+
const contentLength = response.headers.get("content-length");
|
|
2274
|
+
if (contentLength !== null) {
|
|
2275
|
+
const parsedLength = Number(contentLength);
|
|
2276
|
+
if (Number.isFinite(parsedLength) && parsedLength > MAX_WORKFLOW_DOWNLOAD_BYTES) {
|
|
2277
|
+
throw new Error(
|
|
2278
|
+
`${sourcePath} exceeds download limit of ${MAX_WORKFLOW_DOWNLOAD_BYTES} bytes`
|
|
2279
|
+
);
|
|
2280
|
+
}
|
|
2257
2281
|
}
|
|
2258
|
-
|
|
2259
|
-
|
|
2260
|
-
|
|
2261
|
-
|
|
2282
|
+
if (!response.body) return "";
|
|
2283
|
+
const reader = response.body.getReader();
|
|
2284
|
+
const chunks = [];
|
|
2285
|
+
let totalBytes = 0;
|
|
2286
|
+
try {
|
|
2287
|
+
while (true) {
|
|
2288
|
+
const { done, value } = await reader.read();
|
|
2289
|
+
if (done) break;
|
|
2290
|
+
if (!value) continue;
|
|
2291
|
+
totalBytes += value.byteLength;
|
|
2292
|
+
if (totalBytes > MAX_WORKFLOW_DOWNLOAD_BYTES) {
|
|
2293
|
+
await reader.cancel().catch(() => {
|
|
2294
|
+
});
|
|
2295
|
+
throw new Error(
|
|
2296
|
+
`${sourcePath} exceeds download limit of ${MAX_WORKFLOW_DOWNLOAD_BYTES} bytes`
|
|
2297
|
+
);
|
|
2298
|
+
}
|
|
2299
|
+
chunks.push(value);
|
|
2262
2300
|
}
|
|
2263
|
-
|
|
2301
|
+
} finally {
|
|
2302
|
+
reader.releaseLock();
|
|
2264
2303
|
}
|
|
2265
|
-
|
|
2266
|
-
|
|
2267
|
-
|
|
2268
|
-
|
|
2269
|
-
|
|
2270
|
-
cumulative.candidateTokens = state.cumulativeUsage.candidateTokens;
|
|
2271
|
-
cumulative.apiTimeMs = state.cumulativeUsage.apiTimeMs;
|
|
2304
|
+
const body = new Uint8Array(totalBytes);
|
|
2305
|
+
let offset = 0;
|
|
2306
|
+
for (const chunk of chunks) {
|
|
2307
|
+
body.set(chunk, offset);
|
|
2308
|
+
offset += chunk.byteLength;
|
|
2272
2309
|
}
|
|
2273
|
-
|
|
2274
|
-
|
|
2310
|
+
return new TextDecoder().decode(body);
|
|
2311
|
+
}
|
|
2312
|
+
__name(readResponseTextWithLimit, "readResponseTextWithLimit");
|
|
2313
|
+
async function resolveSecretsUrl(cwd) {
|
|
2314
|
+
try {
|
|
2315
|
+
const repoInfo = await getGitHubRepoInfoAsync({ cwd });
|
|
2316
|
+
return `https://github.com/${repoInfo.owner}/${repoInfo.repo}/settings/secrets/actions`;
|
|
2317
|
+
} catch {
|
|
2318
|
+
return void 0;
|
|
2275
2319
|
}
|
|
2276
|
-
};
|
|
2277
|
-
function toPendingTranscriptToolCall(pending) {
|
|
2278
|
-
return {
|
|
2279
|
-
callId: pending.callId,
|
|
2280
|
-
toolName: pending.toolName,
|
|
2281
|
-
sourceRecordId: pending.recordId,
|
|
2282
|
-
...pending.timestamp ? { sourceTimestamp: pending.timestamp } : {}
|
|
2283
|
-
};
|
|
2284
2320
|
}
|
|
2285
|
-
__name(
|
|
2286
|
-
function
|
|
2287
|
-
|
|
2288
|
-
|
|
2289
|
-
|
|
2290
|
-
|
|
2291
|
-
|
|
2292
|
-
};
|
|
2321
|
+
__name(resolveSecretsUrl, "resolveSecretsUrl");
|
|
2322
|
+
async function realpathOrResolve(input) {
|
|
2323
|
+
try {
|
|
2324
|
+
return await fsp.realpath(input);
|
|
2325
|
+
} catch {
|
|
2326
|
+
return path.resolve(input);
|
|
2327
|
+
}
|
|
2293
2328
|
}
|
|
2294
|
-
__name(
|
|
2329
|
+
__name(realpathOrResolve, "realpathOrResolve");
|
|
2295
2330
|
|
|
2296
2331
|
// packages/cli/src/ui/utils/export/collect.ts
|
|
2297
2332
|
init_esbuild_shims();
|
|
@@ -2512,7 +2547,7 @@ async function extractMetadata(conversation, config) {
|
|
|
2512
2547
|
const gitBranch = firstRecord?.gitBranch;
|
|
2513
2548
|
let gitRepo;
|
|
2514
2549
|
if (cwd) {
|
|
2515
|
-
const { getGitRepoName } = await import("./deferred-core-runtime-
|
|
2550
|
+
const { getGitRepoName } = await import("./deferred-core-runtime-F4XOQJQL.js");
|
|
2516
2551
|
gitRepo = getGitRepoName(cwd);
|
|
2517
2552
|
}
|
|
2518
2553
|
let model;
|
|
@@ -3386,7 +3421,7 @@ export {
|
|
|
3386
3421
|
};
|
|
3387
3422
|
/**
|
|
3388
3423
|
* @license
|
|
3389
|
-
* Copyright
|
|
3424
|
+
* Copyright 2026 Qwen Team
|
|
3390
3425
|
* SPDX-License-Identifier: Apache-2.0
|
|
3391
3426
|
*/
|
|
3392
3427
|
/**
|
|
@@ -3396,12 +3431,12 @@ export {
|
|
|
3396
3431
|
*/
|
|
3397
3432
|
/**
|
|
3398
3433
|
* @license
|
|
3399
|
-
* Copyright
|
|
3434
|
+
* Copyright 2025 Qwen
|
|
3400
3435
|
* SPDX-License-Identifier: Apache-2.0
|
|
3401
3436
|
*/
|
|
3402
3437
|
/**
|
|
3403
3438
|
* @license
|
|
3404
|
-
* Copyright 2025
|
|
3439
|
+
* Copyright 2025 Google LLC
|
|
3405
3440
|
* SPDX-License-Identifier: Apache-2.0
|
|
3406
3441
|
*/
|
|
3407
3442
|
/**
|