fix: macOS PATH detection + npm install error diagnosis (v0.4.1)

- Fix macOS Node.js/npm/openclaw detection by adding enhanced_path() with common install locations (/usr/local/bin, /opt/homebrew/bin, ~/.nvm, ~/.volta, etc.)
- Add npm install error diagnosis: auto-detect git missing (exit 128), ENOENT, permission denied, network errors, cache corruption
- Show macOS-specific hint when Node.js detection fails in setup page
- Add shared error-diagnosis.js module used by both setup and services pages
- Add troubleshooting section to README.md
- Bump version to 0.4.1
This commit is contained in:
晴天
2026-03-05 22:21:11 +08:00
parent afb9f8ebe5
commit b1b95e5a11
13 changed files with 189 additions and 22 deletions

View File

@@ -39,6 +39,7 @@ fn npm_command() -> Command {
{
let mut cmd = Command::new("npm");
cmd.args(["--registry", &registry]);
cmd.env("PATH", super::enhanced_path());
cmd
}
}
@@ -635,6 +636,8 @@ pub fn check_node() -> Result<Value, String> {
let mut result = serde_json::Map::new();
let mut cmd = Command::new("node");
cmd.arg("--version");
#[cfg(not(target_os = "windows"))]
cmd.env("PATH", super::enhanced_path());
#[cfg(target_os = "windows")]
cmd.creation_flags(0x08000000); // CREATE_NO_WINDOW
match cmd.output() {

View File

@@ -13,3 +13,25 @@ pub mod service;
pub fn openclaw_dir() -> PathBuf {
dirs::home_dir().unwrap_or_default().join(".openclaw")
}
/// macOS/Linux 上 Tauri 从 Finder 启动时 PATH 很短(只有 /usr/bin:/bin:/usr/sbin:/sbin
/// 需要补充 Node.js / npm 常见安装路径,否则 check_node / npm_command 找不到命令
#[cfg(not(target_os = "windows"))]
pub fn enhanced_path() -> String {
let current = std::env::var("PATH").unwrap_or_default();
let home = dirs::home_dir().unwrap_or_default();
let extra: Vec<String> = vec![
"/usr/local/bin".into(),
"/opt/homebrew/bin".into(),
format!("{}/.nvm/current/bin", home.display()),
format!("{}/.volta/bin", home.display()),
format!("{}/.nodenv/shims", home.display()),
format!("{}/.fnm/current/bin", home.display()),
format!("{}/n/bin", home.display()),
];
let mut parts: Vec<&str> = extra.iter().map(|s| s.as_str()).collect();
if !current.is_empty() {
parts.push(&current);
}
parts.join(":")
}