@agentunion/fastaun 0.5.27 → 0.5.28

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 +36 -0
  2. package/_packed_docs/CHANGELOG.md +36 -0
  3. package/_packed_docs/INDEX.md +17 -2
  4. package/_packed_docs/KITE_DOCS_GUIDE.md +12 -9
  5. package/_packed_docs/sdk/AUN_DOCS_GUIDE.md +2 -2
  6. package/_packed_docs/sdk/INDEX.md +5 -3
  7. package/dist/agent-md-changes.d.ts +42 -0
  8. package/dist/agent-md-changes.js +339 -0
  9. package/dist/agent-md-changes.js.map +1 -0
  10. package/dist/agent-md-schema.d.ts +1 -0
  11. package/dist/agent-md-schema.js +30 -13
  12. package/dist/agent-md-schema.js.map +1 -1
  13. package/dist/agent-md.d.ts +11 -0
  14. package/dist/agent-md.js +86 -15
  15. package/dist/agent-md.js.map +1 -1
  16. package/dist/aid-store.d.ts +11 -0
  17. package/dist/aid-store.js +102 -21
  18. package/dist/aid-store.js.map +1 -1
  19. package/dist/auth.d.ts +10 -0
  20. package/dist/auth.js +44 -4
  21. package/dist/auth.js.map +1 -1
  22. package/dist/client/control-messages.d.ts +31 -0
  23. package/dist/client/control-messages.js +474 -0
  24. package/dist/client/control-messages.js.map +1 -0
  25. package/dist/client/delivery.js +10 -2
  26. package/dist/client/delivery.js.map +1 -1
  27. package/dist/client/lifecycle.js +10 -0
  28. package/dist/client/lifecycle.js.map +1 -1
  29. package/dist/client/rpc-pipeline.js +76 -13
  30. package/dist/client/rpc-pipeline.js.map +1 -1
  31. package/dist/client/v2-e2ee.d.ts +3 -0
  32. package/dist/client/v2-e2ee.js +5 -0
  33. package/dist/client/v2-e2ee.js.map +1 -1
  34. package/dist/client.d.ts +26 -0
  35. package/dist/client.js +267 -7
  36. package/dist/client.js.map +1 -1
  37. package/dist/discovery.d.ts +3 -0
  38. package/dist/discovery.js +52 -2
  39. package/dist/discovery.js.map +1 -1
  40. package/dist/events.js +14 -1
  41. package/dist/events.js.map +1 -1
  42. package/dist/risk-control.d.ts +68 -0
  43. package/dist/risk-control.js +344 -0
  44. package/dist/risk-control.js.map +1 -0
  45. package/dist/storage/lowlevel.d.ts +1 -0
  46. package/dist/storage/lowlevel.js +2 -2
  47. package/dist/storage/lowlevel.js.map +1 -1
  48. package/dist/tools/cross-sdk-agent.d.ts +1 -1
  49. package/dist/transport.d.ts +21 -1
  50. package/dist/transport.js +199 -20
  51. package/dist/transport.js.map +1 -1
  52. package/dist/version.d.ts +1 -1
  53. package/dist/version.js +1 -1
  54. package/package.json +1 -1
  55. package/_packed_docs/cli//345/207/255/350/257/201/344/270/216/347/273/204/347/273/207/346/234/215/345/212/241CLI/345/274/200/345/217/221/344/270/216/344/275/277/347/224/250/346/214/207/345/215/227.md +0 -869
  56. package/_packed_docs/sdk/0.5.27-SDK/345/272/224/347/224/250/351/233/206/346/210/220/346/214/207/345/215/227.md +0 -408
  57. package/_packed_docs/sdk/0.5.27-SDK/345/274/200/345/217/221/344/270/216/347/247/273/346/244/215/346/214/207/345/215/227.md +0 -410
