Commit Graph

9859 Commits

Author SHA1 Message Date
laithrw 702b7352c3 Fix: Catch TypeError during lmnr import to prevent CLI startup crash (#4046) (#4104)
## Summary

Fixes #4046

The skill CLI crashes on startup when `lmnr` is installed but internally
broken (e.g., Python 3.13 with certain package states). The import
raises `TypeError` instead of `ImportError`, which escapes the existing
handler and kills the entire application.

## Root Cause

`browser_use/observability.py` line 52 only catches `ImportError`, but a
broken `lmnr` installation can raise `TypeError` during its internal
initialization.

## Fix

Broadened `except ImportError` to `except (ImportError, TypeError)` so
the no-op fallback decorator is used in both failure modes. Chose
specific exceptions over `except Exception` to avoid masking unrelated
errors.

## Tests Added

New file: `tests/ci/test_observability.py` with 4 tests:
- `test_fallback_when_lmnr_not_installed`  ImportError fallback
- `test_fallback_when_lmnr_raises_type_error` TypeError fallback
(regression for #4046)
- `test_observe_noop_decorator_works_on_sync_function` sync decorator
verification
- `test_observe_noop_decorator_works_on_async_function` async decorator
verification

All pass. Happy to adjust based on feedback!

<!-- This is an auto-generated description by cubic. -->
---
## Summary by cubic
Fixes a startup crash in the skill CLI when `lmnr` is installed but
broken by catching `TypeError` during import and falling back to the
no-op observe decorator. Keeps the CLI running even if observability is
unavailable.

- **Bug Fixes**
- Catch `(ImportError, TypeError)` in `browser_use/observability.py` and
disable observability when `lmnr` fails to import.

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

<!-- End of auto-generated description by cubic. -->
2026-04-15 18:38:48 -04:00
Laith Weinberger 80f798bc17 drop test 2026-04-15 18:34:03 -04:00
Laith Weinberger a336bd8a50 Merge remote-tracking branch 'origin/main' into fix/handle-lmnr-type-error-on-import-4046 2026-04-15 18:33:31 -04:00
laithrw d49d3bd1ef fix input clear fallbacks and clarify clear-then-type behavior (#4692)
Resolves #4683

<!-- This is an auto-generated description by cubic. -->
---
## Summary by cubic
Fixes input clearing so we don’t stop on JS clear failures, and
clarifies “clear-then-type” as the default. Adds a clear-only option via
text="" and a way to append via clear=False. Resolves #4683.

- **Bug Fixes**
  - Removed premature returns in JS clear to enable fallback strategies.
- Aligned docs and help to the default behavior: clear-then-type;
`text=""` clears only; `clear=False` appends (`browser_type` tool,
`InputTextAction` schema, CLI `input`, SKILL.md).

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

<!-- End of auto-generated description by cubic. -->
2026-04-15 17:35:56 -04:00
Laith Weinberger 4476f6e16e fix input clear fallbacks and clarify clear-then-type behavior 2026-04-15 17:31:04 -04:00
laithrw 91d2eff4ac fix: add utf-8 encoding to Local State file read in list_chrome_profiles (#4690)
## Problem

`list_chrome_profiles()` in `browser_use/skill_cli/utils.py` opens
Chrome's `Local State` JSON file without specifying an encoding:

```python
with open(local_state_path) as f:
```

On Windows with a non-UTF-8 default locale (e.g. Chinese GBK/CP936),
Python's `open()` uses the system code page. Chrome's `Local State` is
always UTF-8, so profile names containing non-ASCII characters (e.g.
Chinese `用户1`) are decoded as mojibake (`鐢ㄦ埛1`).

## Fix

Add `encoding='utf-8'` to the `open()` call, consistent with how
`browser_use/browser/profile.py` already handles file reads (e.g. lines
949, 1062, 1108).

## Reproduction

On a Windows machine with Chinese system locale:
```python
profiles = Browser.list_chrome_profiles()
for p in profiles:
    print(p["name"])  # Before fix: 鐢ㄦ埛1 (mojibake)
                       # After fix:  用户1 (correct)
```

Fixes #4673

<!-- This is an auto-generated description by cubic. -->
---
## Summary by cubic
Read Chrome’s `Local State` in `list_chrome_profiles()` using UTF-8 to
prevent garbled profile names on Windows with non-UTF-8 locales.
Non-ASCII names (e.g., Chinese) now display correctly.

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

<!-- End of auto-generated description by cubic. -->
2026-04-15 16:09:37 -04:00
laithrw 9c314e626e Merge branch 'main' into fix/local-state-utf8-encoding 2026-04-15 16:06:56 -04:00
voidborne-d 4c2d136de9 fix: add utf-8 encoding to Local State file read in list_chrome_profiles
On Windows with a non-UTF-8 default locale (e.g. Chinese GBK/CP936),
open() without an explicit encoding uses the system code page. Chrome's
Local State file is always UTF-8, so profile names containing non-ASCII
characters (e.g. Chinese '用户1') are decoded as mojibake.

Fixes #4673
2026-04-15 17:07:51 +00:00
shawn pana 15373241cd improve connect failure UX: fix chrome://inspect link and add fallbac… (#4678)
…k guidance

When `browser-use connect` fails to discover a running Chrome, the error
now points to the correct `chrome://inspect/#remote-debugging` URL. The
SKILL.md also guides agents to prompt users with two options: enable
remote debugging or use managed Chromium with a Chrome profile.

<!-- This is an auto-generated description by cubic. -->
---
## Summary by cubic
Fixes the connect failure UX by pointing to the correct Chrome remote
debugging page and adding clear fallback steps. The error now links to
`chrome://inspect/#remote-debugging`, and SKILL.md guides users to
either enable remote debugging or use managed Chromium with their Chrome
profile.

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

<!-- End of auto-generated description by cubic. -->
2026-04-14 15:01:37 -07:00
Alisha Ukani 628d8f44a7 Search for playwright-installed Chromium in chrome-mac or chrome-mac-arm64 folders 2026-04-14 13:10:31 -07:00
Shawn Pana d0fbf4c580 improve connect failure UX: fix chrome://inspect link and add fallback guidance
When `browser-use connect` fails to discover a running Chrome, the error
now points to the correct `chrome://inspect/#remote-debugging` URL. The
SKILL.md also guides agents to prompt users with two options: enable
remote debugging or use managed Chromium with a Chrome profile.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-14 11:23:50 -07:00
Saurav Panda ef32ed708a ci: pin stale workflow action (#4656)
## Summary
- pin the privileged stale workflow action to the immutable commit
behind `actions/stale@v9`
- preserve current behavior by keeping the same major tag target and
only removing tag-retarget drift
- leave existing workflow permissions and stale policy settings
unchanged

## Why
This scheduled workflow runs with `issues: write` and `pull-requests:
write`, so pinning the marketplace action to a commit reduces
supply-chain drift without changing workflow behavior.

## Validation
- `git diff --check`
- `python -c "from pathlib import Path; import yaml;
yaml.safe_load(Path('.github/workflows/stale-bot.yml').read_text(encoding='utf-8'));
print('yaml-parse-ok')"`
- local PC Control review-coder queued against the staged diff; it
remained running during push, so I treated it as degraded evidence and
completed a bounded manual preflight on the one-line workflow change

## Notes
- This intentionally stays scoped to one workflow line.
- I did not change permissions, timing, or stale policy behavior.
- `uv` / `pre-commit` and `actionlint` were not available on this
Windows shell, so I did not claim those checks ran locally.

<!-- This is an auto-generated description by cubic. -->
---
## Summary by cubic
Pin `actions/stale` in the scheduled workflow to the immutable v9 commit
to eliminate tag drift and reduce supply-chain risk. Behavior,
permissions, schedule, and stale policy remain unchanged.

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

<!-- End of auto-generated description by cubic. -->
2026-04-13 17:34:47 -07:00
grtninja b1f755d509 Merge branch 'main' into codex/ci-pin-stale-bot-sha 2026-04-12 19:18:48 -04:00
laithrw 5970007d86 close alias for BrowserSession stop (#4665)
thousands of users have attempted to use close, so why not add it

<!-- This is an auto-generated description by cubic. -->
---
## Summary by cubic
Adds `close()` to `BrowserSession` as an alias for `stop()`, so
`session.close()` cleanly stops the session and matches common APIs.

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

<!-- End of auto-generated description by cubic. -->
2026-04-12 17:51:28 -04:00
laithrw 76604913ad Merge branch 'main' into fix/browser-session-close 2026-04-12 17:45:44 -04:00
Laith Weinberger c1eb87a35f close alias for BrowserSession stop
thousands of users have attempted to use close, so why not add it
2026-04-12 17:43:04 -04:00
laithrw 36438e409e prefer Playwright chromium over sys Chrome by default (#4664)
Resolves #4610

<!-- This is an auto-generated description by cubic. -->
## Summary by cubic
Prefer the `playwright`-bundled Chromium over system Chrome by default
to make local launches consistent across machines and CI. Also switches
installation to `uvx playwright install chromium`.

- **Refactors**
- Reordered search priority: channel-specific (non-default) ->
Playwright Chromium -> system Chrome -> other native browsers ->
Playwright headless-shell.
- Unified pattern ordering to always prioritize the target browser
group, then fall back to others.
- Switched install command and error messages from `chrome` to
`chromium`.

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

<!-- End of auto-generated description by cubic. -->
2026-04-12 11:47:27 -04:00
Laith Weinberger 03e2bc4da8 prefer Playwright chromium over sys Chrome by default 2026-04-12 11:41:50 -04:00
laithrw 700833d2c0 fix: handle BrokenPipeError gracefully when MCP client disconnects (#4663)
<!-- This is an auto-generated description by cubic. -->
## Summary by cubic
Gracefully handle MCP stdio disconnections by catching BrokenPipeError,
preventing crashes and shutting down the server cleanly.

- **Bug Fixes**
  - Wrap `server.run` in a `try/except BrokenPipeError`.
  - Log a warning and exit cleanly when the MCP client disconnects.

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

<!-- End of auto-generated description by cubic. -->
2026-04-12 11:37:56 -04:00
Laith Weinberger df4e2f9f15 fix: handle BrokenPipeError gracefully when MCP client disconnects 2026-04-12 11:34:39 -04:00
grtninja 7775265340 Merge branch 'main' into codex/ci-pin-stale-bot-sha 2026-04-11 22:15:59 -04:00
laithrw 1324a88445 fix pagination classifier to prioritize semantic labels over glyph syms (#4661)
Resolves #4620

<!-- This is an auto-generated description by cubic. -->
---
## Summary by cubic
Fix pagination button detection to prefer semantic labels ("first",
"last") over shared glyphs ("«", "»") across sites. Removed those glyphs
from first/last patterns and reordered checks so first/last win before
next/prev, treating "«" and "»" only as prev/next fallbacks.

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

<!-- End of auto-generated description by cubic. -->
2026-04-11 18:39:05 -04:00
Laith Weinberger 9ad4c63cdb fix pagination classifier to prioritize semantic labels over shared glyph symbols 2026-04-11 18:30:46 -04:00
laithrw 24be2f0488 fix sensitive_data redaction order to prevent substring leaks (#4660)
Resolves #4609

<!-- This is an auto-generated description by cubic. -->
---
## Summary by cubic
Fixes #4609 by preventing substring leaks during sensitive data
redaction. Redaction now replaces longer secrets first and uses shared
utils for consistent behavior.

- **Bug Fixes**
  - Redact longest matches first to avoid partial/substring leaks.
  - Support both legacy flat and domain-scoped `sensitive_data` formats.
  - Apply consistent redaction across message manager and views.

- **Refactors**
- Added `collect_sensitive_data_values` and `redact_sensitive_string` in
`browser_use/utils.py`.
- Replaced inline redaction logic in
`browser_use/agent/message_manager/service.py` and
`browser_use/agent/views.py`.

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

<!-- End of auto-generated description by cubic. -->
2026-04-11 18:21:03 -04:00
Laith Weinberger 65f87b7fca fix sensitive_data redaction order to prevent substring leaks 2026-04-11 18:16:24 -04:00
laithrw 67c2eddf85 fix asyncio.get_event_loop for python 3.14 compat (#4659)
Fixes #4626

<!-- This is an auto-generated description by cubic. -->
---
## Summary by cubic
Replace deprecated asyncio.get_event_loop/run_until_complete with
asyncio.run() in the CLI to restore Python 3.14 compatibility. Fixes
#4626 and prevents runtime errors in the `doctor` and `tunnel` commands.

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

<!-- End of auto-generated description by cubic. -->
2026-04-11 18:13:27 -04:00
Laith Weinberger 99a8674214 fix asyncio.get_event_loop for python 3.14 cli compatibilit 2026-04-11 18:10:12 -04:00
laithrw 184c49713e fix(#4631): clear dom cache after scroll to prevent stale extract data (#4658)
Resolves #4631

<!-- This is an auto-generated description by cubic. -->
---
## Summary by cubic
Clears the DOM watchdog cache after scrolls to prevent stale extraction
data and ensure DOM reads reflect the current page state. Addresses
#4631 where post-scroll data could be outdated.

- **Bug Fixes**
- Clear `_dom_watchdog` cache after both element-target and CDP gesture
scrolls.
- Wait ~200ms before clearing after element-target scroll so the DOM can
settle.

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

<!-- End of auto-generated description by cubic. -->
2026-04-11 18:09:26 -04:00
laithrw 60e7767228 Merge branch 'main' into issue-4631-review 2026-04-11 18:07:12 -04:00
Laith Weinberger 534eaafe7a clear dom cache after scroll to prevent stale extract data 2026-04-11 18:03:06 -04:00
grtninja 81089417fa ci: pin stale workflow action 2026-04-11 03:13:48 -04:00
Alexander Yue cd60e6bdd5 Add per-link utm_medium slugs to README cloud links (#4653)
## Summary
- Differentiates the 8 cloud-bound README links by changing
`utm_medium=readme` to `utm_medium=readme-{slug}` (e.g.
`readme-badge-cloud`, `readme-skip-setup`, `readme-faq-captcha`)
- Enables per-placement attribution in PostHog without adding extra UTM
fields
- `utm_source=github` is unchanged so existing filters still work

## Slugs

| Link | `utm_medium` |
|---|---|
| Download stats badge | `readme-badge-downloads` |
| Cloud badge (nav) | `readme-badge-cloud` |
| "Skip the setup" CTA | `readme-skip-setup` |
| Quickstart API key | `readme-quickstart-api-key` |
| Cloud docs | `readme-cloud-docs` |
| Fully-Hosted Cloud Agent | `readme-hosted-agent` |
| CAPTCHA FAQ | `readme-faq-captcha` |
| Production FAQ | `readme-faq-production` |
2026-04-10 15:53:11 -07:00
Alezander9 889ccb81bb Add per-link utm_medium slugs to README cloud links for placement attribution 2026-04-10 15:48:51 -07:00
Alexander Yue eeb767ef18 Improve OSS-to-cloud conversion: UTM tracking, better error messages, and cloud nudges (#4646)
## Summary

- Add UTM tracking params to all cloud-bound links across README, CLI,
and error messages — enables measuring which OSS surfaces drive cloud
sign-ups
- Rewrite README "Open Source vs Cloud" section: position cloud browsers
as the recommended pairing for OSS users, remove separate "Use Both"
section
- Rewrite error messages for `use_cloud=True` and `ChatBrowserUse()` to
clearly state what is wrong and what to do next (not vague
"authentication failed" messages)
- Add missing URLs to dead-end errors: invalid API key now links to key
page, insufficient credits now links to billing page
- Add cloud browser nudge on captcha detection (`logger.warning`)
- Add cloud browser nudge on local browser launch failure (Chromium not
installed, etc.)
- Fix pre-existing pyright error with `readline.add_history` on Windows

## Changes by file

**README.md** — UTM params on 8 cloud links, "Use Both" section folded
into "Use Open Source" with cloud browsers as recommended pairing

**browser_use/agent/service.py** — Captcha nudges rewritten as
`logger.warning` with cloud URL + UTM

**browser_use/browser/cloud/cloud.py** — Error messages rewritten:
"BROWSER_USE_API_KEY is not set" / "is invalid" + UTM on URLs

**browser_use/browser/session.py** — Auth error re-raise simplified (no
rewrap), new nudge on local browser launch failure

**browser_use/llm/browser_use/chat.py** — Error messages rewritten,
added URL to 401 (invalid key) and billing URL to 402 (insufficient
credits)

**browser_use/cli.py** — UTM params added to all cloud URLs, fix
`readline.add_history` pyright error on Windows by using `getattr` at
import time

**browser_use/init_cmd.py** — UTM param added to API key URL

**browser_use/skill_cli/commands/cloud.py** — UTM param added to API key
URL

## UTM scheme

| utm_source | utm_medium | Where |
|---|---|---|
| `github` | `readme` | README links |
| `oss` | `cli` | CLI init/TUI messages |
| `oss` | `use_cloud` | `Browser(use_cloud=True)` errors |
| `oss` | `chat_browser_use` | `ChatBrowserUse()` errors |
| `oss` | `captcha_nudge` | Runtime captcha detection |
| `oss` | `browser_launch_failure` | Local browser launch failure |
2026-04-08 22:19:38 -07:00
Alezander9 f8f7be2e90 Fix test assertions to match updated error messages 2026-04-08 22:12:16 -07:00
Alezander9 76569995fd Improve OSS-to-cloud conversion: UTM tracking, better error messages, and cloud nudges
- Add UTM params to all cloud-bound links across README, CLI, and error messages
- Rewrite README Open Source vs Cloud section: position cloud browsers as
  recommended pairing for OSS users, remove separate Use Both section
- Rewrite error messages for use_cloud=True and ChatBrowserUse() to clearly
  state what is wrong and what to do next
- Add missing URLs: invalid API key now links to key page, insufficient
  credits now links to billing page
- Add cloud browser nudge on captcha detection (logger.warning)
- Add cloud browser nudge on local browser launch failure
2026-04-08 22:05:50 -07:00
Saurav Panda fa17b89846 chore: update browser-use-sdk from 2.0.15 to 3.4.2 (#4644)
## Summary
- Updates `browser-use-sdk` dependency from `2.0.15` to `3.4.2`
- All existing imports verified working with the new version

## Test plan
- [x] `uv sync` succeeds
- [x] All SDK imports (`AsyncBrowserUse`, type imports) verified working
- [ ] CI tests pass

🤖 Generated with [Claude Code](https://claude.com/claude-code)

<!-- This is an auto-generated description by cubic. -->
---
## Summary by cubic
Upgrade `browser-use-sdk` from 2.0.15 to 3.4.2 and align our code with
v3 API changes. No behavior changes.

- **Dependencies**
  - Updated `browser-use-sdk` to `3.4.2` in `pyproject.toml`.

- **Refactors**
- Moved to new top‑level SDK imports (`AsyncBrowserUse`,
`ExecuteSkillResponse`, `SkillListResponse`, `ParameterSchema`,
`SkillResponse`).
- Handle UUID skill IDs from the SDK by casting to and comparing as
`str`.
- On error, return `ExecuteSkillResponse` with `result=None`,
`stderr=None`, and `latencyMs=None` for schema compatibility.

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

<!-- End of auto-generated description by cubic. -->
2026-04-08 18:28:17 -07:00
Saurav Panda 1a94f96ce9 fix: update imports for browser-use-sdk 3.4.2 and handle UUID id fields 2026-04-08 17:51:22 -07:00
Saurav Panda c690af2051 chore: update browser-use-sdk from 2.0.15 to 3.4.2 2026-04-08 17:41:57 -07:00
laithrw 92d3d152a2 fix: guard against missing stdin in MCP stdio server startup (#4642)
<!-- This is an auto-generated description by cubic. -->
## Summary by cubic
Guard `mcp.server.stdio` startup against missing stdin. When stdin is
absent, raise a clear RuntimeError so the process fails fast instead of
producing ambiguous startup errors.

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

<!-- End of auto-generated description by cubic. -->
2026-04-08 17:29:24 -04:00
laithrw 83317179cb Merge branch 'main' into fix/mcp-stdin-guard 2026-04-08 17:25:16 -04:00
laithrw fa7bae3400 fix: use setattr for LLM ainvoke patching to avoid pydantic crash (#4641)
<!-- This is an auto-generated description by cubic. -->
---
## Summary by cubic
Fixes runtime crashes when patching LLM ainvoke on Pydantic-backed
models by using `object.__setattr__` to assign `tracked_ainvoke`. This
bypasses Pydantic attribute validation and keeps the tracking wrapper
working.

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

<!-- End of auto-generated description by cubic. -->
2026-04-08 17:24:47 -04:00
Laith Weinberger 674547a414 fix: guard against missing stdin in MCP stdio server startup 2026-04-08 17:21:11 -04:00
Laith Weinberger 3242d9dbc2 fix: use object.__setattr__ for LLM ainvoke patching to avoid pydantic crash 2026-04-08 17:20:46 -04:00
laithrw 8de903dfdd fix: prevent KeyError in load_from_dict and IndexError in final_result (#4464)
## Fixes #4463

### Problems

**1. `AgentHistoryList.load_from_dict` — KeyError on missing keys**

The current implementation uses direct dict subscript access that
crashes when loading history saved with an older browser-use version or
when a step entry is missing expected keys:

```python
for h in data['history']:           # KeyError if 'history' key absent
    if h['model_output']:           # KeyError if 'model_output' absent
    if 'interacted_element' not in h['state']:  # KeyError if 'state' absent
```

**2. `AgentHistoryList.final_result()` — IndexError on empty result
list**

```python
if self.history and self.history[-1].result[-1].extracted_content:
#                              ^^^^^^^^^^^^^^^^ IndexError when result == []
```

Every sibling method (`is_done`, `is_successful`, `judgement`,
`is_judged`, `is_validated`) already guards with
`len(self.history[-1].result) > 0`. `final_result` was the only one
missing this check.

### Fix

- **`load_from_dict`**: use `data.get('history', [])` and `h.get(key)`
instead of direct subscript access, matching standard defensive Python
dict usage.
- **`final_result`**: add `len(self.history[-1].result) > 0` guard
before accessing `result[-1]`, consistent with all other methods in the
class.

### Changes

Only `browser_use/agent/views.py` is modified (14 additions, 8
deletions).

<!-- This is an auto-generated description by cubic. -->
---
## Summary by cubic
Prevent crashes when loading agent history with missing fields and when
reading the final result on empty lists. This makes `AgentHistoryList`
safer and backward-compatible with legacy or partial histories.

- **Bug Fixes**
- `load_from_dict`: use `data.get('history', [])` and `h.get()` for safe
access; initialize missing `state` and default
`state.interacted_element` to `None`; validate `model_output` only when
it’s a dict.
- `final_result`: check `len(self.history[-1].result) > 0` before
indexing; return `None` when empty or no extracted content, consistent
with other methods.

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

<!-- End of auto-generated description by cubic. -->
2026-04-07 14:20:28 -04:00
laithrw 6129ceb0b0 Merge branch 'main' into fix/agent-history-safe-access 2026-04-07 14:18:38 -04:00
laithrw 55ca9cb27d improve model docs (#4616)
In response to #4214

<!-- This is an auto-generated description by cubic. -->
## Summary by cubic
Revamped the LLM model docs with a quick-reference table, use‑case
recommendations, and clearer provider setup. Adds native coverage for
more providers, updates examples, and improves env/installation
guidance.

- **Refactors**
- Added Quick Reference (provider → class → env) and use‑case picks
based on benchmarks.
- Renamed to “Browser Use Cloud,” updated pricing/models, and listed
`browser-use/bu-30b-a3b-preview`.
- Expanded provider docs: DeepSeek, Mistral, Cerebras, OpenRouter,
LiteLLM; improved OpenAI/Anthropic/Gemini/Azure/Bedrock/Vercel/OCI
guidance with links.
- Standardized examples to `Agent` + `Chat*` classes and noted key env
vars.
- Moved OpenRouter out of OpenAI-compatible section; trimmed/reorganized
OpenAI-compatible examples.
- Minor fixes: `GOOGLE_API_KEY` deprecation note, Anthropic coordinate
clicking note, “LangChain” capitalization.

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

<!-- End of auto-generated description by cubic. -->
2026-04-05 22:01:37 -04:00
Laith Weinberger c1151715d3 improve model docs 2026-04-05 21:59:33 -04:00
Saurav Panda de14b9aa31 fix: add per-session auth token to daemon socket (#4598)
## Summary

- **Root cause**: The daemon accepted any connection on its socket
without authentication. On Windows the port is deterministic
(`adler32(session)`-derived), so any local process could connect and
dispatch the `python` action, executing arbitrary code via
`eval()`/`exec()` as the daemon owner. On Unix the socket may be
world-writable under a permissive umask.
- **Fix**: On `Daemon.run()`, generate a `secrets.token_hex(32)` token,
write it atomically to `~/.browser-use/{session}.token` with `chmod
0o600`. Validate every incoming request with `hmac.compare_digest`
before dispatching. Delete the token file on shutdown.
- **Client**: `send_command()` in `main.py` now reads the token file and
attaches it to every request. Falls back to `''` for old daemons
(no-op).

## Test plan

- [ ] Start daemon, run `browser-use python "1+1"` — should work
normally
- [ ] Send a raw request without token to socket — should get
`{"success": false, "error": "Unauthorized"}`
- [ ] Unauthenticated `shutdown` action should be ignored (daemon stays
up)
- [ ] After daemon stops, `~/.browser-use/default.token` should be
deleted
- [ ] All CI tests pass (`uv run pytest -vxs tests/ci`)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

<!-- This is an auto-generated description by cubic. -->
---
## Summary by cubic
Secure the daemon socket with a per-session auth token to block
unauthorized local connections and arbitrary code execution via the
`python` action. The CLI now reads the token and includes it with each
command.

- **Bug Fixes**
- Generate a session token in `Daemon.run()` (`secrets.token_hex(32)`);
write it atomically to `~/.browser-use/{session}.token` via a `*.tmp`
file created with `0o600`, then replace; raise if write fails; delete on
shutdown.
- Validate every request using `hmac.compare_digest`; unauthorized calls
return `{"success": false, "error": "Unauthorized"}` and `shutdown` is
honored only for authorized, successful requests.
- Client `send_command()` reads the token and sends it as `token`; falls
back to `''` for older daemons.

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

<!-- End of auto-generated description by cubic. -->
2026-04-03 10:54:19 -07:00
sauravpanda ca2185ba61 fix: create token temp file with 0o600 at open() time; raise on failure
- Use os.open() with mode 0o600 instead of write-then-chmod to eliminate
  the permission race window where the temp file is briefly world-readable.
- Raise instead of warn when token file write fails: a daemon that cannot
  persist its auth token is permanently unauthorized for all clients, so
  failing fast is correct (identified by cubic).
2026-04-02 17:58:12 -07:00