Repository navigation
fix(browser-control): keep external CDP control in the background - #3445
Merged
Merged
Conversation
External browser control raised the user's browser on every attach: connect, switch_page and tab_new defaulted to activate=true and sent Page.bringToFront, new tabs used Target.createTarget's foreground default, and the macOS launch path used `open -na`, which activates the app. Browser control is background work now. Tabs are created with background: true, Page.bringToFront only runs for an explicit `activate` request, and the macOS launch path uses `open -g`. The legacy /json/new endpoint cannot create a background tab, so background creation goes through the browser-level WebSocket advertised by /json/version and falls back to the HTTP endpoint when that is unavailable. Launched automation instances also disable occluded-window backgrounding so a background page still loads, renders and captures. The two flows that genuinely need a visible window keep their activation: the browser-owned approval prompt before a real-profile connection, and a user-initiated restart. Windows and Linux have no supported non-activating launch, so only that first launch can take focus; every CDP operation afterwards stays in the background. Co-authored-by: OpenBitFun <318544290+bitfun-ai@users.noreply.github.com>
… work Record the browser activation contract next to the existing browser tool orchestration section so a future change does not reintroduce window raising: tabs are created in the background, page selection never surfaces the window, and only an explicit `activate` request, a browser-owned approval prompt, or a user-initiated restart may bring the browser forward. Co-authored-by: OpenBitFun <318544290+bitfun-ai@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
External CDP browser control brought the user's browser to the front on practically every attach. Four independent causes:
connect,switch_pageandtab_newdefaultedactivatetotrueand sentPage.bringToFront.Target.createTargetwithoutbackground: true, and the protocol default is a foreground tab that raises the window.open -na <App>, which activates the application.PUT /json/newendpoint has no background option at all.Browser control is now background by default; the window and focus stay where the user left them.
Type and Areas
Type: bug fix
Areas: Rust core (agent tools / browser control), services (browser launch), desktop/Tauri (Settings > Browser Control), docs (architecture)
Motivation / Impact
A user driving an existing, logged-in browser only wanted the page read or clicked. Each
connect/navigateinstead pulled the browser over their editor and stole keyboard focus, so background automation was not usable at all.What changes:
background: true;Page.bringToFrontruns only for an explicitactivate: truerequest. Results keepactivatedand addactivation: background|foreground.user_data_dir) creates its background tab through the browser-level WebSocket advertised by/json/version, then resolves the page WebSocket from/json; it falls back to the HTTP endpoint when that WebSocket is unavailable.open -g(newBrowserLaunchOptions.activate, default false). Launched automation instances also pass--disable-backgrounding-occluded-windows,--disable-renderer-backgroundingand--disable-background-timer-throttlingso a background page still loads, renders and captures.BrowserLauncher::activate_browserbefore the request), and a user-initiated browser restart from Settings.activateand when it is allowed, so the model does not raise the window to make an action "look" like it ran.docs/architecture/computer-use-control.mdand in the nearest module guide, so a later change does not silently reintroduce window raising.Windows and Linux have no supported non-activating launch through
process_manager(CREATE_NO_WINDOWhides consoles, not GUI windows), so only the initial launch of a not-yet-running browser can take focus there. Every CDP operation afterwards stays in the background on all three platforms.activate_browserreportsfalseon platforms without a supported activation entry point instead of pretending.Verification
cargo test -p openbitfun-core --no-default-features --features agent-runtime,tools-browser-web,tools-computer-use,git --lib browser_control::— passed (41 tests; includes newpage_creation_only_asks_for_a_background_tab_when_requested)cargo test -p openbitfun-core --no-default-features --features agent-runtime,tools-browser-web,tools-computer-use,git --lib control_hub_tool::— passed (55 tests; includes newbrowser_activation_is_opt_in,description_documents_background_browser_control)cargo test -p openbitfun-services-integrations --features browser-control browser_control::— passed (11 tests; includes newmacos_background_launch_keeps_the_browser_out_of_the_foreground,browser_launch_does_not_activate_by_default)cargo clippy -p openbitfun-services-integrations --features browser-control --lib --all-targetsandcargo clippy -p openbitfun-core --no-default-features --features agent-runtime,tools-browser-web,tools-computer-use,git --lib— no new warningscargo fmt --all -- --check— passednode scripts/check-core-boundaries.mjs— passedringis missing); the CI matrix is the evidence for those targets.Reviewer Notes
Target.createTarget backgroundis a Chrome-only protocol parameter. Chromium-based browsers that ignore it degrade to the previous foreground behavior; the call does not fail.activate: trueis the only opt-in.Generated with OpenBitFun