@agentunion/fastaun 0.5.18 → 0.5.19

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 (94) hide show
  1. package/CHANGELOG.md +44 -2
  2. package/_packed_docs/CHANGELOG.md +44 -2
  3. package/_packed_docs/INDEX.md +136 -14
  4. package/_packed_docs/KITE_DOCS_GUIDE.md +42 -16
  5. package/_packed_docs/agent.md/SCHEMA.md +245 -205
  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 +42 -15
  7. package/_packed_docs/aun/346/265/213/350/257/225/350/277/220/350/241/214/346/214/207/345/215/227.md +4 -4
  8. package/_packed_docs/protocol/01-/350/272/253/344/273/275/344/270/216/345/207/255/350/257/201/345/215/217/350/256/256-auth.md +45 -134
  9. package/_packed_docs/protocol/07-/351/224/231/350/257/257/347/240/201/344/270/216/347/212/266/346/200/201/346/234/272.md +5 -20
  10. package/_packed_docs/protocol/10-Group-/345/255/220/345/215/217/350/256/256.md +28 -9
  11. package/_packed_docs/protocol/11-Storage-/345/255/220/345/215/217/350/256/256.md +22 -27
  12. package/_packed_docs/protocol/agent.md/SCHEMA.md +4 -0
  13. package/_packed_docs/sdk/04-/350/277/236/346/216/245/344/270/216/350/256/244/350/257/201.md +5 -2
  14. package/_packed_docs/sdk/06-API/346/211/213/345/206/214.md +250 -283
  15. package/_packed_docs/sdk/09-group-rpc-manual.md +46 -14
  16. package/_packed_docs/sdk/09-message-rpc-manual.md +40 -2
  17. package/_packed_docs/sdk/09-storage-rpc-manual.md +74 -64
  18. package/_packed_docs/sdk/AUN_DOCS_GUIDE.md +25 -5
  19. package/_packed_docs/sdk/INDEX.md +76 -17
  20. package/dist/agent-md-schema.d.ts +2 -0
  21. package/dist/agent-md-schema.js +45 -10
  22. package/dist/agent-md-schema.js.map +1 -1
  23. package/dist/agent-md.d.ts +47 -2
  24. package/dist/agent-md.js +493 -33
  25. package/dist/agent-md.js.map +1 -1
  26. package/dist/aid-store.d.ts +9 -59
  27. package/dist/aid-store.js +135 -245
  28. package/dist/aid-store.js.map +1 -1
  29. package/dist/aid.js +19 -5
  30. package/dist/aid.js.map +1 -1
  31. package/dist/auth.d.ts +6 -1
  32. package/dist/auth.js +428 -15
  33. package/dist/auth.js.map +1 -1
  34. package/dist/cert-utils.d.ts +1 -1
  35. package/dist/cert-utils.js +19 -7
  36. package/dist/cert-utils.js.map +1 -1
  37. package/dist/client/delivery.d.ts +2 -1
  38. package/dist/client/delivery.js +143 -52
  39. package/dist/client/delivery.js.map +1 -1
  40. package/dist/client/rpc-pipeline.js +22 -5
  41. package/dist/client/rpc-pipeline.js.map +1 -1
  42. package/dist/client/v2-e2ee.d.ts +1 -0
  43. package/dist/client/v2-e2ee.js +93 -29
  44. package/dist/client/v2-e2ee.js.map +1 -1
  45. package/dist/client.d.ts +84 -1
  46. package/dist/client.js +749 -28
  47. package/dist/client.js.map +1 -1
  48. package/dist/errors.js +4 -3
  49. package/dist/errors.js.map +1 -1
  50. package/dist/events.d.ts +5 -1
  51. package/dist/events.js +47 -6
  52. package/dist/events.js.map +1 -1
  53. package/dist/facades.d.ts +83 -3
  54. package/dist/facades.js +98 -4
  55. package/dist/facades.js.map +1 -1
  56. package/dist/index.d.ts +8 -4
  57. package/dist/index.js +3 -2
  58. package/dist/index.js.map +1 -1
  59. package/dist/keystore/aid-db.d.ts +5 -0
  60. package/dist/keystore/aid-db.js +48 -0
  61. package/dist/keystore/aid-db.js.map +1 -1
  62. package/dist/keystore/index.d.ts +8 -0
  63. package/dist/keystore/local-identity-store.js +10 -3
  64. package/dist/keystore/local-identity-store.js.map +1 -1
  65. package/dist/keystore/local-token-store.d.ts +6 -1
  66. package/dist/keystore/local-token-store.js +24 -1
  67. package/dist/keystore/local-token-store.js.map +1 -1
  68. package/dist/org-protocol.d.ts +98 -0
  69. package/dist/org-protocol.js +1689 -0
  70. package/dist/org-protocol.js.map +1 -0
  71. package/dist/ownership-proof.d.ts +82 -5
  72. package/dist/ownership-proof.js +327 -31
  73. package/dist/ownership-proof.js.map +1 -1
  74. package/dist/ownership-v21.d.ts +178 -0
  75. package/dist/ownership-v21.js +635 -0
  76. package/dist/ownership-v21.js.map +1 -0
  77. package/dist/ownership-workflow.d.ts +82 -0
  78. package/dist/ownership-workflow.js +872 -0
  79. package/dist/ownership-workflow.js.map +1 -0
  80. package/dist/seq-tracker.d.ts +1 -0
  81. package/dist/seq-tracker.js +10 -1
  82. package/dist/seq-tracker.js.map +1 -1
  83. package/dist/tools/cross-sdk-agent.d.ts +89 -1
  84. package/dist/tools/cross-sdk-agent.js +338 -7
  85. package/dist/tools/cross-sdk-agent.js.map +1 -1
  86. package/dist/transport.d.ts +7 -0
  87. package/dist/transport.js +108 -4
  88. package/dist/transport.js.map +1 -1
  89. package/dist/v2/e2ee/decrypt.d.ts +1 -0
  90. package/dist/v2/e2ee/decrypt.js +9 -1
  91. package/dist/v2/e2ee/decrypt.js.map +1 -1
  92. package/dist/version.d.ts +1 -1
  93. package/dist/version.js +1 -1
  94. package/package.json +1 -1
