feat(providers): add OpenZoo as a JSON-configured OpenAI-compatible provider

Registers openzoo (https://api.openzoo.fun/v1) via the openai_like JSON
provider registry, mirroring the scx-ai registration:

- providers.json entry (OPENZOO_API_KEY / OPENZOO_API_BASE, chat completions)
- constants.py: endpoint URL + openai_compatible_providers slug
- LlmProviders.OPENZOO enum entry
- model prices for z-ai/glm-5.3-flash, qwen/qwen3.7-flash and
  nvidia/nemotron-3.5-lightning (root + backup kept identical)
- provider_endpoints_support (root + backup) and provider_create_fields
- dashboard logo and provider_info_helpers registration
- mocked test suite (no network calls)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
staccDOTsol 2026-09-02 11:43:47 -04:00 • committed by Cursor Agent
parent 6b642f3648
commit 1200f0f49e
No known key found for this signature in database
12 changed files with 377 additions and 0 deletions

View file

@ -938,6 +938,7 @@ openai_compatible_endpoints: Final[list] = [
"https://api.cognition.ai/v1",
"https://api.scx.ai/v1",
"https://gigachat.devices.sberbank.ru/api/v1",
"https://api.openzoo.fun/v1",
]
@ -1010,6 +1011,7 @@ openai_compatible_providers: Final[list] = [
"meta", # Meta Model API (Muse Spark) - JSON-configured provider
"cognition",
"scx-ai",
"openzoo",
]
OPENAI_AUDIO_TRANSCRIPTION_PROVIDERS: Final = frozenset({"openai"} | frozenset(openai_compatible_providers))

View file

@ -200,5 +200,14 @@
"temperature_max": 1.99
},
"supported_endpoints": ["/v1/chat/completions"]
},
"openzoo": {
"base_url": "https://api.openzoo.fun/v1",
"api_key_env": "OPENZOO_API_KEY",
"api_base_env": "OPENZOO_API_BASE",
"param_mappings": {
"max_completion_tokens": "max_tokens"
},
"supported_endpoints": ["/v1/chat/completions"]
}
}

View file

