openclaw-lark-multi-agent 1.0.9 → 1.0.11
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/dist/openclaw-client.d.ts +9 -0
- package/dist/openclaw-client.js +52 -10
- package/package.json +1 -1
|
@@ -36,6 +36,13 @@ export declare class OpenClawClient {
|
|
|
36
36
|
/** Session keys whose proactive messages must be dropped by the bridge (e.g. discussion scheduler owns delivery). */
|
|
37
37
|
private mutedProactiveSessions;
|
|
38
38
|
private mutedProactiveSessionCounts;
|
|
39
|
+
/** Global limiter for chat.send RPC calls; large multi-bot fan-out can
|
|
40
|
+
* saturate the Gateway before collectReply even starts. The slot is released
|
|
41
|
+
* as soon as the chat.send RPC returns a runId; collectReply does not hold it.
|
|
42
|
+
*/
|
|
43
|
+
private chatSendConcurrency;
|
|
44
|
+
private activeChatSends;
|
|
45
|
+
private chatSendWaiters;
|
|
39
46
|
constructor(config: OpenClawConfig);
|
|
40
47
|
connect(): Promise<void>;
|
|
41
48
|
private _doConnect;
|
|
@@ -92,6 +99,8 @@ export declare class OpenClawClient {
|
|
|
92
99
|
private addMutedProactiveKey;
|
|
93
100
|
private releaseMutedProactiveKey;
|
|
94
101
|
muteProactiveDelivery(sessionKey: string): (delayMs?: number) => void;
|
|
102
|
+
private acquireChatSendSlot;
|
|
103
|
+
private releaseChatSendSlot;
|
|
95
104
|
chatSend(params: {
|
|
96
105
|
sessionKey: string;
|
|
97
106
|
message: string;
|
package/dist/openclaw-client.js
CHANGED
|
@@ -37,6 +37,13 @@ export class OpenClawClient {
|
|
|
37
37
|
/** Session keys whose proactive messages must be dropped by the bridge (e.g. discussion scheduler owns delivery). */
|
|
38
38
|
mutedProactiveSessions = new Set();
|
|
39
39
|
mutedProactiveSessionCounts = new Map();
|
|
40
|
+
/** Global limiter for chat.send RPC calls; large multi-bot fan-out can
|
|
41
|
+
* saturate the Gateway before collectReply even starts. The slot is released
|
|
42
|
+
* as soon as the chat.send RPC returns a runId; collectReply does not hold it.
|
|
43
|
+
*/
|
|
44
|
+
chatSendConcurrency = Number(process.env.OPENCLAW_LARK_MULTI_AGENT_CHAT_SEND_CONCURRENCY || 3);
|
|
45
|
+
activeChatSends = 0;
|
|
46
|
+
chatSendWaiters = [];
|
|
40
47
|
constructor(config) {
|
|
41
48
|
this.config = config;
|
|
42
49
|
}
|
|
@@ -606,12 +613,22 @@ export class OpenClawClient {
|
|
|
606
613
|
}
|
|
607
614
|
if (!latestFinalText) {
|
|
608
615
|
const failureText = buildFailureText(ev);
|
|
609
|
-
|
|
616
|
+
const state = ev.data?.livenessState || "";
|
|
617
|
+
const reason = ev.data?.stopReason || "";
|
|
618
|
+
// replayInvalid, cancelled/rpc, and abandoned are often
|
|
619
|
+
// transient runtime states — the real reply may still arrive
|
|
620
|
+
// shortly after via session.message or a subsequent run.
|
|
621
|
+
// Defer the failure instead of finishing immediately.
|
|
622
|
+
const isTransient = ev.data?.replayInvalid
|
|
623
|
+
|| state === "cancelled"
|
|
624
|
+
|| state === "abandoned"
|
|
625
|
+
|| reason === "rpc";
|
|
626
|
+
if (isTransient) {
|
|
610
627
|
pendingRuntimeFailureText = failureText;
|
|
611
|
-
console.warn(`[OpenClaw]
|
|
628
|
+
console.warn(`[OpenClaw] transient lifecycle end (${state}, reason=${reason}) for runId=${evRunId || runId}; waiting for real text or idle timeout`);
|
|
612
629
|
return;
|
|
613
630
|
}
|
|
614
|
-
if (
|
|
631
|
+
if (state !== "working") {
|
|
615
632
|
finish(failureText);
|
|
616
633
|
return;
|
|
617
634
|
}
|
|
@@ -827,6 +844,24 @@ export class OpenClawClient {
|
|
|
827
844
|
release();
|
|
828
845
|
};
|
|
829
846
|
}
|
|
847
|
+
async acquireChatSendSlot() {
|
|
848
|
+
const limit = Math.max(1, this.chatSendConcurrency || 1);
|
|
849
|
+
if (this.activeChatSends < limit) {
|
|
850
|
+
this.activeChatSends++;
|
|
851
|
+
return () => this.releaseChatSendSlot();
|
|
852
|
+
}
|
|
853
|
+
const startedWaitingAt = Date.now();
|
|
854
|
+
await new Promise((resolve) => this.chatSendWaiters.push(resolve));
|
|
855
|
+
this.activeChatSends++;
|
|
856
|
+
console.log(`[OpenClaw] chat.send waited ${Date.now() - startedWaitingAt}ms for concurrency slot (active=${this.activeChatSends}/${limit})`);
|
|
857
|
+
return () => this.releaseChatSendSlot();
|
|
858
|
+
}
|
|
859
|
+
releaseChatSendSlot() {
|
|
860
|
+
this.activeChatSends = Math.max(0, this.activeChatSends - 1);
|
|
861
|
+
const next = this.chatSendWaiters.shift();
|
|
862
|
+
if (next)
|
|
863
|
+
next();
|
|
864
|
+
}
|
|
830
865
|
async chatSend(params) {
|
|
831
866
|
const sk = params.sessionKey;
|
|
832
867
|
const fullSessionKey = `agent:main:${sk}`;
|
|
@@ -839,14 +874,21 @@ export class OpenClawClient {
|
|
|
839
874
|
// the next message while still allowing sessionKey matching for internal runIds.
|
|
840
875
|
this.agentEvents.set(fullSessionKey, []);
|
|
841
876
|
this.agentEvents.set(sk, []);
|
|
877
|
+
const releaseChatSendSlot = await this.acquireChatSendSlot();
|
|
878
|
+
let result;
|
|
842
879
|
const sendStartedAt = Date.now();
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
880
|
+
try {
|
|
881
|
+
result = await this.rpc("chat.send", {
|
|
882
|
+
sessionKey: sk,
|
|
883
|
+
message: params.message,
|
|
884
|
+
attachments: params.attachments,
|
|
885
|
+
deliver: params.deliver ?? false,
|
|
886
|
+
idempotencyKey: randomUUID(),
|
|
887
|
+
});
|
|
888
|
+
}
|
|
889
|
+
finally {
|
|
890
|
+
releaseChatSendSlot();
|
|
891
|
+
}
|
|
850
892
|
console.log(`[OpenClaw] chat.send runId: ${result.runId} (rpc=${Date.now() - sendStartedAt}ms, attachments=${params.attachments?.length || 0})`);
|
|
851
893
|
return await this.collectReply(result.runId, params.timeoutMs || 1800000, sk, { emptyFinalAsNoReply: params.emptyFinalAsNoReply, expectedUserText: params.message });
|
|
852
894
|
}
|