@agentunion/fastaun-browser 0.5.2 → 0.5.4

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 (57) hide show
  1. package/CHANGELOG.md +74 -0
  2. package/_packed_docs/CHANGELOG.md +74 -0
  3. package/_packed_docs/INDEX.md +16 -10
  4. package/_packed_docs/KITE_DOCS_GUIDE.md +4 -2
  5. package/_packed_docs/protocol/10-Group-/345/255/220/345/215/217/350/256/256.md +202 -75
  6. package/_packed_docs/protocol/README.md +3 -2
  7. package/_packed_docs/protocol/aun-docs-guide.md +3 -2
  8. package/_packed_docs/protocol/index.md +6 -5
  9. package/_packed_docs/sdk/03-/346/240/270/345/277/203/346/246/202/345/277/265.md +20 -1
  10. package/_packed_docs/sdk/06-API/346/211/213/345/206/214.md +303 -28
  11. package/_packed_docs/sdk/07-/351/224/231/350/257/257/345/244/204/347/220/206.md +30 -6
  12. package/_packed_docs/sdk/08-/346/234/200/344/275/263/345/256/236/350/267/265.md +28 -12
  13. package/_packed_docs/sdk/09-group-rpc-manual.md +126 -42
  14. package/_packed_docs/sdk/AUN_DOCS_GUIDE.md +6 -4
  15. package/_packed_docs/sdk/INDEX.md +17 -17
  16. package/dist/bundle.js +1084 -296
  17. package/dist/client/delivery.d.ts +4 -0
  18. package/dist/client/delivery.d.ts.map +1 -1
  19. package/dist/client/delivery.js +174 -7
  20. package/dist/client/delivery.js.map +1 -1
  21. package/dist/client/v2-e2ee.js +2 -2
  22. package/dist/client/v2-e2ee.js.map +1 -1
  23. package/dist/client.d.ts +27 -1
  24. package/dist/client.d.ts.map +1 -1
  25. package/dist/client.js +118 -12
  26. package/dist/client.js.map +1 -1
  27. package/dist/facades.d.ts +9 -0
  28. package/dist/facades.d.ts.map +1 -1
  29. package/dist/facades.js +314 -77
  30. package/dist/facades.js.map +1 -1
  31. package/dist/group-index.d.ts +105 -0
  32. package/dist/group-index.d.ts.map +1 -0
  33. package/dist/group-index.js +252 -0
  34. package/dist/group-index.js.map +1 -0
  35. package/dist/index.d.ts +1 -0
  36. package/dist/index.d.ts.map +1 -1
  37. package/dist/index.js +1 -0
  38. package/dist/index.js.map +1 -1
  39. package/dist/keystore/index.d.ts +15 -0
  40. package/dist/keystore/index.d.ts.map +1 -1
  41. package/dist/keystore/indexeddb-shared.d.ts +7 -1
  42. package/dist/keystore/indexeddb-shared.d.ts.map +1 -1
  43. package/dist/keystore/indexeddb-shared.js +63 -2
  44. package/dist/keystore/indexeddb-shared.js.map +1 -1
  45. package/dist/keystore/indexeddb-token-store.d.ts +3 -1
  46. package/dist/keystore/indexeddb-token-store.d.ts.map +1 -1
  47. package/dist/keystore/indexeddb-token-store.js +22 -1
  48. package/dist/keystore/indexeddb-token-store.js.map +1 -1
  49. package/dist/tools/cross-sdk-agent.js +3 -1
  50. package/dist/tools/cross-sdk-agent.js.map +1 -1
  51. package/dist/transport.d.ts +2 -1
  52. package/dist/transport.d.ts.map +1 -1
  53. package/dist/transport.js +17 -31
  54. package/dist/transport.js.map +1 -1
  55. package/dist/version.d.ts +1 -1
  56. package/dist/version.js +1 -1
  57. package/package.json +1 -1
package/dist/client.js CHANGED
@@ -30,6 +30,7 @@ import { decryptMessage, } from './v2/e2ee/index.js';
30
30
  import { ecdsaVerifyRaw } from './v2/crypto/ecdsa.js';
