diff --git a/litellm/llms/openai/chat/gpt_transformation.py b/litellm/llms/openai/chat/gpt_transformation.py index 5fdce1ed283..3c8e26ff443 100644 --- a/litellm/llms/openai/chat/gpt_transformation.py +++ b/litellm/llms/openai/chat/gpt_transformation.py @@ -753,7 +753,9 @@ class OpenAIGPTConfig(BaseLLMModelInfo, BaseConfig): """ Calls OpenAI's `/v1/models` endpoint and returns the list of models. """ - return self._fetch_model_ids(api_base=api_base, bearer_token=api_key or get_secret_str("OPENAI_API_KEY")) + return self._fetch_model_ids( + api_base=api_base, bearer_token=get_secret_str("OPENAI_API_KEY") if api_key is None else api_key + ) def discover_models( self, litellm_params: Mapping[str, object] | None = None @@ -775,7 +777,7 @@ class OpenAIGPTConfig(BaseLLMModelInfo, BaseConfig): def _fetch_model_ids( api_base: str | None, bearer_token: str | None ) -> list[str]: # mutable-ok: matches get_models' list[str] contract shared by every provider override - parsed_url: Final = httpx.URL(api_base or "https://api.openai.com") + parsed_url: Final = httpx.URL("https://api.openai.com" if api_base is None else api_base) port_suffix: Final = f":{parsed_url.port}" if parsed_url.port else "" response: Final = litellm.module_level_client.get( url=f"{parsed_url.scheme}://{parsed_url.host}{port_suffix}/v1/models", diff --git a/tests/test_litellm/llms/anthropic/test_anthropic_common_utils.py b/tests/test_litellm/llms/anthropic/test_anthropic_common_utils.py index 7ede9480346..c2dfb91591b 100644 --- a/tests/test_litellm/llms/anthropic/test_anthropic_common_utils.py +++ b/tests/test_litellm/llms/anthropic/test_anthropic_common_utils.py @@ -3510,9 +3510,11 @@ class TestWifParamsAreNotClientSettable: minted org credential, and the router merges request kwargs over deployment params, so a caller who set it picked the scope instead of the administrator.""" from litellm.proxy.auth.auth_utils import _SERVER_OWNED_WIF_UNCONDITIONAL_BANNED - from litellm.types.utils import anthropic_wif_litellm_params + from litellm.types.utils import anthropic_wif_litellm_params, openai_wif_litellm_params - assert set(anthropic_wif_litellm_params) <= set(_SERVER_OWNED_WIF_UNCONDITIONAL_BANNED) + assert set(_SERVER_OWNED_WIF_UNCONDITIONAL_BANNED) == set(anthropic_wif_litellm_params) | set( + openai_wif_litellm_params + ) class TestWifServerOwnedParamsAreUnconditional: diff --git a/tests/test_litellm/llms/openai/test_openai_workload_identity.py b/tests/test_litellm/llms/openai/test_openai_workload_identity.py index a152a70bcec..1f010ef19ee 100644 --- a/tests/test_litellm/llms/openai/test_openai_workload_identity.py +++ b/tests/test_litellm/llms/openai/test_openai_workload_identity.py @@ -552,6 +552,17 @@ class TestDiscoverModels: assert not exchange_route.called + @respx.mock + def test_empty_static_key_never_borrows_the_env_key(self, monkeypatch: pytest.MonkeyPatch) -> None: + monkeypatch.setenv("OPENAI_API_KEY", "sk-env-key-that-must-stay-home") + foreign_models: Final = respx.get("https://third-party.example/v1/models").mock( + return_value=httpx.Response(200, json={"data": [{"id": "other-model"}]}) + ) + + assert OpenAIGPTConfig().get_models(api_key="", api_base="https://third-party.example") == ["other-model"] + assert foreign_models.calls.last.request.headers["Authorization"] == "Bearer " + + class TestClientsideBaseOverride: def test_client_api_base_override_clears_deployment_wif(self, deployment_wif: dict[str, str]) -> None: from litellm.router_utils.clientside_credential_handler import get_dynamic_litellm_params