from __future__ import annotations import json from pathlib import Path import pytest import yaml from src.core.config import Settings REPO_ROOT = Path(__file__).resolve().parents[3] def _load(path: str) -> dict: with (REPO_ROOT / path).open(encoding="utf-8") as handle: return next(yaml.safe_load_all(handle)) PRODUCTION_PROVIDER_ORDER = [ "ollama_gcp_a", "ollama_gcp_b", "ollama_local", "gemini", ] def test_prod_and_dev_publish_exact_four_hop_fallback() -> None: for path in ( "k8s/awoooi-prod/04-configmap.yaml", "k8s/awoooi-dev/02-configmap.yaml", ): data = _load(path)["data"] assert json.loads(data["AI_FALLBACK_ORDER"]) == PRODUCTION_PROVIDER_ORDER assert data["ALERT_AI_ENFORCE_OLLAMA_FIRST"] == "true" assert data["ALERT_AI_STRICT_PROVIDER_CHAIN"] == "true" assert data["GEMINI_MODEL"] == "gemini-2.5-flash-lite" assert data["GEMINI_DAILY_QUOTA"] == "500" assert data["GEMINI_RPM_LIMIT"] == "10" assert data["GEMINI_DAILY_TOKEN_LIMIT"] == "100000" assert data["GEMINI_DAILY_COST_LIMIT_USD"] == "5.0" assert data["GEMINI_TOTAL_COST_LIMIT_USD"] == "5.0" assert data["GEMINI_COST_ALERT_THRESHOLD_USD"] == "4.0" def test_model_registry_publishes_only_supported_paid_fallback_model() -> None: with (REPO_ROOT / "apps/api/models.json").open(encoding="utf-8") as handle: models = json.load(handle) gemini_models = models["providers"]["gemini"]["models"] assert set(gemini_models.values()) == {"gemini-2.5-flash-lite"} gemini = models["providers"]["gemini"] assert gemini["cost"] == { "input_usd_per_million": 0.1, "output_usd_per_million": 0.4, "conservative_per_1k_tokens": 0.0004, "currency": "USD", "pricing_source": ( "https://ai.google.dev/gemini-api/docs/pricing" "#gemini-2.5-flash-lite" ), "pricing_version": "google-ai-standard-text-2026-07-14", "pricing_checked_at": "2026-07-14", } assert gemini["auth"] == { "type": "api_key", "env_var": "GEMINI_API_KEY", "header": "x-goog-api-key", } assert gemini["rate_limits"]["daily_requests"] == 500 assert gemini["rate_limits"]["daily_tokens"] == 100000 assert gemini["rate_limits"]["requests_per_minute"] == 10 assert models["fallback_order"] == PRODUCTION_PROVIDER_ORDER assert models["tool_calling_fallback_order"] == PRODUCTION_PROVIDER_ORDER assert models["production_route"]["provider_order"] == PRODUCTION_PROVIDER_ORDER for provider in ("claude", "nvidia"): assert models["providers"][provider]["production_executable"] is False assert models["providers"][provider]["mode"] == ( "non_executable_shadow_metadata_only" ) def test_capabilities_publish_route_and_shadow_only_legacy_providers() -> None: with (REPO_ROOT / "capabilities.json").open(encoding="utf-8") as handle: capabilities = json.load(handle) ai_providers = capabilities["ai_providers"] assert ai_providers["fallback_order"] == PRODUCTION_PROVIDER_ORDER assert [provider["name"] for provider in ai_providers["providers"]] == ( PRODUCTION_PROVIDER_ORDER ) assert { provider["name"] for provider in ai_providers["shadow_metadata_only"] } == { "claude", "nemotron", "nvidia", "openclaw", "openclaw_nemo", "ollama_tool", } assert all( provider["production_executable"] is False for provider in ai_providers["shadow_metadata_only"] ) def test_prod_runtime_endpoints_and_nemotron_override_match_strict_chain() -> None: deployment = _load("k8s/awoooi-prod/06-deployment-api.yaml") env = { item["name"]: item.get("value") for item in deployment["spec"]["template"]["spec"]["containers"][0]["env"] } assert env["OLLAMA_URL"] == "http://192.168.0.110:11435" assert env["OLLAMA_SECONDARY_URL"] == "http://192.168.0.110:11436" assert env["OLLAMA_FALLBACK_URL"] == "http://192.168.0.110:11437" assert env["ENABLE_NEMOTRON_COLLABORATION"] == "false" def test_config_parser_rejects_route_reordering_or_provider_insertion() -> None: assert Settings.parse_ai_fallback(PRODUCTION_PROVIDER_ORDER) == ( PRODUCTION_PROVIDER_ORDER ) assert Settings.parse_ai_fallback('["ollama","gemini"]') == ( PRODUCTION_PROVIDER_ORDER ) with pytest.raises(ValueError, match="must be exactly"): Settings.parse_ai_fallback(["gemini"]) with pytest.raises(ValueError, match="must be exactly"): Settings.parse_ai_fallback( ["ollama_gcp_a", "openclaw_nemo", "gemini"] )