Merge pull request #6968 from ouchihao/codex/issue-6903-deepseek-vision-modality

fix(codex): advertise DeepSeek vision image input
This commit is contained in:
Wesley Liddick
2026-09-11 14:01:36 +08:00
committed by GitHub
2 changed files with 81 additions and 3 deletions
@@ -1074,7 +1074,7 @@ func groupCodexModelSupportsImageInput(
return false
}
}
if platform != PlatformOpenAI && platform != PlatformGrok {
if platform != PlatformOpenAI && platform != PlatformGrok && platform != PlatformDeepseek {
return false
}
@@ -1213,7 +1213,7 @@ func accountCodexModelSupportsImageInput(account *Account, upstreamModel string)
return false
}
switch account.Platform {
case PlatformOpenAI:
case PlatformOpenAI, PlatformDeepseek:
if metadata, ok := account.GetUpstreamModelMetadata(upstreamModel); ok {
if modalities := normalizeCodexInputModalities(metadata.InputModalities); len(modalities) > 0 {
// Official GPT-6 Astra metadata briefly shipped with a stale
@@ -1226,7 +1226,10 @@ func accountCodexModelSupportsImageInput(account *Account, upstreamModel string)
return stringSliceContains(modalities, "image")
}
}
if !isOpenAICodexImageInputModel(upstreamModel) {
if strings.EqualFold(strings.TrimSpace(upstreamModel), "deepseek-v4-flash-vision-exp") {
return account.Type == AccountTypeAPIKey
}
if account.Platform != PlatformOpenAI || !isOpenAICodexImageInputModel(upstreamModel) {
return false
}
if account.IsOpenAIOAuth() {
@@ -785,6 +785,81 @@ func TestBuildCodexModelsManifestForGroupUsesProviderImageCapabilities(t *testin
}
}
func TestBuildCodexModelsManifestForGroupUsesDeepSeekVisionCapabilities(t *testing.T) {
t.Parallel()
const visionModel = "deepseek-v4-flash-vision-exp"
newAccount := func(id int64, platform, model string, modalities []string) Account {
account := Account{
ID: id, Platform: platform, Type: AccountTypeAPIKey,
Credentials: map[string]any{"model_mapping": map[string]any{"vision-alias": model}},
}
if modalities != nil {
account.SetUpstreamModelMetadataSnapshot(UpstreamModelMetadataSnapshot{Models: map[string]UpstreamModelMetadata{
model: {ID: model, InputModalities: modalities},
}})
}
return account
}
tests := []struct {
name string
platform string
accounts []Account
modalities []any
}{
{
name: "native DeepSeek", platform: PlatformDeepseek,
accounts: []Account{newAccount(1, PlatformDeepseek, visionModel, nil)},
modalities: []any{"text", "image"},
},
{
name: "OpenAI-compatible DeepSeek", platform: PlatformOpenAI,
accounts: []Account{newAccount(1, PlatformOpenAI, visionModel, nil)},
modalities: []any{"text", "image"},
},
{
name: "Composite DeepSeek alias", platform: PlatformComposite,
accounts: []Account{newAccount(1, PlatformDeepseek, visionModel, nil)},
modalities: []any{"text", "image"},
},
{
name: "text-only DeepSeek Flash", platform: PlatformDeepseek,
accounts: []Account{newAccount(1, PlatformDeepseek, "deepseek-v4-flash", nil)},
modalities: []any{"text"},
},
{
name: "explicit text-only metadata", platform: PlatformDeepseek,
accounts: []Account{newAccount(1, PlatformDeepseek, visionModel, []string{"text"})},
modalities: []any{"text"},
},
{
name: "mixed vision and text-only alias", platform: PlatformDeepseek,
accounts: []Account{
newAccount(1, PlatformDeepseek, visionModel, nil),
newAccount(2, PlatformDeepseek, "deepseek-v4-flash", nil),
},
modalities: []any{"text"},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
t.Parallel()
const groupID int64 = 790
svc := &GatewayService{accountRepo: codexModelsVisibilityAccountRepo{byGroup: map[int64][]Account{
groupID: tt.accounts,
}}}
body, err := svc.BuildCodexModelsManifestForGroup(context.Background(),
&Group{ID: groupID, Platform: tt.platform}, "", []string{"vision-alias"})
require.NoError(t, err)
models := decodeCodexManifestModels(t, body)
require.Len(t, models, 1)
require.Equal(t, tt.modalities, models[0]["input_modalities"])
})
}
}
func TestBuildCodexModelsManifestForGroupPrefersSyncedOpenAIImageCapabilities(t *testing.T) {
t.Parallel()