fix(providers): wire OpenAIChatProvider and AnthropicChatProvider into ProviderRegistry #3464
@@ -373,10 +373,33 @@ Feature: Provider Registry Coverage
|
||||
Given I have a ProviderRegistry with OpenAI API key set
|
||||
And CLEVERAGENTS_DEFAULT_MODEL is not set
|
||||
When I create an AI provider for provider "openai"
|
||||
Then the provider registry AI provider should be a LangChainChatProvider
|
||||
Then the provider registry AI provider should be an OpenAIChatProvider
|
||||
And the provider registry AI provider name should be "openai"
|
||||
And the provider registry AI provider model_id should be "gpt-4o"
|
||||
|
||||
@unit @providers @registry
|
||||
Scenario: Create AI provider returns Anthropic adapter
|
||||
Given I have a ProviderRegistry with Anthropic API key set
|
||||
And CLEVERAGENTS_DEFAULT_MODEL is not set
|
||||
When I create an AI provider for provider "anthropic"
|
||||
Then the provider registry AI provider should be an AnthropicChatProvider
|
||||
And the provider registry AI provider name should be "anthropic"
|
||||
And the provider registry AI provider model_id should be "claude-sonnet-4-20250514"
|
||||
|
||||
@unit @providers @registry
|
||||
Scenario: Create AI provider raises error when OpenAI API key is missing
|
||||
Given I have a ProviderRegistry with no API keys
|
||||
When I try to create an AI provider for provider "openai"
|
||||
Then a provider registry ValueError should be raised
|
||||
And the provider registry error should mention missing "OPENAI_API_KEY" environment variable
|
||||
|
||||
@unit @providers @registry
|
||||
Scenario: Create AI provider raises error when Anthropic API key is missing
|
||||
Given I have a ProviderRegistry with no API keys
|
||||
When I try to create an AI provider for provider "anthropic"
|
||||
Then a provider registry ValueError should be raised
|
||||
And the provider registry error should mention missing "ANTHROPIC_API_KEY" environment variable
|
||||
|
||||
@unit @providers @registry
|
||||
Scenario: Create AI provider returns Google adapter
|
||||
Given I have a ProviderRegistry with "google" API key set
|
||||
@@ -401,7 +424,7 @@ Feature: Provider Registry Coverage
|
||||
And CLEVERAGENTS_DEFAULT_PROVIDER is not set
|
||||
And CLEVERAGENTS_DEFAULT_MODEL is not set
|
||||
When I create an AI provider without specifying a provider
|
||||
Then the provider registry AI provider should be a LangChainChatProvider
|
||||
Then the provider registry AI provider should be an OpenAIChatProvider
|
||||
And the provider registry AI provider name should be "openai"
|
||||
|
||||
|
||||
@@ -414,11 +437,11 @@ Feature: Provider Registry Coverage
|
||||
|
||||
@unit @providers @registry
|
||||
Scenario: AI provider exposes working llm factory
|
||||
Given I have a ProviderRegistry with OpenAI API key set
|
||||
Given I have a ProviderRegistry with "groq" API key set
|
||||
And the provider registry LLM factory is stubbed
|
||||
When I create an AI provider for provider "openai"
|
||||
And I call the AI provider llm factory with model "gpt-mini-cover"
|
||||
Then the stubbed LLM factory should be called for ProviderType.OPENAI with model "gpt-mini-cover"
|
||||
When I create an AI provider for provider "groq"
|
||||
And I call the AI provider llm factory with model "llama-mini-cover"
|
||||
Then the stubbed LLM factory should be called for ProviderType.GROQ with model "llama-mini-cover"
|
||||
|
||||
@unit @providers @registry
|
||||
Scenario: ProviderCapabilities is immutable
|
||||
|
||||
@@ -9,8 +9,10 @@ from unittest.mock import MagicMock
|
||||
|
||||
from behave import given, then, when # type: ignore[import-untyped]
|
||||
|
||||
from cleveragents.providers.llm.anthropic_provider import AnthropicChatProvider
|
||||
from cleveragents.providers.llm.google_provider import GoogleChatProvider
|
||||
from cleveragents.providers.llm.langchain_chat_provider import LangChainChatProvider
|
||||
from cleveragents.providers.llm.openai_provider import OpenAIChatProvider
|
||||
from cleveragents.providers.llm.openrouter_provider import OpenRouterChatProvider
|
||||
from cleveragents.providers.registry import (
|
||||
ProviderCapabilities,
|
||||
@@ -781,6 +783,16 @@ def step_impl_ai_provider_is_langchain(context: Any) -> None:
|
||||
assert isinstance(context.ai_provider, LangChainChatProvider)
|
||||
|
||||
|
||||
@then("the provider registry AI provider should be an OpenAIChatProvider")
|
||||
def step_impl_ai_provider_is_openai(context: Any) -> None:
|
||||
assert isinstance(context.ai_provider, OpenAIChatProvider)
|
||||
|
||||
|
||||
@then("the provider registry AI provider should be an AnthropicChatProvider")
|
||||
def step_impl_ai_provider_is_anthropic(context: Any) -> None:
|
||||
assert isinstance(context.ai_provider, AnthropicChatProvider)
|
||||
|
||||
|
||||
@then("the provider registry AI provider should be a GoogleChatProvider")
|
||||
def step_impl_ai_provider_is_google(context: Any) -> None:
|
||||
assert isinstance(context.ai_provider, GoogleChatProvider)
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
"""LLM provider adapters for CleverAgents.
|
||||
|
||||
Exports all concrete LangChain-backed provider classes so that consumers can
|
||||
import them directly from the ``cleveragents.providers.llm`` subpackage.
|
||||
"""
|
||||
|
||||
from cleveragents.providers.llm.anthropic_provider import AnthropicChatProvider
|
||||
from cleveragents.providers.llm.google_provider import GoogleChatProvider
|
||||
from cleveragents.providers.llm.openai_provider import OpenAIChatProvider
|
||||
from cleveragents.providers.llm.openrouter_provider import OpenRouterChatProvider
|
||||
|
||||
__all__ = [
|
||||
"AnthropicChatProvider",
|
||||
"GoogleChatProvider",
|
||||
"OpenAIChatProvider",
|
||||
"OpenRouterChatProvider",
|
||||
]
|
||||
|
||||
@@ -600,6 +600,49 @@ class ProviderRegistry:
|
||||
provider_info.capabilities if provider_info else ProviderCapabilities()
|
||||
)
|
||||
|
||||
if provider_type == ProviderType.OPENAI:
|
||||
from cleveragents.providers.llm.openai_provider import OpenAIChatProvider
|
||||
|
||||
key_attr = self.PROVIDER_KEY_ATTRS.get(provider_type)
|
||||
api_key = getattr(self._settings, key_attr, None) if key_attr else None
|
||||
if not api_key:
|
||||
missing_env = (
|
||||
key_attr.upper() if key_attr else provider_type.value.upper()
|
||||
)
|
||||
raise ValueError(
|
||||
f"Provider {provider_type.value} is not configured. "
|
||||
f"Please set the {missing_env} environment variable."
|
||||
)
|
||||
|
||||
return OpenAIChatProvider(
|
||||
api_key=api_key,
|
||||
model=model_id or self.DEFAULT_MODELS.get(provider_type, "gpt-4o"),
|
||||
max_retries=max_retries,
|
||||
)
|
||||
|
||||
if provider_type == ProviderType.ANTHROPIC:
|
||||
from cleveragents.providers.llm.anthropic_provider import (
|
||||
AnthropicChatProvider,
|
||||
)
|
||||
|
||||
key_attr = self.PROVIDER_KEY_ATTRS.get(provider_type)
|
||||
api_key = getattr(self._settings, key_attr, None) if key_attr else None
|
||||
if not api_key:
|
||||
missing_env = (
|
||||
key_attr.upper() if key_attr else provider_type.value.upper()
|
||||
)
|
||||
raise ValueError(
|
||||
f"Provider {provider_type.value} is not configured. "
|
||||
f"Please set the {missing_env} environment variable."
|
||||
)
|
||||
|
||||
return AnthropicChatProvider(
|
||||
api_key=api_key,
|
||||
model=model_id
|
||||
or self.DEFAULT_MODELS.get(provider_type, "claude-sonnet-4-20250514"),
|
||||
max_retries=max_retries,
|
||||
)
|
||||
|
||||
if provider_type == ProviderType.GOOGLE:
|
||||
from cleveragents.providers.llm.google_provider import GoogleChatProvider
|
||||
|
||||
|
||||
Reference in New Issue
Block a user