Compare commits
2
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2c3bcb8f3d | ||
|
|
5a61a64559 |
Generated
+1
-1
@@ -45,7 +45,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "agent-browser-stealth"
|
name = "agent-browser-stealth"
|
||||||
version = "0.27.0-fork.37"
|
version = "0.27.0-fork.38"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"aes-gcm",
|
"aes-gcm",
|
||||||
"async-trait",
|
"async-trait",
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "agent-browser-stealth"
|
name = "agent-browser-stealth"
|
||||||
version = "0.27.0-fork.37"
|
version = "0.27.0-fork.38"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
description = "Fast browser automation CLI for AI agents"
|
description = "Fast browser automation CLI for AI agents"
|
||||||
license = "Apache-2.0"
|
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.
|
/// subsequent navigations don't hijack the user's existing tabs.
|
||||||
async fn connect_auto_with_fresh_tab() -> Result<BrowserManager, String> {
|
async fn connect_auto_with_fresh_tab() -> Result<BrowserManager, String> {
|
||||||
let mut mgr = BrowserManager::connect_auto().await?;
|
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?;
|
mgr.tab_new(None, None).await?;
|
||||||
let session_id = mgr.active_session_id()?.to_string();
|
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
|
// Liveness probe: confirm the CDP session can actually round-trip
|
||||||
// before returning success. Without this, a zombie CDP socket (process
|
// before returning success. Without this, a zombie CDP socket (process
|
||||||
|
|||||||
@@ -581,6 +581,7 @@ impl BrowserManager {
|
|||||||
&CreateTargetParams {
|
&CreateTargetParams {
|
||||||
url: "about:blank".to_string(),
|
url: "about:blank".to_string(),
|
||||||
agent_group,
|
agent_group,
|
||||||
|
background: None,
|
||||||
},
|
},
|
||||||
None,
|
None,
|
||||||
)
|
)
|
||||||
@@ -687,6 +688,20 @@ impl BrowserManager {
|
|||||||
Some(session_id),
|
Some(session_id),
|
||||||
)
|
)
|
||||||
.await;
|
.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(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -973,6 +988,7 @@ impl BrowserManager {
|
|||||||
&CreateTargetParams {
|
&CreateTargetParams {
|
||||||
url: "about:blank".to_string(),
|
url: "about:blank".to_string(),
|
||||||
agent_group,
|
agent_group,
|
||||||
|
background: None,
|
||||||
},
|
},
|
||||||
None,
|
None,
|
||||||
)
|
)
|
||||||
@@ -1137,6 +1153,7 @@ impl BrowserManager {
|
|||||||
&CreateTargetParams {
|
&CreateTargetParams {
|
||||||
url: target_url.to_string(),
|
url: target_url.to_string(),
|
||||||
agent_group,
|
agent_group,
|
||||||
|
background: Some(true),
|
||||||
},
|
},
|
||||||
None,
|
None,
|
||||||
)
|
)
|
||||||
@@ -1192,11 +1209,10 @@ impl BrowserManager {
|
|||||||
let session_id = self.pages[index].session_id.clone();
|
let session_id = self.pages[index].session_id.clone();
|
||||||
self.enable_domains(&session_id).await?;
|
self.enable_domains(&session_id).await?;
|
||||||
|
|
||||||
// Bring tab to front
|
// Silent: switching the agent's *internal* active page must not yank the
|
||||||
let _ = self
|
// user's foreground tab. The page is driven in the background (focus is
|
||||||
.client
|
// emulated in enable_domains); the explicit `bringToFront` command is the
|
||||||
.send_command("Page.bringToFront", None, Some(&session_id))
|
// only way a tab is deliberately surfaced.
|
||||||
.await;
|
|
||||||
|
|
||||||
let url = self.get_url().await.unwrap_or_default();
|
let url = self.get_url().await.unwrap_or_default();
|
||||||
let title = self.get_title().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.
|
/// endpoint never receives an unknown parameter.
|
||||||
#[serde(skip_serializing_if = "Option::is_none")]
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
pub agent_group: Option<String>,
|
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)]
|
#[derive(Debug, Deserialize)]
|
||||||
|
|||||||
@@ -121,6 +121,7 @@ async fn collect_storage_via_temp_target(
|
|||||||
url: "about:blank".to_string(),
|
url: "about:blank".to_string(),
|
||||||
// Transient internal target (storage collection) — never grouped.
|
// Transient internal target (storage collection) — never grouped.
|
||||||
agent_group: None,
|
agent_group: None,
|
||||||
|
background: None,
|
||||||
},
|
},
|
||||||
None,
|
None,
|
||||||
)
|
)
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "agent-browser-stealth",
|
"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",
|
"description": "Browser automation CLI for AI agents — stealth fork with anti-detection",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"packageManager": "pnpm@11.1.3",
|
"packageManager": "pnpm@11.1.3",
|
||||||
|
|||||||
Reference in New Issue
Block a user