fix(native): auto_launch() honours AGENT_BROWSER_PROVIDER for cloud providers (#1126)
When a non-launch command (e.g. open, snapshot) triggers auto_launch() before the explicit launch command is processed, auto_launch() now checks AGENT_BROWSER_PROVIDER and connects via the provider API instead of always falling back to a local Chrome instance. Also redirects daemon stderr to /dev/null when not in debug mode to prevent crashes from broken pipe after the CLI drops the piped stderr handle. Cloud providers may write to stderr during connection setup. Fixes #1125 Related: #979
This commit is contained in:
@@ -1481,6 +1481,48 @@ async fn auto_launch(state: &mut DaemonState) -> Result<(), String> {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
// Cloud provider: when AGENT_BROWSER_PROVIDER is set, connect via the
|
||||
// provider API instead of launching a local Chrome instance. This mirrors
|
||||
// the logic in handle_launch() so that auto_launch (triggered by any
|
||||
// command arriving before an explicit "launch") honours the provider env.
|
||||
if let Ok(provider) = env::var("AGENT_BROWSER_PROVIDER") {
|
||||
let p = provider.to_lowercase();
|
||||
// ios/safari are device providers handled via explicit launch command
|
||||
if !p.is_empty() && p != "ios" && p != "safari" {
|
||||
let conn = providers::connect_provider(&p).await?;
|
||||
let ws_headers = if p == "agentcore" {
|
||||
providers::take_agentcore_ws_headers()
|
||||
} else {
|
||||
None
|
||||
};
|
||||
let connect_result = if conn.direct_page {
|
||||
BrowserManager::connect_cdp_direct(&conn.ws_url).await
|
||||
} else if ws_headers.is_some() {
|
||||
BrowserManager::connect_cdp_with_headers(&conn.ws_url, ws_headers).await
|
||||
} else {
|
||||
BrowserManager::connect_cdp(&conn.ws_url).await
|
||||
};
|
||||
match connect_result {
|
||||
Ok(mgr) => {
|
||||
state.reset_input_state();
|
||||
state.browser = Some(mgr);
|
||||
state.subscribe_to_browser_events();
|
||||
state.start_fetch_handler();
|
||||
state.start_dialog_handler();
|
||||
state.update_stream_client().await;
|
||||
write_provider_file(&state.session_id, &p);
|
||||
try_auto_restore_state(state).await;
|
||||
return Ok(());
|
||||
}
|
||||
Err(e) => {
|
||||
if let Some(ref ps) = conn.session {
|
||||
providers::close_provider_session(ps).await;
|
||||
}
|
||||
return Err(format!("Provider '{}' connection failed: {}", p, e));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
let mgr = BrowserManager::launch(options, engine.as_deref()).await?;
|
||||
state.reset_input_state();
|
||||
state.browser = Some(mgr);
|
||||
|
||||
@@ -41,6 +41,22 @@ pub async fn run_daemon(session: &str) {
|
||||
session
|
||||
);
|
||||
}
|
||||
} else {
|
||||
// Redirect stderr to /dev/null to prevent daemon crash when the
|
||||
// parent CLI drops the piped stderr handle after startup. Cloud
|
||||
// providers (AgentCore, Browserbase, etc.) may write to stderr
|
||||
// during connection setup; a broken pipe would kill the daemon.
|
||||
#[cfg(unix)]
|
||||
{
|
||||
use std::os::unix::io::IntoRawFd;
|
||||
if let Ok(devnull) = fs::File::create("/dev/null") {
|
||||
let fd = devnull.into_raw_fd();
|
||||
unsafe {
|
||||
libc::dup2(fd, 2);
|
||||
libc::close(fd);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let pid_path = socket_dir.join(format!("{}.pid", session));
|
||||
|
||||
Reference in New Issue
Block a user