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>>,
|
State(state): State<Arc<AppState>>,
|
||||||
Json(request): Json<AddExtensionRequest>,
|
Json(request): Json<AddExtensionRequest>,
|
||||||
) -> Result<StatusCode, ErrorResponse> {
|
) -> 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?;
|
let agent = state.get_agent(request.session_id).await?;
|
||||||
agent
|
agent
|
||||||
.add_extension(request.config)
|
.add_extension(request.config)
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ use rmcp::transport::{
|
|||||||
};
|
};
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::option::Option;
|
use std::option::Option;
|
||||||
|
use std::path::PathBuf;
|
||||||
use std::process::Stdio;
|
use std::process::Stdio;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
@@ -144,6 +145,16 @@ fn normalize(input: String) -> String {
|
|||||||
result.to_lowercase()
|
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> {
|
fn require_str_parameter<'a>(v: &'a serde_json::Value, name: &str) -> Result<&'a str, ErrorData> {
|
||||||
let v = v.get(name).ok_or_else(|| {
|
let v = v.get(name).ok_or_else(|| {
|
||||||
ErrorData::new(
|
ErrorData::new(
|
||||||
@@ -474,13 +485,16 @@ impl ExtensionManager {
|
|||||||
..
|
..
|
||||||
} => {
|
} => {
|
||||||
let all_envs = merge_environments(envs, env_keys, &sanitized_name).await?;
|
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
|
// Check for malicious packages before launching the process
|
||||||
extension_malware_check::deny_if_malicious_cmd_args(cmd, args).await?;
|
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?;
|
let client = child_process_client(command, timeout, self.provider.clone()).await?;
|
||||||
Box::new(client)
|
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)
|
REM Check if Node.js is installed in Program Files (x86)
|
||||||
if exist "C:\Program Files (x86)\nodejs\node.exe" (
|
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"
|
set "NODE_EXE=C:\Program Files (x86)\nodejs\node.exe"
|
||||||
goto :found
|
goto :found
|
||||||
)
|
)
|
||||||
|
|||||||
Reference in New Issue
Block a user