@agentunion/fastaun 0.5.8 → 0.5.10

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 (54) hide show
  1. package/CHANGELOG.md +64 -0
  2. package/_packed_docs/CHANGELOG.md +64 -0
  3. package/_packed_docs/agent.md/examples//347/276/244/347/273/204-/345/274/200/345/217/221/345/233/242/351/230/237.md +21 -0
  4. package/_packed_docs/sdk/04-/350/277/236/346/216/245/344/270/216/350/256/244/350/257/201.md +6 -5
  5. package/_packed_docs/sdk/06-API/346/211/213/345/206/214.md +43 -8
  6. package/_packed_docs/sdk/09-group-rpc-manual.md +18 -3
  7. package/_packed_docs/sdk/09-message-rpc-manual.md +34 -10
  8. package/dist/agent-md-schema.js +3 -0
  9. package/dist/agent-md-schema.js.map +1 -1
  10. package/dist/agent-md.js +5 -1
  11. package/dist/agent-md.js.map +1 -1
  12. package/dist/aid-store.js +1 -3
  13. package/dist/aid-store.js.map +1 -1
  14. package/dist/auth.d.ts +5 -2
  15. package/dist/auth.js +64 -27
  16. package/dist/auth.js.map +1 -1
  17. package/dist/client/delivery.d.ts +25 -5
  18. package/dist/client/delivery.js +355 -70
  19. package/dist/client/delivery.js.map +1 -1
  20. package/dist/client/group-state.js +8 -8
  21. package/dist/client/group-state.js.map +1 -1
  22. package/dist/client/lifecycle.js +25 -22
  23. package/dist/client/lifecycle.js.map +1 -1
  24. package/dist/client/rpc-pipeline.d.ts +12 -0
  25. package/dist/client/rpc-pipeline.js +182 -32
  26. package/dist/client/rpc-pipeline.js.map +1 -1
  27. package/dist/client/v2-e2ee.d.ts +1 -0
  28. package/dist/client/v2-e2ee.js +55 -21
  29. package/dist/client/v2-e2ee.js.map +1 -1
  30. package/dist/client.js +108 -38
  31. package/dist/client.js.map +1 -1
  32. package/dist/discovery.d.ts +1 -0
  33. package/dist/discovery.js +3 -0
  34. package/dist/discovery.js.map +1 -1
  35. package/dist/events.d.ts +23 -8
  36. package/dist/events.js +120 -26
  37. package/dist/events.js.map +1 -1
  38. package/dist/facades.js +7 -3
  39. package/dist/facades.js.map +1 -1
  40. package/dist/index.d.ts +1 -1
  41. package/dist/index.js.map +1 -1
  42. package/dist/net.d.ts +3 -0
  43. package/dist/net.js +13 -0
  44. package/dist/net.js.map +1 -1
  45. package/dist/register-flow.js +15 -111
  46. package/dist/register-flow.js.map +1 -1
  47. package/dist/transport.d.ts +32 -3
  48. package/dist/transport.js +758 -33
  49. package/dist/transport.js.map +1 -1
  50. package/dist/version.d.ts +1 -1
  51. package/dist/version.js +1 -1
  52. package/dist/version.js.map +1 -1
  53. package/package.json +1 -1
  54. package/_packed_docs//345/217/221/345/270/203/346/212/245/345/221/212-0.5.6.md +0 -260
@@ -298,6 +298,10 @@ export class V2E2EECoordinator {
298
298
  this.pendingForwardCursors.clear();
299
299
  this.pendingForwardAcks.clear();
300
300
  }
