@lingyao037/openclaw-lingyao-cli 0.3.1 → 0.3.2

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 (2) hide show
  1. package/cli.mjs +96 -86
  2. package/package.json +1 -1
package/cli.mjs CHANGED
@@ -2,7 +2,7 @@
2
2
  /**
3
3
  * Lingyao Plugin One-Line Installer
4
4
  *
5
- * 一行命令安装灵尧 Channel Plugin 到 OpenClaw
5
+ * 一行命令安装灵爻 Channel Plugin 到 OpenClaw
6
6
  *
7
7
  * 使用方法:
8
8
  * npx -y @lingyao/openclaw-lingyao-cli install
@@ -27,9 +27,10 @@ const CYAN = '\x1b[36m';
27
27
  const NC = '\x1b[0m';
28
28
 
29
29
  class LingyaoInstaller {
30
- constructor(customPath = null) {
30
+ constructor(customPath = null, skipDeps = false) {
31
31
  this.openclawPath = null;
32
32
  this.customPath = customPath;
33
+ this.skipDeps = skipDeps;
33
34
  this.pluginName = '@lingyao/openclaw-lingyao-cli';
34
35
  this.channelId = 'lingyao';
35
36
  }
@@ -79,10 +80,54 @@ class LingyaoInstaller {
79
80
  }
80
81
  }
81
82
 
83
+ getHomeCandidates() {
84
+ const values = [
85
+ process.env.HOME,
86
+ process.env.USERPROFILE,
87
+ process.env.LOCALAPPDATA,
88
+ process.env.APPDATA
89
+ ].filter((value, index, array) => typeof value === 'string' && value.length > 0 && array.indexOf(value) === index);
90
+
91
+ return values;
92
+ }
93
+
94
+ getOpenClawSearchPaths() {
95
+ const candidates = [];
96
+ for (const home of this.getHomeCandidates()) {
97
+ candidates.push(join(home, '.openclaw'));
98
+ candidates.push(join(home, 'openclaw'));
99
+ candidates.push(join(home, 'Dev', 'openclaw'));
100
+ }
101
+
102
+ candidates.push('/usr/local/lib/openclaw');
103
+ candidates.push('./openclaw');
104
+
105
+ return candidates.filter((value, index, array) => array.indexOf(value) === index);
106
+ }
107
+
108
+ getCommandPathCandidates() {
109
+ const commands = process.platform === 'win32'
110
+ ? ['where openclaw']
111
+ : ['command -v openclaw', 'which openclaw'];
112
+
113
+ for (const command of commands) {
114
+ try {
115
+ const output = execSync(command, { encoding: 'utf-8' }).trim();
116
+ if (output) {
117
+ return output.split(/\r?\n/).filter(Boolean);
118
+ }
119
+ } catch {
120
+ // Ignore and try next resolver.
121
+ }
122
+ }
123
+
124
+ return [];
125
+ }
126
+
82
127
  // 检查 OpenClaw 是否安装
83
128
  checkOpenClaw() {
84
129
  this.log('\n═══════════════════════════════════════════════════', CYAN);
85
- this.log(' 灵尧 (Lingyao) Plugin 安装器', CYAN);
130
+ this.log(' 灵爻 (Lingyao) Plugin 安装器', CYAN);
86
131
  this.log('═══════════════════════════════════════════════════\n', CYAN);
87
132
 
88
133
  // 检查 OpenClaw 命令
@@ -114,60 +159,12 @@ class LingyaoInstaller {
114
159
  }
115
160
  }
116
161
 
117
- // 使用 which/command -v 查找 OpenClaw 命令
118
- try {
119
- let openclawPath = null;
120
-
121
- // 尝试 command -v (POSIX 标准)
122
- try {
123
- openclawPath = execSync('command -v openclaw', { encoding: 'utf-8' }).trim();
124
- } catch {
125
- // 降级到 which
126
- try {
127
- openclawPath = execSync('which openclaw', { encoding: 'utf-8' }).trim();
128
- } catch {
129
- // 命令不存在,继续手动搜索
130
- }
131
- }
132
-
133
- if (openclawPath) {
134
- this.info(`找到 openclaw 命令: ${openclawPath}`);
135
-
136
- // 尝试从命令路径推导项目目录
137
- // npm 全局安装: ~/.nvm/versions/node/vX.X.X/bin/openclaw
138
- // 项目目录通常在: ~/.openclaw 或 ~/openclaw
139
- const searchPaths = [
140
- process.env.HOME ? `${process.env.HOME}/.openclaw` : null,
141
- process.env.HOME ? `${process.env.HOME}/openclaw` : null,
142
- process.env.HOME ? `${process.env.HOME}/Dev/openclaw` : null,
143
- '/usr/local/lib/openclaw',
144
- './openclaw'
145
- ].filter(p => p !== null);
146
-
147
- for (const path of searchPaths) {
148
- if (existsSync(path)) {
149
- if (existsSync(join(path, 'openclaw.json')) ||
150
- existsSync(join(path, 'config.json'))) {
151
- this.openclawPath = path;
152
- this.success(`找到 OpenClaw: ${path}`);
153
- return path;
154
- }
155
- }
156
- }
157
- }
158
- } catch (error) {
159
- // 出错时继续手动搜索
162
+ const commandPaths = this.getCommandPathCandidates();
163
+ if (commandPaths.length > 0) {
164
+ this.info(`找到 openclaw 命令: ${commandPaths[0]}`);
160
165
  }
161
166
 
162
- // 手动搜索(降级方案)
163
- const fallbackPaths = [
164
- process.env.HOME ? `${process.env.HOME}/openclaw` : null,
165
- process.env.HOME ? `${process.env.HOME}/Dev/openclaw` : null,
166
- '/usr/local/lib/openclaw',
167
- './openclaw'
168
- ].filter(p => p !== null);
169
-
170
- for (const path of fallbackPaths) {
167
+ for (const path of this.getOpenClawSearchPaths()) {
171
168
  if (existsSync(path)) {
172
169
  if (existsSync(join(path, 'openclaw.json')) ||
173
170
  existsSync(join(path, 'config.json'))) {
@@ -183,20 +180,8 @@ class LingyaoInstaller {
183
180
 
184
181
  // 安装插件
185
182
  installPlugin() {
186
- this.log('\n正在安装灵尧插件...');
187
-
188
- // 使用 OpenClaw CLI 安装插件
189
- const result = this.exec('openclaw', ['plugins', 'install', '.'], {
190
- cwd: __dirname
191
- });
192
-
193
- if (result.success) {
194
- this.success('插件安装成功');
195
- return true;
196
- }
197
-
198
- // 如果 CLI 安装失败,尝试手动复制到本地 OpenClaw
199
- this.warn('CLI 安装失败,尝试手动安装...');
183
+ this.log('\n正在安装灵爻插件...');
184
+ this.info('使用兼容安装模式,直接部署插件文件到 OpenClaw 目录');
200
185
  return this.manualInstall();
201
186
  }
202
187
 
@@ -222,12 +207,11 @@ class LingyaoInstaller {
222
207
 
223
208
  // 复制所有必要的文件
224
209
  const filesToCopy = [
225
- 'index.ts',
210
+ 'dist',
226
211
  'openclaw.plugin.json',
227
212
  'package.json',
228
- 'tsconfig.json',
229
- 'tsup.config.ts',
230
- 'src/'
213
+ 'package-lock.json',
214
+ 'README.md'
231
215
  ];
232
216
 
233
217
  for (const file of filesToCopy) {
@@ -242,6 +226,21 @@ class LingyaoInstaller {
242
226
  }
243
227
  }
244
228
 
229
+ // 从 npx/npm 临时目录一起复制运行时依赖,避免目标 Gateway 再执行一次安装。
230
+ const runtimeModulesPath = join(__dirname, 'node_modules');
231
+ if (existsSync(runtimeModulesPath) && statSync(runtimeModulesPath).isDirectory()) {
232
+ if (!this.skipDeps) {
233
+ this.log('复制运行时依赖...');
234
+ this.copyDirectory(runtimeModulesPath, join(targetDir, 'node_modules'));
235
+ } else {
236
+ this.info('跳过复制运行时依赖 (--no-deps)');
237
+ }
238
+ } else {
239
+ if (!this.skipDeps) {
240
+ this.warn('未找到本地 node_modules,目标 OpenClaw 可能仍需自行安装依赖');
241
+ }
242
+ }
243
+
245
244
  this.success('插件文件复制成功');
246
245
  } catch (error) {
247
246
  this.error(`复制失败: ${error.message}`);
@@ -346,7 +345,9 @@ class LingyaoInstaller {
346
345
  return true;
347
346
  }
348
347
 
349
- this.error('Gateway 重启失败,请手动重启:');
348
+ this.warn('Gateway 自动重启失败,插件文件和配置已经写入');
349
+ this.log('可能是当前 OpenClaw CLI 自身依赖不完整,而不是灵尧插件缺少依赖。');
350
+ this.log('请在修复 OpenClaw CLI 后手动重启:');
350
351
  this.log(' openclaw gateway restart');
351
352
  return false;
352
353
  }
@@ -357,14 +358,14 @@ class LingyaoInstaller {
357
358
  this.log(' 安装完成!', CYAN);
358
359
  this.log('═══════════════════════════════════════════════════\n', CYAN);
359
360
 
360
- this.success('灵尧 Plugin 已成功安装到 OpenClaw!\n');
361
+ this.success('灵爻 Plugin 已成功安装到 OpenClaw!\n');
361
362
 
362
363
  this.info('快速开始:');
363
364
  this.log('');
364
365
  this.log(' # 查看插件状态');
365
366
  this.log(' openclaw plugins list');
366
367
  this.log('');
367
- this.log(' # 查看灵尧通道状态');
368
+ this.log(' # 查看灵爻通道状态');
368
369
  this.log(' openclaw channels status --channel lingyao');
369
370
  this.log('');
370
371
  this.log(' # 查看收到的消息');
@@ -383,12 +384,12 @@ class LingyaoInstaller {
383
384
  this.log('');
384
385
 
385
386
  this.info('架构说明:');
386
- this.log(' 灵尧 App → lingyao.live → OpenClaw Gateway');
387
- this.log(' Agent → OpenClaw Gateway → lingyao.live → 灵尧 App');
387
+ this.log(' 灵爻 App → lingyao.live → OpenClaw Gateway');
388
+ this.log(' Agent → OpenClaw Gateway → lingyao.live → 灵爻 App');
388
389
  this.log('');
389
390
 
390
391
  this.info('文档:');
391
- this.log(' • 完整测试指南: TESTING.md');
392
+ this.log(' • 安装说明: INSTALL.md');
392
393
  this.log(' • API 文档: README.md');
393
394
  this.log('');
394
395
  }
@@ -412,13 +413,15 @@ class LingyaoInstaller {
412
413
  }
413
414
 
414
415
  // 步骤 4: 重启网关
415
- if (!this.restartGateway()) {
416
- return false;
417
- }
416
+ const restarted = this.restartGateway();
418
417
 
419
418
  // 步骤 5: 显示说明
420
419
  this.showInstructions();
421
420
 
421
+ if (!restarted) {
422
+ this.warn('安装已完成,但需要你在 OpenClaw CLI 可用后手动重启 Gateway。');
423
+ }
424
+
422
425
  return true;
423
426
 
424
427
  } catch (error) {
@@ -430,7 +433,7 @@ class LingyaoInstaller {
430
433
  // 卸载插件
431
434
  async uninstall() {
432
435
  try {
433
- this.log('\n正在卸载灵尧插件...\n');
436
+ this.log('\n正在卸载灵爻插件...\n');
434
437
 
435
438
  const openclawPath = this.findOpenClawPath();
436
439
  if (!openclawPath) {
@@ -520,7 +523,7 @@ class LingyaoInstaller {
520
523
  return false;
521
524
  }
522
525
 
523
- this.success('\n插件已安装,请手动重启 OpenClaw Gateway:');
526
+ this.success('\n插件已安装,请在 OpenClaw CLI 可用后手动重启 Gateway:');
524
527
  this.log(' openclaw gateway restart\n');
525
528
  return true;
526
529
 
@@ -537,17 +540,20 @@ async function main() {
537
540
  const args = process.argv.slice(2);
538
541
  let command = 'install';
539
542
  let customPath = null;
543
+ let skipDeps = false;
540
544
 
541
545
  for (let i = 0; i < args.length; i++) {
542
546
  if (args[i] === '--path' && i + 1 < args.length) {
543
547
  customPath = args[i + 1];
544
548
  i++; // 跳过路径参数
549
+ } else if (args[i] === '--no-deps') {
550
+ skipDeps = true;
545
551
  } else if (!args[i].startsWith('--')) {
546
552
  command = args[i];
547
553
  }
548
554
  }
549
555
 
550
- const installer = new LingyaoInstaller(customPath);
556
+ const installer = new LingyaoInstaller(customPath, skipDeps);
551
557
 
552
558
  if (command === 'install') {
553
559
  const success = await installer.install();
@@ -563,7 +569,7 @@ async function main() {
563
569
 
564
570
  } else if (command === 'help') {
565
571
  console.log(`
566
- 灵尧 Plugin 一键安装器
572
+ 灵爻 Plugin 一键安装器
567
573
 
568
574
  使用方法:
569
575
  node cli.mjs install # 完整安装(包含配对和重启)
@@ -573,6 +579,7 @@ async function main() {
573
579
 
574
580
  参数:
575
581
  --path <目录> # 指定 OpenClaw 安装目录
582
+ --no-deps # 跳过复制 node_modules (解决依赖冲突)
576
583
 
577
584
  环境要求:
578
585
  • Node.js >= 22
@@ -582,6 +589,9 @@ async function main() {
582
589
  # 从 npm 安装(推荐)
583
590
  npx -y @lingyao/openclaw-lingyao-cli install
584
591
 
592
+ # 跳过复制 node_modules (如遇到 @anthropic-ai/vertex-sdk 缺失等报错)
593
+ npx -y @lingyao/openclaw-lingyao-cli install --no-deps
594
+
585
595
  # 从 npm 卸载
586
596
  npx -y @lingyao/openclaw-lingyao-cli uninstall
587
597
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lingyao037/openclaw-lingyao-cli",
3
- "version": "0.3.1",
3
+ "version": "0.3.2",
4
4
  "description": "Lingyao Channel Plugin for OpenClaw - bidirectional sync via lingyao.live server relay",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",