@agentunion/fastaun-browser 0.5.11 → 0.5.12
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/CHANGELOG.md +30 -0
- package/_packed_docs/CHANGELOG.md +30 -0
- package/_packed_docs/INDEX.md +2 -2
- package/_packed_docs/KITE_DOCS_GUIDE.md +1 -1
- package/_packed_docs/protocol/10-Group-/345/255/220/345/215/217/350/256/256.md +21 -3
- package/_packed_docs/sdk/09-group-rpc-manual.md +29 -2
- package/dist/bundle.js +559 -295
- package/dist/client/delivery.d.ts +1 -0
- package/dist/client/delivery.d.ts.map +1 -1
- package/dist/client/delivery.js +161 -242
- package/dist/client/delivery.js.map +1 -1
- package/dist/client/group-state.d.ts.map +1 -1
- package/dist/client/group-state.js +1 -0
- package/dist/client/group-state.js.map +1 -1
- package/dist/client/rpc-pipeline.d.ts.map +1 -1
- package/dist/client/rpc-pipeline.js +24 -11
- package/dist/client/rpc-pipeline.js.map +1 -1
- package/dist/client/v2-e2ee.d.ts +0 -1
- package/dist/client/v2-e2ee.d.ts.map +1 -1
- package/dist/client/v2-e2ee.js +65 -44
- package/dist/client/v2-e2ee.js.map +1 -1
- package/dist/client.d.ts +14 -0
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +341 -18
- package/dist/client.js.map +1 -1
- package/dist/facades.d.ts +7 -0
- package/dist/facades.d.ts.map +1 -1
- package/dist/facades.js +44 -0
- package/dist/facades.js.map +1 -1
- package/dist/seq-tracker.d.ts +2 -2
- package/dist/seq-tracker.d.ts.map +1 -1
- package/dist/seq-tracker.js +11 -7
- package/dist/seq-tracker.js.map +1 -1
- package/dist/tools/cross-sdk-agent.js +50 -12
- package/dist/tools/cross-sdk-agent.js.map +1 -1
- package/dist/transport.d.ts.map +1 -1
- package/dist/transport.js +3 -0
- package/dist/transport.js.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +1 -1
package/dist/bundle.js
CHANGED
|
@@ -460,7 +460,7 @@ var init_indexeddb_store = __esm({
|
|
|
460
460
|
});
|
|
461
461
|
|
|
462
462
|
// src/version.ts
|
|
463
|
-
var VERSION = "0.5.
|
|
463
|
+
var VERSION = "0.5.12";
|
|
464
464
|
|
|
465
465
|
// src/types.ts
|
|
466
466
|
var ConnectionState = /* @__PURE__ */ ((ConnectionState2) => {
|
|
@@ -1747,6 +1747,9 @@ var EVENT_NAME_MAP = {
|
|
|
1747
1747
|
"message.recalled": "message.recalled",
|
|
1748
1748
|
"message.ack": "message.ack",
|
|
1749
1749
|
"group.changed": "group.changed",
|
|
1750
|
+
"group.invite_created": "group.invite_created",
|
|
1751
|
+
"group.invite_received": "group.invite_received",
|
|
1752
|
+
"group.invite_finalized": "group.invite_finalized",
|
|
1750
1753
|
"group.message_created": "group.message_created",
|
|
1751
1754
|
"group.message_recalled": "group.message_recalled",
|
|
1752
1755
|
"group.state_committed": "group.state_committed",
|
|
@@ -4203,7 +4206,6 @@ var SeqTracker = class {
|
|
|
4203
4206
|
if (headSeq === t.headSeq) {
|
|
4204
4207
|
if (windowStartSeq <= t.tailSeq) return false;
|
|
4205
4208
|
t.tailSeq = windowStartSeq;
|
|
4206
|
-
this._normalizeWindow(t);
|
|
4207
4209
|
return true;
|
|
4208
4210
|
}
|
|
4209
4211
|
if (t.headSeq + pageLimit < headSeq && windowStartSeq <= t.headSeq + 1) {
|
|
@@ -4212,7 +4214,6 @@ var SeqTracker = class {
|
|
|
4212
4214
|
if (windowStartSeq > t.headSeq + 1) t.tailSeq = windowStartSeq;
|
|
4213
4215
|
t.headSeq = headSeq;
|
|
4214
4216
|
t.maxSeenSeq = Math.max(t.maxSeenSeq, headSeq);
|
|
4215
|
-
this._normalizeWindow(t);
|
|
4216
4217
|
return true;
|
|
4217
4218
|
}
|
|
4218
4219
|
/** Push 专用:只扩展上界 maxSeenSeq,不动 contiguousSeq。 */
|
|
@@ -4287,8 +4288,8 @@ var SeqTracker = class {
|
|
|
4287
4288
|
}
|
|
4288
4289
|
return true;
|
|
4289
4290
|
}
|
|
4290
|
-
/** 提交已校验的 Forward
|
|
4291
|
-
onPullResult(ns, messages, afterSeq) {
|
|
4291
|
+
/** 提交已校验的 Forward 原始页;缺号只有服务端明确证明时才能跳过。 */
|
|
4292
|
+
onPullResult(ns, messages, afterSeq, contiguousSeq) {
|
|
4292
4293
|
const t = this._get(ns);
|
|
4293
4294
|
const pulledSeqs = /* @__PURE__ */ new Set();
|
|
4294
4295
|
for (const m of messages) {
|
|
@@ -4318,6 +4319,7 @@ var SeqTracker = class {
|
|
|
4318
4319
|
if (maxPulled > 0) {
|
|
4319
4320
|
t.maxSeenSeq = Math.max(t.maxSeenSeq, maxPulled);
|
|
4320
4321
|
}
|
|
4322
|
+
this._tryAdvance(t);
|
|
4321
4323
|
if (maxPulled > t.contiguousSeq) {
|
|
4322
4324
|
for (const [key, probe] of t.pendingGaps) {
|
|
4323
4325
|
if (probe.gapEnd <= maxPulled) t.pendingGaps.delete(key);
|
|
@@ -4327,7 +4329,11 @@ var SeqTracker = class {
|
|
|
4327
4329
|
}
|
|
4328
4330
|
t.contiguousSeq = maxPulled;
|
|
4329
4331
|
}
|
|
4330
|
-
|
|
4332
|
+
let proof = Number.isSafeInteger(contiguousSeq) && contiguousSeq > 0 ? contiguousSeq : 0;
|
|
4333
|
+
if (proof > 0) {
|
|
4334
|
+
if (proof > t.contiguousSeq) this.forceContiguousSeq(ns, proof);
|
|
4335
|
+
}
|
|
4336
|
+
this._normalizeWindow(t);
|
|
4331
4337
|
const remaining = [...t.receivedSeqs].filter((seq2) => seq2 > t.contiguousSeq);
|
|
4332
4338
|
if (remaining.length > 0) {
|
|
4333
4339
|
const firstPending = Math.min(...remaining);
|
|
@@ -4506,7 +4512,6 @@ var SeqTracker = class {
|
|
|
4506
4512
|
restored.tailSeq = Number(tailRaw);
|
|
4507
4513
|
restored.headSeq = Number(headRaw);
|
|
4508
4514
|
restored.maxSeenSeq = Math.max(ack, restored.headSeq);
|
|
4509
|
-
this._normalizeWindow(restored);
|
|
4510
4515
|
this._trackers.set(ns, restored);
|
|
4511
4516
|
}
|
|
4512
4517
|
return issues;
|
|
@@ -5006,6 +5011,9 @@ function positiveSafeSequenceHint(value) {
|
|
|
5006
5011
|
const parsed = Number(value);
|
|
5007
5012
|
return Number.isSafeInteger(parsed) && parsed > 0 ? parsed : 0;
|
|
5008
5013
|
}
|
|
5014
|
+
function hasNonEmptyInlineMessage(value) {
|
|
5015
|
+
return isJsonObject(value) && Object.keys(value).length > 0;
|
|
5016
|
+
}
|
|
5009
5017
|
function nonNegativeSafeSequenceHint(value) {
|
|
5010
5018
|
if (typeof value !== "number" || !Number.isSafeInteger(value) || value < 0) return null;
|
|
5011
5019
|
return value;
|
|
@@ -5794,13 +5802,17 @@ var MessageDeliveryEngine = class {
|
|
|
5794
5802
|
this.markPublishedSeq(ns, seq2);
|
|
5795
5803
|
publishedCount += 1;
|
|
5796
5804
|
}
|
|
5805
|
+
} else if (this.isSelfSentGroupMessage(message)) {
|
|
5806
|
+
this.markPublishedSeq(ns, seq2);
|
|
5797
5807
|
} else if (await this.publishPulledMessage("group.message_created", ns, seq2, message, false)) {
|
|
5798
5808
|
this.ensurePullOperationCurrent();
|
|
5799
5809
|
publishedCount += 1;
|
|
5800
5810
|
}
|
|
5801
5811
|
}
|
|
5802
5812
|
this.ensurePullOperationCurrent();
|
|
5803
|
-
|
|
5813
|
+
const contiguousSeq = Number.isSafeInteger(result.contiguous_seq) ? result.contiguous_seq : void 0;
|
|
5814
|
+
if (contiguousSeq === void 0) client._seqTracker.onPullResult(ns, messages, afterSeq);
|
|
5815
|
+
else client._seqTracker.onPullResult(ns, messages, afterSeq, contiguousSeq);
|
|
5804
5816
|
const commitTarget = Math.max(
|
|
5805
5817
|
client._seqTracker.getContiguousSeq(ns),
|
|
5806
5818
|
retentionFloor,
|
|
@@ -6296,38 +6308,9 @@ var MessageDeliveryEngine = class {
|
|
|
6296
6308
|
return;
|
|
6297
6309
|
}
|
|
6298
6310
|
const ns = `group:${groupId}`;
|
|
6299
|
-
|
|
6300
|
-
|
|
6301
|
-
if (client._seqTracker.getContiguousSeq(ns) === seqNum) {
|
|
6302
|
-
await this.publishGroupRecallTombstone(groupId, seq2, wrapped);
|
|
6303
|
-
return;
|
|
6304
|
-
}
|
|
6305
|
-
client._repairPushContiguousBound(ns, seqNum, true, "_raw.group.message_recalled");
|
|
6306
|
-
}
|
|
6307
|
-
const pushed = client._pushedSeqs.get(ns);
|
|
6308
|
-
const pending = client._pendingOrderedMsgs.get(ns);
|
|
6309
|
-
if (pushed?.has(seqNum) || pending?.has(seqNum)) {
|
|
6310
|
-
await this.publishGroupRecallTombstone(groupId, seq2, wrapped);
|
|
6311
|
-
return;
|
|
6312
|
-
}
|
|
6313
|
-
const contigBefore = client._seqTracker.getContiguousSeq(ns);
|
|
6314
|
-
client._seqTracker.onMessageSeq(ns, seqNum);
|
|
6311
|
+
client._seqTracker.updateMaxSeen(ns, seqNum);
|
|
6312
|
+
if (seqNum > client._seqTracker.getContiguousSeq(ns) && client._sessionOptions?.background_sync !== false) client._safeAsync(this.fillGroupGap(groupId));
|
|
6315
6313
|
await this.publishGroupRecallTombstone(groupId, seq2, wrapped);
|
|
6316
|
-
this.markPublishedSeq(ns, seqNum);
|
|
6317
|
-
const contig = client._seqTracker.getContiguousSeq(ns);
|
|
6318
|
-
if (contig > 0) {
|
|
6319
|
-
const ackSeq = this.clampAckSeq("group.ack_messages", "msg_seq", ns, contig);
|
|
6320
|
-
client._transport.call("group.ack_messages", {
|
|
6321
|
-
group_id: groupId,
|
|
6322
|
-
msg_seq: ackSeq,
|
|
6323
|
-
device_id: client._deviceId,
|
|
6324
|
-
slot_id: client._slotId,
|
|
6325
|
-
_rpc_background: true
|
|
6326
|
-
}).catch((e) => {
|
|
6327
|
-
client._clientLog.warn("group recall auto-ack failed: group=" + groupId, e);
|
|
6328
|
-
});
|
|
6329
|
-
}
|
|
6330
|
-
if (contig !== contigBefore) this.persistSeq(ns);
|
|
6331
6314
|
}
|
|
6332
6315
|
async publishAppEvent(event, payload, source = "direct", ns = "", batch) {
|
|
6333
6316
|
const client = this.runtime.client;
|
|
@@ -6392,6 +6375,16 @@ var MessageDeliveryEngine = class {
|
|
|
6392
6375
|
}
|
|
6393
6376
|
return true;
|
|
6394
6377
|
}
|
|
6378
|
+
isSelfSentGroupMessage(message) {
|
|
6379
|
+
if (!isJsonObject(message)) return false;
|
|
6380
|
+
const client = this.runtime.client;
|
|
6381
|
+
const selfAid = String(client._aid ?? "").trim().toLowerCase();
|
|
6382
|
+
const senderAid = String(message.sender_aid ?? message.from_aid ?? message.from ?? "").trim().toLowerCase();
|
|
6383
|
+
if (!selfAid || senderAid !== selfAid) return false;
|
|
6384
|
+
const senderDevice = Object.prototype.hasOwnProperty.call(message, "sender_device_id") ? message.sender_device_id : message.from_device_id;
|
|
6385
|
+
if (typeof senderDevice !== "string" || !senderDevice.trim() || !String(client._deviceId ?? "").trim()) return false;
|
|
6386
|
+
return senderDevice.trim() === String(client._deviceId).trim();
|
|
6387
|
+
}
|
|
6395
6388
|
strictTargetString(source, key) {
|
|
6396
6389
|
if (!Object.prototype.hasOwnProperty.call(source, key)) {
|
|
6397
6390
|
return { present: false, valid: false, value: "" };
|
|
@@ -6452,11 +6445,11 @@ var MessageDeliveryEngine = class {
|
|
|
6452
6445
|
const client = this.runtime.client;
|
|
6453
6446
|
client._clientLog.debug(`_onRawMessageReceived enter: from=${data?.from ?? "-"} mid=${data?.message_id ?? "-"} seq=${data?.seq ?? "-"}`);
|
|
6454
6447
|
const ns = isJsonObject(data) && client._aid && data.seq !== void 0 ? `p2p:${client._aid}` : "";
|
|
6455
|
-
const seq2 = isJsonObject(data)
|
|
6456
|
-
if (client._v2Session && ns &&
|
|
6448
|
+
const seq2 = isJsonObject(data) ? positiveSafeSequenceHint(data.seq) : 0;
|
|
6449
|
+
if (client._v2Session && ns && seq2 > 0 && this.messageTargetsCurrentInstance(data)) {
|
|
6457
6450
|
client._seqTracker.updateMaxSeen(ns, seq2);
|
|
6458
6451
|
}
|
|
6459
|
-
const hasInlineObject = isJsonObject(data) &&
|
|
6452
|
+
const hasInlineObject = isJsonObject(data) && hasNonEmptyInlineMessage(data.inline_message);
|
|
6460
6453
|
const inlineGeneration = hasInlineObject ? this.captureInlineGeneration() : void 0;
|
|
6461
6454
|
const operation = () => this.processAndPublishMessage(data, inlineGeneration);
|
|
6462
6455
|
client._safeAsync(client._v2Session && ns && !hasInlineObject ? operation() : this.runPushProcessSerialized(ns, operation, inlineGeneration));
|
|
@@ -6468,33 +6461,13 @@ var MessageDeliveryEngine = class {
|
|
|
6468
6461
|
const msg = { ...data };
|
|
6469
6462
|
if (!("type" in msg)) msg.type = "message.recalled";
|
|
6470
6463
|
if (!this.messageTargetsCurrentInstance(msg)) return;
|
|
6471
|
-
const seq2 = msg.seq;
|
|
6472
|
-
if (
|
|
6464
|
+
const seq2 = positiveSafeSequenceHint(msg.seq);
|
|
6465
|
+
if (client._aid && seq2 > 0) {
|
|
6473
6466
|
const ns = `p2p:${client._aid}`;
|
|
6474
|
-
|
|
6475
|
-
|
|
6476
|
-
const seqNeedsPull = client._seqTracker.onMessageSeq(ns, seq2);
|
|
6477
|
-
const published = await this.publishOrderedMessage("message.recalled", ns, seq2, msg);
|
|
6478
|
-
const contigAfter = client._seqTracker.getContiguousSeq(ns);
|
|
6479
|
-
if (seqNeedsPull && !published && client._sessionOptions?.background_sync !== false) {
|
|
6480
|
-
client._safeAsync(this.fillP2pGap());
|
|
6481
|
-
}
|
|
6482
|
-
const contig = client._seqTracker.getContiguousSeq(ns);
|
|
6483
|
-
if (contig > 0) {
|
|
6484
|
-
const ackSeq = this.clampAckSeq("message.ack", "seq", ns, contig);
|
|
6485
|
-
client._transport.call("message.ack", {
|
|
6486
|
-
seq: ackSeq,
|
|
6487
|
-
device_id: client._deviceId,
|
|
6488
|
-
slot_id: client._slotId,
|
|
6489
|
-
_rpc_background: true
|
|
6490
|
-
}).catch((e) => {
|
|
6491
|
-
client._clientLog.warn(`P2P recall auto-ack failed:${String(e)}`);
|
|
6492
|
-
});
|
|
6493
|
-
}
|
|
6494
|
-
if (contigAfter !== contigBefore) this.persistSeq(ns);
|
|
6495
|
-
return;
|
|
6467
|
+
client._seqTracker.updateMaxSeen(ns, seq2);
|
|
6468
|
+
if (seq2 > client._seqTracker.getContiguousSeq(ns) && client._sessionOptions?.background_sync !== false) client._safeAsync(this.fillP2pGap());
|
|
6496
6469
|
}
|
|
6497
|
-
await this.publishMessageRecallTombstone(
|
|
6470
|
+
await this.publishMessageRecallTombstone(msg.seq, msg);
|
|
6498
6471
|
}
|
|
6499
6472
|
async processAndPublishMessage(data, inlineGeneration) {
|
|
6500
6473
|
const client = this.runtime.client;
|
|
@@ -6508,43 +6481,32 @@ var MessageDeliveryEngine = class {
|
|
|
6508
6481
|
return;
|
|
6509
6482
|
}
|
|
6510
6483
|
const legacyPushSeq = positiveSafeSequenceHint(msg.seq);
|
|
6511
|
-
const hasInlineField =
|
|
6484
|
+
const hasInlineField = hasNonEmptyInlineMessage(msg.inline_message);
|
|
6512
6485
|
if (client._v2Session && client._aid && (legacyPushSeq > 0 || hasInlineField)) {
|
|
6513
6486
|
await this.processV2P2PNotification(msg, "v1", inlineGeneration);
|
|
6514
6487
|
return;
|
|
6515
6488
|
}
|
|
6489
|
+
if (client._aid && legacyPushSeq > 0) {
|
|
6490
|
+
const ns2 = `p2p:${client._aid}`;
|
|
6491
|
+
client._seqTracker.updateMaxSeen(ns2, legacyPushSeq);
|
|
6492
|
+
if (client._sessionOptions?.background_sync !== false) client._safeAsync(this.fillP2pGap());
|
|
6493
|
+
return;
|
|
6494
|
+
}
|
|
6516
6495
|
const seq2 = msg.seq;
|
|
6517
6496
|
const encryptedPush = client._isEncryptedPushMessage(msg);
|
|
6518
|
-
|
|
6519
|
-
|
|
6520
|
-
|
|
6521
|
-
|
|
6522
|
-
|
|
6523
|
-
|
|
6524
|
-
|
|
6525
|
-
|
|
6526
|
-
|
|
6527
|
-
|
|
6528
|
-
|
|
6529
|
-
|
|
6530
|
-
if (contig > 0) {
|
|
6531
|
-
const ackSeq = this.clampAckSeq("message.ack", "seq", ns, contig);
|
|
6532
|
-
client._transport.call("message.ack", {
|
|
6533
|
-
seq: ackSeq,
|
|
6534
|
-
device_id: client._deviceId,
|
|
6535
|
-
slot_id: client._slotId,
|
|
6536
|
-
_rpc_background: true
|
|
6537
|
-
}).catch((e) => {
|
|
6538
|
-
client._clientLog.warn(`P2P auto-ack failed:${String(e)}`);
|
|
6539
|
-
});
|
|
6540
|
-
}
|
|
6541
|
-
if (contigAfter !== contigBefore) this.persistSeq(ns);
|
|
6542
|
-
if (encryptedPush) return;
|
|
6497
|
+
const ns = client._aid ? `p2p:${client._aid}` : "";
|
|
6498
|
+
const seqNum = positiveSafeSequenceHint(seq2);
|
|
6499
|
+
if (ns && seqNum > 0) {
|
|
6500
|
+
client._seqTracker.updateMaxSeen(ns, seqNum);
|
|
6501
|
+
if (seqNum > client._seqTracker.getContiguousSeq(ns) && client._sessionOptions?.background_sync !== false) client._safeAsync(this.fillP2pGap());
|
|
6502
|
+
}
|
|
6503
|
+
if (encryptedPush) {
|
|
6504
|
+
await client._publishEncryptedPushMessage("message.received", "message.undecryptable", ns, seq2 ?? 0, msg, false);
|
|
6505
|
+
return;
|
|
6506
|
+
}
|
|
6507
|
+
if (ns && seq2 !== void 0 && seq2 !== null) {
|
|
6508
|
+
await this.publishOrderedMessage("message.received", ns, seq2, msg);
|
|
6543
6509
|
} else {
|
|
6544
|
-
if (encryptedPush) {
|
|
6545
|
-
await client._publishEncryptedPushMessage("message.received", "message.undecryptable", "", seq2 ?? 0, msg, false);
|
|
6546
|
-
return;
|
|
6547
|
-
}
|
|
6548
6510
|
await client._publishAppEvent("message.received", msg, "push");
|
|
6549
6511
|
}
|
|
6550
6512
|
} catch (exc) {
|
|
@@ -6568,13 +6530,13 @@ var MessageDeliveryEngine = class {
|
|
|
6568
6530
|
const client = this.runtime.client;
|
|
6569
6531
|
client._clientLog.debug(`_onRawGroupMessageCreated enter: group_id=${data?.group_id ?? "-"} from=${data?.from ?? "-"} seq=${data?.seq ?? "-"}`);
|
|
6570
6532
|
const groupId = isJsonObject(data) && typeof data.group_id === "string" ? data.group_id.trim() : "";
|
|
6571
|
-
const seq2 = isJsonObject(data) && typeof data.seq === "number" ? data.seq : 0;
|
|
6572
6533
|
const kind = isJsonObject(data) ? String(data.kind ?? "").trim() : "";
|
|
6573
|
-
if (client._v2Session && groupId && kind !== "group.online_unread_hint" && Number.isSafeInteger(seq2) && seq2 > 0) {
|
|
6574
|
-
client._seqTracker.updateMaxSeen(`group:${groupId}`, seq2);
|
|
6575
|
-
}
|
|
6576
6534
|
const ns = groupId ? `group:${groupId}` : "";
|
|
6577
|
-
const
|
|
6535
|
+
const seq2 = isJsonObject(data) ? positiveSafeSequenceHint(data.seq) : 0;
|
|
6536
|
+
if (client._v2Session && ns && kind !== "group.online_unread_hint" && seq2 > 0) {
|
|
6537
|
+
client._seqTracker.updateMaxSeen(ns, seq2);
|
|
6538
|
+
}
|
|
6539
|
+
const hasInlineObject = isJsonObject(data) && hasNonEmptyInlineMessage(data.inline_message);
|
|
6578
6540
|
const inlineGeneration = hasInlineObject ? this.captureInlineGeneration() : void 0;
|
|
6579
6541
|
const operation = () => this.processAndPublishGroupMessage(data, inlineGeneration);
|
|
6580
6542
|
client._safeAsync(client._v2Session && ns && !hasInlineObject ? operation() : this.runPushProcessSerialized(ns, operation, inlineGeneration));
|
|
@@ -6595,69 +6557,56 @@ var MessageDeliveryEngine = class {
|
|
|
6595
6557
|
client._groupSynced.add(groupId);
|
|
6596
6558
|
}
|
|
6597
6559
|
const legacyPushSeq = positiveSafeSequenceHint(seq2);
|
|
6598
|
-
const hasInlineField =
|
|
6560
|
+
const hasInlineField = hasNonEmptyInlineMessage(msg.inline_message);
|
|
6599
6561
|
if (client._v2Session && groupId && (legacyPushSeq > 0 || hasInlineField)) {
|
|
6600
6562
|
await this.processGroupV2MessageCreated(msg, "v1", inlineGeneration);
|
|
6601
6563
|
return;
|
|
6602
6564
|
}
|
|
6565
|
+
if (groupId && legacyPushSeq > 0) {
|
|
6566
|
+
const ns2 = `group:${groupId}`;
|
|
6567
|
+
client._seqTracker.updateMaxSeen(ns2, legacyPushSeq);
|
|
6568
|
+
if (client._sessionOptions?.background_sync !== false) client._safeAsync(this.fillGroupGap(groupId));
|
|
6569
|
+
return;
|
|
6570
|
+
}
|
|
6603
6571
|
if (payload === void 0 || payload === null || typeof payload === "object" && Object.keys(payload).length === 0) {
|
|
6604
|
-
await this.autoPullGroupMessages(msg);
|
|
6572
|
+
if (client._v2Session) await this.autoPullGroupMessages(msg);
|
|
6573
|
+
else if (groupId && seq2 !== void 0 && seq2 !== null) {
|
|
6574
|
+
const ns2 = `group:${groupId}`;
|
|
6575
|
+
const seqNum2 = positiveSafeSequenceHint(seq2);
|
|
6576
|
+
if (seqNum2 > 0) {
|
|
6577
|
+
client._seqTracker.updateMaxSeen(ns2, seqNum2);
|
|
6578
|
+
if (seqNum2 > client._seqTracker.getContiguousSeq(ns2) && client._sessionOptions?.background_sync !== false) client._safeAsync(this.fillGroupGap(groupId));
|
|
6579
|
+
}
|
|
6580
|
+
await this.publishOrderedMessage("group.message_created", ns2, seq2, msg);
|
|
6581
|
+
} else await client._publishAppEvent("group.message_created", msg, "push");
|
|
6605
6582
|
return;
|
|
6606
6583
|
}
|
|
6607
6584
|
const encryptedPush = client._isEncryptedPushMessage(msg);
|
|
6608
|
-
|
|
6609
|
-
|
|
6610
|
-
|
|
6611
|
-
|
|
6612
|
-
|
|
6613
|
-
|
|
6614
|
-
|
|
6615
|
-
|
|
6616
|
-
|
|
6617
|
-
|
|
6618
|
-
if (contig2 > 0) {
|
|
6619
|
-
const ackSeq = this.clampAckSeq("group.ack_messages", "msg_seq", ns, contig2);
|
|
6620
|
-
client._transport.call("group.ack_messages", {
|
|
6621
|
-
group_id: groupId,
|
|
6622
|
-
msg_seq: ackSeq,
|
|
6623
|
-
device_id: client._deviceId,
|
|
6624
|
-
slot_id: client._slotId,
|
|
6625
|
-
_rpc_background: true
|
|
6626
|
-
}).catch((e) => {
|
|
6627
|
-
client._clientLog.warn("group recall auto-ack failed: group=" + groupId, e);
|
|
6628
|
-
});
|
|
6629
|
-
}
|
|
6630
|
-
if (contigAfter2 !== contigBefore) this.persistSeq(ns);
|
|
6631
|
-
return;
|
|
6632
|
-
}
|
|
6633
|
-
const published = encryptedPush ? await client._publishEncryptedPushMessage("group.message_created", "group.message_undecryptable", ns, seq2, msg, true) : await this.publishOrderedMessage("group.message_created", ns, seq2, msg);
|
|
6634
|
-
const contigAfter = client._seqTracker.getContiguousSeq(ns);
|
|
6635
|
-
const needPull = seqNeedsPull && !published;
|
|
6636
|
-
if (needPull && client._sessionOptions?.background_sync !== false) {
|
|
6637
|
-
client._safeAsync(this.fillGroupGap(groupId));
|
|
6638
|
-
}
|
|
6639
|
-
const contig = client._seqTracker.getContiguousSeq(ns);
|
|
6640
|
-
if (contig > 0) {
|
|
6641
|
-
const ackSeq = this.clampAckSeq("group.ack_messages", "msg_seq", ns, contig);
|
|
6642
|
-
client._transport.call("group.ack_messages", {
|
|
6643
|
-
group_id: groupId,
|
|
6644
|
-
msg_seq: ackSeq,
|
|
6645
|
-
device_id: client._deviceId,
|
|
6646
|
-
slot_id: client._slotId,
|
|
6647
|
-
_rpc_background: true
|
|
6648
|
-
}).catch((e) => {
|
|
6649
|
-
client._clientLog.warn("group message auto-ack failed: group=" + groupId, e);
|
|
6650
|
-
});
|
|
6651
|
-
}
|
|
6652
|
-
if (contigAfter !== contigBefore) this.persistSeq(ns);
|
|
6653
|
-
if (encryptedPush) return;
|
|
6654
|
-
} else {
|
|
6655
|
-
if (encryptedPush) {
|
|
6656
|
-
await client._publishEncryptedPushMessage("group.message_created", "group.message_undecryptable", "", seq2 ?? 0, msg, true);
|
|
6657
|
-
return;
|
|
6658
|
-
}
|
|
6659
|
-
await client._publishAppEvent("group.message_created", msg, "push");
|
|
6585
|
+
const ns = groupId ? `group:${groupId}` : "";
|
|
6586
|
+
const seqNum = positiveSafeSequenceHint(seq2);
|
|
6587
|
+
if (ns && seqNum > 0) {
|
|
6588
|
+
client._seqTracker.updateMaxSeen(ns, seqNum);
|
|
6589
|
+
if (seqNum > client._seqTracker.getContiguousSeq(ns) && client._sessionOptions?.background_sync !== false) client._safeAsync(this.fillGroupGap(groupId));
|
|
6590
|
+
}
|
|
6591
|
+
if (this.isSelfSentGroupMessage(msg)) return;
|
|
6592
|
+
if (!encryptedPush && this.recallEventFromGroupMessage(msg)) {
|
|
6593
|
+
await this.publishGroupRecallTombstone(groupId, seq2, msg);
|
|
6594
|
+
return;
|
|
6660
6595
|
}
|
|
6596
|
+
if (encryptedPush) {
|
|
6597
|
+
await client._publishEncryptedPushMessage(
|
|
6598
|
+
"group.message_created",
|
|
6599
|
+
"group.message_undecryptable",
|
|
6600
|
+
ns,
|
|
6601
|
+
seq2 ?? 0,
|
|
6602
|
+
msg,
|
|
6603
|
+
true
|
|
6604
|
+
);
|
|
6605
|
+
return;
|
|
6606
|
+
}
|
|
6607
|
+
if (ns && seq2 !== void 0 && seq2 !== null) {
|
|
6608
|
+
await this.publishOrderedMessage("group.message_created", ns, seq2, msg);
|
|
6609
|
+
} else await client._publishAppEvent("group.message_created", msg, "push");
|
|
6661
6610
|
} catch (exc) {
|
|
6662
6611
|
client._clientLog.warn(`group push processing failed:${String(exc)}`);
|
|
6663
6612
|
if (isJsonObject(data)) {
|
|
@@ -6854,6 +6803,7 @@ var MessageDeliveryEngine = class {
|
|
|
6854
6803
|
client._gapFillDone.add(dedupKey);
|
|
6855
6804
|
this.runtime.delivery.setGapFillActive(true);
|
|
6856
6805
|
let continuationAfterSeq = 0;
|
|
6806
|
+
let pendingAckSeq = 0;
|
|
6857
6807
|
let failed = false;
|
|
6858
6808
|
try {
|
|
6859
6809
|
let nextAfterSeq = afterSeq;
|
|
@@ -6874,9 +6824,9 @@ var MessageDeliveryEngine = class {
|
|
|
6874
6824
|
if (!Array.isArray(events)) return;
|
|
6875
6825
|
const pageContigBefore = client._seqTracker.getContiguousSeq(ns);
|
|
6876
6826
|
const eventObjects = events.filter((evt) => isJsonObject(evt));
|
|
6877
|
-
|
|
6878
|
-
|
|
6879
|
-
|
|
6827
|
+
const contiguousSeq = Number.isSafeInteger(result.contiguous_seq) ? result.contiguous_seq : void 0;
|
|
6828
|
+
if (contiguousSeq === void 0) client._seqTracker.onPullResult(ns, eventObjects, nextAfterSeq);
|
|
6829
|
+
else client._seqTracker.onPullResult(ns, eventObjects, nextAfterSeq, contiguousSeq);
|
|
6880
6830
|
const cursor = isJsonObject(result.cursor) ? result.cursor : null;
|
|
6881
6831
|
const retentionFloor = Math.max(
|
|
6882
6832
|
0,
|
|
@@ -6930,21 +6880,7 @@ var MessageDeliveryEngine = class {
|
|
|
6930
6880
|
this.persistSeq(ns);
|
|
6931
6881
|
}
|
|
6932
6882
|
if (eventObjects.length > 0 && ackContig > 0 && ackContig !== pageContigBefore) {
|
|
6933
|
-
|
|
6934
|
-
const ackPromise = client._transport.call("group.ack_events", {
|
|
6935
|
-
group_id: groupId,
|
|
6936
|
-
event_seq: ackContig,
|
|
6937
|
-
device_id: client._deviceId,
|
|
6938
|
-
slot_id: client._slotId,
|
|
6939
|
-
_rpc_background: true
|
|
6940
|
-
});
|
|
6941
|
-
if (singlePage) await ackPromise;
|
|
6942
|
-
else ackPromise.catch((e) => {
|
|
6943
|
-
client._clientLog.warn("group event auto-ack failed: group=" + groupId, e);
|
|
6944
|
-
});
|
|
6945
|
-
} catch (e) {
|
|
6946
|
-
client._clientLog.warn("group event auto-ack failed: group=" + groupId, e);
|
|
6947
|
-
}
|
|
6883
|
+
pendingAckSeq = Math.max(pendingAckSeq, ackContig);
|
|
6948
6884
|
}
|
|
6949
6885
|
this.onPullPage(
|
|
6950
6886
|
ns,
|
|
@@ -6957,15 +6893,29 @@ var MessageDeliveryEngine = class {
|
|
|
6957
6893
|
eventObjects.length > 0 ? Number(eventObjects[eventObjects.length - 1].event_seq ?? 0) : void 0
|
|
6958
6894
|
);
|
|
6959
6895
|
const nextAfter = Math.max(eventSeqs.length > 0 ? Math.max(...eventSeqs) : nextAfterSeq, nextAfterSeq);
|
|
6960
|
-
|
|
6896
|
+
const needsMore = result.has_more === true || client._seqTracker.getMaxSeenSeq(ns) > nextAfter;
|
|
6897
|
+
if (singlePage && needsMore && nextAfter > nextAfterSeq) {
|
|
6961
6898
|
continuationAfterSeq = nextAfter;
|
|
6962
6899
|
}
|
|
6963
|
-
if (eventObjects.length === 0 || nextAfter <= nextAfterSeq ||
|
|
6900
|
+
if (eventObjects.length === 0 || nextAfter <= nextAfterSeq || !needsMore) break;
|
|
6964
6901
|
nextAfterSeq = nextAfter;
|
|
6965
6902
|
}
|
|
6966
6903
|
if (pageCount >= maxPages) {
|
|
6967
6904
|
client._clientLog.warn(`group event gap fill reached max_pages=${maxPages} group=${groupId} after_seq=${nextAfterSeq}`);
|
|
6968
6905
|
}
|
|
6906
|
+
if (pendingAckSeq > 0) {
|
|
6907
|
+
try {
|
|
6908
|
+
await client._transport.call("group.ack_events", {
|
|
6909
|
+
group_id: groupId,
|
|
6910
|
+
event_seq: pendingAckSeq,
|
|
6911
|
+
device_id: client._deviceId,
|
|
6912
|
+
slot_id: client._slotId,
|
|
6913
|
+
_rpc_background: true
|
|
6914
|
+
});
|
|
6915
|
+
} catch (e) {
|
|
6916
|
+
client._clientLog.warn("group event auto-ack failed: group=" + groupId, e);
|
|
6917
|
+
}
|
|
6918
|
+
}
|
|
6969
6919
|
} catch (exc) {
|
|
6970
6920
|
failed = true;
|
|
6971
6921
|
client._clientLog.warn(`group event gap-fill failed:${String(exc)}`);
|
|
@@ -7001,41 +6951,15 @@ var MessageDeliveryEngine = class {
|
|
|
7001
6951
|
this.enqueueOnlineUnreadEventHint(data);
|
|
7002
6952
|
return;
|
|
7003
6953
|
}
|
|
7004
|
-
if (this.isSelfJoinGroupChanged(data)) {
|
|
7005
|
-
const contig = client._seqTracker.getContiguousSeq(ns);
|
|
7006
|
-
const maxSeen = client._seqTracker.getMaxSeenSeq(ns);
|
|
7007
|
-
if (contig === 0 && maxSeen === 0 && eventSeq > 1) {
|
|
7008
|
-
client._clientLog.debug(`group.changed self-join baseline: group=${groupId}, event_seq=${eventSeq}, baseline=${eventSeq - 1}`);
|
|
7009
|
-
client._seqTracker.forceContiguousSeq(ns, eventSeq - 1);
|
|
7010
|
-
}
|
|
7011
|
-
}
|
|
7012
6954
|
const contigBefore = client._seqTracker.getContiguousSeq(ns);
|
|
6955
|
+
client._seqTracker.updateMaxSeen(ns, eventSeq);
|
|
7013
6956
|
const publishedDuplicate = client._pushedSeqs.get(ns)?.has(eventSeq) === true;
|
|
7014
6957
|
if (eventSeq <= contigBefore || publishedDuplicate) {
|
|
7015
6958
|
client._clientLog.debug(`group.changed skipped duplicate/stale: group=${groupId}, event_seq=${eventSeq}, contiguous=${contigBefore}`);
|
|
7016
|
-
if (eventSeq <= contigBefore) {
|
|
7017
|
-
this.fireGroupEventAck(groupId, ns, eventSeq, "group event covered push ack");
|
|
7018
|
-
} else if (contigBefore > 0) {
|
|
7019
|
-
this.fireGroupEventAck(groupId, ns, contigBefore, "group event covered push ack");
|
|
7020
|
-
}
|
|
7021
6959
|
return;
|
|
7022
6960
|
}
|
|
7023
6961
|
this.enqueueOrderedMessage(ns, "group.changed", eventSeq, data);
|
|
7024
|
-
needPull =
|
|
7025
|
-
const ackContig = client._seqTracker.getContiguousSeq(ns);
|
|
7026
|
-
await this.drainOrderedMessages(ns);
|
|
7027
|
-
if (ackContig > 0 && ackContig !== contigBefore) {
|
|
7028
|
-
if (data.action !== "dissolved") this.persistSeq(ns);
|
|
7029
|
-
client._transport.call("group.ack_events", {
|
|
7030
|
-
group_id: groupId,
|
|
7031
|
-
event_seq: ackContig,
|
|
7032
|
-
device_id: client._deviceId,
|
|
7033
|
-
slot_id: client._slotId,
|
|
7034
|
-
_rpc_background: true
|
|
7035
|
-
}).catch((e) => {
|
|
7036
|
-
client._clientLog.warn("group event push auto-ack failed: group=" + groupId, e);
|
|
7037
|
-
});
|
|
7038
|
-
}
|
|
6962
|
+
needPull = eventSeq > contigBefore;
|
|
7039
6963
|
if (needPull && groupId && !data._from_gap_fill && client._sessionOptions?.background_sync !== false) {
|
|
7040
6964
|
client._safeAsync(this.fillGroupEventGap(groupId));
|
|
7041
6965
|
}
|
|
@@ -7468,16 +7392,18 @@ var MessageDeliveryEngine = class {
|
|
|
7468
7392
|
};
|
|
7469
7393
|
if (forceTail || order[0] === "tail") result = await run(true, false, void 0, false, forceTail);
|
|
7470
7394
|
const state = this.syncState(ns);
|
|
7471
|
-
const tailMissedDuringPull = tailCompleted && Number(client._seqTracker.getMaxSeenSeq(ns) || 0) > state.head;
|
|
7472
7395
|
const maxSeen = Number(client._seqTracker.getMaxSeenSeq(ns) || 0);
|
|
7473
|
-
const
|
|
7474
|
-
const
|
|
7396
|
+
const pendingUpper = Number(this.pendingP2pPullUpper?.get(ns) ?? 0);
|
|
7397
|
+
const observedUpper = Math.max(maxSeen, pendingUpper);
|
|
7398
|
+
const tailMissedDuringPull = tailCompleted && observedUpper > state.head;
|
|
7399
|
+
const pendingThroughSeq = tailMissedDuringPull ? observedUpper : 0;
|
|
7400
|
+
const tailForward = tailCompleted && (state.ack < state.head || tailMissedDuringPull);
|
|
7475
7401
|
const backgroundWindowForward = order[0] === "forward" && !headForward;
|
|
7476
7402
|
if (headForward || tailForward || client._sessionOptions?.background_sync !== false && backgroundWindowForward) {
|
|
7477
7403
|
const forwardTarget = Math.max(
|
|
7478
7404
|
headForward ? Math.max(pushSeq, maxSeen) : 0,
|
|
7479
7405
|
tailForward || backgroundWindowForward ? state.tail - 1 : 0,
|
|
7480
|
-
tailMissedDuringPull ?
|
|
7406
|
+
tailMissedDuringPull ? observedUpper : 0
|
|
7481
7407
|
);
|
|
7482
7408
|
const forwardMaxPages = this.forwardMaxPages(state.ack, forwardTarget, pageLimit);
|
|
7483
7409
|
result = await run(
|
|
@@ -7536,16 +7462,18 @@ var MessageDeliveryEngine = class {
|
|
|
7536
7462
|
};
|
|
7537
7463
|
if (forceTail || order[0] === "tail") result = await run(true, false, void 0, false, forceTail);
|
|
7538
7464
|
const state = this.syncState(ns);
|
|
7539
|
-
const tailMissedDuringPull = tailCompleted && Number(client._seqTracker.getMaxSeenSeq(ns) || 0) > state.head;
|
|
7540
7465
|
const maxSeen = Number(client._seqTracker.getMaxSeenSeq(ns) || 0);
|
|
7541
|
-
const
|
|
7542
|
-
const
|
|
7466
|
+
const pendingUpper = Number(this.pendingGroupPullUpper?.get(ns) ?? 0);
|
|
7467
|
+
const observedUpper = Math.max(maxSeen, pendingUpper);
|
|
7468
|
+
const tailMissedDuringPull = tailCompleted && observedUpper > state.head;
|
|
7469
|
+
const pendingThroughSeq = tailMissedDuringPull ? observedUpper : 0;
|
|
7470
|
+
const tailForward = tailCompleted && (state.ack < state.head || tailMissedDuringPull);
|
|
7543
7471
|
const backgroundWindowForward = order[0] === "forward" && !headForward;
|
|
7544
7472
|
if (headForward || tailForward || client._sessionOptions?.background_sync !== false && backgroundWindowForward) {
|
|
7545
7473
|
const forwardTarget = Math.max(
|
|
7546
7474
|
headForward ? Math.max(pushSeq, maxSeen) : 0,
|
|
7547
7475
|
tailForward || backgroundWindowForward ? state.tail - 1 : 0,
|
|
7548
|
-
tailMissedDuringPull ?
|
|
7476
|
+
tailMissedDuringPull ? observedUpper : 0
|
|
7549
7477
|
);
|
|
7550
7478
|
const forwardMaxPages = this.forwardMaxPages(state.ack, forwardTarget, pageLimit);
|
|
7551
7479
|
result = await run(
|
|
@@ -7597,13 +7525,13 @@ var MessageDeliveryEngine = class {
|
|
|
7597
7525
|
if (!row) return;
|
|
7598
7526
|
const groupId = typeof row.group_id === "string" ? row.group_id.trim() : "";
|
|
7599
7527
|
if (!groupId) return;
|
|
7600
|
-
const seq2 = typeof row.seq === "number" ? row.seq : 0;
|
|
7601
7528
|
const eventKind = String(row.kind ?? "").trim();
|
|
7602
7529
|
const ns = this.resolvePendingGroupInlineAckNamespace(`group:${groupId}`);
|
|
7603
|
-
|
|
7530
|
+
const seq2 = positiveSafeSequenceHint(row.seq);
|
|
7531
|
+
if (client._v2Session && eventKind !== "group.online_unread_hint" && seq2 > 0) {
|
|
7604
7532
|
client._seqTracker.updateMaxSeen(ns, seq2);
|
|
7605
7533
|
}
|
|
7606
|
-
const hasInlineObject =
|
|
7534
|
+
const hasInlineObject = hasNonEmptyInlineMessage(row.inline_message) && eventKind !== "group.online_unread_hint";
|
|
7607
7535
|
const inlineGeneration = hasInlineObject ? this.captureInlineGeneration() : void 0;
|
|
7608
7536
|
const operation = () => this.processGroupV2MessageCreated(data, "v2", inlineGeneration);
|
|
7609
7537
|
if (hasInlineObject) await this.runPushProcessSerialized(ns, operation, inlineGeneration);
|
|
@@ -7615,7 +7543,6 @@ var MessageDeliveryEngine = class {
|
|
|
7615
7543
|
if (!isJsonObject(data) || !client._v2Session) return;
|
|
7616
7544
|
const groupId = typeof data.group_id === "string" ? data.group_id.trim() : "";
|
|
7617
7545
|
const seq2 = positiveSafeSequenceHint(data.seq);
|
|
7618
|
-
const strictSeq = typeof data.seq === "number" && Number.isSafeInteger(data.seq) && data.seq > 0;
|
|
7619
7546
|
if (!groupId) return;
|
|
7620
7547
|
const eventKind = String(data.kind ?? "").trim();
|
|
7621
7548
|
if (eventKind === "group.online_unread_hint") {
|
|
@@ -7624,11 +7551,12 @@ var MessageDeliveryEngine = class {
|
|
|
7624
7551
|
return;
|
|
7625
7552
|
}
|
|
7626
7553
|
const ns = this.resolvePendingGroupInlineAckNamespace(`group:${groupId}`);
|
|
7627
|
-
const inlinePresent =
|
|
7554
|
+
const inlinePresent = hasNonEmptyInlineMessage(data.inline_message);
|
|
7628
7555
|
if (seq2 <= 0) {
|
|
7629
7556
|
if (inlinePresent) await this.recoverInvalidGroupRealtimeHead(groupId, ns, data.seq);
|
|
7630
7557
|
return;
|
|
7631
7558
|
}
|
|
7559
|
+
client._seqTracker.updateMaxSeen(ns, seq2);
|
|
7632
7560
|
const inline = this.inlineMessage(data);
|
|
7633
7561
|
const inlineMatches = inline !== null && this.inlineGroupBindingMatches(data, inline, groupId, seq2, expectedInlineVersion);
|
|
7634
7562
|
const pendingInline = this.pendingGroupInlineAcks?.get(ns);
|
|
@@ -7649,13 +7577,12 @@ var MessageDeliveryEngine = class {
|
|
|
7649
7577
|
}
|
|
7650
7578
|
if (inlineMatches && !this.isInlineGenerationCurrent(inlineGeneration)) return;
|
|
7651
7579
|
const before = this.syncState(ns);
|
|
7652
|
-
if (strictSeq || !inlinePresent) client._seqTracker.updateMaxSeen(ns, seq2);
|
|
7653
7580
|
if (seq2 <= before.ack && before.ack >= before.tail - 1) {
|
|
7654
7581
|
const canonicalNs = this.resolvePendingGroupInlineAckNamespace(ns);
|
|
7655
7582
|
const pending = this.pendingGroupInlineAcks?.get(canonicalNs);
|
|
7656
|
-
if (pending && seq2 >= pending.seq) {
|
|
7583
|
+
if (inlinePresent && pending && seq2 >= pending.seq) {
|
|
7657
7584
|
this.retryPendingGroupInlineAck(canonicalNs, pending.seq, "covered inline Group ack", seq2);
|
|
7658
|
-
} else if (
|
|
7585
|
+
} else if (inlineMatches) {
|
|
7659
7586
|
this.fireGroupV2Ack(
|
|
7660
7587
|
groupId,
|
|
7661
7588
|
ns,
|
|
@@ -7694,7 +7621,7 @@ var MessageDeliveryEngine = class {
|
|
|
7694
7621
|
if (client._v2Session && Number.isSafeInteger(pushSeq) && pushSeq > 0) {
|
|
7695
7622
|
client._seqTracker.updateMaxSeen(ns, pushSeq);
|
|
7696
7623
|
}
|
|
7697
|
-
const hasInlineObject = isJsonObject(data) &&
|
|
7624
|
+
const hasInlineObject = isJsonObject(data) && hasNonEmptyInlineMessage(data.inline_message);
|
|
7698
7625
|
const inlineGeneration = hasInlineObject ? this.captureInlineGeneration() : void 0;
|
|
7699
7626
|
const operation = () => this.processV2P2PNotification(data, "v2", inlineGeneration);
|
|
7700
7627
|
if (hasInlineObject) await this.runPushProcessSerialized(ns, operation, inlineGeneration);
|
|
@@ -7705,10 +7632,10 @@ var MessageDeliveryEngine = class {
|
|
|
7705
7632
|
const client = this.runtime.client;
|
|
7706
7633
|
if (!client._v2Session) return;
|
|
7707
7634
|
const pushSeq = isJsonObject(data) ? positiveSafeSequenceHint(data.seq) : 0;
|
|
7708
|
-
const strictSeq = isJsonObject(data) && typeof data.seq === "number" && Number.isSafeInteger(data.seq) && data.seq > 0;
|
|
7709
7635
|
const ns = client._aid ? `p2p:${client._aid}` : "";
|
|
7710
7636
|
if (!ns) return;
|
|
7711
|
-
|
|
7637
|
+
if (pushSeq > 0) client._seqTracker.updateMaxSeen(ns, pushSeq);
|
|
7638
|
+
const inlinePresent = isJsonObject(data) && hasNonEmptyInlineMessage(data.inline_message);
|
|
7712
7639
|
if (pushSeq <= 0) {
|
|
7713
7640
|
if (inlinePresent) await this.recoverInvalidP2PRealtimeHead(ns, isJsonObject(data) ? data.seq : void 0);
|
|
7714
7641
|
return;
|
|
@@ -7731,10 +7658,9 @@ var MessageDeliveryEngine = class {
|
|
|
7731
7658
|
}
|
|
7732
7659
|
if (inlineMatches && !this.isInlineGenerationCurrent(inlineGeneration)) return;
|
|
7733
7660
|
const before = this.syncState(ns);
|
|
7734
|
-
if (strictSeq || !inlinePresent) client._seqTracker.updateMaxSeen(ns, pushSeq);
|
|
7735
7661
|
if (pushSeq <= before.ack && before.ack >= before.tail - 1) {
|
|
7736
7662
|
const pending = this.pendingP2PInlineAcks?.get(ns);
|
|
7737
|
-
if (pending && pushSeq >= pending.seq) {
|
|
7663
|
+
if (inlinePresent && pending && pushSeq >= pending.seq) {
|
|
7738
7664
|
this.retryPendingP2PInlineAck(ns, pending.seq, "covered inline P2P ack", pushSeq);
|
|
7739
7665
|
} else if (inlineMatches) {
|
|
7740
7666
|
this.fireP2PV2Ack(pushSeq, "P2P inline covered push ack", inlineGeneration);
|
|
@@ -15677,6 +15603,11 @@ var SIGNED_METHODS = /* @__PURE__ */ new Set([
|
|
|
15677
15603
|
"group.v2.get_proposal",
|
|
15678
15604
|
"group.kick",
|
|
15679
15605
|
"group.add_member",
|
|
15606
|
+
"group.invite_member",
|
|
15607
|
+
"group.list_my_invites",
|
|
15608
|
+
"group.accept_invite",
|
|
15609
|
+
"group.reject_invite",
|
|
15610
|
+
"group.revoke_invite",
|
|
15680
15611
|
"group.leave",
|
|
15681
15612
|
"group.remove_member",
|
|
15682
15613
|
"group.update",
|
|
@@ -15829,7 +15760,9 @@ var NON_IDEMPOTENT_METHODS = /* @__PURE__ */ new Set([
|
|
|
15829
15760
|
"mail.send",
|
|
15830
15761
|
"group.send",
|
|
15831
15762
|
"group.create",
|
|
15832
|
-
"group.
|
|
15763
|
+
"group.accept_invite",
|
|
15764
|
+
"group.reject_invite",
|
|
15765
|
+
"group.revoke_invite",
|
|
15833
15766
|
"group.kick",
|
|
15834
15767
|
"group.remove_member",
|
|
15835
15768
|
"group.leave",
|
|
@@ -16855,6 +16788,8 @@ var RpcPipeline = class {
|
|
|
16855
16788
|
}
|
|
16856
16789
|
postprocessMessagePull(params2, result) {
|
|
16857
16790
|
const client = this.runtime.client;
|
|
16791
|
+
const isTail = String(result.window_mode ?? params2.window_mode ?? "").trim().toLowerCase() === "tail";
|
|
16792
|
+
if (isTail) return;
|
|
16858
16793
|
const messages = result.messages;
|
|
16859
16794
|
const rawMessages = (Array.isArray(messages) ? messages : []).filter(isJsonObject);
|
|
16860
16795
|
if (!client._aid || !client._seqTracker) {
|
|
@@ -16862,9 +16797,9 @@ var RpcPipeline = class {
|
|
|
16862
16797
|
}
|
|
16863
16798
|
const ns = `p2p:${client._aid}`;
|
|
16864
16799
|
const contigBefore = client._seqTracker.getContiguousSeq(ns);
|
|
16865
|
-
|
|
16866
|
-
|
|
16867
|
-
|
|
16800
|
+
const contiguousSeq = Number.isSafeInteger(result.contiguous_seq) ? result.contiguous_seq : void 0;
|
|
16801
|
+
if (contiguousSeq === void 0) client._seqTracker.onPullResult(ns, rawMessages, Number(params2.after_seq ?? 0) || 0);
|
|
16802
|
+
else client._seqTracker.onPullResult(ns, rawMessages, Number(params2.after_seq ?? 0) || 0, contiguousSeq);
|
|
16868
16803
|
const retentionFloor = Math.max(0, Number(result.retention_floor_seq ?? 0));
|
|
16869
16804
|
if (retentionFloor > 0) {
|
|
16870
16805
|
const contig = client._seqTracker.getContiguousSeq(ns);
|
|
@@ -16883,6 +16818,8 @@ var RpcPipeline = class {
|
|
|
16883
16818
|
if (Array.isArray(result.messages)) {
|
|
16884
16819
|
result.messages = result.messages.map((message) => normalizeGroupMentionMode(message));
|
|
16885
16820
|
}
|
|
16821
|
+
const isTail = String(result.window_mode ?? params2.window_mode ?? "").trim().toLowerCase() === "tail";
|
|
16822
|
+
if (isTail) return;
|
|
16886
16823
|
const gid = String(params2.group_id ?? params2.group_aid ?? "").trim();
|
|
16887
16824
|
if (!gid || !client._seqTracker) {
|
|
16888
16825
|
return;
|
|
@@ -16891,17 +16828,17 @@ var RpcPipeline = class {
|
|
|
16891
16828
|
const rawMessages = (Array.isArray(messages) ? messages : []).filter(isJsonObject);
|
|
16892
16829
|
const ns = `group:${gid}`;
|
|
16893
16830
|
const contigBefore = client._seqTracker.getContiguousSeq(ns);
|
|
16894
|
-
|
|
16895
|
-
|
|
16896
|
-
|
|
16831
|
+
const contiguousSeq = Number.isSafeInteger(result.contiguous_seq) ? result.contiguous_seq : void 0;
|
|
16832
|
+
const afterSeq = Number(params2.after_message_seq ?? params2.after_seq ?? 0) || 0;
|
|
16833
|
+
if (contiguousSeq === void 0) client._seqTracker.onPullResult(ns, rawMessages, afterSeq);
|
|
16834
|
+
else client._seqTracker.onPullResult(ns, rawMessages, afterSeq, contiguousSeq);
|
|
16897
16835
|
const cursor = isJsonObject(result.cursor) ? result.cursor : null;
|
|
16898
16836
|
const retentionFloor = Math.max(
|
|
16899
16837
|
0,
|
|
16900
16838
|
Number(result.retention_floor_message_seq ?? result.retention_floor_seq ?? 0),
|
|
16901
16839
|
Number(cursor?.retention_floor_seq ?? 0)
|
|
16902
16840
|
);
|
|
16903
|
-
const
|
|
16904
|
-
const visibilityFloor = isTail ? 0 : Math.max(
|
|
16841
|
+
const visibilityFloor = Math.max(
|
|
16905
16842
|
0,
|
|
16906
16843
|
Math.max(0, Number(result.earliest_available_message_seq ?? 1) - 1),
|
|
16907
16844
|
Number(cursor?.join_seq ?? 0)
|
|
@@ -16910,7 +16847,7 @@ var RpcPipeline = class {
|
|
|
16910
16847
|
if (effectiveFloor > 0) {
|
|
16911
16848
|
const contig = client._seqTracker.getContiguousSeq(ns);
|
|
16912
16849
|
if (contig < effectiveFloor) {
|
|
16913
|
-
client._clientLog?.info?.(`group.pull floor advance: ns=${ns} contiguous=${contig} -> effective_floor=${effectiveFloor} retention_floor=${retentionFloor} visibility_floor=${visibilityFloor} mode
|
|
16850
|
+
client._clientLog?.info?.(`group.pull floor advance: ns=${ns} contiguous=${contig} -> effective_floor=${effectiveFloor} retention_floor=${retentionFloor} visibility_floor=${visibilityFloor} mode=forward`);
|
|
16914
16851
|
client._seqTracker.forceContiguousSeq(ns, effectiveFloor);
|
|
16915
16852
|
}
|
|
16916
16853
|
}
|
|
@@ -18443,6 +18380,21 @@ var MessageFacade = class extends RpcFacade {
|
|
|
18443
18380
|
return this.call("message.query_online", params2);
|
|
18444
18381
|
}
|
|
18445
18382
|
};
|
|
18383
|
+
function normalizeInviteParams(params2) {
|
|
18384
|
+
const out = stripNil2(params2);
|
|
18385
|
+
const rawGroupId = out.group_id ?? out.groupId ?? out.group_aid ?? out.groupAid;
|
|
18386
|
+
if (rawGroupId !== void 0) {
|
|
18387
|
+
out.group_id = normalizeGroupId(rawGroupId);
|
|
18388
|
+
delete out.groupId;
|
|
18389
|
+
delete out.group_aid;
|
|
18390
|
+
delete out.groupAid;
|
|
18391
|
+
}
|
|
18392
|
+
for (const [alias, canonical] of [["inviteId", "invite_id"], ["inviteeAid", "invitee_aid"]]) {
|
|
18393
|
+
if (out[canonical] === void 0 && out[alias] !== void 0) out[canonical] = out[alias];
|
|
18394
|
+
delete out[alias];
|
|
18395
|
+
}
|
|
18396
|
+
return out;
|
|
18397
|
+
}
|
|
18446
18398
|
var MailFacade = class extends RpcFacade {
|
|
18447
18399
|
send(params2) {
|
|
18448
18400
|
return this.call("mail.send", params2);
|
|
@@ -18555,6 +18507,32 @@ var GroupFacade = class extends RpcFacade {
|
|
|
18555
18507
|
addMember(params2) {
|
|
18556
18508
|
return this.call("group.add_member", params2);
|
|
18557
18509
|
}
|
|
18510
|
+
async inviteCall(method, params2) {
|
|
18511
|
+
const normalized = normalizeInviteParams(params2);
|
|
18512
|
+
try {
|
|
18513
|
+
const result = await this.call(method, normalized);
|
|
18514
|
+
await this.client._onGroupInviteActionResult?.(method, normalized, result);
|
|
18515
|
+
return result;
|
|
18516
|
+
} catch (error) {
|
|
18517
|
+
await this.client._onGroupInviteActionResult?.(method, normalized, void 0, error);
|
|
18518
|
+
throw error;
|
|
18519
|
+
}
|
|
18520
|
+
}
|
|
18521
|
+
inviteMember(params2) {
|
|
18522
|
+
return this.inviteCall("group.invite_member", params2);
|
|
18523
|
+
}
|
|
18524
|
+
listMyInvites(params2) {
|
|
18525
|
+
return this.inviteCall("group.list_my_invites", params2);
|
|
18526
|
+
}
|
|
18527
|
+
acceptInvite(params2) {
|
|
18528
|
+
return this.inviteCall("group.accept_invite", params2);
|
|
18529
|
+
}
|
|
18530
|
+
rejectInvite(params2) {
|
|
18531
|
+
return this.inviteCall("group.reject_invite", params2);
|
|
18532
|
+
}
|
|
18533
|
+
revokeInvite(params2) {
|
|
18534
|
+
return this.inviteCall("group.revoke_invite", params2);
|
|
18535
|
+
}
|
|
18558
18536
|
getMembers(params2) {
|
|
18559
18537
|
return this.call("group.get_members", params2);
|
|
18560
18538
|
}
|
|
@@ -23942,6 +23920,22 @@ function deduplicateForwardPageMessages(value, afterSeq) {
|
|
|
23942
23920
|
}
|
|
23943
23921
|
return [...bySeq.entries()].sort(([a], [b]) => a - b).map(([, row]) => row);
|
|
23944
23922
|
}
|
|
23923
|
+
function contiguousPullSeq(afterSeq, seqs, proof) {
|
|
23924
|
+
let contiguous = seqs.length > 0 ? Math.max(afterSeq, ...seqs) : afterSeq;
|
|
23925
|
+
const serverProof = safeNonNegativeSeq(proof);
|
|
23926
|
+
return serverProof !== null ? Math.max(contiguous, serverProof) : contiguous;
|
|
23927
|
+
}
|
|
23928
|
+
function deduplicatePulledResults(messages) {
|
|
23929
|
+
const seen = /* @__PURE__ */ new Set();
|
|
23930
|
+
return messages.filter((message) => {
|
|
23931
|
+
if (!isJsonObject(message)) return true;
|
|
23932
|
+
const seq2 = safeNonNegativeSeq(message.seq);
|
|
23933
|
+
if (seq2 === null || seq2 <= 0) return true;
|
|
23934
|
+
if (seen.has(seq2)) return false;
|
|
23935
|
+
seen.add(seq2);
|
|
23936
|
+
return true;
|
|
23937
|
+
});
|
|
23938
|
+
}
|
|
23945
23939
|
function shouldContinueForwardPage({
|
|
23946
23940
|
rawCount,
|
|
23947
23941
|
nextAfterSeq,
|
|
@@ -23950,10 +23944,11 @@ function shouldContinueForwardPage({
|
|
|
23950
23944
|
hasMoreField,
|
|
23951
23945
|
hasMore,
|
|
23952
23946
|
serverHead,
|
|
23953
|
-
pendingAckSeq
|
|
23947
|
+
pendingAckSeq,
|
|
23948
|
+
observedUpper
|
|
23954
23949
|
}) {
|
|
23955
23950
|
if (rawCount <= 0 || nextAfter <= nextAfterSeq) return false;
|
|
23956
|
-
if (hasMore || serverHead > nextAfter || pendingAckSeq > 0) return true;
|
|
23951
|
+
if (hasMore || serverHead > nextAfter || pendingAckSeq > 0 || observedUpper > nextAfter) return true;
|
|
23957
23952
|
return !hasMoreField && limit > 0 && rawCount >= limit;
|
|
23958
23953
|
}
|
|
23959
23954
|
function validateTailPage(result, afterSeq, pageLimit) {
|
|
@@ -24692,7 +24687,7 @@ var V2E2EECoordinator = class {
|
|
|
24692
24687
|
client._clientLog.warn(`V2 sender IK pending group bootstrap failed group=${groupId}: ${String(formatE2EEError(exc))}`);
|
|
24693
24688
|
}
|
|
24694
24689
|
}
|
|
24695
|
-
if (!session.getPeerIK(fromAid, senderDeviceId)) {
|
|
24690
|
+
if (typeof session.getPeerIK === "function" && !session.getPeerIK(fromAid, senderDeviceId)) {
|
|
24696
24691
|
await this.getV2SenderPubDer(fromAid, senderDeviceId);
|
|
24697
24692
|
}
|
|
24698
24693
|
}
|
|
@@ -24728,6 +24723,7 @@ var V2E2EECoordinator = class {
|
|
|
24728
24723
|
client._v2SenderIKPending.delete(key);
|
|
24729
24724
|
const seq2 = Number(entry.msg.seq ?? 0);
|
|
24730
24725
|
if (entry.groupId) {
|
|
24726
|
+
if (client._delivery.isSelfSentGroupMessage?.(entry.msg)) continue;
|
|
24731
24727
|
plaintext = normalizeGroupMentionMode(plaintext, entry.msg, entry.msg.envelope_json);
|
|
24732
24728
|
plaintext.group_id = entry.groupId;
|
|
24733
24729
|
await client._publishPulledMessage("group.message_created", `group:${entry.groupId}`, seq2, plaintext, false, "pending_retry");
|
|
@@ -24920,6 +24916,9 @@ var V2E2EECoordinator = class {
|
|
|
24920
24916
|
client._clientLog.warn(`Group Tail \u5355\u6761\u6D88\u606F\u89E3\u5BC6\u5931\u8D25\uFF0C\u8FDE\u7EED\u6027\u8BC1\u660E\u4ECD\u4FDD\u7559: group=${groupId}, seq=${seq2}`);
|
|
24921
24917
|
return null;
|
|
24922
24918
|
}
|
|
24919
|
+
if (publish && !history && client._delivery.isSelfSentGroupMessage?.(msg)) {
|
|
24920
|
+
return plaintext;
|
|
24921
|
+
}
|
|
24923
24922
|
if (publish) {
|
|
24924
24923
|
if (orderedPublish) {
|
|
24925
24924
|
await client._delivery.publishOrderedMessage(
|
|
@@ -24941,13 +24940,6 @@ var V2E2EECoordinator = class {
|
|
|
24941
24940
|
async decodeInlineGroupMessage(msg, groupId, groupAid) {
|
|
24942
24941
|
return await this.decodeGroupWindowMessage(msg, groupId, groupAid, false, false, "inline_push");
|
|
24943
24942
|
}
|
|
24944
|
-
async applyTailFloor(ns, floor) {
|
|
24945
|
-
const client = this.client;
|
|
24946
|
-
if (!ns || floor <= 0 || client._seqTracker.getContiguousSeq(ns) >= floor) return;
|
|
24947
|
-
client._seqTracker.forceContiguousSeq(ns, floor);
|
|
24948
|
-
client._persistSeq(ns);
|
|
24949
|
-
await client._saveSeqTrackerState?.();
|
|
24950
|
-
}
|
|
24951
24943
|
async pullV2TailInternal(params2, deferPublish = false) {
|
|
24952
24944
|
const client = this.client;
|
|
24953
24945
|
if (params2.window_mode !== "tail") throw new ValidationError("window_mode must equal tail");
|
|
@@ -24957,9 +24949,6 @@ var V2E2EECoordinator = class {
|
|
|
24957
24949
|
const ns = client._aid ? `p2p:${client._aid}` : "";
|
|
24958
24950
|
if (ns) client._delivery.onPullStarted?.(ns);
|
|
24959
24951
|
const result = await client._callRawV2Rpc("message.v2.pull", { window_mode: "tail", after_seq: afterSeq, limit, _rpc_foreground: true });
|
|
24960
|
-
const floor = Number(result.retention_floor_seq ?? 0);
|
|
24961
|
-
const previous = ns ? client._seqTracker.getSyncState(ns) : null;
|
|
24962
|
-
await this.applyTailFloor(ns, Number.isSafeInteger(floor) ? floor : 0);
|
|
24963
24952
|
const page = validateTailPage(result, afterSeq, limit);
|
|
24964
24953
|
if (ns) {
|
|
24965
24954
|
client._seqTracker.commitTailWindow(ns, {
|
|
@@ -24977,7 +24966,6 @@ var V2E2EECoordinator = class {
|
|
|
24977
24966
|
if (plaintext) decoded.push(plaintext);
|
|
24978
24967
|
}
|
|
24979
24968
|
const ack = ns ? client._seqTracker.getContiguousSeq(ns) : 0;
|
|
24980
|
-
if (previous && ack > previous.ack) await this.ackV2(ack);
|
|
24981
24969
|
if (ns) client._delivery.onPullPage?.(
|
|
24982
24970
|
ns,
|
|
24983
24971
|
decoded.length,
|
|
@@ -25097,6 +25085,11 @@ var V2E2EECoordinator = class {
|
|
|
25097
25085
|
const pageContigBefore = ns ? client._seqTracker.getContiguousSeq(ns) : 0;
|
|
25098
25086
|
const pageTrackerSnapshot = ns && typeof client._seqTracker.snapshotNamespace === "function" ? client._seqTracker.snapshotNamespace(ns) : null;
|
|
25099
25087
|
const pageMaxSeq = seqs.length > 0 ? Math.max(...seqs) : nextAfterSeq;
|
|
25088
|
+
const pageContiguousSeq = contiguousPullSeq(
|
|
25089
|
+
pageContigBefore,
|
|
25090
|
+
seqs,
|
|
25091
|
+
result.contiguous_seq
|
|
25092
|
+
);
|
|
25100
25093
|
const deferredKeyFetches = /* @__PURE__ */ new Map();
|
|
25101
25094
|
let blockedSeq = 0;
|
|
25102
25095
|
const pageDecryptedBefore = decrypted.length;
|
|
@@ -25188,11 +25181,12 @@ var V2E2EECoordinator = class {
|
|
|
25188
25181
|
const serverAckSeq = parsedServerAckSeq ?? 0;
|
|
25189
25182
|
const retentionFloor = Math.max(0, Number(result.retention_floor_seq ?? 0));
|
|
25190
25183
|
if (ns) {
|
|
25191
|
-
const commitTarget =
|
|
25184
|
+
const commitTarget = Math.max(
|
|
25192
25185
|
pageContigBefore,
|
|
25193
25186
|
Number.isFinite(retentionFloor) ? retentionFloor : 0,
|
|
25194
25187
|
pageCount === 1 ? deferredServerCursor : 0,
|
|
25195
|
-
|
|
25188
|
+
serverAckSeq,
|
|
25189
|
+
blockedSeq > 0 ? blockedSeq - 1 : pageContiguousSeq
|
|
25196
25190
|
);
|
|
25197
25191
|
let ackSeq = pageContigBefore;
|
|
25198
25192
|
let contigAdvanced = false;
|
|
@@ -25230,10 +25224,10 @@ var V2E2EECoordinator = class {
|
|
|
25230
25224
|
this.recordForwardCursor(ns, serverAckSeq, ackSeq);
|
|
25231
25225
|
}
|
|
25232
25226
|
const knownServerAckSeq = hasServerAckSeq ? serverAckSeq : pageCount === 1 ? deferredServerCursor : 0;
|
|
25233
|
-
const ackNeeded =
|
|
25227
|
+
const ackNeeded = ackSeq > 0 && ackSeq > lastAutoAckSeq && (hasServerAckSeq && ackSeq > serverAckSeq || contigAdvanced && ackSeq > knownServerAckSeq);
|
|
25234
25228
|
if (ackNeeded) {
|
|
25235
25229
|
this.recordForwardAck(ns, ackSeq);
|
|
25236
|
-
const nextAfter2 = Math.max(
|
|
25230
|
+
const nextAfter2 = Math.max(pageContiguousSeq, nextAfterSeq);
|
|
25237
25231
|
const canContinuePage = blockedSeq <= 0 && messages.length > 0 && nextAfter2 > nextAfterSeq;
|
|
25238
25232
|
if (canContinuePage) {
|
|
25239
25233
|
pendingAckSeq = Math.max(pendingAckSeq, ackSeq);
|
|
@@ -25254,7 +25248,7 @@ var V2E2EECoordinator = class {
|
|
|
25254
25248
|
client._seqTracker.getContiguousSeq(ns),
|
|
25255
25249
|
pageMaxSeq
|
|
25256
25250
|
);
|
|
25257
|
-
const nextAfter = Math.max(
|
|
25251
|
+
const nextAfter = Math.max(pageContiguousSeq, nextAfterSeq);
|
|
25258
25252
|
const rawCount = messages.length;
|
|
25259
25253
|
if (blockedSeq > 0) break;
|
|
25260
25254
|
const shouldContinue = shouldContinueForwardPage({
|
|
@@ -25265,7 +25259,8 @@ var V2E2EECoordinator = class {
|
|
|
25265
25259
|
hasMoreField,
|
|
25266
25260
|
hasMore,
|
|
25267
25261
|
serverHead,
|
|
25268
|
-
pendingAckSeq
|
|
25262
|
+
pendingAckSeq,
|
|
25263
|
+
observedUpper: typeof client._seqTracker.getMaxSeenSeq === "function" ? client._seqTracker.getMaxSeenSeq(ns) : nextAfter
|
|
25269
25264
|
});
|
|
25270
25265
|
if (!shouldContinue) break;
|
|
25271
25266
|
if (pullGateKey && opts?.gateLocked && client._rpcPipeline?.yieldPullGate) {
|
|
@@ -25289,7 +25284,7 @@ var V2E2EECoordinator = class {
|
|
|
25289
25284
|
}
|
|
25290
25285
|
}
|
|
25291
25286
|
client._delivery.onPullWorkSettled?.();
|
|
25292
|
-
return decrypted;
|
|
25287
|
+
return deduplicatePulledResults(decrypted);
|
|
25293
25288
|
}
|
|
25294
25289
|
async confirmForwardP2PAck(upToSeq, inlineGeneration) {
|
|
25295
25290
|
const ns = this.client._aid ? `p2p:${this.client._aid}` : "";
|
|
@@ -25375,10 +25370,7 @@ var V2E2EECoordinator = class {
|
|
|
25375
25370
|
if (isJsonObject(result)) {
|
|
25376
25371
|
const seq2 = Number(result.seq ?? 0);
|
|
25377
25372
|
if (seq2 > 0) {
|
|
25378
|
-
|
|
25379
|
-
client._seqTracker.onMessageSeq(ns, seq2);
|
|
25380
|
-
client._markPublishedSeq(ns, seq2);
|
|
25381
|
-
await client._saveSeqTrackerState();
|
|
25373
|
+
client._markPublishedSeq(`group:${gid}`, seq2);
|
|
25382
25374
|
}
|
|
25383
25375
|
}
|
|
25384
25376
|
return client._delivery.attachSendResultEnvelope("group.send", withExplicitGroupAid({
|
|
@@ -25398,10 +25390,7 @@ var V2E2EECoordinator = class {
|
|
|
25398
25390
|
if (isJsonObject(result)) {
|
|
25399
25391
|
const seq2 = Number(result.seq ?? 0);
|
|
25400
25392
|
if (seq2 > 0) {
|
|
25401
|
-
|
|
25402
|
-
client._seqTracker.onMessageSeq(ns, seq2);
|
|
25403
|
-
client._markPublishedSeq(ns, seq2);
|
|
25404
|
-
await client._saveSeqTrackerState();
|
|
25393
|
+
client._markPublishedSeq(`group:${gid}`, seq2);
|
|
25405
25394
|
}
|
|
25406
25395
|
}
|
|
25407
25396
|
return client._delivery.attachSendResultEnvelope("group.send", withExplicitGroupAid({
|
|
@@ -25440,9 +25429,6 @@ var V2E2EECoordinator = class {
|
|
|
25440
25429
|
}, groupAid));
|
|
25441
25430
|
const resultAid = String(result.group_aid ?? result.groupAid ?? "").trim();
|
|
25442
25431
|
if (resultAid) groupAid = resultAid;
|
|
25443
|
-
const floor = Number(result.retention_floor_message_seq ?? result.retention_floor_seq ?? 0);
|
|
25444
|
-
const previous = client._seqTracker.getSyncState(ns);
|
|
25445
|
-
await this.applyTailFloor(ns, Number.isSafeInteger(floor) ? floor : 0);
|
|
25446
25432
|
const page = validateTailPage(result, afterSeq, limit);
|
|
25447
25433
|
client._seqTracker.commitTailWindow(ns, {
|
|
25448
25434
|
windowStartSeq: page.windowStart,
|
|
@@ -25459,7 +25445,6 @@ var V2E2EECoordinator = class {
|
|
|
25459
25445
|
if (plaintext) decoded.push(plaintext);
|
|
25460
25446
|
}
|
|
25461
25447
|
const ack = client._seqTracker.getContiguousSeq(ns);
|
|
25462
|
-
if (ack > previous.ack) await this.ackGroupV2(groupId, ack, groupAid);
|
|
25463
25448
|
if (ownsCursor) client._delivery.onPullPage?.(
|
|
25464
25449
|
ns,
|
|
25465
25450
|
decoded.length,
|
|
@@ -25616,6 +25601,11 @@ var V2E2EECoordinator = class {
|
|
|
25616
25601
|
const pageContigBefore = client._seqTracker.getContiguousSeq(ns);
|
|
25617
25602
|
const pageTrackerSnapshot = typeof client._seqTracker.snapshotNamespace === "function" ? client._seqTracker.snapshotNamespace(ns) : null;
|
|
25618
25603
|
const pageMaxSeq = seqs.length > 0 ? Math.max(...seqs) : nextAfterSeq;
|
|
25604
|
+
const pageContiguousSeq = contiguousPullSeq(
|
|
25605
|
+
pageContigBefore,
|
|
25606
|
+
seqs,
|
|
25607
|
+
result.contiguous_seq
|
|
25608
|
+
);
|
|
25619
25609
|
const deferredKeyFetches = /* @__PURE__ */ new Map();
|
|
25620
25610
|
let blockedSeq = 0;
|
|
25621
25611
|
const pageDecryptedBefore = decrypted.length;
|
|
@@ -25653,7 +25643,11 @@ var V2E2EECoordinator = class {
|
|
|
25653
25643
|
};
|
|
25654
25644
|
v1Msg = normalizeGroupMentionMode(v1Msg, msg, msg.envelope_json);
|
|
25655
25645
|
attachGatewayProximity(v1Msg, msg);
|
|
25656
|
-
|
|
25646
|
+
if (!client._delivery.isSelfSentGroupMessage?.(msg)) {
|
|
25647
|
+
await client._publishPulledMessage("group.message_created", ns, seq2, v1Msg, false);
|
|
25648
|
+
} else {
|
|
25649
|
+
client._markPublishedSeq(ns, seq2);
|
|
25650
|
+
}
|
|
25657
25651
|
decrypted.push(v1Msg);
|
|
25658
25652
|
continue;
|
|
25659
25653
|
}
|
|
@@ -25697,7 +25691,11 @@ var V2E2EECoordinator = class {
|
|
|
25697
25691
|
if (plaintext2) {
|
|
25698
25692
|
plaintext2.group_id = gid;
|
|
25699
25693
|
plaintext2.group_aid = eventGroupAid;
|
|
25700
|
-
|
|
25694
|
+
if (!client._delivery.isSelfSentGroupMessage?.(msg)) {
|
|
25695
|
+
await client._publishPulledMessage("group.message_created", ns, seq2, plaintext2, false);
|
|
25696
|
+
} else {
|
|
25697
|
+
client._markPublishedSeq(ns, seq2);
|
|
25698
|
+
}
|
|
25701
25699
|
decrypted.push(plaintext2);
|
|
25702
25700
|
}
|
|
25703
25701
|
}
|
|
@@ -25725,7 +25723,11 @@ var V2E2EECoordinator = class {
|
|
|
25725
25723
|
plaintext = normalizeGroupMentionMode(plaintext, msg, msg.envelope_json);
|
|
25726
25724
|
plaintext.group_id = gid;
|
|
25727
25725
|
plaintext.group_aid = eventGroupAid;
|
|
25728
|
-
|
|
25726
|
+
if (!client._delivery.isSelfSentGroupMessage?.(msg)) {
|
|
25727
|
+
await client._publishPulledMessage("group.message_created", ns, seq2, plaintext, false);
|
|
25728
|
+
} else {
|
|
25729
|
+
client._markPublishedSeq(ns, seq2);
|
|
25730
|
+
}
|
|
25729
25731
|
decrypted.push(plaintext);
|
|
25730
25732
|
}
|
|
25731
25733
|
const hasServerCursor = cursor !== null && Object.prototype.hasOwnProperty.call(cursor, "current_seq");
|
|
@@ -25741,11 +25743,12 @@ var V2E2EECoordinator = class {
|
|
|
25741
25743
|
Number(cursor?.join_seq ?? 0)
|
|
25742
25744
|
);
|
|
25743
25745
|
const effectiveFloor = Math.max(retentionFloor, visibilityFloor);
|
|
25744
|
-
const commitTarget =
|
|
25746
|
+
const commitTarget = Math.max(
|
|
25745
25747
|
pageContigBefore,
|
|
25746
25748
|
Number.isFinite(effectiveFloor) ? effectiveFloor : 0,
|
|
25747
25749
|
ownsCursor && pageCount === 1 ? deferredServerCursor : 0,
|
|
25748
|
-
|
|
25750
|
+
cursorCurrentSeq,
|
|
25751
|
+
blockedSeq > 0 ? blockedSeq - 1 : pageContiguousSeq
|
|
25749
25752
|
);
|
|
25750
25753
|
let ackSeq = pageContigBefore;
|
|
25751
25754
|
let contigAdvanced = false;
|
|
@@ -25795,10 +25798,10 @@ var V2E2EECoordinator = class {
|
|
|
25795
25798
|
this.recordForwardCursor(ns, cursorCurrentSeq, ackSeq);
|
|
25796
25799
|
}
|
|
25797
25800
|
const knownServerCursorSeq = hasServerCursor ? cursorCurrentSeq : ownsCursor && pageCount === 1 ? deferredServerCursor : 0;
|
|
25798
|
-
const ackNeeded =
|
|
25801
|
+
const ackNeeded = ackSeq > 0 && ackSeq > lastAutoAckSeq && ownsCursor && (hasServerCursor && ackSeq > cursorCurrentSeq || contigAdvanced && ackSeq > knownServerCursorSeq);
|
|
25799
25802
|
if (ackNeeded) {
|
|
25800
25803
|
this.recordForwardAck(ns, ackSeq);
|
|
25801
|
-
const nextAfter2 = Math.max(
|
|
25804
|
+
const nextAfter2 = Math.max(pageContiguousSeq, nextAfterSeq);
|
|
25802
25805
|
const canContinuePage = blockedSeq <= 0 && messages.length > 0 && nextAfter2 > nextAfterSeq && ownsCursor;
|
|
25803
25806
|
if (canContinuePage) {
|
|
25804
25807
|
pendingAckSeq = Math.max(pendingAckSeq, ackSeq);
|
|
@@ -25808,7 +25811,7 @@ var V2E2EECoordinator = class {
|
|
|
25808
25811
|
lastAutoAckSeq = Math.max(lastAutoAckSeq, ackSeq);
|
|
25809
25812
|
}
|
|
25810
25813
|
}
|
|
25811
|
-
const nextAfter = Math.max(
|
|
25814
|
+
const nextAfter = Math.max(pageContiguousSeq, nextAfterSeq);
|
|
25812
25815
|
if (!ownsCursor) break;
|
|
25813
25816
|
const rawCount = messages.length;
|
|
25814
25817
|
if (blockedSeq > 0) break;
|
|
@@ -25820,7 +25823,8 @@ var V2E2EECoordinator = class {
|
|
|
25820
25823
|
hasMoreField,
|
|
25821
25824
|
hasMore,
|
|
25822
25825
|
serverHead,
|
|
25823
|
-
pendingAckSeq
|
|
25826
|
+
pendingAckSeq,
|
|
25827
|
+
observedUpper: typeof client._seqTracker.getMaxSeenSeq === "function" ? client._seqTracker.getMaxSeenSeq(ns) : nextAfter
|
|
25824
25828
|
});
|
|
25825
25829
|
if (!shouldContinue) break;
|
|
25826
25830
|
if (pullGateKey && opts?.gateLocked && client._rpcPipeline?.yieldPullGate) {
|
|
@@ -25846,7 +25850,7 @@ var V2E2EECoordinator = class {
|
|
|
25846
25850
|
}
|
|
25847
25851
|
}
|
|
25848
25852
|
client._delivery.onPullWorkSettled?.();
|
|
25849
|
-
return decrypted;
|
|
25853
|
+
return deduplicatePulledResults(decrypted);
|
|
25850
25854
|
}
|
|
25851
25855
|
async confirmForwardGroupAck(groupId, upToSeq, groupAid) {
|
|
25852
25856
|
const ns = `group:${String(groupId ?? "").trim()}`;
|
|
@@ -26683,7 +26687,8 @@ var MEMBERSHIP_MUTATION_METHODS = /* @__PURE__ */ new Set([
|
|
|
26683
26687
|
"group.review_join_request",
|
|
26684
26688
|
"group.batch_review_join_request",
|
|
26685
26689
|
"group.use_invite_code",
|
|
26686
|
-
"group.request_join"
|
|
26690
|
+
"group.request_join",
|
|
26691
|
+
"group.accept_invite"
|
|
26687
26692
|
]);
|
|
26688
26693
|
var SPK_REGISTRATION_MUTATION_METHODS = /* @__PURE__ */ new Set([
|
|
26689
26694
|
"group.create",
|
|
@@ -29412,6 +29417,7 @@ var RECONNECT_MIN_BASE_DELAY_SECONDS = 1;
|
|
|
29412
29417
|
var RECONNECT_MAX_BASE_DELAY_SECONDS = 64;
|
|
29413
29418
|
var TOKEN_REFRESH_CHECK_INTERVAL_MS = 3e4;
|
|
29414
29419
|
var MAX_NOTIFY_PAYLOAD_SIZE = 64 * 1024;
|
|
29420
|
+
var GROUP_INVITE_METADATA_KEY = "group_invite_pending_v1";
|
|
29415
29421
|
function clampReconnectDelaySeconds(value, fallback, upper = RECONNECT_MAX_BASE_DELAY_SECONDS) {
|
|
29416
29422
|
const parsed = Number(value);
|
|
29417
29423
|
const seconds = Number.isFinite(parsed) ? parsed : fallback;
|
|
@@ -29804,6 +29810,9 @@ var _AUNClient = class _AUNClient {
|
|
|
29804
29810
|
__publicField(this, "_mailFacade");
|
|
29805
29811
|
__publicField(this, "_groupFacade");
|
|
29806
29812
|
__publicField(this, "_streamFacade");
|
|
29813
|
+
__publicField(this, "_groupInvitePending", /* @__PURE__ */ new Map());
|
|
29814
|
+
__publicField(this, "_groupInviteStateAid", null);
|
|
29815
|
+
__publicField(this, "_groupInviteStateLoad", null);
|
|
29807
29816
|
/**
|
|
29808
29817
|
* 处理 V2 push 通知:自动 pull + decrypt + emit。
|
|
29809
29818
|
*/
|
|
@@ -29927,6 +29936,15 @@ var _AUNClient = class _AUNClient {
|
|
|
29927
29936
|
this._dispatcher.subscribe("_raw.group.changed", (data) => {
|
|
29928
29937
|
this._onRawGroupChanged(data);
|
|
29929
29938
|
});
|
|
29939
|
+
this._dispatcher.subscribe("_raw.group.invite_created", (data) => {
|
|
29940
|
+
this._safeAsync(this._onRawGroupInviteReceived(data, "push"));
|
|
29941
|
+
});
|
|
29942
|
+
this._dispatcher.subscribe("_raw.group.invite_received", (data) => {
|
|
29943
|
+
this._safeAsync(this._onRawGroupInviteReceived(data, "push"));
|
|
29944
|
+
});
|
|
29945
|
+
this._dispatcher.subscribe("_raw.group.invite_finalized", (data) => {
|
|
29946
|
+
this._safeAsync(this._onRawGroupInviteFinalized(data));
|
|
29947
|
+
});
|
|
29930
29948
|
this._dispatcher.subscribe("_raw.peer.v2.message_received", (data) => {
|
|
29931
29949
|
this._safeAsync(this._onV2PushNotification(data));
|
|
29932
29950
|
});
|
|
@@ -30474,6 +30492,8 @@ var _AUNClient = class _AUNClient {
|
|
|
30474
30492
|
}
|
|
30475
30493
|
this._aidStore = store;
|
|
30476
30494
|
const payload = { ...params2 };
|
|
30495
|
+
const initialMembers = payload.members;
|
|
30496
|
+
delete payload.members;
|
|
30477
30497
|
if (payload.group_name === void 0 && payload.groupName !== void 0) {
|
|
30478
30498
|
payload.group_name = payload.groupName;
|
|
30479
30499
|
delete payload.groupName;
|
|
@@ -30503,7 +30523,8 @@ var _AUNClient = class _AUNClient {
|
|
|
30503
30523
|
const result2 = { ...createdMap, ...boundMap, group: { ...createdGroup, ...boundGroup } };
|
|
30504
30524
|
const postprocessParams2 = { ...payload };
|
|
30505
30525
|
delete postprocessParams2._defer_group_ready_postprocess;
|
|
30506
|
-
|
|
30526
|
+
const processed2 = await this._groupState.postprocessResult("group.create", postprocessParams2, result2);
|
|
30527
|
+
return await this._inviteInitialGroupMembers(processed2, groupId, initialMembers);
|
|
30507
30528
|
}
|
|
30508
30529
|
const pendingKey = `create:${String(payload.group_name).trim().toLowerCase()}`;
|
|
30509
30530
|
const keystore = store._keystore;
|
|
@@ -30553,7 +30574,29 @@ var _AUNClient = class _AUNClient {
|
|
|
30553
30574
|
}
|
|
30554
30575
|
const postprocessParams = { ...payload };
|
|
30555
30576
|
delete postprocessParams._defer_group_ready_postprocess;
|
|
30556
|
-
|
|
30577
|
+
const processed = await this._groupState.postprocessResult("group.create", postprocessParams, result);
|
|
30578
|
+
return await this._inviteInitialGroupMembers(processed, String(group.group_id ?? groupAid).trim(), initialMembers);
|
|
30579
|
+
}
|
|
30580
|
+
async _inviteInitialGroupMembers(result, groupId, members) {
|
|
30581
|
+
const invites = [];
|
|
30582
|
+
const inviteErrors = [];
|
|
30583
|
+
const seen = /* @__PURE__ */ new Set();
|
|
30584
|
+
if (Array.isArray(members)) {
|
|
30585
|
+
for (const item of members) {
|
|
30586
|
+
const aid = typeof item === "string" ? item.trim() : isJsonObject(item) ? String(item.aid ?? "").trim() : "";
|
|
30587
|
+
const memberType = isJsonObject(item) ? String(item.member_type ?? "").trim() : "";
|
|
30588
|
+
if (!aid || aid === String(this._aid ?? this._currentAid?.aid ?? "").trim() || seen.has(aid)) continue;
|
|
30589
|
+
seen.add(aid);
|
|
30590
|
+
const params2 = { group_id: groupId, invitee_aid: aid };
|
|
30591
|
+
if (memberType) params2.member_type = memberType;
|
|
30592
|
+
try {
|
|
30593
|
+
invites.push(await this.group.inviteMember(params2));
|
|
30594
|
+
} catch (err) {
|
|
30595
|
+
inviteErrors.push({ aid, error: err instanceof Error ? err.message : String(err) });
|
|
30596
|
+
}
|
|
30597
|
+
}
|
|
30598
|
+
}
|
|
30599
|
+
return { ...isJsonObject(result) ? result : {}, invites, invite_errors: inviteErrors };
|
|
30557
30600
|
}
|
|
30558
30601
|
_groupAgentMdContent(groupAid, params2 = {}, group = {}) {
|
|
30559
30602
|
const explicit = params2.group_agent_md ?? params2.groupAgentMd ?? params2.content;
|
|
@@ -31135,6 +31178,239 @@ var _AUNClient = class _AUNClient {
|
|
|
31135
31178
|
const member = isJsonObject(result.member) ? result.member : null;
|
|
31136
31179
|
return member ? String(member.group_id ?? member.groupId ?? member.group_aid ?? member.groupAid ?? "") : "";
|
|
31137
31180
|
}
|
|
31181
|
+
groupInviteKey(groupId, inviteeAid) {
|
|
31182
|
+
const group = normalizeGroupId(groupId);
|
|
31183
|
+
const invitee = String(inviteeAid ?? "").trim().toLowerCase();
|
|
31184
|
+
return group && invitee ? `${group}
|
|
31185
|
+
${invitee}` : "";
|
|
31186
|
+
}
|
|
31187
|
+
async ensureGroupInviteStateLoaded() {
|
|
31188
|
+
const aid = String(this._aid ?? "").trim();
|
|
31189
|
+
if (!aid) {
|
|
31190
|
+
this._groupInvitePending.clear();
|
|
31191
|
+
this._groupInviteStateAid = null;
|
|
31192
|
+
return;
|
|
31193
|
+
}
|
|
31194
|
+
if (this._groupInviteStateAid === aid) return;
|
|
31195
|
+
if (this._groupInviteStateLoad) {
|
|
31196
|
+
await this._groupInviteStateLoad;
|
|
31197
|
+
if (this._groupInviteStateAid === aid) return;
|
|
31198
|
+
}
|
|
31199
|
+
this._groupInviteStateLoad = (async () => {
|
|
31200
|
+
this._groupInvitePending.clear();
|
|
31201
|
+
this._groupInviteStateAid = aid;
|
|
31202
|
+
const getter = this._tokenStore?.getMetadata;
|
|
31203
|
+
if (typeof getter !== "function") return;
|
|
31204
|
+
try {
|
|
31205
|
+
const raw = await getter.call(this._tokenStore, aid, GROUP_INVITE_METADATA_KEY);
|
|
31206
|
+
const parsed = raw ? JSON.parse(String(raw)) : {};
|
|
31207
|
+
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) return;
|
|
31208
|
+
for (const [key, value] of Object.entries(parsed)) {
|
|
31209
|
+
if (value && typeof value === "object" && !Array.isArray(value)) {
|
|
31210
|
+
this._groupInvitePending.set(key, value);
|
|
31211
|
+
}
|
|
31212
|
+
}
|
|
31213
|
+
} catch (exc) {
|
|
31214
|
+
this._clientLog.debug(`group invite state restore skipped: ${String(exc)}`);
|
|
31215
|
+
}
|
|
31216
|
+
})().finally(() => {
|
|
31217
|
+
this._groupInviteStateLoad = null;
|
|
31218
|
+
});
|
|
31219
|
+
return this._groupInviteStateLoad;
|
|
31220
|
+
}
|
|
31221
|
+
async persistGroupInviteState() {
|
|
31222
|
+
const aid = String(this._aid ?? "").trim();
|
|
31223
|
+
const setter = this._tokenStore?.setMetadata;
|
|
31224
|
+
if (!aid || typeof setter !== "function") return;
|
|
31225
|
+
const state = {};
|
|
31226
|
+
for (const [key, value] of this._groupInvitePending) state[key] = value;
|
|
31227
|
+
try {
|
|
31228
|
+
await setter.call(this._tokenStore, aid, GROUP_INVITE_METADATA_KEY, JSON.stringify(state));
|
|
31229
|
+
} catch (exc) {
|
|
31230
|
+
this._clientLog.debug(`group invite state persist skipped: ${String(exc)}`);
|
|
31231
|
+
}
|
|
31232
|
+
}
|
|
31233
|
+
inviteArray(value, singular) {
|
|
31234
|
+
const values = Array.isArray(value) ? value : singular !== void 0 ? [singular] : [];
|
|
31235
|
+
return [...new Set(values.map((item) => String(item ?? "").trim()).filter(Boolean))];
|
|
31236
|
+
}
|
|
31237
|
+
inviteBool(value) {
|
|
31238
|
+
return value === true || value === 1 || String(value ?? "").trim().toLowerCase() === "true";
|
|
31239
|
+
}
|
|
31240
|
+
async _onRawGroupInviteReceived(data, source = "push") {
|
|
31241
|
+
if (!isJsonObject(data)) return;
|
|
31242
|
+
const groupId = normalizeGroupId(data.group_id ?? data.groupId ?? data.group_aid ?? data.groupAid);
|
|
31243
|
+
const inviteeAid = String(data.invitee_aid ?? data.inviteeAid ?? this._aid ?? "").trim();
|
|
31244
|
+
if (!groupId || !inviteeAid || this._aid && inviteeAid.toLowerCase() !== this._aid.toLowerCase()) return;
|
|
31245
|
+
if (String(data.status ?? "pending").trim().toLowerCase() !== "pending") {
|
|
31246
|
+
await this._onRawGroupInviteFinalized(data);
|
|
31247
|
+
return;
|
|
31248
|
+
}
|
|
31249
|
+
await this.ensureGroupInviteStateLoaded();
|
|
31250
|
+
const key = this.groupInviteKey(groupId, inviteeAid);
|
|
31251
|
+
if (!key) return;
|
|
31252
|
+
const inviteIds = this.inviteArray(data.invite_ids, data.invite_id);
|
|
31253
|
+
const inviterAids = this.inviteArray(data.inviter_aids, data.inviter_aid);
|
|
31254
|
+
const existing = this._groupInvitePending.get(key);
|
|
31255
|
+
if (existing) {
|
|
31256
|
+
existing.invite_ids = [.../* @__PURE__ */ new Set([...this.inviteArray(existing.invite_ids), ...inviteIds])];
|
|
31257
|
+
existing.inviter_aids = [.../* @__PURE__ */ new Set([...this.inviteArray(existing.inviter_aids), ...inviterAids])];
|
|
31258
|
+
await this.persistGroupInviteState();
|
|
31259
|
+
return;
|
|
31260
|
+
}
|
|
31261
|
+
const payload = {
|
|
31262
|
+
...data,
|
|
31263
|
+
group_id: groupId,
|
|
31264
|
+
group_aid: groupId,
|
|
31265
|
+
invitee_aid: inviteeAid,
|
|
31266
|
+
invite_ids: inviteIds,
|
|
31267
|
+
inviter_aids: inviterAids,
|
|
31268
|
+
role: data.role ?? "member",
|
|
31269
|
+
member_type: data.member_type ?? data.memberType ?? "human",
|
|
31270
|
+
created_at: data.created_at ?? data.createdAt ?? 0,
|
|
31271
|
+
expires_at: data.expires_at ?? data.expiresAt ?? 0,
|
|
31272
|
+
status: "pending"
|
|
31273
|
+
};
|
|
31274
|
+
delete payload.groupId;
|
|
31275
|
+
delete payload.groupAid;
|
|
31276
|
+
delete payload.inviteeAid;
|
|
31277
|
+
delete payload.inviterAid;
|
|
31278
|
+
this._groupInvitePending.set(key, payload);
|
|
31279
|
+
await this.persistGroupInviteState();
|
|
31280
|
+
await this._publishAppEvent("group.invite_received", JSON.parse(JSON.stringify(payload)), source);
|
|
31281
|
+
}
|
|
31282
|
+
async _onRawGroupInviteFinalized(data) {
|
|
31283
|
+
if (!isJsonObject(data)) return;
|
|
31284
|
+
await this.ensureGroupInviteStateLoaded();
|
|
31285
|
+
const groupId = normalizeGroupId(data.group_id ?? data.groupId ?? data.group_aid ?? data.groupAid);
|
|
31286
|
+
const inviteeAid = String(data.invitee_aid ?? data.inviteeAid ?? this._aid ?? "").trim();
|
|
31287
|
+
if (this._aid && inviteeAid.toLowerCase() !== this._aid.toLowerCase()) return;
|
|
31288
|
+
const inviteId = String(data.invite_id ?? "").trim();
|
|
31289
|
+
const key = this.groupInviteKey(groupId, inviteeAid);
|
|
31290
|
+
const status = String(data.status ?? "").trim().toLowerCase();
|
|
31291
|
+
const aggregateStatus = String(data.aggregate_status ?? data.aggregateStatus ?? "").trim().toLowerCase();
|
|
31292
|
+
const pendingIds = this.inviteArray(data.pending_invite_ids ?? data.pendingInviteIds);
|
|
31293
|
+
const pendingInviters = this.inviteArray(data.pending_inviter_aids ?? data.pendingInviterAids);
|
|
31294
|
+
const finalizedIds = this.inviteBool(data.remaining_pending) && inviteId ? [inviteId] : this.inviteArray(data.invite_ids, data.invite_id);
|
|
31295
|
+
const finalizedInviters = this.inviteArray(data.inviter_aids, data.inviter_aid);
|
|
31296
|
+
const leavesPending = this.inviteBool(data.remaining_pending) || this.inviteBool(data.pending) || status === "pending" || aggregateStatus === "pending" || pendingIds.length > 0;
|
|
31297
|
+
let changed = false;
|
|
31298
|
+
const candidates = [];
|
|
31299
|
+
if (key) {
|
|
31300
|
+
const current = this._groupInvitePending.get(key);
|
|
31301
|
+
if (current) candidates.push([key, current]);
|
|
31302
|
+
}
|
|
31303
|
+
if (candidates.length === 0 && inviteId) {
|
|
31304
|
+
for (const [itemKey, item] of this._groupInvitePending) {
|
|
31305
|
+
if (this.inviteArray(item.invite_ids).includes(inviteId)) candidates.push([itemKey, item]);
|
|
31306
|
+
}
|
|
31307
|
+
}
|
|
31308
|
+
for (const [itemKey, item] of candidates) {
|
|
31309
|
+
if (!leavesPending) {
|
|
31310
|
+
this._groupInvitePending.delete(itemKey);
|
|
31311
|
+
changed = true;
|
|
31312
|
+
continue;
|
|
31313
|
+
}
|
|
31314
|
+
const currentIds = this.inviteArray(item.invite_ids);
|
|
31315
|
+
const currentInviters = this.inviteArray(item.inviter_aids);
|
|
31316
|
+
const finalizedIndexes = new Set(currentIds.map((id, index) => finalizedIds.includes(id) ? index : -1).filter((index) => index >= 0));
|
|
31317
|
+
const nextIds = pendingIds.length > 0 ? pendingIds : finalizedIds.length > 0 ? currentIds.filter((id) => !finalizedIds.includes(id)) : currentIds;
|
|
31318
|
+
const nextInviters = pendingInviters.length > 0 ? pendingInviters : finalizedInviters.length > 0 ? currentInviters.filter((aid) => !finalizedInviters.includes(aid)) : finalizedIndexes.size > 0 ? currentInviters.filter((_aid, index) => !finalizedIndexes.has(index)) : currentInviters;
|
|
31319
|
+
if (nextIds.length === 0) {
|
|
31320
|
+
this._groupInvitePending.delete(itemKey);
|
|
31321
|
+
} else {
|
|
31322
|
+
item.invite_ids = nextIds;
|
|
31323
|
+
item.inviter_aids = nextInviters;
|
|
31324
|
+
}
|
|
31325
|
+
changed = true;
|
|
31326
|
+
}
|
|
31327
|
+
if (changed) await this.persistGroupInviteState();
|
|
31328
|
+
}
|
|
31329
|
+
async _onGroupInviteActionResult(method, params2, result, error) {
|
|
31330
|
+
if (method === "group.list_my_invites" && !error && (isJsonObject(result) || Array.isArray(result))) {
|
|
31331
|
+
await this.restoreGroupInvitesFromResult(result, params2);
|
|
31332
|
+
return;
|
|
31333
|
+
}
|
|
31334
|
+
if (!["group.accept_invite", "group.reject_invite", "group.revoke_invite"].includes(method)) return;
|
|
31335
|
+
const text3 = String(error instanceof Error ? error.message : error ?? "").toLowerCase();
|
|
31336
|
+
const resultStatus = isJsonObject(result) ? String(result.status ?? "").toLowerCase() : "";
|
|
31337
|
+
const aggregateResultStatus = isJsonObject(result) ? String(result.aggregate_status ?? result.aggregateStatus ?? "").toLowerCase() : "";
|
|
31338
|
+
const terminalStatus = resultStatus || aggregateResultStatus;
|
|
31339
|
+
const pendingResult = resultStatus === "pending" || aggregateResultStatus === "pending" || isJsonObject(result) && (this.inviteBool(result.remaining_pending) || this.inviteBool(result.pending));
|
|
31340
|
+
if (pendingResult) {
|
|
31341
|
+
if (isJsonObject(result) && (this.inviteBool(result.remaining_pending) || this.inviteArray(result.pending_invite_ids ?? result.pendingInviteIds).length > 0)) {
|
|
31342
|
+
await this._onRawGroupInviteFinalized({ ...params2, ...result });
|
|
31343
|
+
}
|
|
31344
|
+
return;
|
|
31345
|
+
}
|
|
31346
|
+
const terminal = !pendingResult && (!error || ["accepted", "rejected", "revoked", "expired", "ended"].includes(terminalStatus) || /ended|expired|not.*pending|no longer.*pending|not found|finalized|already\s+(?:been\s+)?(?:accepted|rejected|revoked)/.test(text3));
|
|
31347
|
+
if (!terminal) return;
|
|
31348
|
+
await this._onRawGroupInviteFinalized({
|
|
31349
|
+
...params2,
|
|
31350
|
+
...isJsonObject(result) ? result : {},
|
|
31351
|
+
status: terminalStatus || "ended"
|
|
31352
|
+
});
|
|
31353
|
+
}
|
|
31354
|
+
async restoreGroupInvitesFromResult(result, requestParams = {}) {
|
|
31355
|
+
const seen = /* @__PURE__ */ new Set();
|
|
31356
|
+
const visitedPages = /* @__PURE__ */ new Set();
|
|
31357
|
+
let current = result;
|
|
31358
|
+
let currentParams = { ...requestParams };
|
|
31359
|
+
let finalPage = false;
|
|
31360
|
+
while (!finalPage) {
|
|
31361
|
+
const root = Array.isArray(current) ? null : isJsonObject(current) ? current : null;
|
|
31362
|
+
const nestedValue = root && isJsonObject(root.data) ? root.data : root;
|
|
31363
|
+
const nested = nestedValue ?? {};
|
|
31364
|
+
const rawItems = Array.isArray(nested.items) ? nested.items : Array.isArray(nested.invites) ? nested.invites : Array.isArray(current) ? current : [];
|
|
31365
|
+
for (const item of rawItems) {
|
|
31366
|
+
if (!isJsonObject(item)) continue;
|
|
31367
|
+
const status = String(item.status ?? "pending").toLowerCase();
|
|
31368
|
+
const gid = normalizeGroupId(item.group_id ?? item.group_aid ?? item.groupId ?? item.groupAid);
|
|
31369
|
+
const aid = String(item.invitee_aid ?? item.inviteeAid ?? this._aid ?? "").trim();
|
|
31370
|
+
if (this._aid && aid.toLowerCase() !== this._aid.toLowerCase()) continue;
|
|
31371
|
+
const key = this.groupInviteKey(gid, aid);
|
|
31372
|
+
if (status === "pending" && key) {
|
|
31373
|
+
seen.add(key);
|
|
31374
|
+
await this._onRawGroupInviteReceived(item, "pull");
|
|
31375
|
+
} else if (key) {
|
|
31376
|
+
seen.add(key);
|
|
31377
|
+
await this._onRawGroupInviteFinalized(item);
|
|
31378
|
+
}
|
|
31379
|
+
}
|
|
31380
|
+
const hasMore = this.inviteBool(nested.has_more ?? nested.hasMore ?? (root ? root.has_more ?? root.hasMore : void 0));
|
|
31381
|
+
if (!hasMore) {
|
|
31382
|
+
finalPage = true;
|
|
31383
|
+
break;
|
|
31384
|
+
}
|
|
31385
|
+
const page = Number(nested.page ?? root?.page ?? currentParams.page ?? 1);
|
|
31386
|
+
const nextPageValue = nested.next_page ?? nested.nextPage ?? root?.next_page ?? root?.nextPage;
|
|
31387
|
+
const nextPage = Number(nextPageValue ?? page + 1);
|
|
31388
|
+
if (!Number.isFinite(nextPage) || nextPage <= 0 || visitedPages.has(nextPage) || nextPage === page) break;
|
|
31389
|
+
visitedPages.add(page);
|
|
31390
|
+
currentParams = { ...currentParams, page: nextPage };
|
|
31391
|
+
if (currentParams.size === void 0) {
|
|
31392
|
+
const size = nested.size ?? root?.size;
|
|
31393
|
+
if (size !== void 0) currentParams.size = size;
|
|
31394
|
+
}
|
|
31395
|
+
current = await this.call("group.list_my_invites", currentParams);
|
|
31396
|
+
}
|
|
31397
|
+
await this.ensureGroupInviteStateLoaded();
|
|
31398
|
+
let changed = false;
|
|
31399
|
+
for (const key of this._groupInvitePending.keys()) {
|
|
31400
|
+
if (!seen.has(key)) {
|
|
31401
|
+
this._groupInvitePending.delete(key);
|
|
31402
|
+
changed = true;
|
|
31403
|
+
}
|
|
31404
|
+
}
|
|
31405
|
+
if (changed) await this.persistGroupInviteState();
|
|
31406
|
+
}
|
|
31407
|
+
async restoreGroupInvitesAfterConnect() {
|
|
31408
|
+
if (!this._aid || this._state !== "connected") return;
|
|
31409
|
+
const result = await this.call("group.list_my_invites", { page: 1, size: 200, _rpc_background: true });
|
|
31410
|
+
if (isJsonObject(result) || Array.isArray(result)) {
|
|
31411
|
+
await this.restoreGroupInvitesFromResult(result, { page: 1, size: 200, _rpc_background: true });
|
|
31412
|
+
}
|
|
31413
|
+
}
|
|
31138
31414
|
async _onRawGroupChanged(data) {
|
|
31139
31415
|
const tStart = Date.now();
|
|
31140
31416
|
const action = String(data?.action ?? "");
|
|
@@ -31465,6 +31741,7 @@ var _AUNClient = class _AUNClient {
|
|
|
31465
31741
|
}
|
|
31466
31742
|
this._lifecycle.assertConnectionAttemptOwner(connectionOwner);
|
|
31467
31743
|
this._startBackgroundTasks();
|
|
31744
|
+
this._safeAsync(this.restoreGroupInvitesAfterConnect());
|
|
31468
31745
|
const connectionKind = String(params2.connection_kind ?? "long");
|
|
31469
31746
|
const isShortConnection = connectionKind === "short";
|
|
31470
31747
|
const hasExplicitBackgroundSync = Object.prototype.hasOwnProperty.call(params2, "background_sync");
|
|
@@ -32175,20 +32452,7 @@ var _AUNClient = class _AUNClient {
|
|
|
32175
32452
|
return this._delivery.clampAckParams(method, params2);
|
|
32176
32453
|
}
|
|
32177
32454
|
_repairPushContiguousBound(ns, pushSeq, hasPayload, label) {
|
|
32178
|
-
|
|
32179
|
-
return ns ? this._seqTracker.getContiguousSeq(ns) : 0;
|
|
32180
|
-
}
|
|
32181
|
-
const contig = this._seqTracker.getContiguousSeq(ns);
|
|
32182
|
-
const shouldRepair = contig > pushSeq;
|
|
32183
|
-
if (!shouldRepair) return contig;
|
|
32184
|
-
const repairedTo = Math.max(0, pushSeq - 1);
|
|
32185
|
-
this._seqTracker.repairContiguousSeq(ns, repairedTo);
|
|
32186
|
-
const repaired = this._seqTracker.getContiguousSeq(ns);
|
|
32187
|
-
this._persistRepairedSeq(ns);
|
|
32188
|
-
this._clientLog.warn(
|
|
32189
|
-
`${label} push repaired contiguous_seq: ns=${ns} payload=${hasPayload} push_seq=${pushSeq} contiguous=${contig}->${repaired}`
|
|
32190
|
-
);
|
|
32191
|
-
return repaired;
|
|
32455
|
+
return ns ? this._seqTracker.getContiguousSeq(ns) : 0;
|
|
32192
32456
|
}
|
|
32193
32457
|
async _ensureV2SessionReady(method, errorMessage3) {
|
|
32194
32458
|
if (!this._v2SessionMatchesIdentity()) {
|