@@ -825,11 +825,12 @@ export class V2E2EECoordinator {
825
825
  client._clientLog.debug(`V2 sender IK pending retry delivered: key=${key}`);
826
826
  continue;
827
827
  }
828
- pending.delete(key);
829
828
  const seq = Number(entry.msg.seq ?? 0);
830
829
  if (entry.groupId) {
831
- if (client._delivery.isSelfSentGroupMessage?.(entry.msg))
830
+ if (client._delivery.isSelfSentGroupMessage?.(entry.msg)) {
831
+ pending.delete(key);
832
832
  continue;
833
+ }
833
834
  plaintext = normalizeGroupMentionMode(plaintext, entry.msg, entry.msg.envelope_json);
834
835
  plaintext.group_id = entry.groupId;
835
836
  await client._publishPulledMessage('group.message_created', `group:${entry.groupId}`, seq, plaintext, false, 'pending_retry');
@@ -837,6 +838,8 @@ export class V2E2EECoordinator {
837
838
  else {
838
839
  await client._publishPulledMessage('message.received', `p2p:${client._aid ?? ''}`, seq, plaintext, false, 'pending_retry');
839
840
  }
841
+ if (generationIsCurrent())
842
+ pending.delete(key);
840
843
  client._clientLog.debug(`V2 sender IK pending retry delivered: key=${key}`);
841
844
  }
842
845
  }
@@ -1122,6 +1125,11 @@ export class V2E2EECoordinator {
1122
1125
  history_error: { code: 'decrypt_failed', message: reason },
1123
1126
  };
1124
1127
  }
