From 8f39754812c021d6d11b682ac2ef305562465b00 Mon Sep 17 00:00:00 2001 From: shaw Date: Wed, 4 Feb 2026 17:50:05 +0800 Subject: [PATCH] =?UTF-8?q?fix(gateway):=20=E4=BF=AE=E5=A4=8D=E6=A8=A1?= =?UTF-8?q?=E5=9E=8B=E5=89=8D=E7=BC=80=E6=98=A0=E5=B0=84=E9=80=BB=E8=BE=91?= =?UTF-8?q?=E9=94=99=E8=AF=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 问题:normalizeClaudeModelForAnthropic 函数错误地将长模型ID截断为短ID, 导致 APIKey 账号的模型名被错误修改。 修复: - 删除错误的 normalizeClaudeModelForAnthropic 函数和 anthropicPrefixMappings 变量 - 直接使用 claude.NormalizeModelID(正确的短ID->长ID扩展) - APIKey 账号无显式映射时透传原始模型名 --- backend/internal/service/gateway_service.go | 36 ++++++++------------- 1 file changed, 13 insertions(+), 23 deletions(-) diff --git a/backend/internal/service/gateway_service.go b/backend/internal/service/gateway_service.go index 79fda860..b2ac1efa 100644 --- a/backend/internal/service/gateway_service.go +++ b/backend/internal/service/gateway_service.go @@ -70,15 +70,6 @@ func shortSessionHash(sessionHash string) string { return sessionHash[:8] } -func normalizeClaudeModelForAnthropic(requestedModel string) string { - for _, prefix := range anthropicPrefixMappings { - if strings.HasPrefix(requestedModel, prefix) { - return prefix - } - } - return requestedModel -} - func redactAuthHeaderValue(v string) string { v = strings.TrimSpace(v) if v == "" { @@ -261,12 +252,6 @@ var ( "You are a file search specialist for Claude Code", // Explore Agent 版 "You are a helpful AI assistant tasked with summarizing conversations", // Compact 版 } - - anthropicPrefixMappings = []string{ - "claude-opus-4-5", - "claude-haiku-4-5", - "claude-sonnet-4-5", - } ) // ErrClaudeCodeOnly 表示分组仅允许 Claude Code 客户端访问 @@ -2576,8 +2561,9 @@ func (s *GatewayService) isModelSupportedByAccount(account *Account, requestedMo // Antigravity 平台使用专门的模型支持检查 return IsAntigravityModelSupported(requestedModel) } - if account.Platform == PlatformAnthropic { - requestedModel = normalizeClaudeModelForAnthropic(requestedModel) + // OAuth/SetupToken 账号使用 Anthropic 标准映射(短ID → 长ID) + if account.Platform == PlatformAnthropic && account.Type != AccountTypeAPIKey { + requestedModel = claude.NormalizeModelID(requestedModel) } // Gemini API Key 账户直接透传,由上游判断模型是否支持 if account.Platform == PlatformGemini && account.Type == AccountTypeAPIKey { @@ -3028,7 +3014,9 @@ func (s *GatewayService) Forward(ctx context.Context, c *gin.Context, account *A // 强制执行 cache_control 块数量限制(最多 4 个) body = enforceCacheControlLimit(body) - // 应用模型映射(APIKey 明确映射优先,其次使用 Anthropic 前缀映射) + // 应用模型映射: + // - APIKey 账号:使用账号级别的显式映射(如果配置),否则透传原始模型名 + // - OAuth/SetupToken 账号:使用 Anthropic 标准映射(短ID → 长ID) mappedModel := reqModel mappingSource := "" if account.Type == AccountTypeAPIKey { @@ -3037,8 +3025,8 @@ func (s *GatewayService) Forward(ctx context.Context, c *gin.Context, account *A mappingSource = "account" } } - if mappingSource == "" && account.Platform == PlatformAnthropic { - normalized := normalizeClaudeModelForAnthropic(reqModel) + if mappingSource == "" && account.Platform == PlatformAnthropic && account.Type != AccountTypeAPIKey { + normalized := claude.NormalizeModelID(reqModel) if normalized != reqModel { mappedModel = normalized mappingSource = "prefix" @@ -4979,7 +4967,9 @@ func (s *GatewayService) ForwardCountTokens(ctx context.Context, c *gin.Context, return nil } - // 应用模型映射(APIKey 明确映射优先,其次使用 Anthropic 前缀映射) + // 应用模型映射: + // - APIKey 账号:使用账号级别的显式映射(如果配置),否则透传原始模型名 + // - OAuth/SetupToken 账号:使用 Anthropic 标准映射(短ID → 长ID) if reqModel != "" { mappedModel := reqModel mappingSource := "" @@ -4989,8 +4979,8 @@ func (s *GatewayService) ForwardCountTokens(ctx context.Context, c *gin.Context, mappingSource = "account" } } - if mappingSource == "" && account.Platform == PlatformAnthropic { - normalized := normalizeClaudeModelForAnthropic(reqModel) + if mappingSource == "" && account.Platform == PlatformAnthropic && account.Type != AccountTypeAPIKey { + normalized := claude.NormalizeModelID(reqModel) if normalized != reqModel { mappedModel = normalized mappingSource = "prefix"