openclaw-quiubo 2.6.9 → 2.6.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/index.js
CHANGED
|
@@ -12470,6 +12470,11 @@ var RealtimeGateway = class {
|
|
|
12470
12470
|
pollTimer = null;
|
|
12471
12471
|
polling = false;
|
|
12472
12472
|
cursors = /* @__PURE__ */ new Map();
|
|
12473
|
+
/** Message IDs already dispatched (Pusher + poll dedup). Capped to prevent unbounded growth. */
|
|
12474
|
+
dispatched = /* @__PURE__ */ new Set();
|
|
12475
|
+
// Cached directory group IDs from listAgentGroups (refreshed every 60s)
|
|
12476
|
+
agentGroupsCache = null;
|
|
12477
|
+
AGENT_GROUPS_TTL = 6e4;
|
|
12473
12478
|
// Bot config cache (per group)
|
|
12474
12479
|
botConfigCache = /* @__PURE__ */ new Map();
|
|
12475
12480
|
// Owner takeover suppression: groupId → suppressedUntil timestamp
|
|
@@ -12503,6 +12508,13 @@ var RealtimeGateway = class {
|
|
|
12503
12508
|
setBotConfig(groupId, config) {
|
|
12504
12509
|
this.botConfigCache.set(groupId, config);
|
|
12505
12510
|
}
|
|
12511
|
+
/** Track a dispatched message ID (capped at 500 to prevent unbounded growth) */
|
|
12512
|
+
markDispatched(messageId) {
|
|
12513
|
+
this.dispatched.add(messageId);
|
|
12514
|
+
if (this.dispatched.size > 500) {
|
|
12515
|
+
this.dispatched.clear();
|
|
12516
|
+
}
|
|
12517
|
+
}
|
|
12506
12518
|
/** Get bot config for a group (for outbound scope checks) */
|
|
12507
12519
|
getBotConfig(groupId) {
|
|
12508
12520
|
return this.botConfigCache.get(groupId);
|
|
@@ -12757,10 +12769,12 @@ var RealtimeGateway = class {
|
|
|
12757
12769
|
agentDisplayName: this.agentDisplayName ?? void 0,
|
|
12758
12770
|
securityMode: data.securityMode
|
|
12759
12771
|
});
|
|
12772
|
+
this.agentGroupsCache = null;
|
|
12760
12773
|
});
|
|
12761
12774
|
channel.bind("agent:group-removed", (data) => {
|
|
12762
12775
|
log.info?.(`agent:group-removed for group ${data.groupId}`);
|
|
12763
12776
|
this.botConfigCache.delete(data.groupId);
|
|
12777
|
+
this.agentGroupsCache = null;
|
|
12764
12778
|
});
|
|
12765
12779
|
channel.bind_global((eventName, data) => {
|
|
12766
12780
|
console.log(`[gw:pusher:raw] event=${eventName} data=${JSON.stringify(data).slice(0, 200)}`);
|
|
@@ -12781,6 +12795,7 @@ var RealtimeGateway = class {
|
|
|
12781
12795
|
if (!shouldProcess) return;
|
|
12782
12796
|
if (data.plaintext) {
|
|
12783
12797
|
this.cursors.set(data.groupId, data.messageId);
|
|
12798
|
+
this.markDispatched(data.messageId);
|
|
12784
12799
|
Promise.resolve(this.onMessage({
|
|
12785
12800
|
messageId: data.messageId,
|
|
12786
12801
|
groupId: data.groupId,
|
|
@@ -12808,6 +12823,7 @@ var RealtimeGateway = class {
|
|
|
12808
12823
|
const plaintext = decryptGroupMessage(data.ciphertext, cached.key);
|
|
12809
12824
|
log.info?.(`[e2ee:pusher] group=${data.groupId} decrypted OK: ${plaintext?.length} chars \u2014 routing to onMessage`);
|
|
12810
12825
|
this.cursors.set(data.groupId, data.messageId);
|
|
12826
|
+
this.markDispatched(data.messageId);
|
|
12811
12827
|
return Promise.resolve(this.onMessage({
|
|
12812
12828
|
messageId: data.messageId,
|
|
12813
12829
|
groupId: data.groupId,
|
|
@@ -12859,6 +12875,8 @@ var RealtimeGateway = class {
|
|
|
12859
12875
|
this.log.warn?.(`Message ${messageId} has no plaintext`);
|
|
12860
12876
|
return;
|
|
12861
12877
|
}
|
|
12878
|
+
if (this.dispatched.has(msg.id)) return;
|
|
12879
|
+
this.markDispatched(msg.id);
|
|
12862
12880
|
await this.onMessage({
|
|
12863
12881
|
messageId: msg.id,
|
|
12864
12882
|
groupId,
|
|
@@ -12891,13 +12909,61 @@ var RealtimeGateway = class {
|
|
|
12891
12909
|
this.pollTimer = null;
|
|
12892
12910
|
}
|
|
12893
12911
|
}
|
|
12912
|
+
/**
|
|
12913
|
+
* Get directory group IDs, refreshing from API every AGENT_GROUPS_TTL ms.
|
|
12914
|
+
* Falls back to botConfigCache if the API call fails.
|
|
12915
|
+
* Pusher agent:group-added/removed events also invalidate the cache.
|
|
12916
|
+
*/
|
|
12917
|
+
async getDirectoryGroupIds() {
|
|
12918
|
+
if (!this.agentId) {
|
|
12919
|
+
const ids = /* @__PURE__ */ new Set();
|
|
12920
|
+
for (const [gid, config] of this.botConfigCache) {
|
|
12921
|
+
if (config.source === "directory" && config.enabled) ids.add(gid);
|
|
12922
|
+
}
|
|
12923
|
+
return ids;
|
|
12924
|
+
}
|
|
12925
|
+
const now = Date.now();
|
|
12926
|
+
if (this.agentGroupsCache && now - this.agentGroupsCache.fetchedAt < this.AGENT_GROUPS_TTL) {
|
|
12927
|
+
return this.agentGroupsCache.groupIds;
|
|
12928
|
+
}
|
|
12929
|
+
try {
|
|
12930
|
+
const { groups: agentGroups } = await this.client.listAgentGroups(this.agentId);
|
|
12931
|
+
const ids = /* @__PURE__ */ new Set();
|
|
12932
|
+
for (const ag of agentGroups) {
|
|
12933
|
+
if (ag.source === "directory" && (ag.enabled ?? true)) {
|
|
12934
|
+
ids.add(ag.groupId);
|
|
12935
|
+
if (!this.botConfigCache.has(ag.groupId)) {
|
|
12936
|
+
this.botConfigCache.set(ag.groupId, {
|
|
12937
|
+
enabled: ag.enabled ?? true,
|
|
12938
|
+
suppressionMinutes: 10,
|
|
12939
|
+
ownerIdentityId: "",
|
|
12940
|
+
groupType: ag.groupType ?? "standard",
|
|
12941
|
+
source: "directory",
|
|
12942
|
+
grantedScopes: ag.grantedScopes,
|
|
12943
|
+
agentDisplayName: ag.agentDisplayName ?? this.agentDisplayName ?? void 0,
|
|
12944
|
+
securityMode: ag.securityMode
|
|
12945
|
+
});
|
|
12946
|
+
}
|
|
12947
|
+
}
|
|
12948
|
+
}
|
|
12949
|
+
this.agentGroupsCache = { groupIds: ids, fetchedAt: now };
|
|
12950
|
+
return ids;
|
|
12951
|
+
} catch (err) {
|
|
12952
|
+
this.log.warn?.(`listAgentGroups failed: ${err}, using cache`);
|
|
12953
|
+
if (this.agentGroupsCache) return this.agentGroupsCache.groupIds;
|
|
12954
|
+
const ids = /* @__PURE__ */ new Set();
|
|
12955
|
+
for (const [gid, config] of this.botConfigCache) {
|
|
12956
|
+
if (config.source === "directory" && config.enabled) ids.add(gid);
|
|
12957
|
+
}
|
|
12958
|
+
return ids;
|
|
12959
|
+
}
|
|
12960
|
+
}
|
|
12894
12961
|
async poll() {
|
|
12895
12962
|
if (this.polling) return;
|
|
12896
12963
|
this.polling = true;
|
|
12897
12964
|
try {
|
|
12898
12965
|
this.clearStaleSuppression();
|
|
12899
12966
|
const { groups } = await this.client.listGroups(this.botIdentityId);
|
|
12900
|
-
console.log(`[gw:poll] listGroups returned ${groups.length} groups, botConfigCache has ${this.botConfigCache.size} entries`);
|
|
12901
12967
|
for (const group of groups) {
|
|
12902
12968
|
if (!this.botConfigCache.has(group.id) && group.settings) {
|
|
12903
12969
|
const botSettings = group.settings?.bot ?? {};
|
|
@@ -12911,11 +12977,9 @@ var RealtimeGateway = class {
|
|
|
12911
12977
|
}
|
|
12912
12978
|
}
|
|
12913
12979
|
const groupIds = new Set(groups.map((g) => g.id));
|
|
12914
|
-
|
|
12915
|
-
|
|
12916
|
-
|
|
12917
|
-
}
|
|
12918
|
-
}
|
|
12980
|
+
const directoryIds = await this.getDirectoryGroupIds();
|
|
12981
|
+
for (const gid of directoryIds) groupIds.add(gid);
|
|
12982
|
+
console.log(`[gw:poll] partner=${groups.length} directory=${directoryIds.size} total=${groupIds.size} groups=[${[...groupIds].join(", ")}]`);
|
|
12919
12983
|
await Promise.allSettled(
|
|
12920
12984
|
[...groupIds].map((gid) => this.pollGroup(gid))
|
|
12921
12985
|
);
|
|
@@ -12956,8 +13020,13 @@ var RealtimeGateway = class {
|
|
|
12956
13020
|
console.log(`[gw:pollGroup] skipping msg=${msg.id} in group=${groupId} (shouldProcess=false)`);
|
|
12957
13021
|
continue;
|
|
12958
13022
|
}
|
|
13023
|
+
if (this.dispatched.has(msg.id)) {
|
|
13024
|
+
console.log(`[gw:pollGroup] skipping msg=${msg.id} in group=${groupId} (already dispatched)`);
|
|
13025
|
+
continue;
|
|
13026
|
+
}
|
|
12959
13027
|
try {
|
|
12960
13028
|
console.log(`[gw:pollGroup] dispatching msg=${msg.id} group=${groupId} text=${plaintext?.slice(0, 60)}`);
|
|
13029
|
+
this.markDispatched(msg.id);
|
|
12961
13030
|
await this.onMessage({
|
|
12962
13031
|
messageId: msg.id,
|
|
12963
13032
|
groupId,
|