a23d5073fb
switch_model() unconditionally set agent.provider but only set agent.base_url when the resolved value was truthy. When a real provider change resolved an empty base_url (e.g. minimax after copilot), the agent ended up with provider="minimax" but base_url still pointing at api.githubcopilot.com. That incoherent pair then got snapshotted into agent._primary_runtime, so it kept re-applying on every subsequent turn via restore_primary_runtime() until the process restarted. try_activate_fallback() and _swap_credential() were audited and confirmed unaffected: both always derive base_url from an actually constructed client, never from a possibly-empty resolver hint. Fix: when base_url is empty AND the provider is genuinely changing, raise ValueError instead of silently keeping the old provider's URL. This routes through switch_model()'s existing snapshot/rollback path, and callers (tui_gateway/server.py's _apply_model_switch) already catch and surface a clean "switch failed, staying on X" message. Re-selecting the SAME provider with an empty base_url (credential-only refresh) still keeps the current URL, unchanged. Fixes #47828 Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>