Compare commits
2
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2c3bcb8f3d | ||
|
|
5a61a64559 |
Generated
+1
-1
@@ -45,7 +45,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "agent-browser-stealth"
|
||||
version = "0.27.0-fork.37"
|
||||
version = "0.27.0-fork.38"
|
||||
dependencies = [
|
||||
"aes-gcm",
|
||||
"async-trait",
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "agent-browser-stealth"
|
||||
version = "0.27.0-fork.37"
|
||||
version = "0.27.0-fork.38"
|
||||
edition = "2021"
|
||||
description = "Fast browser automation CLI for AI agents"
|
||||
license = "Apache-2.0"
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -581,6 +581,7 @@ impl BrowserManager {
|
||||
&CreateTargetParams {
|
||||
url: "about:blank".to_string(),
|
||||
agent_group,
|
||||
background: None,
|
||||
},
|
||||
None,
|
||||
)
|
||||
@@ -687,6 +688,20 @@ impl BrowserManager {
|
||||
Some(session_id),
|
||||
)
|
||||
.await;
|
||||
// Silent operation: agent tabs are driven in the background (we never
|
||||
// force them to the foreground), so emulate focus. Without this a
|
||||
// backgrounded tab is render-throttled and reports `document.hidden` /
|
||||
// `!document.hasFocus()` — which both breaks timing-sensitive pages and
|
||||
// is itself a bot signal (a real user looks at the page). Best-effort;
|
||||
// ignored on engines without Emulation support.
|
||||
let _ = self
|
||||
.client
|
||||
.send_command(
|
||||
"Emulation.setFocusEmulationEnabled",
|
||||
Some(json!({ "enabled": true })),
|
||||
Some(session_id),
|
||||
)
|
||||
.await;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -973,6 +988,7 @@ impl BrowserManager {
|
||||
&CreateTargetParams {
|
||||
url: "about:blank".to_string(),
|
||||
agent_group,
|
||||
background: None,
|
||||
},
|
||||
None,
|
||||
)
|
||||
@@ -1137,6 +1153,7 @@ impl BrowserManager {
|
||||
&CreateTargetParams {
|
||||
url: target_url.to_string(),
|
||||
agent_group,
|
||||
background: Some(true),
|
||||
},
|
||||
None,
|
||||
)
|
||||
@@ -1192,11 +1209,10 @@ impl BrowserManager {
|
||||
let session_id = self.pages[index].session_id.clone();
|
||||
self.enable_domains(&session_id).await?;
|
||||
|
||||
// Bring tab to front
|
||||
let _ = self
|
||||
.client
|
||||
.send_command("Page.bringToFront", None, Some(&session_id))
|
||||
.await;
|
||||
// Silent: switching the agent's *internal* active page must not yank the
|
||||
// user's foreground tab. The page is driven in the background (focus is
|
||||
// emulated in enable_domains); the explicit `bringToFront` command is the
|
||||
// only way a tab is deliberately surfaced.
|
||||
|
||||
let url = self.get_url().await.unwrap_or_default();
|
||||
let title = self.get_title().await.unwrap_or_default();
|
||||
|
||||
@@ -153,6 +153,12 @@ pub struct CreateTargetParams {
|
||||
/// endpoint never receives an unknown parameter.
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub agent_group: Option<String>,
|
||||
/// Create the tab in the background so opening it never steals the user's
|
||||
/// foreground tab (silent operation). Standard CDP param; the ab-connect
|
||||
/// extension creates its tabs `active: false` regardless, so this only
|
||||
/// affects the raw-CDP (no extension) path.
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub background: Option<bool>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
|
||||
@@ -121,6 +121,7 @@ async fn collect_storage_via_temp_target(
|
||||
url: "about:blank".to_string(),
|
||||
// Transient internal target (storage collection) — never grouped.
|
||||
agent_group: None,
|
||||
background: None,
|
||||
},
|
||||
None,
|
||||
)
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "agent-browser-stealth",
|
||||
"version": "0.27.0-fork.37",
|
||||
"version": "0.27.0-fork.38",
|
||||
"description": "Browser automation CLI for AI agents — stealth fork with anti-detection",
|
||||
"type": "module",
|
||||
"packageManager": "pnpm@11.1.3",
|
||||
|
||||
Reference in New Issue
Block a user