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

@@ -5,6 +5,18 @@
格式遵循 [Keep a Changelog](https://keepachangelog.com/zh-CN/1.1.0/)
版本号遵循 [语义化版本](https://semver.org/lang/zh-CN/)。
## [0.4.1] - 2026-03-06
### 修复 (Bug Fixes)
- **macOS Node.js 检测失败** — Tauri 从 Finder 启动时 PATH 不含 `/usr/local/bin``/opt/homebrew/bin` 等常见路径,导致 `check_node``npm_command``openclaw_command` 找不到命令。新增 `enhanced_path()` 补充 nvm/volta/nodenv/fnm/n 等 Node.js 管理器路径
- **npm 安装失败无引导** — 安装/升级 OpenClaw 失败时仅显示"安装失败"现在自动诊断错误类型Git 未安装 / 文件访问 / 权限不足 / 网络错误 / 缓存损坏)并给出具体修复命令
### 优化 (Improvements)
- **macOS 检测引导** — 安装引导页 Node.js 检测失败时macOS 用户会看到"已经装了但检测不到?"提示,引导从终端启动
- **错误诊断模块** — 新增 `error-diagnosis.js` 共享模块,安装引导页和服务管理页共用错误诊断逻辑
## [0.4.0] - 2026-03-05
### 新增 (Features)

View File

@@ -257,6 +257,49 @@ npm run tauri build -- --bundles nsis
产物位于 `src-tauri/target/release/` 目录。
## 常见问题
### macOS 提示"已损坏,无法打开"
没有苹果开发者签名macOS Gatekeeper 会拦截。终端执行:
```bash
sudo xattr -rd com.apple.quarantine /Applications/ClawPanel.app
```
或前往「系统设置 → 隐私与安全性」点击「仍要打开」。
### macOS 检测不到 Node.js
从 Finder/Dock 启动 ClawPanel 时,应用的 PATH 环境变量可能不包含 Node.js 安装路径。
**v0.4.1 已修复**:自动补充 `/usr/local/bin``/opt/homebrew/bin``~/.nvm``~/.volta` 等常见路径。
临时解决:从终端启动 ClawPanel
```bash
open /Applications/ClawPanel.app
```
### Windows 安装 OpenClaw 报 ENOENT (-4058)
通常是文件权限或 npm 缓存问题:
1. 以管理员身份运行 ClawPanel
2. 或打开 PowerShell管理员手动安装
```powershell
npm install -g @qingchencloud/openclaw-zh --registry https://registry.npmmirror.com
```
3. 如果仍报错,清理 npm 缓存:`npm cache clean --force`
### Windows 安装报 exit 128 (access rights)
npm 依赖需要 Git但系统未安装。请先安装 [Git for Windows](https://git-scm.com/download/win),安装后重启 ClawPanel。
### 安装后 Node.js 检测不到Windows
安装 Node.js 后需要重启 ClawPanel或重启电脑新的 PATH 环境变量才能生效。
## 相关项目
| 项目 | 说明 |

View File

@@ -34,7 +34,7 @@
"description": "OpenClaw AI Agent 可视化管理面板,基于 Tauri v2 的跨平台桌面应用。支持仪表盘监控、多模型配置、实时 AI 聊天、记忆管理、Agent 管理、网关配置、内网穿透等功能。",
"url": "https://claw.qt.cool/",
"downloadUrl": "https://github.com/qingchencloud/clawpanel/releases/latest",
"softwareVersion": "0.4.0",
"softwareVersion": "0.4.1",
"author": {
"@type": "Organization",
"name": "晴辰云 QingchenCloud",
@@ -429,7 +429,7 @@
<div class="orb orb-1" id="orb1"></div>
<div class="orb orb-2" id="orb2"></div>
<div class="hero-inner">
<div class="reveal hero-badge"><span class="pulse"></span> v0.4.0 已发布 — Gateway 守护、配置同步、流式超时</div>
<div class="reveal hero-badge"><span class="pulse"></span> v0.4.1 已发布 — Gateway 守护、配置同步、流式超时</div>
<h1 class="reveal hero-title">管理你的 <span class="gradient-text shimmer">AI Agent</span><br>从未如此直观</h1>
<p class="reveal hero-subtitle">ClawPanel 是 <strong>OpenClaw</strong> 的可视化管理面板,基于 Tauri v2 构建。<br>仪表盘、模型配置、实时聊天、记忆管理 — 一站式掌控。</p>
<div class="reveal hero-cta">
@@ -696,7 +696,7 @@
<div class="orb orb-2" style="top:auto;bottom:-100px"></div>
<div class="container-sm" style="position:relative;z-index:10">
<div class="section-header">
<div class="reveal download-version"><span class="pulse"></span> v0.4.0 最新版</div>
<div class="reveal download-version"><span class="pulse"></span> v0.4.1 最新版</div>
<h2 class="reveal section-title"><span class="gradient-text">下载安装</span></h2>
<p class="reveal section-desc">选择你的操作系统,一键下载安装</p>
</div>
@@ -706,11 +706,11 @@
<h3>macOS</h3>
<p class="dl-desc">支持 Apple Silicon 和 Intel 芯片</p>
<div class="dl-links">
<a class="dl-link" href="https://github.com/qingchencloud/clawpanel/releases/latest/download/ClawPanel_0.4.0_aarch64.dmg" target="_blank" rel="noopener">
<a class="dl-link" href="https://github.com/qingchencloud/clawpanel/releases/latest/download/ClawPanel_0.4.1_aarch64.dmg" target="_blank" rel="noopener">
Apple Silicon (M1/M2/M3/M4)
<span class="dl-format">.dmg</span>
</a>
<a class="dl-link" href="https://github.com/qingchencloud/clawpanel/releases/latest/download/ClawPanel_0.4.0_x64.dmg" target="_blank" rel="noopener">
<a class="dl-link" href="https://github.com/qingchencloud/clawpanel/releases/latest/download/ClawPanel_0.4.1_x64.dmg" target="_blank" rel="noopener">
Intel 芯片
<span class="dl-format">.dmg</span>
</a>
@@ -721,11 +721,11 @@
<h3>Windows</h3>
<p class="dl-desc">支持 Windows 10 及以上版本</p>
<div class="dl-links">
<a class="dl-link" href="https://github.com/qingchencloud/clawpanel/releases/latest/download/ClawPanel_0.4.0_x64-setup.exe" target="_blank" rel="noopener">
<a class="dl-link" href="https://github.com/qingchencloud/clawpanel/releases/latest/download/ClawPanel_0.4.1_x64-setup.exe" target="_blank" rel="noopener">
安装程序
<span class="dl-format">.exe</span>
</a>
<a class="dl-link" href="https://github.com/qingchencloud/clawpanel/releases/latest/download/ClawPanel_0.4.0_x64_en-US.msi" target="_blank" rel="noopener">
<a class="dl-link" href="https://github.com/qingchencloud/clawpanel/releases/latest/download/ClawPanel_0.4.1_x64_en-US.msi" target="_blank" rel="noopener">
MSI 安装包
<span class="dl-format">.msi</span>
</a>
@@ -736,11 +736,11 @@
<h3>Linux</h3>
<p class="dl-desc">支持主流 Linux 发行版</p>
<div class="dl-links">
<a class="dl-link" href="https://github.com/qingchencloud/clawpanel/releases/latest/download/ClawPanel_0.4.0_amd64.AppImage" target="_blank" rel="noopener">
<a class="dl-link" href="https://github.com/qingchencloud/clawpanel/releases/latest/download/ClawPanel_0.4.1_amd64.AppImage" target="_blank" rel="noopener">
通用版
<span class="dl-format">.AppImage</span>
</a>
<a class="dl-link" href="https://github.com/qingchencloud/clawpanel/releases/latest/download/ClawPanel_0.4.0_amd64.deb" target="_blank" rel="noopener">
<a class="dl-link" href="https://github.com/qingchencloud/clawpanel/releases/latest/download/ClawPanel_0.4.1_amd64.deb" target="_blank" rel="noopener">
Debian / Ubuntu
<span class="dl-format">.deb</span>
</a>

View File

@@ -1,6 +1,6 @@
{
"name": "clawpanel",
"version": "0.4.0",
"version": "0.4.1",
"private": true,
"description": "ClawPanel - OpenClaw 可视化管理面板,基于 Tauri v2 的跨平台桌面应用",
"type": "module",

2
src-tauri/Cargo.lock generated
View File

@@ -328,7 +328,7 @@ dependencies = [
[[package]]
name = "clawpanel"
version = "0.2.1"
version = "0.4.1"
dependencies = [
"base64 0.22.1",
"chrono",

View File

@@ -1,6 +1,6 @@
[package]
name = "clawpanel"
version = "0.2.1"
version = "0.4.1"
edition = "2021"
description = "ClawPanel - OpenClaw 可视化管理面板"
authors = ["qingchencloud"]

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(":")
}

View File

@@ -15,7 +15,9 @@ pub fn openclaw_command() -> std::process::Command {
}
#[cfg(not(target_os = "windows"))]
{
std::process::Command::new("openclaw")
let mut cmd = std::process::Command::new("openclaw");
cmd.env("PATH", crate::commands::enhanced_path());
cmd
}
}
@@ -31,6 +33,8 @@ pub fn openclaw_command_async() -> tokio::process::Command {
}
#[cfg(not(target_os = "windows"))]
{
tokio::process::Command::new("openclaw")
let mut cmd = tokio::process::Command::new("openclaw");
cmd.env("PATH", crate::commands::enhanced_path());
cmd
}
}

View File

@@ -1,7 +1,7 @@
{
"$schema": "https://raw.githubusercontent.com/tauri-apps/tauri/dev/crates/tauri-config-schema/schema.json",
"productName": "ClawPanel",
"version": "0.4.0",
"version": "0.4.1",
"identifier": "ai.openclaw.clawpanel",
"build": {
"frontendDist": "../dist",

View File

@@ -0,0 +1,67 @@
/**
* npm install / upgrade 常见错误诊断
* 解析 npm 错误信息,返回用户友好的提示和修复建议
*/
/**
* @param {string} errStr - npm 错误输出
* @returns {{ title: string, hint?: string, command?: string }}
*/
export function diagnoseInstallError(errStr) {
const s = errStr.toLowerCase()
// git 未安装exit 128 + access rights
if (s.includes('code 128') || s.includes('exit 128') || s.includes('access rights')) {
return {
title: '安装失败 — 需要安装 Git',
hint: '部分依赖需要通过 Git 下载。请先安装 Git 后重试。',
command: '下载 Git: https://git-scm.com/downloads',
}
}
// ENOENT文件找不到
if (s.includes('enoent') || s.includes('-4058') || s.includes('code -4058')) {
return {
title: '安装失败 — 文件访问错误',
hint: '尝试以管理员身份运行 ClawPanel或在终端手动安装',
command: 'npm install -g @qingchencloud/openclaw-zh --registry https://registry.npmmirror.com',
}
}
// 权限不足EACCES / EPERM
if (s.includes('eacces') || s.includes('eperm') || s.includes('permission denied')) {
const isMac = navigator.platform?.includes('Mac') || navigator.userAgent?.includes('Mac')
return {
title: '安装失败 — 权限不足',
hint: isMac ? '请在终端使用 sudo 安装:' : '请以管理员身份打开终端安装:',
command: isMac
? 'sudo npm install -g @qingchencloud/openclaw-zh --registry https://registry.npmmirror.com'
: 'npm install -g @qingchencloud/openclaw-zh --registry https://registry.npmmirror.com',
}
}
// 网络错误
if (s.includes('etimedout') || s.includes('econnrefused') || s.includes('enotfound')
|| s.includes('network') || s.includes('fetch failed') || s.includes('socket hang up')) {
return {
title: '安装失败 — 网络连接错误',
hint: '请检查网络连接,或尝试切换 npm 镜像源后重试。',
}
}
// npm 缓存损坏
if (s.includes('integrity') || s.includes('sha512') || s.includes('cache')) {
return {
title: '安装失败 — npm 缓存异常',
hint: '尝试清理 npm 缓存后重试:',
command: 'npm cache clean --force',
}
}
// 通用 fallback
return {
title: '安装失败',
hint: '请在终端手动尝试安装,查看完整错误信息:',
command: 'npm install -g @qingchencloud/openclaw-zh --registry https://registry.npmmirror.com',
}
}

View File

@@ -6,6 +6,7 @@ import { api } from '../lib/tauri-api.js'
import { toast } from '../components/toast.js'
import { showConfirm, showUpgradeModal } from '../components/modal.js'
import { isMacPlatform, setUpgrading, setUserStopped, resetAutoRestart } from '../lib/app-state.js'
import { diagnoseInstallError } from '../lib/error-diagnosis.js'
// HTML 转义,防止 XSS
function escapeHtml(str) {
@@ -421,8 +422,13 @@ async function doUpgradeWithModal(source, page) {
modal.setDone(typeof msg === 'string' ? msg : (msg?.message || '升级完成'))
await loadVersion(page)
} catch (e) {
modal.appendLog(String(e))
modal.setError('升级失败')
const errStr = String(e)
modal.appendLog(errStr)
const diagnosis = diagnoseInstallError(errStr)
modal.setError(diagnosis.title)
if (diagnosis.hint) modal.appendLog('')
if (diagnosis.hint) modal.appendLog(' ' + diagnosis.hint)
if (diagnosis.command) modal.appendLog('💻 ' + diagnosis.command)
} finally {
setUpgrading(false)
unlistenLog?.()

View File

@@ -5,7 +5,8 @@
import { api } from '../lib/tauri-api.js'
import { showUpgradeModal } from '../components/modal.js'
import { toast } from '../components/toast.js'
import { setUpgrading } from '../lib/app-state.js'
import { setUpgrading, isMacPlatform } from '../lib/app-state.js'
import { diagnoseInstallError } from '../lib/error-diagnosis.js'
export async function render() {
const page = document.createElement('div')
@@ -84,7 +85,12 @@ function renderSteps(page, { node, cliOk, config }) {
OpenClaw 基于 Node.js 运行,请先安装。
</p>
<a class="btn btn-primary btn-sm" href="https://nodejs.org/" target="_blank" rel="noopener">下载 Node.js</a>
<span class="form-hint" style="margin-left:8px">安装后点击「重新检测」</span>`
<span class="form-hint" style="margin-left:8px">安装后点击「重新检测」</span>
${isMacPlatform() ? `
<div style="margin-top:var(--space-sm);padding:8px 12px;background:var(--bg-tertiary);border-radius:var(--radius-sm);font-size:var(--font-size-xs);color:var(--text-secondary);line-height:1.6">
<strong>已经装了但检测不到?</strong> macOS 上从 Finder 启动可能找不到 Node.js。试试关掉 ClawPanel 后从终端启动:<br>
<code style="background:var(--bg-secondary);padding:2px 6px;border-radius:3px;user-select:all">open /Applications/ClawPanel.app</code>
</div>` : ''}`
}
</div>
`
@@ -211,8 +217,13 @@ function bindEvents(page, nodeOk) {
toast('OpenClaw 安装成功', 'success')
setTimeout(() => window.location.reload(), 1500)
} catch (e) {
modal.appendLog(String(e))
modal.setError('安装失败')
const errStr = String(e)
modal.appendLog(errStr)
const diagnosis = diagnoseInstallError(errStr)
modal.setError(diagnosis.title)
if (diagnosis.hint) modal.appendLog('')
if (diagnosis.hint) modal.appendLog(' ' + diagnosis.hint)
if (diagnosis.command) modal.appendLog('💻 ' + diagnosis.command)
} finally {
setUpgrading(false)
unlistenLog?.()
@@ -221,4 +232,3 @@ function bindEvents(page, nodeOk) {
})
}