""" Backend adaptation at the provider choke point (workspace T-137). The flavor globals are set directly so the tests are deterministic regardless of which backend is reachable; the wire facts the probe relies on are the wrapper's contract, pinned in its own repo. """ import pytest from src.ollama import provider from src.shared.config import get_settings @pytest.fixture(autouse=True) def reset_flavor(monkeypatch): """Each test states its flavor; nothing leaks between them.""" monkeypatch.setattr(provider, "_local_flavor", None) @pytest.mark.anyio async def test_ollama_keeps_the_advisory_nudge(monkeypatch): monkeypatch.setattr(provider, "_local_flavor", "ollama") kwargs = await provider._adapt_to_backend( {"extra_body": {"tool_choice": "required"}} ) assert kwargs["extra_body"] == {"tool_choice": "required"} @pytest.mark.anyio async def test_wrapper_strips_the_nudge_and_names_the_session(monkeypatch): # tool_choice "required" is enforced by llama-server — through the # wrapper it is the unbreakable tool loop, so it must not pass. monkeypatch.setattr(provider, "_local_flavor", "boilerroom") kwargs = await provider._adapt_to_backend( {"extra_body": {"tool_choice": "required"}} ) extra = kwargs["extra_body"] assert "tool_choice" not in extra assert extra["session"] == "webber" assert extra["eviction_order"] == 20 @pytest.mark.anyio async def test_bare_llama_server_strips_without_naming(monkeypatch): monkeypatch.setattr(provider, "_local_flavor", "llama-server") kwargs = await provider._adapt_to_backend( {"extra_body": {"tool_choice": "required"}} ) assert "extra_body" not in kwargs @pytest.mark.anyio async def test_rank_and_name_come_from_settings(monkeypatch): monkeypatch.setattr(provider, "_local_flavor", "boilerroom") settings = get_settings() monkeypatch.setattr(settings, "backend_session_name", "webber-test") monkeypatch.setattr(settings, "backend_session_rank", 7) kwargs = await provider._adapt_to_backend({}) assert kwargs["extra_body"] == {"session": "webber-test", "eviction_order": 7} @pytest.mark.anyio async def test_other_extension_fields_survive_adaptation(monkeypatch): monkeypatch.setattr(provider, "_local_flavor", "boilerroom") kwargs = await provider._adapt_to_backend({"extra_body": {"marker": 1}}) assert kwargs["extra_body"]["marker"] == 1 assert kwargs["extra_body"]["session"] == "webber" def test_body_signals_are_logged(monkeypatch): # The httpx event-hook variant never fired under the SDK; the body # read must demonstrably log, or the signal passes silently again. calls = [] class StubLogger: def info(self, msg): calls.append(("info", msg)) def warning(self, msg): calls.append(("warning", msg)) monkeypatch.setattr(provider, "logger", StubLogger()) class Busy: model_extra = {"balancing": [{"parked": "librarian"}], "compaction_due": True} provider._log_wrapper_signals(Busy()) assert any(kind == "info" and "parked" in msg for kind, msg in calls) assert any(kind == "warning" for kind, msg in calls) calls.clear() class Quiet: model_extra = {"balancing": [], "compaction_due": False} provider._log_wrapper_signals(Quiet()) assert calls == [] def test_provider_serves_the_sanitized_client(): # The whole mechanism rides on `.client` returning OUR instance: # assigning a lookalike attribute after super().__init__ built its # own client is how the sanitizer silently died until 2026-09-13. p = provider.WebberOllamaProvider(base_url="http://127.0.0.1:9/v1") assert isinstance(p.client, provider._SanitizedAsyncOpenAI) @pytest.mark.anyio async def test_probe_failure_answers_ollama_without_caching(monkeypatch): # A backend that is down at first call must be re-probed later — # caching "ollama" forever would nudge llama-server into the tool # loop the moment the wrapper came back. settings = get_settings() monkeypatch.setattr(settings, "ollama_url", "http://127.0.0.1:9") flavor = await provider._detect_flavor() assert flavor == "ollama" assert provider._local_flavor is None