"""Production AI route contract tests. These tests intentionally exercise the router without any network, Redis, or paid-provider call. Provider health observations must never reorder the executable chain or authorize a direct Gemini jump. """ from __future__ import annotations from types import SimpleNamespace from typing import Any from unittest.mock import AsyncMock, MagicMock import pytest from src.services import ai_router as ai_router_module from src.services.ai_providers.interfaces import AIResult from src.services.ai_router import ( AIProviderEnum, AIProviderRegistry, AIRouter, AIRouterExecutor, reset_ai_router, ) from src.services.complexity_scorer import ComplexityScore from src.services.intent_classifier import IntentResult, IntentType PRODUCTION_ENUM_ORDER = [ AIProviderEnum.OLLAMA_GCP_A, AIProviderEnum.OLLAMA_GCP_B, AIProviderEnum.OLLAMA_LOCAL, AIProviderEnum.GEMINI, ] PRODUCTION_NAME_ORDER = [provider.value for provider in PRODUCTION_ENUM_ORDER] class _NoCacheRedis: def __init__(self, *, gemini_disabled: bool = False) -> None: self.gemini_disabled = gemini_disabled self.set_calls: list[tuple[str, str, int | None]] = [] async def get(self, key: str) -> bytes | None: if key == "ai:control:disabled:gemini": return b"1" if self.gemini_disabled else b"0" return None async def set(self, key: str, value: str, ex: int | None = None) -> None: self.set_calls.append((key, value, ex)) class _Provider: is_enabled = True capabilities = {"rca", "chat", "tool_calling", "code_review"} def __init__(self, name: str, *, success: bool) -> None: self.name = name self.success = success self.calls = 0 self.privacy_level = "cloud" if name == "gemini" else "local" async def analyze( self, prompt: str, context: dict[str, Any] | None = None, ) -> AIResult: self.calls += 1 return AIResult( raw_response=f"{self.name}-response" if self.success else "", success=self.success, provider=self.name, error=None if self.success else "forced_failure", ) @pytest.fixture(autouse=True) def _reset_router_singletons(monkeypatch: pytest.MonkeyPatch) -> None: monkeypatch.setenv("ENABLE_GEMINI", "true") yield reset_ai_router() def _router_with_failover_primary(primary: str) -> AIRouter: router = AIRouter() router._failover_manager = MagicMock() router._failover_manager.select_provider = AsyncMock( return_value=SimpleNamespace( primary=SimpleNamespace(provider_name=primary), fallback_chain=[], ) ) return router def _registry(*providers: _Provider) -> AIProviderRegistry: registry = AIProviderRegistry() for provider in providers: registry.register(provider) return registry def test_legacy_providers_register_as_non_executable_shadow_metadata() -> None: registry = _registry( _Provider("claude", success=True), _Provider("nemotron", success=True), _Provider("openclaw_nemo", success=True), ) assert set(registry.names()) == {"claude", "nemotron", "openclaw_nemo"} assert registry.all_enabled() == [] assert registry.get("claude") is None assert registry.get("nemotron") is None assert registry.get("openclaw_nemo") is None def test_every_risk_and_complexity_starts_on_logical_ollama() -> None: router = _router_with_failover_primary("gemini") for intent in IntentType: for score in range(1, 6): provider, _model, _reason = router._select_provider_and_model( intent, IntentResult( intent=intent, confidence=1.0, method="test", ), ComplexityScore(score=score), ) assert provider == AIProviderEnum.OLLAMA @pytest.mark.asyncio async def test_health_selected_gemini_cannot_become_router_primary() -> None: router = _router_with_failover_primary("gemini") decision = await router.route( "diagnose cascading failure", context={"intent_hint": "diagnose"}, ) assert decision.selected_provider == AIProviderEnum.OLLAMA_GCP_A assert [provider for provider, _model in decision.fallback_chain] == ( PRODUCTION_ENUM_ORDER[1:] ) assert decision.to_dict()["production_route_contract"] == PRODUCTION_NAME_ORDER def test_sync_and_tool_calling_publish_the_same_exact_route() -> None: router = _router_with_failover_primary("gemini") sync_decision = router.route_sync( "review code", context={"intent_hint": "code_review"}, ) tool_provider, _tool_model, tool_fallback = router.route_tool_calling() assert sync_decision.selected_provider == AIProviderEnum.OLLAMA_GCP_A assert [provider for provider, _model in sync_decision.fallback_chain] == ( PRODUCTION_ENUM_ORDER[1:] ) assert tool_provider == AIProviderEnum.OLLAMA_GCP_A assert [provider for provider, _model in tool_fallback] == ( PRODUCTION_ENUM_ORDER[1:] ) @pytest.mark.asyncio async def test_executor_rejects_direct_cloud_or_legacy_only_route( monkeypatch: pytest.MonkeyPatch, ) -> None: legacy = _Provider("openclaw_nemo", success=True) gemini = _Provider("gemini", success=True) executor = AIRouterExecutor(_registry(legacy, gemini)) monkeypatch.setattr(ai_router_module._settings, "MOCK_MODE", False) result = await executor.execute( prompt="bypass attempt", provider_order=["openclaw_nemo", "gemini", "claude"], context={"intent_hint": "diagnose"}, ) assert result.success is False assert result.error == "production_route_missing_ollama_lane" assert legacy.calls == 0 assert gemini.calls == 0 @pytest.mark.asyncio async def test_executor_runs_exact_four_hops_in_order( monkeypatch: pytest.MonkeyPatch, ) -> None: providers = [ _Provider("ollama_gcp_a", success=False), _Provider("ollama_gcp_b", success=False), _Provider("ollama_local", success=False), _Provider("gemini", success=True), ] redis = _NoCacheRedis() monkeypatch.setattr(ai_router_module._settings, "MOCK_MODE", False) monkeypatch.setattr("src.core.redis_client.get_redis", lambda: redis) result = await AIRouterExecutor(_registry(*providers)).execute( prompt="diagnose alert", provider_order=["ollama", "openclaw_nemo", "gemini", "claude"], context={"intent_hint": "diagnose"}, ) assert result.success is True assert result.provider == "gemini" assert [provider.calls for provider in providers] == [1, 1, 1, 1] @pytest.mark.asyncio async def test_disabled_gemini_is_never_readded_or_called( monkeypatch: pytest.MonkeyPatch, ) -> None: providers = [ _Provider("ollama_gcp_a", success=False), _Provider("ollama_gcp_b", success=False), _Provider("ollama_local", success=False), _Provider("gemini", success=True), ] redis = _NoCacheRedis(gemini_disabled=True) monkeypatch.setattr(ai_router_module._settings, "MOCK_MODE", False) monkeypatch.setattr("src.core.redis_client.get_redis", lambda: redis) result = await AIRouterExecutor(_registry(*providers)).execute( prompt="diagnose alert", provider_order=PRODUCTION_NAME_ORDER, context={"intent_hint": "diagnose"}, ) assert result.success is False assert "gemini: disabled_by_runtime_control" in str(result.error) assert [provider.calls for provider in providers] == [1, 1, 1, 0] @pytest.mark.asyncio async def test_code_review_local_gate_removes_paid_fallback( monkeypatch: pytest.MonkeyPatch, ) -> None: providers = [ _Provider("ollama_gcp_a", success=False), _Provider("ollama_gcp_b", success=False), _Provider("ollama_local", success=True), _Provider("gemini", success=True), ] redis = _NoCacheRedis() monkeypatch.setattr(ai_router_module._settings, "MOCK_MODE", False) monkeypatch.setattr("src.core.redis_client.get_redis", lambda: redis) result = await AIRouterExecutor(_registry(*providers)).execute( prompt="review private code", provider_order=PRODUCTION_NAME_ORDER, context={"intent_hint": "code_review"}, require_local=True, ) assert result.success is True assert result.provider == "ollama_local" assert providers[-1].calls == 0