From 38453baeee4046d742b0d315918442bd6640acc6 Mon Sep 17 00:00:00 2001 From: Teknium <127238744+teknium1@users.noreply.github.com> Date: Sat, 1 Aug 2026 14:53:38 -0700 Subject: [PATCH] fix(setup): warn loudly when the wizard finishes without a working provider MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cancelling the API-key prompt mid-wizard (Enter → 'Cancelled.') let the wizard continue through Terminal/Gateway/Tools and finish 'successfully' with no model configured — the user exits believing they're set up, then hits a broken chat. _print_setup_summary() (called by every setup path: full, quick, blank-slate, portal) now probes resolve_provider() and, when nothing is configured, prints an unmissable warning with the two one-line fixes (hermes model / hermes setup --portal). Consumer-onboarding audit finding #7 (sev 4), Aug 2026. --- hermes_cli/setup.py | 19 +++++++ .../test_setup_summary_provider_warning.py | 49 +++++++++++++++++++ 2 files changed, 68 insertions(+) create mode 100644 tests/hermes_cli/test_setup_summary_provider_warning.py diff --git a/hermes_cli/setup.py b/hermes_cli/setup.py index 9031524a4f..6fe25a3fdb 100644 --- a/hermes_cli/setup.py +++ b/hermes_cli/setup.py @@ -395,6 +395,25 @@ def _prompt_api_key(var: dict): def _print_setup_summary(config: dict, hermes_home): """Print the setup completion summary.""" + # Provider readiness — the one thing setup absolutely must produce. + # Previously a user could cancel the API-key prompt mid-wizard (Enter → + # "Cancelled."), watch the wizard continue through Terminal/Gateway/Tools, + # and exit "successfully" with NO working model — believing they were set + # up. Say so loudly instead (consumer-onboarding audit finding #7). + try: + from hermes_cli.auth import resolve_provider + + resolve_provider() + _provider_ready = True + except Exception: + _provider_ready = False + if not _provider_ready: + print() + print_warning("No inference provider is configured — Hermes cannot chat yet.") + print_info(" Finish this one step with either of:") + print_info(" hermes model (pick any provider/model)") + print_info(" hermes setup --portal (Nous Portal OAuth, no API key)") + # Tool availability summary print() print_header("Tool Availability Summary") diff --git a/tests/hermes_cli/test_setup_summary_provider_warning.py b/tests/hermes_cli/test_setup_summary_provider_warning.py new file mode 100644 index 0000000000..4d8cfb2ad9 --- /dev/null +++ b/tests/hermes_cli/test_setup_summary_provider_warning.py @@ -0,0 +1,49 @@ +"""Setup summary must warn loudly when no provider got configured. + +Regression test for the "wizard silently succeeds with no model" dead end: +cancelling the API-key prompt mid-wizard printed "Cancelled." but the wizard +continued through the remaining sections and finished "successfully" with no +working model configured (consumer-onboarding audit finding #7, Aug 2026). +""" + +from unittest.mock import patch + +from hermes_cli.auth import AuthError + + +def _summary_output(capsys, provider_ready: bool): + from hermes_cli import setup as setup_mod + + if provider_ready: + resolver = lambda *a, **k: "openrouter" # noqa: E731 + else: + def resolver(*a, **k): + raise AuthError( + "No inference provider configured.", + code="no_provider_configured", + ) + + # Keep the summary fast/hermetic: stub the heavier feature probes. + with patch("hermes_cli.auth.resolve_provider", resolver), \ + patch.object(setup_mod, "get_nous_subscription_features") as feats: + feats.side_effect = Exception("stubbed") + try: + setup_mod._print_setup_summary({}, "/tmp/nowhere") + except Exception: + # Downstream summary sections may fail from the stubbed + # features — the provider warning prints first and is what + # this test asserts on. + pass + return capsys.readouterr().out + + +def test_summary_warns_when_no_provider(capsys): + out = _summary_output(capsys, provider_ready=False) + assert "No inference provider is configured" in out + assert "hermes model" in out + assert "hermes setup --portal" in out + + +def test_summary_quiet_when_provider_ready(capsys): + out = _summary_output(capsys, provider_ready=True) + assert "No inference provider is configured" not in out