diff --git a/apps/agents/agent-tauri/src-tauri/src/helpers/paths.rs b/apps/agents/agent-tauri/src-tauri/src/helpers/paths.rs index a651125e..30993b08 100644 --- a/apps/agents/agent-tauri/src-tauri/src/helpers/paths.rs +++ b/apps/agents/agent-tauri/src-tauri/src/helpers/paths.rs @@ -1,8 +1,17 @@ /// Expands `~` in paths to the `$HOME` directory. +/// +/// Canonicalizes `$HOME` first: on OSTree/atomic distros (Bazzite, Anatase) +/// `/home` is a symlink to `/var/home`, and Steam's sandboxed runtime +/// (pressure-vessel) does not resolve it — a shortcut written as +/// `/home/user/...` fails to launch (`chdir` ENOENT) even though the path +/// is valid outside the sandbox. pub(crate) fn expand_path(path: &str) -> String { if path.starts_with("~/") && let Ok(home) = std::env::var("HOME") { + let home = std::fs::canonicalize(&home) + .map(|p| p.to_string_lossy().into_owned()) + .unwrap_or(home); return format!("{}{}", home, &path[1..]); } path.to_string() diff --git a/crates/agent-server/src/lib.rs b/crates/agent-server/src/lib.rs index bba53108..ecf53124 100644 --- a/crates/agent-server/src/lib.rs +++ b/crates/agent-server/src/lib.rs @@ -30,7 +30,7 @@ pub enum ServerError { Io(#[from] std::io::Error), #[error("WebSocket error: {0}")] - WebSocket(#[from] tokio_tungstenite::tungstenite::Error), + WebSocket(#[from] Box), #[error("JSON error: {0}")] Json(#[from] serde_json::Error), diff --git a/crates/agent-server/src/server.rs b/crates/agent-server/src/server.rs index 408c9c68..1c70907f 100644 --- a/crates/agent-server/src/server.rs +++ b/crates/agent-server/src/server.rs @@ -166,7 +166,9 @@ impl AgentServer { let mut ws_config = tokio_tungstenite::tungstenite::protocol::WebSocketConfig::default(); ws_config.max_message_size = Some(WS_MAX_MESSAGE_SIZE); ws_config.max_frame_size = Some(WS_MAX_MESSAGE_SIZE); - let ws_stream = accept_async_with_config(stream, Some(ws_config)).await?; + let ws_stream = accept_async_with_config(stream, Some(ws_config)) + .await + .map_err(Box::new)?; tracing::info!(%peer_addr, "WebSocket connection established"); let meta = HubMeta { diff --git a/crates/hub-connection/src/manager.rs b/crates/hub-connection/src/manager.rs index 6cf596b8..a82b78bb 100644 --- a/crates/hub-connection/src/manager.rs +++ b/crates/hub-connection/src/manager.rs @@ -281,7 +281,7 @@ impl ConnectionManager { cancel_any_reconnect(&self.reconnect_cancel); // Set any Reconnecting agents to Disconnected. let mut states = self.state.write().await; - for (_, state) in states.iter_mut() { + for state in states.values_mut() { if matches!(state, ConnectionState::Reconnecting { .. }) { *state = ConnectionState::Disconnected; } diff --git a/crates/hub-connection/src/ws_client.rs b/crates/hub-connection/src/ws_client.rs index 797ff9a7..1f62bc2f 100644 --- a/crates/hub-connection/src/ws_client.rs +++ b/crates/hub-connection/src/ws_client.rs @@ -23,7 +23,7 @@ use capydeploy_protocol::messages::{ #[derive(Debug, thiserror::Error)] pub enum WsError { #[error("WebSocket error: {0}")] - Ws(#[from] tungstenite::Error), + Ws(#[from] Box), #[error("JSON error: {0}")] Json(#[from] serde_json::Error), @@ -88,7 +88,9 @@ impl WsClient { ws_config.max_message_size = Some(WS_MAX_MESSAGE_SIZE); ws_config.max_frame_size = Some(WS_MAX_MESSAGE_SIZE); let (ws_stream, _) = - tokio_tungstenite::connect_async_with_config(url, Some(ws_config), false).await?; + tokio_tungstenite::connect_async_with_config(url, Some(ws_config), false) + .await + .map_err(Box::new)?; let (write, read) = ws_stream.split(); let (write_tx, write_rx) = mpsc::channel::(256);