fix(cli): harden hermes portal SystemExit handling + finish model-pick doc sweep
Self-review of #38465 surfaced three real items: 1. SystemExit escape (defense): `_login_nous` raises SystemExit(130)/(1) on cancel/failure. The logged-out login path inside `_model_flow_nous` catches it, but the expired-session re-login path (main.py) only catches Exception, so a Ctrl-C during re-auth could propagate past `_run_portal_one_shot` and kill the CLI. Add SystemExit to the portal handler so all cancel/abort cases end with the graceful 'Setup cancelled / retry later' message. 2. Doc sweep: the model-pick step was only added to the bare-`hermes portal` prose. Propagate it to the surfaces describing `hermes setup --portal` behavior that still omitted model selection: - `--portal` argparse help (main.py) - nous-portal.md intro + the numbered 'what it does' step list (EN + zh-Hans) - run-hermes-with-nous-portal.md 'default model after setup --portal' line, which was now contradictory (there's a picker, not a forced default) (EN + zh) 3. Test coverage: add parametrized regression test asserting the portal handler swallows KeyboardInterrupt / EOFError / SystemExit (returns None, no escape). Note on 'Skip (keep current)': delegating to _model_flow_nous means picking Skip preserves the prior provider instead of force-switching to nous — this is intentional and matches quick setup exactly; docs now say 'sets Nous as your provider (when you pick a model)' rather than unconditionally.
This commit is contained in:
@@ -135,3 +135,23 @@ def test_one_shot_delegates_to_model_flow_nous(monkeypatch):
|
||||
"`hermes portal` must route through _model_flow_nous so the model "
|
||||
"picker runs every time (matching quick setup)."
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("exc", [KeyboardInterrupt, EOFError, SystemExit])
|
||||
def test_one_shot_swallows_cancel_and_systemexit(monkeypatch, exc):
|
||||
"""A cancel/abort from the delegated Nous flow must NOT escape and kill the
|
||||
CLI. `_login_nous` raises SystemExit(130)/(1) on cancel/failure, and the
|
||||
expired-session re-login path inside `_model_flow_nous` only catches
|
||||
Exception — so SystemExit could otherwise propagate out. The portal handler
|
||||
must treat KeyboardInterrupt/EOFError/SystemExit as a graceful cancel.
|
||||
"""
|
||||
import hermes_cli.setup as setup_mod
|
||||
|
||||
def boom(config):
|
||||
raise exc
|
||||
|
||||
monkeypatch.setattr("hermes_cli.main._model_flow_nous", boom)
|
||||
monkeypatch.setattr("hermes_cli.config.load_config", lambda: {})
|
||||
|
||||
# Must return normally (None), not propagate the exception.
|
||||
assert setup_mod._run_portal_one_shot({}) is None
|
||||
|
||||
Reference in New Issue
Block a user