claw-subagent-service 0.0.50 → 0.0.52
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
|
@@ -111,8 +111,13 @@ function getGatewayToken() {
|
|
|
111
111
|
if (fs.existsSync(filePath)) {
|
|
112
112
|
const content = fs.readFileSync(filePath, 'utf-8');
|
|
113
113
|
const config = JSON.parse(content);
|
|
114
|
-
// 可能的 token
|
|
115
|
-
const token = config.gatewayToken
|
|
114
|
+
// 可能的 token 字段名(支持嵌套路径 gateway.auth.token)
|
|
115
|
+
const token = config.gatewayToken
|
|
116
|
+
|| (config.gateway?.auth?.token)
|
|
117
|
+
|| config.token
|
|
118
|
+
|| config.apiKey
|
|
119
|
+
|| config.api_key
|
|
120
|
+
|| config.password;
|
|
116
121
|
if (token) {
|
|
117
122
|
return String(token);
|
|
118
123
|
}
|
|
@@ -191,6 +196,30 @@ function startOpenClawGateway(log) {
|
|
|
191
196
|
}
|
|
192
197
|
|
|
193
198
|
class OpenClawClient {
|
|
199
|
+
// 全局并发限制:同时最多运行 N 个 openclaw agent 进程
|
|
200
|
+
static maxConcurrency = 2;
|
|
201
|
+
static runningCount = 0;
|
|
202
|
+
static waitQueue = [];
|
|
203
|
+
// Session 级串行锁:确保同一 session 不会并发 spawn 多个进程
|
|
204
|
+
static sessionLocks = new Map();
|
|
205
|
+
|
|
206
|
+
static async acquireSlot() {
|
|
207
|
+
if (OpenClawClient.runningCount < OpenClawClient.maxConcurrency) {
|
|
208
|
+
OpenClawClient.runningCount++;
|
|
209
|
+
return;
|
|
210
|
+
}
|
|
211
|
+
return new Promise(resolve => OpenClawClient.waitQueue.push(resolve));
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
static releaseSlot() {
|
|
215
|
+
OpenClawClient.runningCount--;
|
|
216
|
+
if (OpenClawClient.waitQueue.length > 0) {
|
|
217
|
+
const next = OpenClawClient.waitQueue.shift();
|
|
218
|
+
OpenClawClient.runningCount++;
|
|
219
|
+
next();
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
|
|
194
223
|
constructor(log) {
|
|
195
224
|
this.log = log;
|
|
196
225
|
this.gatewayStarting = false;
|
|
@@ -255,6 +284,35 @@ class OpenClawClient {
|
|
|
255
284
|
|
|
256
285
|
async chatViaCLI(message, fromUser) {
|
|
257
286
|
const sessionId = `clawmessenger-${fromUser}`;
|
|
287
|
+
|
|
288
|
+
// 1. Session 级串行锁:同一用户的消息排队执行,避免多个进程竞争同一 session 文件
|
|
289
|
+
const previousLock = OpenClawClient.sessionLocks.get(sessionId);
|
|
290
|
+
let resolveLock;
|
|
291
|
+
const currentLock = new Promise(r => { resolveLock = r; });
|
|
292
|
+
OpenClawClient.sessionLocks.set(sessionId, currentLock);
|
|
293
|
+
if (previousLock) {
|
|
294
|
+
this.log?.info(`[OpenClawClient] session ${sessionId} 正在处理中,排队等待...`);
|
|
295
|
+
await previousLock;
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
// 2. 全局并发槽位限制:所有实例共享,防止服务器资源耗尽
|
|
299
|
+
await OpenClawClient.acquireSlot();
|
|
300
|
+
this.log?.info(`[OpenClawClient] 获得执行槽位 (当前运行: ${OpenClawClient.runningCount}/${OpenClawClient.maxConcurrency})`);
|
|
301
|
+
|
|
302
|
+
try {
|
|
303
|
+
return await this._runAgentCLI(message, fromUser, sessionId);
|
|
304
|
+
} finally {
|
|
305
|
+
OpenClawClient.releaseSlot();
|
|
306
|
+
this.log?.info(`[OpenClawClient] 释放执行槽位 (当前运行: ${OpenClawClient.runningCount}/${OpenClawClient.maxConcurrency})`);
|
|
307
|
+
// 释放 session 锁
|
|
308
|
+
resolveLock();
|
|
309
|
+
if (OpenClawClient.sessionLocks.get(sessionId) === currentLock) {
|
|
310
|
+
OpenClawClient.sessionLocks.delete(sessionId);
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
_runAgentCLI(message, fromUser, sessionId) {
|
|
258
316
|
const escapedMessage = message
|
|
259
317
|
.replace(/\\/g, '\\\\')
|
|
260
318
|
.replace(/"/g, '\\"')
|