openclawsetup 2.4.5 → 2.4.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/bin/cli.mjs +68 -10
  2. package/install.sh +20 -0
  3. package/package.json +1 -1
package/bin/cli.mjs CHANGED
@@ -148,20 +148,62 @@ function checkNodeVersion() {
148
148
 
149
149
  function needsSudo() {
150
150
  const os = platform();
151
- if (os === 'win32' || os === 'darwin') return false;
151
+ if (os === 'win32') return false;
152
152
 
153
- try {
154
- const testDir = '/usr/lib/node_modules';
155
- if (existsSync(testDir)) {
156
- accessSync(testDir, fsConstants.W_OK);
157
- return false;
153
+ // 获取 npm 全局安装目录并检查写权限
154
+ const npmPrefixResult = safeExec('npm prefix -g');
155
+ if (npmPrefixResult.ok && npmPrefixResult.output) {
156
+ const globalDir = join(npmPrefixResult.output.trim(), 'lib', 'node_modules');
157
+ try {
158
+ if (existsSync(globalDir)) {
159
+ accessSync(globalDir, fsConstants.W_OK);
160
+ return false;
161
+ }
162
+ // 目录不存在,检查父目录
163
+ const parentDir = npmPrefixResult.output.trim();
164
+ if (existsSync(parentDir)) {
165
+ accessSync(parentDir, fsConstants.W_OK);
166
+ return false;
167
+ }
168
+ } catch {
169
+ return true;
170
+ }
171
+ }
172
+
173
+ // 回退检查
174
+ const testDirs = os === 'darwin'
175
+ ? ['/usr/local/lib/node_modules', '/opt/homebrew/lib/node_modules']
176
+ : ['/usr/lib/node_modules'];
177
+ for (const testDir of testDirs) {
178
+ try {
179
+ if (existsSync(testDir)) {
180
+ accessSync(testDir, fsConstants.W_OK);
181
+ return false;
182
+ }
183
+ } catch {
184
+ return true;
158
185
  }
159
- } catch {
160
- return true;
161
186
  }
162
187
  return true;
163
188
  }
164
189
 
190
+ function fixNpmCacheOwnership() {
191
+ // sudo npm install 会把 ~/.npm 的文件 owner 改成 root
192
+ // 导致后续普通用户的 npx 无法写缓存(EACCES)
193
+ if (platform() === 'win32') return;
194
+ const npmCacheDir = join(homedir(), '.npm');
195
+ if (!existsSync(npmCacheDir)) return;
196
+ try {
197
+ accessSync(npmCacheDir, fsConstants.W_OK);
198
+ } catch {
199
+ const user = process.env.USER || process.env.LOGNAME;
200
+ if (user) {
201
+ log.hint('修复 npm 缓存目录权限...');
202
+ safeExec(`sudo chown -R ${user} "${npmCacheDir}"`);
203
+ }
204
+ }
205
+ }
206
+
165
207
  function detectExistingInstall() {
166
208
  const home = homedir();
167
209
  const openclawDir = join(home, '.openclaw');
@@ -397,7 +439,8 @@ async function installOpenClaw() {
397
439
  console.log(colors.bold(colors.cyan('\n[1/2] 安装 OpenClaw CLI\n')));
398
440
 
399
441
  if (useSudo) {
400
- log.hint('Linux 系统需要 sudo 权限安装全局包');
442
+ const osName = platform() === 'darwin' ? 'macOS' : 'Linux';
443
+ log.hint(`${osName} 系统需要 sudo 权限安装全局包`);
401
444
  console.log(colors.yellow('\n请运行以下命令:'));
402
445
  console.log(colors.green(' sudo npm install -g openclaw@latest\n'));
403
446
 
@@ -410,10 +453,11 @@ async function installOpenClaw() {
410
453
  process.exit(1);
411
454
  }
412
455
  log.success(`OpenClaw 已安装: ${check.output}`);
456
+ fixNpmCacheOwnership();
413
457
  return 'openclaw';
414
458
  }
415
459
 
416
- // macOS 或有权限的 Linux:直接安装
460
+ // 有权限:直接安装
417
461
  console.log(colors.gray('正在安装 openclaw...\n'));
418
462
 
419
463
  const result = spawnSync('npm', ['install', '-g', 'openclaw@latest'], {
@@ -426,6 +470,20 @@ async function installOpenClaw() {
426
470
  return 'openclaw';
427
471
  }
428
472
 
473
+ // 安装失败,可能是权限问题,尝试 sudo(非 Windows)
474
+ if (platform() !== 'win32') {
475
+ log.warn('安装失败,可能是权限不足,尝试使用 sudo...');
476
+ const sudoResult = spawnSync('sudo', ['npm', 'install', '-g', 'openclaw@latest'], {
477
+ stdio: 'inherit',
478
+ shell: true,
479
+ });
480
+ if (sudoResult.status === 0) {
481
+ fixNpmCacheOwnership();
482
+ log.success('OpenClaw CLI 安装完成(sudo)');
483
+ return 'openclaw';
484
+ }
485
+ }
486
+
429
487
  // 尝试 clawdbot
430
488
  log.warn('openclaw 安装失败,尝试 clawdbot...');
431
489
  const fallback = spawnSync('npm', ['install', '-g', 'clawdbot@latest'], {
package/install.sh CHANGED
@@ -258,6 +258,7 @@ install_node() {
258
258
  # 验证安装
259
259
  if command -v node &> /dev/null; then
260
260
  log_success "Node.js 安装完成: $(node -v)"
261
+ fix_npm_cache_ownership
261
262
  else
262
263
  log_error "Node.js 安装失败"
263
264
  echo ""
@@ -401,6 +402,22 @@ show_installed_info() {
401
402
  echo " 飞书: npx openclaw-chat-cn@latest feishu"
402
403
  }
403
404
 
405
+ # 修复 npm 缓存目录权限(sudo 安装后 ~/.npm 可能被 root 占用)
406
+ fix_npm_cache_ownership() {
407
+ local npm_cache="$HOME/.npm"
408
+ if [ -d "$npm_cache" ]; then
409
+ local current_user
410
+ current_user=$(whoami 2>/dev/null || echo "")
411
+ if [ -n "$current_user" ] && [ "$current_user" != "root" ]; then
412
+ # 检查是否有 root 拥有的文件
413
+ if find "$npm_cache" -maxdepth 1 -user root 2>/dev/null | grep -q .; then
414
+ log_info "修复 npm 缓存目录权限..."
415
+ sudo chown -R "$current_user" "$npm_cache" 2>/dev/null || true
416
+ fi
417
+ fi
418
+ fi
419
+ }
420
+
404
421
  # 显示菜单并获取选择
405
422
  show_menu() {
406
423
  local choice=""
@@ -541,6 +558,9 @@ install_openclaw() {
541
558
  log_info "开始安装 OpenClaw..."
542
559
  echo ""
543
560
 
561
+ # 修复 npm 缓存权限(防止之前 sudo 导致的 EACCES)
562
+ fix_npm_cache_ownership
563
+
544
564
  # 清除 npm 缓存确保获取最新版本
545
565
  log_info "清除 npm 缓存..."
546
566
  npm cache clean --force 2>/dev/null || true
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "openclawsetup",
3
- "version": "2.4.5",
3
+ "version": "2.4.7",
4
4
  "description": "OpenClaw 安装向导 - 智能安装、诊断、自动修复",
5
5
  "type": "module",
6
6
  "bin": {