claw-subagent-service 0.0.0

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 (48) hide show
  1. package/README.md +44 -0
  2. package/cli.js +254 -0
  3. package/command/linux/restart.sh +98 -0
  4. package/command/linux/start.sh +101 -0
  5. package/command/linux/status.sh +140 -0
  6. package/command/linux/stop.sh +112 -0
  7. package/command/win/restart.bat +39 -0
  8. package/command/win/start.bat +65 -0
  9. package/command/win/status.bat +52 -0
  10. package/command/win/stop.bat +55 -0
  11. package/command/win/windows/345/220/257/345/212/250/350/204/232/346/234/254 +0 -0
  12. package/package.json +37 -0
  13. package/scripts/install-silent.js +167 -0
  14. package/scripts/uninstall.js +61 -0
  15. package/service/daemon.js +189 -0
  16. package/service/logger.js +31 -0
  17. package/service/modules/auth.js +17 -0
  18. package/service/modules/business-message-handler.js +118 -0
  19. package/service/modules/command-handler.js +152 -0
  20. package/service/modules/config.js +44 -0
  21. package/service/modules/dashboard-collector.js +588 -0
  22. package/service/modules/heartbeat-dashboard.js +153 -0
  23. package/service/modules/mac-address.js +15 -0
  24. package/service/modules/message-processor-example.js +72 -0
  25. package/service/modules/message-processor.js +62 -0
  26. package/service/modules/normal-message-handler.js +60 -0
  27. package/service/modules/openclaw-control.js +128 -0
  28. package/service/modules/openclaw-enum.js +48 -0
  29. package/service/modules/opencode-service.js +199 -0
  30. package/service/modules/opencode-starter.js +194 -0
  31. package/service/modules/port-checker.js +31 -0
  32. package/service/modules/rongyun-message-handler.js +250 -0
  33. package/service/modules/rongyun-message-sender.js +157 -0
  34. package/service/modules/rongyun-message-types.js +28 -0
  35. package/service/modules/script-executor.js +550 -0
  36. package/service/modules/service-manager.js +319 -0
  37. package/service/modules/structured-message-router.js +118 -0
  38. package/service/rongcloud/env-polyfill.js +95 -0
  39. package/service/rongcloud/index.js +19 -0
  40. package/service/rongcloud/message-handler.js +147 -0
  41. package/service/rongcloud/message-types.js +22 -0
  42. package/service/rongcloud/openclaw-client.js +98 -0
  43. package/service/rongcloud/openclaw-config.js +108 -0
  44. package/service/rongcloud/rongcloud-client.js +273 -0
  45. package/service/rongcloud/types.js +9 -0
  46. package/service/updater.js +348 -0
  47. package/service/worker.js +376 -0
  48. package/version.json +4 -0
