@agentunion/fastaun 0.4.4 → 0.4.5

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 (41) hide show
  1. package/CHANGELOG.md +15 -0
  2. package/_packed_docs/CHANGELOG.md +15 -0
  3. package/_packed_docs/sdk/01-/345/277/253/351/200/237/345/274/200/345/247/213.md +1 -1
  4. package/_packed_docs/sdk/05-E2EE/345/212/240/345/257/206/351/200/232/344/277/241.md +1 -1
  5. package/dist/aid-store.d.ts +1 -0
  6. package/dist/aid-store.js +26 -3
  7. package/dist/aid-store.js.map +1 -1
  8. package/dist/auth.d.ts +17 -32
  9. package/dist/auth.js +42 -295
  10. package/dist/auth.js.map +1 -1
  11. package/dist/client.d.ts +4 -3
  12. package/dist/client.js +77 -92
  13. package/dist/client.js.map +1 -1
  14. package/dist/index.d.ts +1 -0
  15. package/dist/index.js +1 -0
  16. package/dist/index.js.map +1 -1
  17. package/dist/keystore/aid-db.d.ts +0 -4
  18. package/dist/keystore/aid-db.js +4 -95
  19. package/dist/keystore/aid-db.js.map +1 -1
  20. package/dist/keystore/file.d.ts +8 -3
  21. package/dist/keystore/file.js +103 -24
  22. package/dist/keystore/file.js.map +1 -1
  23. package/dist/keystore/index.d.ts +39 -36
  24. package/dist/keystore/index.js +3 -2
  25. package/dist/keystore/index.js.map +1 -1
  26. package/dist/register-flow.d.ts +49 -0
  27. package/dist/register-flow.js +366 -0
  28. package/dist/register-flow.js.map +1 -0
  29. package/dist/secret-store/file-store.js +6 -1
  30. package/dist/secret-store/file-store.js.map +1 -1
  31. package/dist/v2/session/keystore.d.ts +5 -0
  32. package/dist/v2/session/keystore.js +21 -3
  33. package/dist/v2/session/keystore.js.map +1 -1
  34. package/dist/version.d.ts +1 -1
  35. package/dist/version.js +1 -1
  36. package/package.json +1 -1
  37. package/_packed_docs/0.4.0_/345/267/256/345/274/202/346/240/270/345/256/236/345/206/263/347/255/226/350/256/260/345/275/225.md +0 -302
  38. package/_packed_docs/AUN_SDK_0.4.0_/350/256/276/350/256/241/345/257/271/346/257/224/345/210/206/346/236/220.md +0 -194
  39. package/_packed_docs/AUN_SDK_/351/207/215/346/236/204/345/256/236/346/226/275/350/256/241/345/210/222.md +0 -596
  40. 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 +0 -1698
  41. package/_packed_docs/python-sdk-v2-only-changelog.md +0 -189
package/dist/auth.js CHANGED
@@ -17,7 +17,7 @@ import * as https from 'node:https';
17
17
  import * as path from 'node:path';
18
18
  import { URL, fileURLToPath } from 'node:url';
19
19
  import WebSocket from 'ws';
20
- import { AuthError, StateError, ValidationError, IdentityConflictError, mapRemoteError } from './errors.js';
20
+ import { AuthError, StateError, ValidationError, mapRemoteError } from './errors.js';
21
21
  import { isJsonObject, } from './types.js';
22
22
  import { VERSION as AUN_SDK_VERSION } from './version.js';
