Files
buzz/desktop/src-tauri/src/managed_agents/managed_node_paths.rs
Will Pfleger 596386ee55 feat(node): add Windows managed Node.js fallback (win-x64 + win-arm64) (#2661)
Signed-off-by: Will Pfleger <pfleger.will@gmail.com>
Co-authored-by: npub1mn7jgtj4w2pd0g0zeuhxsa6jy6p0rewxz4kujt98my82ahfmp72sxjexk7 <dcfd242e557282d7a1e2cf2e6877522682f1e5c6156dc92ca7d90eaedd3b0f95@buzz.block.builderlab.xyz>
2026-07-24 12:11:09 -04:00

102 lines
2.8 KiB
Rust

use std::path::PathBuf;
pub(crate) fn buzz_managed_npm_prefix() -> Option<PathBuf> {
dirs::data_dir().map(|dir| dir.join("Buzz").join("node-tools"))
}
const BUZZ_MANAGED_NODE_VERSION: &str = "v24.11.0";
pub(crate) fn buzz_managed_node_root() -> Option<PathBuf> {
dirs::data_dir().map(|dir| dir.join("Buzz").join("runtimes").join("node"))
}
pub(crate) fn buzz_managed_node_bin_dir() -> Option<PathBuf> {
let (platform, bin_subdir): (&str, Option<&str>) =
match (std::env::consts::OS, std::env::consts::ARCH) {
("macos", "aarch64") => ("darwin-arm64", Some("bin")),
("macos", "x86_64") => ("darwin-x64", Some("bin")),
("linux", "x86_64") => ("linux-x64", Some("bin")),
("linux", "aarch64") => ("linux-arm64", Some("bin")),
// Windows zips have node.exe + npm.cmd at the archive root — no bin/ subdir
("windows", "x86_64") => ("win-x64", None),
("windows", "aarch64") => ("win-arm64", None),
_ => return None,
};
buzz_managed_node_root().map(|root| {
let dir = root.join(BUZZ_MANAGED_NODE_VERSION).join(platform);
match bin_subdir {
Some(sub) => dir.join(sub),
None => dir,
}
})
}
pub(crate) fn buzz_managed_node_bin_path() -> Option<PathBuf> {
buzz_managed_node_bin_dir().map(|bin| {
#[cfg(windows)]
{
bin.join("node.exe")
}
#[cfg(not(windows))]
{
bin.join("node")
}
})
}
pub(crate) fn buzz_managed_npm_bin_dir() -> Option<PathBuf> {
buzz_managed_npm_prefix().map(|prefix| {
#[cfg(windows)]
{
prefix
}
#[cfg(not(windows))]
{
prefix.join("bin")
}
})
}
pub(crate) fn buzz_managed_command_path(command: &str, basename: &str) -> Option<PathBuf> {
if command.contains(std::path::MAIN_SEPARATOR)
|| !matches!(
command,
"codex-acp" | "claude-agent-acp" | "claude-code-acp" | "node" | "npm"
)
{
return None;
}
let mut dirs = Vec::new();
if let Some(managed_bin) = buzz_managed_npm_bin_dir() {
dirs.push(managed_bin);
}
if let Some(managed_node_bin) = buzz_managed_node_bin_dir() {
dirs.push(managed_node_bin);
}
dirs.into_iter()
.map(|dir| dir.join(basename))
.find(|candidate| is_executable_file(candidate))
}
fn is_executable_file(path: &std::path::Path) -> bool {
let Ok(metadata) = path.metadata() else {
return false;
};
if !metadata.is_file() {
return false;
}
#[cfg(unix)]
{
use std::os::unix::fs::PermissionsExt;
metadata.permissions().mode() & 0o111 != 0
}
#[cfg(not(unix))]
{
true
}
}