@lingyao037/openclaw-lingyao-cli 0.3.0-alpha.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/README.md +325 -0
- package/cli.mjs +609 -0
- package/dist/accounts-Bkwmg14Q.d.ts +325 -0
- package/dist/cli.d.ts +175 -0
- package/dist/cli.js +181 -0
- package/dist/cli.js.map +1 -0
- package/dist/index.d.ts +1229 -0
- package/dist/index.js +3332 -0
- package/dist/index.js.map +1 -0
- package/openclaw.plugin.json +53 -0
- package/package.json +62 -0
package/cli.mjs
ADDED
|
@@ -0,0 +1,609 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Lingyao Plugin One-Line Installer
|
|
4
|
+
*
|
|
5
|
+
* 一行命令安装灵尧 Channel Plugin 到 OpenClaw
|
|
6
|
+
*
|
|
7
|
+
* 使用方法:
|
|
8
|
+
* npx -y @lingyao/openclaw-lingyao-cli install
|
|
9
|
+
*
|
|
10
|
+
* 或者本地测试:
|
|
11
|
+
* node cli.mjs install
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
import { spawnSync, spawn, execSync } from 'child_process';
|
|
15
|
+
import { existsSync, readFileSync, writeFileSync, mkdirSync, copyFileSync, readdirSync, statSync } from 'fs';
|
|
16
|
+
import { join, dirname } from 'path';
|
|
17
|
+
import { fileURLToPath } from 'url';
|
|
18
|
+
|
|
19
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
20
|
+
const __dirname = dirname(__filename);
|
|
21
|
+
|
|
22
|
+
// 颜色
|
|
23
|
+
const GREEN = '\x1b[32m';
|
|
24
|
+
const YELLOW = '\x1b[33m';
|
|
25
|
+
const RED = '\x1b[31m';
|
|
26
|
+
const CYAN = '\x1b[36m';
|
|
27
|
+
const NC = '\x1b[0m';
|
|
28
|
+
|
|
29
|
+
class LingyaoInstaller {
|
|
30
|
+
constructor(customPath = null) {
|
|
31
|
+
this.openclawPath = null;
|
|
32
|
+
this.customPath = customPath;
|
|
33
|
+
this.pluginName = '@lingyao/openclaw-lingyao-cli';
|
|
34
|
+
this.channelId = 'lingyao';
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
setOpenClawPath(path) {
|
|
38
|
+
this.customPath = path;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
log(message, color = NC) {
|
|
42
|
+
console.log(`${color}${message}${NC}`);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
error(message) {
|
|
46
|
+
this.log(`✗ ${message}`, RED);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
success(message) {
|
|
50
|
+
this.log(`✓ ${message}`, GREEN);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
info(message) {
|
|
54
|
+
this.log(`ℹ ${message}`, CYAN);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
warn(message) {
|
|
58
|
+
this.log(`⚠ ${message}`, YELLOW);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// 执行命令并返回结果
|
|
62
|
+
exec(command, args = [], options = {}) {
|
|
63
|
+
try {
|
|
64
|
+
const result = spawnSync(command, args, {
|
|
65
|
+
stdio: 'inherit',
|
|
66
|
+
shell: true,
|
|
67
|
+
...options
|
|
68
|
+
});
|
|
69
|
+
return {
|
|
70
|
+
success: result.status === 0,
|
|
71
|
+
status: result.status,
|
|
72
|
+
error: result.error
|
|
73
|
+
};
|
|
74
|
+
} catch (error) {
|
|
75
|
+
return {
|
|
76
|
+
success: false,
|
|
77
|
+
error
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// 检查 OpenClaw 是否安装
|
|
83
|
+
checkOpenClaw() {
|
|
84
|
+
this.log('\n═══════════════════════════════════════════════════', CYAN);
|
|
85
|
+
this.log(' 灵尧 (Lingyao) Plugin 安装器', CYAN);
|
|
86
|
+
this.log('═══════════════════════════════════════════════════\n', CYAN);
|
|
87
|
+
|
|
88
|
+
// 检查 OpenClaw 命令
|
|
89
|
+
const result = this.exec('openclaw', ['--version'], { stdio: 'pipe' });
|
|
90
|
+
|
|
91
|
+
if (result.success) {
|
|
92
|
+
this.success('OpenClaw 已安装');
|
|
93
|
+
return true;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
this.error('OpenClaw 未安装');
|
|
97
|
+
this.info('\n请先安装 OpenClaw:');
|
|
98
|
+
console.log(' npm install -g openclaw');
|
|
99
|
+
console.log(' 或访问: https://docs.openclaw.ai/install\n');
|
|
100
|
+
return false;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
// 查找 OpenClaw 目录
|
|
104
|
+
findOpenClawPath() {
|
|
105
|
+
// 如果指定了自定义路径,优先使用
|
|
106
|
+
if (this.customPath) {
|
|
107
|
+
if (existsSync(this.customPath)) {
|
|
108
|
+
this.openclawPath = this.customPath;
|
|
109
|
+
this.success(`使用指定路径: ${this.customPath}`);
|
|
110
|
+
return this.customPath;
|
|
111
|
+
} else {
|
|
112
|
+
this.error(`指定的路径不存在: ${this.customPath}`);
|
|
113
|
+
return null;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
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
|
+
// 出错时继续手动搜索
|
|
160
|
+
}
|
|
161
|
+
|
|
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) {
|
|
171
|
+
if (existsSync(path)) {
|
|
172
|
+
if (existsSync(join(path, 'openclaw.json')) ||
|
|
173
|
+
existsSync(join(path, 'config.json'))) {
|
|
174
|
+
this.openclawPath = path;
|
|
175
|
+
this.success(`找到 OpenClaw: ${path}`);
|
|
176
|
+
return path;
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
return null;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
// 安装插件
|
|
185
|
+
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 安装失败,尝试手动安装...');
|
|
200
|
+
return this.manualInstall();
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
// 手动安装
|
|
204
|
+
manualInstall() {
|
|
205
|
+
const openclawPath = this.findOpenClawPath();
|
|
206
|
+
|
|
207
|
+
if (!openclawPath) {
|
|
208
|
+
this.error('无法找到 OpenClaw 安装目录');
|
|
209
|
+
this.info('\n请指定 OpenClaw 安装路径:');
|
|
210
|
+
console.log(' node cli.mjs install /path/to/openclaw\n');
|
|
211
|
+
return false;
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
const targetDir = join(openclawPath, 'extensions', 'lingyao');
|
|
215
|
+
|
|
216
|
+
// 复制插件文件
|
|
217
|
+
this.log(`复制插件到: ${targetDir}`);
|
|
218
|
+
|
|
219
|
+
// 创建目标目录
|
|
220
|
+
try {
|
|
221
|
+
mkdirSync(targetDir, { recursive: true });
|
|
222
|
+
|
|
223
|
+
// 复制所有必要的文件
|
|
224
|
+
const filesToCopy = [
|
|
225
|
+
'index.ts',
|
|
226
|
+
'openclaw.plugin.json',
|
|
227
|
+
'package.json',
|
|
228
|
+
'tsconfig.json',
|
|
229
|
+
'tsup.config.ts',
|
|
230
|
+
'src/'
|
|
231
|
+
];
|
|
232
|
+
|
|
233
|
+
for (const file of filesToCopy) {
|
|
234
|
+
const srcPath = join(__dirname, file);
|
|
235
|
+
const destPath = join(targetDir, file);
|
|
236
|
+
if (existsSync(srcPath)) {
|
|
237
|
+
if (statSync(srcPath).isDirectory()) {
|
|
238
|
+
this.copyDirectory(srcPath, destPath);
|
|
239
|
+
} else {
|
|
240
|
+
copyFileSync(srcPath, destPath);
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
this.success('插件文件复制成功');
|
|
246
|
+
} catch (error) {
|
|
247
|
+
this.error(`复制失败: ${error.message}`);
|
|
248
|
+
return false;
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
return true;
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
// 递归复制目录
|
|
255
|
+
copyDirectory(src, dest) {
|
|
256
|
+
mkdirSync(dest, { recursive: true });
|
|
257
|
+
|
|
258
|
+
for (const entry of readdirSync(src, { withFileTypes: true })) {
|
|
259
|
+
const srcPath = join(src, entry.name);
|
|
260
|
+
const destPath = join(dest, entry.name);
|
|
261
|
+
|
|
262
|
+
if (entry.isDirectory()) {
|
|
263
|
+
this.copyDirectory(srcPath, destPath);
|
|
264
|
+
} else {
|
|
265
|
+
copyFileSync(srcPath, destPath);
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
// 配置插件
|
|
271
|
+
configurePlugin() {
|
|
272
|
+
this.log('\n配置插件...');
|
|
273
|
+
|
|
274
|
+
const openclawPath = this.findOpenClawPath();
|
|
275
|
+
if (!openclawPath) {
|
|
276
|
+
this.error('无法找到 OpenClaw 配置目录');
|
|
277
|
+
return false;
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
const configFiles = [
|
|
281
|
+
join(openclawPath, 'openclaw.json'),
|
|
282
|
+
join(openclawPath, 'config.json')
|
|
283
|
+
];
|
|
284
|
+
|
|
285
|
+
let configFile = null;
|
|
286
|
+
for (const file of configFiles) {
|
|
287
|
+
if (existsSync(file)) {
|
|
288
|
+
configFile = file;
|
|
289
|
+
break;
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
if (!configFile) {
|
|
294
|
+
this.error('找不到 OpenClaw 配置文件');
|
|
295
|
+
return false;
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
let config = {};
|
|
299
|
+
try {
|
|
300
|
+
config = JSON.parse(readFileSync(configFile, 'utf-8'));
|
|
301
|
+
} catch (e) {
|
|
302
|
+
this.warn(`无法解析配置文件,将创建新配置`);
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
// 添加插件配置
|
|
306
|
+
if (!config.plugins) config.plugins = {};
|
|
307
|
+
if (!config.plugins.entries) config.plugins.entries = {};
|
|
308
|
+
|
|
309
|
+
// 添加 lingyao 到加载路径
|
|
310
|
+
if (!config.plugins.load) config.plugins.load = {};
|
|
311
|
+
if (!config.plugins.load.paths) config.plugins.load.paths = [];
|
|
312
|
+
|
|
313
|
+
const pluginPath = join(openclawPath, 'extensions', 'lingyao');
|
|
314
|
+
if (!config.plugins.load.paths.includes(pluginPath)) {
|
|
315
|
+
config.plugins.load.paths.push(pluginPath);
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
// 启用 lingyao 插件(serverUrl 已内置,用户不可配置)
|
|
319
|
+
config.plugins.entries.lingyao = {
|
|
320
|
+
enabled: true,
|
|
321
|
+
config: {
|
|
322
|
+
maxOfflineMessages: 100,
|
|
323
|
+
tokenExpiryDays: 30
|
|
324
|
+
}
|
|
325
|
+
};
|
|
326
|
+
|
|
327
|
+
// 写回配置文件
|
|
328
|
+
try {
|
|
329
|
+
writeFileSync(configFile, JSON.stringify(config, null, 2), 'utf-8');
|
|
330
|
+
this.success('插件配置已更新');
|
|
331
|
+
return true;
|
|
332
|
+
} catch (e) {
|
|
333
|
+
this.error(`配置写入失败: ${e.message}`);
|
|
334
|
+
return false;
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
// 重启网关
|
|
339
|
+
restartGateway() {
|
|
340
|
+
this.log('\n正在重启 OpenClaw Gateway...\n');
|
|
341
|
+
|
|
342
|
+
const result = this.exec('openclaw', ['gateway', 'restart']);
|
|
343
|
+
|
|
344
|
+
if (result.success) {
|
|
345
|
+
this.success('Gateway 重启成功');
|
|
346
|
+
return true;
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
this.error('Gateway 重启失败,请手动重启:');
|
|
350
|
+
this.log(' openclaw gateway restart');
|
|
351
|
+
return false;
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
// 显示使用说明
|
|
355
|
+
showInstructions() {
|
|
356
|
+
this.log('\n═══════════════════════════════════════════════════', CYAN);
|
|
357
|
+
this.log(' 安装完成!', CYAN);
|
|
358
|
+
this.log('═══════════════════════════════════════════════════\n', CYAN);
|
|
359
|
+
|
|
360
|
+
this.success('灵尧 Plugin 已成功安装到 OpenClaw!\n');
|
|
361
|
+
|
|
362
|
+
this.info('快速开始:');
|
|
363
|
+
this.log('');
|
|
364
|
+
this.log(' # 查看插件状态');
|
|
365
|
+
this.log(' openclaw plugins list');
|
|
366
|
+
this.log('');
|
|
367
|
+
this.log(' # 查看灵尧通道状态');
|
|
368
|
+
this.log(' openclaw channels status --channel lingyao');
|
|
369
|
+
this.log('');
|
|
370
|
+
this.log(' # 查看收到的消息');
|
|
371
|
+
this.log(' openclaw channels logs --channel lingyao');
|
|
372
|
+
this.log('');
|
|
373
|
+
|
|
374
|
+
this.info('测试插件:');
|
|
375
|
+
this.log(' # 发送测试消息');
|
|
376
|
+
this.log(' openclaw channels send --channel lingyao "Hello from OpenClaw!"');
|
|
377
|
+
this.log('');
|
|
378
|
+
|
|
379
|
+
this.warn('注意事项:');
|
|
380
|
+
this.log(' • 确保 OpenClaw Gateway 正在运行');
|
|
381
|
+
this.log(' • 需要可访问的 lingyao.live 中转服务');
|
|
382
|
+
this.log(' • 配对与设备接入通过灵爻 App 和中转服务完成');
|
|
383
|
+
this.log('');
|
|
384
|
+
|
|
385
|
+
this.info('架构说明:');
|
|
386
|
+
this.log(' 灵尧 App → lingyao.live → OpenClaw Gateway');
|
|
387
|
+
this.log(' Agent → OpenClaw Gateway → lingyao.live → 灵尧 App');
|
|
388
|
+
this.log('');
|
|
389
|
+
|
|
390
|
+
this.info('文档:');
|
|
391
|
+
this.log(' • 完整测试指南: TESTING.md');
|
|
392
|
+
this.log(' • API 文档: README.md');
|
|
393
|
+
this.log('');
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
// 主安装流程
|
|
397
|
+
async install() {
|
|
398
|
+
try {
|
|
399
|
+
// 步骤 1: 检查 OpenClaw
|
|
400
|
+
if (!this.checkOpenClaw()) {
|
|
401
|
+
return false;
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
// 步骤 2: 安装插件
|
|
405
|
+
if (!this.installPlugin()) {
|
|
406
|
+
return false;
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
// 步骤 3: 配置插件
|
|
410
|
+
if (!this.configurePlugin()) {
|
|
411
|
+
return false;
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
// 步骤 4: 重启网关
|
|
415
|
+
if (!this.restartGateway()) {
|
|
416
|
+
return false;
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
// 步骤 5: 显示说明
|
|
420
|
+
this.showInstructions();
|
|
421
|
+
|
|
422
|
+
return true;
|
|
423
|
+
|
|
424
|
+
} catch (error) {
|
|
425
|
+
this.error(`安装失败: ${error.message}`);
|
|
426
|
+
return false;
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
// 卸载插件
|
|
431
|
+
async uninstall() {
|
|
432
|
+
try {
|
|
433
|
+
this.log('\n正在卸载灵尧插件...\n');
|
|
434
|
+
|
|
435
|
+
const openclawPath = this.findOpenClawPath();
|
|
436
|
+
if (!openclawPath) {
|
|
437
|
+
this.error('无法找到 OpenClaw 安装目录');
|
|
438
|
+
return false;
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
const targetDir = join(openclawPath, 'extensions', 'lingyao');
|
|
442
|
+
|
|
443
|
+
// 检查是否安装
|
|
444
|
+
if (!existsSync(targetDir)) {
|
|
445
|
+
this.warn('插件未安装');
|
|
446
|
+
return true;
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
// 删除插件目录
|
|
450
|
+
this.log(`删除插件目录: ${targetDir}`);
|
|
451
|
+
const fs = await import('fs');
|
|
452
|
+
fs.rmSync(targetDir, { recursive: true, force: true });
|
|
453
|
+
|
|
454
|
+
this.success('插件已删除');
|
|
455
|
+
|
|
456
|
+
// 更新配置文件
|
|
457
|
+
this.log('\n更新 OpenClaw 配置...');
|
|
458
|
+
const configFiles = [
|
|
459
|
+
join(openclawPath, 'openclaw.json'),
|
|
460
|
+
join(openclawPath, 'config.json')
|
|
461
|
+
];
|
|
462
|
+
|
|
463
|
+
let configFile = null;
|
|
464
|
+
for (const file of configFiles) {
|
|
465
|
+
if (existsSync(file)) {
|
|
466
|
+
configFile = file;
|
|
467
|
+
break;
|
|
468
|
+
}
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
if (configFile) {
|
|
472
|
+
let config = {};
|
|
473
|
+
try {
|
|
474
|
+
config = JSON.parse(readFileSync(configFile, 'utf-8'));
|
|
475
|
+
|
|
476
|
+
// 移除插件配置
|
|
477
|
+
if (config.plugins?.entries?.lingyao) {
|
|
478
|
+
delete config.plugins.entries.lingyao;
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
// 移除加载路径
|
|
482
|
+
if (config.plugins?.load?.paths) {
|
|
483
|
+
config.plugins.load.paths = config.plugins.load.paths.filter(
|
|
484
|
+
(p) => !p.includes('lingyao')
|
|
485
|
+
);
|
|
486
|
+
}
|
|
487
|
+
|
|
488
|
+
writeFileSync(configFile, JSON.stringify(config, null, 2), 'utf-8');
|
|
489
|
+
this.success('配置已更新');
|
|
490
|
+
} catch (e) {
|
|
491
|
+
this.warn(`配置更新失败: ${e.message}`);
|
|
492
|
+
}
|
|
493
|
+
}
|
|
494
|
+
|
|
495
|
+
// 重启网关
|
|
496
|
+
this.log('\n重启 OpenClaw Gateway...');
|
|
497
|
+
this.exec('openclaw', ['gateway', 'restart']);
|
|
498
|
+
|
|
499
|
+
this.success('\n✓ 卸载完成!\n');
|
|
500
|
+
return true;
|
|
501
|
+
|
|
502
|
+
} catch (error) {
|
|
503
|
+
this.error(`卸载失败: ${error.message}`);
|
|
504
|
+
return false;
|
|
505
|
+
}
|
|
506
|
+
}
|
|
507
|
+
|
|
508
|
+
// 仅安装(不重启网关,不配对)
|
|
509
|
+
async installOnly() {
|
|
510
|
+
try {
|
|
511
|
+
if (!this.checkOpenClaw()) {
|
|
512
|
+
return false;
|
|
513
|
+
}
|
|
514
|
+
|
|
515
|
+
if (!this.installPlugin()) {
|
|
516
|
+
return false;
|
|
517
|
+
}
|
|
518
|
+
|
|
519
|
+
if (!this.configurePlugin()) {
|
|
520
|
+
return false;
|
|
521
|
+
}
|
|
522
|
+
|
|
523
|
+
this.success('\n插件已安装,请手动重启 OpenClaw Gateway:');
|
|
524
|
+
this.log(' openclaw gateway restart\n');
|
|
525
|
+
return true;
|
|
526
|
+
|
|
527
|
+
} catch (error) {
|
|
528
|
+
this.error(`安装失败: ${error.message}`);
|
|
529
|
+
return false;
|
|
530
|
+
}
|
|
531
|
+
}
|
|
532
|
+
}
|
|
533
|
+
|
|
534
|
+
// 主函数
|
|
535
|
+
async function main() {
|
|
536
|
+
// 解析参数
|
|
537
|
+
const args = process.argv.slice(2);
|
|
538
|
+
let command = 'install';
|
|
539
|
+
let customPath = null;
|
|
540
|
+
|
|
541
|
+
for (let i = 0; i < args.length; i++) {
|
|
542
|
+
if (args[i] === '--path' && i + 1 < args.length) {
|
|
543
|
+
customPath = args[i + 1];
|
|
544
|
+
i++; // 跳过路径参数
|
|
545
|
+
} else if (!args[i].startsWith('--')) {
|
|
546
|
+
command = args[i];
|
|
547
|
+
}
|
|
548
|
+
}
|
|
549
|
+
|
|
550
|
+
const installer = new LingyaoInstaller(customPath);
|
|
551
|
+
|
|
552
|
+
if (command === 'install') {
|
|
553
|
+
const success = await installer.install();
|
|
554
|
+
process.exit(success ? 0 : 1);
|
|
555
|
+
|
|
556
|
+
} else if (command === 'install-only') {
|
|
557
|
+
const success = await installer.installOnly();
|
|
558
|
+
process.exit(success ? 0 : 1);
|
|
559
|
+
|
|
560
|
+
} else if (command === 'uninstall') {
|
|
561
|
+
const success = await installer.uninstall();
|
|
562
|
+
process.exit(success ? 0 : 1);
|
|
563
|
+
|
|
564
|
+
} else if (command === 'help') {
|
|
565
|
+
console.log(`
|
|
566
|
+
灵尧 Plugin 一键安装器
|
|
567
|
+
|
|
568
|
+
使用方法:
|
|
569
|
+
node cli.mjs install # 完整安装(包含配对和重启)
|
|
570
|
+
node cli.mjs install-only # 仅安装插件(不重启网关)
|
|
571
|
+
node cli.mjs uninstall # 卸载插件
|
|
572
|
+
node cli.mjs help # 显示此帮助
|
|
573
|
+
|
|
574
|
+
参数:
|
|
575
|
+
--path <目录> # 指定 OpenClaw 安装目录
|
|
576
|
+
|
|
577
|
+
环境要求:
|
|
578
|
+
• Node.js >= 22
|
|
579
|
+
• 已安装 OpenClaw
|
|
580
|
+
|
|
581
|
+
示例:
|
|
582
|
+
# 从 npm 安装(推荐)
|
|
583
|
+
npx -y @lingyao/openclaw-lingyao-cli install
|
|
584
|
+
|
|
585
|
+
# 从 npm 卸载
|
|
586
|
+
npx -y @lingyao/openclaw-lingyao-cli uninstall
|
|
587
|
+
|
|
588
|
+
# 本地测试
|
|
589
|
+
node cli.mjs install
|
|
590
|
+
|
|
591
|
+
# 指定 OpenClaw 路径
|
|
592
|
+
node cli.mjs install --path /opt/openclaw
|
|
593
|
+
|
|
594
|
+
# 仅安装,稍后手动重启
|
|
595
|
+
node cli.mjs install-only
|
|
596
|
+
`);
|
|
597
|
+
|
|
598
|
+
} else {
|
|
599
|
+
console.error(`未知命令: ${command}`);
|
|
600
|
+
console.log('运行 "node cli.mjs help" 查看帮助');
|
|
601
|
+
process.exit(1);
|
|
602
|
+
}
|
|
603
|
+
}
|
|
604
|
+
|
|
605
|
+
// 运行主函数
|
|
606
|
+
main().catch((error) => {
|
|
607
|
+
console.error('安装失败:', error);
|
|
608
|
+
process.exit(1);
|
|
609
|
+
});
|