Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in / Register
Toggle navigation
Menu
Open sidebar
陈曦
sub2api
Commits
2c71c8b9
Commit
2c71c8b9
authored
Jan 01, 2026
by
shaw
Browse files
Merge PR #119: 支持自定义模型和优化模型选择
parents
901b03b8
7331220e
Changes
14
Hide whitespace changes
Inline
Side-by-side
backend/cmd/server/wire_gen.go
View file @
2c71c8b9
...
...
@@ -114,15 +114,15 @@ func initializeApplication(buildInfo handler.BuildInfo) (*Application, error) {
gitHubReleaseClient
:=
repository
.
NewGitHubReleaseClient
()
serviceBuildInfo
:=
provideServiceBuildInfo
(
buildInfo
)
updateService
:=
service
.
ProvideUpdateService
(
updateCache
,
gitHubReleaseClient
,
serviceBuildInfo
)
systemHandler
:=
handler
.
ProvideSystemHandler
(
updateService
)
adminSubscriptionHandler
:=
admin
.
NewSubscriptionHandler
(
subscriptionService
)
adminUsageHandler
:=
admin
.
NewUsageHandler
(
usageService
,
apiKeyService
,
adminService
)
adminHandlers
:=
handler
.
ProvideAdminHandlers
(
dashboardHandler
,
adminUserHandler
,
groupHandler
,
accountHandler
,
oAuthHandler
,
openAIOAuthHandler
,
geminiOAuthHandler
,
antigravityOAuthHandler
,
proxyHandler
,
adminRedeemHandler
,
settingHandler
,
systemHandler
,
adminSubscriptionHandler
,
adminUsageHandler
)
pricingRemoteClient
:=
repository
.
NewPricingRemoteClient
()
pricingService
,
err
:=
service
.
ProvidePricingService
(
configConfig
,
pricingRemoteClient
)
if
err
!=
nil
{
return
nil
,
err
}
systemHandler
:=
handler
.
ProvideSystemHandler
(
updateService
)
adminSubscriptionHandler
:=
admin
.
NewSubscriptionHandler
(
subscriptionService
)
adminUsageHandler
:=
admin
.
NewUsageHandler
(
usageService
,
apiKeyService
,
adminService
)
adminHandlers
:=
handler
.
ProvideAdminHandlers
(
dashboardHandler
,
adminUserHandler
,
groupHandler
,
accountHandler
,
oAuthHandler
,
openAIOAuthHandler
,
geminiOAuthHandler
,
antigravityOAuthHandler
,
proxyHandler
,
adminRedeemHandler
,
settingHandler
,
systemHandler
,
adminSubscriptionHandler
,
adminUsageHandler
)
billingService
:=
service
.
NewBillingService
(
configConfig
,
pricingService
)
identityCache
:=
repository
.
NewIdentityCache
(
redisClient
)
identityService
:=
service
.
NewIdentityService
(
identityCache
)
...
...
backend/internal/handler/gateway_handler.go
View file @
2c71c8b9
...
...
@@ -396,12 +396,42 @@ func (h *GatewayHandler) Messages(c *gin.Context) {
// Models handles listing available models
// GET /v1/models
// Returns different model lists based on the API key's group platform
// Returns models based on account configurations (model_mapping whitelist)
// Falls back to default models if no whitelist is configured
func
(
h
*
GatewayHandler
)
Models
(
c
*
gin
.
Context
)
{
apiKey
,
_
:=
middleware2
.
GetApiKeyFromContext
(
c
)
// Return OpenAI models for OpenAI platform groups
if
apiKey
!=
nil
&&
apiKey
.
Group
!=
nil
&&
apiKey
.
Group
.
Platform
==
"openai"
{
var
groupID
*
int64
var
platform
string
if
apiKey
!=
nil
&&
apiKey
.
Group
!=
nil
{
groupID
=
&
apiKey
.
Group
.
ID
platform
=
apiKey
.
Group
.
Platform
}
// Get available models from account configurations (without platform filter)
availableModels
:=
h
.
gatewayService
.
GetAvailableModels
(
c
.
Request
.
Context
(),
groupID
,
""
)
if
len
(
availableModels
)
>
0
{
// Build model list from whitelist
models
:=
make
([]
claude
.
Model
,
0
,
len
(
availableModels
))
for
_
,
modelID
:=
range
availableModels
{
models
=
append
(
models
,
claude
.
Model
{
ID
:
modelID
,
Type
:
"model"
,
DisplayName
:
modelID
,
CreatedAt
:
"2024-01-01T00:00:00Z"
,
})
}
c
.
JSON
(
http
.
StatusOK
,
gin
.
H
{
"object"
:
"list"
,
"data"
:
models
,
})
return
}
// Fallback to default models
if
platform
==
"openai"
{
c
.
JSON
(
http
.
StatusOK
,
gin
.
H
{
"object"
:
"list"
,
"data"
:
openai
.
DefaultModels
,
...
...
@@ -409,7 +439,6 @@ func (h *GatewayHandler) Models(c *gin.Context) {
return
}
// Default: Claude models
c
.
JSON
(
http
.
StatusOK
,
gin
.
H
{
"object"
:
"list"
,
"data"
:
claude
.
DefaultModels
,
...
...
backend/internal/service/gateway_service.go
View file @
2c71c8b9
...
...
@@ -1925,3 +1925,58 @@ func (s *GatewayService) countTokensError(c *gin.Context, status int, errType, m
},
})
}
// GetAvailableModels returns the list of models available for a group
// It aggregates model_mapping keys from all schedulable accounts in the group
func
(
s
*
GatewayService
)
GetAvailableModels
(
ctx
context
.
Context
,
groupID
*
int64
,
platform
string
)
[]
string
{
var
accounts
[]
Account
var
err
error
if
groupID
!=
nil
{
accounts
,
err
=
s
.
accountRepo
.
ListSchedulableByGroupID
(
ctx
,
*
groupID
)
}
else
{
accounts
,
err
=
s
.
accountRepo
.
ListSchedulable
(
ctx
)
}
if
err
!=
nil
||
len
(
accounts
)
==
0
{
return
nil
}
// Filter by platform if specified
if
platform
!=
""
{
filtered
:=
make
([]
Account
,
0
)
for
_
,
acc
:=
range
accounts
{
if
acc
.
Platform
==
platform
{
filtered
=
append
(
filtered
,
acc
)
}
}
accounts
=
filtered
}
// Collect unique models from all accounts
modelSet
:=
make
(
map
[
string
]
struct
{})
hasAnyMapping
:=
false
for
_
,
acc
:=
range
accounts
{
mapping
:=
acc
.
GetModelMapping
()
if
len
(
mapping
)
>
0
{
hasAnyMapping
=
true
for
model
:=
range
mapping
{
modelSet
[
model
]
=
struct
{}{}
}
}
}
// If no account has model_mapping, return nil (use default)
if
!
hasAnyMapping
{
return
nil
}
// Convert to slice
models
:=
make
([]
string
,
0
,
len
(
modelSet
))
for
model
:=
range
modelSet
{
models
=
append
(
models
,
model
)
}
return
models
}
frontend/package-lock.json
View file @
2c71c8b9
This source diff could not be displayed because it is too large. You can
view the blob
instead.
frontend/package.json
View file @
2c71c8b9
...
...
@@ -11,6 +11,7 @@
"typecheck"
:
"vue-tsc --noEmit"
},
"dependencies"
:
{
"@lobehub/icons"
:
"^4.0.2"
,
"@vueuse/core"
:
"^10.7.0"
,
"axios"
:
"^1.6.2"
,
"chart.js"
:
"^4.4.1"
,
...
...
@@ -25,6 +26,7 @@
},
"devDependencies"
:
{
"@types/file-saver"
:
"^2.0.7"
,
"@types/mdx"
:
"^2.0.13"
,
"@types/node"
:
"^20.10.5"
,
"@vitejs/plugin-vue"
:
"^5.2.3"
,
"autoprefixer"
:
"^10.4.16"
,
...
...
frontend/pnpm-lock.yaml
View file @
2c71c8b9
...
...
@@ -20,6 +20,9 @@ importers:
driver.js
:
specifier
:
^1.4.0
version
:
1.4.0
file-saver
:
specifier
:
^2.0.5
version
:
2.0.5
pinia
:
specifier
:
^2.1.7
version
:
2.3.1(typescript@5.6.3)(vue@3.5.26(typescript@5.6.3))
...
...
@@ -35,7 +38,13 @@ importers:
vue-router
:
specifier
:
^4.2.5
version
:
4.6.4(vue@3.5.26(typescript@5.6.3))
xlsx
:
specifier
:
^0.18.5
version
:
0.18.5
devDependencies
:
'
@types/file-saver'
:
specifier
:
^2.0.7
version
:
2.0.7
'
@types/node'
:
specifier
:
^20.10.5
version
:
20.19.27
...
...
@@ -303,67 +312,56 @@ packages:
resolution
:
{
integrity
:
sha512-EHMUcDwhtdRGlXZsGSIuXSYwD5kOT9NVnx9sqzYiwAc91wfYOE1g1djOEDseZJKKqtHAHGwnGPQu3kytmfaXLQ==
}
cpu
:
[
arm
]
os
:
[
linux
]
libc
:
[
glibc
]
'
@rollup/rollup-linux-arm-musleabihf@4.54.0'
:
resolution
:
{
integrity
:
sha512-+pBrqEjaakN2ySv5RVrj/qLytYhPKEUwk+e3SFU5jTLHIcAtqh2rLrd/OkbNuHJpsBgxsD8ccJt5ga/SeG0JmA==
}
cpu
:
[
arm
]
os
:
[
linux
]
libc
:
[
musl
]
'
@rollup/rollup-linux-arm64-gnu@4.54.0'
:
resolution
:
{
integrity
:
sha512-NSqc7rE9wuUaRBsBp5ckQ5CVz5aIRKCwsoa6WMF7G01sX3/qHUw/z4pv+D+ahL1EIKy6Enpcnz1RY8pf7bjwng==
}
cpu
:
[
arm64
]
os
:
[
linux
]
libc
:
[
glibc
]
'
@rollup/rollup-linux-arm64-musl@4.54.0'
:
resolution
:
{
integrity
:
sha512-gr5vDbg3Bakga5kbdpqx81m2n9IX8M6gIMlQQIXiLTNeQW6CucvuInJ91EuCJ/JYvc+rcLLsDFcfAD1K7fMofg==
}
cpu
:
[
arm64
]
os
:
[
linux
]
libc
:
[
musl
]
'
@rollup/rollup-linux-loong64-gnu@4.54.0'
:
resolution
:
{
integrity
:
sha512-gsrtB1NA3ZYj2vq0Rzkylo9ylCtW/PhpLEivlgWe0bpgtX5+9j9EZa0wtZiCjgu6zmSeZWyI/e2YRX1URozpIw==
}
cpu
:
[
loong64
]
os
:
[
linux
]
libc
:
[
glibc
]
'
@rollup/rollup-linux-ppc64-gnu@4.54.0'
:
resolution
:
{
integrity
:
sha512-y3qNOfTBStmFNq+t4s7Tmc9hW2ENtPg8FeUD/VShI7rKxNW7O4fFeaYbMsd3tpFlIg1Q8IapFgy7Q9i2BqeBvA==
}
cpu
:
[
ppc64
]
os
:
[
linux
]
libc
:
[
glibc
]
'
@rollup/rollup-linux-riscv64-gnu@4.54.0'
:
resolution
:
{
integrity
:
sha512-89sepv7h2lIVPsFma8iwmccN7Yjjtgz0Rj/Ou6fEqg3HDhpCa+Et+YSufy27i6b0Wav69Qv4WBNl3Rs6pwhebQ==
}
cpu
:
[
riscv64
]
os
:
[
linux
]
libc
:
[
glibc
]
'
@rollup/rollup-linux-riscv64-musl@4.54.0'
:
resolution
:
{
integrity
:
sha512-ZcU77ieh0M2Q8Ur7D5X7KvK+UxbXeDHwiOt/CPSBTI1fBmeDMivW0dPkdqkT4rOgDjrDDBUed9x4EgraIKoR2A==
}
cpu
:
[
riscv64
]
os
:
[
linux
]
libc
:
[
musl
]
'
@rollup/rollup-linux-s390x-gnu@4.54.0'
:
resolution
:
{
integrity
:
sha512-2AdWy5RdDF5+4YfG/YesGDDtbyJlC9LHmL6rZw6FurBJ5n4vFGupsOBGfwMRjBYH7qRQowT8D/U4LoSvVwOhSQ==
}
cpu
:
[
s390x
]
os
:
[
linux
]
libc
:
[
glibc
]
'
@rollup/rollup-linux-x64-gnu@4.54.0'
:
resolution
:
{
integrity
:
sha512-WGt5J8Ij/rvyqpFexxk3ffKqqbLf9AqrTBbWDk7ApGUzaIs6V+s2s84kAxklFwmMF/vBNGrVdYgbblCOFFezMQ==
}
cpu
:
[
x64
]
os
:
[
linux
]
libc
:
[
glibc
]
'
@rollup/rollup-linux-x64-musl@4.54.0'
:
resolution
:
{
integrity
:
sha512-JzQmb38ATzHjxlPHuTH6tE7ojnMKM2kYNzt44LO/jJi8BpceEC8QuXYA908n8r3CNuG/B3BV8VR3Hi1rYtmPiw==
}
cpu
:
[
x64
]
os
:
[
linux
]
libc
:
[
musl
]
'
@rollup/rollup-openharmony-arm64@4.54.0'
:
resolution
:
{
integrity
:
sha512-huT3fd0iC7jigGh7n3q/+lfPcXxBi+om/Rs3yiFxjvSxbSB6aohDFXbWvlspaqjeOh+hx7DDHS+5Es5qRkWkZg==
}
...
...
@@ -393,6 +391,9 @@ packages:
'
@types/estree@1.0.8'
:
resolution
:
{
integrity
:
sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==
}
'
@types/file-saver@2.0.7'
:
resolution
:
{
integrity
:
sha512-dNKVfHd/jk0SkR/exKGj2ggkB45MAkzvWCaqLUUgkyjITkGNzH8H+yUwr+BLJUBjZOe9w8X3wgmXhZDRg1ED6A==
}
'
@types/node@20.19.27'
:
resolution
:
{
integrity
:
sha512-N2clP5pJhB2YnZJ3PIHFk5RkygRX5WO/5f0WC08tp0wd+sv0rsJk3MqWn3CbNmT2J505a5336jaQj4ph1AdMug==
}
...
...
@@ -467,6 +468,10 @@ packages:
'
@vueuse/shared@10.11.1'
:
resolution
:
{
integrity
:
sha512-LHpC8711VFZlDaYUXEBbFBCQ7GS3dVU9mjOhhMhXP6txTV4EhYQg/KGnQuvt/sPAtoUKq7VVUnL6mVtFoL42sA==
}
adler-32@1.3.1
:
resolution
:
{
integrity
:
sha512-ynZ4w/nUUv5rrsR8UUGoe1VC9hZj6V5hU9Qw1HlMDJGEJw5S7TfTErWTjMys6M7vr0YWcPqs3qAr4ss0nDfP+A==
}
engines
:
{
node
:
'
>=0.8'
}
alien-signals@1.0.13
:
resolution
:
{
integrity
:
sha512-OGj9yyTnJEttvzhTUWuscOvtqxq5vrhF7vL9oS0xJ2mK0ItPYP1/y+vCFebfxoEyAz0++1AIwJ5CMr+Fk3nDmg==
}
...
...
@@ -531,6 +536,10 @@ packages:
caniuse-lite@1.0.30001761
:
resolution
:
{
integrity
:
sha512-JF9ptu1vP2coz98+5051jZ4PwQgd2ni8A+gYSN7EA7dPKIMf0pDlSUxhdmVOaV3/fYK5uWBkgSXJaRLr4+3A6g==
}
cfb@1.2.2
:
resolution
:
{
integrity
:
sha512-KfdUZsSOw19/ObEWasvBP/Ac4reZvAGauZhs6S/gqNhXhI7cKwvlH7ulj+dOEYnca4bm4SGo8C1bTAQvnTjgQA==
}
engines
:
{
node
:
'
>=0.8'
}
chart.js@4.5.1
:
resolution
:
{
integrity
:
sha512-GIjfiT9dbmHRiYi6Nl2yFCq7kkwdkp1W/lp2J99rX0yo9tgJGn3lKQATztIjb5tVtevcBtIdICNWqlq5+E8/Pw==
}
engines
:
{
pnpm
:
'
>=8'
}
...
...
@@ -543,6 +552,10 @@ packages:
resolution
:
{
integrity
:
sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==
}
engines
:
{
node
:
'
>=
14.16.0'
}
codepage@1.15.0
:
resolution
:
{
integrity
:
sha512-3g6NUTPd/YtuuGrhMnOMRjFc+LJw/bnMp3+0r/Wcz3IXUuCosKRJvMphm5+Q+bvTVGcJJuRvVLuYba+WojaFaA==
}
engines
:
{
node
:
'
>=0.8'
}
combined-stream@1.0.8
:
resolution
:
{
integrity
:
sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==
}
engines
:
{
node
:
'
>=
0.8'
}
...
...
@@ -551,6 +564,11 @@ packages:
resolution
:
{
integrity
:
sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==
}
engines
:
{
node
:
'
>=
6'
}
crc-32@1.2.2
:
resolution
:
{
integrity
:
sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ==
}
engines
:
{
node
:
'
>=0.8'
}
hasBin
:
true
cssesc@3.0.0
:
resolution
:
{
integrity
:
sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==
}
engines
:
{
node
:
'
>=4'
}
...
...
@@ -630,6 +648,9 @@ packages:
picomatch
:
optional
:
true
file-saver@2.0.5
:
resolution
:
{
integrity
:
sha512-P9bmyZ3h/PRG+Nzga+rbdI4OEpNDzAVyy74uVO9ATgzLK6VtAsYybF/+TOCvrc0MO793d6+42lLyZTw7/ArVzA==
}
fill-range@7.1.1
:
resolution
:
{
integrity
:
sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==
}
engines
:
{
node
:
'
>=8'
}
...
...
@@ -647,6 +668,10 @@ packages:
resolution
:
{
integrity
:
sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==
}
engines
:
{
node
:
'
>=
6'
}
frac@1.1.2
:
resolution
:
{
integrity
:
sha512-w/XBfkibaTl3YDqASwfDUqkna4Z2p9cFSr1aHDt0WoMTECnRfBOv2WArlZILlqgWlmdIlALXGpM2AOhEk5W3IA==
}
engines
:
{
node
:
'
>=0.8'
}
fraction.js@5.3.4
:
resolution
:
{
integrity
:
sha512-1X1NTtiJphryn/uLQz3whtY6jK3fTqoE3ohKs0tT+Ujr1W59oopxmoEh7Lu5p6vBaPbgoM0bzveAW4Qi5RyWDQ==
}
...
...
@@ -908,6 +933,10 @@ packages:
resolution
:
{
integrity
:
sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==
}
engines
:
{
node
:
'
>=0.10.0'
}
ssf@0.11.2
:
resolution
:
{
integrity
:
sha512-+idbmIXoYET47hH+d7dfm2epdOMUDjqcB4648sTZ+t2JwoyBFL/insLfB/racrDmsKB3diwsDA696pZMieAC5g==
}
engines
:
{
node
:
'
>=0.8'
}
strip-ansi@7.1.2
:
resolution
:
{
integrity
:
sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA==
}
engines
:
{
node
:
'
>=12'
}
...
...
@@ -1078,6 +1107,19 @@ packages:
typescript
:
optional
:
true
wmf@1.0.2
:
resolution
:
{
integrity
:
sha512-/p9K7bEh0Dj6WbXg4JG0xvLQmIadrner1bi45VMJTfnbVHsc7yIajZyoSoK60/dtVBs12Fm6WkUI5/3WAVsNMw==
}
engines
:
{
node
:
'
>=0.8'
}
word@0.3.0
:
resolution
:
{
integrity
:
sha512-OELeY0Q61OXpdUfTp+oweA/vtLVg5VDOXh+3he3PNzLGG/y0oylSOC1xRVj0+l4vQ3tj/bB1HVHv1ocXkQceFA==
}
engines
:
{
node
:
'
>=0.8'
}
xlsx@0.18.5
:
resolution
:
{
integrity
:
sha512-dmg3LCjBPHZnQp5/F/+nnTa+miPJxUXB6vtk42YjBBKayDNagxGEeIdWApkYPOf3Z3pm3k62Knjzp7lMeTEtFQ==
}
engines
:
{
node
:
'
>=0.8'
}
hasBin
:
true
snapshots
:
'
@alloc/quick-lru@5.2.0'
:
{}
...
...
@@ -1278,6 +1320,8 @@ snapshots:
'
@types/estree@1.0.8'
:
{}
'
@types/file-saver@2.0.7'
:
{}
'
@types/node@20.19.27'
:
dependencies
:
undici-types
:
6.21.0
...
...
@@ -1394,6 +1438,8 @@ snapshots:
-
'
@vue/composition-api'
-
vue
adler-32@1.3.1
:
{}
alien-signals@1.0.13
:
{}
ansi-regex@6.2.2
:
{}
...
...
@@ -1457,6 +1503,11 @@ snapshots:
caniuse-lite@1.0.30001761
:
{}
cfb@1.2.2
:
dependencies
:
adler-32
:
1.3.1
crc-32
:
1.2.2
chart.js@4.5.1
:
dependencies
:
'
@kurkle/color'
:
0.3.4
...
...
@@ -1477,12 +1528,16 @@ snapshots:
dependencies
:
readdirp
:
4.1.2
codepage@1.15.0
:
{}
combined-stream@1.0.8
:
dependencies
:
delayed-stream
:
1.0.0
commander@4.1.1
:
{}
crc-32@1.2.2
:
{}
cssesc@3.0.0
:
{}
csstype@3.2.3
:
{}
...
...
@@ -1568,6 +1623,8 @@ snapshots:
optionalDependencies
:
picomatch
:
4.0.3
file-saver@2.0.5
:
{}
fill-range@7.1.1
:
dependencies
:
to-regex-range
:
5.0.1
...
...
@@ -1582,6 +1639,8 @@ snapshots:
hasown
:
2.0.2
mime-types
:
2.1.35
frac@1.1.2
:
{}
fraction.js@5.3.4
:
{}
fsevents@2.3.3
:
...
...
@@ -1818,6 +1877,10 @@ snapshots:
source-map-js@1.2.1
:
{}
ssf@0.11.2
:
dependencies
:
frac
:
1.1.2
strip-ansi@7.1.2
:
dependencies
:
ansi-regex
:
6.2.2
...
...
@@ -1960,3 +2023,17 @@ snapshots:
'@vue/shared'
:
3.5.26
optionalDependencies
:
typescript
:
5.6.3
wmf@1.0.2
:
{}
word@0.3.0
:
{}
xlsx@0.18.5
:
dependencies
:
adler-32
:
1.3.1
cfb
:
1.2.2
codepage
:
1.15.0
crc-32
:
1.2.2
ssf
:
0.11.2
wmf
:
1.0.2
word
:
0.3.0
frontend/src/components/account/CreateAccountModal.vue
View file @
2c71c8b9
...
...
@@ -880,47 +880,7 @@
<!-- Whitelist Mode -->
<div
v-if=
"modelRestrictionMode === 'whitelist'"
>
<div
class=
"mb-3 rounded-lg bg-blue-50 p-3 dark:bg-blue-900/20"
>
<p
class=
"text-xs text-blue-700 dark:text-blue-400"
>
<svg
class=
"mr-1 inline h-4 w-4"
fill=
"none"
viewBox=
"0 0 24 24"
stroke=
"currentColor"
>
<path
stroke-linecap=
"round"
stroke-linejoin=
"round"
stroke-width=
"2"
d=
"M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"
/>
</svg>
{{
t
(
'
admin.accounts.selectAllowedModels
'
)
}}
</p>
</div>
<!-- Model Checkbox List -->
<div
class=
"mb-3 grid grid-cols-2 gap-2"
>
<label
v-for=
"model in commonModels"
:key=
"model.value"
class=
"flex cursor-pointer items-center rounded-lg border p-3 transition-all hover:bg-gray-50 dark:border-dark-600 dark:hover:bg-dark-700"
:class=
"
allowedModels.includes(model.value)
? 'border-primary-500 bg-primary-50 dark:bg-primary-900/20'
: 'border-gray-200'
"
>
<input
type=
"checkbox"
:value=
"model.value"
v-model=
"allowedModels"
class=
"mr-2 rounded border-gray-300 text-primary-600 focus:ring-primary-500"
/>
<span
class=
"text-sm text-gray-700 dark:text-gray-300"
>
{{
model
.
label
}}
</span>
</label>
</div>
<ModelWhitelistSelector
v-model=
"allowedModels"
:platform=
"form.platform"
/>
<p
class=
"text-xs text-gray-500 dark:text-gray-400"
>
{{
t
(
'
admin.accounts.selectedModels
'
,
{
count
:
allowedModels
.
length
}
)
}}
<
span
v
-
if
=
"
allowedModels.length === 0
"
>
{{
...
...
@@ -1549,6 +1509,7 @@
import
{
ref
,
reactive
,
computed
,
watch
}
from
'
vue
'
import
{
useI18n
}
from
'
vue-i18n
'
import
{
useAppStore
}
from
'
@/stores/app
'
import
{
claudeModels
,
getPresetMappingsByPlatform
,
getModelsByPlatform
,
commonErrorCodes
,
buildModelMappingObject
}
from
'
@/composables/useModelWhitelist
'
import
{
useAuthStore
}
from
'
@/stores/auth
'
import
{
adminAPI
}
from
'
@/api/admin
'
import
{
...
...
@@ -1563,6 +1524,7 @@ import type { Proxy, Group, AccountPlatform, AccountType } from '@/types'
import
BaseDialog
from
'
@/components/common/BaseDialog.vue
'
import
ProxySelector
from
'
@/components/common/ProxySelector.vue
'
import
GroupSelector
from
'
@/components/common/GroupSelector.vue
'
import
ModelWhitelistSelector
from
'
@/components/account/ModelWhitelistSelector.vue
'
import
OAuthAuthorizationFlow
from
'
./OAuthAuthorizationFlow.vue
'
// Type for exposed OAuthAuthorizationFlow component
...
...
@@ -1676,37 +1638,6 @@ const geminiOAuthType = ref<'code_assist' | 'google_one' | 'ai_studio'>('google_
const
geminiAIStudioOAuthEnabled
=
ref
(
false
)
const
showAdvancedOAuth
=
ref
(
false
)
// Common models for whitelist - Anthropic
const
anthropicModels
=
[
{
value
:
'
claude-opus-4-5-20251101
'
,
label
:
'
Claude Opus 4.5
'
}
,
{
value
:
'
claude-sonnet-4-20250514
'
,
label
:
'
Claude Sonnet 4
'
}
,
{
value
:
'
claude-sonnet-4-5-20250929
'
,
label
:
'
Claude Sonnet 4.5
'
}
,
{
value
:
'
claude-3-5-haiku-20241022
'
,
label
:
'
Claude 3.5 Haiku
'
}
,
{
value
:
'
claude-haiku-4-5-20251001
'
,
label
:
'
Claude Haiku 4.5
'
}
,
{
value
:
'
claude-3-opus-20240229
'
,
label
:
'
Claude 3 Opus
'
}
,
{
value
:
'
claude-3-5-sonnet-20241022
'
,
label
:
'
Claude 3.5 Sonnet
'
}
,
{
value
:
'
claude-3-haiku-20240307
'
,
label
:
'
Claude 3 Haiku
'
}
]
// Common models for whitelist - OpenAI
const
openaiModels
=
[
{
value
:
'
gpt-5.2-2025-12-11
'
,
label
:
'
GPT-5.2
'
}
,
{
value
:
'
gpt-5.2-codex
'
,
label
:
'
GPT-5.2 Codex
'
}
,
{
value
:
'
gpt-5.1-codex-max
'
,
label
:
'
GPT-5.1 Codex Max
'
}
,
{
value
:
'
gpt-5.1-codex
'
,
label
:
'
GPT-5.1 Codex
'
}
,
{
value
:
'
gpt-5.1-2025-11-13
'
,
label
:
'
GPT-5.1
'
}
,
{
value
:
'
gpt-5.1-codex-mini
'
,
label
:
'
GPT-5.1 Codex Mini
'
}
,
{
value
:
'
gpt-5-2025-08-07
'
,
label
:
'
GPT-5
'
}
]
// Common models for whitelist - Gemini
const
geminiModels
=
[
{
value
:
'
gemini-2.0-flash
'
,
label
:
'
Gemini 2.0 Flash
'
}
,
{
value
:
'
gemini-2.0-flash-lite
'
,
label
:
'
Gemini 2.0 Flash Lite
'
}
,
{
value
:
'
gemini-1.5-pro
'
,
label
:
'
Gemini 1.5 Pro
'
}
,
{
value
:
'
gemini-1.5-flash
'
,
label
:
'
Gemini 1.5 Flash
'
}
]
const
geminiQuotaDocs
=
{
codeAssist
:
'
https://developers.google.com/gemini-code-assist/resources/quotas
'
,
aiStudio
:
'
https://ai.google.dev/pricing
'
,
...
...
@@ -1721,147 +1652,8 @@ const geminiHelpLinks = {
countryCheck
:
'
https://policies.google.com/country-association-form
'
}
// Computed: current models based on platform
const
commonModels
=
computed
(()
=>
{
if
(
form
.
platform
===
'
openai
'
)
return
openaiModels
if
(
form
.
platform
===
'
gemini
'
)
return
geminiModels
return
anthropicModels
}
)
// Preset mappings for quick add - Anthropic
const
anthropicPresetMappings
=
[
{
label
:
'
Sonnet 4
'
,
from
:
'
claude-sonnet-4-20250514
'
,
to
:
'
claude-sonnet-4-20250514
'
,
color
:
'
bg-blue-100 text-blue-700 hover:bg-blue-200 dark:bg-blue-900/30 dark:text-blue-400
'
}
,
{
label
:
'
Sonnet 4.5
'
,
from
:
'
claude-sonnet-4-5-20250929
'
,
to
:
'
claude-sonnet-4-5-20250929
'
,
color
:
'
bg-indigo-100 text-indigo-700 hover:bg-indigo-200 dark:bg-indigo-900/30 dark:text-indigo-400
'
}
,
{
label
:
'
Opus 4.5
'
,
from
:
'
claude-opus-4-5-20251101
'
,
to
:
'
claude-opus-4-5-20251101
'
,
color
:
'
bg-purple-100 text-purple-700 hover:bg-purple-200 dark:bg-purple-900/30 dark:text-purple-400
'
}
,
{
label
:
'
Haiku 3.5
'
,
from
:
'
claude-3-5-haiku-20241022
'
,
to
:
'
claude-3-5-haiku-20241022
'
,
color
:
'
bg-green-100 text-green-700 hover:bg-green-200 dark:bg-green-900/30 dark:text-green-400
'
}
,
{
label
:
'
Haiku 4.5
'
,
from
:
'
claude-haiku-4-5-20251001
'
,
to
:
'
claude-haiku-4-5-20251001
'
,
color
:
'
bg-emerald-100 text-emerald-700 hover:bg-emerald-200 dark:bg-emerald-900/30 dark:text-emerald-400
'
}
,
{
label
:
'
Opus->Sonnet
'
,
from
:
'
claude-opus-4-5-20251101
'
,
to
:
'
claude-sonnet-4-5-20250929
'
,
color
:
'
bg-amber-100 text-amber-700 hover:bg-amber-200 dark:bg-amber-900/30 dark:text-amber-400
'
}
]
// Preset mappings for quick add - OpenAI
const
openaiPresetMappings
=
[
{
label
:
'
GPT-5.2
'
,
from
:
'
gpt-5.2-2025-12-11
'
,
to
:
'
gpt-5.2-2025-12-11
'
,
color
:
'
bg-green-100 text-green-700 hover:bg-green-200 dark:bg-green-900/30 dark:text-green-400
'
}
,
{
label
:
'
GPT-5.2 Codex
'
,
from
:
'
gpt-5.2-codex
'
,
to
:
'
gpt-5.2-codex
'
,
color
:
'
bg-blue-100 text-blue-700 hover:bg-blue-200 dark:bg-blue-900/30 dark:text-blue-400
'
}
,
{
label
:
'
GPT-5.1 Codex
'
,
from
:
'
gpt-5.1-codex
'
,
to
:
'
gpt-5.1-codex
'
,
color
:
'
bg-indigo-100 text-indigo-700 hover:bg-indigo-200 dark:bg-indigo-900/30 dark:text-indigo-400
'
}
,
{
label
:
'
Codex Max
'
,
from
:
'
gpt-5.1-codex-max
'
,
to
:
'
gpt-5.1-codex-max
'
,
color
:
'
bg-purple-100 text-purple-700 hover:bg-purple-200 dark:bg-purple-900/30 dark:text-purple-400
'
}
,
{
label
:
'
Codex Mini
'
,
from
:
'
gpt-5.1-codex-mini
'
,
to
:
'
gpt-5.1-codex-mini
'
,
color
:
'
bg-emerald-100 text-emerald-700 hover:bg-emerald-200 dark:bg-emerald-900/30 dark:text-emerald-400
'
}
,
{
label
:
'
Max->Codex
'
,
from
:
'
gpt-5.1-codex-max
'
,
to
:
'
gpt-5.1-codex
'
,
color
:
'
bg-amber-100 text-amber-700 hover:bg-amber-200 dark:bg-amber-900/30 dark:text-amber-400
'
}
]
// Preset mappings for quick add - Gemini
const
geminiPresetMappings
=
[
{
label
:
'
Flash
'
,
from
:
'
gemini-2.0-flash
'
,
to
:
'
gemini-2.0-flash
'
,
color
:
'
bg-blue-100 text-blue-700 hover:bg-blue-200 dark:bg-blue-900/30 dark:text-blue-400
'
}
,
{
label
:
'
Flash Lite
'
,
from
:
'
gemini-2.0-flash-lite
'
,
to
:
'
gemini-2.0-flash-lite
'
,
color
:
'
bg-indigo-100 text-indigo-700 hover:bg-indigo-200 dark:bg-indigo-900/30 dark:text-indigo-400
'
}
,
{
label
:
'
1.5 Pro
'
,
from
:
'
gemini-1.5-pro
'
,
to
:
'
gemini-1.5-pro
'
,
color
:
'
bg-purple-100 text-purple-700 hover:bg-purple-200 dark:bg-purple-900/30 dark:text-purple-400
'
}
,
{
label
:
'
1.5 Flash
'
,
from
:
'
gemini-1.5-flash
'
,
to
:
'
gemini-1.5-flash
'
,
color
:
'
bg-emerald-100 text-emerald-700 hover:bg-emerald-200 dark:bg-emerald-900/30 dark:text-emerald-400
'
}
]
// Computed: current preset mappings based on platform
const
presetMappings
=
computed
(()
=>
{
if
(
form
.
platform
===
'
openai
'
)
return
openaiPresetMappings
if
(
form
.
platform
===
'
gemini
'
)
return
geminiPresetMappings
return
anthropicPresetMappings
}
)
// Common HTTP error codes for quick selection
const
commonErrorCodes
=
[
{
value
:
401
,
label
:
'
Unauthorized
'
}
,
{
value
:
403
,
label
:
'
Forbidden
'
}
,
{
value
:
429
,
label
:
'
Rate Limit
'
}
,
{
value
:
500
,
label
:
'
Server Error
'
}
,
{
value
:
502
,
label
:
'
Bad Gateway
'
}
,
{
value
:
503
,
label
:
'
Unavailable
'
}
,
{
value
:
529
,
label
:
'
Overloaded
'
}
]
const
presetMappings
=
computed
(()
=>
getPresetMappingsByPlatform
(
form
.
platform
))
const
form
=
reactive
({
name
:
''
,
...
...
@@ -1899,7 +1691,10 @@ const canExchangeCode = computed(() => {
watch
(
()
=>
props
.
show
,
(
newVal
)
=>
{
if
(
!
newVal
)
{
if
(
newVal
)
{
// Modal opened - fill related models
allowedModels
.
value
=
[...
getModelsByPlatform
(
form
.
platform
)]
}
else
{
resetForm
()
}
}
...
...
@@ -1973,6 +1768,16 @@ const handleSelectGeminiOAuthType = (oauthType: 'code_assist' | 'google_one' | '
geminiOAuthType
.
value
=
oauthType
}
// Auto-fill related models when switching to whitelist mode or changing platform
watch
(
[
modelRestrictionMode
,
()
=>
form
.
platform
],
([
newMode
])
=>
{
if
(
newMode
===
'
whitelist
'
)
{
allowedModels
.
value
=
[...
getModelsByPlatform
(
form
.
platform
)]
}
}
)
// Model mapping helpers
const
addModelMapping
=
()
=>
{
modelMappings
.
value
.
push
({
from
:
''
,
to
:
''
}
)
...
...
@@ -1983,9 +1788,7 @@ const removeModelMapping = (index: number) => {
}
const
addPresetMapping
=
(
from
:
string
,
to
:
string
)
=>
{
// Check if mapping already exists
const
exists
=
modelMappings
.
value
.
some
((
m
)
=>
m
.
from
===
from
)
if
(
exists
)
{
if
(
modelMappings
.
value
.
some
((
m
)
=>
m
.
from
===
from
))
{
appStore
.
showInfo
(
t
(
'
admin.accounts.mappingExists
'
,
{
model
:
from
}
))
return
}
...
...
@@ -2025,28 +1828,6 @@ const removeErrorCode = (code: number) => {
}
}
const
buildModelMappingObject
=
():
Record
<
string
,
string
>
|
null
=>
{
const
mapping
:
Record
<
string
,
string
>
=
{
}
if
(
modelRestrictionMode
.
value
===
'
whitelist
'
)
{
// Whitelist mode: map model to itself
for
(
const
model
of
allowedModels
.
value
)
{
mapping
[
model
]
=
model
}
}
else
{
// Mapping mode: use custom mappings
for
(
const
m
of
modelMappings
.
value
)
{
const
from
=
m
.
from
.
trim
()
const
to
=
m
.
to
.
trim
()
if
(
from
&&
to
)
{
mapping
[
from
]
=
to
}
}
}
return
Object
.
keys
(
mapping
).
length
>
0
?
mapping
:
null
}
// Methods
const
resetForm
=
()
=>
{
step
.
value
=
1
...
...
@@ -2064,7 +1845,7 @@ const resetForm = () => {
apiKeyValue
.
value
=
''
modelMappings
.
value
=
[]
modelRestrictionMode
.
value
=
'
whitelist
'
allowedModels
.
value
=
[
]
allowedModels
.
value
=
[
...
claudeModels
]
// Default fill related models
customErrorCodesEnabled
.
value
=
false
selectedErrorCodes
.
value
=
[]
customErrorCodeInput
.
value
=
null
...
...
@@ -2113,7 +1894,7 @@ const handleSubmit = async () => {
}
// Add model mapping if configured
const
modelMapping
=
buildModelMappingObject
()
const
modelMapping
=
buildModelMappingObject
(
modelRestrictionMode
.
value
,
allowedModels
.
value
,
modelMappings
.
value
)
if
(
modelMapping
)
{
credentials
.
model_mapping
=
modelMapping
}
...
...
frontend/src/components/account/EditAccountModal.vue
View file @
2c71c8b9
...
...
@@ -111,47 +111,7 @@
<!-- Whitelist Mode -->
<div
v-if=
"modelRestrictionMode === 'whitelist'"
>
<div
class=
"mb-3 rounded-lg bg-blue-50 p-3 dark:bg-blue-900/20"
>
<p
class=
"text-xs text-blue-700 dark:text-blue-400"
>
<svg
class=
"mr-1 inline h-4 w-4"
fill=
"none"
viewBox=
"0 0 24 24"
stroke=
"currentColor"
>
<path
stroke-linecap=
"round"
stroke-linejoin=
"round"
stroke-width=
"2"
d=
"M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"
/>
</svg>
{{
t
(
'
admin.accounts.selectAllowedModels
'
)
}}
</p>
</div>
<!-- Model Checkbox List -->
<div
class=
"mb-3 grid grid-cols-2 gap-2"
>
<label
v-for=
"model in commonModels"
:key=
"model.value"
class=
"flex cursor-pointer items-center rounded-lg border p-3 transition-all hover:bg-gray-50 dark:border-dark-600 dark:hover:bg-dark-700"
:class=
"
allowedModels.includes(model.value)
? 'border-primary-500 bg-primary-50 dark:bg-primary-900/20'
: 'border-gray-200'
"
>
<input
type=
"checkbox"
:value=
"model.value"
v-model=
"allowedModels"
class=
"mr-2 rounded border-gray-300 text-primary-600 focus:ring-primary-500"
/>
<span
class=
"text-sm text-gray-700 dark:text-gray-300"
>
{{
model
.
label
}}
</span>
</label>
</div>
<ModelWhitelistSelector
v-model=
"allowedModels"
:platform=
"account?.platform || 'anthropic'"
/>
<p
class=
"text-xs text-gray-500 dark:text-gray-400"
>
{{
t
(
'
admin.accounts.selectedModels
'
,
{
count
:
allowedModels
.
length
}
)
}}
<
span
v
-
if
=
"
allowedModels.length === 0
"
>
{{
...
...
@@ -565,6 +525,12 @@ import BaseDialog from '@/components/common/BaseDialog.vue'
import
Select
from
'
@/components/common/Select.vue
'
import
ProxySelector
from
'
@/components/common/ProxySelector.vue
'
import
GroupSelector
from
'
@/components/common/GroupSelector.vue
'
import
ModelWhitelistSelector
from
'
@/components/account/ModelWhitelistSelector.vue
'
import
{
getPresetMappingsByPlatform
,
commonErrorCodes
,
buildModelMappingObject
}
from
'
@/composables/useModelWhitelist
'
interface
Props
{
show
:
boolean
...
...
@@ -610,167 +576,8 @@ const customErrorCodeInput = ref<number | null>(null)
const
interceptWarmupRequests
=
ref
(
false
)
const
mixedScheduling
=
ref
(
false
)
// For antigravity accounts: enable mixed scheduling
// Common models for whitelist - Anthropic
const
anthropicModels
=
[
{
value
:
'
claude-opus-4-5-20251101
'
,
label
:
'
Claude Opus 4.5
'
}
,
{
value
:
'
claude-sonnet-4-20250514
'
,
label
:
'
Claude Sonnet 4
'
}
,
{
value
:
'
claude-sonnet-4-5-20250929
'
,
label
:
'
Claude Sonnet 4.5
'
}
,
{
value
:
'
claude-3-5-haiku-20241022
'
,
label
:
'
Claude 3.5 Haiku
'
}
,
{
value
:
'
claude-haiku-4-5-20251001
'
,
label
:
'
Claude Haiku 4.5
'
}
,
{
value
:
'
claude-3-opus-20240229
'
,
label
:
'
Claude 3 Opus
'
}
,
{
value
:
'
claude-3-5-sonnet-20241022
'
,
label
:
'
Claude 3.5 Sonnet
'
}
,
{
value
:
'
claude-3-haiku-20240307
'
,
label
:
'
Claude 3 Haiku
'
}
]
// Common models for whitelist - OpenAI
const
openaiModels
=
[
{
value
:
'
gpt-5.2-2025-12-11
'
,
label
:
'
GPT-5.2
'
}
,
{
value
:
'
gpt-5.2-codex
'
,
label
:
'
GPT-5.2 Codex
'
}
,
{
value
:
'
gpt-5.1-codex-max
'
,
label
:
'
GPT-5.1 Codex Max
'
}
,
{
value
:
'
gpt-5.1-codex
'
,
label
:
'
GPT-5.1 Codex
'
}
,
{
value
:
'
gpt-5.1-2025-11-13
'
,
label
:
'
GPT-5.1
'
}
,
{
value
:
'
gpt-5.1-codex-mini
'
,
label
:
'
GPT-5.1 Codex Mini
'
}
,
{
value
:
'
gpt-5-2025-08-07
'
,
label
:
'
GPT-5
'
}
]
// Common models for whitelist - Gemini
const
geminiModels
=
[
{
value
:
'
gemini-2.0-flash
'
,
label
:
'
Gemini 2.0 Flash
'
}
,
{
value
:
'
gemini-2.0-flash-lite
'
,
label
:
'
Gemini 2.0 Flash Lite
'
}
,
{
value
:
'
gemini-1.5-pro
'
,
label
:
'
Gemini 1.5 Pro
'
}
,
{
value
:
'
gemini-1.5-flash
'
,
label
:
'
Gemini 1.5 Flash
'
}
]
// Computed: current models based on platform
const
commonModels
=
computed
(()
=>
{
if
(
props
.
account
?.
platform
===
'
openai
'
)
return
openaiModels
if
(
props
.
account
?.
platform
===
'
gemini
'
)
return
geminiModels
return
anthropicModels
}
)
// Preset mappings for quick add - Anthropic
const
anthropicPresetMappings
=
[
{
label
:
'
Sonnet 4
'
,
from
:
'
claude-sonnet-4-20250514
'
,
to
:
'
claude-sonnet-4-20250514
'
,
color
:
'
bg-blue-100 text-blue-700 hover:bg-blue-200 dark:bg-blue-900/30 dark:text-blue-400
'
}
,
{
label
:
'
Sonnet 4.5
'
,
from
:
'
claude-sonnet-4-5-20250929
'
,
to
:
'
claude-sonnet-4-5-20250929
'
,
color
:
'
bg-indigo-100 text-indigo-700 hover:bg-indigo-200 dark:bg-indigo-900/30 dark:text-indigo-400
'
}
,
{
label
:
'
Opus 4.5
'
,
from
:
'
claude-opus-4-5-20251101
'
,
to
:
'
claude-opus-4-5-20251101
'
,
color
:
'
bg-purple-100 text-purple-700 hover:bg-purple-200 dark:bg-purple-900/30 dark:text-purple-400
'
}
,
{
label
:
'
Haiku 3.5
'
,
from
:
'
claude-3-5-haiku-20241022
'
,
to
:
'
claude-3-5-haiku-20241022
'
,
color
:
'
bg-green-100 text-green-700 hover:bg-green-200 dark:bg-green-900/30 dark:text-green-400
'
}
,
{
label
:
'
Haiku 4.5
'
,
from
:
'
claude-haiku-4-5-20251001
'
,
to
:
'
claude-haiku-4-5-20251001
'
,
color
:
'
bg-emerald-100 text-emerald-700 hover:bg-emerald-200 dark:bg-emerald-900/30 dark:text-emerald-400
'
}
,
{
label
:
'
Opus->Sonnet
'
,
from
:
'
claude-opus-4-5-20251101
'
,
to
:
'
claude-sonnet-4-5-20250929
'
,
color
:
'
bg-amber-100 text-amber-700 hover:bg-amber-200 dark:bg-amber-900/30 dark:text-amber-400
'
}
]
// Preset mappings for quick add - OpenAI
const
openaiPresetMappings
=
[
{
label
:
'
GPT-5.2
'
,
from
:
'
gpt-5.2-2025-12-11
'
,
to
:
'
gpt-5.2-2025-12-11
'
,
color
:
'
bg-green-100 text-green-700 hover:bg-green-200 dark:bg-green-900/30 dark:text-green-400
'
}
,
{
label
:
'
GPT-5.2 Codex
'
,
from
:
'
gpt-5.2-codex
'
,
to
:
'
gpt-5.2-codex
'
,
color
:
'
bg-blue-100 text-blue-700 hover:bg-blue-200 dark:bg-blue-900/30 dark:text-blue-400
'
}
,
{
label
:
'
GPT-5.1 Codex
'
,
from
:
'
gpt-5.1-codex
'
,
to
:
'
gpt-5.1-codex
'
,
color
:
'
bg-indigo-100 text-indigo-700 hover:bg-indigo-200 dark:bg-indigo-900/30 dark:text-indigo-400
'
}
,
{
label
:
'
Codex Max
'
,
from
:
'
gpt-5.1-codex-max
'
,
to
:
'
gpt-5.1-codex-max
'
,
color
:
'
bg-purple-100 text-purple-700 hover:bg-purple-200 dark:bg-purple-900/30 dark:text-purple-400
'
}
,
{
label
:
'
Codex Mini
'
,
from
:
'
gpt-5.1-codex-mini
'
,
to
:
'
gpt-5.1-codex-mini
'
,
color
:
'
bg-emerald-100 text-emerald-700 hover:bg-emerald-200 dark:bg-emerald-900/30 dark:text-emerald-400
'
}
,
{
label
:
'
Max->Codex
'
,
from
:
'
gpt-5.1-codex-max
'
,
to
:
'
gpt-5.1-codex
'
,
color
:
'
bg-amber-100 text-amber-700 hover:bg-amber-200 dark:bg-amber-900/30 dark:text-amber-400
'
}
]
// Preset mappings for quick add - Gemini
const
geminiPresetMappings
=
[
{
label
:
'
Flash
'
,
from
:
'
gemini-2.0-flash
'
,
to
:
'
gemini-2.0-flash
'
,
color
:
'
bg-blue-100 text-blue-700 hover:bg-blue-200 dark:bg-blue-900/30 dark:text-blue-400
'
}
,
{
label
:
'
Flash Lite
'
,
from
:
'
gemini-2.0-flash-lite
'
,
to
:
'
gemini-2.0-flash-lite
'
,
color
:
'
bg-indigo-100 text-indigo-700 hover:bg-indigo-200 dark:bg-indigo-900/30 dark:text-indigo-400
'
}
,
{
label
:
'
1.5 Pro
'
,
from
:
'
gemini-1.5-pro
'
,
to
:
'
gemini-1.5-pro
'
,
color
:
'
bg-purple-100 text-purple-700 hover:bg-purple-200 dark:bg-purple-900/30 dark:text-purple-400
'
}
,
{
label
:
'
1.5 Flash
'
,
from
:
'
gemini-1.5-flash
'
,
to
:
'
gemini-1.5-flash
'
,
color
:
'
bg-emerald-100 text-emerald-700 hover:bg-emerald-200 dark:bg-emerald-900/30 dark:text-emerald-400
'
}
]
// Computed: current preset mappings based on platform
const
presetMappings
=
computed
(()
=>
{
if
(
props
.
account
?.
platform
===
'
openai
'
)
return
openaiPresetMappings
if
(
props
.
account
?.
platform
===
'
gemini
'
)
return
geminiPresetMappings
return
anthropicPresetMappings
}
)
const
presetMappings
=
computed
(()
=>
getPresetMappingsByPlatform
(
props
.
account
?.
platform
||
'
anthropic
'
))
// Computed: default base URL based on platform
const
defaultBaseUrl
=
computed
(()
=>
{
...
...
@@ -779,17 +586,6 @@ const defaultBaseUrl = computed(() => {
return
'
https://api.anthropic.com
'
}
)
// Common HTTP error codes for quick selection
const
commonErrorCodes
=
[
{
value
:
401
,
label
:
'
Unauthorized
'
}
,
{
value
:
403
,
label
:
'
Forbidden
'
}
,
{
value
:
429
,
label
:
'
Rate Limit
'
}
,
{
value
:
500
,
label
:
'
Server Error
'
}
,
{
value
:
502
,
label
:
'
Bad Gateway
'
}
,
{
value
:
503
,
label
:
'
Unavailable
'
}
,
{
value
:
529
,
label
:
'
Overloaded
'
}
]
const
form
=
reactive
({
name
:
''
,
proxy_id
:
null
as
number
|
null
,
...
...
@@ -940,28 +736,6 @@ const removeErrorCode = (code: number) => {
}
}
const
buildModelMappingObject
=
():
Record
<
string
,
string
>
|
null
=>
{
const
mapping
:
Record
<
string
,
string
>
=
{
}
if
(
modelRestrictionMode
.
value
===
'
whitelist
'
)
{
// Whitelist mode: model maps to itself
for
(
const
model
of
allowedModels
.
value
)
{
mapping
[
model
]
=
model
}
}
else
{
// Mapping mode: use the mapping entries
for
(
const
m
of
modelMappings
.
value
)
{
const
from
=
m
.
from
.
trim
()
const
to
=
m
.
to
.
trim
()
if
(
from
&&
to
)
{
mapping
[
from
]
=
to
}
}
}
return
Object
.
keys
(
mapping
).
length
>
0
?
mapping
:
null
}
// Methods
const
handleClose
=
()
=>
{
emit
(
'
close
'
)
...
...
@@ -978,7 +752,7 @@ const handleSubmit = async () => {
if
(
props
.
account
.
type
===
'
apikey
'
)
{
const
currentCredentials
=
(
props
.
account
.
credentials
as
Record
<
string
,
unknown
>
)
||
{
}
const
newBaseUrl
=
editBaseUrl
.
value
.
trim
()
||
defaultBaseUrl
.
value
const
modelMapping
=
buildModelMappingObject
()
const
modelMapping
=
buildModelMappingObject
(
modelRestrictionMode
.
value
,
allowedModels
.
value
,
modelMappings
.
value
)
// Always update credentials for apikey type to handle model mapping changes
const
newCredentials
:
Record
<
string
,
unknown
>
=
{
...
...
frontend/src/components/account/ModelWhitelistSelector.vue
0 → 100644
View file @
2c71c8b9
<
template
>
<div>
<!-- Multi-select Dropdown -->
<div
class=
"relative mb-3"
>
<div
@
click=
"toggleDropdown"
class=
"cursor-pointer rounded-lg border border-gray-300 bg-white px-3 py-2 dark:border-dark-500 dark:bg-dark-700"
>
<div
class=
"grid grid-cols-2 gap-1.5"
>
<span
v-for=
"model in modelValue"
:key=
"model"
class=
"inline-flex items-center justify-between gap-1 rounded bg-gray-100 px-2 py-1 text-xs text-gray-700 dark:bg-dark-600 dark:text-gray-300"
>
<span
class=
"flex items-center gap-1 truncate"
>
<ModelIcon
:model=
"model"
size=
"14px"
/>
<span
class=
"truncate"
>
{{
model
}}
</span>
</span>
<button
type=
"button"
@
click.stop=
"removeModel(model)"
class=
"shrink-0 rounded-full hover:bg-gray-200 dark:hover:bg-dark-500"
>
<svg
class=
"h-3.5 w-3.5"
fill=
"none"
viewBox=
"0 0 24 24"
stroke=
"currentColor"
>
<path
stroke-linecap=
"round"
stroke-linejoin=
"round"
stroke-width=
"2"
d=
"M6 18L18 6M6 6l12 12"
/>
</svg>
</button>
</span>
</div>
<div
class=
"mt-2 flex items-center justify-between border-t border-gray-200 pt-2 dark:border-dark-600"
>
<span
class=
"text-xs text-gray-400"
>
{{
t
(
'
admin.accounts.modelCount
'
,
{
count
:
modelValue
.
length
}
)
}}
<
/span
>
<
svg
class
=
"
h-5 w-5 text-gray-400
"
fill
=
"
none
"
viewBox
=
"
0 0 24 24
"
stroke
=
"
currentColor
"
>
<
path
stroke
-
linecap
=
"
round
"
stroke
-
linejoin
=
"
round
"
stroke
-
width
=
"
2
"
d
=
"
M19 9l-7 7-7-7
"
/>
<
/svg
>
<
/div
>
<
/div
>
<!--
Dropdown
List
-->
<
div
v
-
if
=
"
showDropdown
"
class
=
"
absolute left-0 right-0 top-full z-50 mt-1 rounded-lg border border-gray-200 bg-white shadow-lg dark:border-dark-600 dark:bg-dark-700
"
>
<
div
class
=
"
sticky top-0 border-b border-gray-200 bg-white p-2 dark:border-dark-600 dark:bg-dark-700
"
>
<
input
v
-
model
=
"
searchQuery
"
type
=
"
text
"
class
=
"
input w-full text-sm
"
:
placeholder
=
"
t('admin.accounts.searchModels')
"
@
click
.
stop
/>
<
/div
>
<
div
class
=
"
max-h-52 overflow-auto
"
>
<
button
v
-
for
=
"
model in filteredModels
"
:
key
=
"
model.value
"
type
=
"
button
"
@
click
=
"
toggleModel(model.value)
"
class
=
"
flex w-full items-center gap-2 px-3 py-2 text-left text-sm hover:bg-gray-100 dark:hover:bg-dark-600
"
>
<
span
:
class
=
"
[
'flex h-4 w-4 shrink-0 items-center justify-center rounded border',
modelValue.includes(model.value)
? 'border-primary-500 bg-primary-500 text-white'
: 'border-gray-300 dark:border-dark-500'
]
"
>
<
svg
v
-
if
=
"
modelValue.includes(model.value)
"
class
=
"
h-3 w-3
"
fill
=
"
none
"
viewBox
=
"
0 0 24 24
"
stroke
=
"
currentColor
"
>
<
path
stroke
-
linecap
=
"
round
"
stroke
-
linejoin
=
"
round
"
stroke
-
width
=
"
3
"
d
=
"
M5 13l4 4L19 7
"
/>
<
/svg
>
<
/span
>
<
ModelIcon
:
model
=
"
model.value
"
size
=
"
18px
"
/>
<
span
class
=
"
truncate text-gray-900 dark:text-white
"
>
{{
model
.
value
}}
<
/span
>
<
/button
>
<
div
v
-
if
=
"
filteredModels.length === 0
"
class
=
"
px-3 py-4 text-center text-sm text-gray-500
"
>
{{
t
(
'
admin.accounts.noMatchingModels
'
)
}}
<
/div
>
<
/div
>
<
/div
>
<
/div
>
<!--
Quick
Actions
-->
<
div
class
=
"
mb-4 flex flex-wrap gap-2
"
>
<
button
type
=
"
button
"
@
click
=
"
fillRelated
"
class
=
"
rounded-lg border border-blue-200 px-3 py-1.5 text-sm text-blue-600 hover:bg-blue-50 dark:border-blue-800 dark:text-blue-400 dark:hover:bg-blue-900/30
"
>
{{
t
(
'
admin.accounts.fillRelatedModels
'
)
}}
<
/button
>
<
button
type
=
"
button
"
@
click
=
"
clearAll
"
class
=
"
rounded-lg border border-red-200 px-3 py-1.5 text-sm text-red-600 hover:bg-red-50 dark:border-red-800 dark:text-red-400 dark:hover:bg-red-900/30
"
>
{{
t
(
'
admin.accounts.clearAllModels
'
)
}}
<
/button
>
<
/div
>
<!--
Custom
Model
Input
-->
<
div
class
=
"
mb-3
"
>
<
label
class
=
"
mb-1.5 block text-sm font-medium text-gray-700 dark:text-gray-300
"
>
{{
t
(
'
admin.accounts.customModelName
'
)
}}
<
/label
>
<
div
class
=
"
flex gap-2
"
>
<
input
v
-
model
=
"
customModel
"
type
=
"
text
"
class
=
"
input flex-1
"
:
placeholder
=
"
t('admin.accounts.enterCustomModelName')
"
@
keydown
.
enter
.
prevent
=
"
handleEnter
"
@
compositionstart
=
"
isComposing = true
"
@
compositionend
=
"
isComposing = false
"
/>
<
button
type
=
"
button
"
@
click
=
"
addCustom
"
class
=
"
rounded-lg bg-primary-50 px-4 py-2 text-sm font-medium text-primary-600 hover:bg-primary-100 dark:bg-primary-900/30 dark:text-primary-400 dark:hover:bg-primary-900/50
"
>
{{
t
(
'
admin.accounts.addModel
'
)
}}
<
/button
>
<
/div
>
<
/div
>
<
/div
>
<
/template
>
<
script
setup
lang
=
"
ts
"
>
import
{
ref
,
computed
}
from
'
vue
'
import
{
useI18n
}
from
'
vue-i18n
'
import
{
useAppStore
}
from
'
@/stores/app
'
import
ModelIcon
from
'
@/components/common/ModelIcon.vue
'
import
{
allModels
,
getModelsByPlatform
}
from
'
@/composables/useModelWhitelist
'
const
{
t
}
=
useI18n
()
const
props
=
defineProps
<
{
modelValue
:
string
[]
platform
:
string
}
>
()
const
emit
=
defineEmits
<
{
'
update:modelValue
'
:
[
value
:
string
[]]
}
>
()
const
appStore
=
useAppStore
()
const
showDropdown
=
ref
(
false
)
const
searchQuery
=
ref
(
''
)
const
customModel
=
ref
(
''
)
const
isComposing
=
ref
(
false
)
const
filteredModels
=
computed
(()
=>
{
const
query
=
searchQuery
.
value
.
toLowerCase
().
trim
()
if
(
!
query
)
return
allModels
return
allModels
.
filter
(
m
=>
m
.
value
.
toLowerCase
().
includes
(
query
)
||
m
.
label
.
toLowerCase
().
includes
(
query
)
)
}
)
const
toggleDropdown
=
()
=>
{
showDropdown
.
value
=
!
showDropdown
.
value
if
(
!
showDropdown
.
value
)
searchQuery
.
value
=
''
}
const
removeModel
=
(
model
:
string
)
=>
{
emit
(
'
update:modelValue
'
,
props
.
modelValue
.
filter
(
m
=>
m
!==
model
))
}
const
toggleModel
=
(
model
:
string
)
=>
{
if
(
props
.
modelValue
.
includes
(
model
))
{
removeModel
(
model
)
}
else
{
emit
(
'
update:modelValue
'
,
[...
props
.
modelValue
,
model
])
}
}
const
addCustom
=
()
=>
{
const
model
=
customModel
.
value
.
trim
()
if
(
!
model
)
return
if
(
props
.
modelValue
.
includes
(
model
))
{
appStore
.
showInfo
(
t
(
'
admin.accounts.modelExists
'
))
return
}
emit
(
'
update:modelValue
'
,
[...
props
.
modelValue
,
model
])
customModel
.
value
=
''
}
const
handleEnter
=
()
=>
{
if
(
!
isComposing
.
value
)
addCustom
()
}
const
fillRelated
=
()
=>
{
const
models
=
getModelsByPlatform
(
props
.
platform
)
const
newModels
=
[...
props
.
modelValue
]
for
(
const
model
of
models
)
{
if
(
!
newModels
.
includes
(
model
))
newModels
.
push
(
model
)
}
emit
(
'
update:modelValue
'
,
newModels
)
}
const
clearAll
=
()
=>
{
emit
(
'
update:modelValue
'
,
[])
}
<
/script
>
frontend/src/components/common/ModelIcon.vue
0 → 100644
View file @
2c71c8b9
<
template
>
<svg
v-if=
"iconInfo"
:width=
"size"
:height=
"size"
viewBox=
"0 0 24 24"
xmlns=
"http://www.w3.org/2000/svg"
class=
"model-icon"
fill=
"currentColor"
fill-rule=
"evenodd"
>
<path
v-for=
"(p, idx) in iconInfo.paths"
:key=
"idx"
:d=
"p"
:fill=
"iconInfo.color"
/>
</svg>
<span
v-else
class=
"model-icon-fallback"
:style=
"
{ width: size, height: size, fontSize: `calc(${size} * 0.5)` }">
{{
fallbackText
}}
</span>
</
template
>
<
script
setup
lang=
"ts"
>
import
{
computed
}
from
'
vue
'
const
props
=
withDefaults
(
defineProps
<
{
model
:
string
size
?:
string
}
>
(),
{
size
:
'
18px
'
})
interface
IconData
{
color
:
string
paths
:
string
[]
}
// SVG paths extracted from @lobehub/icons Mono.js files
const
iconData
:
Record
<
string
,
IconData
>
=
{
claude
:
{
color
:
'
#D97706
'
,
paths
:
[
'
M4.709 15.955l4.72-2.647.08-.23-.08-.128H9.2l-.79-.048-2.698-.073-2.339-.097-2.266-.122-.571-.121L0 11.784l.055-.352.48-.321.686.06 1.52.103 2.278.158 1.652.097 2.449.255h.389l.055-.157-.134-.098-.103-.097-2.358-1.596-2.552-1.688-1.336-.972-.724-.491-.364-.462-.158-1.008.656-.722.881.06.225.061.893.686 1.908 1.476 2.491 1.833.365.304.145-.103.019-.073-.164-.274-1.355-2.446-1.446-2.49-.644-1.032-.17-.619a2.97 2.97 0 01-.104-.729L6.283.134 6.696 0l.996.134.42.364.62 1.414 1.002 2.229 1.555 3.03.456.898.243.832.091.255h.158V9.01l.128-1.706.237-2.095.23-2.695.08-.76.376-.91.747-.492.584.28.48.685-.067.444-.286 1.851-.559 2.903-.364 1.942h.212l.243-.242.985-1.306 1.652-2.064.73-.82.85-.904.547-.431h1.033l.76 1.129-.34 1.166-1.064 1.347-.881 1.142-1.264 1.7-.79 1.36.073.11.188-.02 2.856-.606 1.543-.28 1.841-.315.833.388.091.395-.328.807-1.969.486-2.309.462-3.439.813-.042.03.049.061 1.549.146.662.036h1.622l3.02.225.79.522.474.638-.079.485-1.215.62-1.64-.389-3.829-.91-1.312-.329h-.182v.11l1.093 1.068 2.006 1.81 2.509 2.33.127.578-.322.455-.34-.049-2.205-1.657-.851-.747-1.926-1.62h-.128v.17l.444.649 2.345 3.521.122 1.08-.17.353-.608.213-.668-.122-1.374-1.925-1.415-2.167-1.143-1.943-.14.08-.674 7.254-.316.37-.729.28-.607-.461-.322-.747.322-1.476.389-1.924.315-1.53.286-1.9.17-.632-.012-.042-.14.018-1.434 1.967-2.18 2.945-1.726 1.845-.414.164-.717-.37.067-.662.401-.589 2.388-3.036 1.44-1.882.93-1.086-.006-.158h-.055L4.132 18.56l-1.13.146-.487-.456.061-.746.231-.243 1.908-1.312-.006.006z
'
]
},
openai
:
{
color
:
'
#000000
'
,
paths
:
[
'
M21.55 10.004a5.416 5.416 0 00-.478-4.501c-1.217-2.09-3.662-3.166-6.05-2.66A5.59 5.59 0 0010.831 1C8.39.995 6.224 2.546 5.473 4.838A5.553 5.553 0 001.76 7.496a5.487 5.487 0 00.691 6.5 5.416 5.416 0 00.477 4.502c1.217 2.09 3.662 3.165 6.05 2.66A5.586 5.586 0 0013.168 23c2.443.006 4.61-1.546 5.361-3.84a5.553 5.553 0 003.715-2.66 5.488 5.488 0 00-.693-6.497v.001zm-8.381 11.558a4.199 4.199 0 01-2.675-.954c.034-.018.093-.05.132-.074l4.44-2.53a.71.71 0 00.364-.623v-6.176l1.877 1.069c.02.01.033.029.036.05v5.115c-.003 2.274-1.87 4.118-4.174 4.123zM4.192 17.78a4.059 4.059 0 01-.498-2.763c.032.02.09.055.131.078l4.44 2.53c.225.13.504.13.73 0l5.42-3.088v2.138a.068.068 0 01-.027.057L9.9 19.288c-1.999 1.136-4.552.46-5.707-1.51h-.001zM3.023 8.216A4.15 4.15 0 015.198 6.41l-.002.151v5.06a.711.711 0 00.364.624l5.42 3.087-1.876 1.07a.067.067 0 01-.063.005l-4.489-2.559c-1.995-1.14-2.679-3.658-1.53-5.63h.001zm15.417 3.54l-5.42-3.088L14.896 7.6a.067.067 0 01.063-.006l4.489 2.557c1.998 1.14 2.683 3.662 1.529 5.633a4.163 4.163 0 01-2.174 1.807V12.38a.71.71 0 00-.363-.623zm1.867-2.773a6.04 6.04 0 00-.132-.078l-4.44-2.53a.731.731 0 00-.729 0l-5.42 3.088V7.325a.068.068 0 01.027-.057L14.1 4.713c2-1.137 4.555-.46 5.707 1.513.487.833.664 1.809.499 2.757h.001zm-11.741 3.81l-1.877-1.068a.065.065 0 01-.036-.051V6.559c.001-2.277 1.873-4.122 4.181-4.12.976 0 1.92.338 2.671.954-.034.018-.092.05-.131.073l-4.44 2.53a.71.71 0 00-.365.623l-.003 6.173v.002zm1.02-2.168L12 9.25l2.414 1.375v2.75L12 14.75l-2.415-1.375v-2.75z
'
]
},
gemini
:
{
color
:
'
#4285F4
'
,
paths
:
[
'
M20.616 10.835a14.147 14.147 0 01-4.45-3.001 14.111 14.111 0 01-3.678-6.452.503.503 0 00-.975 0 14.134 14.134 0 01-3.679 6.452 14.155 14.155 0 01-4.45 3.001c-.65.28-1.318.505-2.002.678a.502.502 0 000 .975c.684.172 1.35.397 2.002.677a14.147 14.147 0 014.45 3.001 14.112 14.112 0 013.679 6.453.502.502 0 00.975 0c.172-.685.397-1.351.677-2.003a14.145 14.145 0 013.001-4.45 14.113 14.113 0 016.453-3.678.503.503 0 000-.975 13.245 13.245 0 01-2.003-.678z
'
]
},
zhipu
:
{
color
:
'
#3859FF
'
,
paths
:
[
'
M11.991 23.503a.24.24 0 00-.244.248.24.24 0 00.244.249.24.24 0 00.245-.249.24.24 0 00-.22-.247l-.025-.001zM9.671 5.365a1.697 1.697 0 011.099 2.132l-.071.172-.016.04-.018.054c-.07.16-.104.32-.104.498-.035.71.47 1.279 1.186 1.314h.366c1.309.053 2.338 1.173 2.286 2.523-.052 1.332-1.152 2.38-2.478 2.327h-.174c-.715.018-1.274.64-1.239 1.368 0 .124.018.23.053.337.209.373.54.658.96.8.75.23 1.517-.125 1.9-.782l.018-.035c.402-.64 1.17-.96 1.92-.711.854.284 1.378 1.226 1.099 2.167a1.661 1.661 0 01-2.077 1.102 1.711 1.711 0 01-.907-.711l-.017-.035c-.2-.323-.463-.58-.851-.711l-.056-.018a1.646 1.646 0 00-1.954.746 1.66 1.66 0 01-1.065.764 1.677 1.677 0 01-1.989-1.279c-.209-.906.332-1.83 1.257-2.043a1.51 1.51 0 01.296-.035h.018c.68-.071 1.151-.622 1.116-1.333a1.307 1.307 0 00-.227-.693 2.515 2.515 0 01-.366-1.403 2.39 2.39 0 01.366-1.208c.14-.195.21-.444.227-.693.018-.71-.506-1.261-1.186-1.332l-.07-.018a1.43 1.43 0 01-.299-.07l-.05-.019a1.7 1.7 0 01-1.047-2.114 1.68 1.68 0 012.094-1.101zm-5.575 10.11c.26-.264.639-.367.994-.27.355.096.633.379.728.74.095.362-.007.748-.267 1.013-.402.41-1.053.41-1.455 0a1.062 1.062 0 010-1.482zm14.845-.294c.359-.09.738.024.992.297.254.274.344.665.237 1.025-.107.36-.396.634-.756.718-.551.128-1.1-.22-1.23-.781a1.05 1.05 0 01.757-1.26zm-.064-4.39c.314.32.49.753.49 1.206 0 .452-.176.886-.49 1.206-.315.32-.74.5-1.185.5-.444 0-.87-.18-1.184-.5a1.727 1.727 0 010-2.412 1.654 1.654 0 012.369 0zm-11.243.163c.364.484.447 1.128.218 1.691a1.665 1.665 0 01-2.188.923c-.855-.36-1.26-1.358-.907-2.228a1.68 1.68 0 011.33-1.038c.593-.08 1.183.169 1.547.652zm11.545-4.221c.368 0 .708.2.892.524.184.324.184.724 0 1.048a1.026 1.026 0 01-.892.524c-.568 0-1.03-.47-1.03-1.048 0-.579.462-1.048 1.03-1.048zm-14.358 0c.368 0 .707.2.891.524.184.324.184.724 0 1.048a1.026 1.026 0 01-.891.524c-.569 0-1.03-.47-1.03-1.048 0-.579.461-1.048 1.03-1.048zm10.031-1.475c.925 0 1.675.764 1.675 1.706s-.75 1.705-1.675 1.705-1.674-.763-1.674-1.705c0-.942.75-1.706 1.674-1.706zm-2.626-.684c.362-.082.653-.356.761-.718a1.062 1.062 0 00-.238-1.028 1.017 1.017 0 00-.996-.294c-.547.14-.881.7-.752 1.257.13.558.675.907 1.225.783zm0 16.876c.359-.087.644-.36.75-.72a1.062 1.062 0 00-.237-1.019 1.018 1.018 0 00-.985-.301 1.037 1.037 0 00-.762.717c-.108.361-.017.754.239 1.028.245.263.606.377.953.305l.043-.01zM17.19 3.5a.631.631 0 00.628-.64c0-.355-.279-.64-.628-.64a.631.631 0 00-.628.64c0 .355.28.64.628.64zm-10.38 0a.631.631 0 00.628-.64c0-.355-.28-.64-.628-.64a.631.631 0 00-.628.64c0 .355.279.64.628.64zm-5.182 7.852a.631.631 0 00-.628.64c0 .354.28.639.628.639a.63.63 0 00.627-.606l.001-.034a.62.62 0 00-.628-.64zm5.182 9.13a.631.631 0 00-.628.64c0 .355.279.64.628.64a.631.631 0 00.628-.64c0-.355-.28-.64-.628-.64zm10.38.018a.631.631 0 00-.628.64c0 .355.28.64.628.64a.631.631 0 00.628-.64c0-.355-.279-.64-.628-.64zm5.182-9.148a.631.631 0 00-.628.64c0 .354.279.639.628.639a.631.631 0 00.628-.64c0-.355-.28-.64-.628-.64zm-.384-4.992a.24.24 0 00.244-.249.24.24 0 00-.244-.249.24.24 0 00-.244.249c0 .142.122.249.244.249zM11.991.497a.24.24 0 00.245-.248A.24.24 0 0011.99 0a.24.24 0 00-.244.249c0 .133.108.236.223.247l.021.001zM2.011 6.36a.24.24 0 00.245-.249.24.24 0 00-.244-.249.24.24 0 00-.244.249.24.24 0 00.244.249zm0 11.263a.24.24 0 00-.243.248.24.24 0 00.244.249.24.24 0 00.244-.249.252.252 0 00-.244-.248zm19.995-.018a.24.24 0 00-.245.248.24.24 0 00.245.25.24.24 0 00.244-.25.252.252 0 00-.244-.248z
'
]
},
qwen
:
{
color
:
'
#615EFF
'
,
paths
:
[
'
M12.604 1.34c.393.69.784 1.382 1.174 2.075a.18.18 0 00.157.091h5.552c.174 0 .322.11.446.327l1.454 2.57c.19.337.24.478.024.837-.26.43-.513.864-.76 1.3l-.367.658c-.106.196-.223.28-.04.512l2.652 4.637c.172.301.111.494-.043.77-.437.785-.882 1.564-1.335 2.34-.159.272-.352.375-.68.37-.777-.016-1.552-.01-2.327.016a.099.099 0 00-.081.05 575.097 575.097 0 01-2.705 4.74c-.169.293-.38.363-.725.364-.997.003-2.002.004-3.017.002a.537.537 0 01-.465-.271l-1.335-2.323a.09.09 0 00-.083-.049H4.982c-.285.03-.553-.001-.805-.092l-1.603-2.77a.543.543 0 01-.002-.54l1.207-2.12a.198.198 0 000-.197 550.951 550.951 0 01-1.875-3.272l-.79-1.395c-.16-.31-.173-.496.095-.965.465-.813.927-1.625 1.387-2.436.132-.234.304-.334.584-.335a338.3 338.3 0 012.589-.001.124.124 0 00.107-.063l2.806-4.895a.488.488 0 01.422-.246c.524-.001 1.053 0 1.583-.006L11.704 1c.341-.003.724.032.9.34zm-3.432.403a.06.06 0 00-.052.03L6.254 6.788a.157.157 0 01-.135.078H3.253c-.056 0-.07.025-.041.074l5.81 10.156c.025.042.013.062-.034.063l-2.795.015a.218.218 0 00-.2.116l-1.32 2.31c-.044.078-.021.118.068.118l5.716.008c.046 0 .08.02.104.061l1.403 2.454c.046.081.092.082.139 0l5.006-8.76.783-1.382a.055.055 0 01.096 0l1.424 2.53a.122.122 0 00.107.062l2.763-.02a.04.04 0 00.035-.02.041.041 0 000-.04l-2.9-5.086a.108.108 0 010-.113l.293-.507 1.12-1.977c.024-.041.012-.062-.035-.062H9.2c-.059 0-.073-.026-.043-.077l1.434-2.505a.107.107 0 000-.114L9.225 1.774a.06.06 0 00-.053-.031zm6.29 8.02c.046 0 .058.02.034.06l-.832 1.465-2.613 4.585a.056.056 0 01-.05.029.058.058 0 01-.05-.029L8.498 9.841c-.02-.034-.01-.052.028-.054l.216-.012 6.722-.012z
'
]
},
deepseek
:
{
color
:
'
#4D6BFE
'
,
paths
:
[
'
M23.748 4.482c-.254-.124-.364.113-.512.234-.051.039-.094.09-.137.136-.372.397-.806.657-1.373.626-.829-.046-1.537.214-2.163.848-.133-.782-.575-1.248-1.247-1.548-.352-.156-.708-.311-.955-.65-.172-.241-.219-.51-.305-.774-.055-.16-.11-.323-.293-.35-.2-.031-.278.136-.356.276-.313.572-.434 1.202-.422 1.84.027 1.436.633 2.58 1.838 3.393.137.093.172.187.129.323-.082.28-.18.552-.266.833-.055.179-.137.217-.329.14a5.526 5.526 0 01-1.736-1.18c-.857-.828-1.631-1.742-2.597-2.458a11.365 11.365 0 00-.689-.471c-.985-.957.13-1.743.388-1.836.27-.098.093-.432-.779-.428-.872.004-1.67.295-2.687.684a3.055 3.055 0 01-.465.137 9.597 9.597 0 00-2.883-.102c-1.885.21-3.39 1.102-4.497 2.623C.082 8.606-.231 10.684.152 12.85c.403 2.284 1.569 4.175 3.36 5.653 1.858 1.533 3.997 2.284 6.438 2.14 1.482-.085 3.133-.284 4.994-1.86.47.234.962.327 1.78.397.63.059 1.236-.03 1.705-.128.735-.156.684-.837.419-.961-2.155-1.004-1.682-.595-2.113-.926 1.096-1.296 2.746-2.642 3.392-7.003.05-.347.007-.565 0-.845-.004-.17.035-.237.23-.256a4.173 4.173 0 001.545-.475c1.396-.763 1.96-2.015 2.093-3.517.02-.23-.004-.467-.247-.588zM11.581 18c-2.089-1.642-3.102-2.183-3.52-2.16-.392.024-.321.471-.235.763.09.288.207.486.371.739.114.167.192.416-.113.603-.673.416-1.842-.14-1.897-.167-1.361-.802-2.5-1.86-3.301-3.307-.774-1.393-1.224-2.887-1.298-4.482-.02-.386.093-.522.477-.592a4.696 4.696 0 011.529-.039c2.132.312 3.946 1.265 5.468 2.774.868.86 1.525 1.887 2.202 2.891.72 1.066 1.494 2.082 2.48 2.914.348.292.625.514.891.677-.802.09-2.14.11-3.054-.614zm1-6.44a.306.306 0 01.415-.287.302.302 0 01.2.288.306.306 0 01-.31.307.303.303 0 01-.304-.308zm3.11 1.596c-.2.081-.399.151-.59.16a1.245 1.245 0 01-.798-.254c-.274-.23-.47-.358-.552-.758a1.73 1.73 0 01.016-.588c.07-.327-.008-.537-.239-.727-.187-.156-.426-.199-.688-.199a.559.559 0 01-.254-.078c-.11-.054-.2-.19-.114-.358.028-.054.16-.186.192-.21.356-.202.767-.136 1.146.016.352.144.618.408 1.001.782.391.451.462.576.685.914.176.265.336.537.445.848.067.195-.019.354-.25.452z
'
]
},
mistral
:
{
color
:
'
#F7D046
'
,
paths
:
[
'
M3.428 3.4h3.429v3.428h3.429v3.429h-.002 3.431V6.828h3.427V3.4h3.43v13.714H24v3.429H13.714v-3.428h-3.428v-3.429h-3.43v3.428h3.43v3.429H0v-3.429h3.428V3.4zm10.286 13.715h3.428v-3.429h-3.427v3.429z
'
]
},
meta
:
{
color
:
'
#0668E1
'
,
paths
:
[
'
M6.897 4c1.915 0 3.516.932 5.43 3.376l.282-.373c.19-.246.383-.484.58-.71l.313-.35C14.588 4.788 15.792 4 17.225 4c1.273 0 2.469.557 3.491 1.516l.218.213c1.73 1.765 2.917 4.71 3.053 8.026l.011.392.002.25c0 1.501-.28 2.759-.818 3.7l-.14.23-.108.153c-.301.42-.664.758-1.086 1.009l-.265.142-.087.04a3.493 3.493 0 01-.302.118 4.117 4.117 0 01-1.33.208c-.524 0-.996-.067-1.438-.215-.614-.204-1.163-.56-1.726-1.116l-.227-.235c-.753-.812-1.534-1.976-2.493-3.586l-1.43-2.41-.544-.895-1.766 3.13-.343.592C7.597 19.156 6.227 20 4.356 20c-1.21 0-2.205-.42-2.936-1.182l-.168-.184c-.484-.573-.837-1.311-1.043-2.189l-.067-.32a8.69 8.69 0 01-.136-1.288L0 14.468c.002-.745.06-1.49.174-2.23l.1-.573c.298-1.53.828-2.958 1.536-4.157l.209-.34c1.177-1.83 2.789-3.053 4.615-3.16L6.897 4zm-.033 2.615l-.201.01c-.83.083-1.606.673-2.252 1.577l-.138.199-.01.018c-.67 1.017-1.185 2.378-1.456 3.845l-.004.022a12.591 12.591 0 00-.207 2.254l.002.188c.004.18.017.36.04.54l.043.291c.092.503.257.908.486 1.208l.117.137c.303.323.698.492 1.17.492 1.1 0 1.796-.676 3.696-3.641l2.175-3.4.454-.701-.139-.198C9.11 7.3 8.084 6.616 6.864 6.616zm10.196-.552l-.176.007c-.635.048-1.223.359-1.82.933l-.196.198c-.439.462-.887 1.064-1.367 1.807l.266.398c.18.274.362.56.55.858l.293.475 1.396 2.335.695 1.114c.583.926 1.03 1.6 1.408 2.082l.213.262c.282.326.529.54.777.673l.102.05c.227.1.457.138.718.138.176.002.35-.023.518-.073.338-.104.61-.32.813-.637l.095-.163.077-.162c.194-.459.29-1.06.29-1.785l-.006-.449c-.08-2.871-.938-5.372-2.2-6.798l-.176-.189c-.67-.683-1.444-1.074-2.27-1.074z
'
]
},
cohere
:
{
color
:
'
#39594D
'
,
paths
:
[
'
M8.128 14.099c.592 0 1.77-.033 3.398-.703 1.897-.781 5.672-2.2 8.395-3.656 1.905-1.018 2.74-2.366 2.74-4.18A4.56 4.56 0 0018.1 1H7.549A6.55 6.55 0 001 7.55c0 3.617 2.745 6.549 7.128 6.549z
'
,
'
M9.912 18.61a4.387 4.387 0 012.705-4.052l3.323-1.38c3.361-1.394 7.06 1.076 7.06 4.715a5.104 5.104 0 01-5.105 5.104l-3.597-.001a4.386 4.386 0 01-4.386-4.387z
'
,
'
M4.776 14.962A3.775 3.775 0 001 18.738v.489a3.776 3.776 0 007.551 0v-.49a3.775 3.775 0 00-3.775-3.775z
'
]
},
yi
:
{
color
:
'
#003425
'
,
paths
:
[
'
M12 2L2 7l10 5 10-5-10-5zM2 17l10 5 10-5M2 12l10 5 10-5
'
]
},
xai
:
{
color
:
'
#000000
'
,
paths
:
[
'
M9.27 15.29l7.978-5.897c.391-.29.95-.177 1.137.272.98 2.369.542 5.215-1.41 7.169-1.951 1.954-4.667 2.382-7.149 1.406l-2.711 1.257c3.889 2.661 8.611 2.003 11.562-.953 2.341-2.344 3.066-5.539 2.388-8.42l.006.007c-.983-4.232.242-5.924 2.75-9.383.06-.082.12-.164.179-.248l-3.301 3.305v-.01L9.267 15.292M7.623 16.723c-2.792-2.67-2.31-6.801.071-9.184 1.761-1.763 4.647-2.483 7.166-1.425l2.705-1.25a7.808 7.808 0 00-1.829-1A8.975 8.975 0 005.984 5.83c-2.533 2.536-3.33 6.436-1.962 9.764 1.022 2.487-.653 4.246-2.34 6.022-.599.63-1.199 1.259-1.682 1.925l7.62-6.815
'
]
},
moonshot
:
{
color
:
'
#16191E
'
,
paths
:
[
'
M1.052 16.916l9.539 2.552a21.007 21.007 0 00.06 2.033l5.956 1.593a11.997 11.997 0 01-5.586.865l-.18-.016-.044-.004-.084-.009-.094-.01a11.605 11.605 0 01-.157-.02l-.107-.014-.11-.016a11.962 11.962 0 01-.32-.051l-.042-.008-.075-.013-.107-.02-.07-.015-.093-.019-.075-.016-.095-.02-.097-.023-.094-.022-.068-.017-.088-.022-.09-.024-.095-.025-.082-.023-.109-.03-.062-.02-.084-.025-.093-.028-.105-.034-.058-.019-.08-.026-.09-.031-.066-.024a6.293 6.293 0 01-.044-.015l-.068-.025-.101-.037-.057-.022-.08-.03-.087-.035-.088-.035-.079-.032-.095-.04-.063-.028-.063-.027a5.655 5.655 0 01-.041-.018l-.066-.03-.103-.047-.052-.024-.096-.046-.062-.03-.084-.04-.086-.044-.093-.047-.052-.027-.103-.055-.057-.03-.058-.032a6.49 6.49 0 01-.046-.026l-.094-.053-.06-.034-.051-.03-.072-.041-.082-.05-.093-.056-.052-.032-.084-.053-.061-.039-.079-.05-.07-.047-.053-.035a7.785 7.785 0 01-.054-.036l-.044-.03-.044-.03a6.066 6.066 0 01-.04-.028l-.057-.04-.076-.054-.069-.05-.074-.054-.056-.042-.076-.057-.076-.059-.086-.067-.045-.035-.064-.052-.074-.06-.089-.073-.046-.039-.046-.039a7.516 7.516 0 01-.043-.037l-.045-.04-.061-.053-.07-.062-.068-.06-.062-.058-.067-.062-.053-.05-.088-.084a13.28 13.28 0 01-.099-.097l-.029-.028-.041-.042-.069-.07-.05-.051-.05-.053a6.457 6.457 0 01-.168-.179l-.08-.088-.062-.07-.071-.08-.042-.049-.053-.062-.058-.068-.046-.056a7.175 7.175 0 01-.027-.033l-.045-.055-.066-.082-.041-.052-.05-.064-.02-.025a11.99 11.99 0 01-1.44-2.402zm-1.02-5.794l11.353 3.037a20.468 20.468 0 00-.469 2.011l10.817 2.894a12.076 12.076 0 01-1.845 2.005L.657 15.923l-.016-.046-.035-.104a11.965 11.965 0 01-.05-.153l-.007-.023a11.896 11.896 0 01-.207-.741l-.03-.126-.018-.08-.021-.097-.018-.081-.018-.09-.017-.084-.018-.094c-.026-.141-.05-.283-.071-.426l-.017-.118-.011-.083-.013-.102a12.01 12.01 0 01-.019-.161l-.005-.047a12.12 12.12 0 01-.034-2.145zm1.593-5.15l11.948 3.196c-.368.605-.705 1.231-1.01 1.875l11.295 3.022c-.142.82-.368 1.612-.668 2.365l-11.55-3.09L.124 10.26l.015-.1.008-.049.01-.067.015-.087.018-.098c.026-.148.056-.295.088-.442l.028-.124.02-.085.024-.097c.022-.09.045-.18.07-.268l.028-.102.023-.083.03-.1.025-.082.03-.096.026-.082.031-.095a11.896 11.896 0 011.01-2.232zm4.442-4.4L17.352 4.59a20.77 20.77 0 00-1.688 1.721l7.823 2.093c.267.852.442 1.744.513 2.665L2.106 5.213l.045-.065.027-.04.04-.055.046-.065.055-.076.054-.072.064-.086.05-.065.057-.073.055-.07.06-.074.055-.069.065-.077.054-.066.066-.077.053-.06.072-.082.053-.06.067-.074.054-.058.073-.078.058-.06.063-.067.168-.17.1-.098.059-.056.076-.071a12.084 12.084 0 012.272-1.677zM12.017 0h.097l.082.001.069.001.054.002.068.002.046.001.076.003.047.002.06.003.054.002.087.005.105.007.144.011.088.007.044.004.077.008.082.008.047.005.102.012.05.006.108.014.081.01.042.006.065.01.207.032.07.012.065.011.14.026.092.018.11.022.046.01.075.016.041.01L14.7.3l.042.01.065.015.049.012.071.017.096.024.112.03.113.03.113.032.05.015.07.02.078.024.073.023.05.016.05.016.076.025.099.033.102.036.048.017.064.023.093.034.11.041.116.045.1.04.047.02.06.024.041.018.063.026.04.018.057.025.11.048.1.046.074.035.075.036.06.028.092.046.091.045.102.052.053.028.049.026.046.024.06.033.041.022.052.029.088.05.106.06.087.051.057.034.053.032.096.059.088.055.098.062.036.024.064.041.084.056.04.027.062.042.062.043.023.017c.054.037.108.075.161.114l.083.06.065.048.056.043.086.065.082.064.04.03.05.041.086.069.079.065.085.071c.712.6 1.353 1.283 1.909 2.031L7.222.994l.062-.027.065-.028.081-.034.086-.035c.113-.045.227-.09.341-.131l.096-.035.093-.033.084-.03.096-.031c.087-.03.176-.058.264-.085l.091-.027.086-.025.102-.03.085-.023.1-.026L9.04.37l.09-.023.091-.022.095-.022.09-.02.098-.021.091-.02.095-.018.092-.018.1-.018.091-.016.098-.017.092-.014.097-.015.092-.013.102-.013.091-.012.105-.012.09-.01.105-.01c.093-.01.186-.018.28-.024l.106-.008.09-.005.11-.006.093-.004.1-.004.097-.002.099-.002.197-.002z
'
]
},
doubao
:
{
color
:
'
#1C64F2
'
,
paths
:
[
'
M5.31 15.756c.172-3.75 1.883-5.999 2.549-6.739-3.26 2.058-5.425 5.658-6.358 8.308v1.12C1.501 21.513 4.226 24 7.59 24a6.59 6.59 0 002.2-.375c.353-.12.7-.248 1.039-.378.913-.899 1.65-1.91 2.243-2.992-4.877 2.431-7.974.072-7.763-4.5l.002.001z
'
,
'
M22.57 10.283c-1.212-.901-4.109-2.404-7.397-2.8.295 3.792.093 8.766-2.1 12.773a12.782 12.782 0 01-2.244 2.992c3.764-1.448 6.746-3.457 8.596-5.219 2.82-2.683 3.353-5.178 3.361-6.66a2.737 2.737 0 00-.216-1.084v-.002zM14.303 1.867C12.955.7 11.248 0 9.39 0 7.532 0 5.883.677 4.545 1.807 2.791 3.29 1.627 5.557 1.5 8.125v9.201c.932-2.65 3.097-6.25 6.357-8.307.5-.318 1.025-.595 1.569-.829 1.883-.801 3.878-.932 5.746-.706-.222-2.83-.718-5.002-.87-5.617h.001z
'
,
'
M17.305 4.961a199.47 199.47 0 01-1.08-1.094c-.202-.213-.398-.419-.586-.622l-1.333-1.378c.151.615.648 2.786.869 5.617 3.288.395 6.185 1.898 7.396 2.8-1.306-1.275-3.475-3.487-5.266-5.323z
'
]
},
minimax
:
{
color
:
'
#F23F5D
'
,
paths
:
[
'
M16.278 2c1.156 0 2.093.927 2.093 2.07v12.501a.74.74 0 00.744.709.74.74 0 00.743-.709V9.099a2.06 2.06 0 012.071-2.049A2.06 2.06 0 0124 9.1v6.561a.649.649 0 01-.652.645.649.649 0 01-.653-.645V9.1a.762.762 0 00-.766-.758.762.762 0 00-.766.758v7.472a2.037 2.037 0 01-2.048 2.026 2.037 2.037 0 01-2.048-2.026v-12.5a.785.785 0 00-.788-.753.785.785 0 00-.789.752l-.001 15.904A2.037 2.037 0 0113.441 22a2.037 2.037 0 01-2.048-2.026V18.04c0-.356.292-.645.652-.645.36 0 .652.289.652.645v1.934c0 .263.142.506.372.638.23.131.514.131.744 0a.734.734 0 00.372-.638V4.07c0-1.143.937-2.07 2.093-2.07zm-5.674 0c1.156 0 2.093.927 2.093 2.07v11.523a.648.648 0 01-.652.645.648.648 0 01-.652-.645V4.07a.785.785 0 00-.789-.78.785.785 0 00-.789.78v14.013a2.06 2.06 0 01-2.07 2.048 2.06 2.06 0 01-2.071-2.048V9.1a.762.762 0 00-.766-.758.762.762 0 00-.766.758v3.8a2.06 2.06 0 01-2.071 2.049A2.06 2.06 0 010 12.9v-1.378c0-.357.292-.646.652-.646.36 0 .653.29.653.646V12.9c0 .418.343.757.766.757s.766-.339.766-.757V9.099a2.06 2.06 0 012.07-2.048 2.06 2.06 0 012.071 2.048v8.984c0 .419.343.758.767.758.423 0 .766-.339.766-.758V4.07c0-1.143.937-2.07 2.093-2.07z
'
]
},
wenxin
:
{
color
:
'
#167ADF
'
,
paths
:
[
'
M8.859 11.735c1.017-1.71 4.059-3.083 6.202.286 1.579 2.284 4.284 4.397 4.284 4.397s2.027 1.601.73 4.684c-1.24 2.956-5.64 1.607-6.005 1.49l-.024-.009s-1.746-.568-3.776-.112c-2.026.458-3.773.286-3.773.286l-.045-.001c-.328-.01-2.38-.187-3.001-2.968-.675-3.028 2.365-4.687 2.592-4.968.226-.288 1.802-1.37 2.816-3.085zm.986 1.738v2.032h-1.64s-1.64.138-2.213 2.014c-.2 1.252.177 1.99.242 2.148.067.157.596 1.073 1.927 1.342h3.078v-7.514l-1.394-.022zm3.588 2.191l-1.44.024v3.956s.064.985 1.44 1.344h3.541v-5.3h-1.528v3.979h-1.46s-.466-.068-.553-.447v-3.556zM9.82 16.715v3.06H8.58s-.863-.045-1.126-1.049c-.136-.445.02-.959.088-1.16.063-.203.353-.671.951-.85H9.82zm9.525-9.036c2.086 0 2.646 2.06 2.646 2.742 0 .688.284 3.597-2.309 3.655-2.595.057-2.704-1.77-2.704-3.08 0-1.374.277-3.317 2.367-3.317zM4.24 6.08c1.523-.135 2.645 1.55 2.762 2.513.07.625.393 3.486-1.975 4-2.364.515-3.244-2.249-2.984-3.544 0 0 .28-2.797 2.197-2.969zm8.847-1.483c.14-1.31 1.69-3.316 2.931-3.028 1.236.285 2.367 1.944 2.137 3.37-.224 1.428-1.345 3.313-3.095 3.082-1.748-.226-2.143-1.823-1.973-3.424zM9.425 1c1.307 0 2.364 1.519 2.364 3.398 0 1.879-1.057 3.4-2.364 3.4s-2.367-1.521-2.367-3.4C7.058 2.518 8.118 1 9.425 1z
'
]
},
spark
:
{
color
:
'
#0070F0
'
,
paths
:
[
'
M11.615 0l6.237 6.107c2.382 2.338 2.823 3.743 3.161 6.15-1.197-1.732-1.776-2.02-4.504-2.772C12.48 8.374 11.095 5.933 11.615 0z
'
,
'
M9.32 2.122C4.771 6.367 2 9.182 2 13.08c0 5.76 4.288 9.788 9.745 9.918 5.457.13 9.441-5.284 9.095-8.403-.347-3.118-4.418-3.81-4.418-3.81 1.69 3.16-.13 8.098-4.894 8.098-5.154 0-6.8-6.02-4.2-9.008.82 1.617 1.879 2.563 2.674 3.273.717.64 1.219 1.09 1.136 1.664-.173 1.213-1.385.866-1.385.866.346.607 3.6 1.473 4.59-1.342.613-1.741-.423-2.789-1.714-4.096-1.632-1.651-3.672-3.717-3.31-8.118z
'
]
},
hunyuan
:
{
color
:
'
#0053E0
'
,
paths
:
[
'
M12 0c6.627 0 12 5.373 12 12s-5.373 12-12 12S0 18.627 0 12 5.373 0 12 0zm1.652 1.123l-.01-.001c.533.097 1.023.233 1.41.404 6.084 2.683 7.396 9.214 1.601 14.338a3.781 3.781 0 01-5.337-.328 3.654 3.654 0 01-.884-3.044c-1.934.6-3.295 2.305-3.524 4.45-.204 1.912.324 4.044 2.056 5.634l.245.067C10.1 22.876 11.036 23 12 23c6.075 0 11-4.925 11-11 0-5.513-4.056-10.08-9.348-10.877zM2.748 6.21c-.178.269-.348.536-.51.803l-.235.394.078-.167A10.957 10.957 0 001 12c0 4.919 3.228 9.083 7.682 10.49l.214.065C3.523 18.528 2.84 14.149 6.47 8.68A2.234 2.234 0 102.748 6.21zm10.157-5.172c4.408 1.33 3.61 5.41 2.447 6.924-.86 1.117-2.922 1.46-3.708 2.238-.666.657-1.077 1.462-1.212 2.291A5.303 5.303 0 0112 12.258a5.672 5.672 0 001.404-11.169 10.51 10.51 0 00-.5-.052z
'
]
},
cloudflare
:
{
color
:
'
#F38020
'
,
paths
:
[
'
M16.493 17.4c.135-.52.08-.983-.161-1.338-.215-.328-.592-.519-1.05-.519l-8.663-.109a.148.148 0 01-.135-.082c-.027-.054-.027-.109-.027-.163.027-.082.108-.164.189-.164l8.744-.11c1.05-.054 2.153-.9 2.556-1.937l.511-1.31c.027-.055.027-.11.027-.164C17.92 8.91 15.66 7 12.942 7c-2.503 0-4.628 1.638-5.381 3.903a2.432 2.432 0 00-1.803-.491c-1.21.109-2.153 1.092-2.287 2.32-.027.328 0 .628.054.9C1.56 13.688 0 15.326 0 17.319c0 .19.027.355.027.545 0 .082.08.137.161.137h15.983c.08 0 .188-.055.215-.164l.107-.437
'
,
'
M19.238 11.75h-.242c-.054 0-.108.054-.135.109l-.35 1.2c-.134.52-.08.983.162 1.338.215.328.592.518 1.05.518l1.855.11c.054 0 .108.027.135.082.027.054.027.109.027.163-.027.082-.108.164-.188.164l-1.91.11c-1.05.054-2.153.9-2.557 1.937l-.134.355c-.027.055.026.137.107.137h6.592c.081 0 .162-.055.162-.137.107-.41.188-.846.188-1.31-.027-2.62-2.153-4.777-4.762-4.777
'
]
},
midjourney
:
{
color
:
'
#000000
'
,
paths
:
[
'
M22.369 17.676c-1.387 1.259-3.17 2.378-5.332 3.417.044.03.086.057.13.083l.018.01.019.012c.216.123.42.184.641.184.222 0 .426-.061.642-.184l.018-.011.019-.011c.14-.084.266-.178.492-.366l.178-.148c.279-.232.426-.342.625-.456.304-.174.612-.266.949-.266.337 0 .645.092.949.266l.023.014c.188.109.334.219.602.442l.178.148c.221.184.346.278.483.36l.028.017.018.01c.21.12.407.181.62.185h.022a.31.31 0 110 .618c-.337 0-.645-.092-.95-.266a3.137 3.137 0 01-.09-.054l-.022-.014-.022-.013-.02-.014a5.356 5.356 0 01-.49-.377l-.159-.132a3.836 3.836 0 00-.483-.36l-.027-.017-.019-.01a1.256 1.256 0 00-.641-.185c-.222 0-.426.061-.641.184l-.02.011-.018.011c-.14.084-.266.178-.492.366l-.158.132a5.125 5.125 0 01-.51.39l-.022.014-.022.014-.09.054a1.868 1.868 0 01-.95.266c-.337 0-.644-.092-.949-.266a3.137 3.137 0 01-.09-.054l-.022-.014-.022-.013-.026-.017a4.881 4.881 0 01-.425-.325.308.308 0 01-.12-.1l-.098-.081a3.836 3.836 0 00-.483-.36l-.027-.017-.019-.01a1.256 1.256 0 00-.641-.185c-.222 0-.426.061-.642.184l-.018.011-.019.011c-.14.084-.266.178-.492.366l-.158.132a5.125 5.125 0 01-.51.39l-.023.014-.022.014-.09.054A1.868 1.868 0 0112 22c-.337 0-.645-.092-.949-.266a3.137 3.137 0 01-.09-.054l-.022-.014-.022-.013-.021-.014a5.356 5.356 0 01-.49-.377l-.158-.132a3.836 3.836 0 00-.483-.36l-.028-.017-.018-.01a1.256 1.256 0 00-.642-.185c-.221 0-.425.061-.641.184l-.019.011-.018.011c-.141.084-.266.178-.492.366l-.158.132a5.125 5.125 0 01-.511.39l-.022.014-.022.014-.09.054a1.868 1.868 0 01-.986.264c-.746-.09-1.319-.38-1.89-.866l-.035-.03c-.047-.041-.118-.106-.192-.174l-.196-.181-.107-.1-.011-.01a1.531 1.531 0 00-.336-.253.313.313 0 00-.095-.03h-.005c-.119.022-.238.059-.361.11a.308.308 0 01-.077.061l-.008.005a.309.309 0 01-.126.034 5.66 5.66 0 00-.774.518l-.416.324-.055.043a6.542 6.542 0 01-.324.236c-.305.207-.552.315-.8.315a.31.31 0 01-.01-.618h.01c.09 0 .235-.062.438-.198l.04-.027c.077-.054.163-.117.27-.199l.385-.301.06-.047c.268-.206.506-.373.73-.505l-.633-1.21a.309.309 0 01.254-.451l20.287-1.305a.309.309 0 01.228.537zm-1.118.14L2.369 19.03l.423.809c.128-.045.256-.078.388-.1a.31.31 0 01.052-.005c.132 0 .26.032.386.093.153.073.294.179.483.35l.016.015.092.086.144.134.097.089c.065.06.125.114.16.144.485.418.948.658 1.554.736h.011a1.25 1.25 0 00.6-.172l.021-.011.019-.011.018-.011c.141-.084.266-.178.492-.366l.178-.148c.279-.232.426-.342.625-.456.305-.174.612-.266.95-.266.336 0 .644.092.948.266l.023.014c.188.109.335.219.603.442l.177.148c.222.184.346.278.484.36l.027.017.019.01c.215.124.42.185.641.185.222 0 .426-.061.641-.184l.019-.011.018-.011c.141-.084.267-.178.493-.366l.177-.148c.28-.232.427-.342.626-.456.304-.174.612-.266.949-.266.337 0 .644.092.949.266l.025.015c.187.109.334.22.603.443 1.867-.878 3.448-1.811 4.73-2.832l.02-.016zM3.653 2.026C6.073 3.06 8.69 4.941 10.8 7.258c2.46 2.7 4.109 5.828 4.637 9.149a.31.31 0 01-.421.335c-2.348-.945-4.54-1.258-6.59-1.02-1.739.2-3.337.792-4.816 1.703-.294.182-.62-.182-.405-.454 1.856-2.355 2.581-4.99 2.343-7.794-.195-2.292-1.031-4.61-2.284-6.709a.31.31 0 01.388-.442zM10.04 4.45c1.778.543 3.892 2.102 5.782 4.243 1.984 2.248 3.552 4.934 4.347 7.582a.31.31 0 01-.401.38l-.022-.01-.386-.154a10.594 10.594 0 00-.291-.112l-.016-.006c-.68-.247-1.199-.291-1.944-.101a.31.31 0 01-.375-.218C15.378 11.123 13.073 7.276 9.775 5c-.291-.201-.072-.653.266-.55zM4.273 2.996l.008.015c1.028 1.94 1.708 4.031 1.885 6.113.213 2.513-.31 4.906-1.673 7.092l-.02.031.003-.001c1.198-.581 2.47-.969 3.825-1.132l.055-.006c1.981-.23 4.083.029 6.309.837l.066.025-.007-.039c-.593-2.95-2.108-5.737-4.31-8.179l-.07-.078c-1.785-1.96-3.944-3.6-6.014-4.65l-.057-.028zm7.92 3.238l.048.048c2.237 2.295 3.885 5.431 4.974 9.191l.038.132.022-.004c.71-.133 1.284-.063 1.963.18l.027.01.066.024.046.018-.025-.073c-.811-2.307-2.208-4.62-3.936-6.594l-.058-.065c-1.02-1.155-2.103-2.132-3.15-2.856l-.015-.011z
'
]
},
perplexity
:
{
color
:
'
#22B8CD
'
,
paths
:
[
'
M19.785 0v7.272H22.5V17.62h-2.935V24l-7.037-6.194v6.145h-1.091v-6.152L4.392 24v-6.465H1.5V7.188h2.884V0l7.053 6.494V.19h1.09v6.49L19.786 0zm-7.257 9.044v7.319l5.946 5.234V14.44l-5.946-5.397zm-1.099-.08l-5.946 5.398v7.235l5.946-5.234V8.965zm8.136 7.58h1.844V8.349H13.46l6.105 5.54v2.655zm-8.982-8.28H2.59v8.195h1.8v-2.576l6.192-5.62zM5.475 2.476v4.71h5.115l-5.115-4.71zm13.219 0l-5.115 4.71h5.115v-4.71z
'
]
},
jina
:
{
color
:
'
#000000
'
,
paths
:
[
'
M6.608 21.416a4.608 4.608 0 100-9.217 4.608 4.608 0 000 9.217zM20.894 2.015c.614 0 1.106.492 1.106 1.106v9.002c0 5.13-4.148 9.309-9.217 9.37v-9.355l-.03-9.032c0-.614.491-1.106 1.106-1.106h7.158l-.123.015z
'
]
},
openrouter
:
{
color
:
'
#6566F1
'
,
paths
:
[
'
M16.804 1.957l7.22 4.105v.087L16.73 10.21l.017-2.117-.821-.03c-1.059-.028-1.611.002-2.268.11-1.064.175-2.038.577-3.147 1.352L8.345 11.03c-.284.195-.495.336-.68.455l-.515.322-.397.234.385.23.53.338c.476.314 1.17.796 2.701 1.866 1.11.775 2.083 1.177 3.147 1.352l.3.045c.694.091 1.375.094 2.825.033l.022-2.159 7.22 4.105v.087L16.589 22l.014-1.862-.635.022c-1.386.042-2.137.002-3.138-.162-1.694-.28-3.26-.926-4.881-2.059l-2.158-1.5a21.997 21.997 0 00-.755-.498l-.467-.28a55.927 55.927 0 00-.76-.43C2.908 14.73.563 14.116 0 14.116V9.888l.14.004c.564-.007 2.91-.622 3.809-1.124l1.016-.58.438-.274c.428-.28 1.072-.726 2.686-1.853 1.621-1.133 3.186-1.78 4.881-2.059 1.152-.19 1.974-.213 3.814-.138l.02-1.907z
'
]
},
suno
:
{
color
:
'
#000000
'
,
paths
:
[
'
M16.5 0C20.642 0 24 5.373 24 12h-9c0 6.627-3.358 12-7.5 12C3.358 24 0 18.627 0 12h9c0-6.627 3.358-12 7.5-12z
'
]
},
ollama
:
{
color
:
'
#000000
'
,
paths
:
[
'
M7.905 1.09c.216.085.411.225.588.41.295.306.544.744.734 1.263.191.522.315 1.1.362 1.68a5.054 5.054 0 012.049-.636l.051-.004c.87-.07 1.73.087 2.48.474.101.053.2.11.297.17.05-.569.172-1.134.36-1.644.19-.52.439-.957.733-1.264a1.67 1.67 0 01.589-.41c.257-.1.53-.118.796-.042.401.114.745.368 1.016.737.248.337.434.769.561 1.287.23.934.27 2.163.115 3.645l.053.04.026.019c.757.576 1.284 1.397 1.563 2.35.435 1.487.216 3.155-.534 4.088l-.018.021.002.003c.417.762.67 1.567.724 2.4l.002.03c.064 1.065-.2 2.137-.814 3.19l-.007.01.01.024c.472 1.157.62 2.322.438 3.486l-.006.039a.651.651 0 01-.747.536.648.648 0 01-.54-.742c.167-1.033.01-2.069-.48-3.123a.643.643 0 01.04-.617l.004-.006c.604-.924.854-1.83.8-2.72-.046-.779-.325-1.544-.8-2.273a.644.644 0 01.18-.886l.009-.006c.243-.159.467-.565.58-1.12a4.229 4.229 0 00-.095-1.974c-.205-.7-.58-1.284-1.105-1.683-.595-.454-1.383-.673-2.38-.61a.653.653 0 01-.632-.371c-.314-.665-.772-1.141-1.343-1.436a3.288 3.288 0 00-1.772-.332c-1.245.099-2.343.801-2.67 1.686a.652.652 0 01-.61.425c-1.067.002-1.893.252-2.497.703-.522.39-.878.935-1.066 1.588a4.07 4.07 0 00-.068 1.886c.112.558.331 1.02.582 1.269l.008.007c.212.207.257.53.109.785-.36.622-.629 1.549-.673 2.44-.05 1.018.186 1.902.719 2.536l.016.019a.643.643 0 01.095.69c-.576 1.236-.753 2.252-.562 3.052a.652.652 0 01-1.269.298c-.243-1.018-.078-2.184.473-3.498l.014-.035-.008-.012a4.339 4.339 0 01-.598-1.309l-.005-.019a5.764 5.764 0 01-.177-1.785c.044-.91.278-1.842.622-2.59l.012-.026-.002-.002c-.293-.418-.51-.953-.63-1.545l-.005-.024a5.352 5.352 0 01.093-2.49c.262-.915.777-1.701 1.536-2.269.06-.045.123-.09.186-.132-.159-1.493-.119-2.73.112-3.67.127-.518.314-.95.562-1.287.27-.368.614-.622 1.015-.737.266-.076.54-.059.797.042zm4.116 9.09c.936 0 1.8.313 2.446.855.63.527 1.005 1.235 1.005 1.94 0 .888-.406 1.58-1.133 2.022-.62.375-1.451.557-2.403.557-1.009 0-1.871-.259-2.493-.734-.617-.47-.963-1.13-.963-1.845 0-.707.398-1.417 1.056-1.946.668-.537 1.55-.849 2.485-.849zm0 .896a3.07 3.07 0 00-1.916.65c-.461.37-.722.835-.722 1.25 0 .428.21.829.61 1.134.455.347 1.124.548 1.943.548.799 0 1.473-.147 1.932-.426.463-.28.7-.686.7-1.257 0-.423-.246-.89-.683-1.256-.484-.405-1.14-.643-1.864-.643zm.662 1.21l.004.004c.12.151.095.37-.056.49l-.292.23v.446a.375.375 0 01-.376.373.375.375 0 01-.376-.373v-.46l-.271-.218a.347.347 0 01-.052-.49.353.353 0 01.494-.051l.215.172.22-.174a.353.353 0 01.49.051zm-5.04-1.919c.478 0 .867.39.867.871a.87.87 0 01-.868.871.87.87 0 01-.867-.87.87.87 0 01.867-.872zm8.706 0c.48 0 .868.39.868.871a.87.87 0 01-.868.871.87.87 0 01-.867-.87.87.87 0 01.867-.872zM7.44 2.3l-.003.002a.659.659 0 00-.285.238l-.005.006c-.138.189-.258.467-.348.832-.17.692-.216 1.631-.124 2.782.43-.128.899-.208 1.404-.237l.01-.001.019-.034c.046-.082.095-.161.148-.239.123-.771.022-1.692-.253-2.444-.134-.364-.297-.65-.453-.813a.628.628 0 00-.107-.09L7.44 2.3zm9.174.04l-.002.001a.628.628 0 00-.107.09c-.156.163-.32.45-.453.814-.29.794-.387 1.776-.23 2.572l.058.097.008.014h.03a5.184 5.184 0 011.466.212c.086-1.124.038-2.043-.128-2.722-.09-.365-.21-.643-.349-.832l-.004-.006a.659.659 0 00-.285-.239h-.004z
'
]
},
ai360
:
{
color
:
'
#23B7E5
'
,
paths
:
[
'
M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 18c-4.41 0-8-3.59-8-8s3.59-8 8-8 8 3.59 8 8-3.59 8-8 8z
'
]
},
dify
:
{
color
:
'
#1677FF
'
,
paths
:
[
'
M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 18c-4.41 0-8-3.59-8-8s3.59-8 8-8 8 3.59 8 8-3.59 8-8 8z
'
]
},
coze
:
{
color
:
'
#5436F5
'
,
paths
:
[
'
M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 18c-4.41 0-8-3.59-8-8s3.59-8 8-8 8 3.59 8 8-3.59 8-8 8z
'
]
}
}
const
fallbackText
=
computed
(()
=>
props
.
model
.
charAt
(
0
).
toUpperCase
())
const
iconKey
=
computed
(()
=>
{
const
modelLower
=
props
.
model
.
toLowerCase
()
// OpenAI models
if
(
modelLower
.
startsWith
(
'
gpt
'
)
||
modelLower
.
startsWith
(
'
o1
'
)
||
modelLower
.
startsWith
(
'
o3
'
)
||
modelLower
.
startsWith
(
'
o4
'
)
||
modelLower
.
includes
(
'
chatgpt
'
)
||
modelLower
.
includes
(
'
dall-e
'
)
||
modelLower
.
includes
(
'
whisper
'
)
||
modelLower
.
includes
(
'
tts-1
'
)
||
modelLower
.
includes
(
'
text-embedding-3
'
)
||
modelLower
.
includes
(
'
text-moderation
'
)
||
modelLower
.
includes
(
'
babbage
'
)
||
modelLower
.
includes
(
'
davinci
'
)
||
modelLower
.
includes
(
'
curie
'
)
||
modelLower
.
includes
(
'
ada
'
))
return
'
openai
'
// Anthropic Claude
if
(
modelLower
.
includes
(
'
claude
'
))
return
'
claude
'
// Google Gemini
if
(
modelLower
.
includes
(
'
gemini
'
)
||
modelLower
.
includes
(
'
gemma
'
)
||
modelLower
.
includes
(
'
learnlm
'
)
||
modelLower
.
includes
(
'
imagen-
'
)
||
modelLower
.
includes
(
'
veo-
'
))
return
'
gemini
'
// Zhipu GLM
if
(
modelLower
.
includes
(
'
glm
'
)
||
modelLower
.
includes
(
'
chatglm
'
)
||
modelLower
.
includes
(
'
cogview
'
)
||
modelLower
.
includes
(
'
cogvideo
'
))
return
'
zhipu
'
// Alibaba Qwen
if
(
modelLower
.
includes
(
'
qwen
'
)
||
modelLower
.
includes
(
'
qwq
'
))
return
'
qwen
'
// DeepSeek
if
(
modelLower
.
includes
(
'
deepseek
'
))
return
'
deepseek
'
// Mistral
if
(
modelLower
.
includes
(
'
mistral
'
)
||
modelLower
.
includes
(
'
mixtral
'
)
||
modelLower
.
includes
(
'
codestral
'
)
||
modelLower
.
includes
(
'
pixtral
'
)
||
modelLower
.
includes
(
'
voxtral
'
)
||
modelLower
.
includes
(
'
magistral
'
))
return
'
mistral
'
// Meta Llama
if
(
modelLower
.
includes
(
'
llama
'
))
return
'
meta
'
// Cohere
if
(
modelLower
.
includes
(
'
command
'
)
||
modelLower
.
includes
(
'
c4ai-
'
)
||
modelLower
.
includes
(
'
embed-
'
))
return
'
cohere
'
// Yi
if
(
modelLower
.
startsWith
(
'
yi-
'
)
||
modelLower
.
startsWith
(
'
yi
'
))
return
'
yi
'
// xAI Grok
if
(
modelLower
.
includes
(
'
grok
'
))
return
'
xai
'
// Moonshot
if
(
modelLower
.
includes
(
'
moonshot
'
)
||
modelLower
.
includes
(
'
kimi
'
))
return
'
moonshot
'
// Doubao (ByteDance)
if
(
modelLower
.
includes
(
'
doubao
'
))
return
'
doubao
'
// MiniMax
if
(
modelLower
.
includes
(
'
abab
'
)
||
modelLower
.
includes
(
'
minimax
'
))
return
'
minimax
'
// Baidu Wenxin
if
(
modelLower
.
includes
(
'
ernie
'
)
||
modelLower
.
includes
(
'
wenxin
'
))
return
'
wenxin
'
// iFlytek Spark
if
(
modelLower
.
includes
(
'
spark
'
))
return
'
spark
'
// Tencent Hunyuan
if
(
modelLower
.
includes
(
'
hunyuan
'
))
return
'
hunyuan
'
// Cloudflare
if
(
modelLower
.
includes
(
'
@cf/
'
))
return
'
cloudflare
'
// Midjourney
if
(
modelLower
.
includes
(
'
mj_
'
)
||
modelLower
.
includes
(
'
midjourney
'
))
return
'
midjourney
'
// Perplexity
if
(
modelLower
.
includes
(
'
perplexity
'
)
||
modelLower
.
includes
(
'
pplx
'
))
return
'
perplexity
'
// Jina
if
(
modelLower
.
includes
(
'
jina
'
))
return
'
jina
'
// OpenRouter
if
(
modelLower
.
includes
(
'
openrouter
'
))
return
'
openrouter
'
// Suno
if
(
modelLower
.
includes
(
'
suno
'
))
return
'
suno
'
// Ollama
if
(
modelLower
.
includes
(
'
ollama
'
))
return
'
ollama
'
// 360
if
(
modelLower
.
includes
(
'
360
'
))
return
'
ai360
'
// Dify
if
(
modelLower
.
includes
(
'
dify
'
))
return
'
dify
'
// Coze
if
(
modelLower
.
includes
(
'
coze
'
))
return
'
coze
'
return
null
})
const
iconInfo
=
computed
(()
=>
iconKey
.
value
?
iconData
[
iconKey
.
value
]
:
null
)
</
script
>
<
style
scoped
>
.model-icon
{
flex-shrink
:
0
;
}
.model-icon-fallback
{
display
:
inline-flex
;
align-items
:
center
;
justify-content
:
center
;
border-radius
:
4px
;
background
:
linear-gradient
(
135deg
,
#6366f1
,
#8b5cf6
);
color
:
white
;
font-weight
:
600
;
flex-shrink
:
0
;
}
</
style
>
frontend/src/composables/useModelWhitelist.ts
0 → 100644
View file @
2c71c8b9
// =====================
// 模型列表(硬编码,与 new-api 一致)
// =====================
// OpenAI
const
openaiModels
=
[
'
gpt-3.5-turbo
'
,
'
gpt-3.5-turbo-0125
'
,
'
gpt-3.5-turbo-1106
'
,
'
gpt-3.5-turbo-16k
'
,
'
gpt-4
'
,
'
gpt-4-turbo
'
,
'
gpt-4-turbo-preview
'
,
'
gpt-4o
'
,
'
gpt-4o-2024-08-06
'
,
'
gpt-4o-2024-11-20
'
,
'
gpt-4o-mini
'
,
'
gpt-4o-mini-2024-07-18
'
,
'
gpt-4.5-preview
'
,
'
gpt-4.1
'
,
'
gpt-4.1-mini
'
,
'
gpt-4.1-nano
'
,
'
o1
'
,
'
o1-preview
'
,
'
o1-mini
'
,
'
o1-pro
'
,
'
o3
'
,
'
o3-mini
'
,
'
o3-pro
'
,
'
o4-mini
'
,
'
gpt-5
'
,
'
gpt-5-mini
'
,
'
gpt-5-nano
'
,
'
chatgpt-4o-latest
'
,
'
gpt-4o-audio-preview
'
,
'
gpt-4o-realtime-preview
'
]
// Anthropic Claude
export
const
claudeModels
=
[
'
claude-3-5-sonnet-20241022
'
,
'
claude-3-5-sonnet-20240620
'
,
'
claude-3-5-haiku-20241022
'
,
'
claude-3-opus-20240229
'
,
'
claude-3-sonnet-20240229
'
,
'
claude-3-haiku-20240307
'
,
'
claude-3-7-sonnet-20250219
'
,
'
claude-sonnet-4-20250514
'
,
'
claude-opus-4-20250514
'
,
'
claude-opus-4-1-20250805
'
,
'
claude-sonnet-4-5-20250929
'
,
'
claude-haiku-4-5-20251001
'
,
'
claude-opus-4-5-20251101
'
,
'
claude-2.1
'
,
'
claude-2.0
'
,
'
claude-instant-1.2
'
]
// Google Gemini
const
geminiModels
=
[
'
gemini-2.0-flash
'
,
'
gemini-2.0-flash-lite-preview
'
,
'
gemini-2.0-flash-exp
'
,
'
gemini-2.0-pro-exp
'
,
'
gemini-2.0-flash-thinking-exp
'
,
'
gemini-2.5-pro-exp-03-25
'
,
'
gemini-2.5-pro-preview-03-25
'
,
'
gemini-3-pro-preview
'
,
'
gemini-1.5-pro
'
,
'
gemini-1.5-pro-latest
'
,
'
gemini-1.5-flash
'
,
'
gemini-1.5-flash-latest
'
,
'
gemini-1.5-flash-8b
'
,
'
gemini-exp-1206
'
]
// 智谱 GLM
const
zhipuModels
=
[
'
glm-4
'
,
'
glm-4v
'
,
'
glm-4-plus
'
,
'
glm-4-0520
'
,
'
glm-4-air
'
,
'
glm-4-airx
'
,
'
glm-4-long
'
,
'
glm-4-flash
'
,
'
glm-4v-plus
'
,
'
glm-4.5
'
,
'
glm-4.6
'
,
'
glm-3-turbo
'
,
'
glm-4-alltools
'
,
'
chatglm_turbo
'
,
'
chatglm_pro
'
,
'
chatglm_std
'
,
'
chatglm_lite
'
,
'
cogview-3
'
,
'
cogvideo
'
]
// 阿里 通义千问
const
qwenModels
=
[
'
qwen-turbo
'
,
'
qwen-plus
'
,
'
qwen-max
'
,
'
qwen-max-longcontext
'
,
'
qwen-long
'
,
'
qwen2-72b-instruct
'
,
'
qwen2-57b-a14b-instruct
'
,
'
qwen2-7b-instruct
'
,
'
qwen2.5-72b-instruct
'
,
'
qwen2.5-32b-instruct
'
,
'
qwen2.5-14b-instruct
'
,
'
qwen2.5-7b-instruct
'
,
'
qwen2.5-3b-instruct
'
,
'
qwen2.5-1.5b-instruct
'
,
'
qwen2.5-coder-32b-instruct
'
,
'
qwen2.5-coder-14b-instruct
'
,
'
qwen2.5-coder-7b-instruct
'
,
'
qwen3-235b-a22b
'
,
'
qwq-32b
'
,
'
qwq-32b-preview
'
]
// DeepSeek
const
deepseekModels
=
[
'
deepseek-chat
'
,
'
deepseek-coder
'
,
'
deepseek-reasoner
'
,
'
deepseek-v3
'
,
'
deepseek-v3-0324
'
,
'
deepseek-r1
'
,
'
deepseek-r1-0528
'
,
'
deepseek-r1-distill-qwen-32b
'
,
'
deepseek-r1-distill-qwen-14b
'
,
'
deepseek-r1-distill-qwen-7b
'
,
'
deepseek-r1-distill-llama-70b
'
,
'
deepseek-r1-distill-llama-8b
'
]
// Mistral
const
mistralModels
=
[
'
mistral-small-latest
'
,
'
mistral-medium-latest
'
,
'
mistral-large-latest
'
,
'
open-mistral-7b
'
,
'
open-mixtral-8x7b
'
,
'
open-mixtral-8x22b
'
,
'
codestral-latest
'
,
'
codestral-mamba
'
,
'
pixtral-12b-2409
'
,
'
pixtral-large-latest
'
]
// Meta Llama
const
metaModels
=
[
'
llama-3.3-70b-instruct
'
,
'
llama-3.2-90b-vision-instruct
'
,
'
llama-3.2-11b-vision-instruct
'
,
'
llama-3.2-3b-instruct
'
,
'
llama-3.2-1b-instruct
'
,
'
llama-3.1-405b-instruct
'
,
'
llama-3.1-70b-instruct
'
,
'
llama-3.1-8b-instruct
'
,
'
llama-3-70b-instruct
'
,
'
llama-3-8b-instruct
'
,
'
codellama-70b-instruct
'
,
'
codellama-34b-instruct
'
,
'
codellama-13b-instruct
'
]
// xAI Grok
const
xaiModels
=
[
'
grok-4
'
,
'
grok-4-0709
'
,
'
grok-3-beta
'
,
'
grok-3-mini-beta
'
,
'
grok-3-fast-beta
'
,
'
grok-2
'
,
'
grok-2-vision
'
,
'
grok-2-image
'
,
'
grok-beta
'
,
'
grok-vision-beta
'
]
// Cohere
const
cohereModels
=
[
'
command-a-03-2025
'
,
'
command-r
'
,
'
command-r-plus
'
,
'
command-r-08-2024
'
,
'
command-r-plus-08-2024
'
,
'
c4ai-aya-23-35b
'
,
'
c4ai-aya-23-8b
'
,
'
command
'
,
'
command-light
'
]
// Yi (01.AI)
const
yiModels
=
[
'
yi-large
'
,
'
yi-large-turbo
'
,
'
yi-large-rag
'
,
'
yi-medium
'
,
'
yi-medium-200k
'
,
'
yi-spark
'
,
'
yi-vision
'
,
'
yi-1.5-34b-chat
'
,
'
yi-1.5-9b-chat
'
,
'
yi-1.5-6b-chat
'
]
// Moonshot/Kimi
const
moonshotModels
=
[
'
moonshot-v1-8k
'
,
'
moonshot-v1-32k
'
,
'
moonshot-v1-128k
'
,
'
kimi-latest
'
]
// 字节跳动 豆包
const
doubaoModels
=
[
'
doubao-pro-256k
'
,
'
doubao-pro-128k
'
,
'
doubao-pro-32k
'
,
'
doubao-pro-4k
'
,
'
doubao-lite-128k
'
,
'
doubao-lite-32k
'
,
'
doubao-lite-4k
'
,
'
doubao-vision-pro-32k
'
,
'
doubao-vision-lite-32k
'
,
'
doubao-1.5-pro-256k
'
,
'
doubao-1.5-pro-32k
'
,
'
doubao-1.5-lite-32k
'
,
'
doubao-1.5-pro-vision-32k
'
,
'
doubao-1.5-thinking-pro
'
]
// MiniMax
const
minimaxModels
=
[
'
abab6.5-chat
'
,
'
abab6.5s-chat
'
,
'
abab6.5s-chat-pro
'
,
'
abab6-chat
'
,
'
abab5.5-chat
'
,
'
abab5.5s-chat
'
]
// 百度 文心
const
baiduModels
=
[
'
ernie-4.0-8k-latest
'
,
'
ernie-4.0-8k
'
,
'
ernie-4.0-turbo-8k
'
,
'
ernie-3.5-8k
'
,
'
ernie-3.5-128k
'
,
'
ernie-speed-8k
'
,
'
ernie-speed-128k
'
,
'
ernie-speed-pro-128k
'
,
'
ernie-lite-8k
'
,
'
ernie-lite-pro-128k
'
,
'
ernie-tiny-8k
'
]
// 讯飞 星火
const
sparkModels
=
[
'
spark-desk
'
,
'
spark-desk-v1.1
'
,
'
spark-desk-v2.1
'
,
'
spark-desk-v3.1
'
,
'
spark-desk-v3.5
'
,
'
spark-desk-v4.0
'
,
'
spark-lite
'
,
'
spark-pro
'
,
'
spark-max
'
,
'
spark-ultra
'
]
// 腾讯 混元
const
hunyuanModels
=
[
'
hunyuan-lite
'
,
'
hunyuan-standard
'
,
'
hunyuan-standard-256k
'
,
'
hunyuan-pro
'
,
'
hunyuan-turbo
'
,
'
hunyuan-large
'
,
'
hunyuan-vision
'
,
'
hunyuan-code
'
]
// Perplexity
const
perplexityModels
=
[
'
sonar
'
,
'
sonar-pro
'
,
'
sonar-reasoning
'
,
'
llama-3-sonar-small-32k-online
'
,
'
llama-3-sonar-large-32k-online
'
,
'
llama-3-sonar-small-32k-chat
'
,
'
llama-3-sonar-large-32k-chat
'
]
// 所有模型(去重)
const
allModelsList
:
string
[]
=
[
...
openaiModels
,
...
claudeModels
,
...
geminiModels
,
...
zhipuModels
,
...
qwenModels
,
...
deepseekModels
,
...
mistralModels
,
...
metaModels
,
...
xaiModels
,
...
cohereModels
,
...
yiModels
,
...
moonshotModels
,
...
doubaoModels
,
...
minimaxModels
,
...
baiduModels
,
...
sparkModels
,
...
hunyuanModels
,
...
perplexityModels
]
// 转换为下拉选项格式
export
const
allModels
=
allModelsList
.
map
(
m
=>
({
value
:
m
,
label
:
m
}))
// =====================
// 预设映射
// =====================
const
anthropicPresetMappings
=
[
{
label
:
'
Sonnet 4
'
,
from
:
'
claude-sonnet-4-20250514
'
,
to
:
'
claude-sonnet-4-20250514
'
,
color
:
'
bg-blue-100 text-blue-700 hover:bg-blue-200 dark:bg-blue-900/30 dark:text-blue-400
'
},
{
label
:
'
Sonnet 4.5
'
,
from
:
'
claude-sonnet-4-5-20250929
'
,
to
:
'
claude-sonnet-4-5-20250929
'
,
color
:
'
bg-indigo-100 text-indigo-700 hover:bg-indigo-200 dark:bg-indigo-900/30 dark:text-indigo-400
'
},
{
label
:
'
Opus 4.5
'
,
from
:
'
claude-opus-4-5-20251101
'
,
to
:
'
claude-opus-4-5-20251101
'
,
color
:
'
bg-purple-100 text-purple-700 hover:bg-purple-200 dark:bg-purple-900/30 dark:text-purple-400
'
},
{
label
:
'
Haiku 3.5
'
,
from
:
'
claude-3-5-haiku-20241022
'
,
to
:
'
claude-3-5-haiku-20241022
'
,
color
:
'
bg-green-100 text-green-700 hover:bg-green-200 dark:bg-green-900/30 dark:text-green-400
'
},
{
label
:
'
Haiku 4.5
'
,
from
:
'
claude-haiku-4-5-20251001
'
,
to
:
'
claude-haiku-4-5-20251001
'
,
color
:
'
bg-emerald-100 text-emerald-700 hover:bg-emerald-200 dark:bg-emerald-900/30 dark:text-emerald-400
'
},
{
label
:
'
Opus->Sonnet
'
,
from
:
'
claude-opus-4-5-20251101
'
,
to
:
'
claude-sonnet-4-5-20250929
'
,
color
:
'
bg-amber-100 text-amber-700 hover:bg-amber-200 dark:bg-amber-900/30 dark:text-amber-400
'
}
]
const
openaiPresetMappings
=
[
{
label
:
'
GPT-4o
'
,
from
:
'
gpt-4o
'
,
to
:
'
gpt-4o
'
,
color
:
'
bg-green-100 text-green-700 hover:bg-green-200 dark:bg-green-900/30 dark:text-green-400
'
},
{
label
:
'
GPT-4o Mini
'
,
from
:
'
gpt-4o-mini
'
,
to
:
'
gpt-4o-mini
'
,
color
:
'
bg-blue-100 text-blue-700 hover:bg-blue-200 dark:bg-blue-900/30 dark:text-blue-400
'
},
{
label
:
'
GPT-4.1
'
,
from
:
'
gpt-4.1
'
,
to
:
'
gpt-4.1
'
,
color
:
'
bg-indigo-100 text-indigo-700 hover:bg-indigo-200 dark:bg-indigo-900/30 dark:text-indigo-400
'
},
{
label
:
'
o1
'
,
from
:
'
o1
'
,
to
:
'
o1
'
,
color
:
'
bg-purple-100 text-purple-700 hover:bg-purple-200 dark:bg-purple-900/30 dark:text-purple-400
'
},
{
label
:
'
o3
'
,
from
:
'
o3
'
,
to
:
'
o3
'
,
color
:
'
bg-emerald-100 text-emerald-700 hover:bg-emerald-200 dark:bg-emerald-900/30 dark:text-emerald-400
'
},
{
label
:
'
GPT-5
'
,
from
:
'
gpt-5
'
,
to
:
'
gpt-5
'
,
color
:
'
bg-amber-100 text-amber-700 hover:bg-amber-200 dark:bg-amber-900/30 dark:text-amber-400
'
}
]
const
geminiPresetMappings
=
[
{
label
:
'
Flash 2.0
'
,
from
:
'
gemini-2.0-flash
'
,
to
:
'
gemini-2.0-flash
'
,
color
:
'
bg-blue-100 text-blue-700 hover:bg-blue-200 dark:bg-blue-900/30 dark:text-blue-400
'
},
{
label
:
'
Flash Lite
'
,
from
:
'
gemini-2.0-flash-lite-preview
'
,
to
:
'
gemini-2.0-flash-lite-preview
'
,
color
:
'
bg-indigo-100 text-indigo-700 hover:bg-indigo-200 dark:bg-indigo-900/30 dark:text-indigo-400
'
},
{
label
:
'
1.5 Pro
'
,
from
:
'
gemini-1.5-pro
'
,
to
:
'
gemini-1.5-pro
'
,
color
:
'
bg-purple-100 text-purple-700 hover:bg-purple-200 dark:bg-purple-900/30 dark:text-purple-400
'
},
{
label
:
'
1.5 Flash
'
,
from
:
'
gemini-1.5-flash
'
,
to
:
'
gemini-1.5-flash
'
,
color
:
'
bg-emerald-100 text-emerald-700 hover:bg-emerald-200 dark:bg-emerald-900/30 dark:text-emerald-400
'
}
]
// =====================
// 常用错误码
// =====================
export
const
commonErrorCodes
=
[
{
value
:
401
,
label
:
'
Unauthorized
'
},
{
value
:
403
,
label
:
'
Forbidden
'
},
{
value
:
429
,
label
:
'
Rate Limit
'
},
{
value
:
500
,
label
:
'
Server Error
'
},
{
value
:
502
,
label
:
'
Bad Gateway
'
},
{
value
:
503
,
label
:
'
Unavailable
'
},
{
value
:
529
,
label
:
'
Overloaded
'
}
]
// =====================
// 辅助函数
// =====================
// 按平台获取模型
export
function
getModelsByPlatform
(
platform
:
string
):
string
[]
{
switch
(
platform
)
{
case
'
openai
'
:
return
openaiModels
case
'
anthropic
'
:
case
'
claude
'
:
return
claudeModels
case
'
gemini
'
:
return
geminiModels
case
'
zhipu
'
:
return
zhipuModels
case
'
qwen
'
:
return
qwenModels
case
'
deepseek
'
:
return
deepseekModels
case
'
mistral
'
:
return
mistralModels
case
'
meta
'
:
return
metaModels
case
'
xai
'
:
return
xaiModels
case
'
cohere
'
:
return
cohereModels
case
'
yi
'
:
return
yiModels
case
'
moonshot
'
:
return
moonshotModels
case
'
doubao
'
:
return
doubaoModels
case
'
minimax
'
:
return
minimaxModels
case
'
baidu
'
:
return
baiduModels
case
'
spark
'
:
return
sparkModels
case
'
hunyuan
'
:
return
hunyuanModels
case
'
perplexity
'
:
return
perplexityModels
default
:
return
claudeModels
}
}
// 按平台获取预设映射
export
function
getPresetMappingsByPlatform
(
platform
:
string
)
{
if
(
platform
===
'
openai
'
)
return
openaiPresetMappings
if
(
platform
===
'
gemini
'
)
return
geminiPresetMappings
return
anthropicPresetMappings
}
// =====================
// 构建模型映射对象(用于 API)
// =====================
export
function
buildModelMappingObject
(
mode
:
'
whitelist
'
|
'
mapping
'
,
allowedModels
:
string
[],
modelMappings
:
{
from
:
string
;
to
:
string
}[]
):
Record
<
string
,
string
>
|
null
{
const
mapping
:
Record
<
string
,
string
>
=
{}
if
(
mode
===
'
whitelist
'
)
{
for
(
const
model
of
allowedModels
)
{
mapping
[
model
]
=
model
}
}
else
{
for
(
const
m
of
modelMappings
)
{
const
from
=
m
.
from
.
trim
()
const
to
=
m
.
to
.
trim
()
if
(
from
&&
to
)
mapping
[
from
]
=
to
}
}
return
Object
.
keys
(
mapping
).
length
>
0
?
mapping
:
null
}
frontend/src/i18n/locales/en.ts
View file @
2c71c8b9
...
...
@@ -945,6 +945,15 @@ export default {
actualModel
:
'
Actual model
'
,
addMapping
:
'
Add Mapping
'
,
mappingExists
:
'
Mapping for {model} already exists
'
,
searchModels
:
'
Search models...
'
,
noMatchingModels
:
'
No matching models
'
,
fillRelatedModels
:
'
Fill related models
'
,
clearAllModels
:
'
Clear all models
'
,
customModelName
:
'
Custom model name
'
,
enterCustomModelName
:
'
Enter custom model name
'
,
addModel
:
'
Add
'
,
modelExists
:
'
Model already exists
'
,
modelCount
:
'
{count} models
'
,
customErrorCodes
:
'
Custom Error Codes
'
,
customErrorCodesHint
:
'
Only stop scheduling for selected error codes
'
,
customErrorCodesWarning
:
...
...
frontend/src/i18n/locales/zh.ts
View file @
2c71c8b9
...
...
@@ -1102,6 +1102,15 @@ export default {
actualModel
:
'
实际模型
'
,
addMapping
:
'
添加映射
'
,
mappingExists
:
'
模型 {model} 的映射已存在
'
,
searchModels
:
'
搜索模型...
'
,
noMatchingModels
:
'
没有匹配的模型
'
,
fillRelatedModels
:
'
填入相关模型
'
,
clearAllModels
:
'
清除所有模型
'
,
customModelName
:
'
自定义模型名称
'
,
enterCustomModelName
:
'
输入自定义模型名称
'
,
addModel
:
'
填入
'
,
modelExists
:
'
该模型已存在
'
,
modelCount
:
'
{count} 个模型
'
,
customErrorCodes
:
'
自定义错误码
'
,
customErrorCodesHint
:
'
仅对选中的错误码停止调度
'
,
customErrorCodesWarning
:
'
仅选中的错误码会停止调度,其他错误将返回 500。
'
,
...
...
frontend/tsconfig.json
View file @
2c71c8b9
...
...
@@ -17,7 +17,8 @@
"noFallthroughCasesInSwitch"
:
true
,
"paths"
:
{
"@/*"
:
[
"./src/*"
]
}
},
"types"
:
[
"vite/client"
]
},
"include"
:
[
"src/**/*.ts"
,
"src/**/*.tsx"
,
"src/**/*.vue"
],
"references"
:
[{
"path"
:
"./tsconfig.node.json"
}]
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment