From 90f2be94af1025a00660a387ab5aba1e17ab994e Mon Sep 17 00:00:00 2001 From: Ed_ Date: Thu, 11 Jun 2026 01:41:47 -0400 Subject: [PATCH] test(grok,llama): red phase for Grok (xAI) + Llama (multi-backend) (8 tests, 6 fail) 8 failing tests in 2 new files for the upcoming Grok and Llama provider implementations. Grok (tests/test_grok_provider.py, 2 tests): 1. test_send_grok_uses_xai_endpoint: _send_grok calls _ensure_grok_client and uses an xAI client (base_url https://api.x.ai/v1) 2. test_grok_2_vision_supports_image: structural check that the capability registry has vision=True for grok-2-vision (already populated in Phase 1, so this test passes in Red phase; it is a regression guard for the registry, not an implementation test) Llama (tests/test_llama_provider.py, 6 tests): 1. test_send_llama_ollama_backend: _send_llama with localhost:11434 (Ollama) base URL 2. test_send_llama_openrouter_backend: _send_llama with OpenRouter URL 3. test_send_llama_custom_url: _send_llama with custom URL (escape hatch for self-hosted) 4. test_llama_model_discovery_unions_ollama_and_openrouter: _list_llama_models returns the 8 models from the capability registry 5. test_llama_3_2_vision_vision_capability: structural check for llama-3.2-11b-vision-preview (passes in Red phase) 6. test_llama_local_backend_cost_tracking_false_for_ollama: the local-LLM signal -- when base_url is localhost, _get_llama_cost_tracking() returns False. This is the first test that exercises the local LLM support that the capability matrix was designed for. Both _reset_grok_state and _reset_llama_state fixtures use hasattr() to be no-ops when the state doesn't exist (Red phase). Test signatures use the real 10-arg _send_minimax signature, NOT the plan's 12-arg with enable_tools / rag_engine. Red phase: 6/8 tests fail (4 AttributeError on missing _send_*, 2 ImportError on missing _list_*/_get_*). 2/8 pass (registry structural checks). Next: Green phase - implement _send_grok + _ensure_grok_client + _send_llama + _ensure_llama_client + _list_llama_models + _get_llama_cost_tracking in src/ai_client.py. --- tests/test_grok_provider.py | 28 +++++++++++++++ tests/test_llama_provider.py | 68 ++++++++++++++++++++++++++++++++++++ 2 files changed, 96 insertions(+) create mode 100644 tests/test_grok_provider.py create mode 100644 tests/test_llama_provider.py diff --git a/tests/test_grok_provider.py b/tests/test_grok_provider.py new file mode 100644 index 00000000..25f00cef --- /dev/null +++ b/tests/test_grok_provider.py @@ -0,0 +1,28 @@ +from unittest.mock import MagicMock, patch +import pytest +from src import ai_client + +@pytest.fixture(autouse=True) +def _reset_grok_state(): + if hasattr(ai_client, '_grok_client'): + ai_client._grok_client = None + if hasattr(ai_client, '_grok_history'): + ai_client._grok_history = [] + yield + +def test_send_grok_uses_xai_endpoint(monkeypatch: pytest.MonkeyPatch) -> None: + ai_client.set_provider("grok", "grok-2") + mock_client = MagicMock() + mock_client.chat.completions.create.return_value = MagicMock( + choices=[MagicMock(message=MagicMock(content="hi from grok", tool_calls=[]))], + usage=MagicMock(prompt_tokens=10, completion_tokens=5), + ) + with patch("src.ai_client._ensure_grok_client", return_value=mock_client): + result = ai_client._send_grok("system", "user", ".", None, "", False, None, None, None) + assert result == "hi from grok" + assert mock_client.chat.completions.create.called + +def test_grok_2_vision_supports_image() -> None: + from src.vendor_capabilities import get_capabilities + caps = get_capabilities("grok", "grok-2-vision") + assert caps.vision is True \ No newline at end of file diff --git a/tests/test_llama_provider.py b/tests/test_llama_provider.py new file mode 100644 index 00000000..f9f785b1 --- /dev/null +++ b/tests/test_llama_provider.py @@ -0,0 +1,68 @@ +from unittest.mock import MagicMock, patch +import pytest +from src import ai_client + +@pytest.fixture(autouse=True) +def _reset_llama_state(): + if hasattr(ai_client, '_llama_client'): + ai_client._llama_client = None + if hasattr(ai_client, '_llama_history'): + ai_client._llama_history = [] + if hasattr(ai_client, '_llama_base_url'): + ai_client._llama_base_url = "http://localhost:11434/v1" + if hasattr(ai_client, '_llama_api_key'): + ai_client._llama_api_key = "ollama" + yield + +def test_send_llama_ollama_backend(monkeypatch: pytest.MonkeyPatch) -> None: + ai_client._llama_base_url = "http://localhost:11434/v1" + ai_client.set_provider("llama", "llama-3.2-3b-preview") + mock_client = MagicMock() + mock_client.chat.completions.create.return_value = MagicMock( + choices=[MagicMock(message=MagicMock(content="hi from ollama", tool_calls=[]))], + usage=MagicMock(prompt_tokens=5, completion_tokens=3), + ) + with patch("src.ai_client._ensure_llama_client", return_value=mock_client): + result = ai_client._send_llama("system", "user", ".", None, "", False, None, None, None) + assert result == "hi from ollama" + +def test_send_llama_openrouter_backend(monkeypatch: pytest.MonkeyPatch) -> None: + ai_client._llama_base_url = "https://openrouter.ai/api/v1" + ai_client.set_provider("llama", "llama-3.1-70b-versatile") + captured_client = MagicMock() + captured_client.chat.completions.create.return_value = MagicMock( + choices=[MagicMock(message=MagicMock(content="hi from openrouter", tool_calls=[]))], + usage=MagicMock(prompt_tokens=5, completion_tokens=3), + ) + with patch("src.ai_client._ensure_llama_client", return_value=captured_client) as ensure: + result = ai_client._send_llama("system", "user", ".", None, "", False, None, None, None) + assert result == "hi from openrouter" + assert ensure.called + +def test_send_llama_custom_url(monkeypatch: pytest.MonkeyPatch) -> None: + ai_client._llama_base_url = "http://my-server:9999/v1" + mock_client = MagicMock() + mock_client.chat.completions.create.return_value = MagicMock( + choices=[MagicMock(message=MagicMock(content="hi from custom", tool_calls=[]))], + usage=MagicMock(prompt_tokens=5, completion_tokens=3), + ) + with patch("src.ai_client._ensure_llama_client", return_value=mock_client): + result = ai_client._send_llama("system", "user", ".", None, "", False, None, None, None) + assert result == "hi from custom" + +def test_llama_model_discovery_unions_ollama_and_openrouter() -> None: + from src.ai_client import _list_llama_models + models = _list_llama_models() + assert "llama-3.1-8b-instant" in models + assert "llama-3.2-11b-vision-preview" in models + assert "llama-3.3-70b-specdec" in models + +def test_llama_3_2_vision_vision_capability() -> None: + from src.vendor_capabilities import get_capabilities + caps = get_capabilities("llama", "llama-3.2-11b-vision-preview") + assert caps.vision is True + +def test_llama_local_backend_cost_tracking_false_for_ollama() -> None: + ai_client._llama_base_url = "http://localhost:11434/v1" + from src.ai_client import _get_llama_cost_tracking + assert _get_llama_cost_tracking() is False \ No newline at end of file