diff --git a/data/cli_flag_snapshot.txt b/data/cli_flag_snapshot.txt index 93df7c13..5da2d28d 100644 --- a/data/cli_flag_snapshot.txt +++ b/data/cli_flag_snapshot.txt @@ -36,6 +36,7 @@ --enable-pytest-compression --enable-pytest-full-suite-steering --force-context-window +--force-model --force-set-project --gemini-api-base-url --gemini-api-key diff --git a/data/test_suite_state.json b/data/test_suite_state.json index f3d0b8c5..753a7437 100644 --- a/data/test_suite_state.json +++ b/data/test_suite_state.json @@ -1,4 +1,4 @@ -{ - "test_count": 3054, - "last_updated": "1760246496.86542" +{ + "test_count": 3017, + "last_updated": "1760308090.250383" } \ No newline at end of file diff --git a/src/core/cli.py b/src/core/cli.py index c4abc8c9..b12c2ab5 100644 --- a/src/core/cli.py +++ b/src/core/cli.py @@ -93,12 +93,19 @@ def build_cli_parser() -> argparse.ArgumentParser: choices=registered_backends, # Dynamically populated help=argparse.SUPPRESS, ) - parser.add_argument( + route_group = parser.add_mutually_exclusive_group() + route_group.add_argument( "--static-route", dest="static_route", metavar="BACKEND:MODEL", help="Force all requests to use this backend:model combination (e.g., gemini-cli-oauth-personal:gemini-2.5-pro)", ) + route_group.add_argument( + "--force-model", + dest="force_model", + metavar="MODEL", + help="Force all requests to use this model while keeping the backend unchanged (alias for --static-route MODEL)", + ) def validate_model_alias(value: str) -> tuple[str, str]: """Validate model alias format: pattern=replacement""" @@ -647,6 +654,11 @@ def record_cli(path: str, value: Any, flag: str) -> None: backend_overrides["static_route"] = args.static_route os.environ["STATIC_ROUTE"] = args.static_route record_cli("backends.static_route", args.static_route, "--static-route") + elif getattr(args, "force_model", None) is not None: + backend_overrides = cli_overrides.setdefault("backends", {}) + backend_overrides["static_route"] = args.force_model + os.environ["STATIC_ROUTE"] = args.force_model + record_cli("backends.static_route", args.force_model, "--force-model") # Model aliases configuration (CLI overrides config file) if getattr(args, "model_aliases", None) is not None: diff --git a/tests/unit/test_cli.py b/tests/unit/test_cli.py index 4112d4de..606c8c13 100644 --- a/tests/unit/test_cli.py +++ b/tests/unit/test_cli.py @@ -17,7 +17,7 @@ def clean_cli_environment(): """Ensure clean environment for CLI tests to prevent contamination.""" # Store original values original_env = {} - env_vars_to_clean = ["COMMAND_PREFIX", "MODEL_ALIASES"] + env_vars_to_clean = ["COMMAND_PREFIX", "MODEL_ALIASES", "STATIC_ROUTE"] for var in env_vars_to_clean: original_env[var] = os.environ.get(var) @@ -223,6 +223,18 @@ def test_cli_context_window_override_environment_variable() -> None: del os.environ["FORCE_CONTEXT_WINDOW"] +def test_cli_force_model_argument_parsing() -> None: + """Test that the --force-model CLI argument forces static routing to the specified model.""" + + with patch("src.core.config.app_config.load_config", return_value=AppConfig()): + args = parse_cli_args(["--force-model", "gemini-2.5-pro"]) + assert args.force_model == "gemini-2.5-pro" + + config = _unwrap_config(apply_cli_args(args)) + assert config.backends.static_route == "gemini-2.5-pro" + assert os.environ.get("STATIC_ROUTE") == "gemini-2.5-pro" + + def test_cli_pytest_compression_flags() -> None: """Test that --enable-pytest-compression and --disable-pytest-compression flags work.""" # Patch load_config where it is looked up (in the 'cli' module) diff --git a/tests/unit/test_static_route.py b/tests/unit/test_static_route.py index d1c02878..f047343d 100644 --- a/tests/unit/test_static_route.py +++ b/tests/unit/test_static_route.py @@ -7,6 +7,8 @@ from src.core.domain.chat import ChatRequest from src.core.services.backend_service import BackendService +from tests.unit.test_cli import _unwrap_config + class TestStaticRoute: """Test suite for static_route override functionality.""" @@ -206,10 +208,12 @@ def test_cli_config_application(self): ) assert config.backends.default_backend == "openai" - def test_cli_rejects_force_model(self): - """Test that --force-model is rejected (removed parameter).""" - from src.core.cli import parse_cli_args + def test_cli_accepts_force_model_alias(self): + """Test that --force-model is accepted as an alias for static routing.""" + from src.core.cli import apply_cli_args, parse_cli_args + + args = parse_cli_args(["--force-model", "gemini-2.5-pro"]) + assert args.force_model == "gemini-2.5-pro" - # Should raise SystemExit because --force-model is not a valid argument - with pytest.raises(SystemExit): - parse_cli_args(["--force-model", "gemini-2.5-pro"]) + config = _unwrap_config(apply_cli_args(args)) + assert config.backends.static_route == "gemini-2.5-pro"