From c183b77991f1e25b6e399f8e21cc855f80674c7f Mon Sep 17 00:00:00 2001 From: alex-clawd Date: Wed, 25 Mar 2026 14:22:13 -0700 Subject: [PATCH] fix: address Copilot review on OpenAI-compatible providers (#5042) (#5089) - Delegate supports_function_calling() to parent (handles o1 models via OpenRouter) - Guard empty env vars in base_url resolution - Fix misleading comment about model validation rules - Remove unused MagicMock import - Use 'is not None' for env var restoration in tests Co-authored-by: Joao Moura --- lib/crewai/src/crewai/llm.py | 4 ++-- .../llms/providers/openai_compatible/completion.py | 11 +++++++---- .../llms/openai_compatible/test_openai_compatible.py | 4 ++-- 3 files changed, 11 insertions(+), 8 deletions(-) diff --git a/lib/crewai/src/crewai/llm.py b/lib/crewai/src/crewai/llm.py index 0b3b158d6..75b1f6546 100644 --- a/lib/crewai/src/crewai/llm.py +++ b/lib/crewai/src/crewai/llm.py @@ -483,8 +483,8 @@ class LLM(BaseLLM): for prefix in ["gpt-", "gpt-35-", "o1", "o3", "o4", "azure-"] ) - # OpenAI-compatible providers - accept any model name since these - # providers host many different models with varied naming conventions + # OpenAI-compatible providers - most accept any model name, but some + # (DeepSeek, Dashscope) restrict to their own model prefixes if provider == "deepseek": return model_lower.startswith("deepseek") diff --git a/lib/crewai/src/crewai/llms/providers/openai_compatible/completion.py b/lib/crewai/src/crewai/llms/providers/openai_compatible/completion.py index 9c308f52e..293e73ff0 100644 --- a/lib/crewai/src/crewai/llms/providers/openai_compatible/completion.py +++ b/lib/crewai/src/crewai/llms/providers/openai_compatible/completion.py @@ -239,7 +239,8 @@ class OpenAICompatibleCompletion(OpenAICompletion): if base_url: resolved = base_url elif config.base_url_env: - resolved = os.getenv(config.base_url_env, config.base_url) + env_value = os.getenv(config.base_url_env) + resolved = env_value if env_value else config.base_url else: resolved = config.base_url @@ -274,9 +275,11 @@ class OpenAICompatibleCompletion(OpenAICompletion): def supports_function_calling(self) -> bool: """Check if the provider supports function calling. - All modern OpenAI-compatible providers support function calling. + Delegates to the parent OpenAI implementation which handles + edge cases like o1 models (which may be routed through + OpenRouter or other compatible providers). Returns: - True, as all supported providers have function calling support. + Whether the model supports function calling. """ - return True + return super().supports_function_calling() diff --git a/lib/crewai/tests/llms/openai_compatible/test_openai_compatible.py b/lib/crewai/tests/llms/openai_compatible/test_openai_compatible.py index ade54fb8c..fd5970299 100644 --- a/lib/crewai/tests/llms/openai_compatible/test_openai_compatible.py +++ b/lib/crewai/tests/llms/openai_compatible/test_openai_compatible.py @@ -1,7 +1,7 @@ """Tests for OpenAI-compatible providers.""" import os -from unittest.mock import MagicMock, patch +from unittest.mock import patch import pytest @@ -133,7 +133,7 @@ class TestOpenAICompatibleCompletion: with pytest.raises(ValueError, match="API key required"): OpenAICompatibleCompletion(model="deepseek-chat", provider="deepseek") finally: - if original: + if original is not None: os.environ[env_key] = original def test_api_key_from_env(self):