* fix: Windows auto-connect profiling (#835) Fix three interrelated bugs causing `--auto-connect` to fail on Windows, plus a UX issue where auto-connect hijacked existing tabs: 1. Stale DevToolsActivePort — add TCP port liveness check before returning M144+ WebSocket URL; remove stale files when port is dead. 2. Missing Windows error codes — add os error 10061 (WSAECONNREFUSED) and 10054 (WSAECONNRESET) to is_transient_error() so daemon startup races are retried on Windows. 3. --auto-connect not propagated to daemon — add auto_connect to DaemonOptions, set AGENT_BROWSER_AUTO_CONNECT env var via apply_daemon_env(), and guard the headed launch block so it doesn't send a second launch that overrides the auto-connect. 4. Auto-connect opens a fresh tab — after connecting to an existing Chrome, create a new about:blank tab and bring it to front so navigations don't hijack the user's existing tabs. Made-with: Cursor * fix: address review feedback — cargo fmt, shared helper, Windows tests - Run cargo fmt on is_port_reachable() formatting - Extract duplicated auto-connect-with-fresh-tab logic into connect_auto_with_fresh_tab() helper used by both handle_launch() and auto_launch() - Add unit tests for Windows WSAECONNREFUSED (os error 10061) and WSAECONNRESET (os error 10054) in is_transient_error() --------- Co-authored-by: ctate <366502+ctate@users.noreply.github.com>
This commit is contained in:
@@ -234,6 +234,7 @@ pub struct DaemonOptions<'a> {
|
||||
pub action_policy: Option<&'a str>,
|
||||
pub confirm_actions: Option<&'a str>,
|
||||
pub engine: Option<&'a str>,
|
||||
pub auto_connect: bool,
|
||||
pub idle_timeout: Option<&'a str>,
|
||||
pub cdp: Option<&'a str>,
|
||||
}
|
||||
@@ -302,6 +303,9 @@ fn apply_daemon_env(cmd: &mut Command, session: &str, opts: &DaemonOptions) {
|
||||
if let Some(engine) = opts.engine {
|
||||
cmd.env("AGENT_BROWSER_ENGINE", engine);
|
||||
}
|
||||
if opts.auto_connect {
|
||||
cmd.env("AGENT_BROWSER_AUTO_CONNECT", "1");
|
||||
}
|
||||
if let Some(idle) = opts.idle_timeout {
|
||||
cmd.env("AGENT_BROWSER_IDLE_TIMEOUT_MS", idle);
|
||||
}
|
||||
@@ -533,6 +537,8 @@ fn is_transient_error(error: &str) -> bool {
|
||||
|| error.contains("os error 2") // No such file or directory (socket gone)
|
||||
|| error.contains("os error 61") // Connection refused (macOS)
|
||||
|| error.contains("os error 111") // Connection refused (Linux)
|
||||
|| error.contains("os error 10061") // Connection refused (Windows)
|
||||
|| error.contains("os error 10054") // Connection reset by peer (Windows)
|
||||
}
|
||||
|
||||
fn send_command_once(cmd: &Value, session: &str) -> Result<Response, String> {
|
||||
@@ -708,6 +714,20 @@ mod tests {
|
||||
));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_is_transient_error_connection_refused_windows() {
|
||||
assert!(is_transient_error(
|
||||
"Failed to connect: No connection could be made because the target machine actively refused it. (os error 10061)"
|
||||
));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_is_transient_error_connection_reset_windows() {
|
||||
assert!(is_transient_error(
|
||||
"Failed to send: An existing connection was forcibly closed by the remote host. (os error 10054)"
|
||||
));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_is_transient_error_non_transient() {
|
||||
// These should NOT be considered transient
|
||||
|
||||
Reference in New Issue
Block a user