23
23
  const _noopLogger = {
@@ -236,7 +236,7 @@ export class AuthFlow {
236
236
  'access_token_expires_at',
237
237
  ];
238
238
  _logger;
239
- _keystore;
239
+ _tokenStore;
240
240
  _crypto;
241
241
  _aid;
242
242
  _deviceId;
@@ -258,9 +258,11 @@ export class AuthFlow {
258
258
  _chainVerifiedCache = new Map();
259
259
  // Gateway CA 链预验证标记:cache_key -> verified
260
260
  _gatewayCaVerified = new Map();
261
+ // 调用方注入的内存私钥(由 AUNClient.loadIdentity 传入,不走 tokenStore 解密)
262
+ _memIdentity = null;
261
263
  constructor(opts) {
262
264
  this._logger = opts.logger ?? _noopLogger;
263
- this._keystore = opts.keystore;
265
+ this._tokenStore = opts.tokenStore;
264
266
  this._crypto = opts.crypto;
265
267
  this._aid = opts.aid ?? null;
266
268
  this._deviceId = String(opts.deviceId ?? '').trim();
@@ -273,10 +275,19 @@ export class AuthFlow {
273
275
  this._rootCerts = this._loadRootCerts(this._rootCaPath);
274
276
  }
275
277
  // ── 公开方法 ────────────────────────────────────────────────
278
+ /**
279
+ * 注入内存私钥(由 AUNClient.loadIdentity 调用)。
280
+ * AuthFlow 内部不再从 tokenStore 解密私钥,只使用此处注入的明文。
281
+ */
282
+ setIdentity(identity) {
283
+ this._memIdentity = identity;
284
+ if (identity?.aid)
285
+ this._aid = String(identity.aid);
286
+ }
276
287
  /** 加载身份信息(密钥对 + 证书 + 元数据) */
277
288
  loadIdentity(aid) {
278
289
  const identity = this._loadIdentityOrRaise(aid);
279
- const cert = this._keystore.loadCert(String(identity.aid));
290
+ const cert = this._tokenStore.loadCert(String(identity.aid));
280
291
  if (cert)
281
292
  identity.cert = cert;
282
293
  const instanceState = this._loadInstanceState(String(identity.aid));
@@ -317,235 +328,6 @@ export class AuthFlow {
317
328
  this._deviceId = String(opts.deviceId ?? '').trim();
318
329
  this._slotId = String(opts.slotId ?? '').trim();
319
330
  }
320
- /**
321
- * 注册新 AID(原子流程,必须由应用层显式调用)。
322
- *
323
- * 安全约束(与 Python register_aid 对齐):
324
- * - **绝不**被 SDK 内部任何路径自动调用(authenticate / connect / 等)
325
- * - 本地已有任何痕迹 → 抛 IdentityConflictError,应用层应改用 loadIdentity
326
- * - 服务端已注册同名 AID → 抛 IdentityConflictError
327
- *
328
- * 异常分支与恢复:
329
- * A. 全新流程:临时目录生成 keypair → RPC → cert → 原子 rename
330
- * B. 恢复流程:上次 RPC 没收到响应就崩溃;扫描 _pending,公钥匹配
331
- * 则下载 cert 完成 promote(防止"已注册但本地没保存")
332
- */
333
- async registerAid(gatewayUrl, aid) {
334
- const tStart = Date.now();
335
- AuthFlow._validateAidName(aid);
336
- this._logger.debug(`registerAid enter: aid=${aid}, gateway=${gatewayUrl}`);
337
- try {
338
- // Step 1: 本地完整身份的幂等处理
339
- // - 服务端 cert 公钥匹配 → 视为已注册成功,幂等返回
340
- // - 服务端 cert 公钥不匹配 → IdentityConflictError(被别人占)
341
- // - 服务端无记录 → IdentityConflictError(要求清理本地)
342
- const existing = this._keystore.loadIdentity(aid);
343
- if (existing !== null && existing.public_key_der_b64) {
344
- this._logger.debug(`registerAid: local keypair exists, checking server for idempotency: aid=${aid}`);
345
- const localPubB64 = String(existing.public_key_der_b64);
346
- const serverCertPem = await this._downloadRegisteredCert(gatewayUrl, aid);
347
- if (!serverCertPem) {
348
- // 服务端无记录 → 用现有 keypair 发起注册
349
- this._logger.debug(`registerAid: server has no record, registering with existing keypair: aid=${aid}`);
350
- const pendingDir = this._keystore.pendingIdentityDir?.(aid);
351
- let created;
352
- try {
353
- created = await this._createAid(gatewayUrl, existing);
354
- }
355
- catch (e) {
356
- this._logger.warn(`registerAid RPC failed (existing keypair): aid=${aid}, error=${e instanceof Error ? e.message : String(e)}`);
357
- throw e;
358
- }
359
- const certPem = String(created.cert ?? '');
360
- if (!certPem) {
361
- throw new AuthError(`registerAid: server response missing cert for ${aid}`);
362
- }
363
- existing.cert = certPem;
364
- this._assertCertMatchesLocalKeypair(existing);
365
- this._persistIdentity(existing);
366
- this._aid = aid;
367
- this._logger.debug(`registerAid exit (recovered): elapsed=${Date.now() - tStart}ms aid=${aid}`);
368
- return { aid, cert: certPem };
369
- }
370
- // 比对公钥
371
- const cert = _loadX509(serverCertPem);
372
- const serverPubDer = _extractPublicKey(cert).export({ type: 'spki', format: 'der' });
373
- const localPubDer = Buffer.from(localPubB64, 'base64');
374
- if (!serverPubDer.equals(localPubDer)) {
375
- throw new IdentityConflictError(`AID '${aid}' is registered by another party on server (public key mismatch). ` +
376
- `Choose a different name.`);
377
- }
378
- // 公钥匹配 → 幂等返回;如本地缺 cert,把服务端 cert 写入
379
- this._logger.info(`registerAid: idempotent return for already-registered AID: aid=${aid}`);
380
- if (!existing.cert) {
381
- existing.cert = serverCertPem;
382
- this._persistIdentity(existing);
383
- }
384
- this._aid = aid;
385
- return { aid, cert: serverCertPem };
386
- }
387
- // Step 2: 检查 _pending/ 残留临时目录(崩溃恢复)
388
- const recovered = await this._tryRecoverPendingRegistration(gatewayUrl, aid);
389
- if (recovered !== null) {
390
- this._logger.info(`registerAid recovered from pending: aid=${aid}`);
391
- return recovered;
392
- }
393
- // Step 3: 服务端查重
394
- const existingCert = await this._downloadRegisteredCert(gatewayUrl, aid);
395
- if (existingCert) {
396
- this._logger.warn(`registerAid aborted: AID already registered on server: aid=${aid}`);
397
- throw new IdentityConflictError(`AID '${aid}' is already registered on server. Choose a different name, or if you own the keypair use a recovery flow.`);
398
- }
399
- // Step 4: 创建临时目录 + 生成 keypair + 写 priv
400
- const identity = this._crypto.generateIdentity();
401
- identity.aid = aid;
402
- const pendingDir = this._keystore.pendingIdentityDir(aid);
403
- this._writePendingKeypair(pendingDir, identity);
404
- // Step 5: 服务端注册拿 cert
405
- let created;
406
- try {
407
- created = await this._createAid(gatewayUrl, identity);
408
- }
409
- catch (e) {
410
- this._logger.warn(`registerAid RPC failed (pending kept for recovery): aid=${aid}, pending=${pendingDir}, error=${e instanceof Error ? e.message : String(e)}`);
411
- throw e;
412
- }
413
- const certPem = String(created.cert ?? '');
414
- if (!certPem) {
415
- throw new AuthError(`registerAid: server response missing cert for ${aid}`);
416
- }
417
- identity.cert = certPem;
418
- // Step 6: 校验 cert 公钥 == 本地公钥
419
- this._assertCertMatchesLocalKeypair(identity);
420
- // Step 7: 写 cert.pem 到临时目录
421
- this._writePendingCert(pendingDir, certPem);
422
- // Step 8: 原子 rename
423
- try {
424
- this._keystore.promotePendingIdentity(pendingDir, aid);
425
- }
426
- catch (e) {
427
- this._logger.warn(`registerAid promote failed: aid=${aid}, error=${e instanceof Error ? e.message : String(e)}`);
428
- throw new IdentityConflictError(`AID '${aid}' was created by another process during registration; pending dir kept for cleanup.`);
429
- }
430
- // Step 9: 标准持久化
431
- this._persistIdentity(identity);
432
- this._aid = aid;
433
- this._logger.debug(`registerAid exit: elapsed=${Date.now() - tStart}ms aid=${aid}`);
434
- return { aid: identity.aid, cert: identity.cert };
435
- }
436
- catch (err) {
437
- this._logger.debug(`registerAid exit (error): elapsed=${Date.now() - tStart}ms err=${err instanceof Error ? err.message : String(err)}`);
438
- throw err;
439
- }
440
- }
441
- /**
442
- * 检查 AIDs/_pending/ 下是否有该 aid 的残留,尝试恢复(崩溃恢复)。
443
- * 返回 dict 表示恢复成功;null 表示无残留 / 残留已清理;抛错表示明确失败。
444
- */
445
- async _tryRecoverPendingRegistration(gatewayUrl, aid) {
446
- const aidsRoot = this._keystore._aidsRoot;
447
- const pendingRoot = path.join(aidsRoot, '_pending');
448
- if (!fs.existsSync(pendingRoot))
449
- return null;
450
- const safe = this._keystore.constructor === undefined ? aid : aid;
451
- const safeAid = aid.replace(/\//g, '_').replace(/\\/g, '_').replace(/:/g, '_');
452
- const prefix = safeAid + '-';
453
- const candidates = fs.readdirSync(pendingRoot, { withFileTypes: true })
454
- .filter((e) => e.isDirectory() && e.name.startsWith(prefix))
455
- .map((e) => path.join(pendingRoot, e.name))
456
- .sort((a, b) => fs.statSync(b).mtimeMs - fs.statSync(a).mtimeMs);
457
- if (candidates.length === 0)
458
- return null;
459
- for (const pendingDir of candidates) {
460
- const privPath = path.join(pendingDir, 'private', 'key.json');
461
- if (!fs.existsSync(privPath)) {
462
- try {
463
- fs.rmSync(pendingDir, { recursive: true, force: true });
464
- }
465
- catch { /* ignore */ }
466
- continue;
467
- }
468
- let privData;
469
- try {
470
- privData = JSON.parse(fs.readFileSync(privPath, 'utf-8'));
471
- }
472
- catch {
473
- try {
474
- fs.rmSync(pendingDir, { recursive: true, force: true });
475
- }
476
- catch { /* ignore */ }
477
- continue;
478
- }
479
- const localPriv = privData.private_key_pem ?? '';
480
- const localPubB64 = privData.public_key_der_b64 ?? '';
481
- if (!localPriv || !localPubB64) {
482
- try {
483
- fs.rmSync(pendingDir, { recursive: true, force: true });
484
- }
485
- catch { /* ignore */ }
486
- continue;
487
- }
488
- const serverCert = await this._downloadRegisteredCert(gatewayUrl, aid);
489
- if (!serverCert) {
490
- // 上次 RPC 没生效 → 清理临时目录,由调用方走全新注册流程
491
- this._logger.info(`pending dir found but server has no registration; cleaning up: ${pendingDir}`);
492
- try {
493
- fs.rmSync(pendingDir, { recursive: true, force: true });
494
- }
495
- catch { /* ignore */ }
496
- return null;
497
- }
498
- // 比对公钥
499
- const cert = _loadX509(serverCert);
500
- const certPubKey = _extractPublicKey(cert);
501
- const certPubDer = certPubKey.export({ type: 'spki', format: 'der' });
502
- const localPubDer = Buffer.from(localPubB64, 'base64');
503
- if (!certPubDer.equals(localPubDer)) {
504
- this._logger.warn(`pending dir public key does not match server cert; AID '${aid}' was taken`);
505
- try {
506
- fs.rmSync(pendingDir, { recursive: true, force: true });
507
- }
508
- catch { /* ignore */ }
509
- throw new IdentityConflictError(`AID '${aid}' has been registered by another party while local pending registration was incomplete; local pending key discarded.`);
510
- }
511
- // 公钥匹配 → 上次 RPC 成功,补 cert + promote
512
- this._logger.info(`pending recovery: cert public key matches; finalizing registration: aid=${aid}`);
513
- this._writePendingCert(pendingDir, serverCert);
514
- const identity = {
515
- aid,
516
- private_key_pem: localPriv,
517
- public_key_der_b64: localPubB64,
518
- curve: privData.curve ?? 'P-256',
519
- cert: serverCert,
520
- };
521
- try {
522
- this._keystore.promotePendingIdentity(pendingDir, aid);
523
- }
524
- catch (e) {
525
- throw new IdentityConflictError(`AID '${aid}' was created by another process during recovery; pending dir kept for cleanup.`);
526
- }
527
- this._persistIdentity(identity);
528
- this._aid = aid;
529
- return { aid, cert: serverCert };
530
- }
531
- return null;
532
- }
533
- _writePendingKeypair(pendingDir, identity) {
534
- const priv = String(identity.private_key_pem ?? '');
535
- const pub = String(identity.public_key_der_b64 ?? '');
536
- const curve = String(identity.curve ?? 'P-256');
537
- if (!priv || !pub) {
538
- throw new AuthError('registerAid: generated identity missing keypair fields');
539
- }
540
- const dir = path.join(pendingDir, 'private');
541
- fs.mkdirSync(dir, { recursive: true });
542
- fs.writeFileSync(path.join(dir, 'key.json'), JSON.stringify({ private_key_pem: priv, public_key_der_b64: pub, curve }, null, 2), { encoding: 'utf-8', mode: 0o600 });
543
- }
544
- _writePendingCert(pendingDir, certPem) {
545
- const dir = path.join(pendingDir, 'public');
546
- fs.mkdirSync(dir, { recursive: true });
547
- fs.writeFileSync(path.join(dir, 'cert.pem'), certPem, { encoding: 'utf-8', mode: 0o600 });
548
- }
549
331
  /**
550
332
  * 认证(登录)到 Gateway。
551
333
  * 执行两阶段挑战-应答认证,返回 token 信息。
@@ -555,7 +337,7 @@ export class AuthFlow {
555
337
  let identity = this._loadIdentityOrRaise(opts?.aid);
556
338
  this._logger.debug(`authenticate enter: aid=${identity.aid}, gateway=${gatewayUrl}`);
557
339
  try {
558
- // 优先复用 keystore 里的 cached access_token(未过期且有 refresh_token)
340
+ // 优先复用 tokenStore 里的 cached access_token(未过期且有 refresh_token)
559
341
  // 避免每次调 authenticate 都走两阶段重登的网络往返
560
342
  // 注意:_loadIdentityOrRaise 不带 instance_state(access_token 等),
561
343
  // 这里需要主动走 _loadInstanceState 拿到 token
@@ -976,15 +758,6 @@ export class AuthFlow {
976
758
  });
977
759
  }
978
760
  // ── 内部方法:认证流程 ──────────────────────────────────────
979
- /** 注册 AID 到 Gateway */
980
- async _createAid(gatewayUrl, identity) {
981
- const response = await this._shortRpc(gatewayUrl, 'auth.create_aid', {
982
- aid: identity.aid,
983
- public_key: identity.public_key_der_b64,
984
- curve: identity.curve || 'P-256',
985
- });
986
- return { cert: response.cert };
987
- }
988
761
  /** 两阶段登录 */
989
762
  async _login(gatewayUrl, identity) {
990
763
  const tStart = Date.now();
@@ -1969,51 +1742,36 @@ export class AuthFlow {
1969
1742
  }
1970
1743
  // (_ensureLocalIdentity 已硬移除:注册和登录彻底分离,登录路径绝不再
1971
1744
  // 隐式生成密钥;新身份必须由应用层显式调 registerAid)
1972
- /** 加载身份信息,不存在或半成品时抛出 StateError */
1745
+ /** 加载身份信息,不存在或半成品时抛出 StateError
1746
+ * 优先使用调用方注入的内存私钥(_memIdentity),不从 tokenStore 解密私钥。
1747
+ */
1973
1748
  _loadIdentityOrRaise(aid) {
1974
1749
  const requestedAid = aid ?? this._aid;
1975
- if (requestedAid) {
1976
- const existing = this._keystore.loadIdentity(requestedAid);
1977
- if (existing === null) {
1978
- throw new StateError(`identity not found for aid: ${requestedAid}`);
1979
- }
1980
- // 防线 A:拒绝半成品 identity(缺 keypair 任一字段)。
1981
- // 这是上次 registerAid 半完成 / keystore 损坏的常见症状;如果让它流到
1982
- // _login,签名一定失败,且服务端可能记录一次无效登录尝试。
1983
- if (!existing.private_key_pem || !existing.public_key_der_b64) {
1984
- throw new StateError(`local identity for aid ${requestedAid} is incomplete (missing keypair); ` +
1985
- `call auth.registerAid() first`);
1750
+ // 优先路径:使用注入的内存 identity(私钥已由 AIDStore 解密并传入)
1751
+ if (this._memIdentity) {
1752
+ const mem = this._memIdentity;
1753
+ if (requestedAid && String(mem.aid ?? '') !== requestedAid) {
1754
+ throw new StateError(`identity mismatch: requested ${requestedAid}, loaded ${mem.aid}`);
1986
1755
  }
1987
- this._aid = requestedAid;
1988
- if (!existing.aid)
1989
- existing.aid = requestedAid;
1990
- return existing;
1991
- }
1992
- // 尝试加载任意身份
1993
- const ks = this._keystore;
1994
- if (typeof ks.loadAnyIdentity === 'function') {
1995
- const existing = ks.loadAnyIdentity();
1996
- if (existing !== null && existing !== undefined) {
1997
- if (!existing.private_key_pem || !existing.public_key_der_b64) {
1998
- throw new StateError(`local identity is incomplete (missing keypair); call auth.registerAid() first`);
1999
- }
2000
- const loadedAid = existing.aid;
2001
- if (typeof loadedAid === 'string' && loadedAid) {
2002
- this._aid = loadedAid;
2003
- }
2004
- return existing;
1756
+ if (!mem.private_key_pem || !mem.public_key_der_b64) {
1757
+ throw new StateError(`injected identity for aid ${mem.aid} is incomplete (missing keypair)`);
2005
1758
  }
1759
+ if (requestedAid)
1760
+ this._aid = requestedAid;
1761
+ return { ...mem };
1762
+ }
1763
+ if (requestedAid) {
1764
+ throw new StateError(`no injected identity for aid ${requestedAid}; call AUNClient.loadIdentity(aid) first`);
2006
1765
  }
2007
- throw new StateError('no local identity found, call auth.registerAid() first');
1766
+ throw new StateError('no local identity found, call AUNClient.loadIdentity(aid) first');
2008
1767
  }
2009
1768
  // (_ensureIdentity 已硬移除:注册和登录彻底分离,登录路径绝不再隐式
2010
1769
  // 生成密钥;调用方应改用 _loadIdentityOrRaise 获取已注册身份)
2011
1770
  _loadInstanceState(aid) {
2012
- const loader = this._keystore.loadInstanceState;
2013
- if (typeof loader !== 'function') {
1771
+ if (typeof this._tokenStore.loadInstanceState !== 'function') {
2014
1772
  return null;
2015
1773
  }
2016
- return loader.call(this._keystore, aid, this._deviceId, this._slotId);
1774
+ return this._tokenStore.loadInstanceState(aid, this._deviceId, this._slotId);
2017
1775
  }
2018
1776
  _persistIdentity(identity) {
2019
1777
  const aid = String(identity.aid ?? '');
@@ -2028,27 +1786,16 @@ export class AuthFlow {
2028
1786
  delete persisted[key];
2029
1787
  }
2030
1788
  }
2031
- // 私钥由 AIDStore 管理,AUNClient 不写 key.json
2032
- for (const key of ['private_key_pem', 'public_key_der_b64', 'curve']) {
2033
- delete persisted[key];
2034
- }
2035
- this._keystore.saveIdentity(aid, persisted);
2036
- // 从共享 metadata_kv 中移除实例级字段(它们已保存到 instance_state)
2037
- const db = this._keystore._getDB?.(aid);
2038
- if (db && typeof db.deleteMetadata === 'function') {
2039
- for (const key of AuthFlow._INSTANCE_STATE_FIELDS) {
2040
- db.deleteMetadata(key);
2041
- db.deleteMetadata(`${key}_protection`);
2042
- }
2043
- }
2044
- if (Object.keys(instanceState).length === 0) {
2045
- return;
1789
+ delete persisted.private_key_pem;
1790
+ delete persisted.public_key_der_b64;
1791
+ delete persisted.curve;
1792
+ if (typeof persisted.cert === 'string' && persisted.cert) {
1793
+ this._tokenStore.saveCert(aid, persisted.cert);
2046
1794
  }
2047
- const updater = this._keystore.updateInstanceState;
2048
- if (typeof updater !== 'function') {
1795
+ if (Object.keys(instanceState).length === 0 || typeof this._tokenStore.updateInstanceState !== 'function') {
2049
1796
  return;
2050
1797
  }
2051
- updater.call(this._keystore, aid, this._deviceId, this._slotId, (current) => {
1798
+ this._tokenStore.updateInstanceState(aid, this._deviceId, this._slotId, (current) => {
2052
1799
  Object.assign(current, instanceState);
2053
1800
  return current;
2054
1801
  });