import json import os import shutil import subprocess from collections.abc import Mapping from pathlib import Path from typing import Any, cast import pytest from free_claude_code.cli.launchers.codex_model_catalog import ( build_codex_model_catalog, write_codex_model_catalog, ) def _models_payload(*model_ids: str) -> dict[str, Any]: return { "data": [ { "id": model_id, "display_name": model_id.replace("anthropic/", ""), } for model_id in model_ids ] } def _catalog_models(catalog: Mapping[str, Any]) -> list[Mapping[str, Any]]: models = catalog["models"] assert isinstance(models, list) catalog_models: list[Mapping[str, Any]] = [] for model in models: assert isinstance(model, Mapping) catalog_models.append(cast(Mapping[str, Any], model)) return catalog_models def _slugs(catalog: Mapping[str, Any]) -> list[str]: slugs: list[str] = [] for model in _catalog_models(catalog): slug = model["slug"] assert isinstance(slug, str) slugs.append(slug) return slugs def test_codex_catalog_converts_configured_and_cached_models_to_direct_slugs() -> None: catalog = build_codex_model_catalog( _models_payload( "anthropic/nvidia_nim/nvidia/nemotron-3-super", "claude-3-freecc-no-thinking/nvidia_nim/nvidia/nemotron-3-super", "anthropic/open_router/meta-llama/llama-3.3-70b", "claude-3-freecc-no-thinking/open_router/meta-llama/llama-3.3-70b", ) ) assert _slugs(catalog) == [ "nvidia_nim/nvidia/nemotron-3-super", "open_router/meta-llama/llama-3.3-70b", ] model = _catalog_models(catalog)[0] assert { "slug", "display_name", "description", "default_reasoning_level", "supported_reasoning_levels", "shell_type", "visibility", "supported_in_api", "priority", "additional_speed_tiers", "service_tiers", } <= set(model) def test_codex_catalog_excludes_claude_compatibility_model_ids() -> None: catalog = build_codex_model_catalog( _models_payload( "claude-opus-4-20250514", "claude-3-haiku-20240307", "anthropic/nvidia_nim/provider-model", ) ) assert _slugs(catalog) == ["nvidia_nim/provider-model"] def test_codex_catalog_skips_no_thinking_duplicate_when_normal_slug_exists() -> None: catalog = build_codex_model_catalog( _models_payload( "claude-3-freecc-no-thinking/nvidia_nim/provider-model", "anthropic/nvidia_nim/provider-model", ) ) assert _slugs(catalog) == ["nvidia_nim/provider-model"] def test_codex_catalog_preserves_no_thinking_only_entries_for_routing() -> None: catalog = build_codex_model_catalog( _models_payload("claude-3-freecc-no-thinking/open_router/plain-model") ) assert _slugs(catalog) == ["claude-3-freecc-no-thinking/open_router/plain-model"] def test_codex_catalog_ordering_and_priorities_are_deterministic() -> None: catalog = build_codex_model_catalog( _models_payload( "anthropic/gemini/models/gemini-test", "anthropic/nvidia_nim/nvidia/test", "anthropic/gemini/models/gemini-test", "anthropic/open_router/provider/test", ) ) models = _catalog_models(catalog) assert _slugs(catalog) == [ "gemini/models/gemini-test", "nvidia_nim/nvidia/test", "open_router/provider/test", ] assert [model["priority"] for model in models] == [0, 1, 2] def test_codex_catalog_accepts_future_direct_provider_slugs() -> None: catalog = build_codex_model_catalog( _models_payload( "nvidia_nim/provider-model", "anthropic/open_router/provider-model", ) ) assert _slugs(catalog) == [ "nvidia_nim/provider-model", "open_router/provider-model", ] def test_generated_catalog_schema_is_accepted_by_installed_codex( tmp_path: Path, ) -> None: codex_binary = shutil.which("codex") if codex_binary is None: pytest.skip("Codex CLI is not installed") catalog_path = tmp_path / "codex-model-catalog.json" write_codex_model_catalog( catalog_path, build_codex_model_catalog(_models_payload("anthropic/nvidia_nim/test-model")), ) codex_home = tmp_path / "codex-home" codex_home.mkdir() codex_env = os.environ.copy() for key in ( "CODEX_THREAD_ID", "CODEX_INTERNAL_ORIGINATOR_OVERRIDE", "CODEX_SHELL", "CODEX_PERMISSION_PROFILE", ): codex_env.pop(key, None) codex_env["CODEX_HOME"] = str(codex_home) result = subprocess.run( [ codex_binary, "debug", "models", "-c", f"model_catalog_json={json.dumps(str(catalog_path))}", ], capture_output=True, check=False, encoding="utf-8", env=codex_env, errors="replace", text=True, timeout=10, ) assert result.returncode == 0, result.stderr assert "nvidia_nim/test-model" in result.stdout