feat(tools): always show Nous Tool Gateway backends, login on select (#35792)
* feat(tools): always show Nous Tool Gateway backends, login on select The Nous-managed Tool Gateway rows in `hermes tools` (Firecrawl, OpenAI TTS, Browser Use, FAL image/video) were hidden unless the user was already logged into Nous Portal with paid access. Now they are always listed. Selecting one runs an inline Nous Portal device-code OAuth + entitlement check — auth only, no inference-provider switch and no bulk 'enable all tools' prompt (that stays in `hermes model`). The row only activates the gateway once paid access is confirmed. - _visible_providers: stop hiding managed_nous_feature rows (incl. those also flagged requires_nous_auth); pure pre-auth UX rows still gate on login - nous_subscription.ensure_nous_portal_access(): auth + entitlement gate that preserves the user's active inference provider - _configure_provider / _reconfigure_provider: run the inline gate for managed backends; write config only when entitled - picker marker: 'via Nous Portal (login on select)' for logged-out users - _hidden_nous_gateway_message: now a no-op (rows are never hidden) * docs: hermes tools is a first-class Tool Gateway entry point The Tool Gateway docs framed `hermes setup --portal` / `hermes model` as the activation path and only mentioned `hermes tools` for mixing in your own keys. With the inline-login change, picking a Nous-managed backend in `hermes tools` is a complete path on its own — it logs you into Nous Portal on select if needed, without switching your inference provider or prompting to enable every other tool. - tool-gateway.md: Get started now lists three peer entry points; new paragraph explaining login-on-select and the no-prompt fast path when OAuth is already active - nous-portal.md + run-hermes-with-nous-portal.md: note that managed rows appear logged-out and trigger inline login on select
This commit is contained in:
@@ -321,3 +321,70 @@ def test_apply_nous_managed_defaults_preserves_existing_video_gen_section(monkey
|
||||
assert config["video_gen"]["use_gateway"] is True
|
||||
# Pre-existing keys should be preserved
|
||||
assert config["video_gen"]["model"] == "pixverse-v6"
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# ensure_nous_portal_access — inline login gate for `hermes tools`
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
|
||||
def test_ensure_nous_portal_access_fast_path_when_already_paid(monkeypatch):
|
||||
"""Already-entitled users return True without any login prompt."""
|
||||
login_called = {"v": False}
|
||||
|
||||
monkeypatch.setattr(
|
||||
ns, "get_nous_portal_account_info",
|
||||
lambda **kw: _account(logged_in=True, paid=True),
|
||||
)
|
||||
|
||||
def _login(**kw):
|
||||
login_called["v"] = True
|
||||
return True
|
||||
|
||||
monkeypatch.setattr(ns, "_run_nous_portal_login_only", _login)
|
||||
|
||||
assert ns.ensure_nous_portal_access() is True
|
||||
assert login_called["v"] is False
|
||||
|
||||
|
||||
def test_ensure_nous_portal_access_logs_in_then_grants(monkeypatch):
|
||||
"""Logged-out user logs in, then entitlement re-check shows paid access."""
|
||||
states = iter([
|
||||
_account(logged_in=False, paid=None), # initial check
|
||||
_account(logged_in=True, paid=True), # after login
|
||||
])
|
||||
monkeypatch.setattr(
|
||||
ns, "get_nous_portal_account_info", lambda **kw: next(states),
|
||||
)
|
||||
monkeypatch.setattr(ns, "_run_nous_portal_login_only", lambda **kw: True)
|
||||
|
||||
assert ns.ensure_nous_portal_access() is True
|
||||
|
||||
|
||||
def test_ensure_nous_portal_access_returns_false_when_login_declined(monkeypatch):
|
||||
monkeypatch.setattr(
|
||||
ns, "get_nous_portal_account_info",
|
||||
lambda **kw: _account(logged_in=False, paid=None),
|
||||
)
|
||||
monkeypatch.setattr(ns, "_run_nous_portal_login_only", lambda **kw: False)
|
||||
|
||||
assert ns.ensure_nous_portal_access() is False
|
||||
|
||||
|
||||
def test_ensure_nous_portal_access_false_when_logged_in_but_unpaid(monkeypatch):
|
||||
"""Logged in already but no paid access — no login attempt, returns False."""
|
||||
login_called = {"v": False}
|
||||
monkeypatch.setattr(
|
||||
ns, "get_nous_portal_account_info",
|
||||
lambda **kw: _account(logged_in=True, paid=False),
|
||||
)
|
||||
|
||||
def _login(**kw):
|
||||
login_called["v"] = True
|
||||
return True
|
||||
|
||||
monkeypatch.setattr(ns, "_run_nous_portal_login_only", _login)
|
||||
|
||||
assert ns.ensure_nous_portal_access() is False
|
||||
# Already logged in, so no device-code login should be attempted.
|
||||
assert login_called["v"] is False
|
||||
|
||||
Reference in New Issue
Block a user