@agentunion/fastaun-browser 0.5.11 → 0.5.13

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.
Files changed (47) hide show
  1. package/CHANGELOG.md +46 -0
  2. package/_packed_docs/CHANGELOG.md +46 -0
  3. package/_packed_docs/INDEX.md +3 -3
  4. package/_packed_docs/KITE_DOCS_GUIDE.md +1 -1
  5. package/_packed_docs/agent.md/SCHEMA.md +84 -84
  6. package/_packed_docs/aun/345/210/206/345/270/203/345/274/217/346/265/213/350/257/225/350/277/220/350/241/214/346/214/207/345/215/227.md +8 -6
  7. package/_packed_docs/aun/346/265/213/350/257/225/350/277/220/350/241/214/346/214/207/345/215/227.md +29 -15
  8. package/_packed_docs/protocol/10-Group-/345/255/220/345/215/217/350/256/256.md +21 -3
  9. package/_packed_docs/sdk/09-group-rpc-manual.md +29 -2
  10. package/dist/agent-md-schema.d.ts.map +1 -1
  11. package/dist/agent-md-schema.js +8 -4
  12. package/dist/agent-md-schema.js.map +1 -1
  13. package/dist/bundle.js +565 -298
  14. package/dist/client/delivery.d.ts +1 -0
  15. package/dist/client/delivery.d.ts.map +1 -1
  16. package/dist/client/delivery.js +161 -242
  17. package/dist/client/delivery.js.map +1 -1
  18. package/dist/client/group-state.d.ts.map +1 -1
  19. package/dist/client/group-state.js +1 -0
  20. package/dist/client/group-state.js.map +1 -1
  21. package/dist/client/rpc-pipeline.d.ts.map +1 -1
  22. package/dist/client/rpc-pipeline.js +24 -11
  23. package/dist/client/rpc-pipeline.js.map +1 -1
  24. package/dist/client/v2-e2ee.d.ts +0 -1
  25. package/dist/client/v2-e2ee.d.ts.map +1 -1
  26. package/dist/client/v2-e2ee.js +65 -44
  27. package/dist/client/v2-e2ee.js.map +1 -1
  28. package/dist/client.d.ts +14 -0
  29. package/dist/client.d.ts.map +1 -1
  30. package/dist/client.js +341 -18
  31. package/dist/client.js.map +1 -1
  32. package/dist/facades.d.ts +7 -0
  33. package/dist/facades.d.ts.map +1 -1
  34. package/dist/facades.js +44 -0
  35. package/dist/facades.js.map +1 -1
  36. package/dist/seq-tracker.d.ts +2 -2
  37. package/dist/seq-tracker.d.ts.map +1 -1
  38. package/dist/seq-tracker.js +11 -7
  39. package/dist/seq-tracker.js.map +1 -1
  40. package/dist/tools/cross-sdk-agent.js +50 -12
  41. package/dist/tools/cross-sdk-agent.js.map +1 -1
  42. package/dist/transport.d.ts.map +1 -1
  43. package/dist/transport.js +3 -0
  44. package/dist/transport.js.map +1 -1
  45. package/dist/version.d.ts +1 -1
  46. package/dist/version.js +1 -1
  47. 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.11";
