From 2db78bd3d68f58968d73b664c289c79ebee71aee Mon Sep 17 00:00:00 2001 From: lyy0709 <65712338+lyy0709@users.noreply.github.com> Date: Mon, 7 Sep 2026 01:12:55 +0800 Subject: [PATCH 1/2] fix(codex): preserve Astra Ultra workflow metadata --- .../service/openai_codex_model_metadata.go | 5 +- .../openai_codex_model_metadata_test.go | 52 +++++++++++++++++++ .../service/openai_codex_models_service.go | 8 ++- .../openai_codex_models_service_test.go | 9 ++-- 4 files changed, 69 insertions(+), 5 deletions(-) diff --git a/backend/internal/service/openai_codex_model_metadata.go b/backend/internal/service/openai_codex_model_metadata.go index 656919fd8c..393621a181 100644 --- a/backend/internal/service/openai_codex_model_metadata.go +++ b/backend/internal/service/openai_codex_model_metadata.go @@ -9,6 +9,7 @@ import ( var codexToolCapabilityFields = []string{ "supports_search_tool", "apply_patch_tool_type", "comp_hash", "tool_mode", "use_responses_lite", + "multi_agent_reasoning_effort", "multi_agent_version", } func applyCodexToolCapabilities(dst, src map[string]json.RawMessage, overwrite bool) bool { @@ -18,7 +19,7 @@ func applyCodexToolCapabilities(dst, src map[string]json.RawMessage, overwrite b if len(value) == 0 { continue } - // These five Codex fields are nullable booleans or strings, never arbitrary objects. + // These Codex fields are nullable booleans or strings, never arbitrary objects. if !bytes.Equal(value, []byte("null")) { if field == "supports_search_tool" || field == "use_responses_lite" { if !bytes.Equal(value, []byte("true")) && !bytes.Equal(value, []byte("false")) { @@ -396,6 +397,8 @@ func configuredCodexReasoningLevelDescription(level string) string { return "Extra-high reasoning depth for difficult tasks" case "max": return "Maximum reasoning depth for complex tasks" + case "ultra": + return "Maximum reasoning with automatic task delegation" default: return "Reasoning effort supported by the upstream model" } diff --git a/backend/internal/service/openai_codex_model_metadata_test.go b/backend/internal/service/openai_codex_model_metadata_test.go index 55bc233ed2..470c9faf5f 100644 --- a/backend/internal/service/openai_codex_model_metadata_test.go +++ b/backend/internal/service/openai_codex_model_metadata_test.go @@ -9,6 +9,58 @@ import ( "github.com/stretchr/testify/require" ) +func TestAstraUltraCatalogPreservesWorkflowMetadata(t *testing.T) { + // Ultra is a Codex workflow. Its inference effort must survive catalog sync, + // aliases and group generation instead of silently falling back to max. + _, metadata, err := extractUpstreamModelCatalog([]byte(`{"models":[{ + "slug":"gpt-6-astra","supported_reasoning_levels":[{"effort":"high"},{"effort":"ultra"}], + "multi_agent_reasoning_effort":"high","multi_agent_version":"v2" + }]}`), false) + require.NoError(t, err) + account := Account{Platform: PlatformOpenAI, Type: AccountTypeAPIKey, Credentials: map[string]any{ + "base_url": "https://relay.example/v1", "model_mapping": map[string]any{"public-astra": "gpt-6-astra"}, + }} + account.SetUpstreamModelMetadataSnapshot(UpstreamModelMetadataSnapshot{Models: metadata}) + body, err := buildCodexModelsManifestForAccounts(PlatformOpenAI, []string{"public-astra"}, []Account{account}, nil, true) + require.NoError(t, err) + model := decodeCodexManifestModels(t, body)[0] + require.Equal(t, "high", model["multi_agent_reasoning_effort"]) + require.Equal(t, "v2", model["multi_agent_version"]) + require.Equal(t, []string{"high", "ultra"}, effortsFromManifestModel(t, model)) + + peer := Account{Platform: PlatformOpenAI, Type: AccountTypeAPIKey, Credentials: account.Credentials} + body, err = buildCodexModelsManifestForAccounts(PlatformOpenAI, []string{"public-astra"}, []Account{account, peer}, nil, true) + require.NoError(t, err) + model = decodeCodexManifestModels(t, body)[0] + require.Nil(t, model["multi_agent_reasoning_effort"], "do not advertise one account's override for all peers") + require.Nil(t, model["multi_agent_version"]) +} + +func TestAstraUltraCatalogPreservesExplicitWorkflowOverrides(t *testing.T) { + account := &Account{Platform: PlatformOpenAI, Type: AccountTypeAPIKey, + Credentials: map[string]any{"base_url": "https://relay.example/v1"}} + for _, fields := range []string{ + `"multi_agent_reasoning_effort":"high","multi_agent_version":"v1"`, + `"multi_agent_reasoning_effort":null,"multi_agent_version":null`, + } { + for _, source := range []string{ + `{"models":[{"slug":"gpt-6-astra",` + fields + `}]}`, + `{"data":[{"id":"gpt-6-astra",` + fields + `}]}`, + } { + converted := convertOpenAIModelListToCodexManifestForAccount([]byte(source), account) + body, err := completeAPIKeyCodexModelsManifestMetadata(converted, true, account) + require.NoError(t, err) + model := decodeCodexManifestModels(t, body)[0] + var expected map[string]any + require.NoError(t, json.Unmarshal([]byte(`{`+fields+`}`), &expected)) + for key, value := range expected { + require.Contains(t, model, key) + require.Equal(t, value, model[key]) + } + } + } +} + func TestAstraCodexToolCapabilitiesUseAccountScopeAndSharedDeclarations(t *testing.T) { newAccount := func(baseURL string) Account { return Account{Platform: PlatformOpenAI, Type: AccountTypeAPIKey, Credentials: map[string]any{ diff --git a/backend/internal/service/openai_codex_models_service.go b/backend/internal/service/openai_codex_models_service.go index 9e537a9c78..03cf6de5dd 100644 --- a/backend/internal/service/openai_codex_models_service.go +++ b/backend/internal/service/openai_codex_models_service.go @@ -361,6 +361,7 @@ type configuredCodexModelDescriptor struct { Description string `json:"description"` DefaultReasoningLevel *string `json:"default_reasoning_level,omitempty"` SupportedReasoningLevels []configuredCodexReasoningLevel `json:"supported_reasoning_levels"` + MultiAgentReasoningEffort *string `json:"multi_agent_reasoning_effort,omitempty"` ShellType string `json:"shell_type"` Visibility string `json:"visibility"` SupportedInAPI bool `json:"supported_in_api"` @@ -492,6 +493,11 @@ func newConfiguredCodexModelDescriptor(modelID string) configuredCodexModelDescr descriptor.MaxContextWindow = configuredCodexGPT56MaxContext } if isOpenAIGPT6AstraModel(modelID) { + // Codex resolves the Ultra workflow to this effort before inference. + // openai/codex a9896da3: codex-rs/models-manager/models.json. + multiAgentEffort := "xhigh" + descriptor.MultiAgentReasoningEffort = &multiAgentEffort + descriptor.MultiAgentVersion = "v2" descriptor.ContextWindow = configuredCodexGPT6AstraContext descriptor.MaxContextWindow = configuredCodexGPT6AstraContext } @@ -602,7 +608,7 @@ func configuredCodexGPTReasoningLevels(modelID string) []configuredCodexReasonin Description: "Maximum reasoning depth for complex tasks", }) } - if normalized == "gpt-5.6-sol" || normalized == "gpt-5.6-terra" { + if isOpenAIGPT6AstraModel(modelID) || normalized == "gpt-5.6-sol" || normalized == "gpt-5.6-terra" { levels = append(levels, configuredCodexReasoningLevel{ Effort: "ultra", Description: "Maximum reasoning with automatic task delegation", diff --git a/backend/internal/service/openai_codex_models_service_test.go b/backend/internal/service/openai_codex_models_service_test.go index f6e51d3453..a21bc4f53a 100644 --- a/backend/internal/service/openai_codex_models_service_test.go +++ b/backend/internal/service/openai_codex_models_service_test.go @@ -353,8 +353,10 @@ func TestNewConfiguredCodexModelDescriptorUsesProviderMetadataAndSafeFallback(t require.Equal(t, "GPT-6 Astra", gpt6Astra.DisplayName) require.NotNil(t, gpt6Astra.DefaultReasoningLevel) require.Equal(t, "medium", *gpt6Astra.DefaultReasoningLevel) - require.Equal(t, []string{"low", "medium", "high", "xhigh", "max"}, effortsFromConfiguredCodexLevels(gpt6Astra.SupportedReasoningLevels)) - require.NotContains(t, gpt6Astra.SupportedReasoningLevels, configuredCodexReasoningLevel{Effort: "ultra"}) + require.Equal(t, []string{"low", "medium", "high", "xhigh", "max", "ultra"}, effortsFromConfiguredCodexLevels(gpt6Astra.SupportedReasoningLevels)) + require.NotNil(t, gpt6Astra.MultiAgentReasoningEffort) + require.Equal(t, "xhigh", *gpt6Astra.MultiAgentReasoningEffort) + require.Equal(t, "v2", gpt6Astra.MultiAgentVersion) require.NotContains(t, gpt6Astra.SupportedReasoningLevels, configuredCodexReasoningLevel{Effort: "none"}) require.True(t, configuredCodexSupportsPriorityServiceTier("gpt-6-astra")) require.Equal(t, []configuredCodexServiceTier{{ @@ -370,7 +372,8 @@ func TestNewConfiguredCodexModelDescriptorUsesProviderMetadataAndSafeFallback(t require.Equal(t, int64(1_050_000), gpt6Astra.MaxContextWindow) gpt6 := newConfiguredCodexModelDescriptor("gpt-6") require.Equal(t, "GPT-6 (Astra)", gpt6.DisplayName) - require.Equal(t, []string{"low", "medium", "high", "xhigh", "max"}, effortsFromConfiguredCodexLevels(gpt6.SupportedReasoningLevels)) + require.Equal(t, []string{"low", "medium", "high", "xhigh", "max", "ultra"}, effortsFromConfiguredCodexLevels(gpt6.SupportedReasoningLevels)) + require.Equal(t, "xhigh", *gpt6.MultiAgentReasoningEffort) require.Equal(t, int64(1_050_000), gpt6.ContextWindow) gpt55 := newConfiguredCodexModelDescriptor("gpt-5.5") From ad4b2f30f591e4aa9bf331cc450e4ffd9b02aaf9 Mon Sep 17 00:00:00 2001 From: lyy0709 <65712338+lyy0709@users.noreply.github.com> Date: Mon, 7 Sep 2026 11:23:11 +0800 Subject: [PATCH 2/2] test(codex): assert alias workflow effort before dereferencing --- backend/internal/service/openai_codex_models_service_test.go | 1 + 1 file changed, 1 insertion(+) diff --git a/backend/internal/service/openai_codex_models_service_test.go b/backend/internal/service/openai_codex_models_service_test.go index a21bc4f53a..6382db2b2b 100644 --- a/backend/internal/service/openai_codex_models_service_test.go +++ b/backend/internal/service/openai_codex_models_service_test.go @@ -373,6 +373,7 @@ func TestNewConfiguredCodexModelDescriptorUsesProviderMetadataAndSafeFallback(t gpt6 := newConfiguredCodexModelDescriptor("gpt-6") require.Equal(t, "GPT-6 (Astra)", gpt6.DisplayName) require.Equal(t, []string{"low", "medium", "high", "xhigh", "max", "ultra"}, effortsFromConfiguredCodexLevels(gpt6.SupportedReasoningLevels)) + require.NotNil(t, gpt6.MultiAgentReasoningEffort) require.Equal(t, "xhigh", *gpt6.MultiAgentReasoningEffort) require.Equal(t, int64(1_050_000), gpt6.ContextWindow)