openclaw-quiubo 2.6.15 → 2.6.16
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
|
@@ -12451,7 +12451,6 @@ function signChallenge(challengeBase64, signingPrivateKey) {
|
|
|
12451
12451
|
|
|
12452
12452
|
// src/realtime-gateway.ts
|
|
12453
12453
|
var CURSORS_DIR = join(process.env.HOME ?? process.env.USERPROFILE ?? "", ".openclaw", "cron");
|
|
12454
|
-
var CURSORS_FILE = join(CURSORS_DIR, "quiubo-cursors.json");
|
|
12455
12454
|
var consoleLogger = {
|
|
12456
12455
|
debug: (...args) => console.debug("[Quiubo]", ...args),
|
|
12457
12456
|
info: (...args) => console.log("[Quiubo]", ...args),
|
|
@@ -12496,6 +12495,7 @@ var RealtimeGateway = class {
|
|
|
12496
12495
|
heartbeatTimer = null;
|
|
12497
12496
|
// Cursor save debounce (avoids disk thrash on rapid Pusher events)
|
|
12498
12497
|
cursorSaveTimer = null;
|
|
12498
|
+
cursorsFile;
|
|
12499
12499
|
// Pusher connection timeout (cancelled on stop to prevent stale firing)
|
|
12500
12500
|
pusherConnectTimeout = null;
|
|
12501
12501
|
// E2EE state
|
|
@@ -12508,6 +12508,7 @@ var RealtimeGateway = class {
|
|
|
12508
12508
|
constructor(opts) {
|
|
12509
12509
|
this.client = opts.client;
|
|
12510
12510
|
this.botIdentityId = opts.botIdentityId;
|
|
12511
|
+
this.cursorsFile = join(CURSORS_DIR, `quiubo-cursors-${opts.accountId}.json`);
|
|
12511
12512
|
this.pusherConfig = opts.pusher ?? null;
|
|
12512
12513
|
this.pollIntervalMs = opts.pollIntervalMs ?? 5e3;
|
|
12513
12514
|
this.onMessage = opts.onMessage;
|
|
@@ -12526,7 +12527,7 @@ var RealtimeGateway = class {
|
|
|
12526
12527
|
*/
|
|
12527
12528
|
async loadCursors() {
|
|
12528
12529
|
try {
|
|
12529
|
-
const raw = await readFile(
|
|
12530
|
+
const raw = await readFile(this.cursorsFile, "utf-8");
|
|
12530
12531
|
const data = JSON.parse(raw);
|
|
12531
12532
|
let count = 0;
|
|
12532
12533
|
for (const [groupId, cursor] of Object.entries(data)) {
|
|
@@ -12551,7 +12552,7 @@ var RealtimeGateway = class {
|
|
|
12551
12552
|
data[groupId] = cursor;
|
|
12552
12553
|
}
|
|
12553
12554
|
await mkdir(CURSORS_DIR, { recursive: true });
|
|
12554
|
-
await writeFile(
|
|
12555
|
+
await writeFile(this.cursorsFile, JSON.stringify(data, null, 2), "utf-8");
|
|
12555
12556
|
} catch (err) {
|
|
12556
12557
|
this.log.warn?.(`Failed to persist cursors: ${err}`);
|
|
12557
12558
|
}
|
|
@@ -12932,6 +12933,9 @@ var RealtimeGateway = class {
|
|
|
12932
12933
|
*/
|
|
12933
12934
|
async fetchAndRouteMessage(groupId, messageId) {
|
|
12934
12935
|
try {
|
|
12936
|
+
if (!this.cursors.has(groupId)) {
|
|
12937
|
+
await this.seekToLatest(groupId);
|
|
12938
|
+
}
|
|
12935
12939
|
const cursor = this.cursors.get(groupId);
|
|
12936
12940
|
const { messages } = await this.client.listMessages(groupId, cursor, 100);
|
|
12937
12941
|
if (messages.length > 0) {
|
|
@@ -12940,10 +12944,6 @@ var RealtimeGateway = class {
|
|
|
12940
12944
|
}
|
|
12941
12945
|
const msg = messages.find((m) => m.id === messageId);
|
|
12942
12946
|
if (!msg) {
|
|
12943
|
-
if (!cursor) {
|
|
12944
|
-
this.log.info?.(`fetchAndRoute: no cursor for group ${groupId}, caught up to latest (skip history)`);
|
|
12945
|
-
return;
|
|
12946
|
-
}
|
|
12947
12947
|
this.log.warn?.(`Message ${messageId} not found in group ${groupId} (fetched ${messages.length} from cursor)`);
|
|
12948
12948
|
return;
|
|
12949
12949
|
}
|
|
@@ -13090,14 +13090,36 @@ var RealtimeGateway = class {
|
|
|
13090
13090
|
this.polling = false;
|
|
13091
13091
|
}
|
|
13092
13092
|
}
|
|
13093
|
+
/**
|
|
13094
|
+
* Seek cursor to the latest message without processing anything.
|
|
13095
|
+
* Called on cold start (no cursor for a group) to avoid replaying history.
|
|
13096
|
+
* Paginates forward until there are no more messages.
|
|
13097
|
+
*/
|
|
13098
|
+
async seekToLatest(groupId) {
|
|
13099
|
+
let cursor;
|
|
13100
|
+
let hasMore = true;
|
|
13101
|
+
while (hasMore) {
|
|
13102
|
+
const result = await this.client.listMessages(groupId, cursor, 100);
|
|
13103
|
+
if (result.messages.length === 0) break;
|
|
13104
|
+
cursor = result.messages[result.messages.length - 1].id;
|
|
13105
|
+
hasMore = result.hasMore;
|
|
13106
|
+
}
|
|
13107
|
+
if (cursor) {
|
|
13108
|
+
this.cursors.set(groupId, cursor);
|
|
13109
|
+
this.log.info?.(`Seeked to latest in group ${groupId}: cursor=${cursor}`);
|
|
13110
|
+
}
|
|
13111
|
+
}
|
|
13093
13112
|
async pollGroup(groupId) {
|
|
13094
13113
|
try {
|
|
13095
13114
|
const cursor = this.cursors.get(groupId);
|
|
13115
|
+
if (!cursor) {
|
|
13116
|
+
await this.seekToLatest(groupId);
|
|
13117
|
+
return;
|
|
13118
|
+
}
|
|
13096
13119
|
const { messages } = await this.client.listMessages(groupId, cursor);
|
|
13097
13120
|
if (messages.length === 0) return;
|
|
13098
13121
|
const lastMessage = messages[messages.length - 1];
|
|
13099
13122
|
this.cursors.set(groupId, lastMessage.id);
|
|
13100
|
-
if (!cursor) return;
|
|
13101
13123
|
for (const msg of messages) {
|
|
13102
13124
|
if (msg.senderIdentityId === this.botIdentityId) continue;
|
|
13103
13125
|
let plaintext = msg.plaintext;
|
|
@@ -13807,6 +13829,7 @@ var quiuboPlugin = {
|
|
|
13807
13829
|
const gateway = new RealtimeGateway({
|
|
13808
13830
|
client,
|
|
13809
13831
|
botIdentityId,
|
|
13832
|
+
accountId,
|
|
13810
13833
|
pusher: pusherConfig,
|
|
13811
13834
|
pollIntervalMs: pollIntervalMs ?? 5e3,
|
|
13812
13835
|
log: gatewayLog,
|