claw-subagent-service 0.0.89 → 0.0.90
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
|
@@ -85,31 +85,45 @@ async function manageWithServiceManager(command) {
|
|
|
85
85
|
|
|
86
86
|
/**
|
|
87
87
|
* 使用 ScriptExecutor 执行脚本(Docker 模式)
|
|
88
|
+
* @returns {Object} { result, output }
|
|
88
89
|
*/
|
|
89
90
|
async function executeWithScript(command) {
|
|
90
91
|
const executor = getExecutor();
|
|
91
92
|
const scriptName = getScriptName(command);
|
|
92
93
|
|
|
93
94
|
try {
|
|
94
|
-
|
|
95
|
+
const result = await executor.executeWithStatus(command, scriptName);
|
|
96
|
+
// ScriptExecutor 现在返回 { status, message, output }
|
|
97
|
+
return {
|
|
98
|
+
result: { status: result.status, message: result.message },
|
|
99
|
+
output: result.output || ''
|
|
100
|
+
};
|
|
95
101
|
} catch (e) {
|
|
96
102
|
const msg = e instanceof Error ? e.message : String(e);
|
|
97
103
|
console.log(`[OpenClawControl] 脚本执行异常: ${msg}`);
|
|
98
104
|
return {
|
|
99
|
-
|
|
100
|
-
|
|
105
|
+
result: {
|
|
106
|
+
status: OpenClawServiceStatus.ERROR,
|
|
107
|
+
message: `执行异常: ${msg}`
|
|
108
|
+
},
|
|
109
|
+
output: ''
|
|
101
110
|
};
|
|
102
111
|
}
|
|
103
112
|
}
|
|
104
113
|
|
|
105
114
|
/**
|
|
106
115
|
* 验证命令执行结果
|
|
116
|
+
*
|
|
117
|
+
* 注意:在 Docker 环境中,端口检查可能不可靠(服务可能绑定到特定网络接口)
|
|
118
|
+
* 因此,如果脚本输出明确指示成功,但端口检查失败,会给出警告但保留脚本结果
|
|
107
119
|
*/
|
|
108
|
-
async function verifyCommandResult(command, result) {
|
|
120
|
+
async function verifyCommandResult(command, result, scriptOutput = '') {
|
|
109
121
|
if (result.status === OpenClawServiceStatus.ERROR) {
|
|
110
122
|
return result;
|
|
111
123
|
}
|
|
112
124
|
|
|
125
|
+
const outputUpper = (scriptOutput || '').toUpperCase();
|
|
126
|
+
|
|
113
127
|
if (command === OpenClawCommandEnum.STOP) {
|
|
114
128
|
// 等待 3 秒后验证端口
|
|
115
129
|
await new Promise(resolve => setTimeout(resolve, 3000));
|
|
@@ -117,6 +131,15 @@ async function verifyCommandResult(command, result) {
|
|
|
117
131
|
console.log(`[OpenClawControl] 停止后端口状态: ${portStatus === 1 ? '运行中' : '未运行'}`);
|
|
118
132
|
|
|
119
133
|
if (portStatus === 1) {
|
|
134
|
+
// 端口仍在监听,但检查脚本是否报告已停止
|
|
135
|
+
if (outputUpper.includes('SUCCESS') || outputUpper.includes('STOPPED')) {
|
|
136
|
+
console.warn(`[OpenClawControl] 警告: 端口仍在监听,但脚本报告成功。可能是僵尸进程或服务未正确停止。`);
|
|
137
|
+
// 仍然返回成功,但附带警告信息
|
|
138
|
+
return {
|
|
139
|
+
status: result.status,
|
|
140
|
+
message: result.message + ' (警告: 端口仍在监听)'
|
|
141
|
+
};
|
|
142
|
+
}
|
|
120
143
|
return {
|
|
121
144
|
status: OpenClawServiceStatus.ERROR,
|
|
122
145
|
message: '停止失败: 服务仍在运行'
|
|
@@ -138,6 +161,15 @@ async function verifyCommandResult(command, result) {
|
|
|
138
161
|
console.log(`[OpenClawControl] ${getCommandName(command)}后端口状态: ${portStatus === 1 ? '运行中' : '未运行'}`);
|
|
139
162
|
|
|
140
163
|
if (portStatus === 0) {
|
|
164
|
+
// 端口未监听,但检查脚本是否报告成功(可能是服务绑定到其他接口)
|
|
165
|
+
if (outputUpper.includes('SUCCESS') || outputUpper.includes('ALREADY RUNNING')) {
|
|
166
|
+
console.warn(`[OpenClawControl] 警告: 端口检查失败,但脚本报告成功。服务可能绑定到其他网络接口。`);
|
|
167
|
+
// 信任脚本结果,但添加警告
|
|
168
|
+
return {
|
|
169
|
+
status: result.status,
|
|
170
|
+
message: result.message + ' (警告: 端口检查可能不准确)'
|
|
171
|
+
};
|
|
172
|
+
}
|
|
141
173
|
return {
|
|
142
174
|
status: OpenClawServiceStatus.ERROR,
|
|
143
175
|
message: `${getCommandName(command)}失败: 服务未运行`
|
|
@@ -160,12 +192,15 @@ async function executeCommand(command, window, sendResponse) {
|
|
|
160
192
|
}
|
|
161
193
|
|
|
162
194
|
// 如果 ServiceManager 失败或不是 Linux/macOS,使用脚本方式
|
|
195
|
+
let scriptOutput = '';
|
|
163
196
|
if (!result) {
|
|
164
|
-
|
|
197
|
+
const scriptResult = await executeWithScript(command);
|
|
198
|
+
result = scriptResult.result;
|
|
199
|
+
scriptOutput = scriptResult.output;
|
|
165
200
|
}
|
|
166
201
|
|
|
167
|
-
//
|
|
168
|
-
result = await verifyCommandResult(command, result);
|
|
202
|
+
// 验证结果(传递脚本输出用于后备检查)
|
|
203
|
+
result = await verifyCommandResult(command, result, scriptOutput);
|
|
169
204
|
|
|
170
205
|
// 输出日志
|
|
171
206
|
if (result.status === OpenClawServiceStatus.START_SUCCESS ||
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
const net = require('net');
|
|
2
|
+
const os = require('os');
|
|
2
3
|
|
|
3
|
-
function checkPortListening(port) {
|
|
4
|
+
function checkPortListening(port, host = '127.0.0.1') {
|
|
4
5
|
return new Promise((resolve) => {
|
|
5
6
|
const sock = new net.Socket();
|
|
6
7
|
sock.setTimeout(3000);
|
|
@@ -16,16 +17,47 @@ function checkPortListening(port) {
|
|
|
16
17
|
sock.destroy();
|
|
17
18
|
resolve(false);
|
|
18
19
|
});
|
|
19
|
-
sock.connect(port,
|
|
20
|
+
sock.connect(port, host);
|
|
20
21
|
});
|
|
21
22
|
}
|
|
22
23
|
|
|
24
|
+
/**
|
|
25
|
+
* 检查端口是否在所有网络接口上监听
|
|
26
|
+
* Docker 环境中,服务可能绑定到 0.0.0.0 而不是 127.0.0.1
|
|
27
|
+
*/
|
|
28
|
+
async function checkPortOnAllInterfaces(port) {
|
|
29
|
+
// 先检查 localhost
|
|
30
|
+
const localhostListening = await checkPortListening(port, '127.0.0.1');
|
|
31
|
+
if (localhostListening) return true;
|
|
32
|
+
|
|
33
|
+
// 再检查 0.0.0.0(所有接口)
|
|
34
|
+
const allInterfacesListening = await checkPortListening(port, '0.0.0.0');
|
|
35
|
+
if (allInterfacesListening) return true;
|
|
36
|
+
|
|
37
|
+
// 获取所有网络接口并逐一检查
|
|
38
|
+
const interfaces = os.networkInterfaces();
|
|
39
|
+
for (const [name, addrs] of Object.entries(interfaces)) {
|
|
40
|
+
for (const addr of addrs) {
|
|
41
|
+
if (addr.family === 'IPv4' && !addr.internal) {
|
|
42
|
+
const listening = await checkPortListening(port, addr.address);
|
|
43
|
+
if (listening) {
|
|
44
|
+
console.log(`[PortChecker] 端口 ${port} 在 ${addr.address} (${name}) 上监听`);
|
|
45
|
+
return true;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
return false;
|
|
52
|
+
}
|
|
53
|
+
|
|
23
54
|
async function getOpenClawStatus(port = 18789) {
|
|
24
|
-
const isListening = await
|
|
55
|
+
const isListening = await checkPortOnAllInterfaces(port);
|
|
25
56
|
return isListening ? 1 : 0;
|
|
26
57
|
}
|
|
27
58
|
|
|
28
59
|
module.exports = {
|
|
29
60
|
checkPortListening,
|
|
61
|
+
checkPortOnAllInterfaces,
|
|
30
62
|
getOpenClawStatus,
|
|
31
63
|
};
|
|
@@ -103,11 +103,16 @@ class ScriptExecutor {
|
|
|
103
103
|
console.log(`[ScriptExecutor] 停止脚本退出码非零(${exitCode}),返回错误`);
|
|
104
104
|
return {
|
|
105
105
|
status: OpenClawServiceStatus.ERROR,
|
|
106
|
-
message: `停止失败: 脚本退出码 ${exitCode}
|
|
106
|
+
message: `停止失败: 脚本退出码 ${exitCode}`,
|
|
107
|
+
output: fullOutput
|
|
107
108
|
};
|
|
108
109
|
}
|
|
109
110
|
|
|
110
|
-
|
|
111
|
+
// 返回结果时附带原始输出
|
|
112
|
+
return {
|
|
113
|
+
...result,
|
|
114
|
+
output: fullOutput
|
|
115
|
+
};
|
|
111
116
|
} catch (e) {
|
|
112
117
|
const msg = e instanceof Error ? e.message : String(e);
|
|
113
118
|
return { status: OpenClawServiceStatus.ERROR, message: `执行异常: ${msg}` };
|