Commit Graph

9153 Commits

Author SHA1 Message Date
ShawnPana ae93cee5c2 fix: unify CLI cloud auth so cloud connect uses ~/.browser-use/config.json
cloud connect was silently reading credentials from the library's
~/.config/browseruse/cloud_auth.json, bypassing cloud login/logout
entirely. Now ensure_daemon injects the CLI config's API key into the
daemon subprocess env, so all cloud commands share a single auth source.
2026-03-28 15:56:56 -07:00
ShawnPana 1f8b4a5346 fix: rewrite register tests to use real code path via subprocess 2026-03-27 11:49:47 -07:00
ShawnPana 6bb73ab274 merge upstream/main, resolve install_lite.sh conflict (take upstream) 2026-03-26 11:40:33 -07:00
ShawnPana 464bd167c3 fix: daemon zombie on close, add idle timeout, clean up PID file before exit 2026-03-26 11:31:15 -07:00
shawn pana eee98ff272 feat(cli): add install-lite.sh script for the CLI (#4534)
<!-- This is an auto-generated description by cubic. -->
## Summary by cubic
Adds a lightweight installer (`install_lite.sh`) that sets up the
`browser-use` CLI with minimal deps and Chromium, avoiding the full
library. Also extracts CLI deps into `requirements-cli.txt`, adds a CI
test, and hardens the installer with a `curl` pre-check and non-fatal
validate.

- New Features
- `install_lite.sh` installs Python 3.11+, `uv`, the CLI (`--no-deps`)
with minimal deps from `requirements-cli.txt`, and Chromium via `uvx
playwright` in `~/.browser-use-env`, and configures PATH (Linux, macOS,
Windows).
- Installs the `profile-use` helper into `~/.browser-use/bin` for
profile management.
- CI test (`tests/ci/test_cli_lite_deps.py`) boots the CLI in a clean
venv with only minimal deps and checks key imports.
- Minimal CLI deps pinned in
`browser_use/skill_cli/requirements-cli.txt`.

- Bug Fixes
  - Validation is non-fatal; next steps are shown even if checks warn.
- Checks for `curl` before installing `uv` to prevent confusing
failures.

<sup>Written for commit 7e92031593.
Summary will update on new commits.</sup>

<!-- End of auto-generated description by cubic. -->
2026-03-26 09:47:18 -07:00
shawn pana 7e92031593 Merge branch 'main' into install-lite 2026-03-26 09:43:49 -07:00
ShawnPana e3a994a39d fix: non-fatal validate + curl check before use 2026-03-26 09:40:35 -07:00
ShawnPana 2f41a42eab extract CLI deps to requirements-cli.txt + add CI test 2026-03-26 09:27:18 -07:00
ShawnPana 822a4d948b add aiohttp to lite install deps (needed by LocalBrowserWatchdog._wait_for_cdp_url) 2026-03-26 09:15:29 -07:00
ShawnPana a2cbe678b7 add lightweight CLI install script 2026-03-26 09:15:29 -07:00
laithrw 76cc49089b fix(mcp): remove oneOf from browser_click schema that breaks Claude API clients (#4212)
## Problem

Closes #4211

`browser_click` in the MCP server uses `oneOf` at the top level of
`inputSchema` to express "provide either `index` OR
`coordinate_x`+`coordinate_y`":

```json
{
  "type": "object",
  "properties": { ... },
  "oneOf": [
    {"required": ["index"]},
    {"required": ["coordinate_x", "coordinate_y"]}
  ]
}
```

Claude's API (and other strict MCP clients) rejects
`oneOf`/`allOf`/`anyOf` at the top level of a tool input schema:

```
400 tools.N.custom.input_schema: input_schema does not support oneOf, allOf, or anyOf at the top level
```

This cascades — it breaks **all** MCP tools in the session, not just
`browser_click`.

## Fix

Remove the `oneOf` block. The constraint is now expressed in the
property descriptions instead. No behaviour change: the runtime guard in
`_click()` already returns a clear error string when neither `index` nor
coordinates are provided.

## Diff summary

- `-4 lines`: remove the `oneOf: [...]` block entirely
- `+3 lines`: update the three property descriptions to say "Provide
this OR ..."

The `_click()` handler is untouched.

<!-- This is an auto-generated description by cubic. -->
---
## Summary by cubic
Remove the top-level oneOf from the `browser_click` tool input schema so
Claude and other strict MCP clients accept it and the session doesn’t
break. No behavior change; `_click()` still validates, and field
descriptions now clarify using `index` or `coordinate_x`+`coordinate_y`.

<sup>Written for commit 6094cddd90.
Summary will update on new commits.</sup>

<!-- End of auto-generated description by cubic. -->
2026-03-26 11:08:20 -04:00
laithrw 6094cddd90 Merge branch 'main' into fix/mcp-browser-click-oneof-schema 2026-03-26 10:59:46 -04:00
ShawnPana 24a0df7e72 add aiohttp to lite install deps (needed by LocalBrowserWatchdog._wait_for_cdp_url) 2026-03-25 22:27:43 -07:00
ShawnPana d8aeaa9ab4 add lightweight CLI install script 2026-03-25 22:15:45 -07:00
laithrw 8f201decd3 fix: stop cloud sessions when reconnecting via cdp_url (#4096)
## Summary
- derive cloud browser session UUID from Browser Use CDP host (e.g.
`<uuid>.cdp0.browser-use.com`)
- use that UUID as fallback in `BrowserSession.on_BrowserStopEvent` when
`_cloud_browser_client.current_session_id` is empty
- ensure reconnected sessions created via `BrowserSession(cdp_url=...)`
are properly stopped in cloud, not just reset locally

## Why
Reconnected cloud sessions (common MFA resume pattern) can leak browser
instances because stop logic only used `current_session_id`, which is
populated when the same process created the cloud browser. In reconnect
flows, that field is often unset.



<!-- This is an auto-generated description by cubic. -->
---
## Summary by cubic
Ensure cloud browser sessions are stopped when reconnecting via cdp_url,
preventing leaked instances during MFA/resume flows. We derive the
session UUID from the CDP URL host and pass it to `stop_browser` with
the explicit ID.

- **Bug Fixes**
- Added a helper to extract the session UUID from the CDP host (e.g.,
<uuid>.cdpN.browser-use.com).
- Updated stop logic to use `current_session_id` or the derived UUID and
call `stop_browser(id)`; logs now include the session ID.

<sup>Written for commit 4c883feb7c.
Summary will update on new commits.</sup>

<!-- End of auto-generated description by cubic. -->
2026-03-25 19:39:19 -04:00
ShawnPana e09ba11ef1 feat: remove event bus dependency, add dialog handling
- Remove event bus tab listeners from daemon — track tabs directly
- Remove dead event bus fallback branches from commands/browser.py
- Replace SwitchTabEvent/CloseTabEvent dispatches with direct CDP calls
- Update python_session.py to use ActionHandler instead of event bus
- Add JS dialog handler (alert/confirm/prompt) to CLIBrowserSession
- Surface auto-dismissed popup messages in state output
- Only dummy EventBus() for watchdog constructors remains (unavoidable)
2026-03-25 16:37:26 -07:00
laithrw 4c883feb7c Merge branch 'main' into fix/cloud-session-stop-cdp-reconnect 2026-03-25 19:34:25 -04:00
laithrw 6ce58afbc3 fix tunnel process kill and daemon spawn on windows (#4530)
Resolves #4352

<!-- This is an auto-generated description by cubic. -->
---
## Summary by cubic
Fixes Windows tunnel lifecycle bugs by spawning `cloudflared` as a
detached daemon and reliably terminating it to prevent orphaned
processes. Resolves #4352.

- **Bug Fixes**
- Windows spawn uses `CREATE_NEW_PROCESS_GROUP | CREATE_NO_WINDOW`; Unix
uses `start_new_session=True`.
- Windows kill uses Win32 `OpenProcess/TerminateProcess` with brief
polling; Unix uses `SIGTERM` with `SIGKILL` fallback.

<sup>Written for commit 4950c3baa1.
Summary will update on new commits.</sup>

<!-- End of auto-generated description by cubic. -->
2026-03-25 19:34:17 -04:00
laithrw 4950c3baa1 Merge branch 'main' into fix-4352 2026-03-25 19:32:05 -04:00
Laith Weinberger 9b401cf04c fix tunnel process kill and daemon spawn on windows 2026-03-25 19:28:47 -04:00
laithrw 86d33635c5 fix(agent): prevent stale history and stuck step counter on timeout (#4481)
## Summary

- Clear `last_model_output` and `last_result` at the start of `step()`
to prevent stale data from previous steps being recorded in history on
timeout
- Increment `n_steps` in `_execute_step`'s timeout handler to prevent
the main loop from retrying the same step number

Fixes #4480

## What changed

**`step()` — clear stale state at entry:**
```diff
  self.step_start_time = time.time()
+
+ # Clear previous step state to prevent stale data from being recorded
+ self.state.last_model_output = None
+ self.state.last_result = None
+
  browser_state_summary = None
```

**`_execute_step()` — ensure counter advances on timeout:**
```diff
  self.state.last_result = [ActionResult(error=error_msg)]
+ # Ensure step counter advances on timeout
+ if self.state.n_steps == step + 1:
+     self.state.n_steps += 1
```

The guard `if self.state.n_steps == step + 1` prevents double-increment
when `_finalize()` has already incremented on the normal path.

<!-- This is an auto-generated description by cubic. -->
---
## Summary by cubic
Fixes stale history entries and a stuck step counter when a step times
out. Clears per-step state after `_prepare_context` and ensures
`n_steps` advances on timeout.

- **Bug Fixes**
- Clear `last_model_output` and `last_result` right after
`_prepare_context` (before LLM/action calls) so prompts keep previous
output and timeouts don't record stale data.
- In `_execute_step()`, increment `n_steps` after a timeout (with a
guard) so the loop moves forward.

<sup>Written for commit c0a11dc61e.
Summary will update on new commits.</sup>

<!-- End of auto-generated description by cubic. -->
2026-03-25 19:28:20 -04:00
laithrw 8fcbe9f2fa Merge branch 'main' into fix/step-timeout-counter-and-stale-history 2026-03-25 19:22:19 -04:00
laithrw 34597151bc fix anthropic action field double-serialization (#4529)
Resolves #4510

<!-- This is an auto-generated description by cubic. -->
---
## Summary by cubic
Fixes double-serialized action fields in Anthropic tool responses to
prevent schema validation errors and failed tool calls. Preserves
original tracebacks in the fallback path.

- **Bug Fixes**
- Parse nested JSON strings in tool inputs; normalize newline/carriage
return/tab escapes when needed.
- Applied in `browser_use/llm/anthropic/chat.py` and
`browser_use/llm/aws/chat_anthropic.py`.

<sup>Written for commit f74a4435b1.
Summary will update on new commits.</sup>

<!-- End of auto-generated description by cubic. -->
2026-03-25 19:20:51 -04:00
laithrw f74a4435b1 Merge branch 'main' into fix-4510 2026-03-25 19:18:32 -04:00
Laith Weinberger 69c7df060f use just raise to preserve traceback in anthropic fallback 2026-03-25 19:16:50 -04:00
Laith Weinberger 8e8ab73575 fix anthropic action field double-serialization 2026-03-25 19:12:56 -04:00
laithrw fe2a72a59b feat(tokens): allow overriding model pricing URL (#4528)
Slightly modified #4401

<!-- This is an auto-generated description by cubic. -->
---
## Summary by cubic
Allow overriding the model pricing source for token cost calculations,
with URL-aware caching to keep caches from different sources separate.
Defaults remain the LiteLLM pricing JSON.

- **New Features**
- `TokenCost` accepts an optional `pricing_url`; `Agent(...,
pricing_url=...)` passes it through.
- New env var BROWSER_USE_MODEL_PRICING_URL to set a global pricing
source.
- Cache files now include `source_url` so multiple sources can coexist.

- **Bug Fixes**
- Cache validation and cleanup are source-aware and only remove expired
or same-source files.

<sup>Written for commit 4f268e4390.
Summary will update on new commits.</sup>

<!-- End of auto-generated description by cubic. -->
2026-03-25 18:22:50 -04:00
laithrw 4f268e4390 Merge branch 'main' into override-price-config 2026-03-25 18:20:20 -04:00
Laith Weinberger f6c6046215 fix pricing url cache cleanup and remove phantom code_use module 2026-03-25 18:16:53 -04:00
laithrw db7bdb3d1b Feature/cdp navigation timeout (#4527)
Resolves #4491

<!-- This is an auto-generated description by cubic. -->
## Summary by cubic
Make CDP navigation timeout configurable and apply it to
`Page.navigate`, fixing mismatched timeouts. This aligns
`NavigateToUrlEvent` (and `TIMEOUT_NavigateToUrlEvent`) with the actual
CDP call and prevents early failures on heavy pages.

- **Bug Fixes**
- Add `nav_timeout` to `_navigate_and_wait` and use it for
`Page.navigate(...)`.
- Pass `event.event_timeout`; default remains 20s when not provided.
Outer `timeout_ms` behavior is unchanged.

<sup>Written for commit 801b134f90.
Summary will update on new commits.</sup>

<!-- End of auto-generated description by cubic. -->
2026-03-25 17:33:12 -04:00
laithrw a2313d9665 Merge branch 'main' into feature/cdp-navigation-timeout 2026-03-25 17:30:42 -04:00
Laith Weinberger 801b134f90 undo ci 2026-03-25 17:28:30 -04:00
laithrw 72c403acb4 fix daemon orphaning when external browser dies on --connect/--cdp-url (#4526)
Resolves #4492

<!-- This is an auto-generated description by cubic. -->
---
## Summary by cubic
Fixes daemon orphaning when the external browser or CDP connection dies
(with `--connect`, `--cdp-url`, or cloud). Adds safer connection
watching, bounded cleanup, and a hard exit that preserves the exit code.
Resolves #4492.

- **Bug Fixes**
- Skip shutdown while the browser is reconnecting; shut down only when
CDP stays disconnected.
  - Prevent duplicate shutdowns by scheduling a single shutdown task.
- Add 10s timeouts around `browser_session.stop()`/`kill()` to avoid
hangs; log on timeout.
- Force process exit in `finally` via `os._exit(exit_code)` to preserve
error status and prevent orphaned daemons.

<sup>Written for commit a31809b83d.
Summary will update on new commits.</sup>

<!-- End of auto-generated description by cubic. -->
2026-03-25 17:18:28 -04:00
Laith Weinberger a31809b83d preserve error exit code 2026-03-25 17:15:34 -04:00
ShawnPana 4c5fae3a17 feat: lightweight CLIBrowserSession — no watchdogs, no event bus
CLIBrowserSession.start() now handles all three browser modes without
loading watchdogs or the event bus:

- --connect: CDP URL already known, calls connect() directly
- Managed Chromium: launches browser via LocalBrowserWatchdog._launch_browser()
  (instantiated as plain object, not registered on event bus), then connect()
- Cloud: provisions via CloudBrowserClient, then connect()

All modes converge at connect() for lightweight CDP setup. Also adds
process cleanup in kill() for managed Chromium, and is_cdp_connected
property for daemon watchdog polling.
2026-03-25 14:13:25 -07:00
laithrw b845cb262f Merge branch 'main' into fix-4492 2026-03-25 17:11:56 -04:00
Laith Weinberger c9ea2fb1cf fix daemon orphaning when external browser dies on --connect/--cdp-url 2026-03-25 17:07:03 -04:00
laithrw d16261f8b7 rm pass (#4525)
<!-- This is an auto-generated description by cubic. -->
## Summary by cubic
Removed a redundant pass in the exception handler of
`SecurityWatchdog.on_NavigationCompleteEvent`, simplifying the code
while keeping error logging intact. No behavior change.

<sup>Written for commit 393d2c5b0f.
Summary will update on new commits.</sup>

<!-- End of auto-generated description by cubic. -->
2026-03-25 16:58:25 -04:00
Laith Weinberger 393d2c5b0f rm pass 2026-03-25 16:56:36 -04:00
ShawnPana 7bb2741292 feat: lightweight CLIBrowserSession — no watchdogs, no event bus
Subclass BrowserSession as CLIBrowserSession that calls connect()
directly instead of start(). Skips all 13 watchdogs and event bus
handler registration. Actions execute via ActionHandler which calls
DefaultActionWatchdog methods directly and DomService for DOM snapshots.

- CLIBrowserSession.start() → connect() only (CDP + SessionManager)
- CLIBrowserSession.stop() → close websocket directly (no BrowserStopEvent)
- CLIBrowserSession.kill() → Browser.close + disconnect
- ActionHandler wraps DefaultActionWatchdog for click/type/scroll/keys/etc
- DomService called directly for state (no DOMWatchdog)
- Monkey-patches _enable_page_monitoring to no-op after initial connect
- Disables auto-reconnect (_intentional_stop = True)
- Falls back to event bus path if ActionHandler is not available
2026-03-25 13:28:12 -07:00
laithrw 8b14384531 fix(utils): add option to disable SignalHandler for host app signal control (#4387)
The SignalHandler class registers SIGINT/SIGTERM handlers that override
host application signal handling. This breaks server embeddings
(uvicorn, FastAPI, etc.) where the framework needs to control the signal
lifecycle for graceful shutdown.

Add disabled parameter to SignalHandler class to allow opting out of
signal handling. Add enable_signal_handler parameter to Agent class
(default True for backward compatibility).

Usage for embedding applications:



Fixes #4385

<!-- This is an auto-generated description by cubic. -->
---
## Summary by cubic
Fixes #4385 by adding an opt-out for internal SIGINT/SIGTERM handling so
host apps like `uvicorn`/`FastAPI` can control graceful shutdown.
`SignalHandler` now supports `disabled`, and `Agent` adds
`enable_signal_handler` (default True).

- **Bug Fixes**
- `SignalHandler(disabled: bool)` added; when True,
`register()`/`unregister()` are no-ops.
- `Agent(enable_signal_handler: bool = True)` added and passed through
as `disabled=not enable_signal_handler`.

- **Migration**
- For embeddings, use `Agent(..., enable_signal_handler=False)` or
`SignalHandler(disabled=True)`.

<sup>Written for commit 4f33289c48.
Summary will update on new commits.</sup>

<!-- End of auto-generated description by cubic. -->
2026-03-25 16:21:40 -04:00
laithrw 4f33289c48 Merge branch 'main' into clawoss/fix/signal-handler-opt-out-4385 2026-03-25 16:19:49 -04:00
laithrw e9d2e91bf7 fix: use login shell for PATH configuration in install script (#4457)
## Summary
- Fix install script writing PATH to `~/.bashrc` instead of `~/.zshrc`
for zsh users
- Use `$SHELL` (user's login shell) instead of
`$BASH_VERSION`/`$ZSH_VERSION` (running shell) for shell detection
- When executed via `curl ... | bash`, the script always runs in bash,
so `$BASH_VERSION` is always set regardless of the user's actual shell

## Changes
- `configure_path()`: Replace `$BASH_VERSION`/`$ZSH_VERSION` check with
`$(basename "$SHELL")`
- `print_next_steps()`: Same fix for the shell RC file displayed in
completion message


This could be considered as a follow-up improvement if the maintainers
prefer.

Fixes #4440
2026-03-25 16:16:52 -04:00
laithrw b6e17ceb05 Merge branch 'main' into fix/install-shell-detection 2026-03-25 16:13:42 -04:00
laithrw 762a1ee269 fix bedrock structured output w SchemaOptimizer to flatten schema (#4524)
Resolves #4411

<!-- This is an auto-generated description by cubic. -->
---
## Summary by cubic
Fixes Bedrock structured output by using `SchemaOptimizer` to generate a
flattened JSON Schema for tool inputs, preventing invalid schemas and
extraction errors. Resolves #4411.

- **Bug Fixes**
- Replaced manual `properties/required` builder with
`SchemaOptimizer.create_optimized_json_schema(...)`.
- Passed the optimized schema directly to `toolSpec.inputSchema.json`
for Bedrock tool calls.

<sup>Written for commit d897ffbd4c.
Summary will update on new commits.</sup>

<!-- End of auto-generated description by cubic. -->
2026-03-25 15:53:02 -04:00
Laith Weinberger d897ffbd4c fix bedrock structured output w SchemaOptimizer to flatten schema 2026-03-25 15:48:12 -04:00
Saurav Panda c186be39c4 fix: set default temperature to 1.0 for gemini-3 models (#4489)
As per the [Gemini 3 best practices
guide](https://ai.google.dev/gemini-api/docs/gemini-3#temperature),
temperature is recommended to stay at 1.0 for 3-series models. Currently
the default is 0.5 across the board, which is potentially detrimental.

<!-- This is an auto-generated description by cubic. -->
---
## Summary by cubic
Set dynamic default temperature: 1.0 for `gemini-3`, 0.5 otherwise; if
`temperature` is provided, it’s used as-is.

<sup>Written for commit c657ba72c3.
Summary will update on new commits.</sup>

<!-- End of auto-generated description by cubic. -->
2026-03-25 09:15:57 -07:00
Matt Greathouse df47c01449 Merge branch 'main' into override-price-config 2026-03-25 08:06:42 -04:00
Mark McDonald c657ba72c3 Merge branch 'main' into fix-gemini-3-temperature 2026-03-25 11:57:43 +08:00
Magnus Müller 45f3dc5593 Remove litellm from dependencies (supply chain attack) (#4515)
## Summary

Remove `litellm` from `pyproject.toml` dependencies entirely.
`ChatLiteLLM` wrapper is kept but requires manual installation:

```
pip install litellm
```

## What changed

- **pyproject.toml**: `litellm==1.82.2` removed from core dependencies
- **browser_use/llm/litellm/chat.py**: Added docstring noting manual
install requirement, added `# type: ignore` for pyright since litellm is
no longer in the environment
- **ChatLiteLLM stays in the public API** — it already lazy-imports
litellm inside methods, so users who don't use it are never affected

## Context

litellm versions 1.82.7 and 1.82.8 were backdoored on March 24, 2026 by
TeamPCP via a compromised Trivy CI/CD pipeline. `browser-use==0.12.3`
shipped `litellm>=1.82.2` (unpinned) as a core dependency, and BigQuery
analysis shows ~6,900 installs pulled the backdoored litellm during the
4-hour attack window.

By removing it from dependencies entirely, `pip install browser-use` no
longer pulls litellm, and browser-use will not appear in litellm's
dependency graph.

## References

- [TeamPCP Backdoors LiteLLM — The Hacker
News](https://thehackernews.com/2026/03/teampcp-backdoors-litellm-versions.html)
- [LiteLLM infected via Trivy — The
Register](https://www.theregister.com/2026/03/24/trivy_compromise_litellm/)

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Medium Risk**
> Medium risk because removing `litellm` from required dependencies can
break existing installs that relied on `ChatLiteLLM` working
out-of-the-box; runtime imports now require manual installation.
> 
> **Overview**
> Stops installing `litellm` as a core dependency (and bumps the package
version to `0.12.5`), requiring users to install it explicitly when
using the LiteLLM integration.
> 
> Keeps `ChatLiteLLM` but adds a module docstring documenting the manual
install and updates `litellm` imports with `# type: ignore` to avoid
type-check failures when `litellm` is absent.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
d4b9e30188. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
0.12.5
2026-03-24 20:36:50 -07:00