diff --git a/crates/goose-server/src/routes/agent.rs b/crates/goose-server/src/routes/agent.rs index 3d1be23ae215..f5440663e6a9 100644 --- a/crates/goose-server/src/routes/agent.rs +++ b/crates/goose-server/src/routes/agent.rs @@ -482,78 +482,6 @@ async fn agent_add_extension( State(state): State>, Json(request): Json, ) -> Result { - #[cfg(windows)] - { - use winreg::enums::{HKEY_LOCAL_MACHINE, KEY_READ}; - use winreg::RegKey; - - if let ExtensionConfig::Stdio { cmd, .. } = &request.config { - if cmd.ends_with("npx.cmd") || cmd.ends_with("npx") { - let mut node_exists = std::path::Path::new(r"C:\Program Files\nodejs\node.exe") - .exists() - || std::path::Path::new(r"C:\Program Files (x86)\nodejs\node.exe").exists(); - - // Also check Windows registry: HKEY_LOCAL_MACHINE\\SOFTWARE\\Node.js InstallPath - if !node_exists { - // Try 64-bit view first, then 32-bit. Use open_subkey_with_flags to avoid WOW64 redirection issues. - let install_path_from_reg: Option = (|| { - let hk_local_machine = RegKey::predef(HKEY_LOCAL_MACHINE); - // Common keys to try - let keys = vec!["SOFTWARE\\Node.js", "SOFTWARE\\WOW6432Node\\Node.js"]; - for k in keys.iter() { - if let Ok(subkey) = hk_local_machine.open_subkey_with_flags(k, KEY_READ) - { - if let Ok(val) = subkey.get_value::("InstallPath") { - if !val.trim().is_empty() { - return Some(val); - } - } - } - } - None - })(); - - if let Some(path_str) = install_path_from_reg { - let node_path = std::path::Path::new(&path_str).join("node.exe"); - if node_path.exists() { - node_exists = true; - } - } - } - - if !node_exists { - let cmd_path = std::path::Path::new(&cmd); - let script_dir = cmd_path - .parent() - .ok_or_else(|| ErrorResponse::internal("Invalid command path"))?; - let install_script = script_dir.join("install-node.cmd"); - - if install_script.exists() { - eprintln!("Node.js not found on the system, installing Node.js..."); - let output = std::process::Command::new(&install_script) - .arg("https://nodejs.org/dist/v23.10.0/node-v23.10.0-x64.msi") - .output() - .map_err(|_e| { - ErrorResponse::internal("Failed to run Node.js installer") - })?; - - if !output.status.success() { - return Err(ErrorResponse::internal(format!( - "Failed to install Node.js: {}", - String::from_utf8_lossy(&output.stderr) - ))); - } - } else { - return Err(ErrorResponse::internal(format!( - "Node.js not found on the system, and no installer script found at: {}", - install_script.display() - ))); - } - } - } - } - } - let agent = state.get_agent(request.session_id).await?; agent .add_extension(request.config) diff --git a/crates/goose/src/agents/extension_manager.rs b/crates/goose/src/agents/extension_manager.rs index dd8f356ded2f..4384e9841e36 100644 --- a/crates/goose/src/agents/extension_manager.rs +++ b/crates/goose/src/agents/extension_manager.rs @@ -13,6 +13,7 @@ use rmcp::transport::{ }; use std::collections::HashMap; use std::option::Option; +use std::path::PathBuf; use std::process::Stdio; use std::sync::Arc; use std::time::Duration; @@ -144,6 +145,16 @@ fn normalize(input: String) -> String { result.to_lowercase() } +fn resolve_command(cmd: &str) -> PathBuf { + SearchPaths::builder() + .with_npm() + .resolve(cmd) + .unwrap_or_else(|_| { + // let the OS raise the error + PathBuf::from(cmd) + }) +} + fn require_str_parameter<'a>(v: &'a serde_json::Value, name: &str) -> Result<&'a str, ErrorData> { let v = v.get(name).ok_or_else(|| { ErrorData::new( @@ -474,13 +485,16 @@ impl ExtensionManager { .. } => { let all_envs = merge_environments(envs, env_keys, &sanitized_name).await?; - let command = Command::new(cmd).configure(|command| { - command.args(args).envs(all_envs); - }); // Check for malicious packages before launching the process extension_malware_check::deny_if_malicious_cmd_args(cmd, args).await?; + let cmd = resolve_command(cmd); + + let command = Command::new(cmd).configure(|command| { + command.args(args).envs(all_envs); + }); + let client = child_process_client(command, timeout, self.provider.clone()).await?; Box::new(client) } diff --git a/ui/desktop/src/platform/windows/bin/install-node.cmd b/ui/desktop/src/platform/windows/bin/install-node.cmd index 84fbb41d8da6..26abe9b09b03 100644 --- a/ui/desktop/src/platform/windows/bin/install-node.cmd +++ b/ui/desktop/src/platform/windows/bin/install-node.cmd @@ -10,7 +10,7 @@ if exist "C:\Program Files\nodejs\node.exe" ( REM Check if Node.js is installed in Program Files (x86) if exist "C:\Program Files (x86)\nodejs\node.exe" ( - echo Node.js found in Program Files (x86) + echo "Node.js found in Program Files (x86)" set "NODE_EXE=C:\Program Files (x86)\nodejs\node.exe" goto :found )