From 83b368553de186906d1dd356bc4266f9b0d0d4b8 Mon Sep 17 00:00:00 2001 From: HuntercodeT <61233559+HuntercodeT@users.noreply.github.com> Date: Mon, 27 Jul 2026 14:20:12 +0800 Subject: [PATCH] fix(openai): honor passthrough over model_mapping in IsModelSupported (#4936) An OpenAI account with auto-passthrough enabled (extra.openai_passthrough=true, "replace auth only, allow all models") was still filtered out during account selection when it had a non-empty credentials.model_mapping that did not list the requested model. isOpenAICompatibleAccountEligibleForRequest calls Account.IsModelSupported directly, and IsModelSupported only bypassed the mapping whitelist for passthrough accounts when the mapping was empty. A leftover mapping (common after switching an account from whitelist mode to passthrough) therefore excluded the account -> zero candidates -> ErrNoAvailableAccounts, and the client saw 404 "Model ... is not supported by any configured account in this group" even though a direct account test with the same model succeeded (that path already honored passthrough via isModelSupportedByAccount). Fix: short-circuit passthrough at the top of Account.IsModelSupported, before the model_mapping check, so it is consistent with isModelSupportedByAccount. Add a regression test covering passthrough + non-empty leftover mapping. --- backend/internal/service/account.go | 9 ++++++++- .../service/openai_oauth_model_support_test.go | 14 ++++++++++++++ 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/backend/internal/service/account.go b/backend/internal/service/account.go index b7f6d2266a..e3a461367a 100644 --- a/backend/internal/service/account.go +++ b/backend/internal/service/account.go @@ -779,9 +779,16 @@ func resolveRequestedModelInMapping(mapping map[string]string, requestedModel st // 请求卡死在该账号上、无法 failover 到真正支持该模型的 API Key 账号(#3662)。 // 未知/自定义别名仍保持允许(兼容渠道级映射),见 isOpenAIOAuthServableModel。 func (a *Account) IsModelSupported(requestedModel string) bool { + // 透传模式仅替换认证、模型语义完全交由上游决定,因此放行所有模型。 + // 该短路必须在 model_mapping 判定之前:账号从"白名单模式"切换到透传后, + // credentials 里常残留旧的非空 model_mapping,若不在此放行,透传账号会被 + // model_mapping 白名单错误排除出候选集,导致 no available accounts / 404(issue #4936)。 + if a.IsOpenAIPassthroughEnabled() { + return true + } mapping := a.GetModelMapping() if len(mapping) == 0 { - if a.IsOpenAIOAuth() && !a.IsOpenAIPassthroughEnabled() { + if a.IsOpenAIOAuth() { return isOpenAIOAuthServableModel(requestedModel) } return true // 无映射 = 允许所有 diff --git a/backend/internal/service/openai_oauth_model_support_test.go b/backend/internal/service/openai_oauth_model_support_test.go index 1350dcd3bf..4367c3de7d 100644 --- a/backend/internal/service/openai_oauth_model_support_test.go +++ b/backend/internal/service/openai_oauth_model_support_test.go @@ -81,6 +81,20 @@ func TestIsModelSupported_OpenAIOAuthPassthroughAllowsAll(t *testing.T) { require.True(t, account.IsModelSupported("deepseek-v4")) } +func TestIsModelSupported_OpenAIOAuthPassthroughIgnoresLeftoverMapping(t *testing.T) { + account := newOpenAIOAuthAccountForModelTest() + account.Extra = map[string]any{"openai_passthrough": true} + // 账号从"白名单模式"切到透传后,credentials 里常残留旧的非空 model_mapping。 + // 透传应无视该白名单,放行不在其中的模型(issue #4936);否则透传账号会被 + // 调度期的 IsModelSupported 排除,客户端收到 404 "not supported by any account"。 + account.Credentials = map[string]any{ + "model_mapping": map[string]any{"gpt-5.4": "gpt-5.4"}, + } + + require.True(t, account.IsModelSupported("gpt-5.6-sol"), "透传应放行不在残留白名单中的新模型") + require.True(t, account.IsModelSupported("deepseek-v4"), "透传应放行任意模型") +} + func TestIsModelSupported_OpenAIAPIKeyEmptyMappingAllowsAll(t *testing.T) { account := &Account{ ID: 2,