diff --git a/src/api/system.rs b/src/api/system.rs index f915e7f..76e8831 100644 --- a/src/api/system.rs +++ b/src/api/system.rs @@ -26,6 +26,23 @@ use super::routes::AppState; /// Default repo path for Open Agent source const OPEN_AGENT_REPO_PATH: &str = "/opt/open_agent/vaduz-v1"; +fn resolve_open_agent_install_dir() -> PathBuf { + if let Ok(dir) = std::env::var("OPEN_AGENT_BIN_DIR") { + let trimmed = dir.trim(); + if !trimmed.is_empty() { + return PathBuf::from(trimmed); + } + } + + if let Ok(exe) = std::env::current_exe() { + if let Some(parent) = exe.parent() { + return parent.to_path_buf(); + } + } + + PathBuf::from("/usr/local/bin") +} + fn resolve_opencode_binary_path() -> PathBuf { if let Ok(path) = std::env::var("OPENCODE_BIN_PATH") { if !path.trim().is_empty() { @@ -822,16 +839,18 @@ fn stream_open_agent_update() -> impl Stream impl Stream {} Ok(output) => { let stderr = String::from_utf8_lossy(&output.stderr); + if stderr.contains("Permission denied") { + let sudo_result = Command::new("sudo") + .args(["-n", "install", "-m", "0755", &src, dest.as_ref()]) + .output() + .await; + match sudo_result { + Ok(sudo_output) if sudo_output.status.success() => { + continue; + } + Ok(sudo_output) => { + let sudo_stderr = String::from_utf8_lossy(&sudo_output.stderr); + yield Ok(Event::default().data(serde_json::to_string(&UpdateProgressEvent { + event_type: "error".to_string(), + message: format!( + "Failed to install {} with sudo: {}. Set OPEN_AGENT_BIN_DIR to a writable path or grant passwordless sudo for install.", + name, sudo_stderr + ), + progress: None, + }).unwrap())); + return; + } + Err(e) => { + yield Ok(Event::default().data(serde_json::to_string(&UpdateProgressEvent { + event_type: "error".to_string(), + message: format!( + "Failed to run sudo install for {}: {}. Set OPEN_AGENT_BIN_DIR to a writable path or grant passwordless sudo for install.", + name, e + ), + progress: None, + }).unwrap())); + return; + } + } + } yield Ok(Event::default().data(serde_json::to_string(&UpdateProgressEvent { event_type: "error".to_string(), message: format!("Failed to install {}: {}", name, stderr),