import pytest from proteus.providers import FakeProvider, make_provider, available_providers from proteus.providers.factory import _REGISTRY def test_fake_spec_builds_fakeprovider_with_model_name(): p = make_provider("fake:smoke-1") assert isinstance(p, FakeProvider) assert p.model_name == "smoke-1" # It is usable offline without arguments beyond the spec. assert p.complete([]).text # returns the canned scripted response def test_fake_spec_without_model_defaults_name(): assert make_provider("fake:").model_name == "fake" def test_spec_without_colon_raises(): with pytest.raises(ValueError, match=":"): make_provider("anthropic") # missing ':model' def test_unknown_provider_raises_listing_available(): with pytest.raises(ValueError, match="Unknown provider"): make_provider("bogus:whatever") def test_available_providers_contains_cloud_and_fake(): names = available_providers() assert {"openai", "anthropic", "gemini", "ollama", "fake"} <= set(names) def test_registry_resolves_to_module_class_strings_without_importing(): # Resolution is by string (lazy import) so this works with no SDK installed. assert _REGISTRY["anthropic"] == ("proteus.providers.anthropic_provider", "AnthropicProvider") assert _REGISTRY["openai"] == ("proteus.providers.openai", "OpenAIProvider") assert _REGISTRY["gemini"] == ("proteus.providers.gemini", "GeminiProvider") assert _REGISTRY["ollama"] == ("proteus.providers.ollama_cloud", "OllamaCloudProvider") def test_model_with_colons_is_preserved(): # Ollama-style models contain ':' — only the FIRST ':' splits name from model. p = make_provider("fake:qwen3.5:cloud") assert p.model_name == "qwen3.5:cloud"