import pytest from agent.core import model_switcher from agent.core.local_models import is_local_model_id def test_local_model_helper_accepts_supported_prefixes(): assert is_local_model_id("ollama/llama3.1:8b") assert is_local_model_id("vllm/meta-llama/Llama-3.1-8B-Instruct") assert is_local_model_id("lm_studio/google/gemma-3-4b") assert is_local_model_id("llamacpp/unsloth/Qwen3.5-2B") def test_model_switcher_accepts_supported_local_prefixes(): assert model_switcher.is_valid_model_id("ollama/llama3.1:8b") assert model_switcher.is_valid_model_id("vllm/meta-llama/Llama-3.1-8B") assert model_switcher.is_valid_model_id("lm_studio/google/gemma-3-4b") assert model_switcher.is_valid_model_id("llamacpp/llama-3.1-8b") def test_model_switcher_rejects_empty_or_whitespace_local_ids(): assert not model_switcher.is_valid_model_id("ollama/") assert not model_switcher.is_valid_model_id("vllm/") assert not model_switcher.is_valid_model_id("lm_studio/") assert not model_switcher.is_valid_model_id("llamacpp/") assert not model_switcher.is_valid_model_id("ollama/llama 3.1") def test_openai_compat_prefix_is_not_supported(): assert not model_switcher.is_valid_model_id("openai-compat/custom-model") def test_local_models_skip_hf_router_catalog_output(): class NoPrintConsole: def print(self, *args, **kwargs): raise AssertionError("local models should not print HF catalog info") assert model_switcher._print_hf_routing_info( "ollama/llama3.1:8b", NoPrintConsole(), ) @pytest.mark.asyncio async def test_probe_and_switch_local_model_uses_no_effort(monkeypatch): calls = [] async def fake_acompletion(**kwargs): calls.append(kwargs) return object() monkeypatch.setattr(model_switcher, "acompletion", fake_acompletion) class Config: model_name = "openai/gpt-5.5" reasoning_effort = "max" class Session: def __init__(self): self.model_id = None self.model_effective_effort = {} def update_model(self, model_id): self.model_id = model_id class Console: def print(self, *args, **kwargs): pass session = Session() await model_switcher.probe_and_switch_model( "ollama/llama3.1:8b", Config(), session, Console(), hf_token=None, ) assert session.model_id == "ollama/llama3.1:8b" assert session.model_effective_effort["ollama/llama3.1:8b"] is None assert calls[0]["model"] == "openai/llama3.1:8b" assert "reasoning_effort" not in calls[0] assert "extra_body" not in calls[0] @pytest.mark.asyncio async def test_probe_and_switch_local_model_rejects_probe_errors(monkeypatch): async def failing_acompletion(**kwargs): raise ConnectionRefusedError("no server") monkeypatch.setattr(model_switcher, "acompletion", failing_acompletion) class Config: model_name = "openai/gpt-5.5" reasoning_effort = None class Session: def __init__(self): self.model_id = None self.model_effective_effort = {} def update_model(self, model_id): self.model_id = model_id class Console: def print(self, *args, **kwargs): pass config = Config() session = Session() await model_switcher.probe_and_switch_model( "ollama/llama3.1:8b", config, session, Console(), hf_token=None, ) assert config.model_name == "openai/gpt-5.5" assert session.model_id is None assert "ollama/llama3.1:8b" not in session.model_effective_effort