diff --git a/cli/src/native/actions.rs b/cli/src/native/actions.rs index 2887853..40ab436 100644 --- a/cli/src/native/actions.rs +++ b/cli/src/native/actions.rs @@ -1,5 +1,6 @@ use serde_json::{json, Value}; use std::env; +use std::io::Write; use std::sync::Arc; use tokio::sync::{broadcast, RwLock}; @@ -1247,7 +1248,7 @@ fn open_url_in_browser(url: &str) { "unsupported platform", )); if let Err(e) = result { - eprintln!("[inspect] Failed to open browser: {}", e); + let _ = writeln!(std::io::stderr(), "[inspect] Failed to open browser: {}", e); } } diff --git a/cli/src/native/auth.rs b/cli/src/native/auth.rs index 20af27c..c157761 100644 --- a/cli/src/native/auth.rs +++ b/cli/src/native/auth.rs @@ -3,6 +3,7 @@ use base64::{engine::general_purpose::STANDARD, Engine}; use serde::{Deserialize, Serialize}; use serde_json::{json, Value}; use std::fs; +use std::io::Write; use std::path::PathBuf; #[derive(Debug, Clone, Serialize, Deserialize)] @@ -137,7 +138,8 @@ fn ensure_encryption_key() -> Result, String> { let _ = fs::set_permissions(&key_file, fs::Permissions::from_mode(0o600)); } - eprintln!( + let _ = writeln!( + std::io::stderr(), "[agent-browser] Auto-generated encryption key at {} -- back up this file or set {}", key_file.display(), ENCRYPTION_KEY_ENV diff --git a/cli/src/native/cdp/chrome.rs b/cli/src/native/cdp/chrome.rs index d810aec..b6128a0 100644 --- a/cli/src/native/cdp/chrome.rs +++ b/cli/src/native/cdp/chrome.rs @@ -1,4 +1,4 @@ -use std::io::{BufRead, BufReader}; +use std::io::{BufRead, BufReader, Write}; use std::path::{Path, PathBuf}; use std::process::{Child, Command, Stdio}; use std::time::Duration; @@ -47,7 +47,10 @@ impl Drop for ChromeProcess { std::thread::sleep(Duration::from_millis(100)); } Err(e) => { - eprintln!( + // Use write! instead of eprintln! to avoid panicking + // if the daemon's stderr pipe is broken (parent dropped it). + let _ = writeln!( + std::io::stderr(), "Warning: failed to clean up temp profile {}: {}", dir.display(), e @@ -207,9 +210,13 @@ pub fn launch_chrome(options: &LaunchOptions) -> Result { Err(e) => { last_err = e; if attempt < max_attempts { - eprintln!( + // Use write! instead of eprintln! to avoid panicking + // if the daemon's stderr pipe is broken (parent dropped it). + let _ = writeln!( + std::io::stderr(), "[chrome] Launch attempt {}/{} failed, retrying in 500ms...", - attempt, max_attempts + attempt, + max_attempts ); std::thread::sleep(Duration::from_millis(500)); } diff --git a/cli/src/native/daemon.rs b/cli/src/native/daemon.rs index 65d3918..ab5ba71 100644 --- a/cli/src/native/daemon.rs +++ b/cli/src/native/daemon.rs @@ -1,6 +1,7 @@ use serde_json::Value; use std::env; use std::fs; +use std::io::Write; use std::path::PathBuf; use std::process; use std::sync::Arc; @@ -47,11 +48,12 @@ pub async fn run_daemon(session: &str) { stream_client = Some(client_slot.clone()); let stream_path = socket_dir.join(format!("{}.stream", session)); if let Err(e) = fs::write(&stream_path, stream_server.port().to_string()) { - eprintln!("Failed to write .stream file: {}", e); + let _ = + writeln!(std::io::stderr(), "Failed to write .stream file: {}", e); } } Err(e) => { - eprintln!("Stream server failed to start: {}", e); + let _ = writeln!(std::io::stderr(), "Stream server failed to start: {}", e); } } } @@ -73,7 +75,7 @@ pub async fn run_daemon(session: &str) { let _ = fs::remove_file(&stream_path); if let Err(e) = result { - eprintln!("Daemon error: {}", e); + let _ = writeln!(std::io::stderr(), "Daemon error: {}", e); process::exit(1); } } @@ -112,7 +114,7 @@ async fn run_socket_server( }); } Err(e) => { - eprintln!("Accept error: {}", e); + let _ = writeln!(std::io::stderr(), "Accept error: {}", e); } } } @@ -185,7 +187,7 @@ async fn run_socket_server( }); } Err(e) => { - eprintln!("Accept error: {}", e); + let _ = writeln!(std::io::stderr(), "Accept error: {}", e); } } } @@ -299,21 +301,25 @@ async fn shutdown_signal() { let mut sigint = match signal::unix::signal(signal::unix::SignalKind::interrupt()) { Ok(s) => s, Err(e) => { - eprintln!("Failed to install SIGINT handler: {}", e); + let _ = writeln!(std::io::stderr(), "Failed to install SIGINT handler: {}", e); process::exit(1); } }; let mut sigterm = match signal::unix::signal(signal::unix::SignalKind::terminate()) { Ok(s) => s, Err(e) => { - eprintln!("Failed to install SIGTERM handler: {}", e); + let _ = writeln!( + std::io::stderr(), + "Failed to install SIGTERM handler: {}", + e + ); process::exit(1); } }; let mut sighup = match signal::unix::signal(signal::unix::SignalKind::hangup()) { Ok(s) => s, Err(e) => { - eprintln!("Failed to install SIGHUP handler: {}", e); + let _ = writeln!(std::io::stderr(), "Failed to install SIGHUP handler: {}", e); process::exit(1); } }; @@ -328,7 +334,7 @@ async fn shutdown_signal() { #[cfg(windows)] { if let Err(e) = signal::ctrl_c().await { - eprintln!("Failed to install Ctrl+C handler: {}", e); + let _ = writeln!(std::io::stderr(), "Failed to install Ctrl+C handler: {}", e); process::exit(1); } } diff --git a/cli/src/native/inspect_server.rs b/cli/src/native/inspect_server.rs index 518c2ad..1c151a4 100644 --- a/cli/src/native/inspect_server.rs +++ b/cli/src/native/inspect_server.rs @@ -1,3 +1,4 @@ +use std::io::Write; use std::sync::atomic::{AtomicI64, Ordering}; use std::sync::Arc; @@ -87,7 +88,7 @@ async fn accept_loop( tokio::spawn(async move { if let Err(e) = handle_connection(stream, proxy, tid, chp, proxy_port).await { - eprintln!("[inspect] connection error: {}", e); + let _ = writeln!(std::io::stderr(), "[inspect] connection error: {}", e); } }); } @@ -233,7 +234,8 @@ async fn handle_ws_proxy( let raw_msg = match raw_rx.recv().await { Ok(msg) => msg, Err(tokio::sync::broadcast::error::RecvError::Lagged(n)) => { - eprintln!( + let _ = writeln!( + std::io::stderr(), "[inspect] warning: dropped {} CDP messages (channel lag)", n );