diff --git a/hermes_cli/cli_agent_setup_mixin.py b/hermes_cli/cli_agent_setup_mixin.py index 402e185303..9f332f2054 100644 --- a/hermes_cli/cli_agent_setup_mixin.py +++ b/hermes_cli/cli_agent_setup_mixin.py @@ -381,23 +381,19 @@ class CLIAgentSetupMixin: if _fb_api_key: _fb_kwargs["explicit_api_key"] = _fb_api_key runtime = resolve_runtime_provider(**_fb_kwargs) + # A 429/quota AuthError leaves the credentials valid; saying "auth failed" sends + # operators hunting for an expired token (#117482). if is_rate_limited_auth_error(primary_exc): - logger.warning( - "Primary provider rate-limited (429): %s. Falling through to fallback: %s/%s", - primary_exc, _fb_provider, _fb_model) - from gateway.warning_notifications import render_notification - render_notification( - lambda: _cprint( - f"⚠️ Primary provider quota exhausted — switching to fallback: {_fb_provider} / {_fb_model}"), - platform="cli") + _why_log, _why = "rate-limited (429)", "Primary provider quota exhausted" else: - logger.warning( - "Primary provider auth failed (%s). Falling through to fallback: %s/%s", - primary_exc, _fb_provider, _fb_model) - from gateway.warning_notifications import render_notification - render_notification( - lambda: _cprint(f"⚠️ Primary auth failed — switching to fallback: {_fb_provider} / {_fb_model}"), - platform="cli") + _why_log, _why = "auth failed", "Primary auth failed" + logger.warning( + "Primary provider %s (%s). Falling through to fallback: %s/%s", + _why_log, primary_exc, _fb_provider, _fb_model) + from gateway.warning_notifications import render_notification + render_notification( + lambda: _cprint(f"⚠️ {_why} — switching to fallback: {_fb_provider} / {_fb_model}"), + platform="cli") self.requested_provider = _fb_provider self.model = _fb_model # reasoning_config follows the swap in _ensure_runtime_credentials (the only caller). diff --git a/tests/agent/test_grid_sweep_cli_tui_stream_diagnostics.py b/tests/agent/test_grid_sweep_cli_tui_stream_diagnostics.py index 7d0c81b069..2a76ebac09 100644 --- a/tests/agent/test_grid_sweep_cli_tui_stream_diagnostics.py +++ b/tests/agent/test_grid_sweep_cli_tui_stream_diagnostics.py @@ -170,8 +170,9 @@ def test_cli_provider_fallback_notice_honors_policy(tmp_path, monkeypatch, setti from hermes_cli import cli_agent_setup_mixin as m out = [] monkeypatch.setattr(climod, "_cprint", lambda s: out.append(s)) - _cli_block(m, "from gateway.warning_notifications import render_notification\n render_notification(\n lambda: _cprint(f\"⚠️ Primary auth failed", - "self.requested_provider = _fb_provider", {"_fb_provider": "p", "_fb_model": "m"}) + _cli_block(m, "from gateway.warning_notifications import render_notification\n render_notification(\n lambda: _cprint(f\"⚠️ {_why}", + "self.requested_provider = _fb_provider", + {"_fb_provider": "p", "_fb_model": "m", "_why": "Primary auth failed"}) assert (len(out) == 1 and "Primary auth failed" in out[0]) is _visible(setting)