Fix PATH on Windows for extensions (#6000)
This commit is contained in:
@@ -504,78 +504,6 @@ async fn agent_add_extension(
|
||||
State(state): State<Arc<AppState>>,
|
||||
Json(request): Json<AddExtensionRequest>,
|
||||
) -> Result<StatusCode, ErrorResponse> {
|
||||
#[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<String> = (|| {
|
||||
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::<String, _>("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)
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user