@qwen-code/qwen-code 0.21.1 → 0.21.2-nightly.20260801.bc382c3ff
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 +9 -7
- package/bundled/qc-helper/docs/features/channels/_meta.ts +1 -0
- package/bundled/qc-helper/docs/features/channels/github.md +49 -10
- package/bundled/qc-helper/docs/features/channels/gitlab.md +177 -0
- package/bundled/qc-helper/docs/features/code-review.md +20 -0
- package/bundled/qc-helper/docs/features/commands.md +1 -0
- package/bundled/qc-helper/docs/features/hooks.md +135 -18
- package/bundled/qc-helper/docs/features/memory.md +27 -0
- package/bundled/qc-helper/docs/features/skills.md +14 -0
- package/bundled/qc-helper/docs/features/sub-agents.md +55 -8
- package/bundled/qc-helper/docs/features/tool-use-summaries.md +7 -7
- package/bundled/qc-helper/docs/qwen-serve.md +28 -6
- package/bundled/qc-helper/docs/reference/keyboard-shortcuts.md +2 -2
- package/bundled/review/SKILL.md +1 -1
- package/chunks/{MaxSizedBox-VI3ROJJA.js → MaxSizedBox-CDHTDITS.js} +45 -40
- package/chunks/{StandaloneSessionPicker-LYXKD2EV.js → StandaloneSessionPicker-L63HUAHP.js} +65 -60
- package/chunks/{acp-startup-profiler-DFVPFQ6C.js → acp-startup-profiler-3RICG2YW.js} +2 -2
- package/chunks/{acpAgent-WN5SRDQO.js → acpAgent-6WVVT2P3.js} +962 -599
- package/chunks/{agent-K6ECSM64.js → agent-KDM4CBOU.js} +40 -35
- package/chunks/agent-headless-AS7K2K57.js +79 -0
- package/chunks/{anthropicContentGenerator-V2QOGVYD.js → anthropicContentGenerator-WCBYB6JG.js} +337 -27
- package/chunks/{artifact-tool-6K6U7XYJ.js → artifact-tool-ANV4CFCR.js} +2 -2
- package/chunks/{askUserQuestion-GD2IJJ7I.js → askUserQuestion-MALEB47H.js} +2 -2
- package/chunks/{bridge-3KJEWDNE.js → bridge-JNEW6FES.js} +46 -41
- package/chunks/{build-S6DO7LMM.js → build-GDBLPA24.js} +1 -1
- package/chunks/{ca-6W3SK7OQ.js → ca-4OJN75WT.js} +46 -5
- package/chunks/{channel-management-service-XR7GZSWF.js → channel-management-service-QOO7TD3T.js} +21 -6
- package/chunks/{channel-settings-store-HW4FXXUA.js → channel-settings-store-4CSMTR4L.js} +47 -42
- package/chunks/{channel-worker-group-XDPTDWTX.js → channel-worker-group-ERSUOPIR.js} +8 -8
- package/chunks/{channel-worker-manager-YYEHVRRE.js → channel-worker-manager-X247YDQ7.js} +8 -8
- package/chunks/{channel-worker-supervisor-74HTWA2G.js → channel-worker-supervisor-ORJIEEPP.js} +4 -4
- package/chunks/{chunk-VWOOBLTY.js → chunk-25QQVOCG.js} +5 -5
- package/chunks/{chunk-CAPPWD3X.js → chunk-2A6MHYIA.js} +3 -3
- package/chunks/{chunk-2XSLTRFZ.js → chunk-2CTKGIFR.js} +2 -2
- package/chunks/{chunk-DZLYR4U3.js → chunk-2DNKEBXY.js} +1 -1
- package/chunks/{chunk-UWMLWVCA.js → chunk-2IIJTXYF.js} +26 -10
- package/chunks/{chunk-JYBU6YUE.js → chunk-2M5N3DHY.js} +1 -1
- package/chunks/{chunk-AQIDMUGU.js → chunk-2PNQQ4UR.js} +2 -2
- package/chunks/{chunk-OKF7JF3R.js → chunk-2UISUFHQ.js} +3 -3
- package/chunks/{chunk-2LQTH543.js → chunk-33FNCQSY.js} +2 -2
- package/chunks/{chunk-M7OONWYU.js → chunk-3LGZEYOF.js} +4 -2
- package/chunks/{chunk-ZURDMIDR.js → chunk-3MHPWQ2M.js} +242 -76
- package/chunks/{chunk-UHUSJ6X7.js → chunk-3RXUYQJI.js} +25 -6
- package/chunks/{chunk-E5Z2AVNV.js → chunk-3SH53ANB.js} +0 -11
- package/chunks/{chunk-BNWB5CYE.js → chunk-3WXMXT7C.js} +22 -11
- package/chunks/{chunk-A2D5BAVP.js → chunk-42IKVPST.js} +1 -1
- package/chunks/{chunk-2DN4J57Y.js → chunk-432XCUHF.js} +1 -1
- package/chunks/{chunk-EVKE2FZL.js → chunk-433VD3HX.js} +4 -4
- package/chunks/{chunk-Q43KPN7X.js → chunk-434YCHSV.js} +6 -6
- package/chunks/{chunk-5TBMQLGG.js → chunk-4LKVQFHM.js} +2 -2
- package/chunks/{chunk-YDLJGZHL.js → chunk-4NFY2S7N.js} +0 -33
- package/chunks/{chunk-6PE7N3A4.js → chunk-5UJ6A3CH.js} +145 -10
- package/chunks/{chunk-GNR2RNMP.js → chunk-5UZITEHA.js} +3 -3
- package/chunks/chunk-6FMJLI5M.js +1591 -0
- package/chunks/{chunk-RPLGZJV2.js → chunk-6O5DVH27.js} +1 -1
- package/chunks/{chunk-2RFKHEXL.js → chunk-6PLDPT2C.js} +1 -1
- package/chunks/{chunk-7AEJDLRA.js → chunk-7IYLHTTM.js} +3 -3
- package/chunks/{chunk-65PQENQP.js → chunk-7K2WTPQO.js} +5 -5
- package/chunks/{chunk-P4WOAOJW.js → chunk-7MY2AR5A.js} +72 -26
- package/chunks/{chunk-GXIJHV66.js → chunk-A2A34TSB.js} +3 -3
- package/chunks/{chunk-XWWKIXVD.js → chunk-A5YZ3FA2.js} +2 -1
- package/chunks/{chunk-64LQLPL7.js → chunk-A6SX5TAH.js} +3 -3
- package/chunks/{chunk-SZ3KHTDR.js → chunk-AKA24BGO.js} +1 -1
- package/chunks/chunk-AQ37AY7B.js +93 -0
- package/chunks/{chunk-2N7CODY5.js → chunk-AQEWCKX4.js} +2 -2
- package/chunks/{chunk-KCO4FLFJ.js → chunk-AYB4HSBI.js} +3 -3
- package/chunks/{chunk-WZRWHXFE.js → chunk-BFHXDAR7.js} +1 -1
- package/chunks/{chunk-L55JWS76.js → chunk-BGXZBI5B.js} +1 -1
- package/chunks/{chunk-5MKRTI4T.js → chunk-BKUN5QHP.js} +7 -7
- package/chunks/{chunk-Y4IHBGBP.js → chunk-BV4QX43X.js} +1 -1
- package/chunks/{chunk-PB3MBFKG.js → chunk-C4L2MEIT.js} +4 -4
- package/chunks/{chunk-TCIFAA7K.js → chunk-CHCLO3M7.js} +14 -14
- package/chunks/{chunk-CVHIL5IG.js → chunk-CWEIMFFW.js} +13 -6
- package/chunks/{chunk-2FAK6PNM.js → chunk-DUIJ2IXG.js} +5 -13
- package/chunks/{chunk-T2QMKU3R.js → chunk-DVGTU5TC.js} +19 -7
- package/chunks/{chunk-LGAOC3ZS.js → chunk-DYA25Y7U.js} +1 -1
- package/chunks/{chunk-SGFT55XI.js → chunk-E4WHKETF.js} +32 -4
- package/chunks/{chunk-WBL3FJEU.js → chunk-FC4KQFCS.js} +1 -1
- package/chunks/{chunk-MHAIJPTD.js → chunk-FJHA23GM.js} +12 -12
- package/chunks/{chunk-S7W2GKIO.js → chunk-G7XXKQYS.js} +2 -0
- package/chunks/{chunk-MR5EAQ5M.js → chunk-GALUTA2C.js} +1 -1
- package/chunks/{chunk-7I5GTCT4.js → chunk-GB3AB7TR.js} +4008 -3648
- package/chunks/{chunk-QIZKCVM3.js → chunk-GHJM2C2T.js} +6 -8
- package/chunks/chunk-GOFAQQZA.js +132 -0
- package/chunks/{chunk-BCZFQXWK.js → chunk-GTM6IHBB.js} +2 -2
- package/chunks/{chunk-5ZF5XXTS.js → chunk-GVISB2OH.js} +2 -2
- package/chunks/{chunk-FNMZK765.js → chunk-H36SETQS.js} +1 -1
- package/chunks/{chunk-UBEPNVDI.js → chunk-H4346YW5.js} +28 -16
- package/chunks/{chunk-CQL64ESB.js → chunk-H4DSRWAS.js} +24 -13
- package/chunks/{chunk-YGF33UXG.js → chunk-H6MC6VQX.js} +222 -173
- package/chunks/{chunk-GZXCZHCT.js → chunk-I3G5JWBV.js} +1 -1
- package/chunks/{chunk-Y6AXW2OG.js → chunk-I5GNT6ZS.js} +7 -1
- package/chunks/{chunk-GEBV2JGB.js → chunk-I6FAHB4N.js} +1 -1
- package/chunks/{chunk-UPUG4GXM.js → chunk-I7JDGNG6.js} +3 -3
- package/chunks/{chunk-JHNRZMHI.js → chunk-II6WPWHY.js} +9 -9
- package/chunks/{chunk-B4AJNNOL.js → chunk-J26HHFI5.js} +1 -1
- package/chunks/{chunk-S3TWXGKA.js → chunk-JE7KQ2UP.js} +4 -2
- package/chunks/{chunk-ZHBO7WVX.js → chunk-JELIWHXD.js} +1 -1
- package/chunks/{chunk-3EFXSQCM.js → chunk-JRIDA5HF.js} +7 -7
- package/chunks/{chunk-TFRMVU6R.js → chunk-K4CGQN4Q.js} +1 -1
- package/chunks/{chunk-WUZ7H6DP.js → chunk-K5Q62CGR.js} +1 -1
- package/chunks/{chunk-JCW2R7WC.js → chunk-K623ENWT.js} +3 -79
- package/chunks/{chunk-T2NCM2ET.js → chunk-K6KS3LTN.js} +2 -749
- package/chunks/{chunk-TDL6LB4K.js → chunk-KG22G46Y.js} +22 -10
- package/chunks/{chunk-GATT5TKW.js → chunk-KKN2IE7Q.js} +1 -1
- package/chunks/{chunk-JMONIXMJ.js → chunk-KVUBYJDM.js} +2 -2
- package/chunks/{chunk-TBBV36Y4.js → chunk-KXSYDCP2.js} +4 -4
- package/chunks/{chunk-EIF3FXTB.js → chunk-LAPK3GLC.js} +121 -18
- package/chunks/chunk-LBOVL47Y.js +29 -0
- package/chunks/{chunk-U3E3UQAA.js → chunk-LBWNSLJK.js} +4 -4
- package/chunks/{chunk-S4WJVPZW.js → chunk-LL4U3BSH.js} +15 -7
- package/chunks/{chunk-657BH7VM.js → chunk-LRJWFR6L.js} +4 -4
- package/chunks/{chunk-PT722TDT.js → chunk-M2F5PLOW.js} +770 -125
- package/chunks/{chunk-3L2SPEBH.js → chunk-M744OFVE.js} +1 -1
- package/chunks/{chunk-VYOXCEPJ.js → chunk-MBKPUM5Y.js} +1 -1
- package/chunks/chunk-MISUEWB4.js +8749 -0
- package/chunks/{chunk-PONHVBRT.js → chunk-MOHAWIAW.js} +2 -2
- package/chunks/{chunk-HMRM2A3U.js → chunk-MSIVKDRC.js} +4 -4
- package/chunks/{record-artifact-XAMSFSW4.js → chunk-MYT7N6QH.js} +22 -7
- package/chunks/{chunk-X5WNMMIA.js → chunk-NGWYUZZO.js} +11510 -15137
- package/chunks/{chunk-PQNHRFJC.js → chunk-NYX53SV4.js} +0 -2
- package/chunks/{chunk-6RPMI2AB.js → chunk-NZB4NDJL.js} +10 -10
- package/chunks/{chunk-BGTQCTQW.js → chunk-O2ZYHG33.js} +6 -5
- package/chunks/chunk-O6GEWCJA.js +21 -0
- package/chunks/{chunk-JX27F6QS.js → chunk-OBAIHYFT.js} +1 -1
- package/chunks/{chunk-BPZKP57P.js → chunk-OCRM53TT.js} +3 -3
- package/chunks/{chunk-V7RNNPGC.js → chunk-P5Y23G2L.js} +18 -1
- package/chunks/{chunk-FTD6DP4T.js → chunk-PDDYAXL2.js} +5 -1
- package/chunks/{chunk-JSD33JG6.js → chunk-PGEGUNH5.js} +67 -10
- package/chunks/{chunk-A4COXFB3.js → chunk-PGP7Y3RQ.js} +5 -5
- package/chunks/{chunk-T3O2B4XO.js → chunk-PHODQP2V.js} +6 -6
- package/chunks/{chunk-BMFALVGQ.js → chunk-PXA5AWHY.js} +1 -1
- package/chunks/chunk-QL4TN4HS.js +59 -0
- package/chunks/{chunk-W4MIWP6M.js → chunk-QMBEW7EW.js} +2 -2
- package/chunks/{chunk-U4VTUMMK.js → chunk-QONSRAEV.js} +1 -1
- package/chunks/{chunk-LW3RFMG7.js → chunk-QYPT3QUD.js} +3 -3
- package/chunks/{chunk-TV64SXKD.js → chunk-RGJ4JWSU.js} +131 -48
- package/chunks/{chunk-75MIQ3LV.js → chunk-RPYYTL7E.js} +61 -13
- package/chunks/{chunk-52ZSWYEG.js → chunk-SK2UKB45.js} +1 -1
- package/chunks/{chunk-PLDQBIO6.js → chunk-SWEBEXPI.js} +1 -1
- package/chunks/chunk-T3CHYWJZ.js +758 -0
- package/chunks/{chunk-VCPIZRYH.js → chunk-TFFMATHX.js} +9 -7
- package/chunks/{chunk-J7OACQDE.js → chunk-TNVKFQXQ.js} +458 -97
- package/chunks/{chunk-A3NDJ5SB.js → chunk-TYERNYH4.js} +2 -2
- package/chunks/{chunk-GKX7E4CO.js → chunk-U25CMJYY.js} +1 -1
- package/chunks/{chunk-7XATOOE7.js → chunk-UH7Z7Y45.js} +1 -1
- package/chunks/{chunk-XFZYFU3I.js → chunk-UHQ3L6GC.js} +1 -1
- package/chunks/{chunk-GZ3RCT54.js → chunk-UHTJC7O3.js} +1 -1
- package/chunks/{chunk-XZC5VLBZ.js → chunk-UKZEXS6K.js} +6 -0
- package/chunks/{chunk-LO4ROVP4.js → chunk-UOFFZNXV.js} +111 -13
- package/chunks/{chunk-5YKDXHUY.js → chunk-URN76TKR.js} +2 -2
- package/chunks/{chunk-T4TXDL7G.js → chunk-UWLG4UCE.js} +132 -35
- package/chunks/{chunk-KAMYKP7E.js → chunk-UWSXFI6E.js} +1 -1
- package/chunks/{chunk-7BAU433D.js → chunk-VS3GXRNZ.js} +1198 -240
- package/chunks/{chunk-EJGJIBRS.js → chunk-VWF42XC6.js} +3 -3
- package/chunks/{chunk-RCUQIPTN.js → chunk-W7XZ3KP5.js} +1 -1
- package/chunks/{chunk-OCESJA77.js → chunk-WISQLM4Q.js} +1197 -1154
- package/chunks/{chunk-NOKIVHOL.js → chunk-WK4TJUEA.js} +1 -1
- package/chunks/{chunk-JFMA7Y5M.js → chunk-WP4HGHFG.js} +5 -5
- package/chunks/{chunk-4G2BISNC.js → chunk-XC2VAFVZ.js} +1 -1
- package/chunks/{chunk-2LKVPASC.js → chunk-XC656O42.js} +3 -3
- package/chunks/{chunk-5KTQXHPY.js → chunk-XCLLRKY5.js} +3 -3
- package/chunks/{chunk-HV26XH34.js → chunk-XFDPIC4P.js} +3 -3
- package/chunks/{chunk-JTV5K7NH.js → chunk-XSA5EKTJ.js} +1 -1
- package/chunks/{chunk-75GFAX4R.js → chunk-YAVY33G4.js} +1 -1
- package/chunks/{chunk-WBSMNTSV.js → chunk-YXEVDA66.js} +2 -2
- package/chunks/{chunk-7DXQIJID.js → chunk-ZRFJ75D7.js} +3 -3
- package/chunks/{chunk-XBYYDKAZ.js → chunk-ZTN6OA5J.js} +8 -7
- package/chunks/{computer-use-ZTIDHMMA.js → computer-use-Z4NCIIJN.js} +40 -35
- package/chunks/{config-utils-NYSXDMEQ.js → config-utils-64LM6OEQ.js} +4 -4
- package/chunks/{contextCommand-2PIEU37Z.js → contextCommand-HVM7XFCB.js} +43 -38
- package/chunks/{core-runtime-3XEYLQFK.js → core-runtime-NL3ZBHBU.js} +40 -35
- package/chunks/{create-sub-session-SBYUMSSS.js → create-sub-session-AM32K2HD.js} +2 -2
- package/chunks/{create-sub-session-R76FVXCI.js → create-sub-session-XHSCDYFU.js} +43 -38
- package/chunks/{cron-create-2QK6TCEC.js → cron-create-HPXYE6C5.js} +4 -4
- package/chunks/{cron-delete-FDCDFYMG.js → cron-delete-FPVNTKPK.js} +4 -4
- package/chunks/{cron-list-XN3WVBTP.js → cron-list-ZEI6PAAV.js} +4 -4
- package/chunks/{daemon-Q2AB5Z23.js → daemon-PCNCI5YU.js} +72 -3
- package/chunks/daemon-status-provider-XD23SNAM.js +94 -0
- package/chunks/{daemon-trust-policy-ILUDTLHD.js → daemon-trust-policy-NOHK7IW5.js} +46 -41
- package/chunks/{daemon-trust-policy-monitor-HS3PKKRO.js → daemon-trust-policy-monitor-ZBTSR333.js} +46 -41
- package/chunks/{de-SY6O76BF.js → de-A6TI4LBB.js} +46 -5
- package/chunks/{deferred-core-runtime-X4QV662U.js → deferred-core-runtime-JJBHKM2C.js} +40 -35
- package/chunks/{dist-HVRQ2CFL.js → dist-4LAMY2SK.js} +1180 -5
- package/chunks/{dist-DOLYHMXE.js → dist-4T4NCJFL.js} +2 -2
- package/chunks/dist-7KOL6OMD.js +13467 -0
- package/chunks/{dist-SSU66DM4.js → dist-BH76AT7N.js} +1 -1
- package/chunks/{dist-BSTVRPMT.js → dist-BXA3JXVQ.js} +541 -19
- package/chunks/{dist-SV7Q3AWJ.js → dist-OEEFI6UU.js} +12 -9
- package/chunks/{dist-YGBBMK3Z.js → dist-SMLVOWKV.js} +5 -4
- package/chunks/{dist-IXQEQWRG.js → dist-V2RK6S6Q.js} +1 -1
- package/chunks/{earlyInputCapture-XKLZT7ZD.js → earlyInputCapture-KLAZDAIP.js} +41 -36
- package/chunks/{edit-HHGIOTQ2.js → edit-YQZWCISX.js} +40 -35
- package/chunks/{en-NBK3JKCE.js → en-RESOFG55.js} +46 -5
- package/chunks/{enter-worktree-ZN7PUQ46.js → enter-worktree-WLVWI3FP.js} +40 -35
- package/chunks/{enterPlanMode-EIFIDSIV.js → enterPlanMode-6RYXFQUD.js} +40 -35
- package/chunks/{environment-XXQ75D2Q.js → environment-DXJTXSVT.js} +43 -38
- package/chunks/{errors-4GMVU7CK.js → errors-XGAGG2S2.js} +43 -38
- package/chunks/{exit-worktree-GXMI4ATY.js → exit-worktree-C4276VPP.js} +40 -35
- package/chunks/{exitPlanMode-34UVY7M6.js → exitPlanMode-MM5HIRUF.js} +40 -35
- package/chunks/{fast-path-VPIVA7L6.js → fast-path-PIXYOHCH.js} +6 -2
- package/chunks/{fr-4KG5V7UT.js → fr-QF7RI5ZE.js} +46 -5
- package/chunks/{gemini-4BWIK4WD.js → gemini-43RLVUNP.js} +158 -96
- package/chunks/{geminiContentGenerator-3XVV5MSS.js → geminiContentGenerator-PNQ4TSID.js} +6 -6
- package/chunks/{glob-TZ2ABCJG.js → glob-ZMBQKAU5.js} +40 -35
- package/chunks/goal-tools-Y767F7LZ.js +335 -0
- package/chunks/{grep-BEF463NA.js → grep-HSV37W2Q.js} +40 -35
- package/chunks/handleAutoUpdate-QDHZPBAY.js +85 -0
- package/chunks/{i18n-FMM5FDXR.js → i18n-ME22A6RN.js} +42 -37
- package/chunks/{image-gen-HHVLF7HS.js → image-gen-IFC7ZWSB.js} +9 -9
- package/chunks/{initializer-625TIAIO.js → initializer-J7H2CHVB.js} +47 -42
- package/chunks/{installationInfo-6AM4I2Y3.js → installationInfo-R7FXPQN5.js} +41 -36
- package/chunks/{ja-F3GSQXMF.js → ja-URQESVGW.js} +46 -5
- package/chunks/{keychain-token-storage-72IYCAZV.js → keychain-token-storage-7BT4TQ2A.js} +2 -2
- package/chunks/{kittyProtocolDetector-MBRTDRBK.js → kittyProtocolDetector-BFLAKYXH.js} +1 -1
- package/chunks/list-OYDIBA4N.js +93 -0
- package/chunks/{list-agents-R6KDXQR3.js → list-agents-GATIBBQQ.js} +2 -2
- package/chunks/{loadedSettingsAdapter-SPUTNKAV.js → loadedSettingsAdapter-OK6GK2GE.js} +46 -41
- package/chunks/{loggingContentGenerator-LKOF7XI7.js → loggingContentGenerator-U4ZEG4GL.js} +53 -38
- package/chunks/{loop-wakeup-3IQKCYAH.js → loop-wakeup-3DZMQQQQ.js} +13 -6
- package/chunks/{ls-DKZ37A7N.js → ls-7F4GHXIH.js} +4 -4
- package/chunks/{lsp-QNWN7KN3.js → lsp-6FEHVBWI.js} +2 -2
- package/chunks/{managed-npm-update-ACQGGIN5.js → managed-npm-update-PGKAJLLO.js} +43 -38
- package/chunks/mcp-S4DXJD2G.js +87 -0
- package/chunks/{monitor-DF52UVHI.js → monitor-E5ZFMT74.js} +40 -35
- package/chunks/nonInteractiveCli-HNOHKEPE.js +149 -0
- package/chunks/{notebook-edit-FCWS4XVN.js → notebook-edit-6QDN6VZJ.js} +40 -35
- package/chunks/{openaiContentGenerator-7LDK3DCJ.js → openaiContentGenerator-3NLB2C5O.js} +19 -19
- package/chunks/{pidfile-6ERW3DF4.js → pidfile-ZMOIUGG6.js} +41 -36
- package/chunks/{processUtils-COKZAMUP.js → processUtils-E4QGQVWW.js} +2 -2
- package/chunks/{pt-EQ33KWEN.js → pt-EEEQXRUI.js} +46 -5
- package/chunks/{qwenContentGenerator-TKWUMR7N.js → qwenContentGenerator-2LFRWJTM.js} +46 -41
- package/chunks/{qwenOAuth2-7HMU47SF.js → qwenOAuth2-N32BUQDC.js} +8 -8
- package/chunks/{read-file-X6DRC574.js → read-file-GLDCWZBG.js} +11 -11
- package/chunks/{read-mcp-resource-GFTWYXMK.js → read-mcp-resource-AFS3UKZO.js} +2 -2
- package/chunks/record-artifact-ECZSCEG5.js +21 -0
- package/chunks/{resumeHistoryUtils-PFPM2GWM.js → resumeHistoryUtils-F5BE5QDW.js} +48 -43
- package/chunks/ripGrep-T23Y4AGY.js +77 -0
- package/chunks/{ru-7OZAUKGG.js → ru-WGZDYQAB.js} +46 -5
- package/chunks/{run-qwen-serve-TSTCO4XE.js → run-qwen-serve-TI2HGLLU.js} +290 -75
- package/chunks/{runtime-DAUPSUKI.js → runtime-WCWM3DO7.js} +53 -46
- package/chunks/{scheduler-KMADMT26.js → scheduler-2QZO5AV5.js} +40 -35
- package/chunks/{sdk-exporters-http-WO556XNU.js → sdk-exporters-http-IKNWQJNV.js} +3 -3
- package/chunks/{sdk-impl-LPAVACSF.js → sdk-impl-7CUUMQDB.js} +3 -3
- package/chunks/{send-message-SAWK4DZX.js → send-message-X7G2JSII.js} +6 -11
- package/chunks/{serve-NNRWS6F4.js → serve-DZOMYUFU.js} +46 -41
- package/chunks/{server-WEH7DVCH.js → server-N4AJRKIQ.js} +2269 -1016
- package/chunks/{session-WXC56V2I.js → session-GS6AKMN7.js} +151 -86
- package/chunks/{settings-DJDXFDZ3.js → settings-CUN3SELH.js} +50 -45
- package/chunks/{shell-JN5VRQXD.js → shell-NGBFVXC5.js} +40 -35
- package/chunks/{skill-SGXPKJCS.js → skill-SC2BSO75.js} +30 -16
- package/chunks/{skill-settings-VJ5PDMZI.js → skill-settings-XVPCPW5K.js} +45 -40
- package/chunks/{spawnChannel-ETMJW7YX.js → spawnChannel-RILO4YY3.js} +42 -37
- package/chunks/{standalone-update-MK3Z7KBI.js → standalone-update-TMLT6LVJ.js} +43 -38
- package/chunks/{startInteractiveUI-ZCGIXPGT.js → startInteractiveUI-J45WOEOU.js} +883 -1112
- package/chunks/{syntheticOutput-355CB6CJ.js → syntheticOutput-FHRY3BPQ.js} +3 -3
- package/chunks/{task-create-INGWNUG4.js → task-create-LAQXBIHC.js} +11 -10
- package/chunks/{task-list-5XNNGTF4.js → task-list-V6K5DRDH.js} +6 -6
- package/chunks/{task-stop-4ROAOBXH.js → task-stop-LQXE52L6.js} +2 -2
- package/chunks/{task-update-CRK5VWWZ.js → task-update-NXRCXSPB.js} +11 -10
- package/chunks/{team-create-QQGAJG7P.js → team-create-W3EVWCTA.js} +40 -35
- package/chunks/{team-delete-S2RCXA4P.js → team-delete-Z4KGO7RC.js} +6 -6
- package/chunks/{team-plan-approval-RT7Q5R6O.js → team-plan-approval-URYVKJF4.js} +40 -35
- package/chunks/theme-manager-CUAMS2NI.js +81 -0
- package/chunks/{todoWrite-7WM3VDMY.js → todoWrite-OFIZDI7P.js} +32 -4
- package/chunks/{tool-search-Z3Z4AYKP.js → tool-search-DCICFL32.js} +15 -14
- package/chunks/total-session-admission-3ZTAXVUK.js +89 -0
- package/chunks/{trustedFolders-X2JEIO57.js → trustedFolders-EVCN36O5.js} +42 -37
- package/chunks/{update-relaunch-VWNPYDIP.js → update-relaunch-XLW46RHQ.js} +5 -5
- package/chunks/{updateCheck-KAQH67DV.js → updateCheck-ZHVXDAIH.js} +44 -39
- package/chunks/{useAutoAcceptIndicator-JH6BCF7S.js → useAutoAcceptIndicator-ZGD6BJSP.js} +50 -45
- package/chunks/{validateNonInterActiveAuth-GIUJ2UFS.js → validateNonInterActiveAuth-R3BAQFDY.js} +88 -83
- package/chunks/{version-BGLYIJUY.js → version-PMWREGCG.js} +1 -1
- package/chunks/{web-fetch-OTDU4VQF.js → web-fetch-PGN27SGF.js} +14 -14
- package/chunks/{web-search-FP6SIHPR.js → web-search-KW4UNMRE.js} +8 -8
- package/chunks/{workflow-YCIVBYSB.js → workflow-SN3TJBTJ.js} +363 -310
- package/chunks/workspace-providers-status-O3HUZGGR.js +90 -0
- package/chunks/{workspace-registration-store-OTMS3H4C.js → workspace-registration-store-M3FJ74RS.js} +2 -2
- package/chunks/{workspace-registry-O63R6IZ4.js → workspace-registry-U7ISW23N.js} +47 -42
- package/chunks/{workspace-service-M6LLHKJ5.js → workspace-service-VH6IWADT.js} +53 -48
- package/chunks/{workspace-skills-status-C2V7BAIS.js → workspace-skills-status-XANARSZS.js} +48 -43
- package/chunks/{workspace-trust-reconciler-IBUPOUJN.js → workspace-trust-reconciler-35EFR4GC.js} +53 -48
- package/chunks/write-file-NCRSGUDT.js +79 -0
- package/chunks/{zh-H3YDK5QW.js → zh-OHX23Q44.js} +43 -5
- package/chunks/{zh-TW-JYCP7XUA.js → zh-TW-4G7YKDAQ.js} +43 -5
- package/chunks/zoom-image-X7CIADYC.js +224 -0
- package/cli.js +55 -48
- package/locales/ca.js +60 -4
- package/locales/de.js +62 -4
- package/locales/en.js +59 -4
- package/locales/fr.js +64 -4
- package/locales/ja.js +61 -4
- package/locales/pt.js +60 -4
- package/locales/ru.js +63 -4
- package/locales/zh-TW.js +52 -4
- package/locales/zh.js +52 -4
- package/package.json +3 -3
- package/web-shell/assets/{arc-75-Wdeo3.js → arc-CaMTqKio.js} +1 -1
- package/web-shell/assets/{architectureDiagram-3BPJPVTR-FKeXQbyP.js → architectureDiagram-3BPJPVTR-Bjxztij2.js} +1 -1
- package/web-shell/assets/{blockDiagram-GPEHLZMM-CY0vc-A3.js → blockDiagram-GPEHLZMM-BYJzeHi9.js} +1 -1
- package/web-shell/assets/{c4Diagram-AAUBKEIU-CNP-A-8u.js → c4Diagram-AAUBKEIU-fYAa-Eil.js} +1 -1
- package/web-shell/assets/channel-LEZei0-5.js +1 -0
- package/web-shell/assets/{chunk-2J33WTMH-GybS4Gii.js → chunk-2J33WTMH-B1OTlTml.js} +1 -1
- package/web-shell/assets/{chunk-4BX2VUAB-02H91V8v.js → chunk-4BX2VUAB-DNj4uy6k.js} +1 -1
- package/web-shell/assets/{chunk-55IACEB6-D3M-2VT6.js → chunk-55IACEB6-DAqNmg3c.js} +1 -1
- package/web-shell/assets/{chunk-727SXJPM-CCu29u4H.js → chunk-727SXJPM-BwB4ddxE.js} +1 -1
- package/web-shell/assets/{chunk-AQP2D5EJ-CaFKWgrn.js → chunk-AQP2D5EJ-DmHR_UZs.js} +1 -1
- package/web-shell/assets/{chunk-FMBD7UC4-ZZpPqIwQ.js → chunk-FMBD7UC4-BlfOXumo.js} +1 -1
- package/web-shell/assets/{chunk-ND2GUHAM-D22DqGs8.js → chunk-ND2GUHAM-BKogiSy7.js} +1 -1
- package/web-shell/assets/{chunk-QZHKN3VN-Bu85S0fw.js → chunk-QZHKN3VN-DEclVrOF.js} +1 -1
- package/web-shell/assets/classDiagram-4FO5ZUOK-BiaRhfvf.js +1 -0
- package/web-shell/assets/classDiagram-v2-Q7XG4LA2-BiaRhfvf.js +1 -0
- package/web-shell/assets/{cose-bilkent-S5V4N54A-f1CK1Gwe.js → cose-bilkent-S5V4N54A-CwtS21WT.js} +1 -1
- package/web-shell/assets/{dagre-BM42HDAG-D0Ow8F_n.js → dagre-BM42HDAG-BAAIlB4p.js} +1 -1
- package/web-shell/assets/{diagram-2AECGRRQ-BPrmTWp8.js → diagram-2AECGRRQ-ChljtF_V.js} +1 -1
- package/web-shell/assets/{diagram-5GNKFQAL-HccuFAzy.js → diagram-5GNKFQAL-BIXVd31-.js} +1 -1
- package/web-shell/assets/{diagram-KO2AKTUF-BrS76mbA.js → diagram-KO2AKTUF-BEiBaS15.js} +1 -1
- package/web-shell/assets/{diagram-LMA3HP47-V7T9lU-5.js → diagram-LMA3HP47-C-g4tWKM.js} +1 -1
- package/web-shell/assets/{diagram-OG6HWLK6-DKidyJMR.js → diagram-OG6HWLK6-CNCCbNQG.js} +1 -1
- package/web-shell/assets/{erDiagram-TEJ5UH35-DBadZIkp.js → erDiagram-TEJ5UH35-v8ysnsdI.js} +1 -1
- package/web-shell/assets/{flowDiagram-I6XJVG4X-BymfqdNJ.js → flowDiagram-I6XJVG4X-LKVlLjwA.js} +1 -1
- package/web-shell/assets/{ganttDiagram-6RSMTGT7-DOw340jf.js → ganttDiagram-6RSMTGT7-DA5MrKYG.js} +1 -1
- package/web-shell/assets/{gitGraphDiagram-PVQCEYII-_8EiD8sl.js → gitGraphDiagram-PVQCEYII-Cyg5fe6d.js} +1 -1
- package/web-shell/assets/index-BgOcEaVt.js +1756 -0
- package/web-shell/assets/index-C2GE3DAF.js +74 -0
- package/web-shell/assets/{index-CKIadvET.js → index-CKdUkVVS.js} +1 -1
- package/web-shell/assets/index-DA5Lvscv.css +5 -0
- package/web-shell/assets/{infoDiagram-5YYISTIA-D61KYQBu.js → infoDiagram-5YYISTIA-SLsfu3Qd.js} +1 -1
- package/web-shell/assets/{ishikawaDiagram-YF4QCWOH-CsiXSpNx.js → ishikawaDiagram-YF4QCWOH-CmHOmTNx.js} +1 -1
- package/web-shell/assets/{journeyDiagram-JHISSGLW-Sdfionyh.js → journeyDiagram-JHISSGLW-C3gM_HFQ.js} +1 -1
- package/web-shell/assets/{kanban-definition-UN3LZRKU-C3WI3Cnl.js → kanban-definition-UN3LZRKU-BbHD7duM.js} +1 -1
- package/web-shell/assets/{linear-Dpigcc62.js → linear-CSBvm435.js} +1 -1
- package/web-shell/assets/{mermaid.core-Ct97pqgW.js → mermaid.core-CPMw15lU.js} +5 -5
- package/web-shell/assets/{mindmap-definition-RKZ34NQL-BzeaN0rB.js → mindmap-definition-RKZ34NQL-C_tNqXQW.js} +1 -1
- package/web-shell/assets/{pieDiagram-4H26LBE5-CvjgcbVD.js → pieDiagram-4H26LBE5-DH_N-8yY.js} +1 -1
- package/web-shell/assets/{quadrantDiagram-W4KKPZXB-BUzgTNdH.js → quadrantDiagram-W4KKPZXB-CRbS8UkN.js} +1 -1
- package/web-shell/assets/{requirementDiagram-4Y6WPE33-B7zKlgUQ.js → requirementDiagram-4Y6WPE33-DJgdZPZn.js} +1 -1
- package/web-shell/assets/{sankeyDiagram-5OEKKPKP-Bb9CQgrT.js → sankeyDiagram-5OEKKPKP-vhL1y5zx.js} +1 -1
- package/web-shell/assets/{sequenceDiagram-3UESZ5HK-DJ6V7itG.js → sequenceDiagram-3UESZ5HK-UQthhFwd.js} +1 -1
- package/web-shell/assets/{stateDiagram-AJRCARHV-IImflERY.js → stateDiagram-AJRCARHV-CAywEm20.js} +1 -1
- package/web-shell/assets/stateDiagram-v2-BHNVJYJU-lfJQHw-7.js +1 -0
- package/web-shell/assets/{timeline-definition-PNZ67QCA-6Q_uWHKh.js → timeline-definition-PNZ67QCA-CLO8b3FD.js} +1 -1
- package/web-shell/assets/{vennDiagram-CIIHVFJN-TmyKyjwv.js → vennDiagram-CIIHVFJN-BNAAh0Mu.js} +1 -1
- package/web-shell/assets/{wardley-L42UT6IY-CRh9uiPv.js → wardley-L42UT6IY-CUY7bLpN.js} +1 -1
- package/web-shell/assets/{wardleyDiagram-YWT4CUSO-59TKAW8w.js → wardleyDiagram-YWT4CUSO-CSg_ORdW.js} +1 -1
- package/web-shell/assets/{xychartDiagram-2RQKCTM6-GCSUIK2L.js → xychartDiagram-2RQKCTM6-BjffV208.js} +1 -1
- package/web-shell/index.html +2 -2
- package/chunks/agent-headless-NO4Y2HOE.js +0 -74
- package/chunks/chunk-6QIGFD5W.js +0 -82
- package/chunks/chunk-HGT6JR3U.js +0 -177
- package/chunks/daemon-status-provider-3XJI6CAL.js +0 -89
- package/chunks/handleAutoUpdate-L6ERF36Y.js +0 -80
- package/chunks/list-L2GA674Y.js +0 -88
- package/chunks/mcp-SZLHKFJW.js +0 -82
- package/chunks/nonInteractiveCli-5T7KYKLK.js +0 -144
- package/chunks/ripGrep-OWV2IVJC.js +0 -72
- package/chunks/theme-manager-EEWIQJ7J.js +0 -76
- package/chunks/total-session-admission-44JKRWQD.js +0 -84
- package/chunks/workspace-providers-status-S35YAIUS.js +0 -85
- package/chunks/write-file-3BZC3EAE.js +0 -72
- package/chunks/zoom-image-TZ6S2O57.js +0 -351
- package/web-shell/assets/channel-DPYMT76A.js +0 -1
- package/web-shell/assets/classDiagram-4FO5ZUOK--JstsIgL.js +0 -1
- package/web-shell/assets/classDiagram-v2-Q7XG4LA2--JstsIgL.js +0 -1
- package/web-shell/assets/index-D1eXNRHe.js +0 -1389
- package/web-shell/assets/index-DVLD4CQq.css +0 -5
- package/web-shell/assets/stateDiagram-v2-BHNVJYJU-CYI_YoNR.js +0 -1
|
@@ -2,19 +2,16 @@
|
|
|
2
2
|
"use strict";
|
|
3
3
|
import {
|
|
4
4
|
listCommand
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-433VD3HX.js";
|
|
6
6
|
import {
|
|
7
7
|
getErrorMessage as getErrorMessage2
|
|
8
|
-
} from "./chunk-
|
|
9
|
-
import {
|
|
10
|
-
serveCommand
|
|
11
|
-
} from "./chunk-S4WJVPZW.js";
|
|
8
|
+
} from "./chunk-PHODQP2V.js";
|
|
12
9
|
import {
|
|
13
10
|
ObservedChannelContactStore
|
|
14
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-DYA25Y7U.js";
|
|
15
12
|
import {
|
|
16
13
|
escapeAnsiCtrlCodes
|
|
17
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-4NFY2S7N.js";
|
|
18
15
|
import {
|
|
19
16
|
stringWidth
|
|
20
17
|
} from "./chunk-2MIN6GRR.js";
|
|
@@ -24,14 +21,17 @@ import {
|
|
|
24
21
|
import {
|
|
25
22
|
isLoopbackBind
|
|
26
23
|
} from "./chunk-RXFQM6FQ.js";
|
|
24
|
+
import {
|
|
25
|
+
serveCommand
|
|
26
|
+
} from "./chunk-LL4U3BSH.js";
|
|
27
27
|
import {
|
|
28
28
|
resolvePath
|
|
29
|
-
} from "./chunk-
|
|
29
|
+
} from "./chunk-JELIWHXD.js";
|
|
30
30
|
import {
|
|
31
31
|
collectProviderModelsForProtocol,
|
|
32
32
|
getAuthTypeFromEnv,
|
|
33
33
|
resolveCliGenerationConfig
|
|
34
|
-
} from "./chunk-
|
|
34
|
+
} from "./chunk-AYB4HSBI.js";
|
|
35
35
|
import {
|
|
36
36
|
resolveSkillSettings
|
|
37
37
|
} from "./chunk-Z4X5MTRT.js";
|
|
@@ -39,6 +39,7 @@ import {
|
|
|
39
39
|
channelLoopPath,
|
|
40
40
|
createChannel,
|
|
41
41
|
daemonChannelLoopPath,
|
|
42
|
+
daemonChannelStateDir,
|
|
42
43
|
daemonObservedContactsPath,
|
|
43
44
|
daemonSessionRoutesPath,
|
|
44
45
|
loadChannelsConfig,
|
|
@@ -50,23 +51,23 @@ import {
|
|
|
50
51
|
registerToolCallDispatch,
|
|
51
52
|
selectFirstModel,
|
|
52
53
|
sessionsPath
|
|
53
|
-
} from "./chunk-
|
|
54
|
+
} from "./chunk-3WXMXT7C.js";
|
|
54
55
|
import {
|
|
55
56
|
getExtensionManager,
|
|
56
57
|
requestChoicePluginNonInteractive,
|
|
57
58
|
requestConsentNonInteractive,
|
|
58
59
|
requestConsentOrFail,
|
|
59
60
|
resolveExtensionCommandScope
|
|
60
|
-
} from "./chunk-
|
|
61
|
+
} from "./chunk-BKUN5QHP.js";
|
|
61
62
|
import {
|
|
62
63
|
parseChannelConfig
|
|
63
|
-
} from "./chunk-
|
|
64
|
+
} from "./chunk-2CTKGIFR.js";
|
|
64
65
|
import {
|
|
65
66
|
findCliEntryPath
|
|
66
67
|
} from "./chunk-V6WHFGST.js";
|
|
67
68
|
import {
|
|
68
69
|
canonicalizeWorkspace
|
|
69
|
-
} from "./chunk-
|
|
70
|
+
} from "./chunk-6PLDPT2C.js";
|
|
70
71
|
import {
|
|
71
72
|
ChannelLoopMcpWorkerHost
|
|
72
73
|
} from "./chunk-FYJ7W2PI.js";
|
|
@@ -87,11 +88,11 @@ import {
|
|
|
87
88
|
isChannelDeliveryMessage,
|
|
88
89
|
isChannelStartupReportAckMessage,
|
|
89
90
|
isChannelWebhookTaskMessage
|
|
90
|
-
} from "./chunk-
|
|
91
|
+
} from "./chunk-QONSRAEV.js";
|
|
91
92
|
import {
|
|
92
93
|
normalizeWorkerDiagnostic,
|
|
93
94
|
sanitizeWorkerDiagnostic
|
|
94
|
-
} from "./chunk-
|
|
95
|
+
} from "./chunk-UHTJC7O3.js";
|
|
95
96
|
import {
|
|
96
97
|
normalizeServeChannelSelection
|
|
97
98
|
} from "./chunk-ALMR3E6Q.js";
|
|
@@ -104,14 +105,14 @@ import {
|
|
|
104
105
|
signalService,
|
|
105
106
|
waitForExit,
|
|
106
107
|
writeServiceInfo
|
|
107
|
-
} from "./chunk-
|
|
108
|
+
} from "./chunk-XC2VAFVZ.js";
|
|
108
109
|
import {
|
|
109
110
|
DEFAULT_BASE_URL,
|
|
110
111
|
buildHeaders,
|
|
111
112
|
clearAccount,
|
|
112
113
|
loadAccount,
|
|
113
114
|
saveAccount
|
|
114
|
-
} from "./chunk-
|
|
115
|
+
} from "./chunk-I6FAHB4N.js";
|
|
115
116
|
import {
|
|
116
117
|
AcpBridge,
|
|
117
118
|
ChannelLoopScheduler,
|
|
@@ -122,45 +123,41 @@ import {
|
|
|
122
123
|
isChannelProactiveDeliveryError,
|
|
123
124
|
sanitizeLogText,
|
|
124
125
|
sanitizePromptText
|
|
125
|
-
} from "./chunk-
|
|
126
|
+
} from "./chunk-GB3AB7TR.js";
|
|
126
127
|
import {
|
|
127
128
|
assembleMcpServers,
|
|
128
129
|
getPendingGatedMcpServers,
|
|
129
130
|
mcpCommand
|
|
130
|
-
} from "./chunk-
|
|
131
|
+
} from "./chunk-NZB4NDJL.js";
|
|
131
132
|
import {
|
|
132
133
|
loadSettings
|
|
133
|
-
} from "./chunk-
|
|
134
|
+
} from "./chunk-LAPK3GLC.js";
|
|
134
135
|
import {
|
|
135
136
|
detectSystemLanguage,
|
|
136
137
|
getCurrentLanguage,
|
|
137
138
|
initializeI18n,
|
|
138
139
|
resolveLanguageSetting,
|
|
139
140
|
t
|
|
140
|
-
} from "./chunk-
|
|
141
|
+
} from "./chunk-CHCLO3M7.js";
|
|
141
142
|
import {
|
|
142
143
|
loadEnvironment
|
|
143
|
-
} from "./chunk-
|
|
144
|
+
} from "./chunk-AQEWCKX4.js";
|
|
145
|
+
import {
|
|
146
|
+
isWorkspaceTrusted
|
|
147
|
+
} from "./chunk-434YCHSV.js";
|
|
148
|
+
import {
|
|
149
|
+
require_strip_json_comments
|
|
150
|
+
} from "./chunk-ALGGS7UH.js";
|
|
144
151
|
import {
|
|
145
152
|
hideBin,
|
|
146
153
|
yargs_default
|
|
147
154
|
} from "./chunk-XFSFZCM5.js";
|
|
148
155
|
import {
|
|
149
156
|
getCliVersion
|
|
150
|
-
} from "./chunk-
|
|
157
|
+
} from "./chunk-MBKPUM5Y.js";
|
|
151
158
|
import {
|
|
152
159
|
getPackageJson
|
|
153
160
|
} from "./chunk-VJNBRRZG.js";
|
|
154
|
-
import {
|
|
155
|
-
isWorkspaceTrusted
|
|
156
|
-
} from "./chunk-Q43KPN7X.js";
|
|
157
|
-
import {
|
|
158
|
-
require_strip_json_comments
|
|
159
|
-
} from "./chunk-ALGGS7UH.js";
|
|
160
|
-
import {
|
|
161
|
-
writeStderrLine,
|
|
162
|
-
writeStdoutLine
|
|
163
|
-
} from "./chunk-OWAK7LMW.js";
|
|
164
161
|
import {
|
|
165
162
|
Config,
|
|
166
163
|
DEFAULT_TRUNCATE_TOOL_OUTPUT_THRESHOLD,
|
|
@@ -194,7 +191,7 @@ import {
|
|
|
194
191
|
unquoteCStylePath,
|
|
195
192
|
updateChannelMemoryEntry,
|
|
196
193
|
updateSetting
|
|
197
|
-
} from "./chunk-
|
|
194
|
+
} from "./chunk-NGWYUZZO.js";
|
|
198
195
|
import {
|
|
199
196
|
nextFireTime,
|
|
200
197
|
parseCron
|
|
@@ -202,27 +199,27 @@ import {
|
|
|
202
199
|
import {
|
|
203
200
|
parseBooleanEnvFlag,
|
|
204
201
|
resolveTelemetrySettings
|
|
205
|
-
} from "./chunk-
|
|
202
|
+
} from "./chunk-RPYYTL7E.js";
|
|
206
203
|
import {
|
|
207
204
|
getAllGeminiMdFilenames,
|
|
208
205
|
setGeminiMdFilename
|
|
209
|
-
} from "./chunk-
|
|
206
|
+
} from "./chunk-M2F5PLOW.js";
|
|
210
207
|
import {
|
|
211
208
|
SchemaValidator,
|
|
212
209
|
ToolNames
|
|
213
|
-
} from "./chunk-
|
|
210
|
+
} from "./chunk-I5GNT6ZS.js";
|
|
214
211
|
import {
|
|
215
212
|
DEFAULT_QWEN_EMBEDDING_MODEL
|
|
216
|
-
} from "./chunk-
|
|
213
|
+
} from "./chunk-TFFMATHX.js";
|
|
217
214
|
import {
|
|
218
215
|
isTlsVerificationDisabled
|
|
219
|
-
} from "./chunk-
|
|
216
|
+
} from "./chunk-BFHXDAR7.js";
|
|
220
217
|
import {
|
|
221
218
|
atomicWriteFileSync
|
|
222
|
-
} from "./chunk-
|
|
219
|
+
} from "./chunk-UH7Z7Y45.js";
|
|
223
220
|
import {
|
|
224
221
|
recordChannelMemoryRecallMetrics
|
|
225
|
-
} from "./chunk-
|
|
222
|
+
} from "./chunk-O2ZYHG33.js";
|
|
226
223
|
import {
|
|
227
224
|
FatalConfigError,
|
|
228
225
|
FatalSandboxError,
|
|
@@ -230,7 +227,12 @@ import {
|
|
|
230
227
|
createDebugLogger,
|
|
231
228
|
getErrorMessage,
|
|
232
229
|
isNodeError
|
|
233
|
-
} from "./chunk-
|
|
230
|
+
} from "./chunk-3RXUYQJI.js";
|
|
231
|
+
import {
|
|
232
|
+
writeStderrLine,
|
|
233
|
+
writeStderrLineSafe,
|
|
234
|
+
writeStdoutLine
|
|
235
|
+
} from "./chunk-OWAK7LMW.js";
|
|
234
236
|
import {
|
|
235
237
|
init_esbuild_shims
|
|
236
238
|
} from "./chunk-5O2XNYP6.js";
|
|
@@ -363,10 +365,10 @@ var require_command_exists = __commonJS({
|
|
|
363
365
|
module.exports = /* @__PURE__ */ __name(function commandExists2(commandName, callback) {
|
|
364
366
|
var cleanedCommandName = cleanInput(commandName);
|
|
365
367
|
if (!callback && typeof Promise !== "undefined") {
|
|
366
|
-
return new Promise(function(
|
|
368
|
+
return new Promise(function(resolve15, reject) {
|
|
367
369
|
commandExists2(commandName, function(error, output) {
|
|
368
370
|
if (output) {
|
|
369
|
-
|
|
371
|
+
resolve15(commandName);
|
|
370
372
|
} else {
|
|
371
373
|
reject(error);
|
|
372
374
|
}
|
|
@@ -2183,6 +2185,7 @@ __name(isChannelCronEnabled, "isChannelCronEnabled");
|
|
|
2183
2185
|
var MAX_CRASH_RESTARTS = 3;
|
|
2184
2186
|
var CRASH_WINDOW_MS = 5 * 60 * 1e3;
|
|
2185
2187
|
var RESTART_DELAY_MS = 3e3;
|
|
2188
|
+
var BRIDGE_SESSION_RESTORE_TIMEOUT_MS = 60 * 1e3;
|
|
2186
2189
|
function isFileExistsError(err) {
|
|
2187
2190
|
return typeof err === "object" && err !== null && err.code === "EEXIST";
|
|
2188
2191
|
}
|
|
@@ -2238,6 +2241,134 @@ function cleanupStartedChannels(channels, bridge, router) {
|
|
|
2238
2241
|
}
|
|
2239
2242
|
}
|
|
2240
2243
|
__name(cleanupStartedChannels, "cleanupStartedChannels");
|
|
2244
|
+
function createBridgeReadinessGate() {
|
|
2245
|
+
let pending;
|
|
2246
|
+
let releasePending;
|
|
2247
|
+
return {
|
|
2248
|
+
current: /* @__PURE__ */ __name(() => pending, "current"),
|
|
2249
|
+
block: /* @__PURE__ */ __name(() => {
|
|
2250
|
+
if (pending) return;
|
|
2251
|
+
pending = new Promise((resolve15) => {
|
|
2252
|
+
releasePending = resolve15;
|
|
2253
|
+
});
|
|
2254
|
+
}, "block"),
|
|
2255
|
+
release: /* @__PURE__ */ __name(() => {
|
|
2256
|
+
const release = releasePending;
|
|
2257
|
+
pending = void 0;
|
|
2258
|
+
releasePending = void 0;
|
|
2259
|
+
release?.();
|
|
2260
|
+
}, "release")
|
|
2261
|
+
};
|
|
2262
|
+
}
|
|
2263
|
+
__name(createBridgeReadinessGate, "createBridgeReadinessGate");
|
|
2264
|
+
async function restoreBridgeSessions(router) {
|
|
2265
|
+
let timeout;
|
|
2266
|
+
const expired = new Promise((_, reject) => {
|
|
2267
|
+
timeout = setTimeout(
|
|
2268
|
+
() => reject(
|
|
2269
|
+
new Error(
|
|
2270
|
+
`Session restore timed out after ${BRIDGE_SESSION_RESTORE_TIMEOUT_MS}ms`
|
|
2271
|
+
)
|
|
2272
|
+
),
|
|
2273
|
+
BRIDGE_SESSION_RESTORE_TIMEOUT_MS
|
|
2274
|
+
);
|
|
2275
|
+
timeout.unref?.();
|
|
2276
|
+
});
|
|
2277
|
+
try {
|
|
2278
|
+
return await Promise.race([router.restoreSessions(), expired]);
|
|
2279
|
+
} finally {
|
|
2280
|
+
clearTimeout(timeout);
|
|
2281
|
+
}
|
|
2282
|
+
}
|
|
2283
|
+
__name(restoreBridgeSessions, "restoreBridgeSessions");
|
|
2284
|
+
function createBridgeRecovery(options) {
|
|
2285
|
+
const {
|
|
2286
|
+
bridgeOpts,
|
|
2287
|
+
router,
|
|
2288
|
+
channels,
|
|
2289
|
+
scheduler,
|
|
2290
|
+
bridgeReadiness,
|
|
2291
|
+
isShuttingDown,
|
|
2292
|
+
getBridge,
|
|
2293
|
+
setBridge
|
|
2294
|
+
} = options;
|
|
2295
|
+
const crashTimestamps = [];
|
|
2296
|
+
let recoveryTask;
|
|
2297
|
+
let recoveryRequested = false;
|
|
2298
|
+
let recoverySourceBridge;
|
|
2299
|
+
const attachDisconnectHandler = /* @__PURE__ */ __name((failedBridge) => {
|
|
2300
|
+
failedBridge.on("disconnected", () => {
|
|
2301
|
+
if (isShuttingDown() || failedBridge !== getBridge()) return;
|
|
2302
|
+
if (recoveryTask) {
|
|
2303
|
+
if (failedBridge !== recoverySourceBridge) recoveryRequested = true;
|
|
2304
|
+
return;
|
|
2305
|
+
}
|
|
2306
|
+
recoverBridge();
|
|
2307
|
+
});
|
|
2308
|
+
}, "attachDisconnectHandler");
|
|
2309
|
+
const recoverBridge = /* @__PURE__ */ __name(() => {
|
|
2310
|
+
bridgeReadiness.block();
|
|
2311
|
+
scheduler?.markBridgeRecovery();
|
|
2312
|
+
const task = (async () => {
|
|
2313
|
+
do {
|
|
2314
|
+
recoveryRequested = false;
|
|
2315
|
+
recoverySourceBridge = getBridge();
|
|
2316
|
+
const now = Date.now();
|
|
2317
|
+
crashTimestamps.push(now);
|
|
2318
|
+
while (now - crashTimestamps[0] >= CRASH_WINDOW_MS) {
|
|
2319
|
+
crashTimestamps.shift();
|
|
2320
|
+
}
|
|
2321
|
+
const recentCrashCount = crashTimestamps.length;
|
|
2322
|
+
if (recentCrashCount > MAX_CRASH_RESTARTS) {
|
|
2323
|
+
writeStderrLine(
|
|
2324
|
+
`[Channel] Bridge crashed ${recentCrashCount} times in ${CRASH_WINDOW_MS / 1e3}s. Giving up.`
|
|
2325
|
+
);
|
|
2326
|
+
scheduler?.stop();
|
|
2327
|
+
cleanupStartedChannels(channels.values(), getBridge(), router);
|
|
2328
|
+
removeServiceInfo();
|
|
2329
|
+
process.exit(1);
|
|
2330
|
+
}
|
|
2331
|
+
writeStderrLine(
|
|
2332
|
+
`[Channel] Bridge crashed (${recentCrashCount}/${MAX_CRASH_RESTARTS} in window). Restarting in ${RESTART_DELAY_MS / 1e3}s...`
|
|
2333
|
+
);
|
|
2334
|
+
await new Promise((resolve15) => setTimeout(resolve15, RESTART_DELAY_MS));
|
|
2335
|
+
const bridge = new AcpBridge(bridgeOpts);
|
|
2336
|
+
setBridge(bridge);
|
|
2337
|
+
attachDisconnectHandler(bridge);
|
|
2338
|
+
await bridge.start();
|
|
2339
|
+
router.setBridge(bridge);
|
|
2340
|
+
for (const channel of channels.values()) {
|
|
2341
|
+
channel.setBridge(bridge);
|
|
2342
|
+
}
|
|
2343
|
+
registerToolCallDispatch(bridge, router, channels);
|
|
2344
|
+
registerBackgroundResponseRelay(bridge, router, channels);
|
|
2345
|
+
registerPermissionRelay(bridge, router, channels);
|
|
2346
|
+
registerSessionCleanup(bridge, router, channels);
|
|
2347
|
+
const result = await restoreBridgeSessions(router);
|
|
2348
|
+
writeStdoutLine(
|
|
2349
|
+
`[Channel] Bridge restarted. Sessions restored: ${result.restored}, failed: ${result.failed}`
|
|
2350
|
+
);
|
|
2351
|
+
} while (recoveryRequested && !isShuttingDown());
|
|
2352
|
+
})().catch((err) => {
|
|
2353
|
+
writeStderrLine(
|
|
2354
|
+
`[Channel] Failed to restart bridge: ${err instanceof Error ? err.message : String(err)}`
|
|
2355
|
+
);
|
|
2356
|
+
scheduler?.stop();
|
|
2357
|
+
cleanupStartedChannels(channels.values(), getBridge(), router);
|
|
2358
|
+
removeServiceInfo();
|
|
2359
|
+
process.exit(1);
|
|
2360
|
+
}).finally(() => {
|
|
2361
|
+
if (recoveryTask === task) {
|
|
2362
|
+
recoveryTask = void 0;
|
|
2363
|
+
recoverySourceBridge = void 0;
|
|
2364
|
+
bridgeReadiness.release();
|
|
2365
|
+
}
|
|
2366
|
+
});
|
|
2367
|
+
recoveryTask = task;
|
|
2368
|
+
}, "recoverBridge");
|
|
2369
|
+
return { attachDisconnectHandler };
|
|
2370
|
+
}
|
|
2371
|
+
__name(createBridgeRecovery, "createBridgeRecovery");
|
|
2241
2372
|
function checkDuplicateInstance() {
|
|
2242
2373
|
const existing = readServiceInfo();
|
|
2243
2374
|
if (existing) {
|
|
@@ -2282,7 +2413,7 @@ async function startSingle(name, proxy, cronEnabled) {
|
|
|
2282
2413
|
}
|
|
2283
2414
|
const cliEntryPath = findCliEntryPath();
|
|
2284
2415
|
let shuttingDown = false;
|
|
2285
|
-
const
|
|
2416
|
+
const bridgeReadiness = createBridgeReadinessGate();
|
|
2286
2417
|
const bridgeOpts = { cliEntryPath, cwd: config.cwd, model: config.model };
|
|
2287
2418
|
let bridge = new AcpBridge(bridgeOpts);
|
|
2288
2419
|
await bridge.start();
|
|
@@ -2299,7 +2430,8 @@ async function startSingle(name, proxy, cronEnabled) {
|
|
|
2299
2430
|
router,
|
|
2300
2431
|
proxy,
|
|
2301
2432
|
...channelMemoryOptions(() => bridge, config.cwd),
|
|
2302
|
-
...loopController ? { loopController } : {}
|
|
2433
|
+
...loopController ? { loopController } : {},
|
|
2434
|
+
bridgeRecovery: bridgeReadiness.current
|
|
2303
2435
|
});
|
|
2304
2436
|
channels.set(name, channel);
|
|
2305
2437
|
const scheduler = loopStore ? new ChannelLoopScheduler({
|
|
@@ -2326,57 +2458,18 @@ async function startSingle(name, proxy, cronEnabled) {
|
|
|
2326
2458
|
);
|
|
2327
2459
|
scheduler?.start();
|
|
2328
2460
|
writeStdoutLine(`[Channel] "${name}" is running. Press Ctrl+C to stop.`);
|
|
2329
|
-
const attachDisconnectHandler =
|
|
2330
|
-
|
|
2331
|
-
|
|
2332
|
-
|
|
2333
|
-
|
|
2334
|
-
|
|
2335
|
-
|
|
2336
|
-
|
|
2337
|
-
|
|
2338
|
-
|
|
2339
|
-
|
|
2340
|
-
|
|
2341
|
-
scheduler?.stop();
|
|
2342
|
-
channel.disconnect();
|
|
2343
|
-
router.clearAll();
|
|
2344
|
-
removeServiceInfo();
|
|
2345
|
-
process.exit(1);
|
|
2346
|
-
}
|
|
2347
|
-
writeStderrLine(
|
|
2348
|
-
`[Channel] Bridge crashed (${recentCrashes.length}/${MAX_CRASH_RESTARTS} in window). Restarting in ${RESTART_DELAY_MS / 1e3}s...`
|
|
2349
|
-
);
|
|
2350
|
-
scheduler?.stop();
|
|
2351
|
-
await new Promise((r) => setTimeout(r, RESTART_DELAY_MS));
|
|
2352
|
-
try {
|
|
2353
|
-
bridge = new AcpBridge(bridgeOpts);
|
|
2354
|
-
await bridge.start();
|
|
2355
|
-
router.setBridge(bridge);
|
|
2356
|
-
channel.setBridge(bridge);
|
|
2357
|
-
channel.disconnect();
|
|
2358
|
-
await channel.connect();
|
|
2359
|
-
registerToolCallDispatch(bridge, router, channels);
|
|
2360
|
-
registerBackgroundResponseRelay(bridge, router, channels);
|
|
2361
|
-
registerPermissionRelay(bridge, router, channels);
|
|
2362
|
-
registerSessionCleanup(bridge, router, channels);
|
|
2363
|
-
attachDisconnectHandler(bridge);
|
|
2364
|
-
const result = await router.restoreSessions();
|
|
2365
|
-
scheduler?.start();
|
|
2366
|
-
writeStdoutLine(
|
|
2367
|
-
`[Channel] Bridge restarted. Sessions restored: ${result.restored}, failed: ${result.failed}`
|
|
2368
|
-
);
|
|
2369
|
-
} catch (err) {
|
|
2370
|
-
writeStderrLine(
|
|
2371
|
-
`[Channel] Failed to restart bridge: ${err instanceof Error ? err.message : String(err)}`
|
|
2372
|
-
);
|
|
2373
|
-
channel.disconnect();
|
|
2374
|
-
router.clearAll();
|
|
2375
|
-
removeServiceInfo();
|
|
2376
|
-
process.exit(1);
|
|
2377
|
-
}
|
|
2378
|
-
});
|
|
2379
|
-
}, "attachDisconnectHandler");
|
|
2461
|
+
const { attachDisconnectHandler } = createBridgeRecovery({
|
|
2462
|
+
bridgeOpts,
|
|
2463
|
+
router,
|
|
2464
|
+
channels,
|
|
2465
|
+
scheduler,
|
|
2466
|
+
bridgeReadiness,
|
|
2467
|
+
isShuttingDown: /* @__PURE__ */ __name(() => shuttingDown, "isShuttingDown"),
|
|
2468
|
+
getBridge: /* @__PURE__ */ __name(() => bridge, "getBridge"),
|
|
2469
|
+
setBridge: /* @__PURE__ */ __name((next) => {
|
|
2470
|
+
bridge = next;
|
|
2471
|
+
}, "setBridge")
|
|
2472
|
+
});
|
|
2380
2473
|
attachDisconnectHandler(bridge);
|
|
2381
2474
|
const shutdown = /* @__PURE__ */ __name(() => {
|
|
2382
2475
|
shuttingDown = true;
|
|
@@ -2417,7 +2510,7 @@ async function startAll(proxy, cronEnabled) {
|
|
|
2417
2510
|
const cliEntryPath = findCliEntryPath();
|
|
2418
2511
|
const defaultCwd = process.cwd();
|
|
2419
2512
|
let shuttingDown = false;
|
|
2420
|
-
const
|
|
2513
|
+
const bridgeReadiness = createBridgeReadinessGate();
|
|
2421
2514
|
const bridgeOpts = {
|
|
2422
2515
|
cliEntryPath,
|
|
2423
2516
|
cwd: defaultCwd,
|
|
@@ -2442,7 +2535,8 @@ async function startAll(proxy, cronEnabled) {
|
|
|
2442
2535
|
router,
|
|
2443
2536
|
proxy,
|
|
2444
2537
|
...channelMemoryOptions(() => bridge, config.cwd),
|
|
2445
|
-
...loopController ? { loopController } : {}
|
|
2538
|
+
...loopController ? { loopController } : {},
|
|
2539
|
+
bridgeRecovery: bridgeReadiness.current
|
|
2446
2540
|
})
|
|
2447
2541
|
);
|
|
2448
2542
|
}
|
|
@@ -2482,85 +2576,18 @@ async function startAll(proxy, cronEnabled) {
|
|
|
2482
2576
|
writeStdoutLine(
|
|
2483
2577
|
`[Channel] Running ${connectedCount} channel(s). Press Ctrl+C to stop.`
|
|
2484
2578
|
);
|
|
2485
|
-
const attachDisconnectHandler =
|
|
2486
|
-
|
|
2487
|
-
|
|
2488
|
-
|
|
2489
|
-
|
|
2490
|
-
|
|
2491
|
-
|
|
2492
|
-
|
|
2493
|
-
|
|
2494
|
-
|
|
2495
|
-
|
|
2496
|
-
|
|
2497
|
-
scheduler?.stop();
|
|
2498
|
-
for (const channel of channels.values()) {
|
|
2499
|
-
try {
|
|
2500
|
-
channel.disconnect();
|
|
2501
|
-
} catch {
|
|
2502
|
-
}
|
|
2503
|
-
}
|
|
2504
|
-
router.clearAll();
|
|
2505
|
-
removeServiceInfo();
|
|
2506
|
-
process.exit(1);
|
|
2507
|
-
}
|
|
2508
|
-
writeStderrLine(
|
|
2509
|
-
`[Channel] Bridge crashed (${recentCrashes.length}/${MAX_CRASH_RESTARTS} in window). Restarting in ${RESTART_DELAY_MS / 1e3}s...`
|
|
2510
|
-
);
|
|
2511
|
-
scheduler?.stop();
|
|
2512
|
-
await new Promise((r) => setTimeout(r, RESTART_DELAY_MS));
|
|
2513
|
-
try {
|
|
2514
|
-
bridge = new AcpBridge(bridgeOpts);
|
|
2515
|
-
await bridge.start();
|
|
2516
|
-
router.setBridge(bridge);
|
|
2517
|
-
for (const channel of channels.values()) {
|
|
2518
|
-
channel.setBridge(bridge);
|
|
2519
|
-
}
|
|
2520
|
-
for (const [name, channel] of connectedChannels) {
|
|
2521
|
-
try {
|
|
2522
|
-
channel.disconnect();
|
|
2523
|
-
await channel.connect();
|
|
2524
|
-
} catch (err) {
|
|
2525
|
-
writeStderrLine(
|
|
2526
|
-
`[Channel] "${name}" failed to reconnect: ${err instanceof Error ? err.message : String(err)}`
|
|
2527
|
-
);
|
|
2528
|
-
connectedChannels.delete(name);
|
|
2529
|
-
}
|
|
2530
|
-
}
|
|
2531
|
-
if (connectedChannels.size === 0) {
|
|
2532
|
-
writeStderrLine("[Channel] No channels reconnected. Exiting.");
|
|
2533
|
-
bridge.stop();
|
|
2534
|
-
router.clearAll();
|
|
2535
|
-
removeServiceInfo();
|
|
2536
|
-
process.exit(1);
|
|
2537
|
-
}
|
|
2538
|
-
registerToolCallDispatch(bridge, router, channels);
|
|
2539
|
-
registerBackgroundResponseRelay(bridge, router, channels);
|
|
2540
|
-
registerPermissionRelay(bridge, router, channels);
|
|
2541
|
-
registerSessionCleanup(bridge, router, channels);
|
|
2542
|
-
attachDisconnectHandler(bridge);
|
|
2543
|
-
const result = await router.restoreSessions();
|
|
2544
|
-
scheduler?.start();
|
|
2545
|
-
writeStdoutLine(
|
|
2546
|
-
`[Channel] Bridge restarted. Sessions restored: ${result.restored}, failed: ${result.failed}`
|
|
2547
|
-
);
|
|
2548
|
-
} catch (err) {
|
|
2549
|
-
writeStderrLine(
|
|
2550
|
-
`[Channel] Failed to restart bridge: ${err instanceof Error ? err.message : String(err)}`
|
|
2551
|
-
);
|
|
2552
|
-
for (const channel of channels.values()) {
|
|
2553
|
-
try {
|
|
2554
|
-
channel.disconnect();
|
|
2555
|
-
} catch {
|
|
2556
|
-
}
|
|
2557
|
-
}
|
|
2558
|
-
router.clearAll();
|
|
2559
|
-
removeServiceInfo();
|
|
2560
|
-
process.exit(1);
|
|
2561
|
-
}
|
|
2562
|
-
});
|
|
2563
|
-
}, "attachDisconnectHandler");
|
|
2579
|
+
const { attachDisconnectHandler } = createBridgeRecovery({
|
|
2580
|
+
bridgeOpts,
|
|
2581
|
+
router,
|
|
2582
|
+
channels,
|
|
2583
|
+
scheduler,
|
|
2584
|
+
bridgeReadiness,
|
|
2585
|
+
isShuttingDown: /* @__PURE__ */ __name(() => shuttingDown, "isShuttingDown"),
|
|
2586
|
+
getBridge: /* @__PURE__ */ __name(() => bridge, "getBridge"),
|
|
2587
|
+
setBridge: /* @__PURE__ */ __name((next) => {
|
|
2588
|
+
bridge = next;
|
|
2589
|
+
}, "setBridge")
|
|
2590
|
+
});
|
|
2564
2591
|
attachDisconnectHandler(bridge);
|
|
2565
2592
|
const shutdown = /* @__PURE__ */ __name(() => {
|
|
2566
2593
|
shuttingDown = true;
|
|
@@ -2622,7 +2649,7 @@ var stopCommand = {
|
|
|
2622
2649
|
if (argv["daemon-url"]) {
|
|
2623
2650
|
const token = argv.token ?? process.env[QWEN_SERVER_TOKEN_ENV] ?? process.env[QWEN_DAEMON_TOKEN_ENV];
|
|
2624
2651
|
try {
|
|
2625
|
-
const sdk = await import("./daemon-
|
|
2652
|
+
const sdk = await import("./daemon-PCNCI5YU.js");
|
|
2626
2653
|
const client = new sdk.DaemonClient({
|
|
2627
2654
|
baseUrl: argv["daemon-url"],
|
|
2628
2655
|
...token ? { token } : {}
|
|
@@ -2808,7 +2835,7 @@ var statusCommand = {
|
|
|
2808
2835
|
if (argv["daemon-url"]) {
|
|
2809
2836
|
const token = argv.token ?? process.env[QWEN_SERVER_TOKEN_ENV] ?? process.env[QWEN_DAEMON_TOKEN_ENV];
|
|
2810
2837
|
try {
|
|
2811
|
-
const sdk = await import("./daemon-
|
|
2838
|
+
const sdk = await import("./daemon-PCNCI5YU.js");
|
|
2812
2839
|
const client = new sdk.DaemonClient({
|
|
2813
2840
|
baseUrl: argv["daemon-url"],
|
|
2814
2841
|
...token ? { token } : {}
|
|
@@ -2919,7 +2946,7 @@ var reloadCommand = {
|
|
|
2919
2946
|
const token = resolveToken(argv.token);
|
|
2920
2947
|
let sdk;
|
|
2921
2948
|
try {
|
|
2922
|
-
sdk = await import("./daemon-
|
|
2949
|
+
sdk = await import("./daemon-PCNCI5YU.js");
|
|
2923
2950
|
} catch (err) {
|
|
2924
2951
|
writeStderrLine(
|
|
2925
2952
|
`[Channel] Failed to load daemon SDK: ${safeChannelCommandErrorMessage(err)}`
|
|
@@ -2999,7 +3026,7 @@ var setCommand2 = {
|
|
|
2999
3026
|
const selection = names[0] === "all" ? { mode: "all" } : { mode: "names", names };
|
|
3000
3027
|
let sdk;
|
|
3001
3028
|
try {
|
|
3002
|
-
sdk = await import("./daemon-
|
|
3029
|
+
sdk = await import("./daemon-PCNCI5YU.js");
|
|
3003
3030
|
} catch (error) {
|
|
3004
3031
|
writeStderrLine(
|
|
3005
3032
|
`[Channel] Failed to load daemon SDK: ${safeChannelCommandErrorMessage(error)}`
|
|
@@ -3125,7 +3152,7 @@ function createDaemonChannelBridgeFacade(bridge, opts) {
|
|
|
3125
3152
|
}
|
|
3126
3153
|
__name(createDaemonChannelBridgeFacade, "createDaemonChannelBridgeFacade");
|
|
3127
3154
|
async function loadDaemonSdk() {
|
|
3128
|
-
return await import("./daemon-
|
|
3155
|
+
return await import("./daemon-PCNCI5YU.js");
|
|
3129
3156
|
}
|
|
3130
3157
|
__name(loadDaemonSdk, "loadDaemonSdk");
|
|
3131
3158
|
function selectedChannelNames(channelsConfig, selection) {
|
|
@@ -3172,12 +3199,12 @@ async function abortableStartup(value, signal) {
|
|
|
3172
3199
|
const promise = Promise.resolve(value);
|
|
3173
3200
|
if (!signal) return await promise;
|
|
3174
3201
|
if (signal.aborted) throw startupAbortError();
|
|
3175
|
-
return await new Promise((
|
|
3202
|
+
return await new Promise((resolve15, reject) => {
|
|
3176
3203
|
const onAbort = /* @__PURE__ */ __name(() => {
|
|
3177
3204
|
reject(startupAbortError());
|
|
3178
3205
|
}, "onAbort");
|
|
3179
3206
|
signal.addEventListener("abort", onAbort, { once: true });
|
|
3180
|
-
promise.then(
|
|
3207
|
+
promise.then(resolve15, reject).finally(() => {
|
|
3181
3208
|
signal.removeEventListener("abort", onAbort);
|
|
3182
3209
|
});
|
|
3183
3210
|
});
|
|
@@ -3351,6 +3378,7 @@ async function runChannelDaemonWorker(opts) {
|
|
|
3351
3378
|
createChannel(name, config, bridgeFacade, {
|
|
3352
3379
|
...proxy ? { proxy } : {},
|
|
3353
3380
|
router: createdRouter,
|
|
3381
|
+
stateDir: daemonChannelStateDir(daemonWorkspace, name),
|
|
3354
3382
|
channelMemory: {
|
|
3355
3383
|
readChannelMemory,
|
|
3356
3384
|
getChannelMemoryRevision,
|
|
@@ -3584,7 +3612,7 @@ function reportStartupToSupervisor(message, signal, subscribeMessage = (listener
|
|
|
3584
3612
|
if (!send) {
|
|
3585
3613
|
return Promise.reject(new Error("Channel worker IPC is unavailable."));
|
|
3586
3614
|
}
|
|
3587
|
-
return new Promise((
|
|
3615
|
+
return new Promise((resolve15, reject) => {
|
|
3588
3616
|
let settled = false;
|
|
3589
3617
|
let unsubscribeMessage = /* @__PURE__ */ __name(() => {
|
|
3590
3618
|
}, "unsubscribeMessage");
|
|
@@ -3598,7 +3626,7 @@ function reportStartupToSupervisor(message, signal, subscribeMessage = (listener
|
|
|
3598
3626
|
settled = true;
|
|
3599
3627
|
cleanup();
|
|
3600
3628
|
if (error) reject(error);
|
|
3601
|
-
else
|
|
3629
|
+
else resolve15();
|
|
3602
3630
|
}, "finish");
|
|
3603
3631
|
const onMessage = /* @__PURE__ */ __name((value) => {
|
|
3604
3632
|
if (isChannelStartupReportAckMessage(value)) {
|
|
@@ -3846,8 +3874,8 @@ var daemonWorkerCommand = {
|
|
|
3846
3874
|
let shuttingDown = false;
|
|
3847
3875
|
let exitCode = 0;
|
|
3848
3876
|
let finish;
|
|
3849
|
-
const finished = new Promise((
|
|
3850
|
-
finish =
|
|
3877
|
+
const finished = new Promise((resolve15) => {
|
|
3878
|
+
finish = resolve15;
|
|
3851
3879
|
});
|
|
3852
3880
|
const shutdown = /* @__PURE__ */ __name(async (reason) => {
|
|
3853
3881
|
if (shuttingDown) {
|
|
@@ -3875,8 +3903,8 @@ var daemonWorkerCommand = {
|
|
|
3875
3903
|
...activeChannelDeliveries.values(),
|
|
3876
3904
|
...activeWebhookTasks.values()
|
|
3877
3905
|
]),
|
|
3878
|
-
new Promise((
|
|
3879
|
-
const timer = setTimeout(
|
|
3906
|
+
new Promise((resolve15) => {
|
|
3907
|
+
const timer = setTimeout(resolve15, WORKER_SHUTDOWN_DRAIN_MS);
|
|
3880
3908
|
timer.unref();
|
|
3881
3909
|
})
|
|
3882
3910
|
]);
|
|
@@ -6683,6 +6711,7 @@ function unmarkedComments(comments) {
|
|
|
6683
6711
|
__name(unmarkedComments, "unmarkedComments");
|
|
6684
6712
|
|
|
6685
6713
|
// packages/cli/src/commands/review/compose-review.ts
|
|
6714
|
+
var LOW_SIGNAL_SRC_DIFF_LINES = 100;
|
|
6686
6715
|
function withMarker(line) {
|
|
6687
6716
|
return line.startsWith(CRITICAL_PREFIX) ? line : `${CRITICAL_PREFIX} ${line}`;
|
|
6688
6717
|
}
|
|
@@ -6927,6 +6956,19 @@ function composeReview(input) {
|
|
|
6927
6956
|
downgraded = true;
|
|
6928
6957
|
downgradedFrom = "Request changes";
|
|
6929
6958
|
}
|
|
6959
|
+
let lowSignal = null;
|
|
6960
|
+
if (event === "APPROVE" && input.planPath) {
|
|
6961
|
+
try {
|
|
6962
|
+
const plan = JSON.parse(
|
|
6963
|
+
readFileSync8(input.planPath, "utf8")
|
|
6964
|
+
);
|
|
6965
|
+
const src = Number(plan.srcDiffLines ?? 0);
|
|
6966
|
+
if (src > LOW_SIGNAL_SRC_DIFF_LINES) {
|
|
6967
|
+
lowSignal = { agents: requiredAgents(plan).length, srcDiffLines: src };
|
|
6968
|
+
}
|
|
6969
|
+
} catch {
|
|
6970
|
+
}
|
|
6971
|
+
}
|
|
6930
6972
|
const footer = `_\u2014 ${modelId} via Qwen Code /review_`;
|
|
6931
6973
|
const bilingual = bilingualFromPlan(input.planPath, input.prBodyFetcher);
|
|
6932
6974
|
const render = /* @__PURE__ */ __name((parts, sep4) => {
|
|
@@ -7075,7 +7117,8 @@ ${footer}`;
|
|
|
7075
7117
|
cappedBy,
|
|
7076
7118
|
downgraded,
|
|
7077
7119
|
downgradedFrom,
|
|
7078
|
-
remediation
|
|
7120
|
+
remediation,
|
|
7121
|
+
lowSignal
|
|
7079
7122
|
};
|
|
7080
7123
|
}
|
|
7081
7124
|
if (event === "APPROVE") {
|
|
@@ -7092,7 +7135,8 @@ ${footer}`;
|
|
|
7092
7135
|
cappedBy,
|
|
7093
7136
|
downgraded,
|
|
7094
7137
|
downgradedFrom,
|
|
7095
|
-
remediation
|
|
7138
|
+
remediation,
|
|
7139
|
+
lowSignal
|
|
7096
7140
|
};
|
|
7097
7141
|
}
|
|
7098
7142
|
const clauses = [];
|
|
@@ -7146,7 +7190,8 @@ ${footer}`;
|
|
|
7146
7190
|
cappedBy,
|
|
7147
7191
|
downgraded,
|
|
7148
7192
|
downgradedFrom,
|
|
7149
|
-
remediation
|
|
7193
|
+
remediation,
|
|
7194
|
+
lowSignal
|
|
7150
7195
|
};
|
|
7151
7196
|
}
|
|
7152
7197
|
__name(composeReview, "composeReview");
|
|
@@ -7400,6 +7445,9 @@ function verdictLine(r) {
|
|
|
7400
7445
|
} else if (r.downgraded) {
|
|
7401
7446
|
line += " \u2014 downgraded by a presubmit check";
|
|
7402
7447
|
}
|
|
7448
|
+
if (r.event === "APPROVE" && r.lowSignal) {
|
|
7449
|
+
line += ` \u2014 low signal: none of the ${r.lowSignal.agents} review agents reported a finding on a non-trivial diff (${r.lowSignal.srcDiffLines} source diff lines)`;
|
|
7450
|
+
}
|
|
7403
7451
|
return line;
|
|
7404
7452
|
}
|
|
7405
7453
|
__name(verdictLine, "verdictLine");
|
|
@@ -9991,6 +10039,7 @@ var GITHUB_ACTIONS = {
|
|
|
9991
10039
|
- **A fork guard this diff removes or fails to add on a newly-privileged path.** For any trigger a fork can fire, the guard is what makes everything above unreachable: \`if: github.event.pull_request.head.repo.full_name == github.repository\`, an author-association check, or a \`github.repository == '<owner>/<repo>'\` gate on a scheduled job. A diff that adds a privileged trigger without one has added the vulnerability, not inherited it.
|
|
9992
10040
|
- **\`$GITHUB_OUTPUT\` / \`$GITHUB_ENV\` written from untrusted data.** \`echo "x=$UNTRUSTED" >> "$GITHUB_OUTPUT"\` with a value containing a newline injects a second, arbitrary variable \u2014 \`PATH\` or \`NODE_OPTIONS\` among them. Multi-line values need the heredoc form with an unguessable delimiter.
|
|
9993
10041
|
- **Artifact or cache poisoning across a trigger boundary.** A \`workflow_run\` job that downloads an artifact a \`pull_request\` job uploaded is pulling contributor-controlled bytes into a privileged context. So is a cache key a fork can populate.
|
|
10042
|
+
- **A cache or reuse mechanism whose two sides never agree on identity.** \`actions/cache\` matches an entry on \`(key | restore-key)\` **and** a \`version\` that hashes the literal \`path\` strings plus the compression method \u2014 not the key alone. So two jobs can share a key, share the \`path:\` line *as written*, and never hit once: \`\${{ runner.temp }}\` expands to a different string on \`ubuntu-latest\` than in a container job or on a self-hosted runner, and an image without the \`zstd\` binary picks gzip where a hosted runner picks zstd. Compare the **environments** \u2014 \`runs-on\`, \`container\`, what each path expression expands to, what each image ships \u2014 never the YAML strings, which match in exactly the case that fails. The same question governs any restore/skip/reuse mechanism a diff introduces: does the side that writes agree with the side that reads? A mechanism that can never fire is not a slow optimisation, it is a no-op carrying maintenance cost, and no assertion about the YAML's *shape* will ever say so \u2014 tests that the two sides' \`key:\` and \`path:\` strings match pass just as happily when neither side can reach the other's cache. If a hit leaves no observable signal either \u2014 a restore step with no \`id:\`, nothing written to \`$GITHUB_STEP_SUMMARY\` \u2014 the failure is silent and permanent; say that as part of the finding.
|
|
9994
10043
|
|
|
9995
10044
|
**Recommendations (Suggestion) \u2014 say the cost, do not block on them:**
|
|
9996
10045
|
|
|
@@ -10390,7 +10439,7 @@ function buildRoleBrief(report, role, opts = {}) {
|
|
|
10390
10439
|
if (typeof base === "string" && base && pr !== void 0 && opts.planPath) {
|
|
10391
10440
|
parts.push(
|
|
10392
10441
|
"",
|
|
10393
|
-
"**Then run the test-efficacy probe.** A green suite says the tests pass. It does not say they would have failed had the change been wrong, and those are different claims:",
|
|
10442
|
+
"**Then run the test-efficacy probe.** A green suite says the tests pass. It does not say they would have failed had the change been wrong, and those are different claims. Give this call `timeout: 600000` too \u2014 besides the revert probe it runs up to 8 single-statement deletion mutants, each a suite run, and it budgets itself to finish inside that ceiling:",
|
|
10394
10443
|
"",
|
|
10395
10444
|
"```bash",
|
|
10396
10445
|
`"\${QWEN_CODE_CLI:-qwen}" review test-efficacy ${resolve11(opts.planPath)} \\`,
|
|
@@ -10399,7 +10448,7 @@ function buildRoleBrief(report, role, opts = {}) {
|
|
|
10399
10448
|
` --out ${resolve11(dirname12(opts.planPath), `qwen-review-pr-${pr}-efficacy.json`)}`,
|
|
10400
10449
|
"```",
|
|
10401
10450
|
"",
|
|
10402
|
-
'Read its `findings[]`. `kind: "unreachable"` is a test the project\'s test command never collects \u2014 it did not run here and it does not run in CI. `kind: "inert"` is a test that **still passed with the change reverted**: it is green whether or not the feature exists, so it cannot catch a regression in it. Report each as a **Suggestion** with `Source: [test]`, saying plainly which behaviour
|
|
10451
|
+
'Read its `findings[]`. `kind: "unreachable"` is a test the project\'s test command never collects \u2014 it did not run here and it does not run in CI. `kind: "inert"` is a test that **still passed with the change reverted**: it is green whether or not the feature exists, so it cannot catch a regression in it. `kind: "mutant-survived"` is a single safety statement the diff added (a `.clear()`, an `.abort(\u2026)`, a reset-to-empty) that was **deleted and every affected test stayed green** \u2014 no test in the diff fails when it is removed, which the whole-file revert cannot see when the file\'s other, tested behaviours mask it. Report each as a **Suggestion** with `Source: [test]`, saying plainly which behaviour has no test in this diff that would catch its removal. **`inconclusive` is not a finding** \u2014 for probes and mutants alike, reverting or mutating the source often breaks the test\'s own compile, and that is not the test catching anything. Mutants counted in `mutants.skippedForBudget`, `mutants.skippedForCap`, or `mutants.skippedForBaseline` never ran \u2014 not findings either. `mutants.note`, when present, explains why no mutants ran at all. Note them and move on.'
|
|
10403
10452
|
);
|
|
10404
10453
|
}
|
|
10405
10454
|
}
|
|
@@ -10880,7 +10929,13 @@ var agentPromptCommand = {
|
|
|
10880
10929
|
// packages/cli/src/commands/review/build-test.ts
|
|
10881
10930
|
init_esbuild_shims();
|
|
10882
10931
|
import { spawnSync as spawnSync2 } from "node:child_process";
|
|
10883
|
-
import {
|
|
10932
|
+
import {
|
|
10933
|
+
existsSync as existsSync5,
|
|
10934
|
+
readFileSync as readFileSync16,
|
|
10935
|
+
rmSync as rmSync4,
|
|
10936
|
+
statfsSync,
|
|
10937
|
+
writeFileSync as writeFileSync15
|
|
10938
|
+
} from "node:fs";
|
|
10884
10939
|
import { join as join12, resolve as resolve12 } from "node:path";
|
|
10885
10940
|
|
|
10886
10941
|
// packages/cli/src/commands/review/lib/workspaces.ts
|
|
@@ -11081,6 +11136,18 @@ ${rescued.join("\n")}
|
|
|
11081
11136
|
return s.slice(0, KEEP_HEAD) + marker + s.slice(-KEEP_TAIL);
|
|
11082
11137
|
}
|
|
11083
11138
|
__name(trimOutput, "trimOutput");
|
|
11139
|
+
var INSTALL_MIN_FREE_BYTES = 3 * 1024 ** 3;
|
|
11140
|
+
var BUILD_MIN_FREE_BYTES = 1024 ** 3;
|
|
11141
|
+
function freeDiskBytes(dir) {
|
|
11142
|
+
try {
|
|
11143
|
+
const s = statfsSync(dir);
|
|
11144
|
+
return s.bavail * s.bsize;
|
|
11145
|
+
} catch {
|
|
11146
|
+
return null;
|
|
11147
|
+
}
|
|
11148
|
+
}
|
|
11149
|
+
__name(freeDiskBytes, "freeDiskBytes");
|
|
11150
|
+
var gib = /* @__PURE__ */ __name((bytes) => (bytes / 1024 ** 3).toFixed(1), "gib");
|
|
11084
11151
|
function buildRunEnv(base = process.env) {
|
|
11085
11152
|
return {
|
|
11086
11153
|
...base,
|
|
@@ -11226,7 +11293,14 @@ function runBuildTest(args) {
|
|
|
11226
11293
|
);
|
|
11227
11294
|
}
|
|
11228
11295
|
if (args.install && npmLock && !installComplete()) {
|
|
11229
|
-
const
|
|
11296
|
+
const installCmd = "npm ci --no-audit --no-fund";
|
|
11297
|
+
const free = freeDiskBytes(root);
|
|
11298
|
+
if (free !== null && free < INSTALL_MIN_FREE_BYTES) {
|
|
11299
|
+
results.ok = false;
|
|
11300
|
+
results.note = `Insufficient disk space (${gib(free)}G free, need ~${gib(INSTALL_MIN_FREE_BYTES)}G): skipped \`${installCmd}\`, so nothing could be built or tested. This is an environment issue, not a code finding \u2014 report it as informational.`;
|
|
11301
|
+
return results;
|
|
11302
|
+
}
|
|
11303
|
+
const install = exec(installCmd, root, perCommandMs);
|
|
11230
11304
|
results.install = install;
|
|
11231
11305
|
if (install.timedOut) results.timedOut.push(install.command);
|
|
11232
11306
|
if (install.timedOut) {
|
|
@@ -11245,6 +11319,12 @@ function runBuildTest(args) {
|
|
|
11245
11319
|
return results;
|
|
11246
11320
|
}
|
|
11247
11321
|
}
|
|
11322
|
+
const freeForBuild = freeDiskBytes(root);
|
|
11323
|
+
if (freeForBuild !== null && freeForBuild < BUILD_MIN_FREE_BYTES) {
|
|
11324
|
+
results.ok = false;
|
|
11325
|
+
results.note = `Insufficient disk space (${gib(freeForBuild)}G free, need ~${gib(BUILD_MIN_FREE_BYTES)}G): skipped the build and tests rather than fill the disk mid-compile. This is an environment issue, not a code finding \u2014 report it as informational.`;
|
|
11326
|
+
return results;
|
|
11327
|
+
}
|
|
11248
11328
|
const alsoBuild = [];
|
|
11249
11329
|
let set = buildSetFor(affected, packages);
|
|
11250
11330
|
const built = /* @__PURE__ */ new Set();
|
|
@@ -11419,6 +11499,12 @@ function writeSkillArgs(skillName, args) {
|
|
|
11419
11499
|
);
|
|
11420
11500
|
return null;
|
|
11421
11501
|
}
|
|
11502
|
+
if (lstatSync3(path3, { throwIfNoEntry: false })?.isSymbolicLink()) {
|
|
11503
|
+
debugLogger3.warn(
|
|
11504
|
+
`Skill args file ${path3} is a symlink; refusing to write through it.`
|
|
11505
|
+
);
|
|
11506
|
+
return null;
|
|
11507
|
+
}
|
|
11422
11508
|
const fd = openSync2(
|
|
11423
11509
|
path3,
|
|
11424
11510
|
constants.O_WRONLY | constants.O_CREAT | constants.O_TRUNC | constants.O_NOFOLLOW,
|
|
@@ -11791,12 +11877,16 @@ init_esbuild_shims();
|
|
|
11791
11877
|
import { spawnSync as spawnSync3 } from "node:child_process";
|
|
11792
11878
|
import {
|
|
11793
11879
|
mkdirSync as mkdirSync16,
|
|
11880
|
+
readdirSync as readdirSync5,
|
|
11794
11881
|
writeFileSync as writeFileSync16,
|
|
11795
11882
|
readFileSync as readFileSync18,
|
|
11796
11883
|
rmSync as rmSync6,
|
|
11797
11884
|
lstatSync as lstatSync4,
|
|
11798
|
-
existsSync as existsSync7
|
|
11885
|
+
existsSync as existsSync7,
|
|
11886
|
+
statSync as statSync5,
|
|
11887
|
+
symlinkSync
|
|
11799
11888
|
} from "node:fs";
|
|
11889
|
+
import { createRequire } from "node:module";
|
|
11800
11890
|
import { dirname as dirname13, join as join14, isAbsolute as isAbsolute3, sep as sep3 } from "node:path";
|
|
11801
11891
|
var FIXTURE_DIR_RE = /(^|\/)(__fixtures__|__mocks__|__snapshots__|fixtures)\//;
|
|
11802
11892
|
function planTestEfficacy(files, workspaceGlobs) {
|
|
@@ -11813,6 +11903,288 @@ function planTestEfficacy(files, workspaceGlobs) {
|
|
|
11813
11903
|
};
|
|
11814
11904
|
}
|
|
11815
11905
|
__name(planTestEfficacy, "planTestEfficacy");
|
|
11906
|
+
var MAX_MUTANTS = 8;
|
|
11907
|
+
var PROBE_RUN_TIMEOUT_MS = 3e5;
|
|
11908
|
+
var TOTAL_BUDGET_MS = 54e4;
|
|
11909
|
+
var RUN_ESTIMATE_MARGIN_MS = 15e3;
|
|
11910
|
+
var SAFETY_VERB_RE = /\.(?:clear|delete|reset|abort|removeListener|unref)\(|=\s*\[\]\s*;$|=\s*new\s+(?:Map|Set|WeakMap|WeakSet)(?:<[^=;]*>)?\(\)\s*;$/;
|
|
11911
|
+
var MUTANT_SOURCE_RE = /\.(?:ts|tsx|mts|cts|js|jsx|mjs|cjs)$/;
|
|
11912
|
+
var DECLARATION_FILE_RE = /\.d\.[cm]?ts$/;
|
|
11913
|
+
var NON_STATEMENT_START_RE = /^(?:const|let|var|function|class|interface|type|enum|import|export|return|throw|yield|if|for|while|switch|do|else|try|catch|finally|case|default|break|continue|async|public|private|protected|readonly|static)\b/;
|
|
11914
|
+
function skipTemplateOnLine(line, start) {
|
|
11915
|
+
let depth = 0;
|
|
11916
|
+
for (let i = start + 1; i < line.length; i++) {
|
|
11917
|
+
const ch = line[i];
|
|
11918
|
+
if (ch === "\\") {
|
|
11919
|
+
i++;
|
|
11920
|
+
} else if (depth === 0) {
|
|
11921
|
+
if (ch === "`") return i;
|
|
11922
|
+
if (ch === "$" && line[i + 1] === "{") {
|
|
11923
|
+
depth = 1;
|
|
11924
|
+
i++;
|
|
11925
|
+
}
|
|
11926
|
+
} else if (ch === "{") {
|
|
11927
|
+
depth++;
|
|
11928
|
+
} else if (ch === "}") {
|
|
11929
|
+
depth--;
|
|
11930
|
+
}
|
|
11931
|
+
}
|
|
11932
|
+
return -1;
|
|
11933
|
+
}
|
|
11934
|
+
__name(skipTemplateOnLine, "skipTemplateOnLine");
|
|
11935
|
+
function scanLineDelimiters(line) {
|
|
11936
|
+
let paren = 0;
|
|
11937
|
+
let bracket = 0;
|
|
11938
|
+
let brace = 0;
|
|
11939
|
+
for (let i = 0; i < line.length; i++) {
|
|
11940
|
+
const ch = line[i];
|
|
11941
|
+
if (ch === "`") {
|
|
11942
|
+
const close = skipTemplateOnLine(line, i);
|
|
11943
|
+
if (close < 0) return null;
|
|
11944
|
+
i = close;
|
|
11945
|
+
continue;
|
|
11946
|
+
}
|
|
11947
|
+
if (ch === '"' || ch === "'") {
|
|
11948
|
+
i++;
|
|
11949
|
+
while (i < line.length && line[i] !== ch) {
|
|
11950
|
+
if (line[i] === "\\") i++;
|
|
11951
|
+
i++;
|
|
11952
|
+
}
|
|
11953
|
+
if (i >= line.length) return null;
|
|
11954
|
+
continue;
|
|
11955
|
+
}
|
|
11956
|
+
if (ch === "/" && line[i + 1] === "/") break;
|
|
11957
|
+
if (ch === "/" && line[i + 1] === "*") {
|
|
11958
|
+
const close = line.indexOf("*/", i + 2);
|
|
11959
|
+
if (close < 0) return null;
|
|
11960
|
+
i = close + 1;
|
|
11961
|
+
continue;
|
|
11962
|
+
}
|
|
11963
|
+
if (ch === "(") paren++;
|
|
11964
|
+
else if (ch === ")") paren--;
|
|
11965
|
+
else if (ch === "[") bracket++;
|
|
11966
|
+
else if (ch === "]") bracket--;
|
|
11967
|
+
else if (ch === "{") brace++;
|
|
11968
|
+
else if (ch === "}") brace--;
|
|
11969
|
+
if (paren < 0 || bracket < 0 || brace < 0) return null;
|
|
11970
|
+
}
|
|
11971
|
+
return { paren, bracket, brace };
|
|
11972
|
+
}
|
|
11973
|
+
__name(scanLineDelimiters, "scanLineDelimiters");
|
|
11974
|
+
function scanFileLines(content) {
|
|
11975
|
+
const inLiteral = [];
|
|
11976
|
+
const codeLines = [];
|
|
11977
|
+
let state = "code";
|
|
11978
|
+
const templates = [];
|
|
11979
|
+
let buf = "";
|
|
11980
|
+
let lineStart = 0;
|
|
11981
|
+
let rawLine = false;
|
|
11982
|
+
const inTemplateOrComment = /* @__PURE__ */ __name(() => state !== "code" || templates.length > 0, "inTemplateOrComment");
|
|
11983
|
+
inLiteral.push(inTemplateOrComment());
|
|
11984
|
+
const endLine = /* @__PURE__ */ __name((i) => {
|
|
11985
|
+
codeLines.push(rawLine ? content.slice(lineStart, i).trim() : buf.trim());
|
|
11986
|
+
buf = "";
|
|
11987
|
+
rawLine = false;
|
|
11988
|
+
lineStart = i + 1;
|
|
11989
|
+
}, "endLine");
|
|
11990
|
+
for (let i = 0; i < content.length; i++) {
|
|
11991
|
+
const ch = content[i];
|
|
11992
|
+
if (ch === "\n") {
|
|
11993
|
+
endLine(i);
|
|
11994
|
+
inLiteral.push(inTemplateOrComment());
|
|
11995
|
+
continue;
|
|
11996
|
+
}
|
|
11997
|
+
if (templates.length > 0) {
|
|
11998
|
+
const top = templates.length - 1;
|
|
11999
|
+
if (ch === "\\" && content[i + 1] !== "\n") {
|
|
12000
|
+
i++;
|
|
12001
|
+
} else if (templates[top] < 0) {
|
|
12002
|
+
if (ch === "`") {
|
|
12003
|
+
templates.pop();
|
|
12004
|
+
if (templates.length === 0) buf += "`";
|
|
12005
|
+
} else if (ch === "$" && content[i + 1] === "{") {
|
|
12006
|
+
templates[top] = 0;
|
|
12007
|
+
i++;
|
|
12008
|
+
}
|
|
12009
|
+
} else if (ch === "`") {
|
|
12010
|
+
templates.push(-1);
|
|
12011
|
+
} else if (ch === "{") {
|
|
12012
|
+
templates[top]++;
|
|
12013
|
+
} else if (ch === "}") {
|
|
12014
|
+
if (templates[top] === 0) templates[top] = -1;
|
|
12015
|
+
else templates[top]--;
|
|
12016
|
+
}
|
|
12017
|
+
continue;
|
|
12018
|
+
}
|
|
12019
|
+
if (state === "comment") {
|
|
12020
|
+
if (ch === "*" && content[i + 1] === "/") {
|
|
12021
|
+
state = "code";
|
|
12022
|
+
i++;
|
|
12023
|
+
}
|
|
12024
|
+
continue;
|
|
12025
|
+
}
|
|
12026
|
+
if (ch === "`") {
|
|
12027
|
+
buf += "`";
|
|
12028
|
+
templates.push(-1);
|
|
12029
|
+
} else if (ch === "/" && content[i + 1] === "*") {
|
|
12030
|
+
state = "comment";
|
|
12031
|
+
i++;
|
|
12032
|
+
} else if (ch === "/" && content[i + 1] === "/") {
|
|
12033
|
+
while (i + 1 < content.length && content[i + 1] !== "\n") i++;
|
|
12034
|
+
} else if (ch === '"' || ch === "'") {
|
|
12035
|
+
let k = i + 1;
|
|
12036
|
+
while (k < content.length && content[k] !== ch && content[k] !== "\n") {
|
|
12037
|
+
if (content[k] === "\\" && content[k + 1] !== "\n") k++;
|
|
12038
|
+
k++;
|
|
12039
|
+
}
|
|
12040
|
+
if (k < content.length && content[k] === ch) {
|
|
12041
|
+
buf += ch + ch;
|
|
12042
|
+
i = k;
|
|
12043
|
+
} else {
|
|
12044
|
+
rawLine = true;
|
|
12045
|
+
i = k < content.length && content[k] === "\n" ? k - 1 : k;
|
|
12046
|
+
}
|
|
12047
|
+
} else {
|
|
12048
|
+
buf += ch;
|
|
12049
|
+
}
|
|
12050
|
+
}
|
|
12051
|
+
endLine(content.length);
|
|
12052
|
+
return {
|
|
12053
|
+
inLiteral,
|
|
12054
|
+
codeLines,
|
|
12055
|
+
endState: templates.length > 0 ? "template" : state
|
|
12056
|
+
};
|
|
12057
|
+
}
|
|
12058
|
+
__name(scanFileLines, "scanFileLines");
|
|
12059
|
+
function insideClassBody(codeLines, idx) {
|
|
12060
|
+
let depth = 0;
|
|
12061
|
+
for (let j = idx - 1; j >= 0; j--) {
|
|
12062
|
+
const code = codeLines[j];
|
|
12063
|
+
for (let i = code.length - 1; i >= 0; i--) {
|
|
12064
|
+
const ch = code[i];
|
|
12065
|
+
if (ch === "}") depth++;
|
|
12066
|
+
else if (ch === "{") {
|
|
12067
|
+
if (depth === 0) {
|
|
12068
|
+
if (/\bclass\b/.test(code.slice(0, i))) return true;
|
|
12069
|
+
for (let k = j - 1; k >= 0; k--) {
|
|
12070
|
+
const prev = codeLines[k];
|
|
12071
|
+
if (prev.includes(";")) break;
|
|
12072
|
+
const d = scanLineDelimiters(prev);
|
|
12073
|
+
if (!d || d.brace !== 0) break;
|
|
12074
|
+
if (/\bclass\b/.test(prev)) return true;
|
|
12075
|
+
}
|
|
12076
|
+
return false;
|
|
12077
|
+
}
|
|
12078
|
+
depth--;
|
|
12079
|
+
}
|
|
12080
|
+
}
|
|
12081
|
+
}
|
|
12082
|
+
return false;
|
|
12083
|
+
}
|
|
12084
|
+
__name(insideClassBody, "insideClassBody");
|
|
12085
|
+
function isRemovableStatement(lines2, codeLines, idx) {
|
|
12086
|
+
const t2 = (lines2[idx] ?? "").trim();
|
|
12087
|
+
if (!(codeLines[idx] ?? "").endsWith(";")) return false;
|
|
12088
|
+
if ((codeLines[idx] ?? "").slice(0, -1).includes(";")) return false;
|
|
12089
|
+
if (!/^(?:await\s+)?[A-Za-z_$]/.test(t2)) return false;
|
|
12090
|
+
if (NON_STATEMENT_START_RE.test(t2)) return false;
|
|
12091
|
+
if (insideClassBody(codeLines, idx)) return false;
|
|
12092
|
+
const depth = scanLineDelimiters(t2);
|
|
12093
|
+
if (!depth || depth.paren !== 0 || depth.bracket !== 0 || depth.brace !== 0) {
|
|
12094
|
+
return false;
|
|
12095
|
+
}
|
|
12096
|
+
let j = idx - 1;
|
|
12097
|
+
while (j >= 0 && codeLines[j] === "") j--;
|
|
12098
|
+
if (j < 0) return true;
|
|
12099
|
+
return /[;{}]$/.test(codeLines[j]);
|
|
12100
|
+
}
|
|
12101
|
+
__name(isRemovableStatement, "isRemovableStatement");
|
|
12102
|
+
function selectMutants(files, cap = MAX_MUTANTS) {
|
|
12103
|
+
const preferred = [];
|
|
12104
|
+
const rest = [];
|
|
12105
|
+
const derailed = [];
|
|
12106
|
+
for (const f of files) {
|
|
12107
|
+
const lines2 = f.content.split("\n");
|
|
12108
|
+
const { inLiteral, codeLines, endState } = scanFileLines(f.content);
|
|
12109
|
+
if (endState !== "code") {
|
|
12110
|
+
derailed.push(f.file);
|
|
12111
|
+
continue;
|
|
12112
|
+
}
|
|
12113
|
+
for (const n of [...f.addedLines].sort((a, b) => a - b)) {
|
|
12114
|
+
const raw = lines2[n - 1];
|
|
12115
|
+
if (raw === void 0) continue;
|
|
12116
|
+
const t2 = raw.trim();
|
|
12117
|
+
if (!SAFETY_VERB_RE.test(codeLines[n - 1] ?? "")) continue;
|
|
12118
|
+
if (inLiteral[n - 1]) continue;
|
|
12119
|
+
if (!isRemovableStatement(lines2, codeLines, n - 1)) continue;
|
|
12120
|
+
(f.hasNewTests ? preferred : rest).push({
|
|
12121
|
+
file: f.file,
|
|
12122
|
+
line: n,
|
|
12123
|
+
statement: t2
|
|
12124
|
+
});
|
|
12125
|
+
}
|
|
12126
|
+
}
|
|
12127
|
+
const eligible = [...preferred, ...rest];
|
|
12128
|
+
return {
|
|
12129
|
+
selected: eligible.slice(0, cap),
|
|
12130
|
+
skippedForCap: Math.max(0, eligible.length - cap),
|
|
12131
|
+
derailed
|
|
12132
|
+
};
|
|
12133
|
+
}
|
|
12134
|
+
__name(selectMutants, "selectMutants");
|
|
12135
|
+
function parseAddedLines(diffText) {
|
|
12136
|
+
const added = /* @__PURE__ */ new Map();
|
|
12137
|
+
let file = null;
|
|
12138
|
+
let inHunk = false;
|
|
12139
|
+
let newLine = 0;
|
|
12140
|
+
for (const line of diffText.split("\n")) {
|
|
12141
|
+
if (line.startsWith("diff --git ")) {
|
|
12142
|
+
inHunk = false;
|
|
12143
|
+
continue;
|
|
12144
|
+
}
|
|
12145
|
+
if (!inHunk && line.startsWith("+++ ")) {
|
|
12146
|
+
const p = line.slice(4).split(" ")[0];
|
|
12147
|
+
file = p === "/dev/null" ? null : p.replace(/^b\//, "");
|
|
12148
|
+
continue;
|
|
12149
|
+
}
|
|
12150
|
+
const m = /^@@ -\d+(?:,\d+)? \+(\d+)(?:,\d+)? @@/.exec(line);
|
|
12151
|
+
if (m) {
|
|
12152
|
+
newLine = Number(m[1]);
|
|
12153
|
+
inHunk = true;
|
|
12154
|
+
continue;
|
|
12155
|
+
}
|
|
12156
|
+
if (!inHunk || !file) continue;
|
|
12157
|
+
if (line.startsWith("+")) {
|
|
12158
|
+
const list = added.get(file);
|
|
12159
|
+
if (list) list.push(newLine);
|
|
12160
|
+
else added.set(file, [newLine]);
|
|
12161
|
+
newLine++;
|
|
12162
|
+
} else if (!line.startsWith("-") && !line.startsWith("\\")) {
|
|
12163
|
+
newLine++;
|
|
12164
|
+
}
|
|
12165
|
+
}
|
|
12166
|
+
return added;
|
|
12167
|
+
}
|
|
12168
|
+
__name(parseAddedLines, "parseAddedLines");
|
|
12169
|
+
function hasCollocatedNewTest(file, testPaths) {
|
|
12170
|
+
const stem = file.replace(/\.[^./]+$/, "");
|
|
12171
|
+
return testPaths.some((t2) => {
|
|
12172
|
+
const tstem = t2.replace(/\.[^./]+$/, "");
|
|
12173
|
+
return tstem === `${stem}.test` || tstem === `${stem}.spec`;
|
|
12174
|
+
});
|
|
12175
|
+
}
|
|
12176
|
+
__name(hasCollocatedNewTest, "hasCollocatedNewTest");
|
|
12177
|
+
function classifyMutantRun(perFile) {
|
|
12178
|
+
if (perFile.some((r) => r.verdict === "gated")) return "killed";
|
|
12179
|
+
if (perFile.length === 0 || perFile.some((r) => r.verdict === "inconclusive"))
|
|
12180
|
+
return "inconclusive";
|
|
12181
|
+
return "survived";
|
|
12182
|
+
}
|
|
12183
|
+
__name(classifyMutantRun, "classifyMutantRun");
|
|
12184
|
+
function fitsAnotherMutantRun(remainingMs, estimatedRunMs) {
|
|
12185
|
+
return remainingMs >= estimatedRunMs;
|
|
12186
|
+
}
|
|
12187
|
+
__name(fitsAnotherMutantRun, "fitsAnotherMutantRun");
|
|
11816
12188
|
function classifyProbeRun(exitCode, stdout, probes, stderr = "") {
|
|
11817
12189
|
let parsed;
|
|
11818
12190
|
const start = stdout.indexOf("{");
|
|
@@ -11833,9 +12205,12 @@ function classifyProbeRun(exitCode, stdout, probes, stderr = "") {
|
|
|
11833
12205
|
}
|
|
11834
12206
|
const byFile = parsed.testResults ?? [];
|
|
11835
12207
|
return probes.map((file) => {
|
|
11836
|
-
const
|
|
11837
|
-
|
|
11838
|
-
|
|
12208
|
+
const probe = process.platform === "win32" ? file.replace(/\\/g, "/").toLowerCase() : file;
|
|
12209
|
+
const result = byFile.find((r) => {
|
|
12210
|
+
const raw = r.name ?? "";
|
|
12211
|
+
const name = process.platform === "win32" ? raw.replace(/\\/g, "/").toLowerCase() : raw;
|
|
12212
|
+
return name.endsWith(`/${probe}`) || name === probe;
|
|
12213
|
+
});
|
|
11839
12214
|
const assertions = result?.assertionResults ?? [];
|
|
11840
12215
|
const failed = assertions.filter((a) => a.status === "failed").length;
|
|
11841
12216
|
const passed = assertions.filter((a) => a.status === "passed").length;
|
|
@@ -11885,6 +12260,38 @@ function gitOut(cwd, ...args) {
|
|
|
11885
12260
|
return (r.stdout ?? "").trim();
|
|
11886
12261
|
}
|
|
11887
12262
|
__name(gitOut, "gitOut");
|
|
12263
|
+
function findVitestBin(worktree) {
|
|
12264
|
+
const req = createRequire(join14(worktree, "noop.js"));
|
|
12265
|
+
let pkgPath;
|
|
12266
|
+
try {
|
|
12267
|
+
pkgPath = req.resolve("vitest/package.json");
|
|
12268
|
+
} catch (error) {
|
|
12269
|
+
if (error.code === "MODULE_NOT_FOUND") {
|
|
12270
|
+
throw new Error(`vitest not found searching up from ${worktree}`);
|
|
12271
|
+
}
|
|
12272
|
+
throw error;
|
|
12273
|
+
}
|
|
12274
|
+
const pkg = JSON.parse(readFileSync18(pkgPath, "utf8"));
|
|
12275
|
+
const bin = pkg.bin?.vitest;
|
|
12276
|
+
if (!bin) {
|
|
12277
|
+
throw new Error(`vitest package at ${pkgPath} declares no "vitest" bin`);
|
|
12278
|
+
}
|
|
12279
|
+
return join14(dirname13(pkgPath), bin);
|
|
12280
|
+
}
|
|
12281
|
+
__name(findVitestBin, "findVitestBin");
|
|
12282
|
+
function gitCapture(cwd, ...args) {
|
|
12283
|
+
const r = spawnSync3("git", args, {
|
|
12284
|
+
cwd,
|
|
12285
|
+
encoding: "utf8",
|
|
12286
|
+
maxBuffer: 64 * 1024 * 1024
|
|
12287
|
+
});
|
|
12288
|
+
if (r.error) throw r.error;
|
|
12289
|
+
if (r.status !== 0) {
|
|
12290
|
+
throw new Error(`git ${args.join(" ")} failed: ${r.stderr ?? ""}`);
|
|
12291
|
+
}
|
|
12292
|
+
return r.stdout ?? "";
|
|
12293
|
+
}
|
|
12294
|
+
__name(gitCapture, "gitCapture");
|
|
11888
12295
|
function existsAtRev(cwd, rev, path3) {
|
|
11889
12296
|
const r = spawnSync3("git", ["cat-file", "-e", `${rev}:${path3}`], { cwd });
|
|
11890
12297
|
if (r.error) throw r.error;
|
|
@@ -11931,7 +12338,130 @@ function probeCleanupFailureDetail(probeTree, removeError, sweepStderr) {
|
|
|
11931
12338
|
return `could not remove probe worktree ${probeTree}${why ? `: ${why}` : ""}`;
|
|
11932
12339
|
}
|
|
11933
12340
|
__name(probeCleanupFailureDetail, "probeCleanupFailureDetail");
|
|
12341
|
+
function exposeDependencies(probeTree, dependencyRoot) {
|
|
12342
|
+
const done = { linked: 0, failed: 0 };
|
|
12343
|
+
if (probeTree === dependencyRoot) return done;
|
|
12344
|
+
const source = join14(dependencyRoot, "node_modules");
|
|
12345
|
+
const target = join14(probeTree, "node_modules");
|
|
12346
|
+
if (!existsSync7(source) || existsSync7(target)) return done;
|
|
12347
|
+
mkdirSync16(target);
|
|
12348
|
+
const linkType = process.platform === "win32" ? "junction" : "dir";
|
|
12349
|
+
for (const entry of readdirSync5(source, { withFileTypes: true })) {
|
|
12350
|
+
if (entry.name === ".vite" || entry.name === ".vite-temp") continue;
|
|
12351
|
+
const sourceEntry = join14(source, entry.name);
|
|
12352
|
+
const targetEntry = join14(target, entry.name);
|
|
12353
|
+
let sourceStats;
|
|
12354
|
+
try {
|
|
12355
|
+
sourceStats = lstatSync4(sourceEntry);
|
|
12356
|
+
} catch {
|
|
12357
|
+
done.failed++;
|
|
12358
|
+
continue;
|
|
12359
|
+
}
|
|
12360
|
+
if (sourceStats.isSymbolicLink()) {
|
|
12361
|
+
try {
|
|
12362
|
+
if (!statSync5(sourceEntry).isDirectory()) continue;
|
|
12363
|
+
} catch {
|
|
12364
|
+
continue;
|
|
12365
|
+
}
|
|
12366
|
+
} else if (!sourceStats.isDirectory()) {
|
|
12367
|
+
continue;
|
|
12368
|
+
}
|
|
12369
|
+
if (entry.name.startsWith("@")) {
|
|
12370
|
+
let pkgs;
|
|
12371
|
+
try {
|
|
12372
|
+
mkdirSync16(targetEntry);
|
|
12373
|
+
pkgs = readdirSync5(sourceEntry);
|
|
12374
|
+
} catch {
|
|
12375
|
+
done.failed++;
|
|
12376
|
+
continue;
|
|
12377
|
+
}
|
|
12378
|
+
for (const pkg of pkgs) {
|
|
12379
|
+
try {
|
|
12380
|
+
symlinkSync(join14(sourceEntry, pkg), join14(targetEntry, pkg), linkType);
|
|
12381
|
+
done.linked++;
|
|
12382
|
+
} catch {
|
|
12383
|
+
done.failed++;
|
|
12384
|
+
}
|
|
12385
|
+
}
|
|
12386
|
+
} else {
|
|
12387
|
+
try {
|
|
12388
|
+
symlinkSync(sourceEntry, targetEntry, linkType);
|
|
12389
|
+
done.linked++;
|
|
12390
|
+
} catch {
|
|
12391
|
+
done.failed++;
|
|
12392
|
+
}
|
|
12393
|
+
}
|
|
12394
|
+
}
|
|
12395
|
+
return done;
|
|
12396
|
+
}
|
|
12397
|
+
__name(exposeDependencies, "exposeDependencies");
|
|
12398
|
+
function runProbeSuite(probeTree, probes, deadlineAt, now = Date.now, dependencyRoot = probeTree) {
|
|
12399
|
+
const started = now();
|
|
12400
|
+
const timeout = deadlineAt !== void 0 ? Math.max(1, Math.min(PROBE_RUN_TIMEOUT_MS, deadlineAt - started)) : PROBE_RUN_TIMEOUT_MS;
|
|
12401
|
+
const exposed = exposeDependencies(probeTree, dependencyRoot);
|
|
12402
|
+
const r = spawnSync3(
|
|
12403
|
+
process.execPath,
|
|
12404
|
+
[findVitestBin(dependencyRoot), "run", "--reporter=json", ...probes],
|
|
12405
|
+
{
|
|
12406
|
+
cwd: probeTree,
|
|
12407
|
+
encoding: "utf8",
|
|
12408
|
+
timeout,
|
|
12409
|
+
// Vitest's JSON reporter on a large suite easily exceeds spawnSync's
|
|
12410
|
+
// 1 MiB default stdout buffer, which returns ENOBUFS and turns every
|
|
12411
|
+
// probe `inconclusive`. Match the 64 MiB ceiling the gh wrapper uses.
|
|
12412
|
+
maxBuffer: 64 * 1024 * 1024
|
|
12413
|
+
}
|
|
12414
|
+
);
|
|
12415
|
+
if (r.error) throw r.error;
|
|
12416
|
+
if (r.signal) {
|
|
12417
|
+
throw new Error(
|
|
12418
|
+
`runner killed by ${r.signal}${r.signal === "SIGTERM" ? ` (probe timed out after ${Math.round(timeout / 1e3)}s)` : ""}`
|
|
12419
|
+
);
|
|
12420
|
+
}
|
|
12421
|
+
return {
|
|
12422
|
+
perFile: classifyProbeRun(
|
|
12423
|
+
r.status ?? 1,
|
|
12424
|
+
`${r.stdout ?? ""}`,
|
|
12425
|
+
probes,
|
|
12426
|
+
`${r.stderr ?? ""}`
|
|
12427
|
+
),
|
|
12428
|
+
ms: now() - started,
|
|
12429
|
+
exposed
|
|
12430
|
+
};
|
|
12431
|
+
}
|
|
12432
|
+
__name(runProbeSuite, "runProbeSuite");
|
|
12433
|
+
function runOneMutant(probeTree, mutant, probes, deadlineAt, now = Date.now, dependencyRoot = probeTree) {
|
|
12434
|
+
const abs = join14(probeTree, mutant.file);
|
|
12435
|
+
const original = readFileSync18(abs, "utf8");
|
|
12436
|
+
const lines2 = original.split("\n");
|
|
12437
|
+
if ((lines2[mutant.line - 1] ?? "").trim() !== mutant.statement) {
|
|
12438
|
+
return {
|
|
12439
|
+
...mutant,
|
|
12440
|
+
verdict: "inconclusive",
|
|
12441
|
+
detail: "the probe tree does not match the selected statement at this line \u2014 nothing was mutated"
|
|
12442
|
+
};
|
|
12443
|
+
}
|
|
12444
|
+
lines2.splice(mutant.line - 1, 1);
|
|
12445
|
+
try {
|
|
12446
|
+
writeFileSync16(abs, lines2.join("\n"), "utf8");
|
|
12447
|
+
const { perFile } = runProbeSuite(
|
|
12448
|
+
probeTree,
|
|
12449
|
+
probes,
|
|
12450
|
+
deadlineAt,
|
|
12451
|
+
now,
|
|
12452
|
+
dependencyRoot
|
|
12453
|
+
);
|
|
12454
|
+
const verdict = classifyMutantRun(perFile);
|
|
12455
|
+
const detail = verdict === "killed" ? "the suite went red with this statement deleted \u2014 a test catches its removal" : verdict === "survived" ? "every affected test still PASSED with this statement deleted \u2014 no test fails when it is removed" : "the mutated tree produced no clean verdict (likely a compile or import error) \u2014 not evidence either way";
|
|
12456
|
+
return { ...mutant, verdict, detail };
|
|
12457
|
+
} finally {
|
|
12458
|
+
writeFileSync16(abs, original, "utf8");
|
|
12459
|
+
}
|
|
12460
|
+
}
|
|
12461
|
+
__name(runOneMutant, "runOneMutant");
|
|
11934
12462
|
async function runTestEfficacy(args) {
|
|
12463
|
+
const now = args.now ?? Date.now;
|
|
12464
|
+
const startedAt = now();
|
|
11935
12465
|
const { report, worktree, base, out } = args;
|
|
11936
12466
|
const plan = JSON.parse(readFileSync18(report, "utf8"));
|
|
11937
12467
|
const rootPkg = JSON.parse(
|
|
@@ -11953,8 +12483,69 @@ async function runTestEfficacy(args) {
|
|
|
11953
12483
|
}
|
|
11954
12484
|
const results = [];
|
|
11955
12485
|
let cleanupFailure;
|
|
12486
|
+
const mutantResults = [];
|
|
12487
|
+
let mutantsSkippedForBudget = 0;
|
|
12488
|
+
let mutantsSkippedForCap = 0;
|
|
12489
|
+
let mutantsSkippedForBaseline = 0;
|
|
12490
|
+
let mutantsNote;
|
|
12491
|
+
const noteMutants = /* @__PURE__ */ __name((note) => {
|
|
12492
|
+
mutantsNote = mutantsNote ? `${mutantsNote}; ${note}` : note;
|
|
12493
|
+
}, "noteMutants");
|
|
12494
|
+
const noteDependencyFarm = /* @__PURE__ */ __name((exposed) => {
|
|
12495
|
+
if (exposed.failed > 0) {
|
|
12496
|
+
noteMutants(
|
|
12497
|
+
`dependency farm incomplete: exposed ${exposed.linked}/${exposed.linked + exposed.failed} dependencies into the probe tree (${exposed.failed} failed to link) \u2014 probe results may not be evidence`
|
|
12498
|
+
);
|
|
12499
|
+
}
|
|
12500
|
+
}, "noteDependencyFarm");
|
|
11956
12501
|
if (probes.length > 0 && revert.length > 0) {
|
|
11957
12502
|
const headSha = gitOut(worktree, "rev-parse", "HEAD");
|
|
12503
|
+
let candidates = [];
|
|
12504
|
+
try {
|
|
12505
|
+
const mutantFiles = revert.filter(
|
|
12506
|
+
(p) => MUTANT_SOURCE_RE.test(p) && !DECLARATION_FILE_RE.test(p)
|
|
12507
|
+
);
|
|
12508
|
+
if (mutantFiles.length > 0) {
|
|
12509
|
+
const added = parseAddedLines(
|
|
12510
|
+
gitCapture(
|
|
12511
|
+
worktree,
|
|
12512
|
+
"-c",
|
|
12513
|
+
"core.quotePath=false",
|
|
12514
|
+
"diff",
|
|
12515
|
+
"--unified=0",
|
|
12516
|
+
"--no-color",
|
|
12517
|
+
"--src-prefix=a/",
|
|
12518
|
+
"--dst-prefix=b/",
|
|
12519
|
+
"--no-ext-diff",
|
|
12520
|
+
"--no-textconv",
|
|
12521
|
+
base,
|
|
12522
|
+
headSha,
|
|
12523
|
+
"--",
|
|
12524
|
+
...mutantFiles
|
|
12525
|
+
)
|
|
12526
|
+
);
|
|
12527
|
+
const selection = selectMutants(
|
|
12528
|
+
mutantFiles.filter((p) => (added.get(p) ?? []).length > 0).map((p) => ({
|
|
12529
|
+
file: p,
|
|
12530
|
+
content: gitCapture(worktree, "show", `${headSha}:${p}`),
|
|
12531
|
+
addedLines: added.get(p) ?? [],
|
|
12532
|
+
hasNewTests: hasCollocatedNewTest(p, probes)
|
|
12533
|
+
}))
|
|
12534
|
+
);
|
|
12535
|
+
candidates = selection.selected;
|
|
12536
|
+
mutantsSkippedForCap = selection.skippedForCap;
|
|
12537
|
+
if (selection.derailed.length > 0) {
|
|
12538
|
+
noteMutants(
|
|
12539
|
+
`mutant selection dropped ${selection.derailed.length} file(s) whose literal scan derailed (${selection.derailed.join(", ")}) \u2014 a regex literal holding a quote or backtick can do this; their candidates were not probed`
|
|
12540
|
+
);
|
|
12541
|
+
}
|
|
12542
|
+
}
|
|
12543
|
+
} catch (e) {
|
|
12544
|
+
noteMutants(
|
|
12545
|
+
`mutant selection failed: ${e instanceof Error ? e.message : String(e)} \u2014 no mutants were run`
|
|
12546
|
+
);
|
|
12547
|
+
candidates = [];
|
|
12548
|
+
}
|
|
11958
12549
|
const probeTree = probeWorktreePath(worktree);
|
|
11959
12550
|
let created = false;
|
|
11960
12551
|
let sweep;
|
|
@@ -11967,6 +12558,57 @@ async function runTestEfficacy(args) {
|
|
|
11967
12558
|
for (const file of probes) {
|
|
11968
12559
|
results.push({ file, verdict: "inconclusive", detail });
|
|
11969
12560
|
}
|
|
12561
|
+
for (const c of candidates) {
|
|
12562
|
+
mutantResults.push({ ...c, verdict: "inconclusive", detail });
|
|
12563
|
+
}
|
|
12564
|
+
}
|
|
12565
|
+
if (created && candidates.length > 0) {
|
|
12566
|
+
try {
|
|
12567
|
+
const mutantDeadline = startedAt + TOTAL_BUDGET_MS - PROBE_RUN_TIMEOUT_MS;
|
|
12568
|
+
const baseline = runProbeSuite(
|
|
12569
|
+
probeTree,
|
|
12570
|
+
probes,
|
|
12571
|
+
mutantDeadline,
|
|
12572
|
+
now,
|
|
12573
|
+
worktree
|
|
12574
|
+
);
|
|
12575
|
+
noteDependencyFarm(baseline.exposed);
|
|
12576
|
+
const greenProbes = baseline.perFile.filter((r) => r.verdict === "inert").map((r) => r.file);
|
|
12577
|
+
if (greenProbes.length === 0) {
|
|
12578
|
+
mutantsSkippedForBaseline = candidates.length;
|
|
12579
|
+
noteMutants(
|
|
12580
|
+
"mutants not run: no probe file was green in the unmutated baseline (every file was red or collected nothing), so a red mutant run would prove nothing"
|
|
12581
|
+
);
|
|
12582
|
+
} else {
|
|
12583
|
+
const estimatedRunMs = baseline.ms + RUN_ESTIMATE_MARGIN_MS;
|
|
12584
|
+
for (const c of candidates) {
|
|
12585
|
+
const remaining = mutantDeadline - now();
|
|
12586
|
+
if (!fitsAnotherMutantRun(remaining, estimatedRunMs)) {
|
|
12587
|
+
mutantsSkippedForBudget = candidates.length - mutantResults.length;
|
|
12588
|
+
break;
|
|
12589
|
+
}
|
|
12590
|
+
mutantResults.push(
|
|
12591
|
+
runOneMutant(
|
|
12592
|
+
probeTree,
|
|
12593
|
+
c,
|
|
12594
|
+
greenProbes,
|
|
12595
|
+
mutantDeadline,
|
|
12596
|
+
now,
|
|
12597
|
+
worktree
|
|
12598
|
+
)
|
|
12599
|
+
);
|
|
12600
|
+
}
|
|
12601
|
+
}
|
|
12602
|
+
} catch (e) {
|
|
12603
|
+
const detail = `mutation probe could not run: ${e instanceof Error ? e.message : String(e)}`;
|
|
12604
|
+
for (const c of candidates.slice(mutantResults.length)) {
|
|
12605
|
+
mutantResults.push({
|
|
12606
|
+
...c,
|
|
12607
|
+
verdict: "inconclusive",
|
|
12608
|
+
detail
|
|
12609
|
+
});
|
|
12610
|
+
}
|
|
12611
|
+
}
|
|
11970
12612
|
}
|
|
11971
12613
|
if (created) {
|
|
11972
12614
|
try {
|
|
@@ -11979,33 +12621,15 @@ async function runTestEfficacy(args) {
|
|
|
11979
12621
|
git2(probeTree, "checkout", base, "--", ...modified);
|
|
11980
12622
|
}
|
|
11981
12623
|
for (const p of added) safeRmWithin(probeTree, p);
|
|
11982
|
-
const
|
|
11983
|
-
|
|
11984
|
-
|
|
11985
|
-
|
|
11986
|
-
|
|
11987
|
-
|
|
11988
|
-
timeout: 3e5,
|
|
11989
|
-
// Vitest's JSON reporter on a large suite easily exceeds spawnSync's
|
|
11990
|
-
// 1 MiB default stdout buffer, which returns ENOBUFS and turns every
|
|
11991
|
-
// probe `inconclusive`. Match the 64 MiB ceiling the gh wrapper uses.
|
|
11992
|
-
maxBuffer: 64 * 1024 * 1024
|
|
11993
|
-
}
|
|
11994
|
-
);
|
|
11995
|
-
if (r.error) throw r.error;
|
|
11996
|
-
if (r.signal) {
|
|
11997
|
-
throw new Error(
|
|
11998
|
-
`runner killed by ${r.signal}${r.signal === "SIGTERM" ? " (probe timed out after 300s)" : ""}`
|
|
11999
|
-
);
|
|
12000
|
-
}
|
|
12001
|
-
results.push(
|
|
12002
|
-
...classifyProbeRun(
|
|
12003
|
-
r.status ?? 1,
|
|
12004
|
-
`${r.stdout ?? ""}`,
|
|
12005
|
-
probes,
|
|
12006
|
-
`${r.stderr ?? ""}`
|
|
12007
|
-
)
|
|
12624
|
+
const revertRun = runProbeSuite(
|
|
12625
|
+
probeTree,
|
|
12626
|
+
probes,
|
|
12627
|
+
startedAt + TOTAL_BUDGET_MS,
|
|
12628
|
+
now,
|
|
12629
|
+
worktree
|
|
12008
12630
|
);
|
|
12631
|
+
noteDependencyFarm(revertRun.exposed);
|
|
12632
|
+
results.push(...revertRun.perFile);
|
|
12009
12633
|
} catch (e) {
|
|
12010
12634
|
const detail = `probe could not run: ${e instanceof Error ? e.message : String(e)}`;
|
|
12011
12635
|
results.push(
|
|
@@ -12043,23 +12667,57 @@ async function runTestEfficacy(args) {
|
|
|
12043
12667
|
file: r.file,
|
|
12044
12668
|
kind: "inert",
|
|
12045
12669
|
message: `\`${r.file}\`: ${r.detail}. It passes whether or not the change is present, so it cannot catch a regression in it.`
|
|
12670
|
+
})),
|
|
12671
|
+
...mutantResults.filter((m) => m.verdict === "survived").map((m) => ({
|
|
12672
|
+
file: m.file,
|
|
12673
|
+
kind: "mutant-survived",
|
|
12674
|
+
message: `\`${m.file}:${m.line}\`: deleting the added safety statement \`${m.statement}\` leaves every affected test green. No test in this diff fails when it is removed \u2014 confirm an existing test covers it, or add one, so a regression that drops or skips this statement is caught.`
|
|
12046
12675
|
}))
|
|
12047
12676
|
];
|
|
12677
|
+
const count = /* @__PURE__ */ __name((v) => mutantResults.filter((m) => m.verdict === v).length, "count");
|
|
12048
12678
|
const result = {
|
|
12049
12679
|
unreachable,
|
|
12050
12680
|
probed: results,
|
|
12051
12681
|
inconclusive: results.filter((r) => r.verdict === "inconclusive"),
|
|
12682
|
+
mutants: {
|
|
12683
|
+
probed: mutantResults,
|
|
12684
|
+
killed: count("killed"),
|
|
12685
|
+
survived: count("survived"),
|
|
12686
|
+
inconclusive: count("inconclusive"),
|
|
12687
|
+
skippedForBudget: mutantsSkippedForBudget,
|
|
12688
|
+
skippedForCap: mutantsSkippedForCap,
|
|
12689
|
+
skippedForBaseline: mutantsSkippedForBaseline,
|
|
12690
|
+
...mutantsNote ? { note: mutantsNote } : {}
|
|
12691
|
+
},
|
|
12052
12692
|
findings,
|
|
12053
12693
|
cleanupFailure
|
|
12054
12694
|
};
|
|
12055
12695
|
mkdirSync16(dirname13(out), { recursive: true });
|
|
12056
12696
|
writeFileSync16(out, JSON.stringify(result, null, 2), "utf8");
|
|
12057
12697
|
writeStdoutLine(
|
|
12058
|
-
`Wrote test-efficacy report to ${out} (${unreachable.length} unreachable, ${results.length} probed, ${findings.length} finding(s))`
|
|
12698
|
+
`Wrote test-efficacy report to ${out} (${unreachable.length} unreachable, ${results.length} probed, ${mutantResults.length} mutant(s), ${findings.length} finding(s))`
|
|
12059
12699
|
);
|
|
12060
12700
|
for (const f of findings) {
|
|
12061
12701
|
writeStdoutLine(` [test] ${f.kind}: ${f.file}`);
|
|
12062
12702
|
}
|
|
12703
|
+
if (mutantsSkippedForCap > 0) {
|
|
12704
|
+
writeStdoutLine(
|
|
12705
|
+
` ${mutantsSkippedForCap} mutant(s) skipped: more candidates than the cap of ${MAX_MUTANTS}`
|
|
12706
|
+
);
|
|
12707
|
+
}
|
|
12708
|
+
if (mutantsSkippedForBaseline > 0) {
|
|
12709
|
+
writeStdoutLine(
|
|
12710
|
+
` ${mutantsSkippedForBaseline} mutant(s) skipped: no probe file was green in the unmutated baseline`
|
|
12711
|
+
);
|
|
12712
|
+
}
|
|
12713
|
+
if (mutantsSkippedForBudget > 0) {
|
|
12714
|
+
writeStdoutLine(
|
|
12715
|
+
` ${mutantsSkippedForBudget} mutant(s) skipped: the remaining budget cannot fit another suite run`
|
|
12716
|
+
);
|
|
12717
|
+
}
|
|
12718
|
+
if (mutantsNote) {
|
|
12719
|
+
writeStdoutLine(` ${mutantsNote}`);
|
|
12720
|
+
}
|
|
12063
12721
|
if (cleanupFailure) {
|
|
12064
12722
|
writeStderrLine(`WARNING: ${cleanupFailure}`);
|
|
12065
12723
|
}
|
|
@@ -12067,7 +12725,7 @@ async function runTestEfficacy(args) {
|
|
|
12067
12725
|
__name(runTestEfficacy, "runTestEfficacy");
|
|
12068
12726
|
var testEfficacyCommand = {
|
|
12069
12727
|
command: "test-efficacy <report>",
|
|
12070
|
-
describe: "Check whether the diff's new tests actually gate its new behaviour (unreachable + revert probe)",
|
|
12728
|
+
describe: "Check whether the diff's new tests actually gate its new behaviour (unreachable + revert probe + statement-deletion mutants)",
|
|
12071
12729
|
builder: /* @__PURE__ */ __name((yargs) => yargs.positional("report", {
|
|
12072
12730
|
type: "string",
|
|
12073
12731
|
demandOption: true,
|
|
@@ -12093,7 +12751,7 @@ var testEfficacyCommand = {
|
|
|
12093
12751
|
// packages/cli/src/commands/review/cleanup.ts
|
|
12094
12752
|
init_esbuild_shims();
|
|
12095
12753
|
import { execFileSync as execFileSync5 } from "node:child_process";
|
|
12096
|
-
import { existsSync as existsSync8, readFileSync as readFileSync19, readdirSync as
|
|
12754
|
+
import { existsSync as existsSync8, readFileSync as readFileSync19, readdirSync as readdirSync6, rmSync as rmSync7 } from "node:fs";
|
|
12097
12755
|
import { join as join15 } from "node:path";
|
|
12098
12756
|
var AUTOMATION_MARKER = "<!-- qwen-";
|
|
12099
12757
|
function isAutomationComment(body) {
|
|
@@ -12291,7 +12949,7 @@ function runCleanup(target) {
|
|
|
12291
12949
|
const prefix = tmpPrefix(target);
|
|
12292
12950
|
let tmpEntries = [];
|
|
12293
12951
|
try {
|
|
12294
|
-
tmpEntries = existsSync8(REVIEW_TMP_DIR) ?
|
|
12952
|
+
tmpEntries = existsSync8(REVIEW_TMP_DIR) ? readdirSync6(REVIEW_TMP_DIR) : [];
|
|
12295
12953
|
} catch (err) {
|
|
12296
12954
|
writeStderrLine(
|
|
12297
12955
|
`Failed to read ${REVIEW_TMP_DIR}: ${err.message}`
|
|
@@ -12330,13 +12988,285 @@ var cleanupCommand = {
|
|
|
12330
12988
|
}, "handler")
|
|
12331
12989
|
};
|
|
12332
12990
|
|
|
12991
|
+
// packages/cli/src/commands/review/run.ts
|
|
12992
|
+
init_esbuild_shims();
|
|
12993
|
+
import { spawn, execFileSync as execFileSync6 } from "node:child_process";
|
|
12994
|
+
import { readdirSync as readdirSync7, readFileSync as readFileSync20, statSync as statSync6 } from "node:fs";
|
|
12995
|
+
import { join as join16, resolve as resolve13 } from "node:path";
|
|
12996
|
+
var COMPOSED_PATTERN = /^qwen-review-.*composed\.json$/;
|
|
12997
|
+
var COMPOSED_POLL_MS = 250;
|
|
12998
|
+
var SIGNAL_EXIT_CODES = {
|
|
12999
|
+
SIGHUP: 129,
|
|
13000
|
+
SIGINT: 130,
|
|
13001
|
+
SIGTERM: 143
|
|
13002
|
+
};
|
|
13003
|
+
var PARENT_SIGNALS = Object.keys(SIGNAL_EXIT_CODES);
|
|
13004
|
+
function buildReviewPrompt(args) {
|
|
13005
|
+
const parts = ["/review"];
|
|
13006
|
+
if (args.target) {
|
|
13007
|
+
if (/\s/.test(args.target) || args.target.startsWith("-") || /['"]/.test(args.target)) {
|
|
13008
|
+
throw new Error(
|
|
13009
|
+
`Invalid review target ${JSON.stringify(args.target)}: expected a single PR number, PR URL, or file path`
|
|
13010
|
+
);
|
|
13011
|
+
}
|
|
13012
|
+
parts.push(args.target);
|
|
13013
|
+
}
|
|
13014
|
+
if (args.effort) parts.push(`--effort ${args.effort}`);
|
|
13015
|
+
if (args.comment) parts.push("--comment");
|
|
13016
|
+
return parts.join(" ");
|
|
13017
|
+
}
|
|
13018
|
+
__name(buildReviewPrompt, "buildReviewPrompt");
|
|
13019
|
+
function newestArtifactSince(dir, pattern, startMs) {
|
|
13020
|
+
let best = null;
|
|
13021
|
+
let names;
|
|
13022
|
+
try {
|
|
13023
|
+
names = readdirSync7(dir);
|
|
13024
|
+
} catch {
|
|
13025
|
+
return null;
|
|
13026
|
+
}
|
|
13027
|
+
for (const name of names) {
|
|
13028
|
+
if (!pattern.test(name)) continue;
|
|
13029
|
+
const path3 = join16(dir, name);
|
|
13030
|
+
let mtime;
|
|
13031
|
+
try {
|
|
13032
|
+
mtime = statSync6(path3).mtimeMs;
|
|
13033
|
+
} catch {
|
|
13034
|
+
continue;
|
|
13035
|
+
}
|
|
13036
|
+
if (mtime < startMs) continue;
|
|
13037
|
+
if (!best || mtime > best.mtime) best = { path: path3, mtime };
|
|
13038
|
+
}
|
|
13039
|
+
return best ? best.path : null;
|
|
13040
|
+
}
|
|
13041
|
+
__name(newestArtifactSince, "newestArtifactSince");
|
|
13042
|
+
function exitCodeFor(completed, event, failOn) {
|
|
13043
|
+
if (!completed) return 1;
|
|
13044
|
+
if (failOn === "request-changes" && event === "REQUEST_CHANGES") return 3;
|
|
13045
|
+
return 0;
|
|
13046
|
+
}
|
|
13047
|
+
__name(exitCodeFor, "exitCodeFor");
|
|
13048
|
+
function readComposed(path3) {
|
|
13049
|
+
try {
|
|
13050
|
+
const parsed = JSON.parse(readFileSync20(path3, "utf8"));
|
|
13051
|
+
return typeof parsed.event === "string" ? parsed : null;
|
|
13052
|
+
} catch {
|
|
13053
|
+
return null;
|
|
13054
|
+
}
|
|
13055
|
+
}
|
|
13056
|
+
__name(readComposed, "readComposed");
|
|
13057
|
+
function killProcessGroup(pid, signal) {
|
|
13058
|
+
if (process.platform === "win32") {
|
|
13059
|
+
try {
|
|
13060
|
+
execFileSync6("taskkill", ["/pid", String(pid), "/T", "/F"], {
|
|
13061
|
+
stdio: "ignore"
|
|
13062
|
+
});
|
|
13063
|
+
} catch {
|
|
13064
|
+
}
|
|
13065
|
+
return;
|
|
13066
|
+
}
|
|
13067
|
+
try {
|
|
13068
|
+
process.kill(-pid, signal);
|
|
13069
|
+
} catch {
|
|
13070
|
+
}
|
|
13071
|
+
}
|
|
13072
|
+
__name(killProcessGroup, "killProcessGroup");
|
|
13073
|
+
async function runReview(args) {
|
|
13074
|
+
const startMs = Date.now();
|
|
13075
|
+
const prompt = buildReviewPrompt(args);
|
|
13076
|
+
const cutoffMs = startMs - 2e3;
|
|
13077
|
+
const child = spawn(
|
|
13078
|
+
process.execPath,
|
|
13079
|
+
[
|
|
13080
|
+
"--expose-gc",
|
|
13081
|
+
process.argv[1],
|
|
13082
|
+
"--prompt",
|
|
13083
|
+
prompt,
|
|
13084
|
+
"--approval-mode",
|
|
13085
|
+
args.approvalMode
|
|
13086
|
+
],
|
|
13087
|
+
{
|
|
13088
|
+
// stdin CLOSED, not inherited: piped input would be prepended to the
|
|
13089
|
+
// prompt and the leading `/` would no longer be the first character —
|
|
13090
|
+
// the slash command would reach the model as plain text.
|
|
13091
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
13092
|
+
// The CLI relaunches itself in a child (for --max-old-space-size), so
|
|
13093
|
+
// the pid we spawn is a wrapper whose grandchild is the real review.
|
|
13094
|
+
// A new process group lets the timeout kill reach both.
|
|
13095
|
+
detached: true
|
|
13096
|
+
}
|
|
13097
|
+
);
|
|
13098
|
+
if (!args.quiet) {
|
|
13099
|
+
const writeProgress = /* @__PURE__ */ __name((chunk) => {
|
|
13100
|
+
try {
|
|
13101
|
+
process.stderr.write(chunk);
|
|
13102
|
+
} catch {
|
|
13103
|
+
}
|
|
13104
|
+
}, "writeProgress");
|
|
13105
|
+
child.stdout?.on("data", writeProgress);
|
|
13106
|
+
child.stderr?.on("data", writeProgress);
|
|
13107
|
+
} else {
|
|
13108
|
+
child.stdout?.resume();
|
|
13109
|
+
child.stderr?.resume();
|
|
13110
|
+
}
|
|
13111
|
+
let capturedPath = null;
|
|
13112
|
+
let capturedVerdict = null;
|
|
13113
|
+
const captureTimer = setInterval(() => {
|
|
13114
|
+
if (capturedVerdict !== null) return;
|
|
13115
|
+
const path3 = newestArtifactSince(
|
|
13116
|
+
REVIEW_TMP_DIR,
|
|
13117
|
+
COMPOSED_PATTERN,
|
|
13118
|
+
cutoffMs
|
|
13119
|
+
);
|
|
13120
|
+
if (path3 === null) return;
|
|
13121
|
+
const verdict = readComposed(path3);
|
|
13122
|
+
if (verdict !== null) {
|
|
13123
|
+
capturedPath = path3;
|
|
13124
|
+
capturedVerdict = verdict;
|
|
13125
|
+
}
|
|
13126
|
+
}, COMPOSED_POLL_MS);
|
|
13127
|
+
let timedOut = false;
|
|
13128
|
+
const timeoutMs = args.timeoutMinutes * 6e4;
|
|
13129
|
+
const timer = setTimeout(() => {
|
|
13130
|
+
timedOut = true;
|
|
13131
|
+
writeStderrLineSafe(
|
|
13132
|
+
`review run: timeout after ${args.timeoutMinutes} minutes \u2014 terminating the review`
|
|
13133
|
+
);
|
|
13134
|
+
const pid = child.pid;
|
|
13135
|
+
if (pid !== void 0) {
|
|
13136
|
+
killProcessGroup(pid, "SIGTERM");
|
|
13137
|
+
setTimeout(() => killProcessGroup(pid, "SIGKILL"), 1e4).unref();
|
|
13138
|
+
}
|
|
13139
|
+
}, timeoutMs);
|
|
13140
|
+
const onParentSignal = /* @__PURE__ */ __name((signal) => {
|
|
13141
|
+
clearTimeout(timer);
|
|
13142
|
+
clearInterval(captureTimer);
|
|
13143
|
+
const pid = child.pid;
|
|
13144
|
+
if (pid !== void 0) {
|
|
13145
|
+
killProcessGroup(pid, "SIGTERM");
|
|
13146
|
+
}
|
|
13147
|
+
process.exit(SIGNAL_EXIT_CODES[signal] ?? 1);
|
|
13148
|
+
}, "onParentSignal");
|
|
13149
|
+
for (const signal of PARENT_SIGNALS) process.on(signal, onParentSignal);
|
|
13150
|
+
const childOutcome = await new Promise((resolvePromise) => {
|
|
13151
|
+
child.on("close", (code, signal) => resolvePromise({ code, signal }));
|
|
13152
|
+
child.on("error", (err) => {
|
|
13153
|
+
writeStderrLineSafe(
|
|
13154
|
+
`review run: failed to launch the CLI: ${err.message}`
|
|
13155
|
+
);
|
|
13156
|
+
resolvePromise({ code: null, signal: null });
|
|
13157
|
+
});
|
|
13158
|
+
});
|
|
13159
|
+
const childExitCode = childOutcome.code;
|
|
13160
|
+
const childSignal = childOutcome.signal;
|
|
13161
|
+
clearTimeout(timer);
|
|
13162
|
+
clearInterval(captureTimer);
|
|
13163
|
+
for (const signal of PARENT_SIGNALS) process.off(signal, onParentSignal);
|
|
13164
|
+
let composedPath = capturedPath;
|
|
13165
|
+
let composed = capturedVerdict;
|
|
13166
|
+
if (composed === null) {
|
|
13167
|
+
composedPath = newestArtifactSince(
|
|
13168
|
+
REVIEW_TMP_DIR,
|
|
13169
|
+
COMPOSED_PATTERN,
|
|
13170
|
+
cutoffMs
|
|
13171
|
+
);
|
|
13172
|
+
composed = composedPath ? readComposed(composedPath) : null;
|
|
13173
|
+
}
|
|
13174
|
+
const reportPath = newestArtifactSince(REVIEWS_DIR, /\.md$/, cutoffMs);
|
|
13175
|
+
const completed = composed !== null;
|
|
13176
|
+
const result = {
|
|
13177
|
+
completed,
|
|
13178
|
+
event: composed?.event ?? null,
|
|
13179
|
+
verdictLine: composed?.verdictLine ?? null,
|
|
13180
|
+
baseEvent: composed?.baseEvent ?? null,
|
|
13181
|
+
cappedBy: composed?.cappedBy ?? [],
|
|
13182
|
+
downgraded: composed?.downgraded ?? false,
|
|
13183
|
+
downgradedFrom: composed?.downgradedFrom ?? null,
|
|
13184
|
+
remediation: composed?.remediation ?? [],
|
|
13185
|
+
composedPath: composedPath ? resolve13(composedPath) : null,
|
|
13186
|
+
reportPath: reportPath ? resolve13(reportPath) : null,
|
|
13187
|
+
childExitCode,
|
|
13188
|
+
childSignal,
|
|
13189
|
+
timedOut,
|
|
13190
|
+
durationMs: Date.now() - startMs
|
|
13191
|
+
};
|
|
13192
|
+
process.exitCode = exitCodeFor(completed, result.event, args.failOn);
|
|
13193
|
+
try {
|
|
13194
|
+
if (args.json) {
|
|
13195
|
+
writeStdoutLine(JSON.stringify(result, null, 2));
|
|
13196
|
+
} else if (completed) {
|
|
13197
|
+
writeStdoutLine(result.verdictLine ?? `Event: ${result.event}`);
|
|
13198
|
+
if (result.reportPath) writeStdoutLine(`Report: ${result.reportPath}`);
|
|
13199
|
+
} else {
|
|
13200
|
+
const detail = composedPath !== null ? `a composed verdict was found at ${resolve13(composedPath)} but could not be parsed` : "no composed verdict was produced";
|
|
13201
|
+
writeStdoutLine(
|
|
13202
|
+
timedOut ? "Review did not complete: timed out." : `Review did not complete: ${detail}${childExitCode !== null ? ` (CLI exit ${childExitCode})` : ""}${childSignal !== null ? ` (killed by ${childSignal})` : ""}.`
|
|
13203
|
+
);
|
|
13204
|
+
}
|
|
13205
|
+
} catch {
|
|
13206
|
+
}
|
|
13207
|
+
}
|
|
13208
|
+
__name(runReview, "runReview");
|
|
13209
|
+
var runCommand = {
|
|
13210
|
+
command: "run [target]",
|
|
13211
|
+
describe: "Run a full /review non-interactively and print the verdict (machine-readable with --json)",
|
|
13212
|
+
builder: /* @__PURE__ */ __name((yargs) => yargs.positional("target", {
|
|
13213
|
+
type: "string",
|
|
13214
|
+
describe: "What to review: a PR number, a PR URL, or a file path; omit to review the local working tree"
|
|
13215
|
+
}).option("effort", {
|
|
13216
|
+
type: "string",
|
|
13217
|
+
choices: [...EFFORT_LEVELS],
|
|
13218
|
+
describe: "The review effort. Defaults to the skill default for the target (high for a PR, medium locally)."
|
|
13219
|
+
}).option("comment", {
|
|
13220
|
+
type: "boolean",
|
|
13221
|
+
default: false,
|
|
13222
|
+
describe: "Authorise posting the review to GitHub (PR targets only) \u2014 same meaning as `/review <pr> --comment`"
|
|
13223
|
+
}).option("json", {
|
|
13224
|
+
type: "boolean",
|
|
13225
|
+
default: false,
|
|
13226
|
+
describe: "Print the full result as JSON on stdout"
|
|
13227
|
+
}).option("fail-on", {
|
|
13228
|
+
type: "string",
|
|
13229
|
+
choices: ["none", "request-changes"],
|
|
13230
|
+
default: "none",
|
|
13231
|
+
describe: "Exit 3 when the review completes with this outcome \u2014 lets CI gate on the verdict without parsing output"
|
|
13232
|
+
}).option("timeout-minutes", {
|
|
13233
|
+
type: "number",
|
|
13234
|
+
default: 120,
|
|
13235
|
+
describe: "Terminate the review after this long without a verdict (exit 1)"
|
|
13236
|
+
}).option("approval-mode", {
|
|
13237
|
+
type: "string",
|
|
13238
|
+
default: "yolo",
|
|
13239
|
+
choices: ["plan", "default", "auto-edit", "auto", "yolo"],
|
|
13240
|
+
describe: "Approval mode for the child CLI. The default is yolo: headless runs cannot answer confirmation prompts, and anything still unapproved would be auto-denied mid-review."
|
|
13241
|
+
}).option("quiet", {
|
|
13242
|
+
type: "boolean",
|
|
13243
|
+
default: false,
|
|
13244
|
+
describe: "Suppress the child CLI progress stream on stderr"
|
|
13245
|
+
}), "builder"),
|
|
13246
|
+
handler: /* @__PURE__ */ __name(async (argv) => {
|
|
13247
|
+
await runReview({
|
|
13248
|
+
target: argv["target"],
|
|
13249
|
+
effort: argv["effort"],
|
|
13250
|
+
comment: Boolean(argv["comment"]),
|
|
13251
|
+
json: Boolean(argv["json"]),
|
|
13252
|
+
failOn: argv["fail-on"] ?? "none",
|
|
13253
|
+
// `|| 120` would treat an explicit `--timeout-minutes 0` as falsy and
|
|
13254
|
+
// silently substitute the default; decide default-vs-value by finiteness
|
|
13255
|
+
// so 0 still reaches the 1-minute floor.
|
|
13256
|
+
timeoutMinutes: Number.isFinite(Number(argv["timeout-minutes"])) ? Math.max(1, Number(argv["timeout-minutes"])) : 120,
|
|
13257
|
+
approvalMode: String(argv["approval-mode"] ?? "yolo"),
|
|
13258
|
+
quiet: Boolean(argv["quiet"])
|
|
13259
|
+
});
|
|
13260
|
+
}, "handler")
|
|
13261
|
+
};
|
|
13262
|
+
|
|
12333
13263
|
// packages/cli/src/commands/review.ts
|
|
12334
13264
|
var reviewCommand = {
|
|
12335
13265
|
command: "review",
|
|
12336
|
-
describe: "
|
|
12337
|
-
builder: /* @__PURE__ */ __name((yargs) => yargs.command(parseArgsCommand).command(fetchPrCommand).command(captureLocalCommand).command(planDiffCommand).command(prContextCommand).command(commentStatusCommand).command(loadRulesCommand).command(agentPromptCommand).command(buildTestCommand).command(scriptLintCommand).command(resolveAnchorsCommand).command(checkCoverageCommand).command(presubmitCommand).command(testEfficacyCommand).command(composeReviewCommand).command(submitCommand).command(cleanupCommand).demandCommand(
|
|
13266
|
+
describe: "Run a review non-interactively (`run`), plus the internal helpers used by the /review skill (PR worktree setup, context fetch, rules loading, presubmit checks, cleanup)",
|
|
13267
|
+
builder: /* @__PURE__ */ __name((yargs) => yargs.command(runCommand).command(parseArgsCommand).command(fetchPrCommand).command(captureLocalCommand).command(planDiffCommand).command(prContextCommand).command(commentStatusCommand).command(loadRulesCommand).command(agentPromptCommand).command(buildTestCommand).command(scriptLintCommand).command(resolveAnchorsCommand).command(checkCoverageCommand).command(presubmitCommand).command(testEfficacyCommand).command(composeReviewCommand).command(submitCommand).command(cleanupCommand).demandCommand(
|
|
12338
13268
|
1,
|
|
12339
|
-
"Specify a subcommand: parse-args, fetch-pr, capture-local, plan-diff, pr-context, comment-status, load-rules, agent-prompt, build-test, script-lint, resolve-anchors, check-coverage, presubmit, test-efficacy, compose-review, submit, or cleanup."
|
|
13269
|
+
"Specify a subcommand: run, parse-args, fetch-pr, capture-local, plan-diff, pr-context, comment-status, load-rules, agent-prompt, build-test, script-lint, resolve-anchors, check-coverage, presubmit, test-efficacy, compose-review, submit, or cleanup."
|
|
12340
13270
|
).version(false), "builder"),
|
|
12341
13271
|
handler: /* @__PURE__ */ __name(() => {
|
|
12342
13272
|
}, "handler")
|
|
@@ -12536,10 +13466,10 @@ var updateCommand3 = {
|
|
|
12536
13466
|
stdioHelpers,
|
|
12537
13467
|
{ updateEventEmitter }
|
|
12538
13468
|
] = await Promise.all([
|
|
12539
|
-
import("./settings-
|
|
12540
|
-
import("./updateCheck-
|
|
12541
|
-
import("./installationInfo-
|
|
12542
|
-
import("./standalone-update-
|
|
13469
|
+
import("./settings-CUN3SELH.js"),
|
|
13470
|
+
import("./updateCheck-ZHVXDAIH.js"),
|
|
13471
|
+
import("./installationInfo-R7FXPQN5.js"),
|
|
13472
|
+
import("./standalone-update-TMLT6LVJ.js"),
|
|
12543
13473
|
import("./stdioHelpers-HGIYTWAY.js"),
|
|
12544
13474
|
import("./updateEventEmitter-5MKC7BLQ.js")
|
|
12545
13475
|
]);
|
|
@@ -12649,6 +13579,16 @@ var VALID_APPROVAL_MODE_VALUES = [
|
|
|
12649
13579
|
"auto",
|
|
12650
13580
|
"yolo"
|
|
12651
13581
|
];
|
|
13582
|
+
var SKILL_LEVELS = [
|
|
13583
|
+
"project",
|
|
13584
|
+
"user",
|
|
13585
|
+
"extension",
|
|
13586
|
+
"bundled"
|
|
13587
|
+
];
|
|
13588
|
+
function isSkillLevel(value) {
|
|
13589
|
+
return SKILL_LEVELS.includes(value);
|
|
13590
|
+
}
|
|
13591
|
+
__name(isSkillLevel, "isSkillLevel");
|
|
12652
13592
|
function formatApprovalModeError(value) {
|
|
12653
13593
|
return new Error(
|
|
12654
13594
|
`Invalid approval mode: ${value}. Valid values are: ${VALID_APPROVAL_MODE_VALUES.join(
|
|
@@ -13364,7 +14304,18 @@ function buildDisabledSkillNamesProvider(loadedSettings) {
|
|
|
13364
14304
|
return () => resolveSkillSettings(loadedSettings).disabledNames;
|
|
13365
14305
|
}
|
|
13366
14306
|
__name(buildDisabledSkillNamesProvider, "buildDisabledSkillNamesProvider");
|
|
13367
|
-
|
|
14307
|
+
var SessionIdConflictError = class extends Error {
|
|
14308
|
+
static {
|
|
14309
|
+
__name(this, "SessionIdConflictError");
|
|
14310
|
+
}
|
|
14311
|
+
sessionId;
|
|
14312
|
+
constructor(sessionId, message) {
|
|
14313
|
+
super(message);
|
|
14314
|
+
this.name = "SessionIdConflictError";
|
|
14315
|
+
this.sessionId = sessionId;
|
|
14316
|
+
}
|
|
14317
|
+
};
|
|
14318
|
+
async function loadCliConfig(settings, argv, cwd = process.cwd(), overrideExtensions, hooksConfig, disabledSkillNamesProvider, sessionMcpServers, settingsWatcher, throwOnSessionIdConflict = false) {
|
|
13368
14319
|
const debugMode = isDebugMode(argv);
|
|
13369
14320
|
if (debugMode && process.env["QWEN_DEBUG_LOG_FILE"] === void 0) {
|
|
13370
14321
|
process.env["QWEN_DEBUG_LOG_FILE"] = "1";
|
|
@@ -13651,6 +14602,9 @@ async function loadCliConfig(settings, argv, cwd = process.cwd(), overrideExtens
|
|
|
13651
14602
|
);
|
|
13652
14603
|
if (exists) {
|
|
13653
14604
|
const message = `Error: Session Id ${argv["sessionId"]} already exists (active or archived). Delete or unarchive it first.`;
|
|
14605
|
+
if (throwOnSessionIdConflict) {
|
|
14606
|
+
throw new SessionIdConflictError(argv["sessionId"], message);
|
|
14607
|
+
}
|
|
13654
14608
|
writeStderrLine(message);
|
|
13655
14609
|
process.exit(1);
|
|
13656
14610
|
}
|
|
@@ -13681,11 +14635,13 @@ async function loadCliConfig(settings, argv, cwd = process.cwd(), overrideExtens
|
|
|
13681
14635
|
excludeTools: mergedDeny,
|
|
13682
14636
|
disabledSlashCommands: disabledSlashCommands.length > 0 ? disabledSlashCommands : void 0,
|
|
13683
14637
|
disabledSkillNamesProvider: bareMode || safeMode ? void 0 : disabledSkillNamesProvider,
|
|
14638
|
+
disabledSkillLevels: bareMode || safeMode || !Array.isArray(settings.skills?.disabledLevels) ? void 0 : settings.skills.disabledLevels.filter(isSkillLevel),
|
|
13684
14639
|
customSkillDirs: bareMode || safeMode ? void 0 : (Array.isArray(settings.skills?.directories) ? settings.skills.directories : []).filter(
|
|
13685
14640
|
(d) => typeof d === "string" && d.trim().length > 0
|
|
13686
14641
|
).map((d) => d.trim()),
|
|
13687
14642
|
disabledTools: disabledTools.length > 0 ? disabledTools : void 0,
|
|
13688
14643
|
visibleTools: visibleTools.length > 0 ? visibleTools : void 0,
|
|
14644
|
+
toolSearchThreshold: bareMode || safeMode ? 0 : settings.tools?.toolSearch?.threshold,
|
|
13689
14645
|
// New unified permissions (PermissionManager source of truth).
|
|
13690
14646
|
permissions: {
|
|
13691
14647
|
allow: mergedAllow.length > 0 ? mergedAllow : void 0,
|
|
@@ -13796,6 +14752,7 @@ async function loadCliConfig(settings, argv, cwd = process.cwd(), overrideExtens
|
|
|
13796
14752
|
bareMode,
|
|
13797
14753
|
safeMode,
|
|
13798
14754
|
allowedHttpHookUrls: bareMode || safeMode ? [] : settings.security?.allowedHttpHookUrls ?? [],
|
|
14755
|
+
allowPrivateNetworkHooks: bareMode || safeMode ? false : settings.security?.allowPrivateNetworkHooks ?? false,
|
|
13799
14756
|
cliVersion: await getCliVersion(),
|
|
13800
14757
|
ideMode,
|
|
13801
14758
|
chatCompression: settings.model?.chatCompression,
|
|
@@ -14089,6 +15046,7 @@ export {
|
|
|
14089
15046
|
loadHierarchicalGeminiMemory,
|
|
14090
15047
|
isDebugMode,
|
|
14091
15048
|
buildDisabledSkillNamesProvider,
|
|
15049
|
+
SessionIdConflictError,
|
|
14092
15050
|
loadCliConfig,
|
|
14093
15051
|
EXTENSION_RELOAD_FAILED_REASON,
|
|
14094
15052
|
ExtensionRefreshState
|