463
+ var VERSION = "0.5.13";
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
- this._tryAdvance(t);
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
- if (messages.length > 0) client._seqTracker.onPullResult(ns, messages, afterSeq);
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
- if (seqNum > 0) {
6300
- client._seqTracker.updateMaxSeen(ns, seqNum);
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) && typeof data.seq === "number" ? data.seq : 0;
6456
- if (client._v2Session && ns && Number.isSafeInteger(seq2) && seq2 > 0 && this.messageTargetsCurrentInstance(data)) {
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) && isJsonObject(data.inline_message);
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 (seq2 !== void 0 && seq2 !== null && client._aid) {
6464
+ const seq2 = positiveSafeSequenceHint(msg.seq);
6465
+ if (client._aid && seq2 > 0) {
6473
6466
  const ns = `p2p:${client._aid}`;
6474
- if (seq2 > 0) client._seqTracker.updateMaxSeen(ns, seq2);
6475
- const contigBefore = client._seqTracker.getContiguousSeq(ns);
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(seq2, msg);
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 = Object.prototype.hasOwnProperty.call(msg, "inline_message");
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
- if (seq2 !== void 0 && seq2 !== null && client._aid) {
6519
- const ns = `p2p:${client._aid}`;
6520
- if (seq2 > 0) client._seqTracker.updateMaxSeen(ns, seq2);
6521
- const contigBefore = client._seqTracker.getContiguousSeq(ns);
6522
- const seqNeedsPull = client._seqTracker.onMessageSeq(ns, seq2);
6523
- const published = encryptedPush ? await client._publishEncryptedPushMessage("message.received", "message.undecryptable", ns, seq2, msg, false) : await this.publishOrderedMessage("message.received", ns, seq2, msg);
6524
- const contigAfter = client._seqTracker.getContiguousSeq(ns);
6525
- const needPull = seqNeedsPull && !published;
6526
- if (needPull && client._sessionOptions?.background_sync !== false) {
6527
- client._safeAsync(this.fillP2pGap());
6528
- }
6529
- const contig = client._seqTracker.getContiguousSeq(ns);
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 hasInlineObject = isJsonObject(data) && isJsonObject(data.inline_message);
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 = Object.prototype.hasOwnProperty.call(msg, "inline_message");
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
- if (groupId && seq2 !== void 0 && seq2 !== null) {
6609
- const ns = `group:${groupId}`;
6610
- if (seq2 > 0) client._seqTracker.updateMaxSeen(ns, seq2);
6611
- const contigBefore = client._seqTracker.getContiguousSeq(ns);
6612
- const seqNeedsPull = client._seqTracker.onMessageSeq(ns, seq2);
6613
- if (!encryptedPush && this.recallEventFromGroupMessage(msg)) {
6614
- await this.publishGroupRecallTombstone(groupId, seq2, msg);
6615
- this.markPublishedSeq(ns, Number(seq2));
6616
- const contigAfter2 = client._seqTracker.getContiguousSeq(ns);
6617
- const contig2 = client._seqTracker.getContiguousSeq(ns);
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
- if (eventObjects.length > 0) {
6878
- client._seqTracker.onPullResult(ns, eventObjects, nextAfterSeq);
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
- try {
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
- if (singlePage && result.has_more === true && nextAfter > nextAfterSeq) {
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 || result.has_more !== true) break;
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 = client._seqTracker.onMessageSeq(ns, eventSeq);
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 pendingThroughSeq = tailMissedDuringPull ? maxSeen : 0;
7474
- const tailForward = tailCompleted && (state.ack < state.tail - 1 || tailMissedDuringPull);
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 ? maxSeen : 0
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 pendingThroughSeq = tailMissedDuringPull ? maxSeen : 0;
7542
- const tailForward = tailCompleted && (state.ack < state.tail - 1 || tailMissedDuringPull);
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 ? maxSeen : 0
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
- if (client._v2Session && eventKind !== "group.online_unread_hint" && Number.isSafeInteger(seq2) && seq2 > 0) {
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 = isJsonObject(row.inline_message) && eventKind !== "group.online_unread_hint";
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 = Object.prototype.hasOwnProperty.call(data, "inline_message");
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 (!inlinePresent || inlineMatches) {
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) && isJsonObject(data.inline_message);
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
- const inlinePresent = isJsonObject(data) && Object.prototype.hasOwnProperty.call(data, "inline_message");
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);
@@ -15405,12 +15331,15 @@ function validateAgentMdDocument(content, opts = {}) {
15405
15331
  if (new TextEncoder().encode(parsed.payload).byteLength > (opts.maxPayloadBytes ?? 4096)) throw new ValidationError("agent.md payload exceeds 4096 bytes");
15406
15332
  if (parsed.fields && new TextEncoder().encode(String(content)).byteLength - new TextEncoder().encode(parsed.payload).byteLength > AGENT_MD_MAX_SIGNATURE_BYTES) throw new ValidationError(`agent.md signature block exceeds ${AGENT_MD_MAX_SIGNATURE_BYTES} bytes`);
15407
15333
  const meta = frontmatter(parsed.payload);
15408
- for (const key of ["aid", "name", "type", "version", "description"]) if (!(key in meta)) throw new ValidationError(`agent.md frontmatter missing ${key}`);
15334
+ for (const key of ["aid", "name", "type", "version"]) if (!(key in meta)) throw new ValidationError(`agent.md frontmatter missing ${key}`);
15409
15335
  if (typeof meta.aid !== "string" || !AID_RE.test(meta.aid)) throw new ValidationError("agent.md frontmatter aid has invalid format");
15410
15336
  if (opts.expectedAid && meta.aid.toLowerCase() !== opts.expectedAid.trim().toLowerCase()) throw new ValidationError("agent.md frontmatter aid does not match local AID");
15411
- for (const key of ["name", "type", "description"]) if (typeof meta[key] !== "string" || !String(meta[key]).trim()) throw new ValidationError(`agent.md frontmatter ${key} must be a non-empty string`);
15337
+ for (const key of ["name", "type"]) if (typeof meta[key] !== "string" || !String(meta[key]).trim()) throw new ValidationError(`agent.md frontmatter ${key} must be a non-empty string`);
15412
15338
  if (typeof meta.version !== "string" || !SEMVER_RE.test(meta.version)) throw new ValidationError("agent.md version must be SemVer MAJOR.MINOR.PATCH");
15413
- if (Array.from(String(meta.description)).length > 100) throw new ValidationError("agent.md description exceeds 100 characters");
15339
+ if ("description" in meta) {
15340
+ if (typeof meta.description !== "string") throw new ValidationError("agent.md frontmatter description must be a string");
15341
+ if (Array.from(meta.description).length > 100) throw new ValidationError("agent.md description exceeds 100 characters");
15342
+ }
15414
15343
  if (meta.tags !== void 0 && (!Array.isArray(meta.tags) || meta.tags.some((item) => typeof item !== "string"))) throw new ValidationError("agent.md tags must be an array of strings");
15415
15344
  const fields = parsed.fields;
15416
15345
  if (fields) {
@@ -15677,6 +15606,11 @@ var SIGNED_METHODS = /* @__PURE__ */ new Set([
15677
15606
  "group.v2.get_proposal",
15678
15607
  "group.kick",
15679
15608
  "group.add_member",
15609
+ "group.invite_member",
15610
+ "group.list_my_invites",
15611
+ "group.accept_invite",
15612
+ "group.reject_invite",
15613
+ "group.revoke_invite",
15680
15614
  "group.leave",
15681
15615
  "group.remove_member",
15682
15616
  "group.update",
@@ -15829,7 +15763,9 @@ var NON_IDEMPOTENT_METHODS = /* @__PURE__ */ new Set([
15829
15763
  "mail.send",
15830
15764
  "group.send",
15831
15765
  "group.create",
15832
- "group.invite",
15766
+ "group.accept_invite",
15767
+ "group.reject_invite",
15768
+ "group.revoke_invite",
15833
15769
  "group.kick",
15834
15770
  "group.remove_member",
15835
15771
  "group.leave",
@@ -16855,6 +16791,8 @@ var RpcPipeline = class {
16855
16791
  }
16856
16792
  postprocessMessagePull(params2, result) {
16857
16793
  const client = this.runtime.client;
16794
+ const isTail = String(result.window_mode ?? params2.window_mode ?? "").trim().toLowerCase() === "tail";
16795
+ if (isTail) return;
16858
16796
  const messages = result.messages;
16859
16797
  const rawMessages = (Array.isArray(messages) ? messages : []).filter(isJsonObject);
16860
16798
  if (!client._aid || !client._seqTracker) {
@@ -16862,9 +16800,9 @@ var RpcPipeline = class {
16862
16800
  }
16863
16801
  const ns = `p2p:${client._aid}`;
16864
16802
  const contigBefore = client._seqTracker.getContiguousSeq(ns);
16865
- if (rawMessages.length) {
16866
- client._seqTracker.onPullResult(ns, rawMessages, Number(params2.after_seq ?? 0) || 0);
16867
- }
16803
+ const contiguousSeq = Number.isSafeInteger(result.contiguous_seq) ? result.contiguous_seq : void 0;
16804
+ if (contiguousSeq === void 0) client._seqTracker.onPullResult(ns, rawMessages, Number(params2.after_seq ?? 0) || 0);
16805
+ else client._seqTracker.onPullResult(ns, rawMessages, Number(params2.after_seq ?? 0) || 0, contiguousSeq);
16868
16806
  const retentionFloor = Math.max(0, Number(result.retention_floor_seq ?? 0));
16869
16807
  if (retentionFloor > 0) {
16870
16808
  const contig = client._seqTracker.getContiguousSeq(ns);
@@ -16883,6 +16821,8 @@ var RpcPipeline = class {
16883
16821
  if (Array.isArray(result.messages)) {
16884
16822
  result.messages = result.messages.map((message) => normalizeGroupMentionMode(message));
16885
16823
  }
16824
+ const isTail = String(result.window_mode ?? params2.window_mode ?? "").trim().toLowerCase() === "tail";
16825
+ if (isTail) return;
16886
16826
  const gid = String(params2.group_id ?? params2.group_aid ?? "").trim();
16887
16827
  if (!gid || !client._seqTracker) {
16888
16828
  return;
@@ -16891,17 +16831,17 @@ var RpcPipeline = class {
16891
16831
  const rawMessages = (Array.isArray(messages) ? messages : []).filter(isJsonObject);
16892
16832
  const ns = `group:${gid}`;
16893
16833
  const contigBefore = client._seqTracker.getContiguousSeq(ns);
16894
- if (rawMessages.length) {
16895
- client._seqTracker.onPullResult(ns, rawMessages, Number(params2.after_message_seq ?? params2.after_seq ?? 0) || 0);
16896
- }
16834
+ const contiguousSeq = Number.isSafeInteger(result.contiguous_seq) ? result.contiguous_seq : void 0;
16835
+ const afterSeq = Number(params2.after_message_seq ?? params2.after_seq ?? 0) || 0;
16836
+ if (contiguousSeq === void 0) client._seqTracker.onPullResult(ns, rawMessages, afterSeq);
16837
+ else client._seqTracker.onPullResult(ns, rawMessages, afterSeq, contiguousSeq);
16897
16838
  const cursor = isJsonObject(result.cursor) ? result.cursor : null;
16898
16839
  const retentionFloor = Math.max(
16899
16840
  0,
16900
16841
  Number(result.retention_floor_message_seq ?? result.retention_floor_seq ?? 0),
16901
16842
  Number(cursor?.retention_floor_seq ?? 0)
16902
16843
  );
16903
- const isTail = String(result.window_mode ?? params2.window_mode ?? "").trim().toLowerCase() === "tail";
16904
- const visibilityFloor = isTail ? 0 : Math.max(
16844
+ const visibilityFloor = Math.max(
16905
16845
  0,
16906
16846
  Math.max(0, Number(result.earliest_available_message_seq ?? 1) - 1),
16907
16847
  Number(cursor?.join_seq ?? 0)
@@ -16910,7 +16850,7 @@ var RpcPipeline = class {
16910
16850
  if (effectiveFloor > 0) {
16911
16851
  const contig = client._seqTracker.getContiguousSeq(ns);
16912
16852
  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=${isTail ? "tail" : "forward"}`);
16853
+ client._clientLog?.info?.(`group.pull floor advance: ns=${ns} contiguous=${contig} -> effective_floor=${effectiveFloor} retention_floor=${retentionFloor} visibility_floor=${visibilityFloor} mode=forward`);
16914
16854
  client._seqTracker.forceContiguousSeq(ns, effectiveFloor);
16915
16855
  }
16916
16856
  }
@@ -18443,6 +18383,21 @@ var MessageFacade = class extends RpcFacade {
18443
18383
  return this.call("message.query_online", params2);
18444
18384
  }
18445
18385
  };
18386
+ function normalizeInviteParams(params2) {
18387
+ const out = stripNil2(params2);
18388
+ const rawGroupId = out.group_id ?? out.groupId ?? out.group_aid ?? out.groupAid;
18389
+ if (rawGroupId !== void 0) {
18390
+ out.group_id = normalizeGroupId(rawGroupId);
18391
+ delete out.groupId;
18392
+ delete out.group_aid;
18393
+ delete out.groupAid;
18394
+ }
18395
+ for (const [alias, canonical] of [["inviteId", "invite_id"], ["inviteeAid", "invitee_aid"]]) {
18396
+ if (out[canonical] === void 0 && out[alias] !== void 0) out[canonical] = out[alias];
18397
+ delete out[alias];
18398
+ }
18399
+ return out;
18400
+ }
18446
18401
  var MailFacade = class extends RpcFacade {
18447
18402
  send(params2) {
18448
18403
  return this.call("mail.send", params2);
@@ -18555,6 +18510,32 @@ var GroupFacade = class extends RpcFacade {
18555
18510
  addMember(params2) {
18556
18511
  return this.call("group.add_member", params2);
18557
18512
  }
18513
+ async inviteCall(method, params2) {
18514
+ const normalized = normalizeInviteParams(params2);
18515
+ try {
18516
+ const result = await this.call(method, normalized);
18517
+ await this.client._onGroupInviteActionResult?.(method, normalized, result);
18518
+ return result;
18519
+ } catch (error) {
18520
+ await this.client._onGroupInviteActionResult?.(method, normalized, void 0, error);
18521
+ throw error;
18522
+ }
18523
+ }
18524
+ inviteMember(params2) {
18525
+ return this.inviteCall("group.invite_member", params2);
18526
+ }
18527
+ listMyInvites(params2) {
18528
+ return this.inviteCall("group.list_my_invites", params2);
18529
+ }
18530
+ acceptInvite(params2) {
18531
+ return this.inviteCall("group.accept_invite", params2);
18532
+ }
18533
+ rejectInvite(params2) {
18534
+ return this.inviteCall("group.reject_invite", params2);
18535
+ }
18536
+ revokeInvite(params2) {
18537
+ return this.inviteCall("group.revoke_invite", params2);
18538
+ }
18558
18539
  getMembers(params2) {
18559
18540
  return this.call("group.get_members", params2);
18560
18541
  }
@@ -23942,6 +23923,22 @@ function deduplicateForwardPageMessages(value, afterSeq) {
23942
23923
  }
23943
23924
  return [...bySeq.entries()].sort(([a], [b]) => a - b).map(([, row]) => row);
23944
23925
  }
23926
+ function contiguousPullSeq(afterSeq, seqs, proof) {
23927
+ let contiguous = seqs.length > 0 ? Math.max(afterSeq, ...seqs) : afterSeq;
23928
+ const serverProof = safeNonNegativeSeq(proof);
23929
+ return serverProof !== null ? Math.max(contiguous, serverProof) : contiguous;
23930
+ }
23931
+ function deduplicatePulledResults(messages) {
23932
+ const seen = /* @__PURE__ */ new Set();
23933
+ return messages.filter((message) => {
23934
+ if (!isJsonObject(message)) return true;
23935
+ const seq2 = safeNonNegativeSeq(message.seq);
23936
+ if (seq2 === null || seq2 <= 0) return true;
23937
+ if (seen.has(seq2)) return false;
23938
+ seen.add(seq2);
23939
+ return true;
23940
+ });
23941
+ }
23945
23942
  function shouldContinueForwardPage({
23946
23943
  rawCount,
23947
23944
  nextAfterSeq,
@@ -23950,10 +23947,11 @@ function shouldContinueForwardPage({
23950
23947
  hasMoreField,
23951
23948
  hasMore,
23952
23949
  serverHead,
23953
- pendingAckSeq
23950
+ pendingAckSeq,
23951
+ observedUpper
23954
23952
  }) {
23955
23953
  if (rawCount <= 0 || nextAfter <= nextAfterSeq) return false;
23956
- if (hasMore || serverHead > nextAfter || pendingAckSeq > 0) return true;
23954
+ if (hasMore || serverHead > nextAfter || pendingAckSeq > 0 || observedUpper > nextAfter) return true;
23957
23955
  return !hasMoreField && limit > 0 && rawCount >= limit;
23958
23956
  }
23959
23957
  function validateTailPage(result, afterSeq, pageLimit) {
@@ -24692,7 +24690,7 @@ var V2E2EECoordinator = class {
24692
24690
  client._clientLog.warn(`V2 sender IK pending group bootstrap failed group=${groupId}: ${String(formatE2EEError(exc))}`);
24693
24691
  }
24694
24692
  }
24695
- if (!session.getPeerIK(fromAid, senderDeviceId)) {
24693
+ if (typeof session.getPeerIK === "function" && !session.getPeerIK(fromAid, senderDeviceId)) {
24696
24694
  await this.getV2SenderPubDer(fromAid, senderDeviceId);
24697
24695
  }
24698
24696
  }
@@ -24728,6 +24726,7 @@ var V2E2EECoordinator = class {
24728
24726
  client._v2SenderIKPending.delete(key);
24729
24727
  const seq2 = Number(entry.msg.seq ?? 0);
24730
24728
  if (entry.groupId) {
24729
+ if (client._delivery.isSelfSentGroupMessage?.(entry.msg)) continue;
24731
24730
  plaintext = normalizeGroupMentionMode(plaintext, entry.msg, entry.msg.envelope_json);
24732
24731
  plaintext.group_id = entry.groupId;
24733
24732
  await client._publishPulledMessage("group.message_created", `group:${entry.groupId}`, seq2, plaintext, false, "pending_retry");
@@ -24920,6 +24919,9 @@ var V2E2EECoordinator = class {
24920
24919
  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
24920
  return null;
24922
24921
  }
24922
+ if (publish && !history && client._delivery.isSelfSentGroupMessage?.(msg)) {
24923
+ return plaintext;
24924
+ }
24923
24925
  if (publish) {
24924
24926
  if (orderedPublish) {
24925
24927
  await client._delivery.publishOrderedMessage(
@@ -24941,13 +24943,6 @@ var V2E2EECoordinator = class {
24941
24943
  async decodeInlineGroupMessage(msg, groupId, groupAid) {
24942
24944
  return await this.decodeGroupWindowMessage(msg, groupId, groupAid, false, false, "inline_push");
24943
24945
  }
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
24946
  async pullV2TailInternal(params2, deferPublish = false) {
24952
24947
  const client = this.client;
24953
24948
  if (params2.window_mode !== "tail") throw new ValidationError("window_mode must equal tail");
@@ -24957,9 +24952,6 @@ var V2E2EECoordinator = class {
24957
24952
  const ns = client._aid ? `p2p:${client._aid}` : "";
24958
24953
  if (ns) client._delivery.onPullStarted?.(ns);
24959
24954
  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
24955
  const page = validateTailPage(result, afterSeq, limit);
24964
24956
  if (ns) {
24965
24957
  client._seqTracker.commitTailWindow(ns, {
@@ -24977,7 +24969,6 @@ var V2E2EECoordinator = class {
24977
24969
  if (plaintext) decoded.push(plaintext);
24978
24970
  }
24979
24971
  const ack = ns ? client._seqTracker.getContiguousSeq(ns) : 0;
24980
- if (previous && ack > previous.ack) await this.ackV2(ack);
24981
24972
  if (ns) client._delivery.onPullPage?.(
24982
24973
  ns,
24983
24974
  decoded.length,
@@ -25097,6 +25088,11 @@ var V2E2EECoordinator = class {
25097
25088
  const pageContigBefore = ns ? client._seqTracker.getContiguousSeq(ns) : 0;
25098
25089
  const pageTrackerSnapshot = ns && typeof client._seqTracker.snapshotNamespace === "function" ? client._seqTracker.snapshotNamespace(ns) : null;
25099
25090
  const pageMaxSeq = seqs.length > 0 ? Math.max(...seqs) : nextAfterSeq;
25091
+ const pageContiguousSeq = contiguousPullSeq(
25092
+ pageContigBefore,
25093
+ seqs,
25094
+ result.contiguous_seq
25095
+ );
25100
25096
  const deferredKeyFetches = /* @__PURE__ */ new Map();
25101
25097
  let blockedSeq = 0;
25102
25098
  const pageDecryptedBefore = decrypted.length;
@@ -25188,11 +25184,12 @@ var V2E2EECoordinator = class {
25188
25184
  const serverAckSeq = parsedServerAckSeq ?? 0;
25189
25185
  const retentionFloor = Math.max(0, Number(result.retention_floor_seq ?? 0));
25190
25186
  if (ns) {
25191
- const commitTarget = blockedSeq > 0 ? pageContigBefore : Math.max(
25187
+ const commitTarget = Math.max(
25192
25188
  pageContigBefore,
25193
25189
  Number.isFinite(retentionFloor) ? retentionFloor : 0,
25194
25190
  pageCount === 1 ? deferredServerCursor : 0,
25195
- seqs.length > 0 ? pageMaxSeq : pageContigBefore
25191
+ serverAckSeq,
25192
+ blockedSeq > 0 ? blockedSeq - 1 : pageContiguousSeq
25196
25193
  );
25197
25194
  let ackSeq = pageContigBefore;
25198
25195
  let contigAdvanced = false;
@@ -25230,10 +25227,10 @@ var V2E2EECoordinator = class {
25230
25227
  this.recordForwardCursor(ns, serverAckSeq, ackSeq);
25231
25228
  }
25232
25229
  const knownServerAckSeq = hasServerAckSeq ? serverAckSeq : pageCount === 1 ? deferredServerCursor : 0;
25233
- const ackNeeded = blockedSeq <= 0 && ackSeq > 0 && ackSeq > lastAutoAckSeq && (hasServerAckSeq && ackSeq > serverAckSeq || contigAdvanced && ackSeq > knownServerAckSeq);
25230
+ const ackNeeded = ackSeq > 0 && ackSeq > lastAutoAckSeq && (hasServerAckSeq && ackSeq > serverAckSeq || contigAdvanced && ackSeq > knownServerAckSeq);
25234
25231
  if (ackNeeded) {
25235
25232
  this.recordForwardAck(ns, ackSeq);
25236
- const nextAfter2 = Math.max(pageMaxSeq, nextAfterSeq);
25233
+ const nextAfter2 = Math.max(pageContiguousSeq, nextAfterSeq);
25237
25234
  const canContinuePage = blockedSeq <= 0 && messages.length > 0 && nextAfter2 > nextAfterSeq;
25238
25235
  if (canContinuePage) {
25239
25236
  pendingAckSeq = Math.max(pendingAckSeq, ackSeq);
@@ -25254,7 +25251,7 @@ var V2E2EECoordinator = class {
25254
25251
  client._seqTracker.getContiguousSeq(ns),
25255
25252
  pageMaxSeq
25256
25253
  );
25257
- const nextAfter = Math.max(pageMaxSeq, nextAfterSeq);
25254
+ const nextAfter = Math.max(pageContiguousSeq, nextAfterSeq);
25258
25255
  const rawCount = messages.length;
25259
25256
  if (blockedSeq > 0) break;
25260
25257
  const shouldContinue = shouldContinueForwardPage({
@@ -25265,7 +25262,8 @@ var V2E2EECoordinator = class {
25265
25262
  hasMoreField,
25266
25263
  hasMore,
25267
25264
  serverHead,
25268
- pendingAckSeq
25265
+ pendingAckSeq,
25266
+ observedUpper: typeof client._seqTracker.getMaxSeenSeq === "function" ? client._seqTracker.getMaxSeenSeq(ns) : nextAfter
25269
25267
  });
25270
25268
  if (!shouldContinue) break;
25271
25269
  if (pullGateKey && opts?.gateLocked && client._rpcPipeline?.yieldPullGate) {
@@ -25289,7 +25287,7 @@ var V2E2EECoordinator = class {
25289
25287
  }
25290
25288
  }
25291
25289
  client._delivery.onPullWorkSettled?.();
25292
- return decrypted;
25290
+ return deduplicatePulledResults(decrypted);
25293
25291
  }
25294
25292
  async confirmForwardP2PAck(upToSeq, inlineGeneration) {
25295
25293
  const ns = this.client._aid ? `p2p:${this.client._aid}` : "";
@@ -25375,10 +25373,7 @@ var V2E2EECoordinator = class {
25375
25373
  if (isJsonObject(result)) {
25376
25374
  const seq2 = Number(result.seq ?? 0);
25377
25375
  if (seq2 > 0) {
25378
- const ns = `group:${gid}`;
25379
- client._seqTracker.onMessageSeq(ns, seq2);
25380
- client._markPublishedSeq(ns, seq2);
25381
- await client._saveSeqTrackerState();
25376
+ client._markPublishedSeq(`group:${gid}`, seq2);
25382
25377
  }
25383
25378
  }
25384
25379
  return client._delivery.attachSendResultEnvelope("group.send", withExplicitGroupAid({
@@ -25398,10 +25393,7 @@ var V2E2EECoordinator = class {
25398
25393
  if (isJsonObject(result)) {
25399
25394
  const seq2 = Number(result.seq ?? 0);
25400
25395
  if (seq2 > 0) {
25401
- const ns = `group:${gid}`;
25402
- client._seqTracker.onMessageSeq(ns, seq2);
25403
- client._markPublishedSeq(ns, seq2);
25404
- await client._saveSeqTrackerState();
25396
+ client._markPublishedSeq(`group:${gid}`, seq2);
25405
25397
  }
25406
25398
  }
25407
25399
  return client._delivery.attachSendResultEnvelope("group.send", withExplicitGroupAid({
@@ -25440,9 +25432,6 @@ var V2E2EECoordinator = class {
25440
25432
  }, groupAid));
25441
25433
  const resultAid = String(result.group_aid ?? result.groupAid ?? "").trim();
25442
25434
  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
25435
  const page = validateTailPage(result, afterSeq, limit);
25447
25436
  client._seqTracker.commitTailWindow(ns, {
25448
25437
  windowStartSeq: page.windowStart,
@@ -25459,7 +25448,6 @@ var V2E2EECoordinator = class {
25459
25448
  if (plaintext) decoded.push(plaintext);
25460
25449
  }
25461
25450
  const ack = client._seqTracker.getContiguousSeq(ns);
25462
- if (ack > previous.ack) await this.ackGroupV2(groupId, ack, groupAid);
25463
25451
  if (ownsCursor) client._delivery.onPullPage?.(
25464
25452
  ns,
25465
25453
  decoded.length,
@@ -25616,6 +25604,11 @@ var V2E2EECoordinator = class {
25616
25604
  const pageContigBefore = client._seqTracker.getContiguousSeq(ns);
25617
25605
  const pageTrackerSnapshot = typeof client._seqTracker.snapshotNamespace === "function" ? client._seqTracker.snapshotNamespace(ns) : null;
25618
25606
  const pageMaxSeq = seqs.length > 0 ? Math.max(...seqs) : nextAfterSeq;
25607
+ const pageContiguousSeq = contiguousPullSeq(
25608
+ pageContigBefore,
25609
+ seqs,
25610
+ result.contiguous_seq
25611
+ );
25619
25612
  const deferredKeyFetches = /* @__PURE__ */ new Map();
25620
25613
  let blockedSeq = 0;
25621
25614
  const pageDecryptedBefore = decrypted.length;
@@ -25653,7 +25646,11 @@ var V2E2EECoordinator = class {
25653
25646
  };
25654
25647
  v1Msg = normalizeGroupMentionMode(v1Msg, msg, msg.envelope_json);
25655
25648
  attachGatewayProximity(v1Msg, msg);
25656
- await client._publishPulledMessage("group.message_created", ns, seq2, v1Msg, false);
25649
+ if (!client._delivery.isSelfSentGroupMessage?.(msg)) {
25650
+ await client._publishPulledMessage("group.message_created", ns, seq2, v1Msg, false);
25651
+ } else {
25652
+ client._markPublishedSeq(ns, seq2);
25653
+ }
25657
25654
  decrypted.push(v1Msg);
25658
25655
  continue;
25659
25656
  }
@@ -25697,7 +25694,11 @@ var V2E2EECoordinator = class {
25697
25694
  if (plaintext2) {
25698
25695
  plaintext2.group_id = gid;
25699
25696
  plaintext2.group_aid = eventGroupAid;
25700
- await client._publishPulledMessage("group.message_created", ns, seq2, plaintext2, false);
25697
+ if (!client._delivery.isSelfSentGroupMessage?.(msg)) {
25698
+ await client._publishPulledMessage("group.message_created", ns, seq2, plaintext2, false);
25699
+ } else {
25700
+ client._markPublishedSeq(ns, seq2);
25701
+ }
25701
25702
  decrypted.push(plaintext2);
25702
25703
  }
25703
25704
  }
@@ -25725,7 +25726,11 @@ var V2E2EECoordinator = class {
25725
25726
  plaintext = normalizeGroupMentionMode(plaintext, msg, msg.envelope_json);
25726
25727
  plaintext.group_id = gid;
25727
25728
  plaintext.group_aid = eventGroupAid;
25728
- await client._publishPulledMessage("group.message_created", ns, seq2, plaintext, false);
25729
+ if (!client._delivery.isSelfSentGroupMessage?.(msg)) {
25730
+ await client._publishPulledMessage("group.message_created", ns, seq2, plaintext, false);
25731
+ } else {
25732
+ client._markPublishedSeq(ns, seq2);
25733
+ }
25729
25734
  decrypted.push(plaintext);
25730
25735
  }
25731
25736
  const hasServerCursor = cursor !== null && Object.prototype.hasOwnProperty.call(cursor, "current_seq");
@@ -25741,11 +25746,12 @@ var V2E2EECoordinator = class {
25741
25746
  Number(cursor?.join_seq ?? 0)
25742
25747
  );
25743
25748
  const effectiveFloor = Math.max(retentionFloor, visibilityFloor);
25744
- const commitTarget = blockedSeq > 0 ? pageContigBefore : Math.max(
25749
+ const commitTarget = Math.max(
25745
25750
  pageContigBefore,
25746
25751
  Number.isFinite(effectiveFloor) ? effectiveFloor : 0,
25747
25752
  ownsCursor && pageCount === 1 ? deferredServerCursor : 0,
25748
- seqs.length > 0 ? pageMaxSeq : pageContigBefore
25753
+ cursorCurrentSeq,
25754
+ blockedSeq > 0 ? blockedSeq - 1 : pageContiguousSeq
25749
25755
  );
25750
25756
  let ackSeq = pageContigBefore;
25751
25757
  let contigAdvanced = false;
@@ -25795,10 +25801,10 @@ var V2E2EECoordinator = class {
25795
25801
  this.recordForwardCursor(ns, cursorCurrentSeq, ackSeq);
25796
25802
  }
25797
25803
  const knownServerCursorSeq = hasServerCursor ? cursorCurrentSeq : ownsCursor && pageCount === 1 ? deferredServerCursor : 0;
25798
- const ackNeeded = blockedSeq <= 0 && ackSeq > 0 && ackSeq > lastAutoAckSeq && ownsCursor && (hasServerCursor && ackSeq > cursorCurrentSeq || contigAdvanced && ackSeq > knownServerCursorSeq);
25804
+ const ackNeeded = ackSeq > 0 && ackSeq > lastAutoAckSeq && ownsCursor && (hasServerCursor && ackSeq > cursorCurrentSeq || contigAdvanced && ackSeq > knownServerCursorSeq);
25799
25805
  if (ackNeeded) {
25800
25806
  this.recordForwardAck(ns, ackSeq);
25801
- const nextAfter2 = Math.max(pageMaxSeq, nextAfterSeq);
25807
+ const nextAfter2 = Math.max(pageContiguousSeq, nextAfterSeq);
25802
25808
  const canContinuePage = blockedSeq <= 0 && messages.length > 0 && nextAfter2 > nextAfterSeq && ownsCursor;
25803
25809
  if (canContinuePage) {
25804
25810
  pendingAckSeq = Math.max(pendingAckSeq, ackSeq);
@@ -25808,7 +25814,7 @@ var V2E2EECoordinator = class {
25808
25814
  lastAutoAckSeq = Math.max(lastAutoAckSeq, ackSeq);
25809
25815
  }
25810
25816
  }
25811
- const nextAfter = Math.max(pageMaxSeq, nextAfterSeq);
25817
+ const nextAfter = Math.max(pageContiguousSeq, nextAfterSeq);
25812
25818
  if (!ownsCursor) break;
25813
25819
  const rawCount = messages.length;
25814
25820
  if (blockedSeq > 0) break;
@@ -25820,7 +25826,8 @@ var V2E2EECoordinator = class {
25820
25826
  hasMoreField,
25821
25827
  hasMore,
25822
25828
  serverHead,
25823
- pendingAckSeq
25829
+ pendingAckSeq,
25830
+ observedUpper: typeof client._seqTracker.getMaxSeenSeq === "function" ? client._seqTracker.getMaxSeenSeq(ns) : nextAfter
25824
25831
  });
25825
25832
  if (!shouldContinue) break;
25826
25833
  if (pullGateKey && opts?.gateLocked && client._rpcPipeline?.yieldPullGate) {
@@ -25846,7 +25853,7 @@ var V2E2EECoordinator = class {
25846
25853
  }
25847
25854
  }
25848
25855
  client._delivery.onPullWorkSettled?.();
25849
- return decrypted;
25856
+ return deduplicatePulledResults(decrypted);
25850
25857
  }
25851
25858
  async confirmForwardGroupAck(groupId, upToSeq, groupAid) {
25852
25859
  const ns = `group:${String(groupId ?? "").trim()}`;
@@ -26683,7 +26690,8 @@ var MEMBERSHIP_MUTATION_METHODS = /* @__PURE__ */ new Set([
26683
26690
  "group.review_join_request",
26684
26691
  "group.batch_review_join_request",
26685
26692
  "group.use_invite_code",
26686
- "group.request_join"
26693
+ "group.request_join",
26694
+ "group.accept_invite"
26687
26695
  ]);
26688
26696
  var SPK_REGISTRATION_MUTATION_METHODS = /* @__PURE__ */ new Set([
26689
26697
  "group.create",
@@ -29412,6 +29420,7 @@ var RECONNECT_MIN_BASE_DELAY_SECONDS = 1;
29412
29420
  var RECONNECT_MAX_BASE_DELAY_SECONDS = 64;
29413
29421
  var TOKEN_REFRESH_CHECK_INTERVAL_MS = 3e4;
29414
29422
  var MAX_NOTIFY_PAYLOAD_SIZE = 64 * 1024;
29423
+ var GROUP_INVITE_METADATA_KEY = "group_invite_pending_v1";
29415
29424
  function clampReconnectDelaySeconds(value, fallback, upper = RECONNECT_MAX_BASE_DELAY_SECONDS) {
29416
29425
  const parsed = Number(value);
29417
29426
  const seconds = Number.isFinite(parsed) ? parsed : fallback;
@@ -29804,6 +29813,9 @@ var _AUNClient = class _AUNClient {
29804
29813
  __publicField(this, "_mailFacade");
29805
29814
  __publicField(this, "_groupFacade");
29806
29815
  __publicField(this, "_streamFacade");
29816
+ __publicField(this, "_groupInvitePending", /* @__PURE__ */ new Map());
29817
+ __publicField(this, "_groupInviteStateAid", null);
29818
+ __publicField(this, "_groupInviteStateLoad", null);
29807
29819
  /**
29808
29820
  * 处理 V2 push 通知:自动 pull + decrypt + emit。
29809
29821
  */
@@ -29927,6 +29939,15 @@ var _AUNClient = class _AUNClient {
29927
29939
  this._dispatcher.subscribe("_raw.group.changed", (data) => {
29928
29940
  this._onRawGroupChanged(data);
29929
29941
  });
29942
+ this._dispatcher.subscribe("_raw.group.invite_created", (data) => {
29943
+ this._safeAsync(this._onRawGroupInviteReceived(data, "push"));
29944
+ });
29945
+ this._dispatcher.subscribe("_raw.group.invite_received", (data) => {
29946
+ this._safeAsync(this._onRawGroupInviteReceived(data, "push"));
29947
+ });
29948
+ this._dispatcher.subscribe("_raw.group.invite_finalized", (data) => {
29949
+ this._safeAsync(this._onRawGroupInviteFinalized(data));
29950
+ });
29930
29951
  this._dispatcher.subscribe("_raw.peer.v2.message_received", (data) => {
29931
29952
  this._safeAsync(this._onV2PushNotification(data));
29932
29953
  });
@@ -30474,6 +30495,8 @@ var _AUNClient = class _AUNClient {
30474
30495
  }
30475
30496
  this._aidStore = store;
30476
30497
  const payload = { ...params2 };
30498
+ const initialMembers = payload.members;
30499
+ delete payload.members;
30477
30500
  if (payload.group_name === void 0 && payload.groupName !== void 0) {
30478
30501
  payload.group_name = payload.groupName;
30479
30502
  delete payload.groupName;
@@ -30503,7 +30526,8 @@ var _AUNClient = class _AUNClient {
30503
30526
  const result2 = { ...createdMap, ...boundMap, group: { ...createdGroup, ...boundGroup } };
30504
30527
  const postprocessParams2 = { ...payload };
30505
30528
  delete postprocessParams2._defer_group_ready_postprocess;
30506
- return await this._groupState.postprocessResult("group.create", postprocessParams2, result2);
30529
+ const processed2 = await this._groupState.postprocessResult("group.create", postprocessParams2, result2);
30530
+ return await this._inviteInitialGroupMembers(processed2, groupId, initialMembers);
30507
30531
  }
30508
30532
  const pendingKey = `create:${String(payload.group_name).trim().toLowerCase()}`;
30509
30533
  const keystore = store._keystore;
@@ -30553,7 +30577,29 @@ var _AUNClient = class _AUNClient {
30553
30577
  }
30554
30578
  const postprocessParams = { ...payload };
30555
30579
  delete postprocessParams._defer_group_ready_postprocess;
30556
- return await this._groupState.postprocessResult("group.create", postprocessParams, result);
30580
+ const processed = await this._groupState.postprocessResult("group.create", postprocessParams, result);
30581
+ return await this._inviteInitialGroupMembers(processed, String(group.group_id ?? groupAid).trim(), initialMembers);
30582
+ }
30583
+ async _inviteInitialGroupMembers(result, groupId, members) {
30584
+ const invites = [];
30585
+ const inviteErrors = [];
30586
+ const seen = /* @__PURE__ */ new Set();
30587
+ if (Array.isArray(members)) {
30588
+ for (const item of members) {
30589
+ const aid = typeof item === "string" ? item.trim() : isJsonObject(item) ? String(item.aid ?? "").trim() : "";
30590
+ const memberType = isJsonObject(item) ? String(item.member_type ?? "").trim() : "";
30591
+ if (!aid || aid === String(this._aid ?? this._currentAid?.aid ?? "").trim() || seen.has(aid)) continue;
30592
+ seen.add(aid);
30593
+ const params2 = { group_id: groupId, invitee_aid: aid };
30594
+ if (memberType) params2.member_type = memberType;
30595
+ try {
30596
+ invites.push(await this.group.inviteMember(params2));
30597
+ } catch (err) {
30598
+ inviteErrors.push({ aid, error: err instanceof Error ? err.message : String(err) });
30599
+ }
30600
+ }
30601
+ }
30602
+ return { ...isJsonObject(result) ? result : {}, invites, invite_errors: inviteErrors };
30557
30603
  }
30558
30604
  _groupAgentMdContent(groupAid, params2 = {}, group = {}) {
30559
30605
  const explicit = params2.group_agent_md ?? params2.groupAgentMd ?? params2.content;
@@ -31135,6 +31181,239 @@ var _AUNClient = class _AUNClient {
31135
31181
  const member = isJsonObject(result.member) ? result.member : null;
31136
31182
  return member ? String(member.group_id ?? member.groupId ?? member.group_aid ?? member.groupAid ?? "") : "";
31137
31183
  }
31184
+ groupInviteKey(groupId, inviteeAid) {
31185
+ const group = normalizeGroupId(groupId);
31186
+ const invitee = String(inviteeAid ?? "").trim().toLowerCase();
31187
+ return group && invitee ? `${group}
31188
+ ${invitee}` : "";
31189
+ }
31190
+ async ensureGroupInviteStateLoaded() {
31191
+ const aid = String(this._aid ?? "").trim();
31192
+ if (!aid) {
31193
+ this._groupInvitePending.clear();
31194
+ this._groupInviteStateAid = null;
31195
+ return;
31196
+ }
31197
+ if (this._groupInviteStateAid === aid) return;
31198
+ if (this._groupInviteStateLoad) {
31199
+ await this._groupInviteStateLoad;
31200
+ if (this._groupInviteStateAid === aid) return;
31201
+ }
31202
+ this._groupInviteStateLoad = (async () => {
31203
+ this._groupInvitePending.clear();
31204
+ this._groupInviteStateAid = aid;
31205
+ const getter = this._tokenStore?.getMetadata;
31206
+ if (typeof getter !== "function") return;
31207
+ try {
31208
+ const raw = await getter.call(this._tokenStore, aid, GROUP_INVITE_METADATA_KEY);
31209
+ const parsed = raw ? JSON.parse(String(raw)) : {};
31210
+ if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) return;
31211
+ for (const [key, value] of Object.entries(parsed)) {
31212
+ if (value && typeof value === "object" && !Array.isArray(value)) {
31213
+ this._groupInvitePending.set(key, value);
31214
+ }
31215
+ }
31216
+ } catch (exc) {
31217
+ this._clientLog.debug(`group invite state restore skipped: ${String(exc)}`);
31218
+ }
31219
+ })().finally(() => {
31220
+ this._groupInviteStateLoad = null;
31221
+ });
31222
+ return this._groupInviteStateLoad;
31223
+ }
31224
+ async persistGroupInviteState() {
31225
+ const aid = String(this._aid ?? "").trim();
31226
+ const setter = this._tokenStore?.setMetadata;
31227
+ if (!aid || typeof setter !== "function") return;
31228
+ const state = {};
31229
+ for (const [key, value] of this._groupInvitePending) state[key] = value;
31230
+ try {
31231
+ await setter.call(this._tokenStore, aid, GROUP_INVITE_METADATA_KEY, JSON.stringify(state));
31232
+ } catch (exc) {
31233
+ this._clientLog.debug(`group invite state persist skipped: ${String(exc)}`);
31234
+ }
31235
+ }
31236
+ inviteArray(value, singular) {
31237
+ const values = Array.isArray(value) ? value : singular !== void 0 ? [singular] : [];
31238
+ return [...new Set(values.map((item) => String(item ?? "").trim()).filter(Boolean))];
31239
+ }
31240
+ inviteBool(value) {
31241
+ return value === true || value === 1 || String(value ?? "").trim().toLowerCase() === "true";
31242
+ }
31243
+ async _onRawGroupInviteReceived(data, source = "push") {
31244
+ if (!isJsonObject(data)) return;
31245
+ const groupId = normalizeGroupId(data.group_id ?? data.groupId ?? data.group_aid ?? data.groupAid);
31246
+ const inviteeAid = String(data.invitee_aid ?? data.inviteeAid ?? this._aid ?? "").trim();
31247
+ if (!groupId || !inviteeAid || this._aid && inviteeAid.toLowerCase() !== this._aid.toLowerCase()) return;
31248
+ if (String(data.status ?? "pending").trim().toLowerCase() !== "pending") {
31249
+ await this._onRawGroupInviteFinalized(data);
31250
+ return;
31251
+ }
31252
+ await this.ensureGroupInviteStateLoaded();
31253
+ const key = this.groupInviteKey(groupId, inviteeAid);
31254
+ if (!key) return;
31255
+ const inviteIds = this.inviteArray(data.invite_ids, data.invite_id);
31256
+ const inviterAids = this.inviteArray(data.inviter_aids, data.inviter_aid);
31257
+ const existing = this._groupInvitePending.get(key);
31258
+ if (existing) {
31259
+ existing.invite_ids = [.../* @__PURE__ */ new Set([...this.inviteArray(existing.invite_ids), ...inviteIds])];
31260
+ existing.inviter_aids = [.../* @__PURE__ */ new Set([...this.inviteArray(existing.inviter_aids), ...inviterAids])];
31261
+ await this.persistGroupInviteState();
31262
+ return;
31263
+ }
31264
+ const payload = {
31265
+ ...data,
31266
+ group_id: groupId,
31267
+ group_aid: groupId,
31268
+ invitee_aid: inviteeAid,
31269
+ invite_ids: inviteIds,
31270
+ inviter_aids: inviterAids,
31271
+ role: data.role ?? "member",
31272
+ member_type: data.member_type ?? data.memberType ?? "human",
31273
+ created_at: data.created_at ?? data.createdAt ?? 0,
31274
+ expires_at: data.expires_at ?? data.expiresAt ?? 0,
31275
+ status: "pending"
31276
+ };
31277
+ delete payload.groupId;
31278
+ delete payload.groupAid;
31279
+ delete payload.inviteeAid;
31280
+ delete payload.inviterAid;
31281
+ this._groupInvitePending.set(key, payload);
31282
+ await this.persistGroupInviteState();
31283
+ await this._publishAppEvent("group.invite_received", JSON.parse(JSON.stringify(payload)), source);
31284
+ }
31285
+ async _onRawGroupInviteFinalized(data) {
31286
+ if (!isJsonObject(data)) return;
31287
+ await this.ensureGroupInviteStateLoaded();
31288
+ const groupId = normalizeGroupId(data.group_id ?? data.groupId ?? data.group_aid ?? data.groupAid);
31289
+ const inviteeAid = String(data.invitee_aid ?? data.inviteeAid ?? this._aid ?? "").trim();
31290
+ if (this._aid && inviteeAid.toLowerCase() !== this._aid.toLowerCase()) return;
31291
+ const inviteId = String(data.invite_id ?? "").trim();
31292
+ const key = this.groupInviteKey(groupId, inviteeAid);
31293
+ const status = String(data.status ?? "").trim().toLowerCase();
31294
+ const aggregateStatus = String(data.aggregate_status ?? data.aggregateStatus ?? "").trim().toLowerCase();
31295
+ const pendingIds = this.inviteArray(data.pending_invite_ids ?? data.pendingInviteIds);
31296
+ const pendingInviters = this.inviteArray(data.pending_inviter_aids ?? data.pendingInviterAids);
31297
+ const finalizedIds = this.inviteBool(data.remaining_pending) && inviteId ? [inviteId] : this.inviteArray(data.invite_ids, data.invite_id);
31298
+ const finalizedInviters = this.inviteArray(data.inviter_aids, data.inviter_aid);
31299
+ const leavesPending = this.inviteBool(data.remaining_pending) || this.inviteBool(data.pending) || status === "pending" || aggregateStatus === "pending" || pendingIds.length > 0;
31300
+ let changed = false;
31301
+ const candidates = [];
31302
+ if (key) {
31303
+ const current = this._groupInvitePending.get(key);
31304
+ if (current) candidates.push([key, current]);
31305
+ }
31306
+ if (candidates.length === 0 && inviteId) {
31307
+ for (const [itemKey, item] of this._groupInvitePending) {
31308
+ if (this.inviteArray(item.invite_ids).includes(inviteId)) candidates.push([itemKey, item]);
31309
+ }
31310
+ }
31311
+ for (const [itemKey, item] of candidates) {
31312
+ if (!leavesPending) {
31313
+ this._groupInvitePending.delete(itemKey);
31314
+ changed = true;
31315
+ continue;
31316
+ }
31317
+ const currentIds = this.inviteArray(item.invite_ids);
31318
+ const currentInviters = this.inviteArray(item.inviter_aids);
31319
+ const finalizedIndexes = new Set(currentIds.map((id, index) => finalizedIds.includes(id) ? index : -1).filter((index) => index >= 0));
31320
+ const nextIds = pendingIds.length > 0 ? pendingIds : finalizedIds.length > 0 ? currentIds.filter((id) => !finalizedIds.includes(id)) : currentIds;
31321
+ 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;
31322
+ if (nextIds.length === 0) {
31323
+ this._groupInvitePending.delete(itemKey);
31324
+ } else {
31325
+ item.invite_ids = nextIds;
31326
+ item.inviter_aids = nextInviters;
31327
+ }
31328
+ changed = true;
31329
+ }
31330
+ if (changed) await this.persistGroupInviteState();
31331
+ }
31332
+ async _onGroupInviteActionResult(method, params2, result, error) {
31333
+ if (method === "group.list_my_invites" && !error && (isJsonObject(result) || Array.isArray(result))) {
31334
+ await this.restoreGroupInvitesFromResult(result, params2);
31335
+ return;
31336
+ }
31337
+ if (!["group.accept_invite", "group.reject_invite", "group.revoke_invite"].includes(method)) return;
31338
+ const text3 = String(error instanceof Error ? error.message : error ?? "").toLowerCase();
31339
+ const resultStatus = isJsonObject(result) ? String(result.status ?? "").toLowerCase() : "";
31340
+ const aggregateResultStatus = isJsonObject(result) ? String(result.aggregate_status ?? result.aggregateStatus ?? "").toLowerCase() : "";
31341
+ const terminalStatus = resultStatus || aggregateResultStatus;
31342
+ const pendingResult = resultStatus === "pending" || aggregateResultStatus === "pending" || isJsonObject(result) && (this.inviteBool(result.remaining_pending) || this.inviteBool(result.pending));
31343
+ if (pendingResult) {
31344
+ if (isJsonObject(result) && (this.inviteBool(result.remaining_pending) || this.inviteArray(result.pending_invite_ids ?? result.pendingInviteIds).length > 0)) {
31345
+ await this._onRawGroupInviteFinalized({ ...params2, ...result });
31346
+ }
31347
+ return;
31348
+ }
31349
+ 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));
31350
+ if (!terminal) return;
31351
+ await this._onRawGroupInviteFinalized({
31352
+ ...params2,
31353
+ ...isJsonObject(result) ? result : {},
31354
+ status: terminalStatus || "ended"
31355
+ });
31356
+ }
31357
+ async restoreGroupInvitesFromResult(result, requestParams = {}) {
31358
+ const seen = /* @__PURE__ */ new Set();
31359
+ const visitedPages = /* @__PURE__ */ new Set();
31360
+ let current = result;
31361
+ let currentParams = { ...requestParams };
31362
+ let finalPage = false;
31363
+ while (!finalPage) {
31364
+ const root = Array.isArray(current) ? null : isJsonObject(current) ? current : null;
31365
+ const nestedValue = root && isJsonObject(root.data) ? root.data : root;
31366
+ const nested = nestedValue ?? {};
31367
+ const rawItems = Array.isArray(nested.items) ? nested.items : Array.isArray(nested.invites) ? nested.invites : Array.isArray(current) ? current : [];
31368
+ for (const item of rawItems) {
31369
+ if (!isJsonObject(item)) continue;
31370
+ const status = String(item.status ?? "pending").toLowerCase();
31371
+ const gid = normalizeGroupId(item.group_id ?? item.group_aid ?? item.groupId ?? item.groupAid);
31372
+ const aid = String(item.invitee_aid ?? item.inviteeAid ?? this._aid ?? "").trim();
31373
+ if (this._aid && aid.toLowerCase() !== this._aid.toLowerCase()) continue;
31374
+ const key = this.groupInviteKey(gid, aid);
31375
+ if (status === "pending" && key) {
31376
+ seen.add(key);
31377
+ await this._onRawGroupInviteReceived(item, "pull");
31378
+ } else if (key) {
31379
+ seen.add(key);
31380
+ await this._onRawGroupInviteFinalized(item);
31381
+ }
31382
+ }
31383
+ const hasMore = this.inviteBool(nested.has_more ?? nested.hasMore ?? (root ? root.has_more ?? root.hasMore : void 0));
31384
+ if (!hasMore) {
31385
+ finalPage = true;
31386
+ break;
31387
+ }
31388
+ const page = Number(nested.page ?? root?.page ?? currentParams.page ?? 1);
31389
+ const nextPageValue = nested.next_page ?? nested.nextPage ?? root?.next_page ?? root?.nextPage;
31390
+ const nextPage = Number(nextPageValue ?? page + 1);
31391
+ if (!Number.isFinite(nextPage) || nextPage <= 0 || visitedPages.has(nextPage) || nextPage === page) break;
31392
+ visitedPages.add(page);
31393
+ currentParams = { ...currentParams, page: nextPage };
31394
+ if (currentParams.size === void 0) {
31395
+ const size = nested.size ?? root?.size;
31396
+ if (size !== void 0) currentParams.size = size;
31397
+ }
31398
+ current = await this.call("group.list_my_invites", currentParams);
31399
+ }
31400
+ await this.ensureGroupInviteStateLoaded();
31401
+ let changed = false;
31402
+ for (const key of this._groupInvitePending.keys()) {
31403
+ if (!seen.has(key)) {
31404
+ this._groupInvitePending.delete(key);
31405
+ changed = true;
31406
+ }
31407
+ }
31408
+ if (changed) await this.persistGroupInviteState();
31409
+ }
31410
+ async restoreGroupInvitesAfterConnect() {
31411
+ if (!this._aid || this._state !== "connected") return;
31412
+ const result = await this.call("group.list_my_invites", { page: 1, size: 200, _rpc_background: true });
31413
+ if (isJsonObject(result) || Array.isArray(result)) {
31414
+ await this.restoreGroupInvitesFromResult(result, { page: 1, size: 200, _rpc_background: true });
31415
+ }
31416
+ }
31138
31417
  async _onRawGroupChanged(data) {
31139
31418
  const tStart = Date.now();
31140
31419
  const action = String(data?.action ?? "");
@@ -31465,6 +31744,7 @@ var _AUNClient = class _AUNClient {
31465
31744
  }
31466
31745
  this._lifecycle.assertConnectionAttemptOwner(connectionOwner);
31467
31746
  this._startBackgroundTasks();
31747
+ this._safeAsync(this.restoreGroupInvitesAfterConnect());
31468
31748
  const connectionKind = String(params2.connection_kind ?? "long");
31469
31749
  const isShortConnection = connectionKind === "short";
31470
31750
  const hasExplicitBackgroundSync = Object.prototype.hasOwnProperty.call(params2, "background_sync");
@@ -32175,20 +32455,7 @@ var _AUNClient = class _AUNClient {
32175
32455
  return this._delivery.clampAckParams(method, params2);
32176
32456
  }
32177
32457
  _repairPushContiguousBound(ns, pushSeq, hasPayload, label) {
32178
- if (!ns || !Number.isFinite(pushSeq) || pushSeq <= 0) {
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;
32458
+ return ns ? this._seqTracker.getContiguousSeq(ns) : 0;
32192
32459
  }
32193
32460
  async _ensureV2SessionReady(method, errorMessage3) {
32194
32461
  if (!this._v2SessionMatchesIdentity()) {