claw-subagent-service 0.0.27 → 0.0.28
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
|
@@ -122,9 +122,6 @@ class MessageHandler {
|
|
|
122
122
|
this.sendReadReceiptFn(msg).catch(() => {});
|
|
123
123
|
}
|
|
124
124
|
|
|
125
|
-
// 先回复"正在处理",让用户知道消息已被接收
|
|
126
|
-
this.sendFn(targetId, '🤖 正在思考中,请稍候...', msg.conversationType).catch(() => {});
|
|
127
|
-
|
|
128
125
|
// 后台执行 openclaw,不阻塞消息队列
|
|
129
126
|
this.openclawClient.chat(msg.content, msg.senderUserId)
|
|
130
127
|
.then(reply => {
|
|
@@ -93,6 +93,38 @@ function getOpenClawEnv(baseEnv = process.env) {
|
|
|
93
93
|
return env;
|
|
94
94
|
}
|
|
95
95
|
|
|
96
|
+
/**
|
|
97
|
+
* 尝试读取 OpenClaw 的 gateway token
|
|
98
|
+
* openclaw agent 连接 gateway 需要认证,token 通常存储在配置文件中
|
|
99
|
+
*/
|
|
100
|
+
function getGatewayToken() {
|
|
101
|
+
const homeDir = getRealHomeDir();
|
|
102
|
+
const possibleFiles = [
|
|
103
|
+
path.join(homeDir, '.openclaw', 'openclaw.json'),
|
|
104
|
+
path.join(homeDir, '.openclaw', 'config.json'),
|
|
105
|
+
path.join(homeDir, '.openclaw', 'tools.json'),
|
|
106
|
+
path.join(homeDir, '.openclaw', 'settings.json'),
|
|
107
|
+
];
|
|
108
|
+
|
|
109
|
+
for (const filePath of possibleFiles) {
|
|
110
|
+
try {
|
|
111
|
+
if (fs.existsSync(filePath)) {
|
|
112
|
+
const content = fs.readFileSync(filePath, 'utf-8');
|
|
113
|
+
const config = JSON.parse(content);
|
|
114
|
+
// 可能的 token 字段名
|
|
115
|
+
const token = config.gatewayToken || config.token || config.apiKey || config.api_key || config.password;
|
|
116
|
+
if (token) {
|
|
117
|
+
return String(token);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
} catch {
|
|
121
|
+
// 忽略读取/解析错误
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
return null;
|
|
126
|
+
}
|
|
127
|
+
|
|
96
128
|
/**
|
|
97
129
|
* 检测端口是否监听
|
|
98
130
|
*/
|
|
@@ -139,10 +171,9 @@ function startOpenClawGateway(log) {
|
|
|
139
171
|
const interval = setInterval(async () => {
|
|
140
172
|
attempts++;
|
|
141
173
|
const gatewayRunning = await checkPort(18789);
|
|
142
|
-
const apiRunning = await checkPort(5678);
|
|
143
174
|
if (gatewayRunning) {
|
|
144
175
|
clearInterval(interval);
|
|
145
|
-
log?.info(
|
|
176
|
+
log?.info('[OpenClawClient] OpenClaw gateway 启动成功 (18789)');
|
|
146
177
|
resolve(true);
|
|
147
178
|
} else if (attempts >= maxAttempts) {
|
|
148
179
|
clearInterval(interval);
|
|
@@ -173,30 +204,13 @@ class OpenClawClient {
|
|
|
173
204
|
if (this.gatewayStarted) return true;
|
|
174
205
|
|
|
175
206
|
const gatewayRunning = await checkPort(18789);
|
|
176
|
-
const apiRunning = await checkPort(5678);
|
|
177
207
|
|
|
178
|
-
if (gatewayRunning
|
|
179
|
-
this.log?.info('[OpenClawClient] OpenClaw gateway
|
|
208
|
+
if (gatewayRunning) {
|
|
209
|
+
this.log?.info('[OpenClawClient] OpenClaw gateway 已在运行 (18789)');
|
|
180
210
|
this.gatewayStarted = true;
|
|
181
211
|
return true;
|
|
182
212
|
}
|
|
183
213
|
|
|
184
|
-
if (gatewayRunning && !apiRunning) {
|
|
185
|
-
this.log?.info('[OpenClawClient] gateway 已运行 (18789),但 API (5678) 未就绪,继续等待...');
|
|
186
|
-
// 等待最多 10 秒让 API 就绪
|
|
187
|
-
for (let i = 0; i < 10; i++) {
|
|
188
|
-
await new Promise(r => setTimeout(r, 1000));
|
|
189
|
-
if (await checkPort(5678)) {
|
|
190
|
-
this.log?.info('[OpenClawClient] API (5678) 已就绪');
|
|
191
|
-
this.gatewayStarted = true;
|
|
192
|
-
return true;
|
|
193
|
-
}
|
|
194
|
-
}
|
|
195
|
-
this.log?.warn('[OpenClawClient] API (5678) 等待超时,gateway 可能未完全初始化');
|
|
196
|
-
// gateway 在运行但 API 没好,仍然允许继续,让 HTTP fallback 到 CLI
|
|
197
|
-
return true;
|
|
198
|
-
}
|
|
199
|
-
|
|
200
214
|
// 避免并发启动
|
|
201
215
|
if (this.gatewayStarting) {
|
|
202
216
|
this.log?.info('[OpenClawClient] gateway 正在启动中,等待...');
|
|
@@ -284,25 +298,33 @@ class OpenClawClient {
|
|
|
284
298
|
.replace(/\n/g, ' ')
|
|
285
299
|
.replace(/\r/g, ' ');
|
|
286
300
|
|
|
287
|
-
const gatewayUrl = 'http://127.0.0.1:5678';
|
|
288
301
|
const realHome = getRealHomeDir();
|
|
289
302
|
this.log?.info(`[OpenClawClient] 使用用户目录: ${realHome}`);
|
|
290
303
|
|
|
304
|
+
// 尝试读取 gateway token,解决 SYSTEM 账户下认证问题
|
|
305
|
+
const gatewayToken = getGatewayToken();
|
|
306
|
+
if (gatewayToken) {
|
|
307
|
+
this.log?.info('[OpenClawClient] 已读取到 gateway token');
|
|
308
|
+
}
|
|
309
|
+
|
|
291
310
|
const args = ['agent', '-m', escapedMessage, '--session-id', sessionId];
|
|
292
|
-
|
|
311
|
+
if (gatewayToken) {
|
|
312
|
+
args.push('--token', gatewayToken);
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
this.log?.info(`[OpenClawClient] 执行: openclaw ${args.map(a => a.includes(' ') ? `"${a}"` : a).join(' ')}`);
|
|
293
316
|
|
|
294
317
|
return new Promise((resolve) => {
|
|
295
318
|
let stdout = '';
|
|
296
319
|
let stderr = '';
|
|
297
320
|
let killed = false;
|
|
298
321
|
|
|
322
|
+
// 关键:不设置 OPENCLAW_GATEWAY_URL,避免触发 "gateway url override requires explicit credentials"
|
|
323
|
+
// 让 openclaw agent 通过默认方式自动发现本地 gateway
|
|
299
324
|
const child = spawn('openclaw', args, {
|
|
300
325
|
shell: true,
|
|
301
326
|
windowsHide: true,
|
|
302
|
-
env:
|
|
303
|
-
...getOpenClawEnv(),
|
|
304
|
-
OPENCLAW_GATEWAY_URL: gatewayUrl,
|
|
305
|
-
},
|
|
327
|
+
env: getOpenClawEnv(),
|
|
306
328
|
});
|
|
307
329
|
|
|
308
330
|
this.log?.info(`[OpenClawClient] CLI 子进程 PID=${child.pid}`);
|
|
@@ -314,15 +336,15 @@ class OpenClawClient {
|
|
|
314
336
|
const text = chunk.toString();
|
|
315
337
|
stderr += text;
|
|
316
338
|
// 实时记录 stderr,方便调试卡死问题
|
|
317
|
-
this.log?.info(`[OpenClawClient] CLI stderr: ${text.trim().substring(0,
|
|
339
|
+
this.log?.info(`[OpenClawClient] CLI stderr: ${text.trim().substring(0, 300)}`);
|
|
318
340
|
});
|
|
319
341
|
|
|
320
|
-
// 超时兜底(
|
|
342
|
+
// 超时兜底(30 秒)
|
|
321
343
|
const timeout = setTimeout(() => {
|
|
322
344
|
killed = true;
|
|
323
345
|
child.kill('SIGTERM');
|
|
324
|
-
this.log?.error('[OpenClawClient] CLI 执行超时(
|
|
325
|
-
},
|
|
346
|
+
this.log?.error('[OpenClawClient] CLI 执行超时(30秒),强制终止');
|
|
347
|
+
}, 30000);
|
|
326
348
|
|
|
327
349
|
child.on('error', (err) => {
|
|
328
350
|
clearTimeout(timeout);
|
|
@@ -338,7 +360,7 @@ class OpenClawClient {
|
|
|
338
360
|
clearTimeout(timeout);
|
|
339
361
|
|
|
340
362
|
if (killed) {
|
|
341
|
-
resolve('OpenClaw
|
|
363
|
+
resolve('OpenClaw 响应超时(30秒),请检查 openclaw 服务状态');
|
|
342
364
|
return;
|
|
343
365
|
}
|
|
344
366
|
|
|
@@ -348,7 +370,7 @@ class OpenClawClient {
|
|
|
348
370
|
if (code !== 0) {
|
|
349
371
|
const errOutput = stderr || stdout || '';
|
|
350
372
|
this.log?.error(`[OpenClawClient] CLI 错误输出: ${errOutput.substring(0, 500)}`);
|
|
351
|
-
resolve(`OpenClaw
|
|
373
|
+
resolve(`OpenClaw 调用失败: ${errOutput.substring(0, 200)}`);
|
|
352
374
|
return;
|
|
353
375
|
}
|
|
354
376
|
|