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. -->
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. -->
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. -->
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.
<!-- 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. -->
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
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. -->
## 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
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. -->
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. -->
## 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 -->
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, exposing
~6,900 users to the backdoored versions during the 4-hour window.
This commit:
- Removes litellm entirely from pyproject.toml (core and optional)
- Keeps ChatLiteLLM wrapper intact with a docstring noting
`pip install litellm` is required separately
- litellm is already lazy-imported inside methods, so users who
don't use ChatLiteLLM are never affected
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- `browser-use register` assigns numeric agent index for --connect mode
- `--connect <index>` requires explicit agent index (no more bare --connect)
- `tab list` shows all tabs with lock status per agent
- `tab new [url]` creates a new tab without visually switching
- `tab switch <index>` changes agent focus without activating Chrome tab
- `tab close <index> [index...]` closes multiple tabs in one command
- Agent registry in ~/.browser-use/agents.json with 5min expiry
- Improved error messages guide agents to register or use their own tab
- Session lock prevents double BrowserSession creation on simultaneous connect
- Updated SKILL.md with register workflow and tab commands
Multiple agents can share one browser via --connect without interfering
with each other. Each agent registers with `browser-use register` to get
a numeric index, then passes it with `--connect <index>` on every command.
- Tab locking: mutating commands (click, type, open) lock the tab to the
agent. Other agents get an error if they try to mutate the same tab.
Read-only commands (state, screenshot) work on any tab.
- Agent registry: agents.json tracks registered agents with timestamps.
Expired agents (5min inactive) get cleaned up automatically.
- Session lock: prevents double BrowserSession creation when two agents
connect simultaneously.
- Focus swap: daemon swaps agent_focus_target_id and cached_selector_map
per-agent before each command, so element indices are isolated.
- Use os.environ.pop() to completely clear TIMEOUT_NavigateToUrlEvent before test
- Add explicit env var deletion to ensure clean test state
- Properly restore original env var in finally block for isolation
- Prevents flaky behavior when env var is pre-set in test environment
- Replace brittle timing-based assertions with direct parameter verification
- Test both default (30s) and env-var override (40s) behavior
- Remove problematic integration test that relied on fake target IDs
- Keep focused, reliable test that validates timeout parameter propagation
- Ensure bug fix path is properly protected without brittleness
- Replace brittle timing-based test with direct parameter verification
- Use mocking to verify exact timeout values passed to CDP
- Test both default (30s) and env-var override (35s) behavior
- Remove reliance on agent navigation flow and timing assumptions
- Add comprehensive assertions with clear error messages
- Add nav_timeout parameter to navigate_to_url_and_wait() method
- Pass nav_timeout from NavigateToUrlEvent to control CDP navigation timeout
- Fix issue where TIMEOUT_NavigateToUrlEvent env var only controlled outer timeout but CDP call had hardcoded 20s timeout
- Add comprehensive test case to verify env var controls CDP timeout
Fixes bug where `browser-use` CLI installation failed if the user had
installed via curl and note Homebrew.
`install_uv` checked `command -v uv` before adding `~/.local/bin` to
PATH. This worked for Homebrew but not for curl-based installs, because
Homebrew installs to a directory already in PATH.
<!-- This is an auto-generated description by cubic. -->
---
## Summary by cubic
Fixes `browser-use` CLI installs failing when `uv` was installed via the
curl script, and makes the installer script executable. We now add
common `uv` paths to PATH before detection so it works for both curl and
Homebrew installs.
- **Bug Fixes**
- Prepend `$HOME/.local/bin` and `$HOME/.cargo/bin` to PATH before
`command -v uv`; drop the redundant export after install.
- Mark `browser_use/skill_cli/install.sh` as executable so it can run
directly.
<sup>Written for commit fae8036728.
Summary will update on new commits.</sup>
<!-- End of auto-generated description by cubic. -->
<!-- This is an auto-generated description by cubic. -->
## Summary by cubic
Bump the `browser-use` package version from 0.12.2 to 0.12.3 in
`pyproject.toml` to prepare the 0.12.3 release.
<sup>Written for commit 45bff34a18.
Summary will update on new commits.</sup>
<!-- End of auto-generated description by cubic. -->