Commit Graph

92 Commits

Author SHA1 Message Date
Laith Weinberger
4476f6e16e fix input clear fallbacks and clarify clear-then-type behavior 2026-04-15 17:31:04 -04:00
Laith Weinberger
99a8674214 fix asyncio.get_event_loop for python 3.14 cli compatibilit 2026-04-11 18:10:12 -04:00
sauravpanda
a05a053da6 fix: add per-session auth token to daemon socket to prevent unauthorized code execution
Generate a secrets.token_hex(32) on daemon startup, write it atomically
to ~/.browser-use/{session}.token (chmod 0o600), and validate it on every
incoming request via hmac.compare_digest. The client reads the token file
and includes it in each send_command() call.

This closes the arbitrary-code-execution vector where any local process
could connect to the deterministic Windows TCP port (or a world-readable
Unix socket) and dispatch the 'python' action to run eval()/exec() as the
daemon owner.
2026-04-02 17:41:15 -07:00
ShawnPana
0530545c1a fix: API key single source of truth (config.json only), daemon-safe profile creation
- Remove BROWSER_USE_API_KEY env var as a read source from CLI code; config.json is the only source of truth
- Split _create_cloud_profile into daemon-safe _inner (raises) and CLI wrapper (sys.exit)
- Daemon auto-heal no longer kills process on profile creation API errors
2026-04-02 11:51:38 -07:00
ShawnPana
47ba16b8ab ux: show Connecting.../Closing... status during slow operations 2026-04-02 11:29:03 -07:00
ShawnPana
1deb430f8f perf: skip profile validation HTTP call on cloud connect
_get_or_create_cloud_profile reads config instantly instead of
validating via GET /profiles/{id} on every connect. If the profile
is invalid, _provision_cloud_browser auto-heals by creating a new
one and retrying. Saves ~500ms-1s on every cloud connect.
2026-04-02 11:21:12 -07:00
ShawnPana
63904858f4 fix: CDP URL only in sessions --json, not in table output 2026-04-01 22:40:48 -07:00
ShawnPana
8c6d042a79 fix: truncate CDP URL in sessions table, full URL in --json 2026-04-01 22:39:30 -07:00
ShawnPana
b1522b5e23 fix: sessions shows CDP URL for cloud sessions too
Ping response now returns live CDP URL from the browser session
(not just the constructor arg). Cloud sessions show their
provisioned CDP URL.
2026-04-01 22:37:23 -07:00
ShawnPana
c09ea5a0b2 feat: sessions command shows CDP URL for each session 2026-04-01 22:35:11 -07:00
ShawnPana
0bf1f02d97 fix: CI failures — ruff formatting, type errors, test_setup_command
- Ruff format all skill_cli and test files
- Fix type: get_config_value returns str|int|None, callers cast properly
- Fix type: BrowserWrapper.actions is non-optional (always provided)
- Fix type: config comparison uses 'is' not '=='
- Rewrite test_setup_command for new setup.handle(yes=True) API
- Add None guard in test_cli_lifecycle for state file
2026-04-01 19:58:33 -07:00
ShawnPana
bebb3d1a80 fix: treat empty BROWSER_USE_API_KEY as missing in ensure_daemon
Consistent with the same fix applied to config.py and browser.py.
2026-04-01 19:51:36 -07:00
ShawnPana
1711a8918e fix: sessions won't delete socket of live daemon with stale PID
Check socket_reachable before cleaning up files. A daemon with a
corrupt/stale PID file but a live socket is still running.
2026-04-01 19:31:59 -07:00
ShawnPana
e09f55eedc chore: remove more dead code (second codex pass)
- Removed utils.py is_daemon_alive() (stale duplicate of main.py version)
- Removed TunnelManager.is_available() (unused, get_status() used instead)
- Removed dead json_output param from setup.handle()
2026-04-01 17:56:39 -07:00
ShawnPana
ca05f46352 refactor: remove --agent/register/tab-ownership, sessions-as-agents model
Multi-agent isolation is now achieved through separate sessions
(--session NAME), each with its own browser. Removed:
- register command and agents.json
- --agent flag and agent_id plumbing
- TabOwnershipManager and all tab locking logic
- dispatch lock and focus swapping between agents
- tab_ownership.py (deleted)
- test_tab_ownership.py (deleted)

Simplified tab commands: no lock checks, no _tab_list injection,
no _resolved_target_id params. agent_focus_target_id stays for
single-agent tab tracking.

