"""Tests for CLI model resolution (--model > EVAL_MODEL > config preset > provider default).""" import argparse from pathlib import Path import pytest from skill_eval_runner.cli import _resolve_grader_model, _resolve_model from skill_eval_runner.config import load_config from skill_eval_runner.providers import get_provider def _args( command: str, model: str | None = None, grader_model: str | None = None ) -> argparse.Namespace: """Build the minimal Namespace the resolvers read (command + model + grader_model).""" return argparse.Namespace(command=command, model=model, grader_model=grader_model) def test_explicit_model_wins(tmp_path: Path, monkeypatch: pytest.MonkeyPatch) -> None: """--model overrides env, config, and provider presets.""" monkeypatch.delenv("EVAL_MODEL", raising=False) config = load_config(tmp_path) provider = get_provider("anthropic") assert _resolve_model(_args("iterate", "my-model"), config, provider) == "my-model" def test_eval_model_env_beats_presets( tmp_path: Path, monkeypatch: pytest.MonkeyPatch ) -> None: """EVAL_MODEL is used when --model is absent, ahead of any preset.""" monkeypatch.setenv("EVAL_MODEL", "env-model") config = load_config(tmp_path) provider = get_provider("anthropic") assert _resolve_model(_args("validate"), config, provider) == "env-model" def test_iterate_falls_back_to_provider_small( tmp_path: Path, monkeypatch: pytest.MonkeyPatch ) -> None: """With nothing else set, iterate uses the provider's small preset.""" monkeypatch.delenv("EVAL_MODEL", raising=False) config = load_config(tmp_path) provider = get_provider("anthropic") assert _resolve_model(_args("iterate"), config, provider) == provider.small_model def test_run_uses_config_default( tmp_path: Path, monkeypatch: pytest.MonkeyPatch ) -> None: """run/grade honor [skill_eval.models] default over the provider default.""" monkeypatch.delenv("EVAL_MODEL", raising=False) config = load_config(tmp_path) config.models.default = "configured-default" provider = get_provider("anthropic") assert _resolve_model(_args("run"), config, provider) == "configured-default" def test_run_falls_back_to_provider_default( tmp_path: Path, monkeypatch: pytest.MonkeyPatch ) -> None: """With no config default, run/grade use the provider's default model.""" monkeypatch.delenv("EVAL_MODEL", raising=False) config = load_config(tmp_path) provider = get_provider("anthropic") assert _resolve_model(_args("grade"), config, provider) == provider.default_model def test_grader_model_explicit_wins( tmp_path: Path, monkeypatch: pytest.MonkeyPatch ) -> None: """--grader-model overrides env, config, and the agent-model fallback.""" monkeypatch.delenv("EVAL_GRADER_MODEL", raising=False) config = load_config(tmp_path) args = _args("iterate", grader_model="big-judge") assert _resolve_grader_model(args, config, "agent-model") == "big-judge" def test_grader_model_uses_config_preset( tmp_path: Path, monkeypatch: pytest.MonkeyPatch ) -> None: """With no flag/env, the [models].grader preset is used over the agent model.""" monkeypatch.delenv("EVAL_GRADER_MODEL", raising=False) config = load_config(tmp_path) config.models.grader = "configured-judge" assert _resolve_grader_model(_args("iterate"), config, "agent-model") == ( "configured-judge" ) def test_grader_model_defaults_to_agent_model( tmp_path: Path, monkeypatch: pytest.MonkeyPatch ) -> None: """With nothing set, the grader falls back to whatever the agent model resolved to.""" monkeypatch.delenv("EVAL_GRADER_MODEL", raising=False) config = load_config(tmp_path) assert _resolve_grader_model(_args("iterate"), config, "agent-model") == ( "agent-model" )