@agentunion/fastaun 0.4.8 → 0.4.9

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.
package/dist/client.js CHANGED
@@ -836,72 +836,14 @@ export class AUNClient {
836
836
  }
837
837
  /** 关闭连接 */
838
838
  async close() {
839
- const tStart = Date.now();
840
- this._clientLog.debug(`close enter: state=${this._state}, aid=${this._aid ?? ''}`);
841
- try {
842
- this._closing = true;
843
- this._saveSeqTrackerState();
844
- this._stopBackgroundTasks();
845
- this._stopReconnect();
846
- if (this.state === ConnectionState.NO_IDENTITY || this.state === ConnectionState.CLOSED) {
847
- const closableStore = this._tokenStore;
848
- closableStore.close?.();
849
- this._state = 'closed';
850
- this._logger.close();
851
- this._resetSeqTrackingState();
852
- this._clientLog.debug(`close exit: elapsed=${Date.now() - tStart}ms (was no_identity/closed)`);
853
- return;
854
- }
855
- await this._transport.close();
856
- const closableStore = this._tokenStore;
857
- closableStore.close?.();
858
- this._state = 'closed';
859
- this._logger.close();
860
- await this._dispatcher.publish('state_change', { state: this._publicState(this._state) });
861
- this._resetSeqTrackingState();
862
- this._clientLog.debug(`close exit: elapsed=${Date.now() - tStart}ms`);
863
- }
864
- catch (err) {
865
- this._clientLog.debug(`close exit (error): elapsed=${Date.now() - tStart}ms err=${err instanceof Error ? err.message : String(err)}`);
866
- throw err;
867
- }
839
+ return this._lifecycle.close();
868
840
  }
869
841
  /**
870
842
  * 断开连接但不关闭客户端(可重新 connect,对齐 Python disconnect)。
871
843
  * disconnect 是可恢复的:停止心跳、关闭 WebSocket,但不清理 keystore 等状态。
872
844
  */
873
845
  async disconnect() {
874
- const tStart = Date.now();
875
- this._clientLog.debug(`disconnect enter: state=${this._state}, aid=${this._aid ?? ''}, closing=${this._closing}`);
876
- try {
877
- // 若 close() 已在执行中,跳过 disconnect 避免竞态
878
- if (this._closing) {
879
- this._clientLog.debug(`disconnect exit: elapsed=${Date.now() - tStart}ms (closing)`);
880
- return;
881
- }
882
- if (![
883
- ConnectionState.AUTHENTICATED,
884
- ConnectionState.CONNECTING,
885
- ConnectionState.READY,
886
- ConnectionState.RETRY_BACKOFF,
887
- ConnectionState.RECONNECTING,
888
- ConnectionState.CONNECTION_FAILED,
889
- ].includes(this.state)) {
890
- this._clientLog.debug(`disconnect exit: elapsed=${Date.now() - tStart}ms (state=${this._state})`);
891
- return;
892
- }
893
- this._saveSeqTrackerState();
894
- this._stopBackgroundTasks();
895
- this._stopReconnect();
896
- await this._transport.close();
897
- this._state = 'standby';
898
- await this._dispatcher.publish('state_change', { state: this._publicState(this._state) });
899
- this._clientLog.debug(`disconnect exit: elapsed=${Date.now() - tStart}ms`);
900
- }
901
- catch (err) {
902
- this._clientLog.debug(`disconnect exit (error): elapsed=${Date.now() - tStart}ms err=${err instanceof Error ? err.message : String(err)}`);
903
- throw err;
904
- }
846
+ return this._lifecycle.disconnect();
905
847
  }
906
848
  // ── RPC ───────────────────────────────────────────────────
907
849
  /**
@@ -909,154 +851,7 @@ export class AUNClient {
909
851
  * 自动处理内部方法限制、E2EE 加解密、客户端签名等。
910
852
  */
