diff --git a/litellm/proxy/public_endpoints/provider_create_fields.json b/litellm/proxy/public_endpoints/provider_create_fields.json index 66f8c2ea36f..cd781abee26 100644 --- a/litellm/proxy/public_endpoints/provider_create_fields.json +++ b/litellm/proxy/public_endpoints/provider_create_fields.json @@ -688,6 +688,13 @@ ], "default_model_placeholder": "gpt-3.5-turbo" }, + { + "provider": "CHATGPT", + "provider_display_name": "ChatGPT Subscription", + "litellm_provider": "chatgpt", + "credential_fields": [], + "default_model_placeholder": "chatgpt/gpt-5.4" + }, { "provider": "CLARIFAI", "provider_display_name": "Clarifai", diff --git a/tests/test_litellm/proxy/public_endpoints/test_public_endpoints.py b/tests/test_litellm/proxy/public_endpoints/test_public_endpoints.py index 4a19ad3541c..0d82ed778f5 100644 --- a/tests/test_litellm/proxy/public_endpoints/test_public_endpoints.py +++ b/tests/test_litellm/proxy/public_endpoints/test_public_endpoints.py @@ -1,5 +1,6 @@ import re from datetime import datetime, timezone +from typing import Final from unittest.mock import AsyncMock, MagicMock, patch import pytest @@ -327,6 +328,85 @@ def test_cognition_provider_fields(): assert fields_by_key["api_base"]["required"] is False +def test_chatgpt_provider_fields(): + app_instance = FastAPI() + app_instance.include_router(router) + test_client = TestClient(app_instance) + + response = test_client.get("/public/providers/fields") + assert response.status_code == 200 + providers = response.json() + + chatgpt = next((p for p in providers if p["provider"] == "CHATGPT"), None) + assert chatgpt is not None, "ChatGPT provider entry not found" + + assert chatgpt["provider_display_name"] == "ChatGPT Subscription" + assert chatgpt["litellm_provider"] == LlmProviders.CHATGPT.value + assert chatgpt["default_model_placeholder"].startswith("chatgpt/") + assert chatgpt["credential_fields"] == [] + + +ADD_MODEL_UNLISTED_PROVIDERS: Final = frozenset( + { + "a2a", + "a2a_agent", + "amazon_nova", + "apertis", + "aws_polly", + "black_forest_labs", + "charity_engine", + "chutes", + "darkbloom", + "gdc", + "helicone", + "inception", + "langflow", + "langgraph", + "libertai", + "litellm_agent", + "manus", + "meta", + "modelscope", + "mongodb", + "nano-gpt", + "neosantara", + "parasail", + "pinstripes", + "poe", + "publicai", + "ragflow", + "reducto", + "s3_vectors", + "sagemaker_nova", + "scaleway", + "stability", + "synthetic", + "tencent", + "tensormesh", + "text-completion-inception", + "valkey", + "xiaomi_mimo", + "zai", + } +) + + +def test_every_backend_provider_is_listed_in_add_model_or_frozen_as_unlisted(): + app_instance = FastAPI() + app_instance.include_router(router) + test_client = TestClient(app_instance) + + response = test_client.get("/public/providers/fields") + assert response.status_code == 200 + listed = {p["litellm_provider"] for p in response.json()} + + unlisted = {provider.value for provider in LlmProviders} - listed + assert unlisted == ADD_MODEL_UNLISTED_PROVIDERS, ( + "Add Model dropdown drift: give the new provider an entry in provider_create_fields.json " + "rather than adding it to ADD_MODEL_UNLISTED_PROVIDERS" + ) + + def test_google_ai_studio_provider_fields_expose_api_base(): """The Google AI Studio (gemini) credential form must let admins set a custom api_base so they can point at a Gemini-compatible gateway (e.g. a self-hosted diff --git a/ui/litellm-dashboard/src/components/provider_info_helpers.test.tsx b/ui/litellm-dashboard/src/components/provider_info_helpers.test.tsx index dfc737ddd45..4c68e302267 100644 --- a/ui/litellm-dashboard/src/components/provider_info_helpers.test.tsx +++ b/ui/litellm-dashboard/src/components/provider_info_helpers.test.tsx @@ -89,6 +89,16 @@ describe("provider_info_helpers", () => { expect(result.logo).toBe(providerLogoMap[Providers.BedrockMantle]); }); + it("should map the chatgpt slug and CHATGPT enum key to the ChatGPT Subscription name and OpenAI logo", () => { + const fromSlug = getProviderLogoAndName("chatgpt"); + expect(fromSlug.displayName).toBe("ChatGPT Subscription"); + expect(fromSlug.logo).toContain("openai_small"); + + const fromEnumKey = getProviderLogoAndName("CHATGPT"); + expect(fromEnumKey.displayName).toBe("ChatGPT Subscription"); + expect(fromEnumKey.logo).toContain("openai_small"); + }); + it("should handle provider values case-insensitively", () => { const result = getProviderLogoAndName("OPENAI"); expect(result.displayName).toBe(Providers.OpenAI); @@ -272,6 +282,10 @@ describe("provider_info_helpers", () => { expect(getPlaceholder(Providers.Cognition)).toBe("cognition/swe-1.7"); }); + it("should return a chatgpt/ placeholder for the CHATGPT dropdown key", () => { + expect(getPlaceholder("CHATGPT")).toBe("chatgpt/gpt-5.4"); + }); + it("should return default gpt-3.5-turbo placeholder for unknown provider", () => { expect(getPlaceholder("UnknownProvider" as any)).toBe("gpt-3.5-turbo"); }); diff --git a/ui/litellm-dashboard/src/components/provider_info_helpers.tsx b/ui/litellm-dashboard/src/components/provider_info_helpers.tsx index d01a6a34cbe..72ec5990557 100644 --- a/ui/litellm-dashboard/src/components/provider_info_helpers.tsx +++ b/ui/litellm-dashboard/src/components/provider_info_helpers.tsx @@ -84,6 +84,7 @@ export enum Providers { BASETEN = "Baseten", BYTEZ = "Bytez", Cerebras = "Cerebras", + CHATGPT = "ChatGPT Subscription", CLARIFAI = "Clarifai", CLOUDFLARE = "Cloudflare", CODESTRAL = "Codestral", @@ -198,6 +199,7 @@ export const provider_map: Record = { BedrockMantle: "bedrock_mantle", BYTEZ: "bytez", Cerebras: "cerebras", + CHATGPT: "chatgpt", CLARIFAI: "clarifai", CLOUDFLARE: "cloudflare", CODESTRAL: "codestral", @@ -314,6 +316,7 @@ export const providerLogoMap: Partial> = { [Providers.BedrockMantle]: bedrockLogo.src, [Providers.SageMaker]: bedrockLogo.src, [Providers.Cerebras]: cerebrasLogo.src, + [Providers.CHATGPT]: openaiSmallLogo.src, [Providers.CLOUDFLARE]: cloudflareLogo.src, [Providers.CODESTRAL]: mistralLogo.src, [Providers.Cohere]: cohereLogo.src, @@ -425,6 +428,7 @@ const providerPlaceholderMap: Partial> = { [Providers.Azure]: "my-deployment", [Providers.Azure_AI_Studio]: "azure_ai/command-r-plus", [Providers.Bedrock]: "claude-3-opus", + [Providers.CHATGPT]: "chatgpt/gpt-5.4", [Providers.Cognition]: "cognition/swe-1.7", [Providers.Cursor]: "cursor/claude-4-sonnet", [Providers.DeepInfra]: "deepinfra/",