claw-subagent-service 0.0.127 → 0.0.129

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.
@@ -17,6 +17,14 @@ log_info() { echo -e "${GREEN}[INFO]${NC} $1"; }
17
17
  log_warn() { echo -e "${YELLOW}[WARN]${NC} $1"; }
18
18
  log_error() { echo -e "${RED}[ERROR]${NC} $1"; }
19
19
 
20
+ # 调试模式:如果 DEBUG=1,输出更多日志
21
+ DEBUG="${DEBUG:-0}"
22
+ debug_log() {
23
+ if [ "$DEBUG" = "1" ]; then
24
+ echo -e "${YELLOW}[DEBUG]${NC} $1"
25
+ fi
26
+ }
27
+
20
28
  SERVICE_NAME="openclaw-gateway.service"
21
29
  MAX_WAIT=300 # 最长等待5分钟
22
30
  PORT="18789"
@@ -187,10 +195,13 @@ start_docker() {
187
195
  fi
188
196
 
189
197
  # 检查 openclaw 命令是否存在
198
+ debug_log "检查 openclaw 命令..."
190
199
  if ! command -v openclaw &>/dev/null; then
191
200
  log_error "openclaw 命令未找到,请先安装 OpenClaw。"
201
+ log_error "PATH: $PATH"
192
202
  exit 1
193
203
  fi
204
+ debug_log "openclaw 命令存在: $(which openclaw)"
194
205
 
195
206
  # 确保日志目录存在
196
207
  local log_dir="/tmp/openclaw"
@@ -201,10 +212,41 @@ start_docker() {
201
212
 
202
213
  log_info "正在启动 OpenClaw 服务..."
203
214
 
204
- # 使用 nohup 后台启动
205
- nohup openclaw gateway --port "$PORT" > "$log_file" 2>&1 &
215
+ # 使用 nohup 后台启动,指定 host 为 0.0.0.0(Docker 环境需要)
216
+ # 注意:openclaw gateway 可能需要不同的参数格式
217
+ log_info "执行命令: nohup openclaw gateway --port $PORT --host 0.0.0.0"
218
+ debug_log "当前工作目录: $(pwd)"
219
+ debug_log "当前用户: $(whoami)"
220
+ debug_log "环境变量 PATH: $PATH"
221
+
222
+ # 先检查 openclaw 版本
223
+ debug_log "openclaw 版本信息:"
224
+ openclaw --version 2>&1 | head -5 || true
225
+
226
+ # 检查 openclaw gateway help,确认参数格式
227
+ debug_log "openclaw gateway help 信息:"
228
+ openclaw gateway --help 2>&1 | head -20 || true
229
+
230
+ # 尝试启动,如果失败则尝试其他参数格式
231
+ log_info "尝试启动 openclaw gateway..."
232
+ nohup openclaw gateway --port "$PORT" --host 0.0.0.0 > "$log_file" 2>&1 &
233
+
234
+ # 等待 2 秒检查进程是否启动
235
+ sleep 2
236
+ local started_pid=$!
237
+ if ! ps -p "$started_pid" > /dev/null 2>&1; then
238
+ log_warn "进程 $started_pid 已退出,尝试其他启动方式..."
239
+ # 尝试不带 --host 参数
240
+ nohup openclaw gateway --port "$PORT" > "$log_file" 2>&1 &
241
+ started_pid=$!
242
+ sleep 2
243
+ if ! ps -p "$started_pid" > /dev/null 2>&1; then
244
+ log_error "所有启动方式均失败,请检查日志:$log_file"
245
+ exit 1
246
+ fi
247
+ fi
206
248
 
207
- log_info "OpenClaw 服务启动命令已发送(PID: $!)"
249
+ log_info "OpenClaw 服务启动命令已发送(PID: $started_pid)"
208
250
  log_info "日志文件: $log_file"
209
251
 
210
252
  # 等待端口就绪
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claw-subagent-service",
3
- "version": "0.0.127",
3
+ "version": "0.0.129",
4
4
  "description": "虾说智能助手",
5
5
  "main": "cli.js",
6
6
  "bin": {
@@ -181,25 +181,40 @@ async function verifyCommandResult(command, result, scriptOutput = '') {
181
181
 
182
182
  async function executeCommand(command, window, sendResponse) {
183
183
  const cmdName = getCommandName(command);
184
- console.log(`[OpenClawControl] ${cmdName} OpenClaw...`);
184
+ console.log(`[OpenClawControl] ====== 开始执行 ${cmdName} 命令 ======`);
185
+ console.log(`[OpenClawControl] 命令代码: ${command}`);
186
+ console.log(`[OpenClawControl] 平台: ${process.platform}`);
185
187
 
186
188
  let result;
187
189
 
188
190
  // 优先尝试 ServiceManager(systemd 模式)
189
191
  if (process.platform === 'linux' || process.platform === 'darwin') {
192
+ console.log(`[OpenClawControl] 尝试使用 ServiceManager...`);
190
193
  result = await manageWithServiceManager(command);
194
+ if (result) {
195
+ console.log(`[OpenClawControl] ServiceManager 结果: ${result.status} - ${result.message}`);
196
+ } else {
197
+ console.log(`[OpenClawControl] ServiceManager 不可用,回退到脚本方式`);
198
+ }
191
199
  }
192
200
 
193
201
  // 如果 ServiceManager 失败或不是 Linux/macOS,使用脚本方式
194
202
  let scriptOutput = '';
195
203
  if (!result) {
204
+ console.log(`[OpenClawControl] 使用脚本方式执行...`);
196
205
  const scriptResult = await executeWithScript(command);
197
206
  result = scriptResult.result;
198
207
  scriptOutput = scriptResult.output;
208
+ console.log(`[OpenClawControl] 脚本执行结果: ${result.status} - ${result.message}`);
209
+ if (scriptOutput) {
210
+ console.log(`[OpenClawControl] 脚本输出长度: ${scriptOutput.length}`);
211
+ }
199
212
  }
200
213
 
201
214
  // 验证结果(传递脚本输出用于后备检查)
215
+ console.log(`[OpenClawControl] 开始验证命令结果...`);
202
216
  result = await verifyCommandResult(command, result, scriptOutput);
217
+ console.log(`[OpenClawControl] 验证后结果: ${result.status} - ${result.message}`);
203
218
 
204
219
  // 输出日志
205
220
  if (result.status === OpenClawServiceStatus.START_SUCCESS ||
@@ -221,33 +236,41 @@ async function executeCommand(command, window, sendResponse) {
221
236
 
222
237
  // 获取操作后的真实状态
223
238
  let realStatus = result.status;
239
+ let realMessage = result.message;
224
240
  if (command === OpenClawCommandEnum.STOP || command === OpenClawCommandEnum.START || command === OpenClawCommandEnum.RESTART) {
225
241
  try {
242
+ console.log(`[OpenClawControl] 检测操作后的真实状态...`);
226
243
  const { getOpenClawStatus } = require('./port-checker');
227
244
  const portStatus = await getOpenClawStatus(18789);
245
+ console.log(`[OpenClawControl] 端口状态: ${portStatus}`);
228
246
  // 更新真实状态
229
247
  if (command === OpenClawCommandEnum.STOP) {
230
248
  realStatus = portStatus === 1 ? OpenClawServiceStatus.RUNNING : OpenClawServiceStatus.STOP_SUCCESS;
249
+ realMessage = portStatus === 1 ? '停止失败: 服务仍在运行' : '服务已停止';
231
250
  } else if (command === OpenClawCommandEnum.START) {
232
251
  realStatus = portStatus === 1 ? OpenClawServiceStatus.START_SUCCESS : OpenClawServiceStatus.ERROR;
252
+ realMessage = portStatus === 1 ? '服务已启动' : '启动失败: 服务未运行';
233
253
  } else if (command === OpenClawCommandEnum.RESTART) {
234
254
  realStatus = portStatus === 1 ? OpenClawServiceStatus.RESTART_SUCCESS : OpenClawServiceStatus.ERROR;
255
+ realMessage = portStatus === 1 ? '服务已重启' : '重启失败: 服务未运行';
235
256
  }
236
- console.log(`[OpenClawControl] 操作后真实状态检测: portStatus=${portStatus}, realStatus=${realStatus}`);
257
+ console.log(`[OpenClawControl] 操作后真实状态: portStatus=${portStatus}, realStatus=${realStatus}, message=${realMessage}`);
237
258
  } catch (e) {
238
259
  console.error(`[OpenClawControl] 真实状态检测失败: ${e.message}`);
239
260
  }
240
261
  }
241
262
 
263
+ console.log(`[OpenClawControl] 发送响应: status=${httpStatus}, message=${realMessage}`);
242
264
  sendResponse({
243
265
  type: 'command_result',
244
266
  command,
245
267
  status: httpStatus,
246
- message: result.message,
268
+ message: realMessage,
247
269
  service_status: realStatus
248
270
  });
249
271
  }
250
272
 
273
+ console.log(`[OpenClawControl] ====== ${cmdName} 命令执行完成 ======`);
251
274
  return result;
252
275
  }
253
276
 
@@ -27,7 +27,13 @@ function checkPortListening(port, host = '127.0.0.1') {
27
27
  resolve(false);
28
28
  });
29
29
 
30
- sock.connect(port, host);
30
+ try {
31
+ sock.connect(port, host);
32
+ } catch (err) {
33
+ console.error(`[PortChecker] 连接异常: ${err.message}`);
34
+ sock.destroy();
35
+ resolve(false);
36
+ }
31
37
  });
32
38
  }
33
39
 
@@ -150,6 +156,27 @@ async function getOpenClawStatus(port = 18789) {
150
156
  const processExists = checkProcessExists();
151
157
  if (processExists) {
152
158
  console.warn(`[PortChecker] 警告: openclaw 进程存在,但端口 ${port} 未监听。服务可能未正确启动或已崩溃。`);
159
+ // 尝试获取进程详细信息
160
+ try {
161
+ const { execSync } = require('child_process');
162
+ const psOutput = execSync('ps aux | grep -v grep | grep openclaw', { encoding: 'utf8', timeout: 5000 }).trim();
163
+ console.log(`[PortChecker] 进程详细信息:\n${psOutput}`);
164
+
165
+ // 尝试获取进程监听的端口
166
+ const pid = psOutput.split(/\s+/)[1];
167
+ if (pid) {
168
+ try {
169
+ const netstatOutput = execSync(`netstat -tlnp 2>/dev/null | grep ${pid} || ss -tlnp 2>/dev/null | grep ${pid}`, { encoding: 'utf8', timeout: 5000 }).trim();
170
+ if (netstatOutput) {
171
+ console.log(`[PortChecker] 进程 ${pid} 监听的端口:\n${netstatOutput}`);
172
+ }
173
+ } catch (e) {
174
+ // 忽略错误
175
+ }
176
+ }
177
+ } catch (e) {
178
+ // 忽略错误
179
+ }
153
180
  }
154
181
 
155
182
  console.log(`[PortChecker] 端口 ${port} 检测为未运行`);
@@ -164,9 +164,27 @@ class RongyunMessageHandler {
164
164
  // 异步命令不在这里响应,因为已经提前响应了
165
165
  // 但我们可以在这里记录执行结果
166
166
  this.logInfo(`[RongyunMessageHandler] 命令执行完成: command=${command}, status=${response.status}, message=${response.message}`);
167
+ }).then(() => {
168
+ // 命令执行完成后,立即释放锁
169
+ this.commandLock = false;
170
+ if (this.commandLockTimer) {
171
+ clearTimeout(this.commandLockTimer);
172
+ this.commandLockTimer = null;
173
+ }
167
174
  }).catch(err => {
168
175
  this.logError(`[RongyunMessageHandler] 命令执行失败: ${err.message}`);
176
+ // 执行失败后也要释放锁
177
+ this.commandLock = false;
178
+ if (this.commandLockTimer) {
179
+ clearTimeout(this.commandLockTimer);
180
+ this.commandLockTimer = null;
181
+ }
169
182
  });
183
+
184
+ // 异步命令立即返回,不等待执行完成
185
+ if (isAsyncCommand) {
186
+ return;
187
+ }
170
188
  } catch (e) {
171
189
  const msg = e instanceof Error ? e.message : String(e);
172
190
  this.logError(`命令执行异常: ${msg}`);
@@ -176,7 +194,7 @@ class RongyunMessageHandler {
176
194
  status: 'error',
177
195
  message: msg
178
196
  }, requestId, sourceId);
