fix(setup): default browser/TTS picker to free local backend, not paid Nous (#37800)
The Browser Automation and Text-to-Speech provider pickers listed the paid "Nous Subscription" gateway row first, so on a fresh install the menu cursor defaulted to index 0 (Nous). Pressing Enter selected it and ran the inline Nous Portal device-code login — walking users into a paid offering they never chose. Reorder both provider lists so the free, no-key local backend is index 0 (Local Browser / Microsoft Edge TTS). Users who already configured Nous are unaffected: _detect_active_provider_index still resolves their active row first, so the cursor lands on Nous (now index 1) for them. Reported by Javier via Kujila.
This commit is contained in:
@ -202,6 +202,13 @@ TOOL_CATEGORIES = {
|
||||
"name": "Text-to-Speech",
|
||||
"icon": "🔊",
|
||||
"providers": [
|
||||
{
|
||||
"name": "Microsoft Edge TTS",
|
||||
"badge": "★ recommended · free",
|
||||
"tag": "Good quality, no API key needed",
|
||||
"env_vars": [],
|
||||
"tts_provider": "edge",
|
||||
},
|
||||
{
|
||||
"name": "Nous Subscription",
|
||||
"badge": "subscription",
|
||||
@ -212,13 +219,6 @@ TOOL_CATEGORIES = {
|
||||
"managed_nous_feature": "tts",
|
||||
"override_env_vars": ["VOICE_TOOLS_OPENAI_KEY", "OPENAI_API_KEY"],
|
||||
},
|
||||
{
|
||||
"name": "Microsoft Edge TTS",
|
||||
"badge": "★ recommended · free",
|
||||
"tag": "Good quality, no API key needed",
|
||||
"env_vars": [],
|
||||
"tts_provider": "edge",
|
||||
},
|
||||
{
|
||||
"name": "OpenAI TTS",
|
||||
"badge": "paid",
|
||||
@ -406,15 +406,26 @@ TOOL_CATEGORIES = {
|
||||
# Per-provider rows for Browserbase, Browser Use, and Firecrawl are
|
||||
# injected at runtime from plugins.browser.<vendor>.provider via
|
||||
# _plugin_browser_providers() in _visible_providers(). Only
|
||||
# non-provider UX setup-flow rows remain here:
|
||||
# non-provider UX setup-flow rows remain here. "Local Browser" is
|
||||
# listed FIRST so it is the default-highlighted (index 0) choice on a
|
||||
# fresh install — pressing Enter must land on the free, no-key local
|
||||
# backend, never on the paid Nous Subscription gateway row:
|
||||
# - "Local Browser" — non-cloud option, no CloudBrowserProvider.
|
||||
# - "Nous Subscription (Browser Use cloud)" — managed Browser Use
|
||||
# billed via Nous subscription (requires_nous_auth +
|
||||
# override_env_vars). Uses the browser-use plugin as the
|
||||
# underlying backend but has a distinct setup UX.
|
||||
# - "Local Browser" — non-cloud option, no CloudBrowserProvider.
|
||||
# - "Camofox" — anti-detection local Firefox; short-circuits the
|
||||
# cloud-provider dispatch path via _is_camofox_mode().
|
||||
"providers": [
|
||||
{
|
||||
"name": "Local Browser",
|
||||
"badge": "★ recommended · free",
|
||||
"tag": "Headless Chromium, no API key needed",
|
||||
"env_vars": [],
|
||||
"browser_provider": "local",
|
||||
"post_setup": "agent_browser",
|
||||
},
|
||||
{
|
||||
"name": "Nous Subscription (Browser Use cloud)",
|
||||
"badge": "subscription",
|
||||
@ -426,14 +437,6 @@ TOOL_CATEGORIES = {
|
||||
"override_env_vars": ["BROWSER_USE_API_KEY"],
|
||||
"post_setup": "agent_browser",
|
||||
},
|
||||
{
|
||||
"name": "Local Browser",
|
||||
"badge": "★ recommended · free",
|
||||
"tag": "Headless Chromium, no API key needed",
|
||||
"env_vars": [],
|
||||
"browser_provider": "local",
|
||||
"post_setup": "agent_browser",
|
||||
},
|
||||
{
|
||||
"name": "Camofox",
|
||||
"badge": "free · local",
|
||||
|
||||
@ -609,7 +609,12 @@ def test_visible_providers_include_nous_subscription_when_logged_in(monkeypatch)
|
||||
|
||||
providers = _visible_providers(TOOL_CATEGORIES["browser"], config)
|
||||
|
||||
assert providers[0]["name"].startswith("Nous Subscription")
|
||||
# The managed Nous row is listed (not necessarily first — "Local Browser"
|
||||
# sorts first so a fresh-install Enter lands on the free local backend).
|
||||
assert any(p["name"].startswith("Nous Subscription") for p in providers)
|
||||
# "Local Browser" must be the index-0 default so pressing Enter never
|
||||
# walks a user into a paid Nous Portal login.
|
||||
assert providers[0]["name"] == "Local Browser"
|
||||
|
||||
|
||||
def test_visible_providers_show_nous_subscription_when_logged_out(monkeypatch):
|
||||
@ -685,7 +690,9 @@ def test_visible_providers_force_fresh_shows_nous_subscription_after_upgrade(mon
|
||||
force_fresh=True,
|
||||
)
|
||||
|
||||
assert providers[0]["name"].startswith("Nous Subscription")
|
||||
# The managed Nous row reappears after the entitlement upgrade. It is no
|
||||
# longer asserted to be first — "Local Browser" sorts first by design.
|
||||
assert any(p["name"].startswith("Nous Subscription") for p in providers)
|
||||
assert ("features", True) in calls
|
||||
|
||||
|
||||
@ -702,6 +709,33 @@ def test_local_browser_provider_is_saved_explicitly(monkeypatch):
|
||||
assert config["browser"]["cloud_provider"] == "local"
|
||||
|
||||
|
||||
def test_fresh_install_browser_default_is_free_local_not_paid_nous():
|
||||
"""On a fresh install the browser picker must default to the free local
|
||||
backend, never the paid Nous Subscription gateway.
|
||||
|
||||
Regression: the Nous row used to sort first, so the menu cursor defaulted
|
||||
to index 0 (Nous) and pressing Enter walked users straight into a Nous
|
||||
Portal login for a paid offering (Javier's bug, June 2026).
|
||||
"""
|
||||
from hermes_cli.tools_config import _detect_active_provider_index
|
||||
|
||||
providers = TOOL_CATEGORIES["browser"]["providers"]
|
||||
assert providers[0]["name"] == "Local Browser"
|
||||
assert providers[0]["browser_provider"] == "local"
|
||||
# Nothing active/configured → cursor defaults to index 0 (the free local row).
|
||||
assert _detect_active_provider_index(providers, {}) == 0
|
||||
|
||||
|
||||
def test_fresh_install_tts_default_is_free_edge_not_paid_nous():
|
||||
"""TTS picker defaults to the free Edge backend on a fresh install."""
|
||||
from hermes_cli.tools_config import _detect_active_provider_index
|
||||
|
||||
providers = TOOL_CATEGORIES["tts"]["providers"]
|
||||
assert providers[0]["name"] == "Microsoft Edge TTS"
|
||||
assert providers[0]["tts_provider"] == "edge"
|
||||
assert _detect_active_provider_index(providers, {}) == 0
|
||||
|
||||
|
||||
def test_reconfigure_lists_enabled_web_without_existing_provider_config(monkeypatch):
|
||||
config = {"platform_toolsets": {"cli": ["web"]}}
|
||||
seen = {}
|
||||
|
||||
Reference in New Issue
Block a user