From df25b1d67fbbd8bfc064b37365458a04b0b1c74f Mon Sep 17 00:00:00 2001 From: Joseph Perla Date: Wed, 22 Jul 2026 10:41:40 -0700 Subject: [PATCH 1/5] feat: add TrustedRouter as a JSON-configured OpenAI-compatible provider TrustedRouter (https://trustedrouter.com) is an OpenAI-compatible LLM router. Added via the JSON provider registry, following the parasail/libertai pattern: providers.json entry, openai_compatible_providers/endpoints lists, LlmProviders enum, and unit tests covering the registry, constants, env-var config, and prefix routing --- litellm/constants.py | 2 + litellm/llms/openai_like/providers.json | 6 ++ litellm/types/utils.py | 1 + .../llms/trustedrouter/test_trustedrouter.py | 59 +++++++++++++++++++ 4 files changed, 68 insertions(+) create mode 100644 tests/test_litellm/llms/trustedrouter/test_trustedrouter.py diff --git a/litellm/constants.py b/litellm/constants.py index 271e42ee661..398e02f9168 100644 --- a/litellm/constants.py +++ b/litellm/constants.py @@ -1014,6 +1014,7 @@ openai_compatible_endpoints: Final[list[str]] = [ "https://api.inference.wandb.ai/v1", "https://api.clarifai.com/v2/ext/openai/v1", "https://api.libertai.io/v1", + "https://api.trustedrouter.com/v1", "https://pinstripes.io/v1", "https://api.meta.ai/v1", "https://api.sailresearch.com/v1", @@ -1069,6 +1070,7 @@ openai_compatible_providers: Final[list] = [ "chutes", # Chutes - JSON-configured provider "parasail", # Parasail - JSON-configured provider "libertai", # LibertAI - JSON-configured provider + "trustedrouter", # TrustedRouter - JSON-configured provider "featherless_ai", "nscale", "nebius", diff --git a/litellm/llms/openai_like/providers.json b/litellm/llms/openai_like/providers.json index aa8a17c3824..4f20fea7c9f 100644 --- a/litellm/llms/openai_like/providers.json +++ b/litellm/llms/openai_like/providers.json @@ -239,5 +239,11 @@ "/v1/responses", "/v1/messages" ] + }, + "trustedrouter": { + "base_url": "https://api.trustedrouter.com/v1", + "api_key_env": "TRUSTEDROUTER_API_KEY", + "api_base_env": "TRUSTEDROUTER_API_BASE", + "supported_endpoints": ["/v1/chat/completions", "/v1/responses"] } } diff --git a/litellm/types/utils.py b/litellm/types/utils.py index 0bcb732a0f5..a0af96e63be 100644 --- a/litellm/types/utils.py +++ b/litellm/types/utils.py @@ -4378,6 +4378,7 @@ class LlmProviders(str, Enum): XIAOMI_MIMO = "xiaomi_mimo" TENSORMESH = "tensormesh" LIBERTAI = "libertai" + TRUSTEDROUTER = "trustedrouter" PINSTRIPES = "pinstripes" COGNITION = "cognition" CORALBRICKS = "coralbricks" diff --git a/tests/test_litellm/llms/trustedrouter/test_trustedrouter.py b/tests/test_litellm/llms/trustedrouter/test_trustedrouter.py new file mode 100644 index 00000000000..d83fe14181f --- /dev/null +++ b/tests/test_litellm/llms/trustedrouter/test_trustedrouter.py @@ -0,0 +1,59 @@ +import os +from unittest.mock import patch + +TRUSTEDROUTER_API_BASE = "https://api.trustedrouter.com/v1" + + +def test_trustedrouter_json_registry(): + import litellm + from litellm.llms.openai_like.json_loader import JSONProviderRegistry + + assert litellm.LlmProviders.TRUSTEDROUTER.value == "trustedrouter" + assert litellm.LlmProviders("trustedrouter") == litellm.LlmProviders.TRUSTEDROUTER + assert JSONProviderRegistry.exists("trustedrouter") + config = JSONProviderRegistry.get("trustedrouter") + assert config is not None + assert config.base_url == TRUSTEDROUTER_API_BASE + assert config.api_key_env == "TRUSTEDROUTER_API_KEY" + assert config.api_base_env == "TRUSTEDROUTER_API_BASE" + assert "/v1/chat/completions" in config.supported_endpoints + assert "/v1/responses" in config.supported_endpoints + + +def test_trustedrouter_listed_in_openai_compatible_providers(): + from litellm.constants import ( + openai_compatible_endpoints, + openai_compatible_providers, + ) + + assert "trustedrouter" in openai_compatible_providers + assert TRUSTEDROUTER_API_BASE in openai_compatible_endpoints + + +def test_trustedrouter_dynamic_config_env_vars(): + from litellm.llms.openai_like.dynamic_config import create_config_class + from litellm.llms.openai_like.json_loader import JSONProviderRegistry + + config = create_config_class(JSONProviderRegistry.get("trustedrouter"))() + + with patch.dict( + os.environ, + { + "TRUSTEDROUTER_API_KEY": "test-key", + "TRUSTEDROUTER_API_BASE": "https://example.com/v1", + }, + ): + api_base, api_key = config._get_openai_compatible_provider_info(None, None) + + assert api_base == "https://example.com/v1" + assert api_key == "test-key" + + +def test_trustedrouter_provider_detection_by_prefix(): + from litellm.litellm_core_utils.get_llm_provider_logic import get_llm_provider + + model, provider, _, api_base = get_llm_provider("trustedrouter/zdr") + + assert model == "zdr" + assert provider == "trustedrouter" + assert api_base == TRUSTEDROUTER_API_BASE From 4896ece68a139bb075106233a4584d7e70395d32 Mon Sep 17 00:00:00 2001 From: Joseph Perla Date: Sat, 25 Jul 2026 10:14:29 -0700 Subject: [PATCH 2/5] feat(ui): add TrustedRouter to the model-add provider dropdown Mirror the Openrouter entry so TrustedRouter is a first-class option in the Add Model provider dropdown: the Providers enum, provider_map pointing at the trustedrouter custom_llm_provider, and providerLogoMap with a new trustedrouter.svg mark. This completes the user-facing surface for the provider registered in this PR --- ui/litellm-dashboard/public/assets/logos/trustedrouter.svg | 7 +++++++ .../src/components/provider_info_helpers.tsx | 4 ++++ 2 files changed, 11 insertions(+) create mode 100644 ui/litellm-dashboard/public/assets/logos/trustedrouter.svg diff --git a/ui/litellm-dashboard/public/assets/logos/trustedrouter.svg b/ui/litellm-dashboard/public/assets/logos/trustedrouter.svg new file mode 100644 index 00000000000..b4d9f4cd233 --- /dev/null +++ b/ui/litellm-dashboard/public/assets/logos/trustedrouter.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/ui/litellm-dashboard/src/components/provider_info_helpers.tsx b/ui/litellm-dashboard/src/components/provider_info_helpers.tsx index 3925118a881..58dd6e9b28f 100644 --- a/ui/litellm-dashboard/src/components/provider_info_helpers.tsx +++ b/ui/litellm-dashboard/src/components/provider_info_helpers.tsx @@ -45,6 +45,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 trustedrouterLogo from "../../public/assets/logos/trustedrouter.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"; @@ -180,6 +181,7 @@ export enum Providers { TogetherAI = "TogetherAI", TOPAZ = "Topaz", Triton = "Triton", + Trustedrouter = "Trustedrouter", TypeSafe = "TypeSafe", V0 = "V0", VERCEL_AI_GATEWAY = "Vercel Ai Gateway", @@ -306,6 +308,7 @@ export const provider_map: Record = { TogetherAI: "together_ai", TOPAZ: "topaz", Triton: "triton", + Trustedrouter: "trustedrouter", TypeSafe: "typesafe", V0: "v0", VERCEL_AI_GATEWAY: "vercel_ai_gateway", @@ -412,6 +415,7 @@ export const providerLogoMap: Partial> = { [Providers.TogetherAI]: togetheraiLogo.src, [Providers.TOPAZ]: topazLogo.src, [Providers.Triton]: nvidiaTritonLogo.src, + [Providers.Trustedrouter]: trustedrouterLogo.src, [Providers.TypeSafe]: typesafeLogo.src, [Providers.V0]: v0Logo.src, [Providers.VERCEL_AI_GATEWAY]: vercelLogo.src, From f1da19dc59bf01b8979aefbc8a1f1703f6052019 Mon Sep 17 00:00:00 2001 From: jperla Date: Mon, 21 Sep 2026 19:49:19 -0700 Subject: [PATCH 3/5] docs: document trustedrouter in provider_endpoints_support.json check_provider_folders_documented.py requires every provider in litellm/llms/openai_like/providers.json to have an entry here, so code-quality failed on the TrustedRouter addition. Endpoints mirror the provider's supported_endpoints: /chat/completions and /responses. Co-Authored-By: Claude Opus 5 (1M context) --- provider_endpoints_support.json | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/provider_endpoints_support.json b/provider_endpoints_support.json index 45104d40018..6fc0fc20334 100644 --- a/provider_endpoints_support.json +++ b/provider_endpoints_support.json @@ -3246,6 +3246,23 @@ "rerank": false, "a2a": false } + }, + "trustedrouter": { + "display_name": "TrustedRouter (`trustedrouter`)", + "url": "https://docs.litellm.ai/docs/providers/trustedrouter", + "endpoints": { + "chat_completions": true, + "messages": false, + "responses": true, + "embeddings": false, + "image_generations": false, + "audio_transcriptions": false, + "audio_speech": false, + "moderations": false, + "batches": false, + "rerank": false, + "a2a": false + } } }, "endpoints": { From 185efd8b551ea447dc7134aa651aac024e431026 Mon Sep 17 00:00:00 2001 From: jperla Date: Mon, 21 Sep 2026 20:10:16 -0700 Subject: [PATCH 4/5] feat(ui): add TrustedRouter to the Add Model provider fields test_every_backend_provider_is_listed_in_add_model_or_frozen_as_unlisted asserts every LlmProviders value is either served by /public/providers/fields or frozen in ADD_MODEL_UNLISTED_PROVIDERS. The test message asks for a provider_create_fields.json entry rather than an addition to the frozen set, and the branch already adds TrustedRouter to the dashboard dropdown, so it belongs in the listed set. api_base is optional with a null default so the canonical URL is not persisted into every credential record. Co-Authored-By: Claude Opus 5 (1M context) --- .../provider_create_fields.json | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/litellm/proxy/public_endpoints/provider_create_fields.json b/litellm/proxy/public_endpoints/provider_create_fields.json index 4a6a88f9a86..9795b62ad87 100644 --- a/litellm/proxy/public_endpoints/provider_create_fields.json +++ b/litellm/proxy/public_endpoints/provider_create_fields.json @@ -4004,5 +4004,33 @@ } ], "default_model_placeholder": "cursor/claude-4-sonnet" + }, + { + "provider": "Trustedrouter", + "provider_display_name": "TrustedRouter", + "litellm_provider": "trustedrouter", + "credential_fields": [ + { + "key": "api_key", + "label": "TrustedRouter API Key", + "placeholder": "Your TrustedRouter API key from trustedrouter.com", + "tooltip": "Get your API key from the TrustedRouter dashboard at trustedrouter.com", + "required": true, + "field_type": "password", + "options": null, + "default_value": null + }, + { + "key": "api_base", + "label": "API Base", + "placeholder": "https://api.trustedrouter.com/v1", + "tooltip": "TrustedRouter API base URL (defaults to https://api.trustedrouter.com/v1)", + "required": false, + "field_type": "text", + "options": null, + "default_value": null + } + ], + "default_model_placeholder": "trustedrouter/auto" } ] From 5b5eefcf63c048e0259b083167a8c9b103cdab6f Mon Sep 17 00:00:00 2001 From: Joseph Perla Date: Sat, 10 Oct 2026 09:14:34 -0700 Subject: [PATCH 5/5] test: move TrustedRouter provider tests to tests/unit/llms/openai_like Co-Authored-By: Claude Opus 5.5 --- .../llms/openai_like/test_trustedrouter_provider.py} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename tests/{test_litellm/llms/trustedrouter/test_trustedrouter.py => unit/llms/openai_like/test_trustedrouter_provider.py} (100%) diff --git a/tests/test_litellm/llms/trustedrouter/test_trustedrouter.py b/tests/unit/llms/openai_like/test_trustedrouter_provider.py similarity index 100% rename from tests/test_litellm/llms/trustedrouter/test_trustedrouter.py rename to tests/unit/llms/openai_like/test_trustedrouter_provider.py