claw-subagent-service 0.0.125 → 0.0.126

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claw-subagent-service",
3
- "version": "0.0.125",
3
+ "version": "0.0.126",
4
4
  "description": "虾说智能助手",
5
5
  "main": "cli.js",
6
6
  "bin": {
@@ -136,121 +136,43 @@ async function verifyCommandResult(command, result, scriptOutput = '') {
136
136
  }
137
137
 
138
138
  if (command === OpenClawCommandEnum.STOP) {
139
- // 停止命令验证:多次检查端口并重复执行停止,处理看门狗自动重启
139
+ // 停止命令验证:快速检查端口状态
140
140
  console.log(`[OpenClawControl] 开始验证停止结果...`);
141
141
 
142
- let portStatus = 1;
143
- let stopAttempts = 0;
144
- const maxStopAttempts = 3; // 最多执行 3 次停止
142
+ // 等待 2 秒后检查
143
+ await new Promise(resolve => setTimeout(resolve, 2000));
144
+ const portStatus = await getOpenClawStatus(18789);
145
+ console.log(`[OpenClawControl] 停止后端口状态: ${portStatus}`);
145
146
 
146
- // 等待 3 秒,给看门狗一次重启机会,然后验证
147
- await new Promise(resolve => setTimeout(resolve, 3000));
148
-
149
- while (stopAttempts < maxStopAttempts) {
150
- portStatus = await getOpenClawStatus(18789);
151
- console.log(`[OpenClawControl] 停止后端口状态 (尝试 ${stopAttempts + 1}/${maxStopAttempts}): ${portStatus}`);
152
-
153
- if (portStatus !== 1) {
154
- console.log(`[OpenClawControl] 停止验证通过: 端口已关闭`);
155
- break;
156
- }
157
-
158
- stopAttempts++;
159
- if (stopAttempts < maxStopAttempts) {
160
- console.log(`[OpenClawControl] 端口仍在监听,尝试第 ${stopAttempts + 1} 次停止...`);
161
- const scriptResult = await executeWithScript(command);
162
- const retryResult = scriptResult.result;
163
- console.log(`[OpenClawControl] 第 ${stopAttempts} 次重试停止结果: ${retryResult.status} - ${retryResult.message}`);
164
-
165
- // 等待看门狗重启后再检查
166
- await new Promise(resolve => setTimeout(resolve, 3000));
167
- }
168
- }
169
-
170
- if (portStatus === 1) {
171
- console.error(`[OpenClawControl] 停止失败: 端口 18789 仍在监听。尝试直接强制终止进程...`);
172
-
173
- // 直接执行强制终止命令(不通过脚本)
174
- try {
175
- const { execSync } = require('child_process');
176
-
177
- // 先尝试 pkill
178
- try {
179
- execSync('pkill -9 -f "openclaw"', { timeout: 5000 });
180
- console.log('[OpenClawControl] pkill -9 -f openclaw 执行成功');
181
- } catch (e) {
182
- console.log('[OpenClawControl] pkill 执行失败或没有匹配进程');
183
- }
184
-
185
- // 再尝试 killall
186
- try {
187
- execSync('killall -9 openclaw', { timeout: 5000 });
188
- console.log('[OpenClawControl] killall -9 openclaw 执行成功');
189
- } catch (e) {
190
- console.log('[OpenClawControl] killall 执行失败或没有匹配进程');
191
- }
192
-
193
- // 等待进程退出
194
- await new Promise(resolve => setTimeout(resolve, 5000));
195
-
196
- // 再次验证端口
197
- const finalPortStatus = await getOpenClawStatus(18789);
198
-
199
- if (finalPortStatus !== 1) {
200
- console.log(`[OpenClawControl] 强制停止成功: 端口已关闭`);
201
- return {
202
- status: OpenClawServiceStatus.STOP_SUCCESS,
203
- message: '服务已停止(强制停止)'
204
- };
205
- }
206
- } catch (err) {
207
- console.error(`[OpenClawControl] 强制停止异常: ${err.message}`);
208
- }
209
-
210
- console.error(`[OpenClawControl] 停止失败: 端口 18789 仍在监听。所有停止方法均已尝试。`);
147
+ if (portStatus !== 1) {
148
+ console.log(`[OpenClawControl] 停止验证通过: 端口已关闭`);
149
+ } else {
150
+ console.error(`[OpenClawControl] 停止失败: 端口 18789 仍在监听。`);
211
151
  return {
212
152
  status: OpenClawServiceStatus.ERROR,
213
153
  message: '停止失败: 服务仍在运行'
214
154
  };
215
155
  }
216
-
217
- console.log(`[OpenClawControl] 停止验证通过: 端口已关闭`);
218
156
  } else if (command === OpenClawCommandEnum.START || command === OpenClawCommandEnum.RESTART) {
219
- // 等待服务启动
220
- const maxWait = command === OpenClawCommandEnum.START ? 30 : 60;
157
+ // 等待服务启动(最多等待 30 秒)
158
+ const maxWait = 15; // 最多 15 次检查
221
159
  let attempts = 0;
222
160
  let portStatus = 0;
223
161
 
224
162
  while (attempts < maxWait) {
225
163
  await new Promise(resolve => setTimeout(resolve, 2000));
226
164
  portStatus = await getOpenClawStatus(18789);
227
- if (portStatus === 1 || portStatus === 2) break; // 端口监听或进程存在都算成功
165
+ if (portStatus === 1) break; // 端口监听算成功
228
166
  attempts++;
229
167
  }
230
168
 
231
169
  console.log(`[OpenClawControl] ${getCommandName(command)}后端口状态: ${portStatus}`);
232
170
 
233
171
  if (portStatus === 0) {
234
- // 端口未监听且进程不存在,但检查脚本是否报告成功
235
- if (outputUpper.includes('SUCCESS') || outputUpper.includes('ALREADY RUNNING')) {
236
- console.warn(`[OpenClawControl] 警告: 端口检查失败,但脚本报告成功。服务可能绑定到其他网络接口。`);
237
- // 信任脚本结果,但添加警告
238
- return {
239
- status: result.status,
240
- message: result.message + ' (警告: 端口检查可能不准确)'
241
- };
242
- }
243
172
  return {
244
173
  status: OpenClawServiceStatus.ERROR,
245
174
  message: `${getCommandName(command)}失败: 服务未运行`
246
175
  };
247
- } else if (portStatus === 2) {
248
- // 进程存在但端口未监听,服务可能在启动中或绑定到其他地址
249
- console.warn(`[OpenClawControl] 警告: openclaw 进程存在但端口 ${portStatus} 未监听。`);
250
- return {
251
- status: result.status === OpenClawServiceStatus.START_SUCCESS ? result.status : OpenClawServiceStatus.START_SUCCESS,
252
- message: result.message + ' (进程已启动,端口检查可能不准确)'
253
- };
254
176
  }
255
177
  }
256
178
 
@@ -40,9 +40,21 @@ function isValidCommand(command) {
40
40
  return Object.values(OpenClawCommandEnum).includes(command);
41
41
  }
42
42
 
43
+ function getCommandName(command) {
44
+ const names = {
45
+ [OpenClawCommandEnum.START]: '启动',
46
+ [OpenClawCommandEnum.STOP]: '停止',
47
+ [OpenClawCommandEnum.RESTART]: '重启',
48
+ [OpenClawCommandEnum.STATUS]: '状态检查',
49
+ [OpenClawCommandEnum.CONFIG_FIX]: '配置修复'
50
+ };
51
+ return names[command] || '未知命令';
52
+ }
53
+
43
54
  module.exports = {
44
55
  OpenClawCommandEnum,
45
56
  OpenClawServiceStatus,
46
57
  getServiceStatusMessage,
47
- isValidCommand
58
+ isValidCommand,
59
+ getCommandName
48
60
  };
@@ -8,7 +8,7 @@
8
8
  * - DELETE_OPENCODE_SESSION: 删除会话
9
9
  */
10
10
  const { RongyunMessageTypeEnum } = require('./rongyun-message-types');
11
- const { OpenClawCommandEnum } = require('./openclaw-enum');
11
+ const { OpenClawCommandEnum, getCommandName } = require('./openclaw-enum');
12
12
  const { executeCommand } = require('./openclaw-control');
13
13
  const { createOpencodeSession, deleteOpencodeSession, forwardChatMessage } = require('./opencode-service');
14
14
  const { ServiceManager } = require('./service-manager');
@@ -128,21 +128,39 @@ class RongyunMessageHandler {
128
128
  }
129
129
 
130
130
  this.commandLock = true;
131
- // 设置 60 秒超时保护,防止命令永久卡住导致锁无法释放
131
+ // 设置 120 秒超时保护,防止命令永久卡住导致锁无法释放
132
+ // 启动命令可能需要较长时间(等待服务启动)
132
133
  this.commandLockTimer = setTimeout(() => {
133
- this.logWarn('[RongyunMessageHandler] 命令锁超时(60秒),自动释放');
134
+ this.logWarn('[RongyunMessageHandler] 命令锁超时(120秒),自动释放');
134
135
  this.commandLock = false;
135
136
  this.commandLockTimer = null;
136
- }, 60000);
137
+ }, 120000);
137
138
 
