From 3323b9d90929593bfa2deacd2060b8928efa0b49 Mon Sep 17 00:00:00 2001 From: wylab Date: Fri, 13 Feb 2026 13:05:51 +0100 Subject: [PATCH] feat(providers): add create_provider factory with OAuth detection Co-Authored-By: Claude Opus 4.6 --- nanobot/providers/__init__.py | 43 +++++++++++++++++++++++++++++++--- tests/test_provider_factory.py | 32 +++++++++++++++++++++++++ 2 files changed, 72 insertions(+), 3 deletions(-) create mode 100644 tests/test_provider_factory.py diff --git a/nanobot/providers/__init__.py b/nanobot/providers/__init__.py index ceff8fa..e5b3950 100644 --- a/nanobot/providers/__init__.py +++ b/nanobot/providers/__init__.py @@ -1,6 +1,43 @@ -"""LLM provider abstraction module.""" +"""Provider module exports.""" -from nanobot.providers.base import LLMProvider, LLMResponse +from nanobot.providers.base import LLMProvider, LLMResponse, ToolCallRequest from nanobot.providers.litellm_provider import LiteLLMProvider +from nanobot.providers.anthropic_oauth import AnthropicOAuthProvider +from nanobot.providers.registry import should_use_oauth_provider -__all__ = ["LLMProvider", "LLMResponse", "LiteLLMProvider"] +__all__ = [ + "LLMProvider", + "LLMResponse", + "ToolCallRequest", + "LiteLLMProvider", + "AnthropicOAuthProvider", + "create_provider", +] + + +def create_provider( + api_key: str, + model: str, + api_base: str | None = None, + extra_headers: dict[str, str] | None = None, + provider_name: str | None = None, +) -> LLMProvider: + """Factory function to create appropriate provider. + + Automatically selects AnthropicOAuthProvider for OAuth tokens, + LiteLLMProvider for everything else. + """ + if should_use_oauth_provider(api_key, model): + return AnthropicOAuthProvider( + oauth_token=api_key, + default_model=model, + api_base=api_base, + ) + + return LiteLLMProvider( + api_key=api_key, + api_base=api_base, + default_model=model, + extra_headers=extra_headers, + provider_name=provider_name, + ) diff --git a/tests/test_provider_factory.py b/tests/test_provider_factory.py new file mode 100644 index 0000000..4d25979 --- /dev/null +++ b/tests/test_provider_factory.py @@ -0,0 +1,32 @@ +"""Test provider factory with OAuth support.""" +import pytest +from nanobot.providers import create_provider +from nanobot.providers.anthropic_oauth import AnthropicOAuthProvider +from nanobot.providers.litellm_provider import LiteLLMProvider + + +def test_create_provider_oauth_token(): + """OAuth tokens should create AnthropicOAuthProvider.""" + provider = create_provider( + api_key="sk-ant-oat01-test-token", + model="anthropic/claude-opus-4-5" + ) + assert isinstance(provider, AnthropicOAuthProvider) + + +def test_create_provider_regular_key(): + """Regular API keys should create LiteLLMProvider.""" + provider = create_provider( + api_key="sk-ant-api03-regular-key", + model="anthropic/claude-opus-4-5" + ) + assert isinstance(provider, LiteLLMProvider) + + +def test_create_provider_openrouter(): + """OpenRouter keys should create LiteLLMProvider.""" + provider = create_provider( + api_key="sk-or-v1-xxx", + model="anthropic/claude-opus-4-5" + ) + assert isinstance(provider, LiteLLMProvider)