[claude] Document and validate AirLLM Apple Silicon requirements (#1284) (#1298)
Some checks failed
Tests / lint (push) Has been cancelled
Tests / test (push) Has been cancelled

This commit was merged in pull request #1298.
This commit is contained in:
2026-03-24 01:52:16 +00:00
parent fc0a94202f
commit 00ef4fbd22
5 changed files with 178 additions and 3 deletions

View File

@@ -0,0 +1,135 @@
"""Unit tests for AirLLM backend graceful degradation.
Verifies that setting TIMMY_MODEL_BACKEND=airllm on non-Apple-Silicon hardware
(Intel Mac, Linux, Windows) or when the airllm package is not installed
falls back to the Ollama backend without crashing.
Refs #1284
"""
import sys
from unittest.mock import MagicMock, patch
import pytest
pytestmark = pytest.mark.unit
class TestIsAppleSilicon:
"""is_apple_silicon() correctly identifies the host platform."""
def test_returns_true_on_arm64_darwin(self):
from timmy.backends import is_apple_silicon
with patch("platform.system", return_value="Darwin"), patch(
"platform.machine", return_value="arm64"
):
assert is_apple_silicon() is True
def test_returns_false_on_intel_mac(self):
from timmy.backends import is_apple_silicon
with patch("platform.system", return_value="Darwin"), patch(
"platform.machine", return_value="x86_64"
):
assert is_apple_silicon() is False
def test_returns_false_on_linux(self):
from timmy.backends import is_apple_silicon
with patch("platform.system", return_value="Linux"), patch(
"platform.machine", return_value="x86_64"
):
assert is_apple_silicon() is False
def test_returns_false_on_windows(self):
from timmy.backends import is_apple_silicon
with patch("platform.system", return_value="Windows"), patch(
"platform.machine", return_value="AMD64"
):
assert is_apple_silicon() is False
class TestAirLLMGracefulDegradation:
"""create_timmy(backend='airllm') falls back to Ollama on unsupported platforms."""
def _make_fake_ollama_agent(self):
"""Return a lightweight stub that satisfies the Agno Agent interface."""
agent = MagicMock()
agent.run = MagicMock(return_value=MagicMock(content="ok"))
return agent
def test_falls_back_to_ollama_on_non_apple_silicon(self, caplog):
"""On Intel/Linux, airllm backend logs a warning and creates an Ollama agent."""
import logging
from timmy.agent import create_timmy
fake_agent = self._make_fake_ollama_agent()
with (
patch("timmy.backends.is_apple_silicon", return_value=False),
patch("timmy.agent._create_ollama_agent", return_value=fake_agent) as mock_create,
patch("timmy.agent._resolve_model_with_fallback", return_value=("qwen3:8b", False)),
patch("timmy.agent._check_model_available", return_value=True),
patch("timmy.agent._build_tools_list", return_value=[]),
patch("timmy.agent._build_prompt", return_value="test prompt"),
caplog.at_level(logging.WARNING, logger="timmy.agent"),
):
result = create_timmy(backend="airllm")
assert result is fake_agent
mock_create.assert_called_once()
assert "Apple Silicon" in caplog.text
def test_falls_back_to_ollama_when_airllm_not_installed(self, caplog):
"""When the airllm package is missing, log a warning and use Ollama."""
import logging
from timmy.agent import create_timmy
fake_agent = self._make_fake_ollama_agent()
# Simulate Apple Silicon + missing airllm package
def _import_side_effect(name, *args, **kwargs):
if name == "airllm":
raise ImportError("No module named 'airllm'")
return original_import(name, *args, **kwargs)
original_import = __builtins__["__import__"] if isinstance(__builtins__, dict) else __import__
with (
patch("timmy.backends.is_apple_silicon", return_value=True),
patch("builtins.__import__", side_effect=_import_side_effect),
patch("timmy.agent._create_ollama_agent", return_value=fake_agent) as mock_create,
patch("timmy.agent._resolve_model_with_fallback", return_value=("qwen3:8b", False)),
patch("timmy.agent._check_model_available", return_value=True),
patch("timmy.agent._build_tools_list", return_value=[]),
patch("timmy.agent._build_prompt", return_value="test prompt"),
caplog.at_level(logging.WARNING, logger="timmy.agent"),
):
result = create_timmy(backend="airllm")
assert result is fake_agent
mock_create.assert_called_once()
assert "airllm" in caplog.text.lower() or "AirLLM" in caplog.text
def test_airllm_backend_does_not_raise(self):
"""create_timmy(backend='airllm') never raises — it degrades gracefully."""
from timmy.agent import create_timmy
fake_agent = self._make_fake_ollama_agent()
with (
patch("timmy.backends.is_apple_silicon", return_value=False),
patch("timmy.agent._create_ollama_agent", return_value=fake_agent),
patch("timmy.agent._resolve_model_with_fallback", return_value=("qwen3:8b", False)),
patch("timmy.agent._check_model_available", return_value=True),
patch("timmy.agent._build_tools_list", return_value=[]),
patch("timmy.agent._build_prompt", return_value="test prompt"),
):
# Should not raise under any circumstances
result = create_timmy(backend="airllm")
assert result is not None