911
853
  async call(method, params) {
912
- const tStart = Date.now();
913
- this._clientLog.debug(`call enter: method=${method}`);
914
- try {
915
- const preflight = this._rpcPipeline.preflight(method, params);
916
- const p = preflight.params;
917
- const rpcBackground = preflight.rpcBackground;
918
- const runWithRpcPriority = async (operation) => {
919
- if (!rpcBackground)
920
- return await operation();
921
- return await this._withBackgroundRpc(operation);
922
- };
923
- const pullGateLocked = Boolean(p._pull_gate_locked);
924
- if ('_pull_gate_locked' in p) {
925
- delete p._pull_gate_locked;
926
- }
927
- const pullGateKey = this._pullGateKeyForCall(method, p);
928
- if (pullGateKey && this._isPullResponseProcessing(pullGateKey)) {
929
- this._clientLog.debug(`pull skipped while processing pull response: method=${method} key=${pullGateKey}`);
930
- return this._emptyPullResultForCall(method);
931
- }
932
- if (pullGateKey && !pullGateLocked) {
933
- const lockedParams = { ...p, _pull_gate_locked: true };
934
- if (rpcBackground)
935
- lockedParams._rpc_background = true;
936
- const result = await this._runPullSerialized(pullGateKey, async () => this.call(method, lockedParams));
937
- return result;
938
- }
939
- // 自动加密:message.send 默认加密(encrypt 默认 true)— V2-only
940
- if (method === 'message.send') {
941
- const encrypt = p.encrypt ?? true;
942
- delete p.encrypt;
943
- if (encrypt) {
944
- return await runWithRpcPriority(() => this._sendV2(String(p.to ?? ''), p.payload, {
945
- messageId: String(p.message_id ?? '') || undefined,
946
- timestamp: p.timestamp,
947
- protectedHeaders: this._protectedHeadersFromParams(p),
948
- context: isJsonObject(p.context) ? p.context : undefined,
949
- }));
950
- }
951
- // encrypt=false:明文走通用 RPC 路径;protected_headers/headers 是信封元数据,加密与否都保留
952
- this._maybeAppendEchoTraceSend(p);
953
- }
954
- // 自动加密:group.send 默认加密(encrypt 默认 true)— V2-only
955
- if (method === 'group.send') {
956
- const encrypt = p.encrypt ?? true;
957
- delete p.encrypt;
958
- if (encrypt) {
959
- return await runWithRpcPriority(() => this._sendGroupV2(String(p.group_id ?? ''), p.payload, {
960
- messageId: String(p.message_id ?? '') || undefined,
961
- timestamp: p.timestamp,
962
- protectedHeaders: this._protectedHeadersFromParams(p),
963
- context: isJsonObject(p.context) ? p.context : undefined,
964
- }));
965
- }
966
- this._maybeAppendEchoTraceSend(p);
967
- }
968
- if (method === 'group.thought.put') {
969
- const encrypt = p.encrypt ?? true;
970
- delete p.encrypt;
971
- if (encrypt) {
972
- const v2Error = 'V2 session not initialized; encrypted group.thought.put requires V2 (V1 E2EE removed)';
973
- if (!this._v2Session || !String(p.group_id ?? '').trim()) {
974
- throw new StateError(v2Error);
975
- }
976
- return await runWithRpcPriority(() => this._putGroupThoughtEncryptedV2(p));
977
- }
978
- }
979
- if (method === 'message.thought.put') {
980
- const encrypt = p.encrypt ?? true;
981
- delete p.encrypt;
982
- if (encrypt) {
983
- await this._ensureV2SessionReady('message.thought.put', 'V2 session not initialized; encrypted message.thought.put requires V2 (V1 E2EE removed)');
984
- return await runWithRpcPriority(() => this._putMessageThoughtEncryptedV2(p));
985
- }
986
- }
987
- // V2-only:兼容入口名只作为 SDK 内部适配层存在,底层绝不能降级发 legacy RPC。
988
- if (method === 'message.pull' || method === 'message.v2.pull') {
989
- await this._ensureV2SessionReady('message.pull');
990
- const skipAutoAck = p._skip_auto_ack === true || p.skip_auto_ack === true;
991
- const force = p.force === true;
992
- const afterSeq = Number(p.after_seq ?? 0) || 0;
993
- const limit = Number(p.limit ?? 50) || 50;
994
- const messages = skipAutoAck
995
- ? await runWithRpcPriority(() => this._pullV2(afterSeq, limit, { skipAutoAck: true, gateLocked: true, force }))
996
- : await runWithRpcPriority(() => this._pullV2(afterSeq, limit, { gateLocked: true, force }));
997
- return { messages };
998
- }
999
- if (method === 'message.ack' || method === 'message.v2.ack') {
1000
- await this._ensureV2SessionReady('message.ack');
1001
- return await runWithRpcPriority(() => this._ackV2(Number(p.seq ?? p.up_to_seq ?? 0) || undefined));
1002
- }
1003
- if (method === 'group.pull' || method === 'group.v2.pull') {
1004
- if (!String(p.group_id ?? '').trim()) {
1005
- throw new ValidationError('group.pull requires group_id');
1006
- }
1007
- await this._ensureV2SessionReady('group.pull');
1008
- const hasExplicitAfterSeq = 'after_seq' in p || 'after_message_seq' in p;
1009
- const cursorParams = this._explicitGroupCursorParams(p);
1010
- const ownsCursor = Object.keys(cursorParams).length === 0 || this._groupCursorTargetsCurrentInstance(cursorParams);
1011
- const pullOpts = { gateLocked: true };
1012
- if (hasExplicitAfterSeq)
1013
- pullOpts.explicitAfterSeq = true;
1014
- if (Object.keys(cursorParams).length > 0)
1015
- pullOpts.cursorParams = cursorParams;
1016
- if (!ownsCursor)
1017
- pullOpts.ownsCursor = false;
1018
- const messages = await runWithRpcPriority(() => this._pullGroupV2(String(p.group_id), Number(p.after_seq ?? p.after_message_seq ?? 0) || 0, Number(p.limit ?? 50) || 50, pullOpts));
1019
- return { messages };
1020
- }
1021
- if (method === 'group.ack_messages' || method === 'group.v2.ack') {
1022
- if (!String(p.group_id ?? '').trim()) {
1023
- throw new ValidationError('group.ack_messages requires group_id');
1024
- }
1025
- await this._ensureV2SessionReady('group.ack_messages');
1026
- const cursorParams = this._explicitGroupCursorParams(p);
1027
- const ownsCursor = Object.keys(cursorParams).length === 0 || this._groupCursorTargetsCurrentInstance(cursorParams);
1028
- if (method === 'group.ack_messages' && !ownsCursor) {
1029
- return await runWithRpcPriority(() => this._rawGroupAckMessages(p));
1030
- }
1031
- return await runWithRpcPriority(() => this._ackGroupV2(String(p.group_id), Number(p.seq ?? p.msg_seq ?? p.up_to_seq ?? 0) || undefined));
1032
- }
1033
- if (method === 'message.pull') {
1034
- delete p._skip_auto_ack;
1035
- delete p.skip_auto_ack;
1036
- }
1037
- delete p._group_cursor_params;
1038
- // 关键操作自动附加客户端签名
1039
- this._rpcPipeline.applyClientSignature(method, p);
1040
- // P1-23: 非幂等方法使用更长超时
1041
- const callTimeout = NON_IDEMPOTENT_METHODS.has(method) ? NON_IDEMPOTENT_TIMEOUT_MS : undefined;
1042
- if (method === 'group.thought.get' || method === 'message.thought.get') {
1043
- this._clientLog.debug(`thought.get transport call start: method=${method}, params=${this._debugJson(this._messageEnvelopeFieldsForDebug(p))}`);
1044
- }
1045
- let result = callTimeout
1046
- ? (rpcBackground
1047
- ? await this._transport.call(method, p, callTimeout, undefined, true)
1048
- : await this._transport.call(method, p, callTimeout))
1049
- : (rpcBackground
1050
- ? await this._transport.call(method, p, undefined, undefined, true)
1051
- : await this._transport.call(method, p));
1052
- result = await this._rpcPipeline.postprocessResult(method, p, result);
1053
- this._clientLog.debug(`call exit: method=${method} elapsed=${Date.now() - tStart}ms`);
1054
- return result;
1055
- }
1056
- catch (err) {
1057
- this._clientLog.debug(`call exit (error): method=${method} elapsed=${Date.now() - tStart}ms err=${err instanceof Error ? err.message : String(err)}`);
1058
- throw err;
1059
- }
854
+ return await this._rpcPipeline.call(method, params);
1060
855
  }