package/dist/transport.js CHANGED
@@ -14,6 +14,8 @@ import { AUNError, AuthError, CertificateRevokedError, ClientSignatureError, Con
14
14
  import { trafficLogContext, withLogContext } from './logger.js';
15
15
  import { isJsonObject } from './types.js';
16
16
  import { parseJsonStrict, validateOrgRequestJSON } from './org-protocol.js';
17
+ import { RiskController } from './risk-control.js';
18
+ import { messageClassOf } from './client/control-messages.js';
17
19
  const MAX_WS_PAYLOAD_SIZE = 1_000_000;
18
20
  const MAX_RPC_INFLIGHT = 16;
19
21
  const MAX_BACKGROUND_RPC_INFLIGHT = 8;
@@ -572,11 +574,17 @@ export class RPCTransport {
572
574
  _drainingRpcQueue = false;
573
575
  _onForegroundDrained;
574
576
  _onRpcResponse;
575
- _sendChain = Promise.resolve();
577
+ _sendQueue = [];
578
+ _sending = false;
579
+ _riskDeliveries = 0;
576
580
  _idCounter = 0;
577
581
  // Gateway 在 RPC envelope 注入 _meta 字段(与 result 同级),由 client 层 observer 接收。
578
582
  // observer 抛异常会被吞掉,不影响 RPC result 返回。
579
583
  _metaObserver = null;
584
+ _requestAdmission = null;
585
+ _requestCheck = null;
586
+ _riskControlHandler = null;
587
+ _classMessageHandler = null;
580
588
  _protocolMetaObserver = false;
581
589
  // Trace 模式:off / log / diag
582
590
  _traceMode = 'off';
@@ -829,6 +837,16 @@ export class RPCTransport {
829
837
  }
830
838
  if (this._workerGeneration === null || message.generation !== this._workerGeneration)
831
839
  return;
840
+ if (message.event === '_transport.risk_control') {
841
+ this._dispatchRiskControl(message.payload, () => message.generation === this._workerGeneration);
842
+ return;
843
+ }
844
+ if (message.event === '_transport.class_message') {
845
+ const value = message.payload;
846
+ if (value && typeof value.event === 'string')
847
+ this._routeClassMessage(value.event, value.payload);
848
+ return;
849
+ }
832
850
  if (message.event === '_transport.observer') {
833
851
  const item = message.payload;
834
852
  const observer = item?.kind?.includes('trace') ? this._traceObserver : this._metaObserver;
@@ -997,6 +1015,66 @@ export class RPCTransport {
997
1015
  this._metaObserver = observer;
998
1016
  this._protocolMetaObserver = false;
999
1017
  }
1018
+ setRequestAdmission(admission) { this._requestAdmission = admission; }
1019
+ setRequestCheck(check) { this._requestCheck = check; }
1020
+ setClassMessageHandler(handler) { this._classMessageHandler = handler; }
1021
+ _routeClassMessage(event, payload) {
1022
+ if (!['message.received', 'group.message_created'].includes(event) || !isJsonObject(payload))
1023
+ return false;
1024
+ const value = payload;
1025
+ const messageClass = messageClassOf(value);
1026
+ if (value.delivery_class === 'normal' && messageClass !== 'sdk_control')
1027
+ return false;
1028
+ if (messageClass === 'normal' && !(event === 'group.message_created' && (value.storage === 'volatile' || value.volatile === true)))
1029
+ return false;
1030
+ if (!isMainThread && Boolean(workerData?.aunTransportWorker) && parentPort) {
1031
+ parentPort.postMessage({ type: 'event', generation: this._connectionGeneration, event: '_transport.class_message', payload: { event, payload: value } });
1032
+ }
1033
+ else {
1034
+ try {
1035
+ this._classMessageHandler?.(event, value);
1036
+ }
1037
+ catch { /* 控制正文保持内部隔离 */ }
1038
+ }
1039
+ return true;
1040
+ }
1041
+ async setRiskSnapshot(state) {
1042
+ if (this._worker)
1043
+ await this._workerCommand({ type: 'risk_snapshot', riskState: state });
1044
+ }
1045
+ setRiskControlHandler(handler) {
1046
+ this._riskControlHandler = handler;
1047
+ }
1048
+ _finishRiskDelivery() {
1049
+ this._riskDeliveries = Math.max(0, this._riskDeliveries - 1);
1050
+ if (this._riskDeliveries === 0)
1051
+ this._startSendQueue();
1052
+ }
1053
+ _receiveRiskControl(payload) {
1054
+ if (!isJsonObject(payload))
1055
+ return;
1056
+ if (!isMainThread && Boolean(workerData?.aunTransportWorker) && parentPort) {
1057
+ this._riskDeliveries += 1;
1058
+ parentPort.postMessage({ type: 'event', generation: this._connectionGeneration, event: '_transport.risk_control', payload });
1059
+ }
1060
+ else {
1061
+ const generation = this._connectionGeneration;
1062
+ this._dispatchRiskControl(payload, () => generation === this._connectionGeneration);
1063
+ }
1064
+ }
1065
+ _dispatchRiskControl(payload, current) {
1066
+ const handler = this._riskControlHandler;
1067
+ this._riskDeliveries += 1;
1068
+ const value = structuredClone(payload);
1069
+ void Promise.resolve().then(() => {
1070
+ if (current() && handler && this._riskControlHandler === handler && isJsonObject(value))
1071
+ return handler(value);
1072
+ }).catch(() => { }).finally(() => {
1073
+ this._finishRiskDelivery();
1074
+ if (current() && this._worker)
1075
+ this._worker.postMessage({ type: 'risk_release', generation: this._workerGeneration ?? undefined });
1076
+ });
1077
+ }
1000
1078
  setProtocolMetaObserver(observer) {
1001
1079
  this._metaObserver = observer;
1002
1080
  this._protocolMetaObserver = true;
@@ -1453,6 +1531,8 @@ export class RPCTransport {
1453
1531
  this._handshakeAbort = null;
1454
1532
  abortHandshake?.();
1455
1533
  this._closed = true;
1534
+ this._riskDeliveries = 0;
1535
+ this._startSendQueue();
1456
1536
  this._connectionGeneration += 1;
1457
1537
  this._stopWebSocketHeartbeat();
1458
1538
  // 取消所有待处理的 RPC
@@ -1548,6 +1628,20 @@ export class RPCTransport {
1548
1628
  return Object.assign(result, { cancel: request.cancel });
1549
1629
  }
1550
1630
  _call(method, params, timeout, trace, background = false, onSent, sentCheckpoint) {
1631
+ if (!this._requestAdmission)
1632
+ return this._callAdmitted(method, params, timeout, trace, background, onSent, sentCheckpoint);
1633
+ let release;
1634
+ try {
1635
+ release = this._requestAdmission?.(`rpc:${method}`);
1636
+ const request = this._callAdmitted(method, params, timeout, trace, background, onSent, sentCheckpoint);
1637
+ return Object.assign(request.finally(() => release?.()), { cancel: request.cancel });
1638
+ }
1639
+ catch (error) {
1640
+ release?.();
1641
+ return Promise.reject(error);
1642
+ }
1643
+ }
1644
+ _callAdmitted(method, params, timeout, trace, background = false, onSent, sentCheckpoint) {
1551
1645
  if (this._worker) {
1552
1646
  const requestContext = trafficLogContext('outbound', params ?? {});
1553
1647
  const requestLog = withLogContext(this._logger, requestContext);
@@ -1680,6 +1774,7 @@ export class RPCTransport {
1680
1774
  tStart,
1681
1775
  timeoutMs: effectiveTimeout,
1682
1776
  background: backgroundRpc,
1777
+ priority: this._messagePriority(localParams.message_class),
1683
1778
  logger: requestLog,
1684
1779
  onSent,
1685
1780
  });
@@ -1693,6 +1788,7 @@ export class RPCTransport {
1693
1788
  tStart,
1694
1789
  timeoutMs: effectiveTimeout,
1695
1790
  background: true,
1791
+ priority: this._messagePriority(localParams.message_class),
1696
1792
  logger: requestLog,
1697
1793
  onSent,
1698
1794
  });
@@ -1703,6 +1799,15 @@ export class RPCTransport {
1703
1799
  }
1704
1800
  /** 发送 JSON-RPC 2.0 Notification,不分配 id,也不等待响应。 */
1705
1801
  async notify(method, params) {
1802
+ const release = this._requestAdmission?.(`rpc:${String(method).replace(/^(notification|event)\//, '')}`);
1803
+ try {
1804
+ await this._notifyAdmitted(method, params);
1805
+ }
1806
+ finally {
1807
+ release?.();
1808
+ }
1809
+ }
1810
+ async _notifyAdmitted(method, params) {
1706
1811
  if (this._worker) {
1707
1812
  await this._workerCommand({ type: 'notify', method, params });
1708
1813
  return;
@@ -1733,15 +1838,43 @@ export class RPCTransport {
1733
1838
  throw new ValidationError('payload is too large');
1734
1839
  }
1735
1840
  const notifyLog = withLogContext(this._logger, trafficLogContext('outbound', params ?? {}));
1736
- await this._sendText(payload, `notification ${normalizedMethod}`);
1841
+ await this._sendText(payload, `notification ${normalizedMethod}`, () => { this._requestCheck?.(`rpc:${normalizedMethod.replace(/^(notification|event)\//, '')}`); return true; }, this._messagePriority(params?.message_class));
1737
1842
  notifyLog.debug(`notification sent: method=${normalizedMethod}, size=${payloadSize}`);
1738
1843
  }
1739
- _enqueueSend(task) {
1740
- const run = this._sendChain.then(task, task);
1741
- this._sendChain = run.catch(() => { });
1742
- return run;
1844
+ _messagePriority(messageClass) { return messageClass === 'sdk_control' ? 2 : messageClass === 'control' ? 1 : 0; }
1845
+ _isRiskControlMethod(method) { return ['gateway.risk_ack', 'meta.ping', 'system.ping', 'ping', 'auth.disconnect', 'gateway.risk_status'].includes(method); }
1846
+ _enqueueSend(task, priority = 0) {
1847
+ const result = new Promise((resolve, reject) => { this._sendQueue.push({ task, priority, resolve, reject }); });
1848
+ this._startSendQueue();
1849
+ return result;
1850
+ }
1851
+ _startSendQueue() {
1852
+ if (this._sending)
1853
+ return;
1854
+ this._sending = true;
1855
+ void Promise.resolve().then(async () => {
1856
+ try {
1857
+ while (this._sendQueue.length) {
1858
+ this._sendQueue.sort((left, right) => right.priority - left.priority);
1859
+ const index = this._riskDeliveries > 0 ? this._sendQueue.findIndex(entry => entry.priority === 3) : 0;
1860
+ if (index < 0)
1861
+ break;
1862
+ const entry = this._sendQueue.splice(index, 1)[0];
1863
+ try {
1864
+ await entry.task();
1865
+ entry.resolve();
1866
+ }
1867
+ catch (error) {
1868
+ entry.reject(error);
1869
+ }
1870
+ }
1871
+ }
1872
+ finally {
1873
+ this._sending = false;
1874
+ }
1875
+ });
1743
1876
  }
1744
- _sendText(payload, context, beforeSend) {
1877
+ _sendText(payload, context, beforeSend, priority = 0) {
1745
1878
  return this._enqueueSend(async () => {
1746
1879
  if (beforeSend && !beforeSend()) {
1747
1880
  throw new ConnectionError(`send cancelled before write: ${context}`);
@@ -1767,7 +1900,7 @@ export class RPCTransport {
1767
1900
  this._sendFailureError(context, err, ws).then(reject, reject);
1768
1901
  }
1769
1902
  });
1770
- });
1903
+ }, priority);
1771
1904
  }
1772
1905
  async _sendFailureError(context, err, ws) {
1773
1906
  const original = err instanceof Error ? err.message : String(err);
@@ -1839,19 +1972,29 @@ export class RPCTransport {
1839
1972
  this._drainingRpcQueue = true;
1840
1973
  let foregroundDrained = false;
1841
1974
  try {
1842
- while (!this._closed && this._ws && this._pending.size < MAX_RPC_INFLIGHT) {
1975
+ while (!this._closed && this._ws) {
1976
+ const controlOnly = this._pending.size >= MAX_RPC_INFLIGHT;
1977
+ if (controlOnly && (!this._rpcQueue.some(entry => this._isRiskControlMethod(entry.method)) || Array.from(this._pendingMeta.values()).filter(entry => this._isRiskControlMethod(entry.method)).length >= 4))
1978
+ break;
1843
1979
  let entry;
1844
- if (this._rpcQueue.length > 0) {
1845
- entry = this._rpcQueue.shift();
1846
- if (this._rpcQueue.length === 0)
1847
- foregroundDrained = true;
1848
- }
1849
- else if (this._backgroundRpcQueue.length > 0 && this._pendingBackground.size < MAX_BACKGROUND_RPC_INFLIGHT) {
1850
- entry = this._backgroundRpcQueue.shift();
1980
+ let selectedQueue;
1981
+ let selectedIndex = -1;
1982
+ for (const queue of [this._rpcQueue, ...(this._pendingBackground.size < MAX_BACKGROUND_RPC_INFLIGHT ? [this._backgroundRpcQueue] : [])]) {
1983
+ for (let index = 0; index < queue.length; index++) {
1984
+ if (controlOnly && !this._isRiskControlMethod(queue[index].method))
1985
+ continue;
1986
+ if (!entry || queue[index].priority > entry.priority) {
1987
+ entry = queue[index];
1988
+ selectedQueue = queue;
1989
+ selectedIndex = index;
1990
+ }
1991
+ }
1851
1992
  }
1852
- else {
1993
+ if (!entry || !selectedQueue)
1853
1994
  break;
1854
- }
1995
+ selectedQueue.splice(selectedIndex, 1);
1996
+ if (selectedQueue === this._rpcQueue && this._rpcQueue.length === 0)
1997
+ foregroundDrained = true;
1855
1998
  const elapsed = Date.now() - entry.tStart;
1856
1999
  if (elapsed >= entry.timeoutMs) {
1857
2000
  clearTimeout(entry.pending.timer);
@@ -1870,7 +2013,12 @@ export class RPCTransport {
1870
2013
  if (entry.background) {
1871
2014
  this._pendingBackground.add(entry.rpcId);
1872
2015
  }
1873
- this._sendText(entry.payload, `rpc ${entry.method}`, () => this._pending.get(entry.rpcId) === entry.pending).then(() => {
2016
+ this._sendText(entry.payload, `rpc ${entry.method}`, () => {
2017
+ if (this._pending.get(entry.rpcId) !== entry.pending)
2018
+ return false;
2019
+ this._requestCheck?.(`rpc:${entry.method}`);
2020
+ return true;
2021
+ }, this._isRiskControlMethod(entry.method) ? 3 : entry.priority).then(() => {
1874
2022
  entry.logger.debug(`RPC request sent: method=${entry.method}, id=${entry.rpcId}, background=${entry.background}`);
1875
2023
  return entry.onSent?.();
1876
2024
  }).catch((err) => {
@@ -1878,7 +2026,7 @@ export class RPCTransport {
1878
2026
  return;
1879
2027
  this._removeRpc(entry.rpcId, entry.pending);
1880
2028
  entry.logger.error(`RPC send failed: method=${entry.method}, id=${entry.rpcId}, error=${err instanceof Error ? err.message : String(err)}`);
1881
- entry.pending.reject(err instanceof ConnectionError
2029
+ entry.pending.reject(err instanceof ConnectionError || err instanceof StateError
1882
2030
  ? err
1883
2031
  : new ConnectionError(`failed to send rpc ${entry.method}: ${err instanceof Error ? err.message : String(err)}`));
1884
2032
  this._drainRpcQueue();
@@ -2073,6 +2221,14 @@ export class RPCTransport {
2073
2221
  this._logger.debug(`_routeMessage enter: has_id=${hasId}, method=${methodStr || '<none>'}`);
2074
2222
  // RPC 响应(有 id 字段)
2075
2223
  if ('id' in message) {
2224
+ const error = message.error;
2225
+ if (isJsonObject(error) && isJsonObject(error.data) && isJsonObject(error.data.risk_state)) {
2226
+ const states = error.data.risk_state.states;
2227
+ if (Array.isArray(states))
2228
+ for (const state of states)
2229
+ this._receiveRiskControl(state);
2230
+ delete error.data.risk_state;
2231
+ }
2076
2232
  const rpcId = String(message.id);
2077
2233
  const pending = this._pending.get(rpcId);
2078
2234
  if (pending) {
@@ -2086,6 +2242,10 @@ export class RPCTransport {
2086
2242
  return;
2087
2243
  }
2088
2244
  const method = String(message.method ?? '');
2245
+ if (method === 'event/gateway.risk_control' || method === 'gateway.risk_control') {
2246
+ this._receiveRiskControl(message.params);
2247
+ return;
2248
+ }
2089
2249
  // Challenge 消息
2090
2250
  if (method === 'challenge') {
2091
2251
  this._challenge = message;
@@ -2127,6 +2287,8 @@ export class RPCTransport {
2127
2287
  eventLog.info(`[trace=${String(traceObj.trace_id ?? '')}] event_recv event=${sdkEvent}`);
2128
2288
  }
2129
2289
  }
2290
+ if (this._routeClassMessage(sdkEvent, params))
2291
+ return;
2130
2292
  // 发布为 _raw.{event},由 AUNClient 处理后再发布用户可见的事件
2131
2293
  if (sdkEvent.startsWith('app.') || sdkEvent.startsWith('org.member.') || sdkEvent.startsWith('org.lifecycle.')) {
2132
2294
  this._dispatcher.enqueue(sdkEvent, params);
@@ -2238,6 +2400,8 @@ if (!isMainThread && Boolean(workerData?.aunTransportWorker) && parentPort) {
2238
2400
  onDisconnect: () => { },
2239
2401
  });
2240
2402
  workerActor = actor;
2403
+ const riskGate = new RiskController();
2404
+ actor.setRequestCheck((request) => riskGate.check(request));
2241
2405
  actor._onForegroundDrained = () => parentPort.postMessage({
2242
2406
  type: 'foreground_drained', generation: bridgeGeneration(),
2243
2407
  });
@@ -2260,6 +2424,11 @@ if (!isMainThread && Boolean(workerData?.aunTransportWorker) && parentPort) {
2260
2424
  parentPort.on('message', async (command) => {
2261
2425
  const id = command.id;
2262
2426
  try {
2427
+ if (command.type === 'risk_release') {
2428
+ if (command.generation === bridgeGeneration())
2429
+ actor['_finishRiskDelivery']();
2430
+ return;
2431
+ }
2263
2432
  if (command.type === 'cancel') {
2264
2433
  const pending = active.get(String(command.targetId ?? ''));
2265
2434
  pending?.cancel?.();
@@ -2267,6 +2436,16 @@ if (!isMainThread && Boolean(workerData?.aunTransportWorker) && parentPort) {
2267
2436
  }
2268
2437
  let result;
2269
2438
  switch (command.type) {
2439
+ case 'risk_snapshot': {
2440
+ const state = command.riskState;
2441
+ const target = state.target;
2442
+ const [keyId, key] = Object.entries(state.signing_keys)[0] ?? [];
2443
+ riskGate.configure({ aid: String(target.aid), device_id: String(target.device_id ?? ''), slot_id: String(target.slot_id ?? ''), connection_id: String(target.connection_id ?? '') }, { key_id: keyId, public_key: Buffer.from(key).toString('base64url'), algorithm: 'ECDSA-P256-SHA256' }, Number(state.server_time_ms));
2444
+ await riskGate.restore(state);
2445
+ riskGate.close();
2446
+ result = null;
2447
+ break;
2448
+ }
2270
2449
  case 'connect': {
2271
2450
  dnsFallback = command.dnsFallback ?? null;
2272
2451
  const request = actor.connect(String(command.url ?? ''));