gerege-cli 0.26.5 → 0.26.6
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/README.md +8 -8
- package/chunks/{MaxSizedBox-VMVLMS4X.js → MaxSizedBox-QCIXIS4P.js} +1 -1
- package/chunks/{StandaloneSessionPicker-UNORCVYY.js → StandaloneSessionPicker-BAFAIRT7.js} +1 -1
- package/chunks/{acp-subagent-executor-623ZUTJT.js → acp-subagent-executor-TPVXURLW.js} +1 -1
- package/chunks/{acpAgent-MTTDTK2C.js → acpAgent-67UN66PB.js} +3 -3
- package/chunks/{advisor-ANUGICJ5.js → advisor-SAXMI4QZ.js} +1 -1
- package/chunks/{agent-GNCQDICJ.js → agent-KV7BXY6C.js} +1 -1
- package/chunks/{agent-headless-OPUXAXQM.js → agent-headless-FQX3JGG6.js} +1 -1
- package/chunks/{agent-host-client-K6GRPTFD.js → agent-host-client-L5EHC4AC.js} +1 -1
- package/chunks/{agent-host-connections-MF3YBZU2.js → agent-host-connections-EDBMCVQF.js} +1 -1
- package/chunks/{anthropicContentGenerator-OK4PFE5Y.js → anthropicContentGenerator-V7TX2NXP.js} +1 -1
- package/chunks/{autofix-pr-MABTGEHZ.js → autofix-pr-WP34NYHL.js} +1 -1
- package/chunks/{batch-V2NJT3M5.js → batch-XFVQ4BLM.js} +1 -1
- package/chunks/{bridge-BJQ627CX.js → bridge-AE7AFEXB.js} +1 -1
- package/chunks/{channel-settings-store-4JMCI4UR.js → channel-settings-store-X63P5OVT.js} +1 -1
- package/chunks/{chunk-ZN57TOVA.js → chunk-2DU2WMTL.js} +1 -1
- package/chunks/{chunk-Z5XENA4A.js → chunk-2JGTWRZJ.js} +8 -7
- package/chunks/{chunk-MTW3A3KT.js → chunk-2LWJGXTW.js} +1 -1
- package/chunks/{chunk-OCBJCZC2.js → chunk-2N3NBTYJ.js} +1 -1
- package/chunks/{chunk-WI4UMN3Q.js → chunk-2TAJ5STJ.js} +1 -1
- package/chunks/{chunk-EIILQ6KT.js → chunk-32XHDDIA.js} +1 -1
- package/chunks/{chunk-FNXO5KWB.js → chunk-34HC2AXI.js} +2 -2
- package/chunks/{chunk-2X3UF2CF.js → chunk-3W32X2DH.js} +1 -1
- package/chunks/{chunk-CKZRJP4F.js → chunk-4ME3BUJK.js} +1 -1
- package/chunks/{chunk-NVSKOSFG.js → chunk-4NDJKNN6.js} +1 -1
- package/chunks/{chunk-BRPJ5EHA.js → chunk-5EXL4TKQ.js} +1 -1
- package/chunks/{chunk-3XBJYUWP.js → chunk-65ME4BOH.js} +1 -1
- package/chunks/{chunk-TQTIEK2W.js → chunk-7453BHJO.js} +1 -1
- package/chunks/{chunk-HSYBIGMS.js → chunk-76FSYQTG.js} +1 -1
- package/chunks/{chunk-FNB3DPQZ.js → chunk-7RNOS7R4.js} +1 -1
- package/chunks/{chunk-H57IX45A.js → chunk-AEKEZRIU.js} +1 -1
- package/chunks/{chunk-CXGGC4NO.js → chunk-AEZYXPFS.js} +1 -1
- package/chunks/{chunk-NGOIJH7K.js → chunk-AFO5ER23.js} +1 -1
- package/chunks/{chunk-UY2ET2AL.js → chunk-AYVCT5FF.js} +1 -1
- package/chunks/{chunk-QOYRDEXR.js → chunk-B37YY4XU.js} +1 -1
- package/chunks/{chunk-IDUGQMTP.js → chunk-BAUMVH4Q.js} +1 -1
- package/chunks/{chunk-CAPG7UVH.js → chunk-BCI62WSL.js} +1 -1
- package/chunks/{chunk-USJFJZ23.js → chunk-BGELKSQ4.js} +1 -1
- package/chunks/{chunk-6X73W4TL.js → chunk-BHIDG6VZ.js} +1 -1
- package/chunks/{chunk-26ISBUM7.js → chunk-BPFFRPWE.js} +6 -6
- package/chunks/{chunk-YGHM5CDT.js → chunk-BQZF3UKI.js} +1 -1
- package/chunks/{chunk-3NQESE5K.js → chunk-CBE6ZIHU.js} +1 -1
- package/chunks/{chunk-DEMXCA3K.js → chunk-CF6SZJNP.js} +1 -1
- package/chunks/{chunk-2VCDJ6UF.js → chunk-CGDFZEER.js} +1 -1
- package/chunks/{chunk-3WQPUP5U.js → chunk-CUP2TNJK.js} +1 -1
- package/chunks/{chunk-2IGE2K5V.js → chunk-DA6LOBSB.js} +1 -1
- package/chunks/{chunk-HFV6CQWE.js → chunk-EFIRES46.js} +1 -1
- package/chunks/{chunk-E5YRAQXM.js → chunk-EKRUF347.js} +1 -1
- package/chunks/{chunk-KN27BFXM.js → chunk-ELDZ4MNL.js} +1 -1
- package/chunks/{chunk-ADTFKUH2.js → chunk-ET5M5WFN.js} +1 -1
- package/chunks/{chunk-IBYFSHBB.js → chunk-EXIFPXMB.js} +1 -1
- package/chunks/{chunk-IA4K4PGK.js → chunk-EYPLBTMI.js} +1 -1
- package/chunks/{chunk-DTTC4ZKY.js → chunk-FEP6W4NJ.js} +1 -1
- package/chunks/{chunk-FHBGTZ4K.js → chunk-FKL3V5BO.js} +1 -1
- package/chunks/{chunk-Q5E5SOY2.js → chunk-FKZ46GKL.js} +1 -1
- package/chunks/{chunk-OPYGNTZP.js → chunk-FYBJGRX7.js} +1 -1
- package/chunks/{chunk-FPZPCZFS.js → chunk-G6DALGGS.js} +1 -1
- package/chunks/{chunk-3Y6LSWEW.js → chunk-GBSRWT7J.js} +1 -1
- package/chunks/{chunk-SMYBY353.js → chunk-GHIFIXNX.js} +1 -1
- package/chunks/{chunk-DE53B2R7.js → chunk-GRAECADD.js} +1 -1
- package/chunks/{chunk-UJYOILZR.js → chunk-GSPGIGO5.js} +3 -3
- package/chunks/{chunk-5UZT4SXG.js → chunk-H3IR3GIE.js} +1 -1
- package/chunks/{chunk-ADZI3OFT.js → chunk-HOG66S6K.js} +1 -1
- package/chunks/{chunk-WB34KMOT.js → chunk-HTAUIJB4.js} +1 -1
- package/chunks/{chunk-MPAR4JBP.js → chunk-I6PUY2T3.js} +1 -1
- package/chunks/{chunk-5ZQWQ3RK.js → chunk-IZ5MWA6E.js} +1 -1
- package/chunks/{chunk-7IERHQ63.js → chunk-JEDL4IKF.js} +1 -1
- package/chunks/{chunk-RVJJFDF3.js → chunk-JH3V5SPA.js} +1 -1
- package/chunks/{chunk-SELRSZFK.js → chunk-JRTOPEM3.js} +1 -1
- package/chunks/{chunk-SQQORHMS.js → chunk-JWNKPINR.js} +1 -1
- package/chunks/{chunk-55RVKT4O.js → chunk-KJGRCIVY.js} +1 -1
- package/chunks/{chunk-GSOBASYW.js → chunk-KZNYALFU.js} +1 -1
- package/chunks/{chunk-FDUXQAGW.js → chunk-LBLLWAKK.js} +1 -1
- package/chunks/{chunk-ZSVSRF4C.js → chunk-LT3J74BZ.js} +1 -1
- package/chunks/{chunk-AMTFJVDD.js → chunk-LTE4N6L3.js} +1 -1
- package/chunks/{chunk-F26LTWDZ.js → chunk-M6KB5RVD.js} +1 -1
- package/chunks/{chunk-2PY7R7GG.js → chunk-MGATL4OA.js} +1 -1
- package/chunks/{chunk-KGJ47CI5.js → chunk-MPVQDYPH.js} +1 -1
- package/chunks/{chunk-BBOJUFMW.js → chunk-MTDBCIDA.js} +1 -1
- package/chunks/{chunk-ZYTG6R7S.js → chunk-MYV7GY3H.js} +1 -1
- package/chunks/{chunk-4GC5HJZO.js → chunk-N7PWZBXV.js} +1 -1
- package/chunks/{chunk-2NOMOJWE.js → chunk-NA4ZF2FE.js} +2 -2
- package/chunks/{chunk-7MTBINFX.js → chunk-NEKPQLFY.js} +2 -2
- package/chunks/{chunk-ABJGFEES.js → chunk-NO7VTKRL.js} +1 -1
- package/chunks/{chunk-OHXQYU6S.js → chunk-NONBHCXP.js} +1 -1
- package/chunks/{chunk-ZOBX6C7E.js → chunk-NVOI6UDQ.js} +1 -1
- package/chunks/{chunk-YLAI26PX.js → chunk-OJ4K62S2.js} +1 -1
- package/chunks/{chunk-CCOUFBOY.js → chunk-OK7LBM5G.js} +1 -1
- package/chunks/{chunk-POA4NX4N.js → chunk-OOJ2AQT3.js} +1 -1
- package/chunks/{chunk-5WLKN3GD.js → chunk-OU7CEG7Q.js} +1 -1
- package/chunks/{chunk-4TYTJQWR.js → chunk-P3JEEDQZ.js} +1 -1
- package/chunks/{chunk-AQWHCRKY.js → chunk-P62S5JGM.js} +1 -1
- package/chunks/{chunk-B6D3KTUK.js → chunk-QDCUR3JB.js} +1 -1
- package/chunks/{chunk-XFLLE2J3.js → chunk-RSLTOIG5.js} +2 -2
- package/chunks/{chunk-ISGF3BVD.js → chunk-RXN7DUMP.js} +2 -2
- package/chunks/{chunk-PN62SUYK.js → chunk-SKGJ26HQ.js} +1 -1
- package/chunks/{chunk-62NLMVVT.js → chunk-SP6CQ3MO.js} +1 -1
- package/chunks/{chunk-4EQWJTJR.js → chunk-T2YTHAJW.js} +1 -1
- package/chunks/{chunk-NO26JN24.js → chunk-T53VMDXH.js} +1 -1
- package/chunks/{chunk-X4BFEDWU.js → chunk-T5DKF33F.js} +1 -1
- package/chunks/{chunk-KKBOCRPF.js → chunk-TB4AUC2L.js} +1 -1
- package/chunks/{chunk-Q6QS5JTK.js → chunk-U3Q72OGV.js} +1 -1
- package/chunks/{chunk-FLJLUMQF.js → chunk-UKLXKJKL.js} +1 -1
- package/chunks/{chunk-IH2PFVWO.js → chunk-VD2GSW64.js} +1 -1
- package/chunks/{chunk-VDRE7U3P.js → chunk-VRKYBH5G.js} +5 -5
- package/chunks/{chunk-MOPJNP5I.js → chunk-W2RQIZ6B.js} +1 -1
- package/chunks/{chunk-2LLPGSUK.js → chunk-W5Z4BWWA.js} +1 -1
- package/chunks/{chunk-CNFA5UUM.js → chunk-W66WWTOP.js} +1 -1
- package/chunks/{chunk-C56YJIEI.js → chunk-WGFX3EL3.js} +1 -1
- package/chunks/{chunk-6NI33TVK.js → chunk-X2TY7VTY.js} +1 -1
- package/chunks/{chunk-FIM7MM25.js → chunk-XISR37DQ.js} +1 -1
- package/chunks/{chunk-KDYUZBZC.js → chunk-YH2XRWRF.js} +1 -1
- package/chunks/{chunk-UBXLQ6TP.js → chunk-ZENMAISJ.js} +1 -1
- package/chunks/{codex-subagent-executor-EK3A2WBH.js → codex-subagent-executor-OLMGVPVS.js} +1 -1
- package/chunks/{config-utils-DLOK7OLM.js → config-utils-OWY5G5Y2.js} +1 -1
- package/chunks/{contextCommand-AVCUCHQC.js → contextCommand-IXFUZH65.js} +1 -1
- package/chunks/{core-runtime-QSS4ZTG6.js → core-runtime-O4LC4NY3.js} +1 -1
- package/chunks/{create-sub-session-PNF7QDKC.js → create-sub-session-6F7C3TMT.js} +1 -1
- package/chunks/{cron-create-C6JOFIU4.js → cron-create-2422NBSJ.js} +1 -1
- package/chunks/{daemon-git-worktree-guard-5XZAZ7D2.js → daemon-git-worktree-guard-EWPQA6NO.js} +1 -1
- package/chunks/{daemon-status-provider-MRNELSNJ.js → daemon-status-provider-FAHOXNFW.js} +1 -1
- package/chunks/{daemon-trust-policy-26CMW3WY.js → daemon-trust-policy-L3DM6AI5.js} +1 -1
- package/chunks/{daemon-trust-policy-monitor-3DWO6NQY.js → daemon-trust-policy-monitor-HNPY5KJ4.js} +1 -1
- package/chunks/{deferred-core-runtime-DEC3N46T.js → deferred-core-runtime-JF42NQJK.js} +1 -1
- package/chunks/{edit-3HMQPCHN.js → edit-E5LEI2LL.js} +1 -1
- package/chunks/{enterPlanMode-QHJF4JXZ.js → enterPlanMode-3COTUV5V.js} +1 -1
- package/chunks/{environment-NGIBJWOT.js → environment-XBBIB3VA.js} +1 -1
- package/chunks/{errors-MSTGCVGJ.js → errors-LNMQ7TUK.js} +1 -1
- package/chunks/{execution-tool-VR4TGOI4.js → execution-tool-QDDKJD2K.js} +1 -1
- package/chunks/{execution-worker-EJH7HIE2.js → execution-worker-TXGZRZXE.js} +1 -1
- package/chunks/{exitPlanMode-P25OHQJ6.js → exitPlanMode-Z7QEMWPE.js} +1 -1
- package/chunks/{fast-path-II433ZDP.js → fast-path-M6K2RACY.js} +1 -1
- package/chunks/{glob-4Q6DCT3F.js → glob-N2QT4U7U.js} +1 -1
- package/chunks/{goal-tools-FFMAJW6V.js → goal-tools-CUSQD3DG.js} +1 -1
- package/chunks/{handleAutoUpdate-QNM26NZK.js → handleAutoUpdate-QF2YQHF6.js} +1 -1
- package/chunks/{i18n-L5URVOBB.js → i18n-AGOA6MUI.js} +1 -1
- package/chunks/{initializer-NQ2NECYP.js → initializer-FRKYDUSX.js} +1 -1
- package/chunks/{installationInfo-BCTXASUM.js → installationInfo-OKA4WXAS.js} +1 -1
- package/chunks/{interactive-mod-session-PPTBI37E.js → interactive-mod-session-MWYN5IFK.js} +1 -1
- package/chunks/{list-7TE5TUZJ.js → list-DE7VUIR2.js} +1 -1
- package/chunks/{llm-BWWKUBBZ.js → llm-N3JGJHYC.js} +4 -4
- package/chunks/{llm-content-generator-QOTGPBYC.js → llm-content-generator-VMUBA7OJ.js} +1 -1
- package/chunks/{loadedSettingsAdapter-THAGI5M2.js → loadedSettingsAdapter-5C36OZ7N.js} +1 -1
- package/chunks/{local-7BTAGV4J.js → local-BE624O3A.js} +1 -1
- package/chunks/{local-execution-environment-S3OR4KSC.js → local-execution-environment-OPGM7Y6L.js} +1 -1
- package/chunks/{loggingContentGenerator-AXJ5E5RS.js → loggingContentGenerator-2MHAI6JR.js} +1 -1
- package/chunks/{loop-wakeup-AJTLMLRX.js → loop-wakeup-BDLATBXH.js} +1 -1
- package/chunks/{manage-memory-JHTUVMDJ.js → manage-memory-BBCEIIWB.js} +1 -1
- package/chunks/{managed-execution-engine-U6GNJ4U4.js → managed-execution-engine-SRFALTCX.js} +1 -1
- package/chunks/{managed-local-serve-P4ZXVRBU.js → managed-local-serve-ICNAS3E6.js} +1 -1
- package/chunks/{managed-npm-update-UDUILNR5.js → managed-npm-update-CTL6LH5Z.js} +1 -1
- package/chunks/{managed-runtime-attestation-worker-P34ZBNRG.js → managed-runtime-attestation-worker-ZRDWKXCI.js} +1 -1
- package/chunks/{managed-runtime-bootstrap-CLMYNPH5.js → managed-runtime-bootstrap-6NTGZXQL.js} +1 -1
- package/chunks/{managed-runtime-session-worker-7H7AZJBV.js → managed-runtime-session-worker-RKQBBFR6.js} +1 -1
- package/chunks/{managed-runtime-ssh-worker-5KEMC7FD.js → managed-runtime-ssh-worker-FCGV6FSW.js} +1 -1
- package/chunks/{managed-session-authority-CFUZ45HT.js → managed-session-authority-C7IW6TJX.js} +1 -1
- package/chunks/{mcp-YMG4RVMC.js → mcp-VC4CJPE5.js} +1 -1
- package/chunks/{memory-7STURUXK.js → memory-S6OJA3ZD.js} +1 -1
- package/chunks/mn-JMS6SWTO.js +8 -0
- package/chunks/{model-call-collection-WBWTO3EG.js → model-call-collection-MJZWRQSU.js} +1 -1
- package/chunks/{model-configuration-6KCZZSZD.js → model-configuration-SKU6L3QI.js} +1 -1
- package/chunks/{modelConfigUtils-Z2EKFSPN.js → modelConfigUtils-TJCB6NXT.js} +1 -1
- package/chunks/{monitor-U5E33JO6.js → monitor-M3PNLCYP.js} +1 -1
- package/chunks/{nonInteractiveCli-BVCL5I5R.js → nonInteractiveCli-MR7JLAWU.js} +1 -1
- package/chunks/{nonInteractiveToolExecutor-B4EUOMYF.js → nonInteractiveToolExecutor-YKA6JMTY.js} +1 -1
- package/chunks/{notebook-edit-MXKD5J2C.js → notebook-edit-ENTFB5D7.js} +1 -1
- package/chunks/{omni-I5YECZBW.js → omni-6YBX4R6K.js} +1 -1
- package/chunks/{openaiContentGenerator-Q5SINFJJ.js → openaiContentGenerator-XRXX33FY.js} +1 -1
- package/chunks/{openaiResponsesContentGenerator-R3XCZLZY.js → openaiResponsesContentGenerator-L6ONEHMR.js} +1 -1
- package/chunks/{pidfile-UOGUNUTK.js → pidfile-XR4JF2Z6.js} +1 -1
- package/chunks/{processUtils-QGQGZHBA.js → processUtils-GQYNJRBJ.js} +1 -1
- package/chunks/{prompt-terminal-ledger-L57JMVSR.js → prompt-terminal-ledger-7BM7YDLG.js} +1 -1
- package/chunks/{qwenContentGenerator-UKZ237LC.js → qwenContentGenerator-QSA32XEL.js} +1 -1
- package/chunks/{reactive-degrade-3OM3HWVA.js → reactive-degrade-TFNBAAPZ.js} +1 -1
- package/chunks/{read-file-63ZLWMOW.js → read-file-VD7OFO2E.js} +1 -1
- package/chunks/{resumeHistoryUtils-R5YQS4YQ.js → resumeHistoryUtils-2B4KPI7G.js} +1 -1
- package/chunks/{review-AT6OWVDO.js → review-C365WGCW.js} +1 -1
- package/chunks/{ripGrep-7KBZGTPV.js → ripGrep-D7WPMBXR.js} +1 -1
- package/chunks/{run-qwen-serve-CLBG7W6F.js → run-qwen-serve-NZWQHWQA.js} +1 -1
- package/chunks/{runtime-R3QIGB7U.js → runtime-J6SPBSCS.js} +1 -1
- package/chunks/{sandboxConfig-PM3ZRQYV.js → sandboxConfig-QS2XBPZG.js} +1 -1
- package/chunks/{scheduled-tasks-PUMNN5XV.js → scheduled-tasks-YNNIOOPM.js} +1 -1
- package/chunks/{scheduler-KTPM226B.js → scheduler-KCMSPHON.js} +1 -1
- package/chunks/{search-memory-7I5MGDNV.js → search-memory-EUBJ7IAV.js} +1 -1
- package/chunks/{send-message-J526AEBI.js → send-message-CWWZUPSK.js} +1 -1
- package/chunks/{serve-KLTMPK4W.js → serve-4CB4BWJ5.js} +1 -1
- package/chunks/{server-VLRNY6KG.js → server-JNANUIGC.js} +3 -3
- package/chunks/{session-2EB57NXY.js → session-3LQLXPUA.js} +1 -1
- package/chunks/{session-attachments-root-I7TESMWL.js → session-attachments-root-BWIVWFHJ.js} +1 -1
- package/chunks/{session-execution-engine-selector-5FAMSPSO.js → session-execution-engine-selector-5OLRX57L.js} +1 -1
- package/chunks/{session-pr-refresh-JCPVQPNJ.js → session-pr-refresh-RLF3EXS3.js} +1 -1
- package/chunks/{sessionService-YRW2IFPR.js → sessionService-U7ACD2HP.js} +1 -1
- package/chunks/{settings-KO2Q47JP.js → settings-FTGWYTUH.js} +1 -1
- package/chunks/{shell-OLZVNTQZ.js → shell-E4RENYQC.js} +1 -1
- package/chunks/{skill-XW2AQS7M.js → skill-OLNPHRWB.js} +1 -1
- package/chunks/{skill-settings-TKAVQ4XP.js → skill-settings-R2BV2GEK.js} +1 -1
- package/chunks/{spawnChannel-MBGCTK2J.js → spawnChannel-LOPAR5T2.js} +1 -1
- package/chunks/{standalone-update-A3YLLIAN.js → standalone-update-IGDX2RGN.js} +1 -1
- package/chunks/{start-opentui-ui-G5ROAR4V.js → start-opentui-ui-33QLBNRC.js} +1 -1
- package/chunks/{startInteractiveUI-PZQR4U53.js → startInteractiveUI-RQKHD7MM.js} +1 -1
- package/chunks/{team-create-S5ZY2UMF.js → team-create-HAVKHNU5.js} +1 -1
- package/chunks/{team-plan-approval-KX6RXEST.js → team-plan-approval-7MCQX67C.js} +1 -1
- package/chunks/{terminal-image-renderer-SCJREXE6.js → terminal-image-renderer-XT5JVEO6.js} +1 -1
- package/chunks/{theme-manager-DZSM4EBR.js → theme-manager-DR5EYGLT.js} +1 -1
- package/chunks/{tool-call-UK56SWCT.js → tool-call-LZHZ5RVH.js} +1 -1
- package/chunks/{tool-result-media-JLLSLGFL.js → tool-result-media-XCXCF4YC.js} +1 -1
- package/chunks/{tool-search-OWPFLVV5.js → tool-search-K6S3ON7M.js} +1 -1
- package/chunks/{total-session-admission-NQU4ACKH.js → total-session-admission-LGSS2VWS.js} +1 -1
- package/chunks/{trustedFolders-N7GXFYSF.js → trustedFolders-IIR2UZRL.js} +1 -1
- package/chunks/{update-relaunch-5SPXXHM2.js → update-relaunch-WVIFX5CN.js} +1 -1
- package/chunks/{updateCheck-VXUIX2XG.js → updateCheck-CMEWLLZJ.js} +1 -1
- package/chunks/{upload-config-OWLL4SRQ.js → upload-config-TCCFCNCD.js} +1 -1
- package/chunks/{useAutoAcceptIndicator-OUYRR56F.js → useAutoAcceptIndicator-5RTTH3OW.js} +1 -1
- package/chunks/{validateNonInterActiveAuth-PSVJO5HK.js → validateNonInterActiveAuth-AO336KDX.js} +1 -1
- package/chunks/{version-C26S7UAW.js → version-JYWKKMNP.js} +1 -1
- package/chunks/{web-fetch-AYOYV7R4.js → web-fetch-HWTAWXFM.js} +1 -1
- package/chunks/{web-search-DAREKD3Z.js → web-search-HAI5LW3G.js} +1 -1
- package/chunks/{workflow-WBGPKVO6.js → workflow-BZ2YFGF6.js} +1 -1
- package/chunks/{workflow-ancestor-trust-GEEB53TB.js → workflow-ancestor-trust-26TFXFPO.js} +1 -1
- package/chunks/{workspace-agents-IMAQME4W.js → workspace-agents-DLI4JQJZ.js} +1 -1
- package/chunks/{workspace-providers-status-VALHVEU2.js → workspace-providers-status-64C7DJZU.js} +1 -1
- package/chunks/{workspace-recovery-worker-AIAVRDGU.js → workspace-recovery-worker-IFRT3KKP.js} +1 -1
- package/chunks/{workspace-registration-store-FXEGZG3L.js → workspace-registration-store-MYKJM2SK.js} +1 -1
- package/chunks/{workspace-registry-GYFFHWCD.js → workspace-registry-GZJRONAY.js} +1 -1
- package/chunks/{workspace-runtime-coordinator-VZ462TLU.js → workspace-runtime-coordinator-44KW6HSN.js} +1 -1
- package/chunks/{workspace-service-5DIZM4IZ.js → workspace-service-YHTSZYYD.js} +1 -1
- package/chunks/{workspace-skills-status-DOOBVL5N.js → workspace-skills-status-NEB62X24.js} +1 -1
- package/chunks/{workspace-trust-reconciler-LOICVUVW.js → workspace-trust-reconciler-HZLOOZWM.js} +1 -1
- package/chunks/{write-file-EJNMAHQD.js → write-file-HD5LHXGL.js} +1 -1
- package/chunks/{zoom-image-S3OARMYP.js → zoom-image-W4BMRC5T.js} +1 -1
- package/cli.js +2 -2
- package/execution-worker.js +1 -1
- package/export-transcript-document.js +1 -1
- package/gerege.mjs +53 -15
- package/locales/mn.js +2702 -3774
- package/package.json +3 -3
- package/chunks/mn-YH2OTBWJ.js +0 -8
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// Force strict mode and setup for ESM
|
|
2
2
|
"use strict";
|
|
3
|
-
import{LEASE_PREFIX,REVIEW_TMP_DIR,inertPath,reviewBranch,reviewTrustStateDir}from"./chunk-
|
|
3
|
+
import{LEASE_PREFIX,REVIEW_TMP_DIR,inertPath,reviewBranch,reviewTrustStateDir}from"./chunk-T53VMDXH.js";import{writeStderrLineSafe}from"./chunk-M4ECEHLX.js";import{createDebugLogger}from"./chunk-JAUJI56S.js";import{init_esbuild_shims}from"./chunk-VKDAXTCZ.js";import{__name}from"./chunk-KBWJGX7I.js";init_esbuild_shims();import{execFileSync}from"node:child_process";import{randomBytes}from"node:crypto";import{existsSync,lstatSync,mkdirSync,readFileSync,readdirSync,renameSync,rmdirSync,rmSync,writeFileSync}from"node:fs";import{basename,dirname,isAbsolute,join,relative,resolve}from"node:path";var GIT_TIMEOUT_MS=12e4;var debugLogger=createDebugLogger("REVIEW_WORKTREE_LEASE");function gitOptions(timeout){return{stdio:"ignore",timeout,env:{...process.env,GIT_TERMINAL_PROMPT:"0"}}}__name(gitOptions,"gitOptions");function validTarget(target){return/^pr-\d+$/.test(target)}__name(validTarget,"validTarget");function isReviewLeaseFile(fileName){if(!fileName.startsWith(LEASE_PREFIX)||!fileName.endsWith(".json")){return false}const target=fileName.slice(LEASE_PREFIX.length,fileName.length-".json".length);return validTarget(target)}__name(isReviewLeaseFile,"isReviewLeaseFile");function leaseDirectory(repositoryRoot){return reviewTrustStateDir(repositoryRoot)}__name(leaseDirectory,"leaseDirectory");function legacyLeasePath(repositoryRoot,target){return join(repositoryRoot,REVIEW_TMP_DIR,`${LEASE_PREFIX}${target}.json`)}__name(legacyLeasePath,"legacyLeasePath");function leasePath(repositoryRoot,target){return join(leaseDirectory(repositoryRoot),`${LEASE_PREFIX}${target}.json`)}__name(leasePath,"leasePath");function clearReviewWorktreeLease(repositoryRoot,target){if(!validTarget(target))return;const root=resolve(repositoryRoot);rmSync(leasePath(root,target),{force:true});reclaimBaseTreeTrust(root,target);const legacy=legacyLeasePath(root,target);try{rmSync(legacy,{force:true,recursive:true})}catch(error){writeStderrLineSafe(`warning: could not remove the pre-move review lease at ${legacy} (${error.code??error}); the trusted lease for ${target} is released, but a build from before the lease move will keep seeing this one until it is deleted by hand.`)}}__name(clearReviewWorktreeLease,"clearReviewWorktreeLease");function clearReviewWorktreeLeaseIfOwned(repositoryRoot,target,owner){const lease=readReviewWorktreeLease(repositoryRoot,target);if(!lease||lease.sessionId!==owner.sessionId||lease.promptId!==owner.promptId){return}clearReviewWorktreeLease(repositoryRoot,target)}__name(clearReviewWorktreeLeaseIfOwned,"clearReviewWorktreeLeaseIfOwned");function mintIdentity(){return Math.floor(Date.now()/1e3)*2**20+randomBytes(3).readUIntBE(0,3)%2**20}__name(mintIdentity,"mintIdentity");function recordReviewWorktreeLeaseMergeBase(repositoryRoot,target,mergeBaseSha,sessionId,options={}){if(!validTarget(target)||!mergeBaseSha)return;const stale=options.stale===true;const root=resolve(repositoryRoot);const path=leasePath(root,target);const existing=readLease(path);if(!existing)return;if(sessionId!==void 0&&existing.sessionId!==sessionId)return;if(existing.mergeBaseSha===mergeBaseSha&&existing.mergeBaseStale===true===stale){return}const previous=existing.mergeBaseSha??existing.priorMergeBaseSha;const next={...existing,mergeBaseSha,mergeBaseStale:stale,priorMergeBaseSha:mergeBaseSha,priorMergeBaseStale:stale,priorMergeBaseCurrent:true,identity:previous===void 0||previous===mergeBaseSha?existing.identity??mintIdentity():mintIdentity()};try{atomicWriteLease(path,`${JSON.stringify(next,null,2)}
|
|
4
4
|
`)}catch(error){debugLogger.debug(`Failed to record the merge base in ${path}:`,error)}}__name(recordReviewWorktreeLeaseMergeBase,"recordReviewWorktreeLeaseMergeBase");function atomicWriteLease(path,data){const tmp=`${path}.${process.pid}.${randomBytes(6).toString("hex")}.tmp`;try{writeFileSync(tmp,data,{encoding:"utf8",flag:"wx"});renameSync(tmp,path)}catch(error){try{rmSync(tmp,{force:true})}catch{}throw error}}__name(atomicWriteLease,"atomicWriteLease");function reclaimBaseTreeTrust(root,target){const dir=join(leaseDirectory(root),"base-tree",target);let entries;try{entries=readdirSync(dir)}catch(error){if(error.code!=="ENOENT"){debugLogger.debug(`Failed to reclaim base-tree trust state for ${target}:`,error)}return}for(const name of entries){if(name.endsWith(".lock"))continue;try{rmSync(join(dir,name),{recursive:true,force:true})}catch(error){debugLogger.debug(`Failed to reclaim base-tree trust state ${name} for ${target}:`,error)}}try{rmdirSync(dir)}catch{}}__name(reclaimBaseTreeTrust,"reclaimBaseTreeTrust");function restoreReviewWorktreeLeaseMergeBase(repositoryRoot,target,sessionId){if(!validTarget(target)||!sessionId)return;const path=leasePath(resolve(repositoryRoot),target);const existing=readLease(path);if(!existing||existing.sessionId!==sessionId)return;if(existing.mergeBaseSha!==void 0)return;if(existing.priorMergeBaseResumable!==true)return;const next={...existing,mergeBaseSha:existing.priorMergeBaseSha,mergeBaseStale:existing.priorMergeBaseStale===true,priorMergeBaseCurrent:true};try{atomicWriteLease(path,`${JSON.stringify(next,null,2)}
|
|
5
5
|
`)}catch(error){debugLogger.debug(`Failed to restore the merge base in ${path}:`,error)}}__name(restoreReviewWorktreeLeaseMergeBase,"restoreReviewWorktreeLeaseMergeBase");function createReviewWorktreeLease(params){if(!params.sessionId||!params.promptId||!validTarget(params.target)){return}const repositoryRoot=resolve(params.repositoryRoot);const path=leasePath(repositoryRoot,params.target);const leaseFor=__name((identity,prior)=>{const lease={sessionId:params.sessionId,promptId:params.promptId,target:params.target,repositoryRoot,worktreePath:resolve(repositoryRoot,params.worktreePath),branch:params.branch,identity,...prior===void 0?{}:{priorMergeBaseSha:prior.sha,priorMergeBaseStale:prior.stale,priorMergeBaseResumable:prior.resumable}};return`${JSON.stringify(lease,null,2)}
|
|
6
6
|
`},"leaseFor");let data=leaseFor(mintIdentity());mkdirSync(leaseDirectory(repositoryRoot),{recursive:true,mode:448});const legacy=legacyLeasePath(repositoryRoot,params.target);try{writeFileSync(path,data,{encoding:"utf8",flag:"wx"})}catch(error){if(error.code!=="EEXIST")throw error;const existing=readLease(path);if(existing&&existing.sessionId!==params.sessionId){throw new Error(`review worktree lease for ${params.target} is held by another session (session ${existing.sessionId}) at ${path}; it was acquired between the gate read and the lease write \u2014 retry`)}if(existing){data=leaseFor(typeof existing.identity==="number"&&Number.isFinite(existing.identity)?existing.identity:mintIdentity(),existing.mergeBaseSha!==void 0?{sha:existing.mergeBaseSha,stale:existing.mergeBaseStale===true,resumable:existing.priorMergeBaseCurrent===true}:existing.priorMergeBaseSha!==void 0?{sha:existing.priorMergeBaseSha,stale:existing.priorMergeBaseStale===true,resumable:existing.priorMergeBaseCurrent===true}:void 0)}atomicWriteLease(path,data)}mirrorLeaseAtLegacyPath(legacy,data,params.sessionId,params.target)}__name(createReviewWorktreeLease,"createReviewWorktreeLease");function mirrorLeaseAtLegacyPath(legacy,data,sessionId,target){try{mkdirSync(dirname(legacy),{recursive:true});writeFileSync(legacy,data,{encoding:"utf8",flag:"wx"});return}catch(error){if(error.code!=="EEXIST"){warnMirrorSkipped(legacy,error);return}}const displaced=readLease(legacy);const tmp=`${legacy}.${process.pid}.${randomBytes(6).toString("hex")}.tmp`;try{writeFileSync(tmp,data,{encoding:"utf8",flag:"wx"});renameSync(tmp,legacy)}catch(error){try{rmSync(tmp,{force:true})}catch{}warnMirrorSkipped(legacy,error);return}if(displaced&&displaced.sessionId!==sessionId){writeStderrLineSafe(`warning: replaced the pre-move review lease for ${target} at ${legacy} (recorded session ${inertSessionId(displaced.sessionId)}) \u2014 if a pre-move build is still reviewing ${target} on this machine, its worktree is no longer protected; otherwise this was residue or a plant, and it is gone.`)}}__name(mirrorLeaseAtLegacyPath,"mirrorLeaseAtLegacyPath");function inertSessionId(id){const inert=inertPath(id);return inert.length>120?`${inert.slice(0,120)}\u2026`:inert}__name(inertSessionId,"inertSessionId");function warnMirrorSkipped(legacy,error){writeStderrLineSafe(`warning: could not mirror the review worktree lease to the pre-move path ${legacy} (${error.code??error}); the acquisition stands on the new-path lease, but builds from before the lease move will not see this lock.`)}__name(warnMirrorSkipped,"warnMirrorSkipped");function readLease(path){try{if(!lstatSync(path).isFile()){rmSync(path,{force:true,recursive:true});return null}}catch(error){if(error.code!=="ENOENT"){debugLogger.debug(`Failed to inspect review lease ${path}:`,error)}return null}try{const value=JSON.parse(readFileSync(path,"utf8"));if(typeof value.sessionId!=="string"||typeof value.promptId!=="string"||typeof value.target!=="string"||typeof value.repositoryRoot!=="string"||typeof value.worktreePath!=="string"||typeof value.branch!=="string"||value.identity!==void 0&&(typeof value.identity!=="number"||!Number.isFinite(value.identity))||value.mergeBaseSha!==void 0&&typeof value.mergeBaseSha!=="string"||value.priorMergeBaseSha!==void 0&&typeof value.priorMergeBaseSha!=="string"||value.mergeBaseStale!==void 0&&typeof value.mergeBaseStale!=="boolean"||value.priorMergeBaseStale!==void 0&&typeof value.priorMergeBaseStale!=="boolean"||value.priorMergeBaseCurrent!==void 0&&typeof value.priorMergeBaseCurrent!=="boolean"||value.priorMergeBaseResumable!==void 0&&typeof value.priorMergeBaseResumable!=="boolean"){return null}return value}catch(error){debugLogger.debug(`Failed to read review lease ${path}:`,error);return null}}__name(readLease,"readLease");function readReviewWorktreeLease(repositoryRoot,target){return readReviewWorktreeLeaseAt(repositoryRoot,target)?.lease??null}__name(readReviewWorktreeLease,"readReviewWorktreeLease");function readReviewWorktreeLeaseAt(repositoryRoot,target){if(!validTarget(target))return null;const root=resolve(repositoryRoot);const current=leasePath(root,target);const lease=readLease(current);return lease?{lease,path:current}:null}__name(readReviewWorktreeLeaseAt,"readReviewWorktreeLeaseAt");function reviewLeaseHeldByAnotherSession(lease){if(!lease)return false;const sessionId=process.env["QWEN_CODE_SESSION_ID"]?.trim();return!sessionId||lease.sessionId!==sessionId}__name(reviewLeaseHeldByAnotherSession,"reviewLeaseHeldByAnotherSession");function sameLease(a,b){return b!==null&&a.sessionId===b.sessionId&&a.promptId===b.promptId&&a.target===b.target&&a.repositoryRoot===b.repositoryRoot&&a.worktreePath===b.worktreePath&&a.branch===b.branch}__name(sameLease,"sameLease");function removeLeaseWorktree(lease,gitTimeout){const prMatch=/^pr-(\d+)$/.exec(lease.target);if(!prMatch||lease.branch!==reviewBranch(prMatch[1])){debugLogger.debug(`Rejected invalid review lease ${lease.target}`);return false}const repositoryRoot=resolve(lease.repositoryRoot);const worktreePath=resolve(lease.worktreePath);const reviewTmpRoot=resolve(repositoryRoot,REVIEW_TMP_DIR);const worktreeRelative=relative(reviewTmpRoot,worktreePath);if(worktreeRelative===""||worktreeRelative.startsWith("..")||isAbsolute(worktreeRelative)){debugLogger.debug(`Rejected review lease outside ${REVIEW_TMP_DIR}: ${worktreePath}`);return false}try{execFileSync("git",["-C",repositoryRoot,"worktree","remove",worktreePath,"--force"],gitOptions(gitTimeout))}catch(error){debugLogger.debug(`Git failed to remove review worktree ${lease.target}:`,error);try{rmSync(worktreePath,{recursive:true,force:true});execFileSync("git",["-C",repositoryRoot,"worktree","prune"],gitOptions(gitTimeout))}catch(fallbackError){debugLogger.debug(`Fallback failed to remove review worktree ${lease.target}:`,fallbackError);return false}}let branchExists=true;try{execFileSync("git",["-C",repositoryRoot,"show-ref","--verify","--quiet",`refs/heads/${lease.branch}`],gitOptions(gitTimeout))}catch(error){if(error.status!==1){debugLogger.debug(`Failed to inspect review branch ${lease.branch}:`,error);return false}branchExists=false}if(branchExists){try{execFileSync("git",["-C",repositoryRoot,"branch","-D",lease.branch],gitOptions(gitTimeout))}catch(error){debugLogger.debug(`Failed to delete review branch ${lease.branch}:`,error);return false}}return!existsSync(worktreePath)}__name(removeLeaseWorktree,"removeLeaseWorktree");function cleanupReviewWorktreeLeases(params){try{const repositoryRoot=resolve(params.repositoryRoot);const newLeaseDirectory=leaseDirectory(repositoryRoot);if(!existsSync(newLeaseDirectory))return;let entries;try{entries=readdirSync(newLeaseDirectory)}catch(error){debugLogger.debug(`Failed to list ${newLeaseDirectory} for lease cleanup:`,error);return}for(const entry of entries){if(!isReviewLeaseFile(entry))continue;const path=join(newLeaseDirectory,basename(entry));const lease=readLease(path);if(!lease||lease.sessionId!==params.sessionId||lease.promptId!==params.promptId||resolve(lease.repositoryRoot)!==repositoryRoot){continue}if(!removeLeaseWorktree(lease,params.gitTimeout??GIT_TIMEOUT_MS)){continue}rmSync(path,{force:true});reclaimBaseTreeTrust(repositoryRoot,lease.target);const twin=join(repositoryRoot,REVIEW_TMP_DIR,basename(entry));try{if(sameLease(lease,readLease(twin))){rmSync(twin,{force:true})}}catch(error){debugLogger.debug(`Failed to remove legacy lease twin ${twin}:`,error)}}}catch(error){debugLogger.debug("Failed to clean up review worktree leases:",error)}}__name(cleanupReviewWorktreeLeases,"cleanupReviewWorktreeLeases");export{isReviewLeaseFile,clearReviewWorktreeLease,clearReviewWorktreeLeaseIfOwned,recordReviewWorktreeLeaseMergeBase,restoreReviewWorktreeLeaseMergeBase,createReviewWorktreeLease,readReviewWorktreeLease,readReviewWorktreeLeaseAt,reviewLeaseHeldByAnotherSession,cleanupReviewWorktreeLeases};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// Force strict mode and setup for ESM
|
|
2
2
|
"use strict";
|
|
3
|
-
import{MAX_DROPPED_MSG_IDS,MAX_FRAME_BYTES,MAX_RETAINED_REPLY_TOKEN_CHARS,MAX_SENDER_KEY_CHARS,MAX_SOCKET_PATH_BYTES,SOCKET_DIR_NAME,isLocalIpcPath,parsePeerAuthLine,parsePeerFrame,peerSenderKey,probePeerSocketVerdict,resolvePeerSocketCandidates}from"./chunk-MKH3EH7O.js";import{scanForSecrets}from"./chunk-AKWYMQKU.js";import{collectPtyProcessTree}from"./chunk-PGRN3GZY.js";import{BudgetExhaustedError,IDE_DEFINITIONS,MCP_BUDGET_REARM_FRACTION,MCP_BUDGET_WARN_FRACTION,McpClient,ORPHAN_TOOL_USE_REPAIR_REASON,POOLED_TRANSPORTS_DEFAULT,QWEN_CODE_COMPANION_EXTENSION_NAME,SessionService,StandardFileSystemService,aggregateUsage,buildSessionHistoryFromConversation,buildSyntheticToolResponseParts,classifyShellCommandSafety,classifyShellCommandSafetyInDirectory,coerceMcpFilterEntries,connectionIdOf,convertToFunctionErrorResponse,convertToFunctionResponse,createForkedChat,detectTurnInterruption,discoveryTimeoutFor,estimateContentTokens,evaluateToolInvocationGuard,finalizeToolResponses,getCacheSafeParams,getCacheSafeParamsSessionId,getTimeRangeBounds,isPoolable,listDescendantPids,listExistingSkillDirNames,loadUsageHistoryWithLive,mcpSessionMetadataKey,mcpTransportOf,normalizeMcpIncludeEntry,observeToolResultBoundary,parseConnectionId,recursivelyHydrateStrings,repairOrphanedToolUseTurns,runForkedAgent,runWithForkedChatModel,runWithTimeout,sigtermPids,stripToolResultImages,toolResultBoundaryArtifact,toolResultPartDiagnosticValues,withoutAutoMemorySnapshots}from"./chunk-Z5XENA4A.js";import{shellResultText}from"./chunk-T7CHK6C2.js";import{runGit,runGitCapture,streamGitRecords}from"./chunk-ILECDNJX.js";import{hasVerifiableInode,openNoFollow,openSyncNoFollow}from"./chunk-QXQGUM3Y.js";import{projectUserTranscriptForDisplay}from"./chunk-SZCBUCNH.js";import{toolSearchBridgeSentence}from"./chunk-5SUFJTQQ.js";import{flattenPeerLabel}from"./chunk-BYU42MLK.js";import{isPidAlive}from"./chunk-5LZ2DPLH.js";import{getProjectSkillsRoot}from"./chunk-XQJOZDV7.js";import{parse}from"./chunk-KLC3OD2M.js";import{glob,globSync}from"./chunk-OBOU4ZZM.js";import{isDeferredToolBridgeAvailable}from"./chunk-7CQMWEMY.js";import{require_picomatch}from"./chunk-OUC3WICA.js";import{BUILT_IN_OUTPUT_STYLES,getBuiltInOutputStyle}from"./chunk-OV3EBH6J.js";import{NO_EXEC_CONFIG}from"./chunk-EBMCWXGZ.js";import{require_proper_lockfile}from"./chunk-YIW3H46P.js";import{disposeConoutWorker,loadPty,loadXtermHeadless,noteConPtyHostReleased,releaseConPtyHost}from"./chunk-NMY3PYNO.js";import{stripAnsi}from"./chunk-YGLM5XPP.js";import{resolveBundleDir}from"./chunk-4NPYOXJO.js";import{escapeJsonTagCharacters}from"./chunk-NTRFETZB.js";import{getModelsForProviderProtocol,tryResolveModelProtocol}from"./chunk-ET2Z7ZGF.js";import{fetchWithPolicy}from"./chunk-5CWTKFI4.js";import{COMBINED_PASS_TOLERANCE_FACTOR,TOOL_OUTPUT_TRUNCATED_PREFIX,TRUNCATION_FALLBACK_ENVELOPE_SLACK,addMCPStatusChangeListener,removeMCPStatusChangeListener,updateMCPServerStatus}from"./chunk-ZWPSBU7K.js";import{E_TIMEOUT,Mutex,withTimeout}from"./chunk-HDGTWJ24.js";import{runSideQuery}from"./chunk-K7JCVESI.js";import{MEMORY_SECTION_HEADER,VISION_BRIDGE_MAX_IMAGES,VISION_BRIDGE_MAX_IMAGE_BASE64_BYTES,detectFileType,getCurrentMemoryFilename,isCacheableReadResult,isWithinRoot,processSingleFileContent}from"./chunk-Y6HHV4LC.js";import{getInvocationContext}from"./chunk-EFTJIDS3.js";import{DEFAULT_IMAGE_TOKEN_ESTIMATE,estimatePartChars}from"./chunk-Q6UAOTP3.js";import{atomicWriteFile,atomicWriteJSON}from"./chunk-BMHYEQTI.js";import{isBinary,normalizeContent,stripAnsiAndControl,stripHtmlComments}from"./chunk-DBRQGEEI.js";import{cloneApiHistory,getFolderStructure,getStartupContextLength,stripSystemReminderBlocks}from"./chunk-B3ZFUGTC.js";import{getQwenIgnoreFileNames,require_ignore}from"./chunk-5DTFN37U.js";import{ToolNames,canonicalToolName}from"./chunk-SBZFGYYS.js";import{createDebugLogger}from"./chunk-JAUJI56S.js";import{Storage}from"./chunk-EPODBRBP.js";import{PATH_ARG_KEYS,QWEN_DIR,tildeifyPath,unescapePath}from"./chunk-OKN3Z5C5.js";import{getErrorMessage,isAbortError,isNodeError}from"./chunk-XYB7GC5U.js";import{init_esbuild_shims}from"./chunk-VKDAXTCZ.js";import{__name,__require,__toESM}from"./chunk-KBWJGX7I.js";init_esbuild_shims();var JsonFormatter=class{static{__name(this,"JsonFormatter")}format(response,stats,error){const output={};if(response!==void 0){output.response=stripAnsi(response)}if(stats){output.stats=stats}if(error){output.error=error}return JSON.stringify(output,null,2)}formatError(error,code){const jsonError={type:error.constructor.name,message:stripAnsi(error.message),...code&&{code}};return this.format(void 0,void 0,jsonError)}};init_esbuild_shims();function createPlanId(sessionId,historyLength){return`${sessionId}:${historyLength}`}__name(createPlanId,"createPlanId");function buildVisibleNotice(kind,repairs,historyGaps){if(kind==="clean"){return void 0}if(kind==="degraded_history"){return`Resumed session history is incomplete: detected ${historyGaps.length} missing parent link(s). Automatic continuation is disabled for this recovery.`}if(kind==="interrupted_prompt"){return"Previous session appears to have stopped after user input before the model completed a response."}const synthesized=repairs.filter(repair=>repair.type==="synthesized_tool_result").length;if(synthesized>0){return`Previous session appears to have stopped during tool execution. Synthesized ${synthesized} failed tool result(s) so the history can continue safely.`}return"Previous session appears to have stopped during tool execution."}__name(buildVisibleNotice,"buildVisibleNotice");function buildSessionRecoveryPlan({sessionId,conversation,historyGaps,options}){return buildSessionRecoveryPlanFromApiHistory({sessionId,...buildSessionHistoryFromConversation(conversation),historyGaps,options})}__name(buildSessionRecoveryPlan,"buildSessionRecoveryPlan");function buildSessionRecoveryPlanFromApiHistory({sessionId,apiHistory:inputApiHistory,completedToolCallIds,trailingSystemNotifications,historyGaps,options}){const originalApiHistory=inputApiHistory;const gaps=historyGaps??[];const planId=createPlanId(sessionId,originalApiHistory.length);const apiHistory=cloneApiHistory(originalApiHistory);const repairResult=repairOrphanedToolUseTurns(apiHistory);const repairs=[...repairResult.injected.map(repair=>({type:"synthesized_tool_result",callId:repair.callId,name:repair.name})),...repairResult.droppedDuplicates.map(repair=>({type:"dropped_duplicate_tool_result",callId:repair.callId,name:repair.name})),...gaps.map(gap=>({type:"history_gap",childUuid:gap.childUuid,missingParentUuid:gap.missingParentUuid}))];if(gaps.length>0){return{planId,sessionId,kind:"degraded_history",originalApiHistory,apiHistory,repairs,canContinue:false,canAutoContinue:false,requiresUserConfirmation:true,visibleNotice:buildVisibleNotice("degraded_history",repairs,gaps)}}const interruption=detectTurnInterruption(originalApiHistory,completedToolCallIds,trailingSystemNotifications);if(interruption.kind==="none"){return{planId,sessionId,kind:"clean",originalApiHistory,apiHistory,repairs,canContinue:false,canAutoContinue:false,requiresUserConfirmation:false}}if(interruption.kind==="interrupted_prompt"){const continuation2={mode:"retry_user_parts",parts:interruption.parts,displayText:"Continue interrupted user prompt"};return{planId,sessionId,kind:"interrupted_prompt",originalApiHistory,apiHistory,repairs,canContinue:true,canAutoContinue:options?.allowAutoContinue===true,requiresUserConfirmation:options?.allowAutoContinue!==true,visibleNotice:buildVisibleNotice("interrupted_prompt",repairs,gaps),continuation:continuation2}}const continuation={mode:"tool_result_parts",parts:buildSyntheticToolResponseParts(interruption.danglingCalls,ORPHAN_TOOL_USE_REPAIR_REASON),displayText:"Continue interrupted tool turn"};return{planId,sessionId,kind:"interrupted_turn",originalApiHistory,apiHistory,repairs,canContinue:true,canAutoContinue:false,requiresUserConfirmation:true,visibleNotice:buildVisibleNotice("interrupted_turn",repairs,gaps),continuation}}__name(buildSessionRecoveryPlanFromApiHistory,"buildSessionRecoveryPlanFromApiHistory");init_esbuild_shims();init_esbuild_shims();import{EventEmitter}from"node:events";init_esbuild_shims();var debugLogger=createDebugLogger("McpPool:Entry");function defaultPoolEntryOptions(transport){const isRemote=transport==="http"||transport==="sse"||transport==="websocket";return{drainDelayMs:3e4,maxIdleMs:5*6e4,maxReconnectAttempts:isRemote?5:3,reconnectStrategy:isRemote?{kind:"exponential",baseMs:1e3,capMs:16e3}:{kind:"fixed",delayMs:5e3}}}__name(defaultPoolEntryOptions,"defaultPoolEntryOptions");var PoolEntry=class{constructor(id,serverName,entryIndex,cfg,client,cliConfig,opts,onClosed,aggregateStatusByName){this.id=id;this.serverName=serverName;this.entryIndex=entryIndex;this.cfg=cfg;this.client=client;this.cliConfig=cliConfig;this.opts=opts;this.onClosed=onClosed;this.aggregateStatusByName=aggregateStatusByName;this.transportId=connectionIdOf(serverName,cfg);this.emitter.setMaxListeners(0);this.statusChangeListener=(name,status)=>{if(name!==this.serverName)return;if(status===void 0)return;if(this.suppressNextStatusEcho){this.suppressNextStatusEcho=false;return}if(this.client.getStatus()!==status)return;if(status===this.localStatus)return;this.localStatus=status;if(status==="disconnected"&&(this.state==="active"||this.state==="draining")&&!this.restartInProgress){const wasDraining=this.state==="draining";this.state="failed";if(wasDraining){this.cancelDrainTimer()}if(this.maxIdleTimer){clearTimeout(this.maxIdleTimer);this.maxIdleTimer=void 0}if(this.statusChangeListener){removeMCPStatusChangeListener(this.statusChangeListener);this.statusChangeListener=void 0}debugLogger.error(`PoolEntry ${this.id} silent transport drop (prev state='${wasDraining?"draining":"active"}', localStatus\u2192DISCONNECTED). Transitioning to 'failed'; evicting from pool.entries + pooledConnections (W122 R20).`);const upstreamError=this.client.getLastTransportError();this.emit({kind:"failed",serverName:this.serverName,generation:this._generation,lastError:upstreamError?`transport disconnected (silent transport drop): ${upstreamError.message}`:"transport disconnected (silent transport drop)"});for(const[sid]of[...this.subscribers]){this.detach(sid)}void this.sweepAndDisconnect("silent_drop").then(result=>{const partialSignal=result.descendantsFound!==void 0&&result.descendantsSignaled!==void 0&&result.descendantsSignaled<result.descendantsFound;if(result.pidSweepError!==void 0||partialSignal){debugLogger.warn(`PoolEntry ${this.id} silent-drop sweep observability: descendantsFound=${result.descendantsFound??"unknown"}, descendantsSignaled=${result.descendantsSignaled??"unknown"}, pidSweepError=${result.pidSweepError?.message??"none"}. Possible orphan-process pressure \u2014 operator should check for lingering subprocess descendants of the dead transport.`)}this.updateGlobalStatus()},()=>{this.updateGlobalStatus()});this.updateGlobalStatus();this.onClosed(this.id)}};addMCPStatusChangeListener(this.statusChangeListener)}static{__name(this,"PoolEntry")}localStatus="connecting";state="spawning";_generation=0;refs=new Set;subscribers=new Map;subscriberHandles=new Map;toolsSnapshot=[];promptsSnapshot=[];resourcesSnapshot=[];drainTimer;maxIdleTimer;firstIdleAt;restartInFlight;restartInProgress=false;emitter=new EventEmitter;statusChangeListener;suppressNextStatusEcho=false;transportId;get generation(){return this._generation}get currentState(){return this.state}get transportKind(){return mcpTransportOf(this.cfg)}isTerminated(){return this.state==="closed"||this.state==="failed"}markActive(initialTools,initialPrompts,initialResources){if(this.state==="closed"||this.state==="failed")return;this.toolsSnapshot=initialTools;this.promptsSnapshot=initialPrompts;this.resourcesSnapshot=initialResources;this.state="active";this.localStatus="connected";this.updateGlobalStatus()}attach(sessionId,view,opts){if(this.state==="closed"||this.state==="failed"){throw new Error(`Cannot attach to PoolEntry ${this.id} in state ${this.state}`)}const previousState=this.state;const hadRef=this.refs.has(sessionId);const previousView=this.subscribers.get(sessionId);const previousHandle=this.subscriberHandles.get(sessionId);this.refs.add(sessionId);this.subscribers.set(sessionId,view);this.cancelDrainTimer();if(this.state==="draining")this.state="active";if(this.state==="active"&&opts?.skipReplay!==true){try{view.applyTools(this.toolsSnapshot);view.applyPrompts(this.promptsSnapshot);view.applyResources(this.resourcesSnapshot)}catch(err){if(!hadRef){this.refs.delete(sessionId);this.subscribers.delete(sessionId);this.subscriberHandles.delete(sessionId);try{view.teardown()}catch{}}else if(previousView){this.subscribers.set(sessionId,previousView);if(previousHandle){this.subscriberHandles.set(sessionId,previousHandle)}}if(previousState==="draining"&&this.refs.size===0){this.startDrainTimer(this.opts.drainDelayMs)}else{this.state=previousState}debugLogger.error(`Snapshot replay failed for ${sessionId}/${this.serverName}: ${String(err)}`);throw err}}const handle=new PooledConnectionImpl(this,sessionId,opts?.release);this.subscriberHandles.set(sessionId,handle);return handle}updateSessionConfig(sessionId,cfg){if(this.isTerminated()){throw new Error(`Cannot update config on PoolEntry ${this.id} in state ${this.state}`)}const view=this.subscribers.get(sessionId);if(!view){throw new Error(`Cannot update config for detached session ${sessionId} on PoolEntry ${this.id}`)}if(!view.updateConfig(cfg))return;if(this.state==="active"){view.applyTools(this.toolsSnapshot);view.applyPrompts(this.promptsSnapshot);view.applyResources(this.resourcesSnapshot)}}detach(sessionId){const view=this.subscribers.get(sessionId);if(view){try{view.teardown()}catch(err){debugLogger.error(`View teardown failed for ${sessionId}/${this.serverName}: ${String(err)}`)}}this.subscribers.delete(sessionId);this.subscriberHandles.delete(sessionId);this.refs.delete(sessionId)}startDrainTimer(delayMs){this.cancelDrainTimer();this.state="draining";if(this.firstIdleAt===void 0){this.firstIdleAt=Date.now();this.maxIdleTimer=setTimeout(()=>{if(this.refs.size>0){debugLogger.debug(`PoolEntry ${this.id} max-idle reached but ${this.refs.size} sessions active; deferring close, resetting first-idle window`);this.maxIdleTimer=void 0;this.firstIdleAt=void 0;return}debugLogger.warn(`PoolEntry ${this.id} hit MAX_IDLE_MS (${this.opts.maxIdleMs}ms); force-closing`);void this.forceShutdown("max_idle")},this.opts.maxIdleMs);this.maxIdleTimer.unref?.()}this.drainTimer=setTimeout(()=>{void this.forceShutdown("drain_timer")},delayMs);this.drainTimer.unref?.()}cancelDrainTimer(){if(this.drainTimer){clearTimeout(this.drainTimer);this.drainTimer=void 0}}async forceShutdown(reason){if(this.state==="closed"||this.state==="failed")return;this.state="closed";this.localStatus="disconnected";this.suppressNextStatusEcho=true;this.cancelDrainTimer();if(this.maxIdleTimer){clearTimeout(this.maxIdleTimer);this.maxIdleTimer=void 0}if(this.statusChangeListener){removeMCPStatusChangeListener(this.statusChangeListener);this.statusChangeListener=void 0}this.emit({kind:"disconnected",serverName:this.serverName,generation:this._generation,reason:"transport_closed"});for(const[sid]of this.subscribers){this.detach(sid)}await this.sweepAndDisconnect(reason);this.updateGlobalStatus();this.onClosed(this.id)}async sweepAndDisconnect(reason){const result={};try{const rootPid=this.client.getTransportPid?.();if(rootPid!==void 0){const descendants=await listDescendantPids(rootPid);if(descendants.length>0){result.descendantsFound=descendants.length;result.descendantsSignaled=sigtermPids(descendants);debugLogger.debug(`Sent SIGTERM to ${result.descendantsSignaled}/${descendants.length} descendants of pid ${rootPid} for ${this.id} (${reason})`)}}}catch(err){result.pidSweepError=err instanceof Error?err:new Error(String(err));debugLogger.warn(`Descendant pid sweep failed for ${this.id} (${reason}): ${String(err)}. Proceeding with disconnect.`)}try{await this.client.disconnect()}catch(err){debugLogger.error(`client.disconnect failed for ${this.id} (${reason}): ${String(err)}`)}return result}async restart(){if(this.restartInFlight)return this.restartInFlight;this.restartInFlight=this.doRestart().finally(()=>{this.restartInFlight=void 0});return this.restartInFlight}async doRestart(){if(this.state==="closed"||this.state==="failed"){throw new Error(`Cannot restart PoolEntry ${this.id} in state ${this.state}`)}this.restartInProgress=true;try{return await this.doRestartInner()}finally{this.restartInProgress=false}}async doRestartInner(){this.cancelDrainTimer();if(this.maxIdleTimer){clearTimeout(this.maxIdleTimer);this.maxIdleTimer=void 0}this.firstIdleAt=void 0;if(this.state==="draining"){this.state="active"}const oldGen=this._generation;this._generation+=1;this.emit({kind:"disconnected",serverName:this.serverName,generation:oldGen,reason:"restart"});await this.sweepAndDisconnect("restart");let snap;try{const timeoutMs=discoveryTimeoutFor(this.cfg);snap=await runWithTimeout((async()=>{await this.client.connect();return this.client.discoverAndReturn(this.cliConfig,{applyConfigFilters:false})})(),timeoutMs,`pool restart for ${this.id} (pool will roll back the restart and free its budget slot)`)}catch(err){debugLogger.error(`Restart of ${this.id} failed at connect/discover: ${String(err)}. Transitioning to 'failed'.`);await this.sweepAndDisconnect("restart_failed");this.state="failed";this.localStatus="disconnected";this.suppressNextStatusEcho=true;this.updateGlobalStatus();if(this.statusChangeListener){removeMCPStatusChangeListener(this.statusChangeListener);this.statusChangeListener=void 0}this.emit({kind:"failed",serverName:this.serverName,generation:this._generation,lastError:err instanceof Error?err.message:String(err)});for(const[sid]of this.subscribers){this.detach(sid)}this.onClosed(this.id);throw err}if(oldGen+1!==this._generation){await this.sweepAndDisconnect("restart_superseded");throw new Error(`Restart of ${this.id} superseded by newer generation; discarded stale snapshot + swept new transport.`)}const currentState=this.state;if(currentState==="closed"||currentState==="failed"){await this.sweepAndDisconnect("restart_superseded");throw new Error(`Restart of ${this.id} aborted: entry state is ${currentState} (forceShutdown ran concurrently mid-restart). Snapshot discarded; new transport swept.`)}this.toolsSnapshot=snap.tools;this.promptsSnapshot=snap.prompts;if(snap.resources.length>0){this.resourcesSnapshot=snap.resources}for(const[sid,view]of this.subscribers){try{view.applyTools(this.toolsSnapshot);view.applyPrompts(this.promptsSnapshot);view.applyResources(this.resourcesSnapshot)}catch(err){debugLogger.error(`Restart fan-out to view ${sid}/${this.serverName} failed: ${String(err)}`)}}this.localStatus="connected";this.suppressNextStatusEcho=true;this.updateGlobalStatus();this.emit({kind:"reconnected",serverName:this.serverName,generation:this._generation});this.emit({kind:"toolsChanged",serverName:this.serverName,snapshot:this.toolsSnapshot,generation:this._generation});this.emit({kind:"promptsChanged",serverName:this.serverName,snapshot:this.promptsSnapshot,generation:this._generation});this.emit({kind:"resourcesChanged",serverName:this.serverName,snapshot:this.resourcesSnapshot,generation:this._generation})}emit(event){const listeners=this.emitter.listeners("event");for(const listener of listeners){try{listener(event)}catch(err){debugLogger.error(`PoolEntry listener error for ${this.id} (event.kind=${event.kind}): ${err instanceof Error?err.message:String(err)}`)}}}internalOn(listener){this.emitter.on("event",listener)}internalOff(listener){this.emitter.off("event",listener)}updateGlobalStatus(){const aggregated=this.aggregateStatusByName(this.serverName);updateMCPServerStatus(this.serverName,aggregated)}getLocalStatus(){return this.localStatus}};var PooledConnectionImpl=class{constructor(entry,sessionId,releaseCallback){this.entry=entry;this.sessionId=sessionId;this.releaseCallback=releaseCallback}static{__name(this,"PooledConnectionImpl")}listeners=new Set;released=false;get id(){return this.entry.id}get transportId(){return this.entry.transportId}get serverName(){return this.entry.serverName}get entryIndex(){return this.entry.entryIndex}get client(){return this.entry.client}get toolsSnapshot(){return this.entry.toolsSnapshot}get promptsSnapshot(){return this.entry.promptsSnapshot}get resourcesSnapshot(){return this.entry.resourcesSnapshot}updateConfig(cfg){if(this.released){throw new Error(`Cannot update config on released MCP connection ${this.id}`)}this.entry.updateSessionConfig(this.sessionId,cfg)}on(event,listener){if(event!=="event")return this;if(this.listeners.has(listener))return this;this.listeners.add(listener);this.entry.internalOn(listener);return this}off(event,listener){if(event!=="event")return this;this.listeners.delete(listener);this.entry.internalOff(listener);return this}release(){if(this.released)return;this.released=true;for(const l of this.listeners){this.entry.internalOff(l)}this.listeners.clear();this.releaseCallback?.()}};init_esbuild_shims();var debugLogger2=createDebugLogger("McpPool:View");function compileNameFilter(includeTools,excludeTools){return{excludeSet:excludeTools?new Set(coerceMcpFilterEntries(excludeTools)):void 0,includeSet:includeTools!=null?new Set(coerceMcpFilterEntries(includeTools).map(normalizeMcpIncludeEntry)):void 0}}__name(compileNameFilter,"compileNameFilter");function compiledFilterAccepts(filter2,name){if(filter2.excludeSet?.has(name))return false;if(!filter2.includeSet)return true;return filter2.includeSet.has(name)}__name(compiledFilterAccepts,"compiledFilterAccepts");var SessionMcpView=class{constructor(sessionToolRegistry,sessionPromptRegistry,sessionResourceRegistry,sessionId,serverName,cfg){this.sessionToolRegistry=sessionToolRegistry;this.sessionPromptRegistry=sessionPromptRegistry;this.sessionResourceRegistry=sessionResourceRegistry;this.sessionId=sessionId;this.serverName=serverName;this.cfg=cfg;this.metadataKey=mcpSessionMetadataKey(cfg)}static{__name(this,"SessionMcpView")}metadataKey;applyTools(snapshot){this.sessionToolRegistry.removeMcpToolsByServer(this.serverName);const filter2=compileNameFilter(this.cfg.includeTools,this.cfg.excludeTools);let registered=0;for(const tool of snapshot){if(!compiledFilterAccepts(filter2,tool.serverToolName)){continue}const sessionTool=tool.withSessionConfig(this.cfg.trust,this.cfg.alwaysLoadTools===true);try{this.sessionToolRegistry.registerTool(sessionTool);registered+=1}catch(err){debugLogger2.error(`SessionMcpView[${this.sessionId}/${this.serverName}] failed to register tool ${tool.serverToolName}: ${String(err instanceof Error?err.message:err)}`)}}debugLogger2.debug(`SessionMcpView[${this.sessionId}/${this.serverName}] applied ${snapshot.length} tools (filtered to ${registered} registered)`)}applyPrompts(snapshot){this.sessionPromptRegistry.removePromptsByServer(this.serverName);const filter2=compileNameFilter(this.cfg.includeTools,this.cfg.excludeTools);let registered=0;for(const prompt of snapshot){if(!compiledFilterAccepts(filter2,prompt.name)){continue}try{this.sessionPromptRegistry.registerPrompt(prompt);registered+=1}catch(err){debugLogger2.error(`SessionMcpView[${this.sessionId}/${this.serverName}] failed to register prompt ${prompt.name}: ${String(err instanceof Error?err.message:err)}`)}}debugLogger2.debug(`SessionMcpView[${this.sessionId}/${this.serverName}] applied ${snapshot.length} prompts (filtered to ${registered} registered)`)}applyResources(snapshot){if(snapshot.length===0){return}this.sessionResourceRegistry.removeResourcesByServer(this.serverName);for(const resource of snapshot){try{this.sessionResourceRegistry.registerResource(resource)}catch(err){debugLogger2.error(`SessionMcpView[${this.sessionId}/${this.serverName}] failed to register resource ${resource.uri}: ${String(err instanceof Error?err.message:err)}`)}}debugLogger2.debug(`SessionMcpView[${this.sessionId}/${this.serverName}] applied ${snapshot.length} resources`)}updateConfig(cfg){const nextKey=mcpSessionMetadataKey(cfg);const changed=this.metadataKey!==nextKey;this.cfg=cfg;this.metadataKey=nextKey;return changed}teardown(){this.sessionToolRegistry.removeMcpToolsByServer(this.serverName);this.sessionPromptRegistry.removePromptsByServer(this.serverName);this.sessionResourceRegistry.removeResourcesByServer(this.serverName);debugLogger2.debug(`SessionMcpView[${this.sessionId}/${this.serverName}] torn down`)}};var debugLogger3=createDebugLogger("McpPool");var McpTransportPool=class{constructor(cliConfig,options){this.cliConfig=cliConfig;this.opts={workspaceContext:options.workspaceContext,debugMode:options.debugMode,sendSdkMcpMessage:options.sendSdkMcpMessage,pooledTransports:options.pooledTransports??POOLED_TRANSPORTS_DEFAULT,drainDelayMs:options.drainDelayMs??3e4,entryOptions:options.entryOptions??defaultPoolEntryOptions,budget:options.budget}}static{__name(this,"McpTransportPool")}entries=new Map;unpooledIds=new Set;spawnInFlight=new Map;sessionToEntries=new Map;draining=false;nextIndexByName=new Map;opts;getBudget(){return this.opts.budget}hasNameSibling(serverName){for(const e of this.entries.values()){if(e.serverName===serverName)return true}for(const id of this.spawnInFlight.keys()){try{if(parseConnectionId(id).serverName===serverName)return true}catch{}}return false}async acquire(serverName,cfg,sessionId,sessionToolRegistry,sessionPromptRegistry,sessionResourceRegistry){if(this.draining){throw new Error(`McpTransportPool is draining; refusing acquire for ${serverName} (session ${sessionId})`)}const poolable=isPoolable(cfg,this.opts.pooledTransports);const id=poolable?connectionIdOf(serverName,cfg):void 0;if(id!==void 0){const existing=this.entries.get(id);if(existing&&!existing.isTerminated()){try{const conn=this.attachPooledSession(existing,id,serverName,cfg,sessionId,sessionToolRegistry,sessionPromptRegistry,sessionResourceRegistry);this.indexAttach(sessionId,id);return conn}catch(err){if(existing.isTerminated()){this.evictEntry(id,existing);debugLogger3.warn(`pool self-heal: evicted terminal entry ${id} (state='${existing.currentState}', serverName='${serverName}') mid-attach race; falling through to spawn fresh entry`)}else{throw err}}}else if(existing&&existing.isTerminated()){this.evictEntry(id,existing);debugLogger3.warn(`pool self-heal: evicted stale terminal entry ${id} (state='${existing.currentState}', serverName='${serverName}') before fast-path attach; falling through to spawn fresh entry`)}}let reservationResult;if(this.opts.budget!==void 0){const reservation=this.opts.budget.tryReserve(serverName);if(reservation==="refused"){const transport=mcpTransportOf(cfg);this.opts.budget.recordRefusal(serverName,transport);throw new BudgetExhaustedError(serverName,this.opts.budget.getBudget()??0,this.opts.budget.getReservedCount())}reservationResult=reservation}if(!poolable){try{return await this.createUnpooledConnection(serverName,cfg,sessionId,sessionToolRegistry,sessionPromptRegistry,sessionResourceRegistry)}catch(err){this.rollbackReservationOnSpawnFailure(reservationResult,serverName);throw err}}if(id===void 0){throw new Error("unreachable: poolable && id === undefined")}let inFlight=this.spawnInFlight.get(id);if(!inFlight){const spawnPromise=this.spawnEntry(serverName,cfg,id);inFlight=spawnPromise.finally(()=>{this.spawnInFlight.delete(id)}).catch(err=>{this.rollbackReservationOnSpawnFailure(reservationResult,serverName);throw err});this.spawnInFlight.set(id,inFlight)}this.indexAttach(sessionId,id);let entry;try{entry=await inFlight}catch(err){this.indexDetach(sessionId,id);throw err}if(!this.entries.has(id)||entry.isTerminated()){this.indexDetach(sessionId,id);throw new Error(`PoolEntry ${id} torn down before attach (concurrent release)`)}try{const conn=this.attachPooledSession(entry,id,serverName,cfg,sessionId,sessionToolRegistry,sessionPromptRegistry,sessionResourceRegistry);this.indexAttach(sessionId,id);return conn}catch(err){this.indexDetach(sessionId,id);throw err}}release(id,sessionId){const entry=this.entries.get(id);if(!entry)return;entry.detach(sessionId);this.indexDetach(sessionId,id);if(entry.refs.size===0){if(this.unpooledIds.has(id)){void entry.forceShutdown("manual");return}entry.startDrainTimer(this.opts.drainDelayMs)}}releaseSession(sessionId){const ids=this.sessionToEntries.get(sessionId);if(!ids)return;const idList=[...ids];for(const id of idList){const entry=this.entries.get(id);if(!entry)continue;entry.detach(sessionId);if(entry.refs.size===0){if(this.unpooledIds.has(id)){void entry.forceShutdown("manual");continue}entry.startDrainTimer(this.opts.drainDelayMs)}}this.sessionToEntries.delete(sessionId)}async restartByName(serverName,opts){if(this.draining)return[];const matching=[...this.entries.values()].filter(e=>e.serverName===serverName&&(opts?.entryIndex===void 0||e.entryIndex===opts.entryIndex));if(matching.length===0)return[];return Promise.all(matching.map(async entry=>{const started=Date.now();try{await entry.restart();if(entry.refs.size===0&&!this.unpooledIds.has(entry.id)){entry.startDrainTimer(this.opts.drainDelayMs)}return{entryIndex:entry.entryIndex,restarted:true,durationMs:Date.now()-started}}catch(err){return{entryIndex:entry.entryIndex,restarted:false,reason:String(err instanceof Error?err.message:err)}}}))}getSnapshot(){const byName=new Map;let total=0;let subprocessCount=0;for(const entry of this.entries.values()){const status=entry.getLocalStatus();if(status==="connected"){total+=1;if(entry.transportKind==="stdio"){subprocessCount+=1}}const row=byName.get(entry.serverName)??{entryCount:0,entrySummary:[]};row.entryCount+=1;row.entrySummary.push({entryIndex:entry.entryIndex,refs:entry.refs.size,status});byName.set(entry.serverName,row)}return{total,subprocessCount,byName:Object.fromEntries(byName.entries())}}aggregateStatusByName(serverName){let sawConnecting=false;for(const entry of this.entries.values()){if(entry.serverName!==serverName)continue;const s=entry.getLocalStatus();if(s==="connected")return"connected";if(s==="connecting")sawConnecting=true}return sawConnecting?"connecting":"disconnected"}async drainAll(opts){const timeoutMs=opts?.timeoutMs??1e4;const force=opts?.force??false;this.draining=true;const deadline=Date.now()+timeoutMs;if(this.spawnInFlight.size>0){const spawnWait=Promise.allSettled([...this.spawnInFlight.values()]);let inflightTimer;await Promise.race([spawnWait.then(()=>{if(inflightTimer)clearTimeout(inflightTimer)}),new Promise(resolve9=>{inflightTimer=setTimeout(()=>{const stuckIds=[...this.spawnInFlight.keys()];debugLogger3.warn(`drainAll: spawnInFlight wait timed out after ${timeoutMs}ms; ${stuckIds.length} spawn(s) still in-flight: ${stuckIds.join(", ")}. Proceeding with drain.`);resolve9()},Math.max(0,deadline-Date.now()));inflightTimer.unref?.()})])}const entries=[...this.entries.values()];const drained=[];const errors=[];const shutdownPromises=entries.map(entry=>entry.forceShutdown(force?"manual":"drain_timer").then(()=>drained.push(entry.entryIndex)).catch(err=>{errors.push({entryIndex:entry.entryIndex,serverName:entry.serverName,error:String(err instanceof Error?err.message:err)})}));let drainTimer;const remaining=Math.max(0,deadline-Date.now());await Promise.race([Promise.all(shutdownPromises).then(()=>{if(drainTimer)clearTimeout(drainTimer)}),new Promise(resolve9=>{drainTimer=setTimeout(()=>resolve9(),remaining);drainTimer.unref?.()})]);const drainedCount=drained.length;const errorsCount=errors.length;const forced=Math.max(0,entries.length-drainedCount-errorsCount);const errorsCopy=[...errors];this.entries.clear();this.unpooledIds.clear();this.sessionToEntries.clear();this.spawnInFlight.clear();return{drained:drainedCount,forced,errors:errorsCopy}}attachPooledSession(entry,id,serverName,cfg,sessionId,sessionToolRegistry,sessionPromptRegistry,sessionResourceRegistry){const view=new SessionMcpView(sessionToolRegistry,sessionPromptRegistry,sessionResourceRegistry,sessionId,serverName,cfg);return entry.attach(sessionId,view,{release:__name(()=>this.release(id,sessionId),"release")})}rollbackReservationOnSpawnFailure(reservationResult,serverName){if(this.opts.budget!==void 0&&reservationResult==="reserved"&&!this.hasNameSibling(serverName)){this.opts.budget.release(serverName)}}evictEntry(id,entry){if(entry===void 0)return;const current=this.entries.get(id);if(current!==entry)return;this.entries.delete(id);if(this.opts.budget!==void 0){if(!this.hasNameSibling(entry.serverName)){this.opts.budget.release(entry.serverName)}}}async spawnEntry(serverName,cfg,id){const entryIndex=this.allocateEntryIndex(serverName);const transport=mcpTransportOf(cfg);const entryOpts=this.opts.entryOptions(transport);const client=new McpClient(serverName,cfg,poisonedToolRegistry(serverName),poisonedPromptRegistry(serverName),this.opts.workspaceContext,this.opts.debugMode,this.opts.sendSdkMcpMessage);const entryRef={current:void 0};const onClosedForThisEntry=__name(closedId=>{this.evictEntry(closedId,entryRef.current)},"onClosedForThisEntry");const entry=new PoolEntry(id,serverName,entryIndex,cfg,client,this.cliConfig,entryOpts,onClosedForThisEntry,name=>this.aggregateStatusByName(name));entryRef.current=entry;try{const timeoutMs=discoveryTimeoutFor(cfg);const snap=await runWithTimeout((async()=>{await client.connect();return client.discoverAndReturn(this.cliConfig,{applyConfigFilters:false})})(),timeoutMs,`pool spawn for ${id} (pool will roll back the spawn and free its budget slot)`);if(this.draining){debugLogger3.warn(`Spawn for ${id} completed while pool is draining; discarding entry`);try{await entry.forceShutdown("manual")}catch{}throw new Error(`McpTransportPool is draining; discarded spawn ${id}`)}this.entries.set(id,entry);entry.markActive(snap.tools,snap.prompts,snap.resources);debugLogger3.info(`Spawned pool entry ${id} (entryIndex=${entryIndex}, transport=${transport})`);return entry}catch(err){debugLogger3.error(`Failed to spawn pool entry for '${serverName}' (id=${id}, transport=${transport}): ${String(err)}`);try{await entry.forceShutdown("manual")}catch{}this.entries.delete(id);try{await client.disconnect()}catch{}throw err}}allocateEntryIndex(serverName){const next=this.nextIndexByName.get(serverName)??0;this.nextIndexByName.set(serverName,next+1);return next}indexAttach(sessionId,id){let ids=this.sessionToEntries.get(sessionId);if(!ids){ids=new Set;this.sessionToEntries.set(sessionId,ids)}ids.add(id)}indexDetach(sessionId,id){const ids=this.sessionToEntries.get(sessionId);if(!ids)return;ids.delete(id);if(ids.size===0)this.sessionToEntries.delete(sessionId)}async createUnpooledConnection(serverName,cfg,sessionId,sessionToolRegistry,sessionPromptRegistry,sessionResourceRegistry){const entryIndex=this.allocateEntryIndex(serverName);const id=`${serverName}::unpooled-${entryIndex}`;const transport=mcpTransportOf(cfg);const entryOpts=this.opts.entryOptions(transport);const client=new McpClient(serverName,cfg,sessionToolRegistry,sessionPromptRegistry,this.opts.workspaceContext,this.opts.debugMode,this.opts.sendSdkMcpMessage);const view=new SessionMcpView(sessionToolRegistry,sessionPromptRegistry,sessionResourceRegistry,sessionId,serverName,cfg);const entry=new PoolEntry(id,serverName,entryIndex,cfg,client,this.cliConfig,entryOpts,closedId=>{this.entries.delete(closedId);this.unpooledIds.delete(closedId);if(this.opts.budget!==void 0){if(!this.hasNameSibling(serverName)){this.opts.budget.release(serverName)}}},()=>client.getStatus());try{this.entries.set(id,entry);this.unpooledIds.add(id);this.indexAttach(sessionId,id);const timeoutMs=discoveryTimeoutFor(cfg);const snap=await runWithTimeout((async()=>{await client.connect();return await client.discoverAndReturn(this.cliConfig,{applyConfigFilters:false})})(),timeoutMs,`unpooled spawn for ${id} (pool will roll back the spawn and free its budget slot)`);if(this.draining||!this.entries.has(id)||entry.isTerminated()){try{view.teardown()}catch{}try{await entry.forceShutdown("manual")}catch{}this.indexDetach(sessionId,id);throw new Error(`McpTransportPool is draining or unpooled ${id} was cancelled`)}entry.markActive(snap.tools,snap.prompts,snap.resources);const conn=entry.attach(sessionId,view,{release:__name(()=>{this.indexDetach(sessionId,id);void entry.forceShutdown("manual")},"release")});return conn}catch(err){try{await entry.forceShutdown("manual")}catch{}this.entries.delete(id);this.unpooledIds.delete(id);this.indexDetach(sessionId,id);try{await client.disconnect()}catch{}throw err}}};function poisonedToolRegistry(serverName){return{registerTool(){throw new Error(`Pool invariant violated: poisoned ToolRegistry for ${serverName} received registerTool. A pool path must use discoverAndReturn, not discover.`)}}}__name(poisonedToolRegistry,"poisonedToolRegistry");function poisonedPromptRegistry(serverName){return{registerPrompt(){throw new Error(`Pool invariant violated: poisoned PromptRegistry for ${serverName} received registerPrompt. A pool path must use discoverAndReturn.`)}}}__name(poisonedPromptRegistry,"poisonedPromptRegistry");init_esbuild_shims();var debugLogger4=createDebugLogger("McpPool:Budget");var WorkspaceMcpBudget=class{static{__name(this,"WorkspaceMcpBudget")}clientBudget;mode;onEvent;reservedSlots=new Set;pendingRefusalNames=new Set;pendingRefusalTransports=new Map;lastRefusedServerNames=[];warnArmed=true;bulkPassDepth=0;constructor(opts){this.clientBudget=opts.clientBudget;this.mode=opts.mode;this.onEvent=opts.mode==="off"?void 0:opts.onEvent}getMode(){return this.mode}getBudget(){return this.clientBudget}getReservedSlots(){return Array.from(this.reservedSlots)}getRefusedServerNames(){return this.lastRefusedServerNames}getReservedCount(){return this.reservedSlots.size}tryReserve(serverName){if(this.reservedSlots.has(serverName))return"already_held";if(this.clientBudget===void 0||this.mode==="off"){return"reserved"}if(this.mode==="enforce"&&this.reservedSlots.size>=this.clientBudget){return"refused"}this.reservedSlots.add(serverName);this.evaluateState();return"reserved"}release(serverName){const had=this.reservedSlots.delete(serverName);if(had)this.evaluateState();return had}recordRefusal(serverName,transport){if(this.mode!=="enforce")return;this.pendingRefusalNames.add(serverName);this.pendingRefusalTransports.set(serverName,transport);debugLogger4.warn(`MCP server '${serverName}' refused at pool acquire (budget exhausted, budget=${this.clientBudget}, mode=${this.mode})`);if(this.bulkPassDepth===0){this.flushRefusedBatch()}}beginBulkPass(){if(this.bulkPassDepth===0){this.lastRefusedServerNames=[]}this.bulkPassDepth+=1}endBulkPass(){if(this.bulkPassDepth===0){debugLogger4.warn("WorkspaceMcpBudget.endBulkPass called without matching beginBulkPass; ignoring");return}this.bulkPassDepth-=1;if(this.bulkPassDepth>0)return;this.flushRefusedBatch()}flushRefusedBatch(){if(this.pendingRefusalNames.size===0)return;if(this.clientBudget===void 0||this.mode!=="enforce"){this.pendingRefusalNames.clear();this.pendingRefusalTransports.clear();return}const refusedServers=[];const names=[];for(const name of this.pendingRefusalNames){const transport=this.pendingRefusalTransports.get(name)??"unknown";refusedServers.push({name,transport,reason:"budget_exhausted"});names.push(name)}this.lastRefusedServerNames=Object.freeze(names);this.pendingRefusalNames.clear();this.pendingRefusalTransports.clear();if(this.onEvent){try{this.onEvent({kind:"refused_batch",refusedServers,budget:this.clientBudget,liveCount:this.reservedSlots.size,reservedCount:this.reservedSlots.size,mode:"enforce"})}catch(err){debugLogger4.error(`WorkspaceMcpBudget refused_batch event delivery failed: ${err instanceof Error?err.message:String(err)}`)}}}evaluateState(){if(this.mode==="off"||this.clientBudget===void 0)return;const ratio=this.reservedSlots.size/this.clientBudget;if(this.warnArmed&&ratio>=MCP_BUDGET_WARN_FRACTION){this.warnArmed=false;debugLogger4.info(`MCP workspace budget warning fired (ratio=${ratio.toFixed(2)}, reservedCount=${this.reservedSlots.size}, budget=${this.clientBudget}, mode=${this.mode})`);if(this.onEvent){try{this.onEvent({kind:"budget_warning",liveCount:this.reservedSlots.size,reservedCount:this.reservedSlots.size,budget:this.clientBudget,thresholdRatio:MCP_BUDGET_WARN_FRACTION,mode:this.mode})}catch(err){debugLogger4.error(`WorkspaceMcpBudget budget_warning event delivery failed: ${err instanceof Error?err.message:String(err)}`)}}}else if(!this.warnArmed&&ratio<MCP_BUDGET_REARM_FRACTION){this.warnArmed=true;debugLogger4.info(`MCP workspace budget warning re-armed (ratio=${ratio.toFixed(2)}, budget=${this.clientBudget}; next 75% crossing will fire)`)}}};init_esbuild_shims();function preservePlaceholders(value,resolved,original){if(typeof original==="string"&&value===resolved)return original;if(Array.isArray(value)&&Array.isArray(resolved)&&Array.isArray(original)){return value.map((entry,index)=>preservePlaceholders(entry,resolved[index],original[index]))}if(value&&resolved&&original&&typeof value==="object"&&!Array.isArray(value)&&typeof resolved==="object"&&!Array.isArray(resolved)&&typeof original==="object"&&!Array.isArray(original)){return Object.fromEntries(Object.entries(value).map(([key,entry])=>[key,preservePlaceholders(entry,resolved[key],original[key])]))}return value}__name(preservePlaceholders,"preservePlaceholders");function preserveModelProviderPlaceholders(models,provider,resolvedProviders,rawProviders,mapping){const pairs=Object.entries(resolvedProviders).flatMap(([providerId,entries])=>{if(!Array.isArray(entries))return[];return entries.flatMap((entry,index)=>{const resolved=provider==="openai"?getModelsForProviderProtocol({[providerId]:[entry]},"openai",mapping)[0]:providerId===provider?entry:void 0;return resolved?[{providerId,resolved,source:entry,raw:rawProviders[providerId]?.[index]??entry}]:[]})});return models.map(model=>{const matches=pairs.filter(({resolved})=>resolved.id===model.id&&resolved.baseUrl===model.baseUrl&&tryResolveModelProtocol(provider,resolved,mapping)===tryResolveModelProtocol(provider,model,mapping));const sourceMatches=matches.filter(pair=>pair.providerId===matches[0]?.providerId);if(sourceMatches.length>1&&sourceMatches.some(pair=>JSON.stringify(pair.raw)!==JSON.stringify(pair.source))){throw new Error("Cannot preserve placeholders in an ambiguous model configuration. Remove duplicate model entries first.")}const match=matches[0];return match?preservePlaceholders(model,match.resolved,match.raw):model})}__name(preserveModelProviderPlaceholders,"preserveModelProviderPlaceholders");init_esbuild_shims();init_esbuild_shims();var DISCOVERY_TIMEOUT_MS=5e3;var DISCOVERY_MAX_BYTES=1024*1024;var MAX_MODEL_ID_LENGTH=256;var UNSAFE_MODEL_ID_CHARS=/[,\p{C}\p{Zl}\p{Zp}]/u;function readModels(value){if(!value||typeof value!=="object"||!("data"in value)){return null}const data=value.data;if(!Array.isArray(data)){return null}const models=[];const seen=new Set;for(const item of data){if(!item||typeof item!=="object"||!("id"in item)){return null}const id=item.id;if(typeof id!=="string"){return null}const trimmedId=id.trim();if(trimmedId&&trimmedId.length<=MAX_MODEL_ID_LENGTH&&!UNSAFE_MODEL_ID_CHARS.test(trimmedId)&&!seen.has(trimmedId)){seen.add(trimmedId);const created=item.created;const creationTime=typeof created==="number"&&Number.isFinite(created)&&created>=0?created:void 0;models.push({id:trimmedId,...creationTime===void 0?{}:{created:creationTime}})}}return models.length>0?models:null}__name(readModels,"readModels");function mergeModelSpecs(discoveredModels,staticModels){const staticModelsById=new Map(staticModels.map(model=>[model.id,model]));const orderedModels=[...discoveredModels];if(orderedModels.every(model=>model.created!==void 0)){orderedModels.sort((left,right)=>(right.created??0)-(left.created??0))}return orderedModels.map(({id})=>staticModelsById.get(id)??{id})}__name(mergeModelSpecs,"mergeModelSpecs");async function discoverProviderModels({baseUrl,apiKey,staticModels,signal}){const normalizedBaseUrl=baseUrl.trim();const normalizedApiKey=apiKey.trim();if(!normalizedBaseUrl||!normalizedApiKey){return null}try{const modelsUrl=`${normalizedBaseUrl.replace(/\/+$/,"")}/models`;const result=await fetchWithPolicy(modelsUrl,{timeoutMs:DISCOVERY_TIMEOUT_MS,maxBytes:DISCOVERY_MAX_BYTES,maxRedirects:2,headers:{Accept:"application/json",Authorization:`Bearer ${normalizedApiKey}`},signal});if(result.kind!=="response"||result.status<200||result.status>=300){return null}const models=readModels(JSON.parse(result.body.toString("utf8")));return models?mergeModelSpecs(models,staticModels):null}catch{return null}}__name(discoverProviderModels,"discoverProviderModels");init_esbuild_shims();var IMAGE_CAPABILITY=Object.freeze({autoHandlesWrongModel:true,maxBytes:VISION_BRIDGE_MAX_IMAGE_BASE64_BYTES,maxImagesPerTurn:VISION_BRIDGE_MAX_IMAGES});init_esbuild_shims();var debugLogger5=createDebugLogger("SESSION_RECAP");var RECENT_MESSAGE_WINDOW=30;var RECAP_SYSTEM_PROMPT=`You generate session recaps for a programming assistant CLI.
|
|
3
|
+
import{MAX_DROPPED_MSG_IDS,MAX_FRAME_BYTES,MAX_RETAINED_REPLY_TOKEN_CHARS,MAX_SENDER_KEY_CHARS,MAX_SOCKET_PATH_BYTES,SOCKET_DIR_NAME,isLocalIpcPath,parsePeerAuthLine,parsePeerFrame,peerSenderKey,probePeerSocketVerdict,resolvePeerSocketCandidates}from"./chunk-MKH3EH7O.js";import{scanForSecrets}from"./chunk-AKWYMQKU.js";import{collectPtyProcessTree}from"./chunk-PGRN3GZY.js";import{BudgetExhaustedError,IDE_DEFINITIONS,MCP_BUDGET_REARM_FRACTION,MCP_BUDGET_WARN_FRACTION,McpClient,ORPHAN_TOOL_USE_REPAIR_REASON,POOLED_TRANSPORTS_DEFAULT,QWEN_CODE_COMPANION_EXTENSION_NAME,SessionService,StandardFileSystemService,aggregateUsage,buildSessionHistoryFromConversation,buildSyntheticToolResponseParts,classifyShellCommandSafety,classifyShellCommandSafetyInDirectory,coerceMcpFilterEntries,connectionIdOf,convertToFunctionErrorResponse,convertToFunctionResponse,createForkedChat,detectTurnInterruption,discoveryTimeoutFor,estimateContentTokens,evaluateToolInvocationGuard,finalizeToolResponses,getCacheSafeParams,getCacheSafeParamsSessionId,getTimeRangeBounds,isPoolable,listDescendantPids,listExistingSkillDirNames,loadUsageHistoryWithLive,mcpSessionMetadataKey,mcpTransportOf,normalizeMcpIncludeEntry,observeToolResultBoundary,parseConnectionId,recursivelyHydrateStrings,repairOrphanedToolUseTurns,runForkedAgent,runWithForkedChatModel,runWithTimeout,sigtermPids,stripToolResultImages,toolResultBoundaryArtifact,toolResultPartDiagnosticValues,withoutAutoMemorySnapshots}from"./chunk-2JGTWRZJ.js";import{shellResultText}from"./chunk-T7CHK6C2.js";import{runGit,runGitCapture,streamGitRecords}from"./chunk-ILECDNJX.js";import{hasVerifiableInode,openNoFollow,openSyncNoFollow}from"./chunk-QXQGUM3Y.js";import{projectUserTranscriptForDisplay}from"./chunk-SZCBUCNH.js";import{toolSearchBridgeSentence}from"./chunk-5SUFJTQQ.js";import{flattenPeerLabel}from"./chunk-BYU42MLK.js";import{isPidAlive}from"./chunk-5LZ2DPLH.js";import{getProjectSkillsRoot}from"./chunk-XQJOZDV7.js";import{parse}from"./chunk-KLC3OD2M.js";import{glob,globSync}from"./chunk-OBOU4ZZM.js";import{isDeferredToolBridgeAvailable}from"./chunk-7CQMWEMY.js";import{require_picomatch}from"./chunk-OUC3WICA.js";import{BUILT_IN_OUTPUT_STYLES,getBuiltInOutputStyle}from"./chunk-OV3EBH6J.js";import{NO_EXEC_CONFIG}from"./chunk-EBMCWXGZ.js";import{require_proper_lockfile}from"./chunk-YIW3H46P.js";import{disposeConoutWorker,loadPty,loadXtermHeadless,noteConPtyHostReleased,releaseConPtyHost}from"./chunk-NMY3PYNO.js";import{stripAnsi}from"./chunk-YGLM5XPP.js";import{resolveBundleDir}from"./chunk-4NPYOXJO.js";import{escapeJsonTagCharacters}from"./chunk-NTRFETZB.js";import{getModelsForProviderProtocol,tryResolveModelProtocol}from"./chunk-ET2Z7ZGF.js";import{fetchWithPolicy}from"./chunk-5CWTKFI4.js";import{COMBINED_PASS_TOLERANCE_FACTOR,TOOL_OUTPUT_TRUNCATED_PREFIX,TRUNCATION_FALLBACK_ENVELOPE_SLACK,addMCPStatusChangeListener,removeMCPStatusChangeListener,updateMCPServerStatus}from"./chunk-ZWPSBU7K.js";import{E_TIMEOUT,Mutex,withTimeout}from"./chunk-HDGTWJ24.js";import{runSideQuery}from"./chunk-K7JCVESI.js";import{MEMORY_SECTION_HEADER,VISION_BRIDGE_MAX_IMAGES,VISION_BRIDGE_MAX_IMAGE_BASE64_BYTES,detectFileType,getCurrentMemoryFilename,isCacheableReadResult,isWithinRoot,processSingleFileContent}from"./chunk-Y6HHV4LC.js";import{getInvocationContext}from"./chunk-EFTJIDS3.js";import{DEFAULT_IMAGE_TOKEN_ESTIMATE,estimatePartChars}from"./chunk-Q6UAOTP3.js";import{atomicWriteFile,atomicWriteJSON}from"./chunk-BMHYEQTI.js";import{isBinary,normalizeContent,stripAnsiAndControl,stripHtmlComments}from"./chunk-DBRQGEEI.js";import{cloneApiHistory,getFolderStructure,getStartupContextLength,stripSystemReminderBlocks}from"./chunk-B3ZFUGTC.js";import{getQwenIgnoreFileNames,require_ignore}from"./chunk-5DTFN37U.js";import{ToolNames,canonicalToolName}from"./chunk-SBZFGYYS.js";import{createDebugLogger}from"./chunk-JAUJI56S.js";import{Storage}from"./chunk-EPODBRBP.js";import{PATH_ARG_KEYS,QWEN_DIR,tildeifyPath,unescapePath}from"./chunk-OKN3Z5C5.js";import{getErrorMessage,isAbortError,isNodeError}from"./chunk-XYB7GC5U.js";import{init_esbuild_shims}from"./chunk-VKDAXTCZ.js";import{__name,__require,__toESM}from"./chunk-KBWJGX7I.js";init_esbuild_shims();var JsonFormatter=class{static{__name(this,"JsonFormatter")}format(response,stats,error){const output={};if(response!==void 0){output.response=stripAnsi(response)}if(stats){output.stats=stats}if(error){output.error=error}return JSON.stringify(output,null,2)}formatError(error,code){const jsonError={type:error.constructor.name,message:stripAnsi(error.message),...code&&{code}};return this.format(void 0,void 0,jsonError)}};init_esbuild_shims();function createPlanId(sessionId,historyLength){return`${sessionId}:${historyLength}`}__name(createPlanId,"createPlanId");function buildVisibleNotice(kind,repairs,historyGaps){if(kind==="clean"){return void 0}if(kind==="degraded_history"){return`Resumed session history is incomplete: detected ${historyGaps.length} missing parent link(s). Automatic continuation is disabled for this recovery.`}if(kind==="interrupted_prompt"){return"Previous session appears to have stopped after user input before the model completed a response."}const synthesized=repairs.filter(repair=>repair.type==="synthesized_tool_result").length;if(synthesized>0){return`Previous session appears to have stopped during tool execution. Synthesized ${synthesized} failed tool result(s) so the history can continue safely.`}return"Previous session appears to have stopped during tool execution."}__name(buildVisibleNotice,"buildVisibleNotice");function buildSessionRecoveryPlan({sessionId,conversation,historyGaps,options}){return buildSessionRecoveryPlanFromApiHistory({sessionId,...buildSessionHistoryFromConversation(conversation),historyGaps,options})}__name(buildSessionRecoveryPlan,"buildSessionRecoveryPlan");function buildSessionRecoveryPlanFromApiHistory({sessionId,apiHistory:inputApiHistory,completedToolCallIds,trailingSystemNotifications,historyGaps,options}){const originalApiHistory=inputApiHistory;const gaps=historyGaps??[];const planId=createPlanId(sessionId,originalApiHistory.length);const apiHistory=cloneApiHistory(originalApiHistory);const repairResult=repairOrphanedToolUseTurns(apiHistory);const repairs=[...repairResult.injected.map(repair=>({type:"synthesized_tool_result",callId:repair.callId,name:repair.name})),...repairResult.droppedDuplicates.map(repair=>({type:"dropped_duplicate_tool_result",callId:repair.callId,name:repair.name})),...gaps.map(gap=>({type:"history_gap",childUuid:gap.childUuid,missingParentUuid:gap.missingParentUuid}))];if(gaps.length>0){return{planId,sessionId,kind:"degraded_history",originalApiHistory,apiHistory,repairs,canContinue:false,canAutoContinue:false,requiresUserConfirmation:true,visibleNotice:buildVisibleNotice("degraded_history",repairs,gaps)}}const interruption=detectTurnInterruption(originalApiHistory,completedToolCallIds,trailingSystemNotifications);if(interruption.kind==="none"){return{planId,sessionId,kind:"clean",originalApiHistory,apiHistory,repairs,canContinue:false,canAutoContinue:false,requiresUserConfirmation:false}}if(interruption.kind==="interrupted_prompt"){const continuation2={mode:"retry_user_parts",parts:interruption.parts,displayText:"Continue interrupted user prompt"};return{planId,sessionId,kind:"interrupted_prompt",originalApiHistory,apiHistory,repairs,canContinue:true,canAutoContinue:options?.allowAutoContinue===true,requiresUserConfirmation:options?.allowAutoContinue!==true,visibleNotice:buildVisibleNotice("interrupted_prompt",repairs,gaps),continuation:continuation2}}const continuation={mode:"tool_result_parts",parts:buildSyntheticToolResponseParts(interruption.danglingCalls,ORPHAN_TOOL_USE_REPAIR_REASON),displayText:"Continue interrupted tool turn"};return{planId,sessionId,kind:"interrupted_turn",originalApiHistory,apiHistory,repairs,canContinue:true,canAutoContinue:false,requiresUserConfirmation:true,visibleNotice:buildVisibleNotice("interrupted_turn",repairs,gaps),continuation}}__name(buildSessionRecoveryPlanFromApiHistory,"buildSessionRecoveryPlanFromApiHistory");init_esbuild_shims();init_esbuild_shims();import{EventEmitter}from"node:events";init_esbuild_shims();var debugLogger=createDebugLogger("McpPool:Entry");function defaultPoolEntryOptions(transport){const isRemote=transport==="http"||transport==="sse"||transport==="websocket";return{drainDelayMs:3e4,maxIdleMs:5*6e4,maxReconnectAttempts:isRemote?5:3,reconnectStrategy:isRemote?{kind:"exponential",baseMs:1e3,capMs:16e3}:{kind:"fixed",delayMs:5e3}}}__name(defaultPoolEntryOptions,"defaultPoolEntryOptions");var PoolEntry=class{constructor(id,serverName,entryIndex,cfg,client,cliConfig,opts,onClosed,aggregateStatusByName){this.id=id;this.serverName=serverName;this.entryIndex=entryIndex;this.cfg=cfg;this.client=client;this.cliConfig=cliConfig;this.opts=opts;this.onClosed=onClosed;this.aggregateStatusByName=aggregateStatusByName;this.transportId=connectionIdOf(serverName,cfg);this.emitter.setMaxListeners(0);this.statusChangeListener=(name,status)=>{if(name!==this.serverName)return;if(status===void 0)return;if(this.suppressNextStatusEcho){this.suppressNextStatusEcho=false;return}if(this.client.getStatus()!==status)return;if(status===this.localStatus)return;this.localStatus=status;if(status==="disconnected"&&(this.state==="active"||this.state==="draining")&&!this.restartInProgress){const wasDraining=this.state==="draining";this.state="failed";if(wasDraining){this.cancelDrainTimer()}if(this.maxIdleTimer){clearTimeout(this.maxIdleTimer);this.maxIdleTimer=void 0}if(this.statusChangeListener){removeMCPStatusChangeListener(this.statusChangeListener);this.statusChangeListener=void 0}debugLogger.error(`PoolEntry ${this.id} silent transport drop (prev state='${wasDraining?"draining":"active"}', localStatus\u2192DISCONNECTED). Transitioning to 'failed'; evicting from pool.entries + pooledConnections (W122 R20).`);const upstreamError=this.client.getLastTransportError();this.emit({kind:"failed",serverName:this.serverName,generation:this._generation,lastError:upstreamError?`transport disconnected (silent transport drop): ${upstreamError.message}`:"transport disconnected (silent transport drop)"});for(const[sid]of[...this.subscribers]){this.detach(sid)}void this.sweepAndDisconnect("silent_drop").then(result=>{const partialSignal=result.descendantsFound!==void 0&&result.descendantsSignaled!==void 0&&result.descendantsSignaled<result.descendantsFound;if(result.pidSweepError!==void 0||partialSignal){debugLogger.warn(`PoolEntry ${this.id} silent-drop sweep observability: descendantsFound=${result.descendantsFound??"unknown"}, descendantsSignaled=${result.descendantsSignaled??"unknown"}, pidSweepError=${result.pidSweepError?.message??"none"}. Possible orphan-process pressure \u2014 operator should check for lingering subprocess descendants of the dead transport.`)}this.updateGlobalStatus()},()=>{this.updateGlobalStatus()});this.updateGlobalStatus();this.onClosed(this.id)}};addMCPStatusChangeListener(this.statusChangeListener)}static{__name(this,"PoolEntry")}localStatus="connecting";state="spawning";_generation=0;refs=new Set;subscribers=new Map;subscriberHandles=new Map;toolsSnapshot=[];promptsSnapshot=[];resourcesSnapshot=[];drainTimer;maxIdleTimer;firstIdleAt;restartInFlight;restartInProgress=false;emitter=new EventEmitter;statusChangeListener;suppressNextStatusEcho=false;transportId;get generation(){return this._generation}get currentState(){return this.state}get transportKind(){return mcpTransportOf(this.cfg)}isTerminated(){return this.state==="closed"||this.state==="failed"}markActive(initialTools,initialPrompts,initialResources){if(this.state==="closed"||this.state==="failed")return;this.toolsSnapshot=initialTools;this.promptsSnapshot=initialPrompts;this.resourcesSnapshot=initialResources;this.state="active";this.localStatus="connected";this.updateGlobalStatus()}attach(sessionId,view,opts){if(this.state==="closed"||this.state==="failed"){throw new Error(`Cannot attach to PoolEntry ${this.id} in state ${this.state}`)}const previousState=this.state;const hadRef=this.refs.has(sessionId);const previousView=this.subscribers.get(sessionId);const previousHandle=this.subscriberHandles.get(sessionId);this.refs.add(sessionId);this.subscribers.set(sessionId,view);this.cancelDrainTimer();if(this.state==="draining")this.state="active";if(this.state==="active"&&opts?.skipReplay!==true){try{view.applyTools(this.toolsSnapshot);view.applyPrompts(this.promptsSnapshot);view.applyResources(this.resourcesSnapshot)}catch(err){if(!hadRef){this.refs.delete(sessionId);this.subscribers.delete(sessionId);this.subscriberHandles.delete(sessionId);try{view.teardown()}catch{}}else if(previousView){this.subscribers.set(sessionId,previousView);if(previousHandle){this.subscriberHandles.set(sessionId,previousHandle)}}if(previousState==="draining"&&this.refs.size===0){this.startDrainTimer(this.opts.drainDelayMs)}else{this.state=previousState}debugLogger.error(`Snapshot replay failed for ${sessionId}/${this.serverName}: ${String(err)}`);throw err}}const handle=new PooledConnectionImpl(this,sessionId,opts?.release);this.subscriberHandles.set(sessionId,handle);return handle}updateSessionConfig(sessionId,cfg){if(this.isTerminated()){throw new Error(`Cannot update config on PoolEntry ${this.id} in state ${this.state}`)}const view=this.subscribers.get(sessionId);if(!view){throw new Error(`Cannot update config for detached session ${sessionId} on PoolEntry ${this.id}`)}if(!view.updateConfig(cfg))return;if(this.state==="active"){view.applyTools(this.toolsSnapshot);view.applyPrompts(this.promptsSnapshot);view.applyResources(this.resourcesSnapshot)}}detach(sessionId){const view=this.subscribers.get(sessionId);if(view){try{view.teardown()}catch(err){debugLogger.error(`View teardown failed for ${sessionId}/${this.serverName}: ${String(err)}`)}}this.subscribers.delete(sessionId);this.subscriberHandles.delete(sessionId);this.refs.delete(sessionId)}startDrainTimer(delayMs){this.cancelDrainTimer();this.state="draining";if(this.firstIdleAt===void 0){this.firstIdleAt=Date.now();this.maxIdleTimer=setTimeout(()=>{if(this.refs.size>0){debugLogger.debug(`PoolEntry ${this.id} max-idle reached but ${this.refs.size} sessions active; deferring close, resetting first-idle window`);this.maxIdleTimer=void 0;this.firstIdleAt=void 0;return}debugLogger.warn(`PoolEntry ${this.id} hit MAX_IDLE_MS (${this.opts.maxIdleMs}ms); force-closing`);void this.forceShutdown("max_idle")},this.opts.maxIdleMs);this.maxIdleTimer.unref?.()}this.drainTimer=setTimeout(()=>{void this.forceShutdown("drain_timer")},delayMs);this.drainTimer.unref?.()}cancelDrainTimer(){if(this.drainTimer){clearTimeout(this.drainTimer);this.drainTimer=void 0}}async forceShutdown(reason){if(this.state==="closed"||this.state==="failed")return;this.state="closed";this.localStatus="disconnected";this.suppressNextStatusEcho=true;this.cancelDrainTimer();if(this.maxIdleTimer){clearTimeout(this.maxIdleTimer);this.maxIdleTimer=void 0}if(this.statusChangeListener){removeMCPStatusChangeListener(this.statusChangeListener);this.statusChangeListener=void 0}this.emit({kind:"disconnected",serverName:this.serverName,generation:this._generation,reason:"transport_closed"});for(const[sid]of this.subscribers){this.detach(sid)}await this.sweepAndDisconnect(reason);this.updateGlobalStatus();this.onClosed(this.id)}async sweepAndDisconnect(reason){const result={};try{const rootPid=this.client.getTransportPid?.();if(rootPid!==void 0){const descendants=await listDescendantPids(rootPid);if(descendants.length>0){result.descendantsFound=descendants.length;result.descendantsSignaled=sigtermPids(descendants);debugLogger.debug(`Sent SIGTERM to ${result.descendantsSignaled}/${descendants.length} descendants of pid ${rootPid} for ${this.id} (${reason})`)}}}catch(err){result.pidSweepError=err instanceof Error?err:new Error(String(err));debugLogger.warn(`Descendant pid sweep failed for ${this.id} (${reason}): ${String(err)}. Proceeding with disconnect.`)}try{await this.client.disconnect()}catch(err){debugLogger.error(`client.disconnect failed for ${this.id} (${reason}): ${String(err)}`)}return result}async restart(){if(this.restartInFlight)return this.restartInFlight;this.restartInFlight=this.doRestart().finally(()=>{this.restartInFlight=void 0});return this.restartInFlight}async doRestart(){if(this.state==="closed"||this.state==="failed"){throw new Error(`Cannot restart PoolEntry ${this.id} in state ${this.state}`)}this.restartInProgress=true;try{return await this.doRestartInner()}finally{this.restartInProgress=false}}async doRestartInner(){this.cancelDrainTimer();if(this.maxIdleTimer){clearTimeout(this.maxIdleTimer);this.maxIdleTimer=void 0}this.firstIdleAt=void 0;if(this.state==="draining"){this.state="active"}const oldGen=this._generation;this._generation+=1;this.emit({kind:"disconnected",serverName:this.serverName,generation:oldGen,reason:"restart"});await this.sweepAndDisconnect("restart");let snap;try{const timeoutMs=discoveryTimeoutFor(this.cfg);snap=await runWithTimeout((async()=>{await this.client.connect();return this.client.discoverAndReturn(this.cliConfig,{applyConfigFilters:false})})(),timeoutMs,`pool restart for ${this.id} (pool will roll back the restart and free its budget slot)`)}catch(err){debugLogger.error(`Restart of ${this.id} failed at connect/discover: ${String(err)}. Transitioning to 'failed'.`);await this.sweepAndDisconnect("restart_failed");this.state="failed";this.localStatus="disconnected";this.suppressNextStatusEcho=true;this.updateGlobalStatus();if(this.statusChangeListener){removeMCPStatusChangeListener(this.statusChangeListener);this.statusChangeListener=void 0}this.emit({kind:"failed",serverName:this.serverName,generation:this._generation,lastError:err instanceof Error?err.message:String(err)});for(const[sid]of this.subscribers){this.detach(sid)}this.onClosed(this.id);throw err}if(oldGen+1!==this._generation){await this.sweepAndDisconnect("restart_superseded");throw new Error(`Restart of ${this.id} superseded by newer generation; discarded stale snapshot + swept new transport.`)}const currentState=this.state;if(currentState==="closed"||currentState==="failed"){await this.sweepAndDisconnect("restart_superseded");throw new Error(`Restart of ${this.id} aborted: entry state is ${currentState} (forceShutdown ran concurrently mid-restart). Snapshot discarded; new transport swept.`)}this.toolsSnapshot=snap.tools;this.promptsSnapshot=snap.prompts;if(snap.resources.length>0){this.resourcesSnapshot=snap.resources}for(const[sid,view]of this.subscribers){try{view.applyTools(this.toolsSnapshot);view.applyPrompts(this.promptsSnapshot);view.applyResources(this.resourcesSnapshot)}catch(err){debugLogger.error(`Restart fan-out to view ${sid}/${this.serverName} failed: ${String(err)}`)}}this.localStatus="connected";this.suppressNextStatusEcho=true;this.updateGlobalStatus();this.emit({kind:"reconnected",serverName:this.serverName,generation:this._generation});this.emit({kind:"toolsChanged",serverName:this.serverName,snapshot:this.toolsSnapshot,generation:this._generation});this.emit({kind:"promptsChanged",serverName:this.serverName,snapshot:this.promptsSnapshot,generation:this._generation});this.emit({kind:"resourcesChanged",serverName:this.serverName,snapshot:this.resourcesSnapshot,generation:this._generation})}emit(event){const listeners=this.emitter.listeners("event");for(const listener of listeners){try{listener(event)}catch(err){debugLogger.error(`PoolEntry listener error for ${this.id} (event.kind=${event.kind}): ${err instanceof Error?err.message:String(err)}`)}}}internalOn(listener){this.emitter.on("event",listener)}internalOff(listener){this.emitter.off("event",listener)}updateGlobalStatus(){const aggregated=this.aggregateStatusByName(this.serverName);updateMCPServerStatus(this.serverName,aggregated)}getLocalStatus(){return this.localStatus}};var PooledConnectionImpl=class{constructor(entry,sessionId,releaseCallback){this.entry=entry;this.sessionId=sessionId;this.releaseCallback=releaseCallback}static{__name(this,"PooledConnectionImpl")}listeners=new Set;released=false;get id(){return this.entry.id}get transportId(){return this.entry.transportId}get serverName(){return this.entry.serverName}get entryIndex(){return this.entry.entryIndex}get client(){return this.entry.client}get toolsSnapshot(){return this.entry.toolsSnapshot}get promptsSnapshot(){return this.entry.promptsSnapshot}get resourcesSnapshot(){return this.entry.resourcesSnapshot}updateConfig(cfg){if(this.released){throw new Error(`Cannot update config on released MCP connection ${this.id}`)}this.entry.updateSessionConfig(this.sessionId,cfg)}on(event,listener){if(event!=="event")return this;if(this.listeners.has(listener))return this;this.listeners.add(listener);this.entry.internalOn(listener);return this}off(event,listener){if(event!=="event")return this;this.listeners.delete(listener);this.entry.internalOff(listener);return this}release(){if(this.released)return;this.released=true;for(const l of this.listeners){this.entry.internalOff(l)}this.listeners.clear();this.releaseCallback?.()}};init_esbuild_shims();var debugLogger2=createDebugLogger("McpPool:View");function compileNameFilter(includeTools,excludeTools){return{excludeSet:excludeTools?new Set(coerceMcpFilterEntries(excludeTools)):void 0,includeSet:includeTools!=null?new Set(coerceMcpFilterEntries(includeTools).map(normalizeMcpIncludeEntry)):void 0}}__name(compileNameFilter,"compileNameFilter");function compiledFilterAccepts(filter2,name){if(filter2.excludeSet?.has(name))return false;if(!filter2.includeSet)return true;return filter2.includeSet.has(name)}__name(compiledFilterAccepts,"compiledFilterAccepts");var SessionMcpView=class{constructor(sessionToolRegistry,sessionPromptRegistry,sessionResourceRegistry,sessionId,serverName,cfg){this.sessionToolRegistry=sessionToolRegistry;this.sessionPromptRegistry=sessionPromptRegistry;this.sessionResourceRegistry=sessionResourceRegistry;this.sessionId=sessionId;this.serverName=serverName;this.cfg=cfg;this.metadataKey=mcpSessionMetadataKey(cfg)}static{__name(this,"SessionMcpView")}metadataKey;applyTools(snapshot){this.sessionToolRegistry.removeMcpToolsByServer(this.serverName);const filter2=compileNameFilter(this.cfg.includeTools,this.cfg.excludeTools);let registered=0;for(const tool of snapshot){if(!compiledFilterAccepts(filter2,tool.serverToolName)){continue}const sessionTool=tool.withSessionConfig(this.cfg.trust,this.cfg.alwaysLoadTools===true);try{this.sessionToolRegistry.registerTool(sessionTool);registered+=1}catch(err){debugLogger2.error(`SessionMcpView[${this.sessionId}/${this.serverName}] failed to register tool ${tool.serverToolName}: ${String(err instanceof Error?err.message:err)}`)}}debugLogger2.debug(`SessionMcpView[${this.sessionId}/${this.serverName}] applied ${snapshot.length} tools (filtered to ${registered} registered)`)}applyPrompts(snapshot){this.sessionPromptRegistry.removePromptsByServer(this.serverName);const filter2=compileNameFilter(this.cfg.includeTools,this.cfg.excludeTools);let registered=0;for(const prompt of snapshot){if(!compiledFilterAccepts(filter2,prompt.name)){continue}try{this.sessionPromptRegistry.registerPrompt(prompt);registered+=1}catch(err){debugLogger2.error(`SessionMcpView[${this.sessionId}/${this.serverName}] failed to register prompt ${prompt.name}: ${String(err instanceof Error?err.message:err)}`)}}debugLogger2.debug(`SessionMcpView[${this.sessionId}/${this.serverName}] applied ${snapshot.length} prompts (filtered to ${registered} registered)`)}applyResources(snapshot){if(snapshot.length===0){return}this.sessionResourceRegistry.removeResourcesByServer(this.serverName);for(const resource of snapshot){try{this.sessionResourceRegistry.registerResource(resource)}catch(err){debugLogger2.error(`SessionMcpView[${this.sessionId}/${this.serverName}] failed to register resource ${resource.uri}: ${String(err instanceof Error?err.message:err)}`)}}debugLogger2.debug(`SessionMcpView[${this.sessionId}/${this.serverName}] applied ${snapshot.length} resources`)}updateConfig(cfg){const nextKey=mcpSessionMetadataKey(cfg);const changed=this.metadataKey!==nextKey;this.cfg=cfg;this.metadataKey=nextKey;return changed}teardown(){this.sessionToolRegistry.removeMcpToolsByServer(this.serverName);this.sessionPromptRegistry.removePromptsByServer(this.serverName);this.sessionResourceRegistry.removeResourcesByServer(this.serverName);debugLogger2.debug(`SessionMcpView[${this.sessionId}/${this.serverName}] torn down`)}};var debugLogger3=createDebugLogger("McpPool");var McpTransportPool=class{constructor(cliConfig,options){this.cliConfig=cliConfig;this.opts={workspaceContext:options.workspaceContext,debugMode:options.debugMode,sendSdkMcpMessage:options.sendSdkMcpMessage,pooledTransports:options.pooledTransports??POOLED_TRANSPORTS_DEFAULT,drainDelayMs:options.drainDelayMs??3e4,entryOptions:options.entryOptions??defaultPoolEntryOptions,budget:options.budget}}static{__name(this,"McpTransportPool")}entries=new Map;unpooledIds=new Set;spawnInFlight=new Map;sessionToEntries=new Map;draining=false;nextIndexByName=new Map;opts;getBudget(){return this.opts.budget}hasNameSibling(serverName){for(const e of this.entries.values()){if(e.serverName===serverName)return true}for(const id of this.spawnInFlight.keys()){try{if(parseConnectionId(id).serverName===serverName)return true}catch{}}return false}async acquire(serverName,cfg,sessionId,sessionToolRegistry,sessionPromptRegistry,sessionResourceRegistry){if(this.draining){throw new Error(`McpTransportPool is draining; refusing acquire for ${serverName} (session ${sessionId})`)}const poolable=isPoolable(cfg,this.opts.pooledTransports);const id=poolable?connectionIdOf(serverName,cfg):void 0;if(id!==void 0){const existing=this.entries.get(id);if(existing&&!existing.isTerminated()){try{const conn=this.attachPooledSession(existing,id,serverName,cfg,sessionId,sessionToolRegistry,sessionPromptRegistry,sessionResourceRegistry);this.indexAttach(sessionId,id);return conn}catch(err){if(existing.isTerminated()){this.evictEntry(id,existing);debugLogger3.warn(`pool self-heal: evicted terminal entry ${id} (state='${existing.currentState}', serverName='${serverName}') mid-attach race; falling through to spawn fresh entry`)}else{throw err}}}else if(existing&&existing.isTerminated()){this.evictEntry(id,existing);debugLogger3.warn(`pool self-heal: evicted stale terminal entry ${id} (state='${existing.currentState}', serverName='${serverName}') before fast-path attach; falling through to spawn fresh entry`)}}let reservationResult;if(this.opts.budget!==void 0){const reservation=this.opts.budget.tryReserve(serverName);if(reservation==="refused"){const transport=mcpTransportOf(cfg);this.opts.budget.recordRefusal(serverName,transport);throw new BudgetExhaustedError(serverName,this.opts.budget.getBudget()??0,this.opts.budget.getReservedCount())}reservationResult=reservation}if(!poolable){try{return await this.createUnpooledConnection(serverName,cfg,sessionId,sessionToolRegistry,sessionPromptRegistry,sessionResourceRegistry)}catch(err){this.rollbackReservationOnSpawnFailure(reservationResult,serverName);throw err}}if(id===void 0){throw new Error("unreachable: poolable && id === undefined")}let inFlight=this.spawnInFlight.get(id);if(!inFlight){const spawnPromise=this.spawnEntry(serverName,cfg,id);inFlight=spawnPromise.finally(()=>{this.spawnInFlight.delete(id)}).catch(err=>{this.rollbackReservationOnSpawnFailure(reservationResult,serverName);throw err});this.spawnInFlight.set(id,inFlight)}this.indexAttach(sessionId,id);let entry;try{entry=await inFlight}catch(err){this.indexDetach(sessionId,id);throw err}if(!this.entries.has(id)||entry.isTerminated()){this.indexDetach(sessionId,id);throw new Error(`PoolEntry ${id} torn down before attach (concurrent release)`)}try{const conn=this.attachPooledSession(entry,id,serverName,cfg,sessionId,sessionToolRegistry,sessionPromptRegistry,sessionResourceRegistry);this.indexAttach(sessionId,id);return conn}catch(err){this.indexDetach(sessionId,id);throw err}}release(id,sessionId){const entry=this.entries.get(id);if(!entry)return;entry.detach(sessionId);this.indexDetach(sessionId,id);if(entry.refs.size===0){if(this.unpooledIds.has(id)){void entry.forceShutdown("manual");return}entry.startDrainTimer(this.opts.drainDelayMs)}}releaseSession(sessionId){const ids=this.sessionToEntries.get(sessionId);if(!ids)return;const idList=[...ids];for(const id of idList){const entry=this.entries.get(id);if(!entry)continue;entry.detach(sessionId);if(entry.refs.size===0){if(this.unpooledIds.has(id)){void entry.forceShutdown("manual");continue}entry.startDrainTimer(this.opts.drainDelayMs)}}this.sessionToEntries.delete(sessionId)}async restartByName(serverName,opts){if(this.draining)return[];const matching=[...this.entries.values()].filter(e=>e.serverName===serverName&&(opts?.entryIndex===void 0||e.entryIndex===opts.entryIndex));if(matching.length===0)return[];return Promise.all(matching.map(async entry=>{const started=Date.now();try{await entry.restart();if(entry.refs.size===0&&!this.unpooledIds.has(entry.id)){entry.startDrainTimer(this.opts.drainDelayMs)}return{entryIndex:entry.entryIndex,restarted:true,durationMs:Date.now()-started}}catch(err){return{entryIndex:entry.entryIndex,restarted:false,reason:String(err instanceof Error?err.message:err)}}}))}getSnapshot(){const byName=new Map;let total=0;let subprocessCount=0;for(const entry of this.entries.values()){const status=entry.getLocalStatus();if(status==="connected"){total+=1;if(entry.transportKind==="stdio"){subprocessCount+=1}}const row=byName.get(entry.serverName)??{entryCount:0,entrySummary:[]};row.entryCount+=1;row.entrySummary.push({entryIndex:entry.entryIndex,refs:entry.refs.size,status});byName.set(entry.serverName,row)}return{total,subprocessCount,byName:Object.fromEntries(byName.entries())}}aggregateStatusByName(serverName){let sawConnecting=false;for(const entry of this.entries.values()){if(entry.serverName!==serverName)continue;const s=entry.getLocalStatus();if(s==="connected")return"connected";if(s==="connecting")sawConnecting=true}return sawConnecting?"connecting":"disconnected"}async drainAll(opts){const timeoutMs=opts?.timeoutMs??1e4;const force=opts?.force??false;this.draining=true;const deadline=Date.now()+timeoutMs;if(this.spawnInFlight.size>0){const spawnWait=Promise.allSettled([...this.spawnInFlight.values()]);let inflightTimer;await Promise.race([spawnWait.then(()=>{if(inflightTimer)clearTimeout(inflightTimer)}),new Promise(resolve9=>{inflightTimer=setTimeout(()=>{const stuckIds=[...this.spawnInFlight.keys()];debugLogger3.warn(`drainAll: spawnInFlight wait timed out after ${timeoutMs}ms; ${stuckIds.length} spawn(s) still in-flight: ${stuckIds.join(", ")}. Proceeding with drain.`);resolve9()},Math.max(0,deadline-Date.now()));inflightTimer.unref?.()})])}const entries=[...this.entries.values()];const drained=[];const errors=[];const shutdownPromises=entries.map(entry=>entry.forceShutdown(force?"manual":"drain_timer").then(()=>drained.push(entry.entryIndex)).catch(err=>{errors.push({entryIndex:entry.entryIndex,serverName:entry.serverName,error:String(err instanceof Error?err.message:err)})}));let drainTimer;const remaining=Math.max(0,deadline-Date.now());await Promise.race([Promise.all(shutdownPromises).then(()=>{if(drainTimer)clearTimeout(drainTimer)}),new Promise(resolve9=>{drainTimer=setTimeout(()=>resolve9(),remaining);drainTimer.unref?.()})]);const drainedCount=drained.length;const errorsCount=errors.length;const forced=Math.max(0,entries.length-drainedCount-errorsCount);const errorsCopy=[...errors];this.entries.clear();this.unpooledIds.clear();this.sessionToEntries.clear();this.spawnInFlight.clear();return{drained:drainedCount,forced,errors:errorsCopy}}attachPooledSession(entry,id,serverName,cfg,sessionId,sessionToolRegistry,sessionPromptRegistry,sessionResourceRegistry){const view=new SessionMcpView(sessionToolRegistry,sessionPromptRegistry,sessionResourceRegistry,sessionId,serverName,cfg);return entry.attach(sessionId,view,{release:__name(()=>this.release(id,sessionId),"release")})}rollbackReservationOnSpawnFailure(reservationResult,serverName){if(this.opts.budget!==void 0&&reservationResult==="reserved"&&!this.hasNameSibling(serverName)){this.opts.budget.release(serverName)}}evictEntry(id,entry){if(entry===void 0)return;const current=this.entries.get(id);if(current!==entry)return;this.entries.delete(id);if(this.opts.budget!==void 0){if(!this.hasNameSibling(entry.serverName)){this.opts.budget.release(entry.serverName)}}}async spawnEntry(serverName,cfg,id){const entryIndex=this.allocateEntryIndex(serverName);const transport=mcpTransportOf(cfg);const entryOpts=this.opts.entryOptions(transport);const client=new McpClient(serverName,cfg,poisonedToolRegistry(serverName),poisonedPromptRegistry(serverName),this.opts.workspaceContext,this.opts.debugMode,this.opts.sendSdkMcpMessage);const entryRef={current:void 0};const onClosedForThisEntry=__name(closedId=>{this.evictEntry(closedId,entryRef.current)},"onClosedForThisEntry");const entry=new PoolEntry(id,serverName,entryIndex,cfg,client,this.cliConfig,entryOpts,onClosedForThisEntry,name=>this.aggregateStatusByName(name));entryRef.current=entry;try{const timeoutMs=discoveryTimeoutFor(cfg);const snap=await runWithTimeout((async()=>{await client.connect();return client.discoverAndReturn(this.cliConfig,{applyConfigFilters:false})})(),timeoutMs,`pool spawn for ${id} (pool will roll back the spawn and free its budget slot)`);if(this.draining){debugLogger3.warn(`Spawn for ${id} completed while pool is draining; discarding entry`);try{await entry.forceShutdown("manual")}catch{}throw new Error(`McpTransportPool is draining; discarded spawn ${id}`)}this.entries.set(id,entry);entry.markActive(snap.tools,snap.prompts,snap.resources);debugLogger3.info(`Spawned pool entry ${id} (entryIndex=${entryIndex}, transport=${transport})`);return entry}catch(err){debugLogger3.error(`Failed to spawn pool entry for '${serverName}' (id=${id}, transport=${transport}): ${String(err)}`);try{await entry.forceShutdown("manual")}catch{}this.entries.delete(id);try{await client.disconnect()}catch{}throw err}}allocateEntryIndex(serverName){const next=this.nextIndexByName.get(serverName)??0;this.nextIndexByName.set(serverName,next+1);return next}indexAttach(sessionId,id){let ids=this.sessionToEntries.get(sessionId);if(!ids){ids=new Set;this.sessionToEntries.set(sessionId,ids)}ids.add(id)}indexDetach(sessionId,id){const ids=this.sessionToEntries.get(sessionId);if(!ids)return;ids.delete(id);if(ids.size===0)this.sessionToEntries.delete(sessionId)}async createUnpooledConnection(serverName,cfg,sessionId,sessionToolRegistry,sessionPromptRegistry,sessionResourceRegistry){const entryIndex=this.allocateEntryIndex(serverName);const id=`${serverName}::unpooled-${entryIndex}`;const transport=mcpTransportOf(cfg);const entryOpts=this.opts.entryOptions(transport);const client=new McpClient(serverName,cfg,sessionToolRegistry,sessionPromptRegistry,this.opts.workspaceContext,this.opts.debugMode,this.opts.sendSdkMcpMessage);const view=new SessionMcpView(sessionToolRegistry,sessionPromptRegistry,sessionResourceRegistry,sessionId,serverName,cfg);const entry=new PoolEntry(id,serverName,entryIndex,cfg,client,this.cliConfig,entryOpts,closedId=>{this.entries.delete(closedId);this.unpooledIds.delete(closedId);if(this.opts.budget!==void 0){if(!this.hasNameSibling(serverName)){this.opts.budget.release(serverName)}}},()=>client.getStatus());try{this.entries.set(id,entry);this.unpooledIds.add(id);this.indexAttach(sessionId,id);const timeoutMs=discoveryTimeoutFor(cfg);const snap=await runWithTimeout((async()=>{await client.connect();return await client.discoverAndReturn(this.cliConfig,{applyConfigFilters:false})})(),timeoutMs,`unpooled spawn for ${id} (pool will roll back the spawn and free its budget slot)`);if(this.draining||!this.entries.has(id)||entry.isTerminated()){try{view.teardown()}catch{}try{await entry.forceShutdown("manual")}catch{}this.indexDetach(sessionId,id);throw new Error(`McpTransportPool is draining or unpooled ${id} was cancelled`)}entry.markActive(snap.tools,snap.prompts,snap.resources);const conn=entry.attach(sessionId,view,{release:__name(()=>{this.indexDetach(sessionId,id);void entry.forceShutdown("manual")},"release")});return conn}catch(err){try{await entry.forceShutdown("manual")}catch{}this.entries.delete(id);this.unpooledIds.delete(id);this.indexDetach(sessionId,id);try{await client.disconnect()}catch{}throw err}}};function poisonedToolRegistry(serverName){return{registerTool(){throw new Error(`Pool invariant violated: poisoned ToolRegistry for ${serverName} received registerTool. A pool path must use discoverAndReturn, not discover.`)}}}__name(poisonedToolRegistry,"poisonedToolRegistry");function poisonedPromptRegistry(serverName){return{registerPrompt(){throw new Error(`Pool invariant violated: poisoned PromptRegistry for ${serverName} received registerPrompt. A pool path must use discoverAndReturn.`)}}}__name(poisonedPromptRegistry,"poisonedPromptRegistry");init_esbuild_shims();var debugLogger4=createDebugLogger("McpPool:Budget");var WorkspaceMcpBudget=class{static{__name(this,"WorkspaceMcpBudget")}clientBudget;mode;onEvent;reservedSlots=new Set;pendingRefusalNames=new Set;pendingRefusalTransports=new Map;lastRefusedServerNames=[];warnArmed=true;bulkPassDepth=0;constructor(opts){this.clientBudget=opts.clientBudget;this.mode=opts.mode;this.onEvent=opts.mode==="off"?void 0:opts.onEvent}getMode(){return this.mode}getBudget(){return this.clientBudget}getReservedSlots(){return Array.from(this.reservedSlots)}getRefusedServerNames(){return this.lastRefusedServerNames}getReservedCount(){return this.reservedSlots.size}tryReserve(serverName){if(this.reservedSlots.has(serverName))return"already_held";if(this.clientBudget===void 0||this.mode==="off"){return"reserved"}if(this.mode==="enforce"&&this.reservedSlots.size>=this.clientBudget){return"refused"}this.reservedSlots.add(serverName);this.evaluateState();return"reserved"}release(serverName){const had=this.reservedSlots.delete(serverName);if(had)this.evaluateState();return had}recordRefusal(serverName,transport){if(this.mode!=="enforce")return;this.pendingRefusalNames.add(serverName);this.pendingRefusalTransports.set(serverName,transport);debugLogger4.warn(`MCP server '${serverName}' refused at pool acquire (budget exhausted, budget=${this.clientBudget}, mode=${this.mode})`);if(this.bulkPassDepth===0){this.flushRefusedBatch()}}beginBulkPass(){if(this.bulkPassDepth===0){this.lastRefusedServerNames=[]}this.bulkPassDepth+=1}endBulkPass(){if(this.bulkPassDepth===0){debugLogger4.warn("WorkspaceMcpBudget.endBulkPass called without matching beginBulkPass; ignoring");return}this.bulkPassDepth-=1;if(this.bulkPassDepth>0)return;this.flushRefusedBatch()}flushRefusedBatch(){if(this.pendingRefusalNames.size===0)return;if(this.clientBudget===void 0||this.mode!=="enforce"){this.pendingRefusalNames.clear();this.pendingRefusalTransports.clear();return}const refusedServers=[];const names=[];for(const name of this.pendingRefusalNames){const transport=this.pendingRefusalTransports.get(name)??"unknown";refusedServers.push({name,transport,reason:"budget_exhausted"});names.push(name)}this.lastRefusedServerNames=Object.freeze(names);this.pendingRefusalNames.clear();this.pendingRefusalTransports.clear();if(this.onEvent){try{this.onEvent({kind:"refused_batch",refusedServers,budget:this.clientBudget,liveCount:this.reservedSlots.size,reservedCount:this.reservedSlots.size,mode:"enforce"})}catch(err){debugLogger4.error(`WorkspaceMcpBudget refused_batch event delivery failed: ${err instanceof Error?err.message:String(err)}`)}}}evaluateState(){if(this.mode==="off"||this.clientBudget===void 0)return;const ratio=this.reservedSlots.size/this.clientBudget;if(this.warnArmed&&ratio>=MCP_BUDGET_WARN_FRACTION){this.warnArmed=false;debugLogger4.info(`MCP workspace budget warning fired (ratio=${ratio.toFixed(2)}, reservedCount=${this.reservedSlots.size}, budget=${this.clientBudget}, mode=${this.mode})`);if(this.onEvent){try{this.onEvent({kind:"budget_warning",liveCount:this.reservedSlots.size,reservedCount:this.reservedSlots.size,budget:this.clientBudget,thresholdRatio:MCP_BUDGET_WARN_FRACTION,mode:this.mode})}catch(err){debugLogger4.error(`WorkspaceMcpBudget budget_warning event delivery failed: ${err instanceof Error?err.message:String(err)}`)}}}else if(!this.warnArmed&&ratio<MCP_BUDGET_REARM_FRACTION){this.warnArmed=true;debugLogger4.info(`MCP workspace budget warning re-armed (ratio=${ratio.toFixed(2)}, budget=${this.clientBudget}; next 75% crossing will fire)`)}}};init_esbuild_shims();function preservePlaceholders(value,resolved,original){if(typeof original==="string"&&value===resolved)return original;if(Array.isArray(value)&&Array.isArray(resolved)&&Array.isArray(original)){return value.map((entry,index)=>preservePlaceholders(entry,resolved[index],original[index]))}if(value&&resolved&&original&&typeof value==="object"&&!Array.isArray(value)&&typeof resolved==="object"&&!Array.isArray(resolved)&&typeof original==="object"&&!Array.isArray(original)){return Object.fromEntries(Object.entries(value).map(([key,entry])=>[key,preservePlaceholders(entry,resolved[key],original[key])]))}return value}__name(preservePlaceholders,"preservePlaceholders");function preserveModelProviderPlaceholders(models,provider,resolvedProviders,rawProviders,mapping){const pairs=Object.entries(resolvedProviders).flatMap(([providerId,entries])=>{if(!Array.isArray(entries))return[];return entries.flatMap((entry,index)=>{const resolved=provider==="openai"?getModelsForProviderProtocol({[providerId]:[entry]},"openai",mapping)[0]:providerId===provider?entry:void 0;return resolved?[{providerId,resolved,source:entry,raw:rawProviders[providerId]?.[index]??entry}]:[]})});return models.map(model=>{const matches=pairs.filter(({resolved})=>resolved.id===model.id&&resolved.baseUrl===model.baseUrl&&tryResolveModelProtocol(provider,resolved,mapping)===tryResolveModelProtocol(provider,model,mapping));const sourceMatches=matches.filter(pair=>pair.providerId===matches[0]?.providerId);if(sourceMatches.length>1&&sourceMatches.some(pair=>JSON.stringify(pair.raw)!==JSON.stringify(pair.source))){throw new Error("Cannot preserve placeholders in an ambiguous model configuration. Remove duplicate model entries first.")}const match=matches[0];return match?preservePlaceholders(model,match.resolved,match.raw):model})}__name(preserveModelProviderPlaceholders,"preserveModelProviderPlaceholders");init_esbuild_shims();init_esbuild_shims();var DISCOVERY_TIMEOUT_MS=5e3;var DISCOVERY_MAX_BYTES=1024*1024;var MAX_MODEL_ID_LENGTH=256;var UNSAFE_MODEL_ID_CHARS=/[,\p{C}\p{Zl}\p{Zp}]/u;function readModels(value){if(!value||typeof value!=="object"||!("data"in value)){return null}const data=value.data;if(!Array.isArray(data)){return null}const models=[];const seen=new Set;for(const item of data){if(!item||typeof item!=="object"||!("id"in item)){return null}const id=item.id;if(typeof id!=="string"){return null}const trimmedId=id.trim();if(trimmedId&&trimmedId.length<=MAX_MODEL_ID_LENGTH&&!UNSAFE_MODEL_ID_CHARS.test(trimmedId)&&!seen.has(trimmedId)){seen.add(trimmedId);const created=item.created;const creationTime=typeof created==="number"&&Number.isFinite(created)&&created>=0?created:void 0;models.push({id:trimmedId,...creationTime===void 0?{}:{created:creationTime}})}}return models.length>0?models:null}__name(readModels,"readModels");function mergeModelSpecs(discoveredModels,staticModels){const staticModelsById=new Map(staticModels.map(model=>[model.id,model]));const orderedModels=[...discoveredModels];if(orderedModels.every(model=>model.created!==void 0)){orderedModels.sort((left,right)=>(right.created??0)-(left.created??0))}return orderedModels.map(({id})=>staticModelsById.get(id)??{id})}__name(mergeModelSpecs,"mergeModelSpecs");async function discoverProviderModels({baseUrl,apiKey,staticModels,signal}){const normalizedBaseUrl=baseUrl.trim();const normalizedApiKey=apiKey.trim();if(!normalizedBaseUrl||!normalizedApiKey){return null}try{const modelsUrl=`${normalizedBaseUrl.replace(/\/+$/,"")}/models`;const result=await fetchWithPolicy(modelsUrl,{timeoutMs:DISCOVERY_TIMEOUT_MS,maxBytes:DISCOVERY_MAX_BYTES,maxRedirects:2,headers:{Accept:"application/json",Authorization:`Bearer ${normalizedApiKey}`},signal});if(result.kind!=="response"||result.status<200||result.status>=300){return null}const models=readModels(JSON.parse(result.body.toString("utf8")));return models?mergeModelSpecs(models,staticModels):null}catch{return null}}__name(discoverProviderModels,"discoverProviderModels");init_esbuild_shims();var IMAGE_CAPABILITY=Object.freeze({autoHandlesWrongModel:true,maxBytes:VISION_BRIDGE_MAX_IMAGE_BASE64_BYTES,maxImagesPerTurn:VISION_BRIDGE_MAX_IMAGES});init_esbuild_shims();var debugLogger5=createDebugLogger("SESSION_RECAP");var RECENT_MESSAGE_WINDOW=30;var RECAP_SYSTEM_PROMPT=`You generate session recaps for a programming assistant CLI.
|
|
4
4
|
|
|
5
5
|
The user stepped away and is coming back. Recap in under 40 words, 1-2 plain sentences, no markdown. Lead with the overall goal and current task, then the one next action. Skip root-cause narrative, fix internals, secondary to-dos, and em-dash tangents.
|
|
6
6
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// Force strict mode and setup for ESM
|
|
2
2
|
"use strict";
|
|
3
|
-
import{loadUndici}from"./chunk-XKSB7VTV.js";import{updateEventEmitter}from"./chunk-VDUNIK4I.js";import{require_semver}from"./chunk-YZUKMJW7.js";import{hasStandaloneArchiveLayout,standaloneRuntimePaths}from"./chunk-26MNTKT2.js";import{t}from"./chunk-ABJGFEES.js";import{So}from"./chunk-Z5XENA4A.js";import{createDebugLogger}from"./chunk-JAUJI56S.js";import{init_esbuild_shims}from"./chunk-VKDAXTCZ.js";import{__name,__toESM}from"./chunk-KBWJGX7I.js";init_esbuild_shims();import{createHash}from"node:crypto";import*as fs from"node:fs";import*as os from"node:os";import*as path from"node:path";import{Readable,Transform}from"node:stream";import{spawn,execFile}from"node:child_process";import{pipeline}from"node:stream/promises";var import_semver=__toESM(require_semver(),1);init_esbuild_shims();import{createPublicKey,verify}from"node:crypto";var RELEASE_PUBLIC_KEY_DER_B64="MCowBQYDK2VwAyEAr9WRFLDauibZQKCe1oKfuFZn6zRMaEkD5+KVqN6mKM4=";function verifySignature(sha256sumsContent,signatureBase64){const key=createPublicKey({key:Buffer.from(RELEASE_PUBLIC_KEY_DER_B64,"base64"),format:"der",type:"spki"});const signature=Buffer.from(signatureBase64,"base64");if(signature.length!==64){throw new Error(`Invalid signature length: expected 64 bytes, got ${signature.length}`)}const valid=verify(null,Buffer.from(sha256sumsContent),key,signature);if(!valid){throw new Error("SHA256SUMS signature verification failed \u2014 possible tampering detected")}}__name(verifySignature,"verifySignature");var debugLogger=createDebugLogger("STANDALONE_UPDATE");var OSS_BASE="https://qwen-code-assets.oss-cn-hangzhou.aliyuncs.com/releases/qwen-code";var GITHUB_BASE="https://github.com/QwenLM/qwen-code/releases/download";var FETCH_TIMEOUT_MS=3e4;var ARCHIVE_TIMEOUT_MS=3e5;var VALID_TARGETS=new Set(["darwin-arm64","darwin-x64","linux-arm64","linux-x64","win-x64"]);var SEMVER_RE=/^v?\d+\.\d+\.\d+(-[\w.]+)?$/;function isConcreteVersion(version){return SEMVER_RE.test(version)&&import_semver.default.valid(version)!==null}__name(isConcreteVersion,"isConcreteVersion");function normalizeVersion(version){if(!isConcreteVersion(version)){throw new Error(`Invalid version format: ${version}`)}return version.startsWith("v")?version:`v${version}`}__name(normalizeVersion,"normalizeVersion");function validateTarget(target){if(!VALID_TARGETS.has(target)){throw new Error(`Unknown target: ${target}`)}}__name(validateTarget,"validateTarget");function archiveFilename(target,runtime){const ext=target.startsWith("win")?"zip":"tar.gz";const suffix=runtime==="bun"?"-opentui-preview":"";return`qwen-code-${target}${suffix}.${ext}`}__name(archiveFilename,"archiveFilename");function escapePS(s){return s.replace(/'/g,"''")}__name(escapePS,"escapePS");function resolveUpdateBaseUrl(){const value=process.env["QWEN_UPDATE_BASE_URL"]?.trim();if(!value)return void 0;const invalidUrl=__name(()=>new Error("QWEN_UPDATE_BASE_URL must be an absolute HTTPS URL without credentials, query parameters, or a fragment."),"invalidUrl");let url;try{url=new URL(value)}catch{throw invalidUrl()}if(!/^https:\/\//i.test(value)||url.username||url.password||/[?#\s]/.test(value)){throw invalidUrl()}return url.href.replace(/\/+$/,"")}__name(resolveUpdateBaseUrl,"resolveUpdateBaseUrl");async function tryFetch(url,timeoutMs=FETCH_TIMEOUT_MS){try{const{fetch}=await loadUndici();const res=await fetch(url,{signal:AbortSignal.timeout(timeoutMs)});if(res.ok)return{response:res};await res.body?.cancel().catch(()=>{});return{error:new Error(`HTTP ${res.status} ${res.statusText}`)}}catch(err){const error=err instanceof Error?err:new Error(String(err));debugLogger.debug(`Fetch failed for ${url}: ${error.message}`);return{error}}}__name(tryFetch,"tryFetch");async function downloadWithFallback(versionPath,filename,timeoutMs=FETCH_TIMEOUT_MS,baseUrl){if(baseUrl){const result=await tryFetch(`${baseUrl}/${versionPath}/${filename}`,timeoutMs);if(result.response)return result.response;throw new Error(`Failed to download ${filename} from QWEN_UPDATE_BASE_URL: ${result.error.message}`)}const ossUrl=`${OSS_BASE}/${versionPath}/${filename}`;const ossResult=await tryFetch(ossUrl,timeoutMs);if(ossResult.response)return ossResult.response;const ghUrl=`${GITHUB_BASE}/${versionPath}/${filename}`;const ghResult=await tryFetch(ghUrl,timeoutMs);if(ghResult.response)return ghResult.response;throw new Error(`Failed to download ${filename}: OSS (${ossResult.error?.message??"unknown"}), GitHub (${ghResult.error?.message??"unknown"})`)}__name(downloadWithFallback,"downloadWithFallback");async function verifyChecksum(actualHash,filename,versionPath,baseUrl){const response=await downloadWithFallback(versionPath,"SHA256SUMS",FETCH_TIMEOUT_MS,baseUrl);const text=await response.text();const requireSig=process.env["QWEN_REQUIRE_SIGNATURE"]==="1";let sigResponse;try{sigResponse=await downloadWithFallback(versionPath,"SHA256SUMS.sig",FETCH_TIMEOUT_MS,baseUrl)}catch(err){debugLogger.debug("SHA256SUMS.sig not available:",err)}if(sigResponse){const sigContent=await sigResponse.text();verifySignature(text,sigContent.trim());debugLogger.info("SHA256SUMS signature verified.")}else if(requireSig){throw new Error("SHA256SUMS.sig not found and QWEN_REQUIRE_SIGNATURE=1 is set")}else{debugLogger.warn("SHA256SUMS.sig not available \u2014 update integrity relies on SHA256 checksum only. Set QWEN_REQUIRE_SIGNATURE=1 to enforce signature verification.")}const expectedLine=text.split("\n").find(line=>{const parts=line.trim().split(/\s+/);if(parts.length<2)return false;const name=parts[parts.length-1].replace(/^\*/,"");return name===filename});if(!expectedLine){throw new Error(`No checksum found for ${filename} in SHA256SUMS`)}const expectedHash=expectedLine.trim().split(/\s+/)[0];if(actualHash!==expectedHash){throw new Error(`Checksum mismatch: expected ${expectedHash}, got ${actualHash}`)}}__name(verifyChecksum,"verifyChecksum");var MAX_DOWNLOAD_BYTES=512*1024*1024;async function downloadToFile(versionPath,filename,destPath,baseUrl){const response=await downloadWithFallback(versionPath,filename,ARCHIVE_TIMEOUT_MS,baseUrl);const body=response.body;if(!body)throw new Error("Empty response body");const contentLength=response.headers.get("content-length");if(contentLength&&parseInt(contentLength,10)>MAX_DOWNLOAD_BYTES){await body.cancel().catch(()=>{});throw new Error(`Download too large: ${contentLength} bytes exceeds ${MAX_DOWNLOAD_BYTES} limit`)}const hash=createHash("sha256");let bytesWritten=0;const dest=fs.createWriteStream(destPath);const sizeGuard=new Transform({transform(chunk,_encoding,callback){bytesWritten+=chunk.length;if(bytesWritten>MAX_DOWNLOAD_BYTES){callback(new Error(`Download exceeded ${MAX_DOWNLOAD_BYTES} byte limit`))}else{hash.update(chunk);callback(null,chunk)}}});await pipeline(Readable.fromWeb(body),sizeGuard,dest);return hash.digest("hex")}__name(downloadToFile,"downloadToFile");function isPathInside(base,candidate){const rel=path.relative(base,candidate);return rel===""||!!rel&&rel!==".."&&!rel.startsWith(`..${path.sep}`)&&!path.isAbsolute(rel)}__name(isPathInside,"isPathInside");function normalizeTarEntryPath(entryPath){const parts=entryPath.split(/[\\/]+/).filter(part=>part&&part!==".");if(parts.length===0||parts.includes("..")){return null}return parts.join("/")}__name(normalizeTarEntryPath,"normalizeTarEntryPath");function isSafeTarLinkTarget(entryPath,linkPath,resolvedDest){if(path.posix.isAbsolute(linkPath)||path.win32.isAbsolute(linkPath)){return false}const normalizedEntryPath=normalizeTarEntryPath(entryPath);if(!normalizedEntryPath){return false}const archiveRoot=normalizedEntryPath.split("/")[0];const linkTarget=path.resolve(resolvedDest,path.posix.dirname(normalizedEntryPath),linkPath);return isPathInside(path.join(resolvedDest,archiveRoot),linkTarget)}__name(isSafeTarLinkTarget,"isSafeTarLinkTarget");function getTarEntryType(entry){if("type"in entry)return entry.type;if("isFile"in entry&&entry.isFile())return"File";if("isDirectory"in entry&&entry.isDirectory())return"Directory";if("isSymbolicLink"in entry&&entry.isSymbolicLink()){return"SymbolicLink"}return void 0}__name(getTarEntryType,"getTarEntryType");function isSafeTarEntry(entryPath,entry,resolvedDest){if(!isSafeTarEntryPath(entryPath))return false;const entryType=getTarEntryType(entry);const linkPath="linkpath"in entry?entry.linkpath:void 0;if(entryType!=="File"&&entryType!=="Directory"&&entryType!=="SymbolicLink"){return false}if(entryType==="SymbolicLink"){if(linkPath===void 0)return false;return isSafeTarLinkTarget(entryPath,String(linkPath),resolvedDest)}return true}__name(isSafeTarEntry,"isSafeTarEntry");function isAlreadyExistsError(err){return typeof err==="object"&&err!==null&&"code"in err&&err.code==="EEXIST"}__name(isAlreadyExistsError,"isAlreadyExistsError");function validateExtractedPaths(resolvedDest,options={}){const entries=fs.readdirSync(resolvedDest,{recursive:true,withFileTypes:true});for(const entry of entries){if(options.symlinksOnly&&!entry.isSymbolicLink()){continue}const fullPath=path.join(String(entry.parentPath||entry.path),entry.name);let resolved;try{resolved=fs.realpathSync(fullPath)}catch(err){fs.rmSync(resolvedDest,{recursive:true,force:true});const detail=err instanceof Error?err.message:String(err);throw new Error(`Invalid archive entry: ${entry.name} could not be resolved (${detail})`)}if(!isPathInside(resolvedDest,resolved)){fs.rmSync(resolvedDest,{recursive:true,force:true});throw new Error(`Path traversal detected in archive: ${entry.name} resolves to ${resolved}`)}}}__name(validateExtractedPaths,"validateExtractedPaths");function isSafeTarEntryPath(entryPath){if(entryPath.length===0)return false;if(path.posix.isAbsolute(entryPath)||path.win32.isAbsolute(entryPath)){return false}return normalizeTarEntryPath(entryPath)!==null}__name(isSafeTarEntryPath,"isSafeTarEntryPath");async function extractArchive(archivePath,destDir,target){fs.mkdirSync(destDir,{recursive:true});if(target.startsWith("win")){await new Promise((resolve2,reject)=>{const ps=spawn("powershell.exe",["-NoProfile","-Command",`Expand-Archive -Path '${escapePS(archivePath)}' -DestinationPath '${escapePS(destDir)}' -Force`],{stdio:"ignore"});ps.on("close",code=>code===0?resolve2():reject(new Error(`Expand-Archive exited with code ${code}`)));ps.on("error",reject)});const resolvedDest=fs.realpathSync(destDir);validateExtractedPaths(resolvedDest)}else{const resolvedDest=fs.realpathSync(destDir);await So({file:archivePath,cwd:destDir,preservePaths:false,filter:__name((p,entry)=>isSafeTarEntry(p,entry,resolvedDest),"filter")});validateExtractedPaths(fs.realpathSync(destDir),{symlinksOnly:true})}}__name(extractArchive,"extractArchive");function spawnAndCapture(command,args,timeoutMs,cwd){const env={...process.env};for(const key of Object.keys(env)){if(/^(NODE_OPTIONS|BUN_OPTIONS|CLI_VERSION|QWEN_CODE_RELAUNCH_ARGS)$/i.test(key))delete env[key]}return new Promise((resolve2,reject)=>{let settled=false;const child=execFile(command,args,{env,cwd,timeout:timeoutMs,killSignal:"SIGKILL",maxBuffer:64*1024},(err,out,stderr)=>{if(settled)return;settled=true;if(err&&("killed"in err&&err.killed||"signal"in err&&err.signal)){reject(new Error("Smoke test timed out"));return}if(err){const exitCode="code"in err&&typeof err.code==="number"?err.code:1;resolve2({exitCode,stdout:out||"",stderr:stderr||""});return}resolve2({exitCode:0,stdout:out||"",stderr:stderr||""})});child.on("error",()=>{if(settled)return;settled=true;reject(new Error("Smoke test failed: unable to start new binary"))})})}__name(spawnAndCapture,"spawnAndCapture");async function smokeTest(newInstallDir,target,runtime,expectedVersion){const resolvedInstallDir=path.resolve(newInstallDir);const interpreter=target.startsWith("win")?path.join(resolvedInstallDir,runtime,`${runtime}.exe`):path.join(resolvedInstallDir,runtime,"bin",runtime);const cliBin=path.join(resolvedInstallDir,"lib","cli.js");if(!fs.existsSync(interpreter)){throw new Error(`Smoke test failed: ${runtime} binary not found at ${interpreter}`)}if(!fs.existsSync(cliBin)){throw new Error(`Smoke test failed: CLI entry not found at ${cliBin}`)}const cwd=fs.mkdtempSync(path.join(os.tmpdir(),"qwen-code-smoke-"));try{const identity=await spawnAndCapture(interpreter,["-e",'console.log(JSON.stringify({runtime:process.versions.bun?"bun":"node",platform:process.platform,arch:process.arch}))'],1e4,cwd);let actual;try{actual=JSON.parse(identity.stdout)}catch{throw new Error("Smoke test failed: invalid interpreter identity")}const[platform2,arch2]=target.split("-");if(identity.exitCode!==0||!actual||typeof actual!=="object"||Array.isArray(actual)||Reflect.get(actual,"runtime")!==runtime||Reflect.get(actual,"platform")!==(platform2==="win"?"win32":platform2)||Reflect.get(actual,"arch")!==arch2){throw new Error("Smoke test failed: interpreter identity does not match the expected runtime and target")}const{exitCode,stdout}=await spawnAndCapture(interpreter,[cliBin,"--version"],1e4,cwd);if(exitCode!==0){throw new Error(`Smoke test failed: new binary exited with code ${exitCode}`)}const version=stdout.trim();if(!SEMVER_RE.test(version)){throw new Error("Smoke test failed: unexpected version output")}let versionMatches;try{versionMatches=import_semver.default.eq(version,expectedVersion)}catch{versionMatches=false}if(!versionMatches){throw new Error("Smoke test failed: CLI version does not match the expected version")}const launcher=await spawnAndCapture(interpreter,[path.join(resolvedInstallDir,"lib","cli-entry.js"),"--help"],1e4,cwd);if(launcher.exitCode!==0){throw new Error("Smoke test failed: launcher could not load CLI")}debugLogger.info(`Smoke test passed: ${version}`)}finally{try{fs.rmSync(cwd,{recursive:true,force:true})}catch{debugLogger.warn("Could not remove the smoke test temporary directory")}}}__name(smokeTest,"smokeTest");function pendingSwapError(standaloneDir){return new Error(`A previous update left a pending swap at ${standaloneDir}.new. If no qwen-update.bat process is running, remove the pending swap and .qwen-update.lock, then try again.`)}__name(pendingSwapError,"pendingSwapError");function deferredMarkerError(standaloneDir){return new Error(`A previous update left a deferred-swap marker at ${standaloneDir}.deferred. If no qwen-update.bat process is running, remove the marker, the pending swap at ${standaloneDir}.new, and .qwen-update.lock, then try again.`)}__name(deferredMarkerError,"deferredMarkerError");var PENDING_SWAP_STALE_MS=15*60*1e3;function checkDeferredSwap(standaloneDir){const deferredMarker=`${standaloneDir}.deferred`;let swapProvenDead=false;if(fs.existsSync(deferredMarker)){let marker;try{marker=fs.readFileSync(deferredMarker,"utf-8").trim()}catch{throw deferredMarkerError(standaloneDir)}const batPid=parseInt(marker,10);if(!Number.isSafeInteger(batPid)||batPid<=0||batPid>2147483647){throw deferredMarkerError(standaloneDir)}if(!isProcessProvablyGone(batPid)){let markerStale=false;try{markerStale=Date.now()-fs.statSync(deferredMarker).mtimeMs>PENDING_SWAP_STALE_MS}catch{}if(markerStale){throw new Error(`A previous update left a deferred-swap marker at ${standaloneDir}.deferred. If a qwen-update.bat process is still running, end it first; then remove the marker, the pending swap at ${standaloneDir}.new, and .qwen-update.lock, and try again.`)}throw new Error("A previous update is still being applied. Please wait a moment and try again.")}swapProvenDead=true;try{fs.unlinkSync(deferredMarker)}catch{}}const pendingDir=`${standaloneDir}.new`;if(fs.existsSync(pendingDir)){if(!swapProvenDead){let stale=false;try{stale=Date.now()-fs.statSync(pendingDir).mtimeMs>PENDING_SWAP_STALE_MS}catch{}if(!stale){throw pendingSwapError(standaloneDir)}}try{fs.rmSync(pendingDir,{recursive:true,force:true})}catch(err){const reason=err instanceof Error?err.message:String(err);throw new Error(`A previous update left a pending swap at ${pendingDir} that could not be removed (${reason}). Remove it and .qwen-update.lock, then try again.`)}}}__name(checkDeferredSwap,"checkDeferredSwap");function acquireLock(lockPath,standaloneDir){try{fs.writeFileSync(lockPath,String(process.pid),{flag:"wx"});if(standaloneDir){checkDeferredSwap(standaloneDir)}return true}catch(fastPathErr){if(fastPathErr instanceof Error&&(fastPathErr.message.startsWith("A previous update")||fastPathErr.message.includes("pending swap"))){try{fs.unlinkSync(lockPath)}catch{}throw fastPathErr}let pidStr;try{pidStr=fs.readFileSync(lockPath,"utf-8").trim()}catch{return false}const pid=parseInt(pidStr,10);if(!Number.isNaN(pid)&&isProcessAlive(pid)){return false}if(standaloneDir){checkDeferredSwap(standaloneDir)}try{fs.unlinkSync(lockPath);fs.writeFileSync(lockPath,String(process.pid),{flag:"wx"});return true}catch{return false}}}__name(acquireLock,"acquireLock");function releaseLock(lockPath){try{fs.unlinkSync(lockPath)}catch{}}__name(releaseLock,"releaseLock");function cleanupEmptyStandaloneDir(standaloneDir){const manifestPath=path.join(standaloneDir,"manifest.json");if(fs.existsSync(standaloneDir)&&!fs.existsSync(manifestPath)){fs.rmSync(standaloneDir,{recursive:true,force:true})}}__name(cleanupEmptyStandaloneDir,"cleanupEmptyStandaloneDir");var UNSAFE_SHELL_CHARS=/[\0\n\r]/;var UNSAFE_CMD_CHARS=/[&|<>^%!"`\n\r]/;function assertSafeForSingleQuotedShellPath(p,context){if(UNSAFE_SHELL_CHARS.test(p)){throw new Error(`${context} contains characters unsafe for shell embedding: ${p}`)}}__name(assertSafeForSingleQuotedShellPath,"assertSafeForSingleQuotedShellPath");function shellQuoteForSh(p){return`'${p.replace(/'/g,"'\\''")}'`}__name(shellQuoteForSh,"shellQuoteForSh");function shellQuoteForFish(p){return shellQuoteForSh(p)}__name(shellQuoteForFish,"shellQuoteForFish");function isProcessAlive(pid){try{process.kill(pid,0);return true}catch{return false}}__name(isProcessAlive,"isProcessAlive");function isProcessProvablyGone(pid){try{process.kill(pid,0);return false}catch(err){return err.code==="ESRCH"}}__name(isProcessProvablyGone,"isProcessProvablyGone");function atomicReplace(standaloneDir,newDir,lockPath){const oldDir=`${standaloneDir}.old`;const pendingDir=`${standaloneDir}.new`;if(fs.existsSync(oldDir)){fs.rmSync(oldDir,{recursive:true,force:true})}if(os.platform()==="win32"){if(UNSAFE_CMD_CHARS.test(standaloneDir)||UNSAFE_CMD_CHARS.test(oldDir)||UNSAFE_CMD_CHARS.test(pendingDir)){throw new Error("Installation path contains characters unsafe for deferred update script")}if(fs.existsSync(pendingDir)){fs.rmSync(pendingDir,{recursive:true,force:true})}fs.renameSync(newDir,pendingDir);const lockFile=lockPath;const deferredMarker=`${standaloneDir}.deferred`;const logFile=path.join(path.dirname(standaloneDir),"qwen-update.log");const script=["@echo off","set /a TRIES=0",":wait","set /a TRIES+=1","if %TRIES% GTR 30 goto proceed",`tasklist /FI "PID eq ${process.pid}" 2>nul | find "${process.pid}" >nul && (timeout /t 1 >nul & goto wait)`,...process.env["QWEN_CODE_LAUNCHER_PID"]?.match(/^\d+$/)?["set /a LAUNCHER_TRIES=0",":wait_launcher","set /a LAUNCHER_TRIES+=1","if %LAUNCHER_TRIES% GTR 30 goto proceed",`tasklist /FI "PID eq ${process.env["QWEN_CODE_LAUNCHER_PID"]}" 2>nul | find "${process.env["QWEN_CODE_LAUNCHER_PID"]}" >nul && (timeout /t 1 >nul & goto wait_launcher)`]:[],":proceed",`echo [%DATE% %TIME%] starting swap >> "${logFile}"`,`move /Y "${standaloneDir}" "${oldDir}"`,"if errorlevel 1 goto move1_failed",`move /Y "${pendingDir}" "${standaloneDir}"`,"if errorlevel 1 goto move2_failed",`echo [%DATE% %TIME%] swap completed >> "${logFile}"`,"goto cleanup",":move1_failed",`echo [%DATE% %TIME%] ERROR: failed to rename install to .old (errorlevel %errorlevel%) >> "${logFile}"`,"goto cleanup",":move2_failed",`echo [%DATE% %TIME%] ERROR: failed to promote .new; rolling back >> "${logFile}"`,`move /Y "${oldDir}" "${standaloneDir}"`,"if errorlevel 1 (",` echo [%DATE% %TIME%] CRITICAL: rollback also failed; manual recovery: move "${oldDir}" "${standaloneDir}" >> "${logFile}"`,") else (",` echo [%DATE% %TIME%] rollback succeeded >> "${logFile}"`,")",":cleanup",`del /F /Q "${deferredMarker}" 2>nul`,`del /F /Q "${lockFile}" 2>nul`,`del "%~f0"`].join("\r\n");const scriptPath=path.join(path.dirname(standaloneDir),"qwen-update.bat");fs.writeFileSync(scriptPath,script);const child=spawn("cmd.exe",["/c",scriptPath],{detached:true,stdio:"ignore",windowsHide:true});child.on("error",err=>{debugLogger.warn("Deferred bat script failed to spawn:",err)});child.unref();if(!child.pid){throw new Error("Failed to spawn deferred update script. Update was not applied.")}fs.writeFileSync(deferredMarker,String(child.pid));return"deferred"}else{fs.renameSync(standaloneDir,oldDir);try{fs.renameSync(newDir,standaloneDir)}catch(promoteErr){try{fs.renameSync(oldDir,standaloneDir)}catch(rollbackErr){const detail=`Standalone update failed AND rollback failed.
|
|
3
|
+
import{loadUndici}from"./chunk-XKSB7VTV.js";import{updateEventEmitter}from"./chunk-VDUNIK4I.js";import{require_semver}from"./chunk-YZUKMJW7.js";import{hasStandaloneArchiveLayout,standaloneRuntimePaths}from"./chunk-26MNTKT2.js";import{t}from"./chunk-NO7VTKRL.js";import{So}from"./chunk-2JGTWRZJ.js";import{createDebugLogger}from"./chunk-JAUJI56S.js";import{init_esbuild_shims}from"./chunk-VKDAXTCZ.js";import{__name,__toESM}from"./chunk-KBWJGX7I.js";init_esbuild_shims();import{createHash}from"node:crypto";import*as fs from"node:fs";import*as os from"node:os";import*as path from"node:path";import{Readable,Transform}from"node:stream";import{spawn,execFile}from"node:child_process";import{pipeline}from"node:stream/promises";var import_semver=__toESM(require_semver(),1);init_esbuild_shims();import{createPublicKey,verify}from"node:crypto";var RELEASE_PUBLIC_KEY_DER_B64="MCowBQYDK2VwAyEAr9WRFLDauibZQKCe1oKfuFZn6zRMaEkD5+KVqN6mKM4=";function verifySignature(sha256sumsContent,signatureBase64){const key=createPublicKey({key:Buffer.from(RELEASE_PUBLIC_KEY_DER_B64,"base64"),format:"der",type:"spki"});const signature=Buffer.from(signatureBase64,"base64");if(signature.length!==64){throw new Error(`Invalid signature length: expected 64 bytes, got ${signature.length}`)}const valid=verify(null,Buffer.from(sha256sumsContent),key,signature);if(!valid){throw new Error("SHA256SUMS signature verification failed \u2014 possible tampering detected")}}__name(verifySignature,"verifySignature");var debugLogger=createDebugLogger("STANDALONE_UPDATE");var OSS_BASE="https://qwen-code-assets.oss-cn-hangzhou.aliyuncs.com/releases/qwen-code";var GITHUB_BASE="https://github.com/QwenLM/qwen-code/releases/download";var FETCH_TIMEOUT_MS=3e4;var ARCHIVE_TIMEOUT_MS=3e5;var VALID_TARGETS=new Set(["darwin-arm64","darwin-x64","linux-arm64","linux-x64","win-x64"]);var SEMVER_RE=/^v?\d+\.\d+\.\d+(-[\w.]+)?$/;function isConcreteVersion(version){return SEMVER_RE.test(version)&&import_semver.default.valid(version)!==null}__name(isConcreteVersion,"isConcreteVersion");function normalizeVersion(version){if(!isConcreteVersion(version)){throw new Error(`Invalid version format: ${version}`)}return version.startsWith("v")?version:`v${version}`}__name(normalizeVersion,"normalizeVersion");function validateTarget(target){if(!VALID_TARGETS.has(target)){throw new Error(`Unknown target: ${target}`)}}__name(validateTarget,"validateTarget");function archiveFilename(target,runtime){const ext=target.startsWith("win")?"zip":"tar.gz";const suffix=runtime==="bun"?"-opentui-preview":"";return`qwen-code-${target}${suffix}.${ext}`}__name(archiveFilename,"archiveFilename");function escapePS(s){return s.replace(/'/g,"''")}__name(escapePS,"escapePS");function resolveUpdateBaseUrl(){const value=process.env["QWEN_UPDATE_BASE_URL"]?.trim();if(!value)return void 0;const invalidUrl=__name(()=>new Error("QWEN_UPDATE_BASE_URL must be an absolute HTTPS URL without credentials, query parameters, or a fragment."),"invalidUrl");let url;try{url=new URL(value)}catch{throw invalidUrl()}if(!/^https:\/\//i.test(value)||url.username||url.password||/[?#\s]/.test(value)){throw invalidUrl()}return url.href.replace(/\/+$/,"")}__name(resolveUpdateBaseUrl,"resolveUpdateBaseUrl");async function tryFetch(url,timeoutMs=FETCH_TIMEOUT_MS){try{const{fetch}=await loadUndici();const res=await fetch(url,{signal:AbortSignal.timeout(timeoutMs)});if(res.ok)return{response:res};await res.body?.cancel().catch(()=>{});return{error:new Error(`HTTP ${res.status} ${res.statusText}`)}}catch(err){const error=err instanceof Error?err:new Error(String(err));debugLogger.debug(`Fetch failed for ${url}: ${error.message}`);return{error}}}__name(tryFetch,"tryFetch");async function downloadWithFallback(versionPath,filename,timeoutMs=FETCH_TIMEOUT_MS,baseUrl){if(baseUrl){const result=await tryFetch(`${baseUrl}/${versionPath}/${filename}`,timeoutMs);if(result.response)return result.response;throw new Error(`Failed to download ${filename} from QWEN_UPDATE_BASE_URL: ${result.error.message}`)}const ossUrl=`${OSS_BASE}/${versionPath}/${filename}`;const ossResult=await tryFetch(ossUrl,timeoutMs);if(ossResult.response)return ossResult.response;const ghUrl=`${GITHUB_BASE}/${versionPath}/${filename}`;const ghResult=await tryFetch(ghUrl,timeoutMs);if(ghResult.response)return ghResult.response;throw new Error(`Failed to download ${filename}: OSS (${ossResult.error?.message??"unknown"}), GitHub (${ghResult.error?.message??"unknown"})`)}__name(downloadWithFallback,"downloadWithFallback");async function verifyChecksum(actualHash,filename,versionPath,baseUrl){const response=await downloadWithFallback(versionPath,"SHA256SUMS",FETCH_TIMEOUT_MS,baseUrl);const text=await response.text();const requireSig=process.env["QWEN_REQUIRE_SIGNATURE"]==="1";let sigResponse;try{sigResponse=await downloadWithFallback(versionPath,"SHA256SUMS.sig",FETCH_TIMEOUT_MS,baseUrl)}catch(err){debugLogger.debug("SHA256SUMS.sig not available:",err)}if(sigResponse){const sigContent=await sigResponse.text();verifySignature(text,sigContent.trim());debugLogger.info("SHA256SUMS signature verified.")}else if(requireSig){throw new Error("SHA256SUMS.sig not found and QWEN_REQUIRE_SIGNATURE=1 is set")}else{debugLogger.warn("SHA256SUMS.sig not available \u2014 update integrity relies on SHA256 checksum only. Set QWEN_REQUIRE_SIGNATURE=1 to enforce signature verification.")}const expectedLine=text.split("\n").find(line=>{const parts=line.trim().split(/\s+/);if(parts.length<2)return false;const name=parts[parts.length-1].replace(/^\*/,"");return name===filename});if(!expectedLine){throw new Error(`No checksum found for ${filename} in SHA256SUMS`)}const expectedHash=expectedLine.trim().split(/\s+/)[0];if(actualHash!==expectedHash){throw new Error(`Checksum mismatch: expected ${expectedHash}, got ${actualHash}`)}}__name(verifyChecksum,"verifyChecksum");var MAX_DOWNLOAD_BYTES=512*1024*1024;async function downloadToFile(versionPath,filename,destPath,baseUrl){const response=await downloadWithFallback(versionPath,filename,ARCHIVE_TIMEOUT_MS,baseUrl);const body=response.body;if(!body)throw new Error("Empty response body");const contentLength=response.headers.get("content-length");if(contentLength&&parseInt(contentLength,10)>MAX_DOWNLOAD_BYTES){await body.cancel().catch(()=>{});throw new Error(`Download too large: ${contentLength} bytes exceeds ${MAX_DOWNLOAD_BYTES} limit`)}const hash=createHash("sha256");let bytesWritten=0;const dest=fs.createWriteStream(destPath);const sizeGuard=new Transform({transform(chunk,_encoding,callback){bytesWritten+=chunk.length;if(bytesWritten>MAX_DOWNLOAD_BYTES){callback(new Error(`Download exceeded ${MAX_DOWNLOAD_BYTES} byte limit`))}else{hash.update(chunk);callback(null,chunk)}}});await pipeline(Readable.fromWeb(body),sizeGuard,dest);return hash.digest("hex")}__name(downloadToFile,"downloadToFile");function isPathInside(base,candidate){const rel=path.relative(base,candidate);return rel===""||!!rel&&rel!==".."&&!rel.startsWith(`..${path.sep}`)&&!path.isAbsolute(rel)}__name(isPathInside,"isPathInside");function normalizeTarEntryPath(entryPath){const parts=entryPath.split(/[\\/]+/).filter(part=>part&&part!==".");if(parts.length===0||parts.includes("..")){return null}return parts.join("/")}__name(normalizeTarEntryPath,"normalizeTarEntryPath");function isSafeTarLinkTarget(entryPath,linkPath,resolvedDest){if(path.posix.isAbsolute(linkPath)||path.win32.isAbsolute(linkPath)){return false}const normalizedEntryPath=normalizeTarEntryPath(entryPath);if(!normalizedEntryPath){return false}const archiveRoot=normalizedEntryPath.split("/")[0];const linkTarget=path.resolve(resolvedDest,path.posix.dirname(normalizedEntryPath),linkPath);return isPathInside(path.join(resolvedDest,archiveRoot),linkTarget)}__name(isSafeTarLinkTarget,"isSafeTarLinkTarget");function getTarEntryType(entry){if("type"in entry)return entry.type;if("isFile"in entry&&entry.isFile())return"File";if("isDirectory"in entry&&entry.isDirectory())return"Directory";if("isSymbolicLink"in entry&&entry.isSymbolicLink()){return"SymbolicLink"}return void 0}__name(getTarEntryType,"getTarEntryType");function isSafeTarEntry(entryPath,entry,resolvedDest){if(!isSafeTarEntryPath(entryPath))return false;const entryType=getTarEntryType(entry);const linkPath="linkpath"in entry?entry.linkpath:void 0;if(entryType!=="File"&&entryType!=="Directory"&&entryType!=="SymbolicLink"){return false}if(entryType==="SymbolicLink"){if(linkPath===void 0)return false;return isSafeTarLinkTarget(entryPath,String(linkPath),resolvedDest)}return true}__name(isSafeTarEntry,"isSafeTarEntry");function isAlreadyExistsError(err){return typeof err==="object"&&err!==null&&"code"in err&&err.code==="EEXIST"}__name(isAlreadyExistsError,"isAlreadyExistsError");function validateExtractedPaths(resolvedDest,options={}){const entries=fs.readdirSync(resolvedDest,{recursive:true,withFileTypes:true});for(const entry of entries){if(options.symlinksOnly&&!entry.isSymbolicLink()){continue}const fullPath=path.join(String(entry.parentPath||entry.path),entry.name);let resolved;try{resolved=fs.realpathSync(fullPath)}catch(err){fs.rmSync(resolvedDest,{recursive:true,force:true});const detail=err instanceof Error?err.message:String(err);throw new Error(`Invalid archive entry: ${entry.name} could not be resolved (${detail})`)}if(!isPathInside(resolvedDest,resolved)){fs.rmSync(resolvedDest,{recursive:true,force:true});throw new Error(`Path traversal detected in archive: ${entry.name} resolves to ${resolved}`)}}}__name(validateExtractedPaths,"validateExtractedPaths");function isSafeTarEntryPath(entryPath){if(entryPath.length===0)return false;if(path.posix.isAbsolute(entryPath)||path.win32.isAbsolute(entryPath)){return false}return normalizeTarEntryPath(entryPath)!==null}__name(isSafeTarEntryPath,"isSafeTarEntryPath");async function extractArchive(archivePath,destDir,target){fs.mkdirSync(destDir,{recursive:true});if(target.startsWith("win")){await new Promise((resolve2,reject)=>{const ps=spawn("powershell.exe",["-NoProfile","-Command",`Expand-Archive -Path '${escapePS(archivePath)}' -DestinationPath '${escapePS(destDir)}' -Force`],{stdio:"ignore"});ps.on("close",code=>code===0?resolve2():reject(new Error(`Expand-Archive exited with code ${code}`)));ps.on("error",reject)});const resolvedDest=fs.realpathSync(destDir);validateExtractedPaths(resolvedDest)}else{const resolvedDest=fs.realpathSync(destDir);await So({file:archivePath,cwd:destDir,preservePaths:false,filter:__name((p,entry)=>isSafeTarEntry(p,entry,resolvedDest),"filter")});validateExtractedPaths(fs.realpathSync(destDir),{symlinksOnly:true})}}__name(extractArchive,"extractArchive");function spawnAndCapture(command,args,timeoutMs,cwd){const env={...process.env};for(const key of Object.keys(env)){if(/^(NODE_OPTIONS|BUN_OPTIONS|CLI_VERSION|QWEN_CODE_RELAUNCH_ARGS)$/i.test(key))delete env[key]}return new Promise((resolve2,reject)=>{let settled=false;const child=execFile(command,args,{env,cwd,timeout:timeoutMs,killSignal:"SIGKILL",maxBuffer:64*1024},(err,out,stderr)=>{if(settled)return;settled=true;if(err&&("killed"in err&&err.killed||"signal"in err&&err.signal)){reject(new Error("Smoke test timed out"));return}if(err){const exitCode="code"in err&&typeof err.code==="number"?err.code:1;resolve2({exitCode,stdout:out||"",stderr:stderr||""});return}resolve2({exitCode:0,stdout:out||"",stderr:stderr||""})});child.on("error",()=>{if(settled)return;settled=true;reject(new Error("Smoke test failed: unable to start new binary"))})})}__name(spawnAndCapture,"spawnAndCapture");async function smokeTest(newInstallDir,target,runtime,expectedVersion){const resolvedInstallDir=path.resolve(newInstallDir);const interpreter=target.startsWith("win")?path.join(resolvedInstallDir,runtime,`${runtime}.exe`):path.join(resolvedInstallDir,runtime,"bin",runtime);const cliBin=path.join(resolvedInstallDir,"lib","cli.js");if(!fs.existsSync(interpreter)){throw new Error(`Smoke test failed: ${runtime} binary not found at ${interpreter}`)}if(!fs.existsSync(cliBin)){throw new Error(`Smoke test failed: CLI entry not found at ${cliBin}`)}const cwd=fs.mkdtempSync(path.join(os.tmpdir(),"qwen-code-smoke-"));try{const identity=await spawnAndCapture(interpreter,["-e",'console.log(JSON.stringify({runtime:process.versions.bun?"bun":"node",platform:process.platform,arch:process.arch}))'],1e4,cwd);let actual;try{actual=JSON.parse(identity.stdout)}catch{throw new Error("Smoke test failed: invalid interpreter identity")}const[platform2,arch2]=target.split("-");if(identity.exitCode!==0||!actual||typeof actual!=="object"||Array.isArray(actual)||Reflect.get(actual,"runtime")!==runtime||Reflect.get(actual,"platform")!==(platform2==="win"?"win32":platform2)||Reflect.get(actual,"arch")!==arch2){throw new Error("Smoke test failed: interpreter identity does not match the expected runtime and target")}const{exitCode,stdout}=await spawnAndCapture(interpreter,[cliBin,"--version"],1e4,cwd);if(exitCode!==0){throw new Error(`Smoke test failed: new binary exited with code ${exitCode}`)}const version=stdout.trim();if(!SEMVER_RE.test(version)){throw new Error("Smoke test failed: unexpected version output")}let versionMatches;try{versionMatches=import_semver.default.eq(version,expectedVersion)}catch{versionMatches=false}if(!versionMatches){throw new Error("Smoke test failed: CLI version does not match the expected version")}const launcher=await spawnAndCapture(interpreter,[path.join(resolvedInstallDir,"lib","cli-entry.js"),"--help"],1e4,cwd);if(launcher.exitCode!==0){throw new Error("Smoke test failed: launcher could not load CLI")}debugLogger.info(`Smoke test passed: ${version}`)}finally{try{fs.rmSync(cwd,{recursive:true,force:true})}catch{debugLogger.warn("Could not remove the smoke test temporary directory")}}}__name(smokeTest,"smokeTest");function pendingSwapError(standaloneDir){return new Error(`A previous update left a pending swap at ${standaloneDir}.new. If no qwen-update.bat process is running, remove the pending swap and .qwen-update.lock, then try again.`)}__name(pendingSwapError,"pendingSwapError");function deferredMarkerError(standaloneDir){return new Error(`A previous update left a deferred-swap marker at ${standaloneDir}.deferred. If no qwen-update.bat process is running, remove the marker, the pending swap at ${standaloneDir}.new, and .qwen-update.lock, then try again.`)}__name(deferredMarkerError,"deferredMarkerError");var PENDING_SWAP_STALE_MS=15*60*1e3;function checkDeferredSwap(standaloneDir){const deferredMarker=`${standaloneDir}.deferred`;let swapProvenDead=false;if(fs.existsSync(deferredMarker)){let marker;try{marker=fs.readFileSync(deferredMarker,"utf-8").trim()}catch{throw deferredMarkerError(standaloneDir)}const batPid=parseInt(marker,10);if(!Number.isSafeInteger(batPid)||batPid<=0||batPid>2147483647){throw deferredMarkerError(standaloneDir)}if(!isProcessProvablyGone(batPid)){let markerStale=false;try{markerStale=Date.now()-fs.statSync(deferredMarker).mtimeMs>PENDING_SWAP_STALE_MS}catch{}if(markerStale){throw new Error(`A previous update left a deferred-swap marker at ${standaloneDir}.deferred. If a qwen-update.bat process is still running, end it first; then remove the marker, the pending swap at ${standaloneDir}.new, and .qwen-update.lock, and try again.`)}throw new Error("A previous update is still being applied. Please wait a moment and try again.")}swapProvenDead=true;try{fs.unlinkSync(deferredMarker)}catch{}}const pendingDir=`${standaloneDir}.new`;if(fs.existsSync(pendingDir)){if(!swapProvenDead){let stale=false;try{stale=Date.now()-fs.statSync(pendingDir).mtimeMs>PENDING_SWAP_STALE_MS}catch{}if(!stale){throw pendingSwapError(standaloneDir)}}try{fs.rmSync(pendingDir,{recursive:true,force:true})}catch(err){const reason=err instanceof Error?err.message:String(err);throw new Error(`A previous update left a pending swap at ${pendingDir} that could not be removed (${reason}). Remove it and .qwen-update.lock, then try again.`)}}}__name(checkDeferredSwap,"checkDeferredSwap");function acquireLock(lockPath,standaloneDir){try{fs.writeFileSync(lockPath,String(process.pid),{flag:"wx"});if(standaloneDir){checkDeferredSwap(standaloneDir)}return true}catch(fastPathErr){if(fastPathErr instanceof Error&&(fastPathErr.message.startsWith("A previous update")||fastPathErr.message.includes("pending swap"))){try{fs.unlinkSync(lockPath)}catch{}throw fastPathErr}let pidStr;try{pidStr=fs.readFileSync(lockPath,"utf-8").trim()}catch{return false}const pid=parseInt(pidStr,10);if(!Number.isNaN(pid)&&isProcessAlive(pid)){return false}if(standaloneDir){checkDeferredSwap(standaloneDir)}try{fs.unlinkSync(lockPath);fs.writeFileSync(lockPath,String(process.pid),{flag:"wx"});return true}catch{return false}}}__name(acquireLock,"acquireLock");function releaseLock(lockPath){try{fs.unlinkSync(lockPath)}catch{}}__name(releaseLock,"releaseLock");function cleanupEmptyStandaloneDir(standaloneDir){const manifestPath=path.join(standaloneDir,"manifest.json");if(fs.existsSync(standaloneDir)&&!fs.existsSync(manifestPath)){fs.rmSync(standaloneDir,{recursive:true,force:true})}}__name(cleanupEmptyStandaloneDir,"cleanupEmptyStandaloneDir");var UNSAFE_SHELL_CHARS=/[\0\n\r]/;var UNSAFE_CMD_CHARS=/[&|<>^%!"`\n\r]/;function assertSafeForSingleQuotedShellPath(p,context){if(UNSAFE_SHELL_CHARS.test(p)){throw new Error(`${context} contains characters unsafe for shell embedding: ${p}`)}}__name(assertSafeForSingleQuotedShellPath,"assertSafeForSingleQuotedShellPath");function shellQuoteForSh(p){return`'${p.replace(/'/g,"'\\''")}'`}__name(shellQuoteForSh,"shellQuoteForSh");function shellQuoteForFish(p){return shellQuoteForSh(p)}__name(shellQuoteForFish,"shellQuoteForFish");function isProcessAlive(pid){try{process.kill(pid,0);return true}catch{return false}}__name(isProcessAlive,"isProcessAlive");function isProcessProvablyGone(pid){try{process.kill(pid,0);return false}catch(err){return err.code==="ESRCH"}}__name(isProcessProvablyGone,"isProcessProvablyGone");function atomicReplace(standaloneDir,newDir,lockPath){const oldDir=`${standaloneDir}.old`;const pendingDir=`${standaloneDir}.new`;if(fs.existsSync(oldDir)){fs.rmSync(oldDir,{recursive:true,force:true})}if(os.platform()==="win32"){if(UNSAFE_CMD_CHARS.test(standaloneDir)||UNSAFE_CMD_CHARS.test(oldDir)||UNSAFE_CMD_CHARS.test(pendingDir)){throw new Error("Installation path contains characters unsafe for deferred update script")}if(fs.existsSync(pendingDir)){fs.rmSync(pendingDir,{recursive:true,force:true})}fs.renameSync(newDir,pendingDir);const lockFile=lockPath;const deferredMarker=`${standaloneDir}.deferred`;const logFile=path.join(path.dirname(standaloneDir),"qwen-update.log");const script=["@echo off","set /a TRIES=0",":wait","set /a TRIES+=1","if %TRIES% GTR 30 goto proceed",`tasklist /FI "PID eq ${process.pid}" 2>nul | find "${process.pid}" >nul && (timeout /t 1 >nul & goto wait)`,...process.env["QWEN_CODE_LAUNCHER_PID"]?.match(/^\d+$/)?["set /a LAUNCHER_TRIES=0",":wait_launcher","set /a LAUNCHER_TRIES+=1","if %LAUNCHER_TRIES% GTR 30 goto proceed",`tasklist /FI "PID eq ${process.env["QWEN_CODE_LAUNCHER_PID"]}" 2>nul | find "${process.env["QWEN_CODE_LAUNCHER_PID"]}" >nul && (timeout /t 1 >nul & goto wait_launcher)`]:[],":proceed",`echo [%DATE% %TIME%] starting swap >> "${logFile}"`,`move /Y "${standaloneDir}" "${oldDir}"`,"if errorlevel 1 goto move1_failed",`move /Y "${pendingDir}" "${standaloneDir}"`,"if errorlevel 1 goto move2_failed",`echo [%DATE% %TIME%] swap completed >> "${logFile}"`,"goto cleanup",":move1_failed",`echo [%DATE% %TIME%] ERROR: failed to rename install to .old (errorlevel %errorlevel%) >> "${logFile}"`,"goto cleanup",":move2_failed",`echo [%DATE% %TIME%] ERROR: failed to promote .new; rolling back >> "${logFile}"`,`move /Y "${oldDir}" "${standaloneDir}"`,"if errorlevel 1 (",` echo [%DATE% %TIME%] CRITICAL: rollback also failed; manual recovery: move "${oldDir}" "${standaloneDir}" >> "${logFile}"`,") else (",` echo [%DATE% %TIME%] rollback succeeded >> "${logFile}"`,")",":cleanup",`del /F /Q "${deferredMarker}" 2>nul`,`del /F /Q "${lockFile}" 2>nul`,`del "%~f0"`].join("\r\n");const scriptPath=path.join(path.dirname(standaloneDir),"qwen-update.bat");fs.writeFileSync(scriptPath,script);const child=spawn("cmd.exe",["/c",scriptPath],{detached:true,stdio:"ignore",windowsHide:true});child.on("error",err=>{debugLogger.warn("Deferred bat script failed to spawn:",err)});child.unref();if(!child.pid){throw new Error("Failed to spawn deferred update script. Update was not applied.")}fs.writeFileSync(deferredMarker,String(child.pid));return"deferred"}else{fs.renameSync(standaloneDir,oldDir);try{fs.renameSync(newDir,standaloneDir)}catch(promoteErr){try{fs.renameSync(oldDir,standaloneDir)}catch(rollbackErr){const detail=`Standalone update failed AND rollback failed.
|
|
4
4
|
Original error: ${promoteErr.message}
|
|
5
5
|
Rollback error: ${rollbackErr.message}
|
|
6
6
|
Manual recovery: mv "${oldDir}" "${standaloneDir}"`;throw new Error(detail)}throw promoteErr}return"done"}}__name(atomicReplace,"atomicReplace");function ensureBinWrapper(standaloneDir,target,runtime="node"){const binDir=path.join(path.dirname(standaloneDir),"..","bin");const artifacts={wrapperCreated:false};const{launcher,interpreter,entryPoint}=standaloneRuntimePaths(standaloneDir,target,runtime);const hasLauncher=fs.existsSync(launcher);try{fs.mkdirSync(binDir,{recursive:true});if(target.startsWith("win")){if(UNSAFE_CMD_CHARS.test(standaloneDir)){throw new Error("standaloneDir contains characters unsafe for cmd.exe wrapper")}const wrapperPath=path.join(binDir,"qwen.cmd");artifacts.wrapperPath=wrapperPath;const content=hasLauncher?`@echo off\r
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// Force strict mode and setup for ESM
|
|
2
2
|
"use strict";
|
|
3
|
-
import{loadProjectMcpServers}from"./chunk-KN27BFXM.js";import{loadSettings}from"./chunk-WI4UMN3Q.js";import{getCurrentLanguage}from"./chunk-ABJGFEES.js";import{require_strip_json_comments}from"./chunk-DOLUT3XC.js";import{isWorkspaceTrusted}from"./chunk-BBOJUFMW.js";import{hashMcpServerConfig}from"./chunk-5WLKN3GD.js";import{Config,ExtensionManager,FileDiscoveryService,MCPOAuthTokenStorage,createMcpClient,createTransport,isGatedMcpScope,runWithTimeout}from"./chunk-Z5XENA4A.js";import{parseBooleanEnvFlag}from"./chunk-HW6AWS7W.js";import{getMCPServerLastError,getMCPServerStatus}from"./chunk-ZWPSBU7K.js";import{atomicWriteFile}from"./chunk-BMHYEQTI.js";import{writeStderrLine,writeStdoutLine}from"./chunk-M4ECEHLX.js";import{Storage}from"./chunk-EPODBRBP.js";import{getErrorMessage}from"./chunk-XYB7GC5U.js";import{init_esbuild_shims}from"./chunk-VKDAXTCZ.js";import{__name,__toESM}from"./chunk-KBWJGX7I.js";init_esbuild_shims();init_esbuild_shims();function splitCommaList(values){if(values===void 0)return void 0;const strings=values.filter(value=>typeof value==="string");if(strings.length===0)return values.length?void 0:[];return strings.flatMap(value=>value.split(",")).map(value=>value.trim()).filter(Boolean)}__name(splitCommaList,"splitCommaList");async function addMcpServer(name,commandOrUrl,args,options){const{scope,transport,env,header,timeout,trust,description,includeTools,excludeTools,oauthClientId,oauthClientSecret,oauthRedirectUri,oauthAuthorizationUrl,oauthTokenUrl,oauthScopes}=options;const settings=loadSettings(process.cwd());const inHome=settings.workspace.path===settings.user.path;if(scope==="project"&&inHome){writeStderrLine("Error: Please use --scope user to edit settings in the home directory.");process.exit(1)}const settingsScope=scope==="user"?"User":"Workspace";let newServer={};const scopes=splitCommaList(oauthScopes);const hasOAuth=Boolean(oauthClientId||oauthClientSecret||oauthRedirectUri||oauthAuthorizationUrl||oauthTokenUrl||scopes&&scopes.length>0);if(hasOAuth&&transport==="stdio"){writeStderrLine("Error: OAuth options (--oauth-*) are only supported with --transport sse or --transport http.");process.exit(1)}const oauthConfig=hasOAuth?{enabled:true,...oauthClientId&&{clientId:oauthClientId},...oauthClientSecret&&{clientSecret:oauthClientSecret},...oauthRedirectUri&&{redirectUri:oauthRedirectUri},...oauthAuthorizationUrl&&{authorizationUrl:oauthAuthorizationUrl},...oauthTokenUrl&&{tokenUrl:oauthTokenUrl},...scopes&&scopes.length>0&&{scopes}}:void 0;const headers=header?.reduce((acc,curr)=>{const[key,...valueParts]=curr.split(":");const value=valueParts.join(":").trim();if(key.trim()&&value){acc[key.trim()]=value}return acc},{});switch(transport){case"sse":newServer={url:commandOrUrl,headers,timeout,trust,description,includeTools,excludeTools,oauth:oauthConfig};break;case"http":newServer={httpUrl:commandOrUrl,headers,timeout,trust,description,includeTools,excludeTools,oauth:oauthConfig};break;case"stdio":default:newServer={command:commandOrUrl,args:args?.map(String),env:env?.reduce((acc,curr)=>{const separator=curr.indexOf("=");if(separator===-1){return acc}const key=curr.slice(0,separator);const value=curr.slice(separator+1);if(key&&value){acc[key]=value}return acc},{}),timeout,trust,description,includeTools,excludeTools};break}const existingSettings=settings.forScope(settingsScope).settings;const mcpServers=existingSettings.mcpServers||{};const isExistingServer=!!mcpServers[name];if(isExistingServer){writeStdoutLine(`MCP server "${name}" is already configured within ${scope} settings.`)}mcpServers[name]=newServer;settings.setValue(settingsScope,"mcpServers",mcpServers);if(isExistingServer){writeStdoutLine(`MCP server "${name}" updated in ${scope} settings.`)}else{writeStdoutLine(`MCP server "${name}" added to ${scope} settings. (${transport})`)}}__name(addMcpServer,"addMcpServer");var addCommand={command:"add <name> <commandOrUrl> [args...]",describe:"Add a server",builder:__name(yargs=>yargs.usage("Usage: gerege mcp add [options] <name> <commandOrUrl> [args...]").parserConfiguration({"unknown-options-as-args":true,"populate--":true}).positional("name",{describe:"Name of the server",type:"string",demandOption:true}).positional("commandOrUrl",{describe:"Command (stdio) or URL (sse, http)",type:"string",demandOption:true}).option("scope",{alias:"s",describe:"Configuration scope (user or project)",type:"string",default:"user",choices:["user","project"]}).option("transport",{alias:"t",describe:"Transport type (stdio, sse, http). Auto-detected from URL if not specified.",type:"string",choices:["stdio","sse","http"]}).option("env",{alias:"e",describe:"Set environment variables (e.g. -e KEY=value)",type:"array",string:true,nargs:1}).option("header",{alias:"H",describe:'Set HTTP headers for SSE and HTTP transports (e.g. -H "X-Api-Key: abc123" -H "Authorization: Bearer abc123")',type:"array",string:true,nargs:1}).option("timeout",{describe:"Set connection timeout in milliseconds",type:"number"}).option("trust",{describe:"Trust the server (bypass its tool call confirmations in a trusted workspace)",type:"boolean"}).option("description",{describe:"Set the description for the server",type:"string"}).option("include-tools",{describe:"A comma-separated list of tools to include",type:"array",string:true}).option("exclude-tools",{describe:"A comma-separated list of tools to exclude",type:"array",string:true}).option("oauth-client-id",{describe:"OAuth client ID for MCP server authentication",type:"string"}).option("oauth-client-secret",{describe:"OAuth client secret for MCP server authentication",type:"string"}).option("oauth-redirect-uri",{describe:"OAuth redirect URI (e.g., https://your-server.com/oauth/callback). Defaults to localhost for local setups.",type:"string"}).option("oauth-authorization-url",{describe:"OAuth authorization URL",type:"string"}).option("oauth-token-url",{describe:"OAuth token URL",type:"string"}).option("oauth-scopes",{describe:"OAuth scopes (comma-separated)",type:"array",string:true}).middleware(argv=>{if(argv["--"]){const existingArgs=argv["args"]||[];argv["args"]=[...existingArgs,...argv["--"]]}if(!argv["transport"]){const commandOrUrl=argv["commandOrUrl"];if(commandOrUrl&&/^https?:\/\//i.test(commandOrUrl)){argv["transport"]="http"}else{argv["transport"]="stdio"}}}),"builder"),handler:__name(async argv=>{await addMcpServer(argv["name"],argv["commandOrUrl"],argv["args"],{scope:argv["scope"],transport:argv["transport"],env:argv["env"],header:argv["header"],timeout:argv["timeout"],trust:argv["trust"],description:argv["description"],includeTools:splitCommaList(argv["includeTools"]),excludeTools:splitCommaList(argv["excludeTools"]),oauthClientId:argv["oauthClientId"],oauthClientSecret:argv["oauthClientSecret"],oauthRedirectUri:argv["oauthRedirectUri"],oauthAuthorizationUrl:argv["oauthAuthorizationUrl"],oauthTokenUrl:argv["oauthTokenUrl"],oauthScopes:argv["oauthScopes"]})},"handler")};init_esbuild_shims();async function removeMcpServer(name,options){const{scope}=options;const settingsScope=scope==="user"?"User":"Workspace";const settings=loadSettings();const existingSettings=settings.forScope(settingsScope).settings;const mcpServers=existingSettings.mcpServers||{};if(!mcpServers[name]){writeStdoutLine(`Server "${name}" not found in ${scope} settings.`);return}delete mcpServers[name];settings.setValue(settingsScope,"mcpServers",mcpServers);try{const tokenStorage=new MCPOAuthTokenStorage;await tokenStorage.deleteCredentials(name)}catch{}writeStdoutLine(`Server "${name}" removed from ${scope} settings.`)}__name(removeMcpServer,"removeMcpServer");var removeCommand={command:"remove <name>",describe:"Remove a server",builder:__name(yargs=>yargs.usage("Usage: gerege mcp remove [options] <name>").positional("name",{describe:"Name of the server",type:"string",demandOption:true}).option("scope",{alias:"s",describe:"Configuration scope (user or project)",type:"string",default:"user",choices:["user","project"]}),"builder"),handler:__name(async argv=>{await removeMcpServer(argv["name"],{scope:argv["scope"]})},"handler")};init_esbuild_shims();init_esbuild_shims();function assembleMcpServers(mergedSettingsServers,cwd,cliMcpServers){const belowProject={};const aboveProject={};for(const[name,config]of Object.entries(mergedSettingsServers??{})){if(config.scope==="workspace"||config.scope==="system"){aboveProject[name]=config}else{belowProject[name]=config}}const projectResult=loadProjectMcpServers(cwd);for(const error of projectResult.errors){writeStderrLine(`Warning: ${error}`)}return{...belowProject,...projectResult.servers,...aboveProject,...cliMcpServers??{}}}__name(assembleMcpServers,"assembleMcpServers");init_esbuild_shims();import*as fs from"node:fs";import*as os from"node:os";import*as path from"node:path";var import_strip_json_comments=__toESM(require_strip_json_comments(),1);var MCP_APPROVALS_FILENAME="mcpApprovals.json";function getMcpApprovalsPath(){if(process.env["QWEN_CODE_MCP_APPROVALS_PATH"]){return process.env["QWEN_CODE_MCP_APPROVALS_PATH"]}return path.join(Storage.getGlobalQwenDir(),MCP_APPROVALS_FILENAME)}__name(getMcpApprovalsPath,"getMcpApprovalsPath");function normalizeProjectRoot(projectRoot){const resolved=path.resolve(projectRoot);return os.platform()==="win32"?resolved.toLowerCase():resolved}__name(normalizeProjectRoot,"normalizeProjectRoot");function isApprovalRecordMap(value){return typeof value==="object"&&value!==null&&!Array.isArray(value)}__name(isApprovalRecordMap,"isApprovalRecordMap");function isWin32AbsolutePath(p){return/^[A-Za-z]:[\\/]/.test(p)||/^\\\\/.test(p)}__name(isWin32AbsolutePath,"isWin32AbsolutePath");function mergeApprovalRecords(existing,incoming){const merged=Object.assign(Object.create(null),existing);for(const[name,record]of Object.entries(incoming)){if(!isApprovalRecordMap(record)){continue}const current=merged[name];if(!current){merged[name]=record}else if(current.status!==record.status){merged[name]=current.status==="rejected"?current:record}}return merged}__name(mergeApprovalRecords,"mergeApprovalRecords");function normalizeStoredProjectKeys(config){if(os.platform()!=="win32"){return config}const normalized=Object.create(null);for(const[key,value]of Object.entries(config)){const projectKey=isWin32AbsolutePath(key)?key.toLowerCase():key;const existing=normalized[projectKey];normalized[projectKey]=isApprovalRecordMap(existing)&&isApprovalRecordMap(value)?mergeApprovalRecords(existing,value):isApprovalRecordMap(value)||!isApprovalRecordMap(existing)?value:existing}return normalized}__name(normalizeStoredProjectKeys,"normalizeStoredProjectKeys");var LoadedMcpApprovals=class{constructor(file,errors){this.file=file;this.errors=errors}static{__name(this,"LoadedMcpApprovals")}getState(projectRoot,serverName,config){const record=this.file.config[normalizeProjectRoot(projectRoot)]?.[serverName];if(!record){return"pending"}if(record.hash!==hashMcpServerConfig(config)){return"pending"}return record.status}async setState(projectRoot,serverName,config,status){const root=normalizeProjectRoot(projectRoot);const existing=this.file.config[root];const project=isApprovalRecordMap(existing)?existing:Object.create(null);Object.defineProperty(project,serverName,{value:{hash:hashMcpServerConfig(config),status},enumerable:true,configurable:true,writable:true});this.file.config[root]=project;await saveMcpApprovals(this.file)}};var loadedMcpApprovals;function loadMcpApprovals(){if(loadedMcpApprovals){return loadedMcpApprovals}const errors=[];let config={};const filePath=getMcpApprovalsPath();try{if(fs.existsSync(filePath)){const content=fs.readFileSync(filePath,"utf-8");const parsed=JSON.parse((0,import_strip_json_comments.default)(content));if(typeof parsed!=="object"||parsed===null||Array.isArray(parsed)){errors.push({message:"MCP approvals file is not a valid JSON object.",path:filePath})}else{config=normalizeStoredProjectKeys(parsed)}}}catch(error){errors.push({message:getErrorMessage(error),path:filePath})}loadedMcpApprovals=new LoadedMcpApprovals({path:filePath,config},errors);for(const error of errors){writeStderrLine(`Warning: MCP approvals file error: ${error.message}`)}return loadedMcpApprovals}__name(loadMcpApprovals,"loadMcpApprovals");function getPendingGatedMcpServers(mcpServers,projectRoot){const approvals=loadMcpApprovals();const pending=[];for(const[name,config]of Object.entries(mcpServers)){if(!isGatedMcpScope(config.scope)){continue}if(approvals.getState(projectRoot,name,config)!=="approved"){pending.push(name)}}return pending}__name(getPendingGatedMcpServers,"getPendingGatedMcpServers");function getPromptableMcpServers(mcpServers,projectRoot){const approvals=loadMcpApprovals();const promptable=[];for(const[name,config]of Object.entries(mcpServers)){if(!isGatedMcpScope(config.scope)){continue}if(approvals.getState(projectRoot,name,config)==="pending"){promptable.push(name)}}return promptable}__name(getPromptableMcpServers,"getPromptableMcpServers");async function saveMcpApprovals(file){try{const dirPath=path.dirname(file.path);if(!fs.existsSync(dirPath)){fs.mkdirSync(dirPath,{recursive:true})}await atomicWriteFile(file.path,JSON.stringify(file.config,null,2),{mode:384})}catch(error){writeStderrLine("Error saving MCP approvals file.");writeStderrLine(error instanceof Error?error.message:String(error))}}__name(saveMcpApprovals,"saveMcpApprovals");var COLOR_GREEN="\x1B[32m";var COLOR_YELLOW="\x1B[33m";var COLOR_RED="\x1B[31m";var RESET_COLOR="\x1B[0m";var MCP_CONNECT_TIMEOUT_MS=1e4;async function getMcpServersFromConfig(){const settings=loadSettings();const extensionManager=new ExtensionManager({isWorkspaceTrusted:isWorkspaceTrusted(settings.merged).isTrusted??true,telemetrySettings:settings.merged.telemetry,locale:getCurrentLanguage()});await extensionManager.refreshCache();const extensions=extensionManager.getLoadedExtensions();const mcpServers=assembleMcpServers(settings.merged.mcpServers,process.cwd());for(const extension of extensions){if(extension.isActive){Object.entries(extension.config.mcpServers||{}).forEach(([key,server])=>{if(mcpServers[key]){return}mcpServers[key]={...server,extensionName:extension.config.name}})}}return mcpServers}__name(getMcpServersFromConfig,"getMcpServersFromConfig");async function testMCPConnection(serverName,config){const client=createMcpClient("mcp-test-client",config);let transport;try{transport=await createTransport(serverName,config,false)}catch(_error){await client.close();return{status:"disconnected",timedOut:false}}try{await runWithTimeout(client.connect(transport,{timeout:MCP_CONNECT_TIMEOUT_MS}),MCP_CONNECT_TIMEOUT_MS,`MCP connection for ${serverName}`);await client.close();return{status:"connected",timedOut:false}}catch(error){await transport.close();return{status:"disconnected",timedOut:error instanceof Error&&error.message.startsWith("Timed out after ")}}}__name(testMCPConnection,"testMCPConnection");async function getServerStatus(serverName,server){return await testMCPConnection(serverName,server)}__name(getServerStatus,"getServerStatus");async function listMcpServers(){const mcpServers=await getMcpServersFromConfig();const serverNames=Object.keys(mcpServers);if(serverNames.length===0){writeStdoutLine("No MCP servers configured.");return}writeStdoutLine("Configured MCP servers:\n");const cwd=process.cwd();let approvals;for(const serverName of serverNames){const server=mcpServers[serverName];let serverInfo=`${serverName}: `;if(server.httpUrl){serverInfo+=`${server.httpUrl} (http)`}else if(server.url){serverInfo+=`${server.url} (sse)`}else if(server.command){serverInfo+=`${server.command} ${server.args?.join(" ")||""} (stdio)`}if(isGatedMcpScope(server.scope)){approvals??=loadMcpApprovals();const state=approvals.getState(cwd,serverName,server);if(state!=="approved"){const statusText2=state==="rejected"?"Rejected":"Pending approval";writeStdoutLine(`${COLOR_YELLOW}\u25CF${RESET_COLOR} ${serverInfo} - ${statusText2}`);continue}}const{status,timedOut}=await getServerStatus(serverName,server);let statusIndicator="";let statusText="";switch(status){case"connected":statusIndicator=COLOR_GREEN+"\u2713"+RESET_COLOR;statusText="Connected";break;case"connecting":statusIndicator=COLOR_YELLOW+"\u2026"+RESET_COLOR;statusText="Connecting";break;case"disconnected":default:statusIndicator=COLOR_RED+"\u2717"+RESET_COLOR;statusText=timedOut?`Disconnected (timed out after ${MCP_CONNECT_TIMEOUT_MS}ms)`:"Disconnected";break}writeStdoutLine(`${statusIndicator} ${serverInfo} - ${statusText}`)}}__name(listMcpServers,"listMcpServers");var listCommand={command:"list",describe:"List all configured MCP servers",handler:__name(async()=>{await listMcpServers()},"handler")};init_esbuild_shims();async function getMcpServersFromConfig2(extensionManager){const settings=loadSettings();const extManager=extensionManager??new ExtensionManager({isWorkspaceTrusted:isWorkspaceTrusted(settings.merged).isTrusted??true,telemetrySettings:settings.merged.telemetry,locale:getCurrentLanguage()});if(!extensionManager){await extManager.refreshCache()}const extensions=extManager.getLoadedExtensions();const mcpServers=assembleMcpServers(settings.merged.mcpServers,process.cwd());for(const extension of extensions){if(extension.isActive){Object.entries(extension.config.mcpServers||{}).forEach(([key,server])=>{if(mcpServers[key]){return}mcpServers[key]={...server,extensionName:extension.config.name}})}}return mcpServers}__name(getMcpServersFromConfig2,"getMcpServersFromConfig");async function createMinimalConfig(){const settings=loadSettings();const cwd=process.cwd();const fileFiltering=settings.merged.context?.fileFiltering;const fileService=new FileDiscoveryService(cwd,fileFiltering?.customIgnoreFiles);const mcpServers=await getMcpServersFromConfig2();const allowedMcpServers=settings.merged.mcp?.allowed?new Set(settings.merged.mcp.allowed.filter(Boolean)):void 0;const excludedMcpServers=settings.merged.mcp?.excluded?new Set(settings.merged.mcp.excluded.filter(Boolean)):void 0;const config=new Config({sessionId:"mcp-reconnect",targetDir:cwd,cwd,debugMode:false,chatRecording:false,mcpServers,pendingMcpServers:getPendingGatedMcpServers(mcpServers,cwd),fileDiscoveryService:fileService,mcpServerCommand:settings.merged.mcp?.serverCommand,allowedMcpServers:allowedMcpServers?Array.from(allowedMcpServers):void 0,excludedMcpServers:excludedMcpServers?Array.from(excludedMcpServers):void 0,trustedFolder:isWorkspaceTrusted(settings.merged).isTrusted??true,usageStatisticsEnabled:parseBooleanEnvFlag(process.env["QWEN_USAGE_STATISTICS_ENABLED"])??settings.merged.privacy?.usageStatisticsEnabled??true,proxy:settings.merged.proxy||process.env["HTTPS_PROXY"]||process.env["https_proxy"]||process.env["HTTP_PROXY"]||process.env["http_proxy"],...fileFiltering!==void 0?{fileFiltering}:{}});await config.initialize({skipMcpDiscovery:true});return config}__name(createMinimalConfig,"createMinimalConfig");var SkippedConnectionError=class extends Error{static{__name(this,"SkippedConnectionError")}skipReason;constructor(skipReason){super(`no connection attempt was made: ${skipReason}`);this.name="SkippedConnectionError";this.skipReason=skipReason}};var SESSION_SCOPE_NOTE="Note: this command reconnects in a separate process; it cannot refresh the MCP tools of an already-running Qwen Code session. Restart that session if its tools remain unavailable.";function createReconnectError(message,exitCode=1){const error=new Error(message);error.exitCode=exitCode;return error}__name(createReconnectError,"createReconnectError");function describeSkippedConnectionReason(config,serverName){const unavailableReason=config.getMcpServerUnavailableReason(serverName);if(unavailableReason==="excluded"){return"server is excluded in settings (mcp.excluded)"}if(unavailableReason==="not_allowed"){return"server is not in the mcp.allowed list"}if(config.isMcpServerDisabled(serverName)){return"server is disabled in settings"}if(config.isMcpServerPendingApproval(serverName)){return"server is pending approval (.mcp.json)"}if(config.isTrustedFolder()===false){return"workspace folder is not trusted"}return void 0}__name(describeSkippedConnectionReason,"describeSkippedConnectionReason");async function discoverAndVerifyConnection(config,serverName){const toolRegistry=config.getToolRegistry();await toolRegistry.discoverToolsForServer(serverName);const status=getMCPServerStatus(serverName);if(status!=="connected"){const skippedReason=describeSkippedConnectionReason(config,serverName);if(skippedReason){throw new SkippedConnectionError(skippedReason)}const lastError=getMCPServerLastError(serverName);throw new Error(`connection attempt finished without a live connection (status: ${status})`+(lastError?`: ${lastError}`:""))}}__name(discoverAndVerifyConnection,"discoverAndVerifyConnection");async function reconnectMcpServer(serverName){const mcpServers=await getMcpServersFromConfig2();if(!mcpServers[serverName]){throw createReconnectError(`Error: Server "${serverName}" not found in configuration.`)}writeStdoutLine(`Reconnecting to server "${serverName}"...`);let config;try{config=await createMinimalConfig();await discoverAndVerifyConnection(config,serverName);writeStdoutLine(`Successfully reconnected to server "${serverName}".`);writeStdoutLine(SESSION_SCOPE_NOTE)}catch(error){const message=error instanceof Error?error.message:String(error);writeStdoutLine(SESSION_SCOPE_NOTE);throw createReconnectError(`Failed to reconnect to server "${serverName}": ${message}`)}finally{if(config){await config.shutdown()}}}__name(reconnectMcpServer,"reconnectMcpServer");async function reconnectAllMcpServers(){const settings=loadSettings();const extensionManager=new ExtensionManager({isWorkspaceTrusted:isWorkspaceTrusted(settings.merged).isTrusted??true,telemetrySettings:settings.merged.telemetry,locale:getCurrentLanguage()});await extensionManager.refreshCache();const mcpServers=await getMcpServersFromConfig2(extensionManager);const serverNames=Object.keys(mcpServers);if(serverNames.length===0){writeStdoutLine("No MCP servers configured.");return}writeStdoutLine("Reconnecting to all MCP servers...\n");let config;let failedCount=0;try{config=await createMinimalConfig();for(const serverName of serverNames){try{await discoverAndVerifyConnection(config,serverName);writeStdoutLine(`\u2713 ${serverName}: Reconnected successfully`)}catch(error){if(error instanceof SkippedConnectionError){writeStdoutLine(`- ${serverName}: Skipped - ${error.skipReason}`);continue}failedCount++;const message=error instanceof Error?error.message:String(error);writeStdoutLine(`\u2717 ${serverName}: Failed - ${message}`)}}writeStdoutLine("");writeStdoutLine(SESSION_SCOPE_NOTE)}finally{if(config){await config.shutdown()}}if(failedCount>0){throw createReconnectError(`Failed to reconnect ${failedCount} of ${serverNames.length} configured server(s).`)}}__name(reconnectAllMcpServers,"reconnectAllMcpServers");var reconnectCommand={command:"reconnect [server-name]",describe:"Reconnect MCP server(s)",builder:__name(yargs=>yargs.usage("Usage: gerege mcp reconnect [options] [server-name]").positional("server-name",{describe:"Name of the server to reconnect",type:"string"}).option("all",{alias:"a",describe:"Reconnect all configured servers",type:"boolean",default:false}).conflicts("server-name","all").check(argv=>{const serverName=argv["server-name"];const all=argv["all"];if(!serverName&&!all){throw new Error("Please specify a server name or use --all to reconnect all servers.")}return true}),"builder"),handler:__name(async argv=>{const serverName=argv["server-name"];const all=argv["all"];try{if(all){await reconnectAllMcpServers()}else if(serverName){await reconnectMcpServer(serverName)}}catch(error){const message=error instanceof Error?error.message:String(error);const exitCode=error?.exitCode??1;writeStderrLine(message);process.exit(exitCode)}},"handler")};init_esbuild_shims();function loadGatedServers(cwd){const settings=loadSettings(cwd);const all=assembleMcpServers(settings.merged.mcpServers,cwd);const gated={};for(const[serverName,config]of Object.entries(all)){if(isGatedMcpScope(config.scope)){gated[serverName]=config}}return gated}__name(loadGatedServers,"loadGatedServers");async function setProjectServerStatus(name,status,all){const cwd=process.cwd();const servers=loadGatedServers(cwd);const names=Object.keys(servers);if(names.length===0){writeStdoutLine("No approval-requiring MCP servers found (looked in .mcp.json and .qwen/settings.json).");return}const verb=status==="approved"?"Approved":"Rejected";const approvals=loadMcpApprovals();const targets=all?names:name?[name]:[];if(targets.length===0){writeStdoutLine("Specify a server name or pass --all.");return}for(const target of targets){const config=servers[target];if(!config){writeStdoutLine(`Server "${target}" not found. Available: ${names.join(", ")}`);continue}await approvals.setState(cwd,target,config,status);writeStdoutLine(`${verb} MCP server "${target}" (bound to its current config).`)}if(status==="approved"){writeStdoutLine("Approved servers connect in your next interactive session.")}}__name(setProjectServerStatus,"setProjectServerStatus");var approveCommand={command:"approve [name]",describe:"Approve a gated MCP server (.mcp.json or workspace .qwen/settings.json)",builder:__name(yargs=>yargs.usage("Usage: gerege mcp approve [options] [name]").positional("name",{describe:"Name of the gated server to approve",type:"string"}).option("all",{describe:"Approve all gated servers in this workspace",type:"boolean",default:false}),"builder"),handler:__name(async argv=>{await setProjectServerStatus(argv["name"],"approved",argv["all"])},"handler")};var rejectCommand={command:"reject [name]",describe:"Reject a gated MCP server (.mcp.json or workspace .qwen/settings.json)",builder:__name(yargs=>yargs.usage("Usage: gerege mcp reject [options] [name]").positional("name",{describe:"Name of the gated server to reject",type:"string"}).option("all",{describe:"Reject all gated servers in this workspace",type:"boolean",default:false}),"builder"),handler:__name(async argv=>{await setProjectServerStatus(argv["name"],"rejected",argv["all"])},"handler")};var mcpCommand={command:"mcp",describe:"Manage MCP servers",builder:__name(yargs=>yargs.command(addCommand).command(removeCommand).command(listCommand).command(reconnectCommand).command(approveCommand).command(rejectCommand).demandCommand(1,"You need at least one command before continuing.").version(false),"builder"),handler:__name(()=>{},"handler")};export{assembleMcpServers,loadMcpApprovals,getPendingGatedMcpServers,getPromptableMcpServers,mcpCommand};
|
|
3
|
+
import{loadProjectMcpServers}from"./chunk-ELDZ4MNL.js";import{loadSettings}from"./chunk-2TAJ5STJ.js";import{getCurrentLanguage}from"./chunk-NO7VTKRL.js";import{require_strip_json_comments}from"./chunk-DOLUT3XC.js";import{isWorkspaceTrusted}from"./chunk-MTDBCIDA.js";import{hashMcpServerConfig}from"./chunk-OU7CEG7Q.js";import{Config,ExtensionManager,FileDiscoveryService,MCPOAuthTokenStorage,createMcpClient,createTransport,isGatedMcpScope,runWithTimeout}from"./chunk-2JGTWRZJ.js";import{parseBooleanEnvFlag}from"./chunk-HW6AWS7W.js";import{getMCPServerLastError,getMCPServerStatus}from"./chunk-ZWPSBU7K.js";import{atomicWriteFile}from"./chunk-BMHYEQTI.js";import{writeStderrLine,writeStdoutLine}from"./chunk-M4ECEHLX.js";import{Storage}from"./chunk-EPODBRBP.js";import{getErrorMessage}from"./chunk-XYB7GC5U.js";import{init_esbuild_shims}from"./chunk-VKDAXTCZ.js";import{__name,__toESM}from"./chunk-KBWJGX7I.js";init_esbuild_shims();init_esbuild_shims();function splitCommaList(values){if(values===void 0)return void 0;const strings=values.filter(value=>typeof value==="string");if(strings.length===0)return values.length?void 0:[];return strings.flatMap(value=>value.split(",")).map(value=>value.trim()).filter(Boolean)}__name(splitCommaList,"splitCommaList");async function addMcpServer(name,commandOrUrl,args,options){const{scope,transport,env,header,timeout,trust,description,includeTools,excludeTools,oauthClientId,oauthClientSecret,oauthRedirectUri,oauthAuthorizationUrl,oauthTokenUrl,oauthScopes}=options;const settings=loadSettings(process.cwd());const inHome=settings.workspace.path===settings.user.path;if(scope==="project"&&inHome){writeStderrLine("Error: Please use --scope user to edit settings in the home directory.");process.exit(1)}const settingsScope=scope==="user"?"User":"Workspace";let newServer={};const scopes=splitCommaList(oauthScopes);const hasOAuth=Boolean(oauthClientId||oauthClientSecret||oauthRedirectUri||oauthAuthorizationUrl||oauthTokenUrl||scopes&&scopes.length>0);if(hasOAuth&&transport==="stdio"){writeStderrLine("Error: OAuth options (--oauth-*) are only supported with --transport sse or --transport http.");process.exit(1)}const oauthConfig=hasOAuth?{enabled:true,...oauthClientId&&{clientId:oauthClientId},...oauthClientSecret&&{clientSecret:oauthClientSecret},...oauthRedirectUri&&{redirectUri:oauthRedirectUri},...oauthAuthorizationUrl&&{authorizationUrl:oauthAuthorizationUrl},...oauthTokenUrl&&{tokenUrl:oauthTokenUrl},...scopes&&scopes.length>0&&{scopes}}:void 0;const headers=header?.reduce((acc,curr)=>{const[key,...valueParts]=curr.split(":");const value=valueParts.join(":").trim();if(key.trim()&&value){acc[key.trim()]=value}return acc},{});switch(transport){case"sse":newServer={url:commandOrUrl,headers,timeout,trust,description,includeTools,excludeTools,oauth:oauthConfig};break;case"http":newServer={httpUrl:commandOrUrl,headers,timeout,trust,description,includeTools,excludeTools,oauth:oauthConfig};break;case"stdio":default:newServer={command:commandOrUrl,args:args?.map(String),env:env?.reduce((acc,curr)=>{const separator=curr.indexOf("=");if(separator===-1){return acc}const key=curr.slice(0,separator);const value=curr.slice(separator+1);if(key&&value){acc[key]=value}return acc},{}),timeout,trust,description,includeTools,excludeTools};break}const existingSettings=settings.forScope(settingsScope).settings;const mcpServers=existingSettings.mcpServers||{};const isExistingServer=!!mcpServers[name];if(isExistingServer){writeStdoutLine(`MCP server "${name}" is already configured within ${scope} settings.`)}mcpServers[name]=newServer;settings.setValue(settingsScope,"mcpServers",mcpServers);if(isExistingServer){writeStdoutLine(`MCP server "${name}" updated in ${scope} settings.`)}else{writeStdoutLine(`MCP server "${name}" added to ${scope} settings. (${transport})`)}}__name(addMcpServer,"addMcpServer");var addCommand={command:"add <name> <commandOrUrl> [args...]",describe:"Add a server",builder:__name(yargs=>yargs.usage("Usage: gerege mcp add [options] <name> <commandOrUrl> [args...]").parserConfiguration({"unknown-options-as-args":true,"populate--":true}).positional("name",{describe:"Name of the server",type:"string",demandOption:true}).positional("commandOrUrl",{describe:"Command (stdio) or URL (sse, http)",type:"string",demandOption:true}).option("scope",{alias:"s",describe:"Configuration scope (user or project)",type:"string",default:"user",choices:["user","project"]}).option("transport",{alias:"t",describe:"Transport type (stdio, sse, http). Auto-detected from URL if not specified.",type:"string",choices:["stdio","sse","http"]}).option("env",{alias:"e",describe:"Set environment variables (e.g. -e KEY=value)",type:"array",string:true,nargs:1}).option("header",{alias:"H",describe:'Set HTTP headers for SSE and HTTP transports (e.g. -H "X-Api-Key: abc123" -H "Authorization: Bearer abc123")',type:"array",string:true,nargs:1}).option("timeout",{describe:"Set connection timeout in milliseconds",type:"number"}).option("trust",{describe:"Trust the server (bypass its tool call confirmations in a trusted workspace)",type:"boolean"}).option("description",{describe:"Set the description for the server",type:"string"}).option("include-tools",{describe:"A comma-separated list of tools to include",type:"array",string:true}).option("exclude-tools",{describe:"A comma-separated list of tools to exclude",type:"array",string:true}).option("oauth-client-id",{describe:"OAuth client ID for MCP server authentication",type:"string"}).option("oauth-client-secret",{describe:"OAuth client secret for MCP server authentication",type:"string"}).option("oauth-redirect-uri",{describe:"OAuth redirect URI (e.g., https://your-server.com/oauth/callback). Defaults to localhost for local setups.",type:"string"}).option("oauth-authorization-url",{describe:"OAuth authorization URL",type:"string"}).option("oauth-token-url",{describe:"OAuth token URL",type:"string"}).option("oauth-scopes",{describe:"OAuth scopes (comma-separated)",type:"array",string:true}).middleware(argv=>{if(argv["--"]){const existingArgs=argv["args"]||[];argv["args"]=[...existingArgs,...argv["--"]]}if(!argv["transport"]){const commandOrUrl=argv["commandOrUrl"];if(commandOrUrl&&/^https?:\/\//i.test(commandOrUrl)){argv["transport"]="http"}else{argv["transport"]="stdio"}}}),"builder"),handler:__name(async argv=>{await addMcpServer(argv["name"],argv["commandOrUrl"],argv["args"],{scope:argv["scope"],transport:argv["transport"],env:argv["env"],header:argv["header"],timeout:argv["timeout"],trust:argv["trust"],description:argv["description"],includeTools:splitCommaList(argv["includeTools"]),excludeTools:splitCommaList(argv["excludeTools"]),oauthClientId:argv["oauthClientId"],oauthClientSecret:argv["oauthClientSecret"],oauthRedirectUri:argv["oauthRedirectUri"],oauthAuthorizationUrl:argv["oauthAuthorizationUrl"],oauthTokenUrl:argv["oauthTokenUrl"],oauthScopes:argv["oauthScopes"]})},"handler")};init_esbuild_shims();async function removeMcpServer(name,options){const{scope}=options;const settingsScope=scope==="user"?"User":"Workspace";const settings=loadSettings();const existingSettings=settings.forScope(settingsScope).settings;const mcpServers=existingSettings.mcpServers||{};if(!mcpServers[name]){writeStdoutLine(`Server "${name}" not found in ${scope} settings.`);return}delete mcpServers[name];settings.setValue(settingsScope,"mcpServers",mcpServers);try{const tokenStorage=new MCPOAuthTokenStorage;await tokenStorage.deleteCredentials(name)}catch{}writeStdoutLine(`Server "${name}" removed from ${scope} settings.`)}__name(removeMcpServer,"removeMcpServer");var removeCommand={command:"remove <name>",describe:"Remove a server",builder:__name(yargs=>yargs.usage("Usage: gerege mcp remove [options] <name>").positional("name",{describe:"Name of the server",type:"string",demandOption:true}).option("scope",{alias:"s",describe:"Configuration scope (user or project)",type:"string",default:"user",choices:["user","project"]}),"builder"),handler:__name(async argv=>{await removeMcpServer(argv["name"],{scope:argv["scope"]})},"handler")};init_esbuild_shims();init_esbuild_shims();function assembleMcpServers(mergedSettingsServers,cwd,cliMcpServers){const belowProject={};const aboveProject={};for(const[name,config]of Object.entries(mergedSettingsServers??{})){if(config.scope==="workspace"||config.scope==="system"){aboveProject[name]=config}else{belowProject[name]=config}}const projectResult=loadProjectMcpServers(cwd);for(const error of projectResult.errors){writeStderrLine(`Warning: ${error}`)}return{...belowProject,...projectResult.servers,...aboveProject,...cliMcpServers??{}}}__name(assembleMcpServers,"assembleMcpServers");init_esbuild_shims();import*as fs from"node:fs";import*as os from"node:os";import*as path from"node:path";var import_strip_json_comments=__toESM(require_strip_json_comments(),1);var MCP_APPROVALS_FILENAME="mcpApprovals.json";function getMcpApprovalsPath(){if(process.env["QWEN_CODE_MCP_APPROVALS_PATH"]){return process.env["QWEN_CODE_MCP_APPROVALS_PATH"]}return path.join(Storage.getGlobalQwenDir(),MCP_APPROVALS_FILENAME)}__name(getMcpApprovalsPath,"getMcpApprovalsPath");function normalizeProjectRoot(projectRoot){const resolved=path.resolve(projectRoot);return os.platform()==="win32"?resolved.toLowerCase():resolved}__name(normalizeProjectRoot,"normalizeProjectRoot");function isApprovalRecordMap(value){return typeof value==="object"&&value!==null&&!Array.isArray(value)}__name(isApprovalRecordMap,"isApprovalRecordMap");function isWin32AbsolutePath(p){return/^[A-Za-z]:[\\/]/.test(p)||/^\\\\/.test(p)}__name(isWin32AbsolutePath,"isWin32AbsolutePath");function mergeApprovalRecords(existing,incoming){const merged=Object.assign(Object.create(null),existing);for(const[name,record]of Object.entries(incoming)){if(!isApprovalRecordMap(record)){continue}const current=merged[name];if(!current){merged[name]=record}else if(current.status!==record.status){merged[name]=current.status==="rejected"?current:record}}return merged}__name(mergeApprovalRecords,"mergeApprovalRecords");function normalizeStoredProjectKeys(config){if(os.platform()!=="win32"){return config}const normalized=Object.create(null);for(const[key,value]of Object.entries(config)){const projectKey=isWin32AbsolutePath(key)?key.toLowerCase():key;const existing=normalized[projectKey];normalized[projectKey]=isApprovalRecordMap(existing)&&isApprovalRecordMap(value)?mergeApprovalRecords(existing,value):isApprovalRecordMap(value)||!isApprovalRecordMap(existing)?value:existing}return normalized}__name(normalizeStoredProjectKeys,"normalizeStoredProjectKeys");var LoadedMcpApprovals=class{constructor(file,errors){this.file=file;this.errors=errors}static{__name(this,"LoadedMcpApprovals")}getState(projectRoot,serverName,config){const record=this.file.config[normalizeProjectRoot(projectRoot)]?.[serverName];if(!record){return"pending"}if(record.hash!==hashMcpServerConfig(config)){return"pending"}return record.status}async setState(projectRoot,serverName,config,status){const root=normalizeProjectRoot(projectRoot);const existing=this.file.config[root];const project=isApprovalRecordMap(existing)?existing:Object.create(null);Object.defineProperty(project,serverName,{value:{hash:hashMcpServerConfig(config),status},enumerable:true,configurable:true,writable:true});this.file.config[root]=project;await saveMcpApprovals(this.file)}};var loadedMcpApprovals;function loadMcpApprovals(){if(loadedMcpApprovals){return loadedMcpApprovals}const errors=[];let config={};const filePath=getMcpApprovalsPath();try{if(fs.existsSync(filePath)){const content=fs.readFileSync(filePath,"utf-8");const parsed=JSON.parse((0,import_strip_json_comments.default)(content));if(typeof parsed!=="object"||parsed===null||Array.isArray(parsed)){errors.push({message:"MCP approvals file is not a valid JSON object.",path:filePath})}else{config=normalizeStoredProjectKeys(parsed)}}}catch(error){errors.push({message:getErrorMessage(error),path:filePath})}loadedMcpApprovals=new LoadedMcpApprovals({path:filePath,config},errors);for(const error of errors){writeStderrLine(`Warning: MCP approvals file error: ${error.message}`)}return loadedMcpApprovals}__name(loadMcpApprovals,"loadMcpApprovals");function getPendingGatedMcpServers(mcpServers,projectRoot){const approvals=loadMcpApprovals();const pending=[];for(const[name,config]of Object.entries(mcpServers)){if(!isGatedMcpScope(config.scope)){continue}if(approvals.getState(projectRoot,name,config)!=="approved"){pending.push(name)}}return pending}__name(getPendingGatedMcpServers,"getPendingGatedMcpServers");function getPromptableMcpServers(mcpServers,projectRoot){const approvals=loadMcpApprovals();const promptable=[];for(const[name,config]of Object.entries(mcpServers)){if(!isGatedMcpScope(config.scope)){continue}if(approvals.getState(projectRoot,name,config)==="pending"){promptable.push(name)}}return promptable}__name(getPromptableMcpServers,"getPromptableMcpServers");async function saveMcpApprovals(file){try{const dirPath=path.dirname(file.path);if(!fs.existsSync(dirPath)){fs.mkdirSync(dirPath,{recursive:true})}await atomicWriteFile(file.path,JSON.stringify(file.config,null,2),{mode:384})}catch(error){writeStderrLine("Error saving MCP approvals file.");writeStderrLine(error instanceof Error?error.message:String(error))}}__name(saveMcpApprovals,"saveMcpApprovals");var COLOR_GREEN="\x1B[32m";var COLOR_YELLOW="\x1B[33m";var COLOR_RED="\x1B[31m";var RESET_COLOR="\x1B[0m";var MCP_CONNECT_TIMEOUT_MS=1e4;async function getMcpServersFromConfig(){const settings=loadSettings();const extensionManager=new ExtensionManager({isWorkspaceTrusted:isWorkspaceTrusted(settings.merged).isTrusted??true,telemetrySettings:settings.merged.telemetry,locale:getCurrentLanguage()});await extensionManager.refreshCache();const extensions=extensionManager.getLoadedExtensions();const mcpServers=assembleMcpServers(settings.merged.mcpServers,process.cwd());for(const extension of extensions){if(extension.isActive){Object.entries(extension.config.mcpServers||{}).forEach(([key,server])=>{if(mcpServers[key]){return}mcpServers[key]={...server,extensionName:extension.config.name}})}}return mcpServers}__name(getMcpServersFromConfig,"getMcpServersFromConfig");async function testMCPConnection(serverName,config){const client=createMcpClient("mcp-test-client",config);let transport;try{transport=await createTransport(serverName,config,false)}catch(_error){await client.close();return{status:"disconnected",timedOut:false}}try{await runWithTimeout(client.connect(transport,{timeout:MCP_CONNECT_TIMEOUT_MS}),MCP_CONNECT_TIMEOUT_MS,`MCP connection for ${serverName}`);await client.close();return{status:"connected",timedOut:false}}catch(error){await transport.close();return{status:"disconnected",timedOut:error instanceof Error&&error.message.startsWith("Timed out after ")}}}__name(testMCPConnection,"testMCPConnection");async function getServerStatus(serverName,server){return await testMCPConnection(serverName,server)}__name(getServerStatus,"getServerStatus");async function listMcpServers(){const mcpServers=await getMcpServersFromConfig();const serverNames=Object.keys(mcpServers);if(serverNames.length===0){writeStdoutLine("No MCP servers configured.");return}writeStdoutLine("Configured MCP servers:\n");const cwd=process.cwd();let approvals;for(const serverName of serverNames){const server=mcpServers[serverName];let serverInfo=`${serverName}: `;if(server.httpUrl){serverInfo+=`${server.httpUrl} (http)`}else if(server.url){serverInfo+=`${server.url} (sse)`}else if(server.command){serverInfo+=`${server.command} ${server.args?.join(" ")||""} (stdio)`}if(isGatedMcpScope(server.scope)){approvals??=loadMcpApprovals();const state=approvals.getState(cwd,serverName,server);if(state!=="approved"){const statusText2=state==="rejected"?"Rejected":"Pending approval";writeStdoutLine(`${COLOR_YELLOW}\u25CF${RESET_COLOR} ${serverInfo} - ${statusText2}`);continue}}const{status,timedOut}=await getServerStatus(serverName,server);let statusIndicator="";let statusText="";switch(status){case"connected":statusIndicator=COLOR_GREEN+"\u2713"+RESET_COLOR;statusText="Connected";break;case"connecting":statusIndicator=COLOR_YELLOW+"\u2026"+RESET_COLOR;statusText="Connecting";break;case"disconnected":default:statusIndicator=COLOR_RED+"\u2717"+RESET_COLOR;statusText=timedOut?`Disconnected (timed out after ${MCP_CONNECT_TIMEOUT_MS}ms)`:"Disconnected";break}writeStdoutLine(`${statusIndicator} ${serverInfo} - ${statusText}`)}}__name(listMcpServers,"listMcpServers");var listCommand={command:"list",describe:"List all configured MCP servers",handler:__name(async()=>{await listMcpServers()},"handler")};init_esbuild_shims();async function getMcpServersFromConfig2(extensionManager){const settings=loadSettings();const extManager=extensionManager??new ExtensionManager({isWorkspaceTrusted:isWorkspaceTrusted(settings.merged).isTrusted??true,telemetrySettings:settings.merged.telemetry,locale:getCurrentLanguage()});if(!extensionManager){await extManager.refreshCache()}const extensions=extManager.getLoadedExtensions();const mcpServers=assembleMcpServers(settings.merged.mcpServers,process.cwd());for(const extension of extensions){if(extension.isActive){Object.entries(extension.config.mcpServers||{}).forEach(([key,server])=>{if(mcpServers[key]){return}mcpServers[key]={...server,extensionName:extension.config.name}})}}return mcpServers}__name(getMcpServersFromConfig2,"getMcpServersFromConfig");async function createMinimalConfig(){const settings=loadSettings();const cwd=process.cwd();const fileFiltering=settings.merged.context?.fileFiltering;const fileService=new FileDiscoveryService(cwd,fileFiltering?.customIgnoreFiles);const mcpServers=await getMcpServersFromConfig2();const allowedMcpServers=settings.merged.mcp?.allowed?new Set(settings.merged.mcp.allowed.filter(Boolean)):void 0;const excludedMcpServers=settings.merged.mcp?.excluded?new Set(settings.merged.mcp.excluded.filter(Boolean)):void 0;const config=new Config({sessionId:"mcp-reconnect",targetDir:cwd,cwd,debugMode:false,chatRecording:false,mcpServers,pendingMcpServers:getPendingGatedMcpServers(mcpServers,cwd),fileDiscoveryService:fileService,mcpServerCommand:settings.merged.mcp?.serverCommand,allowedMcpServers:allowedMcpServers?Array.from(allowedMcpServers):void 0,excludedMcpServers:excludedMcpServers?Array.from(excludedMcpServers):void 0,trustedFolder:isWorkspaceTrusted(settings.merged).isTrusted??true,usageStatisticsEnabled:parseBooleanEnvFlag(process.env["QWEN_USAGE_STATISTICS_ENABLED"])??settings.merged.privacy?.usageStatisticsEnabled??true,proxy:settings.merged.proxy||process.env["HTTPS_PROXY"]||process.env["https_proxy"]||process.env["HTTP_PROXY"]||process.env["http_proxy"],...fileFiltering!==void 0?{fileFiltering}:{}});await config.initialize({skipMcpDiscovery:true});return config}__name(createMinimalConfig,"createMinimalConfig");var SkippedConnectionError=class extends Error{static{__name(this,"SkippedConnectionError")}skipReason;constructor(skipReason){super(`no connection attempt was made: ${skipReason}`);this.name="SkippedConnectionError";this.skipReason=skipReason}};var SESSION_SCOPE_NOTE="Note: this command reconnects in a separate process; it cannot refresh the MCP tools of an already-running Qwen Code session. Restart that session if its tools remain unavailable.";function createReconnectError(message,exitCode=1){const error=new Error(message);error.exitCode=exitCode;return error}__name(createReconnectError,"createReconnectError");function describeSkippedConnectionReason(config,serverName){const unavailableReason=config.getMcpServerUnavailableReason(serverName);if(unavailableReason==="excluded"){return"server is excluded in settings (mcp.excluded)"}if(unavailableReason==="not_allowed"){return"server is not in the mcp.allowed list"}if(config.isMcpServerDisabled(serverName)){return"server is disabled in settings"}if(config.isMcpServerPendingApproval(serverName)){return"server is pending approval (.mcp.json)"}if(config.isTrustedFolder()===false){return"workspace folder is not trusted"}return void 0}__name(describeSkippedConnectionReason,"describeSkippedConnectionReason");async function discoverAndVerifyConnection(config,serverName){const toolRegistry=config.getToolRegistry();await toolRegistry.discoverToolsForServer(serverName);const status=getMCPServerStatus(serverName);if(status!=="connected"){const skippedReason=describeSkippedConnectionReason(config,serverName);if(skippedReason){throw new SkippedConnectionError(skippedReason)}const lastError=getMCPServerLastError(serverName);throw new Error(`connection attempt finished without a live connection (status: ${status})`+(lastError?`: ${lastError}`:""))}}__name(discoverAndVerifyConnection,"discoverAndVerifyConnection");async function reconnectMcpServer(serverName){const mcpServers=await getMcpServersFromConfig2();if(!mcpServers[serverName]){throw createReconnectError(`Error: Server "${serverName}" not found in configuration.`)}writeStdoutLine(`Reconnecting to server "${serverName}"...`);let config;try{config=await createMinimalConfig();await discoverAndVerifyConnection(config,serverName);writeStdoutLine(`Successfully reconnected to server "${serverName}".`);writeStdoutLine(SESSION_SCOPE_NOTE)}catch(error){const message=error instanceof Error?error.message:String(error);writeStdoutLine(SESSION_SCOPE_NOTE);throw createReconnectError(`Failed to reconnect to server "${serverName}": ${message}`)}finally{if(config){await config.shutdown()}}}__name(reconnectMcpServer,"reconnectMcpServer");async function reconnectAllMcpServers(){const settings=loadSettings();const extensionManager=new ExtensionManager({isWorkspaceTrusted:isWorkspaceTrusted(settings.merged).isTrusted??true,telemetrySettings:settings.merged.telemetry,locale:getCurrentLanguage()});await extensionManager.refreshCache();const mcpServers=await getMcpServersFromConfig2(extensionManager);const serverNames=Object.keys(mcpServers);if(serverNames.length===0){writeStdoutLine("No MCP servers configured.");return}writeStdoutLine("Reconnecting to all MCP servers...\n");let config;let failedCount=0;try{config=await createMinimalConfig();for(const serverName of serverNames){try{await discoverAndVerifyConnection(config,serverName);writeStdoutLine(`\u2713 ${serverName}: Reconnected successfully`)}catch(error){if(error instanceof SkippedConnectionError){writeStdoutLine(`- ${serverName}: Skipped - ${error.skipReason}`);continue}failedCount++;const message=error instanceof Error?error.message:String(error);writeStdoutLine(`\u2717 ${serverName}: Failed - ${message}`)}}writeStdoutLine("");writeStdoutLine(SESSION_SCOPE_NOTE)}finally{if(config){await config.shutdown()}}if(failedCount>0){throw createReconnectError(`Failed to reconnect ${failedCount} of ${serverNames.length} configured server(s).`)}}__name(reconnectAllMcpServers,"reconnectAllMcpServers");var reconnectCommand={command:"reconnect [server-name]",describe:"Reconnect MCP server(s)",builder:__name(yargs=>yargs.usage("Usage: gerege mcp reconnect [options] [server-name]").positional("server-name",{describe:"Name of the server to reconnect",type:"string"}).option("all",{alias:"a",describe:"Reconnect all configured servers",type:"boolean",default:false}).conflicts("server-name","all").check(argv=>{const serverName=argv["server-name"];const all=argv["all"];if(!serverName&&!all){throw new Error("Please specify a server name or use --all to reconnect all servers.")}return true}),"builder"),handler:__name(async argv=>{const serverName=argv["server-name"];const all=argv["all"];try{if(all){await reconnectAllMcpServers()}else if(serverName){await reconnectMcpServer(serverName)}}catch(error){const message=error instanceof Error?error.message:String(error);const exitCode=error?.exitCode??1;writeStderrLine(message);process.exit(exitCode)}},"handler")};init_esbuild_shims();function loadGatedServers(cwd){const settings=loadSettings(cwd);const all=assembleMcpServers(settings.merged.mcpServers,cwd);const gated={};for(const[serverName,config]of Object.entries(all)){if(isGatedMcpScope(config.scope)){gated[serverName]=config}}return gated}__name(loadGatedServers,"loadGatedServers");async function setProjectServerStatus(name,status,all){const cwd=process.cwd();const servers=loadGatedServers(cwd);const names=Object.keys(servers);if(names.length===0){writeStdoutLine("No approval-requiring MCP servers found (looked in .mcp.json and .qwen/settings.json).");return}const verb=status==="approved"?"Approved":"Rejected";const approvals=loadMcpApprovals();const targets=all?names:name?[name]:[];if(targets.length===0){writeStdoutLine("Specify a server name or pass --all.");return}for(const target of targets){const config=servers[target];if(!config){writeStdoutLine(`Server "${target}" not found. Available: ${names.join(", ")}`);continue}await approvals.setState(cwd,target,config,status);writeStdoutLine(`${verb} MCP server "${target}" (bound to its current config).`)}if(status==="approved"){writeStdoutLine("Approved servers connect in your next interactive session.")}}__name(setProjectServerStatus,"setProjectServerStatus");var approveCommand={command:"approve [name]",describe:"Approve a gated MCP server (.mcp.json or workspace .qwen/settings.json)",builder:__name(yargs=>yargs.usage("Usage: gerege mcp approve [options] [name]").positional("name",{describe:"Name of the gated server to approve",type:"string"}).option("all",{describe:"Approve all gated servers in this workspace",type:"boolean",default:false}),"builder"),handler:__name(async argv=>{await setProjectServerStatus(argv["name"],"approved",argv["all"])},"handler")};var rejectCommand={command:"reject [name]",describe:"Reject a gated MCP server (.mcp.json or workspace .qwen/settings.json)",builder:__name(yargs=>yargs.usage("Usage: gerege mcp reject [options] [name]").positional("name",{describe:"Name of the gated server to reject",type:"string"}).option("all",{describe:"Reject all gated servers in this workspace",type:"boolean",default:false}),"builder"),handler:__name(async argv=>{await setProjectServerStatus(argv["name"],"rejected",argv["all"])},"handler")};var mcpCommand={command:"mcp",describe:"Manage MCP servers",builder:__name(yargs=>yargs.command(addCommand).command(removeCommand).command(listCommand).command(reconnectCommand).command(approveCommand).command(rejectCommand).demandCommand(1,"You need at least one command before continuing.").version(false),"builder"),handler:__name(()=>{},"handler")};export{assembleMcpServers,loadMcpApprovals,getPendingGatedMcpServers,getPromptableMcpServers,mcpCommand};
|
|
4
4
|
/**
|
|
5
5
|
* @license
|
|
6
6
|
* Copyright 2025 Google LLC
|