114 Commits

Author SHA1 Message Date
yan5xu 811ae49592 fix: daemon lifecycle — stop stale daemon on startup and CDP port mismatch (#224)
- stopDaemon(): 3-phase shutdown (HTTP → wait → SIGKILL)
- ensureDaemon(): detect CDP port mismatch, stop old daemon before respawn
- Daemon startup: cleanupStaleDaemon() kills orphan processes
- Fixes stale daemon persisting across provider/daemon restarts
2026-05-22 20:18:35 +08:00
yan5xu 635443fe05 feat: Phase 4 — merge provider into daemon with --hub mode
Daemon can now connect to Pinix Hub directly via --hub flag:
  bb-browser daemon --hub https://hub.pinixai.com --hub-token xxx

New: packages/daemon/src/hub-bridge.ts (1042 lines)
- HubBridge class with gRPC ProviderStream connection
- Clip registration (browser clip + platform clips)
- Invoke handling calls dispatchRequest() directly (no HTTP round-trip)
- Streamer (bb-viewer) lifecycle management
- Clip Web UI serving
- TURN credential generation
- Data command file I/O

Key improvement: browser commands invoked via Hub are dispatched
directly in-process instead of HTTP POST to daemon, eliminating
one network hop.

bin/bb-browser-provider.ts kept as-is for backward compat.
2026-05-22 19:02:50 +08:00
yan5xu 8559b772c9 refactor: Phase 2 — new protocol format, command renames, --tab required
Protocol:
- action → method, success/data/error → result/error (mutually exclusive)
- Remove id field from Request/Response
- Error is now {message, hint} object, not plain string
- HTTP method filter renamed: method → httpMethod (avoids conflict)

Command renames:
- snapshot → snap
- refresh → reload
- Remove tab_select (use open --tab)
- Remove tab_close (use close --tab)

--tab required:
- Most commands require --tab, error with hint if missing
- Exceptions: open (optional), site (auto-match domain), tab list/new, daemon

Removed commands:
- fetch (use eval or site run)
- wait (agent polls snap)
- history (not browser control)

Other:
- get supports all 5 attributes (text/url/title/value/html)
- -1400 lines across 36 files
2026-05-22 18:45:35 +08:00
yan5xu c7bd48a900 feat: move site adapter execution from CLI to daemon (Phase 3)
- New: packages/daemon/src/site-adapter.ts — site adapter scanning,
  @meta parsing, domain-based tab matching, and JS evaluation via CDP
- Daemon: add site_run, site_list, site_info, site_search actions
- CLI: site commands now send HTTP to daemon instead of executing locally
- Provider: executeSiteCommand uses daemon site_run instead of shelling
  out to CLI subprocess (removes execFile dependency)
- Protocol: add siteName, siteArgs, query fields to Request type

Site adapter execution is now a single path: CLI/Provider → daemon
→ CDP evaluate. No more three-layer process nesting.
2026-05-22 17:44:58 +08:00
yan5xu 7bb8cd1624 refactor: Phase 1 cleanup — remove MCP, dead code, unify CDP port
- Remove packages/mcp/ entirely (Agent uses CLI or Hub invoke)
- Remove dead code: reload.ts (never routed)
- Unify default CDP port to 9222 (daemon was 19825, viewer was 9222)
- Remove --mcp CLI flag
- Update comments to reflect MCP removal
2026-05-22 17:16:42 +08:00
yan5xu ba86f0c38c feat(daemon): screenshot saves to clip data and returns pinix:// URI
Screenshot command now writes PNG to ~/.pinix/data/browser/screenshots/
and returns a pinix:// URI by default. Base64 dataUrl is only included
when explicitly requested (includeBase64 flag), keeping the response
lightweight for cross-clip consumption.

CLI screenshot command sets includeBase64 for local file saving.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-11 17:54:21 +08:00
Yanwu c0b4ff1691 fix(cli): daemon self-healing on CDP disconnect + cookie persistence (#207)
* fix(cli): daemon self-healing on CDP disconnect + cookie persistence

- ensureDaemon() now checks cdpConnected from /status response; when
  Chrome is killed and daemon loses its CDP WebSocket, the stale daemon
  is stopped and a fresh daemon+Chrome is spawned automatically instead
  of returning 503 on every command.

- daemon status command shows actionable hints: how to start when not
  running, how to stop when running, and a warning with recovery steps
  when CDP is disconnected.

- Add --use-mock-keychain to managed Chrome launch args so cookie
  encryption uses a fixed key instead of macOS Keychain. This fixes
  cookie persistence on headless/remote machines (e.g. Mac Mini via SSH)
  where Keychain access is unavailable (errSecInteractionNotAllowed).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* feat(cli): add `daemon start` subcommand for explicit background startup

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-07 09:20:46 +08:00
Yanwu 3a24359ac6 feat: warn when local adapter overrides community version (#178) (#179)
When running a site adapter that exists in both ~/.bb-browser/sites/
(local) and ~/.bb-browser/bb-sites/ (community), print a warning to
stderr so users know they're running a local override that may be
outdated. Suppressed in --json mode.

Closes #178

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-06 09:32:47 +08:00
Yanwu 03c6bf2010 refactor: provider rewrite + cleanup (-1891 lines) (#176)
* refactor: rewrite Edge Clip provider using @pinixai/hub-client (#175)

Replace hand-written protobuf descriptor in bb-browserd.ts with typed
imports from @pinixai/hub-client. The new bb-browser-provider.ts uses
create() from @bufbuild/protobuf with generated schemas, registers site
adapters as separate per-platform clips, and routes invocations to
either the daemon HTTP layer (browser commands) or CLI (site commands).

- Delete bin/bb-browserd.ts (1140 lines)
- Add bin/bb-browser-provider.ts (~710 lines)
- Add @pinixai/hub-client dependency
- Add bb-browser-provider bin entry and tsup entry point
- Add esbuild plugin to resolve hub-client gen subpath import

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: import from @pinixai/hub-client top-level exports

Use hub-client 0.1.2 which exports ProviderStream types directly.
Remove esbuild plugin hack for deep gen/hub_pb import.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* refactor: delete dead CDP code, fix MCP auth, extract shared daemon client

- Delete cdp-client.ts (1212 lines), cdp-monitor.ts (521 lines),
  cdp-monitor-state.ts (182 lines) — all dead code from pre-daemon era
- Fix MCP server to read daemon.json for token/port instead of
  hardcoded DAEMON_BASE_URL without auth
- Extract httpJson, readDaemonJson, isProcessAlive, DaemonInfo to
  packages/shared/src/daemon-client.ts — eliminates duplication across
  CLI daemon-manager, MCP server, and Edge Clip provider
- Fix scroll left/right: deltaX was hardcoded to 0, now properly
  maps direction to deltaX/deltaY
- Align daemon tsup target from node20 to node18 (matches engines)
- Remove cdp-monitor from tsup entry points

Net: -1891 lines

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: lint — use DAEMON_DIR from shared, remove unused os import

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: review feedback — refresh platformClipAliases on reconnect, remove dead DAEMON_BASE_URL

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: remove duplicate bun shebang from provider source

tsup adds #!/usr/bin/env node via banner config. The source file's
#!/usr/bin/env bun caused a double shebang in dist/provider.js,
breaking node execution.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-06 06:04:43 +08:00
Yanwu 67efdd38fd fix: CDP 503 returns diagnostics immediately instead of 30s timeout (#157)
When Chrome disconnects or CDP connection fails, the daemon now:
- Returns 503 immediately instead of waiting 30 seconds
- Includes CDP target address, failure reason, and remediation hint
- Stores lastError in CdpConnection for diagnostic context

Before: {"error":"CDP connection timeout"} after 30s wait
After:  {"error":"Chrome not connected (CDP at host:port)","reason":"...","hint":"..."} immediately

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-03 10:54:48 +08:00
Yanwu 9243517f18 fix: auto-launch Chrome when daemon starts (#152)
* fix: auto-launch Chrome when daemon starts (#136, #143, #141)

CLI's ensureDaemon() now discovers/launches Chrome via cdp-discovery
before spawning the daemon, and passes --cdp-host/--cdp-port to it.
Previously the daemon was spawned with no CDP info, failed silently,
and users got "Daemon did not start in time" for every command.

- CLI: call discoverCdpPort() before spawn, pass CDP endpoint to daemon
- CLI: improve error messages with specific remediation steps
- CLI: increase startup timeout from 5s to 10s (Chrome launch time)
- MCP: read managed port file and pass --cdp-port to daemon
- Tests: 8 new daemon-startup tests reproducing and verifying the fix
- Tests: fix daemon-lifecycle tests (unique ports, tsx runner, proper cleanup)

Closes #136, closes #143, relates to #141, #118, #146

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: remove unused variable in MCP ensureDaemon

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* test: fix daemon-lifecycle kill-9 assertion for parallel CI

Relax PID equality assertion since parallel test suites share
daemon.json in CI. Assert file existence and valid structure instead.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* Revert "test: fix daemon-lifecycle kill-9 assertion for parallel CI"

This reverts commit ba572d0f2a.

* fix: isolate test suites with BB_BROWSER_HOME to avoid parallel conflicts

Daemon and CLI tests both spawn daemon processes that write to
~/.bb-browser/daemon.json. When turbo runs them in parallel, they
conflict. Fix by:
- Support BB_BROWSER_HOME env var in daemon and daemon-manager
- Each test suite uses its own temp dir via BB_BROWSER_HOME

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: use DAEMON_DIR for managed port file path in daemon

The managed port file path was hardcoded to ~/.bb-browser/browser/cdp-port
ignoring BB_BROWSER_HOME. This broke test isolation in CI.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-03 09:15:08 +08:00
yan5xu 6d52b22601 fix: consolidate daemon state into daemon.json with PID liveness check
Replace separate PID file (/tmp/bb-browser.pid) and token file
(~/.bb-browser/daemon.token) with a single ~/.bb-browser/daemon.json
containing pid, host, port, and token.

CLI now reads daemon.json to connect, using the actual bound address
instead of hardcoded DAEMON_HOST. PID liveness check via process.kill(0)
detects stale daemon.json from crashed processes and auto-recovers.

Add harness tests for PID strategy and cold-start recovery scenario.

Closes #140

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-02 05:48:25 +08:00
yan5xu 7936566ec5 feat!: remove Chrome Extension package
Move buildDomTree.js to packages/shared/. Delete packages/extension/
entirely. Update path references in daemon and CLI. Remove
build:extension script and release-please manifest sync.

The daemon connects directly to Chrome via CDP WebSocket since v0.11.0.
The Extension is no longer needed.

BREAKING CHANGE: Chrome Extension is removed. Users who relied on the
extension-based flow should use the daemon-direct mode instead.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-02 05:33:17 +08:00
Xeon 37f8d64959 fix: align daemon host defaults and restore daemon command (#137) 2026-04-02 05:29:36 +08:00
haibinwang9 208643638e feat(cli): support cdpUrl and cdpHost from OpenClaw (#70)
* feat(cli): support cdpUrl and cdpHost from OpenClaw

- Prioritize cdpUrl field for full CDP endpoint URL
- Fall back to cdpHost + cdpPort if cdpUrl not available
- cdpHost defaults to 127.0.0.1 when not specified

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix(cli): increase openclaw timeout to 30s

* perf(cli): add env var and file cache for CDP discovery

---------

Co-authored-by: User <user@example.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-01 16:01:04 +08:00
yan5xu cbdd26c2c8 fix: update openclaw-bridge tests for new flag ordering (#102)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-01 16:00:48 +08:00
Trystan Lei 1b3a39437f fix(cli): place openclaw browser flags before subcommand (#102) 2026-04-01 15:59:41 +08:00
Yanwu 62af1f89d7 refactor: unify daemon — CDP direct, remove Extension dependency (#132)
Merge daemon + cdp-monitor into a single CDP-direct backend. All CLI
and MCP commands now route through the daemon HTTP API instead of
direct CDP connections or Extension relay.

Key changes:
- Daemon: rewrite to hold persistent CDP WebSocket, handle all 30+
  commands via dispatchRequest, per-tab event state with RingBuffer,
  short tab IDs (4-char hex), global seq counter, incremental queries
  via since/cursor mechanism
- CLI: all commands route through daemon HTTP, --tab accepts string
  short IDs, add --since/--method/--status flags for network queries,
  fix tab close with --tab flag, fix invalid tab ID silent fallback
- MCP: tab parameter z.number() → z.string(), add browser_console
  and browser_errors tools, add since/method/status/limit params to
  browser_network, remove Extension dependency hints
- Shared: export additional types for daemon consumption

Bug fixes from harness testing:
- Invalid tab ID now errors instead of silent fallback
- tab_new works with zero existing tabs
- console.warn() correctly captured as type "warn"
- --tab flag works with tab close command

Closes #131

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-01 11:02:48 +08:00
yan5xu ea6f08c007 fix: remove replMode from CDP evaluate to fix async/Promise results
replMode: true caused Chrome to treat Promise values as plain objects,
bypassing awaitPromise: true. This made all async site adapters
(twitter/reply, twitter/search, etc.) return empty {} instead of
actual results.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-22 15:21:57 +08:00
yan5xu b9ee3aaca2 fix: add Chrome Dev/Beta/Canary and Brave to Windows browser candidates
Chrome Dev installs to %LOCALAPPDATA% on Windows, not Program Files.
Without these paths bb-browser falls through to Edge even when Chrome
Dev is installed.

Fixes feedback from @NormanMises_

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-22 15:05:16 +08:00
yan5xu ee2c404245 fix: follow-up fixes for merged PRs #82, #91, #25
- #82: extract EXEC_TIMEOUT_BUFFER_MS constant for magic number 5000
- #91: remove failed tabs from sessionOpenedTabs to prevent stale entries
- #25: update platform/command counts from 35/97 to 36/103

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-22 14:40:45 +08:00
Waffle 7c2ee5e14e fix(cli): pass timeout through to OpenClaw (#82)
* fix(cli): pass timeout through to OpenClaw

* fix(cli): scope openclaw timeout to subcommands
2026-03-22 14:37:55 +08:00
Ted Li 45c1fbb385 fix(shared): avoid global crypto for request ids (#89) 2026-03-22 14:36:05 +08:00
yan5xu 6d8f18b393 fix: open new tabs in background to avoid bringing Chrome to foreground
Add `background: true` to both `Target.createTarget` CDP calls so that
`bb-browser open --tab` and `bb-browser tab new` no longer activate the
Chrome window. This prevents disrupting the user's workflow when agents
run browser automation in the background.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-22 12:33:24 +08:00
yan5xu 94c94b7c4e feat(cli): add CDP monitor background process for persistent monitoring (Phase 1, #77)
Monitoring commands (network, console, errors, trace) are broken in
direct CDP mode because each CLI invocation is a new short-lived
process that cannot accumulate events over time.

This introduces a long-running background monitor process that
maintains a persistent CDP connection and collects events:

- cdp-monitor-state.ts: MonitorState class extracted from cdp-client.ts
  event handling logic (Network.*, Runtime.*, trace)
- cdp-monitor.ts: standalone Node.js process that connects to Chrome
  via CDP, attaches to all page targets, and serves an HTTP API on
  127.0.0.1 with bearer-token auth
- monitor-manager.ts: CLI-side lifecycle management (spawn, health
  check, shutdown, command forwarding)
- client.ts: routes monitor actions (network/console/errors/trace)
  through the monitor with graceful fallback to direct CDP
- tsup.config.ts: adds cdp-monitor as a build entry point

The monitor auto-discovers new tabs, writes PID/port/token files to
~/.bb-browser/, and auto-exits after 30 minutes of inactivity.
cdp-client.ts is intentionally left untouched to avoid regressions.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-19 23:47:12 +08:00
Yanwu 22d38c1368 Merge pull request #67 from MonkeyLeeT/codex/mcp-site-tools
feat(mcp): add site adapter tools
2026-03-19 20:15:59 +08:00
Yanwu 3a1541114f Merge pull request #69 from ox01024/fix/status-command-help
fix(cli): wire top-level status command
2026-03-19 20:15:22 +08:00
Yanwu a391b8241a Merge pull request #63 from MonkeyLeeT/codex/fix-eval-top-level-await
Clean fix using replMode: true — same approach as Chrome DevTools Console. No side effects on existing expressions. LGTM.
2026-03-19 20:14:39 +08:00
Yanwu 3659fb869a Merge pull request #74 from ox01024/fix/click-navigation
Fixes real click-offset bug on scrolled pages. Viewport coordinate transformation is correct. LGTM.
2026-03-19 20:14:29 +08:00
Yanwu 152225b2e0 Merge pull request #80 from ox01024/fix/get-ref-cross-invocation
Solid state management with proper stale-target protection. LGTM.
2026-03-19 20:14:21 +08:00
Waffle 600244d0da fix(cli): avoid double-inserting typed text 2026-03-19 15:40:47 +08:00
Waffle 578e10f56d fix(cli): persist selected target for get commands 2026-03-19 15:40:10 +08:00
Waffle 92fa9f7fc7 fix(cli): use viewport coordinates for click targets 2026-03-19 14:59:34 +08:00
Waffle c8b1aab0ad fix(cli): wire top-level status command 2026-03-19 11:03:38 +08:00
ted 4626fff84a chore(cli): minimize site command diff 2026-03-18 18:54:06 -07:00
ted 7804f06226 feat(mcp): add site adapter tools 2026-03-18 18:51:25 -07:00
Yanwu d56cab9d6a Merge pull request #62 from MonkeyLeeT/codex/fix-openclaw-noisy-json
LGTM! All review feedback addressed thoroughly in b0b7c7b. Clean implementation, solid test coverage. Thanks for the quick turnaround!
2026-03-18 16:22:58 +08:00
ted 2a5493ea5b Revert "chore(shared): add Runtime.evaluate coverage"
This reverts commit ef79e28e7b.
2026-03-17 23:49:42 -07:00
ted ef79e28e7b chore(shared): add Runtime.evaluate coverage 2026-03-17 23:43:24 -07:00
ted cbad572068 refactor(cli): simplify OpenClaw JSON recovery 2026-03-17 23:39:35 -07:00
ted b0b7c7be0e fix(cli): harden OpenClaw JSON parsing 2026-03-17 23:32:55 -07:00
ted cfbae0763a fix: support top-level await in eval 2026-03-17 23:28:42 -07:00
ted 28e0867ee4 fix(cli): tolerate noisy OpenClaw JSON output 2026-03-17 21:10:29 -07:00
Waffle a1b9f38617 fix: derive version metadata from package.json 2026-03-17 11:25:51 +08:00
Yanwu e7de67c4df fix(cli): add Chrome Dev/Canary/Beta/Arc to browser detection (#42) (#43)
- Add missing browser candidates to findBrowserExecutable() on macOS
- Remove obsolete daemon-era commands (start/stop/status/reload)
- Bump to v0.8.3

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-16 11:04:29 +08:00
yan5xu f36297300c chore: bump to v0.8.2 2026-03-16 10:05:00 +08:00
yan5xu 64bb52ae00 chore: bump to v0.9.0 2026-03-16 10:03:49 +08:00
yan5xu 936047ad2b fix: cross-process refs, fill command, snapshot robustness
- Add DOM.getDocument before DOM.performSearch in xpath fallback (fixes cross-process click/fill)
- Persist refs to /tmp/bb-browser-refs-<targetId>.json for cross-process usage
- Fix fill command: use backendNodeId for DOM.focus, add insertTextIntoNode helper
- Graceful snapshot fallback for complex pages (google.com)

All 13 core commands tested and passing.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-16 09:57:34 +08:00
yan5xu c3a3bf8d1d fix: snapshot, tab list, and discovery overhead in CDP mode
- Fix snapshot: map buildDomTree.js actual API params and parse return format
- Fix tab list: add "list" as recognized subcommand alias
- Fix discovery: check managed browser first, defer OpenClaw probe
- All 9 core commands passing (open, eval, snapshot, screenshot, tab, site, history, recommend)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-16 02:42:46 +08:00
yan5xu 4d63ae2935 fix: process hangs after CDP command completes
- Unref WebSocket so it doesn't keep the event loop alive
- Call process.exit(0) after main() resolves

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-16 02:15:42 +08:00