Tested: 3 concurrent subagents on separate cloud sessions,
3 concurrent subagents on separate headless Chromium sessions.
2026-04-01 17:34:46 -07:00
ShawnPana
73a926caa6 feat: add connect command + --agent flag, decouple multi-agent from Chrome
- browser-use connect: one-time command to discover and connect to local
  Chrome (like cloud connect but for local)
- --agent INDEX: per-command flag for multi-agent tab isolation, works
  with any browser mode (cloud, profile, cdp-url, headless)
- register is now per-session ({session}.agents.json)
- --connect deprecated with migration message
- SKILL.md updated for new connect/--agent workflow
- Tested: 3 concurrent agents on shared cloud browser session
2026-04-01 16:52:56 -07:00
ShawnPana
c19a9a5b1b feat: add browser-use config command (set, get, list, unset)
CLI config management driven by CONFIG_KEYS schema. Validates keys,
coerces types (int for timeout), shows all values with config list.
2026-04-01 15:49:17 -07:00
ShawnPana
d60dd24cdf feat: rewrite setup as interactive post-install command
Six steps: home dir, config.json, Chromium, profile-use, cloudflared,
validation + config display. Interactive prompts for downloads (steps
3-5), --yes for CI. Idempotent — skips what's already installed.
2026-04-01 15:36:47 -07:00
ShawnPana
2e7dff8aa6 feat: doctor shows config state with all keys from schema
After diagnostics, doctor now displays config section showing all
CONFIG_KEYS values: api_key (masked), profile ID, proxy, timeout.
Uses get_config_display() from config module. Includes docs link.
2026-04-01 15:33:14 -07:00
ShawnPana
c2c9aa8556 feat: cloud signup command, unified base URL, auth isolation
- browser-use cloud signup: challenge-response agent self-registration
- browser-use cloud signup --verify: verify and save API key
- browser-use cloud signup --claim: generate account claim URL
- Base URL convention unified: BROWSER_USE_CLOUD_BASE_URL is host-only
  (e.g. https://api.browser-use.com), CLI appends /api/{version}
- CLI daemon blocked from falling back to library's cloud_auth.json
- cloud connect validates API key before spawning daemon
- No-key error message mentions cloud signup
2026-03-31 21:14:20 -07:00
ShawnPana
032e73eec7 feat: config-driven proxy/timeout for cloud connect, enable recording
cloud connect reads cloud_connect_proxy and cloud_connect_timeout from
~/.browser-use/config.json. Recording always enabled via enableRecording
default on CreateBrowserRequest. No CLI flags — edit config for custom
settings, use cloud v2 REST for full control.
2026-03-31 13:44:27 -07:00
ShawnPana
b4b2a4c18d feat: zero-config cloud connect with auto-managed profile
cloud connect now works with no flags. On first use, creates a
"Browser Use CLI" profile via the Cloud API and saves the ID to
config.json. Subsequent connects reuse it (validates on each call,
recreates if deleted).

Removed --timeout, --proxy-country, --profile-id flags and their
plumbing through daemon/sessions. Power users who need custom browser
settings use cloud v2 POST /browsers directly.
2026-03-31 12:28:42 -07:00
ShawnPana
526bde4d0f refactor: remove standalone switch and close-tab command aliases
These were duplicates of tab switch and tab close with separate
lock-checking and focus-resolution code paths. Having one way to
do each thing reduces maintenance surface and avoids isolation bugs.
2026-03-30 20:09:50 -07:00
ShawnPana
a6744f4ade fix: tab close uses caller's logical focus, not Chrome's global focus
Default close-tab and tab-close paths used session_manager.get_focused_target()
which returns Chrome's globally focused tab. In multi-agent mode this lets
one agent close another's tab. Now uses agent_focus_target_id first, falling
back to global focus only in single-agent mode.

Also: fresh daemon spawn now uses phase-aware state file waiting (15s) instead
of fixed 5s socket polling, consistent with ensure_daemon's probe logic.
2026-03-30 20:04:01 -07:00
ShawnPana
d59c0e6984 fix: CLI reconciliation gaps found by codex review
- ensure_daemon now phase-aware: waits for initializing/starting/
  shutting_down with staleness timeouts, errors on unhealthy sessions
- _close_session only cleans files after confirmed PID death
- _handle_sessions won't delete live daemon's files on stale terminal state
- _probe_session uses socket_pid for split-brain PID resolution
- _is_daemon_process works on Windows (wmic)
- Updated + added robustness tests (codex-authored)
2026-03-30 19:49:57 -07:00
ShawnPana
f222c98bbf feat: unified session probe and cross-platform lifecycle helpers
Replace scattered PID/socket/process checks with _probe_session() that
reads the state file, reconciles PIDs, checks liveness, and probes the
socket without deleting anything. Callers decide cleanup policy.

Adds _is_pid_alive, _is_daemon_process, _terminate_pid (cross-platform
with SIGKILL escalation), _close_session (shared by close and close-all).

sessions command now shows phase column. close and close-all both handle
orphaned daemons via SIGTERM fallback. close polls for PID disappearance
up to 15s before giving up.
2026-03-30 18:47:34 -07:00
ShawnPana
ac48ebecaf fix: SIGTERM fallback for orphaned daemons in close command
When the daemon's socket is unreachable but the PID file references a
live process, close now sends SIGTERM directly instead of printing
"No active browser session" and leaving the daemon running forever.
2026-03-30 18:39:06 -07:00
ShawnPana
e989797541 fix: sweep orphaned sockets in sessions command
Sockets without a corresponding live PID file were never cleaned up
because cleanup was only triggered per-session on next use. Add a
glob pass in _handle_sessions to remove any .sock file that doesn't
match a live session.
2026-03-29 18:05:56 -07:00
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
f819d3e3a6 feat: add tab command (list, new, switch, close) and agent registration
- `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
2026-03-24 17:27:38 -07:00
ShawnPana
31694df283 feat: multi-agent tab isolation for --connect mode
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.
2026-03-24 16:38:53 -07:00
ShawnPana
566bca0a88 handle ping success:false case in ensure_daemon config check
Previous commit fixed the exception path. This fixes the case where
ping returns a response with success:false — same fallthrough bug.
2026-03-19 23:10:22 -07:00
ShawnPana
edfd554f0f fix ensure_daemon falling through on ping failure with explicit config
When ping fails but daemon is alive, return instead of trying to spawn
a second daemon. The old daemon holds the socket so the new one can't
bind, causing silent config mismatch.
2026-03-19 23:06:31 -07:00
ShawnPana
f29aa6b5bc fix os.kill(pid, 0) on Windows: use OpenProcess instead of TerminateProcess
On Windows, os.kill(pid, 0) calls TerminateProcess which kills the process
instead of checking liveness. Use ctypes OpenProcess for Windows, keeping
os.kill(pid, 0) for Unix. Affects list_sessions(), tunnel PID checks, and
_handle_sessions().
2026-03-19 22:17:31 -07:00
ShawnPana
54f3febdfa address PR review comments: fix cloud v2 --help, guard double signal, error to stderr, stale port
- Narrow cloud --help intercept to only fire when --help is immediately
  after 'cloud', so 'cloud v2 --help' still shows OpenAPI endpoints
- Guard signal handler against concurrent shutdown tasks on repeated signals
- Route error response bodies to stderr in cloud REST commands
- Replace stale port 49200 in README Windows troubleshooting
2026-03-19 22:04:34 -07:00
ShawnPana
c26f228e5a fix cloud --help to show custom usage, tighten test assertions
- Intercept `cloud --help` early so it routes to _print_cloud_usage()
  instead of argparse's generic stub
- Remove permissive `or 'cloud'` fallback in epilog test assertion
- Delete no-op regex test that didn't verify actual code
- Tighten default socket path assertion to check 'default.sock'
2026-03-19 21:48:28 -07:00
ShawnPana
55665f70b8 fix socket FD leaks on connect() failure in CLI daemon infrastructure
Wrap socket creation + connect in try/finally across 5 locations to
ensure sockets are closed when connect() raises. Previously, failed
connections leaked file descriptors until GC ran.
2026-03-19 19:58:58 -07:00
ShawnPana
694a111fad add upload command to CLI, extract find_file_input_near_element to BrowserSession
- Add `browser-use upload <index> <path>` command for uploading files to
  file input elements via the CLI
- Extract find_file_input_near_element from nested closures in tools/service.py
  to a reusable method on BrowserSession, deduplicating two copies
- Add BrowserWrapper.upload() for the Python REPL
- Resolve file paths to absolute on the client side before sending to daemon
- Update SKILL.md files and README with upload command docs
2026-03-19 17:02:34 -07:00
ShawnPana
c70e5029ae fix profile subcommand argparse passthrough
Use nargs=REMAINDER to capture profile-use args, matching the cloud
subcommand pattern. Without this, argparse rejects unknown args like
'browser-use profile update'.
2026-03-18 16:19:41 -07:00
ShawnPana
d3e1818496 consolidate CLI files under ~/.browser-use/, add profile-use integration and doctor checks
Unify all CLI-managed files under ~/.browser-use/ (config, sockets, PIDs,
binaries, tunnels) instead of scattering across ~/.config/browser-use/ and
~/.browser-use/run/. Add profile-use Go binary as managed subcommand via
browser-use profile, with auto-download fallback and install.sh integration.
Wire cloudflared and profile-use availability checks into browser-use doctor.
2026-03-18 16:16:28 -07:00
ShawnPana
bff2918558 add --connect flag for Chrome auto-discovery and fix daemon shutdown for external browsers
Adds `--connect` to auto-discover running Chrome instances via DevToolsActivePort
files and well-known port probing, eliminating manual CDP URL construction. Fixes
daemon process hanging on `close` when connected to external browsers (--connect,
--cdp-url, cloud) by calling stop() (disconnect) instead of kill() (terminate).
2026-03-18 09:41:58 -07:00
ShawnPana
3318f56318 simplify CLI infrastructure: single-session daemon, remove install modes, streamline setup
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-15 10:12:41 -07:00
ShawnPana
0dc2fc5a6f remove run command and agent infrastructure from CLI
The `run` command pulled in heavy SDK dependencies (openai, anthropic,
google), had a bug (await on sync get_llm), and is superseded by
`browser-use cloud` for agent execution. CLI is now purely a browser
automation interface.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-12 11:44:13 -07:00
ShawnPana
91e987acdc add browser-use cloud command: generic REST passthrough to Cloud API
Login/logout with API key persistence, versioned REST calls (v2/v3),
task polling, and OpenAPI-driven help. Stdlib only, no daemon needed.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-12 11:13:43 -07:00
ShawnPana
4be221386b changes 2026-03-11 12:57:50 -07:00
ShawnPana
859cb97063 simplify daemon architecture: single session, socket-as-liveness, no PID/lock files
Replace the multi-session server (server.py, SessionRegistry, portalocker locking,
PID files, orphan detection) with a minimal daemon (daemon.py) that holds one
BrowserSession in memory. Socket file existence = alive. Auto-exits when browser
dies via CDP watchdog.

-2277 lines, +142 lines across 20 files.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-03 19:05:44 -08:00
ShawnPana
39698e58e4 strip cloud/remote commands from skill_cli
Remove all cloud API paths from the CLI while leaving core library
cloud support (BrowserSession(use_cloud=True), browser/cloud/) untouched.

Deleted: api_key.py, cloud_task.py, cloud_session.py
Removed: --browser remote, cloud-only run flags, task/session subcommands,
cloud profile ops (create/update/delete/sync), remote mode validation
Kept: tunnel (just Cloudflare), all local commands, install_config.py

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-03 15:56:31 -08:00
Saurav Panda
3f63677756 new direct cli mode 2026-02-19 10:18:12 -08:00
ShawnPana
c8242e7edd fix(cli): prevent orphaned server processes with flock-based locking
The session server had a race condition where concurrent CLI calls could
spawn multiple server processes. The old server would be orphaned when
the new one overwrote the PID file and deleted its socket.

Changes:
- Add flock-based locking using portalocker (already a dependency)
- Server acquires exclusive lock before writing PID file
- CLI checks both is_server_running() AND is_session_locked()
- Add kill_orphaned_server() to clean up servers with PID but no lock
- Increase socket timeout from 0.1s to 0.5s for reliability
- cleanup_session_files() now removes .lock and .meta files

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-12 10:10:05 -08:00
ShawnPana
4d8c4e5e48 refactor(cli): consolidate tunnel code into single tunnel.py
- Rename tunnel_manager.py to tunnel.py
- Remove dead code: commands/tunnel.py (session-scoped implementation never reached)
- Remove TunnelInfo dataclass and tunnels field from sessions.py
- Remove tunnel routing from server.py (unreachable code path)
- Update imports in main.py, doctor.py, setup.py, and tests

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-12 02:09:55 -08:00