@lingyao037/openclaw-lingyao-cli 0.9.2 → 0.9.4

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 +97 -7
  2. package/package.json +1 -1
package/cli.mjs CHANGED
@@ -80,6 +80,7 @@ class LingyaoInstaller {
80
80
  this.channelId = 'lingyao';
81
81
  this.gatewayId = null;
82
82
  this.gatewayToken = null;
83
+ this.openclawCommand = null;
83
84
  }
84
85
 
85
86
  setOpenClawPath(path) {
@@ -111,7 +112,7 @@ class LingyaoInstaller {
111
112
  try {
112
113
  const result = spawnSync(command, args, {
113
114
  stdio: 'inherit',
114
- shell: true,
115
+ shell: false,
115
116
  ...options
116
117
  });
117
118
  return {
@@ -171,14 +172,39 @@ class LingyaoInstaller {
171
172
  return [];
172
173
  }
173
174
 
175
+ isNpxEphemeralOpenClawPath(commandPath) {
176
+ if (!commandPath || typeof commandPath !== 'string') return false;
177
+ const normalized = commandPath.replace(/\\/g, '/');
178
+ return normalized.includes('/.npm/_npx/') && normalized.includes('/node_modules/.bin/openclaw');
179
+ }
180
+
181
+ resolveOpenClawCommandPath() {
182
+ const commandPaths = this.getCommandPathCandidates();
183
+ if (commandPaths.length === 0) {
184
+ return null;
185
+ }
186
+
187
+ const nonEphemeral = commandPaths.filter((path) => !this.isNpxEphemeralOpenClawPath(path));
188
+ if (nonEphemeral.length > 0) {
189
+ return nonEphemeral[0];
190
+ }
191
+
192
+ return commandPaths[0];
193
+ }
194
+
174
195
  // 检查 OpenClaw 是否安装
175
196
  checkOpenClaw() {
176
197
  this.log('\n═══════════════════════════════════════════════════', CYAN);
177
198
  this.log(' 灵爻 (Lingyao) Plugin 安装器', CYAN);
178
199
  this.log('═══════════════════════════════════════════════════\n', CYAN);
179
200
 
201
+ this.openclawCommand = this.resolveOpenClawCommandPath() || 'openclaw';
202
+ if (this.openclawCommand !== 'openclaw') {
203
+ this.info(`使用 openclaw 命令: ${this.openclawCommand}`);
204
+ }
205
+
180
206
  // 检查 OpenClaw 命令
181
- const result = this.exec('openclaw', ['--version'], { stdio: 'pipe' });
207
+ const result = this.exec(this.openclawCommand, ['--version'], { stdio: 'pipe' });
182
208
 
183
209
  if (result.success) {
184
210
  this.success('OpenClaw 已安装');
@@ -391,7 +417,11 @@ class LingyaoInstaller {
391
417
  restartGateway() {
392
418
  this.log('\n正在重启 OpenClaw Gateway...\n');
393
419
 
394
- const result = this.exec('openclaw', ['gateway', 'restart']);
420
+ const command = this.openclawCommand || this.resolveOpenClawCommandPath() || 'openclaw';
421
+ if (command !== 'openclaw') {
422
+ this.info(`重启时使用命令: ${command}`);
423
+ }
424
+ const result = this.exec(command, ['gateway', 'restart']);
395
425
 
396
426
  if (result.success) {
397
427
  this.success('Gateway 重启成功');
@@ -448,7 +478,52 @@ class LingyaoInstaller {
448
478
  }
449
479
 
450
480
  // HTTP helpers
481
+ hasProxyEnv() {
482
+ return Boolean(
483
+ process.env.HTTPS_PROXY ||
484
+ process.env.https_proxy ||
485
+ process.env.HTTP_PROXY ||
486
+ process.env.http_proxy ||
487
+ process.env.ALL_PROXY ||
488
+ process.env.all_proxy
489
+ );
490
+ }
491
+
492
+ curlJson(method, path, body = null) {
493
+ return new Promise((resolve, reject) => {
494
+ const url = `${LINGYAO_API}${path}`;
495
+ const args = ['-sS', '-X', method, url, '-H', 'Content-Type: application/json'];
496
+ if (this.gatewayToken) {
497
+ args.push('-H', `Authorization: Bearer ${this.gatewayToken}`);
498
+ }
499
+ if (body !== null) {
500
+ args.push('-d', JSON.stringify(body));
501
+ }
502
+
503
+ const child = spawn('curl', args, { stdio: ['ignore', 'pipe', 'pipe'], shell: false });
504
+ let stdout = '';
505
+ let stderr = '';
506
+ child.stdout.on('data', (chunk) => { stdout += chunk.toString(); });
507
+ child.stderr.on('data', (chunk) => { stderr += chunk.toString(); });
508
+ child.on('error', (error) => reject(error));
509
+ child.on('close', (code) => {
510
+ if (code !== 0) {
511
+ reject(new Error(stderr.trim() || `curl exited with code ${code}`));
512
+ return;
513
+ }
514
+ try {
515
+ resolve(JSON.parse(stdout));
516
+ } catch {
517
+ reject(new Error(`Invalid JSON: ${stdout}`));
518
+ }
519
+ });
520
+ });
521
+ }
522
+
451
523
  httpsPost(path, body) {
524
+ if (this.hasProxyEnv()) {
525
+ return this.curlJson('POST', path, body);
526
+ }
452
527
  return new Promise((resolve, reject) => {
453
528
  const data = JSON.stringify(body);
454
529
  const url = `${LINGYAO_API}${path}`;
@@ -456,7 +531,7 @@ class LingyaoInstaller {
456
531
  if (this.gatewayToken) {
457
532
  headers['Authorization'] = `Bearer ${this.gatewayToken}`;
458
533
  }
459
- const req = https.request(url, { method: 'POST', headers }, (res) => {
534
+ const req = https.request(url, { method: 'POST', headers, timeout: 10000 }, (res) => {
460
535
  let chunk = '';
461
536
  res.on('data', (c) => chunk += c);
462
537
  res.on('end', () => {
@@ -464,6 +539,9 @@ class LingyaoInstaller {
464
539
  catch { reject(new Error(`Invalid JSON: ${chunk}`)); }
465
540
  });
466
541
  });
542
+ req.on('timeout', () => {
543
+ req.destroy(new Error('Request timeout while connecting to lingyao.live'));
544
+ });
467
545
  req.on('error', reject);
468
546
  req.write(data);
469
547
  req.end();
@@ -471,16 +549,23 @@ class LingyaoInstaller {
471
549
  }
472
550
 
473
551
  httpsGet(path) {
552
+ if (this.hasProxyEnv()) {
553
+ return this.curlJson('GET', path, null);
554
+ }
474
555
  return new Promise((resolve, reject) => {
475
556
  const url = `${LINGYAO_API}${path}`;
476
- https.get(url, (res) => {
557
+ const req = https.get(url, { timeout: 10000 }, (res) => {
477
558
  let chunk = '';
478
559
  res.on('data', (c) => chunk += c);
479
560
  res.on('end', () => {
480
561
  try { resolve(JSON.parse(chunk)); }
481
562
  catch { reject(new Error(`Invalid JSON: ${chunk}`)); }
482
563
  });
483
- }).on('error', reject);
564
+ });
565
+ req.on('timeout', () => {
566
+ req.destroy(new Error('Request timeout while connecting to lingyao.live'));
567
+ });
568
+ req.on('error', reject);
484
569
  });
485
570
  }
486
571
 
@@ -585,6 +670,10 @@ class LingyaoInstaller {
585
670
 
586
671
  } catch (error) {
587
672
  this.error(`配对失败: ${error.message}`);
673
+ this.warn('网络诊断建议:');
674
+ this.log(' 1) curl -I https://api.lingyao.live/lyoc/health');
675
+ this.log(' 2) nslookup api.lingyao.live');
676
+ this.log(' 3) 如在公司网络/代理环境,请检查 TLS 拦截或防火墙策略');
588
677
  return false;
589
678
  }
590
679
  }
@@ -720,7 +809,8 @@ class LingyaoInstaller {
720
809
 
721
810
  // 重启网关
722
811
  this.log('\n重启 OpenClaw Gateway...');
723
- this.exec('openclaw', ['gateway', 'restart']);
812
+ const command = this.openclawCommand || this.resolveOpenClawCommandPath() || 'openclaw';
813
+ this.exec(command, ['gateway', 'restart']);
724
814
 
725
815
  this.success('\n✓ 卸载完成!\n');
726
816
  return true;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lingyao037/openclaw-lingyao-cli",
3
- "version": "0.9.2",
3
+ "version": "0.9.4",
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",