From 8d4c7dda524d7e051389a0163af23090f0c50b82 Mon Sep 17 00:00:00 2001 From: Azard Date: Sun, 24 May 2026 10:30:02 +0800 Subject: [PATCH] Add Skypool OpenAI-compatible provider --- litellm/constants.py | 3 + litellm/llms/openai_like/providers.json | 8 ++ litellm/types/utils.py | 1 + provider_endpoints_support.json | 16 ++++ .../llms/openai_like/test_skypool_provider.py | 87 ++++++++++++++++++ .../public/assets/logos/skypool.png | Bin 0 -> 41147 bytes .../components/provider_info_helpers.test.tsx | 10 ++ .../src/components/provider_info_helpers.tsx | 5 + 8 files changed, 130 insertions(+) create mode 100644 tests/litellm/llms/openai_like/test_skypool_provider.py create mode 100644 ui/litellm-dashboard/public/assets/logos/skypool.png diff --git a/litellm/constants.py b/litellm/constants.py index fb765c0226c..d1f0013d474 100644 --- a/litellm/constants.py +++ b/litellm/constants.py @@ -615,6 +615,7 @@ LITELLM_CHAT_PROVIDERS = [ "dashscope", "moonshot", "publicai", + "skypool", "v0", "heroku", "oci", @@ -775,6 +776,7 @@ openai_compatible_endpoints: List = [ "https://nano-gpt.com/api/v1", "https://api.poe.com/v1", "https://llm.chutes.ai/v1/", + "https://a.skypool.xyz/v1", "https://api.v0.dev/v1", "https://api.morphllm.com/v1", "https://api.lambda.ai/v1", @@ -824,6 +826,7 @@ openai_compatible_providers: List = [ "nano-gpt", # Nano-GPT - JSON-configured provider "poe", # Poe - JSON-configured provider "chutes", # Chutes - JSON-configured provider + "skypool", # Skypool - JSON-configured provider "featherless_ai", "nscale", "nebius", diff --git a/litellm/llms/openai_like/providers.json b/litellm/llms/openai_like/providers.json index b5e5aa4ea28..910e8040d3c 100644 --- a/litellm/llms/openai_like/providers.json +++ b/litellm/llms/openai_like/providers.json @@ -114,5 +114,13 @@ "param_mappings": { "max_completion_tokens": "max_tokens" } + }, + "skypool": { + "base_url": "https://a.skypool.xyz/v1", + "api_key_env": "SKYPOOL_API_KEY", + "api_base_env": "SKYPOOL_API_BASE", + "param_mappings": { + "max_completion_tokens": "max_tokens" + } } } diff --git a/litellm/types/utils.py b/litellm/types/utils.py index 282baff07fe..cfb49265c6f 100644 --- a/litellm/types/utils.py +++ b/litellm/types/utils.py @@ -3354,6 +3354,7 @@ class LlmProviders(str, Enum): NANOGPT = "nano-gpt" POE = "poe" CHUTES = "chutes" + SKYPOOL = "skypool" XIAOMI_MIMO = "xiaomi_mimo" LITELLM_AGENT = "litellm_agent" CURSOR = "cursor" diff --git a/provider_endpoints_support.json b/provider_endpoints_support.json index 388752b032e..d31a8310d18 100644 --- a/provider_endpoints_support.json +++ b/provider_endpoints_support.json @@ -2063,6 +2063,22 @@ "interactions": true } }, + "skypool": { + "display_name": "Skypool (`skypool`)", + "endpoints": { + "chat_completions": true, + "messages": false, + "responses": false, + "embeddings": false, + "image_generations": false, + "audio_transcriptions": false, + "audio_speech": false, + "moderations": false, + "batches": false, + "rerank": false, + "a2a": false + } + }, "synthetic": { "display_name": "Synthetic (`synthetic`)", "endpoints": { diff --git a/tests/litellm/llms/openai_like/test_skypool_provider.py b/tests/litellm/llms/openai_like/test_skypool_provider.py new file mode 100644 index 00000000000..9987650057b --- /dev/null +++ b/tests/litellm/llms/openai_like/test_skypool_provider.py @@ -0,0 +1,87 @@ +""" +Unit tests for the Skypool OpenAI-compatible provider. +""" + +import os +import sys + +sys.path.insert( + 0, os.path.abspath(os.path.join(os.path.dirname(__file__), "../../../..")) +) + +from litellm.llms.openai_like.dynamic_config import create_config_class +from litellm.llms.openai_like.json_loader import JSONProviderRegistry + +SKYPOOL_BASE_URL = "https://a.skypool.xyz/v1" + + +def _get_config(): + provider = JSONProviderRegistry.get("skypool") + assert provider is not None + config_class = create_config_class(provider) + return config_class() + + +def test_skypool_provider_registered(): + provider = JSONProviderRegistry.get("skypool") + assert provider is not None + assert provider.base_url == SKYPOOL_BASE_URL + assert provider.api_key_env == "SKYPOOL_API_KEY" + assert provider.api_base_env == "SKYPOOL_API_BASE" + assert provider.param_mappings["max_completion_tokens"] == "max_tokens" + + +def test_skypool_resolves_env_api_key(monkeypatch): + config = _get_config() + monkeypatch.setenv("SKYPOOL_API_KEY", "test-key") + api_base, api_key = config._get_openai_compatible_provider_info(None, None) + assert api_base == SKYPOOL_BASE_URL + assert api_key == "test-key" + + +def test_skypool_resolves_env_api_base(monkeypatch): + config = _get_config() + monkeypatch.setenv("SKYPOOL_API_BASE", "https://example.com/v1") + api_base, api_key = config._get_openai_compatible_provider_info(None, "test-key") + assert api_base == "https://example.com/v1" + assert api_key == "test-key" + + +def test_skypool_complete_url_appends_endpoint(): + config = _get_config() + url = config.get_complete_url( + api_base=SKYPOOL_BASE_URL, + api_key="test-key", + model="skypool/gemma4:26b", + optional_params={}, + litellm_params={}, + stream=False, + ) + assert url == f"{SKYPOOL_BASE_URL}/chat/completions" + + +def test_skypool_provider_resolution(): + from litellm.litellm_core_utils.get_llm_provider_logic import get_llm_provider + + model, provider, api_key, api_base = get_llm_provider( + model="skypool/gemma4:26b", + custom_llm_provider=None, + api_base=None, + api_key=None, + ) + + assert model == "gemma4:26b" + assert provider == "skypool" + assert api_base == SKYPOOL_BASE_URL + + +def test_skypool_provider_config_manager(): + from litellm import LlmProviders + from litellm.utils import ProviderConfigManager + + config = ProviderConfigManager.get_provider_chat_config( + model="gemma4:26b", provider=LlmProviders.SKYPOOL + ) + + assert config is not None + assert config.custom_llm_provider == "skypool" diff --git a/ui/litellm-dashboard/public/assets/logos/skypool.png b/ui/litellm-dashboard/public/assets/logos/skypool.png new file mode 100644 index 0000000000000000000000000000000000000000..17b5f848a0dc30794abf958ea0c846fd621d35ff GIT binary patch literal 41147 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 { expect(result.logo).toBe(providerLogoMap[Providers.Groq]); }); + it("should map skypool provider value to Skypool display name and logo", () => { + const result = getProviderLogoAndName("skypool"); + expect(result.displayName).toBe(Providers.Skypool); + expect(result.logo).toBe(providerLogoMap[Providers.Skypool]); + }); + it("should handle provider values case-insensitively", () => { const result = getProviderLogoAndName("OPENAI"); expect(result.displayName).toBe(Providers.OpenAI); @@ -138,6 +144,10 @@ describe("provider_info_helpers", () => { expect(getPlaceholder(Providers.Snowflake)).toBe("snowflake/mistral-7b"); }); + it("should return skypool placeholder for Skypool provider", () => { + expect(getPlaceholder(Providers.Skypool)).toBe("skypool/gemma4:26b"); + }); + it("should return voyage placeholder for Voyage provider", () => { expect(getPlaceholder(Providers.Voyage)).toBe("voyage/"); }); diff --git a/ui/litellm-dashboard/src/components/provider_info_helpers.tsx b/ui/litellm-dashboard/src/components/provider_info_helpers.tsx index 105951114ca..c9ed1e454e0 100644 --- a/ui/litellm-dashboard/src/components/provider_info_helpers.tsx +++ b/ui/litellm-dashboard/src/components/provider_info_helpers.tsx @@ -87,6 +87,7 @@ export enum Providers { Sambanova = "Sambanova", SAP = "SAP Generative AI Hub", Snowflake = "Snowflake", + Skypool = "Skypool", TEXT_COMPLETION_CODESTRAL = "Text-Completion-Codestral", TogetherAI = "TogetherAI", TOPAZ = "Topaz", @@ -195,6 +196,7 @@ export const provider_map: Record = { Sambanova: "sambanova", SAP: "sap", Snowflake: "snowflake", + Skypool: "skypool", TEXT_COMPLETION_CODESTRAL: "text-completion-codestral", TogetherAI: "together_ai", TOPAZ: "topaz", @@ -286,6 +288,7 @@ export const providerLogoMap: Record = { [Providers.Sambanova]: `${asset_logos_folder}sambanova.svg`, [Providers.SAP]: `${asset_logos_folder}sap.png`, [Providers.Snowflake]: `${asset_logos_folder}snowflake.svg`, + [Providers.Skypool]: `${asset_logos_folder}skypool.png`, [Providers.TEXT_COMPLETION_CODESTRAL]: `${asset_logos_folder}mistral.svg`, [Providers.TogetherAI]: `${asset_logos_folder}togetherai.svg`, [Providers.TOPAZ]: `${asset_logos_folder}topaz.svg`, @@ -352,6 +355,8 @@ export const getPlaceholder = (selectedProvider: string): string => { return "oci/xai.grok-4"; } else if (selectedProvider == Providers.Snowflake) { return "snowflake/mistral-7b"; + } else if (selectedProvider == Providers.Skypool) { + return "skypool/gemma4:26b"; } else if (selectedProvider == Providers.Voyage) { return "voyage/"; } else if (selectedProvider == Providers.JinaAI) {