From c87890bfa459a3401f588560a3e0ab9fea8f13cb Mon Sep 17 00:00:00 2001 From: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Date: Fri, 24 Jul 2026 20:17:30 +0000 Subject: [PATCH] feat(ui): add NanoGPT to the Add Model provider dropdown --- .../provider_create_fields.json | 28 +++++++++++++++++ .../public_endpoints/test_public_endpoints.py | 30 +++++++++++++++++++ .../components/provider_info_helpers.test.tsx | 11 +++++++ .../src/components/provider_info_helpers.tsx | 2 ++ 4 files changed, 71 insertions(+) diff --git a/litellm/proxy/public_endpoints/provider_create_fields.json b/litellm/proxy/public_endpoints/provider_create_fields.json index fcc6aac1c14..d696b382d64 100644 --- a/litellm/proxy/public_endpoints/provider_create_fields.json +++ b/litellm/proxy/public_endpoints/provider_create_fields.json @@ -1922,6 +1922,34 @@ ], "default_model_placeholder": "gpt-3.5-turbo" }, + { + "provider": "NANO_GPT", + "provider_display_name": "NanoGPT", + "litellm_provider": "nano-gpt", + "credential_fields": [ + { + "key": "api_base", + "label": "API Base", + "placeholder": null, + "tooltip": null, + "required": false, + "field_type": "text", + "options": null, + "default_value": null + }, + { + "key": "api_key", + "label": "API Key", + "placeholder": null, + "tooltip": null, + "required": false, + "field_type": "password", + "options": null, + "default_value": null + } + ], + "default_model_placeholder": "nano-gpt/gpt-4o" + }, { "provider": "NEBIUS", "provider_display_name": "Nebius", 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 8b8b7871cce..f38902ab356 100644 --- a/tests/test_litellm/proxy/public_endpoints/test_public_endpoints.py +++ b/tests/test_litellm/proxy/public_endpoints/test_public_endpoints.py @@ -243,6 +243,36 @@ def test_bedrock_mantle_provider_fields(): assert fields_by_key["api_base"]["field_type"] == "text" +def test_nano_gpt_provider_fields(): + """NanoGPT must be a selectable provider in the Add Model flow. + + The dropdown is driven entirely by /public/providers/fields, so a missing + entry means NanoGPT cannot be added through the UI at all even though the + backend already supports the `nano-gpt/` route (regression guard for + https://github.com/BerriAI/litellm/issues/34499). `provider` must equal the + UI provider_map key so the model dropdown resolves nano-gpt models, and + `litellm_provider` must be the backend slug. + """ + 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() + + nano_gpt = next((p for p in providers if p["provider"] == "NANO_GPT"), None) + assert nano_gpt is not None, "NanoGPT provider entry not found" + + assert nano_gpt["provider_display_name"] == "NanoGPT" + assert nano_gpt["litellm_provider"] == "nano-gpt" + assert nano_gpt["default_model_placeholder"].startswith("nano-gpt/") + + fields_by_key = {f["key"]: f for f in nano_gpt["credential_fields"]} + assert "api_key" in fields_by_key + assert fields_by_key["api_key"]["field_type"] == "password" + + 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 777cdc62987..afc90826af8 100644 --- a/ui/litellm-dashboard/src/components/provider_info_helpers.test.tsx +++ b/ui/litellm-dashboard/src/components/provider_info_helpers.test.tsx @@ -94,6 +94,16 @@ describe("provider_info_helpers", () => { expect(result.displayName).toBe(Providers.ZAI); }); + it("should resolve the nano-gpt provider value to the NanoGPT display name", () => { + // Regression test for https://github.com/BerriAI/litellm/issues/34499 — + // the backend already supports the `nano-gpt/` route and the docs have a + // dedicated page, but the UI dropdown was missing an entry, so + // `getProviderLogoAndName("nano-gpt")` previously returned the raw slug + // as the display name (no mapping). + const result = getProviderLogoAndName("nano-gpt"); + expect(result.displayName).toBe(Providers.NANO_GPT); + }); + it("should return provider value as display name when no mapping exists", () => { const unknownProvider = "unknown_provider"; const result = getProviderLogoAndName(unknownProvider); @@ -130,6 +140,7 @@ describe("provider_info_helpers", () => { Providers.LEMONADE, Providers.LLAMAFILE, Providers.MARITALK, + Providers.NANO_GPT, Providers.NLP_CLOUD, Providers.NSCALE, Providers.OVHCLOUD, diff --git a/ui/litellm-dashboard/src/components/provider_info_helpers.tsx b/ui/litellm-dashboard/src/components/provider_info_helpers.tsx index fa6b3c79230..6a8b8c30629 100644 --- a/ui/litellm-dashboard/src/components/provider_info_helpers.tsx +++ b/ui/litellm-dashboard/src/components/provider_info_helpers.tsx @@ -125,6 +125,7 @@ export enum Providers { MistralAI = "Mistral AI", MOONSHOT = "Moonshot", MORPH = "Morph", + NANO_GPT = "NanoGPT", NEBIUS = "Nebius", NLP_CLOUD = "Nlp Cloud", NOVITA = "Novita", @@ -233,6 +234,7 @@ export const provider_map: Record = { MistralAI: "mistral", MOONSHOT: "moonshot", MORPH: "morph", + NANO_GPT: "nano-gpt", NEBIUS: "nebius", NLP_CLOUD: "nlp_cloud", NOVITA: "novita",