@@ -614,7 +614,7 @@ def test_v2_model_sets_transient_launch_override(self, monkeypatch):
614614 @staticmethod
615615 def _provider_launch (monkeypatch , argv , provider_models , relayed = False ):
616616 """Invoke a provider launch with model discovery/config stubbed, returning the
617- configure_tool mock so tests can assert what was threaded to it ."""
617+ configure_tool and launch_agent mocks so tests can assert what was threaded to each ."""
618618 import ucode .cli as cli_mod
619619
620620 monkeypatch .setattr (cli_mod , "ensure_bootstrap_dependencies" , lambda * a , ** k : None )
@@ -623,19 +623,20 @@ def _provider_launch(monkeypatch, argv, provider_models, relayed=False):
623623 monkeypatch .setattr (cli_mod , "configure_shared_state" , lambda * a , ** k : MINIMAL_STATE )
624624 monkeypatch .setattr (cli_mod , "_fetch_managed_config" , lambda s : (None , False ))
625625 monkeypatch .setattr (cli_mod , "_fetch_budget_recommendation" , lambda s , m : None )
626- monkeypatch .setattr (cli_mod , "launch_agent" , lambda * a , ** k : None )
626+ mock_launch = MagicMock ()
627+ monkeypatch .setattr (cli_mod , "launch_agent" , mock_launch )
627628 monkeypatch .setattr (
628629 cli_mod , "resolve_provider_models" , lambda t , s , p : (provider_models , None , relayed )
629630 )
630631 mock_configure = MagicMock (return_value = MINIMAL_STATE )
631632 monkeypatch .setattr (cli_mod , "configure_tool" , mock_configure )
632633 result = runner .invoke (app , argv )
633- return result , mock_configure
634+ return result , mock_configure , mock_launch
634635
635636 def test_model_and_provider_now_pin_the_launch_tier (self , monkeypatch ):
636637 # --model under a provider is no longer rejected: a family alias resolves to that tier's
637638 # declared target and is threaded as route_root_model (ANTHROPIC_MODEL), not custom_model.
638- result , mock_configure = self ._provider_launch (
639+ result , mock_configure , _ = self ._provider_launch (
639640 monkeypatch ,
640641 ["claude" , "--model" , "haiku" , "--provider" , "cat.schema.svc" ],
641642 {"sonnet" : "claude-sonnet-5" , "haiku" : "claude-haiku-4-5" },
@@ -647,7 +648,7 @@ def test_model_and_provider_now_pin_the_launch_tier(self, monkeypatch):
647648 def test_provider_without_opus_auto_picks_best_servable_tier (self , monkeypatch ):
648649 # No --model, and the service declares no opus target: launch on the most capable tier it
649650 # does offer (sonnet) instead of dead-ending on Claude Code's opus default.
650- result , mock_configure = self ._provider_launch (
651+ result , mock_configure , _ = self ._provider_launch (
651652 monkeypatch ,
652653 ["claude" , "--provider" , "cat.schema.svc" ],
653654 {"sonnet" : "claude-sonnet-5" , "haiku" : "claude-haiku-4-5" },
@@ -658,7 +659,7 @@ def test_provider_without_opus_auto_picks_best_servable_tier(self, monkeypatch):
658659 def test_provider_with_opus_keeps_claude_default (self , monkeypatch ):
659660 # Opus is offered, so Claude Code's own default already works — pin nothing (no ANTHROPIC_MODEL
660661 # and no duplicate /model picker row).
661- result , mock_configure = self ._provider_launch (
662+ result , mock_configure , _ = self ._provider_launch (
662663 monkeypatch ,
663664 ["claude" , "--provider" , "cat.schema.svc" ],
664665 {"opus" : "claude-opus-4-8" , "sonnet" : "claude-sonnet-5" },
@@ -667,25 +668,38 @@ def test_provider_with_opus_keeps_claude_default(self, monkeypatch):
667668 assert mock_configure .call_args .kwargs ["route_root_model" ] is None
668669
669670 def test_model_family_not_offered_by_provider_errors (self , monkeypatch ):
670- result , _ = self ._provider_launch (
671+ result , _ , _ = self ._provider_launch (
671672 monkeypatch ,
672673 ["claude" , "--model" , "opus" , "--provider" , "cat.schema.svc" ],
673674 {"sonnet" : "claude-sonnet-5" , "haiku" : "claude-haiku-4-5" },
674675 )
675676 assert result .exit_code == 1
676677 assert "does not offer a 'opus' model" in result .output
677678
678- def test_model_ignored_for_relayed_provider (self , monkeypatch ):
679- # A relayed ( subscription) service selects the model server-side; --model can't be honored .
680- result , mock_configure = self ._provider_launch (
679+ def test_model_forwarded_to_claude_for_relayed_provider (self , monkeypatch ):
680+ # Relayed = a subscription: --model rides Claude Code's own flag, not gateway env .
681+ result , mock_configure , mock_launch = self ._provider_launch (
681682 monkeypatch ,
682- ["claude" , "--model" , "haiku " , "--provider" , "cat.schema.svc" ],
683+ ["claude" , "--model" , "opus " , "--provider" , "cat.schema.svc" ],
683684 None ,
684685 relayed = True ,
685686 )
686687 assert result .exit_code == 0 , result .output
688+ assert mock_launch .call_args .args [2 ] == ["--model" , "opus" ]
687689 assert mock_configure .call_args .kwargs ["route_root_model" ] is None
688- assert "--model is ignored" in _strip_ansi (result .output )
690+ assert mock_configure .call_args .kwargs ["custom_model" ] is None
691+ assert "ignored" not in _strip_ansi (result .output )
692+
693+ def test_relayed_provider_without_model_forwards_nothing (self , monkeypatch ):
694+ # No --model on a relayed launch: nothing to forward.
695+ result , _ , mock_launch = self ._provider_launch (
696+ monkeypatch ,
697+ ["claude" , "--provider" , "cat.schema.svc" ],
698+ None ,
699+ relayed = True ,
700+ )
701+ assert result .exit_code == 0 , result .output
702+ assert mock_launch .call_args .args [2 ] == []
689703
690704 def test_provider_sets_transient_claude_launch_marker (self ):
691705 state = dict (MINIMAL_STATE )
0 commit comments