@agentunion/fastaun 0.5.32 → 0.5.34
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 +58 -0
- package/README.md +28 -26
- package/_packed_docs/CHANGELOG.md +58 -0
- package/_packed_docs/INDEX.md +17 -3
- package/_packed_docs/KITE_DOCS_GUIDE.md +10 -4
- package/_packed_docs/protocol/03-Gateway-/350/277/236/346/216/245/346/250/241/345/274/217.md +58 -8
- package/_packed_docs/sdk/0.5.33-SDK/345/272/224/347/224/250/351/233/206/346/210/220/346/214/207/345/215/227.md +464 -0
- package/_packed_docs/sdk/0.5.33-SDK/345/274/200/345/217/221/344/270/216/347/247/273/346/244/215/346/214/207/345/215/227.md +499 -0
- package/_packed_docs/sdk/0.5.34-SDK/345/272/224/347/224/250/351/233/206/346/210/220/346/214/207/345/215/227.md +133 -0
- package/_packed_docs/sdk/0.5.34-SDK/345/274/200/345/217/221/344/270/216/347/247/273/346/244/215/346/214/207/345/215/227.md +107 -0
- package/_packed_docs/sdk/01-/345/277/253/351/200/237/345/274/200/345/247/213.md +16 -13
- package/_packed_docs/sdk/03-/346/240/270/345/277/203/346/246/202/345/277/265.md +13 -1
- package/_packed_docs/sdk/04-/350/277/236/346/216/245/344/270/216/350/256/244/350/257/201.md +17 -7
- package/_packed_docs/sdk/06-API/346/211/213/345/206/214.md +55 -14
- package/_packed_docs/sdk/09-collab-rpc-manual.md +48 -30
- package/_packed_docs/sdk/09-custody-api-manual.md +3 -3
- package/_packed_docs/sdk/09-group-rpc-manual.md +53 -6
- package/_packed_docs/sdk/09-message-rpc-manual.md +22 -0
- package/_packed_docs/sdk/09-meta-rpc-manual.md +2 -1
- package/_packed_docs/sdk/09-payload-reference.md +9 -8
- package/_packed_docs/sdk/09-proxy-rpc-manual.md +20 -14
- package/_packed_docs/sdk/09-storage-rpc-manual.md +1698 -1642
- package/_packed_docs/sdk/09-stream-rpc-manual.md +33 -20
- package/_packed_docs/sdk/AUN_DOCS_GUIDE.md +11 -9
- package/_packed_docs/sdk/AUN/344/272/213/344/273/266/345/217/221/345/270/203/350/256/242/351/230/205/345/272/224/347/224/250/351/233/206/346/210/220/346/214/207/345/215/227.md +53 -28
- package/_packed_docs/sdk/AUN/344/272/213/344/273/266/345/217/221/345/270/203/350/256/242/351/230/205/345/274/200/345/217/221/347/247/273/346/244/215/346/214/207/345/215/227.md +62 -28
- package/_packed_docs/sdk/INDEX.md +21 -9
- package/_packed_docs/sdk/README.md +11 -6
- package/dist/agent-md.d.ts +2 -1
- package/dist/agent-md.js +17 -0
- package/dist/agent-md.js.map +1 -1
- package/dist/auth.js +8 -2
- package/dist/auth.js.map +1 -1
- package/dist/client/control-messages.js +4 -4
- package/dist/client/control-messages.js.map +1 -1
- package/dist/client/delivery.d.ts +5 -0
- package/dist/client/delivery.js +146 -32
- package/dist/client/delivery.js.map +1 -1
- package/dist/client/lifecycle.js +3 -0
- package/dist/client/lifecycle.js.map +1 -1
- package/dist/client/rpc-budget.d.ts +21 -0
- package/dist/client/rpc-budget.js +82 -0
- package/dist/client/rpc-budget.js.map +1 -0
- package/dist/client/rpc-pipeline.d.ts +3 -0
- package/dist/client/rpc-pipeline.js +193 -65
- package/dist/client/rpc-pipeline.js.map +1 -1
- package/dist/client/sync-channels.d.ts +89 -0
- package/dist/client/sync-channels.js +489 -0
- package/dist/client/sync-channels.js.map +1 -0
- package/dist/client/v2-e2ee.d.ts +4 -1
- package/dist/client/v2-e2ee.js +401 -298
- package/dist/client/v2-e2ee.js.map +1 -1
- package/dist/client.d.ts +9 -4
- package/dist/client.js +125 -15
- package/dist/client.js.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.js.map +1 -1
- package/dist/ownership-workflow.d.ts +23 -3
- package/dist/ownership-workflow.js +36 -13
- package/dist/ownership-workflow.js.map +1 -1
- package/dist/pubsub/binding.js +14 -1
- package/dist/pubsub/binding.js.map +1 -1
- package/dist/pubsub/channel.d.ts +4 -0
- package/dist/pubsub/channel.js +26 -0
- package/dist/pubsub/channel.js.map +1 -1
- package/dist/pubsub/client.d.ts +9 -0
- package/dist/pubsub/client.js +154 -31
- package/dist/pubsub/client.js.map +1 -1
- package/dist/pubsub/credentials.d.ts +3 -0
- package/dist/pubsub/credentials.js +57 -20
- package/dist/pubsub/credentials.js.map +1 -1
- package/dist/pubsub/index.d.ts +3 -0
- package/dist/pubsub/index.js +69 -53
- package/dist/pubsub/index.js.map +1 -1
- package/dist/pubsub/service.d.ts +3 -0
- package/dist/pubsub/service.js +167 -12
- package/dist/pubsub/service.js.map +1 -1
- package/dist/pubsub/types.d.ts +2 -0
- package/dist/storage/lowlevel.d.ts +7 -3
- package/dist/storage/lowlevel.js +15 -0
- package/dist/storage/lowlevel.js.map +1 -1
- package/dist/storage/read-cache.js +12 -0
- package/dist/storage/read-cache.js.map +1 -1
- package/dist/storage/types.d.ts +10 -0
- package/dist/storage/types.js.map +1 -1
- package/dist/storage/vfs.d.ts +7 -3
- package/dist/storage/vfs.js +2 -2
- package/dist/storage/vfs.js.map +1 -1
- package/dist/tools/cross-sdk-agent.d.ts +62 -6
- package/dist/tools/cross-sdk-agent.js +169 -37
- package/dist/tools/cross-sdk-agent.js.map +1 -1
- package/dist/transport.d.ts +12 -0
- package/dist/transport.js +91 -6
- package/dist/transport.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.d.ts
CHANGED
|
@@ -21,7 +21,7 @@ import { StorageVFS } from './storage/vfs.js';
|
|
|
21
21
|
import { type JsonObject, type JsonValue, type RpcParams, type RpcResult, ConnectionState } from './types.js';
|
|
22
22
|
import { AID } from './aid.js';
|
|
23
23
|
import { type OwnershipConsensusResult } from './ownership-v21.js';
|
|
24
|
-
import { type OwnershipTaskResult } from './ownership-workflow.js';
|
|
24
|
+
import { type OwnershipRequestOptions, type OwnershipApprovalBatchResult, type OwnershipTaskResult } from './ownership-workflow.js';
|
|
25
25
|
import { type CertificateMaterial } from './org-protocol.js';
|
|
26
26
|
import { type RecordVerificationContext as SemanticRecordVerificationContext, type SemanticMessageVerificationContext } from './semantic-protocol.js';
|
|
27
27
|
import type { SemanticPersistentState } from './semantic-facade.js';
|
|
@@ -263,6 +263,7 @@ export declare class AUNClient {
|
|
|
263
263
|
private _peerDirectory;
|
|
264
264
|
private _lifecycle;
|
|
265
265
|
private _rpcPipeline;
|
|
266
|
+
private _syncChannelCoordinator;
|
|
266
267
|
private _delivery;
|
|
267
268
|
private _v2E2EE;
|
|
268
269
|
private _groupState;
|
|
@@ -303,14 +304,14 @@ export declare class AUNClient {
|
|
|
303
304
|
get_owner(): string | null;
|
|
304
305
|
getOwnershipStatus(): Record<string, unknown>;
|
|
305
306
|
get_ownership_status(): Record<string, unknown>;
|
|
306
|
-
bindOwneraid(ownerAid: string): Promise<OwnershipTaskResult>;
|
|
307
|
-
bindSubaid(subAid: string): Promise<OwnershipTaskResult>;
|
|
307
|
+
bindOwneraid(ownerAid: string, options?: OwnershipRequestOptions): Promise<OwnershipTaskResult>;
|
|
308
|
+
bindSubaid(subAid: string, options?: OwnershipRequestOptions): Promise<OwnershipTaskResult>;
|
|
308
309
|
bindLocalSubaid(subClient: AUNClient): Promise<OwnershipTaskResult>;
|
|
309
310
|
transferLocalSubaid(subClient: AUNClient, newOwnerClient: AUNClient): Promise<OwnershipTaskResult>;
|
|
310
311
|
private _createOwnershipOperationClient;
|
|
311
312
|
private _localOwnershipOperation;
|
|
312
313
|
releaseSubaid(subAid: string): Promise<OwnershipTaskResult>;
|
|
313
|
-
transferSubaid(subAid: string, newOwnerAid: string): Promise<OwnershipTaskResult>;
|
|
314
|
+
transferSubaid(subAid: string, newOwnerAid: string, options?: OwnershipRequestOptions): Promise<OwnershipTaskResult>;
|
|
314
315
|
checkOwnershipConsensus(subAid?: string, force?: boolean): Promise<OwnershipConsensusResult>;
|
|
315
316
|
private _checkOwnershipConsensusFresh;
|
|
316
317
|
bindAid(subjectAid: string, options?: {
|
|
@@ -331,6 +332,9 @@ export declare class AUNClient {
|
|
|
331
332
|
bind_owner(ownerAid: string, options?: Parameters<AUNClient['bindOwner']>[1]): Promise<RpcResult>;
|
|
332
333
|
releaseOwnership(subjectAid: string): Promise<RpcResult>;
|
|
333
334
|
release_ownership(subjectAid: string): Promise<RpcResult>;
|
|
335
|
+
acceptOwnershipRequests(operationIds: string[]): Promise<OwnershipApprovalBatchResult>;
|
|
336
|
+
rejectOwnershipRequests(operationIds: string[], reason?: string): Promise<OwnershipApprovalBatchResult>;
|
|
337
|
+
private _approveOwnershipRequests;
|
|
334
338
|
acceptOwnershipRequest(operationId: string): Promise<OwnershipTaskResult>;
|
|
335
339
|
rejectOwnershipRequest(operationId: string, reason?: string): Promise<OwnershipTaskResult>;
|
|
336
340
|
private _handleOwnershipMessage;
|
|
@@ -359,6 +363,7 @@ export declare class AUNClient {
|
|
|
359
363
|
lookupPeer(aid: string, certFingerprint?: string | null): Promise<AID>;
|
|
360
364
|
peers(): AID[];
|
|
361
365
|
/** transport 的 meta observer:吸收 gateway 注入的 _meta 字段。失败不影响业务。 */
|
|
366
|
+
private _historyChannels;
|
|
362
367
|
private _observeRpcMeta;
|
|
363
368
|
isGroupIndexStale(groupAid: string): boolean;
|
|
364
369
|
markGroupIndexFresh(groupAid: string, options: {
|
package/dist/client.js
CHANGED
|
@@ -26,6 +26,7 @@ import { AUNLogger } from './logger.js';
|
|
|
26
26
|
import { normalizeGroupId } from './group-id.js';
|
|
27
27
|
import { validateAIDFormat, validateGroupIDFormat } from './validators.js';
|
|
28
28
|
import { RPCTransport } from './transport.js';
|
|
29
|
+
import { SyncChannels } from './client/sync-channels.js';
|
|
29
30
|
import { AuthFlow } from './auth.js';
|
|
30
31
|
import { AgentMdManager, buildDefaultAgentMd, updateOwnershipAgentMd } from './agent-md.js';
|
|
31
32
|
import { AgentMdChangeCoordinator } from './agent-md-changes.js';
|
|
@@ -54,7 +55,7 @@ import { AID } from './aid.js';
|
|
|
54
55
|
import { certFingerprint, certMatchesFingerprint, normalizeFingerprintHex, publicKeyMatchesFingerprint } from './cert-utils.js';
|
|
55
56
|
import { validateAgentMdCertificate, validateAgentMdDocument, validateAgentMdReadDocument } from './agent-md-schema.js';
|
|
56
57
|
import { OwnershipFiles, OwnershipStorageAdapter, ownershipAid, ownershipFailure, ownershipSha256, parseOwnershipFile, signOwnershipFile } from './ownership-v21.js';
|
|
57
|
-
import { OwnershipWorkflow, OWNERSHIP_SDK_MESSAGE_TYPE, parseOwnershipMessage } from './ownership-workflow.js';
|
|
58
|
+
import { ownershipApprovalBatch, OwnershipWorkflow, OWNERSHIP_SDK_MESSAGE_TYPE, parseOwnershipMessage } from './ownership-workflow.js';
|
|
58
59
|
import { canonicalJson, createCredential, createMemberCredential, signMembershipBinding, digest, validateMembershipBinding, verifyMembershipBinding, verifyCredentialSignature, createRepresentationProof, verifyServiceEvent, buildRequestBinding, validateRequestBinding, CredentialRenewal } from './org-protocol.js';
|
|
59
60
|
import { SemanticProtocolError } from './semantic-protocol.js';
|
|
60
61
|
function isPromiseLike(value) {
|
|
@@ -523,7 +524,16 @@ export class AUNClient {
|
|
|
523
524
|
currentType: () => this.getType(), assertCurrent: () => this._ownershipOperationGuard?.(),
|
|
524
525
|
recoverRequest: (operationId) => this._recoverOwnershipRequest(operationId),
|
|
525
526
|
send: (to, payload, messageId) => this.call('message.send', { to, encrypt: true, message_id: messageId, payload: payload }),
|
|
526
|
-
emit: (event, payload) => {
|
|
527
|
+
emit: (event, payload) => {
|
|
528
|
+
this._ownershipConsensusCache = new Map();
|
|
529
|
+
if (typeof payload.sub_aid === 'string') {
|
|
530
|
+
try {
|
|
531
|
+
this._agentMdManager.updateRecord(payload.sub_aid, (record) => { delete record.ownership_snapshot; });
|
|
532
|
+
}
|
|
533
|
+
catch { }
|
|
534
|
+
}
|
|
535
|
+
this._dispatcher.enqueue(event, payload);
|
|
536
|
+
},
|
|
527
537
|
});
|
|
528
538
|
}
|
|
529
539
|
async _recoverOwnershipRequest(operationId) {
|
|
@@ -1041,6 +1051,7 @@ export class AUNClient {
|
|
|
1041
1051
|
_peerDirectory;
|
|
1042
1052
|
_lifecycle;
|
|
1043
1053
|
_rpcPipeline;
|
|
1054
|
+
_syncChannelCoordinator = null;
|
|
1044
1055
|
_delivery;
|
|
1045
1056
|
_v2E2EE;
|
|
1046
1057
|
_groupState;
|
|
@@ -1152,6 +1163,7 @@ export class AUNClient {
|
|
|
1152
1163
|
this._installRiskHooks();
|
|
1153
1164
|
this._transport.setClassMessageHandler((event, payload) => this._controlMessages().onPush(payload, event.includes('group.')));
|
|
1154
1165
|
this._transport.setProtocolMetaObserver((meta) => this._observeRpcMeta(meta));
|
|
1166
|
+
this._transport.setSyncControlObserver((meta, method, params) => this._historyChannels().observe(meta, method, params));
|
|
1155
1167
|
this._transport.setServiceEventVerifier((event, payload) => this._verifyIncomingServiceEvent(event, payload), () => this._identity?.aid ?? '', () => this._serviceEventIdentityVersion);
|
|
1156
1168
|
this._transport.setProtocolDisconnectCallback((err, closeCode) => this._handleTransportDisconnect(err, closeCode));
|
|
1157
1169
|
this._transport._onForegroundDrained = () => this._delivery.onForegroundPullsDrained();
|
|
@@ -1333,8 +1345,8 @@ export class AUNClient {
|
|
|
1333
1345
|
get_ownership_status() {
|
|
1334
1346
|
return this.getOwnershipStatus();
|
|
1335
1347
|
}
|
|
1336
|
-
async bindOwneraid(ownerAid) { return this._getOwnershipWorkflow().bindOwneraid(ownerAid); }
|
|
1337
|
-
async bindSubaid(subAid) { return this._getOwnershipWorkflow().bindSubaid(subAid); }
|
|
1348
|
+
async bindOwneraid(ownerAid, options) { return this._getOwnershipWorkflow().bindOwneraid(ownerAid, options); }
|
|
1349
|
+
async bindSubaid(subAid, options) { return this._getOwnershipWorkflow().bindSubaid(subAid, options); }
|
|
1338
1350
|
async bindLocalSubaid(subClient) { return this._localOwnershipOperation(subClient); }
|
|
1339
1351
|
async transferLocalSubaid(subClient, newOwnerClient) { return this._localOwnershipOperation(subClient, newOwnerClient); }
|
|
1340
1352
|
_createOwnershipOperationClient(slotId) {
|
|
@@ -1342,6 +1354,11 @@ export class AUNClient {
|
|
|
1342
1354
|
const client = new AUNClient(AID._create({ aid: aid.aid, aunPath: aid.aunPath, certPem: aid.certPem, privateKeyPem: aid.privateKeyPem,
|
|
1343
1355
|
certValid: aid.isCertValid(), privateKeyValid: aid.isPrivateKeyValid(), deviceId: this._deviceId, slotId,
|
|
1344
1356
|
verifySsl: aid.verifySsl, rootCaPath: aid.rootCaPath, debug: aid.debug, aidStore: aid._aidStore }));
|
|
1357
|
+
const identity = this._auth.loadIdentityOrNone(), token = String(identity?.access_token ?? ''), expiresAt = identity?.access_token_expires_at;
|
|
1358
|
+
if (identity?.aid === aid.aid && token.startsWith('eyJ') && token.split('.').length === 3
|
|
1359
|
+
&& typeof expiresAt === 'number' && expiresAt > Date.now() / 1000 + 30) {
|
|
1360
|
+
Object.assign(client._identity, { access_token: token, access_token_expires_at: expiresAt });
|
|
1361
|
+
}
|
|
1345
1362
|
client._ownershipOperation = true;
|
|
1346
1363
|
client._ownershipType = this.getType();
|
|
1347
1364
|
return client;
|
|
@@ -1383,24 +1400,34 @@ export class AUNClient {
|
|
|
1383
1400
|
}
|
|
1384
1401
|
}
|
|
1385
1402
|
async releaseSubaid(subAid) { return this._getOwnershipWorkflow().releaseSubaid(subAid); }
|
|
1386
|
-
async transferSubaid(subAid, newOwnerAid) { return this._getOwnershipWorkflow().transferSubaid(subAid, newOwnerAid); }
|
|
1403
|
+
async transferSubaid(subAid, newOwnerAid, options) { return this._getOwnershipWorkflow().transferSubaid(subAid, newOwnerAid, options); }
|
|
1387
1404
|
async checkOwnershipConsensus(subAid, force = false) {
|
|
1388
1405
|
const target = ownershipAid(subAid ?? this._aid, 'sub_aid');
|
|
1389
|
-
const
|
|
1406
|
+
const manager = this._agentMdManager;
|
|
1407
|
+
const record = manager.loadRecord(target);
|
|
1390
1408
|
const observedEtag = String(record?.remote_etag ?? '');
|
|
1409
|
+
const observation = { root: manager.root, etag: observedEtag, version: Number(record?.observation_version ?? 0), content_hash: typeof record?.content === 'string' ? ownershipSha256(record.content) : '' };
|
|
1391
1410
|
const cache = this._ownershipConsensusCache ??= new Map();
|
|
1392
1411
|
const cached = cache.get(target);
|
|
1393
1412
|
if (!force && cached?.result.status === 'consensus' && record?.remote_status !== 'missing'
|
|
1394
|
-
&& (observedEtag === cached.observedEtag || observedEtag === cached.result.agent_md_etag)
|
|
1413
|
+
&& (observedEtag === cached.observedEtag || observedEtag === cached.result.agent_md_etag)
|
|
1414
|
+
&& (typeof record?.content !== 'string' || ownershipSha256(record.content) === cached.result.agent_md_sha256)) {
|
|
1395
1415
|
cached.observedEtag = observedEtag;
|
|
1396
1416
|
return { ...cached.result };
|
|
1397
1417
|
}
|
|
1418
|
+
if (!force && !cached) {
|
|
1419
|
+
const local = manager.localOwnershipConsensus(target, record);
|
|
1420
|
+
if (local) {
|
|
1421
|
+
cache.set(target, { observedEtag, result: local });
|
|
1422
|
+
return { ...local };
|
|
1423
|
+
}
|
|
1424
|
+
}
|
|
1398
1425
|
cache.delete(target);
|
|
1399
1426
|
const result = { status: 'unavailable', sub_aid: target, owner_aid: null, relation_version: 0, lock: 'unlocked', agent_md_etag: '', agent_md_sha256: '' };
|
|
1400
1427
|
const entry = { observedEtag, result: { ...result } };
|
|
1401
1428
|
cache.set(target, entry);
|
|
1402
1429
|
try {
|
|
1403
|
-
const snapshot = await
|
|
1430
|
+
const snapshot = await manager.readOwnershipFresh(target);
|
|
1404
1431
|
Object.assign(result, { relation_version: snapshot.relation_version, lock: snapshot.lock, agent_md_etag: snapshot.etag,
|
|
1405
1432
|
agent_md_sha256: snapshot.exists ? ownershipSha256(snapshot.content) : '' });
|
|
1406
1433
|
if (snapshot.ownership_status)
|
|
@@ -1420,8 +1447,13 @@ export class AUNClient {
|
|
|
1420
1447
|
result.reason = error instanceof Error ? error.message : String(error);
|
|
1421
1448
|
result.retryable = result.status === 'unavailable';
|
|
1422
1449
|
}
|
|
1423
|
-
if (cache.get(target) === entry)
|
|
1450
|
+
if (this._agentMdManager === manager && this._ownershipConsensusCache === cache && cache.get(target) === entry) {
|
|
1424
1451
|
entry.result = { ...result };
|
|
1452
|
+
try {
|
|
1453
|
+
manager.cacheOwnershipSnapshot(target, result, observation);
|
|
1454
|
+
}
|
|
1455
|
+
catch { }
|
|
1456
|
+
}
|
|
1425
1457
|
return result;
|
|
1426
1458
|
}
|
|
1427
1459
|
async _checkOwnershipConsensusFresh(subAid) {
|
|
@@ -1437,6 +1469,20 @@ export class AUNClient {
|
|
|
1437
1469
|
async bind_owner(ownerAid, options = {}) { return this.bindOwner(ownerAid, options); }
|
|
1438
1470
|
async releaseOwnership(subjectAid) { throw ownershipFailure('unsupported_protocol', 'legacy releaseOwnership is unsupported; use releaseSubaid'); }
|
|
1439
1471
|
async release_ownership(subjectAid) { return this.releaseOwnership(subjectAid); }
|
|
1472
|
+
async acceptOwnershipRequests(operationIds) {
|
|
1473
|
+
return this._approveOwnershipRequests(operationIds);
|
|
1474
|
+
}
|
|
1475
|
+
async rejectOwnershipRequests(operationIds, reason) {
|
|
1476
|
+
return this._approveOwnershipRequests(operationIds, true, reason);
|
|
1477
|
+
}
|
|
1478
|
+
async _approveOwnershipRequests(operationIds, reject = false, reason) {
|
|
1479
|
+
const aid = this._aid, generation = this._serviceEventIdentityVersion;
|
|
1480
|
+
return ownershipApprovalBatch(operationIds, async (operationId) => {
|
|
1481
|
+
if (this._aid !== aid || this._serviceEventIdentityVersion !== generation)
|
|
1482
|
+
throw new StateError('ownership approval identity changed', { stringCode: 'conflict' });
|
|
1483
|
+
return reject ? this.rejectOwnershipRequest(operationId, reason) : this.acceptOwnershipRequest(operationId);
|
|
1484
|
+
});
|
|
1485
|
+
}
|
|
1440
1486
|
async acceptOwnershipRequest(operationId) {
|
|
1441
1487
|
return this._getOwnershipWorkflow().acceptOwnershipRequest(operationId);
|
|
1442
1488
|
}
|
|
@@ -1655,6 +1701,7 @@ export class AUNClient {
|
|
|
1655
1701
|
this._installRiskHooks();
|
|
1656
1702
|
this._transport.setClassMessageHandler((event, payload) => this._controlMessages().onPush(payload, event.includes('group.')));
|
|
1657
1703
|
this._transport.setProtocolMetaObserver((meta) => this._observeRpcMeta(meta));
|
|
1704
|
+
this._transport.setSyncControlObserver((meta, method, params) => this._historyChannels().observe(meta, method, params));
|
|
1658
1705
|
this._transport.setServiceEventVerifier((event, payload) => this._verifyIncomingServiceEvent(event, payload), () => this._identity?.aid ?? '', () => this._serviceEventIdentityVersion);
|
|
1659
1706
|
this._transport.setProtocolDisconnectCallback((err, closeCode) => this._handleTransportDisconnect(err, closeCode));
|
|
1660
1707
|
this._transport._onForegroundDrained = () => this._delivery.onForegroundPullsDrained();
|
|
@@ -1710,6 +1757,56 @@ export class AUNClient {
|
|
|
1710
1757
|
return this._peerDirectory.peers();
|
|
1711
1758
|
}
|
|
1712
1759
|
/** transport 的 meta observer:吸收 gateway 注入的 _meta 字段。失败不影响业务。 */
|
|
1760
|
+
_historyChannels() {
|
|
1761
|
+
return this._syncChannelCoordinator ??= new SyncChannels({
|
|
1762
|
+
main: () => this._transport,
|
|
1763
|
+
current: () => this._state === 'ready' && !this._closing && this._transport.isConnected(),
|
|
1764
|
+
wake: () => this._delivery?.requestBackgroundPullRecovery(),
|
|
1765
|
+
owner: () => String(this._aid ?? ''),
|
|
1766
|
+
namespace: (method, params) => this._rpcPipeline.pullGateKeyForCall(method, params).split('|')[0],
|
|
1767
|
+
pendingNamespaces: () => [...this._delivery.pendingHistoryNamespaces(), ...this._rpcPipeline.pendingHistoryNamespaces()],
|
|
1768
|
+
fail: (method, params, error) => this._dispatcher.enqueue('sync.error', { namespace: params.sender_aid ? this._delivery.peerNamespace(String(params.sender_aid)) : `group:${String(params.group_id ?? params.group_aid ?? '')}`, method, code: 'OVERSIZED_MESSAGE', error: error instanceof Error ? error.message : String(error) }),
|
|
1769
|
+
create: async (parent, timeout = 35000, signal) => {
|
|
1770
|
+
const deadline = Date.now() + timeout;
|
|
1771
|
+
const dispatcher = new EventDispatcher(this._logger.for('aun_core.events'));
|
|
1772
|
+
const transport = new RPCTransport({ eventDispatcher: dispatcher, rpcBudget: this._transport.rpcBudget, syncAuxiliary: true,
|
|
1773
|
+
timeout, verifySsl: this._configModel.verifySsl, logger: this._logger.for('aun_core.transport') });
|
|
1774
|
+
transport.setSyncControlObserver((meta, method, params) => this._historyChannels().observe(meta, method, params));
|
|
1775
|
+
transport.setRequestAdmission(this._transport._requestAdmission);
|
|
1776
|
+
transport.setRequestCheck(this._transport._requestCheck);
|
|
1777
|
+
transport.setProtocolDisconnectCallback(() => this._historyChannels().auxiliaryDisconnected(transport));
|
|
1778
|
+
const abort = () => { void transport.close(); };
|
|
1779
|
+
signal?.addEventListener('abort', abort, { once: true });
|
|
1780
|
+
try {
|
|
1781
|
+
if (signal?.aborted)
|
|
1782
|
+
throw new TimeoutError('history sync cancelled', { retryable: true });
|
|
1783
|
+
const challenge = await transport.connect(this._gatewayUrl);
|
|
1784
|
+
if (Date.now() >= deadline || signal?.aborted)
|
|
1785
|
+
throw new TimeoutError('history sync deadline exceeded', { retryable: true });
|
|
1786
|
+
transport.setTimeout(Math.max(1, deadline - Date.now()));
|
|
1787
|
+
const token = AuthFlow._getCachedAccessToken(this._identity ?? {})
|
|
1788
|
+
|| AuthFlow._getCachedAccessToken(this._sessionParams ?? {});
|
|
1789
|
+
if (!token)
|
|
1790
|
+
throw new ConnectionError('auxiliary sync connection has no valid access token');
|
|
1791
|
+
const hello = await this._auth.initializeWithToken(transport, challenge, token, { deviceId: this._deviceId,
|
|
1792
|
+
slotId: this._slotId, connectionKind: 'short', shortTtlMs: 0, extraInfo: { _sync_parent: parent } });
|
|
1793
|
+
if (!isJsonObject(hello.connection) || !hello.connection.id)
|
|
1794
|
+
throw new ConnectionError('auxiliary sync connection has no identity');
|
|
1795
|
+
if (!isJsonObject(hello.negotiated_capabilities) || hello.negotiated_capabilities.elastic_connections_v1 !== true || hello.negotiated_capabilities.sync_channels_v1 !== true)
|
|
1796
|
+
throw new ConnectionError('auxiliary sync capabilities were not negotiated');
|
|
1797
|
+
return { id: String(hello.connection.id), transport, dispose: () => dispatcher.close() };
|
|
1798
|
+
}
|
|
1799
|
+
catch (error) {
|
|
1800
|
+
await transport.close();
|
|
1801
|
+
await dispatcher.close();
|
|
1802
|
+
throw error;
|
|
1803
|
+
}
|
|
1804
|
+
finally {
|
|
1805
|
+
signal?.removeEventListener('abort', abort);
|
|
1806
|
+
}
|
|
1807
|
+
},
|
|
1808
|
+
});
|
|
1809
|
+
}
|
|
1713
1810
|
_observeRpcMeta(meta) {
|
|
1714
1811
|
this._agentMdManager.observeRpcMeta(meta, this._aid);
|
|
1715
1812
|
this._groupIndexMetaCache.observeRpcMeta(meta, { localAid: this._aid ?? '' });
|
|
@@ -2028,6 +2125,9 @@ export class AUNClient {
|
|
|
2028
2125
|
if (!pending?.private_key_pem || !pending.public_key_der_b64)
|
|
2029
2126
|
return false;
|
|
2030
2127
|
}
|
|
2128
|
+
const local = this._agentMdManager.localOwnershipConsensus(target, this._agentMdManager.loadRecord(target));
|
|
2129
|
+
if (local?.owner_aid === this._aid)
|
|
2130
|
+
return true;
|
|
2031
2131
|
const result = await this._entityLifecycle(target, type);
|
|
2032
2132
|
const data = result;
|
|
2033
2133
|
const entity = (isJsonObject(data.group) ? data.group : isJsonObject(data.organization) ? data.organization : data);
|
|
@@ -2201,12 +2301,19 @@ export class AUNClient {
|
|
|
2201
2301
|
if (!aid)
|
|
2202
2302
|
return;
|
|
2203
2303
|
try {
|
|
2204
|
-
const
|
|
2205
|
-
|
|
2206
|
-
|
|
2207
|
-
|
|
2208
|
-
|
|
2209
|
-
|
|
2304
|
+
const record = this._agentMdManager.loadRecord(aid);
|
|
2305
|
+
const verified = record?.verified_agent_md;
|
|
2306
|
+
const local = record?.content && record.remote_status !== 'missing' && record.remote_etag
|
|
2307
|
+
&& (record.local_etag === record.remote_etag || record.verify_status === 'verified' && verified?.etag === record.remote_etag && verified.content_hash === record.local_etag
|
|
2308
|
+
|| this._agentMdManager.localOwnershipConsensus(aid, record));
|
|
2309
|
+
if (!local) {
|
|
2310
|
+
const checked = await this._agentMdManager.check(aid, 0);
|
|
2311
|
+
if (!checked.remote_found) {
|
|
2312
|
+
await this._ensureInitialAgentMd();
|
|
2313
|
+
}
|
|
2314
|
+
else if (checked.in_sync === false) {
|
|
2315
|
+
await this._agentMdManager.download(aid);
|
|
2316
|
+
}
|
|
2210
2317
|
}
|
|
2211
2318
|
}
|
|
2212
2319
|
catch (exc) {
|
|
@@ -4512,6 +4619,7 @@ export class AUNClient {
|
|
|
4512
4619
|
// ── 内部:连接 ────────────────────────────────────────────
|
|
4513
4620
|
/** 执行一次连接流程 */
|
|
4514
4621
|
async _connectOnce(params, allowReauth, reconnectOwner, connectionOwner) {
|
|
4622
|
+
this._syncChannelCoordinator?.reset();
|
|
4515
4623
|
await this._restoreRiskState();
|
|
4516
4624
|
this._assertRiskReconnect();
|
|
4517
4625
|
this._riskNegotiated = false;
|
|
@@ -4623,6 +4731,7 @@ export class AUNClient {
|
|
|
4623
4731
|
this._migrationPending = false;
|
|
4624
4732
|
this._lastDisconnectInfo = null;
|
|
4625
4733
|
this._state = 'ready';
|
|
4734
|
+
this._historyChannels().bind(this._gatewayConnectionId, this._negotiatedCapabilities.elastic_connections_v1 === true && this._negotiatedCapabilities.sync_channels_v1 === true && params.connection_kind !== 'short');
|
|
4626
4735
|
this._connectedAt = Date.now();
|
|
4627
4736
|
if (Array.isArray(params.gateways)) {
|
|
4628
4737
|
this._gatewayCandidates = [...new Set(params.gateways
|
|
@@ -5615,6 +5724,7 @@ export class AUNClient {
|
|
|
5615
5724
|
}
|
|
5616
5725
|
/** 停止所有后台任务 */
|
|
5617
5726
|
_stopBackgroundTasks() {
|
|
5727
|
+
this._syncChannelCoordinator?.reset();
|
|
5618
5728
|
this._stopCredentialRenewal();
|
|
5619
5729
|
this._auth.invalidateStrictPkiCache();
|
|
5620
5730
|
this._certCache.clear();
|