31
31
  import { AUNLogger } from './logger.js';
32
32
  import { AgentMdManager } from './agent-md.js';
33
+ import { GroupIndexMetaCache } from './group-index.js';
33
34
  import { certMatchesFingerprint, normalizeFingerprintHex } from './cert-utils.js';
34
35
  import { AUNError, AuthError, ConnectionError, E2EEError, NotFoundError, PermissionError, StateError, TimeoutError, ValidationError, } from './errors.js';
35
36
  import { isJsonObject, ConnectionState, STATE_TO_PUBLIC, } from './types.js';
@@ -67,6 +68,14 @@ function attachGatewayProximity(message, source) {
67
68
  }
68
69
  }
69
70
  }
71
+ function groupIndexBodyText(value) {
72
+ if (typeof value === 'string')
73
+ return value;
74
+ if (value && typeof value === 'object' && !Array.isArray(value) && 'body' in value) {
75
+ return String(value.body ?? '');
76
+ }
77
+ return '';
78
+ }
70
79
  const DEFAULT_SESSION_OPTIONS = {
71
80
  auto_reconnect: true,
72
81
  heartbeat_interval: 30.0,
@@ -565,6 +574,8 @@ export class AUNClient {
565
574
  _v2LazyProposeTriggered = new Map();
566
575
  /** agent.md 运行时管理器,负责上传、下载、缓存和 RPC 元数据观察。 */
567
576
  _agentMdManager;
577
+ _groupIndexMetaCache = new GroupIndexMetaCache();
578
+ _groupIndexCacheLoaded = new Set();
568
579
  /** 消息序列号跟踪器(群消息 + P2P 空洞检测) */
569
580
  _seqTracker = new SeqTracker();
570
581
  _seqTrackerContext = null;
@@ -574,9 +585,13 @@ export class AUNClient {
574
585
  _pushedSeqs = new Map();
575
586
  /** 已解密但因 seq 空洞暂缓发布的应用层消息(按 namespace -> seq) */
576
587
  _pendingOrderedMsgs = new Map();
588
+ /** push 处理队列:按 P2P / group namespace 串行化异步解密与有序投递。 */
589
+ _pushProcessQueues = new Map();
577
590
  /** Lazy group sync:首次发送群消息前自动拉取历史 */
578
591
  _groupSynced = new Set();
579
- /** 群撤回去重:group_id|sorted(message_ids)|recalled_at -> 时间戳,保证应用层只回调一次 */
592
+ /** P2P 撤回去重:原始 message_id -> 时间戳,保证应用层只回调一次 */
593
+ _messageRecallSeen = new Map();
594
+ /** 群撤回去重:group_id|sorted(message_ids) -> 时间戳,保证应用层只回调一次 */
580
595
  _groupRecallSeen = new Map();
581
596
  /** 在线未读 hint 队列:同一 group 只保留最后一条,延迟 drain 降低登录瞬时拉取压力。 */
582
597
  _onlineUnreadHintQueue = new Map();
@@ -693,11 +708,9 @@ export class AUNClient {
693
708
  timeout: DEFAULT_SESSION_OPTIONS.timeouts.call,
694
709
  onDisconnect: (error, closeCode) => this._handleTransportDisconnect(error, closeCode),
695
710
  });
696
- this._transport.setMetaObserver((meta) => {
697
- void this._observeRpcMeta(meta).catch((exc) => {
698
- this._clientLog.debug(`agent.md meta observer skipped: ${String(exc)}`);
699
- });
700
- });
711
+ this._transport.setMetaObserver((meta) => this._observeRpcMeta(meta).catch((exc) => {
712
+ this._clientLog.debug(`rpc meta observer skipped: ${String(exc)}`);
713
+ }));
701
714
  this._runtime = new ClientRuntime(this);
702
715
  this._identityRuntime = new IdentityRuntimeManager(this._runtime);
703
716
  this._peerDirectory = new PeerDirectory(this._runtime);
@@ -733,6 +746,9 @@ export class AUNClient {
733
746
  this._dispatcher.subscribe('_raw.message.received', (data) => {
734
747
  this._onRawMessageReceived(data);
735
748
  });
749
+ this._dispatcher.subscribe('_raw.message.recalled', (data) => {
750
+ this._safeAsync(this._onRawMessageRecalled(data));
751
+ });
736
752
  // 群组消息推送:re-publish(V2 加密消息走 V2 push 路径)
737
753
  this._dispatcher.subscribe('_raw.group.message_created', (data) => {
738
754
  this._onRawGroupMessageCreated(data);
@@ -766,7 +782,7 @@ export class AUNClient {
766
782
  this._safeAsync(this._onGroupStateCommitted(data));
767
783
  });
768
784
  // 其他事件直接透传
769
- for (const evt of ['message.recalled', 'message.ack', 'storage.object_changed']) {
785
+ for (const evt of ['message.ack', 'storage.object_changed']) {
770
786
  this._dispatcher.subscribe(`_raw.${evt}`, (data) => {
771
787
  this._dispatcher.publish(evt, data);
772
788
  });
@@ -815,7 +831,96 @@ export class AUNClient {
815
831
  }
816
832
  /** transport 的 meta observer:吸收 gateway 注入的 _meta 字段。失败不影响业务。 */
817
833
  async _observeRpcMeta(meta) {
834
+ const groupIndexes = isJsonObject(meta.group_indexes)
835
+ ? meta.group_indexes
836
+ : {};
837
+ for (const groupAid of Object.keys(groupIndexes)) {
838
+ await this._loadGroupIndexCache(groupAid);
839
+ }
840
+ this._groupIndexMetaCache.observeRpcMeta(meta, { localAid: this._aid ?? '' });
818
841
  await this._agentMdManager.observeRpcMeta(meta, this._aid);
842
+ for (const groupAid of Object.keys(groupIndexes)) {
843
+ await this._persistGroupIndexCache(groupAid, {
844
+ remote_meta: this._groupIndexMetaCache.remoteMeta(this._aid ?? '', groupAid) ?? {},
845
+ local_etag: this._groupIndexMetaCache.localEtag(this._aid ?? '', groupAid),
846
+ });
847
+ }
848
+ }
849
+ isGroupIndexStale(groupAid) {
850
+ return this._groupIndexMetaCache.isStale(this._aid ?? '', groupAid);
851
+ }
852
+ markGroupIndexFresh(groupAid, options) {
853
+ this._groupIndexMetaCache.markFresh(this._aid ?? '', groupAid, options);
854
+ void this._persistGroupIndexCache(groupAid, { local_etag: String(options.etag ?? '') });
855
+ }
856
+ getGroupIndexRemoteMeta(groupAid) {
857
+ return this._groupIndexMetaCache.remoteMeta(this._aid ?? '', groupAid);
858
+ }
859
+ getGroupIndexLocalEtag(groupAid) {
860
+ return this._groupIndexMetaCache.localEtag(this._aid ?? '', groupAid);
861
+ }
862
+ async getGroupIndexCachedSettings(groupAid, keys) {
863
+ await this._loadGroupIndexCache(groupAid);
864
+ return this._groupIndexMetaCache.cachedSettings(this._aid ?? '', groupAid, keys.map((item) => String(item)));
865
+ }
866
+ async getGroupIndexCachedSettingsByEntries(groupAid, keys, entries) {
867
+ await this._loadGroupIndexCache(groupAid);
868
+ return this._groupIndexMetaCache.cachedSettingsByEntries(this._aid ?? '', groupAid, keys.map((item) => String(item)), entries);
869
+ }
870
+ cacheGroupIndexSettings(groupAid, settings, options) {
871
+ this._groupIndexMetaCache.cacheSettings(this._aid ?? '', groupAid, settings, options);
872
+ const entryEtags = {};
873
+ for (const item of options?.entries ?? []) {
874
+ const key = String(item.key ?? '');
875
+ if (key)
876
+ entryEtags[key] = String(item.etag ?? '');
877
+ }
878
+ const fields = {
879
+ settings,
880
+ entry_etags: entryEtags,
881
+ remote_meta: this._groupIndexMetaCache.remoteMeta(this._aid ?? '', groupAid) ?? {},
882
+ local_etag: String(options?.etag ?? this._groupIndexMetaCache.localEtag(this._aid ?? '', groupAid) ?? ''),
883
+ };
884
+ const indexJsonl = groupIndexBodyText(options?.groupIndex);
885
+ if (indexJsonl)
886
+ fields.index_jsonl = indexJsonl;
887
+ return this._persistGroupIndexCache(groupAid, fields);
888
+ }
889
+ _groupIndexCacheKey(groupAid) {
890
+ return `${this._aid ?? ''}\x00${String(groupAid ?? '')}`;
891
+ }
892
+ async _loadGroupIndexCache(groupAid) {
893
+ const localAid = String(this._aid ?? '').trim();
894
+ const group = String(groupAid ?? '').trim();
895
+ if (!localAid || !group || typeof this._tokenStore.loadGroupIndexCache !== 'function')
896
+ return;
897
+ const key = this._groupIndexCacheKey(group);
898
+ if (this._groupIndexCacheLoaded.has(key))
899
+ return;
900
+ this._groupIndexCacheLoaded.add(key);
901
+ const record = await this._tokenStore.loadGroupIndexCache(localAid, group);
902
+ if (!record)
903
+ return;
904
+ this._groupIndexMetaCache.restore(localAid, group, {
905
+ remote_meta: record.remote_meta,
906
+ local_etag: record.local_etag,
907
+ settings: record.settings,
908
+ entry_etags: record.entry_etags,
909
+ });
910
+ }
911
+ async _persistGroupIndexCache(groupAid, fields) {
912
+ const localAid = String(this._aid ?? '').trim();
913
+ const group = String(groupAid ?? '').trim();
914
+ if (!localAid || !group || typeof this._tokenStore.upsertGroupIndexCache !== 'function')
915
+ return;
916
+ const record = await this._tokenStore.upsertGroupIndexCache(localAid, group, fields);
917
+ this._groupIndexCacheLoaded.add(this._groupIndexCacheKey(group));
918
+ this._groupIndexMetaCache.restore(localAid, group, {
919
+ remote_meta: record.remote_meta,
920
+ local_etag: record.local_etag,
921
+ settings: record.settings,
922
+ entry_etags: record.entry_etags,
923
+ });
819
924
  }
820
925
  get state() {
821
926
  return this._publicState(this._state);
@@ -968,11 +1073,9 @@ export class AUNClient {
968
1073
  timeout: DEFAULT_SESSION_OPTIONS.timeouts.call,
969
1074
  onDisconnect: (error, closeCode) => this._handleTransportDisconnect(error, closeCode),
970
1075
  });
971
- this._transport.setMetaObserver((meta) => {
972
- void this._observeRpcMeta(meta).catch((exc) => {
973
- this._clientLog.debug(`agent.md meta observer skipped: ${String(exc)}`);
974
- });
975
- });
1076
+ this._transport.setMetaObserver((meta) => this._observeRpcMeta(meta).catch((exc) => {
1077
+ this._clientLog.debug(`rpc meta observer skipped: ${String(exc)}`);
1078
+ }));
976
1079
  this._auth.setLogger(this._logAuth);
977
1080
  this._transport.setLogger(this._logTransport);
978
1081
  this._dispatcher.setLogger(this._logEvents);
@@ -1506,6 +1609,9 @@ export class AUNClient {
1506
1609
  _onRawMessageReceived(data) {
1507
1610
  this._delivery.onRawMessageReceived(data);
1508
1611
  }
1612
+ async _onRawMessageRecalled(data) {
1613
+ return this._delivery.onRawMessageRecalled(data);
1614
+ }
1509
1615
  /** 处理群组消息推送:re-publish(V2 加密消息走 V2 push 路径) */
1510
1616
  _onRawGroupMessageCreated(data) {
1511
1617
  return this._delivery.onRawGroupMessageCreated(data);