"""Model-provider registry: configure several vendors at once, select by name, default selection, and the null fail-loud behavior. No network — we only assert which provider the factory returns and that null providers raise. """ import pytest from app.api.deps import ( build_embedding_providers, build_llm_providers, get_embedding_provider, get_llm_provider, ) from app.core.config import get_settings from app.integrations.models.anthropic_provider import AnthropicLLMProvider from app.integrations.models.base import ModelProviderNotConfigured from app.integrations.models.null import NullEmbeddingProvider, NullLLMProvider from app.integrations.models.openai_compat import ( OpenAICompatibleEmbeddingProvider, OpenAICompatibleLLMProvider, ) def _reset(monkeypatch): s = get_settings() for attr, val in { "default_llm_provider": "null", "default_embedding_provider": "null", "anthropic_api_key": None, "openai_api_key": None, "xai_api_key": None, "ollama_enabled": False, }.items(): monkeypatch.setattr(s, attr, val) return s async def test_default_is_null_and_fails_loud(monkeypatch): _reset(monkeypatch) provider = get_llm_provider() assert isinstance(provider, NullLLMProvider) with pytest.raises(ModelProviderNotConfigured): await provider.complete(prompt="hello") assert isinstance(get_embedding_provider(), NullEmbeddingProvider) async def test_multiple_llm_providers_at_once(monkeypatch): s = _reset(monkeypatch) monkeypatch.setattr(s, "anthropic_api_key", "sk-ant-x") monkeypatch.setattr(s, "openai_api_key", "sk-openai-x") monkeypatch.setattr(s, "xai_api_key", "xai-x") monkeypatch.setattr(s, "ollama_enabled", True) monkeypatch.setattr(s, "default_llm_provider", "anthropic") registry = build_llm_providers() assert set(registry) == {"anthropic", "openai", "xai", "ollama"} # Select any by name. assert isinstance(get_llm_provider("anthropic"), AnthropicLLMProvider) assert isinstance(get_llm_provider("openai"), OpenAICompatibleLLMProvider) assert isinstance(get_llm_provider("xai"), OpenAICompatibleLLMProvider) assert isinstance(get_llm_provider("ollama"), OpenAICompatibleLLMProvider) # Default resolves to the configured default. assert isinstance(get_llm_provider(), AnthropicLLMProvider) # Unknown name → null. assert isinstance(get_llm_provider("nope"), NullLLMProvider) async def test_provider_disabled_without_credentials(monkeypatch): s = _reset(monkeypatch) monkeypatch.setattr(s, "default_llm_provider", "openai") # default names openai… # …but no openai key → registry empty → null fallback. assert build_llm_providers() == {} assert isinstance(get_llm_provider(), NullLLMProvider) async def test_embedding_providers(monkeypatch): s = _reset(monkeypatch) monkeypatch.setattr(s, "openai_api_key", "sk-openai-x") monkeypatch.setattr(s, "ollama_enabled", True) monkeypatch.setattr(s, "default_embedding_provider", "openai") registry = build_embedding_providers() assert set(registry) == {"openai", "ollama"} assert isinstance(get_embedding_provider(), OpenAICompatibleEmbeddingProvider) assert isinstance(get_embedding_provider("ollama"), OpenAICompatibleEmbeddingProvider)