feat(stealth): silent operation — never steal the user's foreground tab
Driving the user's real Chrome should not yank their view around. Now the agent operates entirely in the background: - New tabs are created with `background: true` (CreateTargetParams) so opening one never foregrounds it (the ab-connect extension already used active:false; this covers the raw-CDP path too). - Dropped the two AUTO `Page.bringToFront` calls (auto-connect fresh tab, and the internal active-page switch). The explicit `bringToFront` command is untouched — surfacing a tab stays opt-in. - enable_domains now sets `Emulation.setFocusEmulationEnabled(true)` so a backgrounded agent tab still renders (screenshots work), isn't render-throttled, and reports document.hasFocus()/visibilityState='visible' — which also removes the "tab is hidden the whole session" bot tell. Verified headless: hasFocus=true/visible while backgrounded; click + screenshot still work. Default behaviour, no flag.
This commit is contained in:
@@ -1511,12 +1511,11 @@ pub async fn execute_command(cmd: &Value, state: &mut DaemonState) -> Value {
|
||||
/// subsequent navigations don't hijack the user's existing tabs.
|
||||
async fn connect_auto_with_fresh_tab() -> Result<BrowserManager, String> {
|
||||
let mut mgr = BrowserManager::connect_auto().await?;
|
||||
// tab_new creates the tab in the background (CreateTargetParams.background),
|
||||
// so attaching to the user's Chrome never steals their foreground tab. We
|
||||
// deliberately do NOT bring it to front — silent operation.
|
||||
mgr.tab_new(None, None).await?;
|
||||
let session_id = mgr.active_session_id()?.to_string();
|
||||
let _ = mgr
|
||||
.client
|
||||
.send_command("Page.bringToFront", None, Some(&session_id))
|
||||
.await;
|
||||
|
||||
// Liveness probe: confirm the CDP session can actually round-trip
|
||||
// before returning success. Without this, a zombie CDP socket (process
|
||||
|
||||
Reference in New Issue
Block a user