301
+ hasPendingSenderIKWork() {
302
+ return this.senderIKSyncFetches.size > 0
303
+ || Boolean(this.client._v2SenderIKFetching?.size);
304
+ }
301
305
  pendingForwardCursor(ns, localAck) {
302
306
  if (!ns)
303
307
  return 0;
@@ -648,6 +652,7 @@ export class V2E2EECoordinator {
648
652
  finally {
649
653
  if (this.senderIKSyncFetches.get(fetchKey) === task)
650
654
  this.senderIKSyncFetches.delete(fetchKey);
655
+ client._rpcPipeline?.requestPullDrainedCheck?.();
651
656
  }
652
657
  }
653
658
  scheduleSenderIKPending(args) {
@@ -679,6 +684,10 @@ export class V2E2EECoordinator {
679
684
  }
680
685
  async resolveSenderIKPending(fromAid, senderDeviceId, groupId, fetchKey) {
681
686
  const client = this.client;
687
+ const generation = Number(client._v2RuntimeGeneration ?? 0);
688
+ const pending = client._v2SenderIKPending;
689
+ const fetching = client._v2SenderIKFetching;
690
+ const generationIsCurrent = () => Number(client._v2RuntimeGeneration ?? 0) === generation;
682
691
  try {
683
692
  const session = client._v2Session;
684
693
  if (session && fromAid) {
@@ -718,7 +727,9 @@ export class V2E2EECoordinator {
718
727
  await this.getV2SenderPubDer(fromAid, senderDeviceId);
719
728
  }
720
729
  }
721
- const pendingItems = [...client._v2SenderIKPending.entries()].filter(([, entry]) => entry.fromAid === fromAid && entry.senderDeviceId === senderDeviceId && entry.groupId === groupId);
730
+ if (!generationIsCurrent())
731
+ return;
732
+ const pendingItems = [...pending.entries()].filter(([, entry]) => entry.fromAid === fromAid && entry.senderDeviceId === senderDeviceId && entry.groupId === groupId);
722
733
  for (const [key, entry] of pendingItems) {
723
734
  let plaintext = null;
724
735
  const retryStatus = {};
@@ -727,9 +738,12 @@ export class V2E2EECoordinator {
727
738
  }
728
739
  catch (exc) {
729
740
  client._clientLog.warn(`V2 sender IK pending retry raised: key=${key} err=${formatE2EEError(exc)}`);
730
- client._v2SenderIKPending.delete(key);
741
+ if (generationIsCurrent())
742
+ pending.delete(key);
731
743
  continue;
732
744
  }
745
+ if (!generationIsCurrent())
746
+ return;
733
747
  if (plaintext === null) {
734
748
  if (retryStatus.deferred) {
735
749
  client._clientLog.warn(`V2 pending retry still missing key material: key=${key}`);
@@ -741,10 +755,16 @@ export class V2E2EECoordinator {
741
755
  const safeEvent = this.safeUndecryptablePushEvent(entry.msg, isGroup);
742
756
  safeEvent._decrypt_error = 'sender IK pending retry failed';
743
757
  safeEvent._decrypt_stage = 'sender_ik_pending_retry';
744
- await client._publishAppEvent(eventName, safeEvent, 'pending_retry');
758
+ try {
759
+ await client._publishAppEvent(eventName, safeEvent, 'pending_retry');
760
+ }
761
+ finally {
762
+ if (generationIsCurrent())
763
+ pending.delete(key);
764
+ }
745
765
  continue;
746
766
  }
747
- client._v2SenderIKPending.delete(key);
767
+ pending.delete(key);
748
768
  const seq = Number(entry.msg.seq ?? 0);
749
769
  if (entry.groupId) {
750
770
  plaintext = normalizeGroupMentionMode(plaintext, entry.msg, entry.msg.envelope_json);
@@ -758,7 +778,10 @@ export class V2E2EECoordinator {
758
778
  }
759
779
  }
760
780
  finally {
761
- client._v2SenderIKFetching.delete(fetchKey);
781
+ if (generationIsCurrent() && client._v2SenderIKFetching === fetching) {
782
+ fetching.delete(fetchKey);
783
+ client._rpcPipeline?.requestPullDrainedCheck?.();
784
+ }
762
785
  }
763
786
  }
764
787
  async buildV2P2PEnvelope(opts) {
@@ -924,9 +947,10 @@ export class V2E2EECoordinator {
924
947
  throw new ValidationError("message.send requires 'to'");
925
948
  if (!isJsonObject(payload))
926
949
  throw new ValidationError('message.send payload must be a dict for V2 encryption');
950
+ const messageId = String(opts?.messageId ?? '').trim() || `m-${crypto.randomUUID().replace(/-/g, '')}`;
927
951
  client._logMessageDebug('send-plaintext', 'message.send.v2', 'message.send', {
928
952
  to: toAid,
929
- message_id: opts?.messageId ?? '',
953
+ message_id: messageId,
930
954
  payload,
931
955
  }, { payloadOverride: payload });
932
956
  const attempt = async (useCache) => {
@@ -934,7 +958,7 @@ export class V2E2EECoordinator {
934
958
  const envelope = await client._buildV2P2PEnvelope({
935
959
  to: toAid,
936
960
  payload,
937
- messageId: opts?.messageId,
961
+ messageId,
938
962
  timestamp: opts?.timestamp,
939
963
  protectedHeaders: opts?.protectedHeaders,
940
964
  context: opts?.context,
@@ -943,6 +967,7 @@ export class V2E2EECoordinator {
943
967
  const result = await client.call('message.send', {
944
968
  to: toAid,
945
969
  payload: envelope,
970
+ message_id: messageId,
946
971
  encrypt: false,
947
972
  _skip_send_result_envelope: true,
948
973
  });
@@ -954,7 +979,7 @@ export class V2E2EECoordinator {
954
979
  return client._delivery.attachSendResultEnvelope('message.send', {
955
980
  to: toAid,
956
981
  payload,
957
- message_id: opts?.messageId,
982
+ message_id: messageId,
958
983
  timestamp: opts?.timestamp,
959
984
  protected_headers: opts?.protectedHeaders,
960
985
  context: opts?.context,
@@ -969,7 +994,7 @@ export class V2E2EECoordinator {
969
994
  return client._delivery.attachSendResultEnvelope('message.send', {
970
995
  to: toAid,
971
996
  payload,
972
- message_id: opts?.messageId,
997
+ message_id: messageId,
973
998
  timestamp: opts?.timestamp,
974
999
  protected_headers: opts?.protectedHeaders,
975
1000
  context: opts?.context,
@@ -1022,7 +1047,7 @@ export class V2E2EECoordinator {
1022
1047
  if (publish) {
1023
1048
  const event = client._delivery.p2pAppEventForMessage(plaintext);
1024
1049
  if (orderedPublish) {
1025
- await client._delivery.publishOrderedMessage(event.event, client._aid ? `p2p:${client._aid}` : '', seq, event.payload);
1050
+ await client._delivery.publishOrderedMessage(event.event, client._aid ? `p2p:${client._aid}` : '', seq, event.payload, source);
1026
1051
  }
1027
1052
  else {
1028
1053
  await client._publishAppEvent(event.event, event.payload, source);
@@ -1079,7 +1104,7 @@ export class V2E2EECoordinator {
1079
1104
  }
1080
1105
  if (publish) {
1081
1106
  if (orderedPublish) {
1082
- await client._delivery.publishOrderedMessage('group.message_created', `group:${groupId}`, seq, plaintext);
1107
+ await client._delivery.publishOrderedMessage('group.message_created', `group:${groupId}`, seq, plaintext, source);
1083
1108
  }
1084
1109
  else {
1085
1110
  await client._publishAppEvent('group.message_created', plaintext, source);
@@ -1227,6 +1252,7 @@ export class V2E2EECoordinator {
1227
1252
  pageMaxSeq = Math.max(...seqs);
1228
1253
  }
1229
1254
  const deferredKeyFetches = new Map();
1255
+ let blockedSeq = 0;
1230
1256
  for (const msg of messages) {
1231
1257
  const seq = Number(msg.seq ?? 0);
1232
1258
  if (!Number.isFinite(seq) || seq <= 0)
@@ -1275,6 +1301,9 @@ export class V2E2EECoordinator {
1275
1301
  }
1276
1302
  const deferStatus = {};
1277
1303
  const plaintext = await client._decryptV2Message(msg, true, true, true, true, deferStatus, true);
1304
+ if (deferStatus.deferred) {
1305
+ blockedSeq = blockedSeq > 0 ? Math.min(blockedSeq, seq) : seq;
1306
+ }
1278
1307
  if (deferStatus.deferred && deferStatus.fromAid) {
1279
1308
  const key = `${deferStatus.fromAid}\u0000${deferStatus.senderDeviceId ?? ''}\u0000${deferStatus.groupId ?? ''}`;
1280
1309
  deferredKeyFetches.set(key, {
@@ -1301,7 +1330,7 @@ export class V2E2EECoordinator {
1301
1330
  const serverAckSeq = parsedServerAckSeq ?? 0;
1302
1331
  const retentionFloor = Math.max(0, Number(result.retention_floor_seq ?? 0));
1303
1332
  if (ns) {
1304
- const commitTarget = Math.max(pageContigBefore, Number.isFinite(retentionFloor) ? retentionFloor : 0, pageCount === 1 ? deferredServerCursor : 0, seqs.length > 0 ? pageMaxSeq : pageContigBefore);
1333
+ const commitTarget = Math.max(pageContigBefore, Number.isFinite(retentionFloor) ? retentionFloor : 0, pageCount === 1 ? deferredServerCursor : 0, blockedSeq > 0 ? blockedSeq - 1 : (seqs.length > 0 ? pageMaxSeq : pageContigBefore));
1305
1334
  let ackSeq = pageContigBefore;
1306
1335
  let contigAdvanced = false;
1307
1336
  try {
@@ -1333,7 +1362,7 @@ export class V2E2EECoordinator {
1333
1362
  throw exc;
1334
1363
  }
1335
1364
  if (contigAdvanced)
1336
- await client._drainOrderedMessages(ns, undefined, false, false);
1365
+ await client._drainOrderedMessages(ns, undefined, false, false, 'pull');
1337
1366
  for (const fetch of deferredKeyFetches.values()) {
1338
1367
  this.scheduleSenderIKFetch(fetch.fromAid, fetch.senderDeviceId, fetch.groupId);
1339
1368
  }
@@ -1352,7 +1381,7 @@ export class V2E2EECoordinator {
1352
1381
  if (ackNeeded) {
1353
1382
  this.recordForwardAck(ns, ackSeq);
1354
1383
  const nextAfter = Math.max(pageMaxSeq, nextAfterSeq);
1355
- const canContinuePage = messages.length > 0 && nextAfter > nextAfterSeq;
1384
+ const canContinuePage = blockedSeq <= 0 && messages.length > 0 && nextAfter > nextAfterSeq;
1356
1385
  if (canContinuePage) {
1357
1386
  pendingAckSeq = Math.max(pendingAckSeq, ackSeq);
1358
1387
  lastAutoAckSeq = Math.max(lastAutoAckSeq, ackSeq);
@@ -1483,9 +1512,10 @@ export class V2E2EECoordinator {
1483
1512
  const groupAid = String(opts?.groupAid ?? '').trim();
1484
1513
  if (!isJsonObject(payload))
1485
1514
  throw new ValidationError('group.send payload must be a dict for V2 encryption');
1515
+ const messageId = String(opts?.messageId ?? '').trim() || `m-${crypto.randomUUID().replace(/-/g, '')}`;
1486
1516
  client._logMessageDebug('send-plaintext', 'group.send.v2', 'group.send', withExplicitGroupAid({
1487
1517
  group_id: gid,
1488
- message_id: opts?.messageId ?? '',
1518
+ message_id: messageId,
1489
1519
  payload,
1490
1520
  }, groupAid), { payloadOverride: payload });
1491
1521
  const attempt = async (useCache) => {
@@ -1493,7 +1523,7 @@ export class V2E2EECoordinator {
1493
1523
  const envelope = await client._buildV2GroupEnvelope({
1494
1524
  groupId: gid,
1495
1525
  payload,
1496
- messageId: opts?.messageId,
1526
+ messageId,
1497
1527
  timestamp: opts?.timestamp,
1498
1528
  protectedHeaders: opts?.protectedHeaders,
1499
1529
  context: opts?.context,
@@ -1525,7 +1555,7 @@ export class V2E2EECoordinator {
1525
1555
  return client._delivery.attachSendResultEnvelope('group.send', withExplicitGroupAid({
1526
1556
  group_id: gid,
1527
1557
  payload,
1528
- message_id: opts?.messageId,
1558
+ message_id: messageId,
1529
1559
  timestamp: opts?.timestamp,
1530
1560
  protected_headers: opts?.protectedHeaders,
1531
1561
  context: opts?.context,
@@ -1541,7 +1571,7 @@ export class V2E2EECoordinator {
1541
1571
  return client._delivery.attachSendResultEnvelope('group.send', withExplicitGroupAid({
1542
1572
  group_id: gid,
1543
1573
  payload,
1544
- message_id: opts?.messageId,
1574
+ message_id: messageId,
1545
1575
  timestamp: opts?.timestamp,
1546
1576
  protected_headers: opts?.protectedHeaders,
1547
1577
  context: opts?.context,
@@ -1885,6 +1915,7 @@ export class V2E2EECoordinator {
1885
1915
  pageMaxSeq = Math.max(...seqs);
1886
1916
  }
1887
1917
  const deferredKeyFetches = new Map();
1918
+ let blockedSeq = 0;
1888
1919
  for (const msg of messages) {
1889
1920
  const seq = Number(msg.seq ?? 0);
1890
1921
  if (!Number.isFinite(seq) || seq <= 0)
@@ -1954,6 +1985,9 @@ export class V2E2EECoordinator {
1954
1985
  }
1955
1986
  const deferStatus = {};
1956
1987
  let plaintext = await client._decryptV2Message(msg, true, true, true, true, deferStatus, true);
1988
+ if (deferStatus.deferred) {
1989
+ blockedSeq = blockedSeq > 0 ? Math.min(blockedSeq, seq) : seq;
1990
+ }
1957
1991
  if (deferStatus.deferred && deferStatus.fromAid) {
1958
1992
  const key = `${deferStatus.fromAid}\u0000${deferStatus.senderDeviceId ?? ''}\u0000${deferStatus.groupId ?? ''}`;
1959
1993
  deferredKeyFetches.set(key, {
@@ -1979,7 +2013,7 @@ export class V2E2EECoordinator {
1979
2013
  const retentionFloor = Math.max(client._pullRetentionFloor(result, 'retention_floor_message_seq', 'retention_floor_message_seq'));
1980
2014
  const visibilityFloor = Math.max(0, Math.max(0, Number(result.earliest_available_message_seq ?? 1) - 1), Number(cursor?.join_seq ?? 0));
1981
2015
  const effectiveFloor = Math.max(retentionFloor, visibilityFloor);
1982
- const commitTarget = Math.max(pageContigBefore, effectiveFloor, ownsCursor && pageCount === 1 ? deferredServerCursor : 0, seqs.length > 0 ? pageMaxSeq : pageContigBefore);
2016
+ const commitTarget = Math.max(pageContigBefore, effectiveFloor, ownsCursor && pageCount === 1 ? deferredServerCursor : 0, blockedSeq > 0 ? blockedSeq - 1 : (seqs.length > 0 ? pageMaxSeq : pageContigBefore));
1983
2017
  let ackSeq = pageContigBefore;
1984
2018
  let contigAdvanced = false;
1985
2019
  if (ownsCursor) {
@@ -2012,7 +2046,7 @@ export class V2E2EECoordinator {
2012
2046
  throw exc;
2013
2047
  }
2014
2048
  if (contigAdvanced)
2015
- await client._drainOrderedMessages(ns, undefined, false, false);
2049
+ await client._drainOrderedMessages(ns, undefined, false, false, 'pull');
2016
2050
  }
2017
2051
  for (const fetch of deferredKeyFetches.values()) {
2018
2052
  this.scheduleSenderIKFetch(fetch.fromAid, fetch.senderDeviceId, fetch.groupId);
@@ -2033,7 +2067,7 @@ export class V2E2EECoordinator {
2033
2067
  if (ackNeeded) {
2034
2068
  this.recordForwardAck(ns, ackSeq);
2035
2069
  const nextAfter = Math.max(pageMaxSeq, nextAfterSeq);
2036
- const canContinuePage = messages.length > 0 && nextAfter > nextAfterSeq && ownsCursor;
2070
+ const canContinuePage = blockedSeq <= 0 && messages.length > 0 && nextAfter > nextAfterSeq && ownsCursor;
2037
2071
  if (canContinuePage) {
2038
2072
  pendingAckSeq = Math.max(pendingAckSeq, ackSeq);
2039
2073
  lastAutoAckSeq = Math.max(lastAutoAckSeq, ackSeq);