From f252208117e051a89abca4fb38f8486f3402c027 Mon Sep 17 00:00:00 2001 From: seven7763 Date: Fri, 4 Sep 2026 09:44:27 +0800 Subject: [PATCH 1/4] feat(providers): add DaoXE OpenAI-compatible gateway - litellm/llms/openai_like/providers.json: daoxe entry (base_url, env keys, param mappings, supported endpoints) - litellm/types/utils.py: DAOXE in LlmProviders enum - provider_endpoints_support.json: DaoXE row (chat_completions + responses), including the interactions flag - tests/test_litellm/llms/openai_like/test_daoxe_provider.py: registry + endpoint tests Signed-off-by: seven7763 --- litellm/llms/openai_like/providers.json | 33 +++++++++++-- litellm/types/utils.py | 1 + provider_endpoints_support.json | 38 +++++++-------- .../llms/openai_like/test_daoxe_provider.py | 48 +++++++++++++++++++ 4 files changed, 97 insertions(+), 23 deletions(-) create mode 100644 tests/test_litellm/llms/openai_like/test_daoxe_provider.py diff --git a/litellm/llms/openai_like/providers.json b/litellm/llms/openai_like/providers.json index a458a209ea9..cf9dd004234 100644 --- a/litellm/llms/openai_like/providers.json +++ b/litellm/llms/openai_like/providers.json @@ -130,7 +130,10 @@ "param_mappings": { "max_completion_tokens": "max_tokens" }, - "supported_endpoints": ["/v1/chat/completions", "/v1/responses"] + "supported_endpoints": [ + "/v1/chat/completions", + "/v1/responses" + ] }, "tensormesh": { "base_url": "https://serverless.tensormesh.ai/v1", @@ -140,13 +143,19 @@ "param_mappings": { "max_completion_tokens": "max_tokens" }, - "supported_endpoints": ["/v1/chat/completions", "/v1/responses"] + "supported_endpoints": [ + "/v1/chat/completions", + "/v1/responses" + ] }, "parasail": { "base_url": "https://api.parasail.io/v1", "api_key_env": "PARASAIL_API_KEY", "api_base_env": "PARASAIL_API_BASE", - "supported_endpoints": ["/v1/chat/completions", "/v1/responses"], + "supported_endpoints": [ + "/v1/chat/completions", + "/v1/responses" + ], "special_handling": { "force_store_false": true } @@ -166,7 +175,10 @@ "param_mappings": { "max_completion_tokens": "max_tokens" }, - "supported_endpoints": ["/v1/chat/completions", "/v1/responses"] + "supported_endpoints": [ + "/v1/chat/completions", + "/v1/responses" + ] }, "meta": { "base_url": "https://api.meta.ai/v1", @@ -200,5 +212,18 @@ "temperature_max": 1.99 }, "supported_endpoints": ["/v1/chat/completions"] + }, + "daoxe": { + "base_url": "https://daoxe.com/v1", + "api_key_env": "DAOXE_API_KEY", + "api_base_env": "DAOXE_API_BASE", + "base_class": "openai_gpt", + "param_mappings": { + "max_completion_tokens": "max_tokens" + }, + "supported_endpoints": [ + "/v1/chat/completions", + "/v1/responses" + ] } } diff --git a/litellm/types/utils.py b/litellm/types/utils.py index 34c47d3f201..3e9471b313d 100644 --- a/litellm/types/utils.py +++ b/litellm/types/utils.py @@ -3830,6 +3830,7 @@ class LlmProviders(str, Enum): INCEPTION = "inception" TEXT_COMPLETION_INCEPTION = "text-completion-inception" DEEPSEEK = "deepseek" + DAOXE = "daoxe" SAMBANOVA = "sambanova" MARITALK = "maritalk" VOYAGE = "voyage" diff --git a/provider_endpoints_support.json b/provider_endpoints_support.json index ebc220b3496..cb8d33d8d29 100644 --- a/provider_endpoints_support.json +++ b/provider_endpoints_support.json @@ -488,9 +488,7 @@ "audio_speech": false, "moderations": false, "batches": false, - "rerank": false, - "a2a": false, - "interactions": false + "rerank": false } }, "chutes": { @@ -2994,22 +2992,6 @@ "rerank": false } }, - "charity_engine": { - "display_name": "Charity Engine (`charity_engine`)", - "url": "https://docs.litellm.ai/docs/providers/charity_engine", - "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 - } - }, "empiriolabs": { "display_name": "EmpirioLabs (`empiriolabs`)", "url": "https://docs.litellm.ai/docs/providers/empiriolabs", @@ -3026,6 +3008,24 @@ "rerank": false, "a2a": false } + }, + "daoxe": { + "display_name": "DaoXE (`daoxe`)", + "url": "https://docs.litellm.ai/docs/providers/daoxe", + "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, + "interactions": false + } } }, "endpoints": { diff --git a/tests/test_litellm/llms/openai_like/test_daoxe_provider.py b/tests/test_litellm/llms/openai_like/test_daoxe_provider.py new file mode 100644 index 00000000000..743e5961737 --- /dev/null +++ b/tests/test_litellm/llms/openai_like/test_daoxe_provider.py @@ -0,0 +1,48 @@ +import litellm + + +def test_daoxe_in_provider_list(): + from litellm import LlmProviders + + assert LlmProviders.DAOXE.value == "daoxe" + assert "daoxe" in litellm.provider_list + + +def test_daoxe_json_config(): + from litellm.llms.openai_like.json_loader import JSONProviderRegistry + + assert JSONProviderRegistry.exists("daoxe") + provider = JSONProviderRegistry.get("daoxe") + assert provider is not None + assert provider.base_url == "https://daoxe.com/v1" + assert provider.api_key_env == "DAOXE_API_KEY" + assert provider.api_base_env == "DAOXE_API_BASE" + + +def test_daoxe_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="daoxe/account-model", + custom_llm_provider=None, + api_base=None, + api_key=None, + ) + + assert model == "account-model" + assert provider == "daoxe" + assert api_key is None + assert api_base == "https://daoxe.com/v1" + + +def test_daoxe_responses_api_config(): + from litellm.llms.openai_like.json_loader import JSONProviderRegistry + from litellm.utils import ProviderConfigManager + + assert JSONProviderRegistry.supports_responses_api("daoxe") is True + config = ProviderConfigManager.get_provider_responses_api_config( + provider="daoxe", + model="daoxe/account-model", + ) + assert config is not None + assert config.custom_llm_provider == "daoxe" From 6916f4d4fffa039db519ea33a9825deb3d2a5ce0 Mon Sep 17 00:00:00 2001 From: seven7763 Date: Fri, 4 Sep 2026 10:08:00 +0800 Subject: [PATCH 2/4] chore: refresh PR (no content change) From ce701d37c0e1432883e18334447cfd47edeca11c Mon Sep 17 00:00:00 2001 From: seven7763 Date: Sun, 6 Sep 2026 10:39:36 +0800 Subject: [PATCH 3/4] test: add param mapping and URL construction coverage for daoxe provider --- .../llms/openai_like/test_daoxe_provider.py | 111 ++++++++++++++++++ 1 file changed, 111 insertions(+) diff --git a/tests/test_litellm/llms/openai_like/test_daoxe_provider.py b/tests/test_litellm/llms/openai_like/test_daoxe_provider.py index 743e5961737..e1d7f9d2d96 100644 --- a/tests/test_litellm/llms/openai_like/test_daoxe_provider.py +++ b/tests/test_litellm/llms/openai_like/test_daoxe_provider.py @@ -46,3 +46,114 @@ def test_daoxe_responses_api_config(): ) assert config is not None assert config.custom_llm_provider == "daoxe" + + +def test_daoxe_max_completion_tokens_mapped(): + from litellm.llms.openai_like.dynamic_config import create_config_class + from litellm.llms.openai_like.json_loader import JSONProviderRegistry + + provider = JSONProviderRegistry.get("daoxe") + assert provider is not None + config = create_config_class(provider)() + + optional_params = config.map_openai_params( + non_default_params={"max_completion_tokens": 512}, + optional_params={}, + model="account-model", + drop_params=False, + ) + assert optional_params["max_tokens"] == 512 + assert "max_completion_tokens" not in optional_params + + +def test_daoxe_passthrough_params_kept(): + from litellm.llms.openai_like.dynamic_config import create_config_class + from litellm.llms.openai_like.json_loader import JSONProviderRegistry + + provider = JSONProviderRegistry.get("daoxe") + assert provider is not None + config = create_config_class(provider)() + + optional_params = config.map_openai_params( + non_default_params={"temperature": 0.4, "top_p": 0.9}, + optional_params={}, + model="account-model", + drop_params=False, + ) + assert optional_params["temperature"] == 0.4 + assert optional_params["top_p"] == 0.9 + + +def test_daoxe_chat_completions_url(): + from litellm.llms.openai_like.dynamic_config import create_config_class + from litellm.llms.openai_like.json_loader import JSONProviderRegistry + + provider = JSONProviderRegistry.get("daoxe") + assert provider is not None + config = create_config_class(provider)() + + url = config.get_complete_url( + api_base=None, + api_key="test-key", + model="account-model", + optional_params={}, + litellm_params={}, + ) + assert url == "https://daoxe.com/v1/chat/completions" + + +def test_daoxe_chat_completions_url_custom_base(): + from litellm.llms.openai_like.dynamic_config import create_config_class + from litellm.llms.openai_like.json_loader import JSONProviderRegistry + + provider = JSONProviderRegistry.get("daoxe") + assert provider is not None + config = create_config_class(provider)() + + url = config.get_complete_url( + api_base="https://api.daoxe.com/v1", + api_key="test-key", + model="account-model", + optional_params={}, + litellm_params={}, + ) + assert url == "https://api.daoxe.com/v1/chat/completions" + + +def test_daoxe_responses_url(): + from litellm.utils import ProviderConfigManager + + config = ProviderConfigManager.get_provider_responses_api_config( + provider="daoxe", + model="daoxe/account-model", + ) + assert config is not None + url = config.get_complete_url(api_base=None, litellm_params={}) + assert url == "https://daoxe.com/v1/responses" + + +def test_daoxe_env_base_overrides_default(monkeypatch): + from litellm.llms.openai_like.dynamic_config import create_config_class + from litellm.llms.openai_like.json_loader import JSONProviderRegistry + + monkeypatch.setenv("DAOXE_API_BASE", "https://api.daoxe.com/v1") + provider = JSONProviderRegistry.get("daoxe") + assert provider is not None + config = create_config_class(provider)() + + resolved_base, _resolved_key = config._get_openai_compatible_provider_info( + None, None + ) + assert resolved_base == "https://api.daoxe.com/v1" + + +def test_daoxe_responses_config_url_construction(): + from litellm.utils import ProviderConfigManager + + config = ProviderConfigManager.get_provider_responses_api_config( + provider="daoxe", + model="daoxe/account-model", + ) + assert config is not None + url = config.get_complete_url(api_base=None, litellm_params={}) + assert url == "https://daoxe.com/v1/responses" From b95a9f1fe57eadccfb2583b0a79c1c3d4764c568 Mon Sep 17 00:00:00 2001 From: seven7763 Date: Mon, 7 Sep 2026 22:18:11 +0800 Subject: [PATCH 4/4] chore: retrigger CI after retarget