@@ -0,0 +1,550 @@
1
+ const { spawn } = require('child_process');
2
+ const path = require('path');
3
+
4
+ const OpenClawCommandEnum = {
5
+ START: 1,
6
+ STOP: 2,
7
+ RESTART: 3,
8
+ STATUS: 4,
9
+ CONFIG_FIX: 5
10
+ };
11
+
12
+ const OpenClawServiceStatus = {
13
+ RUNNING: 'running',
14
+ NOT_RUNNING: 'not_running',
15
+ START_SUCCESS: 'starting_success',
16
+ STOP_SUCCESS: 'stop_success',
17
+ RESTART_SUCCESS: 'restart_success',
18
+ CONFIG_FIX_SUCCESS: 'config_fix_success',
19
+ NOT_INSTALL: 'not_install',
20
+ ERROR: 'error'
21
+ };
22
+
23
+ const statusMessages = {
24
+ [OpenClawServiceStatus.RUNNING]: '服务运行中',
25
+ [OpenClawServiceStatus.NOT_RUNNING]: '服务未运行',
26
+ [OpenClawServiceStatus.START_SUCCESS]: '启动成功',
27
+ [OpenClawServiceStatus.STOP_SUCCESS]: '关闭服务成功',
28
+ [OpenClawServiceStatus.RESTART_SUCCESS]: '重启服务成功',
29
+ [OpenClawServiceStatus.CONFIG_FIX_SUCCESS]: '配置修复成功',
30
+ [OpenClawServiceStatus.ERROR]: '未知异常',
31
+ [OpenClawServiceStatus.NOT_INSTALL]: 'openclaw未安装'
32
+ };
33
+
34
+ function getServiceStatusMessage(status) {
35
+ return statusMessages[status] || '状态未知';
36
+ }
37
+
38
+ function commandFromScript(scriptPath) {
39
+ const base = scriptPath.toLowerCase();
40
+ // 注意顺序:restart 必须排在 start 前面,因为 restart 包含 start
41
+ if (base.includes('restart')) return OpenClawCommandEnum.RESTART;
42
+ if (base.includes('start')) return OpenClawCommandEnum.START;
43
+ if (base.includes('stop')) return OpenClawCommandEnum.STOP;
44
+ if (base.includes('status')) return OpenClawCommandEnum.STATUS;
45
+ return null;
46
+ }
47
+
48
+ class ScriptExecutor {
49
+ constructor(scriptDir, successKeyword = 'Success', timeout = 180) {
50
+ const currentDir = __dirname;
51
+ const system = process.platform;
52
+ if (scriptDir) {
53
+ this.scriptDir = scriptDir;
54
+ } else if (system === 'win32') {
55
+ this.scriptDir = path.join(currentDir, '..', '..', 'command', 'win');
56
+ } else {
57
+ this.scriptDir = path.join(currentDir, '..', '..', 'command', 'linux');
58
+ }
59
+ this.successKeyword = successKeyword;
60
+ this.timeout = timeout;
61
+ }
62
+
63
+ async execute(scriptName) {
64
+ const scriptPath = path.join(this.scriptDir, scriptName);
65
+
66
+ try {
67
+ const { stdout, stderr } = await this.runScript(scriptPath);
68
+ const fullOutput = stdout + stderr;
69
+ if (fullOutput.includes(this.successKeyword)) {
70
+ return { success: true, message: '执行成功' };
71
+ }
72
+ return {
73
+ success: false,
74
+ message: `执行失败(未找到成功标识 '${this.successKeyword}')${stderr ? '\n错误输出: ' + stderr.slice(0, 200) : ''}`
75
+ };
76
+ } catch (e) {
77
+ const msg = e instanceof Error ? e.message : String(e);
78
+ return { success: false, message: `执行异常: ${msg}` };
79
+ }
80
+ }
81
+
82
+ async executeWithStatus(command, scriptName) {
83
+ // 配置修复命令特殊处理:直接执行命令,不需要脚本
84
+ if (command === OpenClawCommandEnum.CONFIG_FIX) {
85
+ return await this.executeCommandDirect('openclaw doctor --fix', 120);
86
+ }
87
+
88
+ const scriptPath = path.join(this.scriptDir, scriptName);
89
+
90
+ try {
91
+ const { stdout, stderr } = await this.runScript(scriptPath);
92
+ const fullOutput = stdout + stderr;
93
+ return this.parseStatus(command, fullOutput);
94
+ } catch (e) {
95
+ const msg = e instanceof Error ? e.message : String(e);
96
+ return { status: OpenClawServiceStatus.ERROR, message: `执行异常: ${msg}` };
97
+ }
98
+ }
99
+
100
+ /**
101
+ * 直接执行命令(不通过脚本)
102
+ * @param {string} command - 要执行的命令
103
+ * @param {number} timeout - 超时时间(秒)
104
+ * @returns {Object} { status, message }
105
+ */
106
+ async executeCommandDirect(command, timeout = 180) {
107
+ return new Promise((resolve, reject) => {
108
+ const system = process.platform;
109
+ let cmd;
110
+ let args;
111
+
112
+ if (system === 'win32') {
113
+ cmd = 'cmd';
114
+ args = ['/c', command];
115
+ } else {
116
+ cmd = 'bash';
117
+ args = ['-c', command];
118
+ }
119
+
120
+ const child = spawn(cmd, args, {
121
+ detached: false,
122
+ windowsHide: true
123
+ });
124
+
125
+ let stdout = '';
126
+ let stderr = '';
127
+ let killed = false;
128
+
129
+ const timer = setTimeout(() => {
130
+ killed = true;
131
+ this.killProcessTree(child);
132
+ resolve({
133
+ status: OpenClawServiceStatus.ERROR,
134
+ message: `执行超时(超过 ${timeout} 秒)`
135
+ });
136
+ }, timeout * 1000);
137
+
138
+ child.stdout?.on('data', (data) => {
139
+ const text = data.toString('utf-8');
140
+ stdout += text;
141
+ });
142
+
143
+ child.stderr?.on('data', (data) => {
144
+ const text = data.toString('utf-8');
145
+ stderr += text;
146
+ });
147
+
148
+ child.on('error', (err) => {
149
+ if (!killed) {
150
+ killed = true;
151
+ clearTimeout(timer);
152
+ resolve({
153
+ status: OpenClawServiceStatus.ERROR,
154
+ message: `执行异常: ${err.message}`
155
+ });
156
+ }
157
+ });
158
+
159
+ child.on('close', (code) => {
160
+ if (!killed) {
161
+ killed = true;
162
+ clearTimeout(timer);
163
+ const fullOutput = stdout + stderr;
164
+ // 对于配置修复命令,解析输出结果
165
+ if (command.includes('doctor')) {
166
+ const result = this.parseStatus(OpenClawCommandEnum.CONFIG_FIX, fullOutput);
167
+ resolve(result);
168
+ } else {
169
+ resolve({
170
+ status: code === 0 ? OpenClawServiceStatus.CONFIG_FIX_SUCCESS : OpenClawServiceStatus.ERROR,
171
+ message: code === 0 ? '执行成功' : `执行失败(退出码: ${code})`
172
+ });
173
+ }
174
+ }
175
+ });
176
+ });
177
+ }
178
+
179
+ runScript(scriptPath) {
180
+ return new Promise((resolve, reject) => {
181
+ const system = process.platform;
182
+ let cmd;
183
+ let args;
184
+
185
+ if (system === 'win32') {
186
+ cmd = 'cmd';
187
+ args = ['/c', scriptPath];
188
+ } else {
189
+ cmd = 'bash';
190
+ args = [scriptPath];
191
+ }
192
+
193
+ const child = spawn(cmd, args, {
194
+ detached: false,
195
+ windowsHide: true
196
+ });
197
+
198
+ let stdout = '';
199
+ let stderr = '';
200
+ let killed = false;
201
+
202
+ const timer = setTimeout(() => {
203
+ killed = true;
204
+ this.killProcessTree(child);
205
+ reject(new Error(`执行超时(超过 ${this.timeout} 秒)`));
206
+ }, this.timeout * 1000);
207
+
208
+ child.stdout?.on('data', (data) => {
209
+ const text = data.toString('utf-8');
210
+ stdout += text;
211
+ if (this.shouldReturnEarly(commandFromScript(scriptPath), stdout + stderr)) {
212
+ if (!killed) {
213
+ killed = true;
214
+ clearTimeout(timer);
215
+ this.killProcessTree(child);
216
+ resolve({ stdout, stderr });
217
+ }
218
+ }
219
+ });
220
+
221
+ child.stderr?.on('data', (data) => {
222
+ const text = data.toString('utf-8');
223
+ stderr += text;
224
+ if (this.shouldReturnEarly(commandFromScript(scriptPath), stdout + stderr)) {
225
+ if (!killed) {
226
+ killed = true;
227
+ clearTimeout(timer);
228
+ this.killProcessTree(child);
229
+ resolve({ stdout, stderr });
230
+ }
231
+ }
232
+ });
233
+
234
+ child.on('error', (err) => {
235
+ console.error(`[ScriptExecutor] 子进程错误: ${err.message}`);
236
+ if (!killed) {
237
+ killed = true;
238
+ clearTimeout(timer);
239
+ reject(err);
240
+ }
241
+ });
242
+
243
+ child.on('exit', (code) => {
244
+ if (!killed) {
245
+ killed = true;
246
+ clearTimeout(timer);
247
+ console.log(`[ScriptExecutor] 脚本退出,code=${code}, stdout长度=${stdout.length}`);
248
+ resolve({ stdout, stderr });
249
+ }
250
+ });
251
+
252
+ // 备用:如果 exit 没有被触发,使用 close
253
+ child.on('close', (code) => {
254
+ if (!killed) {
255
+ killed = true;
256
+ clearTimeout(timer);
257
+ console.log(`[ScriptExecutor] 脚本关闭,code=${code}, stdout长度=${stdout.length}`);
258
+ resolve({ stdout, stderr });
259
+ }
260
+ });
261
+
262
+ // 错误处理
263
+ child.on('error', (err) => {
264
+ console.error(`[ScriptExecutor] 子进程错误: ${err.message}`);
265
+ if (!killed) {
266
+ killed = true;
267
+ clearTimeout(timer);
268
+ reject(err);
269
+ }
270
+ });
271
+ });
272
+ }
273
+
274
+ shouldReturnEarly(command, output) {
275
+ const upper = output.toUpperCase();
276
+
277
+ // 只检查错误关键字,错误时立即返回
278
+ const errorKeywords = ['[ERROR]', '错误', 'FAILED', '失败', '[错误]'];
279
+ for (const kw of errorKeywords) {
280
+ if (upper.includes(kw.toUpperCase())) return true;
281
+ }
282
+
283
+ // 对于 START 命令,不提前返回,让脚本完整执行
284
+ // 因为 start.bat 有等待循环,需要完整输出才能判断状态
285
+ if (command === OpenClawCommandEnum.START) {
286
+ return false;
287
+ }
288
+
289
+ let successKeywords;
290
+ if (command === OpenClawCommandEnum.RESTART) {
291
+ successKeywords = [
292
+ '[OK] RESTART COMPLETED SUCCESSFULLY',
293
+ 'RESTART COMPLETED SUCCESSFULLY',
294
+ '[OK] RESTART COMPLETED',
295
+ 'RESTART COMPLETED',
296
+ '重启完成'
297
+ ];
298
+ } else {
299
+ successKeywords = [
300
+ '[OK] RESTART COMPLETED SUCCESSFULLY',
301
+ 'RESTART COMPLETED SUCCESSFULLY',
302
+ '[OK] RESTART COMPLETED',
303
+ 'RESTART COMPLETED',
304
+ '重启完成',
305
+ '[OK] SERVICE IS RUNNING',
306
+ '[OK] SERVICE STOPPED',
307
+ 'STOPPED SUCCESSFULLY',
308
+ '服务停止成功',
309
+ '服务已停止',
310
+ 'GATEWAY STOP SIGNAL SENT',
311
+ 'STOP SIGNAL SENT'
312
+ ];
313
+ }
314
+
315
+ for (const kw of successKeywords) {
316
+ if (upper.includes(kw.toUpperCase())) return true;
317
+ }
318
+
319
+ return false;
320
+ }
321
+
322
+ parseStatus(command, output) {
323
+ const upper = output.toUpperCase();
324
+
325
+ if (
326
+ upper.includes('OPENCLAW COMMAND NOT FOUND') ||
327
+ output.includes('服务 openclaw-gateway.service 未安装') ||
328
+ output.includes('服务 openclaw-gateway.service 不存在') ||
329
+ upper.includes('OPENCLAW-GATEWAY.SERVICE 不存在')
330
+ ) {
331
+ return {
332
+ status: OpenClawServiceStatus.NOT_INSTALL,
333
+ message: getServiceStatusMessage(OpenClawServiceStatus.NOT_INSTALL)
334
+ };
335
+ }
336
+
337
+ if (command === OpenClawCommandEnum.STATUS) {
338
+ if (
339
+ upper.includes('[INFO] STATUS: RUNNING') ||
340
+ upper.includes('[OK] SERVICE IS RUNNING') ||
341
+ (upper.includes('ACTIVE: ACTIVE (RUNNING)') && upper.includes('SUCCESS')) ||
342
+ (upper.includes('LISTENING') && output.includes(':18789'))
343
+ ) {
344
+ return {
345
+ status: OpenClawServiceStatus.RUNNING,
346
+ message: getServiceStatusMessage(OpenClawServiceStatus.RUNNING)
347
+ };
348
+ }
349
+ if (
350
+ upper.includes('[INFO] STATUS: NOT RUNNING') ||
351
+ upper.includes('[INFO] OPENCLAW IS NOT RUNNING') ||
352
+ upper.includes('ACTIVE: INACTIVE (DEAD)') ||
353
+ upper.includes('ACTIVE: FAILED') ||
354
+ output.includes('[INFO] 未启动')
355
+ ) {
356
+ return {
357
+ status: OpenClawServiceStatus.NOT_RUNNING,
358
+ message: getServiceStatusMessage(OpenClawServiceStatus.NOT_RUNNING)
359
+ };
360
+ }
361
+ return {
362
+ status: OpenClawServiceStatus.NOT_RUNNING,
363
+ message: getServiceStatusMessage(OpenClawServiceStatus.NOT_RUNNING)
364
+ };
365
+ }
366
+
367
+ if (command === OpenClawCommandEnum.START) {
368
+ // 优先检查错误
369
+ if (upper.includes('[ERROR]') || output.includes('[错误]')) {
370
+ return { status: OpenClawServiceStatus.ERROR, message: '启动失败' };
371
+ }
372
+ // 检查成功标识:包含 SUCCESS 或 ALREADY RUNNING 即为成功
373
+ if (upper.includes('SUCCESS') || upper.includes('ALREADY RUNNING') || output.includes('服务已经在运行中')) {
374
+ return {
375
+ status: OpenClawServiceStatus.START_SUCCESS,
376
+ message: getServiceStatusMessage(OpenClawServiceStatus.START_SUCCESS)
377
+ };
378
+ }
379
+ // 如果既没有错误也没有成功标识,返回未知(但通常不会发生)
380
+ return { status: OpenClawServiceStatus.ERROR, message: '启动结果未知' };
381
+ }
382
+
383
+ if (command === OpenClawCommandEnum.STOP) {
384
+ if (
385
+ upper.includes('NOT RUNNING') ||
386
+ upper.includes('IS NOT RUNNING') ||
387
+ output.includes('[INFO] 未启动') ||
388
+ upper.includes('OPENCLAW IS NOT RUNNING') ||
389
+ output.includes('服务未运行')
390
+ ) {
391
+ return {
392
+ status: OpenClawServiceStatus.NOT_RUNNING,
393
+ message: '服务已经停止'
394
+ };
395
+ }
396
+ if (
397
+ upper.includes('SUCCESS') ||
398
+ upper.includes('STOPPED') ||
399
+ upper.includes('[OK] STOP COMMAND EXECUTED') ||
400
+ upper.includes('[OK] SERVICE STOPPED') ||
401
+ (output.includes('[INFO] OPENCLAW 服务停止成功') && output.includes('[INFO] 服务已成功停止')) ||
402
+ upper.includes('GATEWAY STOP SIGNAL SENT') ||
403
+ (upper.includes('[INFO] STOPPING SERVICE') && upper.includes('STOP SIGNAL'))
404
+ ) {
405
+ if (
406
+ upper.includes('NOT RUNNING') ||
407
+ upper.includes('ALREADY STOPPED') ||
408
+ output.includes('服务已经停止')
409
+ ) {
410
+ return {
411
+ status: OpenClawServiceStatus.NOT_RUNNING,
412
+ message: '服务已经停止'
413
+ };
414
+ }
415
+ return {
416
+ status: OpenClawServiceStatus.STOP_SUCCESS,
417
+ message: getServiceStatusMessage(OpenClawServiceStatus.STOP_SUCCESS)
418
+ };
419
+ }
420
+ if (
421
+ (upper.includes('[OK]') || upper.includes('[INFO] STOPPING SERVICE')) &&
422
+ !upper.includes('[ERROR]')
423
+ ) {
424
+ return {
425
+ status: OpenClawServiceStatus.STOP_SUCCESS,
426
+ message: getServiceStatusMessage(OpenClawServiceStatus.STOP_SUCCESS)
427
+ };
428
+ }
429
+ return { status: OpenClawServiceStatus.ERROR, message: '停止失败' };
430
+ }
431
+
432
+ if (command === OpenClawCommandEnum.RESTART) {
433
+ if (
434
+ upper.includes('[OK] RESTART COMPLETED SUCCESSFULLY') ||
435
+ upper.includes('RESTART COMPLETED SUCCESSFULLY') ||
436
+ output.includes('[INFO] OPENCLAW 服务已完全重启')
437
+ ) {
438
+ return {
439
+ status: OpenClawServiceStatus.RESTART_SUCCESS,
440
+ message: getServiceStatusMessage(OpenClawServiceStatus.RESTART_SUCCESS)
441
+ };
442
+ }
443
+ if (
444
+ (upper.includes('SUCCESS') && upper.includes('RUNNING')) ||
445
+ (upper.includes('[OK] SERVICE IS RUNNING') && upper.includes('SUCCESS'))
446
+ ) {
447
+ const successCount = upper.split('SUCCESS').length - 1;
448
+ if (successCount >= 2 || upper.includes('RESTART')) {
449
+ return {
450
+ status: OpenClawServiceStatus.RESTART_SUCCESS,
451
+ message: getServiceStatusMessage(OpenClawServiceStatus.RESTART_SUCCESS)
452
+ };
453
+ }
454
+ }
455
+ if (upper.includes('[OK] RESTART COMPLETED') || upper.includes('RESTART COMPLETED')) {
456
+ return {
457
+ status: OpenClawServiceStatus.RESTART_SUCCESS,
458
+ message: getServiceStatusMessage(OpenClawServiceStatus.RESTART_SUCCESS)
459
+ };
460
+ }
461
+ if (upper.includes('[ERROR]')) {
462
+ return { status: OpenClawServiceStatus.ERROR, message: '重启失败' };
463
+ }
464
+ if (output.includes('端口 18789 已就绪') || upper.includes('PORT 18789')) {
465
+ return {
466
+ status: OpenClawServiceStatus.RESTART_SUCCESS,
467
+ message: getServiceStatusMessage(OpenClawServiceStatus.RESTART_SUCCESS)
468
+ };
469
+ }
470
+ const successCount = upper.split('SUCCESS').length - 1;
471
+ if (successCount >= 2 && !upper.includes('[ERROR]')) {
472
+ return {
473
+ status: OpenClawServiceStatus.RESTART_SUCCESS,
474
+ message: getServiceStatusMessage(OpenClawServiceStatus.RESTART_SUCCESS)
475
+ };
476
+ }
477
+ return { status: OpenClawServiceStatus.ERROR, message: '重启失败' };
478
+ }
479
+
480
+ if (command === OpenClawCommandEnum.CONFIG_FIX) {
481
+ // 配置修复命令解析
482
+ if (
483
+ upper.includes('DOCTOR COMPLETE') ||
484
+ upper.includes('CONFIG WAS LAST WRITTEN') ||
485
+ upper.includes('RESTARTED SCHEDULED TASK')
486
+ ) {
487
+ return {
488
+ status: OpenClawServiceStatus.CONFIG_FIX_SUCCESS,
489
+ message: getServiceStatusMessage(OpenClawServiceStatus.CONFIG_FIX_SUCCESS)
490
+ };
491
+ }
492
+ if (upper.includes('[ERROR]') || upper.includes('ERROR')) {
493
+ return { status: OpenClawServiceStatus.ERROR, message: '配置修复失败' };
494
+ }
495
+ // 如果没有明确的错误,默认认为成功(因为 doctor 命令通常会完成)
496
+ return {
497
+ status: OpenClawServiceStatus.CONFIG_FIX_SUCCESS,
498
+ message: getServiceStatusMessage(OpenClawServiceStatus.CONFIG_FIX_SUCCESS)
499
+ };
500
+ }
501
+
502
+ return { status: OpenClawServiceStatus.ERROR, message: `未知命令: ${command}` };
503
+ }
504
+
505
+ killProcessTree(child) {
506
+ if (!child.pid) return;
507
+ try {
508
+ if (process.platform === 'win32') {
509
+ const { execSync } = require('child_process');
510
+ execSync(`taskkill /pid ${child.pid} /T /F`, { windowsHide: true });
511
+ } else {
512
+ child.kill('SIGKILL');
513
+ }
514
+ } catch {}
515
+ }
516
+ }
517
+
518
+ // 脚本映射
519
+ const scriptMap = {
520
+ [OpenClawCommandEnum.START]: 'start-opencode.bat',
521
+ [OpenClawCommandEnum.STOP]: 'stop-opencode.bat',
522
+ [OpenClawCommandEnum.RESTART]: 'restart-opencode.bat',
523
+ [OpenClawCommandEnum.STATUS]: 'status-opencode.bat'
524
+ };
525
+
526
+ // 兼容旧版 API:executeCommand
527
+ async function executeCommand(command, args = [], timeout = 180) {
528
+ const executor = new ScriptExecutor(undefined, 'Success', timeout);
529
+ const scriptName = scriptMap[command];
530
+
531
+ if (!scriptName) {
532
+ throw new Error(`未知命令: ${command}`);
533
+ }
534
+
535
+ const result = await executor.executeWithStatus(command, scriptName);
536
+
537
+ // 转换为旧版 API 格式
538
+ return {
539
+ service_status: result.status,
540
+ message: result.message
541
+ };
542
+ }
543
+
544
+ module.exports = {
545
+ ScriptExecutor,
546
+ executeCommand,
547
+ OpenClawCommandEnum,
548
+ OpenClawServiceStatus,
549
+ getServiceStatusMessage
550
+ };