@ -41983,6 +41983,48 @@
"max_tokens": 128000,
"mode": "chat"
},
"openzoo/nvidia/nemotron-3.5-lightning": {
"input_cost_per_token": 8e-08,
"litellm_provider": "openzoo",
"max_input_tokens": 262144,
"max_output_tokens": 131072,
"max_tokens": 131072,
"mode": "chat",
"output_cost_per_token": 2e-07,
"source": "https://openzoo.fun",
"supports_function_calling": true,
"supports_reasoning": true,
"supports_tool_choice": true,
"supports_vision": false
},
"openzoo/qwen/qwen3.7-flash": {
"input_cost_per_token": 3e-08,
"litellm_provider": "openzoo",
"max_input_tokens": 1000000,
"max_output_tokens": 65536,
"max_tokens": 65536,
"mode": "chat",
"output_cost_per_token": 1.3e-07,
"source": "https://openzoo.fun",
"supports_function_calling": true,
"supports_reasoning": true,
"supports_tool_choice": true,
"supports_vision": false
},
"openzoo/z-ai/glm-5.3-flash": {
"input_cost_per_token": 7.5e-08,
"litellm_provider": "openzoo",
"max_input_tokens": 1310720,
"max_output_tokens": 131072,
"max_tokens": 131072,
"mode": "chat",
"output_cost_per_token": 2.5e-07,
"source": "https://openzoo.fun",
"supports_function_calling": true,
"supports_reasoning": true,
"supports_tool_choice": true,
"supports_vision": false
},
"ovhcloud/DeepSeek-R1-Distill-Llama-70B": {
"input_cost_per_token": 6.7e-07,
"litellm_provider": "ovhcloud",

View file

@ -1802,6 +1802,23 @@
"interactions": true
}
},
"openzoo": {
"display_name": "OpenZoo (`openzoo`)",
"url": "https://docs.litellm.ai/docs/providers/openzoo",
"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
}
},
"ovhcloud": {
"display_name": "OVHCloud AI Endpoints (`ovhcloud`)",
"url": "https://docs.litellm.ai/docs/providers/ovhcloud",

View file

@ -3013,6 +3013,34 @@
],
"default_model_placeholder": "scx-ai/GLM-5.2"
},
{
"provider": "OpenZoo",
"provider_display_name": "OpenZoo",
"litellm_provider": "openzoo",
"credential_fields": [
{
"key": "api_base",
"label": "API Base",
"placeholder": "https://api.openzoo.fun/v1",
"tooltip": null,
"required": false,
"field_type": "text",
"options": null,
"default_value": null
},
{
"key": "api_key",
"label": "API Key",
"placeholder": "sk-openzoo",
"tooltip": "OpenZoo does not require signup. Any key value works; usage is billed per call.",
"required": true,
"field_type": "password",
"options": null,
"default_value": null
}
],
"default_model_placeholder": "openzoo/z-ai/glm-5.3-flash"
},
{
"provider": "Snowflake",
"provider_display_name": "Snowflake",

View file

@ -4296,6 +4296,7 @@ class LlmProviders(str, Enum):
PINSTRIPES = "pinstripes"
COGNITION = "cognition"
SCX_AI = "scx-ai"
OPENZOO = "openzoo"
DARKBLOOM = "darkbloom"
META = "meta"
LITELLM_AGENT = "litellm_agent"

View file

@ -41983,6 +41983,48 @@
"max_tokens": 128000,
"mode": "chat"
},
"openzoo/nvidia/nemotron-3.5-lightning": {
"input_cost_per_token": 8e-08,
"litellm_provider": "openzoo",
"max_input_tokens": 262144,
"max_output_tokens": 131072,
"max_tokens": 131072,
"mode": "chat",
"output_cost_per_token": 2e-07,
"source": "https://openzoo.fun",
"supports_function_calling": true,
"supports_reasoning": true,
"supports_tool_choice": true,
"supports_vision": false
},
"openzoo/qwen/qwen3.7-flash": {
"input_cost_per_token": 3e-08,
"litellm_provider": "openzoo",
"max_input_tokens": 1000000,
"max_output_tokens": 65536,
"max_tokens": 65536,
"mode": "chat",
"output_cost_per_token": 1.3e-07,
"source": "https://openzoo.fun",
"supports_function_calling": true,
"supports_reasoning": true,
"supports_tool_choice": true,
"supports_vision": false
},
"openzoo/z-ai/glm-5.3-flash": {
"input_cost_per_token": 7.5e-08,
"litellm_provider": "openzoo",
"max_input_tokens": 1310720,
"max_output_tokens": 131072,
"max_tokens": 131072,
"mode": "chat",
"output_cost_per_token": 2.5e-07,
"source": "https://openzoo.fun",
"supports_function_calling": true,
"supports_reasoning": true,
"supports_tool_choice": true,
"supports_vision": false
},
"ovhcloud/DeepSeek-R1-Distill-Llama-70B": {
"input_cost_per_token": 6.7e-07,
"litellm_provider": "ovhcloud",

View file

@ -1968,6 +1968,23 @@
"interactions": true
}
},
"openzoo": {
"display_name": "OpenZoo (`openzoo`)",
"url": "https://docs.litellm.ai/docs/providers/openzoo",
"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
}
},
"ovhcloud": {
"display_name": "OVHCloud AI Endpoints (`ovhcloud`)",
"url": "https://docs.litellm.ai/docs/providers/ovhcloud",

View file

@ -0,0 +1,195 @@
"""
Tests for OpenZoo provider configuration and integration.
"""
import litellm
class TestOpenZooProviderConfig:
def test_openzoo_in_provider_list(self):
from litellm import LlmProviders
assert hasattr(LlmProviders, "OPENZOO")
assert LlmProviders.OPENZOO.value == "openzoo"
assert "openzoo" in litellm.provider_list
def test_openzoo_json_config_exists(self):
from litellm.llms.openai_like.json_loader import JSONProviderRegistry
assert JSONProviderRegistry.exists("openzoo")
openzoo = JSONProviderRegistry.get("openzoo")
assert openzoo is not None
assert openzoo.base_url == "https://api.openzoo.fun/v1"
assert openzoo.api_key_env == "OPENZOO_API_KEY"
assert openzoo.param_mappings.get("max_completion_tokens") == "max_tokens"
def test_openzoo_in_openai_compatible_providers(self):
from litellm.constants import openai_compatible_providers
assert "openzoo" in openai_compatible_providers
def test_openzoo_provider_resolution(self):
from litellm.litellm_core_utils.get_llm_provider_logic import get_llm_provider
model, provider, api_key, api_base = get_llm_provider(
model="openzoo/z-ai/glm-5.3-flash",
custom_llm_provider=None,
api_base=None,
api_key=None,
)
assert model == "z-ai/glm-5.3-flash"
assert provider == "openzoo"
assert api_base == "https://api.openzoo.fun/v1"
def test_openzoo_api_base_override(self):
from litellm.litellm_core_utils.get_llm_provider_logic import get_llm_provider
model, provider, api_key, api_base = get_llm_provider(
model="openzoo/z-ai/glm-5.3-flash",
custom_llm_provider=None,
api_base="http://localhost:8402/v1",
api_key="sk-openzoo",
)
assert provider == "openzoo"
assert api_base == "http://localhost:8402/v1"
assert api_key == "sk-openzoo"
def test_openzoo_url_autodetection(self):
from litellm.litellm_core_utils.get_llm_provider_logic import get_llm_provider
model, provider, api_key, api_base = get_llm_provider(
model="z-ai/glm-5.3-flash",
custom_llm_provider=None,
api_base="https://api.openzoo.fun/v1",
api_key=None,
)
assert provider == "openzoo"
assert api_base == "https://api.openzoo.fun/v1"
def test_openzoo_temperature_passthrough(self):
from litellm.llms.openai_like.dynamic_config import create_config_class
from litellm.llms.openai_like.json_loader import JSONProviderRegistry
provider = JSONProviderRegistry.get("openzoo")
assert provider is not None
config = create_config_class(provider)()
optional_params = config.map_openai_params(
non_default_params={"temperature": 0.4},
optional_params={},
model="z-ai/glm-5.3-flash",
drop_params=False,
)
assert optional_params["temperature"] == 0.4
def test_openzoo_max_completion_tokens_mapped(self):
from litellm.llms.openai_like.dynamic_config import create_config_class
from litellm.llms.openai_like.json_loader import JSONProviderRegistry
provider = JSONProviderRegistry.get("openzoo")
assert provider is not None
config = create_config_class(provider)()
optional_params = config.map_openai_params(
non_default_params={"max_completion_tokens": 256},
optional_params={},
model="z-ai/glm-5.3-flash",
drop_params=False,
)
assert optional_params["max_tokens"] == 256
assert "max_completion_tokens" not in optional_params
def test_openzoo_router_config(self):
from litellm import Router
router = Router(
model_list=[
{
"model_name": "openzoo-chat",
"litellm_params": {
"model": "openzoo/z-ai/glm-5.3-flash",
"api_key": "sk-openzoo",
},
}
]
)
assert len(router.model_list) == 1
assert router.model_list[0]["model_name"] == "openzoo-chat"
class TestOpenZooModelMetadata:
OPENZOO_MODELS = (
"openzoo/z-ai/glm-5.3-flash",
"openzoo/qwen/qwen3.7-flash",
"openzoo/nvidia/nemotron-3.5-lightning",
)
MIN_INPUT_TOKENS = {
"openzoo/z-ai/glm-5.3-flash": 1310720,
"openzoo/qwen/qwen3.7-flash": 1000000,
"openzoo/nvidia/nemotron-3.5-lightning": 262144,
}
@staticmethod
def _load(path_parts):
import json
from pathlib import Path
json_path = Path(__file__).parents[4].joinpath(*path_parts)
with open(json_path) as f:
return json.load(f)
def test_openzoo_models_registered_with_correct_metadata(self):
model_cost = self._load(("model_prices_and_context_window.json",))
for model in self.OPENZOO_MODELS:
info = model_cost.get(model)
assert info is not None, f"{model} missing from model_prices_and_context_window.json"
assert info["litellm_provider"] == "openzoo"
assert info["mode"] == "chat"
assert info["input_cost_per_token"] > 0
assert info["output_cost_per_token"] > 0
assert info["supports_function_calling"] is True
assert info["supports_tool_choice"] is True
assert info["supports_reasoning"] is True
assert info.get("supports_vision", False) is False
assert info["max_output_tokens"] > 0
assert info["max_tokens"] == info["max_output_tokens"]
assert info["max_input_tokens"] == self.MIN_INPUT_TOKENS[model]
def test_openzoo_models_synced_to_backup(self):
model_cost = self._load(("model_prices_and_context_window.json",))
backup = self._load(("litellm", "model_prices_and_context_window_backup.json"))
for model in self.OPENZOO_MODELS:
assert model in backup, f"{model} missing from backup json"
assert backup[model] == model_cost[model], f"{model} differs between root and backup json"
class TestOpenZooDashboardRegistration:
@staticmethod
def _provider_create_fields():
import json
from pathlib import Path
import litellm
path = Path(litellm.__file__).parent / "proxy" / "public_endpoints" / "provider_create_fields.json"
with open(path) as f:
return json.load(f)
def test_openzoo_is_selectable_in_the_add_model_form(self):
entries = [e for e in self._provider_create_fields() if e["litellm_provider"] == "openzoo"]
assert len(entries) == 1, "openzoo must appear exactly once in provider_create_fields.json"
entry = entries[0]
assert entry["provider"] == "OpenZoo"
assert entry["provider_display_name"] == "OpenZoo"
assert entry["default_model_placeholder"].startswith("openzoo/")
fields = {f["key"]: f for f in entry["credential_fields"]}
assert fields["api_key"]["required"] is True
assert fields["api_key"]["field_type"] == "password"
assert fields["api_base"]["required"] is False

View file

@ -0,0 +1,4 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32">
<rect width="32" height="32" fill="#070707"/>
<text x="16" y="22" text-anchor="middle" font-family="ui-monospace,monospace" font-size="14" fill="#b6ff3b">OZ</text>
</svg>

After

Width:  |  Height:  |  Size: 236 B

View file

@ -73,6 +73,17 @@ describe("provider_info_helpers", () => {
expect(fromEnumKey.logo).toBe(providerLogoMap[Providers.SCX_AI]);
});
it("should map openzoo slug and OpenZoo enum key to the OpenZoo display name and logo", () => {
const fromSlug = getProviderLogoAndName("openzoo");
expect(fromSlug.displayName).toBe(Providers.OpenZoo);
expect(fromSlug.logo).toBe(providerLogoMap[Providers.OpenZoo]);
expect(fromSlug.logo).toBeTruthy();
const fromEnumKey = getProviderLogoAndName("OpenZoo");
expect(fromEnumKey.displayName).toBe(Providers.OpenZoo);
expect(fromEnumKey.logo).toBe(providerLogoMap[Providers.OpenZoo]);
});
it("should map bedrock_mantle slug to Bedrock Mantle display name and logo", () => {
const result = getProviderLogoAndName("bedrock_mantle");
expect(result.displayName).toBe(Providers.BedrockMantle);
@ -227,6 +238,10 @@ describe("provider_info_helpers", () => {
expect(getPlaceholder(Providers.EDENAI)).toBe("edenai/openai/gpt-mini-latest");
});
it("should return an openzoo model placeholder for OpenZoo provider", () => {
expect(getPlaceholder(Providers.OpenZoo)).toBe("openzoo/z-ai/glm-5.3-flash");
});
it("should return claude-3-opus placeholder for Anthropic provider", () => {
expect(getPlaceholder(Providers.Anthropic)).toBe("claude-3-opus");
});

View file

@ -44,6 +44,7 @@ import nvidiaTritonLogo from "../../public/assets/logos/nvidia_triton.png";
import ollamaLogo from "../../public/assets/logos/ollama.svg";
import openaiSmallLogo from "../../public/assets/logos/openai_small.svg";
import openrouterLogo from "../../public/assets/logos/openrouter.svg";
import openzooLogo from "../../public/assets/logos/openzoo.svg";
import oracleLogo from "../../public/assets/logos/oracle.svg";
import perplexityAiLogo from "../../public/assets/logos/perplexity-ai.svg";
import qwenLogo from "../../public/assets/logos/qwen.png";
@ -148,6 +149,7 @@ export enum Providers {
OpenAI_Text = "OpenAI Text Completion",
OpenAI_Text_Compatible = "OpenAI-Compatible Completions (legacy /v1/completions)",
Openrouter = "Openrouter",
OpenZoo = "OpenZoo",
Oracle = "Oracle Cloud Infrastructure (OCI)",
OVHCLOUD = "Ovhcloud",
Perplexity = "Perplexity",
@ -265,6 +267,7 @@ export const provider_map: Record<string, string> = {
OpenAI_Text: "text-completion-openai",
OpenAI_Text_Compatible: "text-completion-openai",
Openrouter: "openrouter",
OpenZoo: "openzoo",
Oracle: "oci",
OVHCLOUD: "ovhcloud",
Perplexity: "perplexity",
@ -369,6 +372,7 @@ export const providerLogoMap: Partial<Record<Providers, string>> = {
[Providers.OpenAI_Text_Compatible]: openaiSmallLogo.src,
[Providers.OpenAI_Compatible]: openaiSmallLogo.src,
[Providers.Openrouter]: openrouterLogo.src,
[Providers.OpenZoo]: openzooLogo.src,
[Providers.Oracle]: oracleLogo.src,
[Providers.Perplexity]: perplexityAiLogo.src,
[Providers.Qwen_AI_Platform]: qwenLogo.src,
@ -445,6 +449,7 @@ const providerPlaceholderMap: Partial<Record<Providers, string>> = {
[Providers.Google_AI_Studio]: "gemini-pro",
[Providers.JinaAI]: "jina_ai/",
[Providers.NVIDIA_RIVA]: "nvidia_riva/nvidia/parakeet-ctc-1_1b-asr",
[Providers.OpenZoo]: "openzoo/z-ai/glm-5.3-flash",
[Providers.Oracle]: "oci/xai.grok-4",
[Providers.RunwayML]: "runwayml/gen4_turbo",
[Providers.SageMaker]: "sagemaker/jumpstart-dft-meta-textgeneration-llama-2-7b",