mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-06-09 08:21:50 +00:00
feat: switch managed browser provider from Browserbase to Browser Use (#5750)
* feat: switch managed browser provider from Browserbase to Browser Use
The Nous subscription tool gateway now routes browser automation through
Browser Use instead of Browserbase. This commit:
- Adds managed Nous gateway support to BrowserUseProvider (idempotency
keys, X-BB-API-Key auth header, external_call_id persistence)
- Removes managed gateway support from BrowserbaseProvider (now
direct-only via BROWSERBASE_API_KEY/BROWSERBASE_PROJECT_ID)
- Updates browser_tool.py fallback: prefers Browser Use over Browserbase
- Updates nous_subscription.py: gateway vendor 'browser-use', auto-config
sets cloud_provider='browser-use' for new subscribers
- Updates tools_config.py: Nous Subscription entry now uses Browser Use
- Updates setup.py, cli.py, status.py, prompt_builder.py display strings
- Updates all affected tests to match new behavior
Browserbase remains fully functional for users with direct API credentials.
The change only affects the managed/subscription path.
* chore: remove redundant Browser Use hint from system prompt
* fix: upgrade Browser Use provider to v3 API
- Base URL: api/v2 -> api/v3 (v2 is legacy)
- Unified all endpoints to use native Browser Use paths:
- POST /browsers (create session, returns cdpUrl)
- PATCH /browsers/{id} with {action: stop} (close session)
- Removed managed-mode branching that used Browserbase-style
/v1/sessions paths — v3 gateway now supports /browsers directly
- Removed unused managed_mode variable in close_session
* fix(browser-use): use X-Browser-Use-API-Key header for managed mode
The managed gateway expects X-Browser-Use-API-Key, not X-BB-API-Key
(which is a Browserbase-specific header). Using the wrong header caused
a 401 AUTH_ERROR on every managed-mode browser session create.
Simplified _headers() to always use X-Browser-Use-API-Key regardless
of direct vs managed mode.
* fix(nous_subscription): browserbase explicit provider is direct-only
Since managed Nous gateway now routes through Browser Use, the
browserbase explicit provider path should not check managed_browser_available
(which resolves against the browser-use gateway). Simplified to direct-only
with managed=False.
* fix(browser-use): port missing improvements from PR #5605
- CDP URL normalization: resolve HTTP discovery URLs to websocket after
cloud provider create_session() (prevents agent-browser failures)
- Managed session payload: send timeout=5 and proxyCountryCode=us for
gateway-backed sessions (prevents billing overruns)
- Update prompt builder, browser_close schema, and module docstring to
replace remaining Browserbase references with Browser Use
- Dynamic /browser status detection via _get_cloud_provider() instead
of hardcoded env var checks (future-proof for new providers)
- Rename post_setup key from 'browserbase' to 'agent_browser'
- Update setup hint to mention Browser Use alongside Browserbase
- Add tests: CDP normalization, browserbase direct-only guard,
managed browser-use gateway, direct browserbase fallback
---------
Co-authored-by: rob-maron <132852777+rob-maron@users.noreply.github.com>
This commit is contained in:
parent
8b861b77c1
commit
b2f477a30b
16 changed files with 429 additions and 258 deletions
|
|
@ -167,20 +167,20 @@ def _resolve_browser_feature_state(
|
|||
if browser_provider_explicit:
|
||||
current_provider = browser_provider or "local"
|
||||
if current_provider == "browserbase":
|
||||
provider_available = managed_browser_available or direct_browserbase
|
||||
available = bool(browser_local_available and direct_browserbase)
|
||||
active = bool(browser_tool_enabled and available)
|
||||
return current_provider, available, active, False
|
||||
if current_provider == "browser-use":
|
||||
provider_available = managed_browser_available or direct_browser_use
|
||||
available = bool(browser_local_available and provider_available)
|
||||
managed = bool(
|
||||
browser_tool_enabled
|
||||
and browser_local_available
|
||||
and managed_browser_available
|
||||
and not direct_browserbase
|
||||
and not direct_browser_use
|
||||
)
|
||||
active = bool(browser_tool_enabled and available)
|
||||
return current_provider, available, active, managed
|
||||
if current_provider == "browser-use":
|
||||
available = bool(browser_local_available and direct_browser_use)
|
||||
active = bool(browser_tool_enabled and available)
|
||||
return current_provider, available, active, False
|
||||
if current_provider == "firecrawl":
|
||||
available = bool(browser_local_available and direct_firecrawl)
|
||||
active = bool(browser_tool_enabled and available)
|
||||
|
|
@ -193,16 +193,21 @@ def _resolve_browser_feature_state(
|
|||
active = bool(browser_tool_enabled and available)
|
||||
return current_provider, available, active, False
|
||||
|
||||
if managed_browser_available or direct_browserbase:
|
||||
if managed_browser_available or direct_browser_use:
|
||||
available = bool(browser_local_available)
|
||||
managed = bool(
|
||||
browser_tool_enabled
|
||||
and browser_local_available
|
||||
and managed_browser_available
|
||||
and not direct_browserbase
|
||||
and not direct_browser_use
|
||||
)
|
||||
active = bool(browser_tool_enabled and available)
|
||||
return "browserbase", available, active, managed
|
||||
return "browser-use", available, active, managed
|
||||
|
||||
if direct_browserbase:
|
||||
available = bool(browser_local_available)
|
||||
active = bool(browser_tool_enabled and available)
|
||||
return "browserbase", available, active, False
|
||||
|
||||
available = bool(browser_local_available)
|
||||
active = bool(browser_tool_enabled and available)
|
||||
|
|
@ -266,7 +271,7 @@ def get_nous_subscription_features(
|
|||
managed_web_available = managed_tools_flag and nous_auth_present and is_managed_tool_gateway_ready("firecrawl")
|
||||
managed_image_available = managed_tools_flag and nous_auth_present and is_managed_tool_gateway_ready("fal-queue")
|
||||
managed_tts_available = managed_tools_flag and nous_auth_present and is_managed_tool_gateway_ready("openai-audio")
|
||||
managed_browser_available = managed_tools_flag and nous_auth_present and is_managed_tool_gateway_ready("browserbase")
|
||||
managed_browser_available = managed_tools_flag and nous_auth_present and is_managed_tool_gateway_ready("browser-use")
|
||||
managed_modal_available = managed_tools_flag and nous_auth_present and is_managed_tool_gateway_ready("modal")
|
||||
modal_state = resolve_modal_backend_state(
|
||||
modal_mode,
|
||||
|
|
@ -512,10 +517,10 @@ def apply_nous_managed_defaults(
|
|||
changed.add("tts")
|
||||
|
||||
if "browser" in selected_toolsets and not features.browser.explicit_configured and not (
|
||||
get_env_value("BROWSERBASE_API_KEY")
|
||||
or get_env_value("BROWSER_USE_API_KEY")
|
||||
get_env_value("BROWSER_USE_API_KEY")
|
||||
or get_env_value("BROWSERBASE_API_KEY")
|
||||
):
|
||||
browser_cfg["cloud_provider"] = "browserbase"
|
||||
browser_cfg["cloud_provider"] = "browser-use"
|
||||
changed.add("browser")
|
||||
|
||||
if "image_gen" in selected_toolsets and not get_env_value("FAL_KEY"):
|
||||
|
|
|
|||
|
|
@ -660,14 +660,14 @@ def _print_setup_summary(config: dict, hermes_home):
|
|||
# Browser tools (local Chromium, Camofox, Browserbase, Browser Use, or Firecrawl)
|
||||
browser_provider = subscription_features.browser.current_provider
|
||||
if subscription_features.browser.managed_by_nous:
|
||||
tool_status.append(("Browser Automation (Nous Browserbase)", True, None))
|
||||
tool_status.append(("Browser Automation (Nous Browser Use)", True, None))
|
||||
elif subscription_features.browser.available:
|
||||
label = "Browser Automation"
|
||||
if browser_provider:
|
||||
label = f"Browser Automation ({browser_provider})"
|
||||
tool_status.append((label, True, None))
|
||||
else:
|
||||
missing_browser_hint = "npm install -g agent-browser, set CAMOFOX_URL, or configure Browserbase"
|
||||
missing_browser_hint = "npm install -g agent-browser, set CAMOFOX_URL, or configure Browser Use or Browserbase"
|
||||
if browser_provider == "Browserbase":
|
||||
missing_browser_hint = (
|
||||
"npm install -g agent-browser and set "
|
||||
|
|
|
|||
|
|
@ -123,7 +123,8 @@ def show_status(args):
|
|||
"MiniMax-CN": "MINIMAX_CN_API_KEY",
|
||||
"Firecrawl": "FIRECRAWL_API_KEY",
|
||||
"Tavily": "TAVILY_API_KEY",
|
||||
"Browserbase": "BROWSERBASE_API_KEY", # Optional — local browser works without this
|
||||
"Browser Use": "BROWSER_USE_API_KEY", # Optional — local browser works without this
|
||||
"Browserbase": "BROWSERBASE_API_KEY", # Optional — direct credentials only
|
||||
"FAL": "FAL_KEY",
|
||||
"Tinker": "TINKER_API_KEY",
|
||||
"WandB": "WANDB_API_KEY",
|
||||
|
|
|
|||
|
|
@ -280,21 +280,21 @@ TOOL_CATEGORIES = {
|
|||
"icon": "🌐",
|
||||
"providers": [
|
||||
{
|
||||
"name": "Nous Subscription (Browserbase cloud)",
|
||||
"tag": "Managed Browserbase billed to your subscription",
|
||||
"name": "Nous Subscription (Browser Use cloud)",
|
||||
"tag": "Managed Browser Use billed to your subscription",
|
||||
"env_vars": [],
|
||||
"browser_provider": "browserbase",
|
||||
"browser_provider": "browser-use",
|
||||
"requires_nous_auth": True,
|
||||
"managed_nous_feature": "browser",
|
||||
"override_env_vars": ["BROWSERBASE_API_KEY", "BROWSERBASE_PROJECT_ID"],
|
||||
"post_setup": "browserbase",
|
||||
"override_env_vars": ["BROWSER_USE_API_KEY"],
|
||||
"post_setup": "agent_browser",
|
||||
},
|
||||
{
|
||||
"name": "Local Browser",
|
||||
"tag": "Free headless Chromium (no API key needed)",
|
||||
"env_vars": [],
|
||||
"browser_provider": "local",
|
||||
"post_setup": "browserbase", # Same npm install for agent-browser
|
||||
"post_setup": "agent_browser",
|
||||
},
|
||||
{
|
||||
"name": "Browserbase",
|
||||
|
|
@ -304,7 +304,7 @@ TOOL_CATEGORIES = {
|
|||
{"key": "BROWSERBASE_PROJECT_ID", "prompt": "Browserbase project ID"},
|
||||
],
|
||||
"browser_provider": "browserbase",
|
||||
"post_setup": "browserbase",
|
||||
"post_setup": "agent_browser",
|
||||
},
|
||||
{
|
||||
"name": "Browser Use",
|
||||
|
|
@ -313,7 +313,7 @@ TOOL_CATEGORIES = {
|
|||
{"key": "BROWSER_USE_API_KEY", "prompt": "Browser Use API key", "url": "https://browser-use.com"},
|
||||
],
|
||||
"browser_provider": "browser-use",
|
||||
"post_setup": "browserbase",
|
||||
"post_setup": "agent_browser",
|
||||
},
|
||||
{
|
||||
"name": "Firecrawl",
|
||||
|
|
@ -322,7 +322,7 @@ TOOL_CATEGORIES = {
|
|||
{"key": "FIRECRAWL_API_KEY", "prompt": "Firecrawl API key", "url": "https://firecrawl.dev"},
|
||||
],
|
||||
"browser_provider": "firecrawl",
|
||||
"post_setup": "browserbase",
|
||||
"post_setup": "agent_browser",
|
||||
},
|
||||
{
|
||||
"name": "Camofox",
|
||||
|
|
@ -381,7 +381,7 @@ TOOLSET_ENV_REQUIREMENTS = {
|
|||
def _run_post_setup(post_setup_key: str):
|
||||
"""Run post-setup hooks for tools that need extra installation steps."""
|
||||
import shutil
|
||||
if post_setup_key == "browserbase":
|
||||
if post_setup_key in ("agent_browser", "browserbase"):
|
||||
node_modules = PROJECT_ROOT / "node_modules" / "agent-browser"
|
||||
if not node_modules.exists() and shutil.which("npm"):
|
||||
_print_info(" Installing Node.js dependencies for browser tools...")
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue