Commit Graph
10154 Commits
Author SHA1 Message Date
Magnus Müller 4f89716294 fix(agent): preserve downloaded file path order (#5453)
## Summary

- preserve caller-provided `available_file_paths` ordering when
downloads are discovered
- append new downloads in discovery order while deduplicating repeated
paths
- add a regression test covering existing inputs, ordered downloads, and
duplicate download entries

## Problem

`Agent._update_available_file_paths()` converted both the existing file
list and the latest downloads to sets, then rebuilt
`available_file_paths` from their union. Set iteration order is not the
order supplied by the caller or the browser, so the
`<available_file_paths>` block exposed to the model could change order
across processes.

## Fix

Use a set only for membership checks. Keep the original list as the
output source of truth and append each unseen download in first-seen
order.

## Verification

- regression test: RED on `main`, GREEN with this change
- `uv run pytest -q tests/ci/test_agent_download_paths.py
tests/ci/test_beta_agent.py -x`: 202 passed, 1 skipped
- `uv run pyright browser_use/agent/service.py
tests/ci/test_agent_download_paths.py`: 0 errors
- Ruff lint and format checks passed
- full `tests/ci` reached 479 passed / 33 skipped before one
pre-existing module-identity assertion failed; that exact test passed
when rerun alone

AI assistance was used to help inspect the codebase, draft the
regression test, and validate the change.

<!-- This is an auto-generated description by cubic. -->
---
## Summary by cubic
Fixes unstable ordering of `available_file_paths` by preserving the
caller's list order and appending new downloads in discovery order.
Prevents reordering across processes and removes duplicates.

- **Bug Fixes**
- Replaced set-union logic with list + membership checks to keep
original order.
  - Append only unseen downloads in first-seen order; ignore duplicates.
- Added regression test covering input order, download order, and
duplicate entries.

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

<a
href="https://cubic.dev/pr/browser-use/browser-use/pull/5453?utm_source=github"
target="_blank" rel="noopener noreferrer"
data-no-image-dialog="true"><picture><source
media="(prefers-color-scheme: dark)"
srcset="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"><source
media="(prefers-color-scheme: light)"
srcset="https://www.cubic.dev/buttons/review-in-cubic-light.svg"><img
alt="Review in cubic"
src="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"></picture></a>

<!-- End of auto-generated description by cubic. -->
2026-08-30 22:50:02 -07:00
Magnus Müller e785b615d2 Merge branch 'main' into codex/fix-agent-download-path-order 2026-08-30 22:47:23 -07:00
Magnus Müller 34933c4d2c fix(agent): match URL negations as whole words (#5493)
## Summary

- match URL negation terms as whole words instead of arbitrary
substrings
- share the negation matcher across the standard and beta agent URL
extractors
- add regression coverage for both a false positive (`notable`) and an
explicit negation (`do not`)

## Problem

The direct-navigation URL extractors used substring checks for `not`. As
a result, normal prose such as `Open this notable site:
https://example.com` was treated as a negated instruction, so the agent
skipped its initial navigation action.

## Testing

- `python -m pytest -o addopts=''
tests/ci/test_beta_agent.py::test_beta_agent_exposes_task_helper_methods`
- `ruff check browser_use/utils.py browser_use/agent/service.py
browser_use/beta/service.py tests/ci/test_beta_agent.py`
- `ruff format --check browser_use/utils.py browser_use/agent/service.py
browser_use/beta/service.py tests/ci/test_beta_agent.py`

<!-- This is an auto-generated description by cubic. -->
---
## Summary by cubic
Matches URL negations as whole words during direct-navigation
extraction, so prose like "notable" no longer causes false skips.
Previously the extractors substring-matched "not"; now both agents share
a word-boundary regex for never/not/don't (straight or curly
apostrophes) in the 20-character pre-URL context.

- Adds `URL_NEGATION_PATTERN` and `has_url_negation` in
`browser_use/utils.py`; used by `browser_use/agent/service.py` and
`browser_use/beta/service.py`.
- Removes per-extractor `excluded_words`; keeps the 20-character window;
injects the scheme after the negation check; updates debug messaging.
- Adds regression tests allowing "notable" and blocking "Do not open …"
for both agents.

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

<a
href="https://cubic.dev/pr/browser-use/browser-use/pull/5493?utm_source=github"
target="_blank" rel="noopener noreferrer"
data-no-image-dialog="true"><picture><source
media="(prefers-color-scheme: dark)"
srcset="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"><source
media="(prefers-color-scheme: light)"
srcset="https://www.cubic.dev/buttons/review-in-cubic-light.svg"><img
alt="Review in cubic"
src="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"></picture></a>

<!-- End of auto-generated description by cubic. -->
2026-08-30 19:20:02 -07:00
Magnus Müller c05a826af8 Merge branch 'main' into codex/fix-url-negation-boundaries 2026-08-30 19:17:36 -07:00
Magnus Müller 663089797e fix(llm): preserve zero max_retries for Anthropic Bedrock (#5348) 2026-08-30 19:16:30 -07:00
Magnus Müller 90eb2b42de Merge branch 'main' into fix/bedrock-zero-retries 2026-08-30 19:14:28 -07:00
Magnus Müller ad03ce5e32 Merge branch 'main' into codex/fix-url-negation-boundaries 2026-08-30 17:17:30 -07:00
Magnus Müller 5def56e6c0 fix(llm): preserve schema-keyword field names (#5605)
## What

Treat keys inside a schema `properties` map as user field names before
applying schema-keyword rules. This keeps fields named `description` or
`properties` from retaining dangling `$ref` values.

Fixes #5603

## Test

- `uv run pytest -q tests/ci/models/test_llm_schema_optimizer.py`
- `uv run pre-commit run --files browser_use/llm/schema.py
tests/ci/models/test_llm_schema_optimizer.py`

<!-- This is an auto-generated description by cubic. -->
---
## Summary by cubic
Fixes schema optimization so user fields named `description` or
`properties` no longer keep dangling `$ref` values.

- Treats keys inside a `properties` map as field names before applying
schema-keyword rules.
- Simplifies `title` skipping, which now only applies outside
`properties`.
- Adds coverage for nested and aliased fields named after schema
keywords.

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

<a
href="https://cubic.dev/pr/browser-use/browser-use/pull/5605?utm_source=github"
target="_blank" rel="noopener noreferrer"
data-no-image-dialog="true"><picture><source
media="(prefers-color-scheme: dark)"
srcset="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"><source
media="(prefers-color-scheme: light)"
srcset="https://www.cubic.dev/buttons/review-in-cubic-light.svg"><img
alt="Review in cubic"
src="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"></picture></a>

<!-- End of auto-generated description by cubic. -->
2026-08-30 15:03:22 -07:00
MagMueller b2507091aa test: cover aliased schema keyword fields 2026-08-30 14:56:47 -07:00
MagMueller c48b1c9928 fix(llm): preserve schema-keyword field names 2026-08-30 14:48:44 -07:00
Magnus Müller 5fc228f4fd docs(cloud): add API v4 skill reference (#5591)
## Why

The official `cloud` skill still routes new hosted-agent integrations
through
API v2 or v3. Browser Use's current Cloud quickstart uses API v4, so
agents that
load the skill miss the current run, session, and workspace flow.

## What changed

- add a focused API v4 reference for Python, TypeScript, and REST
- route new hosted-agent setup to v4 while keeping v2 and v3 available
for existing integrations
- document the current browser boundary: v4 REST, explicit v3 SDK
namespace, and explicit stop required
- mark the old quickstart as the legacy v2 path

## Verification

- Cloud skill validator passed
- all 12 routed references resolve
- three Python examples parse
- six documented REST routes match the current v4 OpenAPI spec
- repository pre-commit passed for all three changed files
- three skill-install CI tests passed
- `git diff --check` passed

<!-- This is an auto-generated description by cubic. -->
---
## Summary by cubic
Adds an API v4 reference to the `cloud` skill and routes new
hosted-agent setups to v4, while keeping v2 and v3 available for
existing integrations.

- Documents runs, sessions, workspaces, and direct browser control with
Python, TypeScript, and REST examples.
- Notes that the browser-management SDK wrapper still uses the `v3`
namespace, and that browsers must be stopped explicitly because closing
CDP does not stop billing.
- Marks the old quickstart as the legacy v2 path.
- Adds a CI test that verifies the v4 reference's workspace file-listing
examples.

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

<a
href="https://cubic.dev/pr/browser-use/browser-use/pull/5591?utm_source=github"
target="_blank" rel="noopener noreferrer"
data-no-image-dialog="true"><picture><source
media="(prefers-color-scheme: dark)"
srcset="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"><source
media="(prefers-color-scheme: light)"
srcset="https://www.cubic.dev/buttons/review-in-cubic-light.svg"><img
alt="Review in cubic"
src="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"></picture></a>

<!-- End of auto-generated description by cubic. -->
2026-08-30 14:31:38 -07:00
MagMueller 442455465b Merge remote-tracking branch 'origin/main' into agency/cloud-skill-v4
# Conflicts:
#	tests/ci/test_browser_use_skill_install_docs.py
2026-08-30 10:01:11 -07:00
MagMueller cf0b917fba docs: remove stale session discount 2026-08-30 09:10:39 -07:00
MagMueller 3fdb4ab69a docs: correct cloud browser session price 2026-08-30 09:10:39 -07:00
Magnus Müller d2fcda58b8 fix(llm/google): keep the first user message when include_system_in_user is set (#5597)
Fixes #5596

`ChatGoogle(include_system_in_user=True)` is meant to prepend the system
text to the first user message. When that message has list content it
replaced it instead: the system text became the only part sent, and the
user's text and images were dropped.

That is the shape an agent run always produces. `use_vision` defaults to
`True`, `AgentMessagePrompt.get_user_message()` returns list content as
soon as there is a screenshot, and `MessageHistory.get_messages()` puts
the state message first among the user messages. So with this flag on,
every step sent Gemini the system prompt and nothing else, with no error
anywhere.

The cause was structural: the content-part conversion lived in the
`else` arm of the prepend branch, so taking the prepend branch skipped
it. The fix computes the system text first and then always runs the
conversion, folding the system text into the leading text only for `str`
content, which is what it already did.

Before, on `main`:

```
include_system_in_user=False user ["'<browser_state>the page and the task live'", 'image']
include_system_in_user=True  user ["'You are a browser agent.'"]
```

After:

```
include_system_in_user=False user ["'<browser_state>the page and the task live'", 'image']
include_system_in_user=True  user ["'You are a browser agent.'", "'<browser_state>the page and the task live'", 'image']
```

### Tests

Three tests in `tests/ci/models/test_llm_google.py`, real objects only:

- `test_include_system_in_user_keeps_list_content_parts`: text part and
image survive alongside the prepended system text.
- `test_include_system_in_user_string_content_is_merged_into_one_part`:
parity guard for the `str` path, which was already correct and must stay
a single merged part. This one passes on `main` too.
- `test_include_system_in_user_keeps_the_agent_state_message`: builds
the message through the real `AgentMessagePrompt` with `use_vision=True`
and asserts the task and screenshot reach the serialized contents.

Reverting the change in `browser_use/llm/google/serializer.py` and
rerunning:

```
FAILED tests/ci/models/test_llm_google.py::test_include_system_in_user_keeps_list_content_parts
E   AssertionError: user text was dropped
    assert '<browser_state>the page and the task live here</browser_state>' in 'You are a browser agent.'

FAILED tests/ci/models/test_llm_google.py::test_include_system_in_user_keeps_the_agent_state_message
E   AssertionError: the task never reached the model

2 failed, 1 passed
```

With the fix, `pytest tests/ci/models/test_llm_google.py` gives 8
passed, 1 skipped (the skip is the live `gemini-3-flash-preview` test,
no API key here).

### Checks

`pre-commit run --files browser_use/llm/google/serializer.py
tests/ci/models/test_llm_google.py` passes every hook, including ruff
check, ruff format and pyright at the versions pinned in
`.pre-commit-config.yaml`.

Full suite, `pytest tests/ci -q -o addopts="" --timeout=120`: 2 failed,
1108 passed, 34 skipped on this branch, against 2 failed, 1105 passed,
34 skipped on `main` (the +3 are the new tests). The two failures are
the same `tests/ci/test_beta_agent.py` isinstance checks in both runs;
they are order-dependent and pass on their own, and they are unrelated
to this change.

<!-- This is an auto-generated description by cubic. -->
---
## Summary by cubic
Fixes #5596 by keeping the first user message's content when
`include_system_in_user=True` is set on `ChatGoogle`. Previously, when
the message had list content (text plus images, as the agent always
produces with vision on), the system text replaced it and the user's
text and screenshot were dropped; now the system text is prepended and
the user's parts are preserved.

- Reorders the serializer so content conversion runs for both string and
list content, merging system text only into the leading text part.
- Adds three tests covering list content, string content parity, and the
agent's actual message shape.

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

<a
href="https://cubic.dev/pr/browser-use/browser-use/pull/5597?utm_source=github"
target="_blank" rel="noopener noreferrer"
data-no-image-dialog="true"><picture><source
media="(prefers-color-scheme: dark)"
srcset="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"><source
media="(prefers-color-scheme: light)"
srcset="https://www.cubic.dev/buttons/review-in-cubic-light.svg"><img
alt="Review in cubic"
src="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"></picture></a>

<!-- End of auto-generated description by cubic. -->
2026-08-30 02:53:15 -07:00
Magnus Müller 6a2b0f4f6c Merge branch 'main' into fix_gemini_system_in_user_drops_parts 2026-08-30 02:51:07 -07:00
Magnus Müller e6ada0d0b7 fix(browser): honor BROWSER_USE_HEADLESS in BrowserProfile (#5420) (#5475)
- Read BROWSER_USE_HEADLESS env var via default_factory in
BrowserProfile

- Preserve fallback to display detection when env var is unset

- Add unit tests covering env var parsing and overrides

Fixes #5420

<!-- This is an auto-generated description by cubic. -->
---
## Summary by cubic
Honors `BROWSER_USE_HEADLESS` in `BrowserProfile` so the env var now
sets the default headless mode instead of being ignored. Unset values
still fall back to display detection, and explicit headless args still
override. Hosts with `BROWSER_USE_HEADLESS` set may see their default
browser mode change.

- `BrowserLaunchArgs.headless` now uses a `default_factory` that parses
the env var case-insensitively: `'0'`/`'false'`/`'no'`/`'off'`/`''` =>
False, any other non-empty value => True, unset => None.
- `BrowserSession` inherits the value via its `browser_profile`.
- Tests for `BROWSER_USE_HEADLESS` and `BROWSER_USE_DISABLE_EXTENSIONS`
are deduplicated with pytest parametrization, covering profile/session
propagation and explicit overrides.

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

<a
href="https://cubic.dev/pr/browser-use/browser-use/pull/5475?utm_source=github"
target="_blank" rel="noopener noreferrer"
data-no-image-dialog="true"><picture><source
media="(prefers-color-scheme: dark)"
srcset="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"><source
media="(prefers-color-scheme: light)"
srcset="https://www.cubic.dev/buttons/review-in-cubic-light.svg"><img
alt="Review in cubic"
src="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"></picture></a>

<!-- End of auto-generated description by cubic. -->
2026-08-30 02:29:04 -07:00
Magnus Müller 34d7978da9 Merge branch 'main' into fix/issue-5420-honor-browser-use-headless 2026-08-30 02:26:44 -07:00
Magnus Müller df21c18249 docs: correct Cloud signup credit (#5602)
## Summary
- replace the stale five-free-task claim with the current $15 one-time
signup credit
- fix the surrounding grammar

## Test
- `pre-commit run --files CLOUD.md`
- `git diff --check`

<!-- This is an auto-generated description by cubic. -->
---
## Summary by cubic
Corrects the Cloud signup credit in `CLOUD.md` from five free tasks to
the current $15 one-time signup credit (if eligible), and fixes the
surrounding grammar.

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

<a
href="https://cubic.dev/pr/browser-use/browser-use/pull/5602?utm_source=github"
target="_blank" rel="noopener noreferrer"
data-no-image-dialog="true"><picture><source
media="(prefers-color-scheme: dark)"
srcset="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"><source
media="(prefers-color-scheme: light)"
srcset="https://www.cubic.dev/buttons/review-in-cubic-light.svg"><img
alt="Review in cubic"
src="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"></picture></a>

<!-- End of auto-generated description by cubic. -->
2026-08-30 02:02:26 -07:00
MagMueller b4e68f19b2 docs: correct signup credit in Cloud guide
Signed-off-by: MagMueller <mamagnus00@gmail.com>
2026-08-29 21:41:22 -07:00
MagMueller b4bad86d21 fix: allow pydantic 2.13 2026-08-29 20:55:35 -07:00
Magnus Müller b87e33402d docs: migrate remote browser skill to CLI 3.0 (#5583)
## Summary
- replace removed pre-3.0 subcommands in the remote-browser skill with
the current piped-Python workflow
- document named Browser Use Cloud daemons for isolated sandbox browser
work
- add a regression test so deleted CLI commands do not return to the
skill

## Why
`skills/remote-browser/SKILL.md` still starts with `browser-use open`
and `browser-use state`. The current CLI exits 2 for both commands and
tells users to use `new_tab()` and `page_info()` through stdin.

## Test
- `uv run --python 3.11 pytest -q
tests/ci/test_browser_use_skill_install_docs.py`
- `uv run --python 3.11 pre-commit run --files
skills/remote-browser/SKILL.md
tests/ci/test_browser_use_skill_install_docs.py`
- `uv run --python 3.11 python
/Users/magnus/.codex/skills/.system/skill-creator/scripts/quick_validate.py
skills/remote-browser`

<!-- This is an auto-generated description by cubic. -->
---
## Summary by cubic
Migrates the remote-browser skill to the current Browser Use CLI 3.0
workflow, replacing removed pre-3.0 subcommands (`browser-use open`,
`browser-use state`, etc.) with the piped-Python interface via stdin
heredocs.

- Documents named Browser Use Cloud daemons for isolated browser
sessions.
- Adds a regression test blocking retired CLI commands from returning to
the skill.

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

<a
href="https://cubic.dev/pr/browser-use/browser-use/pull/5583?utm_source=github"
target="_blank" rel="noopener noreferrer"
data-no-image-dialog="true"><picture><source
media="(prefers-color-scheme: dark)"
srcset="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"><source
media="(prefers-color-scheme: light)"
srcset="https://www.cubic.dev/buttons/review-in-cubic-light.svg"><img
alt="Review in cubic"
src="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"></picture></a>

<!-- End of auto-generated description by cubic. -->
2026-08-29 20:36:49 -07:00
Aniket Wagh a266399645 fix(llm/google): keep the first user message when include_system_in_user is set 2026-08-29 20:27:38 +05:30
MagMueller 7ed622f0de test: cover all retired browser commands 2026-08-28 22:48:56 -07:00
MagMueller 5525c08c54 docs: migrate remote browser skill to CLI 3.0 2026-08-28 22:48:56 -07:00
MagMueller 295a57d957 docs(cloud): add API v4 skill reference
Signed-off-by: MagMueller <mamagnus00@gmail.com>
2026-08-28 19:31:53 -07:00
Saurav Panda 2e32d26034 fix: keep balanced trailing brackets in URLs extracted from task text (#5576)
Fixes #5575

## What was wrong

`sanitize_url_candidate()` drops trailing prose punctuation so that "Go
to https://example.com/docs." does not navigate with the sentence's
period attached. It did that with a single character class:

```python
return re.sub(r'[.,;:!?()\[\]]+$', '', candidate)
```

which also strips closing brackets the URL opened itself.
`Agent._extract_start_url()` runs every URL it finds in the task through
this before auto-navigating, so:

```
Summarize https://en.wikipedia.org/wiki/Python_(programming_language)
```

navigated to
`https://en.wikipedia.org/wiki/Python_(programming_language` and landed
on the wrong page. Wikipedia disambiguation links are the common shape.

## The fix

Whether a trailing bracket belongs to the URL is a question of balance.
`.../Python_(programming_language)` closes a bracket the URL opened, so
it is part of the path. In "See the docs (https://example.com/guide)"
the prose opened it, so dropping it stays correct. The loop strips
trailing punctuation as before and only drops a closing bracket when the
candidate has more closers than openers.

## Before and after

```python
from browser_use.agent.service import Agent
Agent._extract_start_url(None, 'Summarize https://en.wikipedia.org/wiki/Python_(programming_language)')
```

| task text | before | after |
| --- | --- | --- |
| `Summarize
https://en.wikipedia.org/wiki/Python_(programming_language)` |
`...Python_(programming_language` | `...Python_(programming_language)` |
| `Check https://example.com/a[1] please` | `https://example.com/a[1` |
`https://example.com/a[1]` |
| `Go to https://example.com/docs. Then stop.` |
`https://example.com/docs` | `https://example.com/docs` |
| `See the docs (https://example.com/guide) for details.` |
`https://example.com/guide` | `https://example.com/guide` |

The last two rows are the behaviour that had to be preserved: a sentence
period is still dropped, and a bracket the prose opened is still
dropped.

Bracket totals are counted once and decremented while trimming, with an
end index instead of reslicing, so a candidate ending in a long run of
brackets stays linear like the regex it replaces. 200,000 trailing `)`
takes 0.011s.

## Testing

Added assertions to `test_beta_agent_exposes_task_helper_methods`, next
to the existing `_extract_start_url` cases, covering both directions:
the bracket the URL opened is kept, the one the prose opened is not.
They fail on `main` and pass here.

Full `tests/ci`, before and after, on the same machine:

```
clean tree:  2 failed, 1094 passed, 34 skipped
this branch: 2 failed, 1095 passed, 34 skipped
```

The two failures are pre-existing and unrelated, both in
`test_beta_agent.py`
(`test_beta_agent_constructor_type_hints_match_browser_use_core_params`
and `test_beta_agent_initializes_tools_and_action_models`, `Tools`
class-identity assertions). They fail identically on a clean tree. I
also diffed the skipped-test lists between the two runs and they are
identical, so nothing changed state.

```
uv run ruff check browser_use/utils.py tests/ci/test_beta_agent.py   ->  All checks passed!
uv run ruff format --check ...                                      ->  2 files already formatted
uv run pyright browser_use/utils.py                                 ->  0 errors, 0 warnings, 0 informations
```

No new warnings.
2026-08-28 17:19:10 -07:00
Saurav Panda 4df55bb2bc Merge branch 'main' into fix_url_trailing_bracket_truncation 2026-08-28 17:16:41 -07:00
Saurav Panda 7cdc4dcd5d Upgrade datamodel-code-generator to 0.75.1 (#5588)
Bumps `datamodel-code-generator` from 0.53.0 to 0.75.1 in the `eval`
extra dependencies.

This is a routine dependency update to pull in bug fixes, performance
improvements, and new features from the datamodel-code-generator
project. The eval extra is used for evaluation and code generation
tasks.

No source code changes required—this is a straightforward version bump
of a transitive dependency.

https://claude.ai/code/session_013ZqGkMkydPR5r4zPpEAgKk

<!-- This is an auto-generated description by cubic. -->
---
## Summary by cubic
Bumps `datamodel-code-generator` in the `eval` extra from 0.53.0 to
0.75.1 to clear ten CVEs the old version was vulnerable to. No source
code changes required.

**Context**
- The widest affected advisory is CVE-2026-55415 (<= 0.63.0), so any
release above 0.63.0 clears all ten.
- Nothing in the repo imports the package or calls its CLI, but CI
installs it via `uv sync --dev --all-extras`.
- Verified the full dependency graph (399 packages) still resolves and
0.75.1 generates models correctly.
- The update stays compatible with the project's `requires-python
>=3.10` and `pydantic <3,>=2` pins.

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

<a
href="https://cubic.dev/pr/browser-use/browser-use/pull/5588?utm_source=github"
target="_blank" rel="noopener noreferrer"
data-no-image-dialog="true"><picture><source
media="(prefers-color-scheme: dark)"
srcset="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"><source
media="(prefers-color-scheme: light)"
srcset="https://www.cubic.dev/buttons/review-in-cubic-light.svg"><img
alt="Review in cubic"
src="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"></picture></a>

<!-- End of auto-generated description by cubic. -->
2026-08-28 15:53:41 -07:00
Saurav Panda fee260adf2 Merge branch 'main' into claude/datamodel-code-generator-cves-x37u9r 2026-08-28 15:51:12 -07:00
Magnus Müller f6c66917ab docs(cloud): replace retired V1 API examples with V4 (#5578)
## Why

Every checked-in raw Cloud example targets retired `/api/v1` routes that
now return 404. The folder also shows the old bearer header and legacy
request fields.

## What

- replace the five broken V1 samples with one minimal V4 create → status
→ result flow
- use the current `X-Browser-Use-API-Key` header and terminal run
statuses
- load `.env` as the setup guide promises
- link optional fields to the live V4 OpenAPI spec instead of
duplicating claims that can drift

## Verification

- `uv run ruff check examples/cloud/01_basic_task.py`
- `uv run ruff format --check examples/cloud/01_basic_task.py`
- `uv run python -m py_compile examples/cloud/01_basic_task.py`
- mocked create → running → completed → summary contract test
- `uv run pre-commit run --files examples/cloud/README.md
examples/cloud/env.example examples/cloud/01_basic_task.py`
- live route probe: the three documented V1 routes return 404;
`/api/v4/runs` returns the expected missing-API-key 401 without
credentials

<!-- This is an auto-generated description by cubic. -->
---
## Summary by cubic
Replaces the retired V1 Cloud API examples with a single V4 flow so the
checked-in samples stop hitting endpoints that return 404.

- Drops the fast-mode, structured output, proxy, and search API examples
in favor of one create → status → result flow.
- Switches to the `X-Browser-Use-API-Key` header and terminal run
statuses.
- Cancels a run that exceeds the configurable wait limit and rejects
non-positive or non-finite `BROWSER_USE_RUN_TIMEOUT` values.
- Loads `.env` via `dotenv` as the README setup promises.
- Points optional fields to the live V4 OpenAPI spec instead of
repeating them in the README.

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

<a
href="https://cubic.dev/pr/browser-use/browser-use/pull/5578?utm_source=github"
target="_blank" rel="noopener noreferrer"
data-no-image-dialog="true"><picture><source
media="(prefers-color-scheme: dark)"
srcset="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"><source
media="(prefers-color-scheme: light)"
srcset="https://www.cubic.dev/buttons/review-in-cubic-light.svg"><img
alt="Review in cubic"
src="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"></picture></a>

<!-- End of auto-generated description by cubic. -->
2026-08-28 13:38:32 -07:00
MagMueller 1359fb22cb docs(cloud): validate example timeout setting 2026-08-28 13:35:17 -07:00
MagMueller 2391a244b3 docs(cloud): cancel runs after example timeout 2026-08-28 13:35:17 -07:00
MagMueller 80802eefb9 docs(cloud): replace retired v1 API examples with v4 2026-08-28 13:35:17 -07:00
Magnus Müller 33f22b8b4f Fix WebSocket drops during reconnect window (#5373)
## Summary

- Record WebSocket message-handler drops that occur while an automatic
reconnect is in progress.
- Schedule another automatic reconnect after the in-flight attempt
finishes.
- Clear pending reconnect state during session reset.
- Add a focused regression test.

Fixes #5366

## Tests

- `uv run pre-commit run --all-files --show-diff-on-failure`
- `uv run pyright`
- `uv run pytest -vxs tests/ci/test_browser_session.py`
- `uv run pytest -vxs tests/ci` — 483 passed, 28 skipped before an
unrelated existing failure in
`tests/ci/test_beta_agent.py::test_beta_agent_constructor_type_hints_match_browser_use_core_params`.

<!-- This is an auto-generated description by cubic. -->
---
## Summary by cubic
Fixes WebSocket drops that happen during an in-flight reconnect by
recording them and automatically retrying after the attempt finishes.
Improves session stability and clears pending reconnect state on reset.
Fixes #5366.

- **Bug Fixes**
- Record WS drops during reconnect via `_reconnect_pending`, then
auto-schedule a follow-up reconnect once the attempt ends.
  - Clear `_reconnect_pending` on session reset and wake any waiters.
- Add a focused regression test that verifies a follow-up reconnect is
scheduled after a drop during reconnect.

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

<a
href="https://cubic.dev/pr/browser-use/browser-use/pull/5373?utm_source=github"
target="_blank" rel="noopener noreferrer"
data-no-image-dialog="true"><picture><source
media="(prefers-color-scheme: dark)"
srcset="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"><source
media="(prefers-color-scheme: light)"
srcset="https://www.cubic.dev/buttons/review-in-cubic-light.svg"><img
alt="Review in cubic"
src="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"></picture></a>

<!-- End of auto-generated description by cubic. -->
2026-08-28 13:29:03 -07:00
Magnus Müller 281cbc8c74 Merge branch 'main' into fix/issue-5366 2026-08-28 13:26:58 -07:00
Saurav Panda fce843f406 Merge remote-tracking branch 'origin/main' into claude/datamodel-code-generator-cves-x37u9r 2026-08-28 19:59:33 +00:00
Saurav Panda c1c1830a69 fix(registry): replace sensitive placeholders inside tuple params (#5570)
### Summary

- add tuple traversal to `Registry._replace_sensitive_data`
- preserve tuple containers while replacing nested sensitive-data
placeholders
- add regression coverage for tuple and nested tuple action params

### Tests

```powershell
.venv\Scripts\python.exe -m pytest tests\ci\security\test_sensitive_data.py::test_replace_sensitive_data_inside_tuple tests\ci\security\test_sensitive_data.py::test_replace_sensitive_data_inside_nested_tuple -q
.venv\Scripts\python.exe -m pytest tests\ci\security\test_sensitive_data.py -q
.venv\Scripts\python.exe -m ruff check browser_use\tools\registry\service.py tests\ci\security\test_sensitive_data.py
git diff --check

<!-- This is an auto-generated description by cubic. -->
---
## Summary by cubic
Fixes `Registry._replace_sensitive_data` so sensitive-data placeholders inside tuple action params are replaced instead of left as-is, while preserving tuple types.

**Bug Fixes**
- Adds tuple traversal to the recursive secret replacement, keeping tuple containers intact for top-level and nested tuples.
- Adds regression tests covering tuple and nested tuple action params.

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

<a href="https://cubic.dev/pr/browser-use/browser-use/pull/5570?utm_source=github" target="_blank" rel="noopener noreferrer" data-no-image-dialog="true"><picture><source media="(prefers-color-scheme: dark)" srcset="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"><source media="(prefers-color-scheme: light)" srcset="https://www.cubic.dev/buttons/review-in-cubic-light.svg"><img alt="Review in cubic" src="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"></picture></a>

<!-- End of auto-generated description by cubic. -->
2026-08-28 12:24:18 -07:00
Saurav Panda 8a5a3000e0 Merge branch 'main' into fix/5568-tuple-sensitive-data 2026-08-28 12:22:28 -07:00
MagMueller 6de522cb9a docs: sync generated Browser Harness skill 2026-08-28 12:22:03 -07:00
MagMueller 38fa689a10 build: require Browser Harness 0.1.10 2026-08-28 12:22:03 -07:00
Saurav Panda ab7fd48f63 Merge branch 'main' into fix/5568-tuple-sensitive-data 2026-08-28 12:20:13 -07:00
Saurav Panda 58d88ae309 Bump datamodel-code-generator to 0.75.1 to clear 10 CVEs
The eval extra pinned datamodel-code-generator==0.53.0, which falls inside
the affected range of ten advisories (CVE-2026-54621, -54653, -54654,
-54655, -54656, -54690, -54691, -55389, -55391, -55415). The widest range
is CVE-2026-55415 (<= 0.63.0), so any release above 0.63.0 clears all ten;
0.75.1 is the current latest.

CI installs this via `uv sync --dev --all-extras`, so the vulnerable
package was landing in CI environments even though nothing in the repo
imports it or invokes the datamodel-codegen CLI.

Verified the full graph (399 packages, all extras + dev) still resolves,
and that 0.75.1 installs and generates models correctly. Requires-python
>=3.10 and pydantic <3,>=2 both stay compatible with the project's pins.
2026-08-28 18:11:15 +00:00
Magnus Müller 30b5aca5b0 Merge branch 'main' into fix/issue-5366 2026-08-28 02:25:57 -07:00
Aniket Wagh 3c565af3e0 perf: keep bracket trimming linear in sanitize_url_candidate
The trimming loop counted brackets across the whole candidate on every
iteration, so a candidate ending in many unmatched brackets rescanned it
once per bracket. 50,000 trailing ')' took 0.9s, where the regex this
replaced was linear.

Count the four bracket characters once and decrement as characters are
trimmed, tracking the end index instead of reslicing. Same results, and
200,000 trailing ')' now takes 0.011s.
2026-08-28 09:50:05 +05:30
Aniket Wagh d33cc68f06 fix: keep balanced trailing brackets in URLs extracted from task text
sanitize_url_candidate() strips trailing prose punctuation so that
"Go to https://example.com/docs." does not navigate with the sentence's
period attached. It also stripped every trailing ) and ], including the
ones the URL opened itself, so a task like

    Summarize https://en.wikipedia.org/wiki/Python_(programming_language)

auto-navigated to .../Python_(programming_language and landed on the wrong
page. Wikipedia disambiguation links are the common case.

Whether the bracket belongs to the URL is decided by balance: a closing
bracket with a matching opener inside the candidate is part of the path,
while one the prose opened, as in "(see https://example.com/guide)", is not.
Strip trailing punctuation as before, and only drop a closing bracket when
the candidate has more of them than openers.

Fixes #5575
2026-08-28 09:50:05 +05:30
Magnus Müller 67e7194c06 fix(dom): expose image context for clickable elements (#5541)
Fixes #4312

Image-only clickable elements can be indistinguishable in the serialized
DOM when they have no text or accessible label. Include bounded
descendant image context on the interactive parent, using
alt/title/aria-label and a query-stripped image filename while ignoring
data URLs.

Validation:
- uv run pytest -q tests/ci/test_image_only_dom_representation.py
tests/ci/test_dom_paint_order_serialization.py
- uv run ruff check browser_use/dom/serializer/serializer.py
tests/ci/test_image_only_dom_representation.py
- uv run ruff format --check browser_use/dom/serializer/serializer.py
tests/ci/test_image_only_dom_representation.py
- uv run pre-commit run --files browser_use/dom/serializer/serializer.py
tests/ci/test_image_only_dom_representation.py

<!-- This is an auto-generated description by cubic. -->
---
## Summary by cubic
Fixes #4312 by exposing bounded descendant image context in the
serialized DOM for image-only interactive elements. Previously,
interactive parents without text or labels serialized without context;
now they carry image alt/title/aria-label and a query/fragment-stripped
filename, with traversal and allocation bounds.

- Add `image_alt`, `image_title`, `image_label`, and `image_src`
(query/fragment-stripped filename) to interactive parents; skip `data:`
and query-only sources; cap each value to 100 chars.
- Limit to three descendant images and at most 100 descendants; traverse
lazily without copying child lists to bound allocations.
- Keep paint-order serialization unchanged; add tests for filename
propagation, query/fragment stripping, data URL filtering, traversal
limits, and non-eager traversal.

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

<a
href="https://cubic.dev/pr/browser-use/browser-use/pull/5541?utm_source=github"
target="_blank" rel="noopener noreferrer"
data-no-image-dialog="true"><picture><source
media="(prefers-color-scheme: dark)"
srcset="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"><source
media="(prefers-color-scheme: light)"
srcset="https://www.cubic.dev/buttons/review-in-cubic-light.svg"><img
alt="Review in cubic"
src="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"></picture></a>

<!-- End of auto-generated description by cubic. -->
2026-08-27 20:42:28 -07:00
Magnus Müller fa29b0e05d Merge branch 'main' into fix/image-only-clickable-context 2026-08-27 20:37:34 -07:00
郑耀翔 9bfb1d3258 fix(registry): replace sensitive placeholders in tuples 2026-08-28 09:30:24 +08:00
Magnus Müller 35fccbb418 fix(llm): ignore empty reasoning model patterns (#5545)
## Summary

- centralize reasoning-model pattern matching for the LLM adapters
- ignore empty or whitespace-only patterns instead of treating every
model as a reasoning model
- preserve the existing matching behavior for non-empty patterns across
OpenAI, Azure, and Vercel

This prevents an empty `reasoning_models` entry from silently dropping
sampling parameters such as `temperature` and `frequency_penalty`.

## Testing

- `py -m uv run pytest -q tests/ci/models/test_llm_openai.py` (7 passed,
1 skipped)
- `py -m uv run pytest -q tests/ci/models/test_azure_responses_api.py -k
ShouldUseResponsesAPI` (6 passed)
- `py -m uv run pyright browser_use/llm/base.py
browser_use/llm/openai/chat.py browser_use/llm/azure/chat.py
browser_use/llm/vercel/chat.py tests/ci/models/test_llm_openai.py`
- `py -m uv run ruff check browser_use/llm/base.py
browser_use/llm/openai/chat.py browser_use/llm/azure/chat.py
browser_use/llm/vercel/chat.py tests/ci/models/test_llm_openai.py`

Fixes #5543

<!-- This is an auto-generated description by cubic. -->
---
## Summary by cubic
Ignore empty and whitespace-only reasoning-model patterns so regular
models are no longer treated as reasoning models, which previously
stripped sampling params like `temperature` and `frequency_penalty`.
Matching is centralized in `is_reasoning_model`, and the `openai`,
`azure`, and `vercel` adapters all use it so only real patterns apply.

**Bug Fixes**
- Tests cover empty-pattern cases and verify reasoning params are only
set on true matches.

Fixes #5543.

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

<a
href="https://cubic.dev/pr/browser-use/browser-use/pull/5545?utm_source=github"
target="_blank" rel="noopener noreferrer"
data-no-image-dialog="true"><picture><source
media="(prefers-color-scheme: dark)"
srcset="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"><source
media="(prefers-color-scheme: light)"
srcset="https://www.cubic.dev/buttons/review-in-cubic-light.svg"><img
alt="Review in cubic"
src="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"></picture></a>

<!-- End of auto-generated description by cubic. -->
2026-08-27 17:40:39 -07:00