179
- } finally {
197
+ // 同步命令执行异常时释放锁
180
198
  this.commandLock = false;
181
199
  if (this.commandLockTimer) {
182
200
  clearTimeout(this.commandLockTimer);
@@ -88,15 +88,22 @@ class ScriptExecutor {
88
88
  const scriptPath = path.join(this.scriptDir, scriptName);
89
89
 
90
90
  try {
91
+ console.log(`[ScriptExecutor] 开始执行脚本: ${scriptPath}`);
91
92
  const { stdout, stderr, exitCode } = await this.runScript(scriptPath);
92
93
  const fullOutput = stdout + stderr;
93
94
 
94
95
  // 调试日志:记录脚本实际输出
95
- console.log(`[ScriptExecutor] 执行脚本: ${scriptPath}`);
96
- console.log(`[ScriptExecutor] ${scriptName} 输出:\n${fullOutput}`);
96
+ console.log(`[ScriptExecutor] 执行脚本完成: ${scriptPath}`);
97
97
  console.log(`[ScriptExecutor] ${scriptName} 退出码: ${exitCode}`);
98
+ console.log(`[ScriptExecutor] ${scriptName} 输出长度: ${fullOutput.length}`);
99
+ if (fullOutput.length > 0) {
100
+ console.log(`[ScriptExecutor] ${scriptName} 输出:\n${fullOutput}`);
101
+ } else {
102
+ console.log(`[ScriptExecutor] ${scriptName} 无输出`);
103
+ }
98
104
 
99
105
  const result = this.parseStatus(command, fullOutput);
106
+ console.log(`[ScriptExecutor] ${scriptName} 解析结果: status=${result.status}, message=${result.message}`);
100
107
 
101
108
  // 对于 STOP 命令,如果脚本退出码非零,强制返回错误
102
109
  if (command === OpenClawCommandEnum.STOP && exitCode !== 0) {
@@ -115,6 +122,7 @@ class ScriptExecutor {
115
122
  };
116
123
  } catch (e) {
117
124
  const msg = e instanceof Error ? e.message : String(e);
125
+ console.error(`[ScriptExecutor] 执行脚本异常: ${msg}`);
118
126
  return { status: OpenClawServiceStatus.ERROR, message: `执行异常: ${msg}` };
119
127
  }
120
128
  }