claw-subagent-service 0.0.90 → 0.0.91

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.90",
3
+ "version": "0.0.91",
4
4
  "description": "虾说智能助手",
5
5
  "main": "cli.js",
6
6
  "bin": {
@@ -128,7 +128,7 @@ async function verifyCommandResult(command, result, scriptOutput = '') {
128
128
  // 等待 3 秒后验证端口
129
129
  await new Promise(resolve => setTimeout(resolve, 3000));
130
130
  const portStatus = await getOpenClawStatus(18789);
131
- console.log(`[OpenClawControl] 停止后端口状态: ${portStatus === 1 ? '运行中' : '未运行'}`);
131
+ console.log(`[OpenClawControl] 停止后端口状态: ${portStatus}`);
132
132
 
133
133
  if (portStatus === 1) {
134
134
  // 端口仍在监听,但检查脚本是否报告已停止
@@ -144,6 +144,13 @@ async function verifyCommandResult(command, result, scriptOutput = '') {
144
144
  status: OpenClawServiceStatus.ERROR,
145
145
  message: '停止失败: 服务仍在运行'
146
146
  };
147
+ } else if (portStatus === 2) {
148
+ // 进程存在但端口未监听,可能服务正在停止中
149
+ console.warn(`[OpenClawControl] 警告: openclaw 进程仍存在但端口已关闭。`);
150
+ return {
151
+ status: result.status,
152
+ message: result.message + ' (警告: 进程仍存在)'
153
+ };
147
154
  }
148
155
  } else if (command === OpenClawCommandEnum.START || command === OpenClawCommandEnum.RESTART) {
149
156
  // 等待服务启动
@@ -154,14 +161,14 @@ async function verifyCommandResult(command, result, scriptOutput = '') {
154
161
  while (attempts < maxWait) {
155
162
  await new Promise(resolve => setTimeout(resolve, 2000));
156
163
  portStatus = await getOpenClawStatus(18789);
157
- if (portStatus === 1) break;
164
+ if (portStatus === 1 || portStatus === 2) break; // 端口监听或进程存在都算成功
158
165
  attempts++;
159
166
  }
160
167
 
161
- console.log(`[OpenClawControl] ${getCommandName(command)}后端口状态: ${portStatus === 1 ? '运行中' : '未运行'}`);
168
+ console.log(`[OpenClawControl] ${getCommandName(command)}后端口状态: ${portStatus}`);
162
169
 
163
170
  if (portStatus === 0) {
164
- // 端口未监听,但检查脚本是否报告成功(可能是服务绑定到其他接口)
171
+ // 端口未监听且进程不存在,但检查脚本是否报告成功
165
172
  if (outputUpper.includes('SUCCESS') || outputUpper.includes('ALREADY RUNNING')) {
166
173
  console.warn(`[OpenClawControl] 警告: 端口检查失败,但脚本报告成功。服务可能绑定到其他网络接口。`);
167
174
  // 信任脚本结果,但添加警告
@@ -174,6 +181,13 @@ async function verifyCommandResult(command, result, scriptOutput = '') {
174
181
  status: OpenClawServiceStatus.ERROR,
175
182
  message: `${getCommandName(command)}失败: 服务未运行`
176
183
  };
184
+ } else if (portStatus === 2) {
185
+ // 进程存在但端口未监听,服务可能在启动中或绑定到其他地址
186
+ console.warn(`[OpenClawControl] 警告: openclaw 进程存在但端口 ${portStatus} 未监听。`);
187
+ return {
188
+ status: result.status === OpenClawServiceStatus.START_SUCCESS ? result.status : OpenClawServiceStatus.START_SUCCESS,
189
+ message: result.message + ' (进程已启动,端口检查可能不准确)'
190
+ };
177
191
  }
178
192
  }
179
193
 
@@ -1,22 +1,32 @@
1
1
  const net = require('net');
2
2
  const os = require('os');
3
+ const { execSync } = require('child_process');
3
4
 
4
5
  function checkPortListening(port, host = '127.0.0.1') {
5
6
  return new Promise((resolve) => {
6
7
  const sock = new net.Socket();
7
- sock.setTimeout(3000);
8
+ sock.setTimeout(5000);
9
+
10
+ console.log(`[PortChecker] 尝试连接 ${host}:${port}`);
11
+
8
12
  sock.once('connect', () => {
13
+ console.log(`[PortChecker] 成功连接到 ${host}:${port}`);
9
14
  sock.destroy();
10
15
  resolve(true);
11
16
  });
12
- sock.once('error', () => {
17
+
18
+ sock.once('error', (err) => {
19
+ console.log(`[PortChecker] 连接 ${host}:${port} 失败: ${err.code} - ${err.message}`);
13
20
  sock.destroy();
14
21
  resolve(false);
15
22
  });
23
+
16
24
  sock.once('timeout', () => {
25
+ console.log(`[PortChecker] 连接 ${host}:${port} 超时`);
17
26
  sock.destroy();
18
27
  resolve(false);
19
28
  });
29
+
20
30
  sock.connect(port, host);
21
31
  });
22
32
  }
@@ -51,9 +61,98 @@ async function checkPortOnAllInterfaces(port) {
51
61
  return false;
52
62
  }
53
63
 
64
+ /**
65
+ * 通过系统命令检查端口是否监听(备选方法)
66
+ * 当 net.Socket 连接失败时使用
67
+ */
68
+ function checkPortViaSystemCommand(port) {
69
+ try {
70
+ // 按优先级尝试多种工具
71
+ const commands = [
72
+ `ss -tlnp 2>/dev/null | grep -q ":${port} " && echo "found"`,
73
+ `netstat -tlnp 2>/dev/null | grep -q ":${port} " && echo "found"`,
74
+ `lsof -i :${port} 2>/dev/null | grep -q LISTEN && echo "found"`,
75
+ `fuser ${port}/tcp 2>/dev/null | grep -q '[0-9]' && echo "found"`
76
+ ];
77
+
78
+ for (const cmd of commands) {
79
+ try {
80
+ const result = execSync(cmd, { encoding: 'utf8', timeout: 5000 }).trim();
81
+ if (result === 'found') {
82
+ console.log(`[PortChecker] 系统命令检测到端口 ${port} 正在监听`);
83
+ return true;
84
+ }
85
+ } catch (e) {
86
+ // 命令失败,尝试下一个
87
+ }
88
+ }
89
+ } catch (e) {
90
+ console.error(`[PortChecker] 系统命令检查端口失败: ${e.message}`);
91
+ }
92
+ return false;
93
+ }
94
+
95
+ /**
96
+ * 检查 openclaw 进程是否存在
97
+ */
98
+ function checkProcessExists() {
99
+ try {
100
+ // 尝试多种方法检查进程
101
+ const commands = [
102
+ 'ps aux | grep -v grep | grep openclaw',
103
+ 'pgrep -f openclaw',
104
+ 'pidof openclaw'
105
+ ];
106
+
107
+ for (const cmd of commands) {
108
+ try {
109
+ const output = execSync(cmd, {
110
+ encoding: 'utf8',
111
+ timeout: 5000
112
+ }).trim();
113
+
114
+ if (output) {
115
+ console.log(`[PortChecker] 检测到 openclaw 进程存在 (通过: ${cmd.split(' ')[0]})`);
116
+ console.log(`[PortChecker] 进程信息: ${output.split('\n')[0]}`);
117
+ return true;
118
+ }
119
+ } catch (e) {
120
+ // 命令失败,尝试下一个
121
+ }
122
+ }
123
+
124
+ console.log(`[PortChecker] 未检测到 openclaw 进程`);
125
+ } catch (e) {
126
+ console.error(`[PortChecker] 进程检查失败: ${e.message}`);
127
+ }
128
+ return false;
129
+ }
130
+
54
131
  async function getOpenClawStatus(port = 18789) {
132
+ // 方法1: 通过 net.Socket 检查端口
55
133
  const isListening = await checkPortOnAllInterfaces(port);
56
- return isListening ? 1 : 0;
134
+ if (isListening) {
135
+ console.log(`[PortChecker] 端口 ${port} 检测为运行中(net.Socket)`);
136
+ return 1;
137
+ }
138
+
139
+ // 方法2: 通过系统命令检查端口
140
+ const isListeningViaCmd = checkPortViaSystemCommand(port);
141
+ if (isListeningViaCmd) {
142
+ console.log(`[PortChecker] 端口 ${port} 检测为运行中(系统命令)`);
143
+ return 1;
144
+ }
145
+
146
+ // 方法3: 检查进程是否存在(备选)
147
+ const processExists = checkProcessExists();
148
+ if (processExists) {
149
+ console.warn(`[PortChecker] 警告: openclaw 进程存在,但端口 ${port} 未监听。可能绑定到其他端口或地址。`);
150
+ // 进程存在但端口未监听,返回特殊状态 2
151
+ return 2;
152
+ }
153
+
154
+ console.log(`[PortChecker] 端口 ${port} 检测为未运行`);
155
+ return 0;
57
156
  }
58
157
 
59
158
  module.exports = {
@@ -326,9 +326,20 @@ class RongyunMessageHandler {
326
326
  // 获取 OpenClaw 运行状态(检查端口 18789)
327
327
  const openClawStatus = await getOpenClawStatus();
328
328
 
329
- // 构建精简状态数据(避免超过融云 128KB 限制)
329
+ // 构建状态数据
330
+ // openClawStatus: 1=端口监听正常, 2=进程存在但端口未监听, 0=未运行
331
+ let statusMessage;
332
+ if (openClawStatus === 1) {
333
+ statusMessage = '运行中';
334
+ } else if (openClawStatus === 2) {
335
+ statusMessage = '运行中(端口异常)';
336
+ } else {
337
+ statusMessage = '未运行';
338
+ }
339
+
330
340
  const statusData = {
331
- open_claw_status: openClawStatus, // 1=运行中, 0=未运行
341
+ open_claw_status: openClawStatus, // 1=运行中, 2=进程存在但端口未监听, 0=未运行
342
+ status_message: statusMessage,
332
343
  mac_address: getMacAddress(),
333
344
  version: '0.0.20',
334
345
  timestamp: Date.now(),