@agentunion/fastaun 0.4.0 → 0.4.2
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/CHANGELOG.md +47 -0
- package/_packed_docs/AUN_SDK_/351/207/215/346/236/204/350/256/276/350/256/241/346/226/271/346/241/210_v3.md +158 -94
- package/_packed_docs/CHANGELOG.md +47 -0
- package/_packed_docs/sdk/06-API/346/211/213/345/206/214.md +5 -0
- package/dist/aid-store.d.ts +80 -16
- package/dist/aid-store.js +22 -21
- package/dist/aid-store.js.map +1 -1
- package/dist/aid.d.ts +6 -0
- package/dist/aid.js +6 -0
- package/dist/aid.js.map +1 -1
- package/dist/client.d.ts +11 -23
- package/dist/client.js +51 -72
- package/dist/client.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js.map +1 -1
- package/dist/keystore/file.js +1 -1
- package/dist/keystore/file.js.map +1 -1
- package/dist/tools/cross-sdk-agent.js +5 -12
- package/dist/tools/cross-sdk-agent.js.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +1 -1
package/dist/client.js
CHANGED
|
@@ -542,23 +542,20 @@ export class AUNClient {
|
|
|
542
542
|
_lastDisconnectInfo = null;
|
|
543
543
|
_logger;
|
|
544
544
|
_clientLog;
|
|
545
|
-
constructor(
|
|
546
|
-
if (typeof
|
|
545
|
+
constructor(aid) {
|
|
546
|
+
if (typeof aid === 'string') {
|
|
547
547
|
throw new ValidationError('AUNClient aid must be an AID object, not a string');
|
|
548
548
|
}
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
}
|
|
552
|
-
const inputAid = first instanceof AID ? first : null;
|
|
553
|
-
if (!inputAid && second !== undefined) {
|
|
554
|
-
throw new ValidationError('AUNClient options-only construction accepts a single options object');
|
|
555
|
-
}
|
|
556
|
-
const options = inputAid ? (second ?? {}) : (first ?? {});
|
|
557
|
-
assertClientOptions(options, 'AUNClient options');
|
|
549
|
+
const inputAid = aid instanceof AID ? aid : null;
|
|
550
|
+
const options = {};
|
|
558
551
|
const rawConfig = clientOptionsConfig(options);
|
|
559
|
-
if (inputAid)
|
|
552
|
+
if (inputAid) {
|
|
560
553
|
rawConfig.aun_path = inputAid.aunPath;
|
|
561
|
-
|
|
554
|
+
rawConfig.verify_ssl = inputAid.verifySsl;
|
|
555
|
+
if (inputAid.rootCaPath)
|
|
556
|
+
rawConfig.root_ca_path = inputAid.rootCaPath;
|
|
557
|
+
rawConfig.debug = inputAid.debug;
|
|
558
|
+
}
|
|
562
559
|
this._configModel = configFromMap(rawConfig);
|
|
563
560
|
const initAid = inputAid ? inputAid.aid : null;
|
|
564
561
|
this._agentMdPath = path.join(this._configModel.aunPath, 'AIDs');
|
|
@@ -569,7 +566,7 @@ export class AUNClient {
|
|
|
569
566
|
};
|
|
570
567
|
this._deviceId = (inputAid?.deviceId) || getDeviceId(this._configModel.aunPath);
|
|
571
568
|
// 初始化 Logger(per-client 单例,必须最早创建)
|
|
572
|
-
const debugFlag = this._configModel.debug
|
|
569
|
+
const debugFlag = this._configModel.debug;
|
|
573
570
|
this._logger = new AUNLogger({
|
|
574
571
|
debug: debugFlag,
|
|
575
572
|
aunPath: this._configModel.aunPath,
|
|
@@ -641,9 +638,6 @@ export class AUNClient {
|
|
|
641
638
|
};
|
|
642
639
|
this._state = 'standby';
|
|
643
640
|
}
|
|
644
|
-
if (options?.protected_headers !== undefined) {
|
|
645
|
-
this.setProtectedHeaders(options.protected_headers);
|
|
646
|
-
}
|
|
647
641
|
// 内部订阅:推送消息自动解密后 re-publish 给用户
|
|
648
642
|
this._dispatcher.subscribe('_raw.message.received', (data) => this._onRawMessageReceived(data));
|
|
649
643
|
// V2 P2P 推送通知:收到通知后自动走 message.v2.pull 拉取并解密
|
|
@@ -1026,7 +1020,8 @@ export class AUNClient {
|
|
|
1026
1020
|
const result = peer.verifyAgentMd(content);
|
|
1027
1021
|
if (!result.ok)
|
|
1028
1022
|
throw new AUNError(result.error.message);
|
|
1029
|
-
|
|
1023
|
+
const vd = result.data;
|
|
1024
|
+
return { ...vd, verified: vd.status === 'verified' };
|
|
1030
1025
|
}
|
|
1031
1026
|
/**
|
|
1032
1027
|
* 读取 {agentMdPath}/{self_aid}/agent.md,签名后上传,并把签名结果原子写回本地。
|
|
@@ -1121,44 +1116,6 @@ export class AUNClient {
|
|
|
1121
1116
|
this._agentMdCache.clear();
|
|
1122
1117
|
return this._agentMdPath;
|
|
1123
1118
|
}
|
|
1124
|
-
/**
|
|
1125
|
-
* 记录本地 agent.md 文件路径并一次性计算 etag(quoted sha256,与服务端一致)。
|
|
1126
|
-
*
|
|
1127
|
-
* - path 为空字符串:清除本地 path 与 etag。
|
|
1128
|
-
* - 文件不存在 / 读取失败:清除 etag 并返回空串,不抛异常(应用可读 getLocalAgentMdEtag()
|
|
1129
|
-
* 为空判断)。
|
|
1130
|
-
* - 浏览器环境无文件系统:直接返回空串,记录 warn 日志。
|
|
1131
|
-
* - 文件变更后需要重新调用 setLocalAgentMdPath() 触发重算(按设计:设置时一次性计算)。
|
|
1132
|
-
*
|
|
1133
|
-
* 返回当前 etag(quoted hex 或空串)。
|
|
1134
|
-
*/
|
|
1135
|
-
setLocalAgentMdPath(path) {
|
|
1136
|
-
const rawPath = String(path ?? '').trim();
|
|
1137
|
-
if (!rawPath) {
|
|
1138
|
-
this._localAgentMdPath = '';
|
|
1139
|
-
this._localAgentMdEtag = '';
|
|
1140
|
-
return '';
|
|
1141
|
-
}
|
|
1142
|
-
// 浏览器环境没有 fs,直接退回空串。Node 环境才尝试读文件。
|
|
1143
|
-
const isNode = typeof process !== 'undefined' && !!process.versions?.node;
|
|
1144
|
-
if (!isNode) {
|
|
1145
|
-
this._clientLog.warn(`setLocalAgentMdPath skipped: not running in Node.js (path=${rawPath})`);
|
|
1146
|
-
this._localAgentMdPath = rawPath;
|
|
1147
|
-
this._localAgentMdEtag = '';
|
|
1148
|
-
return '';
|
|
1149
|
-
}
|
|
1150
|
-
this._localAgentMdPath = rawPath;
|
|
1151
|
-
try {
|
|
1152
|
-
const data = fs.readFileSync(rawPath);
|
|
1153
|
-
const digest = crypto.createHash('sha256').update(data).digest('hex');
|
|
1154
|
-
this._localAgentMdEtag = `"${digest}"`;
|
|
1155
|
-
}
|
|
1156
|
-
catch (err) {
|
|
1157
|
-
this._clientLog.warn(`setLocalAgentMdPath 读取失败 path=${rawPath} err=${err instanceof Error ? err.message : String(err)}`);
|
|
1158
|
-
this._localAgentMdEtag = '';
|
|
1159
|
-
}
|
|
1160
|
-
return this._localAgentMdEtag;
|
|
1161
|
-
}
|
|
1162
1119
|
/** 返回 setLocalAgentMdPath 计算的 etag;未设置或读取失败时返回空串。 */
|
|
1163
1120
|
getLocalAgentMdEtag() {
|
|
1164
1121
|
return this._localAgentMdEtag;
|
|
@@ -1618,7 +1575,7 @@ export class AUNClient {
|
|
|
1618
1575
|
throw new StateError('authenticate requires a loaded AID with a valid private key');
|
|
1619
1576
|
}
|
|
1620
1577
|
const publicState = this.state;
|
|
1621
|
-
if (publicState !== ConnectionState.STANDBY
|
|
1578
|
+
if (publicState !== ConnectionState.STANDBY) {
|
|
1622
1579
|
throw new StateError(`authenticate not allowed in state ${publicState}`);
|
|
1623
1580
|
}
|
|
1624
1581
|
if ('aid' in options || 'access_token' in options || 'token' in options || 'kite_token' in options) {
|
|
@@ -1645,13 +1602,31 @@ export class AUNClient {
|
|
|
1645
1602
|
}
|
|
1646
1603
|
}
|
|
1647
1604
|
/** 连接到 Gateway;身份来自构造函数或 loadIdentity(aid),认证由 SDK 内部自动完成。 */
|
|
1648
|
-
async connect(
|
|
1605
|
+
async connect(opts) {
|
|
1649
1606
|
const tStart = Date.now();
|
|
1650
|
-
if (
|
|
1651
|
-
|
|
1607
|
+
if (opts !== undefined && typeof opts === 'object') {
|
|
1608
|
+
const raw = opts;
|
|
1609
|
+
if ('gateway' in raw || 'access_token' in raw || 'aid' in raw || 'token' in raw) {
|
|
1610
|
+
throw new ValidationError('connect options must not include gateway/access_token/aid; these are managed internally');
|
|
1611
|
+
}
|
|
1612
|
+
}
|
|
1613
|
+
const options = {};
|
|
1614
|
+
if (opts?.auto_reconnect !== undefined)
|
|
1615
|
+
options.auto_reconnect = opts.auto_reconnect;
|
|
1616
|
+
if (opts?.heartbeat_interval !== undefined)
|
|
1617
|
+
options.heartbeat_interval = opts.heartbeat_interval;
|
|
1618
|
+
if (opts?.connect_timeout !== undefined || opts?.call_timeout !== undefined) {
|
|
1619
|
+
options.timeouts = {
|
|
1620
|
+
...(opts.connect_timeout !== undefined ? { connect: opts.connect_timeout } : {}),
|
|
1621
|
+
...(opts.call_timeout !== undefined ? { call: opts.call_timeout } : {}),
|
|
1622
|
+
};
|
|
1652
1623
|
}
|
|
1653
|
-
if (
|
|
1654
|
-
|
|
1624
|
+
if (opts?.retry_initial_delay !== undefined || opts?.retry_max_delay !== undefined || opts?.retry_max_attempts !== undefined) {
|
|
1625
|
+
options.retry = {
|
|
1626
|
+
initial_delay: opts.retry_initial_delay ?? 1,
|
|
1627
|
+
max_delay: opts.retry_max_delay ?? 64,
|
|
1628
|
+
max_attempts: opts.retry_max_attempts ?? 0,
|
|
1629
|
+
};
|
|
1655
1630
|
}
|
|
1656
1631
|
const target = this._currentAid?.aid ?? this._aid ?? '';
|
|
1657
1632
|
if (!target || !this._currentAid?.isPrivateKeyValid()) {
|
|
@@ -1670,8 +1645,12 @@ export class AUNClient {
|
|
|
1670
1645
|
if (publicState === ConnectionState.RETRY_BACKOFF) {
|
|
1671
1646
|
this._stopReconnect();
|
|
1672
1647
|
}
|
|
1648
|
+
// gateway 来自 authenticate() 缓存的 this._gatewayUrl;未认证则自动 authenticate()
|
|
1649
|
+
if (!this._gatewayUrl) {
|
|
1650
|
+
await this.authenticate();
|
|
1651
|
+
}
|
|
1673
1652
|
this._state = 'connecting';
|
|
1674
|
-
const gateway = String(
|
|
1653
|
+
const gateway = String(this._gatewayUrl ?? '').trim();
|
|
1675
1654
|
const params = { ...options, gateway };
|
|
1676
1655
|
const normalized = this._normalizeConnectParams(params);
|
|
1677
1656
|
this._captureCapabilitiesFromConnect(normalized);
|
|
@@ -1733,7 +1712,7 @@ export class AUNClient {
|
|
|
1733
1712
|
closableKeyStore.close?.();
|
|
1734
1713
|
this._state = 'closed';
|
|
1735
1714
|
this._logger.close();
|
|
1736
|
-
await this._dispatcher.publish('
|
|
1715
|
+
await this._dispatcher.publish('state_change', { state: this._publicState(this._state) });
|
|
1737
1716
|
this._resetSeqTrackingState();
|
|
1738
1717
|
this._clientLog.debug(`close exit: elapsed=${Date.now() - tStart}ms`);
|
|
1739
1718
|
}
|
|
@@ -1771,7 +1750,7 @@ export class AUNClient {
|
|
|
1771
1750
|
this._stopReconnect();
|
|
1772
1751
|
await this._transport.close();
|
|
1773
1752
|
this._state = 'standby';
|
|
1774
|
-
await this._dispatcher.publish('
|
|
1753
|
+
await this._dispatcher.publish('state_change', { state: this._publicState(this._state) });
|
|
1775
1754
|
this._clientLog.debug(`disconnect exit: elapsed=${Date.now() - tStart}ms`);
|
|
1776
1755
|
}
|
|
1777
1756
|
catch (err) {
|
|
@@ -4044,7 +4023,7 @@ export class AUNClient {
|
|
|
4044
4023
|
this._state = 'ready';
|
|
4045
4024
|
this._connectedAt = Date.now();
|
|
4046
4025
|
this._clientLog.debug(`auth complete, connection ready: aid=${this._aid ?? ''}, gateway=${gatewayUrl}`);
|
|
4047
|
-
await this._dispatcher.publish('
|
|
4026
|
+
await this._dispatcher.publish('state_change', { state: this._publicState(this._state), gateway: gatewayUrl });
|
|
4048
4027
|
// auth 阶段 aid 可能被 identity 覆盖(上方 this._aid = identity.aid);
|
|
4049
4028
|
// 若 context 发生变化,重新 refresh + restore,保持 tracker 与真实身份一致。
|
|
4050
4029
|
if (this._seqTrackerContext !== this._currentSeqTrackerContext()) {
|
|
@@ -6910,7 +6889,7 @@ export class AUNClient {
|
|
|
6910
6889
|
this._clientLog.warn(`transport disconnected: closeCode=${closeCode ?? 'none'}, error=${error ? formatCaughtError(error) : 'none'}`);
|
|
6911
6890
|
this._state = 'standby';
|
|
6912
6891
|
this._stopBackgroundTasks();
|
|
6913
|
-
await this._dispatcher.publish('
|
|
6892
|
+
await this._dispatcher.publish('state_change', { state: this._publicState(this._state), error });
|
|
6914
6893
|
if (!this._sessionOptions.auto_reconnect)
|
|
6915
6894
|
return;
|
|
6916
6895
|
if (this._reconnectActive)
|
|
@@ -6931,7 +6910,7 @@ export class AUNClient {
|
|
|
6931
6910
|
if (disconnectInfo.code !== undefined && disconnectInfo.code !== null) {
|
|
6932
6911
|
eventPayload.code = disconnectInfo.code;
|
|
6933
6912
|
}
|
|
6934
|
-
await this._dispatcher.publish('
|
|
6913
|
+
await this._dispatcher.publish('state_change', eventPayload);
|
|
6935
6914
|
return;
|
|
6936
6915
|
}
|
|
6937
6916
|
// 1000 = 正常关闭, 1006 = 网络异常断开(无 close frame),其他 code = 服务端主动关闭
|
|
@@ -6963,7 +6942,7 @@ export class AUNClient {
|
|
|
6963
6942
|
// max_attempts 检查在循环顶部,覆盖所有路径(含 health-fail)
|
|
6964
6943
|
if (maxAttempts > 0 && attempt > maxAttempts) {
|
|
6965
6944
|
this._state = 'connection_failed';
|
|
6966
|
-
await this._dispatcher.publish('
|
|
6945
|
+
await this._dispatcher.publish('state_change', {
|
|
6967
6946
|
state: this._publicState(this._state),
|
|
6968
6947
|
attempt: attempt - 1,
|
|
6969
6948
|
reason: 'max_attempts_exhausted',
|
|
@@ -6973,7 +6952,7 @@ export class AUNClient {
|
|
|
6973
6952
|
this._retryAttempt = attempt;
|
|
6974
6953
|
this._nextRetryAt = Date.now() + reconnectSleepDelayMs(delay, maxBaseDelay);
|
|
6975
6954
|
this._state = 'retry_backoff';
|
|
6976
|
-
await this._dispatcher.publish('
|
|
6955
|
+
await this._dispatcher.publish('state_change', {
|
|
6977
6956
|
state: this._publicState(this._state),
|
|
6978
6957
|
attempt,
|
|
6979
6958
|
next_retry_at: this._nextRetryAt,
|
|
@@ -6984,7 +6963,7 @@ export class AUNClient {
|
|
|
6984
6963
|
if (this._reconnectAbort?.signal.aborted || this._closing)
|
|
6985
6964
|
break;
|
|
6986
6965
|
this._state = 'reconnecting';
|
|
6987
|
-
await this._dispatcher.publish('
|
|
6966
|
+
await this._dispatcher.publish('state_change', {
|
|
6988
6967
|
state: this._publicState(this._state),
|
|
6989
6968
|
attempt,
|
|
6990
6969
|
});
|
|
@@ -7015,7 +6994,7 @@ export class AUNClient {
|
|
|
7015
6994
|
});
|
|
7016
6995
|
if (!AUNClient._shouldRetryReconnect(exc)) {
|
|
7017
6996
|
this._state = 'connection_failed';
|
|
7018
|
-
await this._dispatcher.publish('
|
|
6997
|
+
await this._dispatcher.publish('state_change', {
|
|
7019
6998
|
state: this._publicState(this._state),
|
|
7020
6999
|
error: formatCaughtError(exc),
|
|
7021
7000
|
attempt,
|