@qwen-code/qwen-code 0.23.5-dev.codemode-responses.20260915.f024b37689 → 0.23.5-preview.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bundled/computer-use/SKILL.md +24 -3
- package/bundled/qc-helper/docs/configuration/model-providers.md +43 -0
- package/bundled/qc-helper/docs/configuration/settings.md +10 -9
- package/bundled/qc-helper/docs/extension/agent-plugins.md +1 -0
- package/bundled/qc-helper/docs/extension/introduction.md +49 -0
- package/bundled/qc-helper/docs/features/channels/dingtalk.md +39 -4
- package/bundled/qc-helper/docs/features/channels/overview.md +12 -0
- package/bundled/qc-helper/docs/features/commands.md +57 -52
- package/bundled/qc-helper/docs/features/computer-use.md +1 -1
- package/bundled/qc-helper/docs/features/goals.md +8 -0
- package/bundled/qc-helper/docs/features/hooks.md +16 -0
- package/bundled/qc-helper/docs/qwen-serve.md +3 -1
- package/bundled/workflow-authoring/SKILL.md +48 -22
- package/chunks/{MaxSizedBox-BFMIFJWT.js → MaxSizedBox-FCF6M53W.js} +40 -43
- package/chunks/{StandaloneSessionPicker-4ZH7MOVG.js → StandaloneSessionPicker-V635V72I.js} +60 -63
- package/chunks/{acp-startup-profiler-RUQNTNU5.js → acp-startup-profiler-MOOU37VM.js} +2 -2
- package/chunks/{acp-subagent-executor-AHMVA4P3.js → acp-subagent-executor-TND6W2O5.js} +46 -47
- package/chunks/{acpAgent-UMAJ3XR3.js → acpAgent-3DPWZTNC.js} +954 -322
- package/chunks/{agent-CXB2CCQN.js → agent-KIHGINKN.js} +27 -30
- package/chunks/{agent-headless-7D5ZC736.js → agent-headless-EJ4QOUSM.js} +27 -30
- package/chunks/{anthropicContentGenerator-H5YPXIDE.js → anthropicContentGenerator-4FGOM5LK.js} +46 -64
- package/chunks/{artifact-tool-MFGORTWZ.js → artifact-tool-MUTNH4NI.js} +1 -1
- package/chunks/{askUserQuestion-WS4GUT7C.js → askUserQuestion-AKIRLVB5.js} +1 -1
- package/chunks/bareMode-QWKZPLPX.js +14 -0
- package/chunks/{bridge-A2WKX6IK.js → bridge-MUX5YJZT.js} +46 -49
- package/chunks/{ca-GZ4FDJU2.js → ca-WC3A5B3Q.js} +12 -1
- package/chunks/{channel-management-service-AFVIT4VH.js → channel-management-service-RRILWSXX.js} +4 -4
- package/chunks/{channel-settings-store-AXJIN7HG.js → channel-settings-store-7CBIRZER.js} +51 -54
- package/chunks/{channel-worker-group-JR6JOELM.js → channel-worker-group-3DUJFZJR.js} +8 -8
- package/chunks/{channel-worker-manager-AVKJEZFL.js → channel-worker-manager-E5UW2VLA.js} +8 -8
- package/chunks/{channel-worker-supervisor-OOYY7BAQ.js → channel-worker-supervisor-VN33GSEC.js} +5 -5
- package/chunks/{chunk-2YMRRI2C.js → chunk-2C5TR6HN.js} +82 -9
- package/chunks/{chunk-YDFOHRS5.js → chunk-2GP6BQ2J.js} +1 -1
- package/chunks/{chunk-RN6BU77T.js → chunk-347O2YZJ.js} +158 -290
- package/chunks/{chunk-LTINUI3O.js → chunk-36NRLIR6.js} +10 -8
- package/chunks/{chunk-AXZMWAJV.js → chunk-36SDZ2Q4.js} +8 -0
- package/chunks/{chunk-QR4Q425T.js → chunk-3BZI5GDP.js} +1 -1
- package/chunks/{chunk-C3YMBSLR.js → chunk-3HTUE6ZR.js} +3 -3
- package/chunks/{chunk-QS5Q5F42.js → chunk-3LLEB5CU.js} +2 -2
- package/chunks/{chunk-FPPG5Y3W.js → chunk-3UGMLA4V.js} +10 -8
- package/chunks/{chunk-66N6C4EH.js → chunk-3WILPKTJ.js} +2 -2
- package/chunks/{chunk-SROLVJFY.js → chunk-3WWPEFMX.js} +1 -1
- package/chunks/{chunk-ZKIAGIGH.js → chunk-3XBUCOWS.js} +1 -1
- package/chunks/{chunk-6RQFMGN2.js → chunk-43Y26NPF.js} +3 -3
- package/chunks/{chunk-INGBUYL6.js → chunk-4FLUQWJ4.js} +1 -1
- package/chunks/{chunk-S77FFY67.js → chunk-4JFLRHNE.js} +1 -1
- package/chunks/{chunk-MJHLKWGJ.js → chunk-4QPVZA5J.js} +70 -23
- package/chunks/{chunk-XX5HQLCZ.js → chunk-6OTF7TTE.js} +32 -1
- package/chunks/{chunk-4Y2I3CI3.js → chunk-6USYH3EU.js} +99 -6
- package/chunks/{chunk-Q3TFRP5G.js → chunk-7D4CV7JH.js} +102 -9
- package/chunks/{chunk-EWJTAP3Y.js → chunk-7O5PYQ3M.js} +20 -1
- package/chunks/chunk-ADN5KESB.js +28 -0
- package/chunks/chunk-AKRSSKUT.js +229 -0
- package/chunks/{chunk-54YUXX7X.js → chunk-AQP3H22J.js} +1 -1
- package/chunks/{chunk-EQWKIA72.js → chunk-AUX2FL5T.js} +24 -7
- package/chunks/{chunk-YGFJ6BRT.js → chunk-AZCTY64Z.js} +1 -1
- package/chunks/{chunk-QLX4D55R.js → chunk-B5TJK7B3.js} +1 -1
- package/chunks/{chunk-HXMDDII6.js → chunk-B6RMK4ED.js} +4 -4
- package/chunks/{chunk-UCKM6KCJ.js → chunk-BHG3H6OZ.js} +1 -1
- package/chunks/{chunk-JLF2AQAL.js → chunk-BHVF3R6B.js} +7 -5
- package/chunks/{chunk-HFJSQ4GL.js → chunk-BTICBRPL.js} +1 -1
- package/chunks/{chunk-KZCK5JUN.js → chunk-C3T6HPNM.js} +1 -1
- package/chunks/{chunk-FCLMJS6N.js → chunk-CDDP4ONL.js} +164 -27
- package/chunks/{chunk-Y3ZXDBUL.js → chunk-CQPM66MG.js} +4 -4
- package/chunks/{chunk-WKVZES7O.js → chunk-CXONOVBN.js} +1 -1
- package/chunks/{chunk-TYBRGFYL.js → chunk-CXY6BICQ.js} +501 -479
- package/chunks/{chunk-W23HOFDK.js → chunk-D3KVGQUV.js} +1 -1
- package/chunks/{chunk-LMJSPC55.js → chunk-D7JMO2GP.js} +3 -7
- package/chunks/{chunk-CXXAZ2LZ.js → chunk-DC4ZNGH4.js} +1 -1
- package/chunks/{chunk-FMLBBXHB.js → chunk-DRAX5YAI.js} +2 -2
- package/chunks/{chunk-DOTF2PF2.js → chunk-DRD6VBNH.js} +1 -1
- package/chunks/chunk-DX6JTDMR.js +105 -0
- package/chunks/{chunk-MNRK6MIH.js → chunk-E2VSBAFA.js} +53 -11
- package/chunks/{chunk-QJKR2P2K.js → chunk-EIBECN2J.js} +3 -3
- package/chunks/{chunk-LWWRJRCD.js → chunk-ESBYWATJ.js} +1 -1
- package/chunks/{chunk-3544ZEGZ.js → chunk-FASYATAZ.js} +5 -7
- package/chunks/{chunk-6YUS5JCV.js → chunk-FBY32737.js} +4 -4
- package/chunks/{chunk-LBWIJ5T7.js → chunk-FCPJXKDG.js} +10 -7
- package/chunks/{chunk-FX6GJIPZ.js → chunk-FEDFZBGR.js} +3 -3
- package/chunks/{chunk-DQ4LBRZN.js → chunk-FIJODK52.js} +3 -3
- package/chunks/{chunk-HVSRWLOW.js → chunk-FX6PZBOV.js} +3 -3
- package/chunks/{chunk-L6DIANLD.js → chunk-G45B3INR.js} +1 -1
- package/chunks/{chunk-EYLUKEYW.js → chunk-GI7SLDOI.js} +2 -2
- package/chunks/chunk-GJKP6XOB.js +1092 -0
- package/chunks/{chunk-I6YJZGHS.js → chunk-GSAOVDTH.js} +9 -9
- package/chunks/{chunk-XK4UQSIR.js → chunk-H6L4NEAT.js} +1 -1
- package/chunks/{chunk-GMCEFKNR.js → chunk-HNFKYKHH.js} +103 -22
- package/chunks/{chunk-6XDB3FR4.js → chunk-HX4WXX3H.js} +301 -138
- package/chunks/{chunk-HG46TTAG.js → chunk-HXUI5D4H.js} +1 -1
- package/chunks/{chunk-QI4WBHPF.js → chunk-HYHSMTRA.js} +4 -4
- package/chunks/{chunk-ZUKC5J6Q.js → chunk-IKBEIDOH.js} +14 -14
- package/chunks/{chunk-LCAJ63TF.js → chunk-INN5ORKX.js} +1 -1
- package/chunks/{chunk-GNV2SFO7.js → chunk-IVFTLUZD.js} +26 -1
- package/chunks/{chunk-GNKSR3FU.js → chunk-IXO2OCIP.js} +2 -2
- package/chunks/{chunk-SNT634Q6.js → chunk-K4XMAIRX.js} +30 -33
- package/chunks/{chunk-WBP64MZR.js → chunk-KAYC5FBN.js} +5269 -2785
- package/chunks/chunk-KEM7MWS7.js +3541 -0
- package/chunks/{chunk-ADQUK6WA.js → chunk-KVC7HZWK.js} +1 -1
- package/chunks/{chunk-UQXURNLM.js → chunk-KVQ3QL4K.js} +3 -3
- package/chunks/{chunk-7U5G6JXI.js → chunk-KWYTSSTJ.js} +105 -6
- package/chunks/{chunk-Q4G2YPI4.js → chunk-L2A5VBDL.js} +3019 -2352
- package/chunks/{chunk-WD6YQI5M.js → chunk-L3SNMEDW.js} +1 -1
- package/chunks/{chunk-BYUAT5OC.js → chunk-L7TJUPNR.js} +19 -3
- package/chunks/{chunk-ABNX6E6K.js → chunk-LFKXIOGC.js} +1 -1
- package/chunks/{chunk-GFAK6DYU.js → chunk-LO2UWNO5.js} +2 -2
- package/chunks/{chunk-67ZDP7UX.js → chunk-M22WLKLI.js} +5 -5
- package/chunks/{chunk-54B2LTKP.js → chunk-M23GFJ5B.js} +24 -5
- package/chunks/{chunk-VGY2RGXL.js → chunk-M4U2LTD2.js} +1 -1
- package/chunks/{chunk-ZNI3YJHS.js → chunk-MFDKHGTD.js} +1 -1
- package/chunks/{chunk-R7OO56VZ.js → chunk-MMRGG6R4.js} +1 -1
- package/chunks/{chunk-E6IR653O.js → chunk-MO4XID7S.js} +1 -1
- package/chunks/{chunk-NJ4ZNDVP.js → chunk-NKTMUPHJ.js} +3 -6
- package/chunks/{chunk-4DTFTPTU.js → chunk-NQ272MQG.js} +1 -1
- package/chunks/{chunk-DWKFTUGI.js → chunk-OALXNGUA.js} +6 -6
- package/chunks/{chunk-FBDHP23D.js → chunk-OSG23MR3.js} +1 -1
- package/chunks/{chunk-NJ2OFVUX.js → chunk-P42KMMU6.js} +860 -1
- package/chunks/{chunk-5KJ54DY3.js → chunk-PF7GAP6K.js} +60 -58
- package/chunks/{chunk-MQRLLBMQ.js → chunk-PPJSG2PU.js} +2 -2
- package/chunks/{chunk-EPVEPTI3.js → chunk-PZRXWQUA.js} +753 -18
- package/chunks/{chunk-VI5UVPOB.js → chunk-Q54O3EIA.js} +30 -28
- package/chunks/{chunk-QTUQV33C.js → chunk-QGEISOJ2.js} +4 -4
- package/chunks/{chunk-XKRYQOHS.js → chunk-QHSOINX6.js} +2 -2
- package/chunks/{chunk-Z6Q7I37O.js → chunk-QIPLWW6Q.js} +1 -1
- package/chunks/chunk-QMENOK5T.js +1246 -0
- package/chunks/chunk-QT6Z2IBF.js +347 -0
- package/chunks/{chunk-TBSCTWKF.js → chunk-RN6A53UJ.js} +25 -0
- package/chunks/{chunk-E7ZTAOJZ.js → chunk-RRI764F7.js} +21 -19
- package/chunks/{chunk-YI2YCNSP.js → chunk-SENYKRII.js} +1 -1
- package/chunks/chunk-SFHX5G2S.js +2796 -0
- package/chunks/chunk-SK3RZOPS.js +34 -0
- package/chunks/{chunk-SKYOAH4Z.js → chunk-SOLRBF7L.js} +13 -9
- package/chunks/{chunk-5WLF44DS.js → chunk-SSWTA7CH.js} +12 -12
- package/chunks/{chunk-IAS753HG.js → chunk-SYMXYRM5.js} +11 -2
- package/chunks/{chunk-FGROOEKM.js → chunk-TDKUXSJO.js} +34 -6
- package/chunks/{chunk-ZJ7JQUGY.js → chunk-TKF4JINY.js} +1 -1
- package/chunks/{chunk-ZOQ6HC7U.js → chunk-TPY6HW55.js} +4 -4
- package/chunks/{chunk-EDB556X7.js → chunk-TRZ22SG5.js} +1 -1
- package/chunks/{chunk-FHSOZSBO.js → chunk-TXTCM3TC.js} +4 -4
- package/chunks/{chunk-5ODRE7E5.js → chunk-U4AASWUQ.js} +28 -12
- package/chunks/{chunk-PPE7VUMD.js → chunk-UQGRJTDK.js} +2 -2
- package/chunks/{chunk-JO67LVXW.js → chunk-UZSB57EV.js} +6 -8
- package/chunks/{chunk-UY4OCBX4.js → chunk-V4JJAVHQ.js} +2 -2
- package/chunks/chunk-VEXUA6DX.js +1026 -0
- package/chunks/{chunk-ME4JBHSB.js → chunk-VQDWCQOE.js} +2 -0
- package/chunks/{chunk-ZC75SULX.js → chunk-VU3XMZ5I.js} +23 -4
- package/chunks/{chunk-A2UYI473.js → chunk-WL36KHUQ.js} +6 -6
- package/chunks/{chunk-IWOJ2FHG.js → chunk-WNQIJTOP.js} +8 -8
- package/chunks/{chunk-IANIY25T.js → chunk-WSJI6ODG.js} +99 -30
- package/chunks/{chunk-3CKAOJ4L.js → chunk-WZWTY7SG.js} +6 -6
- package/chunks/{chunk-EKMJR7M3.js → chunk-X7AYIXC7.js} +1 -1
- package/chunks/{chunk-IBRQG2MP.js → chunk-XAJZFGD2.js} +11 -11
- package/chunks/{chunk-VRQZESKP.js → chunk-XICCGDWF.js} +2 -2
- package/chunks/{chunk-L5R4D5T4.js → chunk-Y2KJC55Y.js} +12 -7
- package/chunks/{chunk-2S2WIGCM.js → chunk-Y4NNIGYO.js} +1 -1
- package/chunks/{chunk-J7LBAKDH.js → chunk-YL3UJML3.js} +7 -7
- package/chunks/{chunk-GSS4SZNG.js → chunk-YP2K3WOS.js} +40 -56
- package/chunks/{chunk-ZZUXUBEB.js → chunk-YQQ2U7AS.js} +8 -5
- package/chunks/{chunk-FAWTMDX7.js → chunk-YXHY6BKS.js} +15 -0
- package/chunks/{chunk-FIP5QS2U.js → chunk-YZXSDPOQ.js} +140 -39
- package/chunks/{chunk-WATHOB6X.js → chunk-ZFHKUQZ4.js} +3 -3
- package/chunks/{chunk-R5OA3ONY.js → chunk-ZMYKNKET.js} +6 -6
- package/chunks/{codex-subagent-executor-LANZAZPH.js → codex-subagent-executor-AEAIQZDC.js} +48 -49
- package/chunks/{config-utils-CRK2LQPA.js → config-utils-KX2YS725.js} +43 -46
- package/chunks/{contextCommand-GY5X3LIY.js → contextCommand-RV6Y5LNJ.js} +41 -44
- package/chunks/{core-runtime-IJIV2LHP.js → core-runtime-ZI4RTOJQ.js} +45 -48
- package/chunks/{create-sub-session-MNIVRHGB.js → create-sub-session-BBWFQARJ.js} +46 -48
- package/chunks/{daemon-NJB4PWZ7.js → daemon-INCM4VBX.js} +3 -1
- package/chunks/{daemon-git-worktree-guard-W6Z2BGDH.js → daemon-git-worktree-guard-KECEMV6A.js} +39 -42
- package/chunks/{daemon-status-provider-TJF3APU3.js → daemon-status-provider-NULJNAEV.js} +53 -56
- package/chunks/{daemon-trust-policy-6INCISDU.js → daemon-trust-policy-S4KWGPV3.js} +47 -50
- package/chunks/{daemon-trust-policy-monitor-JRTAQG54.js → daemon-trust-policy-monitor-546N5ZVL.js} +47 -50
- package/chunks/{de-VGY3VNBU.js → de-6AVKPTXQ.js} +11 -0
- package/chunks/{deferred-core-runtime-2JRTPTNM.js → deferred-core-runtime-T23ZT443.js} +39 -42
- package/chunks/{dist-NIOJXMGY.js → dist-4P3ZJYGI.js} +1 -1
- package/chunks/{dist-VDLSBCLM.js → dist-7MGRENQ5.js} +1 -1
- package/chunks/{dist-SE4J6Z4O.js → dist-BNW423XT.js} +326 -77
- package/chunks/{dist-TFGETXFN.js → dist-CESMUYGN.js} +4 -4
- package/chunks/{dist-MPUZZOG5.js → dist-DBBOFWSC.js} +1 -1
- package/chunks/{dist-T6DDPDLQ.js → dist-G5UMXIGF.js} +1 -1
- package/chunks/{dist-PA7WPFVE.js → dist-UXVNLQHG.js} +3 -3
- package/chunks/{dist-GUB7QRYA.js → dist-VA4LREAQ.js} +2 -2
- package/chunks/{dist-2QYIVNS6.js → dist-XDRTR4QP.js} +1 -1
- package/chunks/{edit-JDIXXCYB.js → edit-CMSQB7NP.js} +27 -30
- package/chunks/{en-E5ZO5TZW.js → en-56QLKXS2.js} +23 -1
- package/chunks/{enter-worktree-CAARFWBI.js → enter-worktree-DA6A4XC5.js} +3 -3
- package/chunks/{enterPlanMode-YTNTBZBN.js → enterPlanMode-UDPMNESD.js} +27 -30
- package/chunks/{environment-UAI5L52V.js → environment-TSQJUTPV.js} +42 -45
- package/chunks/{errors-J4UCDCW5.js → errors-RIVYJS6T.js} +41 -44
- package/chunks/{exit-worktree-JXGGUOBP.js → exit-worktree-4H6Z2VQI.js} +3 -3
- package/chunks/{exitPlanMode-YMWJ2EO7.js → exitPlanMode-BYBBFN2T.js} +27 -30
- package/chunks/{fast-path-MBAN7TK3.js → fast-path-F2CYDDZ4.js} +4 -4
- package/chunks/{fast-path-settings-XDYX7X5Z.js → fast-path-settings-N2VGRGDJ.js} +2 -2
- package/chunks/{fr-UAZJJH5N.js → fr-EBUDHJL3.js} +11 -0
- package/chunks/{glob-YEM24E3Z.js → glob-Z2JMJKKN.js} +27 -30
- package/chunks/{goal-tools-LJIVH5T6.js → goal-tools-HXVVLGCV.js} +27 -30
- package/chunks/{handleAutoUpdate-DYCSYDYL.js → handleAutoUpdate-FZP45KOR.js} +43 -46
- package/chunks/{i18n-PTAV7SN3.js → i18n-OTB62AKW.js} +40 -43
- package/chunks/{image-gen-5G2TQ3DY.js → image-gen-HIAZCB5T.js} +6 -7
- package/chunks/{initializer-MPXTKQA4.js → initializer-4JXZEC4B.js} +47 -50
- package/chunks/{installationInfo-U5EFA3OL.js → installationInfo-2IJV5QKC.js} +39 -42
- package/chunks/{ja-2RITCMAJ.js → ja-NCDT4CGV.js} +11 -0
- package/chunks/{list-YOE25QUI.js → list-KQSQ4A5G.js} +50 -53
- package/chunks/{llm-ZZ2WNQMC.js → llm-LSUBOJAR.js} +154 -974
- package/chunks/{llm-content-generator-CG2HRJZC.js → llm-content-generator-MLIONRXE.js} +17 -12
- package/chunks/{loadedSettingsAdapter-NPGWGURF.js → loadedSettingsAdapter-TZTTNRHI.js} +47 -50
- package/chunks/{loggingContentGenerator-TUL6SJVL.js → loggingContentGenerator-TUPEXFMM.js} +31 -34
- package/chunks/{loop-wakeup-VG6CGBQA.js → loop-wakeup-ZBVRI6VH.js} +1 -1
- package/chunks/{managed-npm-update-YUDSCJP3.js → managed-npm-update-WEA5XMFZ.js} +40 -43
- package/chunks/{mcp-EX3GDQVO.js → mcp-TFDTUPIA.js} +47 -50
- package/chunks/{model-configuration-6DEKTXJI.js → model-configuration-ZCAKKIOF.js} +48 -51
- package/chunks/{modelConfigUtils-4NA2MHEE.js → modelConfigUtils-J3ZPW7ZK.js} +41 -44
- package/chunks/{monitor-PPUGNAWR.js → monitor-CI7YE7MT.js} +29 -32
- package/chunks/{nonInteractiveCli-6TW2XYP5.js → nonInteractiveCli-GPT3TVOK.js} +96 -98
- package/chunks/{notebook-edit-4MUXHZHT.js → notebook-edit-3WCVRNGL.js} +27 -30
- package/chunks/{openaiContentGenerator-5J73W5XZ.js → openaiContentGenerator-OGILGUZE.js} +12 -17
- package/chunks/{openaiResponsesContentGenerator-AWRYZLJU.js → openaiResponsesContentGenerator-NXOXUPFM.js} +45 -13
- package/chunks/{pidfile-M7WELKBB.js → pidfile-GBTBIGHF.js} +39 -42
- package/chunks/{process-registry-X6ZCASEN.js → process-registry-7LAPI3ZB.js} +1 -1
- package/chunks/{processUtils-SPRINFNY.js → processUtils-O4II3RYH.js} +2 -2
- package/chunks/{prompt-terminal-ledger-25BRD7FX.js → prompt-terminal-ledger-ILIXZI3E.js} +40 -43
- package/chunks/{pt-5ZF7ZQUV.js → pt-FYYFWYUC.js} +11 -0
- package/chunks/{qwenContentGenerator-H5AAKXPC.js → qwenContentGenerator-I4LRYADV.js} +33 -36
- package/chunks/{qwenOAuth2-WIEUEFEY.js → qwenOAuth2-3J66TOT5.js} +6 -7
- package/chunks/{read-file-ILGEFPB3.js → read-file-G4XKW2CS.js} +5 -9
- package/chunks/{record-artifact-PXMNP7GZ.js → record-artifact-L3CFJOMA.js} +2 -2
- package/chunks/{report-findings-W6GR7SYZ.js → report-findings-LY5HQY4K.js} +3 -3
- package/chunks/{resumeHistoryUtils-RB52QOCH.js → resumeHistoryUtils-YPJU4XFE.js} +44 -47
- package/chunks/{ripGrep-O6QAFHQK.js → ripGrep-AAKMALLM.js} +7 -11
- package/chunks/{ru-7BNZFQKG.js → ru-RHEB3RNS.js} +11 -0
- package/chunks/{run-qwen-serve-5NO3TKUL.js → run-qwen-serve-ZVEKGS7Y.js} +177 -98
- package/chunks/{runtime-G2YUYMSZ.js → runtime-SJCRYNPA.js} +52 -55
- package/chunks/safe-mode-KLGUG54M.js +11 -0
- package/chunks/sandbox-UIXL423Z.js +146 -0
- package/chunks/sandboxConfig-CY343YNJ.js +114 -0
- package/chunks/{scheduled-tasks-HDHV3URA.js → scheduled-tasks-5UGBEVNZ.js} +50 -53
- package/chunks/{scheduler-6MDJX2ZK.js → scheduler-GCZYLZ2P.js} +41 -44
- package/chunks/{sdk-exporters-http-3R2TRQHE.js → sdk-exporters-http-DR4G663K.js} +1 -1
- package/chunks/{sdk-impl-4WF3VZ2F.js → sdk-impl-SJR26MQF.js} +3 -3
- package/chunks/{send-message-UMJKN27Q.js → send-message-DN76MXDX.js} +6 -6
- package/chunks/{serve-Z2EJQYKB.js → serve-2XXQLVK2.js} +48 -51
- package/chunks/{server-JTNBK3LH.js → server-UHMKPCAZ.js} +408 -211
- package/chunks/{session-5YK2BXH4.js → session-ZLUK7E4P.js} +108 -108
- package/chunks/{session-attachments-root-QO3VFJS6.js → session-attachments-root-DHQM5IEZ.js} +39 -42
- package/chunks/{session-pr-refresh-OTK3HCJZ.js → session-pr-refresh-3OMTQWCZ.js} +48 -51
- package/chunks/{settings-2VKLACYV.js → settings-P4DHIIUP.js} +50 -53
- package/chunks/{shell-64NAVGMS.js → shell-IMFUVQQ5.js} +27 -30
- package/chunks/{skill-R3ALMLLM.js → skill-NB5RJGZW.js} +7 -11
- package/chunks/{skill-settings-HZ34TUMP.js → skill-settings-IXG5CTQO.js} +47 -50
- package/chunks/{spawnChannel-XGFWHEIK.js → spawnChannel-Q3YALTCJ.js} +44 -45
- package/chunks/{standalone-update-R32Y3XRR.js → standalone-update-H5OJ7MM7.js} +41 -44
- package/chunks/{start-opentui-ui-YGJOUE2H.js → start-opentui-ui-JKAIWGF7.js} +733 -386
- package/chunks/{startInteractiveUI-5ZEVKSFF.js → startInteractiveUI-YRPOT6GH.js} +370 -337
- package/chunks/task-create-75HVPEAH.js +1 -1
- package/chunks/{team-create-GCVUXJLE.js → team-create-2XTBYRJF.js} +31 -34
- package/chunks/{team-plan-approval-NOL62FJD.js → team-plan-approval-CFNWW7ZQ.js} +27 -30
- package/chunks/{terminal-image-renderer-WG5TLPGC.js → terminal-image-renderer-UDPJPGPQ.js} +39 -42
- package/chunks/{theme-manager-HDS4YFPW.js → theme-manager-SK57EKMO.js} +39 -42
- package/chunks/{tool-search-HMT5GYUR.js → tool-search-ZHTJU2MV.js} +5 -9
- package/chunks/{total-session-admission-Y5RCHEXO.js → total-session-admission-UUZBDQCG.js} +47 -50
- package/chunks/{tree-sitter-LSORDVZ3.js → tree-sitter-4D7QS7F6.js} +1 -1
- package/chunks/{tree-sitter-bash-UARELQ6C.js → tree-sitter-bash-VEJGF5XF.js} +1 -1
- package/chunks/{trustedFolders-3Y2WCXMR.js → trustedFolders-4LDBLNTS.js} +40 -43
- package/chunks/{update-relaunch-MTJ32SLF.js → update-relaunch-LI7GRP36.js} +5 -5
- package/chunks/{updateCheck-YFX3VY6O.js → updateCheck-PKSSORPO.js} +43 -46
- package/chunks/{useAutoAcceptIndicator-FCHNQPMD.js → useAutoAcceptIndicator-I32UEQPI.js} +50 -53
- package/chunks/{validateNonInterActiveAuth-HUFQKCGG.js → validateNonInterActiveAuth-YFPCYYNL.js} +93 -95
- package/chunks/{version-S5TGWCA3.js → version-4MTL4JVU.js} +1 -1
- package/chunks/{web-fetch-23M7BYHB.js → web-fetch-O6RG6ISB.js} +9 -13
- package/chunks/{web-search-F5PNIQUA.js → web-search-JHAXVEMD.js} +9 -14
- package/chunks/{web-shell-static-T7UGLVE4.js → web-shell-static-FFWCUUZS.js} +8 -4
- package/chunks/{workflow-BLJLID2C.js → workflow-O7L6VDYU.js} +396 -113
- package/chunks/{workspace-providers-status-UH7KLZDT.js → workspace-providers-status-WRX6CJM4.js} +53 -56
- package/chunks/{workspace-registration-store-3SA3V7BA.js → workspace-registration-store-7G4E7YPY.js} +1 -1
- package/chunks/{workspace-registry-C6C6EKQ5.js → workspace-registry-SXIMGT4D.js} +47 -50
- package/chunks/{workspace-runtime-coordinator-RAI6XDJB.js → workspace-runtime-coordinator-7DOEHXYT.js} +47 -50
- package/chunks/{workspace-service-H7UTJYJU.js → workspace-service-HDXOZMYC.js} +53 -56
- package/chunks/{workspace-skills-status-FPVC7XXK.js → workspace-skills-status-VN4L37CA.js} +50 -53
- package/chunks/{workspace-trust-reconciler-JS7A6UIF.js → workspace-trust-reconciler-XEBW5FUL.js} +57 -60
- package/chunks/{write-file-GQGG7NBQ.js → write-file-LKX4ETIO.js} +29 -32
- package/chunks/{zh-V2EYTYJP.js → zh-F76MZTL3.js} +23 -1
- package/chunks/{zh-TW-7PRVUGLW.js → zh-TW-S3YTQ4DS.js} +23 -1
- package/chunks/{zoom-image-EC43KL4H.js → zoom-image-RDPRTP4B.js} +5 -9
- package/cli.js +19 -15
- package/export-transcript-document.css +1 -1
- package/export-transcript-document.js +151 -150
- package/locales/ca.js +19 -2
- package/locales/de.js +18 -0
- package/locales/en.js +33 -2
- package/locales/fr.js +18 -0
- package/locales/ja.js +18 -0
- package/locales/pt.js +18 -0
- package/locales/ru.js +18 -0
- package/locales/zh-TW.js +33 -2
- package/locales/zh.js +33 -2
- package/package.json +3 -3
- package/web-shell/assets/{abnfDiagram-VCTEODGH-BtpzKw3A.js → abnfDiagram-VCTEODGH-RxykUDmi.js} +1 -1
- package/web-shell/assets/{arc-CQiVKZJP.js → arc-CZpgGCJC.js} +1 -1
- package/web-shell/assets/{architectureDiagram-5GKGNRK7-ekIPBb2d.js → architectureDiagram-5GKGNRK7-BHSMzNDT.js} +1 -1
- package/web-shell/assets/{blockDiagram-NRAW4CY4-BrRWkWri.js → blockDiagram-NRAW4CY4-Bn4mF9SZ.js} +1 -1
- package/web-shell/assets/{c4Diagram-UCG6FXSJ-qYS8CYZ3.js → c4Diagram-UCG6FXSJ-CBM-Bj6t.js} +1 -1
- package/web-shell/assets/channel-DFYs_LlK.js +1 -0
- package/web-shell/assets/{chunk-2Q5K7J3B-ZasyyEZm.js → chunk-2Q5K7J3B-D5Fin58O.js} +1 -1
- package/web-shell/assets/{chunk-5VM5RSS4-C_IzCGeA.js → chunk-5VM5RSS4-CY05weF7.js} +1 -1
- package/web-shell/assets/{chunk-F27PBJKO-C25NZOyD.js → chunk-F27PBJKO-3neZnj5Y.js} +1 -1
- package/web-shell/assets/{chunk-G27WJ6UU-XPOHNSGX.js → chunk-G27WJ6UU-Cd7EU4BE.js} +1 -1
- package/web-shell/assets/{chunk-JWPE2WC7-BQBh0Xni.js → chunk-JWPE2WC7-DwK1mqFw.js} +1 -1
- package/web-shell/assets/{chunk-LCL6LL3I-CoShjpX7.js → chunk-LCL6LL3I-Sl7vY22C.js} +1 -1
- package/web-shell/assets/{chunk-POPQ4Y6H-BwRmCDSz.js → chunk-POPQ4Y6H-BXNzpbVg.js} +1 -1
- package/web-shell/assets/{chunk-SVP7TREG-DSzE5-Mw.js → chunk-SVP7TREG-DjjButcp.js} +1 -1
- package/web-shell/assets/{chunk-XXDRQBXY-BQSQv30h.js → chunk-XXDRQBXY-DNOiCjOJ.js} +1 -1
- package/web-shell/assets/classDiagram-DTDB5LWJ-DnGrKXoM.js +1 -0
- package/web-shell/assets/classDiagram-v2-JRS7N3AN-DnGrKXoM.js +1 -0
- package/web-shell/assets/{cose-bilkent-JH36ORCC-XVUVTHVo.js → cose-bilkent-JH36ORCC-BUnker7a.js} +1 -1
- package/web-shell/assets/{cynefin-OW5HDTMX-CrsKx4lQ.js → cynefin-OW5HDTMX-DcUgdWE5.js} +1 -1
- package/web-shell/assets/{cynefinDiagram-5FMLGOSQ-BPeZEuHw.js → cynefinDiagram-5FMLGOSQ-CvDKsZsL.js} +1 -1
- package/web-shell/assets/{dagre-3AP2YEHR-D31cQ2Qs.js → dagre-3AP2YEHR-jpCmUbr1.js} +1 -1
- package/web-shell/assets/{diagram-S7CK7UJ4-zyiG097Q.js → diagram-S7CK7UJ4-DBe_bKE5.js} +1 -1
- package/web-shell/assets/{diagram-UQ7AKVKN-Br3vtfsy.js → diagram-UQ7AKVKN-oXvPpDgs.js} +1 -1
- package/web-shell/assets/{diagram-VSXAHHWV-Bxkhjx4u.js → diagram-VSXAHHWV-BD7-_SGh.js} +1 -1
- package/web-shell/assets/{diagram-VX7I27RA-BQH8QiDk.js → diagram-VX7I27RA-DOJL0wub.js} +1 -1
- package/web-shell/assets/{diagram-Z3DM3KII-B_aQ1cw0.js → diagram-Z3DM3KII-DRIiodDD.js} +1 -1
- package/web-shell/assets/{ebnfDiagram-PWID7BFC-B9N7BRQE.js → ebnfDiagram-PWID7BFC-Db31Ulmb.js} +1 -1
- package/web-shell/assets/{erDiagram-SSCWMZ5O-Cx6Hb1Re.js → erDiagram-SSCWMZ5O-CVHhwI2_.js} +1 -1
- package/web-shell/assets/{flowDiagram-A5DVABFB-DTuLP7GU.js → flowDiagram-A5DVABFB-DWOFy1FK.js} +1 -1
- package/web-shell/assets/{ganttDiagram-EL5Y4UJY-DYS3d-sL.js → ganttDiagram-EL5Y4UJY-C0sxQtPd.js} +1 -1
- package/web-shell/assets/{gitGraphDiagram-WWUBYQGX-Cp0EGx04.js → gitGraphDiagram-WWUBYQGX-CNituBYC.js} +1 -1
- package/web-shell/assets/index-B15NlwB8.js +2213 -0
- package/web-shell/assets/index-BSrS0tQ6.css +36 -0
- package/web-shell/assets/{index-45-LkPDB.js → index-gm9tLk7h.js} +1 -1
- package/web-shell/assets/{infoDiagram-RXCK75RN-9--kukiT.js → infoDiagram-RXCK75RN-CxhJYtIR.js} +1 -1
- package/web-shell/assets/{ishikawaDiagram-5VMMS53U-CGBdsDLD.js → ishikawaDiagram-5VMMS53U-By2mchUy.js} +1 -1
- package/web-shell/assets/{journeyDiagram-EYS64GPL-DeXhcscd.js → journeyDiagram-EYS64GPL-CVH-OweI.js} +1 -1
- package/web-shell/assets/{kanban-definition-3QL26DDD-CFdvsU3b.js → kanban-definition-3QL26DDD-Cc9dQXLy.js} +1 -1
- package/web-shell/assets/knowledge-Dg9788h4.svg +1 -0
- package/web-shell/assets/{layout-DAnwQ3KB.js → layout-C_60ysHw.js} +1 -1
- package/web-shell/assets/{linear-CTo7v7Nh.js → linear-BvAVfqwu.js} +1 -1
- package/web-shell/assets/{mermaid.core-jggSxF1i.js → mermaid.core-C3CoBKAc.js} +6 -6
- package/web-shell/assets/{mindmap-definition-FBJOCRG2-DzIepvlJ.js → mindmap-definition-FBJOCRG2-Cuu8Q8LM.js} +1 -1
- package/web-shell/assets/{pegDiagram-XKGWAZYB-BFGS9GJv.js → pegDiagram-XKGWAZYB-DmAeyDO2.js} +1 -1
- package/web-shell/assets/{pieDiagram-E7YTZNPT-B2UUcNIT.js → pieDiagram-E7YTZNPT-B7vbB_xv.js} +1 -1
- package/web-shell/assets/{quadrantDiagram-AXDQQJYC-BgM6htrX.js → quadrantDiagram-AXDQQJYC-BqOBkRR7.js} +1 -1
- package/web-shell/assets/{railroadDiagram-O6MQD6OU-Dk9cS7N-.js → railroadDiagram-O6MQD6OU-sI06lZIu.js} +1 -1
- package/web-shell/assets/{requirementDiagram-EFPCY7ZU-C9oRg7xi.js → requirementDiagram-EFPCY7ZU-Bg13d10S.js} +1 -1
- package/web-shell/assets/{sankeyDiagram-P5KCCOFB-B-_c7GzI.js → sankeyDiagram-P5KCCOFB-WFOzZHrR.js} +1 -1
- package/web-shell/assets/{sequenceDiagram-WJ2MYXX4-R0M-347u.js → sequenceDiagram-WJ2MYXX4-CCdRbA4E.js} +1 -1
- package/web-shell/assets/{sizeCapture-X5ZJPWSS-Df0f8UAW.js → sizeCapture-X5ZJPWSS-BH5F3bGg.js} +1 -1
- package/web-shell/assets/{stateDiagram-HBIQ2CUA-CsUEfAA-.js → stateDiagram-HBIQ2CUA-NwS2X3QB.js} +1 -1
- package/web-shell/assets/stateDiagram-v2-4QOOHH4V-1aU2JZXO.js +1 -0
- package/web-shell/assets/{swimlanes-XN3QIQJK-9OGHVSrx.js → swimlanes-XN3QIQJK-Bm38pM28.js} +1 -1
- package/web-shell/assets/swimlanesDiagram-VK2B7HYN-Dp-u6kQG.js +8 -0
- package/web-shell/assets/{timeline-definition-24CTP7MA-DAfGqS2B.js → timeline-definition-24CTP7MA-Do-agLSo.js} +1 -1
- package/web-shell/assets/{vennDiagram-4TSXK5OY-CKATpwHi.js → vennDiagram-4TSXK5OY-aggLfZzl.js} +1 -1
- package/web-shell/assets/{wardleyDiagram-VM6X3IG4-CQHdhTrm.js → wardleyDiagram-VM6X3IG4-D5JR3mXX.js} +1 -1
- package/web-shell/assets/{xychartDiagram-S5SC5T6Z-5k9NLqlY.js → xychartDiagram-S5SC5T6Z-DhtLDuXs.js} +1 -1
- package/web-shell/index.html +2 -2
- package/chunks/chunk-4OQSG35W.js +0 -1416
- package/chunks/chunk-7MIBD3LG.js +0 -137
- package/chunks/chunk-ARDHE6MM.js +0 -235
- package/chunks/chunk-C75BXMPM.js +0 -169
- package/chunks/chunk-ERU3SDXT.js +0 -27
- package/chunks/chunk-FPGTNKCP.js +0 -251
- package/chunks/chunk-JIJ65YKA.js +0 -2812
- package/chunks/chunk-JL6APGBX.js +0 -43
- package/chunks/chunk-SGXJQP5Q.js +0 -4172
- package/chunks/chunk-TPEV2QHG.js +0 -514
- package/chunks/chunk-YVWS4SLL.js +0 -137
- package/web-shell/assets/channel-DSQQnOZj.js +0 -1
- package/web-shell/assets/classDiagram-DTDB5LWJ-V94ta08R.js +0 -1
- package/web-shell/assets/classDiagram-v2-JRS7N3AN-V94ta08R.js +0 -1
- package/web-shell/assets/index-H8um-iEl.js +0 -2207
- package/web-shell/assets/index-n6N-2a3v.css +0 -36
- package/web-shell/assets/stateDiagram-v2-4QOOHH4V-CnSuTPJ2.js +0 -1
- package/web-shell/assets/swimlanesDiagram-VK2B7HYN-Bb7TcWQw.js +0 -8
- package/chunks/{chunk-QZW6WRB7.js → chunk-5NUKK2DT.js} +2 -2
- package/chunks/{chunk-JS73NNWF.js → chunk-FUSEMYFX.js} +0 -0
- package/chunks/{chunk-SVWWF5TZ.js → chunk-WVURIAEE.js} +3 -3
- package/chunks/{task-update-RI7QNVDP.js → task-update-3LSYQDRW.js} +4 -4
|
@@ -0,0 +1,3541 @@
|
|
|
1
|
+
// Force strict mode and setup for ESM
|
|
2
|
+
"use strict";
|
|
3
|
+
import {
|
|
4
|
+
DEFAULT_QWEN_MODEL,
|
|
5
|
+
MODEL_GENERATION_CONFIG_FIELDS,
|
|
6
|
+
PROVIDER_SOURCED_FIELDS,
|
|
7
|
+
QWEN_OAUTH_MODELS,
|
|
8
|
+
REASONING_EFFORT_TIERS,
|
|
9
|
+
clampReasoningEffort,
|
|
10
|
+
defaultModalities,
|
|
11
|
+
getGptReasoningCapabilities,
|
|
12
|
+
normalize,
|
|
13
|
+
parseModelReasoningCapabilities,
|
|
14
|
+
tokenLimit
|
|
15
|
+
} from "./chunk-GJKP6XOB.js";
|
|
16
|
+
import {
|
|
17
|
+
AuthType
|
|
18
|
+
} from "./chunk-7O5PYQ3M.js";
|
|
19
|
+
import {
|
|
20
|
+
createDebugLogger
|
|
21
|
+
} from "./chunk-ZAFYHRVY.js";
|
|
22
|
+
import {
|
|
23
|
+
init_esbuild_shims
|
|
24
|
+
} from "./chunk-5O2XNYP6.js";
|
|
25
|
+
import {
|
|
26
|
+
__name
|
|
27
|
+
} from "./chunk-J2S4EL5Y.js";
|
|
28
|
+
|
|
29
|
+
// packages/core/src/core/openaiContentGenerator/constants.ts
|
|
30
|
+
init_esbuild_shims();
|
|
31
|
+
var DEFAULT_TIMEOUT = 12e4;
|
|
32
|
+
var DISABLED_REQUEST_TIMEOUT_MS = 2147483647;
|
|
33
|
+
function resolveRequestTimeout(timeout) {
|
|
34
|
+
if (timeout === void 0 || timeout === null) {
|
|
35
|
+
return DEFAULT_TIMEOUT;
|
|
36
|
+
}
|
|
37
|
+
return timeout <= 0 ? DISABLED_REQUEST_TIMEOUT_MS : timeout;
|
|
38
|
+
}
|
|
39
|
+
__name(resolveRequestTimeout, "resolveRequestTimeout");
|
|
40
|
+
var DEFAULT_STREAM_IDLE_TIMEOUT_MS = 24e4;
|
|
41
|
+
var QWEN_STREAM_IDLE_TIMEOUT_MS_ENV = "QWEN_STREAM_IDLE_TIMEOUT_MS";
|
|
42
|
+
var MAX_STREAM_GUARD_TIMEOUT_MS = 2147483647;
|
|
43
|
+
var DEFAULT_STREAM_MAX_LIFETIME_MS = 9e5;
|
|
44
|
+
var QWEN_STREAM_MAX_LIFETIME_MS_ENV = "QWEN_STREAM_MAX_LIFETIME_MS";
|
|
45
|
+
var DEFAULT_MAX_RETRIES = 3;
|
|
46
|
+
var DEFAULT_OPENAI_BASE_URL = "https://api.openai.com/v1";
|
|
47
|
+
var DEFAULT_DASHSCOPE_BASE_URL = "https://dashscope.aliyuncs.com/compatible-mode/v1";
|
|
48
|
+
var DASHSCOPE_PROXY_BASE_URL = process.env["DASHSCOPE_PROXY_BASE_URL"];
|
|
49
|
+
|
|
50
|
+
// packages/core/src/models/image-generation-capability.ts
|
|
51
|
+
init_esbuild_shims();
|
|
52
|
+
function isImageGenerationCapable(model) {
|
|
53
|
+
return model.supportsImageGeneration === true || model.imageOnly === true;
|
|
54
|
+
}
|
|
55
|
+
__name(isImageGenerationCapable, "isImageGenerationCapable");
|
|
56
|
+
|
|
57
|
+
// packages/core/src/utils/runtimeModelPrefix.ts
|
|
58
|
+
init_esbuild_shims();
|
|
59
|
+
var RUNTIME_SNAPSHOT_PREFIX = "$runtime|";
|
|
60
|
+
function buildRuntimeSnapshotId(authType, modelId) {
|
|
61
|
+
return `${RUNTIME_SNAPSHOT_PREFIX}${authType}|${modelId}`;
|
|
62
|
+
}
|
|
63
|
+
__name(buildRuntimeSnapshotId, "buildRuntimeSnapshotId");
|
|
64
|
+
function stripRuntimeSnapshotPrefix(modelId) {
|
|
65
|
+
let id = modelId;
|
|
66
|
+
while (id.startsWith(RUNTIME_SNAPSHOT_PREFIX)) {
|
|
67
|
+
const stripped = id.split("|").slice(2).join("|");
|
|
68
|
+
if (!stripped) break;
|
|
69
|
+
id = stripped;
|
|
70
|
+
}
|
|
71
|
+
return id;
|
|
72
|
+
}
|
|
73
|
+
__name(stripRuntimeSnapshotPrefix, "stripRuntimeSnapshotPrefix");
|
|
74
|
+
|
|
75
|
+
// packages/core/src/models/modelsConfig.ts
|
|
76
|
+
init_esbuild_shims();
|
|
77
|
+
import process2 from "node:process";
|
|
78
|
+
|
|
79
|
+
// packages/core/src/models/modelRegistry.ts
|
|
80
|
+
init_esbuild_shims();
|
|
81
|
+
|
|
82
|
+
// packages/core/src/models/types.ts
|
|
83
|
+
init_esbuild_shims();
|
|
84
|
+
|
|
85
|
+
// packages/core/src/models/modelRegistry.ts
|
|
86
|
+
var debugLogger = createDebugLogger("MODEL_REGISTRY");
|
|
87
|
+
function validateAuthTypeKey(key) {
|
|
88
|
+
if (Object.values(AuthType).includes(key)) {
|
|
89
|
+
return key;
|
|
90
|
+
}
|
|
91
|
+
return void 0;
|
|
92
|
+
}
|
|
93
|
+
__name(validateAuthTypeKey, "validateAuthTypeKey");
|
|
94
|
+
function resolveProviderProtocol(providerId, providerProtocol) {
|
|
95
|
+
const explicit = providerProtocol && Object.hasOwn(providerProtocol, providerId) ? providerProtocol[providerId] : void 0;
|
|
96
|
+
if (explicit !== void 0) {
|
|
97
|
+
return validateAuthTypeKey(explicit);
|
|
98
|
+
}
|
|
99
|
+
return validateAuthTypeKey(providerId);
|
|
100
|
+
}
|
|
101
|
+
__name(resolveProviderProtocol, "resolveProviderProtocol");
|
|
102
|
+
function shouldUseCanonicalModalities(modelId) {
|
|
103
|
+
return /^minimax-m3/i.test(modelId.trim().toLowerCase());
|
|
104
|
+
}
|
|
105
|
+
__name(shouldUseCanonicalModalities, "shouldUseCanonicalModalities");
|
|
106
|
+
function modelRegistryKey(id, baseUrl) {
|
|
107
|
+
return baseUrl ? `${id}\0${baseUrl}` : id;
|
|
108
|
+
}
|
|
109
|
+
__name(modelRegistryKey, "modelRegistryKey");
|
|
110
|
+
var ModelRegistry = class _ModelRegistry {
|
|
111
|
+
static {
|
|
112
|
+
__name(this, "ModelRegistry");
|
|
113
|
+
}
|
|
114
|
+
modelsByAuthType;
|
|
115
|
+
/** providerId -> SDK protocol mapping; persists across reloads. */
|
|
116
|
+
providerProtocolConfig;
|
|
117
|
+
/** Raw providers config this registry was last built from. */
|
|
118
|
+
modelProvidersConfig;
|
|
119
|
+
getDefaultBaseUrl(authType) {
|
|
120
|
+
switch (authType) {
|
|
121
|
+
case "qwen-oauth" /* QWEN_OAUTH */:
|
|
122
|
+
return "DYNAMIC_QWEN_OAUTH_BASE_URL";
|
|
123
|
+
case "openai" /* USE_OPENAI */:
|
|
124
|
+
return DEFAULT_OPENAI_BASE_URL;
|
|
125
|
+
default:
|
|
126
|
+
return "";
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
constructor(modelProvidersConfig, providerProtocolConfig) {
|
|
130
|
+
this.modelsByAuthType = /* @__PURE__ */ new Map();
|
|
131
|
+
this.providerProtocolConfig = providerProtocolConfig ?? {};
|
|
132
|
+
this.modelProvidersConfig = modelProvidersConfig;
|
|
133
|
+
this.registerAuthTypeModels("qwen-oauth" /* QWEN_OAUTH */, QWEN_OAUTH_MODELS);
|
|
134
|
+
this.registerProvidersConfig(modelProvidersConfig);
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* Register every user-configured provider under its resolved SDK protocol.
|
|
138
|
+
* A provider id maps to a protocol via {@link resolveProviderProtocol}
|
|
139
|
+
* (explicit `providerProtocol` entry, or the id itself when it is a built-in
|
|
140
|
+
* protocol). Unmapped unknown ids are skipped with a warning.
|
|
141
|
+
*/
|
|
142
|
+
registerProvidersConfig(modelProvidersConfig) {
|
|
143
|
+
if (!modelProvidersConfig) return;
|
|
144
|
+
for (const [providerId, models] of Object.entries(modelProvidersConfig)) {
|
|
145
|
+
const protocol = resolveProviderProtocol(
|
|
146
|
+
providerId,
|
|
147
|
+
this.providerProtocolConfig
|
|
148
|
+
);
|
|
149
|
+
if (!protocol) {
|
|
150
|
+
const knownProtocols = Object.values(AuthType).join(", ");
|
|
151
|
+
const mapped = Object.hasOwn(this.providerProtocolConfig, providerId) ? this.providerProtocolConfig[providerId] : void 0;
|
|
152
|
+
const message = mapped !== void 0 ? `Provider "${providerId}" maps to "${mapped}" via providerProtocol, which is not a known protocol (${knownProtocols}); skipping.` : `Provider "${providerId}" in modelProviders is not a built-in protocol (${knownProtocols}) and has no providerProtocol mapping; skipping. Add providerProtocol["${providerId}"] to route it to an SDK protocol.`;
|
|
153
|
+
debugLogger.warn(message);
|
|
154
|
+
continue;
|
|
155
|
+
}
|
|
156
|
+
if (protocol === "qwen-oauth" /* QWEN_OAUTH */) {
|
|
157
|
+
continue;
|
|
158
|
+
}
|
|
159
|
+
this.registerAuthTypeModels(protocol, models, providerId);
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
/**
|
|
163
|
+
* Register models for an authType.
|
|
164
|
+
* Uniqueness is determined by the composite key (id + baseUrl).
|
|
165
|
+
* Two models with the same id but different baseUrls are treated as distinct.
|
|
166
|
+
* If multiple models share both id and baseUrl, the first one takes precedence.
|
|
167
|
+
*/
|
|
168
|
+
registerAuthTypeModels(authType, models, providerId) {
|
|
169
|
+
if (!Array.isArray(models)) {
|
|
170
|
+
debugLogger.warn(
|
|
171
|
+
`modelProviders for provider "${providerId ?? authType}" is not an array; skipping. Expected ModelConfig[]; legacy { protocol, models } entries are normally rewritten by the v5->v4 settings migration.`
|
|
172
|
+
);
|
|
173
|
+
return;
|
|
174
|
+
}
|
|
175
|
+
const modelMap = this.modelsByAuthType.get(authType) ?? /* @__PURE__ */ new Map();
|
|
176
|
+
const providerLabel = providerId && providerId !== authType ? ` (provider "${providerId}")` : "";
|
|
177
|
+
for (const config of models) {
|
|
178
|
+
const key = modelRegistryKey(config.id, config.baseUrl);
|
|
179
|
+
if (modelMap.has(key)) {
|
|
180
|
+
debugLogger.warn(
|
|
181
|
+
`Duplicate model id "${config.id}"${config.baseUrl ? ` with baseUrl "${config.baseUrl}"` : ""} for protocol "${authType}"${providerLabel}. Using the first registered config.`
|
|
182
|
+
);
|
|
183
|
+
continue;
|
|
184
|
+
}
|
|
185
|
+
const resolved = this.resolveModelConfig(config, authType);
|
|
186
|
+
modelMap.set(key, resolved);
|
|
187
|
+
}
|
|
188
|
+
this.modelsByAuthType.set(authType, modelMap);
|
|
189
|
+
}
|
|
190
|
+
/**
|
|
191
|
+
* Get all models for a specific authType.
|
|
192
|
+
* This is used by /model command to show only relevant models.
|
|
193
|
+
*/
|
|
194
|
+
getModelsForAuthType(authType) {
|
|
195
|
+
const models = this.modelsByAuthType.get(authType);
|
|
196
|
+
if (!models) return [];
|
|
197
|
+
return Array.from(models.values()).map((model) => ({
|
|
198
|
+
id: model.id,
|
|
199
|
+
label: model.name,
|
|
200
|
+
description: model.description,
|
|
201
|
+
capabilities: model.capabilities,
|
|
202
|
+
authType: model.authType,
|
|
203
|
+
isVision: model.capabilities?.vision ?? false,
|
|
204
|
+
contextWindowSize: model.generationConfig.contextWindowSize ?? tokenLimit(model.id),
|
|
205
|
+
// `modalities` is auto-filled in `resolveModelConfig`, so it is
|
|
206
|
+
// always defined on `ResolvedModelConfig` — no fallback needed here.
|
|
207
|
+
modalities: model.generationConfig.modalities,
|
|
208
|
+
baseUrl: model.baseUrl,
|
|
209
|
+
...model.registryBaseUrl !== void 0 ? { registryBaseUrl: model.registryBaseUrl } : {},
|
|
210
|
+
envKey: model.envKey,
|
|
211
|
+
fastOnly: model.fastOnly,
|
|
212
|
+
voiceOnly: model.voiceOnly,
|
|
213
|
+
visionOnly: model.visionOnly,
|
|
214
|
+
supportsImageGeneration: model.supportsImageGeneration,
|
|
215
|
+
imageOnly: model.imageOnly
|
|
216
|
+
}));
|
|
217
|
+
}
|
|
218
|
+
/**
|
|
219
|
+
* Get model configuration by authType and modelId.
|
|
220
|
+
* When baseUrl is provided, looks up the exact composite key, then a plain
|
|
221
|
+
* entry whose resolved default baseUrl matches.
|
|
222
|
+
* When baseUrl is omitted, tries the plain id first (backward compatible),
|
|
223
|
+
* then scans all entries for the first match by model id.
|
|
224
|
+
*/
|
|
225
|
+
getModel(authType, modelId, baseUrl) {
|
|
226
|
+
const models = this.modelsByAuthType.get(authType);
|
|
227
|
+
if (!models) return void 0;
|
|
228
|
+
if (baseUrl !== void 0) {
|
|
229
|
+
const exact = models.get(modelRegistryKey(modelId, baseUrl ?? void 0));
|
|
230
|
+
if (exact) return exact;
|
|
231
|
+
if (baseUrl === null) return void 0;
|
|
232
|
+
const plain2 = models.get(modelId);
|
|
233
|
+
return plain2?.baseUrl === baseUrl ? plain2 : void 0;
|
|
234
|
+
}
|
|
235
|
+
const plain = models.get(modelId);
|
|
236
|
+
if (plain) return plain;
|
|
237
|
+
for (const model of models.values()) {
|
|
238
|
+
if (model.id === modelId) return model;
|
|
239
|
+
}
|
|
240
|
+
return void 0;
|
|
241
|
+
}
|
|
242
|
+
/**
|
|
243
|
+
* Check if model exists for given authType.
|
|
244
|
+
* When baseUrl is provided, checks the exact endpoint or matching default.
|
|
245
|
+
* When baseUrl is omitted, checks plain id and scans by model id.
|
|
246
|
+
*/
|
|
247
|
+
hasModel(authType, modelId, baseUrl) {
|
|
248
|
+
return this.getModel(authType, modelId, baseUrl) !== void 0;
|
|
249
|
+
}
|
|
250
|
+
/**
|
|
251
|
+
* Get default model for an authType.
|
|
252
|
+
* For qwen-oauth, returns the coder model.
|
|
253
|
+
* For others, returns the first configured primary-capable model.
|
|
254
|
+
*/
|
|
255
|
+
getDefaultModelForAuthType(authType) {
|
|
256
|
+
if (authType === "qwen-oauth" /* QWEN_OAUTH */) {
|
|
257
|
+
return this.getModel(authType, DEFAULT_QWEN_MODEL);
|
|
258
|
+
}
|
|
259
|
+
const models = this.modelsByAuthType.get(authType);
|
|
260
|
+
if (!models || models.size === 0) return void 0;
|
|
261
|
+
return Array.from(models.values()).find(
|
|
262
|
+
(model) => !model.imageOnly && !model.voiceOnly
|
|
263
|
+
);
|
|
264
|
+
}
|
|
265
|
+
/**
|
|
266
|
+
* Resolve model config by applying defaults
|
|
267
|
+
*/
|
|
268
|
+
resolveModelConfig(config, authType) {
|
|
269
|
+
this.validateModelConfig(config, authType);
|
|
270
|
+
const generationConfig = { ...config.generationConfig ?? {} };
|
|
271
|
+
if (generationConfig.modalities === void 0 || shouldUseCanonicalModalities(config.id)) {
|
|
272
|
+
generationConfig.modalities = defaultModalities(config.id);
|
|
273
|
+
}
|
|
274
|
+
return {
|
|
275
|
+
...config,
|
|
276
|
+
authType,
|
|
277
|
+
name: config.name || config.id,
|
|
278
|
+
baseUrl: config.baseUrl || this.getDefaultBaseUrl(authType),
|
|
279
|
+
...config.baseUrl ? { registryBaseUrl: config.baseUrl } : {},
|
|
280
|
+
generationConfig,
|
|
281
|
+
capabilities: config.capabilities || {}
|
|
282
|
+
};
|
|
283
|
+
}
|
|
284
|
+
/**
|
|
285
|
+
* Validate model configuration
|
|
286
|
+
*/
|
|
287
|
+
validateModelConfig(config, authType) {
|
|
288
|
+
if (!config.id) {
|
|
289
|
+
throw new Error(
|
|
290
|
+
`Model config in authType '${authType}' missing required field: id`
|
|
291
|
+
);
|
|
292
|
+
}
|
|
293
|
+
const selectorOnlyCount = [
|
|
294
|
+
config.fastOnly,
|
|
295
|
+
config.voiceOnly,
|
|
296
|
+
config.visionOnly,
|
|
297
|
+
config.imageOnly
|
|
298
|
+
].filter(Boolean).length;
|
|
299
|
+
if (selectorOnlyCount > 1) {
|
|
300
|
+
debugLogger.warn(
|
|
301
|
+
`Model "${config.id}" in authType "${authType}" has multiple selector-only flags. It will be unreachable in at least one model selector.`
|
|
302
|
+
);
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
/**
|
|
306
|
+
* Reload models from updated configuration.
|
|
307
|
+
* Clears existing user-configured models and re-registers from new config.
|
|
308
|
+
* Preserves hard-coded qwen-oauth models.
|
|
309
|
+
*
|
|
310
|
+
* @param providerProtocolConfig - Updated provider->protocol map. `undefined`
|
|
311
|
+
* PRESERVES the existing map (so a reload carrying only modelProviders does
|
|
312
|
+
* not lose the mapping); any object value REPLACES it, so passing `{}`
|
|
313
|
+
* clears the mapping. Callers that want to preserve must omit the argument,
|
|
314
|
+
* not pass `settings.providerProtocol ?? {}`.
|
|
315
|
+
*/
|
|
316
|
+
reloadModels(modelProvidersConfig, providerProtocolConfig) {
|
|
317
|
+
const reloaded = new _ModelRegistry(
|
|
318
|
+
modelProvidersConfig,
|
|
319
|
+
providerProtocolConfig ?? this.providerProtocolConfig
|
|
320
|
+
);
|
|
321
|
+
this.modelsByAuthType = reloaded.modelsByAuthType;
|
|
322
|
+
this.providerProtocolConfig = reloaded.providerProtocolConfig;
|
|
323
|
+
this.modelProvidersConfig = reloaded.modelProvidersConfig;
|
|
324
|
+
}
|
|
325
|
+
/** The raw providers config this registry was last built from. */
|
|
326
|
+
getModelProvidersConfig() {
|
|
327
|
+
return this.modelProvidersConfig;
|
|
328
|
+
}
|
|
329
|
+
getProviderProtocolConfig() {
|
|
330
|
+
return this.providerProtocolConfig;
|
|
331
|
+
}
|
|
332
|
+
};
|
|
333
|
+
|
|
334
|
+
// packages/core/src/models/modelsConfig.ts
|
|
335
|
+
var debugLogger2 = createDebugLogger("ModelsConfig");
|
|
336
|
+
var ModelsConfig = class _ModelsConfig {
|
|
337
|
+
static {
|
|
338
|
+
__name(this, "ModelsConfig");
|
|
339
|
+
}
|
|
340
|
+
modelRegistry;
|
|
341
|
+
// Current selection state
|
|
342
|
+
currentAuthType;
|
|
343
|
+
currentRegistryBaseUrl;
|
|
344
|
+
// Generation config state
|
|
345
|
+
_generationConfig;
|
|
346
|
+
generationConfigSources;
|
|
347
|
+
// Flag for strict model provider selection
|
|
348
|
+
strictModelProviderSelection = false;
|
|
349
|
+
// One-shot flag for qwen-oauth credential caching
|
|
350
|
+
requireCachedQwenCredentialsOnce = false;
|
|
351
|
+
// One-shot flag indicating credentials were manually set via updateCredentials()
|
|
352
|
+
// When true, syncAfterAuthRefresh should NOT override these credentials with
|
|
353
|
+
// modelProviders defaults (even if the model ID matches a registry entry).
|
|
354
|
+
//
|
|
355
|
+
// This must be persistent across auth refreshes, because refreshAuth() can be
|
|
356
|
+
// triggered multiple times after a credential prompt flow. We only clear this
|
|
357
|
+
// flag when we explicitly apply modelProvider defaults (i.e. when the user
|
|
358
|
+
// switches to a registry model via switchModel).
|
|
359
|
+
hasManualCredentials = false;
|
|
360
|
+
// Callback for notifying Config of model changes
|
|
361
|
+
onModelChange;
|
|
362
|
+
// Flag indicating whether authType was explicitly provided (not defaulted)
|
|
363
|
+
authTypeWasExplicitlyProvided;
|
|
364
|
+
/**
|
|
365
|
+
* Runtime model snapshot storage.
|
|
366
|
+
*
|
|
367
|
+
* These snapshots store runtime-resolved model configurations that are NOT from
|
|
368
|
+
* modelProviders registry (e.g., models with manually set credentials).
|
|
369
|
+
*
|
|
370
|
+
* Key: snapshotId (format: `$runtime|${authType}|${modelId}`)
|
|
371
|
+
* Uses `$runtime|` prefix since `$` and `|` are unlikely to appear in real model IDs.
|
|
372
|
+
* This prevents conflicts with model IDs containing `-` or `:` characters.
|
|
373
|
+
* Value: RuntimeModelSnapshot containing the model's configuration
|
|
374
|
+
*
|
|
375
|
+
* Note: This is different from state snapshots used for rollback during model switching.
|
|
376
|
+
* RuntimeModelSnapshot stores persistent model configurations, while state snapshots
|
|
377
|
+
* are temporary and used only for error recovery.
|
|
378
|
+
*/
|
|
379
|
+
runtimeModelSnapshots = /* @__PURE__ */ new Map();
|
|
380
|
+
/**
|
|
381
|
+
* Currently active RuntimeModelSnapshot ID.
|
|
382
|
+
*
|
|
383
|
+
* When set, indicates that the current model is a runtime model (not from registry).
|
|
384
|
+
* This ID is included in state snapshots for rollback purposes.
|
|
385
|
+
*/
|
|
386
|
+
activeRuntimeModelSnapshotId;
|
|
387
|
+
static deepClone(value) {
|
|
388
|
+
if (value === null || typeof value !== "object") {
|
|
389
|
+
return value;
|
|
390
|
+
}
|
|
391
|
+
if (Array.isArray(value)) {
|
|
392
|
+
return value.map((v) => _ModelsConfig.deepClone(v));
|
|
393
|
+
}
|
|
394
|
+
const out = {};
|
|
395
|
+
for (const key of Object.keys(value)) {
|
|
396
|
+
out[key] = _ModelsConfig.deepClone(
|
|
397
|
+
value[key]
|
|
398
|
+
);
|
|
399
|
+
}
|
|
400
|
+
return out;
|
|
401
|
+
}
|
|
402
|
+
constructor(options = {}) {
|
|
403
|
+
this.modelRegistry = new ModelRegistry(
|
|
404
|
+
options.modelProvidersConfig,
|
|
405
|
+
options.providerProtocolConfig
|
|
406
|
+
);
|
|
407
|
+
this.onModelChange = options.onModelChange;
|
|
408
|
+
this._generationConfig = {
|
|
409
|
+
...options.generationConfig || {}
|
|
410
|
+
};
|
|
411
|
+
this.generationConfigSources = options.generationConfigSources || {};
|
|
412
|
+
this.authTypeWasExplicitlyProvided = options.initialAuthType !== void 0;
|
|
413
|
+
this.currentAuthType = options.initialAuthType;
|
|
414
|
+
const initialModelId = this._generationConfig.model;
|
|
415
|
+
if (this.currentAuthType && initialModelId) {
|
|
416
|
+
const initialModel = this.modelRegistry.getModel(
|
|
417
|
+
this.currentAuthType,
|
|
418
|
+
initialModelId,
|
|
419
|
+
options.initialRegistryBaseUrl
|
|
420
|
+
);
|
|
421
|
+
if (initialModel) {
|
|
422
|
+
this.currentRegistryBaseUrl = initialModel.registryBaseUrl ?? null;
|
|
423
|
+
}
|
|
424
|
+
}
|
|
425
|
+
}
|
|
426
|
+
/**
|
|
427
|
+
* Create a snapshot of the current ModelsConfig state for rollback purposes.
|
|
428
|
+
* Used before model switching operations to enable recovery on errors.
|
|
429
|
+
*
|
|
430
|
+
* Note: This is different from RuntimeModelSnapshot which stores runtime model configs.
|
|
431
|
+
*/
|
|
432
|
+
createStateSnapshotForRollback() {
|
|
433
|
+
return {
|
|
434
|
+
currentAuthType: this.currentAuthType,
|
|
435
|
+
generationConfig: _ModelsConfig.deepClone(this._generationConfig),
|
|
436
|
+
generationConfigSources: _ModelsConfig.deepClone(
|
|
437
|
+
this.generationConfigSources
|
|
438
|
+
),
|
|
439
|
+
strictModelProviderSelection: this.strictModelProviderSelection,
|
|
440
|
+
requireCachedQwenCredentialsOnce: this.requireCachedQwenCredentialsOnce,
|
|
441
|
+
hasManualCredentials: this.hasManualCredentials,
|
|
442
|
+
activeRuntimeModelSnapshotId: this.activeRuntimeModelSnapshotId,
|
|
443
|
+
currentRegistryBaseUrl: this.currentRegistryBaseUrl
|
|
444
|
+
};
|
|
445
|
+
}
|
|
446
|
+
/**
|
|
447
|
+
* Restore ModelsConfig state from a previously created state snapshot.
|
|
448
|
+
* Used for rollback when model switching operations fail.
|
|
449
|
+
*
|
|
450
|
+
* @param snapshot - The state snapshot to restore
|
|
451
|
+
*/
|
|
452
|
+
rollbackToStateSnapshot(snapshot) {
|
|
453
|
+
this.currentAuthType = snapshot.currentAuthType;
|
|
454
|
+
this._generationConfig = snapshot.generationConfig;
|
|
455
|
+
this.generationConfigSources = snapshot.generationConfigSources;
|
|
456
|
+
this.strictModelProviderSelection = snapshot.strictModelProviderSelection;
|
|
457
|
+
this.requireCachedQwenCredentialsOnce = snapshot.requireCachedQwenCredentialsOnce;
|
|
458
|
+
this.hasManualCredentials = snapshot.hasManualCredentials;
|
|
459
|
+
this.activeRuntimeModelSnapshotId = snapshot.activeRuntimeModelSnapshotId;
|
|
460
|
+
this.currentRegistryBaseUrl = snapshot.currentRegistryBaseUrl;
|
|
461
|
+
}
|
|
462
|
+
/**
|
|
463
|
+
* Get current model ID
|
|
464
|
+
*/
|
|
465
|
+
getModel() {
|
|
466
|
+
return this._generationConfig.model || DEFAULT_QWEN_MODEL;
|
|
467
|
+
}
|
|
468
|
+
/**
|
|
469
|
+
* Get current authType
|
|
470
|
+
*/
|
|
471
|
+
getCurrentAuthType() {
|
|
472
|
+
return this.currentAuthType;
|
|
473
|
+
}
|
|
474
|
+
getCurrentRegistryBaseUrl() {
|
|
475
|
+
return this.currentRegistryBaseUrl;
|
|
476
|
+
}
|
|
477
|
+
/**
|
|
478
|
+
* Check if authType was explicitly provided (via CLI or settings).
|
|
479
|
+
* If false, no authType was provided yet (fresh user).
|
|
480
|
+
*/
|
|
481
|
+
wasAuthTypeExplicitlyProvided() {
|
|
482
|
+
return this.authTypeWasExplicitlyProvided;
|
|
483
|
+
}
|
|
484
|
+
/**
|
|
485
|
+
* Get available models for current authType
|
|
486
|
+
*/
|
|
487
|
+
getAvailableModels() {
|
|
488
|
+
return this.currentAuthType ? this.modelRegistry.getModelsForAuthType(this.currentAuthType) : [];
|
|
489
|
+
}
|
|
490
|
+
/**
|
|
491
|
+
* Get available models for a specific authType
|
|
492
|
+
*/
|
|
493
|
+
getAvailableModelsForAuthType(authType) {
|
|
494
|
+
return this.modelRegistry.getModelsForAuthType(authType);
|
|
495
|
+
}
|
|
496
|
+
/**
|
|
497
|
+
* Get all configured models across authTypes.
|
|
498
|
+
*
|
|
499
|
+
* Notes:
|
|
500
|
+
* - By default, returns models across all authTypes.
|
|
501
|
+
* - qwen-oauth models are always ordered first.
|
|
502
|
+
* - Runtime model option (if active) is included before registry models of the same authType.
|
|
503
|
+
*/
|
|
504
|
+
getAllConfiguredModels(authTypes) {
|
|
505
|
+
const inputAuthTypes = authTypes && authTypes.length > 0 ? authTypes : Object.values(AuthType);
|
|
506
|
+
const seen = /* @__PURE__ */ new Set();
|
|
507
|
+
const uniqueAuthTypes = [];
|
|
508
|
+
for (const authType of inputAuthTypes) {
|
|
509
|
+
if (!seen.has(authType)) {
|
|
510
|
+
seen.add(authType);
|
|
511
|
+
uniqueAuthTypes.push(authType);
|
|
512
|
+
}
|
|
513
|
+
}
|
|
514
|
+
const orderedAuthTypes = [];
|
|
515
|
+
if (uniqueAuthTypes.includes("qwen-oauth" /* QWEN_OAUTH */)) {
|
|
516
|
+
orderedAuthTypes.push("qwen-oauth" /* QWEN_OAUTH */);
|
|
517
|
+
}
|
|
518
|
+
for (const authType of uniqueAuthTypes) {
|
|
519
|
+
if (authType !== "qwen-oauth" /* QWEN_OAUTH */) {
|
|
520
|
+
orderedAuthTypes.push(authType);
|
|
521
|
+
}
|
|
522
|
+
}
|
|
523
|
+
const runtimeOption = this.getRuntimeModelOption();
|
|
524
|
+
const allModels = [];
|
|
525
|
+
for (const authType of orderedAuthTypes) {
|
|
526
|
+
if (runtimeOption && runtimeOption.authType === authType) {
|
|
527
|
+
allModels.push(runtimeOption);
|
|
528
|
+
}
|
|
529
|
+
allModels.push(...this.modelRegistry.getModelsForAuthType(authType));
|
|
530
|
+
}
|
|
531
|
+
return allModels;
|
|
532
|
+
}
|
|
533
|
+
/**
|
|
534
|
+
* Check if a model exists for the given authType
|
|
535
|
+
*/
|
|
536
|
+
hasModel(authType, modelId) {
|
|
537
|
+
return this.modelRegistry.hasModel(authType, modelId);
|
|
538
|
+
}
|
|
539
|
+
/**
|
|
540
|
+
* Get a fully resolved provider model config for the given authType/modelId.
|
|
541
|
+
* Returns undefined for raw runtime models that are not present in the registry.
|
|
542
|
+
*/
|
|
543
|
+
getResolvedModel(authType, modelId, baseUrl) {
|
|
544
|
+
return this.modelRegistry.getModel(authType, modelId, baseUrl);
|
|
545
|
+
}
|
|
546
|
+
/**
|
|
547
|
+
* Get the display name for a model by its id.
|
|
548
|
+
* Looks up the model in the registry using the current authType and returns
|
|
549
|
+
* its resolved name. Falls back to the raw model id when the model is not
|
|
550
|
+
* found in the registry (e.g. runtime models or unknown models).
|
|
551
|
+
*/
|
|
552
|
+
getModelDisplayName(modelId) {
|
|
553
|
+
if (!this.currentAuthType) return modelId;
|
|
554
|
+
const resolved = (this.currentRegistryBaseUrl !== void 0 ? this.modelRegistry.getModel(
|
|
555
|
+
this.currentAuthType,
|
|
556
|
+
modelId,
|
|
557
|
+
this.currentRegistryBaseUrl
|
|
558
|
+
) : void 0) ?? this.modelRegistry.getModel(this.currentAuthType, modelId);
|
|
559
|
+
return resolved?.name ?? modelId;
|
|
560
|
+
}
|
|
561
|
+
/**
|
|
562
|
+
* Set model programmatically (e.g., VLM auto-switch, fallback).
|
|
563
|
+
* Supports both registry models and raw model IDs.
|
|
564
|
+
*/
|
|
565
|
+
async setModel(newModel, metadata) {
|
|
566
|
+
if (this.currentAuthType === "qwen-oauth" /* QWEN_OAUTH */ && newModel === DEFAULT_QWEN_MODEL) {
|
|
567
|
+
this.strictModelProviderSelection = false;
|
|
568
|
+
this.currentRegistryBaseUrl = void 0;
|
|
569
|
+
this._generationConfig.model = newModel;
|
|
570
|
+
this.generationConfigSources["model"] = {
|
|
571
|
+
kind: "programmatic",
|
|
572
|
+
detail: metadata?.reason || "setModel"
|
|
573
|
+
};
|
|
574
|
+
this.applyRawModelDerivedDefaults(newModel);
|
|
575
|
+
if (this.onModelChange) {
|
|
576
|
+
await this.onModelChange("qwen-oauth" /* QWEN_OAUTH */, false);
|
|
577
|
+
}
|
|
578
|
+
return;
|
|
579
|
+
}
|
|
580
|
+
if (this.currentAuthType && this.modelRegistry.hasModel(this.currentAuthType, newModel)) {
|
|
581
|
+
await this.switchModel(this.currentAuthType, newModel);
|
|
582
|
+
return;
|
|
583
|
+
}
|
|
584
|
+
const rollbackSnapshot = this.createStateSnapshotForRollback();
|
|
585
|
+
try {
|
|
586
|
+
this.strictModelProviderSelection = false;
|
|
587
|
+
this.currentRegistryBaseUrl = void 0;
|
|
588
|
+
this._generationConfig.model = newModel;
|
|
589
|
+
this.generationConfigSources["model"] = {
|
|
590
|
+
kind: "programmatic",
|
|
591
|
+
detail: metadata?.reason || "setModel"
|
|
592
|
+
};
|
|
593
|
+
this.applyRawModelDerivedDefaults(newModel);
|
|
594
|
+
if (this.onModelChange && this.currentAuthType) {
|
|
595
|
+
await this.onModelChange(this.currentAuthType, true);
|
|
596
|
+
}
|
|
597
|
+
} catch (error) {
|
|
598
|
+
this.rollbackToStateSnapshot(rollbackSnapshot);
|
|
599
|
+
throw error;
|
|
600
|
+
}
|
|
601
|
+
}
|
|
602
|
+
/**
|
|
603
|
+
* Raw model switches keep the current credentials, but model-derived
|
|
604
|
+
* generation defaults must follow the new model. Otherwise a switch from a
|
|
605
|
+
* multimodal registry model to a text-only raw model can keep stale image
|
|
606
|
+
* support and send unsupported inline media.
|
|
607
|
+
*/
|
|
608
|
+
applyRawModelDerivedDefaults(modelId) {
|
|
609
|
+
if (this.shouldUpdateModelDerivedDefault("modalities")) {
|
|
610
|
+
this._generationConfig.modalities = defaultModalities(modelId);
|
|
611
|
+
this.generationConfigSources["modalities"] = {
|
|
612
|
+
kind: "computed",
|
|
613
|
+
detail: "auto-detected from model"
|
|
614
|
+
};
|
|
615
|
+
}
|
|
616
|
+
if (this.shouldUpdateModelDerivedDefault("contextWindowSize")) {
|
|
617
|
+
this._generationConfig.contextWindowSize = tokenLimit(modelId, "input");
|
|
618
|
+
this.generationConfigSources["contextWindowSize"] = {
|
|
619
|
+
kind: "computed",
|
|
620
|
+
detail: "auto-detected from model"
|
|
621
|
+
};
|
|
622
|
+
}
|
|
623
|
+
}
|
|
624
|
+
shouldUpdateModelDerivedDefault(field) {
|
|
625
|
+
const source = this.generationConfigSources[field];
|
|
626
|
+
return source === void 0 || source.kind === "computed" || source.kind === "default" || source.kind === "modelProviders" || source.kind === "programmatic" || source.kind === "unknown";
|
|
627
|
+
}
|
|
628
|
+
/**
|
|
629
|
+
* Switch model (and optionally authType).
|
|
630
|
+
* Supports both registry-backed models and RuntimeModelSnapshots.
|
|
631
|
+
*
|
|
632
|
+
* For runtime models, the modelId can be:
|
|
633
|
+
* - A RuntimeModelSnapshot ID (format: `$runtime|${authType}|${modelId}`)
|
|
634
|
+
* - With explicit `$runtime|` prefix (format: `$runtime|${authType}|${modelId}`)
|
|
635
|
+
*
|
|
636
|
+
* When called from ACP integration, the modelId has already been parsed
|
|
637
|
+
* by parseAcpModelOption, which strips any (${authType}) suffix.
|
|
638
|
+
*/
|
|
639
|
+
async switchModel(authType, modelId, options) {
|
|
640
|
+
const runtimeModelSnapshotId = this.extractRuntimeModelSnapshotId(modelId);
|
|
641
|
+
if (runtimeModelSnapshotId) {
|
|
642
|
+
await this.switchToRuntimeModel(runtimeModelSnapshotId);
|
|
643
|
+
return;
|
|
644
|
+
}
|
|
645
|
+
const rollbackSnapshot = this.createStateSnapshotForRollback();
|
|
646
|
+
if (authType === "qwen-oauth" /* QWEN_OAUTH */ && options?.requireCachedCredentials) {
|
|
647
|
+
this.requireCachedQwenCredentialsOnce = true;
|
|
648
|
+
}
|
|
649
|
+
try {
|
|
650
|
+
const isAuthTypeChange = authType !== this.currentAuthType;
|
|
651
|
+
this.currentAuthType = authType;
|
|
652
|
+
const model = this.modelRegistry.getModel(
|
|
653
|
+
authType,
|
|
654
|
+
modelId,
|
|
655
|
+
options?.baseUrl
|
|
656
|
+
);
|
|
657
|
+
if (!model) {
|
|
658
|
+
throw new Error(
|
|
659
|
+
`Model '${modelId}' not found for authType '${authType}'`
|
|
660
|
+
);
|
|
661
|
+
}
|
|
662
|
+
if (model.imageOnly || model.voiceOnly) {
|
|
663
|
+
throw new Error(
|
|
664
|
+
`${model.imageOnly ? "Image" : "Voice"}-only model '${modelId}' cannot be used as the primary model`
|
|
665
|
+
);
|
|
666
|
+
}
|
|
667
|
+
const previousModelId = rollbackSnapshot.generationConfig.model || "";
|
|
668
|
+
const previousModel = !isAuthTypeChange && previousModelId ? this.modelRegistry.getModel(
|
|
669
|
+
authType,
|
|
670
|
+
previousModelId,
|
|
671
|
+
rollbackSnapshot.currentRegistryBaseUrl
|
|
672
|
+
) ?? this.modelRegistry.getModel(authType, previousModelId) : void 0;
|
|
673
|
+
const canReusePreviousApiKey = authType !== "qwen-oauth" /* QWEN_OAUTH */ && !isAuthTypeChange && !!rollbackSnapshot.generationConfig.apiKey && !!model.envKey && previousModel?.envKey === model.envKey && previousModel.baseUrl === model.baseUrl;
|
|
674
|
+
const previousApiKey = canReusePreviousApiKey ? rollbackSnapshot.generationConfig.apiKey : void 0;
|
|
675
|
+
const previousApiKeySource = canReusePreviousApiKey ? rollbackSnapshot.generationConfigSources["apiKey"] : void 0;
|
|
676
|
+
this.applyResolvedModelDefaults(model);
|
|
677
|
+
if (!this._generationConfig.apiKey && previousApiKey) {
|
|
678
|
+
this._generationConfig.apiKey = previousApiKey;
|
|
679
|
+
if (previousApiKeySource) {
|
|
680
|
+
this.generationConfigSources["apiKey"] = _ModelsConfig.deepClone(previousApiKeySource);
|
|
681
|
+
}
|
|
682
|
+
}
|
|
683
|
+
this.activeRuntimeModelSnapshotId = void 0;
|
|
684
|
+
const requiresRefresh = isAuthTypeChange ? true : this.checkRequiresRefresh(previousModelId);
|
|
685
|
+
if (this.onModelChange) {
|
|
686
|
+
await this.onModelChange(authType, requiresRefresh);
|
|
687
|
+
}
|
|
688
|
+
} catch (error) {
|
|
689
|
+
this.rollbackToStateSnapshot(rollbackSnapshot);
|
|
690
|
+
throw error;
|
|
691
|
+
}
|
|
692
|
+
}
|
|
693
|
+
/**
|
|
694
|
+
* Build a RuntimeModelSnapshot ID from authType and modelId.
|
|
695
|
+
* The format is: `$runtime|${authType}|${modelId}`
|
|
696
|
+
*
|
|
697
|
+
* This is the canonical way to construct snapshot IDs, ensuring
|
|
698
|
+
* consistency across creation and lookup.
|
|
699
|
+
*
|
|
700
|
+
* @param authType - The authentication type
|
|
701
|
+
* @param modelId - The model ID
|
|
702
|
+
* @returns The snapshot ID in format `$runtime|${authType}|${modelId}`
|
|
703
|
+
*/
|
|
704
|
+
buildRuntimeModelSnapshotId(authType, modelId) {
|
|
705
|
+
return buildRuntimeSnapshotId(authType, modelId);
|
|
706
|
+
}
|
|
707
|
+
/**
|
|
708
|
+
* Extract RuntimeModelSnapshot ID from modelId if it's a runtime model reference.
|
|
709
|
+
*
|
|
710
|
+
* Supports the following formats:
|
|
711
|
+
* - Direct snapshot ID: `$runtime|${authType}|${modelId}` → returns as-is if exists in Map
|
|
712
|
+
* - Direct snapshot ID match: returns if exists in Map
|
|
713
|
+
*
|
|
714
|
+
* Note: When called from ACP integration via setModel, the modelId has already
|
|
715
|
+
* been parsed by parseAcpModelOption which strips any (${authType}) suffix.
|
|
716
|
+
* So we don't need to handle ACP format here - the ACP layer handles that.
|
|
717
|
+
*
|
|
718
|
+
* @param modelId - The model ID to parse
|
|
719
|
+
* @returns The RuntimeModelSnapshot ID if found, undefined otherwise
|
|
720
|
+
*/
|
|
721
|
+
extractRuntimeModelSnapshotId(modelId) {
|
|
722
|
+
if (modelId.startsWith(RUNTIME_SNAPSHOT_PREFIX)) {
|
|
723
|
+
if (this.runtimeModelSnapshots.has(modelId)) {
|
|
724
|
+
return modelId;
|
|
725
|
+
}
|
|
726
|
+
return void 0;
|
|
727
|
+
}
|
|
728
|
+
if (this.runtimeModelSnapshots.has(modelId)) {
|
|
729
|
+
return modelId;
|
|
730
|
+
}
|
|
731
|
+
return void 0;
|
|
732
|
+
}
|
|
733
|
+
/**
|
|
734
|
+
* Get generation config for ContentGenerator creation
|
|
735
|
+
*/
|
|
736
|
+
getGenerationConfig() {
|
|
737
|
+
return this._generationConfig;
|
|
738
|
+
}
|
|
739
|
+
/**
|
|
740
|
+
* Get generation config sources for debugging/UI
|
|
741
|
+
*/
|
|
742
|
+
getGenerationConfigSources() {
|
|
743
|
+
return this.generationConfigSources;
|
|
744
|
+
}
|
|
745
|
+
/**
|
|
746
|
+
* Merge settings generation config, preserving existing values.
|
|
747
|
+
* Used when provider-sourced config is cleared but settings should still apply.
|
|
748
|
+
*/
|
|
749
|
+
mergeSettingsGenerationConfig(settingsGenerationConfig) {
|
|
750
|
+
if (!settingsGenerationConfig) {
|
|
751
|
+
return;
|
|
752
|
+
}
|
|
753
|
+
for (const field of MODEL_GENERATION_CONFIG_FIELDS) {
|
|
754
|
+
if (!(field in this._generationConfig) && field in settingsGenerationConfig) {
|
|
755
|
+
this._generationConfig[field] = settingsGenerationConfig[field];
|
|
756
|
+
this.generationConfigSources[field] = {
|
|
757
|
+
kind: "settings",
|
|
758
|
+
detail: `model.generationConfig.${field}`
|
|
759
|
+
};
|
|
760
|
+
}
|
|
761
|
+
}
|
|
762
|
+
}
|
|
763
|
+
/**
|
|
764
|
+
* Update credentials in generation config.
|
|
765
|
+
* Sets a flag to prevent syncAfterAuthRefresh from overriding these credentials.
|
|
766
|
+
*
|
|
767
|
+
* When credentials are manually set, we clear all provider-sourced configuration
|
|
768
|
+
* to maintain provider atomicity (either fully applied or not at all).
|
|
769
|
+
* Other layers (CLI, env, settings, defaults) will participate in resolve.
|
|
770
|
+
*
|
|
771
|
+
* Also updates or creates a RuntimeModelSnapshot when credentials form a complete config
|
|
772
|
+
* for a model not in the registry. This allows the runtime model to be reused later.
|
|
773
|
+
*
|
|
774
|
+
* @param settingsGenerationConfig Optional generation config from settings.json
|
|
775
|
+
* to merge after clearing provider-sourced config.
|
|
776
|
+
* This ensures settings.model.generationConfig fields
|
|
777
|
+
* (e.g., samplingParams, timeout) are preserved.
|
|
778
|
+
*/
|
|
779
|
+
updateCredentials(credentials, settingsGenerationConfig) {
|
|
780
|
+
if (credentials.apiKey || credentials.baseUrl || credentials.model) {
|
|
781
|
+
this.hasManualCredentials = true;
|
|
782
|
+
this.currentRegistryBaseUrl = void 0;
|
|
783
|
+
this.clearProviderSourcedConfig();
|
|
784
|
+
}
|
|
785
|
+
if (credentials.apiKey) {
|
|
786
|
+
this._generationConfig.apiKey = credentials.apiKey;
|
|
787
|
+
this.generationConfigSources["apiKey"] = {
|
|
788
|
+
kind: "programmatic",
|
|
789
|
+
detail: "updateCredentials"
|
|
790
|
+
};
|
|
791
|
+
}
|
|
792
|
+
if (credentials.baseUrl) {
|
|
793
|
+
this._generationConfig.baseUrl = credentials.baseUrl;
|
|
794
|
+
this.generationConfigSources["baseUrl"] = {
|
|
795
|
+
kind: "programmatic",
|
|
796
|
+
detail: "updateCredentials"
|
|
797
|
+
};
|
|
798
|
+
}
|
|
799
|
+
if (credentials.model) {
|
|
800
|
+
this._generationConfig.model = credentials.model;
|
|
801
|
+
this.generationConfigSources["model"] = {
|
|
802
|
+
kind: "programmatic",
|
|
803
|
+
detail: "updateCredentials"
|
|
804
|
+
};
|
|
805
|
+
}
|
|
806
|
+
this.strictModelProviderSelection = false;
|
|
807
|
+
this._generationConfig.apiKeyEnvKey = void 0;
|
|
808
|
+
if (settingsGenerationConfig) {
|
|
809
|
+
this.mergeSettingsGenerationConfig(settingsGenerationConfig);
|
|
810
|
+
}
|
|
811
|
+
this.syncRuntimeModelSnapshotWithCredentials();
|
|
812
|
+
}
|
|
813
|
+
/**
|
|
814
|
+
* Sync RuntimeModelSnapshot with current credentials.
|
|
815
|
+
*
|
|
816
|
+
* Creates or updates a RuntimeModelSnapshot when current credentials form a complete
|
|
817
|
+
* configuration for a model not in the registry. This enables:
|
|
818
|
+
* - Reusing the runtime model configuration later
|
|
819
|
+
* - Showing the runtime model as an available option in model lists
|
|
820
|
+
*
|
|
821
|
+
* Only creates snapshots for models NOT in the registry (to avoid duplication).
|
|
822
|
+
*/
|
|
823
|
+
syncRuntimeModelSnapshotWithCredentials() {
|
|
824
|
+
const currentAuthType = this.currentAuthType;
|
|
825
|
+
const { model, apiKey, baseUrl } = this._generationConfig;
|
|
826
|
+
if (!model || !currentAuthType || !apiKey || !baseUrl) {
|
|
827
|
+
return;
|
|
828
|
+
}
|
|
829
|
+
if (this.modelRegistry.hasModel(currentAuthType, model, baseUrl)) {
|
|
830
|
+
return;
|
|
831
|
+
}
|
|
832
|
+
if (this.activeRuntimeModelSnapshotId && this.runtimeModelSnapshots.has(this.activeRuntimeModelSnapshotId)) {
|
|
833
|
+
const snapshot = this.runtimeModelSnapshots.get(
|
|
834
|
+
this.activeRuntimeModelSnapshotId
|
|
835
|
+
);
|
|
836
|
+
snapshot.apiKey = apiKey;
|
|
837
|
+
snapshot.baseUrl = baseUrl;
|
|
838
|
+
snapshot.modelId = model;
|
|
839
|
+
const newSnapshotId = this.buildRuntimeModelSnapshotId(
|
|
840
|
+
snapshot.authType,
|
|
841
|
+
snapshot.modelId
|
|
842
|
+
);
|
|
843
|
+
if (newSnapshotId !== snapshot.id) {
|
|
844
|
+
this.runtimeModelSnapshots.delete(snapshot.id);
|
|
845
|
+
snapshot.id = newSnapshotId;
|
|
846
|
+
this.runtimeModelSnapshots.set(newSnapshotId, snapshot);
|
|
847
|
+
this.activeRuntimeModelSnapshotId = newSnapshotId;
|
|
848
|
+
}
|
|
849
|
+
snapshot.createdAt = Date.now();
|
|
850
|
+
} else {
|
|
851
|
+
this.detectAndCaptureRuntimeModel();
|
|
852
|
+
}
|
|
853
|
+
}
|
|
854
|
+
/**
|
|
855
|
+
* Clear configuration fields that were sourced from modelProviders.
|
|
856
|
+
* This ensures provider config atomicity when user manually sets credentials.
|
|
857
|
+
* Other layers (CLI, env, settings, defaults) will participate in resolve.
|
|
858
|
+
*/
|
|
859
|
+
clearProviderSourcedConfig() {
|
|
860
|
+
for (const field of PROVIDER_SOURCED_FIELDS) {
|
|
861
|
+
const source = this.generationConfigSources[field];
|
|
862
|
+
if (source?.kind === "modelProviders") {
|
|
863
|
+
delete this._generationConfig[field];
|
|
864
|
+
delete this.generationConfigSources[field];
|
|
865
|
+
}
|
|
866
|
+
}
|
|
867
|
+
}
|
|
868
|
+
/**
|
|
869
|
+
* Get whether strict model provider selection is enabled
|
|
870
|
+
*/
|
|
871
|
+
isStrictModelProviderSelection() {
|
|
872
|
+
return this.strictModelProviderSelection;
|
|
873
|
+
}
|
|
874
|
+
/**
|
|
875
|
+
* Reset strict model provider selection flag
|
|
876
|
+
*/
|
|
877
|
+
resetStrictModelProviderSelection() {
|
|
878
|
+
this.strictModelProviderSelection = false;
|
|
879
|
+
}
|
|
880
|
+
/**
|
|
881
|
+
* Check and consume the one-shot cached credentials flag
|
|
882
|
+
*/
|
|
883
|
+
consumeRequireCachedCredentialsFlag() {
|
|
884
|
+
const value = this.requireCachedQwenCredentialsOnce;
|
|
885
|
+
this.requireCachedQwenCredentialsOnce = false;
|
|
886
|
+
return value;
|
|
887
|
+
}
|
|
888
|
+
/**
|
|
889
|
+
* Apply resolved model config to generation config
|
|
890
|
+
*/
|
|
891
|
+
applyResolvedModelDefaults(model) {
|
|
892
|
+
this.strictModelProviderSelection = true;
|
|
893
|
+
this.currentRegistryBaseUrl = model.registryBaseUrl ?? null;
|
|
894
|
+
this.hasManualCredentials = false;
|
|
895
|
+
this._generationConfig.model = model.id;
|
|
896
|
+
this.generationConfigSources["model"] = {
|
|
897
|
+
kind: "modelProviders",
|
|
898
|
+
authType: model.authType,
|
|
899
|
+
modelId: model.id,
|
|
900
|
+
detail: "model.id"
|
|
901
|
+
};
|
|
902
|
+
if (this.currentAuthType === "qwen-oauth" /* QWEN_OAUTH */) {
|
|
903
|
+
this._generationConfig.apiKey = "QWEN_OAUTH_DYNAMIC_TOKEN";
|
|
904
|
+
this.generationConfigSources["apiKey"] = {
|
|
905
|
+
kind: "computed",
|
|
906
|
+
detail: "Qwen OAuth placeholder token"
|
|
907
|
+
};
|
|
908
|
+
this._generationConfig.apiKeyEnvKey = void 0;
|
|
909
|
+
delete this.generationConfigSources["apiKeyEnvKey"];
|
|
910
|
+
} else {
|
|
911
|
+
this._generationConfig.apiKey = void 0;
|
|
912
|
+
this._generationConfig.apiKeyEnvKey = void 0;
|
|
913
|
+
}
|
|
914
|
+
if (model.envKey !== void 0) {
|
|
915
|
+
const apiKey = process2.env[model.envKey];
|
|
916
|
+
if (apiKey) {
|
|
917
|
+
this._generationConfig.apiKey = apiKey;
|
|
918
|
+
this.generationConfigSources["apiKey"] = {
|
|
919
|
+
kind: "env",
|
|
920
|
+
envKey: model.envKey,
|
|
921
|
+
via: {
|
|
922
|
+
kind: "modelProviders",
|
|
923
|
+
authType: model.authType,
|
|
924
|
+
modelId: model.id,
|
|
925
|
+
detail: "envKey"
|
|
926
|
+
}
|
|
927
|
+
};
|
|
928
|
+
} else {
|
|
929
|
+
debugLogger2.debug(
|
|
930
|
+
`No API key found for model "${model.id}": process.env["${model.envKey}"] is ${apiKey === "" ? "empty string" : "not set"}. Run /auth or set ${model.envKey} in your environment.`
|
|
931
|
+
);
|
|
932
|
+
}
|
|
933
|
+
this._generationConfig.apiKeyEnvKey = model.envKey;
|
|
934
|
+
this.generationConfigSources["apiKeyEnvKey"] = {
|
|
935
|
+
kind: "modelProviders",
|
|
936
|
+
authType: model.authType,
|
|
937
|
+
modelId: model.id,
|
|
938
|
+
detail: "envKey"
|
|
939
|
+
};
|
|
940
|
+
}
|
|
941
|
+
this._generationConfig.baseUrl = model.baseUrl;
|
|
942
|
+
this.generationConfigSources["baseUrl"] = {
|
|
943
|
+
kind: "modelProviders",
|
|
944
|
+
authType: model.authType,
|
|
945
|
+
modelId: model.id,
|
|
946
|
+
detail: "baseUrl"
|
|
947
|
+
};
|
|
948
|
+
const gc = model.generationConfig;
|
|
949
|
+
for (const field of MODEL_GENERATION_CONFIG_FIELDS) {
|
|
950
|
+
this._generationConfig[field] = gc[field];
|
|
951
|
+
this.generationConfigSources[field] = {
|
|
952
|
+
kind: "modelProviders",
|
|
953
|
+
authType: model.authType,
|
|
954
|
+
modelId: model.id,
|
|
955
|
+
detail: `generationConfig.${field}`
|
|
956
|
+
};
|
|
957
|
+
}
|
|
958
|
+
if (gc.contextWindowSize === void 0) {
|
|
959
|
+
this._generationConfig.contextWindowSize = tokenLimit(model.id, "input");
|
|
960
|
+
this.generationConfigSources["contextWindowSize"] = {
|
|
961
|
+
kind: "computed",
|
|
962
|
+
detail: "auto-detected from model"
|
|
963
|
+
};
|
|
964
|
+
}
|
|
965
|
+
if (gc.modalities === void 0) {
|
|
966
|
+
this._generationConfig.modalities = defaultModalities(model.id);
|
|
967
|
+
this.generationConfigSources["modalities"] = {
|
|
968
|
+
kind: "computed",
|
|
969
|
+
detail: "auto-detected from model"
|
|
970
|
+
};
|
|
971
|
+
}
|
|
972
|
+
}
|
|
973
|
+
/**
|
|
974
|
+
* Check if model switch requires ContentGenerator refresh.
|
|
975
|
+
*
|
|
976
|
+
* Note: This method is ONLY called by switchModel() for same-authType model switches.
|
|
977
|
+
* Cross-authType switches use switchModel(authType, modelId), which always requires full refresh.
|
|
978
|
+
*
|
|
979
|
+
* When this method is called:
|
|
980
|
+
* - this.currentAuthType is already the target authType
|
|
981
|
+
* - We're checking if switching between two models within the SAME authType needs refresh
|
|
982
|
+
*
|
|
983
|
+
* Examples:
|
|
984
|
+
* - Qwen OAuth: coder-model switches (same authType, hot-update safe)
|
|
985
|
+
* - OpenAI: model-a -> model-b with same envKey (same authType, hot-update safe)
|
|
986
|
+
* - OpenAI: gpt-4 -> deepseek-chat with different envKey (same authType, needs refresh)
|
|
987
|
+
*
|
|
988
|
+
* Cross-authType scenarios:
|
|
989
|
+
* - OpenAI -> Qwen OAuth: handled by switchModel(authType, modelId), always refreshes
|
|
990
|
+
* - Qwen OAuth -> OpenAI: handled by switchModel(authType, modelId), always refreshes
|
|
991
|
+
*/
|
|
992
|
+
checkRequiresRefresh(previousModelId) {
|
|
993
|
+
const authType = this.currentAuthType;
|
|
994
|
+
if (!authType) {
|
|
995
|
+
return true;
|
|
996
|
+
}
|
|
997
|
+
if (authType === "qwen-oauth" /* QWEN_OAUTH */) {
|
|
998
|
+
return false;
|
|
999
|
+
}
|
|
1000
|
+
const currentModel = this.modelRegistry.getModel(
|
|
1001
|
+
authType,
|
|
1002
|
+
this._generationConfig.model || "",
|
|
1003
|
+
this._generationConfig.baseUrl || void 0
|
|
1004
|
+
);
|
|
1005
|
+
const previousModel = this.modelRegistry.getModel(
|
|
1006
|
+
authType,
|
|
1007
|
+
previousModelId
|
|
1008
|
+
);
|
|
1009
|
+
if (!previousModel || !currentModel) {
|
|
1010
|
+
return true;
|
|
1011
|
+
}
|
|
1012
|
+
const criticalFieldsChanged = previousModel.envKey !== currentModel.envKey || previousModel.baseUrl !== currentModel.baseUrl;
|
|
1013
|
+
if (criticalFieldsChanged) {
|
|
1014
|
+
return true;
|
|
1015
|
+
}
|
|
1016
|
+
return false;
|
|
1017
|
+
}
|
|
1018
|
+
/**
|
|
1019
|
+
* Sync state after auth refresh with fallback strategy:
|
|
1020
|
+
* 1. If modelId can be found in modelRegistry, use the config from modelRegistry.
|
|
1021
|
+
* 2. Otherwise, if existing credentials exist in resolved generationConfig from other sources
|
|
1022
|
+
* (not modelProviders), preserve them and update authType/modelId only.
|
|
1023
|
+
* 3. Otherwise, fall back to default model for the authType.
|
|
1024
|
+
* 4. If no default is available, leave the generationConfig incomplete and let
|
|
1025
|
+
* resolveContentGeneratorConfigWithSources throw exceptions as expected.
|
|
1026
|
+
*/
|
|
1027
|
+
syncAfterAuthRefresh(authType, modelId, providerBaseUrlOverride) {
|
|
1028
|
+
const previousAuthType = this.currentAuthType;
|
|
1029
|
+
const providerBaseUrl = providerBaseUrlOverride ?? (previousAuthType === authType && this.currentRegistryBaseUrl !== void 0 ? this.currentRegistryBaseUrl : this.generationConfigSources["baseUrl"]?.kind === "modelProviders" ? this._generationConfig.baseUrl : void 0);
|
|
1030
|
+
const resolved = modelId ? this.modelRegistry.getModel(authType, modelId, providerBaseUrl) ?? this.modelRegistry.getModel(authType, modelId) : void 0;
|
|
1031
|
+
if (resolved?.imageOnly || resolved?.voiceOnly) {
|
|
1032
|
+
throw new Error(
|
|
1033
|
+
`${resolved.imageOnly ? "Image" : "Voice"}-only model '${modelId}' cannot be used as the primary model`
|
|
1034
|
+
);
|
|
1035
|
+
}
|
|
1036
|
+
this.strictModelProviderSelection = false;
|
|
1037
|
+
this.currentAuthType = authType;
|
|
1038
|
+
if (resolved) {
|
|
1039
|
+
const hasBeenApplied = this.generationConfigSources["baseUrl"]?.kind === "modelProviders";
|
|
1040
|
+
const isProviderChanged = hasBeenApplied && (this._generationConfig.apiKeyEnvKey !== resolved.envKey || this._generationConfig.baseUrl !== resolved.baseUrl);
|
|
1041
|
+
const isUnchanged = previousAuthType === authType && this._generationConfig.model === modelId && !isProviderChanged;
|
|
1042
|
+
const savedApiKey = isUnchanged ? this._generationConfig.apiKey : void 0;
|
|
1043
|
+
const savedApiKeySource = isUnchanged ? this.generationConfigSources["apiKey"] ? { ...this.generationConfigSources["apiKey"] } : void 0 : void 0;
|
|
1044
|
+
const baseUrlSource2 = this.generationConfigSources["baseUrl"];
|
|
1045
|
+
const shouldPreserveResolvedBaseUrl = isUnchanged && !!this._generationConfig.baseUrl && (baseUrlSource2?.kind === "cli" || baseUrlSource2?.kind === "env" || baseUrlSource2?.kind === "settings");
|
|
1046
|
+
const savedBaseUrl = shouldPreserveResolvedBaseUrl ? this._generationConfig.baseUrl : void 0;
|
|
1047
|
+
const savedBaseUrlSource = shouldPreserveResolvedBaseUrl ? baseUrlSource2 ? { ...baseUrlSource2 } : void 0 : void 0;
|
|
1048
|
+
this.applyResolvedModelDefaults(resolved);
|
|
1049
|
+
if (isUnchanged && !this._generationConfig.apiKey && savedApiKey) {
|
|
1050
|
+
this._generationConfig.apiKey = savedApiKey;
|
|
1051
|
+
if (savedApiKeySource) {
|
|
1052
|
+
this.generationConfigSources["apiKey"] = savedApiKeySource;
|
|
1053
|
+
}
|
|
1054
|
+
}
|
|
1055
|
+
if (savedBaseUrl) {
|
|
1056
|
+
this._generationConfig.baseUrl = savedBaseUrl;
|
|
1057
|
+
if (savedBaseUrlSource) {
|
|
1058
|
+
this.generationConfigSources["baseUrl"] = savedBaseUrlSource;
|
|
1059
|
+
}
|
|
1060
|
+
}
|
|
1061
|
+
this.strictModelProviderSelection = true;
|
|
1062
|
+
this.activeRuntimeModelSnapshotId = void 0;
|
|
1063
|
+
return;
|
|
1064
|
+
}
|
|
1065
|
+
const apiKeySource = this.generationConfigSources["apiKey"];
|
|
1066
|
+
const baseUrlSource = this.generationConfigSources["baseUrl"];
|
|
1067
|
+
const hasExistingCredentials = this._generationConfig.apiKey && apiKeySource?.kind !== "modelProviders" || this._generationConfig.baseUrl && baseUrlSource?.kind !== "modelProviders";
|
|
1068
|
+
const isAuthTypeChange = previousAuthType !== authType;
|
|
1069
|
+
const shouldPreserveCredentials = !isAuthTypeChange && (modelId === void 0 || !this.modelRegistry.hasModel(authType, modelId)) && (this.hasManualCredentials || hasExistingCredentials);
|
|
1070
|
+
if (shouldPreserveCredentials) {
|
|
1071
|
+
this.currentRegistryBaseUrl = void 0;
|
|
1072
|
+
if (modelId) {
|
|
1073
|
+
this._generationConfig.model = modelId;
|
|
1074
|
+
if (!this.generationConfigSources["model"]) {
|
|
1075
|
+
this.generationConfigSources["model"] = {
|
|
1076
|
+
kind: "programmatic",
|
|
1077
|
+
detail: "auth refresh (preserved credentials)"
|
|
1078
|
+
};
|
|
1079
|
+
}
|
|
1080
|
+
}
|
|
1081
|
+
return;
|
|
1082
|
+
}
|
|
1083
|
+
const defaultModel = this.modelRegistry.getDefaultModelForAuthType(authType);
|
|
1084
|
+
if (defaultModel) {
|
|
1085
|
+
this.applyResolvedModelDefaults(defaultModel);
|
|
1086
|
+
this.activeRuntimeModelSnapshotId = void 0;
|
|
1087
|
+
return;
|
|
1088
|
+
}
|
|
1089
|
+
if (modelId) {
|
|
1090
|
+
this.currentRegistryBaseUrl = void 0;
|
|
1091
|
+
this._generationConfig.model = modelId;
|
|
1092
|
+
if (!this.generationConfigSources["model"]) {
|
|
1093
|
+
this.generationConfigSources["model"] = {
|
|
1094
|
+
kind: "programmatic",
|
|
1095
|
+
detail: "auth refresh (no default model)"
|
|
1096
|
+
};
|
|
1097
|
+
}
|
|
1098
|
+
}
|
|
1099
|
+
}
|
|
1100
|
+
/**
|
|
1101
|
+
* Update callback for model changes
|
|
1102
|
+
*/
|
|
1103
|
+
setOnModelChange(callback) {
|
|
1104
|
+
this.onModelChange = callback;
|
|
1105
|
+
}
|
|
1106
|
+
/**
|
|
1107
|
+
* Detect and capture RuntimeModelSnapshot during initialization.
|
|
1108
|
+
*
|
|
1109
|
+
* Checks if the current configuration represents a runtime model (not from
|
|
1110
|
+
* modelProviders registry) and captures it as a RuntimeModelSnapshot.
|
|
1111
|
+
*
|
|
1112
|
+
* This enables runtime models to persist across sessions and appear in model lists.
|
|
1113
|
+
*
|
|
1114
|
+
* @returns Created snapshot ID, or undefined if current config is a registry model
|
|
1115
|
+
*/
|
|
1116
|
+
detectAndCaptureRuntimeModel() {
|
|
1117
|
+
const {
|
|
1118
|
+
model: currentModel,
|
|
1119
|
+
apiKey,
|
|
1120
|
+
baseUrl,
|
|
1121
|
+
apiKeyEnvKey,
|
|
1122
|
+
...generationConfig
|
|
1123
|
+
} = this._generationConfig;
|
|
1124
|
+
const currentAuthType = this.currentAuthType;
|
|
1125
|
+
if (!currentModel || !currentAuthType) {
|
|
1126
|
+
return void 0;
|
|
1127
|
+
}
|
|
1128
|
+
if (this.modelRegistry.hasModel(currentAuthType, currentModel, baseUrl)) {
|
|
1129
|
+
this.clearRuntimeModelSnapshotForAuthType(currentAuthType);
|
|
1130
|
+
return void 0;
|
|
1131
|
+
}
|
|
1132
|
+
const hasValidCredentials = this._generationConfig.apiKey && this._generationConfig.baseUrl;
|
|
1133
|
+
if (!hasValidCredentials) {
|
|
1134
|
+
return void 0;
|
|
1135
|
+
}
|
|
1136
|
+
const snapshotId = this.buildRuntimeModelSnapshotId(
|
|
1137
|
+
currentAuthType,
|
|
1138
|
+
currentModel
|
|
1139
|
+
);
|
|
1140
|
+
const snapshot = {
|
|
1141
|
+
id: snapshotId,
|
|
1142
|
+
authType: currentAuthType,
|
|
1143
|
+
modelId: currentModel,
|
|
1144
|
+
apiKey,
|
|
1145
|
+
baseUrl,
|
|
1146
|
+
apiKeyEnvKey,
|
|
1147
|
+
generationConfig,
|
|
1148
|
+
sources: { ...this.generationConfigSources },
|
|
1149
|
+
createdAt: Date.now()
|
|
1150
|
+
};
|
|
1151
|
+
this.runtimeModelSnapshots.set(snapshotId, snapshot);
|
|
1152
|
+
this.activeRuntimeModelSnapshotId = snapshotId;
|
|
1153
|
+
this.currentRegistryBaseUrl = void 0;
|
|
1154
|
+
this.cleanupOldRuntimeModelSnapshots();
|
|
1155
|
+
return snapshotId;
|
|
1156
|
+
}
|
|
1157
|
+
/**
|
|
1158
|
+
* Get the currently active RuntimeModelSnapshot.
|
|
1159
|
+
*
|
|
1160
|
+
* @returns The active RuntimeModelSnapshot, or undefined if no runtime model is active
|
|
1161
|
+
*/
|
|
1162
|
+
getActiveRuntimeModelSnapshot() {
|
|
1163
|
+
if (!this.activeRuntimeModelSnapshotId) {
|
|
1164
|
+
return void 0;
|
|
1165
|
+
}
|
|
1166
|
+
return this.runtimeModelSnapshots.get(this.activeRuntimeModelSnapshotId);
|
|
1167
|
+
}
|
|
1168
|
+
/**
|
|
1169
|
+
* Get the ID of the currently active RuntimeModelSnapshot.
|
|
1170
|
+
*
|
|
1171
|
+
* @returns The active snapshot ID, or undefined if no runtime model is active
|
|
1172
|
+
*/
|
|
1173
|
+
getActiveRuntimeModelSnapshotId() {
|
|
1174
|
+
return this.activeRuntimeModelSnapshotId;
|
|
1175
|
+
}
|
|
1176
|
+
/**
|
|
1177
|
+
* Switch to a RuntimeModelSnapshot.
|
|
1178
|
+
*
|
|
1179
|
+
* Applies the configuration from a previously captured RuntimeModelSnapshot.
|
|
1180
|
+
* Uses state rollback pattern: creates a state snapshot before switching and
|
|
1181
|
+
* restores it on error.
|
|
1182
|
+
*
|
|
1183
|
+
* @param snapshotId - The ID of the RuntimeModelSnapshot to switch to
|
|
1184
|
+
*/
|
|
1185
|
+
async switchToRuntimeModel(snapshotId) {
|
|
1186
|
+
const runtimeModelSnapshot = this.runtimeModelSnapshots.get(snapshotId);
|
|
1187
|
+
if (!runtimeModelSnapshot) {
|
|
1188
|
+
throw new Error(`Runtime model snapshot '${snapshotId}' not found`);
|
|
1189
|
+
}
|
|
1190
|
+
const rollbackSnapshot = this.createStateSnapshotForRollback();
|
|
1191
|
+
try {
|
|
1192
|
+
const isAuthTypeChange = runtimeModelSnapshot.authType !== this.currentAuthType;
|
|
1193
|
+
this.currentAuthType = runtimeModelSnapshot.authType;
|
|
1194
|
+
this.activeRuntimeModelSnapshotId = snapshotId;
|
|
1195
|
+
this.currentRegistryBaseUrl = void 0;
|
|
1196
|
+
this.strictModelProviderSelection = false;
|
|
1197
|
+
this.hasManualCredentials = true;
|
|
1198
|
+
this._generationConfig.model = runtimeModelSnapshot.modelId;
|
|
1199
|
+
this.generationConfigSources["model"] = {
|
|
1200
|
+
kind: "programmatic",
|
|
1201
|
+
detail: "runtimeModelSwitch"
|
|
1202
|
+
};
|
|
1203
|
+
if (runtimeModelSnapshot.apiKey) {
|
|
1204
|
+
this._generationConfig.apiKey = runtimeModelSnapshot.apiKey;
|
|
1205
|
+
this.generationConfigSources["apiKey"] = runtimeModelSnapshot.sources["apiKey"] || {
|
|
1206
|
+
kind: "programmatic",
|
|
1207
|
+
detail: "runtimeModelSwitch"
|
|
1208
|
+
};
|
|
1209
|
+
}
|
|
1210
|
+
if (runtimeModelSnapshot.baseUrl) {
|
|
1211
|
+
this._generationConfig.baseUrl = runtimeModelSnapshot.baseUrl;
|
|
1212
|
+
this.generationConfigSources["baseUrl"] = runtimeModelSnapshot.sources["baseUrl"] || {
|
|
1213
|
+
kind: "programmatic",
|
|
1214
|
+
detail: "runtimeModelSwitch"
|
|
1215
|
+
};
|
|
1216
|
+
}
|
|
1217
|
+
if (runtimeModelSnapshot.apiKeyEnvKey) {
|
|
1218
|
+
this._generationConfig.apiKeyEnvKey = runtimeModelSnapshot.apiKeyEnvKey;
|
|
1219
|
+
}
|
|
1220
|
+
if (runtimeModelSnapshot.generationConfig) {
|
|
1221
|
+
Object.assign(
|
|
1222
|
+
this._generationConfig,
|
|
1223
|
+
runtimeModelSnapshot.generationConfig
|
|
1224
|
+
);
|
|
1225
|
+
}
|
|
1226
|
+
const requiresRefresh = isAuthTypeChange;
|
|
1227
|
+
if (this.onModelChange) {
|
|
1228
|
+
await this.onModelChange(
|
|
1229
|
+
runtimeModelSnapshot.authType,
|
|
1230
|
+
requiresRefresh
|
|
1231
|
+
);
|
|
1232
|
+
}
|
|
1233
|
+
} catch (error) {
|
|
1234
|
+
this.rollbackToStateSnapshot(rollbackSnapshot);
|
|
1235
|
+
throw error;
|
|
1236
|
+
}
|
|
1237
|
+
}
|
|
1238
|
+
/**
|
|
1239
|
+
* Get the active RuntimeModelSnapshot as an AvailableModel option.
|
|
1240
|
+
*
|
|
1241
|
+
* Converts the active RuntimeModelSnapshot to an AvailableModel format for display
|
|
1242
|
+
* in model lists. Returns undefined if no runtime model is active.
|
|
1243
|
+
*
|
|
1244
|
+
* @returns The runtime model as an AvailableModel option, or undefined
|
|
1245
|
+
*/
|
|
1246
|
+
getRuntimeModelOption() {
|
|
1247
|
+
const snapshot = this.getActiveRuntimeModelSnapshot();
|
|
1248
|
+
if (!snapshot) {
|
|
1249
|
+
return void 0;
|
|
1250
|
+
}
|
|
1251
|
+
return {
|
|
1252
|
+
id: snapshot.modelId,
|
|
1253
|
+
label: snapshot.modelId,
|
|
1254
|
+
authType: snapshot.authType,
|
|
1255
|
+
/**
|
|
1256
|
+
* `isVision` is for automatic switching of qwen-oauth vision model.
|
|
1257
|
+
* Runtime models are basically specified via CLI arguments, env variables,
|
|
1258
|
+
* or settings for other auth types.
|
|
1259
|
+
*/
|
|
1260
|
+
isVision: false,
|
|
1261
|
+
contextWindowSize: snapshot.generationConfig?.contextWindowSize,
|
|
1262
|
+
isRuntimeModel: true,
|
|
1263
|
+
runtimeSnapshotId: snapshot.id
|
|
1264
|
+
};
|
|
1265
|
+
}
|
|
1266
|
+
/**
|
|
1267
|
+
* Clear all RuntimeModelSnapshots for a specific authType.
|
|
1268
|
+
*
|
|
1269
|
+
* Removes all RuntimeModelSnapshots associated with the given authType.
|
|
1270
|
+
* Called when switching to a registry model to avoid stale RuntimeModelSnapshots.
|
|
1271
|
+
*
|
|
1272
|
+
* @param authType - The authType whose snapshots should be cleared
|
|
1273
|
+
*/
|
|
1274
|
+
clearRuntimeModelSnapshotForAuthType(authType) {
|
|
1275
|
+
for (const [id, snapshot] of this.runtimeModelSnapshots.entries()) {
|
|
1276
|
+
if (snapshot.authType === authType) {
|
|
1277
|
+
this.runtimeModelSnapshots.delete(id);
|
|
1278
|
+
if (this.activeRuntimeModelSnapshotId === id) {
|
|
1279
|
+
this.activeRuntimeModelSnapshotId = void 0;
|
|
1280
|
+
}
|
|
1281
|
+
}
|
|
1282
|
+
}
|
|
1283
|
+
}
|
|
1284
|
+
/**
|
|
1285
|
+
* Cleanup old RuntimeModelSnapshots to enforce per-authType limit.
|
|
1286
|
+
*
|
|
1287
|
+
* Keeps only the latest RuntimeModelSnapshot for each authType.
|
|
1288
|
+
* Older snapshots are removed to prevent unbounded growth.
|
|
1289
|
+
*/
|
|
1290
|
+
cleanupOldRuntimeModelSnapshots() {
|
|
1291
|
+
const snapshotsByAuthType = /* @__PURE__ */ new Map();
|
|
1292
|
+
for (const snapshot of this.runtimeModelSnapshots.values()) {
|
|
1293
|
+
const existing = snapshotsByAuthType.get(snapshot.authType);
|
|
1294
|
+
if (!existing || snapshot.createdAt > existing.createdAt) {
|
|
1295
|
+
snapshotsByAuthType.set(snapshot.authType, snapshot);
|
|
1296
|
+
}
|
|
1297
|
+
}
|
|
1298
|
+
this.runtimeModelSnapshots.clear();
|
|
1299
|
+
for (const snapshot of snapshotsByAuthType.values()) {
|
|
1300
|
+
this.runtimeModelSnapshots.set(snapshot.id, snapshot);
|
|
1301
|
+
}
|
|
1302
|
+
if (this.activeRuntimeModelSnapshotId && !this.runtimeModelSnapshots.has(this.activeRuntimeModelSnapshotId)) {
|
|
1303
|
+
this.activeRuntimeModelSnapshotId = void 0;
|
|
1304
|
+
}
|
|
1305
|
+
}
|
|
1306
|
+
/**
|
|
1307
|
+
* Reload model providers configuration at runtime.
|
|
1308
|
+
* This enables hot-reloading of modelProviders settings without restarting the CLI.
|
|
1309
|
+
*
|
|
1310
|
+
* @param modelProvidersConfig - The updated model providers configuration
|
|
1311
|
+
* @param providerProtocolConfig - Updated provider->protocol map; `undefined`
|
|
1312
|
+
* preserves the existing map (see {@link ModelRegistry.reloadModels}).
|
|
1313
|
+
*/
|
|
1314
|
+
reloadModelProvidersConfig(modelProvidersConfig, providerProtocolConfig) {
|
|
1315
|
+
this.modelRegistry.reloadModels(
|
|
1316
|
+
modelProvidersConfig,
|
|
1317
|
+
providerProtocolConfig
|
|
1318
|
+
);
|
|
1319
|
+
}
|
|
1320
|
+
/** The raw providers config the registry was last built from. */
|
|
1321
|
+
getModelProvidersConfig() {
|
|
1322
|
+
return this.modelRegistry.getModelProvidersConfig();
|
|
1323
|
+
}
|
|
1324
|
+
getProviderProtocolConfig() {
|
|
1325
|
+
return this.modelRegistry.getProviderProtocolConfig();
|
|
1326
|
+
}
|
|
1327
|
+
};
|
|
1328
|
+
|
|
1329
|
+
// packages/core/src/providers/install.ts
|
|
1330
|
+
init_esbuild_shims();
|
|
1331
|
+
var DENY_ENV_KEYS = /* @__PURE__ */ new Set([
|
|
1332
|
+
"NODE_OPTIONS",
|
|
1333
|
+
"NODE_PATH",
|
|
1334
|
+
"LD_PRELOAD",
|
|
1335
|
+
"LD_LIBRARY_PATH",
|
|
1336
|
+
"DYLD_INSERT_LIBRARIES",
|
|
1337
|
+
"DYLD_LIBRARY_PATH",
|
|
1338
|
+
"PATH",
|
|
1339
|
+
"HOME",
|
|
1340
|
+
"TMPDIR",
|
|
1341
|
+
"TMP",
|
|
1342
|
+
// Windows temp redirect
|
|
1343
|
+
"TEMP"
|
|
1344
|
+
// Windows temp redirect
|
|
1345
|
+
]);
|
|
1346
|
+
function isSameModelIdentity(a, b) {
|
|
1347
|
+
return a.id === b.id && (a.baseUrl ?? "") === (b.baseUrl ?? "");
|
|
1348
|
+
}
|
|
1349
|
+
__name(isSameModelIdentity, "isSameModelIdentity");
|
|
1350
|
+
function applyModelProvidersPatch(existingModelProviders, patch) {
|
|
1351
|
+
const existingModels = existingModelProviders[patch.authType] ?? [];
|
|
1352
|
+
let updatedModels = patch.models;
|
|
1353
|
+
if (patch.mergeStrategy === "append") {
|
|
1354
|
+
updatedModels = [...existingModels, ...patch.models];
|
|
1355
|
+
} else {
|
|
1356
|
+
const ownsModel = patch.ownsModel;
|
|
1357
|
+
const preservedModels = existingModels.filter((model) => {
|
|
1358
|
+
if (ownsModel) {
|
|
1359
|
+
return !ownsModel(model);
|
|
1360
|
+
}
|
|
1361
|
+
return !patch.models.some(
|
|
1362
|
+
(newModel) => isSameModelIdentity(newModel, model)
|
|
1363
|
+
);
|
|
1364
|
+
});
|
|
1365
|
+
updatedModels = patch.mergeStrategy === "replace-owned" ? [...preservedModels, ...patch.models] : [...patch.models, ...preservedModels];
|
|
1366
|
+
}
|
|
1367
|
+
return {
|
|
1368
|
+
...existingModelProviders,
|
|
1369
|
+
[patch.authType]: updatedModels
|
|
1370
|
+
};
|
|
1371
|
+
}
|
|
1372
|
+
__name(applyModelProvidersPatch, "applyModelProvidersPatch");
|
|
1373
|
+
var ProviderInstallError = class extends Error {
|
|
1374
|
+
static {
|
|
1375
|
+
__name(this, "ProviderInstallError");
|
|
1376
|
+
}
|
|
1377
|
+
step;
|
|
1378
|
+
authType;
|
|
1379
|
+
constructor(message, step, authType, options) {
|
|
1380
|
+
super(message, options);
|
|
1381
|
+
this.name = "ProviderInstallError";
|
|
1382
|
+
this.step = step;
|
|
1383
|
+
this.authType = authType;
|
|
1384
|
+
}
|
|
1385
|
+
};
|
|
1386
|
+
async function applyProviderInstallPlan(plan, options) {
|
|
1387
|
+
const {
|
|
1388
|
+
settings,
|
|
1389
|
+
reloadModelProviders,
|
|
1390
|
+
syncAuthState,
|
|
1391
|
+
refreshAuth,
|
|
1392
|
+
doRefreshAuth = true
|
|
1393
|
+
} = options;
|
|
1394
|
+
const serviceOnly = (plan.modelProviders ?? []).flatMap(
|
|
1395
|
+
(patch) => patch.models
|
|
1396
|
+
);
|
|
1397
|
+
const preserveSelection = serviceOnly.length > 0 && serviceOnly.every((model) => model.imageOnly || model.voiceOnly);
|
|
1398
|
+
const previousEnvValues = /* @__PURE__ */ new Map();
|
|
1399
|
+
const previousRuntimeProviders = {
|
|
1400
|
+
...settings.getModelProviders()
|
|
1401
|
+
};
|
|
1402
|
+
for (const patch of plan.modelProviders ?? []) {
|
|
1403
|
+
const existingModels = previousRuntimeProviders[patch.authType] ?? [];
|
|
1404
|
+
const changesRole = existingModels.some(
|
|
1405
|
+
(existing) => patch.models.some(
|
|
1406
|
+
(model) => (isSameModelIdentity(existing, model) || existing.id === model.id && patch.ownsModel?.(existing) && (preserveSelection || patch.mergeStrategy !== "append")) && (Boolean(existing.imageOnly) !== Boolean(model.imageOnly) || Boolean(existing.voiceOnly) !== Boolean(model.voiceOnly) || isImageGenerationCapable(existing) && !isImageGenerationCapable(model))
|
|
1407
|
+
)
|
|
1408
|
+
);
|
|
1409
|
+
const removesConversation = preserveSelection && existingModels.some(
|
|
1410
|
+
(existing) => !existing.imageOnly && !existing.voiceOnly && (patch.ownsModel?.(existing) ?? patch.models.some((model) => isSameModelIdentity(existing, model)))
|
|
1411
|
+
);
|
|
1412
|
+
const removesService = !preserveSelection && patch.mergeStrategy !== "append" && existingModels.some(
|
|
1413
|
+
(existing) => (existing.imageOnly || existing.voiceOnly) && patch.ownsModel?.(existing) && !patch.models.some((model) => model.id === existing.id)
|
|
1414
|
+
);
|
|
1415
|
+
if (changesRole || removesConversation || removesService) {
|
|
1416
|
+
throw new ProviderInstallError(
|
|
1417
|
+
removesConversation ? "This install would remove existing conversation models. Include them in the provider selection, or add the service model with Custom Provider." : removesService ? "This install would remove existing service models. Include them in the provider selection, or add the conversation model with Custom Provider." : "This install would replace a model configured for another purpose. Use a different model ID or endpoint.",
|
|
1418
|
+
"modelPurpose",
|
|
1419
|
+
plan.authType
|
|
1420
|
+
);
|
|
1421
|
+
}
|
|
1422
|
+
}
|
|
1423
|
+
const voiceIds = new Set(
|
|
1424
|
+
[
|
|
1425
|
+
...Object.values(previousRuntimeProviders).flatMap(
|
|
1426
|
+
(models) => Array.isArray(models) ? models : []
|
|
1427
|
+
),
|
|
1428
|
+
...serviceOnly
|
|
1429
|
+
].filter((model) => model?.voiceOnly).map((model) => model.id)
|
|
1430
|
+
);
|
|
1431
|
+
const selectedVoice = settings.getValue("voiceModel");
|
|
1432
|
+
if (typeof selectedVoice === "string" && selectedVoice)
|
|
1433
|
+
voiceIds.add(selectedVoice);
|
|
1434
|
+
const changedVoiceIds = [...voiceIds].filter(
|
|
1435
|
+
(id) => plan.modelProviders?.some(
|
|
1436
|
+
(patch) => patch.models.some((model) => model.id === id)
|
|
1437
|
+
)
|
|
1438
|
+
);
|
|
1439
|
+
if (changedVoiceIds.length) {
|
|
1440
|
+
let prospective = previousRuntimeProviders;
|
|
1441
|
+
for (const patch of plan.modelProviders ?? []) {
|
|
1442
|
+
prospective = applyModelProvidersPatch(prospective, patch);
|
|
1443
|
+
}
|
|
1444
|
+
const configured = new ModelsConfig({
|
|
1445
|
+
modelProvidersConfig: prospective,
|
|
1446
|
+
providerProtocolConfig: settings.getValue("providerProtocol")
|
|
1447
|
+
}).getAllConfiguredModels();
|
|
1448
|
+
if (changedVoiceIds.some(
|
|
1449
|
+
(id) => configured.filter((entry) => entry.id === id).length > 1
|
|
1450
|
+
)) {
|
|
1451
|
+
throw new ProviderInstallError(
|
|
1452
|
+
"A voice model with this ID is already configured at another endpoint. Edit that model or use a different model ID.",
|
|
1453
|
+
"modelPurpose",
|
|
1454
|
+
plan.authType
|
|
1455
|
+
);
|
|
1456
|
+
}
|
|
1457
|
+
}
|
|
1458
|
+
let currentStep = "init";
|
|
1459
|
+
try {
|
|
1460
|
+
currentStep = "backup";
|
|
1461
|
+
settings.backup?.();
|
|
1462
|
+
currentStep = "env";
|
|
1463
|
+
const shadowedEnvKeys = [];
|
|
1464
|
+
for (const [key, value] of Object.entries(plan.env ?? {})) {
|
|
1465
|
+
if (DENY_ENV_KEYS.has(key.toUpperCase())) {
|
|
1466
|
+
throw new Error(
|
|
1467
|
+
`Install plan must not set reserved environment variable: ${key}`
|
|
1468
|
+
);
|
|
1469
|
+
}
|
|
1470
|
+
const previous = process.env[key];
|
|
1471
|
+
if (previous !== void 0 && previous !== "" && previous !== value) {
|
|
1472
|
+
shadowedEnvKeys.push(key);
|
|
1473
|
+
}
|
|
1474
|
+
previousEnvValues.set(key, previous);
|
|
1475
|
+
settings.setValue(`env.${key}`, value);
|
|
1476
|
+
process.env[key] = value;
|
|
1477
|
+
}
|
|
1478
|
+
if (shadowedEnvKeys.length > 0) {
|
|
1479
|
+
console.error(
|
|
1480
|
+
`[auth] Warning: ${shadowedEnvKeys.join(", ")} ${shadowedEnvKeys.length === 1 ? "is" : "are"} also set in your shell environment or .env file. The shell/file value will take priority on restart. To ensure your new key is used, update or remove the variable from your shell profile or .env file.`
|
|
1481
|
+
);
|
|
1482
|
+
}
|
|
1483
|
+
currentStep = "modelProviders";
|
|
1484
|
+
let updatedModelProviders = {
|
|
1485
|
+
...previousRuntimeProviders
|
|
1486
|
+
};
|
|
1487
|
+
for (const patch of plan.modelProviders ?? []) {
|
|
1488
|
+
updatedModelProviders = applyModelProvidersPatch(
|
|
1489
|
+
updatedModelProviders,
|
|
1490
|
+
preserveSelection ? {
|
|
1491
|
+
...patch,
|
|
1492
|
+
mergeStrategy: "replace-owned",
|
|
1493
|
+
ownsModel: /* @__PURE__ */ __name((existing) => (patch.ownsModel?.(existing) ?? false) || patch.models.some(
|
|
1494
|
+
(model) => isSameModelIdentity(existing, model)
|
|
1495
|
+
), "ownsModel")
|
|
1496
|
+
} : patch
|
|
1497
|
+
);
|
|
1498
|
+
settings.setValue(
|
|
1499
|
+
`modelProviders.${patch.authType}`,
|
|
1500
|
+
updatedModelProviders[patch.authType] ?? []
|
|
1501
|
+
);
|
|
1502
|
+
}
|
|
1503
|
+
const effectiveProviders = settings.getModelProviders();
|
|
1504
|
+
for (const patch of plan.modelProviders ?? []) {
|
|
1505
|
+
if (patch.models.some(
|
|
1506
|
+
(model) => !effectiveProviders[patch.authType]?.some(
|
|
1507
|
+
(effective) => isSameModelIdentity(model, effective)
|
|
1508
|
+
)
|
|
1509
|
+
)) {
|
|
1510
|
+
throw new ProviderInstallError(
|
|
1511
|
+
"A higher-precedence settings scope overrides the installed models. Update the scope that owns this provider.",
|
|
1512
|
+
"modelProviders",
|
|
1513
|
+
plan.authType
|
|
1514
|
+
);
|
|
1515
|
+
}
|
|
1516
|
+
}
|
|
1517
|
+
currentStep = "authType";
|
|
1518
|
+
if (!preserveSelection) {
|
|
1519
|
+
settings.setValue("security.auth.selectedType", plan.authType);
|
|
1520
|
+
}
|
|
1521
|
+
currentStep = "legacyCredentials";
|
|
1522
|
+
if (plan.legacyCredentials?.apiKey != null) {
|
|
1523
|
+
settings.setValue("security.auth.apiKey", plan.legacyCredentials.apiKey);
|
|
1524
|
+
}
|
|
1525
|
+
if (plan.legacyCredentials?.baseUrl != null) {
|
|
1526
|
+
settings.setValue(
|
|
1527
|
+
"security.auth.baseUrl",
|
|
1528
|
+
plan.legacyCredentials.baseUrl
|
|
1529
|
+
);
|
|
1530
|
+
}
|
|
1531
|
+
currentStep = "modelSelection";
|
|
1532
|
+
let effectiveModelSelection = preserveSelection ? void 0 : plan.modelSelection;
|
|
1533
|
+
if (effectiveModelSelection?.modelId) {
|
|
1534
|
+
const currentModelId = settings.getValue("model.name");
|
|
1535
|
+
const currentBaseUrl = settings.getValue("model.baseUrl");
|
|
1536
|
+
const planOffersCurrentModel = typeof currentModelId === "string" && currentModelId.length > 0 && (plan.modelProviders ?? []).some(
|
|
1537
|
+
(patch) => patch.models.some(
|
|
1538
|
+
(model) => currentBaseUrl === "" || currentBaseUrl === void 0 ? model.id === currentModelId : isSameModelIdentity(
|
|
1539
|
+
{ id: currentModelId, baseUrl: currentBaseUrl },
|
|
1540
|
+
model
|
|
1541
|
+
)
|
|
1542
|
+
)
|
|
1543
|
+
);
|
|
1544
|
+
if (planOffersCurrentModel) {
|
|
1545
|
+
effectiveModelSelection = void 0;
|
|
1546
|
+
}
|
|
1547
|
+
}
|
|
1548
|
+
if (effectiveModelSelection?.modelId) {
|
|
1549
|
+
settings.setValue("model.name", effectiveModelSelection.modelId);
|
|
1550
|
+
if (effectiveModelSelection.baseUrl) {
|
|
1551
|
+
settings.setValue("model.baseUrl", effectiveModelSelection.baseUrl);
|
|
1552
|
+
} else {
|
|
1553
|
+
settings.setValue("model.baseUrl", "");
|
|
1554
|
+
}
|
|
1555
|
+
}
|
|
1556
|
+
currentStep = "providerState";
|
|
1557
|
+
for (const [key, entries] of Object.entries(plan.providerState ?? {})) {
|
|
1558
|
+
for (const [field, value] of Object.entries(entries)) {
|
|
1559
|
+
settings.setValue(`${key}.${field}`, value);
|
|
1560
|
+
}
|
|
1561
|
+
}
|
|
1562
|
+
currentStep = "persist";
|
|
1563
|
+
settings.persist();
|
|
1564
|
+
currentStep = "reloadModelProviders";
|
|
1565
|
+
updatedModelProviders = settings.getModelProviders();
|
|
1566
|
+
reloadModelProviders?.(updatedModelProviders);
|
|
1567
|
+
if (effectiveModelSelection?.modelId) {
|
|
1568
|
+
currentStep = "syncAuthState";
|
|
1569
|
+
syncAuthState?.(
|
|
1570
|
+
plan.authType,
|
|
1571
|
+
effectiveModelSelection.modelId,
|
|
1572
|
+
effectiveModelSelection.baseUrl
|
|
1573
|
+
);
|
|
1574
|
+
}
|
|
1575
|
+
if (!preserveSelection && doRefreshAuth && refreshAuth) {
|
|
1576
|
+
currentStep = "refreshAuth";
|
|
1577
|
+
await refreshAuth(plan.authType);
|
|
1578
|
+
}
|
|
1579
|
+
currentStep = "cleanupBackup";
|
|
1580
|
+
settings.cleanupBackup?.();
|
|
1581
|
+
return { updatedModelProviders };
|
|
1582
|
+
} catch (error) {
|
|
1583
|
+
try {
|
|
1584
|
+
settings.restore?.();
|
|
1585
|
+
} catch (restoreErr) {
|
|
1586
|
+
console.error(
|
|
1587
|
+
"[applyProviderInstallPlan] settings.restore failed during rollback:",
|
|
1588
|
+
restoreErr
|
|
1589
|
+
);
|
|
1590
|
+
}
|
|
1591
|
+
try {
|
|
1592
|
+
for (const [key, prev] of previousEnvValues) {
|
|
1593
|
+
if (prev === void 0) {
|
|
1594
|
+
delete process.env[key];
|
|
1595
|
+
} else {
|
|
1596
|
+
process.env[key] = prev;
|
|
1597
|
+
}
|
|
1598
|
+
}
|
|
1599
|
+
} catch (envErr) {
|
|
1600
|
+
console.error("[applyProviderInstallPlan] env rollback failed:", envErr);
|
|
1601
|
+
}
|
|
1602
|
+
try {
|
|
1603
|
+
reloadModelProviders?.(previousRuntimeProviders);
|
|
1604
|
+
} catch (reloadErr) {
|
|
1605
|
+
console.error(
|
|
1606
|
+
"[applyProviderInstallPlan] reloadModelProviders failed during rollback:",
|
|
1607
|
+
reloadErr
|
|
1608
|
+
);
|
|
1609
|
+
}
|
|
1610
|
+
const errMsg = error instanceof Error ? error.message : String(error);
|
|
1611
|
+
throw new ProviderInstallError(errMsg, currentStep, plan.authType, {
|
|
1612
|
+
cause: error instanceof Error ? error : void 0
|
|
1613
|
+
});
|
|
1614
|
+
}
|
|
1615
|
+
}
|
|
1616
|
+
__name(applyProviderInstallPlan, "applyProviderInstallPlan");
|
|
1617
|
+
|
|
1618
|
+
// packages/core/src/providers/provider-config.ts
|
|
1619
|
+
init_esbuild_shims();
|
|
1620
|
+
import { createHash } from "node:crypto";
|
|
1621
|
+
function resolveEnvKey(config, inputs) {
|
|
1622
|
+
const protocol = inputs.protocol ?? config.protocol;
|
|
1623
|
+
const key = typeof config.envKey === "function" ? config.envKey(protocol, inputs.baseUrl) : config.envKey;
|
|
1624
|
+
return config.id === "custom-openai-compatible" && inputs.advancedConfig?.purpose ? `${key}_${inputs.advancedConfig.purpose.toUpperCase()}` : key;
|
|
1625
|
+
}
|
|
1626
|
+
__name(resolveEnvKey, "resolveEnvKey");
|
|
1627
|
+
function resolveModelNamePrefix(config, baseUrl) {
|
|
1628
|
+
return typeof config.modelNamePrefix === "function" ? config.modelNamePrefix(baseUrl) : config.modelNamePrefix;
|
|
1629
|
+
}
|
|
1630
|
+
__name(resolveModelNamePrefix, "resolveModelNamePrefix");
|
|
1631
|
+
function resolveOwnsModel(config) {
|
|
1632
|
+
if (config.ownsModel) return config.ownsModel;
|
|
1633
|
+
if (typeof config.envKey !== "string" || typeof config.modelNamePrefix !== "string") {
|
|
1634
|
+
return void 0;
|
|
1635
|
+
}
|
|
1636
|
+
const envKey = config.envKey;
|
|
1637
|
+
const prefix = config.modelNamePrefix;
|
|
1638
|
+
if (!prefix) return (model) => model.envKey === envKey;
|
|
1639
|
+
const namePrefix = `[${prefix}] `;
|
|
1640
|
+
return (model) => model.envKey === envKey && typeof model.name === "string" && model.name.startsWith(namePrefix);
|
|
1641
|
+
}
|
|
1642
|
+
__name(resolveOwnsModel, "resolveOwnsModel");
|
|
1643
|
+
function buildGenerationConfig(spec) {
|
|
1644
|
+
const parts = {};
|
|
1645
|
+
let hasAny = false;
|
|
1646
|
+
if (spec.enableThinking) {
|
|
1647
|
+
parts.extra_body = { enable_thinking: true };
|
|
1648
|
+
hasAny = true;
|
|
1649
|
+
}
|
|
1650
|
+
if (spec.thinkingMandatory) {
|
|
1651
|
+
parts.thinkingMandatory = true;
|
|
1652
|
+
hasAny = true;
|
|
1653
|
+
}
|
|
1654
|
+
if (spec.contextWindowSize) {
|
|
1655
|
+
parts.contextWindowSize = spec.contextWindowSize;
|
|
1656
|
+
hasAny = true;
|
|
1657
|
+
}
|
|
1658
|
+
if (spec.modalities && Object.values(spec.modalities).some(Boolean)) {
|
|
1659
|
+
parts.modalities = spec.modalities;
|
|
1660
|
+
hasAny = true;
|
|
1661
|
+
}
|
|
1662
|
+
return hasAny ? parts : void 0;
|
|
1663
|
+
}
|
|
1664
|
+
__name(buildGenerationConfig, "buildGenerationConfig");
|
|
1665
|
+
function buildAdvancedGenerationConfig(advCfg, protocol) {
|
|
1666
|
+
const cfg = {};
|
|
1667
|
+
let hasAny = false;
|
|
1668
|
+
if (advCfg?.enableThinking) {
|
|
1669
|
+
if (protocol === "openai-responses" /* USE_OPENAI_RESPONSES */) {
|
|
1670
|
+
cfg.reasoning = { effort: "medium" };
|
|
1671
|
+
} else {
|
|
1672
|
+
cfg.extra_body = { enable_thinking: true };
|
|
1673
|
+
}
|
|
1674
|
+
hasAny = true;
|
|
1675
|
+
}
|
|
1676
|
+
if (advCfg?.multimodal && Object.values(advCfg.multimodal).some(Boolean)) {
|
|
1677
|
+
cfg.modalities = advCfg.multimodal;
|
|
1678
|
+
hasAny = true;
|
|
1679
|
+
}
|
|
1680
|
+
if (advCfg?.contextWindowSize && advCfg.contextWindowSize > 0) {
|
|
1681
|
+
cfg.contextWindowSize = advCfg.contextWindowSize;
|
|
1682
|
+
hasAny = true;
|
|
1683
|
+
}
|
|
1684
|
+
if (advCfg?.maxTokens && advCfg.maxTokens > 0) {
|
|
1685
|
+
cfg.samplingParams = { max_tokens: advCfg.maxTokens };
|
|
1686
|
+
hasAny = true;
|
|
1687
|
+
}
|
|
1688
|
+
return hasAny ? cfg : void 0;
|
|
1689
|
+
}
|
|
1690
|
+
__name(buildAdvancedGenerationConfig, "buildAdvancedGenerationConfig");
|
|
1691
|
+
function specToModelConfig(spec, prefix, baseUrl, envKey) {
|
|
1692
|
+
const genConfig = buildGenerationConfig(spec);
|
|
1693
|
+
return {
|
|
1694
|
+
id: spec.id,
|
|
1695
|
+
name: prefix ? `[${prefix}] ${spec.id}` : spec.id,
|
|
1696
|
+
...spec.description ? { description: spec.description } : {},
|
|
1697
|
+
...spec.capabilities ? { capabilities: spec.capabilities } : {},
|
|
1698
|
+
baseUrl,
|
|
1699
|
+
envKey,
|
|
1700
|
+
...spec.supportsImageGeneration ? { supportsImageGeneration: true } : {},
|
|
1701
|
+
...spec.imageOnly ? { imageOnly: true } : {},
|
|
1702
|
+
...genConfig ? { generationConfig: genConfig } : {}
|
|
1703
|
+
};
|
|
1704
|
+
}
|
|
1705
|
+
__name(specToModelConfig, "specToModelConfig");
|
|
1706
|
+
function applyProviderCustomHeaders(models, config) {
|
|
1707
|
+
if (!config.customHeaders) return models;
|
|
1708
|
+
return models.map((model) => {
|
|
1709
|
+
const existing = model.generationConfig ?? {};
|
|
1710
|
+
return {
|
|
1711
|
+
...model,
|
|
1712
|
+
generationConfig: {
|
|
1713
|
+
...existing,
|
|
1714
|
+
customHeaders: {
|
|
1715
|
+
...config.customHeaders,
|
|
1716
|
+
...existing.customHeaders
|
|
1717
|
+
}
|
|
1718
|
+
}
|
|
1719
|
+
};
|
|
1720
|
+
});
|
|
1721
|
+
}
|
|
1722
|
+
__name(applyProviderCustomHeaders, "applyProviderCustomHeaders");
|
|
1723
|
+
function buildModelConfigs(config, inputs) {
|
|
1724
|
+
const envKey = resolveEnvKey(config, inputs);
|
|
1725
|
+
const prefix = resolveModelNamePrefix(config, inputs.baseUrl);
|
|
1726
|
+
const protocol = inputs.protocol ?? config.protocol;
|
|
1727
|
+
let models;
|
|
1728
|
+
if (config.models && !config.modelsEditable) {
|
|
1729
|
+
models = config.models.map(
|
|
1730
|
+
(spec) => specToModelConfig(spec, prefix, inputs.baseUrl, envKey)
|
|
1731
|
+
);
|
|
1732
|
+
} else if (config.models && config.modelsEditable) {
|
|
1733
|
+
const specMap = new Map(config.models.map((s) => [s.id.toLowerCase(), s]));
|
|
1734
|
+
models = inputs.modelIds.map((id) => {
|
|
1735
|
+
const spec = specMap.get(id.toLowerCase());
|
|
1736
|
+
if (spec) {
|
|
1737
|
+
return specToModelConfig(
|
|
1738
|
+
{ ...spec, id },
|
|
1739
|
+
prefix,
|
|
1740
|
+
inputs.baseUrl,
|
|
1741
|
+
envKey
|
|
1742
|
+
);
|
|
1743
|
+
}
|
|
1744
|
+
const genConfig = buildAdvancedGenerationConfig(
|
|
1745
|
+
inputs.advancedConfig,
|
|
1746
|
+
protocol
|
|
1747
|
+
);
|
|
1748
|
+
return {
|
|
1749
|
+
id,
|
|
1750
|
+
name: prefix ? `[${prefix}] ${id}` : id,
|
|
1751
|
+
baseUrl: inputs.baseUrl,
|
|
1752
|
+
envKey,
|
|
1753
|
+
...genConfig ? { generationConfig: genConfig } : {}
|
|
1754
|
+
};
|
|
1755
|
+
});
|
|
1756
|
+
} else {
|
|
1757
|
+
const advCfg = inputs.advancedConfig;
|
|
1758
|
+
const displayName = /* @__PURE__ */ __name((id) => prefix ? `[${prefix}] ${id}` : id, "displayName");
|
|
1759
|
+
models = inputs.modelIds.map((id) => {
|
|
1760
|
+
const genConfig = buildAdvancedGenerationConfig(advCfg, protocol);
|
|
1761
|
+
return {
|
|
1762
|
+
id,
|
|
1763
|
+
name: displayName(id),
|
|
1764
|
+
baseUrl: inputs.baseUrl,
|
|
1765
|
+
envKey,
|
|
1766
|
+
...advCfg?.purpose === "image" ? { supportsImageGeneration: true, imageOnly: true } : advCfg?.purpose === "voice" ? { voiceOnly: true } : {},
|
|
1767
|
+
...genConfig ? { generationConfig: genConfig } : {}
|
|
1768
|
+
};
|
|
1769
|
+
});
|
|
1770
|
+
}
|
|
1771
|
+
return applyProviderCustomHeaders(models, config);
|
|
1772
|
+
}
|
|
1773
|
+
__name(buildModelConfigs, "buildModelConfigs");
|
|
1774
|
+
function resolveMetadataKey(config) {
|
|
1775
|
+
if (!config.models) return void 0;
|
|
1776
|
+
if (config.id.includes(".")) {
|
|
1777
|
+
throw new Error(
|
|
1778
|
+
`Provider id must not contain '.' (would corrupt providerMetadata.${config.id} dotted writes): ${config.id}`
|
|
1779
|
+
);
|
|
1780
|
+
}
|
|
1781
|
+
return config.id;
|
|
1782
|
+
}
|
|
1783
|
+
__name(resolveMetadataKey, "resolveMetadataKey");
|
|
1784
|
+
var PROVIDER_METADATA_NS = "providerMetadata";
|
|
1785
|
+
function resolveProviderState(config, baseUrl, models) {
|
|
1786
|
+
const key = resolveMetadataKey(config);
|
|
1787
|
+
if (key) {
|
|
1788
|
+
return {
|
|
1789
|
+
[`${PROVIDER_METADATA_NS}.${key}`]: {
|
|
1790
|
+
version: computeModelListVersion(models),
|
|
1791
|
+
baseUrl
|
|
1792
|
+
}
|
|
1793
|
+
};
|
|
1794
|
+
}
|
|
1795
|
+
return void 0;
|
|
1796
|
+
}
|
|
1797
|
+
__name(resolveProviderState, "resolveProviderState");
|
|
1798
|
+
function buildInstallPlan(config, inputs, existingModels = []) {
|
|
1799
|
+
const protocol = inputs.protocol ?? config.protocol;
|
|
1800
|
+
let envKey = resolveEnvKey(config, inputs);
|
|
1801
|
+
const providerOwns = resolveOwnsModel(config);
|
|
1802
|
+
let models = inputs.prebuiltModels ?? buildModelConfigs(config, inputs);
|
|
1803
|
+
const providerState = resolveProviderState(config, inputs.baseUrl, models);
|
|
1804
|
+
if (config.id === "custom-openai-compatible" && existingModels?.some(
|
|
1805
|
+
(entry) => providerOwns?.(entry) && (entry.imageOnly || entry.voiceOnly) && models.some((model) => model.id === entry.id) && typeof entry.baseUrl === "string" && entry.baseUrl !== inputs.baseUrl && resolveEnvKey(config, { ...inputs, baseUrl: entry.baseUrl }) === envKey
|
|
1806
|
+
)) {
|
|
1807
|
+
throw new ProviderInstallError(
|
|
1808
|
+
"A service model already uses this credential endpoint. Reconnect using its exact saved base URL.",
|
|
1809
|
+
"modelPurpose",
|
|
1810
|
+
protocol
|
|
1811
|
+
);
|
|
1812
|
+
}
|
|
1813
|
+
if (existingModels?.length && !inputs.advancedConfig?.purpose) {
|
|
1814
|
+
models = models.map((model) => {
|
|
1815
|
+
const existing = existingModels.find(
|
|
1816
|
+
(entry) => providerOwns?.(entry) && entry.id === model.id && entry.baseUrl === model.baseUrl
|
|
1817
|
+
);
|
|
1818
|
+
if (!existing) return model;
|
|
1819
|
+
const preservedGeneration = { ...existing.generationConfig };
|
|
1820
|
+
const advanced = inputs.advancedConfig;
|
|
1821
|
+
if (!config.models && advanced) {
|
|
1822
|
+
if (advanced.replaceExisting) {
|
|
1823
|
+
delete preservedGeneration.contextWindowSize;
|
|
1824
|
+
if (preservedGeneration.samplingParams) {
|
|
1825
|
+
preservedGeneration.samplingParams = {
|
|
1826
|
+
...preservedGeneration.samplingParams
|
|
1827
|
+
};
|
|
1828
|
+
delete preservedGeneration.samplingParams.max_tokens;
|
|
1829
|
+
if (!Object.keys(preservedGeneration.samplingParams).length)
|
|
1830
|
+
delete preservedGeneration.samplingParams;
|
|
1831
|
+
}
|
|
1832
|
+
}
|
|
1833
|
+
if (advanced.replaceExisting || advanced.multimodal !== void 0)
|
|
1834
|
+
delete preservedGeneration.modalities;
|
|
1835
|
+
if (advanced.replaceExisting || advanced.enableThinking !== void 0) {
|
|
1836
|
+
if (preservedGeneration.extra_body) {
|
|
1837
|
+
preservedGeneration.extra_body = {
|
|
1838
|
+
...preservedGeneration.extra_body
|
|
1839
|
+
};
|
|
1840
|
+
delete preservedGeneration.extra_body["enable_thinking"];
|
|
1841
|
+
if (!Object.keys(preservedGeneration.extra_body).length)
|
|
1842
|
+
delete preservedGeneration.extra_body;
|
|
1843
|
+
}
|
|
1844
|
+
if (protocol === "openai-responses" /* USE_OPENAI_RESPONSES */)
|
|
1845
|
+
delete preservedGeneration.reasoning;
|
|
1846
|
+
}
|
|
1847
|
+
}
|
|
1848
|
+
const generationConfig = Object.keys(preservedGeneration).length || model.generationConfig ? {
|
|
1849
|
+
...preservedGeneration,
|
|
1850
|
+
...model.generationConfig,
|
|
1851
|
+
...preservedGeneration.extra_body || model.generationConfig?.extra_body ? {
|
|
1852
|
+
extra_body: {
|
|
1853
|
+
...preservedGeneration.extra_body,
|
|
1854
|
+
...model.generationConfig?.extra_body
|
|
1855
|
+
}
|
|
1856
|
+
} : {},
|
|
1857
|
+
...preservedGeneration.contextWindowSize !== void 0 && inputs.advancedConfig?.contextWindowSize === void 0 ? {
|
|
1858
|
+
contextWindowSize: preservedGeneration.contextWindowSize
|
|
1859
|
+
} : {},
|
|
1860
|
+
...preservedGeneration.samplingParams || model.generationConfig?.samplingParams ? {
|
|
1861
|
+
samplingParams: {
|
|
1862
|
+
...preservedGeneration.samplingParams,
|
|
1863
|
+
...model.generationConfig?.samplingParams
|
|
1864
|
+
}
|
|
1865
|
+
} : {},
|
|
1866
|
+
...preservedGeneration.customHeaders || model.generationConfig?.customHeaders ? {
|
|
1867
|
+
customHeaders: {
|
|
1868
|
+
...preservedGeneration.customHeaders,
|
|
1869
|
+
...model.generationConfig?.customHeaders
|
|
1870
|
+
}
|
|
1871
|
+
} : {}
|
|
1872
|
+
} : void 0;
|
|
1873
|
+
return {
|
|
1874
|
+
...existing,
|
|
1875
|
+
...model,
|
|
1876
|
+
name: existing?.name ?? model.name,
|
|
1877
|
+
generationConfig,
|
|
1878
|
+
...existing?.supportsImageGeneration ? { supportsImageGeneration: true } : {},
|
|
1879
|
+
...existing?.imageOnly ? { imageOnly: true } : {},
|
|
1880
|
+
...existing?.voiceOnly ? { voiceOnly: true } : {},
|
|
1881
|
+
...(existing?.imageOnly || existing?.voiceOnly) && existing.envKey ? { envKey: existing.envKey } : {}
|
|
1882
|
+
};
|
|
1883
|
+
});
|
|
1884
|
+
}
|
|
1885
|
+
if (models.length > 0 && models.every((model) => model.imageOnly || model.voiceOnly)) {
|
|
1886
|
+
const keys = new Set(models.map((model) => model.envKey));
|
|
1887
|
+
if (keys.size > 1) {
|
|
1888
|
+
throw new Error(
|
|
1889
|
+
"Reconnect image and voice models separately to preserve their independent API keys."
|
|
1890
|
+
);
|
|
1891
|
+
}
|
|
1892
|
+
if (keys.size === 1 && models[0]?.envKey) envKey = models[0].envKey;
|
|
1893
|
+
}
|
|
1894
|
+
const ownsModel = config.mergeModelsByIdentity ? void 0 : resolveOwnsModel(config);
|
|
1895
|
+
const firstModel = models.find(
|
|
1896
|
+
(model) => !model.imageOnly && !model.voiceOnly
|
|
1897
|
+
);
|
|
1898
|
+
if (models.length === 0) {
|
|
1899
|
+
throw new Error(
|
|
1900
|
+
`No models configured for provider "${config.id}". Check model list or provider configuration.`
|
|
1901
|
+
);
|
|
1902
|
+
}
|
|
1903
|
+
const firstModelId = firstModel?.id;
|
|
1904
|
+
const modelSelection = firstModelId === void 0 ? void 0 : {
|
|
1905
|
+
modelId: firstModelId,
|
|
1906
|
+
...config.mergeModelsByIdentity && firstModel?.baseUrl ? { baseUrl: firstModel.baseUrl } : {}
|
|
1907
|
+
};
|
|
1908
|
+
return {
|
|
1909
|
+
providerId: config.id,
|
|
1910
|
+
authType: protocol,
|
|
1911
|
+
env: { [envKey]: inputs.apiKey },
|
|
1912
|
+
...modelSelection ? { modelSelection } : {},
|
|
1913
|
+
modelProviders: [
|
|
1914
|
+
{
|
|
1915
|
+
authType: protocol,
|
|
1916
|
+
models,
|
|
1917
|
+
mergeStrategy: "prepend-and-remove-owned",
|
|
1918
|
+
...ownsModel ? { ownsModel } : {}
|
|
1919
|
+
}
|
|
1920
|
+
],
|
|
1921
|
+
providerState
|
|
1922
|
+
};
|
|
1923
|
+
}
|
|
1924
|
+
__name(buildInstallPlan, "buildInstallPlan");
|
|
1925
|
+
function computeModelListVersion(models) {
|
|
1926
|
+
return createHash("sha256").update(JSON.stringify(models)).digest("hex");
|
|
1927
|
+
}
|
|
1928
|
+
__name(computeModelListVersion, "computeModelListVersion");
|
|
1929
|
+
var DEFAULT_BASE_URLS = {
|
|
1930
|
+
["openai" /* USE_OPENAI */]: "https://api.openai.com/v1",
|
|
1931
|
+
["openai-responses" /* USE_OPENAI_RESPONSES */]: "https://api.openai.com",
|
|
1932
|
+
["anthropic" /* USE_ANTHROPIC */]: "https://api.anthropic.com/v1",
|
|
1933
|
+
["gemini" /* USE_GEMINI */]: "https://generativelanguage.googleapis.com"
|
|
1934
|
+
};
|
|
1935
|
+
function getDefaultBaseUrlForProtocol(protocol) {
|
|
1936
|
+
if (protocol === void 0) return "";
|
|
1937
|
+
return DEFAULT_BASE_URLS[protocol] ?? "";
|
|
1938
|
+
}
|
|
1939
|
+
__name(getDefaultBaseUrlForProtocol, "getDefaultBaseUrlForProtocol");
|
|
1940
|
+
function resolveBaseUrl(config, selectedBaseUrl) {
|
|
1941
|
+
if (typeof config.baseUrl === "string") {
|
|
1942
|
+
return config.baseUrl;
|
|
1943
|
+
}
|
|
1944
|
+
if (Array.isArray(config.baseUrl)) {
|
|
1945
|
+
const normalizedSelectedBaseUrl = normalizeBaseUrlForMatching(selectedBaseUrl);
|
|
1946
|
+
const match = config.baseUrl.find(
|
|
1947
|
+
(opt) => normalizeBaseUrlForMatching(opt.url) === normalizedSelectedBaseUrl
|
|
1948
|
+
);
|
|
1949
|
+
if (match) return match.url;
|
|
1950
|
+
return config.baseUrl[0]?.url ?? selectedBaseUrl ?? "";
|
|
1951
|
+
}
|
|
1952
|
+
return selectedBaseUrl ?? "";
|
|
1953
|
+
}
|
|
1954
|
+
__name(resolveBaseUrl, "resolveBaseUrl");
|
|
1955
|
+
function normalizeBaseUrlForMatching(baseUrl) {
|
|
1956
|
+
if (baseUrl === void 0) return "";
|
|
1957
|
+
let end = baseUrl.length;
|
|
1958
|
+
while (end > 0 && baseUrl.charCodeAt(end - 1) === 47) {
|
|
1959
|
+
end--;
|
|
1960
|
+
}
|
|
1961
|
+
return end === baseUrl.length ? baseUrl : baseUrl.slice(0, end);
|
|
1962
|
+
}
|
|
1963
|
+
__name(normalizeBaseUrlForMatching, "normalizeBaseUrlForMatching");
|
|
1964
|
+
function getDefaultModelIds(config) {
|
|
1965
|
+
return config.models?.map((s) => s.id) ?? [];
|
|
1966
|
+
}
|
|
1967
|
+
__name(getDefaultModelIds, "getDefaultModelIds");
|
|
1968
|
+
function isProviderModelConfig(value) {
|
|
1969
|
+
return typeof value === "object" && value !== null && typeof value.id === "string";
|
|
1970
|
+
}
|
|
1971
|
+
__name(isProviderModelConfig, "isProviderModelConfig");
|
|
1972
|
+
function findExistingProviderModels(config, modelProviders) {
|
|
1973
|
+
const ownsModel = resolveOwnsModel(config);
|
|
1974
|
+
if (!ownsModel || !modelProviders) return void 0;
|
|
1975
|
+
const protocols = config.protocolOptions?.length ? config.protocolOptions : [config.protocol];
|
|
1976
|
+
for (const protocol of protocols) {
|
|
1977
|
+
const raw = modelProviders[protocol];
|
|
1978
|
+
if (!Array.isArray(raw)) continue;
|
|
1979
|
+
const models = raw.filter(
|
|
1980
|
+
(m) => isProviderModelConfig(m) && ownsModel(m)
|
|
1981
|
+
);
|
|
1982
|
+
if (models.length > 0) return { protocol, models };
|
|
1983
|
+
}
|
|
1984
|
+
return void 0;
|
|
1985
|
+
}
|
|
1986
|
+
__name(findExistingProviderModels, "findExistingProviderModels");
|
|
1987
|
+
function shouldShowStep(config, step) {
|
|
1988
|
+
switch (step) {
|
|
1989
|
+
case "protocol":
|
|
1990
|
+
return Array.isArray(config.protocolOptions) && config.protocolOptions.length > 1;
|
|
1991
|
+
case "baseUrl":
|
|
1992
|
+
return config.baseUrl === void 0 || Array.isArray(config.baseUrl);
|
|
1993
|
+
case "apiKey":
|
|
1994
|
+
return true;
|
|
1995
|
+
case "models":
|
|
1996
|
+
return !config.models || config.modelsEditable === true;
|
|
1997
|
+
case "advancedConfig":
|
|
1998
|
+
return config.showAdvancedConfig === true;
|
|
1999
|
+
default:
|
|
2000
|
+
return false;
|
|
2001
|
+
}
|
|
2002
|
+
}
|
|
2003
|
+
__name(shouldShowStep, "shouldShowStep");
|
|
2004
|
+
function providerMatchesCredentials(config, baseUrl, envKey) {
|
|
2005
|
+
let configEnvKey;
|
|
2006
|
+
if (typeof config.envKey === "string") {
|
|
2007
|
+
configEnvKey = config.envKey;
|
|
2008
|
+
} else if (typeof config.envKey === "function" && baseUrl) {
|
|
2009
|
+
const protocols = config.protocolOptions?.length ? config.protocolOptions : [config.protocol];
|
|
2010
|
+
for (const proto of protocols) {
|
|
2011
|
+
try {
|
|
2012
|
+
const derived = config.envKey(proto, baseUrl);
|
|
2013
|
+
if (derived === envKey || config.id === "custom-openai-compatible" && (envKey === `${derived}_IMAGE` || envKey === `${derived}_VOICE`)) {
|
|
2014
|
+
configEnvKey = envKey;
|
|
2015
|
+
break;
|
|
2016
|
+
}
|
|
2017
|
+
} catch (err) {
|
|
2018
|
+
let safeHost;
|
|
2019
|
+
try {
|
|
2020
|
+
safeHost = new URL(baseUrl).hostname;
|
|
2021
|
+
} catch {
|
|
2022
|
+
safeHost = "[invalid]";
|
|
2023
|
+
}
|
|
2024
|
+
console.warn(
|
|
2025
|
+
`[providerMatchesCredentials] envKey(${proto}, ${safeHost}) threw (${err instanceof Error ? err.constructor.name : typeof err}); skipping this protocol`
|
|
2026
|
+
);
|
|
2027
|
+
}
|
|
2028
|
+
}
|
|
2029
|
+
}
|
|
2030
|
+
if (configEnvKey !== envKey) {
|
|
2031
|
+
return false;
|
|
2032
|
+
}
|
|
2033
|
+
if (typeof config.baseUrl === "string") {
|
|
2034
|
+
return config.baseUrl === baseUrl;
|
|
2035
|
+
}
|
|
2036
|
+
if (Array.isArray(config.baseUrl)) {
|
|
2037
|
+
return config.baseUrl.some((opt) => opt.url === baseUrl);
|
|
2038
|
+
}
|
|
2039
|
+
if (config.baseUrl === void 0 && configEnvKey !== void 0) {
|
|
2040
|
+
return Boolean(baseUrl);
|
|
2041
|
+
}
|
|
2042
|
+
return false;
|
|
2043
|
+
}
|
|
2044
|
+
__name(providerMatchesCredentials, "providerMatchesCredentials");
|
|
2045
|
+
function buildProviderTemplate(config, baseUrl) {
|
|
2046
|
+
const resolved = resolveBaseUrl(config, baseUrl);
|
|
2047
|
+
return buildModelConfigs(config, {
|
|
2048
|
+
baseUrl: resolved,
|
|
2049
|
+
apiKey: "",
|
|
2050
|
+
modelIds: getDefaultModelIds(config)
|
|
2051
|
+
});
|
|
2052
|
+
}
|
|
2053
|
+
__name(buildProviderTemplate, "buildProviderTemplate");
|
|
2054
|
+
|
|
2055
|
+
// packages/core/src/providers/all-providers.ts
|
|
2056
|
+
init_esbuild_shims();
|
|
2057
|
+
|
|
2058
|
+
// packages/core/src/providers/presets/alibaba-coding-plan.ts
|
|
2059
|
+
init_esbuild_shims();
|
|
2060
|
+
var CODING_PLAN_ENV_KEY = "BAILIAN_CODING_PLAN_API_KEY";
|
|
2061
|
+
var CODING_PLAN_CHINA_BASE_URL = "https://coding.dashscope.aliyuncs.com/v1";
|
|
2062
|
+
var CODING_PLAN_GLOBAL_BASE_URL = "https://coding-intl.dashscope.aliyuncs.com/v1";
|
|
2063
|
+
var MODELSTUDIO_MODELS = [
|
|
2064
|
+
{
|
|
2065
|
+
id: "qwen3.5-plus",
|
|
2066
|
+
capabilities: {
|
|
2067
|
+
reasoning: {
|
|
2068
|
+
thinking: true,
|
|
2069
|
+
toggleOnly: true,
|
|
2070
|
+
disableField: "enable_thinking"
|
|
2071
|
+
}
|
|
2072
|
+
},
|
|
2073
|
+
contextWindowSize: 1e6,
|
|
2074
|
+
enableThinking: true,
|
|
2075
|
+
modalities: { image: true, video: true }
|
|
2076
|
+
},
|
|
2077
|
+
{
|
|
2078
|
+
id: "qwen3.6-plus",
|
|
2079
|
+
capabilities: {
|
|
2080
|
+
reasoning: {
|
|
2081
|
+
thinking: true,
|
|
2082
|
+
toggleOnly: true,
|
|
2083
|
+
disableField: "enable_thinking"
|
|
2084
|
+
}
|
|
2085
|
+
},
|
|
2086
|
+
description: "Currently available to Pro subscribers only.",
|
|
2087
|
+
contextWindowSize: 1e6,
|
|
2088
|
+
enableThinking: true,
|
|
2089
|
+
modalities: { image: true, video: true }
|
|
2090
|
+
},
|
|
2091
|
+
{
|
|
2092
|
+
id: "qwen3.7-plus",
|
|
2093
|
+
capabilities: {
|
|
2094
|
+
reasoning: {
|
|
2095
|
+
thinking: true,
|
|
2096
|
+
toggleOnly: true,
|
|
2097
|
+
disableField: "enable_thinking"
|
|
2098
|
+
}
|
|
2099
|
+
},
|
|
2100
|
+
contextWindowSize: 1e6,
|
|
2101
|
+
enableThinking: true
|
|
2102
|
+
},
|
|
2103
|
+
{ id: "glm-5", contextWindowSize: 202752, enableThinking: true },
|
|
2104
|
+
{
|
|
2105
|
+
id: "kimi-k2.5",
|
|
2106
|
+
capabilities: {
|
|
2107
|
+
reasoning: {
|
|
2108
|
+
thinking: true,
|
|
2109
|
+
toggleOnly: true,
|
|
2110
|
+
disableField: "enable_thinking"
|
|
2111
|
+
}
|
|
2112
|
+
},
|
|
2113
|
+
contextWindowSize: 262144,
|
|
2114
|
+
enableThinking: true,
|
|
2115
|
+
modalities: { image: true, video: true }
|
|
2116
|
+
},
|
|
2117
|
+
{ id: "MiniMax-M2.5", contextWindowSize: 196608, enableThinking: true },
|
|
2118
|
+
{ id: "qwen3-coder-plus", contextWindowSize: 1e6 },
|
|
2119
|
+
{ id: "qwen3-coder-next", contextWindowSize: 262144 },
|
|
2120
|
+
{
|
|
2121
|
+
id: "qwen3-max-2026-01-23",
|
|
2122
|
+
capabilities: {
|
|
2123
|
+
reasoning: {
|
|
2124
|
+
thinking: true,
|
|
2125
|
+
toggleOnly: true,
|
|
2126
|
+
disableField: "enable_thinking"
|
|
2127
|
+
}
|
|
2128
|
+
},
|
|
2129
|
+
contextWindowSize: 262144,
|
|
2130
|
+
enableThinking: true
|
|
2131
|
+
},
|
|
2132
|
+
{ id: "glm-4.7", contextWindowSize: 202752, enableThinking: true }
|
|
2133
|
+
];
|
|
2134
|
+
var codingPlanProvider = {
|
|
2135
|
+
id: "coding-plan",
|
|
2136
|
+
label: "Coding Plan",
|
|
2137
|
+
description: "For individual developers \xB7 Weekly quota included",
|
|
2138
|
+
protocol: "openai" /* USE_OPENAI */,
|
|
2139
|
+
baseUrl: [
|
|
2140
|
+
{
|
|
2141
|
+
id: "aliyun",
|
|
2142
|
+
label: "China (Beijing)",
|
|
2143
|
+
url: CODING_PLAN_CHINA_BASE_URL,
|
|
2144
|
+
documentationUrl: "https://help.aliyun.com/zh/model-studio/coding-plan"
|
|
2145
|
+
},
|
|
2146
|
+
{
|
|
2147
|
+
id: "alibabacloud",
|
|
2148
|
+
label: "Singapore (International)",
|
|
2149
|
+
url: CODING_PLAN_GLOBAL_BASE_URL,
|
|
2150
|
+
documentationUrl: "https://www.alibabacloud.com/help/en/model-studio/coding-plan"
|
|
2151
|
+
}
|
|
2152
|
+
],
|
|
2153
|
+
envKey: CODING_PLAN_ENV_KEY,
|
|
2154
|
+
models: MODELSTUDIO_MODELS,
|
|
2155
|
+
modelsEditable: true,
|
|
2156
|
+
supportsModelDiscovery: true,
|
|
2157
|
+
modelNamePrefix: /* @__PURE__ */ __name((baseUrl) => baseUrl === CODING_PLAN_GLOBAL_BASE_URL ? "ModelStudio Coding Plan for Global/Intl" : "ModelStudio Coding Plan", "modelNamePrefix"),
|
|
2158
|
+
apiKeyPlaceholder: "sk-sp-...",
|
|
2159
|
+
validateApiKey: /* @__PURE__ */ __name((key) => !key.startsWith("sk-sp-") ? 'Invalid API key. Coding Plan API keys start with "sk-sp-". Please check.' : null, "validateApiKey"),
|
|
2160
|
+
ownsModel: /* @__PURE__ */ __name((model) => model.envKey === CODING_PLAN_ENV_KEY && typeof model.baseUrl === "string" && (model.baseUrl === CODING_PLAN_CHINA_BASE_URL || model.baseUrl === CODING_PLAN_GLOBAL_BASE_URL), "ownsModel"),
|
|
2161
|
+
uiGroup: "alibaba",
|
|
2162
|
+
uiLabels: { flowTitle: "Alibaba ModelStudio", baseUrlStepTitle: "Region" }
|
|
2163
|
+
};
|
|
2164
|
+
|
|
2165
|
+
// packages/core/src/providers/presets/alibaba-token-plan.ts
|
|
2166
|
+
init_esbuild_shims();
|
|
2167
|
+
var TOKEN_PLAN_ENV_KEY = "BAILIAN_TOKEN_PLAN_API_KEY";
|
|
2168
|
+
var TOKEN_PLAN_CHINA_BASE_URL = "https://token-plan.cn-beijing.maas.aliyuncs.com/compatible-mode/v1";
|
|
2169
|
+
var TOKEN_PLAN_GLOBAL_BASE_URL = "https://token-plan.ap-southeast-1.maas.aliyuncs.com/compatible-mode/v1";
|
|
2170
|
+
var TOKEN_PLAN_MODELS = [
|
|
2171
|
+
{
|
|
2172
|
+
id: "qwen3.7-plus",
|
|
2173
|
+
capabilities: {
|
|
2174
|
+
reasoning: {
|
|
2175
|
+
thinking: true,
|
|
2176
|
+
toggleOnly: true,
|
|
2177
|
+
disableField: "enable_thinking"
|
|
2178
|
+
}
|
|
2179
|
+
},
|
|
2180
|
+
contextWindowSize: 1e6,
|
|
2181
|
+
enableThinking: true,
|
|
2182
|
+
modalities: { image: true, video: true }
|
|
2183
|
+
},
|
|
2184
|
+
{
|
|
2185
|
+
id: "qwen3.6-plus",
|
|
2186
|
+
capabilities: {
|
|
2187
|
+
reasoning: {
|
|
2188
|
+
thinking: true,
|
|
2189
|
+
toggleOnly: true,
|
|
2190
|
+
disableField: "enable_thinking"
|
|
2191
|
+
}
|
|
2192
|
+
},
|
|
2193
|
+
contextWindowSize: 1e6,
|
|
2194
|
+
enableThinking: true,
|
|
2195
|
+
modalities: { image: true, video: true }
|
|
2196
|
+
},
|
|
2197
|
+
{
|
|
2198
|
+
id: "qwen3.7-max",
|
|
2199
|
+
capabilities: {
|
|
2200
|
+
reasoning: {
|
|
2201
|
+
thinking: true,
|
|
2202
|
+
toggleOnly: true,
|
|
2203
|
+
disableField: "enable_thinking"
|
|
2204
|
+
}
|
|
2205
|
+
},
|
|
2206
|
+
contextWindowSize: 1e6,
|
|
2207
|
+
enableThinking: true
|
|
2208
|
+
},
|
|
2209
|
+
{
|
|
2210
|
+
id: "qwen3.8-max",
|
|
2211
|
+
capabilities: {
|
|
2212
|
+
reasoning: {
|
|
2213
|
+
thinking: true,
|
|
2214
|
+
efforts: ["low", "medium", "xhigh"],
|
|
2215
|
+
defaultEffort: "xhigh",
|
|
2216
|
+
canDisable: false,
|
|
2217
|
+
disableField: "reasoning_effort"
|
|
2218
|
+
}
|
|
2219
|
+
},
|
|
2220
|
+
contextWindowSize: 1e6,
|
|
2221
|
+
enableThinking: true,
|
|
2222
|
+
thinkingMandatory: true,
|
|
2223
|
+
modalities: { image: true, video: true }
|
|
2224
|
+
},
|
|
2225
|
+
{
|
|
2226
|
+
id: "qwen3.8-max-preview",
|
|
2227
|
+
capabilities: {
|
|
2228
|
+
reasoning: {
|
|
2229
|
+
thinking: true,
|
|
2230
|
+
efforts: ["low", "medium", "xhigh"],
|
|
2231
|
+
defaultEffort: "xhigh",
|
|
2232
|
+
canDisable: false,
|
|
2233
|
+
disableField: "reasoning_effort"
|
|
2234
|
+
}
|
|
2235
|
+
},
|
|
2236
|
+
contextWindowSize: 1e6,
|
|
2237
|
+
enableThinking: true,
|
|
2238
|
+
thinkingMandatory: true,
|
|
2239
|
+
modalities: { image: true, video: true }
|
|
2240
|
+
},
|
|
2241
|
+
{
|
|
2242
|
+
id: "qwen3.6-flash",
|
|
2243
|
+
capabilities: {
|
|
2244
|
+
reasoning: {
|
|
2245
|
+
thinking: true,
|
|
2246
|
+
toggleOnly: true,
|
|
2247
|
+
disableField: "enable_thinking"
|
|
2248
|
+
}
|
|
2249
|
+
},
|
|
2250
|
+
contextWindowSize: 1e6,
|
|
2251
|
+
enableThinking: true
|
|
2252
|
+
},
|
|
2253
|
+
{
|
|
2254
|
+
id: "deepseek-v4-pro",
|
|
2255
|
+
capabilities: {
|
|
2256
|
+
reasoning: {
|
|
2257
|
+
thinking: true,
|
|
2258
|
+
efforts: ["high", "max"],
|
|
2259
|
+
defaultEffort: "high",
|
|
2260
|
+
disableField: "enable_thinking"
|
|
2261
|
+
}
|
|
2262
|
+
},
|
|
2263
|
+
contextWindowSize: 1e6
|
|
2264
|
+
},
|
|
2265
|
+
{
|
|
2266
|
+
id: "deepseek-v4-flash-0731",
|
|
2267
|
+
capabilities: {
|
|
2268
|
+
reasoning: {
|
|
2269
|
+
thinking: true,
|
|
2270
|
+
efforts: ["low", "high", "max"],
|
|
2271
|
+
defaultEffort: "high",
|
|
2272
|
+
disableField: "enable_thinking"
|
|
2273
|
+
}
|
|
2274
|
+
},
|
|
2275
|
+
contextWindowSize: 1e6
|
|
2276
|
+
},
|
|
2277
|
+
{
|
|
2278
|
+
id: "deepseek-v3.2",
|
|
2279
|
+
capabilities: {
|
|
2280
|
+
reasoning: {
|
|
2281
|
+
thinking: true,
|
|
2282
|
+
toggleOnly: true,
|
|
2283
|
+
disableField: "enable_thinking"
|
|
2284
|
+
}
|
|
2285
|
+
},
|
|
2286
|
+
contextWindowSize: 131072
|
|
2287
|
+
},
|
|
2288
|
+
{
|
|
2289
|
+
id: "kimi-k2.7-code",
|
|
2290
|
+
capabilities: {
|
|
2291
|
+
reasoning: {
|
|
2292
|
+
thinking: true,
|
|
2293
|
+
toggleOnly: true,
|
|
2294
|
+
canDisable: false,
|
|
2295
|
+
disableField: "enable_thinking"
|
|
2296
|
+
}
|
|
2297
|
+
},
|
|
2298
|
+
contextWindowSize: 262144,
|
|
2299
|
+
enableThinking: true,
|
|
2300
|
+
modalities: { image: true, video: true },
|
|
2301
|
+
thinkingMandatory: true
|
|
2302
|
+
},
|
|
2303
|
+
{
|
|
2304
|
+
id: "kimi-k2.6",
|
|
2305
|
+
capabilities: {
|
|
2306
|
+
reasoning: {
|
|
2307
|
+
thinking: true,
|
|
2308
|
+
toggleOnly: true,
|
|
2309
|
+
disableField: "enable_thinking"
|
|
2310
|
+
}
|
|
2311
|
+
},
|
|
2312
|
+
contextWindowSize: 262144,
|
|
2313
|
+
enableThinking: true
|
|
2314
|
+
},
|
|
2315
|
+
{
|
|
2316
|
+
id: "kimi-k2.5",
|
|
2317
|
+
capabilities: {
|
|
2318
|
+
reasoning: {
|
|
2319
|
+
thinking: true,
|
|
2320
|
+
toggleOnly: true,
|
|
2321
|
+
disableField: "enable_thinking"
|
|
2322
|
+
}
|
|
2323
|
+
},
|
|
2324
|
+
contextWindowSize: 262144,
|
|
2325
|
+
enableThinking: true,
|
|
2326
|
+
modalities: { image: true, video: true }
|
|
2327
|
+
},
|
|
2328
|
+
{ id: "glm-5.2", contextWindowSize: 1e6, enableThinking: true },
|
|
2329
|
+
{ id: "glm-5.1", contextWindowSize: 202752, enableThinking: true },
|
|
2330
|
+
{ id: "glm-5", contextWindowSize: 202752, enableThinking: true },
|
|
2331
|
+
{ id: "MiniMax-M2.5", contextWindowSize: 196608 },
|
|
2332
|
+
{
|
|
2333
|
+
id: "qwen3.8-flash",
|
|
2334
|
+
contextWindowSize: 1e6,
|
|
2335
|
+
capabilities: {
|
|
2336
|
+
reasoning: {
|
|
2337
|
+
thinking: true,
|
|
2338
|
+
efforts: ["low", "medium", "xhigh"],
|
|
2339
|
+
defaultEffort: "xhigh",
|
|
2340
|
+
disableField: "reasoning_effort"
|
|
2341
|
+
}
|
|
2342
|
+
},
|
|
2343
|
+
modalities: { image: true, video: true }
|
|
2344
|
+
},
|
|
2345
|
+
{
|
|
2346
|
+
id: "deepseek-v4-pro-0813",
|
|
2347
|
+
contextWindowSize: 1e6,
|
|
2348
|
+
capabilities: {
|
|
2349
|
+
reasoning: {
|
|
2350
|
+
thinking: true,
|
|
2351
|
+
efforts: ["low", "high", "max"],
|
|
2352
|
+
defaultEffort: "high",
|
|
2353
|
+
disableField: "enable_thinking"
|
|
2354
|
+
}
|
|
2355
|
+
}
|
|
2356
|
+
}
|
|
2357
|
+
];
|
|
2358
|
+
var tokenPlanProvider = {
|
|
2359
|
+
id: "token-plan",
|
|
2360
|
+
label: "Token Plan",
|
|
2361
|
+
description: "For teams and companies \xB7 Usage-based billing with dedicated endpoint",
|
|
2362
|
+
protocol: "openai" /* USE_OPENAI */,
|
|
2363
|
+
baseUrl: [
|
|
2364
|
+
{
|
|
2365
|
+
id: "cn-beijing",
|
|
2366
|
+
label: "China (Beijing)",
|
|
2367
|
+
url: TOKEN_PLAN_CHINA_BASE_URL,
|
|
2368
|
+
documentationUrl: "https://bailian.console.aliyun.com/cn-beijing?tab=doc#/doc/?type=model&url=3028856"
|
|
2369
|
+
},
|
|
2370
|
+
{
|
|
2371
|
+
id: "ap-southeast-1",
|
|
2372
|
+
label: "Singapore (International)",
|
|
2373
|
+
url: TOKEN_PLAN_GLOBAL_BASE_URL,
|
|
2374
|
+
documentationUrl: "https://modelstudio.console.alibabacloud.com/ap-southeast-1?tab=doc#/doc/?type=model"
|
|
2375
|
+
}
|
|
2376
|
+
],
|
|
2377
|
+
envKey: TOKEN_PLAN_ENV_KEY,
|
|
2378
|
+
models: TOKEN_PLAN_MODELS,
|
|
2379
|
+
modelsEditable: true,
|
|
2380
|
+
supportsModelDiscovery: true,
|
|
2381
|
+
modelNamePrefix: /* @__PURE__ */ __name((baseUrl) => baseUrl === TOKEN_PLAN_GLOBAL_BASE_URL ? "ModelStudio Token Plan for Global/Intl" : "ModelStudio Token Plan", "modelNamePrefix"),
|
|
2382
|
+
ownsModel: /* @__PURE__ */ __name((model) => model.envKey === TOKEN_PLAN_ENV_KEY && (typeof model.baseUrl === "string" && (model.baseUrl === TOKEN_PLAN_CHINA_BASE_URL || model.baseUrl === TOKEN_PLAN_GLOBAL_BASE_URL) || typeof model.name === "string" && model.name.startsWith("[ModelStudio Token Plan]")), "ownsModel"),
|
|
2383
|
+
// Same server-side search tools as the Standard endpoints, billed against
|
|
2384
|
+
// the plan's quota (probe 2026-09-08: `web_search` + `web_extractor` both
|
|
2385
|
+
// execute and are reported under `usage.x_tools`).
|
|
2386
|
+
webSearch: { backend: "dashscope" },
|
|
2387
|
+
uiGroup: "alibaba",
|
|
2388
|
+
uiLabels: { flowTitle: "Alibaba ModelStudio", baseUrlStepTitle: "Region" }
|
|
2389
|
+
};
|
|
2390
|
+
|
|
2391
|
+
// packages/core/src/providers/presets/alibaba-standard.ts
|
|
2392
|
+
init_esbuild_shims();
|
|
2393
|
+
var alibabaStandardProvider = {
|
|
2394
|
+
id: "alibabaStandard",
|
|
2395
|
+
label: "Standard API Key",
|
|
2396
|
+
description: "Connect with an existing ModelStudio API key",
|
|
2397
|
+
protocol: "openai" /* USE_OPENAI */,
|
|
2398
|
+
baseUrl: [
|
|
2399
|
+
{
|
|
2400
|
+
id: "cn-beijing",
|
|
2401
|
+
label: "China (Beijing)",
|
|
2402
|
+
url: "https://dashscope.aliyuncs.com/compatible-mode/v1",
|
|
2403
|
+
documentationUrl: "https://bailian.console.aliyun.com/cn-beijing?tab=api#/api"
|
|
2404
|
+
},
|
|
2405
|
+
{
|
|
2406
|
+
id: "sg-singapore",
|
|
2407
|
+
label: "Singapore",
|
|
2408
|
+
url: "https://dashscope-intl.aliyuncs.com/compatible-mode/v1",
|
|
2409
|
+
documentationUrl: "https://modelstudio.console.alibabacloud.com/ap-southeast-1?tab=api#/api/?type=model&url=2712195"
|
|
2410
|
+
},
|
|
2411
|
+
{
|
|
2412
|
+
id: "us-virginia",
|
|
2413
|
+
label: "US (Virginia)",
|
|
2414
|
+
url: "https://dashscope-us.aliyuncs.com/compatible-mode/v1",
|
|
2415
|
+
documentationUrl: "https://modelstudio.console.alibabacloud.com/us-east-1?tab=api#/api/?type=model&url=2712195"
|
|
2416
|
+
},
|
|
2417
|
+
{
|
|
2418
|
+
id: "cn-hongkong",
|
|
2419
|
+
label: "China (Hong Kong)",
|
|
2420
|
+
url: "https://cn-hongkong.dashscope.aliyuncs.com/compatible-mode/v1",
|
|
2421
|
+
documentationUrl: "https://modelstudio.console.alibabacloud.com/cn-hongkong?tab=api#/api/?type=model&url=2712195"
|
|
2422
|
+
}
|
|
2423
|
+
],
|
|
2424
|
+
envKey: "DASHSCOPE_API_KEY",
|
|
2425
|
+
models: [
|
|
2426
|
+
{
|
|
2427
|
+
id: "qwen3.6-plus",
|
|
2428
|
+
capabilities: {
|
|
2429
|
+
reasoning: {
|
|
2430
|
+
thinking: true,
|
|
2431
|
+
toggleOnly: true,
|
|
2432
|
+
disableField: "enable_thinking"
|
|
2433
|
+
}
|
|
2434
|
+
},
|
|
2435
|
+
contextWindowSize: 1e6,
|
|
2436
|
+
enableThinking: true
|
|
2437
|
+
},
|
|
2438
|
+
{
|
|
2439
|
+
id: "qwen3.7-plus",
|
|
2440
|
+
capabilities: {
|
|
2441
|
+
reasoning: {
|
|
2442
|
+
thinking: true,
|
|
2443
|
+
toggleOnly: true,
|
|
2444
|
+
disableField: "enable_thinking"
|
|
2445
|
+
}
|
|
2446
|
+
},
|
|
2447
|
+
contextWindowSize: 1e6,
|
|
2448
|
+
enableThinking: true
|
|
2449
|
+
},
|
|
2450
|
+
{
|
|
2451
|
+
id: "qwen3.7-max",
|
|
2452
|
+
capabilities: {
|
|
2453
|
+
reasoning: {
|
|
2454
|
+
thinking: true,
|
|
2455
|
+
toggleOnly: true,
|
|
2456
|
+
disableField: "enable_thinking"
|
|
2457
|
+
}
|
|
2458
|
+
},
|
|
2459
|
+
contextWindowSize: 1e6,
|
|
2460
|
+
enableThinking: true
|
|
2461
|
+
},
|
|
2462
|
+
{ id: "glm-5.1", contextWindowSize: 202752, enableThinking: true },
|
|
2463
|
+
{
|
|
2464
|
+
id: "deepseek-v4-pro",
|
|
2465
|
+
capabilities: {
|
|
2466
|
+
reasoning: {
|
|
2467
|
+
thinking: true,
|
|
2468
|
+
efforts: ["high", "max"],
|
|
2469
|
+
defaultEffort: "high",
|
|
2470
|
+
disableField: "enable_thinking"
|
|
2471
|
+
}
|
|
2472
|
+
},
|
|
2473
|
+
contextWindowSize: 1e6
|
|
2474
|
+
},
|
|
2475
|
+
{
|
|
2476
|
+
id: "deepseek-v4-flash",
|
|
2477
|
+
capabilities: {
|
|
2478
|
+
reasoning: {
|
|
2479
|
+
thinking: true,
|
|
2480
|
+
efforts: ["high", "max"],
|
|
2481
|
+
defaultEffort: "high",
|
|
2482
|
+
disableField: "enable_thinking"
|
|
2483
|
+
}
|
|
2484
|
+
},
|
|
2485
|
+
contextWindowSize: 1e6
|
|
2486
|
+
},
|
|
2487
|
+
{
|
|
2488
|
+
id: "qwen3.8-max",
|
|
2489
|
+
contextWindowSize: 1e6,
|
|
2490
|
+
capabilities: {
|
|
2491
|
+
reasoning: {
|
|
2492
|
+
thinking: true,
|
|
2493
|
+
efforts: ["low", "medium", "xhigh"],
|
|
2494
|
+
defaultEffort: "xhigh",
|
|
2495
|
+
disableField: "reasoning_effort"
|
|
2496
|
+
}
|
|
2497
|
+
},
|
|
2498
|
+
modalities: { image: true, video: true }
|
|
2499
|
+
},
|
|
2500
|
+
{
|
|
2501
|
+
id: "qwen3.8-max-0902",
|
|
2502
|
+
contextWindowSize: 1e6,
|
|
2503
|
+
capabilities: {
|
|
2504
|
+
reasoning: {
|
|
2505
|
+
thinking: true,
|
|
2506
|
+
efforts: ["low", "medium", "xhigh"],
|
|
2507
|
+
defaultEffort: "xhigh",
|
|
2508
|
+
disableField: "reasoning_effort"
|
|
2509
|
+
}
|
|
2510
|
+
},
|
|
2511
|
+
modalities: { image: true, video: true }
|
|
2512
|
+
},
|
|
2513
|
+
{
|
|
2514
|
+
id: "qwen3.8-flash",
|
|
2515
|
+
contextWindowSize: 1e6,
|
|
2516
|
+
capabilities: {
|
|
2517
|
+
reasoning: {
|
|
2518
|
+
thinking: true,
|
|
2519
|
+
efforts: ["low", "medium", "xhigh"],
|
|
2520
|
+
defaultEffort: "xhigh",
|
|
2521
|
+
disableField: "reasoning_effort"
|
|
2522
|
+
}
|
|
2523
|
+
},
|
|
2524
|
+
modalities: { image: true, video: true }
|
|
2525
|
+
},
|
|
2526
|
+
{
|
|
2527
|
+
id: "deepseek-v4-pro-0813",
|
|
2528
|
+
contextWindowSize: 1e6,
|
|
2529
|
+
capabilities: {
|
|
2530
|
+
reasoning: {
|
|
2531
|
+
thinking: true,
|
|
2532
|
+
efforts: ["low", "high", "max"],
|
|
2533
|
+
defaultEffort: "high",
|
|
2534
|
+
disableField: "enable_thinking"
|
|
2535
|
+
}
|
|
2536
|
+
}
|
|
2537
|
+
},
|
|
2538
|
+
{
|
|
2539
|
+
id: "deepseek-v4-flash-0731",
|
|
2540
|
+
contextWindowSize: 1e6,
|
|
2541
|
+
capabilities: {
|
|
2542
|
+
reasoning: {
|
|
2543
|
+
thinking: true,
|
|
2544
|
+
efforts: ["low", "high", "max"],
|
|
2545
|
+
defaultEffort: "high",
|
|
2546
|
+
disableField: "enable_thinking"
|
|
2547
|
+
}
|
|
2548
|
+
}
|
|
2549
|
+
},
|
|
2550
|
+
{
|
|
2551
|
+
id: "kimi-k3",
|
|
2552
|
+
thinkingMandatory: true,
|
|
2553
|
+
contextWindowSize: 1e6,
|
|
2554
|
+
capabilities: {
|
|
2555
|
+
reasoning: {
|
|
2556
|
+
thinking: true,
|
|
2557
|
+
efforts: ["low", "high", "max"],
|
|
2558
|
+
defaultEffort: "max",
|
|
2559
|
+
canDisable: false,
|
|
2560
|
+
disableField: "reasoning_effort"
|
|
2561
|
+
}
|
|
2562
|
+
},
|
|
2563
|
+
modalities: { image: true }
|
|
2564
|
+
},
|
|
2565
|
+
{
|
|
2566
|
+
id: "kimi-k2.7-code",
|
|
2567
|
+
thinkingMandatory: true,
|
|
2568
|
+
enableThinking: true,
|
|
2569
|
+
contextWindowSize: 262144,
|
|
2570
|
+
capabilities: {
|
|
2571
|
+
reasoning: {
|
|
2572
|
+
thinking: true,
|
|
2573
|
+
toggleOnly: true,
|
|
2574
|
+
canDisable: false,
|
|
2575
|
+
disableField: "enable_thinking"
|
|
2576
|
+
}
|
|
2577
|
+
},
|
|
2578
|
+
modalities: { image: true, video: true }
|
|
2579
|
+
},
|
|
2580
|
+
{
|
|
2581
|
+
id: "kimi-k2.6",
|
|
2582
|
+
enableThinking: true,
|
|
2583
|
+
contextWindowSize: 262144,
|
|
2584
|
+
capabilities: {
|
|
2585
|
+
reasoning: {
|
|
2586
|
+
thinking: true,
|
|
2587
|
+
toggleOnly: true,
|
|
2588
|
+
disableField: "enable_thinking"
|
|
2589
|
+
}
|
|
2590
|
+
},
|
|
2591
|
+
modalities: { image: true, video: true }
|
|
2592
|
+
}
|
|
2593
|
+
],
|
|
2594
|
+
modelsEditable: true,
|
|
2595
|
+
modelNamePrefix: "ModelStudio Standard",
|
|
2596
|
+
// The Responses API on these endpoints serves the server-side `web_search`
|
|
2597
|
+
// / `web_extractor` tools with the same key, so the built-in tool needs no
|
|
2598
|
+
// extra configuration.
|
|
2599
|
+
webSearch: { backend: "dashscope" },
|
|
2600
|
+
uiGroup: "alibaba",
|
|
2601
|
+
uiLabels: { flowTitle: "Alibaba ModelStudio", baseUrlStepTitle: "Region" }
|
|
2602
|
+
};
|
|
2603
|
+
|
|
2604
|
+
// packages/core/src/providers/presets/openrouter.ts
|
|
2605
|
+
init_esbuild_shims();
|
|
2606
|
+
var OPENROUTER_ENV_KEY = "OPENROUTER_API_KEY";
|
|
2607
|
+
var OPENROUTER_BASE_URL = "https://openrouter.ai/api/v1";
|
|
2608
|
+
var openRouterProvider = {
|
|
2609
|
+
id: "openrouter",
|
|
2610
|
+
label: "OpenRouter",
|
|
2611
|
+
description: "Connect with an OpenRouter API key (get one from openrouter.ai/keys)",
|
|
2612
|
+
protocol: "openai" /* USE_OPENAI */,
|
|
2613
|
+
baseUrl: OPENROUTER_BASE_URL,
|
|
2614
|
+
envKey: OPENROUTER_ENV_KEY,
|
|
2615
|
+
models: [
|
|
2616
|
+
{ id: "z-ai/glm-4.5-air:free", contextWindowSize: 128e3 },
|
|
2617
|
+
{ id: "openai/gpt-oss-120b:free", contextWindowSize: 131072 }
|
|
2618
|
+
],
|
|
2619
|
+
modelsEditable: true,
|
|
2620
|
+
modelNamePrefix: "OpenRouter",
|
|
2621
|
+
ownsModel: /* @__PURE__ */ __name((model) => {
|
|
2622
|
+
if (model.envKey !== OPENROUTER_ENV_KEY) return false;
|
|
2623
|
+
try {
|
|
2624
|
+
const host = new URL(model.baseUrl ?? "").hostname;
|
|
2625
|
+
return host === "openrouter.ai" || host.endsWith(".openrouter.ai");
|
|
2626
|
+
} catch {
|
|
2627
|
+
return false;
|
|
2628
|
+
}
|
|
2629
|
+
}, "ownsModel"),
|
|
2630
|
+
customHeaders: {
|
|
2631
|
+
"HTTP-Referer": "https://github.com/QwenLM/qwen-code.git",
|
|
2632
|
+
"X-OpenRouter-Title": "Qwen Code"
|
|
2633
|
+
},
|
|
2634
|
+
documentationUrl: "https://openrouter.ai/docs",
|
|
2635
|
+
uiGroup: "third-party"
|
|
2636
|
+
};
|
|
2637
|
+
|
|
2638
|
+
// packages/core/src/providers/presets/requesty.ts
|
|
2639
|
+
init_esbuild_shims();
|
|
2640
|
+
var REQUESTY_ENV_KEY = "REQUESTY_API_KEY";
|
|
2641
|
+
var REQUESTY_BASE_URL = "https://router.requesty.ai/v1";
|
|
2642
|
+
var requestyProvider = {
|
|
2643
|
+
id: "requesty",
|
|
2644
|
+
label: "Requesty",
|
|
2645
|
+
description: "Connect with a Requesty API key (get one from app.requesty.ai/api-keys)",
|
|
2646
|
+
protocol: "openai" /* USE_OPENAI */,
|
|
2647
|
+
baseUrl: REQUESTY_BASE_URL,
|
|
2648
|
+
envKey: REQUESTY_ENV_KEY,
|
|
2649
|
+
models: [
|
|
2650
|
+
{ id: "openai/gpt-4o-mini", contextWindowSize: 128e3 },
|
|
2651
|
+
{ id: "openai/gpt-4o", contextWindowSize: 128e3 }
|
|
2652
|
+
],
|
|
2653
|
+
modelsEditable: true,
|
|
2654
|
+
modelNamePrefix: "Requesty",
|
|
2655
|
+
ownsModel: /* @__PURE__ */ __name((model) => {
|
|
2656
|
+
if (model.envKey !== REQUESTY_ENV_KEY) return false;
|
|
2657
|
+
try {
|
|
2658
|
+
const host = new URL(model.baseUrl ?? "").hostname;
|
|
2659
|
+
return host === "router.requesty.ai" || host.endsWith(".requesty.ai");
|
|
2660
|
+
} catch {
|
|
2661
|
+
return false;
|
|
2662
|
+
}
|
|
2663
|
+
}, "ownsModel"),
|
|
2664
|
+
customHeaders: {
|
|
2665
|
+
"HTTP-Referer": "https://github.com/QwenLM/qwen-code.git",
|
|
2666
|
+
"X-Title": "Qwen Code"
|
|
2667
|
+
},
|
|
2668
|
+
documentationUrl: "https://docs.requesty.ai",
|
|
2669
|
+
uiGroup: "third-party"
|
|
2670
|
+
};
|
|
2671
|
+
|
|
2672
|
+
// packages/core/src/providers/presets/deepseek.ts
|
|
2673
|
+
init_esbuild_shims();
|
|
2674
|
+
var deepseekProvider = {
|
|
2675
|
+
id: "deepseek",
|
|
2676
|
+
label: "DeepSeek API Key",
|
|
2677
|
+
description: "Quick setup for DeepSeek (deepseek-v4-flash, deepseek-v4-pro)",
|
|
2678
|
+
protocol: "openai" /* USE_OPENAI */,
|
|
2679
|
+
baseUrl: "https://api.deepseek.com",
|
|
2680
|
+
envKey: "DEEPSEEK_API_KEY",
|
|
2681
|
+
models: [
|
|
2682
|
+
{
|
|
2683
|
+
id: "deepseek-v4-pro",
|
|
2684
|
+
contextWindowSize: 1e6,
|
|
2685
|
+
capabilities: {
|
|
2686
|
+
reasoning: {
|
|
2687
|
+
thinking: true,
|
|
2688
|
+
efforts: ["low", "high", "max"],
|
|
2689
|
+
defaultEffort: "high",
|
|
2690
|
+
disableField: "thinking"
|
|
2691
|
+
}
|
|
2692
|
+
}
|
|
2693
|
+
},
|
|
2694
|
+
{
|
|
2695
|
+
id: "deepseek-v4-flash",
|
|
2696
|
+
capabilities: {
|
|
2697
|
+
reasoning: {
|
|
2698
|
+
thinking: true,
|
|
2699
|
+
efforts: ["low", "high", "max"],
|
|
2700
|
+
defaultEffort: "high",
|
|
2701
|
+
disableField: "thinking"
|
|
2702
|
+
}
|
|
2703
|
+
},
|
|
2704
|
+
contextWindowSize: 1e6
|
|
2705
|
+
}
|
|
2706
|
+
],
|
|
2707
|
+
modelsEditable: true,
|
|
2708
|
+
modelNamePrefix: "DeepSeek",
|
|
2709
|
+
documentationUrl: "https://api-docs.deepseek.com/zh-cn/",
|
|
2710
|
+
uiGroup: "third-party"
|
|
2711
|
+
};
|
|
2712
|
+
|
|
2713
|
+
// packages/core/src/providers/presets/grok.ts
|
|
2714
|
+
init_esbuild_shims();
|
|
2715
|
+
var GROK_ENV_KEY = "XAI_API_KEY";
|
|
2716
|
+
var GROK_BASE_URL = "https://api.x.ai/v1";
|
|
2717
|
+
var grokProvider = {
|
|
2718
|
+
id: "grok",
|
|
2719
|
+
label: "Grok (xAI) API Key",
|
|
2720
|
+
description: "Quick setup for xAI Grok chat & code models",
|
|
2721
|
+
protocol: "openai" /* USE_OPENAI */,
|
|
2722
|
+
baseUrl: GROK_BASE_URL,
|
|
2723
|
+
envKey: GROK_ENV_KEY,
|
|
2724
|
+
// xAI's API follows the standard OpenAI format. Grok models reason by
|
|
2725
|
+
// default (grok-4.5 exposes an optional reasoning_effort knob, default
|
|
2726
|
+
// high) and have no Qwen-style enable_thinking toggle, so the preset
|
|
2727
|
+
// carries only each model's context window.
|
|
2728
|
+
models: [
|
|
2729
|
+
{ id: "grok-4.5", contextWindowSize: 5e5 },
|
|
2730
|
+
{ id: "grok-4.3", contextWindowSize: 1e6 },
|
|
2731
|
+
{ id: "grok-4.20-0309-reasoning", contextWindowSize: 1e6 },
|
|
2732
|
+
{ id: "grok-4.20-0309-non-reasoning", contextWindowSize: 1e6 },
|
|
2733
|
+
{ id: "grok-4.20-multi-agent-0309", contextWindowSize: 1e6 },
|
|
2734
|
+
{ id: "grok-build-0.1", contextWindowSize: 262144 }
|
|
2735
|
+
],
|
|
2736
|
+
modelsEditable: true,
|
|
2737
|
+
modelNamePrefix: "Grok",
|
|
2738
|
+
documentationUrl: "https://docs.x.ai/docs",
|
|
2739
|
+
uiGroup: "third-party"
|
|
2740
|
+
};
|
|
2741
|
+
|
|
2742
|
+
// packages/core/src/providers/presets/minimax.ts
|
|
2743
|
+
init_esbuild_shims();
|
|
2744
|
+
var minimaxProvider = {
|
|
2745
|
+
id: "minimax",
|
|
2746
|
+
label: "MiniMax API Key",
|
|
2747
|
+
description: "Quick setup for MiniMax models",
|
|
2748
|
+
protocol: "openai" /* USE_OPENAI */,
|
|
2749
|
+
baseUrl: [
|
|
2750
|
+
{
|
|
2751
|
+
id: "international",
|
|
2752
|
+
label: "International",
|
|
2753
|
+
url: "https://api.minimax.io/v1",
|
|
2754
|
+
documentationUrl: "https://www.minimax.io/platform"
|
|
2755
|
+
},
|
|
2756
|
+
{
|
|
2757
|
+
id: "china",
|
|
2758
|
+
label: "China",
|
|
2759
|
+
url: "https://api.minimaxi.com/v1",
|
|
2760
|
+
documentationUrl: "https://platform.minimaxi.com"
|
|
2761
|
+
}
|
|
2762
|
+
],
|
|
2763
|
+
envKey: "MINIMAX_API_KEY",
|
|
2764
|
+
models: [
|
|
2765
|
+
{
|
|
2766
|
+
id: "MiniMax-M3",
|
|
2767
|
+
contextWindowSize: 1e6,
|
|
2768
|
+
modalities: { image: true, video: true }
|
|
2769
|
+
},
|
|
2770
|
+
{ id: "MiniMax-M2.7", contextWindowSize: 204800 },
|
|
2771
|
+
{ id: "MiniMax-M2.7-highspeed", contextWindowSize: 204800 },
|
|
2772
|
+
{ id: "MiniMax-M2.5", contextWindowSize: 196608 },
|
|
2773
|
+
{ id: "MiniMax-M2.5-highspeed", contextWindowSize: 196608 },
|
|
2774
|
+
{ id: "image-01", imageOnly: true },
|
|
2775
|
+
{ id: "image-01-live", imageOnly: true }
|
|
2776
|
+
],
|
|
2777
|
+
modelsEditable: true,
|
|
2778
|
+
modelNamePrefix: "MiniMax",
|
|
2779
|
+
uiGroup: "third-party"
|
|
2780
|
+
};
|
|
2781
|
+
|
|
2782
|
+
// packages/core/src/providers/presets/zai.ts
|
|
2783
|
+
init_esbuild_shims();
|
|
2784
|
+
var zaiProvider = {
|
|
2785
|
+
id: "zai",
|
|
2786
|
+
label: "Z.AI API Key",
|
|
2787
|
+
description: "Quick setup for Z.AI models",
|
|
2788
|
+
protocol: "openai" /* USE_OPENAI */,
|
|
2789
|
+
baseUrl: [
|
|
2790
|
+
{
|
|
2791
|
+
id: "standard-api-key",
|
|
2792
|
+
label: "Standard API Key",
|
|
2793
|
+
url: "https://api.z.ai/api/paas/v4",
|
|
2794
|
+
documentationUrl: "https://docs.z.ai/"
|
|
2795
|
+
},
|
|
2796
|
+
{
|
|
2797
|
+
id: "coding-plan",
|
|
2798
|
+
label: "Coding Plan",
|
|
2799
|
+
url: "https://api.z.ai/api/coding/paas/v4",
|
|
2800
|
+
documentationUrl: "https://docs.z.ai/"
|
|
2801
|
+
}
|
|
2802
|
+
],
|
|
2803
|
+
envKey: "ZAI_API_KEY",
|
|
2804
|
+
models: [
|
|
2805
|
+
{ id: "GLM-5.2", contextWindowSize: 1e6, enableThinking: true },
|
|
2806
|
+
{ id: "GLM-5.1", contextWindowSize: 204800, enableThinking: true },
|
|
2807
|
+
{ id: "GLM-5", contextWindowSize: 204800 },
|
|
2808
|
+
{ id: "GLM-5-Turbo", contextWindowSize: 204800 }
|
|
2809
|
+
],
|
|
2810
|
+
modelsEditable: true,
|
|
2811
|
+
modelNamePrefix: "Z.AI",
|
|
2812
|
+
uiGroup: "third-party"
|
|
2813
|
+
};
|
|
2814
|
+
|
|
2815
|
+
// packages/core/src/providers/presets/moonshot.ts
|
|
2816
|
+
init_esbuild_shims();
|
|
2817
|
+
var moonshotProvider = {
|
|
2818
|
+
id: "moonshot",
|
|
2819
|
+
label: "Kimi (Moonshot AI) API Key",
|
|
2820
|
+
description: "Quick setup for Kimi models",
|
|
2821
|
+
protocol: "openai" /* USE_OPENAI */,
|
|
2822
|
+
baseUrl: [
|
|
2823
|
+
{
|
|
2824
|
+
id: "international",
|
|
2825
|
+
label: "International",
|
|
2826
|
+
url: "https://api.moonshot.ai/v1",
|
|
2827
|
+
documentationUrl: "https://platform.kimi.ai/docs"
|
|
2828
|
+
},
|
|
2829
|
+
{
|
|
2830
|
+
id: "china",
|
|
2831
|
+
label: "China",
|
|
2832
|
+
url: "https://api.moonshot.cn/v1",
|
|
2833
|
+
documentationUrl: "https://platform.moonshot.cn/docs"
|
|
2834
|
+
}
|
|
2835
|
+
],
|
|
2836
|
+
envKey: "MOONSHOT_API_KEY",
|
|
2837
|
+
models: [
|
|
2838
|
+
{
|
|
2839
|
+
id: "kimi-k3",
|
|
2840
|
+
capabilities: {
|
|
2841
|
+
reasoning: {
|
|
2842
|
+
thinking: true,
|
|
2843
|
+
efforts: ["low", "high", "max"],
|
|
2844
|
+
defaultEffort: "max",
|
|
2845
|
+
canDisable: false,
|
|
2846
|
+
disableField: "reasoning_effort"
|
|
2847
|
+
}
|
|
2848
|
+
},
|
|
2849
|
+
contextWindowSize: 1e6,
|
|
2850
|
+
// K3 always thinks: the API exposes `reasoning_effort` but no way to
|
|
2851
|
+
// turn thinking off, so never emit a disable shape on the wire.
|
|
2852
|
+
thinkingMandatory: true,
|
|
2853
|
+
modalities: { image: true, video: true }
|
|
2854
|
+
},
|
|
2855
|
+
{
|
|
2856
|
+
id: "kimi-k2.7-code",
|
|
2857
|
+
capabilities: {
|
|
2858
|
+
reasoning: {
|
|
2859
|
+
thinking: true,
|
|
2860
|
+
toggleOnly: true,
|
|
2861
|
+
canDisable: false,
|
|
2862
|
+
disableField: "thinking"
|
|
2863
|
+
}
|
|
2864
|
+
},
|
|
2865
|
+
contextWindowSize: 262144,
|
|
2866
|
+
modalities: { image: true, video: true },
|
|
2867
|
+
thinkingMandatory: true
|
|
2868
|
+
},
|
|
2869
|
+
{
|
|
2870
|
+
id: "kimi-k2.7-code-highspeed",
|
|
2871
|
+
capabilities: {
|
|
2872
|
+
reasoning: {
|
|
2873
|
+
thinking: true,
|
|
2874
|
+
toggleOnly: true,
|
|
2875
|
+
canDisable: false,
|
|
2876
|
+
disableField: "thinking"
|
|
2877
|
+
}
|
|
2878
|
+
},
|
|
2879
|
+
contextWindowSize: 262144,
|
|
2880
|
+
modalities: { image: true, video: true },
|
|
2881
|
+
thinkingMandatory: true
|
|
2882
|
+
},
|
|
2883
|
+
{
|
|
2884
|
+
id: "kimi-k2.6",
|
|
2885
|
+
capabilities: {
|
|
2886
|
+
reasoning: {
|
|
2887
|
+
thinking: true,
|
|
2888
|
+
toggleOnly: true,
|
|
2889
|
+
disableField: "thinking"
|
|
2890
|
+
}
|
|
2891
|
+
},
|
|
2892
|
+
contextWindowSize: 262144,
|
|
2893
|
+
modalities: { image: true, video: true }
|
|
2894
|
+
}
|
|
2895
|
+
],
|
|
2896
|
+
modelsEditable: true,
|
|
2897
|
+
modelNamePrefix: "Kimi",
|
|
2898
|
+
uiGroup: "third-party"
|
|
2899
|
+
};
|
|
2900
|
+
|
|
2901
|
+
// packages/core/src/providers/presets/idealab.ts
|
|
2902
|
+
init_esbuild_shims();
|
|
2903
|
+
var idealabProvider = {
|
|
2904
|
+
id: "idealab",
|
|
2905
|
+
label: "Idealab API Key",
|
|
2906
|
+
description: "Alibaba internal LLM service (Qwen3.6-Plus-DogFooding, DeepSeek V4, Kimi K2.6)",
|
|
2907
|
+
protocol: "openai" /* USE_OPENAI */,
|
|
2908
|
+
baseUrl: "https://idealab.alibaba-inc.com/api/openai/v1",
|
|
2909
|
+
envKey: "IDEALAB_API_KEY",
|
|
2910
|
+
models: [
|
|
2911
|
+
{
|
|
2912
|
+
id: "Qwen3.6-Plus-DogFooding",
|
|
2913
|
+
contextWindowSize: 1e6,
|
|
2914
|
+
enableThinking: true,
|
|
2915
|
+
modalities: { image: true, video: true }
|
|
2916
|
+
},
|
|
2917
|
+
{
|
|
2918
|
+
id: "bailian/deepseek-v4-pro",
|
|
2919
|
+
contextWindowSize: 1e6,
|
|
2920
|
+
enableThinking: true
|
|
2921
|
+
},
|
|
2922
|
+
{
|
|
2923
|
+
id: "bailian/deepseek-v4-flash",
|
|
2924
|
+
contextWindowSize: 1e6,
|
|
2925
|
+
enableThinking: true
|
|
2926
|
+
},
|
|
2927
|
+
{
|
|
2928
|
+
id: "bailian/kimi-k2.6",
|
|
2929
|
+
contextWindowSize: 262144,
|
|
2930
|
+
enableThinking: true
|
|
2931
|
+
}
|
|
2932
|
+
],
|
|
2933
|
+
modelsEditable: true,
|
|
2934
|
+
modelNamePrefix: "Idealab",
|
|
2935
|
+
uiGroup: "third-party"
|
|
2936
|
+
};
|
|
2937
|
+
|
|
2938
|
+
// packages/core/src/providers/presets/modelscope.ts
|
|
2939
|
+
init_esbuild_shims();
|
|
2940
|
+
var modelscopeProvider = {
|
|
2941
|
+
id: "modelscope",
|
|
2942
|
+
label: "ModelScope API Key",
|
|
2943
|
+
description: "Quick setup for ModelScope API Inference",
|
|
2944
|
+
protocol: "openai" /* USE_OPENAI */,
|
|
2945
|
+
baseUrl: "https://api-inference.modelscope.cn/v1",
|
|
2946
|
+
envKey: "MODELSCOPE_API_KEY",
|
|
2947
|
+
models: [
|
|
2948
|
+
{
|
|
2949
|
+
id: "deepseek-ai/DeepSeek-V4-Flash",
|
|
2950
|
+
contextWindowSize: 1e6,
|
|
2951
|
+
enableThinking: true
|
|
2952
|
+
},
|
|
2953
|
+
{
|
|
2954
|
+
id: "Qwen/Qwen3.5-397B-A17B",
|
|
2955
|
+
contextWindowSize: 1e6,
|
|
2956
|
+
enableThinking: true
|
|
2957
|
+
},
|
|
2958
|
+
{
|
|
2959
|
+
id: "ZhipuAI/GLM-5.1",
|
|
2960
|
+
contextWindowSize: 1e6,
|
|
2961
|
+
enableThinking: true
|
|
2962
|
+
}
|
|
2963
|
+
],
|
|
2964
|
+
modelsEditable: true,
|
|
2965
|
+
modelNamePrefix: "ModelScope",
|
|
2966
|
+
documentationUrl: "https://modelscope.cn/docs/model-service/API-Inference/intro",
|
|
2967
|
+
uiGroup: "third-party"
|
|
2968
|
+
};
|
|
2969
|
+
|
|
2970
|
+
// packages/core/src/providers/presets/custom-provider.ts
|
|
2971
|
+
init_esbuild_shims();
|
|
2972
|
+
import { createHash as createHash2 } from "node:crypto";
|
|
2973
|
+
var CUSTOM_API_KEY_ENV_PREFIX = "QWEN_CUSTOM_API_KEY_";
|
|
2974
|
+
function normalizeEnvSegment(value) {
|
|
2975
|
+
const upper = value.trim().toUpperCase();
|
|
2976
|
+
let result = "";
|
|
2977
|
+
let prevWasUnderscore = false;
|
|
2978
|
+
for (let i = 0; i < upper.length; i++) {
|
|
2979
|
+
const code = upper.charCodeAt(i);
|
|
2980
|
+
const isAlphaNum = code >= 65 && code <= 90 || code >= 48 && code <= 57;
|
|
2981
|
+
if (isAlphaNum) {
|
|
2982
|
+
result += upper[i];
|
|
2983
|
+
prevWasUnderscore = false;
|
|
2984
|
+
} else if (!prevWasUnderscore) {
|
|
2985
|
+
result += "_";
|
|
2986
|
+
prevWasUnderscore = true;
|
|
2987
|
+
}
|
|
2988
|
+
}
|
|
2989
|
+
let start = 0;
|
|
2990
|
+
let end = result.length;
|
|
2991
|
+
while (start < end && result.charCodeAt(start) === 95) start++;
|
|
2992
|
+
while (end > start && result.charCodeAt(end - 1) === 95) end--;
|
|
2993
|
+
return result.slice(start, end);
|
|
2994
|
+
}
|
|
2995
|
+
__name(normalizeEnvSegment, "normalizeEnvSegment");
|
|
2996
|
+
function stripTrailingSlashes(value) {
|
|
2997
|
+
let end = value.length;
|
|
2998
|
+
while (end > 0 && value.charCodeAt(end - 1) === 47) end--;
|
|
2999
|
+
return value.slice(0, end);
|
|
3000
|
+
}
|
|
3001
|
+
__name(stripTrailingSlashes, "stripTrailingSlashes");
|
|
3002
|
+
function generateCustomEnvKey(protocol, baseUrl) {
|
|
3003
|
+
const canonicalBaseUrl = stripTrailingSlashes(baseUrl.trim());
|
|
3004
|
+
const suffix = createHash2("sha256").update(`${protocol}\0${canonicalBaseUrl}`).digest("hex").slice(0, 12).toUpperCase();
|
|
3005
|
+
return `${CUSTOM_API_KEY_ENV_PREFIX}${normalizeEnvSegment(
|
|
3006
|
+
protocol
|
|
3007
|
+
)}_${normalizeEnvSegment(baseUrl)}_${suffix}`;
|
|
3008
|
+
}
|
|
3009
|
+
__name(generateCustomEnvKey, "generateCustomEnvKey");
|
|
3010
|
+
var customProvider = {
|
|
3011
|
+
id: "custom-openai-compatible",
|
|
3012
|
+
label: "Custom Provider",
|
|
3013
|
+
description: "Manually connect a local server, proxy, or unsupported provider",
|
|
3014
|
+
protocol: "openai" /* USE_OPENAI */,
|
|
3015
|
+
protocolOptions: [
|
|
3016
|
+
"openai" /* USE_OPENAI */,
|
|
3017
|
+
"openai-responses" /* USE_OPENAI_RESPONSES */,
|
|
3018
|
+
"anthropic" /* USE_ANTHROPIC */,
|
|
3019
|
+
"gemini" /* USE_GEMINI */
|
|
3020
|
+
],
|
|
3021
|
+
baseUrl: void 0,
|
|
3022
|
+
envKey: generateCustomEnvKey,
|
|
3023
|
+
models: void 0,
|
|
3024
|
+
modelNamePrefix: "",
|
|
3025
|
+
showAdvancedConfig: true,
|
|
3026
|
+
// Detect existing custom entries by our env-key namespace for UI/ACP flows,
|
|
3027
|
+
// but merge installs by id+baseUrl so /auth can add another custom model
|
|
3028
|
+
// without deleting models from other endpoints or different models on the
|
|
3029
|
+
// same endpoint.
|
|
3030
|
+
ownsModel: /* @__PURE__ */ __name((model) => typeof model.envKey === "string" && model.envKey.startsWith(CUSTOM_API_KEY_ENV_PREFIX), "ownsModel"),
|
|
3031
|
+
mergeModelsByIdentity: true,
|
|
3032
|
+
uiGroup: "custom"
|
|
3033
|
+
};
|
|
3034
|
+
|
|
3035
|
+
// packages/core/src/providers/all-providers.ts
|
|
3036
|
+
var ALL_PROVIDERS = [
|
|
3037
|
+
codingPlanProvider,
|
|
3038
|
+
tokenPlanProvider,
|
|
3039
|
+
alibabaStandardProvider,
|
|
3040
|
+
deepseekProvider,
|
|
3041
|
+
grokProvider,
|
|
3042
|
+
minimaxProvider,
|
|
3043
|
+
zaiProvider,
|
|
3044
|
+
moonshotProvider,
|
|
3045
|
+
idealabProvider,
|
|
3046
|
+
modelscopeProvider,
|
|
3047
|
+
openRouterProvider,
|
|
3048
|
+
requestyProvider,
|
|
3049
|
+
customProvider
|
|
3050
|
+
];
|
|
3051
|
+
var ALIBABA_PROVIDERS = ALL_PROVIDERS.filter(
|
|
3052
|
+
(p) => p.uiGroup === "alibaba"
|
|
3053
|
+
);
|
|
3054
|
+
var THIRD_PARTY_PROVIDERS = ALL_PROVIDERS.filter(
|
|
3055
|
+
(p) => p.uiGroup === "third-party"
|
|
3056
|
+
);
|
|
3057
|
+
function findProviderById(id) {
|
|
3058
|
+
return ALL_PROVIDERS.find((p) => p.id === id);
|
|
3059
|
+
}
|
|
3060
|
+
__name(findProviderById, "findProviderById");
|
|
3061
|
+
function findProviderByCredentials(baseUrl, envKey) {
|
|
3062
|
+
return ALL_PROVIDERS.find(
|
|
3063
|
+
(p) => providerMatchesCredentials(p, baseUrl, envKey)
|
|
3064
|
+
);
|
|
3065
|
+
}
|
|
3066
|
+
__name(findProviderByCredentials, "findProviderByCredentials");
|
|
3067
|
+
function getAllProviderBaseUrls() {
|
|
3068
|
+
return ALL_PROVIDERS.flatMap((p) => {
|
|
3069
|
+
if (typeof p.baseUrl === "string") return [p.baseUrl];
|
|
3070
|
+
if (Array.isArray(p.baseUrl))
|
|
3071
|
+
return p.baseUrl.map((o) => o.url);
|
|
3072
|
+
return [];
|
|
3073
|
+
});
|
|
3074
|
+
}
|
|
3075
|
+
__name(getAllProviderBaseUrls, "getAllProviderBaseUrls");
|
|
3076
|
+
|
|
3077
|
+
// packages/core/src/core/reasoning-overrides.ts
|
|
3078
|
+
init_esbuild_shims();
|
|
3079
|
+
|
|
3080
|
+
// packages/core/src/core/openaiContentGenerator/provider/openrouter.ts
|
|
3081
|
+
init_esbuild_shims();
|
|
3082
|
+
function isOpenRouterHostname(contentGeneratorConfig) {
|
|
3083
|
+
const baseUrl = contentGeneratorConfig.baseUrl ?? "";
|
|
3084
|
+
if (!baseUrl) return false;
|
|
3085
|
+
try {
|
|
3086
|
+
const hostname = new URL(baseUrl).hostname.toLowerCase();
|
|
3087
|
+
return hostname === "openrouter.ai" || hostname.endsWith(".openrouter.ai");
|
|
3088
|
+
} catch {
|
|
3089
|
+
return false;
|
|
3090
|
+
}
|
|
3091
|
+
}
|
|
3092
|
+
__name(isOpenRouterHostname, "isOpenRouterHostname");
|
|
3093
|
+
|
|
3094
|
+
// packages/core/src/core/anthropic-reasoning.ts
|
|
3095
|
+
init_esbuild_shims();
|
|
3096
|
+
var CLAUDE_MODEL_FAMILIES = [
|
|
3097
|
+
"opus",
|
|
3098
|
+
"sonnet",
|
|
3099
|
+
"haiku",
|
|
3100
|
+
"fable",
|
|
3101
|
+
"mythos"
|
|
3102
|
+
];
|
|
3103
|
+
function parseClaudeModelVersion(model) {
|
|
3104
|
+
const match = model.toLowerCase().match(
|
|
3105
|
+
new RegExp(
|
|
3106
|
+
`claude-(${CLAUDE_MODEL_FAMILIES.join(
|
|
3107
|
+
"|"
|
|
3108
|
+
)})-(\\d+)(?:[-.](\\d{1,2})(?!\\d))?`
|
|
3109
|
+
)
|
|
3110
|
+
);
|
|
3111
|
+
if (!match) {
|
|
3112
|
+
return null;
|
|
3113
|
+
}
|
|
3114
|
+
return {
|
|
3115
|
+
family: match[1],
|
|
3116
|
+
major: Number.parseInt(match[2], 10),
|
|
3117
|
+
minor: match[3] ? Number.parseInt(match[3], 10) : 0
|
|
3118
|
+
};
|
|
3119
|
+
}
|
|
3120
|
+
__name(parseClaudeModelVersion, "parseClaudeModelVersion");
|
|
3121
|
+
function anthropicSupportedEffortTiers(model) {
|
|
3122
|
+
const tiers = ["low", "medium", "high"];
|
|
3123
|
+
const parsed = parseClaudeModelVersion(model);
|
|
3124
|
+
if (!parsed) {
|
|
3125
|
+
return tiers;
|
|
3126
|
+
}
|
|
3127
|
+
const { family, major, minor } = parsed;
|
|
3128
|
+
const atLeast = /* @__PURE__ */ __name((maj, min) => major > maj || major === maj && minor >= min, "atLeast");
|
|
3129
|
+
if (major >= 5 || family === "opus" && atLeast(4, 7)) {
|
|
3130
|
+
tiers.push("xhigh");
|
|
3131
|
+
}
|
|
3132
|
+
if (major >= 5 || (family === "opus" || family === "sonnet") && atLeast(4, 6)) {
|
|
3133
|
+
tiers.push("max");
|
|
3134
|
+
}
|
|
3135
|
+
return tiers;
|
|
3136
|
+
}
|
|
3137
|
+
__name(anthropicSupportedEffortTiers, "anthropicSupportedEffortTiers");
|
|
3138
|
+
|
|
3139
|
+
// packages/core/src/core/reasoning-overrides.ts
|
|
3140
|
+
var REASONING_PROFILES = [
|
|
3141
|
+
"openai-effort",
|
|
3142
|
+
"openai-reasoning",
|
|
3143
|
+
"deepseek-openai",
|
|
3144
|
+
"dashscope-effort",
|
|
3145
|
+
"dashscope-thinking",
|
|
3146
|
+
"qwen-chat-template",
|
|
3147
|
+
"anthropic-manual",
|
|
3148
|
+
"anthropic-adaptive",
|
|
3149
|
+
"deepseek-anthropic",
|
|
3150
|
+
"gemini"
|
|
3151
|
+
];
|
|
3152
|
+
function invalidReasoning(route) {
|
|
3153
|
+
throw new Error(
|
|
3154
|
+
`Model "${route.model}" capabilities.reasoning: invalid profile, efforts or defaultEffort`
|
|
3155
|
+
);
|
|
3156
|
+
}
|
|
3157
|
+
__name(invalidReasoning, "invalidReasoning");
|
|
3158
|
+
function validateReasoningDeclaration(route, declaration) {
|
|
3159
|
+
if (declaration === void 0) return void 0;
|
|
3160
|
+
if (!declaration || typeof declaration !== "object" || Array.isArray(declaration))
|
|
3161
|
+
return invalidReasoning(route);
|
|
3162
|
+
const input = declaration;
|
|
3163
|
+
if (input.profile === void 0 && ("thinking" in input || "disableField" in input))
|
|
3164
|
+
return parseModelReasoningCapabilities(input);
|
|
3165
|
+
if (!Object.keys(input).length || Object.keys(input).some(
|
|
3166
|
+
(key) => ![
|
|
3167
|
+
"profile",
|
|
3168
|
+
"efforts",
|
|
3169
|
+
"defaultEffort",
|
|
3170
|
+
"thinking",
|
|
3171
|
+
"toggleOnly",
|
|
3172
|
+
"canDisable",
|
|
3173
|
+
"disableField"
|
|
3174
|
+
].includes(key)
|
|
3175
|
+
))
|
|
3176
|
+
return invalidReasoning(route);
|
|
3177
|
+
if (input.profile !== void 0 && !REASONING_PROFILES.includes(input.profile) || input.thinking !== void 0 && input.thinking !== true || input.toggleOnly !== void 0 && typeof input.toggleOnly !== "boolean" || input.canDisable !== void 0 && input.canDisable !== false)
|
|
3178
|
+
return invalidReasoning(route);
|
|
3179
|
+
if (input.efforts !== void 0 && (!Array.isArray(input.efforts) || !input.efforts.length || input.efforts.some((tier) => !REASONING_EFFORT_TIERS.includes(tier)) || new Set(input.efforts).size !== input.efforts.length))
|
|
3180
|
+
return invalidReasoning(route);
|
|
3181
|
+
if (input.defaultEffort !== void 0 && (!REASONING_EFFORT_TIERS.includes(input.defaultEffort) || input.efforts && !input.efforts.includes(input.defaultEffort)))
|
|
3182
|
+
return invalidReasoning(route);
|
|
3183
|
+
return input;
|
|
3184
|
+
}
|
|
3185
|
+
__name(validateReasoningDeclaration, "validateReasoningDeclaration");
|
|
3186
|
+
function resolveReasoningCapabilities(route, declaration) {
|
|
3187
|
+
try {
|
|
3188
|
+
return validateReasoningCapabilities(route, declaration);
|
|
3189
|
+
} catch {
|
|
3190
|
+
return void 0;
|
|
3191
|
+
}
|
|
3192
|
+
}
|
|
3193
|
+
__name(resolveReasoningCapabilities, "resolveReasoningCapabilities");
|
|
3194
|
+
function validateReasoningCapabilities(route, declaration) {
|
|
3195
|
+
const input = validateReasoningDeclaration(route, declaration);
|
|
3196
|
+
if (!input) return void 0;
|
|
3197
|
+
if (input.profile === void 0 && "thinking" in input)
|
|
3198
|
+
return parseModelReasoningCapabilities(input);
|
|
3199
|
+
const model = normalize(route.model);
|
|
3200
|
+
const provider = ALL_PROVIDERS.find(
|
|
3201
|
+
(candidate) => typeof candidate.baseUrl === "string" ? candidate.baseUrl === route.baseUrl : candidate.baseUrl?.some((option) => option.url === route.baseUrl)
|
|
3202
|
+
);
|
|
3203
|
+
const known = (provider?.models?.find((candidate) => candidate.id === route.model) ?? provider?.models?.find((candidate) => candidate.id === model))?.capabilities?.reasoning;
|
|
3204
|
+
const inherited = parseModelReasoningCapabilities(known);
|
|
3205
|
+
if (!input.profile && inherited?.toggleOnly) {
|
|
3206
|
+
if (input.efforts || input.defaultEffort) return invalidReasoning(route);
|
|
3207
|
+
return parseModelReasoningCapabilities({ ...inherited, ...input });
|
|
3208
|
+
}
|
|
3209
|
+
const gpt = getGptReasoningCapabilities(route.model);
|
|
3210
|
+
const claude = route.authType === "anthropic" ? parseClaudeModelVersion(route.model) : void 0;
|
|
3211
|
+
if (!inherited && !gpt && !claude && !input.profile)
|
|
3212
|
+
return invalidReasoning(route);
|
|
3213
|
+
const auth = route.authType;
|
|
3214
|
+
let host = "";
|
|
3215
|
+
try {
|
|
3216
|
+
host = new URL(route.baseUrl ?? "").hostname.toLowerCase();
|
|
3217
|
+
} catch {
|
|
3218
|
+
host = "";
|
|
3219
|
+
}
|
|
3220
|
+
const dashscope = auth === "qwen-oauth" || /(^|\.)(dashscope(?:-intl|-us)?\.aliyuncs\.com|alibaba-inc\.com|aliyun-inc\.com|alicloudapi\.com)$/.test(
|
|
3221
|
+
host
|
|
3222
|
+
) || /^token-plan\..+\.maas\.aliyuncs\.com$/.test(host);
|
|
3223
|
+
const profile = input.profile ?? (auth === "gemini" || auth === "vertex-ai" ? "gemini" : auth === "openai-responses" ? "openai-reasoning" : auth === "openai" && isOpenRouterHostname(route) ? "openai-reasoning" : auth === "anthropic" ? model.includes("deepseek") ? "deepseek-anthropic" : claude && (claude.major > 4 || claude.major === 4 && claude.minor >= 6) ? "anthropic-adaptive" : "anthropic-manual" : model.startsWith("qwen") ? dashscope ? inherited?.disableField === "reasoning_effort" ? "dashscope-effort" : "dashscope-thinking" : "qwen-chat-template" : inherited?.disableField === "thinking" ? "deepseek-openai" : "openai-effort");
|
|
3224
|
+
const protocol = profile === "gemini" ? "gemini" : profile.startsWith("anthropic-") || profile === "deepseek-anthropic" ? "anthropic" : "openai";
|
|
3225
|
+
if (auth === "openai-responses" && profile !== "openai-reasoning" || auth && protocol !== (auth === "vertex-ai" ? "gemini" : auth === "qwen-oauth" || auth === "openai-responses" ? "openai" : auth))
|
|
3226
|
+
return invalidReasoning(route);
|
|
3227
|
+
const toggleOnly = profile === "dashscope-thinking" || profile === "qwen-chat-template";
|
|
3228
|
+
const disableField = !input.profile && inherited?.disableField || (toggleOnly ? "enable_thinking" : profile === "openai-effort" || profile === "dashscope-effort" ? "reasoning_effort" : "thinking");
|
|
3229
|
+
const inheritedEfforts = inherited && !inherited.toggleOnly ? inherited.efforts : gpt?.efforts ?? (claude ? anthropicSupportedEffortTiers(route.model) : void 0);
|
|
3230
|
+
const efforts = input.efforts ?? inheritedEfforts;
|
|
3231
|
+
const inheritedDefault = inherited && !inherited.toggleOnly ? inherited.defaultEffort : gpt?.defaultEffort;
|
|
3232
|
+
const defaultEffort = input.defaultEffort ?? (inheritedDefault && efforts ? clampReasoningEffort(inheritedDefault, efforts) : void 0);
|
|
3233
|
+
if (toggleOnly && (input.efforts !== void 0 || input.defaultEffort !== void 0) || !toggleOnly && (!efforts || !defaultEffort) || profile === "gemini" && efforts?.some((tier) => tier === "xhigh" || tier === "max"))
|
|
3234
|
+
return invalidReasoning(route);
|
|
3235
|
+
const result = {
|
|
3236
|
+
...input,
|
|
3237
|
+
thinking: true,
|
|
3238
|
+
profile,
|
|
3239
|
+
toggleOnly,
|
|
3240
|
+
disableField,
|
|
3241
|
+
...toggleOnly ? {} : { efforts, defaultEffort },
|
|
3242
|
+
...route.thinkingMandatory || inherited?.canDisable === false || gpt?.thinkingMandatory ? { canDisable: false } : {}
|
|
3243
|
+
};
|
|
3244
|
+
const parsed = parseModelReasoningCapabilities(result);
|
|
3245
|
+
if (!parsed) return invalidReasoning(route);
|
|
3246
|
+
return {
|
|
3247
|
+
...parsed,
|
|
3248
|
+
profile,
|
|
3249
|
+
...gpt && input.defaultEffort === void 0 ? { defaultEnabled: gpt.defaultEnabled } : {}
|
|
3250
|
+
};
|
|
3251
|
+
}
|
|
3252
|
+
__name(validateReasoningCapabilities, "validateReasoningCapabilities");
|
|
3253
|
+
function captureReasoningSnapshot(models) {
|
|
3254
|
+
return Object.freeze(
|
|
3255
|
+
models.map(
|
|
3256
|
+
(model) => Object.freeze({
|
|
3257
|
+
id: model.id,
|
|
3258
|
+
authType: model.authType,
|
|
3259
|
+
baseUrl: model.baseUrl,
|
|
3260
|
+
registryBaseUrl: model.registryBaseUrl,
|
|
3261
|
+
reasoning: model.capabilities?.reasoning && typeof model.capabilities.reasoning === "object" ? Object.freeze({
|
|
3262
|
+
...structuredClone(model.capabilities.reasoning),
|
|
3263
|
+
..."efforts" in model.capabilities.reasoning && Array.isArray(model.capabilities.reasoning.efforts) ? {
|
|
3264
|
+
efforts: Object.freeze([
|
|
3265
|
+
...model.capabilities.reasoning.efforts
|
|
3266
|
+
])
|
|
3267
|
+
} : {}
|
|
3268
|
+
}) : model.capabilities?.reasoning
|
|
3269
|
+
})
|
|
3270
|
+
)
|
|
3271
|
+
);
|
|
3272
|
+
}
|
|
3273
|
+
__name(captureReasoningSnapshot, "captureReasoningSnapshot");
|
|
3274
|
+
function resolveReasoningForModel(config, generation, model = generation.model, strict = false) {
|
|
3275
|
+
let declaration;
|
|
3276
|
+
if (generation.reasoningSnapshot) {
|
|
3277
|
+
const rows = generation.reasoningSnapshot.filter(
|
|
3278
|
+
(row2) => row2.authType === generation.authType && row2.id === model
|
|
3279
|
+
);
|
|
3280
|
+
const row = generation.reasoningRouteBaseUrl === null && model === generation.model ? rows.find((row2) => row2.registryBaseUrl === void 0) : typeof generation.reasoningRouteBaseUrl === "string" && model === generation.model ? rows.find(
|
|
3281
|
+
(row2) => row2.registryBaseUrl === generation.reasoningRouteBaseUrl
|
|
3282
|
+
) : rows.find((row2) => row2.registryBaseUrl === generation.baseUrl) ?? rows.find(
|
|
3283
|
+
(row2) => row2.registryBaseUrl === void 0 && row2.baseUrl === generation.baseUrl
|
|
3284
|
+
);
|
|
3285
|
+
declaration = row?.reasoning;
|
|
3286
|
+
} else {
|
|
3287
|
+
declaration = generation.authType ? config?.getResolvedModelConfig?.(
|
|
3288
|
+
generation.authType,
|
|
3289
|
+
model,
|
|
3290
|
+
generation.baseUrl
|
|
3291
|
+
)?.capabilities?.reasoning : void 0;
|
|
3292
|
+
}
|
|
3293
|
+
return (strict ? validateReasoningCapabilities : resolveReasoningCapabilities)(
|
|
3294
|
+
{
|
|
3295
|
+
...generation,
|
|
3296
|
+
model,
|
|
3297
|
+
thinkingMandatory: model === generation.model ? generation.thinkingMandatory : void 0
|
|
3298
|
+
},
|
|
3299
|
+
declaration
|
|
3300
|
+
);
|
|
3301
|
+
}
|
|
3302
|
+
__name(resolveReasoningForModel, "resolveReasoningForModel");
|
|
3303
|
+
function getEffectiveReasoning(generation, resolved) {
|
|
3304
|
+
if (!resolved) return generation.reasoning;
|
|
3305
|
+
if (generation.reasoning === false && resolved.canDisable !== false)
|
|
3306
|
+
return false;
|
|
3307
|
+
const selected = generation.reasoning || void 0;
|
|
3308
|
+
if (!selected && resolved.defaultEnabled === false && resolved.canDisable !== false)
|
|
3309
|
+
return false;
|
|
3310
|
+
if (resolved.toggleOnly)
|
|
3311
|
+
return selected ?? (resolved.profile ? {} : void 0);
|
|
3312
|
+
const effort = selected?.effort ?? resolved.defaultEffort;
|
|
3313
|
+
return effort ? {
|
|
3314
|
+
...selected,
|
|
3315
|
+
effort: resolved.profile && REASONING_EFFORT_TIERS.includes(effort) ? clampReasoningEffort(effort, resolved.efforts) : effort
|
|
3316
|
+
} : selected;
|
|
3317
|
+
}
|
|
3318
|
+
__name(getEffectiveReasoning, "getEffectiveReasoning");
|
|
3319
|
+
|
|
3320
|
+
// packages/core/src/core/outbound-session-id.ts
|
|
3321
|
+
init_esbuild_shims();
|
|
3322
|
+
|
|
3323
|
+
// packages/core/src/core/outbound-dynamic-headers.ts
|
|
3324
|
+
init_esbuild_shims();
|
|
3325
|
+
var debugLogger3 = createDebugLogger("OUTBOUND_CORRELATION");
|
|
3326
|
+
var PLACEHOLDERS = [{ token: "${session_id}", resolve: /* @__PURE__ */ __name((config) => config.getSessionId(), "resolve") }];
|
|
3327
|
+
var SESSION_ID_PLACEHOLDER_PATTERN = /\$(?:session_id|QWEN_CODE_SESSION_ID)(?!\w)|\$\{(?:session_id|QWEN_CODE_SESSION_ID)\}/gi;
|
|
3328
|
+
var warnedGateOff = /* @__PURE__ */ new Set();
|
|
3329
|
+
function warnIfDynamicHeadersDisabled(customHeaders, config) {
|
|
3330
|
+
try {
|
|
3331
|
+
const names = Object.entries(customHeaders ?? {}).filter(
|
|
3332
|
+
([, value]) => typeof value === "string" && hasDynamicPlaceholder(value)
|
|
3333
|
+
).map(([name]) => name);
|
|
3334
|
+
if (names.length === 0) return;
|
|
3335
|
+
if (config.getOutboundAllowDynamicHeaderValues()) return;
|
|
3336
|
+
const key = names.slice().sort().join(",");
|
|
3337
|
+
if (warnedGateOff.has(key)) return;
|
|
3338
|
+
warnedGateOff.add(key);
|
|
3339
|
+
console.warn(
|
|
3340
|
+
`customHeaders ${names.join(", ")} contain a runtime placeholder, but outboundCorrelation.allowDynamicHeaderValues is not enabled \u2014 the header(s) will not be sent. Set it to true in settings.json to allow the value to be filled in per request.`
|
|
3341
|
+
);
|
|
3342
|
+
} catch {
|
|
3343
|
+
}
|
|
3344
|
+
}
|
|
3345
|
+
__name(warnIfDynamicHeadersDisabled, "warnIfDynamicHeadersDisabled");
|
|
3346
|
+
function hasDynamicPlaceholder(value) {
|
|
3347
|
+
return value.search(SESSION_ID_PLACEHOLDER_PATTERN) !== -1;
|
|
3348
|
+
}
|
|
3349
|
+
__name(hasDynamicPlaceholder, "hasDynamicPlaceholder");
|
|
3350
|
+
function resolveDynamicHeaderValue(value, config) {
|
|
3351
|
+
if (typeof value !== "string") return void 0;
|
|
3352
|
+
if (!hasDynamicPlaceholder(value)) return value;
|
|
3353
|
+
try {
|
|
3354
|
+
if (!config.getOutboundAllowDynamicHeaderValues()) {
|
|
3355
|
+
debugLogger3.warn(
|
|
3356
|
+
`Dropping a customHeaders value containing a runtime placeholder: outboundCorrelation.allowDynamicHeaderValues is not enabled.`
|
|
3357
|
+
);
|
|
3358
|
+
return void 0;
|
|
3359
|
+
}
|
|
3360
|
+
let expanded = value.replace(
|
|
3361
|
+
SESSION_ID_PLACEHOLDER_PATTERN,
|
|
3362
|
+
"${session_id}"
|
|
3363
|
+
);
|
|
3364
|
+
for (const { token, resolve } of PLACEHOLDERS) {
|
|
3365
|
+
if (!expanded.includes(token)) continue;
|
|
3366
|
+
const resolved = resolve(config);
|
|
3367
|
+
if (!resolved) return void 0;
|
|
3368
|
+
expanded = expanded.split(token).join(resolved);
|
|
3369
|
+
}
|
|
3370
|
+
return expanded;
|
|
3371
|
+
} catch (error) {
|
|
3372
|
+
debugLogger3.warn(
|
|
3373
|
+
`Unable to expand a customHeaders placeholder: ${error instanceof Error ? error.message : String(error)}`
|
|
3374
|
+
);
|
|
3375
|
+
return void 0;
|
|
3376
|
+
}
|
|
3377
|
+
}
|
|
3378
|
+
__name(resolveDynamicHeaderValue, "resolveDynamicHeaderValue");
|
|
3379
|
+
function applyDynamicHeaderValues(headers, config) {
|
|
3380
|
+
const pending = [];
|
|
3381
|
+
headers.forEach((value, key) => {
|
|
3382
|
+
if (hasDynamicPlaceholder(value)) pending.push([key, value]);
|
|
3383
|
+
});
|
|
3384
|
+
for (const [key, value] of pending) {
|
|
3385
|
+
const resolved = resolveDynamicHeaderValue(value, config);
|
|
3386
|
+
if (resolved === void 0) {
|
|
3387
|
+
headers.delete(key);
|
|
3388
|
+
} else {
|
|
3389
|
+
headers.set(key, resolved);
|
|
3390
|
+
}
|
|
3391
|
+
}
|
|
3392
|
+
}
|
|
3393
|
+
__name(applyDynamicHeaderValues, "applyDynamicHeaderValues");
|
|
3394
|
+
function expandDynamicHeaders(customHeaders, config) {
|
|
3395
|
+
if (!customHeaders) return {};
|
|
3396
|
+
const expanded = {};
|
|
3397
|
+
for (const [key, value] of Object.entries(customHeaders)) {
|
|
3398
|
+
if (typeof value !== "string" || !hasDynamicPlaceholder(value)) continue;
|
|
3399
|
+
const resolved = resolveDynamicHeaderValue(value, config);
|
|
3400
|
+
if (resolved !== void 0) expanded[key] = resolved;
|
|
3401
|
+
}
|
|
3402
|
+
return expanded;
|
|
3403
|
+
}
|
|
3404
|
+
__name(expandDynamicHeaders, "expandDynamicHeaders");
|
|
3405
|
+
|
|
3406
|
+
// packages/core/src/core/outbound-session-id.ts
|
|
3407
|
+
var debugLogger4 = createDebugLogger("OUTBOUND_CORRELATION");
|
|
3408
|
+
var SESSION_ID_HEADER = "session_id";
|
|
3409
|
+
var SESSION_ID_HEADER_HOSTS = [
|
|
3410
|
+
"routify.alibaba-inc.com",
|
|
3411
|
+
"routify-online.alibaba-inc.com",
|
|
3412
|
+
"routify-pub.alibaba-inc.com"
|
|
3413
|
+
];
|
|
3414
|
+
function requestUrl(input) {
|
|
3415
|
+
try {
|
|
3416
|
+
if (typeof input === "string") return new URL(input);
|
|
3417
|
+
if (input instanceof URL) return input;
|
|
3418
|
+
return new URL(input.url);
|
|
3419
|
+
} catch {
|
|
3420
|
+
return void 0;
|
|
3421
|
+
}
|
|
3422
|
+
}
|
|
3423
|
+
__name(requestUrl, "requestUrl");
|
|
3424
|
+
function buildSessionIdHeaders(config, destination) {
|
|
3425
|
+
try {
|
|
3426
|
+
const url = requestUrl(destination);
|
|
3427
|
+
if (url?.protocol !== "https:" || !SESSION_ID_HEADER_HOSTS.includes(url.hostname.toLowerCase())) {
|
|
3428
|
+
return {};
|
|
3429
|
+
}
|
|
3430
|
+
const sessionId = config.getSessionId();
|
|
3431
|
+
return sessionId ? { [SESSION_ID_HEADER]: sessionId } : {};
|
|
3432
|
+
} catch (error) {
|
|
3433
|
+
debugLogger4.warn(
|
|
3434
|
+
`Unable to add ${SESSION_ID_HEADER} to outbound request: ${error instanceof Error ? error.message : String(error)}`
|
|
3435
|
+
);
|
|
3436
|
+
return {};
|
|
3437
|
+
}
|
|
3438
|
+
}
|
|
3439
|
+
__name(buildSessionIdHeaders, "buildSessionIdHeaders");
|
|
3440
|
+
function wrapFetchWithSessionId(baseFetch, config, customHeaders) {
|
|
3441
|
+
const fetchLike = baseFetch;
|
|
3442
|
+
const expandsHeaders = Object.values(customHeaders ?? {}).some(
|
|
3443
|
+
(value) => typeof value === "string" && hasDynamicPlaceholder(value)
|
|
3444
|
+
);
|
|
3445
|
+
if (expandsHeaders) warnIfDynamicHeadersDisabled(customHeaders, config);
|
|
3446
|
+
const wrapped = /* @__PURE__ */ __name(async (input, init) => {
|
|
3447
|
+
const sessionHeaders = buildSessionIdHeaders(config, input);
|
|
3448
|
+
const sessionId = sessionHeaders[SESSION_ID_HEADER];
|
|
3449
|
+
if (!sessionId && !expandsHeaders) return fetchLike(input, init);
|
|
3450
|
+
const headers = new Headers(
|
|
3451
|
+
input instanceof Request ? input.headers : void 0
|
|
3452
|
+
);
|
|
3453
|
+
new Headers(init?.headers).forEach((value, key) => headers.set(key, value));
|
|
3454
|
+
if (expandsHeaders) applyDynamicHeaderValues(headers, config);
|
|
3455
|
+
if (sessionId) headers.set(SESSION_ID_HEADER, sessionId);
|
|
3456
|
+
return fetchLike(input, { ...init, headers });
|
|
3457
|
+
}, "wrapped");
|
|
3458
|
+
return wrapped;
|
|
3459
|
+
}
|
|
3460
|
+
__name(wrapFetchWithSessionId, "wrapFetchWithSessionId");
|
|
3461
|
+
function buildSessionAwareFetch(runtimeFetch, config, customHeaders) {
|
|
3462
|
+
const baseFetch = runtimeFetch ?? globalThis.fetch;
|
|
3463
|
+
return wrapFetchWithSessionId(baseFetch, config, customHeaders);
|
|
3464
|
+
}
|
|
3465
|
+
__name(buildSessionAwareFetch, "buildSessionAwareFetch");
|
|
3466
|
+
|
|
3467
|
+
export {
|
|
3468
|
+
DISABLED_REQUEST_TIMEOUT_MS,
|
|
3469
|
+
resolveRequestTimeout,
|
|
3470
|
+
DEFAULT_STREAM_IDLE_TIMEOUT_MS,
|
|
3471
|
+
QWEN_STREAM_IDLE_TIMEOUT_MS_ENV,
|
|
3472
|
+
MAX_STREAM_GUARD_TIMEOUT_MS,
|
|
3473
|
+
DEFAULT_STREAM_MAX_LIFETIME_MS,
|
|
3474
|
+
QWEN_STREAM_MAX_LIFETIME_MS_ENV,
|
|
3475
|
+
DEFAULT_MAX_RETRIES,
|
|
3476
|
+
DEFAULT_DASHSCOPE_BASE_URL,
|
|
3477
|
+
DASHSCOPE_PROXY_BASE_URL,
|
|
3478
|
+
isOpenRouterHostname,
|
|
3479
|
+
isImageGenerationCapable,
|
|
3480
|
+
RUNTIME_SNAPSHOT_PREFIX,
|
|
3481
|
+
buildRuntimeSnapshotId,
|
|
3482
|
+
stripRuntimeSnapshotPrefix,
|
|
3483
|
+
ModelsConfig,
|
|
3484
|
+
ProviderInstallError,
|
|
3485
|
+
applyProviderInstallPlan,
|
|
3486
|
+
resolveOwnsModel,
|
|
3487
|
+
resolveMetadataKey,
|
|
3488
|
+
PROVIDER_METADATA_NS,
|
|
3489
|
+
buildInstallPlan,
|
|
3490
|
+
computeModelListVersion,
|
|
3491
|
+
getDefaultBaseUrlForProtocol,
|
|
3492
|
+
resolveBaseUrl,
|
|
3493
|
+
getDefaultModelIds,
|
|
3494
|
+
findExistingProviderModels,
|
|
3495
|
+
shouldShowStep,
|
|
3496
|
+
providerMatchesCredentials,
|
|
3497
|
+
buildProviderTemplate,
|
|
3498
|
+
customProvider,
|
|
3499
|
+
ALL_PROVIDERS,
|
|
3500
|
+
ALIBABA_PROVIDERS,
|
|
3501
|
+
THIRD_PARTY_PROVIDERS,
|
|
3502
|
+
findProviderById,
|
|
3503
|
+
findProviderByCredentials,
|
|
3504
|
+
getAllProviderBaseUrls,
|
|
3505
|
+
parseClaudeModelVersion,
|
|
3506
|
+
anthropicSupportedEffortTiers,
|
|
3507
|
+
resolveReasoningCapabilities,
|
|
3508
|
+
validateReasoningCapabilities,
|
|
3509
|
+
captureReasoningSnapshot,
|
|
3510
|
+
resolveReasoningForModel,
|
|
3511
|
+
getEffectiveReasoning,
|
|
3512
|
+
warnIfDynamicHeadersDisabled,
|
|
3513
|
+
hasDynamicPlaceholder,
|
|
3514
|
+
expandDynamicHeaders,
|
|
3515
|
+
buildSessionIdHeaders,
|
|
3516
|
+
buildSessionAwareFetch,
|
|
3517
|
+
resolveProviderProtocol
|
|
3518
|
+
};
|
|
3519
|
+
/**
|
|
3520
|
+
* @license
|
|
3521
|
+
* Copyright 2026 Qwen Team
|
|
3522
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
3523
|
+
*/
|
|
3524
|
+
/**
|
|
3525
|
+
* @license
|
|
3526
|
+
* Copyright 2025 Qwen
|
|
3527
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
3528
|
+
*/
|
|
3529
|
+
/**
|
|
3530
|
+
* @license
|
|
3531
|
+
* Copyright 2025 Qwen Team
|
|
3532
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
3533
|
+
*/
|
|
3534
|
+
/**
|
|
3535
|
+
* @license
|
|
3536
|
+
* Copyright 2026 Qwen Team
|
|
3537
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
3538
|
+
*
|
|
3539
|
+
* Provider registry — imports all provider definitions and assembles the
|
|
3540
|
+
* lookup tables used by the UI and CLI commands.
|
|
3541
|
+
*/
|