diff --git a/backend/internal/pkg/openai/constants.go b/backend/internal/pkg/openai/constants.go index 49e38bf8..980f058d 100644 --- a/backend/internal/pkg/openai/constants.go +++ b/backend/internal/pkg/openai/constants.go @@ -17,16 +17,9 @@ type Model struct { var DefaultModels = []Model{ {ID: "gpt-5.4", Object: "model", Created: 1738368000, OwnedBy: "openai", Type: "model", DisplayName: "GPT-5.4"}, {ID: "gpt-5.4-mini", Object: "model", Created: 1738368000, OwnedBy: "openai", Type: "model", DisplayName: "GPT-5.4 Mini"}, - {ID: "gpt-5.4-nano", Object: "model", Created: 1738368000, OwnedBy: "openai", Type: "model", DisplayName: "GPT-5.4 Nano"}, {ID: "gpt-5.3-codex", Object: "model", Created: 1735689600, OwnedBy: "openai", Type: "model", DisplayName: "GPT-5.3 Codex"}, {ID: "gpt-5.3-codex-spark", Object: "model", Created: 1735689600, OwnedBy: "openai", Type: "model", DisplayName: "GPT-5.3 Codex Spark"}, {ID: "gpt-5.2", Object: "model", Created: 1733875200, OwnedBy: "openai", Type: "model", DisplayName: "GPT-5.2"}, - {ID: "gpt-5.2-codex", Object: "model", Created: 1733011200, OwnedBy: "openai", Type: "model", DisplayName: "GPT-5.2 Codex"}, - {ID: "gpt-5.1-codex-max", Object: "model", Created: 1730419200, OwnedBy: "openai", Type: "model", DisplayName: "GPT-5.1 Codex Max"}, - {ID: "gpt-5.1-codex", Object: "model", Created: 1730419200, OwnedBy: "openai", Type: "model", DisplayName: "GPT-5.1 Codex"}, - {ID: "gpt-5.1", Object: "model", Created: 1731456000, OwnedBy: "openai", Type: "model", DisplayName: "GPT-5.1"}, - {ID: "gpt-5.1-codex-mini", Object: "model", Created: 1730419200, OwnedBy: "openai", Type: "model", DisplayName: "GPT-5.1 Codex Mini"}, - {ID: "gpt-5", Object: "model", Created: 1722988800, OwnedBy: "openai", Type: "model", DisplayName: "GPT-5"}, } // DefaultModelIDs returns the default model ID list @@ -39,7 +32,7 @@ func DefaultModelIDs() []string { } // DefaultTestModel default model for testing OpenAI accounts -const DefaultTestModel = "gpt-5.1-codex" +const DefaultTestModel = "gpt-5.4" // DefaultInstructions default instructions for non-Codex CLI requests // Content loaded from instructions.txt at compile time diff --git a/backend/internal/service/billing_service.go b/backend/internal/service/billing_service.go index c9f32b3b..a45203a3 100644 --- a/backend/internal/service/billing_service.go +++ b/backend/internal/service/billing_service.go @@ -203,17 +203,6 @@ func (s *BillingService) initFallbackPricing() { SupportsCacheBreakdown: false, } - // OpenAI GPT-5.1(本地兜底,防止动态定价不可用时拒绝计费) - s.fallbackPrices["gpt-5.1"] = &ModelPricing{ - InputPricePerToken: 1.25e-6, // $1.25 per MTok - InputPricePerTokenPriority: 2.5e-6, // $2.5 per MTok - OutputPricePerToken: 10e-6, // $10 per MTok - OutputPricePerTokenPriority: 20e-6, // $20 per MTok - CacheCreationPricePerToken: 1.25e-6, // $1.25 per MTok - CacheReadPricePerToken: 0.125e-6, - CacheReadPricePerTokenPriority: 0.25e-6, - SupportsCacheBreakdown: false, - } // OpenAI GPT-5.4(业务指定价格) s.fallbackPrices["gpt-5.4"] = &ModelPricing{ InputPricePerToken: 2.5e-6, // $2.5 per MTok @@ -234,12 +223,6 @@ func (s *BillingService) initFallbackPricing() { CacheReadPricePerToken: 7.5e-8, SupportsCacheBreakdown: false, } - s.fallbackPrices["gpt-5.4-nano"] = &ModelPricing{ - InputPricePerToken: 2e-7, - OutputPricePerToken: 1.25e-6, - CacheReadPricePerToken: 2e-8, - SupportsCacheBreakdown: false, - } // OpenAI GPT-5.2(本地兜底) s.fallbackPrices["gpt-5.2"] = &ModelPricing{ InputPricePerToken: 1.75e-6, @@ -251,8 +234,8 @@ func (s *BillingService) initFallbackPricing() { CacheReadPricePerTokenPriority: 0.35e-6, SupportsCacheBreakdown: false, } - // Codex 族兜底统一按 GPT-5.1 Codex 价格计费 - s.fallbackPrices["gpt-5.1-codex"] = &ModelPricing{ + // Codex 族兜底统一按 GPT-5.3 Codex 价格计费 + s.fallbackPrices["gpt-5.3-codex"] = &ModelPricing{ InputPricePerToken: 1.5e-6, // $1.5 per MTok InputPricePerTokenPriority: 3e-6, // $3 per MTok OutputPricePerToken: 12e-6, // $12 per MTok @@ -262,17 +245,6 @@ func (s *BillingService) initFallbackPricing() { CacheReadPricePerTokenPriority: 0.3e-6, SupportsCacheBreakdown: false, } - s.fallbackPrices["gpt-5.2-codex"] = &ModelPricing{ - InputPricePerToken: 1.75e-6, - InputPricePerTokenPriority: 3.5e-6, - OutputPricePerToken: 14e-6, - OutputPricePerTokenPriority: 28e-6, - CacheCreationPricePerToken: 1.75e-6, - CacheReadPricePerToken: 0.175e-6, - CacheReadPricePerTokenPriority: 0.35e-6, - SupportsCacheBreakdown: false, - } - s.fallbackPrices["gpt-5.3-codex"] = s.fallbackPrices["gpt-5.1-codex"] } // getFallbackPricing 根据模型系列获取回退价格 @@ -318,20 +290,12 @@ func (s *BillingService) getFallbackPricing(model string) *ModelPricing { switch normalized { case "gpt-5.4-mini": return s.fallbackPrices["gpt-5.4-mini"] - case "gpt-5.4-nano": - return s.fallbackPrices["gpt-5.4-nano"] case "gpt-5.4": return s.fallbackPrices["gpt-5.4"] case "gpt-5.2": return s.fallbackPrices["gpt-5.2"] - case "gpt-5.2-codex": - return s.fallbackPrices["gpt-5.2-codex"] - case "gpt-5.3-codex": + case "gpt-5.3-codex", "gpt-5.3-codex-spark": return s.fallbackPrices["gpt-5.3-codex"] - case "gpt-5.1-codex", "gpt-5.1-codex-max", "gpt-5.1-codex-mini", "codex-mini-latest": - return s.fallbackPrices["gpt-5.1-codex"] - case "gpt-5.1": - return s.fallbackPrices["gpt-5.1"] } } @@ -667,8 +631,13 @@ func (s *BillingService) shouldApplySessionLongContextPricing(tokens UsageTokens } func isOpenAIGPT54Model(model string) bool { - normalized := normalizeCodexModel(strings.TrimSpace(strings.ToLower(model))) - return normalized == "gpt-5.4" + trimmed := strings.TrimSpace(strings.ToLower(model)) + // 仅当模型字符串实际属于 GPT-5/Codex 族时才做归一判定,避免 normalizeCodexModel + // 的默认兜底把非 OpenAI 模型(claude-*、gemini-*、gpt-4o)误识别为 gpt-5.4。 + if !strings.Contains(trimmed, "gpt-5") && !strings.Contains(trimmed, "codex") { + return false + } + return normalizeCodexModel(trimmed) == "gpt-5.4" } // CalculateCostWithConfig 使用配置中的默认倍率计算费用 diff --git a/backend/internal/service/billing_service_test.go b/backend/internal/service/billing_service_test.go index fc8361c7..222abd69 100644 --- a/backend/internal/service/billing_service_test.go +++ b/backend/internal/service/billing_service_test.go @@ -123,15 +123,6 @@ func TestGetModelPricing_UnknownOpenAIModelReturnsError(t *testing.T) { require.Contains(t, err.Error(), "pricing not found") } -func TestGetModelPricing_OpenAIGPT51Fallback(t *testing.T) { - svc := newTestBillingService() - - pricing, err := svc.GetModelPricing("gpt-5.1") - require.NoError(t, err) - require.NotNil(t, pricing) - require.InDelta(t, 1.25e-6, pricing.InputPricePerToken, 1e-12) -} - func TestGetModelPricing_OpenAIGPT54Fallback(t *testing.T) { svc := newTestBillingService() @@ -158,18 +149,6 @@ func TestGetModelPricing_OpenAIGPT54MiniFallback(t *testing.T) { require.Zero(t, pricing.LongContextInputThreshold) } -func TestGetModelPricing_OpenAIGPT54NanoFallback(t *testing.T) { - svc := newTestBillingService() - - pricing, err := svc.GetModelPricing("gpt-5.4-nano") - require.NoError(t, err) - require.NotNil(t, pricing) - require.InDelta(t, 2e-7, pricing.InputPricePerToken, 1e-12) - require.InDelta(t, 1.25e-6, pricing.OutputPricePerToken, 1e-12) - require.InDelta(t, 2e-8, pricing.CacheReadPricePerToken, 1e-12) - require.Zero(t, pricing.LongContextInputThreshold) -} - func TestCalculateCost_OpenAIGPT54LongContextAppliesWholeSessionMultipliers(t *testing.T) { svc := newTestBillingService() @@ -204,13 +183,13 @@ func TestGetFallbackPricing_FamilyMatching(t *testing.T) { {name: "claude generic model fallback sonnet", model: "claude-foo-bar", expectedInput: 3e-6}, {name: "gemini explicit fallback", model: "gemini-3-1-pro", expectedInput: 2e-6}, {name: "gemini unknown no fallback", model: "gemini-2.0-pro", expectNilPricing: true}, - {name: "openai gpt5.1", model: "gpt-5.1", expectedInput: 1.25e-6}, {name: "openai gpt5.4", model: "gpt-5.4", expectedInput: 2.5e-6}, {name: "openai gpt5.4 mini", model: "gpt-5.4-mini", expectedInput: 7.5e-7}, - {name: "openai gpt5.4 nano", model: "gpt-5.4-nano", expectedInput: 2e-7}, {name: "openai gpt5.3 codex", model: "gpt-5.3-codex", expectedInput: 1.5e-6}, - {name: "openai gpt5.1 codex max alias", model: "gpt-5.1-codex-max", expectedInput: 1.5e-6}, - {name: "openai codex mini latest alias", model: "codex-mini-latest", expectedInput: 1.5e-6}, + {name: "openai gpt5.3 codex spark", model: "gpt-5.3-codex-spark", expectedInput: 1.5e-6}, + {name: "openai legacy gpt5.1 falls back to gpt5.4", model: "gpt-5.1", expectedInput: 2.5e-6}, + {name: "openai legacy gpt5.1 codex falls back to gpt5.3 codex", model: "gpt-5.1-codex", expectedInput: 1.5e-6}, + {name: "openai legacy codex mini latest falls back to gpt5.3 codex", model: "codex-mini-latest", expectedInput: 1.5e-6}, {name: "openai unknown no fallback", model: "gpt-unknown-model", expectNilPricing: true}, {name: "non supported family", model: "qwen-max", expectNilPricing: true}, } diff --git a/backend/internal/service/openai_codex_transform.go b/backend/internal/service/openai_codex_transform.go index a266d6a0..457309d3 100644 --- a/backend/internal/service/openai_codex_transform.go +++ b/backend/internal/service/openai_codex_transform.go @@ -8,7 +8,6 @@ import ( var codexModelMap = map[string]string{ "gpt-5.4": "gpt-5.4", "gpt-5.4-mini": "gpt-5.4-mini", - "gpt-5.4-nano": "gpt-5.4-nano", "gpt-5.4-none": "gpt-5.4", "gpt-5.4-low": "gpt-5.4", "gpt-5.4-medium": "gpt-5.4", @@ -22,52 +21,21 @@ var codexModelMap = map[string]string{ "gpt-5.3-high": "gpt-5.3-codex", "gpt-5.3-xhigh": "gpt-5.3-codex", "gpt-5.3-codex": "gpt-5.3-codex", - "gpt-5.3-codex-spark": "gpt-5.3-codex", - "gpt-5.3-codex-spark-low": "gpt-5.3-codex", - "gpt-5.3-codex-spark-medium": "gpt-5.3-codex", - "gpt-5.3-codex-spark-high": "gpt-5.3-codex", - "gpt-5.3-codex-spark-xhigh": "gpt-5.3-codex", + "gpt-5.3-codex-spark": "gpt-5.3-codex-spark", + "gpt-5.3-codex-spark-low": "gpt-5.3-codex-spark", + "gpt-5.3-codex-spark-medium": "gpt-5.3-codex-spark", + "gpt-5.3-codex-spark-high": "gpt-5.3-codex-spark", + "gpt-5.3-codex-spark-xhigh": "gpt-5.3-codex-spark", "gpt-5.3-codex-low": "gpt-5.3-codex", "gpt-5.3-codex-medium": "gpt-5.3-codex", "gpt-5.3-codex-high": "gpt-5.3-codex", "gpt-5.3-codex-xhigh": "gpt-5.3-codex", - "gpt-5.1-codex": "gpt-5.1-codex", - "gpt-5.1-codex-low": "gpt-5.1-codex", - "gpt-5.1-codex-medium": "gpt-5.1-codex", - "gpt-5.1-codex-high": "gpt-5.1-codex", - "gpt-5.1-codex-max": "gpt-5.1-codex-max", - "gpt-5.1-codex-max-low": "gpt-5.1-codex-max", - "gpt-5.1-codex-max-medium": "gpt-5.1-codex-max", - "gpt-5.1-codex-max-high": "gpt-5.1-codex-max", - "gpt-5.1-codex-max-xhigh": "gpt-5.1-codex-max", "gpt-5.2": "gpt-5.2", "gpt-5.2-none": "gpt-5.2", "gpt-5.2-low": "gpt-5.2", "gpt-5.2-medium": "gpt-5.2", "gpt-5.2-high": "gpt-5.2", "gpt-5.2-xhigh": "gpt-5.2", - "gpt-5.2-codex": "gpt-5.2-codex", - "gpt-5.2-codex-low": "gpt-5.2-codex", - "gpt-5.2-codex-medium": "gpt-5.2-codex", - "gpt-5.2-codex-high": "gpt-5.2-codex", - "gpt-5.2-codex-xhigh": "gpt-5.2-codex", - "gpt-5.1-codex-mini": "gpt-5.1-codex-mini", - "gpt-5.1-codex-mini-medium": "gpt-5.1-codex-mini", - "gpt-5.1-codex-mini-high": "gpt-5.1-codex-mini", - "gpt-5.1": "gpt-5.1", - "gpt-5.1-none": "gpt-5.1", - "gpt-5.1-low": "gpt-5.1", - "gpt-5.1-medium": "gpt-5.1", - "gpt-5.1-high": "gpt-5.1", - "gpt-5.1-chat-latest": "gpt-5.1", - "gpt-5-codex": "gpt-5.1-codex", - "codex-mini-latest": "gpt-5.1-codex-mini", - "gpt-5-codex-mini": "gpt-5.1-codex-mini", - "gpt-5-codex-mini-medium": "gpt-5.1-codex-mini", - "gpt-5-codex-mini-high": "gpt-5.1-codex-mini", - "gpt-5": "gpt-5.1", - "gpt-5-mini": "gpt-5.1", - "gpt-5-nano": "gpt-5.1", } type codexTransformResult struct { @@ -220,7 +188,7 @@ func applyCodexOAuthTransform(reqBody map[string]any, isCodexCLI bool, isCompact func normalizeCodexModel(model string) string { if model == "" { - return "gpt-5.1" + return "gpt-5.4" } modelID := model @@ -238,49 +206,29 @@ func normalizeCodexModel(model string) string { if strings.Contains(normalized, "gpt-5.4-mini") || strings.Contains(normalized, "gpt 5.4 mini") { return "gpt-5.4-mini" } - if strings.Contains(normalized, "gpt-5.4-nano") || strings.Contains(normalized, "gpt 5.4 nano") { - return "gpt-5.4-nano" - } if strings.Contains(normalized, "gpt-5.4") || strings.Contains(normalized, "gpt 5.4") { return "gpt-5.4" } - if strings.Contains(normalized, "gpt-5.2-codex") || strings.Contains(normalized, "gpt 5.2 codex") { - return "gpt-5.2-codex" - } if strings.Contains(normalized, "gpt-5.2") || strings.Contains(normalized, "gpt 5.2") { return "gpt-5.2" } + if strings.Contains(normalized, "gpt-5.3-codex-spark") || strings.Contains(normalized, "gpt 5.3 codex spark") { + return "gpt-5.3-codex-spark" + } if strings.Contains(normalized, "gpt-5.3-codex") || strings.Contains(normalized, "gpt 5.3 codex") { return "gpt-5.3-codex" } if strings.Contains(normalized, "gpt-5.3") || strings.Contains(normalized, "gpt 5.3") { return "gpt-5.3-codex" } - if strings.Contains(normalized, "gpt-5.1-codex-max") || strings.Contains(normalized, "gpt 5.1 codex max") { - return "gpt-5.1-codex-max" - } - if strings.Contains(normalized, "gpt-5.1-codex-mini") || strings.Contains(normalized, "gpt 5.1 codex mini") { - return "gpt-5.1-codex-mini" - } - if strings.Contains(normalized, "codex-mini-latest") || - strings.Contains(normalized, "gpt-5-codex-mini") || - strings.Contains(normalized, "gpt 5 codex mini") { - return "codex-mini-latest" - } - if strings.Contains(normalized, "gpt-5.1-codex") || strings.Contains(normalized, "gpt 5.1 codex") { - return "gpt-5.1-codex" - } - if strings.Contains(normalized, "gpt-5.1") || strings.Contains(normalized, "gpt 5.1") { - return "gpt-5.1" - } if strings.Contains(normalized, "codex") { - return "gpt-5.1-codex" + return "gpt-5.3-codex" } if strings.Contains(normalized, "gpt-5") || strings.Contains(normalized, "gpt 5") { - return "gpt-5.1" + return "gpt-5.4" } - return "gpt-5.1" + return "gpt-5.4" } func normalizeOpenAIModelForUpstream(account *Account, model string) string { diff --git a/backend/internal/service/openai_codex_transform_test.go b/backend/internal/service/openai_codex_transform_test.go index 993ade07..22264f5e 100644 --- a/backend/internal/service/openai_codex_transform_test.go +++ b/backend/internal/service/openai_codex_transform_test.go @@ -240,15 +240,13 @@ func TestNormalizeCodexModel_Gpt53(t *testing.T) { "gpt 5.4": "gpt-5.4", "gpt-5.4-mini": "gpt-5.4-mini", "gpt 5.4 mini": "gpt-5.4-mini", - "gpt-5.4-nano": "gpt-5.4-nano", - "gpt 5.4 nano": "gpt-5.4-nano", "gpt-5.3": "gpt-5.3-codex", "gpt-5.3-codex": "gpt-5.3-codex", "gpt-5.3-codex-xhigh": "gpt-5.3-codex", - "gpt-5.3-codex-spark": "gpt-5.3-codex", - "gpt 5.3 codex spark": "gpt-5.3-codex", - "gpt-5.3-codex-spark-high": "gpt-5.3-codex", - "gpt-5.3-codex-spark-xhigh": "gpt-5.3-codex", + "gpt-5.3-codex-spark": "gpt-5.3-codex-spark", + "gpt 5.3 codex spark": "gpt-5.3-codex-spark", + "gpt-5.3-codex-spark-high": "gpt-5.3-codex-spark", + "gpt-5.3-codex-spark-xhigh": "gpt-5.3-codex-spark", "gpt 5.3 codex": "gpt-5.3-codex", } @@ -257,6 +255,26 @@ func TestNormalizeCodexModel_Gpt53(t *testing.T) { } } +func TestNormalizeCodexModel_RemovedModelsFallbackToSupportedTargets(t *testing.T) { + cases := map[string]string{ + "": "gpt-5.4", + "gpt-5": "gpt-5.4", + "gpt-5-mini": "gpt-5.4", + "gpt-5-nano": "gpt-5.4", + "gpt-5.1": "gpt-5.4", + "gpt-5.1-codex": "gpt-5.3-codex", + "gpt-5.1-codex-max": "gpt-5.3-codex", + "gpt-5.1-codex-mini": "gpt-5.3-codex", + "gpt-5.2-codex": "gpt-5.2", + "codex-mini-latest": "gpt-5.3-codex", + "gpt-5-codex": "gpt-5.3-codex", + } + + for input, expected := range cases { + require.Equal(t, expected, normalizeCodexModel(input)) + } +} + func TestApplyCodexOAuthTransform_PreservesBareSparkModel(t *testing.T) { reqBody := map[string]any{ "model": "gpt-5.3-codex-spark", diff --git a/backend/internal/service/openai_compat_prompt_cache_key.go b/backend/internal/service/openai_compat_prompt_cache_key.go index 88e16a4d..fcd27f19 100644 --- a/backend/internal/service/openai_compat_prompt_cache_key.go +++ b/backend/internal/service/openai_compat_prompt_cache_key.go @@ -10,8 +10,14 @@ import ( const compatPromptCacheKeyPrefix = "compat_cc_" func shouldAutoInjectPromptCacheKeyForCompat(model string) bool { - switch normalizeCodexModel(strings.TrimSpace(model)) { - case "gpt-5.4", "gpt-5.3-codex": + trimmed := strings.TrimSpace(strings.ToLower(model)) + // 仅对 Codex OAuth 路径支持的 GPT-5 族开启自动注入,避免 normalizeCodexModel + // 的默认兜底把任意模型(如 gpt-4o、claude-*)误判为 gpt-5.4。 + if !strings.Contains(trimmed, "gpt-5") && !strings.Contains(trimmed, "codex") { + return false + } + switch normalizeCodexModel(trimmed) { + case "gpt-5.4", "gpt-5.3-codex", "gpt-5.3-codex-spark": return true default: return false diff --git a/backend/internal/service/openai_model_mapping_test.go b/backend/internal/service/openai_model_mapping_test.go index cda7e369..35e7c250 100644 --- a/backend/internal/service/openai_model_mapping_test.go +++ b/backend/internal/service/openai_model_mapping_test.go @@ -69,14 +69,14 @@ func TestResolveOpenAIForwardModel(t *testing.T) { } } -func TestResolveOpenAIForwardModel_PreventsClaudeModelFromFallingBackToGpt51(t *testing.T) { +func TestResolveOpenAIForwardModel_PreventsClaudeModelFromFallingBackToGpt54(t *testing.T) { account := &Account{ Credentials: map[string]any{}, } withoutDefault := normalizeCodexModel(resolveOpenAIForwardModel(account, "claude-opus-4-6", "")) - if withoutDefault != "gpt-5.1" { - t.Fatalf("normalizeCodexModel(...) = %q, want %q", withoutDefault, "gpt-5.1") + if withoutDefault != "gpt-5.4" { + t.Fatalf("normalizeCodexModel(...) = %q, want %q", withoutDefault, "gpt-5.4") } withDefault := normalizeCodexModel(resolveOpenAIForwardModel(account, "claude-opus-4-6", "gpt-5.4")) @@ -87,9 +87,9 @@ func TestResolveOpenAIForwardModel_PreventsClaudeModelFromFallingBackToGpt51(t * func TestNormalizeCodexModel(t *testing.T) { cases := map[string]string{ - "gpt-5.3-codex-spark": "gpt-5.3-codex", - "gpt-5.3-codex-spark-high": "gpt-5.3-codex", - "gpt-5.3-codex-spark-xhigh": "gpt-5.3-codex", + "gpt-5.3-codex-spark": "gpt-5.3-codex-spark", + "gpt-5.3-codex-spark-high": "gpt-5.3-codex-spark", + "gpt-5.3-codex-spark-xhigh": "gpt-5.3-codex-spark", "gpt-5.3": "gpt-5.3-codex", } @@ -111,7 +111,7 @@ func TestNormalizeOpenAIModelForUpstream(t *testing.T) { name: "oauth keeps codex normalization behavior", account: &Account{Type: AccountTypeOAuth}, model: "gemini-3-flash-preview", - want: "gpt-5.1", + want: "gpt-5.4", }, { name: "apikey preserves custom compatible model", diff --git a/frontend/src/components/keys/UseKeyModal.vue b/frontend/src/components/keys/UseKeyModal.vue index 7770e658..b3679107 100644 --- a/frontend/src/components/keys/UseKeyModal.vue +++ b/frontend/src/components/keys/UseKeyModal.vue @@ -617,66 +617,6 @@ function generateOpenCodeConfig(platform: string, baseUrl: string, apiKey: strin } } const openaiModels = { - 'gpt-5-codex': { - name: 'GPT-5 Codex', - limit: { - context: 400000, - output: 128000 - }, - options: { - store: false - }, - variants: { - low: {}, - medium: {}, - high: {} - } - }, - 'gpt-5.1-codex': { - name: 'GPT-5.1 Codex', - limit: { - context: 400000, - output: 128000 - }, - options: { - store: false - }, - variants: { - low: {}, - medium: {}, - high: {} - } - }, - 'gpt-5.1-codex-max': { - name: 'GPT-5.1 Codex Max', - limit: { - context: 400000, - output: 128000 - }, - options: { - store: false - }, - variants: { - low: {}, - medium: {}, - high: {} - } - }, - 'gpt-5.1-codex-mini': { - name: 'GPT-5.1 Codex Mini', - limit: { - context: 400000, - output: 128000 - }, - options: { - store: false - }, - variants: { - low: {}, - medium: {}, - high: {} - } - }, 'gpt-5.2': { name: 'GPT-5.2', limit: { @@ -725,22 +665,6 @@ function generateOpenCodeConfig(platform: string, baseUrl: string, apiKey: strin xhigh: {} } }, - 'gpt-5.4-nano': { - name: 'GPT-5.4 Nano', - limit: { - context: 400000, - output: 128000 - }, - options: { - store: false - }, - variants: { - low: {}, - medium: {}, - high: {}, - xhigh: {} - } - }, 'gpt-5.3-codex-spark': { name: 'GPT-5.3 Codex Spark', limit: { @@ -773,22 +697,6 @@ function generateOpenCodeConfig(platform: string, baseUrl: string, apiKey: strin xhigh: {} } }, - 'gpt-5.2-codex': { - name: 'GPT-5.2 Codex', - limit: { - context: 400000, - output: 128000 - }, - options: { - store: false - }, - variants: { - low: {}, - medium: {}, - high: {}, - xhigh: {} - } - }, 'codex-mini-latest': { name: 'Codex Mini', limit: { diff --git a/frontend/src/components/keys/__tests__/UseKeyModal.spec.ts b/frontend/src/components/keys/__tests__/UseKeyModal.spec.ts index 98b5dede..f7db586a 100644 --- a/frontend/src/components/keys/__tests__/UseKeyModal.spec.ts +++ b/frontend/src/components/keys/__tests__/UseKeyModal.spec.ts @@ -17,7 +17,7 @@ vi.mock('@/composables/useClipboard', () => ({ import UseKeyModal from '../UseKeyModal.vue' describe('UseKeyModal', () => { - it('renders updated GPT-5.4 mini/nano names in OpenCode config', async () => { + it('renders GPT-5.4 mini entry in OpenCode config', async () => { const wrapper = mount(UseKeyModal, { props: { show: true, @@ -48,6 +48,6 @@ describe('UseKeyModal', () => { const codeBlock = wrapper.find('pre code') expect(codeBlock.exists()).toBe(true) expect(codeBlock.text()).toContain('"name": "GPT-5.4 Mini"') - expect(codeBlock.text()).toContain('"name": "GPT-5.4 Nano"') + expect(codeBlock.text()).not.toContain('"name": "GPT-5.4 Nano"') }) }) diff --git a/frontend/src/composables/__tests__/useModelWhitelist.spec.ts b/frontend/src/composables/__tests__/useModelWhitelist.spec.ts index 4061be4d..d35e3b12 100644 --- a/frontend/src/composables/__tests__/useModelWhitelist.spec.ts +++ b/frontend/src/composables/__tests__/useModelWhitelist.spec.ts @@ -12,10 +12,20 @@ describe('useModelWhitelist', () => { expect(models).toContain('gpt-5.4') expect(models).toContain('gpt-5.4-mini') - expect(models).toContain('gpt-5.4-nano') expect(models).toContain('gpt-5.4-2026-03-05') }) + it('openai 模型列表不再暴露已下线的 ChatGPT 登录 Codex 模型', () => { + const models = getModelsByPlatform('openai') + + expect(models).not.toContain('gpt-5') + expect(models).not.toContain('gpt-5.1') + expect(models).not.toContain('gpt-5.1-codex') + expect(models).not.toContain('gpt-5.1-codex-max') + expect(models).not.toContain('gpt-5.1-codex-mini') + expect(models).not.toContain('gpt-5.2-codex') + }) + it('antigravity 模型列表包含图片模型兼容项', () => { const models = getModelsByPlatform('antigravity') @@ -55,12 +65,11 @@ describe('useModelWhitelist', () => { }) }) - it('whitelist keeps GPT-5.4 mini and nano exact mappings', () => { - const mapping = buildModelMappingObject('whitelist', ['gpt-5.4-mini', 'gpt-5.4-nano'], []) + it('whitelist keeps GPT-5.4 mini exact mappings', () => { + const mapping = buildModelMappingObject('whitelist', ['gpt-5.4-mini'], []) expect(mapping).toEqual({ - 'gpt-5.4-mini': 'gpt-5.4-mini', - 'gpt-5.4-nano': 'gpt-5.4-nano' + 'gpt-5.4-mini': 'gpt-5.4-mini' }) }) }) diff --git a/frontend/src/composables/useModelWhitelist.ts b/frontend/src/composables/useModelWhitelist.ts index a282ae7d..ddd7af48 100644 --- a/frontend/src/composables/useModelWhitelist.ts +++ b/frontend/src/composables/useModelWhitelist.ts @@ -13,19 +13,11 @@ const openaiModels = [ 'o1', 'o1-preview', 'o1-mini', 'o1-pro', 'o3', 'o3-mini', 'o3-pro', 'o4-mini', - // GPT-5 系列(同步后端定价文件) - 'gpt-5', 'gpt-5-2025-08-07', 'gpt-5-chat', 'gpt-5-chat-latest', - 'gpt-5-codex', 'gpt-5.3-codex-spark', 'gpt-5-pro', 'gpt-5-pro-2025-10-06', - 'gpt-5-mini', 'gpt-5-mini-2025-08-07', - 'gpt-5-nano', 'gpt-5-nano-2025-08-07', - // GPT-5.1 系列 - 'gpt-5.1', 'gpt-5.1-2025-11-13', 'gpt-5.1-chat-latest', - 'gpt-5.1-codex', 'gpt-5.1-codex-max', 'gpt-5.1-codex-mini', // GPT-5.2 系列 'gpt-5.2', 'gpt-5.2-2025-12-11', 'gpt-5.2-chat-latest', - 'gpt-5.2-codex', 'gpt-5.2-pro', 'gpt-5.2-pro-2025-12-11', + 'gpt-5.2-pro', 'gpt-5.2-pro-2025-12-11', // GPT-5.4 系列 - 'gpt-5.4', 'gpt-5.4-mini', 'gpt-5.4-nano', 'gpt-5.4-2026-03-05', + 'gpt-5.4', 'gpt-5.4-mini', 'gpt-5.4-2026-03-05', // GPT-5.3 系列 'gpt-5.3-codex', 'gpt-5.3-codex-spark', 'chatgpt-4o-latest', @@ -264,12 +256,9 @@ const openaiPresetMappings = [ { label: 'GPT-4.1', from: 'gpt-4.1', to: 'gpt-4.1', color: 'bg-indigo-100 text-indigo-700 hover:bg-indigo-200 dark:bg-indigo-900/30 dark:text-indigo-400' }, { label: 'o1', from: 'o1', to: 'o1', color: 'bg-purple-100 text-purple-700 hover:bg-purple-200 dark:bg-purple-900/30 dark:text-purple-400' }, { label: 'o3', from: 'o3', to: 'o3', color: 'bg-emerald-100 text-emerald-700 hover:bg-emerald-200 dark:bg-emerald-900/30 dark:text-emerald-400' }, - { label: 'GPT-5', from: 'gpt-5', to: 'gpt-5', color: 'bg-amber-100 text-amber-700 hover:bg-amber-200 dark:bg-amber-900/30 dark:text-amber-400' }, { label: 'GPT-5.3 Codex Spark', from: 'gpt-5.3-codex-spark', to: 'gpt-5.3-codex-spark', color: 'bg-teal-100 text-teal-700 hover:bg-teal-200 dark:bg-teal-900/30 dark:text-teal-400' }, - { label: 'GPT-5.1', from: 'gpt-5.1', to: 'gpt-5.1', color: 'bg-orange-100 text-orange-700 hover:bg-orange-200 dark:bg-orange-900/30 dark:text-orange-400' }, { label: 'GPT-5.2', from: 'gpt-5.2', to: 'gpt-5.2', color: 'bg-red-100 text-red-700 hover:bg-red-200 dark:bg-red-900/30 dark:text-red-400' }, { label: 'GPT-5.4', from: 'gpt-5.4', to: 'gpt-5.4', color: 'bg-rose-100 text-rose-700 hover:bg-rose-200 dark:bg-rose-900/30 dark:text-rose-400' }, - { label: 'GPT-5.1 Codex', from: 'gpt-5.1-codex', to: 'gpt-5.1-codex', color: 'bg-cyan-100 text-cyan-700 hover:bg-cyan-200 dark:bg-cyan-900/30 dark:text-cyan-400' }, { label: 'Haiku→5.4', from: 'claude-haiku-4-5-20251001', to: 'gpt-5.4', color: 'bg-emerald-100 text-emerald-700 hover:bg-emerald-200 dark:bg-emerald-900/30 dark:text-emerald-400' }, { label: 'Opus→5.4', from: 'claude-opus-4-6', to: 'gpt-5.4', color: 'bg-purple-100 text-purple-700 hover:bg-purple-200 dark:bg-purple-900/30 dark:text-purple-400' }, { label: 'Sonnet→5.4', from: 'claude-sonnet-4-6', to: 'gpt-5.4', color: 'bg-blue-100 text-blue-700 hover:bg-blue-200 dark:bg-blue-900/30 dark:text-blue-400' }