From 2b5ac5ab51e9191b46b5ddfdfeb358c498e8b929 Mon Sep 17 00:00:00 2001 From: SuYao Date: Thu, 13 Nov 2025 16:09:49 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=B7=BB=E5=8A=A0=20AI=20Gateway=20=20?= =?UTF-8?q?Provider=20(#11064)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: 添加 AI Gateway 提供者支持,包括配置、类型定义和本地化文本 * fix(i18n): Auto update translations for PR #11064 * fix/typecheck * fix(i18n): Auto update translations for PR #11064 * fix(i18n): Auto update translations for PR #11064 * feat: cerebras * fix: glm * fix: minimax api host --------- Co-authored-by: GitHub Action --- package.json | 2 + src/renderer/src/aiCore/index_new.ts | 17 ++++- .../aiCore/provider/providerInitialization.ts | 15 +++++ src/renderer/src/aiCore/utils/options.ts | 5 +- src/renderer/src/aiCore/utils/reasoning.ts | 8 +++ .../src/assets/images/providers/cerebras.webp | Bin 0 -> 37604 bytes .../src/assets/images/providers/vercel.svg | 1 + src/renderer/src/config/models/default.ts | 23 ++++++- src/renderer/src/config/providers.ts | 58 ++++++++++++++++-- src/renderer/src/i18n/label.ts | 4 +- src/renderer/src/i18n/locales/en-us.json | 2 + src/renderer/src/i18n/locales/zh-cn.json | 2 + src/renderer/src/i18n/locales/zh-tw.json | 2 + src/renderer/src/i18n/translate/de-de.json | 2 + src/renderer/src/i18n/translate/el-gr.json | 2 + src/renderer/src/i18n/translate/es-es.json | 2 + src/renderer/src/i18n/translate/fr-fr.json | 2 + src/renderer/src/i18n/translate/ja-jp.json | 2 + src/renderer/src/i18n/translate/pt-pt.json | 2 + src/renderer/src/i18n/translate/ru-ru.json | 2 + .../ProviderSettings/ProviderSetting.tsx | 33 +++++----- src/renderer/src/store/index.ts | 2 +- src/renderer/src/store/migrate.ts | 17 +++++ src/renderer/src/types/provider.ts | 7 ++- src/renderer/src/types/sdk.ts | 1 + yarn.lock | 55 ++++++++++++++++- 26 files changed, 236 insertions(+), 32 deletions(-) create mode 100644 src/renderer/src/assets/images/providers/cerebras.webp create mode 100644 src/renderer/src/assets/images/providers/vercel.svg diff --git a/package.json b/package.json index a207b9d8aa..fccb139449 100644 --- a/package.json +++ b/package.json @@ -107,6 +107,8 @@ "@agentic/searxng": "^7.3.3", "@agentic/tavily": "^7.3.3", "@ai-sdk/amazon-bedrock": "^3.0.53", + "@ai-sdk/cerebras": "^1.0.31", + "@ai-sdk/gateway": "^2.0.9", "@ai-sdk/google-vertex": "^3.0.62", "@ai-sdk/huggingface": "patch:@ai-sdk/huggingface@npm%3A0.0.8#~/.yarn/patches/@ai-sdk-huggingface-npm-0.0.8-d4d0aaac93.patch", "@ai-sdk/mistral": "^2.0.23", diff --git a/src/renderer/src/aiCore/index_new.ts b/src/renderer/src/aiCore/index_new.ts index 800d2ff302..434b2322cd 100644 --- a/src/renderer/src/aiCore/index_new.ts +++ b/src/renderer/src/aiCore/index_new.ts @@ -7,16 +7,17 @@ * 2. 暂时保持接口兼容性 */ +import type { GatewayLanguageModelEntry } from '@ai-sdk/gateway' import { createExecutor } from '@cherrystudio/ai-core' import { loggerService } from '@logger' import { getEnableDeveloperMode } from '@renderer/hooks/useSettings' import { addSpan, endSpan } from '@renderer/services/SpanManagerService' import type { StartSpanParams } from '@renderer/trace/types/ModelSpanEntity' -import type { Assistant, GenerateImageParams, Model, Provider } from '@renderer/types' +import { type Assistant, type GenerateImageParams, type Model, type Provider, SystemProviderIds } from '@renderer/types' import type { AiSdkModel, StreamTextParams } from '@renderer/types/aiCoreTypes' import { SUPPORTED_IMAGE_ENDPOINT_LIST } from '@renderer/utils' import { buildClaudeCodeSystemModelMessage } from '@shared/anthropic' -import { type ImageModel, type LanguageModel, type Provider as AiSdkProvider, wrapLanguageModel } from 'ai' +import { gateway, type ImageModel, type LanguageModel, type Provider as AiSdkProvider, wrapLanguageModel } from 'ai' import AiSdkToChunkAdapter from './chunk/AiSdkToChunkAdapter' import LegacyAiProvider from './legacy/index' @@ -439,6 +440,18 @@ export default class ModernAiProvider { // 代理其他方法到原有实现 public async models() { + if (this.actualProvider.id === SystemProviderIds['ai-gateway']) { + const formatModel = function (models: GatewayLanguageModelEntry[]): Model[] { + return models.map((m) => ({ + id: m.id, + name: m.name, + provider: 'gateway', + group: m.id.split('/')[0], + description: m.description ?? undefined + })) + } + return formatModel((await gateway.getAvailableModels()).models) + } return this.legacyProvider.models() } diff --git a/src/renderer/src/aiCore/provider/providerInitialization.ts b/src/renderer/src/aiCore/provider/providerInitialization.ts index 665f2bd05c..baf400508a 100644 --- a/src/renderer/src/aiCore/provider/providerInitialization.ts +++ b/src/renderer/src/aiCore/provider/providerInitialization.ts @@ -71,6 +71,21 @@ export const NEW_PROVIDER_CONFIGS: ProviderConfig[] = [ creatorFunctionName: 'createHuggingFace', supportsImageGeneration: true, aliases: ['hf', 'hugging-face'] + }, + { + id: 'ai-gateway', + name: 'AI Gateway', + import: () => import('@ai-sdk/gateway'), + creatorFunctionName: 'createGateway', + supportsImageGeneration: true, + aliases: ['gateway'] + }, + { + id: 'cerebras', + name: 'Cerebras', + import: () => import('@ai-sdk/cerebras'), + creatorFunctionName: 'createCerebras', + supportsImageGeneration: false } ] as const diff --git a/src/renderer/src/aiCore/utils/options.ts b/src/renderer/src/aiCore/utils/options.ts index 9e296597c2..88f556438b 100644 --- a/src/renderer/src/aiCore/utils/options.ts +++ b/src/renderer/src/aiCore/utils/options.ts @@ -151,11 +151,12 @@ export function buildProviderOptions( ...providerSpecificOptions, ...getCustomParameters(assistant) } - // vertex需要映射到google或anthropic + const rawProviderKey = { 'google-vertex': 'google', - 'google-vertex-anthropic': 'anthropic' + 'google-vertex-anthropic': 'anthropic', + 'ai-gateway': 'gateway' }[rawProviderId] || rawProviderId // 返回 AI Core SDK 要求的格式:{ 'providerId': providerOptions } diff --git a/src/renderer/src/aiCore/utils/reasoning.ts b/src/renderer/src/aiCore/utils/reasoning.ts index 1d7123a47b..d0b6f1df25 100644 --- a/src/renderer/src/aiCore/utils/reasoning.ts +++ b/src/renderer/src/aiCore/utils/reasoning.ts @@ -109,6 +109,11 @@ export function getReasoningEffort(assistant: Assistant, model: Model): Reasonin // use thinking, doubao, zhipu, etc. if (isSupportedThinkingTokenDoubaoModel(model) || isSupportedThinkingTokenZhipuModel(model)) { + if (provider.id === SystemProviderIds.cerebras) { + return { + disable_reasoning: true + } + } return { thinking: { type: 'disabled' } } } @@ -306,6 +311,9 @@ export function getReasoningEffort(assistant: Assistant, model: Model): Reasonin return {} } if (isSupportedThinkingTokenZhipuModel(model)) { + if (provider.id === SystemProviderIds.cerebras) { + return {} + } return { thinking: { type: 'enabled' } } } diff --git a/src/renderer/src/assets/images/providers/cerebras.webp b/src/renderer/src/assets/images/providers/cerebras.webp new file mode 100644 index 0000000000000000000000000000000000000000..1c21b6ff269148005f01ad0f72a75d513bf512be GIT binary patch literal 37604 zcmV)`Kz_ecNk&H8k^lf#MM6+kP&il$0000G000300|5U606|PpNU>1>00I9eBuMc8 zcxyzY?%@yHZr4t-{~Noc7ZN(5hu)=l}H9Wd<8kG`L^Y}27j zIjH(A%URh6dJjqXdRE$jt8Ub$Wz0V^IyNC?+3rl#y!9)h)AJwyy5~0XwQ!Yt=*7<$ z?$1T`maOooxa71eD5b?JBKJ~C01-3**JT`vWB^2B0Ri-WD^X(}eYf^BO4#g1-M8)p_Di{hUZF)NuwQBxdW%+^@Ywk|=tWv? z%ET@!MDNmCQ*P7-H+r2Gnt+&PMd*!MWgO9|+32NOV(d}LH_&^vz|@{_0liwQi+@a- z2fbWtOUslj^nNWY5eX;IE4HfGdoOdLmuyWbpKu1fXDdp}lsxpNEhnLI`_ap`m^4bs zL9g3NVvAnpK`-1o;vah$y>qKbrNngf)~zA!e=A1s-3k)5483~GhrQo!^ztnpez7Oe z>$h}-#$UmEKnq8uZ*uUS(6UiJDG%=vEgBV)^6;L~l2J7|5APu@7*&(=@t)Fh5iz9@ z?=dYFrIYgTp3_nhlyDpGK`j(MaaZu3)G}d@IfeJAR*8Ox@SfEg(P#zU!&)IKr?}9{ z7nG2N_qJ9Cd+Zgw*R?owKY;g+MK@0DOj|mCdP>rSg!s5;Vq#)q`bS4cM_0EpL@q%u zKmYvprPDup_1Qih8dVMg>t*0a`RJW{uI%{z+t*{F>V|-|^NI85bzj{yrmw7Kj(q8FUKdE)T)VPHwE^%r`(cQz-- zHgbSf)o*M*db3$;KYp|-SXw(CM(_1>YJ8LrSX|5e69AJ^P#bu+H>DrwX?E}`?$hGKQo=%Ag11qiLtvvK1a~2J+0v6kb z+tGVGml6{UR$FI60eXq<-H9!2V7+a$2ff3hzv9Y+71tJ*i{4;zdieQq zsT zbtCHZ!I7aLZIwq7mt8_{F>BLz&o}oqMfJXgx?DUj3S_PJ_=FYL(fcg=dwN_`hq=j- z=te!hlUyAH^=TQOdKSIeoXyFxHBC$9*PtFBc`*>gtnyUy_9FC(FaG*+Q@aT%>N4uD zC#|0igp7zuIgH+QR$5}TpQ*_9W-;n+!H@Mp#>k;F&!KmollE?Fhgm3eKI(3Eautv; zC_3pddiU9B2`$Y)51d53y*4Hc_&Xl_a7!`X6Q22DV7STWsa(|A(<1_aefgmaZsWaV z@%qt?%sYN4=2_$%h<RuLYGjG@uQ4ezx{XqNn=w%)(LERe{VAAmW1$EFf zs}g8Gc+_z$X}z9U){GIh4s~!}6llNPN9kA+oBMqY(?!Hyls`Ao7c^fZITuT6-OE~= zE9#v``IpxK%{NUg#uDAl{Y(@suA}&u27u-}|LMUJ-<|zzCW(%BP<8NQjnBrC{=(#7W6nMUHr$BD;?^dH+5{APqAzIG z|D!_m(z9-!KDm2m+N$}#ru^%<^H-#8-F@WrmD}DM7JV9MoV|fkXFmm+?QjgeX!q5< z%YXXvy^&A%Y+JXS6X?SuTRc2q_*)YuE!=W0->X7A*~ut--XqoF2B6izZ`|kw7am_Z z^~1P+tsnZ)-tVP z-k$Q;iDEAY@l00(tZP2X>`AhNMgx=F=(T2SPKl2$52E`-_De|Jo#(}%CnePAYL|^N zXFdX2jXsNBY5J-!hqWsOy6LPx;Jx2Ydnt(Lx*J=K(^2N*4M3xTlRW5kW~}=3iJG9x z;SZ1g<+$4mLC@4611s_}%KS$dXteb)^e%JOB*jF6&WCn-ZQez11Mx&#!>Zg#6xs8M z9kl5jTZ~@h)djD$c7nH9?U{-DTwVnhk8>JRfjdy-f@eXawYQVVf7+GE_B zJnsQmyO=xrJtTI4_>Q(*H3o3yamjC$!0vIpvZ@6f;P)8MQ<>B zd3;0gdcz-|blf{Y{G+_l^Z|G*jRejBT|YF zXws4BLY>b~i?0k`wlgZ}xc;Fh*~dWYT8IL>5sU-tyt#}choeD zT4tlbIekH!kK95%KlWJ%2YB-phOaEvH%x!jAgXp11-{V+H0hV@LH$1SNi(2{aBg+42nP@QrVpz&&p8bL%|1gy-8BH}!9$xSn{> z&iJAI?TPqqdQ&HTUZlJ}cXHZ}BQ=7p(xPR>5x`UV77%y=s z?yc6K#Q`~}tH)mp1N{vSuNK*?WtZsa=-x5^d@MRTI=XGk$g1J~`T+nP7rAu?^PV-V0?@F3}(bNeJyQcT7_kTSGjDQj5WLF6BftFp@7pM6&i+MTj_6U-CJ%t$utU0n zqYRW8DDBCrpuuJrP&aRlD+e;$YY%vD)~+m+I(N^UF#{SnWdX4D-l8LOZN|x~DDAPz zput{QsF#;s2?Bw`y1eqkjvUm({M|pk(y5dn0Pyg7z1Z##hUr7a(j2Y`8XW0DoxJpl zKS&$W>5aK3J*cy1=D*b`NDP2ZX}WN}A{eGsZlJIS$^*UQ8`R0mulR$gwg$s~I_yTh zcI}_`LL-|D01y5lUv@JvOntVXu=~maec)o$$IGw!gP{JM$1G1r{lB&3t#&>V0JK`{ zkk()qC}_5 zf^qs2%6hIk(D%6G0{u%a6n{q- z;2-?t{4DgYZ%pg$#|NP76qhWnUSOOy%ai3=9iUG@@h=au0r!w+7UrQho;l|cKQ;hO zR*Mo3#%b^|6!ms9pr3%!7bFD(^Pp#zi};@&so{%?O&hRo(uSm&J<#`kAd*Ci=F&3>Vk3VvjZjdya?p}OHuau z5y05dcVQ9UYi6djU;)lIvzZk=3v9+-xrpYIEdt4+9!_olmE2xb6Kbuq6O z!9eZq7Ue4-4_u9syS@$vw)UP&TzK!AIi)!RfJe?V`W6h-3fEB5d3LhEH7NO>mcX{m z=u>#FyLq5fdl2+RF_#q%1I4xyC0*wS)PZYJ@SHcCz_szTJiHga_)Zzk0W{mg<8UY# zsIQ=;2g86mXe|o9qB=0O_gUq^d*!@oO*98S?-w$-83_hz{X9u7Rsrgubtre{^T0H4 z(7^u!2C}?IgpblJva&M{yJVWEJ;Jx?WSf|FonNXmy7r;nO zL_rI>0JZ-b6g&528?dbMRW{z6pBfRMEr7op-RXsR z?|${oAZ>wjOo4V5+l`dKV<_l{K<)Sir7lWz0LRFbV!XG%nOI6w0FCx*43v6rBjDIzjtlSoZ;lDo6a-B2XyR%$FjBjF1lj5j)Ze4fo@75@*kG<3O9oeI z3!vW(4dk~4BQ^XI%6YB=P=AU--{=brtIu#@NntmwLB*A1o~OZ3{Tb!VYz)-zq0p-% zK>OvsEx;1PHK2Xl>jgyPz)y2&hHCIx6!S`DAg*}@CBEDNv|eeZ z8%r1qYchgTi&VHD2V->-idobVh|3;Bi8odPjr+uBVu|B-z}gmH^xwvSvD(=q#|uCl zxD_Q%@d1r@J%lBXITd*UL|y(bzuJtIz>_HEWFU6_fdXd@0FBpNj3tp1fPMM(|89#v z7^|P5m>YelCZWKG>w~s^-p#|3$n-FN;4|gloGTB;YSSVyu2cl#*HPf*p`h)kLs&AI z03wbo`X5~$=u905{B9{k6fV6axq5M!B*sPaV=_f{9sbj5{OVtK|_3%Cd%H7exKs+3aQ+E~{u3x=JkSR0L}4#90u6V$fF+!s z7KUEHSt(Z7Xl!#(*h5u8yUs)xmUR9KhW>aI@^V?AO+aDSg@JafZ^jbO;(CT&WWEsY zhk!QPCCoxU(C!l%Sn@dy4E-f2L<<;wv!neUA%~QwL}# zp{$?VK(mkCMlbZvfmO4LzBUx5iLoWe^d=?1QRnxl!{?KuY~VeXi(OWrosD4RSIm)NCXo8?LqT5$jfSm8-M#Qt8}K?y zJ+-7rBkc{n?@`1n;WXc(pyNTKRSuxeUQX^{1MjrlD?7EY6pZ|ug)%$_q|qKhCV@s9 zUqoHaOzCU~Z??fF7pUA#4ZT??;#?pNJCAbCwQHoyZPe4OO}2YBywCT9P;+og>>+YS*< z`jgbl6C=L^XwvU@)I;~OXz=nw6Vm_97%=ktqlnQ!Y2SiUdIo|fgVvx9=6qiZBo40L z;-Tp7F)@SU;@(VXBOXBLn4ACOT9A=v`&)!rK>9k0nE;v$-hlFFe^LenEz|0W*CtF^ zuR~`8&~e~3K;p1qJ+20lhnx-BLy@Wx*5gK{h}O*81leluO%-%kcGE)=UNp5D zaIQ4q>+MCTVLdVS`=EsLfYP=Oh0JdQS`6Kevj1KS*xDPvn0gwuZkE|8K~5EtVJKxR zXfbFLivD+J;96nGFSn4RNv1bS_%2YEy(z_4pv8c-DEZBJ2e5RsOxWy3rY4!~5}foS znT0~Ga%#bU6$+mJNeFPP`276a$k-ecjS}_+%4ihwRB6zlb1BO0`LzZxEcen{7xFg8 zq)Ctll>R4$$Z7-{w9Q1h_eO#C%M4%TLiVPZRw$sm1<3@I(engo@hcQNFVPpY9u~W- z5G6Fl%$Hy~P&Oaiv`gBT?#G&)GoR z5$~NrIn6LBC}1K`4n`R-mIDnAbW1g-JZRd{cS$iyYJ#bhFTmv>iqI=E6mp@7c=<(DYqTcE)P87Q(RIS91ea&9q-YknzpM}U2HiUvh8EVgN& z(m53QayQVht?xRN*!=Pi3fL1U|3nebl>z#Yzft6cWk9>Wv4>D*(~IwA0X6{T<0xW5 zE1-9-M2WMX2kn;q;2KJ8dU+NF>_8E4PKHsS!HFpGwpyUs(w}6b+@_aZ0xSi}aVX*v z(BLQ(xH!=XS}m2BiISULIv{^{Q;I6NB3vz}fo{bDoq78 z`T%{s43u|S7-%#w{whjua;aX-uc#J9bGHb|KwtVKitBpU2HJGKd==$4xqOcNCj;dg zl<=TGopUvcdovm|+T#f7p}8d}gI`_*MPHOKzX{NPiQ?|82HLE*9QD!M@-p)O76_e( zM2H9ar%~M00MKMuQURL3Y)AR!SEd++60Wk*HOrBvU^r;f9(x^i)6~)v`F{_Dq1Pq2 zT^Y#BoIzpFwg63b+>bhHYFW&$pfbfclyE4JJ655v+be(;OHJ{hIjpLS-$WoRnoSRV8te&93TB}iqO)RVVO#{NZ#RB9+0{Les z>gDF3!PsmxlhyUGbJwGoj{=Sa@;)9>_Cx@Encq>L%`0Ca`vpMQ!Xv3m-xZ?G5j z+qANtUw4Wn$p3TzS&KqRW;lR+L>`*XYI@l1vk^St5uh(n2OUL0r`Uno|0mRSv&u)v z{z)KQi2N4-c?t@e1mv~$qY2G^f!!$wK~oREtjc7)Jc7IrdE4TN)%y{A1;4?sD` z0(H|Qpaxa5Vj;3y0BxUq zG`Ic2t}j6+Wd98i+qR&L?ni<4kpeWg1?6x%?;u#fF1rHNa1`Tpb`xsDP zt(aXR5SP9o#J52Eq8rU_e{d_RNbnhQzZpt34P{*7pn21SUZCgZu`Nqyd^tWL;pMov zf%VKLWsA7|3hD#X*}VzG54vU89R#HBpswd0TK4^$16q`~gQ;~Ga_>s;B67dzPh{VP zB3`Tnq_3i07af?B(5niVWB=fG+NRESh~01?9*QCsv<1>(9zAj&N*U737tFJz3b~C1 z^<9zsF(*;TRT)MA>C-OM+uU^%dWVC_b`UamS0|Xy?r9)SLJ?;I>7&J{uZO;T*bhv& z3%R9%`U-{Ijys5I6^O7ekfeJ7>S)%YxN2a|4b0{CG{G3;J_LvtqlC9>0cHCf)XltQ zu|Z(keFB-^4p3)5!|jZds0&Ky=?9c8vrs2fyEIMqv8whs+Ow`YOfTUItp9lM-Ag z3xqytD8GB<03R>`|HN$!!H3BFN&wNzD4@GDQ2vDC=S{5#reOOuW}cerY^S-s0kpx_ zBuE0v4^a9WNfBTYZi~#ffcmb;{8kXrI23T7FU7MS;f}@mgK799ZlefNxlI7tGFbu? zGy%en1t|L2I0u-B_c1H3pe{I@SwSVD&r!g5Agp#1B|jhM1T%3}53?1Zei$;P=(xD& zV`6%?sa@Kn(GQsqP-i>K?4XUNS|Pv7r3lJjM4>M}X#?&)_4~d!ZpO+(>8RLq^T4u+ zZ$H(pl(`~>S#FTJ_Q-rF&`w1D13imi z-$DKN%&z*;RLtYI6bQdSnU8b;w*GBKOy5_G4D+{s`%EnpL_K8wv^vK%X5)eOb7Y@W zgP?~;q@pB0;29W|kd}|Eug#CEZgO~;SwSgv-I2Ge8cpdeey@T0^4Cz}-A#a_BWl9t zLKN}%%98 zn^`ZKkaTv%EkON96!=0H(0ut(Yl~1`*P3BrW`ro@U0hb(h17&C|&K5m5gnihH67XgVU{Eb8IzSRWHXsbXd|)b&T+bAfgjyCtAL+AYqK zQlMe`qkp(jFRzR%XBv16c^?4vvzT?H>4Myg8>$PrfWmr`?4Vu0*rTYcImwkx0+X11 zs?H~a*HNHd%IqplH+smt{l)5i@Wd_n5;E z$>_D_4>H>R;&mL9+pqGfM^dJM*-xN+0*YDK3pCi`IC`<3B)g$z%iuLhT}x!W7f4@6 z-o>?*RnHTn=n>H1umbdM7X%q;^^x~u>JoU3p*g_pXHfntO6h(I=zS)l*Sn{@fi{Gf zJ6v5FuR0{nkhiOjvNj$u-T?YCYtRcm9ci3R;k6Hx`{%Lx8%V!oHWQTpg;J&fee-kZ z6!&u0{Z{Z3=qfd&_{~{T8n|>iQ$+;&75hynY7N zolwN$PCz{wz3{(FgYi9=*DLD2X0;Y5L-KgFQnplvM4%pvUiiMUV1OUy)mGhZR&SC# zi>x<*>UwSwwmPYXqZhuvEEwQ{E>;D8%0gYN>XZD&Yk;z;C}CD45cete!j4u1Bm6;R zy%m)ALeA%b(l3kEbstsb@QPW-^U}sAa~@mx(>>lBIhGO*$P>|qU^8)zX9=E=zX7v0HeGPvRs$>m*8A}qtnL)2qd+-^)hDWgv-s_?)3kMomcMKIYY#{Iz<&;GHSFiJY|hsN zgFS&)V`ZTpPSZ(NvudSk7_#?t1X904D0cRe(e3?!vgT{+T^ue%g3&&cRi0B>C*(Yg z!Y_~0d7G*={N@AgM=139{!+PYK+jQ0#yv(){}DZ@_jA*)WRMj`v3fp#4VynlEAXuI`F4PCAa z#(P<0{jR$GoR$IQdQR6Jsy4DKszoypXvevM`26nG*s1_$bB}D)^ka+ zJ`yAxl0$H#2^jS^SiPt2B&T;M8X@Ous3bn5{y>|63`tgJb5u0ZiKr-`bbLhik3mZ6xl zfDY9MV76+uiNRibS#EsbVU+%O4BmX;A>(wpd^btiDWV{^|w?O7u!6em- zg}B%V1P)p8?{2pSLw_-=AJrY=)SqHBr;k*<$1Md&lTpSqwLoOY#D8w zmdB|!#V?$?sM^S_6-juu4Erm9)bIVT%ywY#-((e|tSU0jcTk*Sl99< zc(@$M{m$Jo9|VKn-@~f8vM!wV17Vnl(O;nW31mKk#C}$UlMx{KoBzn^3`Tz)WF4w( zIHzAJ9zw?BR83`;TZ*JNN_e>%$o>vub`%)?U0K}##{$X^vqfFH10sBRyp2Pk$jIt7Y* zBk$Y3B#9{C>tK#eVfCH5Y)0-t0(%alxvC~Gn*o&e3j+KCCfVhzMk_0gjL!mLZDjnK zs()jdYNJtqg|jlo>?D~hmrjzyJ;pIIlG+7KI7DvVi%){ zs(#~D5JWPKU138o&DLXe0hG_>)P&*=qvuqe=k*s*I&QK15X`e3S#4FfiBl*+MP%Gc zQJ9C<>m==w`)NNDO$@7r>Mk%!2g1&bJi&@OA@6!5xiusJbQni)W z0Fq~s`3f-AE@JhBvhJK-qu9x4m?B#iuSz7T+}fCHHnNIRHiXk-6gL??sHhgQJ`JSj zn5_nL?S5AEl#S-piXa#nhbelD*DR7s$h?oq<^rowWnXiuOwgFoWl;PfuNO%MFgtEH z*<^7l0OfNSdHe|aGFq+bS6)p?zF-y)=31wR(*<>F7-azANJihQ+R5sUon#BI!g3~? zGRXOWx`T|4QcPgF)2^rWI7Wc?*cbL8FEY}1O> zVs-h9ex>+}QF}#=c?}_n<(1)Uwuxr-voe2V{2j$XMpYH{L;;&d82GVn^a{Np;Z?Jk@Srn&7 z392LCZK{4}HIF33!)h^@Za-i(R9QbxT?kq-`c2i}tllSSi>zNX-+aQVzp^2mniKS3 z^tGxCR?m<;&8xoo=37=>mA%TT7QwTOURUIctlN_$u)1wG-~7O;t+Fwk$`QmficwUF zR|LrL`%z zXVue$^CznaWz!g4r$tg4Z`%PQQAbDPsqb>|pOCkSOUUDW|r zfg~Su$^|oS7N#_=RmV6L0O=Q;uA6f5IPFt+i_y0PRT+Jw>MW;Bnq*FA zOgV*|_NdEb^f^IoMqjGB!s!Oh6ix?CIWA5+)#WjoK+u>`lB!#rF46qRX@@Dt!)cqk zVn!blv}80vRTif+G^w1{nsMyNd9yk9kmv(~2N`{! z$mZd+pJqO%#b%rUR%_K2GfE_A&uEMyU*x=tW*(=%%sBqu#(07#MsMrQ98R0fI6ka4 zs4HUhF+oR0Zz!^PIPIrN<+Rs~V`sHlT_K}S2|6))RS^_&I!g01r{iWE@Nn9uu7J_! z1YH=tt}2Vu8Jg*wE}3#%oOY_qXY>_8Cr0n8y2a@dO$w(BQ%)hLJraFG@F1gcs;+Rl zLGu+Sm&1&c!)d>|Y)0P^v|{wRsxDh=4DoG z%s96>9aVRk(N6@882zB?ASVnY8N_OU8Rr(K6Y9<|`jwzAqf}M9SydzH!z#gybB)tk zbw?QeK~R&?Z>qMiYEIID)pRq?Wlq=B?Pau{pc13ys+P0rMpB>EW;4!dPFd=9Fxp8F z%4oH!nXH~731*dPGvOTMRIF|Tqr(IaMw?ZA#p-1eNauvLO*lI^p`WroPd#WqC)Sp7*e zk=1q+&H`4ol}%>kaS$BggQXR9VReiqfmLyc`DPZYCdxizgry0#GpehoF{^wV$>XfB zhxsOjRa<56bE-q|C!-FEDzU;!B=vZGZNB-2Raa&4oE{{Y%jhvhzP#F#IPzE>H{X2B zs=uV)TL{NN4pd3G8Ksbxb$!vl^=G2~N)ue9UN!sy(bepqb6<9n;P0tX@~v zgVUP?Z!!8>)$go+rFoavUenF zBaGIldYP3gfTWy<*GFcXuB>J%3*)qqpbeuls`|0QmLzbJ*CmI^ra7x6%4|i9HV{;2 zRP0pLnAcF6nY^&4$)+Z&jmqFUqhkdAjIgGnU|wI-yu@sg$tIlD0dFZ|wI19vzT*pw~e)RH}UQXyTdSr{a=T#6)^E5x4X_kRJPFPLZSWa^Yx^aqE70(O%(FEu6!=YxG zbF4Zj8^UP^K_sUiRkdO^od$juAiuRqW(TXMly%~iPT(wLv{RKchgXI#O$Pz+e0g)s zQdXmtRp*3d)WJbUxei6JmKXM+fkOh|t{_v)WLDoPa};xGLolBaHdXZzvzbJ%Nq~zS z^3^v1yvu5lGC0d=5J4iRmsIs+cE^vVOuhs-)h6BWypG1-AXag45!IPX)RfW2E z;UhFKM+E#Uq-~MwT-?=Rv4=6 zeNN{I{E8W2MO9On<%Q9}1{rX&U9K`m@t+r}8hpNPRxOkbB4+!EY=?xvRbes(t;PSnJ=oaW$?9EY zK^{&o5xm1`t18&Y3|rH{P$}?u9f^Y0;lEAuGxQd)`cWBN;xvh%2d4smRb#mQK;(Bp z3cS%xo{GEi-_NxhdEc;FuWl`;jRfU6VFy*sxn+mazzbraC&?j9?UVRlCmVThu)3^n zDyQ27aD~&`s%%%7;fqAh6Jj8)t}05ebo}p$2HxYWJb}vI;Dl8PR&YvF1v9uEwbQ_} zg5aGvIcy1TRQbAb*Nhc5QP!7Le}V~|@&i>3<0uvTwG0vs%fa!{j6aZ>|yn| zvPf2+5d64^)~9@3aj^(*|RyVCaB0NSru&NhOLQU zjVOpmA7xi(1rp|VFzPn3nxhPMaLTf)gY%q@DSMsWJgUaUvLJ4ZVio*x0g~QsYS7JK zwNKr2PS}9pH%?enRTVckS0oW6OM|$%9~a?12kRnf%_r&HNCON59!Uah8`QbRYPb~gtaaACa0D1%#^ z3jNfAKMPUQfA|=0aFf++b?Z4{8-g!bB`F)h z4rft8f>?-Hxb=%C8#$FZ8azAoIBI{k-FVx^YOlJlS-nZ{2&+@d%DdRP8d5oT33k`Q zeT%-0f4o!Uh`_r!D>m*jXl&}X9Ax^P@iv`RzEjyCR!a!VcsOBmRglIGf2V>bg~I*& zoQxvmKh|)2lNB~m){s@YT^$@^^|7+&`C%6-cw0w=9AⅈuWjRk;4g_5=>!rTv>1? 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 \ No newline at end of file diff --git a/src/renderer/src/config/models/default.ts b/src/renderer/src/config/models/default.ts index a56ea7f6cb..ea149d3799 100644 --- a/src/renderer/src/config/models/default.ts +++ b/src/renderer/src/config/models/default.ts @@ -1840,5 +1840,26 @@ export const SYSTEM_MODELS: Record = group: 'LongCat' } ], - huggingface: [] + huggingface: [], + 'ai-gateway': [], + cerebras: [ + { + id: 'gpt-oss-120b', + name: 'GPT oss 120B', + provider: 'cerebras', + group: 'openai' + }, + { + id: 'zai-glm-4.6', + name: 'GLM 4.6', + provider: 'cerebras', + group: 'zai' + }, + { + id: 'qwen-3-235b-a22b-instruct-2507', + name: 'Qwen 3 235B A22B Instruct', + provider: 'cerebras', + group: 'qwen' + } + ] } diff --git a/src/renderer/src/config/providers.ts b/src/renderer/src/config/providers.ts index 50b0dbaece..04ef107d14 100644 --- a/src/renderer/src/config/providers.ts +++ b/src/renderer/src/config/providers.ts @@ -12,6 +12,7 @@ import BaiduCloudProviderLogo from '@renderer/assets/images/providers/baidu-clou import BailianProviderLogo from '@renderer/assets/images/providers/bailian.png' import BurnCloudProviderLogo from '@renderer/assets/images/providers/burncloud.png' import CephalonProviderLogo from '@renderer/assets/images/providers/cephalon.jpeg' +import CerebrasProviderLogo from '@renderer/assets/images/providers/cerebras.webp' import CherryInProviderLogo from '@renderer/assets/images/providers/cherryin.png' import DeepSeekProviderLogo from '@renderer/assets/images/providers/deepseek.png' import DmxapiProviderLogo from '@renderer/assets/images/providers/DMXAPI.png' @@ -51,6 +52,7 @@ import StepProviderLogo from '@renderer/assets/images/providers/step.png' import TencentCloudProviderLogo from '@renderer/assets/images/providers/tencent-cloud-ti.png' import TogetherProviderLogo from '@renderer/assets/images/providers/together.png' import TokenFluxProviderLogo from '@renderer/assets/images/providers/tokenflux.png' +import AIGatewayProviderLogo from '@renderer/assets/images/providers/vercel.svg' import VertexAIProviderLogo from '@renderer/assets/images/providers/vertexai.svg' import BytedanceProviderLogo from '@renderer/assets/images/providers/volcengine.png' import VoyageAIProviderLogo from '@renderer/assets/images/providers/voyageai.png' @@ -470,7 +472,7 @@ export const SYSTEM_PROVIDERS_CONFIG: Record = name: 'MiniMax', type: 'openai', apiKey: '', - apiHost: 'https://api.minimax.chat/v1/', + apiHost: 'https://api.minimax.com/v1/', models: SYSTEM_MODELS.minimax, isSystem: true, enabled: false @@ -675,6 +677,26 @@ export const SYSTEM_PROVIDERS_CONFIG: Record = models: [], isSystem: true, enabled: false + }, + 'ai-gateway': { + id: 'ai-gateway', + name: 'AI Gateway', + type: 'ai-gateway', + apiKey: '', + apiHost: 'https://ai-gateway.vercel.sh/v1', + models: [], + isSystem: true, + enabled: false + }, + cerebras: { + id: 'cerebras', + name: 'Cerebras AI', + type: 'openai', + apiKey: '', + apiHost: 'https://api.cerebras.ai/v1', + models: SYSTEM_MODELS.cerebras, + isSystem: true, + enabled: false } } as const @@ -741,7 +763,9 @@ export const PROVIDER_LOGO_MAP: AtLeast = { aionly: AiOnlyProviderLogo, longcat: LongCatProviderLogo, huggingface: HuggingfaceProviderLogo, - sophnet: SophnetProviderLogo + sophnet: SophnetProviderLogo, + 'ai-gateway': AIGatewayProviderLogo, + cerebras: CerebrasProviderLogo } as const export function getProviderLogo(providerId: string) { @@ -1048,7 +1072,7 @@ export const PROVIDER_URLS: Record = { }, minimax: { api: { - url: 'https://api.minimax.chat/v1/' + url: 'https://api.minimax.com/v1/' }, websites: { official: 'https://platform.minimaxi.com/', @@ -1390,6 +1414,28 @@ export const PROVIDER_URLS: Record = { docs: 'https://huggingface.co/docs', models: 'https://huggingface.co/models' } + }, + 'ai-gateway': { + api: { + url: 'https://ai-gateway.vercel.sh/v1/ai' + }, + websites: { + official: 'https://vercel.com/ai-gateway', + apiKey: 'https://vercel.com/', + docs: 'https://vercel.com/docs/ai-gateway', + models: 'https://vercel.com/ai-gateway/models' + } + }, + cerebras: { + api: { + url: 'https://api.cerebras.ai/v1' + }, + websites: { + official: 'https://www.cerebras.ai', + apiKey: 'https://cloud.cerebras.ai', + docs: 'https://inference-docs.cerebras.ai/introduction', + models: 'https://inference-docs.cerebras.ai/models/overview' + } } } @@ -1452,7 +1498,7 @@ export const isSupportEnableThinkingProvider = (provider: Provider) => { ) } -const NOT_SUPPORT_SERVICE_TIER_PROVIDERS = ['github', 'copilot'] as const satisfies SystemProviderId[] +const NOT_SUPPORT_SERVICE_TIER_PROVIDERS = ['github', 'copilot', 'cerebras'] as const satisfies SystemProviderId[] /** * 判断提供商是否支持 service_tier 设置。 Only for OpenAI API. @@ -1519,6 +1565,10 @@ export function isGeminiProvider(provider: Provider): boolean { return provider.type === 'gemini' } +export function isAIGatewayProvider(provider: Provider): boolean { + return provider.type === 'ai-gateway' +} + const NOT_SUPPORT_API_VERSION_PROVIDERS = ['github', 'copilot', 'perplexity'] as const satisfies SystemProviderId[] export const isSupportAPIVersionProvider = (provider: Provider) => { diff --git a/src/renderer/src/i18n/label.ts b/src/renderer/src/i18n/label.ts index f8806359d4..f657fd0e08 100644 --- a/src/renderer/src/i18n/label.ts +++ b/src/renderer/src/i18n/label.ts @@ -86,7 +86,9 @@ const providerKeyMap = { aionly: 'provider.aionly', longcat: 'provider.longcat', huggingface: 'provider.huggingface', - sophnet: 'provider.sophnet' + sophnet: 'provider.sophnet', + 'ai-gateway': 'provider.ai-gateway', + cerebras: 'provider.cerebras' } as const /** diff --git a/src/renderer/src/i18n/locales/en-us.json b/src/renderer/src/i18n/locales/en-us.json index 277598c9ef..1d41d6964e 100644 --- a/src/renderer/src/i18n/locales/en-us.json +++ b/src/renderer/src/i18n/locales/en-us.json @@ -2484,6 +2484,7 @@ }, "provider": { "302ai": "302.AI", + "ai-gateway": "AI Gateway", "aihubmix": "AiHubMix", "aionly": "AiOnly", "alayanew": "Alaya NeW", @@ -2494,6 +2495,7 @@ "baidu-cloud": "Baidu Cloud", "burncloud": "BurnCloud", "cephalon": "Cephalon", + "cerebras": "Cerebras AI", "cherryin": "CherryIN", "copilot": "GitHub Copilot", "dashscope": "Alibaba Cloud", diff --git a/src/renderer/src/i18n/locales/zh-cn.json b/src/renderer/src/i18n/locales/zh-cn.json index 7c5c9b8e3a..f12efbaba5 100644 --- a/src/renderer/src/i18n/locales/zh-cn.json +++ b/src/renderer/src/i18n/locales/zh-cn.json @@ -2484,6 +2484,7 @@ }, "provider": { "302ai": "302.AI", + "ai-gateway": "AI Gateway", "aihubmix": "AiHubMix", "aionly": "唯一AI (AiOnly)", "alayanew": "Alaya NeW", @@ -2494,6 +2495,7 @@ "baidu-cloud": "百度云千帆", "burncloud": "BurnCloud", "cephalon": "Cephalon", + "cerebras": "Cerebras AI", "cherryin": "CherryIN", "copilot": "GitHub Copilot", "dashscope": "阿里云百炼", diff --git a/src/renderer/src/i18n/locales/zh-tw.json b/src/renderer/src/i18n/locales/zh-tw.json index 364ccf573e..c3420c4b38 100644 --- a/src/renderer/src/i18n/locales/zh-tw.json +++ b/src/renderer/src/i18n/locales/zh-tw.json @@ -2484,6 +2484,7 @@ }, "provider": { "302ai": "302.AI", + "ai-gateway": "AI 閘道器", "aihubmix": "AiHubMix", "aionly": "唯一AI (AiOnly)", "alayanew": "Alaya NeW", @@ -2494,6 +2495,7 @@ "baidu-cloud": "百度雲千帆", "burncloud": "BurnCloud", "cephalon": "Cephalon", + "cerebras": "Cerebras AI", "cherryin": "CherryIN", "copilot": "GitHub Copilot", "dashscope": "阿里雲百鍊", diff --git a/src/renderer/src/i18n/translate/de-de.json b/src/renderer/src/i18n/translate/de-de.json index 9b51fd3a6a..fbf7f04956 100644 --- a/src/renderer/src/i18n/translate/de-de.json +++ b/src/renderer/src/i18n/translate/de-de.json @@ -2484,6 +2484,7 @@ }, "provider": { "302ai": "302.AI", + "ai-gateway": "KI-Gateway", "aihubmix": "AiHubMix", "aionly": "Einzige KI (AiOnly)", "alayanew": "Alaya NeW", @@ -2494,6 +2495,7 @@ "baidu-cloud": "Baidu Cloud Qianfan", "burncloud": "BurnCloud", "cephalon": "Cephalon", + "cerebras": "Cerebras AI", "cherryin": "CherryIN", "copilot": "GitHub Copilot", "dashscope": "Alibaba Cloud Bailian", diff --git a/src/renderer/src/i18n/translate/el-gr.json b/src/renderer/src/i18n/translate/el-gr.json index 00ec9dd9aa..1ea17fc20c 100644 --- a/src/renderer/src/i18n/translate/el-gr.json +++ b/src/renderer/src/i18n/translate/el-gr.json @@ -2484,6 +2484,7 @@ }, "provider": { "302ai": "302.AI", + "ai-gateway": "Πύλη Τεχνητής Νοημοσύνης", "aihubmix": "AiHubMix", "aionly": "AiOnly", "alayanew": "Alaya NeW", @@ -2494,6 +2495,7 @@ "baidu-cloud": "Baidu Cloud Qianfan", "burncloud": "BurnCloud", "cephalon": "Cephalon", + "cerebras": "Cerebras AI", "cherryin": "CherryIN", "copilot": "GitHub Copilot", "dashscope": "AliCloud Bailian", diff --git a/src/renderer/src/i18n/translate/es-es.json b/src/renderer/src/i18n/translate/es-es.json index d17b42cbd6..4cd8f8ad1b 100644 --- a/src/renderer/src/i18n/translate/es-es.json +++ b/src/renderer/src/i18n/translate/es-es.json @@ -2484,6 +2484,7 @@ }, "provider": { "302ai": "302.AI", + "ai-gateway": "Puerta de enlace de IA", "aihubmix": "AiHubMix", "aionly": "AiOnly", "alayanew": "Alaya NeW", @@ -2494,6 +2495,7 @@ "baidu-cloud": "Baidu Nube Qiánfān", "burncloud": "BurnCloud", "cephalon": "Cephalon", + "cerebras": "Cerebras AI", "cherryin": "CherryIN", "copilot": "GitHub Copiloto", "dashscope": "Álibaba Nube BaiLiàn", diff --git a/src/renderer/src/i18n/translate/fr-fr.json b/src/renderer/src/i18n/translate/fr-fr.json index f08e127db9..b0a0f0ef49 100644 --- a/src/renderer/src/i18n/translate/fr-fr.json +++ b/src/renderer/src/i18n/translate/fr-fr.json @@ -2484,6 +2484,7 @@ }, "provider": { "302ai": "302.AI", + "ai-gateway": "Passerelle IA", "aihubmix": "AiHubMix", "aionly": "AiOnly", "alayanew": "Alaya NeW", @@ -2494,6 +2495,7 @@ "baidu-cloud": "Baidu Cloud Qianfan", "burncloud": "BurnCloud", "cephalon": "Cephalon", + "cerebras": "Cerebras AI", "cherryin": "CherryIN", "copilot": "GitHub Copilote", "dashscope": "AliCloud BaiLian", diff --git a/src/renderer/src/i18n/translate/ja-jp.json b/src/renderer/src/i18n/translate/ja-jp.json index 3fa82cbd57..57c87ffde2 100644 --- a/src/renderer/src/i18n/translate/ja-jp.json +++ b/src/renderer/src/i18n/translate/ja-jp.json @@ -2484,6 +2484,7 @@ }, "provider": { "302ai": "302.AI", + "ai-gateway": "AIゲートウェイ", "aihubmix": "AiHubMix", "aionly": "AiOnly", "alayanew": "Alaya NeW", @@ -2494,6 +2495,7 @@ "baidu-cloud": "Baidu Cloud", "burncloud": "BurnCloud", "cephalon": "Cephalon", + "cerebras": "Cerebras AI", "cherryin": "CherryIN", "copilot": "GitHub Copilot", "dashscope": "Alibaba Cloud", diff --git a/src/renderer/src/i18n/translate/pt-pt.json b/src/renderer/src/i18n/translate/pt-pt.json index c3431cac53..b8934b3f06 100644 --- a/src/renderer/src/i18n/translate/pt-pt.json +++ b/src/renderer/src/i18n/translate/pt-pt.json @@ -2484,6 +2484,7 @@ }, "provider": { "302ai": "302.AI", + "ai-gateway": "Gateway de IA", "aihubmix": "AiHubMix", "aionly": "AiOnly", "alayanew": "Alaya NeW", @@ -2494,6 +2495,7 @@ "baidu-cloud": "Nuvem Baidu", "burncloud": "BurnCloud", "cephalon": "Cephalon", + "cerebras": "Cerebras AI", "cherryin": "CherryIN", "copilot": "GitHub Copiloto", "dashscope": "Área de Atuação AliCloud", diff --git a/src/renderer/src/i18n/translate/ru-ru.json b/src/renderer/src/i18n/translate/ru-ru.json index e14352886d..5b66ef559a 100644 --- a/src/renderer/src/i18n/translate/ru-ru.json +++ b/src/renderer/src/i18n/translate/ru-ru.json @@ -2484,6 +2484,7 @@ }, "provider": { "302ai": "302.AI", + "ai-gateway": "AI-шлюз", "aihubmix": "AiHubMix", "aionly": "AiOnly", "alayanew": "Alaya NeW", @@ -2494,6 +2495,7 @@ "baidu-cloud": "Baidu Cloud", "burncloud": "BurnCloud", "cephalon": "Cephalon", + "cerebras": "Cerebras AI", "cherryin": "CherryIN", "copilot": "GitHub Copilot", "dashscope": "Alibaba Cloud", diff --git a/src/renderer/src/pages/settings/ProviderSettings/ProviderSetting.tsx b/src/renderer/src/pages/settings/ProviderSettings/ProviderSetting.tsx index 3f8743b66e..f135d83e40 100644 --- a/src/renderer/src/pages/settings/ProviderSettings/ProviderSetting.tsx +++ b/src/renderer/src/pages/settings/ProviderSettings/ProviderSetting.tsx @@ -5,6 +5,7 @@ import { ApiKeyListPopup } from '@renderer/components/Popups/ApiKeyListPopup' import Selector from '@renderer/components/Selector' import { isEmbeddingModel, isRerankModel } from '@renderer/config/models' import { + isAIGatewayProvider, isAnthropicProvider, isAzureOpenAIProvider, isGeminiProvider, @@ -305,6 +306,9 @@ const ProviderSetting: FC = ({ providerId }) => { if (isVertexProvider(provider)) { return formatVertexApiHost(provider) + '/publishers/google' } + if (isAIGatewayProvider(provider)) { + return formatApiHost(apiHost) + '/language-model' + } return formatApiHost(apiHost) } @@ -520,24 +524,17 @@ const ProviderSetting: FC = ({ providerId }) => { {t('settings.provider.vertex_ai.api_host_help')} )} - {(isOpenAICompatibleProvider(provider) || - isAzureOpenAIProvider(provider) || - isAnthropicProvider(provider) || - isGeminiProvider(provider) || - isVertexProvider(provider) || - isOpenAIProvider(provider)) && ( - - - {t('settings.provider.api_host_preview', { url: hostPreview() })} - - - )} + + + {t('settings.provider.api_host_preview', { url: hostPreview() })} + + )} diff --git a/src/renderer/src/store/index.ts b/src/renderer/src/store/index.ts index d718ba1fc1..4baeeddfde 100644 --- a/src/renderer/src/store/index.ts +++ b/src/renderer/src/store/index.ts @@ -67,7 +67,7 @@ const persistedReducer = persistReducer( { key: 'cherry-studio', storage, - version: 173, + version: 174, blacklist: ['runtime', 'messages', 'messageBlocks', 'tabs', 'toolPermissions'], migrate }, diff --git a/src/renderer/src/store/migrate.ts b/src/renderer/src/store/migrate.ts index 4659f1ce7c..10073de1f3 100644 --- a/src/renderer/src/store/migrate.ts +++ b/src/renderer/src/store/migrate.ts @@ -2802,6 +2802,23 @@ const migrateConfig = { logger.error('migrate 173 error', error as Error) return state } + }, + '174': (state: RootState) => { + try { + addProvider(state, SystemProviderIds.longcat) + + addProvider(state, SystemProviderIds['ai-gateway']) + addProvider(state, 'cerebras') + state.llm.providers.forEach((provider) => { + if (provider.id === SystemProviderIds.minimax) { + provider.anthropicApiHost = 'https://api.minimaxi.com/anthropic' + } + }) + return state + } catch (error) { + logger.error('migrate 174 error', error as Error) + return state + } } } diff --git a/src/renderer/src/types/provider.ts b/src/renderer/src/types/provider.ts index b7d669e1f2..5bd605007e 100644 --- a/src/renderer/src/types/provider.ts +++ b/src/renderer/src/types/provider.ts @@ -11,7 +11,8 @@ export const ProviderTypeSchema = z.enum([ 'mistral', 'aws-bedrock', 'vertex-anthropic', - 'new-api' + 'new-api', + 'ai-gateway' ]) export type ProviderType = z.infer @@ -176,7 +177,9 @@ export const SystemProviderIds = { poe: 'poe', aionly: 'aionly', longcat: 'longcat', - huggingface: 'huggingface' + huggingface: 'huggingface', + 'ai-gateway': 'ai-gateway', + cerebras: 'cerebras' } as const export type SystemProviderId = keyof typeof SystemProviderIds diff --git a/src/renderer/src/types/sdk.ts b/src/renderer/src/types/sdk.ts index 90a0101563..66e6b3627a 100644 --- a/src/renderer/src/types/sdk.ts +++ b/src/renderer/src/types/sdk.ts @@ -97,6 +97,7 @@ export type ReasoningEffortOptionalParams = { } } } + disable_reasoning?: boolean // Add any other potential reasoning-related keys here if they exist } diff --git a/yarn.lock b/yarn.lock index 93aa3cbbfb..d06f134acd 100644 --- a/yarn.lock +++ b/yarn.lock @@ -127,6 +127,19 @@ __metadata: languageName: node linkType: hard +"@ai-sdk/cerebras@npm:^1.0.31": + version: 1.0.31 + resolution: "@ai-sdk/cerebras@npm:1.0.31" + dependencies: + "@ai-sdk/openai-compatible": "npm:1.0.27" + "@ai-sdk/provider": "npm:2.0.0" + "@ai-sdk/provider-utils": "npm:3.0.17" + peerDependencies: + zod: ^3.25.76 || ^4.1.8 + checksum: 10c0/0723f0041b767acfb7a9d903d51d5c95af83c31c89b83f242cb5c02a076d8b98f6567334eb32dcdbc8565b55ded2aa5195ca68612bbe7b13e68253cf4ef412d6 + languageName: node + linkType: hard + "@ai-sdk/deepseek@npm:^1.0.27": version: 1.0.27 resolution: "@ai-sdk/deepseek@npm:1.0.27" @@ -153,6 +166,19 @@ __metadata: languageName: node linkType: hard +"@ai-sdk/gateway@npm:^2.0.9": + version: 2.0.9 + resolution: "@ai-sdk/gateway@npm:2.0.9" + dependencies: + "@ai-sdk/provider": "npm:2.0.0" + "@ai-sdk/provider-utils": "npm:3.0.17" + "@vercel/oidc": "npm:3.0.3" + peerDependencies: + zod: ^3.25.76 || ^4.1.8 + checksum: 10c0/840f94795b96c0fa6e73897ea8dba95fc78af1f8482f3b7d8439b6233b4f4de6979a8b67206f4bbf32649baf2acfb1153a46792dfa20259ca9f5fd214fb25fa5 + languageName: node + linkType: hard + "@ai-sdk/google-vertex@npm:^3.0.62": version: 3.0.62 resolution: "@ai-sdk/google-vertex@npm:3.0.62" @@ -242,6 +268,18 @@ __metadata: languageName: node linkType: hard +"@ai-sdk/openai-compatible@npm:1.0.27": + version: 1.0.27 + resolution: "@ai-sdk/openai-compatible@npm:1.0.27" + dependencies: + "@ai-sdk/provider": "npm:2.0.0" + "@ai-sdk/provider-utils": "npm:3.0.17" + peerDependencies: + zod: ^3.25.76 || ^4.1.8 + checksum: 10c0/9f656e4f2ea4d714dc05be588baafd962b2e0360e9195fef373e745efeb20172698ea87e1033c0c5e1f1aa6e0db76a32629427bc8433eb42bd1a0ee00e04af0c + languageName: node + linkType: hard + "@ai-sdk/openai-compatible@npm:^1.0.19": version: 1.0.19 resolution: "@ai-sdk/openai-compatible@npm:1.0.19" @@ -316,7 +354,7 @@ __metadata: languageName: node linkType: hard -"@ai-sdk/provider-utils@npm:3.0.17, @ai-sdk/provider-utils@npm:^3.0.10, @ai-sdk/provider-utils@npm:^3.0.12": +"@ai-sdk/provider-utils@npm:3.0.17, @ai-sdk/provider-utils@npm:^3.0.10": version: 3.0.17 resolution: "@ai-sdk/provider-utils@npm:3.0.17" dependencies: @@ -329,6 +367,19 @@ __metadata: languageName: node linkType: hard +"@ai-sdk/provider-utils@npm:^3.0.12": + version: 3.0.12 + resolution: "@ai-sdk/provider-utils@npm:3.0.12" + dependencies: + "@ai-sdk/provider": "npm:2.0.0" + "@standard-schema/spec": "npm:^1.0.0" + eventsource-parser: "npm:^3.0.5" + peerDependencies: + zod: ^3.25.76 || ^4.1.8 + checksum: 10c0/83886bf188cad0cc655b680b710a10413989eaba9ec59dd24a58b985c02a8a1d50ad0f96dd5259385c07592ec3c37a7769fdf4a1ef569a73c9edbdb2cd585915 + languageName: node + linkType: hard + "@ai-sdk/provider@npm:2.0.0, @ai-sdk/provider@npm:^2.0.0": version: 2.0.0 resolution: "@ai-sdk/provider@npm:2.0.0" @@ -9879,6 +9930,8 @@ __metadata: "@agentic/searxng": "npm:^7.3.3" "@agentic/tavily": "npm:^7.3.3" "@ai-sdk/amazon-bedrock": "npm:^3.0.53" + "@ai-sdk/cerebras": "npm:^1.0.31" + "@ai-sdk/gateway": "npm:^2.0.9" "@ai-sdk/google-vertex": "npm:^3.0.62" "@ai-sdk/huggingface": "patch:@ai-sdk/huggingface@npm%3A0.0.8#~/.yarn/patches/@ai-sdk-huggingface-npm-0.0.8-d4d0aaac93.patch" "@ai-sdk/mistral": "npm:^2.0.23"