138
139
  try {
139
- await executeCommand(command, null, async (response) => {
140
- // 增加短暂延迟,避免融云 SDK 在收到消息后立刻回复时消息丢失
141
- await new Promise(resolve => setTimeout(resolve, 500));
140
+ // 先发送响应,再执行命令(避免前端超时)
141
+ // 启动/停止/重启命令是异步的,前端只需要知道命令已接收
142
+ const isAsyncCommand = [OpenClawCommandEnum.START, OpenClawCommandEnum.STOP, OpenClawCommandEnum.RESTART].includes(command);
143
+
144
+ if (isAsyncCommand) {
145
+ // 立即响应,告知前端命令已接收
142
146
  await this.sendResponse(RongyunMessageTypeEnum.COMMAND_RESULT, {
143
- ...response,
144
- command_id: commandId
147
+ command,
148
+ command_id: commandId,
149
+ status: 'success',
150
+ message: `${getCommandName(command)}命令已接收,正在执行...`
145
151
  }, requestId, sourceId);
152
+ }
153
+
154
+ // 执行命令
155
+ await executeCommand(command, null, async (response) => {
156
+ if (!isAsyncCommand) {
157
+ // 同步命令立即响应
158
+ await this.sendResponse(RongyunMessageTypeEnum.COMMAND_RESULT, {
159
+ ...response,
160
+ command_id: commandId
161
+ }, requestId, sourceId);
162
+ }
163
+ // 异步命令不在这里响应,因为已经提前响应了
146
164
  });
147
165
  } catch (e) {
148
166
  const msg = e instanceof Error ? e.message : String(e);