diff --git a/tests/agent/test_image_routing.py b/tests/agent/test_image_routing.py index 2019bc182d0..6f9b9b292f6 100644 --- a/tests/agent/test_image_routing.py +++ b/tests/agent/test_image_routing.py @@ -248,9 +248,24 @@ class TestLookupSupportsVisionOverride: assert _lookup_supports_vision("anthropic", "claude-sonnet-4", {}) is True def test_no_override_no_models_dev_entry_returns_none(self): - with patch("agent.models_dev.get_model_capabilities", return_value=None): + with patch("agent.models_dev.get_model_capabilities", return_value=None), \ + patch("agent.image_routing._should_probe_ollama_vision", return_value=False): assert _lookup_supports_vision("custom", "my-llava", {}) is None + def test_ollama_probe_when_models_dev_missing(self): + cfg = {"model": {"base_url": "http://localhost:11434/v1"}} + with patch("agent.models_dev.get_model_capabilities", return_value=None), \ + patch("agent.image_routing._should_probe_ollama_vision", return_value=True), \ + patch("agent.model_metadata.query_ollama_supports_vision", return_value=True): + assert _lookup_supports_vision("ollama", "gemma4:e2b", cfg) is True + + def test_ollama_probe_false_for_text_only_model(self): + cfg = {"model": {"base_url": "http://localhost:11434/v1"}} + with patch("agent.models_dev.get_model_capabilities", return_value=None), \ + patch("agent.image_routing._should_probe_ollama_vision", return_value=True), \ + patch("agent.model_metadata.query_ollama_supports_vision", return_value=False): + assert _lookup_supports_vision("custom", "gemma4:31b", cfg) is False + def test_cfg_none_falls_back_to_models_dev(self): # Caller didn't pass cfg at all — old call sites must still work. with patch("agent.models_dev.get_model_capabilities", return_value=None): diff --git a/tests/test_ollama_num_ctx.py b/tests/test_ollama_num_ctx.py index 94b1d7fd6a0..00e96b170a9 100644 --- a/tests/test_ollama_num_ctx.py +++ b/tests/test_ollama_num_ctx.py @@ -8,7 +8,7 @@ Covers: from unittest.mock import patch, MagicMock -from agent.model_metadata import query_ollama_num_ctx +from agent.model_metadata import query_ollama_num_ctx, query_ollama_supports_vision # ═══════════════════════════════════════════════════════════════════════ @@ -132,3 +132,45 @@ class TestQueryOllamaNumCtx: result = query_ollama_num_ctx("model", "http://localhost:11434") assert result is None + + +class TestQueryOllamaSupportsVision: + """Test Ollama /api/show vision capability detection.""" + + def test_returns_true_when_capabilities_include_vision(self): + show_data = {"capabilities": ["completion", "vision"]} + mock_ctx, _ = _mock_httpx_client(show_data) + + with patch("agent.model_metadata.detect_local_server_type", return_value="ollama"): + import httpx + with patch.object(httpx, "Client", return_value=mock_ctx): + result = query_ollama_supports_vision("gemma4:e2b", "http://localhost:11434/v1") + + assert result is True + + def test_returns_false_when_capabilities_exclude_vision(self): + show_data = {"capabilities": ["completion", "tools"]} + mock_ctx, _ = _mock_httpx_client(show_data) + + with patch("agent.model_metadata.detect_local_server_type", return_value="ollama"): + import httpx + with patch.object(httpx, "Client", return_value=mock_ctx): + result = query_ollama_supports_vision("gemma4:31b", "http://localhost:11434/v1") + + assert result is False + + def test_falls_back_to_model_info_vision_block_count(self): + show_data = {"model_info": {"gemma3.vision.block_count": 27}} + mock_ctx, _ = _mock_httpx_client(show_data) + + with patch("agent.model_metadata.detect_local_server_type", return_value="ollama"): + import httpx + with patch.object(httpx, "Client", return_value=mock_ctx): + result = query_ollama_supports_vision("llava", "http://localhost:11434") + + assert result is True + + def test_returns_none_for_non_ollama_server(self): + with patch("agent.model_metadata.detect_local_server_type", return_value="vllm"): + result = query_ollama_supports_vision("llava", "http://localhost:8000/v1") + assert result is None