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
8365a832
Commit
8365a832
authored
Feb 25, 2026
by
erio
Browse files
merge: resolve conflicts with upstream/main (Gemini 3→3.1 mappings)
parents
58f21e4b
516f8f28
Changes
8
Show whitespace changes
Inline
Side-by-side
backend/internal/handler/admin/gemini_oauth_handler.go
View file @
8365a832
...
@@ -61,7 +61,11 @@ func (h *GeminiOAuthHandler) GenerateAuthURL(c *gin.Context) {
...
@@ -61,7 +61,11 @@ func (h *GeminiOAuthHandler) GenerateAuthURL(c *gin.Context) {
if
err
!=
nil
{
if
err
!=
nil
{
msg
:=
err
.
Error
()
msg
:=
err
.
Error
()
// Treat missing/invalid OAuth client configuration as a user/config error.
// Treat missing/invalid OAuth client configuration as a user/config error.
if
strings
.
Contains
(
msg
,
"OAuth client not configured"
)
||
strings
.
Contains
(
msg
,
"requires your own OAuth Client"
)
{
if
strings
.
Contains
(
msg
,
"OAuth client not configured"
)
||
strings
.
Contains
(
msg
,
"requires your own OAuth Client"
)
||
strings
.
Contains
(
msg
,
"requires a custom OAuth Client"
)
||
strings
.
Contains
(
msg
,
"GEMINI_CLI_OAUTH_CLIENT_SECRET_MISSING"
)
||
strings
.
Contains
(
msg
,
"built-in Gemini CLI OAuth client_secret is not configured"
)
{
response
.
BadRequest
(
c
,
"Failed to generate auth URL: "
+
msg
)
response
.
BadRequest
(
c
,
"Failed to generate auth URL: "
+
msg
)
return
return
}
}
...
...
backend/internal/pkg/geminicli/constants.go
View file @
8365a832
...
@@ -39,9 +39,7 @@ const (
...
@@ -39,9 +39,7 @@ const (
// They enable the "login without creating your own OAuth client" experience, but Google may
// They enable the "login without creating your own OAuth client" experience, but Google may
// restrict which scopes are allowed for this client.
// restrict which scopes are allowed for this client.
GeminiCLIOAuthClientID
=
"681255809395-oo8ft2oprdrnp9e3aqf6av3hmdib135j.apps.googleusercontent.com"
GeminiCLIOAuthClientID
=
"681255809395-oo8ft2oprdrnp9e3aqf6av3hmdib135j.apps.googleusercontent.com"
// GeminiCLIOAuthClientSecret is intentionally not embedded in this repository.
GeminiCLIOAuthClientSecret
=
"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"
// If you rely on the built-in Gemini CLI OAuth client, you MUST provide its client_secret via config/env.
GeminiCLIOAuthClientSecret
=
""
// GeminiCLIOAuthClientSecretEnv is the environment variable name for the built-in client secret.
// GeminiCLIOAuthClientSecretEnv is the environment variable name for the built-in client secret.
GeminiCLIOAuthClientSecretEnv
=
"GEMINI_CLI_OAUTH_CLIENT_SECRET"
GeminiCLIOAuthClientSecretEnv
=
"GEMINI_CLI_OAUTH_CLIENT_SECRET"
...
...
backend/internal/pkg/geminicli/oauth_test.go
View file @
8365a832
...
@@ -408,11 +408,10 @@ func TestBuildAuthorizationURL_WithProjectID(t *testing.T) {
...
@@ -408,11 +408,10 @@ func TestBuildAuthorizationURL_WithProjectID(t *testing.T) {
}
}
}
}
func
TestBuildAuthorizationURL_OAuthConfigError
(
t
*
testing
.
T
)
{
func
TestBuildAuthorizationURL_UsesBuiltinSecretFallback
(
t
*
testing
.
T
)
{
// 不设置环境变量,也不提供 client 凭据,EffectiveOAuthConfig 应该报错
t
.
Setenv
(
GeminiCLIOAuthClientSecretEnv
,
""
)
t
.
Setenv
(
GeminiCLIOAuthClientSecretEnv
,
""
)
_
,
err
:=
BuildAuthorizationURL
(
authURL
,
err
:=
BuildAuthorizationURL
(
OAuthConfig
{},
OAuthConfig
{},
"test-state"
,
"test-state"
,
"test-challenge"
,
"test-challenge"
,
...
@@ -420,8 +419,11 @@ func TestBuildAuthorizationURL_OAuthConfigError(t *testing.T) {
...
@@ -420,8 +419,11 @@ func TestBuildAuthorizationURL_OAuthConfigError(t *testing.T) {
""
,
""
,
"code_assist"
,
"code_assist"
,
)
)
if
err
==
nil
{
if
err
!=
nil
{
t
.
Error
(
"当 EffectiveOAuthConfig 失败时,BuildAuthorizationURL 应该返回错误"
)
t
.
Fatalf
(
"BuildAuthorizationURL() 不应报错: %v"
,
err
)
}
if
!
strings
.
Contains
(
authURL
,
"client_id="
+
GeminiCLIOAuthClientID
)
{
t
.
Errorf
(
"应使用内置 Gemini CLI client_id,实际 URL: %s"
,
authURL
)
}
}
}
}
...
@@ -685,15 +687,17 @@ func TestEffectiveOAuthConfig_WhitespaceTriming(t *testing.T) {
...
@@ -685,15 +687,17 @@ func TestEffectiveOAuthConfig_WhitespaceTriming(t *testing.T) {
}
}
func
TestEffectiveOAuthConfig_NoEnvSecret
(
t
*
testing
.
T
)
{
func
TestEffectiveOAuthConfig_NoEnvSecret
(
t
*
testing
.
T
)
{
// 不设置环境变量且不提供凭据,应该报错
t
.
Setenv
(
GeminiCLIOAuthClientSecretEnv
,
""
)
t
.
Setenv
(
GeminiCLIOAuthClientSecretEnv
,
""
)
_
,
err
:=
EffectiveOAuthConfig
(
OAuthConfig
{},
"code_assist"
)
cfg
,
err
:=
EffectiveOAuthConfig
(
OAuthConfig
{},
"code_assist"
)
if
err
==
nil
{
if
err
!=
nil
{
t
.
Error
(
"没有内置 secret 且未提供凭据时应该报错"
)
t
.
Fatalf
(
"不设置环境变量时应回退到内置 secret,实际报错: %v"
,
err
)
}
if
strings
.
TrimSpace
(
cfg
.
ClientSecret
)
==
""
{
t
.
Error
(
"ClientSecret 不应为空"
)
}
}
if
!
strings
.
Contains
(
err
.
Error
(),
GeminiCLIOAuthClient
SecretEnv
)
{
if
cfg
.
ClientID
!=
GeminiCLIOAuthClient
ID
{
t
.
Errorf
(
"
错误消息应提及环境变量 %s
,实际: %
v
"
,
GeminiCLIOAuthClientSecretEnv
,
err
)
t
.
Errorf
(
"
ClientID 应回退为内置客户端 ID
,实际: %
q
"
,
cfg
.
ClientID
)
}
}
}
}
...
...
backend/internal/service/account.go
View file @
8365a832
...
@@ -372,6 +372,9 @@ func (a *Account) GetModelMapping() map[string]string {
...
@@ -372,6 +372,9 @@ func (a *Account) GetModelMapping() map[string]string {
}
}
}
}
if
len
(
result
)
>
0
{
if
len
(
result
)
>
0
{
if
a
.
Platform
==
domain
.
PlatformAntigravity
{
ensureAntigravityDefaultPassthrough
(
result
,
"gemini-3-flash"
)
}
return
result
return
result
}
}
}
}
...
@@ -382,6 +385,21 @@ func (a *Account) GetModelMapping() map[string]string {
...
@@ -382,6 +385,21 @@ func (a *Account) GetModelMapping() map[string]string {
return
nil
return
nil
}
}
func
ensureAntigravityDefaultPassthrough
(
mapping
map
[
string
]
string
,
model
string
)
{
if
mapping
==
nil
||
model
==
""
{
return
}
if
_
,
exists
:=
mapping
[
model
];
exists
{
return
}
for
pattern
:=
range
mapping
{
if
matchWildcard
(
pattern
,
model
)
{
return
}
}
mapping
[
model
]
=
model
}
// IsModelSupported 检查模型是否在 model_mapping 中(支持通配符)
// IsModelSupported 检查模型是否在 model_mapping 中(支持通配符)
// 如果未配置 mapping,返回 true(允许所有模型)
// 如果未配置 mapping,返回 true(允许所有模型)
func
(
a
*
Account
)
IsModelSupported
(
requestedModel
string
)
bool
{
func
(
a
*
Account
)
IsModelSupported
(
requestedModel
string
)
bool
{
...
...
backend/internal/service/account_usage_service.go
View file @
8365a832
...
@@ -4,6 +4,7 @@ import (
...
@@ -4,6 +4,7 @@ import (
"context"
"context"
"fmt"
"fmt"
"log"
"log"
"strings"
"sync"
"sync"
"time"
"time"
...
@@ -217,12 +218,20 @@ func (s *AccountUsageService) GetUsage(ctx context.Context, accountID int64) (*U
...
@@ -217,12 +218,20 @@ func (s *AccountUsageService) GetUsage(ctx context.Context, accountID int64) (*U
}
}
if
account
.
Platform
==
PlatformGemini
{
if
account
.
Platform
==
PlatformGemini
{
return
s
.
getGeminiUsage
(
ctx
,
account
)
usage
,
err
:=
s
.
getGeminiUsage
(
ctx
,
account
)
if
err
==
nil
{
s
.
tryClearRecoverableAccountError
(
ctx
,
account
)
}
return
usage
,
err
}
}
// Antigravity 平台:使用 AntigravityQuotaFetcher 获取额度
// Antigravity 平台:使用 AntigravityQuotaFetcher 获取额度
if
account
.
Platform
==
PlatformAntigravity
{
if
account
.
Platform
==
PlatformAntigravity
{
return
s
.
getAntigravityUsage
(
ctx
,
account
)
usage
,
err
:=
s
.
getAntigravityUsage
(
ctx
,
account
)
if
err
==
nil
{
s
.
tryClearRecoverableAccountError
(
ctx
,
account
)
}
return
usage
,
err
}
}
// 只有oauth类型账号可以通过API获取usage(有profile scope)
// 只有oauth类型账号可以通过API获取usage(有profile scope)
...
@@ -256,6 +265,7 @@ func (s *AccountUsageService) GetUsage(ctx context.Context, accountID int64) (*U
...
@@ -256,6 +265,7 @@ func (s *AccountUsageService) GetUsage(ctx context.Context, accountID int64) (*U
// 4. 添加窗口统计(有独立缓存,1 分钟)
// 4. 添加窗口统计(有独立缓存,1 分钟)
s
.
addWindowStats
(
ctx
,
account
,
usage
)
s
.
addWindowStats
(
ctx
,
account
,
usage
)
s
.
tryClearRecoverableAccountError
(
ctx
,
account
)
return
usage
,
nil
return
usage
,
nil
}
}
...
@@ -486,6 +496,32 @@ func parseTime(s string) (time.Time, error) {
...
@@ -486,6 +496,32 @@ func parseTime(s string) (time.Time, error) {
return
time
.
Time
{},
fmt
.
Errorf
(
"unable to parse time: %s"
,
s
)
return
time
.
Time
{},
fmt
.
Errorf
(
"unable to parse time: %s"
,
s
)
}
}
func
(
s
*
AccountUsageService
)
tryClearRecoverableAccountError
(
ctx
context
.
Context
,
account
*
Account
)
{
if
account
==
nil
||
account
.
Status
!=
StatusError
{
return
}
msg
:=
strings
.
ToLower
(
strings
.
TrimSpace
(
account
.
ErrorMessage
))
if
msg
==
""
{
return
}
if
!
strings
.
Contains
(
msg
,
"token refresh failed"
)
&&
!
strings
.
Contains
(
msg
,
"invalid_client"
)
&&
!
strings
.
Contains
(
msg
,
"missing_project_id"
)
&&
!
strings
.
Contains
(
msg
,
"unauthenticated"
)
{
return
}
if
err
:=
s
.
accountRepo
.
ClearError
(
ctx
,
account
.
ID
);
err
!=
nil
{
log
.
Printf
(
"[usage] failed to clear recoverable account error for account %d: %v"
,
account
.
ID
,
err
)
return
}
account
.
Status
=
StatusActive
account
.
ErrorMessage
=
""
}
// buildUsageInfo 构建UsageInfo
// buildUsageInfo 构建UsageInfo
func
(
s
*
AccountUsageService
)
buildUsageInfo
(
resp
*
ClaudeUsageResponse
,
updatedAt
*
time
.
Time
)
*
UsageInfo
{
func
(
s
*
AccountUsageService
)
buildUsageInfo
(
resp
*
ClaudeUsageResponse
,
updatedAt
*
time
.
Time
)
*
UsageInfo
{
info
:=
&
UsageInfo
{
info
:=
&
UsageInfo
{
...
...
backend/internal/service/account_wildcard_test.go
View file @
8365a832
...
@@ -267,3 +267,38 @@ func TestAccountGetMappedModel(t *testing.T) {
...
@@ -267,3 +267,38 @@ func TestAccountGetMappedModel(t *testing.T) {
})
})
}
}
}
}
func
TestAccountGetModelMapping_AntigravityEnsuresGemini3FlashPassthrough
(
t
*
testing
.
T
)
{
account
:=
&
Account
{
Platform
:
PlatformAntigravity
,
Credentials
:
map
[
string
]
any
{
"model_mapping"
:
map
[
string
]
any
{
"gemini-3-pro-high"
:
"gemini-3.1-pro-high"
,
},
},
}
mapping
:=
account
.
GetModelMapping
()
if
mapping
[
"gemini-3-flash"
]
!=
"gemini-3-flash"
{
t
.
Fatalf
(
"expected gemini-3-flash passthrough to be auto-filled, got: %q"
,
mapping
[
"gemini-3-flash"
])
}
}
func
TestAccountGetModelMapping_AntigravityRespectsWildcardOverride
(
t
*
testing
.
T
)
{
account
:=
&
Account
{
Platform
:
PlatformAntigravity
,
Credentials
:
map
[
string
]
any
{
"model_mapping"
:
map
[
string
]
any
{
"gemini-3*"
:
"gemini-3.1-pro-high"
,
},
},
}
mapping
:=
account
.
GetModelMapping
()
if
_
,
exists
:=
mapping
[
"gemini-3-flash"
];
exists
{
t
.
Fatalf
(
"did not expect explicit gemini-3-flash passthrough when wildcard already exists"
)
}
if
mapped
:=
account
.
GetMappedModel
(
"gemini-3-flash"
);
mapped
!=
"gemini-3.1-pro-high"
{
t
.
Fatalf
(
"expected wildcard mapping to stay effective, got: %q"
,
mapped
)
}
}
frontend/src/components/account/BulkEditAccountModal.vue
View file @
8365a832
...
@@ -768,6 +768,31 @@ const presetMappings = [
...
@@ -768,6 +768,31 @@ const presetMappings = [
color
:
color
:
'
bg-purple-100 text-purple-700 hover:bg-purple-200 dark:bg-purple-900/30 dark:text-purple-400
'
'
bg-purple-100 text-purple-700 hover:bg-purple-200 dark:bg-purple-900/30 dark:text-purple-400
'
}
,
}
,
{
label
:
'
Sonnet4→4.6
'
,
from
:
'
claude-sonnet-4-20250514
'
,
to
:
'
claude-sonnet-4-6
'
,
color
:
'
bg-sky-100 text-sky-700 hover:bg-sky-200 dark:bg-sky-900/30 dark:text-sky-400
'
}
,
{
label
:
'
Sonnet4.5→4.6
'
,
from
:
'
claude-sonnet-4-5-20250929
'
,
to
:
'
claude-sonnet-4-6
'
,
color
:
'
bg-cyan-100 text-cyan-700 hover:bg-cyan-200 dark:bg-cyan-900/30 dark:text-cyan-400
'
}
,
{
label
:
'
Sonnet3.5→4.6
'
,
from
:
'
claude-3-5-sonnet-20241022
'
,
to
:
'
claude-sonnet-4-6
'
,
color
:
'
bg-teal-100 text-teal-700 hover:bg-teal-200 dark:bg-teal-900/30 dark:text-teal-400
'
}
,
{
label
:
'
Opus4.5→4.6
'
,
from
:
'
claude-opus-4-5-20251101
'
,
to
:
'
claude-opus-4-6-thinking
'
,
color
:
'
bg-violet-100 text-violet-700 hover:bg-violet-200 dark:bg-violet-900/30 dark:text-violet-400
'
}
,
{
{
label
:
'
Opus->Sonnet
'
,
label
:
'
Opus->Sonnet
'
,
from
:
'
claude-opus-4-5-20251101
'
,
from
:
'
claude-opus-4-5-20251101
'
,
...
@@ -793,22 +818,34 @@ const presetMappings = [
...
@@ -793,22 +818,34 @@ const presetMappings = [
color
:
'
bg-pink-100 text-pink-700 hover:bg-pink-200 dark:bg-pink-900/30 dark:text-pink-400
'
color
:
'
bg-pink-100 text-pink-700 hover:bg-pink-200 dark:bg-pink-900/30 dark:text-pink-400
'
}
,
}
,
{
{
label
:
'
Gemini Flash 2.0
'
,
label
:
'
3-Pro-Preview→3.1-Pro-High
'
,
from
:
'
gemini-
2.0-flash
'
,
from
:
'
gemini-
3-pro-preview
'
,
to
:
'
gemini-
2.0-flas
h
'
,
to
:
'
gemini-
3.1-pro-hig
h
'
,
color
:
'
bg-
cyan
-100 text-
cyan
-700 hover:bg-
cyan
-200 dark:bg-
cyan
-900/30 dark:text-
cyan
-400
'
color
:
'
bg-
amber
-100 text-
amber
-700 hover:bg-
amber
-200 dark:bg-
amber
-900/30 dark:text-
amber
-400
'
}
,
}
,
{
{
label
:
'
Gemini 2.5 Flas
h
'
,
label
:
'
3-Pro-High→3.1-Pro-Hig
h
'
,
from
:
'
gemini-
2.5-flas
h
'
,
from
:
'
gemini-
3-pro-hig
h
'
,
to
:
'
gemini-
2.5-flas
h
'
,
to
:
'
gemini-
3.1-pro-hig
h
'
,
color
:
'
bg-
teal
-100 text-
teal
-700 hover:bg-
teal
-200 dark:bg-
teal
-900/30 dark:text-
teal
-400
'
color
:
'
bg-
orange
-100 text-
orange
-700 hover:bg-
orange
-200 dark:bg-
orange
-900/30 dark:text-
orange
-400
'
}
,
}
,
{
{
label
:
'
Gemini 2.5 Pro
'
,
label
:
'
3-Pro-Low→3.1-Pro-Low
'
,
from
:
'
gemini-2.5-pro
'
,
from
:
'
gemini-3-pro-low
'
,
to
:
'
gemini-2.5-pro
'
,
to
:
'
gemini-3.1-pro-low
'
,
color
:
'
bg-sky-100 text-sky-700 hover:bg-sky-200 dark:bg-sky-900/30 dark:text-sky-400
'
color
:
'
bg-yellow-100 text-yellow-700 hover:bg-yellow-200 dark:bg-yellow-900/30 dark:text-yellow-400
'
}
,
{
label
:
'
3-Flash透传
'
,
from
:
'
gemini-3-flash
'
,
to
:
'
gemini-3-flash
'
,
color
:
'
bg-lime-100 text-lime-700 hover:bg-lime-200 dark:bg-lime-900/30 dark:text-lime-400
'
}
,
{
label
:
'
2.5-Flash-Lite透传
'
,
from
:
'
gemini-2.5-flash-lite
'
,
to
:
'
gemini-2.5-flash-lite
'
,
color
:
'
bg-green-100 text-green-700 hover:bg-green-200 dark:bg-green-900/30 dark:text-green-400
'
}
}
]
]
...
...
frontend/src/composables/useModelWhitelist.ts
View file @
8365a832
...
@@ -291,13 +291,19 @@ const antigravityPresetMappings = [
...
@@ -291,13 +291,19 @@ const antigravityPresetMappings = [
{
label
:
'
Sonnet→Sonnet
'
,
from
:
'
claude-sonnet-*
'
,
to
:
'
claude-sonnet-4-5
'
,
color
:
'
bg-indigo-100 text-indigo-700 hover:bg-indigo-200 dark:bg-indigo-900/30 dark:text-indigo-400
'
},
{
label
:
'
Sonnet→Sonnet
'
,
from
:
'
claude-sonnet-*
'
,
to
:
'
claude-sonnet-4-5
'
,
color
:
'
bg-indigo-100 text-indigo-700 hover:bg-indigo-200 dark:bg-indigo-900/30 dark:text-indigo-400
'
},
{
label
:
'
Opus→Opus
'
,
from
:
'
claude-opus-*
'
,
to
:
'
claude-opus-4-6-thinking
'
,
color
:
'
bg-purple-100 text-purple-700 hover:bg-purple-200 dark:bg-purple-900/30 dark:text-purple-400
'
},
{
label
:
'
Opus→Opus
'
,
from
:
'
claude-opus-*
'
,
to
:
'
claude-opus-4-6-thinking
'
,
color
:
'
bg-purple-100 text-purple-700 hover:bg-purple-200 dark:bg-purple-900/30 dark:text-purple-400
'
},
{
label
:
'
Haiku→Sonnet
'
,
from
:
'
claude-haiku-*
'
,
to
:
'
claude-sonnet-4-5
'
,
color
:
'
bg-emerald-100 text-emerald-700 hover:bg-emerald-200 dark:bg-emerald-900/30 dark:text-emerald-400
'
},
{
label
:
'
Haiku→Sonnet
'
,
from
:
'
claude-haiku-*
'
,
to
:
'
claude-sonnet-4-5
'
,
color
:
'
bg-emerald-100 text-emerald-700 hover:bg-emerald-200 dark:bg-emerald-900/30 dark:text-emerald-400
'
},
// Gemini 3 映射
{
label
:
'
Sonnet4→4.6
'
,
from
:
'
claude-sonnet-4-20250514
'
,
to
:
'
claude-sonnet-4-6
'
,
color
:
'
bg-sky-100 text-sky-700 hover:bg-sky-200 dark:bg-sky-900/30 dark:text-sky-400
'
},
{
label
:
'
3-Pro-Preview→3-Pro-High
'
,
from
:
'
gemini-3-pro-preview
'
,
to
:
'
gemini-3-pro-high
'
,
color
:
'
bg-amber-100 text-amber-700 hover:bg-amber-200 dark:bg-amber-900/30 dark:text-amber-400
'
},
{
label
:
'
Sonnet4.5→4.6
'
,
from
:
'
claude-sonnet-4-5-20250929
'
,
to
:
'
claude-sonnet-4-6
'
,
color
:
'
bg-cyan-100 text-cyan-700 hover:bg-cyan-200 dark:bg-cyan-900/30 dark:text-cyan-400
'
},
{
label
:
'
3-Pro-High
'
,
from
:
'
gemini-3-pro-high
'
,
to
:
'
gemini-3-pro-high
'
,
color
:
'
bg-orange-100 text-orange-700 hover:bg-orange-200 dark:bg-orange-900/30 dark:text-orange-400
'
},
{
label
:
'
Sonnet3.5→4.6
'
,
from
:
'
claude-3-5-sonnet-20241022
'
,
to
:
'
claude-sonnet-4-6
'
,
color
:
'
bg-teal-100 text-teal-700 hover:bg-teal-200 dark:bg-teal-900/30 dark:text-teal-400
'
},
{
label
:
'
3-Pro-Low
'
,
from
:
'
gemini-3-pro-low
'
,
to
:
'
gemini-3-pro-low
'
,
color
:
'
bg-yellow-100 text-yellow-700 hover:bg-yellow-200 dark:bg-yellow-900/30 dark:text-yellow-400
'
},
{
label
:
'
Opus4.5→4.6
'
,
from
:
'
claude-opus-4-5-20251101
'
,
to
:
'
claude-opus-4-6-thinking
'
,
color
:
'
bg-violet-100 text-violet-700 hover:bg-violet-200 dark:bg-violet-900/30 dark:text-violet-400
'
},
// Gemini 3→3.1 映射
{
label
:
'
3-Pro-Preview→3.1-Pro-High
'
,
from
:
'
gemini-3-pro-preview
'
,
to
:
'
gemini-3.1-pro-high
'
,
color
:
'
bg-amber-100 text-amber-700 hover:bg-amber-200 dark:bg-amber-900/30 dark:text-amber-400
'
},
{
label
:
'
3-Pro-High→3.1-Pro-High
'
,
from
:
'
gemini-3-pro-high
'
,
to
:
'
gemini-3.1-pro-high
'
,
color
:
'
bg-orange-100 text-orange-700 hover:bg-orange-200 dark:bg-orange-900/30 dark:text-orange-400
'
},
{
label
:
'
3-Pro-Low→3.1-Pro-Low
'
,
from
:
'
gemini-3-pro-low
'
,
to
:
'
gemini-3.1-pro-low
'
,
color
:
'
bg-yellow-100 text-yellow-700 hover:bg-yellow-200 dark:bg-yellow-900/30 dark:text-yellow-400
'
},
// Gemini 通配符映射
// Gemini 通配符映射
{
label
:
'
Gemini 3→Flash
'
,
from
:
'
gemini-3*
'
,
to
:
'
gemini-3-flash
'
,
color
:
'
bg-yellow-100 text-yellow-700 hover:bg-yellow-200 dark:bg-yellow-900/30 dark:text-yellow-400
'
},
{
label
:
'
Gemini 3→Flash
'
,
from
:
'
gemini-3*
'
,
to
:
'
gemini-3-flash
'
,
color
:
'
bg-yellow-100 text-yellow-700 hover:bg-yellow-200 dark:bg-yellow-900/30 dark:text-yellow-400
'
},
{
label
:
'
Gemini 2.5→Flash
'
,
from
:
'
gemini-2.5*
'
,
to
:
'
gemini-2.5-flash
'
,
color
:
'
bg-orange-100 text-orange-700 hover:bg-orange-200 dark:bg-orange-900/30 dark:text-orange-400
'
},
{
label
:
'
Gemini 2.5→Flash
'
,
from
:
'
gemini-2.5*
'
,
to
:
'
gemini-2.5-flash
'
,
color
:
'
bg-orange-100 text-orange-700 hover:bg-orange-200 dark:bg-orange-900/30 dark:text-orange-400
'
},
{
label
:
'
3-Flash透传
'
,
from
:
'
gemini-3-flash
'
,
to
:
'
gemini-3-flash
'
,
color
:
'
bg-lime-100 text-lime-700 hover:bg-lime-200 dark:bg-lime-900/30 dark:text-lime-400
'
},
{
label
:
'
2.5-Flash-Lite透传
'
,
from
:
'
gemini-2.5-flash-lite
'
,
to
:
'
gemini-2.5-flash-lite
'
,
color
:
'
bg-green-100 text-green-700 hover:bg-green-200 dark:bg-green-900/30 dark:text-green-400
'
},
// 精确映射
// 精确映射
{
label
:
'
Sonnet 4.6
'
,
from
:
'
claude-sonnet-4-6
'
,
to
:
'
claude-sonnet-4-6
'
,
color
:
'
bg-cyan-100 text-cyan-700 hover:bg-cyan-200 dark:bg-cyan-900/30 dark:text-cyan-400
'
},
{
label
:
'
Sonnet 4.6
'
,
from
:
'
claude-sonnet-4-6
'
,
to
:
'
claude-sonnet-4-6
'
,
color
:
'
bg-cyan-100 text-cyan-700 hover:bg-cyan-200 dark:bg-cyan-900/30 dark:text-cyan-400
'
},
{
label
:
'
Sonnet 4.5
'
,
from
:
'
claude-sonnet-4-5
'
,
to
:
'
claude-sonnet-4-5
'
,
color
:
'
bg-cyan-100 text-cyan-700 hover:bg-cyan-200 dark:bg-cyan-900/30 dark:text-cyan-400
'
},
{
label
:
'
Sonnet 4.5
'
,
from
:
'
claude-sonnet-4-5
'
,
to
:
'
claude-sonnet-4-5
'
,
color
:
'
bg-cyan-100 text-cyan-700 hover:bg-cyan-200 dark:bg-cyan-900/30 dark:text-cyan-400
'
},
...
...
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