diff --git a/litellm/constants.py b/litellm/constants.py
index 18fc6aa7e74..b00b220a252 100644
--- a/litellm/constants.py
+++ b/litellm/constants.py
@@ -965,6 +965,7 @@ openai_compatible_endpoints: Final[list] = [
"https://api.scx.ai/v1",
"https://api.prisminference.com/v1",
"https://gigachat.devices.sberbank.ru/api/v1",
+ "https://api.quicksilverpro.io/v1",
]
@@ -1040,6 +1041,7 @@ openai_compatible_providers: Final[list] = [
"scx-ai",
"prism",
"sail",
+ "quicksilverpro",
]
OPENAI_AUDIO_TRANSCRIPTION_PROVIDERS: Final = frozenset({"openai"} | frozenset(openai_compatible_providers))
diff --git a/litellm/llms/openai_like/providers.json b/litellm/llms/openai_like/providers.json
index 61ff4be3a46..da122375b6b 100644
--- a/litellm/llms/openai_like/providers.json
+++ b/litellm/llms/openai_like/providers.json
@@ -218,5 +218,14 @@
"api_key_env": "SAIL_API_KEY",
"api_base_env": "SAIL_API_BASE",
"supported_endpoints": ["/v1/chat/completions", "/v1/responses", "/v1/messages"]
+ },
+ "quicksilverpro": {
+ "base_url": "https://api.quicksilverpro.io/v1",
+ "api_key_env": "QUICKSILVERPRO_API_KEY",
+ "api_base_env": "QUICKSILVERPRO_API_BASE",
+ "param_mappings": {
+ "max_completion_tokens": "max_tokens"
+ },
+ "supported_endpoints": ["/v1/chat/completions", "/v1/responses", "/v1/messages"]
}
}
diff --git a/litellm/model_prices_and_context_window_backup.json b/litellm/model_prices_and_context_window_backup.json
index 12e4760ed3a..ad745aeac10 100644
--- a/litellm/model_prices_and_context_window_backup.json
+++ b/litellm/model_prices_and_context_window_backup.json
@@ -17209,6 +17209,144 @@
"/v1/images/generations"
]
},
+ "quicksilverpro/claude-opus-5-5": {
+ "cache_creation_input_token_cost": 2e-06,
+ "cache_read_input_token_cost": 8e-08,
+ "input_cost_per_token": 1.6e-06,
+ "litellm_provider": "quicksilverpro",
+ "max_input_tokens": 1000000,
+ "max_output_tokens": 128000,
+ "max_tokens": 128000,
+ "mode": "chat",
+ "output_cost_per_token": 8e-06,
+ "source": "https://quicksilverpro.io/pricing.json",
+ "supports_function_calling": true,
+ "supports_prompt_caching": true,
+ "supports_reasoning": true,
+ "supports_response_schema": false,
+ "supports_tool_choice": true,
+ "supports_vision": true
+ },
+ "quicksilverpro/claude-sonnet-5-5": {
+ "cache_creation_input_token_cost": 1.25e-06,
+ "cache_read_input_token_cost": 1e-07,
+ "input_cost_per_token": 1e-06,
+ "litellm_provider": "quicksilverpro",
+ "max_input_tokens": 1000000,
+ "max_output_tokens": 128000,
+ "max_tokens": 128000,
+ "mode": "chat",
+ "output_cost_per_token": 5e-06,
+ "source": "https://quicksilverpro.io/pricing.json",
+ "supports_function_calling": true,
+ "supports_prompt_caching": true,
+ "supports_reasoning": true,
+ "supports_response_schema": false,
+ "supports_tool_choice": true,
+ "supports_vision": true
+ },
+ "quicksilverpro/deepseek-v4.1-flash": {
+ "cache_read_input_token_cost": 1.25e-08,
+ "input_cost_per_token": 1.25e-07,
+ "litellm_provider": "quicksilverpro",
+ "max_input_tokens": 1048576,
+ "max_tokens": 1048576,
+ "mode": "chat",
+ "output_cost_per_token": 5.5e-07,
+ "source": "https://quicksilverpro.io/pricing.json",
+ "supports_function_calling": true,
+ "supports_prompt_caching": true,
+ "supports_reasoning": true,
+ "supports_response_schema": true,
+ "supports_tool_choice": true,
+ "supports_vision": false
+ },
+ "quicksilverpro/gemini-3.8-flash": {
+ "cache_read_input_token_cost": 6.375e-08,
+ "input_cost_per_token": 6.375e-07,
+ "litellm_provider": "quicksilverpro",
+ "max_input_tokens": 1048576,
+ "max_output_tokens": 65536,
+ "max_tokens": 65536,
+ "mode": "chat",
+ "output_cost_per_token": 3.1875e-06,
+ "source": "https://quicksilverpro.io/pricing.json",
+ "supports_function_calling": true,
+ "supports_prompt_caching": true,
+ "supports_reasoning": true,
+ "supports_response_schema": true,
+ "supports_tool_choice": true,
+ "supports_vision": true
+ },
+ "quicksilverpro/glm-5.3-flash": {
+ "cache_read_input_token_cost": 1.2e-08,
+ "input_cost_per_token": 6e-08,
+ "litellm_provider": "quicksilverpro",
+ "max_input_tokens": 1048576,
+ "max_output_tokens": 131072,
+ "max_tokens": 131072,
+ "mode": "chat",
+ "output_cost_per_token": 2e-07,
+ "source": "https://quicksilverpro.io/pricing.json",
+ "supports_function_calling": true,
+ "supports_prompt_caching": true,
+ "supports_reasoning": true,
+ "supports_response_schema": false,
+ "supports_tool_choice": true,
+ "supports_vision": false
+ },
+ "quicksilverpro/gpt-6.1-sol": {
+ "cache_creation_input_token_cost": 2.5e-06,
+ "cache_read_input_token_cost": 1e-07,
+ "input_cost_per_token": 2e-06,
+ "litellm_provider": "quicksilverpro",
+ "max_input_tokens": 1048576,
+ "max_output_tokens": 128000,
+ "max_tokens": 128000,
+ "mode": "chat",
+ "output_cost_per_token": 1e-05,
+ "source": "https://quicksilverpro.io/pricing.json",
+ "supports_function_calling": true,
+ "supports_prompt_caching": true,
+ "supports_reasoning": true,
+ "supports_response_schema": true,
+ "supports_tool_choice": true,
+ "supports_vision": true
+ },
+ "quicksilverpro/mimo-v2.6-pro": {
+ "cache_read_input_token_cost": 2.88e-09,
+ "input_cost_per_token": 3.48e-07,
+ "litellm_provider": "quicksilverpro",
+ "max_input_tokens": 1048576,
+ "max_tokens": 1048576,
+ "mode": "chat",
+ "output_cost_per_token": 6.96e-07,
+ "source": "https://quicksilverpro.io/pricing.json",
+ "supports_function_calling": true,
+ "supports_prompt_caching": true,
+ "supports_reasoning": true,
+ "supports_response_schema": true,
+ "supports_tool_choice": true,
+ "supports_vision": true
+ },
+ "quicksilverpro/qwen3.8-27b": {
+ "cache_creation_input_token_cost": 4.25e-07,
+ "cache_read_input_token_cost": 6.8e-08,
+ "input_cost_per_token": 3.4e-07,
+ "litellm_provider": "quicksilverpro",
+ "max_input_tokens": 1000000,
+ "max_output_tokens": 131072,
+ "max_tokens": 131072,
+ "mode": "chat",
+ "output_cost_per_token": 2.04e-06,
+ "source": "https://quicksilverpro.io/pricing.json",
+ "supports_function_calling": true,
+ "supports_prompt_caching": true,
+ "supports_reasoning": false,
+ "supports_response_schema": false,
+ "supports_tool_choice": true,
+ "supports_vision": false
+ },
"qwencloud/deepseek-v4-flash": {
"cache_read_input_token_cost": 4e-08,
"input_cost_per_token": 2e-07,
diff --git a/litellm/provider_endpoints_support_backup.json b/litellm/provider_endpoints_support_backup.json
index c9635587eeb..af330a7b3a0 100644
--- a/litellm/provider_endpoints_support_backup.json
+++ b/litellm/provider_endpoints_support_backup.json
@@ -1926,6 +1926,23 @@
"interactions": true
}
},
+ "quicksilverpro": {
+ "display_name": "QuickSilver Pro (`quicksilverpro`)",
+ "url": "https://quicksilverpro.io/docs",
+ "endpoints": {
+ "chat_completions": true,
+ "messages": true,
+ "responses": true,
+ "embeddings": false,
+ "image_generations": false,
+ "audio_transcriptions": false,
+ "audio_speech": false,
+ "moderations": false,
+ "batches": false,
+ "rerank": false,
+ "a2a": false
+ }
+ },
"darkbloom": {
"display_name": "Darkbloom (`darkbloom`)",
"url": "https://docs.litellm.ai/docs/providers/darkbloom",
diff --git a/litellm/proxy/_experimental/out/assets/logos/quicksilverpro.svg b/litellm/proxy/_experimental/out/assets/logos/quicksilverpro.svg
new file mode 100644
index 00000000000..ce98c22bcd3
--- /dev/null
+++ b/litellm/proxy/_experimental/out/assets/logos/quicksilverpro.svg
@@ -0,0 +1,14 @@
+
\ No newline at end of file
diff --git a/litellm/proxy/public_endpoints/provider_create_fields.json b/litellm/proxy/public_endpoints/provider_create_fields.json
index 6e96d6ad0ec..e580598bf65 100644
--- a/litellm/proxy/public_endpoints/provider_create_fields.json
+++ b/litellm/proxy/public_endpoints/provider_create_fields.json
@@ -2883,6 +2883,34 @@
],
"default_model_placeholder": "gpt-3.5-turbo"
},
+ {
+ "provider": "QUICKSILVERPRO",
+ "provider_display_name": "QuickSilver Pro",
+ "litellm_provider": "quicksilverpro",
+ "credential_fields": [
+ {
+ "key": "api_base",
+ "label": "API Base",
+ "placeholder": "https://api.quicksilverpro.io/v1",
+ "tooltip": null,
+ "required": false,
+ "field_type": "text",
+ "options": null,
+ "default_value": null
+ },
+ {
+ "key": "api_key",
+ "label": "API Key",
+ "placeholder": null,
+ "tooltip": null,
+ "required": true,
+ "field_type": "password",
+ "options": null,
+ "default_value": null
+ }
+ ],
+ "default_model_placeholder": "quicksilverpro/claude-sonnet-5-5"
+ },
{
"provider": "PRISM",
"provider_display_name": "Prism",
diff --git a/litellm/types/utils.py b/litellm/types/utils.py
index 8c10b9e3497..28e5b6afa2a 100644
--- a/litellm/types/utils.py
+++ b/litellm/types/utils.py
@@ -4158,6 +4158,7 @@ class LlmProviders(str, Enum):
DARKBLOOM = "darkbloom"
META = "meta"
SAIL = "sail"
+ QUICKSILVERPRO = "quicksilverpro"
LITELLM_AGENT = "litellm_agent"
CURSOR = "cursor"
BEDROCK_MANTLE = "bedrock_mantle"
diff --git a/model_prices_and_context_window.json b/model_prices_and_context_window.json
index 12e4760ed3a..ad745aeac10 100644
--- a/model_prices_and_context_window.json
+++ b/model_prices_and_context_window.json
@@ -17209,6 +17209,144 @@
"/v1/images/generations"
]
},
+ "quicksilverpro/claude-opus-5-5": {
+ "cache_creation_input_token_cost": 2e-06,
+ "cache_read_input_token_cost": 8e-08,
+ "input_cost_per_token": 1.6e-06,
+ "litellm_provider": "quicksilverpro",
+ "max_input_tokens": 1000000,
+ "max_output_tokens": 128000,
+ "max_tokens": 128000,
+ "mode": "chat",
+ "output_cost_per_token": 8e-06,
+ "source": "https://quicksilverpro.io/pricing.json",
+ "supports_function_calling": true,
+ "supports_prompt_caching": true,
+ "supports_reasoning": true,
+ "supports_response_schema": false,
+ "supports_tool_choice": true,
+ "supports_vision": true
+ },
+ "quicksilverpro/claude-sonnet-5-5": {
+ "cache_creation_input_token_cost": 1.25e-06,
+ "cache_read_input_token_cost": 1e-07,
+ "input_cost_per_token": 1e-06,
+ "litellm_provider": "quicksilverpro",
+ "max_input_tokens": 1000000,
+ "max_output_tokens": 128000,
+ "max_tokens": 128000,
+ "mode": "chat",
+ "output_cost_per_token": 5e-06,
+ "source": "https://quicksilverpro.io/pricing.json",
+ "supports_function_calling": true,
+ "supports_prompt_caching": true,
+ "supports_reasoning": true,
+ "supports_response_schema": false,
+ "supports_tool_choice": true,
+ "supports_vision": true
+ },
+ "quicksilverpro/deepseek-v4.1-flash": {
+ "cache_read_input_token_cost": 1.25e-08,
+ "input_cost_per_token": 1.25e-07,
+ "litellm_provider": "quicksilverpro",
+ "max_input_tokens": 1048576,
+ "max_tokens": 1048576,
+ "mode": "chat",
+ "output_cost_per_token": 5.5e-07,
+ "source": "https://quicksilverpro.io/pricing.json",
+ "supports_function_calling": true,
+ "supports_prompt_caching": true,
+ "supports_reasoning": true,
+ "supports_response_schema": true,
+ "supports_tool_choice": true,
+ "supports_vision": false
+ },
+ "quicksilverpro/gemini-3.8-flash": {
+ "cache_read_input_token_cost": 6.375e-08,
+ "input_cost_per_token": 6.375e-07,
+ "litellm_provider": "quicksilverpro",
+ "max_input_tokens": 1048576,
+ "max_output_tokens": 65536,
+ "max_tokens": 65536,
+ "mode": "chat",
+ "output_cost_per_token": 3.1875e-06,
+ "source": "https://quicksilverpro.io/pricing.json",
+ "supports_function_calling": true,
+ "supports_prompt_caching": true,
+ "supports_reasoning": true,
+ "supports_response_schema": true,
+ "supports_tool_choice": true,
+ "supports_vision": true
+ },
+ "quicksilverpro/glm-5.3-flash": {
+ "cache_read_input_token_cost": 1.2e-08,
+ "input_cost_per_token": 6e-08,
+ "litellm_provider": "quicksilverpro",
+ "max_input_tokens": 1048576,
+ "max_output_tokens": 131072,
+ "max_tokens": 131072,
+ "mode": "chat",
+ "output_cost_per_token": 2e-07,
+ "source": "https://quicksilverpro.io/pricing.json",
+ "supports_function_calling": true,
+ "supports_prompt_caching": true,
+ "supports_reasoning": true,
+ "supports_response_schema": false,
+ "supports_tool_choice": true,
+ "supports_vision": false
+ },
+ "quicksilverpro/gpt-6.1-sol": {
+ "cache_creation_input_token_cost": 2.5e-06,
+ "cache_read_input_token_cost": 1e-07,
+ "input_cost_per_token": 2e-06,
+ "litellm_provider": "quicksilverpro",
+ "max_input_tokens": 1048576,
+ "max_output_tokens": 128000,
+ "max_tokens": 128000,
+ "mode": "chat",
+ "output_cost_per_token": 1e-05,
+ "source": "https://quicksilverpro.io/pricing.json",
+ "supports_function_calling": true,
+ "supports_prompt_caching": true,
+ "supports_reasoning": true,
+ "supports_response_schema": true,
+ "supports_tool_choice": true,
+ "supports_vision": true
+ },
+ "quicksilverpro/mimo-v2.6-pro": {
+ "cache_read_input_token_cost": 2.88e-09,
+ "input_cost_per_token": 3.48e-07,
+ "litellm_provider": "quicksilverpro",
+ "max_input_tokens": 1048576,
+ "max_tokens": 1048576,
+ "mode": "chat",
+ "output_cost_per_token": 6.96e-07,
+ "source": "https://quicksilverpro.io/pricing.json",
+ "supports_function_calling": true,
+ "supports_prompt_caching": true,
+ "supports_reasoning": true,
+ "supports_response_schema": true,
+ "supports_tool_choice": true,
+ "supports_vision": true
+ },
+ "quicksilverpro/qwen3.8-27b": {
+ "cache_creation_input_token_cost": 4.25e-07,
+ "cache_read_input_token_cost": 6.8e-08,
+ "input_cost_per_token": 3.4e-07,
+ "litellm_provider": "quicksilverpro",
+ "max_input_tokens": 1000000,
+ "max_output_tokens": 131072,
+ "max_tokens": 131072,
+ "mode": "chat",
+ "output_cost_per_token": 2.04e-06,
+ "source": "https://quicksilverpro.io/pricing.json",
+ "supports_function_calling": true,
+ "supports_prompt_caching": true,
+ "supports_reasoning": false,
+ "supports_response_schema": false,
+ "supports_tool_choice": true,
+ "supports_vision": false
+ },
"qwencloud/deepseek-v4-flash": {
"cache_read_input_token_cost": 4e-08,
"input_cost_per_token": 2e-07,
diff --git a/provider_endpoints_support.json b/provider_endpoints_support.json
index d18f8d2e6d1..0ea1a9124d4 100644
--- a/provider_endpoints_support.json
+++ b/provider_endpoints_support.json
@@ -2186,6 +2186,23 @@
"interactions": true
}
},
+ "quicksilverpro": {
+ "display_name": "QuickSilver Pro (`quicksilverpro`)",
+ "url": "https://quicksilverpro.io/docs",
+ "endpoints": {
+ "chat_completions": true,
+ "messages": true,
+ "responses": true,
+ "embeddings": false,
+ "image_generations": false,
+ "audio_transcriptions": false,
+ "audio_speech": false,
+ "moderations": false,
+ "batches": false,
+ "rerank": false,
+ "a2a": false
+ }
+ },
"darkbloom": {
"display_name": "Darkbloom (`darkbloom`)",
"url": "https://docs.litellm.ai/docs/providers/darkbloom",
diff --git a/tests/unit/llms/openai_like/test_quicksilverpro_provider.py b/tests/unit/llms/openai_like/test_quicksilverpro_provider.py
new file mode 100644
index 00000000000..c0387fcd6ae
--- /dev/null
+++ b/tests/unit/llms/openai_like/test_quicksilverpro_provider.py
@@ -0,0 +1,379 @@
+"""
+Tests for the QuickSilver Pro provider configuration and integration.
+
+QuickSilver Pro (`quicksilverpro`) is a JSON-configured OpenAI-compatible
+provider (https://quicksilverpro.io, operated by MachineFi Inc.). Its price /
+context catalog is committed to the model cost map; these tests check
+LiteLLM's own behaviour against the committed entries rather than pinning
+upstream numbers.
+"""
+
+import json
+from pathlib import Path
+from typing import Final
+
+import pytest
+import respx
+
+import litellm
+from litellm.caching.llm_caching_handler import LLMClientCache
+
+QSP_MODELS: Final = tuple(
+ sorted(name for name in litellm.model_cost if name.startswith("quicksilverpro/"))
+)
+
+
+class TestQuickSilverProProviderConfig:
+ def test_quicksilverpro_in_provider_list(self):
+ from litellm import LlmProviders
+
+ assert hasattr(LlmProviders, "QUICKSILVERPRO")
+ assert LlmProviders.QUICKSILVERPRO.value == "quicksilverpro"
+ assert "quicksilverpro" in litellm.provider_list
+
+ def test_quicksilverpro_json_config_exists(self):
+ from litellm.llms.openai_like.json_loader import JSONProviderRegistry
+
+ assert JSONProviderRegistry.exists("quicksilverpro")
+
+ provider = JSONProviderRegistry.get("quicksilverpro")
+ assert provider is not None
+ assert provider.base_url == "https://api.quicksilverpro.io/v1"
+ assert provider.api_key_env == "QUICKSILVERPRO_API_KEY"
+ assert provider.api_base_env == "QUICKSILVERPRO_API_BASE"
+ assert provider.param_mappings.get("max_completion_tokens") == "max_tokens"
+
+ def test_quicksilverpro_supported_endpoints(self):
+ """chat completions, Responses API and Anthropic /v1/messages are
+ declared; image generations have no JSON-provider mechanism and are
+ not."""
+ from litellm.llms.openai_like.json_loader import JSONProviderRegistry
+
+ provider = JSONProviderRegistry.get("quicksilverpro")
+ assert provider is not None
+ assert provider.supported_endpoints == [
+ "/v1/chat/completions",
+ "/v1/responses",
+ "/v1/messages",
+ ]
+
+ def test_quicksilverpro_in_openai_compatible_providers(self):
+ from litellm.constants import openai_compatible_providers
+
+ assert "quicksilverpro" in openai_compatible_providers
+
+ def test_quicksilverpro_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="quicksilverpro/claude-sonnet-5-5",
+ custom_llm_provider=None,
+ api_base=None,
+ api_key=None,
+ )
+
+ assert model == "claude-sonnet-5-5"
+ assert provider == "quicksilverpro"
+ assert api_base == "https://api.quicksilverpro.io/v1"
+
+ def test_quicksilverpro_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="quicksilverpro/claude-sonnet-5-5",
+ custom_llm_provider=None,
+ api_base="https://custom.quicksilverpro.example/v1",
+ api_key="sk-test",
+ )
+
+ assert provider == "quicksilverpro"
+ assert api_base == "https://custom.quicksilverpro.example/v1"
+ assert api_key == "sk-test"
+
+ def test_quicksilverpro_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="claude-sonnet-5-5",
+ custom_llm_provider=None,
+ api_base="https://api.quicksilverpro.io/v1",
+ api_key=None,
+ )
+ assert provider == "quicksilverpro"
+ assert api_base == "https://api.quicksilverpro.io/v1"
+
+ def test_quicksilverpro_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("quicksilverpro")
+ 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="claude-sonnet-5-5",
+ drop_params=False,
+ )
+ assert optional_params["max_tokens"] == 256
+ assert "max_completion_tokens" not in optional_params
+
+ def test_quicksilverpro_router_config(self):
+ from litellm import Router
+
+ router = Router(
+ model_list=[
+ {
+ "model_name": "quicksilverpro-chat",
+ "litellm_params": {
+ "model": "quicksilverpro/claude-sonnet-5-5",
+ "api_key": "test-key",
+ },
+ }
+ ]
+ )
+
+ assert len(router.model_list) == 1
+ assert router.model_list[0]["model_name"] == "quicksilverpro-chat"
+
+
+class TestQuickSilverProModelMetadata:
+ @staticmethod
+ def _load(path_parts):
+ json_path = Path(__file__).parents[4].joinpath(*path_parts)
+ with open(json_path) as f:
+ return json.load(f)
+
+ def test_all_models_present_in_model_cost(self):
+ model_cost = self._load(("model_prices_and_context_window.json",))
+ for model in QSP_MODELS:
+ assert model in model_cost, f"{model} missing from model cost map"
+ assert model_cost[model]["litellm_provider"] == "quicksilverpro"
+ assert model_cost[model]["mode"] == "chat"
+
+ def test_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 QSP_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"
+ )
+
+ @pytest.mark.parametrize("model", QSP_MODELS)
+ def test_quicksilverpro_model_cost_and_capabilities(self, model: str):
+ """Behaviour against the committed entries: cost_per_token must charge
+ each model's own input/output price, and get_model_info must expose a
+ coherent entry. Expected values are read from the loaded cost map, not
+ hard-coded."""
+ from litellm.cost_calculator import cost_per_token
+
+ prompt_cost, completion_cost = cost_per_token(
+ model=model,
+ prompt_tokens=1_000_000,
+ completion_tokens=1_000_000,
+ custom_llm_provider="quicksilverpro",
+ )
+ model_info = litellm.get_model_info(model)
+
+ assert prompt_cost == pytest.approx(model_info["input_cost_per_token"] * 1_000_000)
+ assert completion_cost == pytest.approx(model_info["output_cost_per_token"] * 1_000_000)
+ assert model_info["output_cost_per_token"] > 0
+ assert 0 < model_info["cache_read_input_token_cost"] < model_info["input_cost_per_token"]
+ # Entries without a provider-specified output cap come back with
+ # max_output_tokens=None; the legacy max_tokens then carries the cap.
+ max_output = model_info.get("max_output_tokens") or model_info["max_input_tokens"]
+ assert (
+ model_info["max_tokens"]
+ == max_output
+ <= model_info["max_input_tokens"]
+ )
+ assert model_info["litellm_provider"] == "quicksilverpro"
+ assert model_info["mode"] == "chat"
+ assert litellm.supports_vision(model) is model_info["supports_vision"]
+
+ def test_quicksilverpro_cost_map_is_queryable(self):
+ """The entries must be consumable through litellm's own cost map, not
+ just present in the JSON file."""
+ from litellm import model_cost
+
+ for model in QSP_MODELS:
+ assert model in model_cost, model
+ assert model_cost[model]["litellm_provider"] == "quicksilverpro"
+
+
+class TestQuickSilverProDashboardRegistration:
+ @staticmethod
+ def _provider_create_fields():
+ path = (
+ Path(litellm.__file__).parent
+ / "proxy"
+ / "public_endpoints"
+ / "provider_create_fields.json"
+ )
+ with open(path) as f:
+ return json.load(f)
+
+ def test_quicksilverpro_is_selectable_in_the_add_model_form(self):
+ entries = [
+ e
+ for e in self._provider_create_fields()
+ if e["litellm_provider"] == "quicksilverpro"
+ ]
+ assert (
+ len(entries) == 1
+ ), "quicksilverpro must appear exactly once in provider_create_fields.json"
+
+ entry = entries[0]
+ assert entry["provider"] == "QUICKSILVERPRO"
+ assert entry["provider_display_name"] == "QuickSilver Pro"
+ assert entry["default_model_placeholder"].startswith("quicksilverpro/")
+
+ 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
+
+ def test_quicksilverpro_supported_endpoints_matrix(self):
+ matrix = json.loads(
+ (
+ Path(litellm.__file__).parent
+ / "provider_endpoints_support_backup.json"
+ ).read_text()
+ )
+
+ endpoints = matrix["providers"]["quicksilverpro"]["endpoints"]
+ assert endpoints["chat_completions"] is True
+ assert endpoints["messages"] is True
+ assert endpoints["responses"] is True
+ assert endpoints["embeddings"] is False
+ assert endpoints["image_generations"] is False
+
+
+def test_quicksilverpro_chat_completion_request():
+ """chat/completions hits the provider's base URL with bearer auth and maps
+ max_completion_tokens -> max_tokens."""
+ with respx.mock() as upstream:
+ route: Final = upstream.post(
+ "https://api.quicksilverpro.io/v1/chat/completions"
+ ).respond(
+ 200,
+ json={
+ "id": "chatcmpl_quicksilverpro",
+ "object": "chat.completion",
+ "created": 1_789_550_000,
+ "model": "claude-sonnet-5-5",
+ "choices": [
+ {
+ "index": 0,
+ "message": {"role": "assistant", "content": "Hello from QuickSilver Pro"},
+ "finish_reason": "stop",
+ }
+ ],
+ "usage": {"prompt_tokens": 4, "completion_tokens": 3, "total_tokens": 7},
+ },
+ )
+ response: Final = litellm.completion(
+ model="quicksilverpro/claude-sonnet-5-5",
+ messages=[{"role": "user", "content": "Say hello"}],
+ max_completion_tokens=128,
+ api_key="quicksilverpro-test-key",
+ )
+
+ request: Final = route.calls.last.request
+ body: Final = json.loads(request.content)
+ assert route.call_count == 1
+ assert str(request.url) == "https://api.quicksilverpro.io/v1/chat/completions"
+ assert request.headers["authorization"] == "Bearer quicksilverpro-test-key"
+ assert body["model"] == "claude-sonnet-5-5"
+ assert body["messages"] == [{"role": "user", "content": "Say hello"}]
+ assert body["max_tokens"] == 128
+ assert "max_completion_tokens" not in body
+ assert response.choices[0].message.content == "Hello from QuickSilver Pro"
+
+
+def test_quicksilverpro_responses_request():
+ with respx.mock() as upstream:
+ route: Final = upstream.post(
+ "https://api.quicksilverpro.io/v1/responses"
+ ).respond(
+ 200,
+ json={
+ "id": "resp_quicksilverpro",
+ "object": "response",
+ "created_at": 1_789_550_000,
+ "model": "claude-sonnet-5-5",
+ "status": "completed",
+ "output": [
+ {
+ "id": "msg_quicksilverpro",
+ "type": "message",
+ "role": "assistant",
+ "status": "completed",
+ "content": [
+ {
+ "type": "output_text",
+ "text": "Hello from QuickSilver Pro",
+ "annotations": [],
+ }
+ ],
+ }
+ ],
+ "usage": {"input_tokens": 4, "output_tokens": 3, "total_tokens": 7},
+ },
+ )
+ response: Final = litellm.responses(
+ model="quicksilverpro/claude-sonnet-5-5",
+ input="Say hello",
+ api_key="quicksilverpro-test-key",
+ )
+
+ request: Final = route.calls.last.request
+ body: Final = json.loads(request.content)
+ assert route.call_count == 1
+ assert str(request.url) == "https://api.quicksilverpro.io/v1/responses"
+ assert request.headers["authorization"] == "Bearer quicksilverpro-test-key"
+ assert body["model"] == "claude-sonnet-5-5"
+ assert body["input"] == "Say hello"
+ assert response.output[0].content[0].text == "Hello from QuickSilver Pro"
+
+
+@pytest.mark.asyncio
+async def test_quicksilverpro_anthropic_messages_request(monkeypatch: pytest.MonkeyPatch):
+ monkeypatch.setattr(litellm, "disable_aiohttp_transport", True)
+ monkeypatch.setattr(litellm, "in_memory_llm_clients_cache", LLMClientCache())
+ with respx.mock() as upstream:
+ route: Final = upstream.post(
+ "https://api.quicksilverpro.io/v1/messages"
+ ).respond(
+ 200,
+ json={
+ "id": "msg_quicksilverpro",
+ "type": "message",
+ "role": "assistant",
+ "model": "claude-sonnet-5-5",
+ "content": [{"type": "text", "text": "Hello from QuickSilver Pro"}],
+ "stop_reason": "end_turn",
+ "stop_sequence": None,
+ "usage": {"input_tokens": 4, "output_tokens": 3},
+ },
+ )
+ response: Final = await litellm.anthropic.messages.acreate(
+ model="quicksilverpro/claude-sonnet-5-5",
+ messages=[{"role": "user", "content": "Say hello"}],
+ max_tokens=32,
+ api_key="quicksilverpro-test-key",
+ )
+
+ request: Final = route.calls.last.request
+ body: Final = json.loads(request.content)
+ assert route.call_count == 1
+ assert str(request.url) == "https://api.quicksilverpro.io/v1/messages"
+ assert request.headers["authorization"] == "Bearer quicksilverpro-test-key"
+ assert request.headers["anthropic-version"] == "2023-06-01"
+ assert body["model"] == "claude-sonnet-5-5"
+ assert body["messages"] == [{"role": "user", "content": "Say hello"}]
+ assert response["content"][0]["text"] == "Hello from QuickSilver Pro"
diff --git a/ui/litellm-dashboard/public/assets/logos/quicksilverpro.svg b/ui/litellm-dashboard/public/assets/logos/quicksilverpro.svg
new file mode 100644
index 00000000000..ce98c22bcd3
--- /dev/null
+++ b/ui/litellm-dashboard/public/assets/logos/quicksilverpro.svg
@@ -0,0 +1,14 @@
+
\ No newline at end of file
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 7cfdaf3275d..0b32132d0a1 100644
--- a/ui/litellm-dashboard/src/components/provider_info_helpers.test.tsx
+++ b/ui/litellm-dashboard/src/components/provider_info_helpers.test.tsx
@@ -73,6 +73,17 @@ describe("provider_info_helpers", () => {
expect(fromEnumKey.logo).toBe(providerLogoMap[Providers.SCX_AI]);
});
+ it("should map quicksilverpro slug and QUICKSILVERPRO enum key to the QuickSilver Pro display name and logo", () => {
+ const fromSlug = getProviderLogoAndName("quicksilverpro");
+ expect(fromSlug.displayName).toBe(Providers.QUICKSILVERPRO);
+ expect(fromSlug.logo).toBe(providerLogoMap[Providers.QUICKSILVERPRO]);
+ expect(fromSlug.logo).toBeTruthy();
+
+ const fromEnumKey = getProviderLogoAndName("QUICKSILVERPRO");
+ expect(fromEnumKey.displayName).toBe(Providers.QUICKSILVERPRO);
+ expect(fromEnumKey.logo).toBe(providerLogoMap[Providers.QUICKSILVERPRO]);
+ });
+
it("should map bedrock_mantle slug to Bedrock Mantle display name and logo", () => {
const result = getProviderLogoAndName("bedrock_mantle");
expect(result.displayName).toBe(Providers.BedrockMantle);
@@ -229,6 +240,10 @@ describe("provider_info_helpers", () => {
expect(getPlaceholder(Providers.SCX_AI)).toBe("scx-ai/GLM-5.2");
});
+ it("should return a quicksilverpro model placeholder for QUICKSILVERPRO provider", () => {
+ expect(getPlaceholder(Providers.QUICKSILVERPRO)).toBe("quicksilverpro/claude-sonnet-5-5");
+ });
+
it("should return an edenai model placeholder for EDENAI provider", () => {
expect(getPlaceholder(Providers.EDENAI)).toBe("edenai/openai/gpt-mini-latest");
});
diff --git a/ui/litellm-dashboard/src/components/provider_info_helpers.tsx b/ui/litellm-dashboard/src/components/provider_info_helpers.tsx
index 5ea693bea10..53be3a359e6 100644
--- a/ui/litellm-dashboard/src/components/provider_info_helpers.tsx
+++ b/ui/litellm-dashboard/src/components/provider_info_helpers.tsx
@@ -47,6 +47,7 @@ import openrouterLogo from "../../public/assets/logos/openrouter.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";
+import quicksilverproLogo from "../../public/assets/logos/quicksilverpro.svg";
import recraftLogo from "../../public/assets/logos/recraft.svg";
import replicateLogo from "../../public/assets/logos/replicate.svg";
import runwayLogo from "../../public/assets/logos/runway.png";
@@ -155,6 +156,7 @@ export enum Providers {
PETALS = "Petals",
PG_VECTOR = "Pg Vector",
PREDIBASE = "Predibase",
+ QUICKSILVERPRO = "QuickSilver Pro",
Qwen_AI_Platform = "Qianwen AI Platform",
QwenCloud = "QwenCloud",
RECRAFT = "Recraft",
@@ -274,6 +276,7 @@ export const provider_map: Record = {
PETALS: "petals",
PG_VECTOR: "pg_vector",
PREDIBASE: "predibase",
+ QUICKSILVERPRO: "quicksilverpro",
Qwen_AI_Platform: "qwen_ai_platform",
QwenCloud: "qwencloud",
RECRAFT: "recraft",
@@ -376,6 +379,7 @@ export const providerLogoMap: Partial> = {
[Providers.Openrouter]: openrouterLogo.src,
[Providers.Oracle]: oracleLogo.src,
[Providers.Perplexity]: perplexityAiLogo.src,
+ [Providers.QUICKSILVERPRO]: quicksilverproLogo.src,
[Providers.Qwen_AI_Platform]: qwenLogo.src,
[Providers.QwenCloud]: qwenLogo.src,
[Providers.RECRAFT]: recraftLogo.src,
@@ -456,6 +460,7 @@ const providerPlaceholderMap: Partial> = {
[Providers.SageMaker]: "sagemaker/jumpstart-dft-meta-textgeneration-llama-2-7b",
[Providers.Sail]: "sail/openai/gpt-oss-120b",
[Providers.SCX_AI]: "scx-ai/GLM-5.2",
+ [Providers.QUICKSILVERPRO]: "quicksilverpro/claude-sonnet-5-5",
[Providers.Snowflake]: "snowflake/mistral-7b",
[Providers.Tencent]: "tencent/deepseek-v4-pro",
[Providers.Vertex_AI]: "gemini-pro",
diff --git a/ui/litellm-dashboard/src/lib/logoTreatments.ts b/ui/litellm-dashboard/src/lib/logoTreatments.ts
index fc19c5c364d..68a5a9f418e 100644
--- a/ui/litellm-dashboard/src/lib/logoTreatments.ts
+++ b/ui/litellm-dashboard/src/lib/logoTreatments.ts
@@ -39,6 +39,7 @@ const TREATMENT_BY_ASSET: Readonly> = {
"fireworks.svg": "plate",
"llm_guard.png": "plate",
"pangea.png": "plate",
+ "quicksilverpro.svg": "plate",
"repelloai.png": "plate",
"sambanova.svg": "plate",
"sentry.svg": "plate",