1128
+ ensureDeliveryCurrent(ns, generation) {
1129
+ if (Number(this.client._v2RuntimeGeneration ?? 0) !== generation
1130
+ || this.client._rpcPipeline?.isPullNamespaceCurrent?.(ns) === false)
1131
+ throw new StateError('pull invalidated');
1132
+ }
1125
1133
  async decodeP2PWindowMessage(msg, publish, history, source, orderedPublish = false) {
1126
1134
  const client = this.client;
1127
1135
  const seq = strictWindowSeq(msg.seq, 'messages[].seq', true);
@@ -1250,6 +1258,7 @@ export class V2E2EECoordinator {
1250
1258
  }
1251
1259
  async pullV2TailInternal(params, deferPublish = false) {
1252
1260
  const client = this.client;
1261
+ const generation = Number(client._v2RuntimeGeneration ?? 0);
1253
1262
  if (params.window_mode !== 'tail')
1254
1263
  throw new ValidationError('window_mode must equal tail');
1255
1264
  if ('ack_up_to_seq' in params || params.force === true)
@@ -1264,6 +1273,14 @@ export class V2E2EECoordinator {
1264
1273
  }, `${ns}|tail|after=${afterSeq}|limit=${limit}`);
1265
1274
  const result = await client._callRawV2Rpc('message.v2.pull', { window_mode: 'tail', after_seq: afterSeq, limit, _rpc_foreground: true }, pullGateKey);
1266
1275
  const page = validateTailPage(result, afterSeq, limit);
1276
+ const decoded = [];
1277
+ for (const msg of page.messages) {
1278
+ this.ensureDeliveryCurrent(ns, generation);
1279
+ const plaintext = await this.decodeP2PWindowMessage(msg, true, false, 'tail', deferPublish);
1280
+ if (plaintext)
1281
+ decoded.push(plaintext);
1282
+ }
1283
+ this.ensureDeliveryCurrent(ns, generation);
1267
1284
  if (ns) {
1268
1285
  client._seqTracker.commitTailWindow(ns, {
1269
1286
  windowStartSeq: page.windowStart,
@@ -1273,12 +1290,7 @@ export class V2E2EECoordinator {
1273
1290
  });
1274
1291
  client._persistSeq(ns);
1275
1292
  await client._saveSeqTrackerState?.();
1276
- }
1277
- const decoded = [];
1278
- for (const msg of page.messages) {
1279
- const plaintext = await this.decodeP2PWindowMessage(msg, true, false, 'tail', deferPublish);
1280
- if (plaintext)
1281
- decoded.push(plaintext);
1293
+ this.ensureDeliveryCurrent(ns, generation);
1282
1294
  }
1283
1295
  const ack = ns ? client._seqTracker.getContiguousSeq(ns) : 0;
1284
1296
  if (ns)
@@ -1308,6 +1320,7 @@ export class V2E2EECoordinator {
1308
1320
  }
1309
1321
  async pullV2Impl(afterSeq = 0, limit = 50, opts) {
1310
1322
  const client = this.client;
1323
+ const generation = Number(client._v2RuntimeGeneration ?? 0);
1311
1324
  await client._ensureV2SessionReady('message.pull');
1312
1325
  const ns = client._aid ? `p2p:${client._aid}` : '';
1313
1326
  if (ns)
@@ -1351,6 +1364,7 @@ export class V2E2EECoordinator {
1351
1364
  const pipelineQueue = new V2PullPageQueue(V2_PULL_PIPELINE_QUEUE_CAPACITY);
1352
1365
  let pipelineProducer = null;
1353
1366
  let pipelineStopped = false;
1367
+ const pipelineResume = { current: null };
1354
1368
  const startPipeline = (startAfterSeq, startVolatileCursor) => {
1355
1369
  if (pipelineRunning || pageCount >= maxPages || limit < V2_PULL_MAX_PAGE_LIMIT)
1356
1370
  return;
@@ -1371,6 +1385,7 @@ export class V2E2EECoordinator {
1371
1385
  if (pipelineStopped)
1372
1386
  break;
1373
1387
  const rawPageMessages = (Array.isArray(result?.messages) ? result.messages : []);
1388
+ const completed = new Promise((resolve) => { pipelineResume.current = resolve; });
1374
1389
  const enqueued = await pipelineQueue.put({
1375
1390
  result,
1376
1391
  afterSeq: producerAfterSeq,
@@ -1381,6 +1396,9 @@ export class V2E2EECoordinator {
1381
1396
  }, rawPageMessages.length);
1382
1397
  if (!enqueued || pipelineStopped)
1383
1398
  break;
1399
+ await completed;
1400
+ if (pipelineStopped)
1401
+ break;
1384
1402
  const volatileMessages = client._delivery.volatileMessages?.(rawPageMessages) ?? [];
1385
1403
  if (volatileMessages.length > 0)
1386
1404
  break;
@@ -1415,6 +1433,8 @@ export class V2E2EECoordinator {
1415
1433
  };
1416
1434
  const stopPipeline = async () => {
1417
1435
  pipelineStopped = true;
1436
+ pipelineResume.current?.();
1437
+ pipelineResume.current = null;
1418
1438
  pipelineQueue.close();
1419
1439
  if (pipelineProducer) {
1420
1440
  const producer = pipelineProducer;
@@ -1504,9 +1524,8 @@ export class V2E2EECoordinator {
1504
1524
  .map((msg) => Number(msg.seq ?? 0))
1505
1525
  .filter((seq) => Number.isFinite(seq) && seq > 0);
1506
1526
  const pageContigBefore = ns ? client._seqTracker.getContiguousSeq(ns) : 0;
1507
- const pageTrackerSnapshot = ns && typeof client._seqTracker.snapshotNamespace === 'function'
1508
- ? client._seqTracker.snapshotNamespace(ns)
1509
- : null;
1527
+ let pageTrackerSnapshot = null;
1528
+ let trackerMutated = false;
1510
1529
  let pageMaxSeq = nextAfterSeq;
1511
1530
  if (seqs.length > 0) {
1512
1531
  pageMaxSeq = Math.max(...seqs);
@@ -1624,7 +1643,17 @@ export class V2E2EECoordinator {
1624
1643
  let ackSeq = pageContigBefore;
1625
1644
  let contigAdvanced = false;
1626
1645
  try {
1646
+ this.ensureDeliveryCurrent(ns, generation);
1647
+ const window = client._seqTracker.getSyncState?.(ns);
1648
+ const deliveryTarget = window && commitTarget >= window.tail - 1
1649
+ ? Math.max(commitTarget, window.head) : commitTarget;
1650
+ if (deliveryTarget > pageContigBefore) {
1651
+ await client._drainOrderedMessages(ns, undefined, false, false, 'pull', deliveryTarget);
1652
+ }
1653
+ this.ensureDeliveryCurrent(ns, generation);
1654
+ pageTrackerSnapshot = client._seqTracker.snapshotNamespace?.(ns) ?? null;
1627
1655
  if (commitTarget > pageContigBefore) {
1656
+ trackerMutated = true;
1628
1657
  client._seqTracker.forceContiguousSeq(ns, commitTarget);
1629
1658
  if (retentionFloor > pageContigBefore) {
1630
1659
  client._clientLog.info(`message.v2.pull retention-floor advance: ns=${ns} contiguous=${pageContigBefore} -> retention_floor_seq=${retentionFloor}`);
@@ -1640,19 +1669,21 @@ export class V2E2EECoordinator {
1640
1669
  contigAdvanced = ackSeq !== pageContigBefore;
1641
1670
  if (contigAdvanced) {
1642
1671
  await client._commitSeqTrackerState(ns);
1672
+ this.ensureDeliveryCurrent(ns, generation);
1643
1673
  if (pageCount === 1 && deferredServerCursor > 0)
1644
1674
  this.clearForwardCursor(ns, ackSeq);
1645
1675
  }
1646
1676
  }
1647
1677
  catch (exc) {
1648
- if (typeof client._seqTracker.restoreNamespaceSnapshot === 'function') {
1649
- client._seqTracker.restoreNamespaceSnapshot(ns, pageTrackerSnapshot);
1678
+ if (trackerMutated && Number(client._v2RuntimeGeneration ?? 0) === generation
1679
+ && client._rpcPipeline?.isPullNamespaceCurrent?.(ns) !== false
1680
+ && typeof client._seqTracker.restoreNamespaceSnapshot === 'function') {
1681
+ (client._seqTracker._restoreNamespaceSnapshotPreservingPush ?? client._seqTracker.restoreNamespaceSnapshot)
1682
+ .call(client._seqTracker, ns, pageTrackerSnapshot);
1650
1683
  }
1651
1684
  client._clientLog.error?.(`message.v2.pull Forward commit rolled back: ns=${ns} target=${commitTarget} error=${formatE2EEError(exc)}`);
1652
1685
  throw exc;
1653
1686
  }
1654
- if (contigAdvanced)
1655
- await client._drainOrderedMessages(ns, undefined, false, false, 'pull');
1656
1687
  for (const fetch of deferredKeyFetches.values()) {
1657
1688
  this.scheduleSenderIKFetch(fetch.fromAid, fetch.senderDeviceId, fetch.groupId);
1658
1689
  }
@@ -1748,6 +1779,10 @@ export class V2E2EECoordinator {
1748
1779
  if (tailDelayMs > 0)
1749
1780
  await v2Sleep(tailDelayMs);
1750
1781
  nextAfterSeq = nextAfter;
1782
+ if (pipelinePage) {
1783
+ pipelineResume.current?.();
1784
+ pipelineResume.current = null;
1785
+ }
1751
1786
  }
1752
1787
  }
1753
1788
  finally {
@@ -2128,6 +2163,7 @@ export class V2E2EECoordinator {
2128
2163
  }
2129
2164
  async pullGroupV2TailInternal(params, deferPublish = false) {
2130
2165
  const client = this.client;
2166
+ const generation = Number(client._v2RuntimeGeneration ?? 0);
2131
2167
  if (params.window_mode !== 'tail')
2132
2168
  throw new ValidationError('window_mode must equal tail');
2133
2169
  if ('ack_up_to_seq' in params || params.force === true)
@@ -2167,6 +2203,15 @@ export class V2E2EECoordinator {
2167
2203
  if (resultAid)
2168
2204
  groupAid = resultAid;
2169
2205
  const page = validateTailPage(result, afterSeq, limit);
2206
+ const decoded = [];
2207
+ for (const msg of page.messages) {
2208
+ this.ensureDeliveryCurrent(ns, generation);
2209
+ client._logMessageDebug('tail-raw', 'group.v2.pull', 'group.message_created', msg);
2210
+ const plaintext = await this.decodeGroupWindowMessage(msg, groupId, groupAid, true, false, 'tail', deferPublish);
2211
+ if (plaintext)
2212
+ decoded.push(plaintext);
2213
+ }
2214
+ this.ensureDeliveryCurrent(ns, generation);
2170
2215
  client._seqTracker.commitTailWindow(ns, {
2171
2216
  windowStartSeq: page.windowStart,
2172
2217
  headSeq: page.head,
@@ -2175,13 +2220,7 @@ export class V2E2EECoordinator {
2175
2220
  });
2176
2221
  client._persistSeq(ns);
2177
2222
  await client._saveSeqTrackerState?.();
2178
- const decoded = [];
2179
- for (const msg of page.messages) {
2180
- client._logMessageDebug('tail-raw', 'group.v2.pull', 'group.message_created', msg);
2181
- const plaintext = await this.decodeGroupWindowMessage(msg, groupId, groupAid, true, false, 'tail', deferPublish);
2182
- if (plaintext)
2183
- decoded.push(plaintext);
2184
- }
2223
+ this.ensureDeliveryCurrent(ns, generation);
2185
2224
  const ack = client._seqTracker.getContiguousSeq(ns);
2186
2225
  if (ownsCursor)
2187
2226
  client._delivery.syncProgress(ns, {
@@ -2229,6 +2268,7 @@ export class V2E2EECoordinator {
2229
2268
  }
2230
2269
  async pullGroupV2Impl(groupId, afterSeq = 0, limit = 50, opts) {
2231
2270
  const client = this.client;
2271
+ const generation = Number(client._v2RuntimeGeneration ?? 0);
2232
2272
  await client._ensureV2SessionReady('group.pull');
2233
2273
  const gid = String(groupId ?? '').trim();
2234
2274
  if (!gid)
@@ -2294,6 +2334,7 @@ export class V2E2EECoordinator {
2294
2334
  const pipelineQueue = new V2PullPageQueue(V2_PULL_PIPELINE_QUEUE_CAPACITY);
2295
2335
  let pipelineProducer = null;
2296
2336
  let pipelineStopped = false;
2337
+ const pipelineResume = { current: null };
2297
2338
  const startPipeline = (startAfterSeq) => {
2298
2339
  if (pipelineRunning || pageCount >= maxPages || limit < V2_PULL_MAX_PAGE_LIMIT || !ownsCursor)
2299
2340
  return;
@@ -2313,6 +2354,7 @@ export class V2E2EECoordinator {
2313
2354
  if (pipelineStopped)
2314
2355
  break;
2315
2356
  const pageMessages = (Array.isArray(result.messages) ? result.messages : []);
2357
+ const completed = new Promise((resolve) => { pipelineResume.current = resolve; });
2316
2358
  const enqueued = await pipelineQueue.put({
2317
2359
  result,
2318
2360
  afterSeq: producerAfterSeq,
@@ -2323,6 +2365,9 @@ export class V2E2EECoordinator {
2323
2365
  }, pageMessages.length);
2324
2366
  if (!enqueued || pipelineStopped)
2325
2367
  break;
2368
+ await completed;
2369
+ if (pipelineStopped)
2370
+ break;
2326
2371
  const messages = deduplicateForwardPageMessages(pageMessages, producerAfterSeq);
2327
2372
  const seqs = messages
2328
2373
  .map((msg) => Number(msg.seq ?? 0))
@@ -2353,6 +2398,8 @@ export class V2E2EECoordinator {
2353
2398
  };
2354
2399
  const stopPipeline = async () => {
2355
2400
  pipelineStopped = true;
2401
+ pipelineResume.current?.();
2402
+ pipelineResume.current = null;
2356
2403
  pipelineQueue.close();
2357
2404
  if (pipelineProducer) {
2358
2405
  const producer = pipelineProducer;
@@ -2429,9 +2476,8 @@ export class V2E2EECoordinator {
2429
2476
  .map((msg) => Number(msg.seq ?? 0))
2430
2477
  .filter((seq) => Number.isFinite(seq) && seq > 0);
2431
2478
  const pageContigBefore = client._seqTracker.getContiguousSeq(ns);
2432
- const pageTrackerSnapshot = typeof client._seqTracker.snapshotNamespace === 'function'
2433
- ? client._seqTracker.snapshotNamespace(ns)
2434
- : null;
2479
+ let pageTrackerSnapshot = null;
2480
+ let trackerMutated = false;
2435
2481
  let pageMaxSeq = nextAfterSeq;
2436
2482
  if (seqs.length > 0) {
2437
2483
  pageMaxSeq = Math.max(...seqs);
@@ -2582,7 +2628,17 @@ export class V2E2EECoordinator {
2582
2628
  let contigAdvanced = false;
2583
2629
  if (ownsCursor) {
2584
2630
  try {
2631
+ this.ensureDeliveryCurrent(ns, generation);
2632
+ const window = client._seqTracker.getSyncState?.(ns);
2633
+ const deliveryTarget = window && commitTarget >= window.tail - 1
2634
+ ? Math.max(commitTarget, window.head) : commitTarget;
2635
+ if (deliveryTarget > pageContigBefore) {
2636
+ await client._drainOrderedMessages(ns, undefined, false, false, 'pull', deliveryTarget);
2637
+ }
2638
+ this.ensureDeliveryCurrent(ns, generation);
2639
+ pageTrackerSnapshot = client._seqTracker.snapshotNamespace?.(ns) ?? null;
2585
2640
  if (commitTarget > pageContigBefore) {
2641
+ trackerMutated = true;
2586
2642
  client._seqTracker.forceContiguousSeq(ns, commitTarget);
2587
2643
  if (effectiveFloor > pageContigBefore) {
2588
2644
  client._clientLog.info(`group.v2.pull floor advance: ns=${ns} contiguous=${pageContigBefore} -> effective_floor=${effectiveFloor} retention_floor=${retentionFloor} visibility_floor=${visibilityFloor}`);
@@ -2598,19 +2654,21 @@ export class V2E2EECoordinator {
2598
2654
  contigAdvanced = ackSeq !== pageContigBefore;
2599
2655
  if (contigAdvanced) {
2600
2656
  await client._commitSeqTrackerState(ns);
2657
+ this.ensureDeliveryCurrent(ns, generation);
2601
2658
  if (pageCount === 1 && deferredServerCursor > 0)
2602
2659
  this.clearForwardCursor(ns, ackSeq);
2603
2660
  }
2604
2661
  }
2605
2662
  catch (exc) {
2606
- if (typeof client._seqTracker.restoreNamespaceSnapshot === 'function') {
2607
- client._seqTracker.restoreNamespaceSnapshot(ns, pageTrackerSnapshot);
2663
+ if (trackerMutated && Number(client._v2RuntimeGeneration ?? 0) === generation
2664
+ && client._rpcPipeline?.isPullNamespaceCurrent?.(ns) !== false
2665
+ && typeof client._seqTracker.restoreNamespaceSnapshot === 'function') {
2666
+ (client._seqTracker._restoreNamespaceSnapshotPreservingPush ?? client._seqTracker.restoreNamespaceSnapshot)
2667
+ .call(client._seqTracker, ns, pageTrackerSnapshot);
2608
2668
  }
2609
2669
  client._clientLog.error?.(`group.v2.pull Forward commit rolled back: group=${gid} ns=${ns} target=${commitTarget} error=${formatE2EEError(exc)}`);
2610
2670
  throw exc;
2611
2671
  }
2612
- if (contigAdvanced)
2613
- await client._drainOrderedMessages(ns, undefined, false, false, 'pull');
2614
2672
  }
2615
2673
  for (const fetch of deferredKeyFetches.values()) {
2616
2674
  this.scheduleSenderIKFetch(fetch.fromAid, fetch.senderDeviceId, fetch.groupId);
@@ -2700,6 +2758,10 @@ export class V2E2EECoordinator {
2700
2758
  if (tailDelayMs > 0)
2701
2759
  await v2Sleep(tailDelayMs);
2702
2760
  nextAfterSeq = nextAfter;
2761
+ if (pipelinePage) {
2762
+ pipelineResume.current?.();
2763
+ pipelineResume.current = null;
2764
+ }
2703
2765
  }
2704
2766
  }
2705
2767
  finally {
@@ -3241,6 +3303,8 @@ export class V2E2EECoordinator {
3241
3303
  encrypted: true,
3242
3304
  e2ee,
3243
3305
  };
3306
+ if (typeof plaintext.type === 'string' && plaintext.type.startsWith('aun.ownership.'))
3307
+ result.from_aid = fromAid;
3244
3308
  const senderDeviceId = String(aad.from_device ?? '').trim();
3245
3309
  if (senderDeviceId)
3246
3310
  result.sender_device_id = senderDeviceId;