1061
856
  // ── 事件 ──────────────────────────────────────────────────
1062
857
  /** 订阅事件 */
@@ -1120,35 +915,14 @@ export class AUNClient {
1120
915
  async _onRawMessageReceived(data) {
1121
916
  return this._delivery.onRawMessageReceived(data);
1122
917
  }
1123
- /** 实际处理推送消息的异步任务 */
1124
- async _processAndPublishMessage(data) {
1125
- return this._delivery.processAndPublishMessage(data);
1126
- }
1127
918
  /** 处理群组消息推送:自动解密后 re-publish */
1128
919
  async _onRawGroupMessageCreated(data) {
1129
920
  return this._delivery.onRawGroupMessageCreated(data);
1130
921
  }
1131
- /**
1132
- * 处理群组推送消息的异步任务。
1133
- *
1134
- * 带 payload 的事件(消息推送):解密后 re-publish。
1135
- * 不带 payload 的事件(通知):自动 pull 最新消息,逐条解密后 re-publish。
1136
- */
1137
- async _processAndPublishGroupMessage(data) {
1138
- return this._delivery.processAndPublishGroupMessage(data);
1139
- }
1140
- /** 后台补齐群消息空洞 */
1141
- async _fillGroupGap(groupId) {
1142
- return this._delivery.fillGroupGap(groupId);
1143
- }
1144
922
  /** 后台补齐 P2P 消息空洞 */
1145
923
  async _fillP2pGap() {
1146
924
  return this._delivery.fillP2pGap();
1147
925
  }
1148
- /** 只按硬上限裁剪 published guard,不能按 contiguousSeq 清理。 */
1149
- _prunePushedSeqs(ns) {
1150
- this._delivery.prunePushedSeqs(ns);
1151
- }
1152
926
  _recordPendingP2pPull(ns, seq) {
1153
927
  if (!ns || seq <= 0)
1154
928
  return;
@@ -1184,9 +958,6 @@ export class AUNClient {
1184
958
  _markPublishedSeq(ns, seq) {
1185
959
  this._delivery.markPublishedSeq(ns, seq);
1186
960
  }
1187
- _attachCurrentInstanceContext(payload) {
1188
- return this._delivery.attachCurrentInstanceContext(payload);
1189
- }
1190
961
  _publishAppEvent(event, payload, source = 'direct') {
1191
962
  return this._delivery.publishAppEvent(event, payload, source);
1192
963
  }
@@ -1260,18 +1031,12 @@ export class AUNClient {
1260
1031
  _logMessageDebug(stage, source, event, message, opts = {}) {
1261
1032
  this._delivery.logMessageDebug(stage, source, event, message, opts);
1262
1033
  }
1263
- _messageTargetsCurrentInstance(message) {
1264
- return this._delivery.messageTargetsCurrentInstance(message);
1265
- }
1266
1034
  _tryAcquirePullGate(key) {
1267
1035
  return this._rpcPipeline.tryAcquirePullGate(key);
1268
1036
  }
1269
1037
  _releasePullGate(key, token) {
1270
1038
  this._rpcPipeline.releasePullGate(key, token);
1271
1039
  }
1272
- _pullGateKeyForCall(method, params) {
1273
- return this._rpcPipeline.pullGateKeyForCall(method, params);
1274
- }
1275
1040
  _isPullResponseProcessing(key) {
1276
1041
  if (!key)
1277
1042
  return false;
@@ -1396,10 +1161,6 @@ export class AUNClient {
1396
1161
  this._seqTracker.onMessageSeq(ns, seq);
1397
1162
  return this._seqTracker.getContiguousSeq(ns) !== before;
1398
1163
  }
1399
- /** 后台补齐群事件空洞 */
1400
- async _fillGroupEventGap(groupId) {
1401
- return this._delivery.fillGroupEventGap(groupId);
1402
- }
1403
1164
  _extractGroupIdFromResult(result) {
1404
1165
  const group = isJsonObject(result.group) ? result.group : null;
1405
1166
  const gid = group ? String(group.group_id ?? '') : '';
@@ -2086,9 +1847,6 @@ export class AUNClient {
2086
1847
  _scheduleV2SenderIKPending(args) {
2087
1848
  return this._v2E2EE.scheduleSenderIKPending(args);
2088
1849
  }
2089
- async _resolveV2SenderIKPending(fromAid, senderDeviceId, groupId, fetchKey) {
2090
- return await this._v2E2EE.resolveSenderIKPending(fromAid, senderDeviceId, groupId, fetchKey);
2091
- }
2092
1850
  /**
2093
1851
  * 构造 V2 P2P envelope;message.send 与 message.thought.put 共用。
2094
1852
  */
@@ -2784,12 +2542,6 @@ export class AUNClient {
2784
2542
  _validateMessageRecipient(toAid) {
2785
2543
  this._rpcPipeline.validateMessageRecipient(toAid);
2786
2544
  }
2787
- _validateOutboundCall(method, params) {
2788
- this._rpcPipeline.validateOutboundCall(method, params);
2789
- }
2790
- _injectMessageCursorContext(method, params) {
2791
- this._rpcPipeline.injectMessageCursorContext(method, params);
2792
- }
2793
2545
  /** 启动 V2 缓存清理后台任务 */
2794
2546
  _startV2MaintenanceTasks() {
2795
2547
  if (this._cacheCleanupTimer === null) {