Fix stale official Astra input modalities

This commit is contained in:
DAlaoli
2026-09-06 00:50:01 +08:00
parent 578785ee7f
commit 8a46947865
2 changed files with 94 additions and 3 deletions
@@ -0,0 +1,72 @@
package service
import (
"context"
"testing"
"github.com/stretchr/testify/require"
)
func TestBuildCodexModelsManifestForGroupCorrectsOfficialAstraStaleModalities(t *testing.T) {
t.Parallel()
const groupID int64 = 780
account := Account{
ID: 1,
Platform: PlatformOpenAI,
Type: AccountTypeAPIKey,
Credentials: map[string]any{"api_key": "sk-test"},
}
account.SetUpstreamModelMetadataSnapshot(UpstreamModelMetadataSnapshot{
Models: map[string]UpstreamModelMetadata{
"gpt-6-astra": {ID: "gpt-6-astra", InputModalities: []string{"text"}},
},
})
svc := &GatewayService{accountRepo: codexModelsVisibilityAccountRepo{
byGroup: map[int64][]Account{groupID: {account}},
}}
body, err := svc.BuildCodexModelsManifestForGroup(
context.Background(),
&Group{ID: groupID, Platform: PlatformOpenAI},
"",
[]string{"gpt-6-astra"},
)
require.NoError(t, err)
models := decodeCodexManifestModels(t, body)
require.Len(t, models, 1)
require.Equal(t, []any{"text", "image"}, models[0]["input_modalities"])
}
func TestBuildCodexModelsManifestForGroupPreservesCompatibleAstraTextOnlyMetadata(t *testing.T) {
t.Parallel()
const groupID int64 = 781
account := Account{
ID: 2,
Platform: PlatformOpenAI,
Type: AccountTypeAPIKey,
Credentials: map[string]any{"api_key": "sk-test", "base_url": "https://relay.example.test/v1"},
}
account.SetUpstreamModelMetadataSnapshot(UpstreamModelMetadataSnapshot{
Models: map[string]UpstreamModelMetadata{
"gpt-6-astra": {ID: "gpt-6-astra", InputModalities: []string{"text"}},
},
})
svc := &GatewayService{accountRepo: codexModelsVisibilityAccountRepo{
byGroup: map[int64][]Account{groupID: {account}},
}}
body, err := svc.BuildCodexModelsManifestForGroup(
context.Background(),
&Group{ID: groupID, Platform: PlatformOpenAI},
"",
[]string{"gpt-6-astra"},
)
require.NoError(t, err)
models := decodeCodexManifestModels(t, body)
require.Len(t, models, 1)
require.Equal(t, []any{"text"}, models[0]["input_modalities"])
}
@@ -888,13 +888,15 @@ func buildCodexModelsManifest(
seen[modelID] = struct{}{}
descriptor := newConfiguredCodexModelDescriptor(metadataModelID)
descriptor.Slug = modelID
if imageInputModels[modelID] {
descriptor.InputModalities = []string{"text", "image"}
}
descriptor.SupportsSearchTool = searchToolModels[modelID]
if metadata, ok := modelMetadata[modelID]; ok {
applyUpstreamModelMetadataToCodexDescriptor(&descriptor, metadata)
}
if imageInputModels[modelID] {
// Apply the capability-derived modality after upstream metadata so
// a stale official Astra snapshot cannot downgrade the catalog.
descriptor.InputModalities = []string{"text", "image"}
}
if metadataModelID != modelID {
descriptor.DisplayName = modelID
descriptor.Description = configuredCodexCustomDescription
@@ -1186,6 +1188,13 @@ func accountCodexModelSupportsImageInput(account *Account, upstreamModel string)
case PlatformOpenAI:
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
// text-only modality list. Keep explicit provider metadata
// authoritative for compatible hosts, but repair that stale
// official snapshot at the capability boundary.
if isOpenAIGPT6AstraModel(upstreamModel) && isOfficialOpenAICodexAccount(account) {
return true
}
return stringSliceContains(modalities, "image")
}
}
@@ -1212,6 +1221,16 @@ func accountCodexModelSupportsImageInput(account *Account, upstreamModel string)
}
}
func isOfficialOpenAICodexAccount(account *Account) bool {
if account == nil || account.Platform != PlatformOpenAI {
return false
}
if account.IsOpenAIOAuth() {
return true
}
return account.IsOpenAIApiKey() && isOfficialOpenAIModelsBaseURL(account.GetOpenAIBaseURL())
}
func isGrokCodexImageInputModel(model string) bool {
switch strings.ToLower(strings.TrimSpace(model)) {
case "grok-4.3",