yingclaw 2.5.0 → 2.5.1

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.
package/bin/cli.js CHANGED
@@ -21,7 +21,7 @@ const {
21
21
  const { execSync, spawn, spawnSync } = require('child_process');
22
22
  const pkg = require('../package.json');
23
23
  const { buildMenuStatusLines, buildStatusView } = require('../lib/panel');
24
- const { buildClaudeInstallCommand } = require('../lib/install');
24
+ const { buildClaudeInstallCommand, checkNodeEnv, getNodeInstallGuide, getInstallFailureHints } = require('../lib/install');
25
25
  const { clearClaudeDesktopConfig, isDesktopConfigured, openClaudeDesktop, writeClaudeDesktopConfig } = require('../lib/desktop');
26
26
  const { runDoctorChecks, summarize, STATUS_OK, STATUS_FAIL, STATUS_WARN, STATUS_INFO } = require('../lib/doctor');
27
27
 
@@ -402,6 +402,31 @@ program
402
402
  if (!yes) return;
403
403
  } catch {}
404
404
 
405
+ // 检查 npm / Node.js 环境
406
+ const nodeEnv = checkNodeEnv();
407
+ if (!nodeEnv.npmOk) {
408
+ console.log(boxen(
409
+ chalk.bold.red('未检测到 npm,无法安装 Claude Code\n\n') +
410
+ chalk.dim('Claude Code 通过 npm 安装,需要先安装 Node.js(含 npm)。\n\n') +
411
+ chalk.bold('安装方式:\n') +
412
+ getNodeInstallGuide().map(l => chalk.cyan(' ' + l)).join('\n') +
413
+ '\n\n' + chalk.dim('安装完成后重新运行 claw install-claude'),
414
+ { padding: { top: 0, bottom: 0, left: 2, right: 2 }, borderStyle: 'round', borderColor: 'red', margin: { top: 1, bottom: 1 } }
415
+ ));
416
+ return;
417
+ }
418
+ if (!nodeEnv.nodeOk) {
419
+ console.log(boxen(
420
+ chalk.bold.yellow(`Node.js 版本过低(当前 v${nodeEnv.nodeVersion},需要 ≥18)\n\n`) +
421
+ chalk.dim('Claude Code 要求 Node.js ≥18,当前版本可能导致安装或运行失败。\n\n') +
422
+ chalk.bold('升级方式:\n') +
423
+ getNodeInstallGuide().map(l => chalk.cyan(' ' + l)).join('\n'),
424
+ { padding: { top: 0, bottom: 0, left: 2, right: 2 }, borderStyle: 'round', borderColor: 'yellow', margin: { top: 1, bottom: 1 } }
425
+ ));
426
+ const proceed = await confirm({ message: '仍然尝试安装?', default: false });
427
+ if (!proceed) return;
428
+ }
429
+
405
430
  const network = await select({ loop: false,
406
431
  message: chalk.cyan('你的网络环境'),
407
432
  choices: [
@@ -423,10 +448,9 @@ program
423
448
  console.log(chalk.green('\n✔ Claude Code 安装成功!'));
424
449
  } else {
425
450
  console.log(chalk.red('\n✘ 安装失败'));
451
+ const hints = getInstallFailureHints(result, chalk);
426
452
  console.log(boxen(
427
- chalk.bold('手动安装:\n\n') +
428
- chalk.cyan('npm config set registry https://registry.npmmirror.com\n') +
429
- chalk.cyan('npm install -g @anthropic-ai/claude-code'),
453
+ hints.join(''),
430
454
  { padding: { top: 0, bottom: 0, left: 2, right: 2 }, borderStyle: 'round', borderColor: 'yellow', margin: { top: 1, bottom: 1 } }
431
455
  ));
432
456
  return;
package/lib/install.js CHANGED
@@ -1,3 +1,5 @@
1
+ const { execSync } = require('child_process');
2
+
1
3
  function buildClaudeInstallCommand(network) {
2
4
  const args = ['install', '-g', '@anthropic-ai/claude-code'];
3
5
  if (network === 'cn') {
@@ -6,4 +8,87 @@ function buildClaudeInstallCommand(network) {
6
8
  return { command: 'npm', args };
7
9
  }
8
10
 
9
- module.exports = { buildClaudeInstallCommand };
11
+ function checkNodeEnv() {
12
+ const nodeVersion = process.versions.node;
13
+ const nodeMajor = parseInt(nodeVersion.split('.')[0], 10);
14
+
15
+ let npmVersion = null;
16
+ try {
17
+ // Windows 上 npm 是 .cmd 文件,必须加 shell: true 才能找到
18
+ npmVersion = execSync('npm --version', {
19
+ encoding: 'utf8',
20
+ stdio: ['ignore', 'pipe', 'ignore'],
21
+ shell: process.platform === 'win32',
22
+ }).trim();
23
+ } catch {}
24
+
25
+ return {
26
+ nodeVersion,
27
+ nodeMajor,
28
+ nodeOk: nodeMajor >= 18,
29
+ npmVersion,
30
+ npmOk: !!npmVersion,
31
+ };
32
+ }
33
+
34
+ function getNodeInstallGuide() {
35
+ const platform = process.platform;
36
+ if (platform === 'darwin') {
37
+ return [
38
+ 'Homebrew: brew install node',
39
+ '官方安装包: https://nodejs.org (选 LTS 版本)',
40
+ ];
41
+ }
42
+ if (platform === 'win32') {
43
+ return [
44
+ '官方安装包: https://nodejs.org (选 LTS 版本)',
45
+ 'winget: winget install OpenJS.NodeJS.LTS',
46
+ ];
47
+ }
48
+ return [
49
+ 'Ubuntu/Debian: sudo apt install nodejs npm',
50
+ 'CentOS/RHEL: sudo yum install nodejs npm',
51
+ 'nvm(推荐): https://github.com/nvm-sh/nvm',
52
+ ];
53
+ }
54
+
55
+ /**
56
+ * 根据 spawnSync 结果判断失败原因,返回对应的提示内容(chalk 字符串数组)。
57
+ * @param {object} result spawnSync 返回值
58
+ * @param {Function} chalk chalk 实例
59
+ * @returns {string[]}
60
+ */
61
+ function getInstallFailureHints(result, chalk) {
62
+ // spawnSync 找不到命令(npm 在执行时消失或环境问题)
63
+ if (result.status === null && result.error?.code === 'ENOENT') {
64
+ return [
65
+ chalk.bold.red('npm 命令未找到\n\n'),
66
+ chalk.dim('安装 Node.js 后重试:\n'),
67
+ ...getNodeInstallGuide().map(l => chalk.cyan(' ' + l)),
68
+ ];
69
+ }
70
+
71
+ // 尝试从 stderr 判断权限错误(stdio inherit 时 stderr 为 null,兜底靠文字提示)
72
+ const stderr = result.stderr ? result.stderr.toString() : '';
73
+ if (stderr.includes('EACCES') || stderr.includes('permission denied') || stderr.includes('Access is denied')) {
74
+ const fixes = process.platform === 'win32'
75
+ ? ['以管理员身份运行 PowerShell / CMD,然后重试']
76
+ : [
77
+ 'sudo npm install -g @anthropic-ai/claude-code',
78
+ '或修复 npm 全局目录权限:https://docs.npmjs.com/resolving-eacces-permissions-errors',
79
+ ];
80
+ return [
81
+ chalk.bold.red('权限不足(EACCES)\n\n'),
82
+ ...fixes.map(l => chalk.cyan(' ' + l)),
83
+ ];
84
+ }
85
+
86
+ // 通用失败:显示手动安装命令
87
+ return [
88
+ chalk.bold('手动安装:\n\n'),
89
+ chalk.cyan('npm config set registry https://registry.npmmirror.com\n'),
90
+ chalk.cyan('npm install -g @anthropic-ai/claude-code'),
91
+ ];
92
+ }
93
+
94
+ module.exports = { buildClaudeInstallCommand, checkNodeEnv, getNodeInstallGuide, getInstallFailureHints };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "yingclaw",
3
- "version": "2.5.0",
3
+ "version": "2.5.1",
4
4
  "description": "Claude Code × 国产大模型一键接入:DeepSeek、Kimi、Qwen、MiniMax、GLM、MiMo",
5
5
  "main": "index.js",
6
6
  "bin": {