@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
package/dist/client.js CHANGED
@@ -688,7 +688,7 @@ export class AUNClient {
688
688
  this._dispatcher.subscribe('_raw.group.state_committed', (data) => this._onGroupStateCommitted(data));
689
689
  // 其他事件直接透传
690
690
  for (const evt of ['message.ack', 'storage.object_changed', 'stream/created', 'stream/closed']) {
691
- this._dispatcher.subscribe(`_raw.${evt}`, (data) => this._dispatcher.publish(evt, data));
691
+ this._dispatcher.subscribe(`_raw.${evt}`, (data) => this._dispatcher.enqueue(evt, data));
692
692
  }
693
693
  // 服务端主动断开通知:记录日志并标记不重连
694
694
  this._dispatcher.subscribe('_raw.gateway.disconnect', (data) => this._onGatewayDisconnect(data));
@@ -852,6 +852,7 @@ export class AUNClient {
852
852
  this._peerCache.clear();
853
853
  this._certCache.clear();
854
854
  this._gatewayUrl = null;
855
+ this._gatewayCandidates = [];
855
856
  this._deviceId = aid.deviceId || getDeviceId(nextConfig.aunPath);
856
857
  this._slotId = aid.slotId || 'default';
857
858
  const debugFlag = nextConfig.debug;
@@ -1059,7 +1060,12 @@ export class AUNClient {
1059
1060
  const target = message.slice(agentPrefix.length).trim();
1060
1061
  if (!target || target.toLowerCase() !== String(this._aid ?? '').trim().toLowerCase())
1061
1062
  return false;
1062
- await this._agentMdManager.upload(buildDefaultAgentMd(target));
1063
+ let agentMd = buildDefaultAgentMd(target);
1064
+ try {
1065
+ agentMd = this._agentMdManager.readContent(target);
1066
+ }
1067
+ catch { }
1068
+ await this._agentMdManager.upload(agentMd);
1063
1069
  return true;
1064
1070
  }
1065
1071
  async _runGroupIdentityOperation(groupId, operation) {
@@ -1091,6 +1097,10 @@ export class AUNClient {
1091
1097
  }
1092
1098
  this._aidStore = store;
1093
1099
  const payload = { ...params };
1100
+ if (payload.group_name === undefined && payload.groupName !== undefined) {
1101
+ payload.group_name = payload.groupName;
1102
+ delete payload.groupName;
1103
+ }
1094
1104
  const isNamed = Boolean(String(payload.group_name ?? '').trim());
1095
1105
  payload._defer_group_ready_postprocess = true;
1096
1106
  if (!isNamed) {
@@ -1116,7 +1126,21 @@ export class AUNClient {
1116
1126
  delete postprocessParams._defer_group_ready_postprocess;
1117
1127
  return await this._groupState.postprocessResult('group.create', postprocessParams, result);
1118
1128
  }
1119
- const keyPair = new CryptoProvider().generateIdentity();
1129
+ const pendingKey = `create:${String(payload.group_name).trim().toLowerCase()}`;
1130
+ const keystore = store._keystore;
1131
+ let keyPair = null;
1132
+ if (keystore && typeof keystore.loadPendingGroupBind === 'function') {
1133
+ keyPair = keystore.loadPendingGroupBind(pendingKey);
1134
+ }
1135
+ if (!keyPair || !keyPair.public_key_der_b64 || !keyPair.private_key_pem) {
1136
+ keyPair = new CryptoProvider().generateIdentity();
1137
+ if (keystore && typeof keystore.savePendingGroupBind === 'function') {
1138
+ keystore.savePendingGroupBind(pendingKey, keyPair);
1139
+ }
1140
+ }
1141
+ if (!keyPair || !keyPair.public_key_der_b64 || !keyPair.private_key_pem) {
1142
+ throw new ValidationError('createGroup: failed to generate or load key pair');
1143
+ }
1120
1144
  payload.public_key = keyPair.public_key_der_b64;
1121
1145
  payload.curve = keyPair.curve;
1122
1146
  const result = await this.call('group.create', payload);
@@ -1138,6 +1162,9 @@ export class AUNClient {
1138
1162
  throw new ValidationError(imported.error.message);
1139
1163
  }
1140
1164
  await this._uploadGroupAgentMd(store, groupAid, payload, group);
1165
+ if (keystore && typeof keystore.clearPendingGroupBind === 'function') {
1166
+ keystore.clearPendingGroupBind(pendingKey);
1167
+ }
1141
1168
  const postprocessParams = { ...payload };
1142
1169
  delete postprocessParams._defer_group_ready_postprocess;
1143
1170
  return await this._groupState.postprocessResult('group.create', postprocessParams, result);
@@ -1193,11 +1220,15 @@ export class AUNClient {
1193
1220
  }
1194
1221
  this._aidStore = store;
1195
1222
  const groupId = String(params.group_id ?? params.group_aid ?? '').trim();
1223
+ const pendingKey = `bind:${groupId}`;
1196
1224
  const keystore = store._keystore; // AIDStore._keystore: LocalIdentityStore
1197
1225
  let keyPair = null;
1198
1226
  // 优先复用 pending 槽位中已暂存的待绑定密钥(崩溃/重试幂等)
1199
1227
  if (groupId && keystore && typeof keystore.loadPendingGroupBind === 'function') {
1200
- keyPair = keystore.loadPendingGroupBind(groupId);
1228
+ keyPair = keystore.loadPendingGroupBind(pendingKey);
1229
+ if (!keyPair || !keyPair.public_key_der_b64 || !keyPair.private_key_pem) {
1230
+ keyPair = keystore.loadPendingGroupBind(groupId);
1231
+ }
1201
1232
  }
1202
1233
  if (!keyPair || !keyPair.public_key_der_b64 || !keyPair.private_key_pem) {
1203
1234
  // 未命中 pending,生成新密钥
@@ -1209,7 +1240,7 @@ export class AUNClient {
1209
1240
  };
1210
1241
  // 发 RPC 前先落盘暂存,确保崩溃后重试能复用同一密钥
1211
1242
  if (groupId && keystore && typeof keystore.savePendingGroupBind === 'function') {
1212
- keystore.savePendingGroupBind(groupId, keyPair);
1243
+ keystore.savePendingGroupBind(pendingKey, keyPair);
1213
1244
  }
1214
1245
  }
1215
1246
  if (!keyPair) {
@@ -1244,6 +1275,7 @@ export class AUNClient {
1244
1275
  await this._uploadGroupAgentMd(store, groupAid, payload, group);
1245
1276
  // 落盘成功,清除 pending 槽位
1246
1277
  if (groupId && keystore && typeof keystore.clearPendingGroupBind === 'function') {
1278
+ keystore.clearPendingGroupBind(pendingKey);
1247
1279
  keystore.clearPendingGroupBind(groupId);
1248
1280
  }
1249
1281
  return result;
@@ -1333,7 +1365,21 @@ export class AUNClient {
1333
1365
  throw new ValidationError(`renewGroupAid: cannot determine old public key for ${groupAid}`);
1334
1366
  }
1335
1367
  // 生成新密钥
1336
- const newKeyPair = new CryptoProvider().generateIdentity();
1368
+ const keystore = store._keystore;
1369
+ const pendingKey = `renew:${groupId}`;
1370
+ let newKeyPair = null;
1371
+ if (keystore && typeof keystore.loadPendingGroupBind === 'function') {
1372
+ newKeyPair = keystore.loadPendingGroupBind(pendingKey);
1373
+ }
1374
+ if (!newKeyPair || !newKeyPair.public_key_der_b64 || !newKeyPair.private_key_pem) {
1375
+ newKeyPair = new CryptoProvider().generateIdentity();
1376
+ if (keystore && typeof keystore.savePendingGroupBind === 'function') {
1377
+ keystore.savePendingGroupBind(pendingKey, newKeyPair);
1378
+ }
1379
+ }
1380
+ if (!newKeyPair || !newKeyPair.public_key_der_b64 || !newKeyPair.private_key_pem) {
1381
+ throw new ValidationError('renewGroupAid: failed to generate or load key pair');
1382
+ }
1337
1383
  const newPublicKey = newKeyPair.public_key_der_b64;
1338
1384
  const newPrivateKey = newKeyPair.private_key_pem;
1339
1385
  const curve = newKeyPair.curve || 'P-256';
@@ -1389,6 +1435,9 @@ export class AUNClient {
1389
1435
  throw new ValidationError(`renewGroupAid failed to persist group identity: ${imported.error.message}`);
1390
1436
  }
1391
1437
  await this._uploadGroupAgentMd(store, returnedGroupAid, payload, group);
1438
+ if (keystore && typeof keystore.clearPendingGroupBind === 'function') {
1439
+ keystore.clearPendingGroupBind(pendingKey);
1440
+ }
1392
1441
  return result;
1393
1442
  }
1394
1443
  async completeGroupTransfer(params = {}, options = {}) {
@@ -1399,12 +1448,26 @@ export class AUNClient {
1399
1448
  if (!store) {
1400
1449
  throw new ValidationError('completeGroupTransfer requires aidStore');
1401
1450
  }
1402
- const keyPair = new CryptoProvider().generateIdentity();
1403
1451
  const payload = { ...params };
1404
1452
  const groupId = String(params.group_id ?? '').trim();
1405
1453
  if (!groupId) {
1406
1454
  throw new ValidationError('completeGroupTransfer requires group_id');
1407
1455
  }
1456
+ const pendingKey = `complete:${groupId}`;
1457
+ const keystore = store._keystore;
1458
+ let keyPair = null;
1459
+ if (keystore && typeof keystore.loadPendingGroupBind === 'function') {
1460
+ keyPair = keystore.loadPendingGroupBind(pendingKey);
1461
+ }
1462
+ if (!keyPair || !keyPair.public_key_der_b64 || !keyPair.private_key_pem) {
1463
+ keyPair = new CryptoProvider().generateIdentity();
1464
+ if (keystore && typeof keystore.savePendingGroupBind === 'function') {
1465
+ keystore.savePendingGroupBind(pendingKey, keyPair);
1466
+ }
1467
+ }
1468
+ if (!keyPair || !keyPair.public_key_der_b64 || !keyPair.private_key_pem) {
1469
+ throw new ValidationError('completeGroupTransfer: failed to generate or load key pair');
1470
+ }
1408
1471
  let groupAid = String(params.group_aid ?? '').trim();
1409
1472
  if (!groupAid) {
1410
1473
  const info = await this.call('group.get_info', { group_id: groupId, required: ['member'] });
@@ -1461,6 +1524,9 @@ export class AUNClient {
1461
1524
  throw new ValidationError(imported.error.message);
1462
1525
  }
1463
1526
  await this._uploadGroupAgentMd(store, returnedGroupAid, payload, group);
1527
+ if (keystore && typeof keystore.clearPendingGroupBind === 'function') {
1528
+ keystore.clearPendingGroupBind(pendingKey);
1529
+ }
1464
1530
  return result;
1465
1531
  }
1466
1532
  /** 证书公钥校验:确保服务端返回的证书公钥 == 本地公钥(DER base64) */
@@ -1877,11 +1943,11 @@ export class AUNClient {
1877
1943
  }
1878
1944
  return true;
1879
1945
  }
1880
- async _drainOrderedMessages(ns, beforeSeq, pullResponse = false, persist = true) {
1881
- return this._delivery.drainOrderedMessages(ns, beforeSeq, pullResponse, persist);
1946
+ async _drainOrderedMessages(ns, beforeSeq, pullResponse = false, persist = true, source = 'push') {
1947
+ return this._delivery.drainOrderedMessages(ns, beforeSeq, pullResponse, persist, source);
1882
1948
  }
1883
- async _publishOrderedMessage(event, ns, seq, payload) {
1884
- return this._delivery.publishOrderedMessage(event, ns, seq, payload);
1949
+ async _publishOrderedMessage(event, ns, seq, payload, source = 'push') {
1950
+ return this._delivery.publishOrderedMessage(event, ns, seq, payload, source);
1885
1951
  }
1886
1952
  async _publishPulledMessage(event, ns, seq, payload, persist = true) {
1887
1953
  return this._delivery.publishPulledMessage(event, ns, seq, payload, persist);
@@ -1926,7 +1992,7 @@ export class AUNClient {
1926
1992
  }
1927
1993
  else {
1928
1994
  // data 非对象也透传给用户(兼容旧版)
1929
- await this._dispatcher.publish('group.changed', data);
1995
+ this._dispatcher.enqueue('group.changed', data);
1930
1996
  }
1931
1997
  this._clientLog.debug(`_onRawGroupChanged exit: elapsed=${Date.now() - tStart}ms`);
1932
1998
  }
@@ -1990,7 +2056,7 @@ export class AUNClient {
1990
2056
  certPem = await this._fetchPeerCert(sigAid, expectedFP || undefined);
1991
2057
  }
1992
2058
  catch {
1993
- this._dispatcher.publish('signature_pending', { aid: sigAid, method }).catch(() => { });
2059
+ this._dispatcher.enqueue('signature_pending', { aid: sigAid, method });
1994
2060
  return false;
1995
2061
  }
1996
2062
  }
@@ -2010,19 +2076,19 @@ export class AUNClient {
2010
2076
  if (!ok) {
2011
2077
  this._clientLog.warn(`group event signature verification failed aid=${sigAid} method=${method}`);
2012
2078
  // P1-16: 签名失败统一发布事件
2013
- this._dispatcher.publish('signature.verification_failed', {
2079
+ this._dispatcher.enqueue('signature.verification_failed', {
2014
2080
  aid: sigAid, method, error: 'ECDSA verification failed',
2015
- }).catch(() => { });
2081
+ });
2016
2082
  }
2017
2083
  return ok;
2018
2084
  }
2019
2085
  catch (exc) {
2020
2086
  this._clientLog.warn(`group event signature verification error: ${formatCaughtError(exc)}`);
2021
2087
  // P1-16: 签名失败统一发布事件
2022
- this._dispatcher.publish('signature.verification_failed', {
2088
+ this._dispatcher.enqueue('signature.verification_failed', {
2023
2089
  aid: String(cs.aid ?? ''), method: String(cs._method ?? ''),
2024
2090
  error: formatCaughtError(exc),
2025
- }).catch(() => { });
2091
+ });
2026
2092
  return false;
2027
2093
  }
2028
2094
  }
@@ -2419,7 +2485,7 @@ export class AUNClient {
2419
2485
  }
2420
2486
  }
2421
2487
  else {
2422
- await this._dispatcher.publish('state_change', statePayload);
2488
+ this._dispatcher.enqueue('state_change', statePayload);
2423
2489
  }
2424
2490
  this._assertReconnectOwner(reconnectOwner);
2425
2491
  this._lifecycle.assertConnectionAttemptOwner(connectionOwner);
@@ -2761,7 +2827,7 @@ export class AUNClient {
2761
2827
  this._attachV2EnvelopeMetadata(event, e2eeMeta);
2762
2828
  this._logMessageDebug('decrypt-fail', 'v2.decrypt', undecryptableEvent, event);
2763
2829
  if (emitUndecryptable)
2764
- await this._dispatcher.publish(undecryptableEvent, event);
2830
+ this._dispatcher.enqueue(undecryptableEvent, event);
2765
2831
  return null;
2766
2832
  }
2767
2833
  this._clientLog.debug(`V2 decrypt key lookup ok: seq=${String(msg.seq ?? '')}, group=${groupIdForKeys || '<p2p>'}, ik_len=${ikPriv.byteLength}, spk_len=${spkPriv?.byteLength ?? 0}`);
@@ -2800,7 +2866,7 @@ export class AUNClient {
2800
2866
  this._attachV2EnvelopeMetadata(event, e2eeMeta);
2801
2867
  this._logMessageDebug('decrypt-fail', 'v2.decrypt', undecryptableEvent, event);
2802
2868
  if (emitUndecryptable)
2803
- await this._dispatcher.publish(undecryptableEvent, event);
2869
+ this._dispatcher.enqueue(undecryptableEvent, event);
2804
2870
  return null;
2805
2871
  }
2806
2872
  let plaintext;
@@ -2829,7 +2895,7 @@ export class AUNClient {
2829
2895
  this._attachV2EnvelopeMetadata(event, e2eeMeta);
2830
2896
  this._logMessageDebug('decrypt-fail', 'v2.decrypt', undecryptableEvent, event);
2831
2897
  if (emitUndecryptable)
2832
- await this._dispatcher.publish(undecryptableEvent, event);
2898
+ this._dispatcher.enqueue(undecryptableEvent, event);
2833
2899
  return null;
2834
2900
  }
2835
2901
  if (plaintext === null) {
@@ -3065,6 +3131,11 @@ export class AUNClient {
3065
3131
  if (!resolvedAid) {
3066
3132
  throw new StateError('gateway discovery requires a loaded AID');
3067
3133
  }
3134
+ const discovery = this._discovery;
3135
+ const tokenStore = this._tokenStore;
3136
+ const discoveryIsCurrent = () => (this._discovery === discovery
3137
+ && this._tokenStore === tokenStore
3138
+ && !this._closing);
3068
3139
  if (this._gatewayCandidates.length > 0)
3069
3140
  return [...this._gatewayCandidates];
3070
3141
  if (this._gatewayUrl) {
@@ -3072,9 +3143,9 @@ export class AUNClient {
3072
3143
  return [...this._gatewayCandidates];
3073
3144
  }
3074
3145
  try {
3075
- const loadMetadata = this._tokenStore.loadMetadata;
3146
+ const loadMetadata = tokenStore.loadMetadata;
3076
3147
  const metadata = typeof loadMetadata === 'function'
3077
- ? loadMetadata.call(this._tokenStore, resolvedAid)
3148
+ ? loadMetadata.call(tokenStore, resolvedAid)
3078
3149
  : null;
3079
3150
  const cachedList = isJsonObject(metadata) && Array.isArray(metadata.gateway_urls)
3080
3151
  ? metadata.gateway_urls.map((item) => String(item ?? '').trim()).filter(Boolean)
@@ -3101,12 +3172,13 @@ export class AUNClient {
3101
3172
  try {
3102
3173
  // discoverAll 是生产路径;若调用方注入了旧版/测试 discovery
3103
3174
  // 替身而只提供 discover,则保留单候选兼容,不影响多候选发现。
3104
- const discovery = this._discovery;
3105
3175
  const hasInjectedDiscover = Object.prototype.hasOwnProperty.call(discovery, 'discover')
3106
3176
  && typeof discovery.discover === 'function';
3107
3177
  const discovered = hasInjectedDiscover
3108
3178
  ? [await discovery.discover(url)]
3109
3179
  : await discovery.discoverAll(url);
3180
+ if (!discoveryIsCurrent())
3181
+ throw new StateError('gateway discovery superseded by identity change');
3110
3182
  const gatewayUrls = [...new Set(discovered.map((item) => String(item ?? '').trim()).filter(Boolean))];
3111
3183
  if (gatewayUrls.length === 0)
3112
3184
  throw new ValidationError('gateway discovery returned no candidates');
@@ -3114,9 +3186,9 @@ export class AUNClient {
3114
3186
  const gateway = gatewayUrls[0];
3115
3187
  this._gatewayUrl = gateway;
3116
3188
  try {
3117
- const saveMetadata = this._tokenStore.saveMetadata;
3189
+ const saveMetadata = tokenStore.saveMetadata;
3118
3190
  if (typeof saveMetadata === 'function') {
3119
- saveMetadata.call(this._tokenStore, resolvedAid, {
3191
+ saveMetadata.call(tokenStore, resolvedAid, {
3120
3192
  gateway_url: gateway,
3121
3193
  gateway_urls: gatewayUrls,
3122
3194
  gateway_cached_at: Date.now(),
@@ -3129,6 +3201,8 @@ export class AUNClient {
3129
3201
  return [...gatewayUrls];
3130
3202
  }
3131
3203
  catch (err) {
3204
+ if (!discoveryIsCurrent())
3205
+ throw new StateError('gateway discovery superseded by identity change');
3132
3206
  lastErr = err;
3133
3207
  this._clientLog.warn(`gateway discovery failed: aid=${resolvedAid} url=${url} err=${formatCaughtError(err)}`);
3134
3208
  }
@@ -3363,7 +3437,7 @@ export class AUNClient {
3363
3437
  if (this._sessionParams !== null && identity.access_token) {
3364
3438
  this._sessionParams.access_token = identity.access_token;
3365
3439
  }
3366
- await this._dispatcher.publish('token.refreshed', {
3440
+ this._dispatcher.enqueue('token.refreshed', {
3367
3441
  aid: identity.aid,
3368
3442
  expires_at: identity.access_token_expires_at,
3369
3443
  });
@@ -3373,7 +3447,7 @@ export class AUNClient {
3373
3447
  if (exc instanceof AuthError) {
3374
3448
  if (authErrorRequiresRelogin(exc)) {
3375
3449
  this._clientLog.warn(`token refresh requires relogin, stopping refresh loop and triggering reconnect: ${exc.message}`);
3376
- await this._dispatcher.publish('token.refresh_exhausted', {
3450
+ this._dispatcher.enqueue('token.refresh_exhausted', {
3377
3451
  aid: this._identity?.aid ?? null,
3378
3452
  consecutive_failures: 1,
3379
3453
  last_error: String(exc),
@@ -3386,7 +3460,7 @@ export class AUNClient {
3386
3460
  this._tokenRefreshFailures++;
3387
3461
  if (this._tokenRefreshFailures >= 3) {
3388
3462
  this._clientLog.warn(`token refresh failed ${this._tokenRefreshFailures} consecutive times, stopping refresh loop and triggering reconnect`);
3389
- await this._dispatcher.publish('token.refresh_exhausted', {
3463
+ this._dispatcher.enqueue('token.refresh_exhausted', {
3390
3464
  aid: this._identity?.aid ?? null,
3391
3465
  consecutive_failures: this._tokenRefreshFailures,
3392
3466
  last_error: String(exc),
@@ -3398,7 +3472,7 @@ export class AUNClient {
3398
3472
  this._clientLog.debug(`token refresh failed (${this._tokenRefreshFailures}/3), will retry: ${exc}`);
3399
3473
  }
3400
3474
  else {
3401
- await this._dispatcher.publish('connection.error', { error: formatCaughtError(exc) });
3475
+ this._dispatcher.enqueue('connection.error', { error: formatCaughtError(exc) });
3402
3476
  }
3403
3477
  }
3404
3478
  scheduleNext();
@@ -3469,7 +3543,7 @@ export class AUNClient {
3469
3543
  this._lastDisconnectInfo = { code, reason, detail };
3470
3544
  // 透传给应用层订阅者
3471
3545
  try {
3472
- await this._dispatcher.publish('gateway.disconnect', {
3546
+ this._dispatcher.enqueue('gateway.disconnect', {
3473
3547
  code,
3474
3548
  reason,
3475
3549
  detail,
@@ -3595,13 +3669,7 @@ export class AUNClient {
3595
3669
  async _publishReconnectEvent(owner, event, payload) {
3596
3670
  if (!this._ownsReconnect(owner))
3597
3671
  return false;
3598
- this._reconnectEventDispatchDepth += 1;
3599
- try {
3600
- await this._dispatcher.publish(event, payload);
3601
- }
3602
- finally {
3603
- this._reconnectEventDispatchDepth -= 1;
3604
- }
3672
+ this._dispatcher.enqueue(event, payload);
3605
3673
  return this._ownsReconnect(owner);
3606
3674
  }
3607
3675
  async _cancelReconnectAndWait() {
@@ -3610,6 +3678,8 @@ export class AUNClient {
3610
3678
  if (!owner && !task && !this._reconnectActive)
3611
3679
  return;
3612
3680
  owner?.abort();
3681
+ this._discovery?._cancelPending?.();
3682
+ this._auth?._cancelPending?.();
3613
3683
  this._stopBackgroundTasks();
3614
3684
  try {
3615
3685
  await this._transport.close();