@agentunion/fastaun-browser 0.4.2 → 0.4.4
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 +190 -164
- 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 +302 -0
- 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 +194 -0
- package/_packed_docs/AUN_SDK_/351/207/215/346/236/204/345/256/236/346/226/275/350/256/241/345/210/222.md +596 -596
- 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 +1698 -1697
- package/_packed_docs/CHANGELOG.md +190 -164
- package/_packed_docs/INDEX.md +17 -17
- package/_packed_docs/KITE_DOCS_GUIDE.md +11 -11
- package/_packed_docs/agent.md/SCHEMA.md +49 -49
- package/_packed_docs/agent.md/examples/signed-openclaw-lobster.md +22 -22
- package/_packed_docs/agent.md//350/277/234/347/250/213agent.md/347/274/223/345/255/230/344/270/216etag/351/200/217/344/274/240/346/226/271/346/241/210.md +327 -327
- package/_packed_docs/cli/AUN-CLI/350/256/276/350/256/241/346/226/207/346/241/243.md +686 -686
- package/_packed_docs/design/2026-05-22-aun-rpc-trace-enhancement.md +542 -542
- package/_packed_docs/design/E2EE_V2/347/256/200/345/214/226/344/270/2721DH/345/212/240Per-AID_Wrap/346/226/271/346/241/210.md +124 -124
- package/_packed_docs/design//350/267/250/350/257/255/350/250/200/345/256/271/345/231/250E2E/346/265/213/350/257/225/346/226/271/346/241/210.md +665 -665
- package/_packed_docs/protocol/01-/350/272/253/344/273/275/344/270/216/345/207/255/350/257/201/345/215/217/350/256/256-auth.md +2 -2
- package/_packed_docs/protocol/14-/344/272/244/344/272/222/346/234/272/345/210/266-/345/223/215/345/272/224/346/250/241/345/274/217/344/270/216/350/207/252/344/270/273/346/250/241/345/274/217.md +170 -170
- package/_packed_docs/protocol/15-/347/246/273/347/272/277/346/216/250/351/200/201/351/200/232/347/237/245/345/215/217/350/256/256.md +419 -419
- package/_packed_docs/protocol/README.md +1 -1
- package/_packed_docs/protocol/aun-docs-guide.md +1 -1
- package/_packed_docs/protocol//351/231/204/345/275/225A-/346/234/257/350/257/255/350/241/250.md +15 -15
- package/_packed_docs/protocol//351/231/204/345/275/225B-/346/211/251/345/261/225/346/200/247/346/214/207/345/215/227.md +4 -4
- package/_packed_docs/protocol//351/231/204/345/275/225J-/345/256/242/346/210/267/347/253/257/346/216/245/345/205/245/347/244/272/344/276/213.md +98 -98
- package/_packed_docs/protocol//351/231/204/345/275/225M-JWT/350/256/244/350/257/201/345/256/236/347/216/260/346/214/207/345/215/227.md +46 -46
- package/_packed_docs/protocol//351/231/204/345/275/225N-/345/210/206/345/270/203/345/274/217Trace/345/215/217/350/256/256.md +257 -257
- package/_packed_docs/python-sdk-v2-only-changelog.md +189 -189
- package/_packed_docs/sdk/01-/345/277/253/351/200/237/345/274/200/345/247/213.md +7 -3
- package/_packed_docs/sdk/03-/346/240/270/345/277/203/346/246/202/345/277/265.md +1 -1
- package/_packed_docs/sdk/04-/350/277/236/346/216/245/344/270/216/350/256/244/350/257/201.md +3 -1
- package/_packed_docs/sdk/05-E2EE/345/212/240/345/257/206/351/200/232/344/277/241.md +1 -1
- package/_packed_docs/sdk/06-API/346/211/213/345/206/214.md +63 -15
- package/_packed_docs/sdk/09-payload-reference.md +13 -13
- package/_packed_docs/sdk/E2EE_V2/346/266/210/346/201/257/351/200/232/344/277/241/346/227/266/345/272/217/345/233/276.md +171 -171
- package/_packed_docs/sdk/README.md +5 -5
- package/dist/aid-store.d.ts.map +1 -1
- package/dist/aid-store.js +5 -6
- package/dist/aid-store.js.map +1 -1
- package/dist/aid.d.ts +2 -1
- package/dist/aid.d.ts.map +1 -1
- package/dist/aid.js +7 -6
- package/dist/aid.js.map +1 -1
- package/dist/auth.d.ts.map +1 -1
- package/dist/auth.js +4 -0
- package/dist/auth.js.map +1 -1
- package/dist/bundle.js +292 -188
- package/dist/client.d.ts +13 -17
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +275 -190
- package/dist/client.js.map +1 -1
- package/dist/config.d.ts +4 -7
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +18 -1
- package/dist/config.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/keystore/indexeddb.js +5 -5
- package/dist/keystore/indexeddb.js.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +1 -1
package/dist/bundle.js
CHANGED
|
@@ -454,7 +454,7 @@ var init_indexeddb_store = __esm({
|
|
|
454
454
|
});
|
|
455
455
|
|
|
456
456
|
// src/version.ts
|
|
457
|
-
var VERSION = "0.4.
|
|
457
|
+
var VERSION = "0.4.4";
|
|
458
458
|
|
|
459
459
|
// src/types.ts
|
|
460
460
|
var ConnectionState = /* @__PURE__ */ ((ConnectionState2) => {
|
|
@@ -708,6 +708,7 @@ function mapRemoteError(error) {
|
|
|
708
708
|
|
|
709
709
|
// src/config.ts
|
|
710
710
|
var INSTANCE_ID_PATTERN = /^[A-Za-z0-9._-]{1,128}$/;
|
|
711
|
+
var SLOT_ID_PATTERN = /^[A-Za-z0-9._-][A-Za-z0-9._/ :-]{0,127}$/;
|
|
711
712
|
function readString(value, fallback) {
|
|
712
713
|
return typeof value === "string" ? value : fallback;
|
|
713
714
|
}
|
|
@@ -731,6 +732,18 @@ function normalizeInstanceId(value, field, opts = {}) {
|
|
|
731
732
|
}
|
|
732
733
|
return text;
|
|
733
734
|
}
|
|
735
|
+
function normalizeSlotId(value, defaultValue = "default") {
|
|
736
|
+
const raw = String(value ?? "");
|
|
737
|
+
const text = raw || defaultValue;
|
|
738
|
+
if (!SLOT_ID_PATTERN.test(text)) {
|
|
739
|
+
throw new ValidationError("slot_id contains unsupported characters");
|
|
740
|
+
}
|
|
741
|
+
return text;
|
|
742
|
+
}
|
|
743
|
+
function slotIsolationKey(slotId) {
|
|
744
|
+
const m = slotId.match(/^[^/ :]+/);
|
|
745
|
+
return m ? m[0] : slotId;
|
|
746
|
+
}
|
|
734
747
|
function getDeviceId() {
|
|
735
748
|
const STORAGE_KEY = "aun_device_id";
|
|
736
749
|
try {
|
|
@@ -752,7 +765,8 @@ var DEFAULTS = {
|
|
|
752
765
|
groupE2ee: true,
|
|
753
766
|
verifySsl: true,
|
|
754
767
|
requireForwardSecrecy: true,
|
|
755
|
-
replayWindowSeconds: 300
|
|
768
|
+
replayWindowSeconds: 300,
|
|
769
|
+
discoveryPort: null
|
|
756
770
|
};
|
|
757
771
|
function createConfig(raw) {
|
|
758
772
|
const data = raw ?? {};
|
|
@@ -769,10 +783,10 @@ function createConfig(raw) {
|
|
|
769
783
|
DEFAULTS.seedPassword
|
|
770
784
|
),
|
|
771
785
|
groupE2ee: true,
|
|
772
|
-
// 必备能力,不可配置
|
|
773
786
|
verifySsl: DEFAULTS.verifySsl,
|
|
774
787
|
requireForwardSecrecy: readBoolean(data.requireForwardSecrecy ?? data.require_forward_secrecy, DEFAULTS.requireForwardSecrecy),
|
|
775
|
-
replayWindowSeconds: readOptionalNumber(data.replayWindowSeconds ?? data.replay_window_seconds, DEFAULTS.replayWindowSeconds) ?? DEFAULTS.replayWindowSeconds
|
|
788
|
+
replayWindowSeconds: readOptionalNumber(data.replayWindowSeconds ?? data.replay_window_seconds, DEFAULTS.replayWindowSeconds) ?? DEFAULTS.replayWindowSeconds,
|
|
789
|
+
discoveryPort: readOptionalNumber(data.discoveryPort ?? data.discovery_port, DEFAULTS.discoveryPort)
|
|
776
790
|
};
|
|
777
791
|
}
|
|
778
792
|
|
|
@@ -3128,6 +3142,9 @@ var _AuthFlow = class _AuthFlow {
|
|
|
3128
3142
|
delete persistedRecord[key];
|
|
3129
3143
|
}
|
|
3130
3144
|
}
|
|
3145
|
+
for (const key of ["private_key_pem", "public_key_der_b64", "curve"]) {
|
|
3146
|
+
delete persistedRecord[key];
|
|
3147
|
+
}
|
|
3131
3148
|
await this._keystore.saveIdentity(aid, persisted);
|
|
3132
3149
|
if (Object.keys(instanceState).length === 0 || typeof this._keystore.updateInstanceState !== "function") {
|
|
3133
3150
|
return;
|
|
@@ -3594,8 +3611,8 @@ function certStoreKey(aid, certFingerprint) {
|
|
|
3594
3611
|
}
|
|
3595
3612
|
function instanceStateStoreKey(aid, deviceId, slotId = "") {
|
|
3596
3613
|
const normalizedDevice = normalizeInstanceId(deviceId, "device_id");
|
|
3597
|
-
const
|
|
3598
|
-
return `${safeAid(aid)}|${encodePart(normalizedDevice)}|${encodePart(
|
|
3614
|
+
const slotKey = slotIsolationKey(slotId) || "_singleton";
|
|
3615
|
+
return `${safeAid(aid)}|${encodePart(normalizedDevice)}|${encodePart(slotKey)}`;
|
|
3599
3616
|
}
|
|
3600
3617
|
function prekeyPrefix(aid) {
|
|
3601
3618
|
return `${safeAid(aid)}|`;
|
|
@@ -3629,8 +3646,8 @@ function sessionStoreKey(aid, sessionId) {
|
|
|
3629
3646
|
}
|
|
3630
3647
|
function seqTrackerPrefix(aid, deviceId, slotId) {
|
|
3631
3648
|
const normalizedDevice = normalizeInstanceId(deviceId, "device_id");
|
|
3632
|
-
const
|
|
3633
|
-
return `_seq_|${safeAid(aid)}|${encodePart(normalizedDevice)}|${encodePart(
|
|
3649
|
+
const slotKey = slotIsolationKey(slotId) || "_singleton";
|
|
3650
|
+
return `_seq_|${safeAid(aid)}|${encodePart(normalizedDevice)}|${encodePart(slotKey)}|`;
|
|
3634
3651
|
}
|
|
3635
3652
|
function seqTrackerStoreKey(aid, deviceId, slotId, namespace) {
|
|
3636
3653
|
return `${seqTrackerPrefix(aid, deviceId, slotId)}${encodePart(namespace)}`;
|
|
@@ -9689,7 +9706,8 @@ var AID = class _AID {
|
|
|
9689
9706
|
__publicField(this, "verifySsl");
|
|
9690
9707
|
__publicField(this, "rootCaPath");
|
|
9691
9708
|
__publicField(this, "debug");
|
|
9692
|
-
|
|
9709
|
+
/** AIDStore 加载时注入的明文私钥 PEM,供 AUNClient 直接使用(无需 seed)。*/
|
|
9710
|
+
__publicField(this, "privateKeyPem");
|
|
9693
9711
|
__publicField(this, "_certValid");
|
|
9694
9712
|
__publicField(this, "_privateKeyValid");
|
|
9695
9713
|
__publicField(this, "_certFingerprint", "");
|
|
@@ -9707,7 +9725,7 @@ var AID = class _AID {
|
|
|
9707
9725
|
this.certIssuer = meta.issuer;
|
|
9708
9726
|
this.certNotBefore = meta.notBefore;
|
|
9709
9727
|
this.certNotAfter = meta.notAfter;
|
|
9710
|
-
this.
|
|
9728
|
+
this.privateKeyPem = params.privateKeyPem ?? "";
|
|
9711
9729
|
this._certValid = params.certValid;
|
|
9712
9730
|
this._privateKeyValid = params.privateKeyValid;
|
|
9713
9731
|
}
|
|
@@ -9726,10 +9744,10 @@ var AID = class _AID {
|
|
|
9726
9744
|
return this._privateKeyValid;
|
|
9727
9745
|
}
|
|
9728
9746
|
async sign(payload) {
|
|
9729
|
-
if (!this._privateKeyValid || !this.
|
|
9747
|
+
if (!this._privateKeyValid || !this.privateKeyPem) return resultErr(PRIVATE_KEY_NOT_VALID, "private key is not valid");
|
|
9730
9748
|
try {
|
|
9731
9749
|
const data = typeof payload === "string" ? new TextEncoder().encode(payload) : payload;
|
|
9732
|
-
return resultOk({ signature: await signBytes(this.
|
|
9750
|
+
return resultOk({ signature: await signBytes(this.privateKeyPem, data) });
|
|
9733
9751
|
} catch (exc) {
|
|
9734
9752
|
return resultErr(SIGNATURE_OPERATION_ERROR, String(exc), exc);
|
|
9735
9753
|
}
|
|
@@ -9744,10 +9762,10 @@ var AID = class _AID {
|
|
|
9744
9762
|
}
|
|
9745
9763
|
}
|
|
9746
9764
|
async signAgentMd(content) {
|
|
9747
|
-
if (!this._privateKeyValid || !this.
|
|
9765
|
+
if (!this._privateKeyValid || !this.privateKeyPem) return resultErr(PRIVATE_KEY_NOT_VALID, "private key is not valid");
|
|
9748
9766
|
try {
|
|
9749
9767
|
const payload = normalizeAgentMdPayload(content);
|
|
9750
|
-
const signature = await signBytes(this.
|
|
9768
|
+
const signature = await signBytes(this.privateKeyPem, new TextEncoder().encode(payload));
|
|
9751
9769
|
return resultOk({ signed: payload + buildAgentMdSignatureBlock(this.certFingerprint, Date.now() / 1e3, signature) });
|
|
9752
9770
|
} catch (exc) {
|
|
9753
9771
|
return resultErr(SIGNATURE_OPERATION_ERROR, String(exc), exc);
|
|
@@ -9795,6 +9813,12 @@ function getV2DeviceId(dev) {
|
|
|
9795
9813
|
}
|
|
9796
9814
|
return { present: false, value: "" };
|
|
9797
9815
|
}
|
|
9816
|
+
function isAIDObject(value) {
|
|
9817
|
+
const candidate = value;
|
|
9818
|
+
return Boolean(
|
|
9819
|
+
candidate && typeof candidate === "object" && typeof candidate.aid === "string" && typeof candidate.aunPath === "string" && typeof candidate.isPrivateKeyValid === "function"
|
|
9820
|
+
);
|
|
9821
|
+
}
|
|
9798
9822
|
function sortObjectKeys(obj) {
|
|
9799
9823
|
if (obj === null || obj === void 0 || typeof obj !== "object") return obj;
|
|
9800
9824
|
if (Array.isArray(obj)) return obj.map(sortObjectKeys);
|
|
@@ -9927,6 +9951,20 @@ var DEFAULT_SESSION_OPTIONS = {
|
|
|
9927
9951
|
http: 30
|
|
9928
9952
|
}
|
|
9929
9953
|
};
|
|
9954
|
+
var PUBLIC_CONNECTION_OPTION_KEYS = /* @__PURE__ */ new Set([
|
|
9955
|
+
"auto_reconnect",
|
|
9956
|
+
"connect_timeout",
|
|
9957
|
+
"retry_initial_delay",
|
|
9958
|
+
"retry_max_delay",
|
|
9959
|
+
"retry_max_attempts",
|
|
9960
|
+
"heartbeat_interval",
|
|
9961
|
+
"call_timeout",
|
|
9962
|
+
"connection_kind",
|
|
9963
|
+
"short_ttl_ms",
|
|
9964
|
+
"delivery_mode",
|
|
9965
|
+
"extra_info",
|
|
9966
|
+
"background_sync"
|
|
9967
|
+
]);
|
|
9930
9968
|
var PROTECTED_HEADERS_METHODS = /* @__PURE__ */ new Set([
|
|
9931
9969
|
"message.send",
|
|
9932
9970
|
"group.send",
|
|
@@ -10308,15 +10346,6 @@ function normalizeDeliveryModeConfig(raw, opts = {}) {
|
|
|
10308
10346
|
affinity_ttl_ms: affinityTtlMs
|
|
10309
10347
|
};
|
|
10310
10348
|
}
|
|
10311
|
-
function clientOptionsConfig(options) {
|
|
10312
|
-
const raw = { ...options ?? {} };
|
|
10313
|
-
if (Object.prototype.hasOwnProperty.call(raw, "aid")) {
|
|
10314
|
-
throw new ValidationError("AUNClient options must not include aid; pass an AID object as the first argument");
|
|
10315
|
-
}
|
|
10316
|
-
delete raw.debug;
|
|
10317
|
-
delete raw.protected_headers;
|
|
10318
|
-
return raw;
|
|
10319
|
-
}
|
|
10320
10349
|
var _AUNClient = class _AUNClient {
|
|
10321
10350
|
constructor(aid) {
|
|
10322
10351
|
/** SDK 配置模型 */
|
|
@@ -10353,6 +10382,7 @@ var _AUNClient = class _AUNClient {
|
|
|
10353
10382
|
// V2 E2EE 状态
|
|
10354
10383
|
__publicField(this, "_v2Session");
|
|
10355
10384
|
__publicField(this, "_v2KeyStore");
|
|
10385
|
+
__publicField(this, "_v2SessionInitInFlight", null);
|
|
10356
10386
|
__publicField(this, "_v2BootstrapCache", /* @__PURE__ */ new Map());
|
|
10357
10387
|
__publicField(this, "_v2SenderIKPending", /* @__PURE__ */ new Map());
|
|
10358
10388
|
__publicField(this, "_v2SenderIKFetching", /* @__PURE__ */ new Set());
|
|
@@ -10428,16 +10458,15 @@ var _AUNClient = class _AUNClient {
|
|
|
10428
10458
|
*/
|
|
10429
10459
|
__publicField(this, "_v2PullInflight", false);
|
|
10430
10460
|
__publicField(this, "_v2PullPending", false);
|
|
10431
|
-
|
|
10432
|
-
|
|
10433
|
-
throw new ValidationError("AUNClient aid must be an AID object, not a string");
|
|
10461
|
+
if (aid !== null && aid !== void 0 && !isAIDObject(aid)) {
|
|
10462
|
+
throw new ValidationError("AUNClient only accepts an AID object or no argument");
|
|
10434
10463
|
}
|
|
10435
|
-
const
|
|
10436
|
-
const rawConfig =
|
|
10464
|
+
const inputAid = aid ?? null;
|
|
10465
|
+
const rawConfig = {};
|
|
10437
10466
|
if (inputAid) rawConfig.aun_path = inputAid.aunPath;
|
|
10438
|
-
const _debug = false;
|
|
10467
|
+
const _debug = inputAid ? inputAid.debug : false;
|
|
10439
10468
|
this.configModel = createConfig(rawConfig);
|
|
10440
|
-
const initAid = inputAid ? inputAid.aid : null;
|
|
10469
|
+
const initAid = inputAid && inputAid.isPrivateKeyValid() ? inputAid.aid : null;
|
|
10441
10470
|
this.config = {
|
|
10442
10471
|
aun_path: this.configModel.aunPath,
|
|
10443
10472
|
root_ca_path: this.configModel.rootCaPem,
|
|
@@ -10456,7 +10485,7 @@ var _AUNClient = class _AUNClient {
|
|
|
10456
10485
|
this._clientLog.info(`AUNClient initialized: debug=${_debug} aunPath=${this.configModel.aunPath} aid=${initAid ?? "-"}`);
|
|
10457
10486
|
this._dispatcher = new EventDispatcher();
|
|
10458
10487
|
this._discovery = new GatewayDiscovery();
|
|
10459
|
-
this._keystore = new IndexedDBKeyStore({
|
|
10488
|
+
this._keystore = new IndexedDBKeyStore({});
|
|
10460
10489
|
this._slotId = inputAid?.slotId || "default";
|
|
10461
10490
|
this._connectDeliveryMode = normalizeDeliveryModeConfig({ mode: "fanout" });
|
|
10462
10491
|
this._defaultConnectDeliveryMode = { ...this._connectDeliveryMode };
|
|
@@ -10481,18 +10510,16 @@ var _AUNClient = class _AUNClient {
|
|
|
10481
10510
|
});
|
|
10482
10511
|
});
|
|
10483
10512
|
if (inputAid) {
|
|
10484
|
-
if (
|
|
10485
|
-
|
|
10486
|
-
|
|
10487
|
-
|
|
10488
|
-
|
|
10489
|
-
|
|
10490
|
-
|
|
10491
|
-
|
|
10492
|
-
|
|
10493
|
-
|
|
10494
|
-
if (options?.protected_headers !== void 0) {
|
|
10495
|
-
this.setProtectedHeaders(options.protected_headers);
|
|
10513
|
+
if (inputAid.isPrivateKeyValid()) {
|
|
10514
|
+
this._currentAid = inputAid;
|
|
10515
|
+
this._identity = {
|
|
10516
|
+
aid: inputAid.aid,
|
|
10517
|
+
private_key_pem: inputAid.privateKeyPem,
|
|
10518
|
+
public_key_der_b64: inputAid.publicKey,
|
|
10519
|
+
cert: inputAid.certPem
|
|
10520
|
+
};
|
|
10521
|
+
this._state = "disconnected";
|
|
10522
|
+
}
|
|
10496
10523
|
}
|
|
10497
10524
|
this._auth.setLogger(this._logAuth);
|
|
10498
10525
|
this._transport.setLogger(this._logTransport);
|
|
@@ -10718,7 +10745,7 @@ var _AUNClient = class _AUNClient {
|
|
|
10718
10745
|
*/
|
|
10719
10746
|
async publishAgentMd(content) {
|
|
10720
10747
|
const target = this._agentMdOwnerAid();
|
|
10721
|
-
if (!target) {
|
|
10748
|
+
if (!target || !this._currentAid) {
|
|
10722
10749
|
throw new ValidationError("publishAgentMd requires local AID");
|
|
10723
10750
|
}
|
|
10724
10751
|
if (content !== void 0 && content !== null) {
|
|
@@ -11213,21 +11240,78 @@ var _AUNClient = class _AUNClient {
|
|
|
11213
11240
|
get lastErrorCode() {
|
|
11214
11241
|
return this._lastErrorCode;
|
|
11215
11242
|
}
|
|
11243
|
+
_applyAidRuntimeContext(aid) {
|
|
11244
|
+
const nextConfig = createConfig({
|
|
11245
|
+
aunPath: aid.aunPath,
|
|
11246
|
+
rootCaPem: aid.rootCaPath,
|
|
11247
|
+
verifySsl: aid.verifySsl
|
|
11248
|
+
});
|
|
11249
|
+
Object.assign(this.configModel, nextConfig);
|
|
11250
|
+
this.config.aun_path = nextConfig.aunPath;
|
|
11251
|
+
this.config.root_ca_path = nextConfig.rootCaPem;
|
|
11252
|
+
this.config.seed_password = nextConfig.seedPassword;
|
|
11253
|
+
this._agentMdPath = this._agentMdDefaultRoot();
|
|
11254
|
+
this._agentMdCache.clear();
|
|
11255
|
+
this._agentMdFetchInflight.clear();
|
|
11256
|
+
this._peerCache.clear();
|
|
11257
|
+
this._certCache.clear();
|
|
11258
|
+
this._gatewayUrl = null;
|
|
11259
|
+
this._deviceId = aid.deviceId || getDeviceId();
|
|
11260
|
+
this._slotId = aid.slotId || "default";
|
|
11261
|
+
this._logger = new AUNLogger({ debug: aid.debug, aunPath: nextConfig.aunPath });
|
|
11262
|
+
this._logger.bindDeviceId(this._deviceId);
|
|
11263
|
+
this._clientLog = this._logger.for("aun_core.client");
|
|
11264
|
+
this._logAuth = this._logger.for("aun_core.auth");
|
|
11265
|
+
this._logTransport = this._logger.for("aun_core.transport");
|
|
11266
|
+
this._logKeystore = this._logger.for("aun_core.keystore");
|
|
11267
|
+
this._logDiscovery = this._logger.for("aun_core.discovery");
|
|
11268
|
+
this._logEvents = this._logger.for("aun_core.events");
|
|
11269
|
+
this._discovery = new GatewayDiscovery();
|
|
11270
|
+
this._keystore = new IndexedDBKeyStore({});
|
|
11271
|
+
this._auth = new AuthFlow({
|
|
11272
|
+
keystore: this._keystore,
|
|
11273
|
+
crypto: new CryptoProvider(),
|
|
11274
|
+
aid: aid.aid,
|
|
11275
|
+
deviceId: this._deviceId,
|
|
11276
|
+
slotId: this._slotId,
|
|
11277
|
+
rootCaPem: nextConfig.rootCaPem,
|
|
11278
|
+
verifySsl: nextConfig.verifySsl
|
|
11279
|
+
});
|
|
11280
|
+
this._transport = new RPCTransport({
|
|
11281
|
+
eventDispatcher: this._dispatcher,
|
|
11282
|
+
timeout: DEFAULT_SESSION_OPTIONS.timeouts.call,
|
|
11283
|
+
onDisconnect: (error, closeCode) => this._handleTransportDisconnect(error, closeCode)
|
|
11284
|
+
});
|
|
11285
|
+
this._transport.setMetaObserver((meta) => {
|
|
11286
|
+
void this._observeRpcMeta(meta).catch((exc) => {
|
|
11287
|
+
this._clientLog.debug(`agent.md meta observer skipped: ${String(exc)}`);
|
|
11288
|
+
});
|
|
11289
|
+
});
|
|
11290
|
+
this._auth.setLogger(this._logAuth);
|
|
11291
|
+
this._transport.setLogger(this._logTransport);
|
|
11292
|
+
this._dispatcher.setLogger(this._logEvents);
|
|
11293
|
+
if (typeof this._discovery.setLogger === "function") {
|
|
11294
|
+
this._discovery.setLogger(this._logDiscovery);
|
|
11295
|
+
}
|
|
11296
|
+
if (typeof this._keystore.setLogger === "function") {
|
|
11297
|
+
this._keystore.setLogger(this._logKeystore);
|
|
11298
|
+
}
|
|
11299
|
+
}
|
|
11216
11300
|
loadIdentity(aid) {
|
|
11217
11301
|
if (!aid?.isPrivateKeyValid()) throw new StateError("loadIdentity requires an AID with a valid private key");
|
|
11218
11302
|
const publicState = this.state;
|
|
11219
11303
|
if (publicState !== "no_identity" /* NO_IDENTITY */ && publicState !== "closed" /* CLOSED */) {
|
|
11220
11304
|
throw new StateError(`loadIdentity not allowed in state ${publicState}`);
|
|
11221
11305
|
}
|
|
11306
|
+
this._applyAidRuntimeContext(aid);
|
|
11222
11307
|
this._currentAid = aid;
|
|
11223
11308
|
this._aid = aid.aid;
|
|
11224
11309
|
this._identity = {
|
|
11225
11310
|
aid: aid.aid,
|
|
11226
|
-
private_key_pem: aid.
|
|
11311
|
+
private_key_pem: aid.privateKeyPem,
|
|
11227
11312
|
public_key_der_b64: aid.publicKey,
|
|
11228
11313
|
cert: aid.certPem
|
|
11229
11314
|
};
|
|
11230
|
-
this._auth._aid = aid.aid;
|
|
11231
11315
|
this._state = "disconnected";
|
|
11232
11316
|
this._closing = false;
|
|
11233
11317
|
}
|
|
@@ -11271,9 +11355,6 @@ var _AUNClient = class _AUNClient {
|
|
|
11271
11355
|
get gatewayUrl() {
|
|
11272
11356
|
return this._gatewayUrl;
|
|
11273
11357
|
}
|
|
11274
|
-
set gatewayUrl(url) {
|
|
11275
|
-
this._gatewayUrl = url;
|
|
11276
|
-
}
|
|
11277
11358
|
get discovery() {
|
|
11278
11359
|
return this._discovery;
|
|
11279
11360
|
}
|
|
@@ -11314,6 +11395,17 @@ var _AUNClient = class _AUNClient {
|
|
|
11314
11395
|
/** 连接到 Gateway;身份来自构造函数或 loadIdentity(aid),认证由 SDK 内部自动完成。 */
|
|
11315
11396
|
async connect(opts) {
|
|
11316
11397
|
const tStart = Date.now();
|
|
11398
|
+
if (opts !== void 0 && opts !== null && typeof opts === "object") {
|
|
11399
|
+
const raw = opts;
|
|
11400
|
+
const invalid = Object.keys(raw).filter((key) => !PUBLIC_CONNECTION_OPTION_KEYS.has(key)).sort();
|
|
11401
|
+
if (invalid.length > 0) {
|
|
11402
|
+
throw new ValidationError(`connect options contain unsupported field(s): ${invalid.join(", ")}`);
|
|
11403
|
+
}
|
|
11404
|
+
}
|
|
11405
|
+
const target = this._currentAid?.aid ?? this._aid ?? "";
|
|
11406
|
+
if (!target || !this._currentAid?.isPrivateKeyValid()) {
|
|
11407
|
+
throw new StateError("connect requires a loaded AID with a valid private key");
|
|
11408
|
+
}
|
|
11317
11409
|
const options = {};
|
|
11318
11410
|
if (opts?.auto_reconnect !== void 0) options.auto_reconnect = opts.auto_reconnect;
|
|
11319
11411
|
if (opts?.heartbeat_interval !== void 0) options.heartbeat_interval = opts.heartbeat_interval;
|
|
@@ -11330,11 +11422,12 @@ var _AUNClient = class _AUNClient {
|
|
|
11330
11422
|
max_attempts: opts.retry_max_attempts ?? 0
|
|
11331
11423
|
};
|
|
11332
11424
|
}
|
|
11425
|
+
if (opts?.connection_kind !== void 0) options.connection_kind = opts.connection_kind;
|
|
11426
|
+
if (opts?.short_ttl_ms !== void 0) options.short_ttl_ms = opts.short_ttl_ms;
|
|
11427
|
+
if (opts?.delivery_mode !== void 0) options.delivery_mode = opts.delivery_mode;
|
|
11428
|
+
if (opts?.extra_info !== void 0) options.extra_info = opts.extra_info;
|
|
11429
|
+
if (opts?.background_sync !== void 0) options.background_sync = opts.background_sync;
|
|
11333
11430
|
this._clientLog.debug(`connect enter: state=${this._state} aid=${this._aid ?? "-"}`);
|
|
11334
|
-
const target = this._currentAid?.aid ?? this._aid ?? "";
|
|
11335
|
-
if (!target || !this._currentAid?.isPrivateKeyValid()) {
|
|
11336
|
-
throw new StateError("connect requires a loaded AID with a valid private key");
|
|
11337
|
-
}
|
|
11338
11431
|
const publicState = this.state;
|
|
11339
11432
|
const allowed = /* @__PURE__ */ new Set([
|
|
11340
11433
|
"standby" /* STANDBY */,
|
|
@@ -11468,6 +11561,12 @@ var _AUNClient = class _AUNClient {
|
|
|
11468
11561
|
}
|
|
11469
11562
|
this._validateOutboundCall(method, p);
|
|
11470
11563
|
this._injectMessageCursorContext(method, p);
|
|
11564
|
+
if (method.startsWith("group.") && !("_group_cursor_params" in p) && !Boolean(p._pull_gate_locked)) {
|
|
11565
|
+
const explicitCursorParams = this._groupCursorParams(p);
|
|
11566
|
+
if (Object.keys(explicitCursorParams).length > 0) {
|
|
11567
|
+
p._group_cursor_params = explicitCursorParams;
|
|
11568
|
+
}
|
|
11569
|
+
}
|
|
11471
11570
|
if (method.startsWith("group.") && p.group_id !== void 0 && p.group_id !== null) {
|
|
11472
11571
|
const rawGroupId = String(p.group_id);
|
|
11473
11572
|
const normalizedGroupId = normalizeGroupId(rawGroupId);
|
|
@@ -11486,9 +11585,10 @@ var _AUNClient = class _AUNClient {
|
|
|
11486
11585
|
const encrypt = p.encrypt !== void 0 ? p.encrypt : true;
|
|
11487
11586
|
delete p.encrypt;
|
|
11488
11587
|
if (encrypt) {
|
|
11489
|
-
|
|
11490
|
-
|
|
11491
|
-
|
|
11588
|
+
await this._ensureV2SessionReady(
|
|
11589
|
+
"message.send",
|
|
11590
|
+
"V2 session not initialized; encrypted message.send requires V2 (V1 E2EE removed)"
|
|
11591
|
+
);
|
|
11492
11592
|
this._clientLog.debug("call route: message.send \u2192 V2 encrypted send");
|
|
11493
11593
|
return await this._sendV2(String(p.to ?? ""), p.payload ?? {}, {
|
|
11494
11594
|
messageId: String(p.message_id ?? "") || void 0,
|
|
@@ -11503,9 +11603,10 @@ var _AUNClient = class _AUNClient {
|
|
|
11503
11603
|
const encrypt = p.encrypt !== void 0 ? p.encrypt : true;
|
|
11504
11604
|
delete p.encrypt;
|
|
11505
11605
|
if (encrypt) {
|
|
11506
|
-
|
|
11507
|
-
|
|
11508
|
-
|
|
11606
|
+
await this._ensureV2SessionReady(
|
|
11607
|
+
"group.send",
|
|
11608
|
+
"V2 session not initialized; encrypted group.send requires V2 (V1 E2EE removed)"
|
|
11609
|
+
);
|
|
11509
11610
|
this._clientLog.debug("call route: group.send \u2192 V2 encrypted send");
|
|
11510
11611
|
return await this._sendGroupV2(String(p.group_id ?? ""), p.payload ?? {}, {
|
|
11511
11612
|
messageId: String(p.message_id ?? "") || void 0,
|
|
@@ -11520,9 +11621,10 @@ var _AUNClient = class _AUNClient {
|
|
|
11520
11621
|
const encrypt = p.encrypt !== void 0 ? p.encrypt : true;
|
|
11521
11622
|
delete p.encrypt;
|
|
11522
11623
|
if (encrypt) {
|
|
11523
|
-
|
|
11524
|
-
|
|
11525
|
-
|
|
11624
|
+
await this._ensureV2SessionReady(
|
|
11625
|
+
"group.thought.put",
|
|
11626
|
+
"V2 session not initialized; encrypted group.thought.put requires V2 (V1 E2EE removed)"
|
|
11627
|
+
);
|
|
11526
11628
|
this._clientLog.debug("call route: group.thought.put \u2192 V2 encrypted put");
|
|
11527
11629
|
return this._putGroupThoughtEncryptedV2(p);
|
|
11528
11630
|
}
|
|
@@ -11531,9 +11633,10 @@ var _AUNClient = class _AUNClient {
|
|
|
11531
11633
|
const encrypt = p.encrypt !== void 0 ? p.encrypt : true;
|
|
11532
11634
|
delete p.encrypt;
|
|
11533
11635
|
if (encrypt) {
|
|
11534
|
-
|
|
11535
|
-
|
|
11536
|
-
|
|
11636
|
+
await this._ensureV2SessionReady(
|
|
11637
|
+
"message.thought.put",
|
|
11638
|
+
"V2 session not initialized; encrypted message.thought.put requires V2 (V1 E2EE removed)"
|
|
11639
|
+
);
|
|
11537
11640
|
this._clientLog.debug("call route: message.thought.put \u2192 V2 encrypted put");
|
|
11538
11641
|
return this._putMessageThoughtEncryptedV2(p);
|
|
11539
11642
|
}
|
|
@@ -11551,26 +11654,43 @@ var _AUNClient = class _AUNClient {
|
|
|
11551
11654
|
* 拆分出来以便 pull gate 包裹整个操作。
|
|
11552
11655
|
*/
|
|
11553
11656
|
async _callImplInner(method, p) {
|
|
11554
|
-
if (method === "message.pull"
|
|
11657
|
+
if (method === "message.pull") {
|
|
11658
|
+
await this._ensureV2SessionReady("message.pull");
|
|
11555
11659
|
this._clientLog.debug("call route: message.pull \u2192 V2 pull");
|
|
11556
11660
|
const messages = await this._pullV2(Number(p.after_seq ?? 0) || 0, Number(p.limit ?? 50) || 50, { force: p.force === true });
|
|
11557
11661
|
return { messages };
|
|
11558
11662
|
}
|
|
11559
|
-
if (method === "message.ack"
|
|
11663
|
+
if (method === "message.ack") {
|
|
11664
|
+
await this._ensureV2SessionReady("message.ack");
|
|
11560
11665
|
this._clientLog.debug("call route: message.ack \u2192 V2 ack");
|
|
11561
11666
|
return await this._ackV2(Number(p.seq ?? p.up_to_seq ?? 0) || void 0);
|
|
11562
11667
|
}
|
|
11563
|
-
if (method === "group.pull" &&
|
|
11668
|
+
if (method === "group.pull" && p.group_id) {
|
|
11669
|
+
await this._ensureV2SessionReady("group.pull");
|
|
11564
11670
|
this._clientLog.debug("call route: group.pull \u2192 V2 pull");
|
|
11671
|
+
const hasExplicitAfterSeq = "after_seq" in p || "after_message_seq" in p;
|
|
11672
|
+
const cursorParams = this._explicitGroupCursorParams(p);
|
|
11673
|
+
const ownsCursor = Object.keys(cursorParams).length === 0 || this._groupCursorTargetsCurrentInstance(cursorParams);
|
|
11674
|
+
const pullOpts = {};
|
|
11675
|
+
if (hasExplicitAfterSeq) pullOpts.explicitAfterSeq = true;
|
|
11676
|
+
if (Object.keys(cursorParams).length > 0) pullOpts.cursorParams = cursorParams;
|
|
11677
|
+
if (!ownsCursor) pullOpts.ownsCursor = false;
|
|
11565
11678
|
const messages = await this._pullGroupV2(
|
|
11566
11679
|
String(p.group_id),
|
|
11567
11680
|
Number(p.after_seq ?? p.after_message_seq ?? 0) || 0,
|
|
11568
|
-
Number(p.limit ?? 50) || 50
|
|
11681
|
+
Number(p.limit ?? 50) || 50,
|
|
11682
|
+
Object.keys(pullOpts).length > 0 ? pullOpts : void 0
|
|
11569
11683
|
);
|
|
11570
11684
|
return { messages };
|
|
11571
11685
|
}
|
|
11572
|
-
if (method === "group.ack_messages" &&
|
|
11686
|
+
if (method === "group.ack_messages" && p.group_id) {
|
|
11687
|
+
await this._ensureV2SessionReady("group.ack_messages");
|
|
11573
11688
|
this._clientLog.debug("call route: group.ack_messages \u2192 V2 ack");
|
|
11689
|
+
const cursorParams = this._explicitGroupCursorParams(p);
|
|
11690
|
+
const ownsCursor = Object.keys(cursorParams).length === 0 || this._groupCursorTargetsCurrentInstance(cursorParams);
|
|
11691
|
+
if (!ownsCursor) {
|
|
11692
|
+
return await this._rawGroupAckMessages(p);
|
|
11693
|
+
}
|
|
11574
11694
|
return await this._ackGroupV2(
|
|
11575
11695
|
String(p.group_id),
|
|
11576
11696
|
Number(p.seq ?? p.msg_seq ?? p.up_to_seq ?? 0) || void 0
|
|
@@ -11671,6 +11791,7 @@ var _AUNClient = class _AUNClient {
|
|
|
11671
11791
|
delete p._pull_gate_locked;
|
|
11672
11792
|
delete p._skip_auto_ack;
|
|
11673
11793
|
delete p.skip_auto_ack;
|
|
11794
|
+
delete p._group_cursor_params;
|
|
11674
11795
|
if (method.startsWith("group.") && p.group_id !== void 0 && p.group_id !== null) {
|
|
11675
11796
|
p.group_id = normalizeGroupId(String(p.group_id)) || String(p.group_id);
|
|
11676
11797
|
}
|
|
@@ -12000,54 +12121,27 @@ var _AUNClient = class _AUNClient {
|
|
|
12000
12121
|
/** 后台补齐群消息空洞 */
|
|
12001
12122
|
async _fillGroupGap(groupId) {
|
|
12002
12123
|
if (this._state !== "connected" || this._closing) return;
|
|
12124
|
+
groupId = normalizeGroupId(groupId) || String(groupId ?? "").trim();
|
|
12125
|
+
if (!groupId) return;
|
|
12003
12126
|
const ns = `group:${groupId}`;
|
|
12004
12127
|
const afterSeq = this._seqTracker.getContiguousSeq(ns);
|
|
12005
12128
|
const dedupKey = `group_pull:${ns}`;
|
|
12006
12129
|
if (this._gapFillDone.has(dedupKey)) return;
|
|
12007
12130
|
this._gapFillDone.add(dedupKey);
|
|
12008
12131
|
this._gapFillActive = true;
|
|
12132
|
+
let filled = 0;
|
|
12009
12133
|
try {
|
|
12010
|
-
const
|
|
12011
|
-
|
|
12012
|
-
|
|
12013
|
-
device_id: this._deviceId,
|
|
12014
|
-
limit: 50
|
|
12015
|
-
});
|
|
12016
|
-
if (isJsonObject(result)) {
|
|
12017
|
-
const messages = result.messages;
|
|
12018
|
-
if (Array.isArray(messages)) {
|
|
12019
|
-
const pushed = this._pushedSeqs.get(ns);
|
|
12020
|
-
for (const msg of messages) {
|
|
12021
|
-
if (isJsonObject(msg)) {
|
|
12022
|
-
const s = msg.seq;
|
|
12023
|
-
if (pushed && s !== void 0 && s !== null && pushed.has(s)) continue;
|
|
12024
|
-
if (s !== void 0 && s !== null) {
|
|
12025
|
-
await this._publishPulledMessage("group.message_created", ns, s, msg);
|
|
12026
|
-
} else {
|
|
12027
|
-
await this._publishAppEvent("group.message_created", msg);
|
|
12028
|
-
}
|
|
12029
|
-
}
|
|
12030
|
-
}
|
|
12031
|
-
this._prunePushedSeqs(ns);
|
|
12032
|
-
const contig = this._seqTracker.getContiguousSeq(ns);
|
|
12033
|
-
if (contig > 0) {
|
|
12034
|
-
const gid = groupId;
|
|
12035
|
-
this._transport.call("group.ack_messages", {
|
|
12036
|
-
group_id: gid,
|
|
12037
|
-
msg_seq: contig,
|
|
12038
|
-
device_id: this._deviceId,
|
|
12039
|
-
slot_id: this._slotId
|
|
12040
|
-
}).catch((e) => {
|
|
12041
|
-
this._clientLog.warn(`group gap-fill auto-ack failed: group=${gid}`, e);
|
|
12042
|
-
});
|
|
12043
|
-
}
|
|
12044
|
-
}
|
|
12045
|
-
}
|
|
12134
|
+
const messages = await this._pullGroupV2(groupId, afterSeq, 50);
|
|
12135
|
+
filled = messages.length;
|
|
12136
|
+
this._prunePushedSeqs(ns);
|
|
12046
12137
|
} catch (exc) {
|
|
12047
12138
|
this._clientLog.warn(`group message gap-fill failed:${String(exc)}`);
|
|
12048
12139
|
} finally {
|
|
12049
12140
|
this._gapFillDone.delete(dedupKey);
|
|
12050
12141
|
this._gapFillActive = false;
|
|
12142
|
+
if (filled > 0 && this._seqTracker.getContiguousSeq(ns) > afterSeq) {
|
|
12143
|
+
this._safeAsync(this._fillGroupGap(groupId));
|
|
12144
|
+
}
|
|
12051
12145
|
}
|
|
12052
12146
|
}
|
|
12053
12147
|
/** 后台补齐群事件空洞 */
|
|
@@ -12145,44 +12239,19 @@ var _AUNClient = class _AUNClient {
|
|
|
12145
12239
|
if (this._gapFillDone.has(dedupKey)) return;
|
|
12146
12240
|
this._gapFillDone.add(dedupKey);
|
|
12147
12241
|
this._gapFillActive = true;
|
|
12242
|
+
let filled = 0;
|
|
12148
12243
|
try {
|
|
12149
|
-
const
|
|
12150
|
-
|
|
12151
|
-
|
|
12152
|
-
});
|
|
12153
|
-
if (isJsonObject(result)) {
|
|
12154
|
-
const messages = result.messages;
|
|
12155
|
-
if (Array.isArray(messages)) {
|
|
12156
|
-
const pushed = this._pushedSeqs.get(ns);
|
|
12157
|
-
for (const msg of messages) {
|
|
12158
|
-
if (isJsonObject(msg)) {
|
|
12159
|
-
const s = msg.seq;
|
|
12160
|
-
if (pushed && s !== void 0 && s !== null && pushed.has(s)) continue;
|
|
12161
|
-
if (s !== void 0 && s !== null) {
|
|
12162
|
-
await this._publishPulledMessage("message.received", ns, s, msg);
|
|
12163
|
-
} else {
|
|
12164
|
-
await this._publishAppEvent("message.received", msg);
|
|
12165
|
-
}
|
|
12166
|
-
}
|
|
12167
|
-
}
|
|
12168
|
-
this._prunePushedSeqs(ns);
|
|
12169
|
-
const contig = this._seqTracker.getContiguousSeq(ns);
|
|
12170
|
-
if (contig > 0) {
|
|
12171
|
-
this._transport.call("message.ack", {
|
|
12172
|
-
seq: contig,
|
|
12173
|
-
device_id: this._deviceId,
|
|
12174
|
-
slot_id: this._slotId
|
|
12175
|
-
}).catch((e) => {
|
|
12176
|
-
this._clientLog.warn(`P2P gap-fill auto-ack failed:${String(e)}`);
|
|
12177
|
-
});
|
|
12178
|
-
}
|
|
12179
|
-
}
|
|
12180
|
-
}
|
|
12244
|
+
const messages = await this._pullV2(afterSeq, 50);
|
|
12245
|
+
filled = messages.length;
|
|
12246
|
+
this._prunePushedSeqs(ns);
|
|
12181
12247
|
} catch (exc) {
|
|
12182
12248
|
this._clientLog.warn(`P2P message gap-fill failed:${String(exc)}`);
|
|
12183
12249
|
} finally {
|
|
12184
12250
|
this._gapFillDone.delete(dedupKey);
|
|
12185
12251
|
this._gapFillActive = false;
|
|
12252
|
+
if (filled > 0 && this._seqTracker.getContiguousSeq(ns) > afterSeq) {
|
|
12253
|
+
this._safeAsync(this._fillP2pGap());
|
|
12254
|
+
}
|
|
12186
12255
|
}
|
|
12187
12256
|
}
|
|
12188
12257
|
/** 只按硬上限裁剪 published guard,不能按 contiguousSeq 清理。 */
|
|
@@ -12304,7 +12373,7 @@ var _AUNClient = class _AUNClient {
|
|
|
12304
12373
|
}
|
|
12305
12374
|
if ("slot_id" in message) {
|
|
12306
12375
|
const targetSlotId = String(message.slot_id ?? "").trim();
|
|
12307
|
-
if (targetSlotId !== this._slotId) {
|
|
12376
|
+
if (slotIsolationKey(targetSlotId) !== slotIsolationKey(this._slotId)) {
|
|
12308
12377
|
return false;
|
|
12309
12378
|
}
|
|
12310
12379
|
}
|
|
@@ -13025,10 +13094,10 @@ var _AUNClient = class _AUNClient {
|
|
|
13025
13094
|
* 使用 SubtleCrypto 异步签名。
|
|
13026
13095
|
*/
|
|
13027
13096
|
async _signClientOperation(method, params) {
|
|
13028
|
-
const
|
|
13029
|
-
if (!
|
|
13097
|
+
const currentAid = this._currentAid;
|
|
13098
|
+
if (!currentAid?.privateKeyPem) return;
|
|
13030
13099
|
try {
|
|
13031
|
-
const aid =
|
|
13100
|
+
const aid = currentAid.aid;
|
|
13032
13101
|
const ts = String(Math.floor(Date.now() / 1e3));
|
|
13033
13102
|
const paramsForHash = {};
|
|
13034
13103
|
for (const [k, v] of Object.entries(params)) {
|
|
@@ -13043,7 +13112,7 @@ var _AUNClient = class _AUNClient {
|
|
|
13043
13112
|
);
|
|
13044
13113
|
const paramsHash = Array.from(new Uint8Array(paramsHashBuf)).map((b) => b.toString(16).padStart(2, "0")).join("");
|
|
13045
13114
|
const signData = new TextEncoder().encode(`${method}|${aid}|${ts}|${paramsHash}`);
|
|
13046
|
-
const pkcs8 = pemToArrayBuffer(
|
|
13115
|
+
const pkcs8 = pemToArrayBuffer(currentAid.privateKeyPem);
|
|
13047
13116
|
const cryptoKey = await crypto.subtle.importKey(
|
|
13048
13117
|
"pkcs8",
|
|
13049
13118
|
pkcs8,
|
|
@@ -13058,7 +13127,7 @@ var _AUNClient = class _AUNClient {
|
|
|
13058
13127
|
);
|
|
13059
13128
|
const sigDer = p1363ToDer(new Uint8Array(sigP1363));
|
|
13060
13129
|
let certFingerprint = "";
|
|
13061
|
-
const certPem =
|
|
13130
|
+
const certPem = currentAid.certPem;
|
|
13062
13131
|
if (certPem) {
|
|
13063
13132
|
const certDer = pemToArrayBuffer(certPem);
|
|
13064
13133
|
const fpBuf = await crypto.subtle.digest("SHA-256", certDer);
|
|
@@ -13158,12 +13227,22 @@ var _AUNClient = class _AUNClient {
|
|
|
13158
13227
|
await this._restoreSeqTrackerState();
|
|
13159
13228
|
}
|
|
13160
13229
|
this._startBackgroundTasks();
|
|
13161
|
-
|
|
13162
|
-
|
|
13163
|
-
|
|
13164
|
-
|
|
13230
|
+
const connectionKind = String(params.connection_kind ?? "long");
|
|
13231
|
+
const isShortConnection = connectionKind === "short";
|
|
13232
|
+
if (!isShortConnection) {
|
|
13233
|
+
try {
|
|
13234
|
+
await this._initV2Session();
|
|
13235
|
+
} catch (exc) {
|
|
13236
|
+
this._clientLog.warn(`V2 session init failed (non-fatal): ${String(exc)}`);
|
|
13237
|
+
}
|
|
13238
|
+
} else {
|
|
13239
|
+
this._clientLog.debug("V2 session init deferred for short connection");
|
|
13240
|
+
}
|
|
13241
|
+
const hasExplicitBackgroundSync = Object.prototype.hasOwnProperty.call(params, "background_sync");
|
|
13242
|
+
const backgroundSyncEnabled = this._sessionOptions?.background_sync !== false && (!isShortConnection || hasExplicitBackgroundSync);
|
|
13243
|
+
if (backgroundSyncEnabled) {
|
|
13244
|
+
this._safeAsync(this._fillP2pGap());
|
|
13165
13245
|
}
|
|
13166
|
-
this._safeAsync(this._fillP2pGap());
|
|
13167
13246
|
this._clientLog.debug(`_connectOnce exit: elapsed=${Date.now() - tStart}ms aid=${this._aid ?? "-"}`);
|
|
13168
13247
|
} catch (err) {
|
|
13169
13248
|
this._clientLog.debug(`_connectOnce exit (error): elapsed=${Date.now() - tStart}ms err=${err instanceof Error ? err.message : String(err)}`);
|
|
@@ -13268,7 +13347,7 @@ var _AUNClient = class _AUNClient {
|
|
|
13268
13347
|
else delete request.access_token;
|
|
13269
13348
|
request.gateway = gateway;
|
|
13270
13349
|
request.device_id = this._deviceId;
|
|
13271
|
-
request.slot_id =
|
|
13350
|
+
request.slot_id = normalizeSlotId(request.slot_id ?? this._slotId, this._slotId || "default");
|
|
13272
13351
|
let deliveryModeRaw = request.delivery_mode;
|
|
13273
13352
|
if (deliveryModeRaw == null) {
|
|
13274
13353
|
deliveryModeRaw = { ...this._defaultConnectDeliveryMode };
|
|
@@ -13338,6 +13417,7 @@ var _AUNClient = class _AUNClient {
|
|
|
13338
13417
|
if (isJsonObject(params.timeouts)) {
|
|
13339
13418
|
Object.assign(options.timeouts, params.timeouts);
|
|
13340
13419
|
}
|
|
13420
|
+
if ("background_sync" in params) options.background_sync = Boolean(params.background_sync);
|
|
13341
13421
|
return options;
|
|
13342
13422
|
}
|
|
13343
13423
|
// ── 内部:后台任务 ────────────────────────────────
|
|
@@ -14039,6 +14119,19 @@ var _AUNClient = class _AUNClient {
|
|
|
14039
14119
|
);
|
|
14040
14120
|
return repaired;
|
|
14041
14121
|
}
|
|
14122
|
+
async _ensureV2SessionReady(method, errorMessage) {
|
|
14123
|
+
if (!this._v2Session) {
|
|
14124
|
+
if (!this._v2SessionInitInFlight) {
|
|
14125
|
+
this._v2SessionInitInFlight = this._initV2Session().finally(() => {
|
|
14126
|
+
this._v2SessionInitInFlight = null;
|
|
14127
|
+
});
|
|
14128
|
+
}
|
|
14129
|
+
await this._v2SessionInitInFlight;
|
|
14130
|
+
}
|
|
14131
|
+
if (!this._v2Session) {
|
|
14132
|
+
throw new StateError(errorMessage ?? `V2 session not initialized; encrypted ${method} requires E2EE V2`);
|
|
14133
|
+
}
|
|
14134
|
+
}
|
|
14042
14135
|
// ── V2 E2EE API(async,与 Python `client.py` `_init_v2_session` / `send_v2` / `pull_v2` / `ack_v2` 对齐) ──
|
|
14043
14136
|
/**
|
|
14044
14137
|
* 初始化 V2 session:从 AID PEM 私钥提取 raw scalar + DER 公钥,
|
|
@@ -14048,31 +14141,13 @@ var _AUNClient = class _AUNClient {
|
|
|
14048
14141
|
*/
|
|
14049
14142
|
async _initV2Session() {
|
|
14050
14143
|
if (!this._aid) return;
|
|
14051
|
-
|
|
14052
|
-
if (!
|
|
14053
|
-
try {
|
|
14054
|
-
const reloaded = await this._keystore.loadIdentity(this._aid);
|
|
14055
|
-
if (reloaded?.private_key_pem) {
|
|
14056
|
-
this._identity = reloaded;
|
|
14057
|
-
identity = reloaded;
|
|
14058
|
-
this._clientLog.warn("V2 session init: identity cache was stale, reloaded from keystore");
|
|
14059
|
-
try {
|
|
14060
|
-
const persistIdentity = this._auth._persistIdentity;
|
|
14061
|
-
if (typeof persistIdentity === "function") {
|
|
14062
|
-
await persistIdentity.call(this._auth, reloaded);
|
|
14063
|
-
}
|
|
14064
|
-
} catch {
|
|
14065
|
-
}
|
|
14066
|
-
}
|
|
14067
|
-
} catch {
|
|
14068
|
-
}
|
|
14069
|
-
}
|
|
14070
|
-
if (!identity?.private_key_pem) {
|
|
14144
|
+
const currentAid = this._currentAid;
|
|
14145
|
+
if (!currentAid?.privateKeyPem) {
|
|
14071
14146
|
this._clientLog.warn("V2 session init skipped: no AID private key");
|
|
14072
14147
|
return;
|
|
14073
14148
|
}
|
|
14074
14149
|
if (this._v2Session) return;
|
|
14075
|
-
const pem =
|
|
14150
|
+
const pem = currentAid.privateKeyPem.trim();
|
|
14076
14151
|
const pemBody = pem.replace(/-----BEGIN [^-]+-----/g, "").replace(/-----END [^-]+-----/g, "").replace(/\s+/g, "");
|
|
14077
14152
|
const pkcs8Der = _v2B64ToBytes(pemBody);
|
|
14078
14153
|
const privKey = await crypto.subtle.importKey(
|
|
@@ -14444,6 +14519,7 @@ var _AUNClient = class _AUNClient {
|
|
|
14444
14519
|
decrypted.push(plaintext);
|
|
14445
14520
|
}
|
|
14446
14521
|
}
|
|
14522
|
+
const hasServerAckSeq = Object.prototype.hasOwnProperty.call(result, "server_ack_seq");
|
|
14447
14523
|
const serverAckSeq = Number(result.server_ack_seq ?? 0);
|
|
14448
14524
|
if (ns && Number.isFinite(serverAckSeq) && serverAckSeq > 0) {
|
|
14449
14525
|
const contig = this._seqTracker.getContiguousSeq(ns);
|
|
@@ -14459,7 +14535,8 @@ var _AUNClient = class _AUNClient {
|
|
|
14459
14535
|
await this._drainOrderedMessages(ns);
|
|
14460
14536
|
this._saveSeqTrackerState();
|
|
14461
14537
|
}
|
|
14462
|
-
|
|
14538
|
+
const ackNeeded = messages.length > 0 && ackSeq > 0 && (contigAdvanced || hasServerAckSeq && ackSeq > serverAckSeq);
|
|
14539
|
+
if (ackNeeded) {
|
|
14463
14540
|
this._safeAsync(this._ackV2(ackSeq).then(() => void 0));
|
|
14464
14541
|
}
|
|
14465
14542
|
}
|
|
@@ -14488,7 +14565,7 @@ var _AUNClient = class _AUNClient {
|
|
|
14488
14565
|
seq = maxSeen;
|
|
14489
14566
|
}
|
|
14490
14567
|
}
|
|
14491
|
-
const raw = await this.
|
|
14568
|
+
const raw = await this._callRawV2Rpc("message.v2.ack", { up_to_seq: seq });
|
|
14492
14569
|
const result = isJsonObject(raw) ? { ...raw } : { result: raw };
|
|
14493
14570
|
let actualAckSeq = seq;
|
|
14494
14571
|
if ("effective_ack_seq" in result) actualAckSeq = Number(result.effective_ack_seq ?? 0);
|
|
@@ -14758,7 +14835,7 @@ var _AUNClient = class _AUNClient {
|
|
|
14758
14835
|
* @param afterSeq 从此 seq 之后开始拉取(0/省略 = 从当前 contiguous 开始)
|
|
14759
14836
|
* @param limit 最多拉取条数
|
|
14760
14837
|
*/
|
|
14761
|
-
async _pullGroupV2(groupId, afterSeq = 0, limit = 50) {
|
|
14838
|
+
async _pullGroupV2(groupId, afterSeq = 0, limit = 50, opts) {
|
|
14762
14839
|
if (!this._v2Session) {
|
|
14763
14840
|
throw new StateError("V2 session not initialized (not connected?)");
|
|
14764
14841
|
}
|
|
@@ -14766,15 +14843,18 @@ var _AUNClient = class _AUNClient {
|
|
|
14766
14843
|
if (!gid) throw new ValidationError("group.pull requires group_id");
|
|
14767
14844
|
const ns = `group:${gid}`;
|
|
14768
14845
|
const decrypted = [];
|
|
14769
|
-
|
|
14846
|
+
const cursorParams = opts?.cursorParams ?? {};
|
|
14847
|
+
const ownsCursor = opts?.ownsCursor !== false;
|
|
14848
|
+
let nextAfterSeq = opts?.explicitAfterSeq ? afterSeq : afterSeq || this._seqTracker.getContiguousSeq(ns);
|
|
14770
14849
|
let pageCount = 0;
|
|
14771
14850
|
const maxPages = 100;
|
|
14772
14851
|
while (pageCount < maxPages) {
|
|
14773
14852
|
pageCount += 1;
|
|
14774
|
-
const result = await this.
|
|
14853
|
+
const result = await this._callRawV2Rpc("group.v2.pull", {
|
|
14775
14854
|
group_id: gid,
|
|
14776
14855
|
after_seq: nextAfterSeq,
|
|
14777
|
-
limit
|
|
14856
|
+
limit,
|
|
14857
|
+
...cursorParams
|
|
14778
14858
|
});
|
|
14779
14859
|
const messages = Array.isArray(result?.messages) ? result.messages : [];
|
|
14780
14860
|
const seqs = messages.map((msg) => Number(msg.seq ?? 0)).filter((seq) => Number.isFinite(seq) && seq > 0);
|
|
@@ -14836,6 +14916,7 @@ var _AUNClient = class _AUNClient {
|
|
|
14836
14916
|
decrypted.push(plaintext);
|
|
14837
14917
|
}
|
|
14838
14918
|
const cursor = isJsonObject(result.cursor) ? result.cursor : null;
|
|
14919
|
+
const hasServerCursor = cursor !== null && Object.prototype.hasOwnProperty.call(cursor, "current_seq");
|
|
14839
14920
|
const serverAckSeq = Number(cursor?.current_seq ?? 0);
|
|
14840
14921
|
if (Number.isFinite(serverAckSeq) && serverAckSeq > 0) {
|
|
14841
14922
|
const contig = this._seqTracker.getContiguousSeq(ns);
|
|
@@ -14850,10 +14931,12 @@ var _AUNClient = class _AUNClient {
|
|
|
14850
14931
|
await this._drainOrderedMessages(ns);
|
|
14851
14932
|
this._saveSeqTrackerState();
|
|
14852
14933
|
}
|
|
14853
|
-
|
|
14934
|
+
const ackNeeded = messages.length > 0 && ackSeq > 0 && ownsCursor && (contigAdvanced || hasServerCursor && ackSeq > serverAckSeq);
|
|
14935
|
+
if (ackNeeded) {
|
|
14854
14936
|
this._safeAsync(this._ackGroupV2(gid, ackSeq).then(() => void 0));
|
|
14855
14937
|
}
|
|
14856
14938
|
const nextAfter = Math.max(pageMaxSeq, nextAfterSeq);
|
|
14939
|
+
if (!ownsCursor) break;
|
|
14857
14940
|
if (messages.length === 0 || nextAfter <= nextAfterSeq || result.has_more === false) break;
|
|
14858
14941
|
nextAfterSeq = nextAfter;
|
|
14859
14942
|
}
|
|
@@ -14862,6 +14945,28 @@ var _AUNClient = class _AUNClient {
|
|
|
14862
14945
|
}
|
|
14863
14946
|
return decrypted;
|
|
14864
14947
|
}
|
|
14948
|
+
_groupCursorParams(params) {
|
|
14949
|
+
const cursorParams = {};
|
|
14950
|
+
for (const key of ["device_id", "slot_id", "device_name", "device_type"]) {
|
|
14951
|
+
const value = params[key];
|
|
14952
|
+
if (value !== void 0 && value !== null) cursorParams[key] = value;
|
|
14953
|
+
}
|
|
14954
|
+
return cursorParams;
|
|
14955
|
+
}
|
|
14956
|
+
_explicitGroupCursorParams(params) {
|
|
14957
|
+
const value = params._group_cursor_params;
|
|
14958
|
+
if (!isJsonObject(value)) return {};
|
|
14959
|
+
return { ...value };
|
|
14960
|
+
}
|
|
14961
|
+
_groupCursorTargetsCurrentInstance(params) {
|
|
14962
|
+
const deviceId = String(params.device_id ?? "").trim();
|
|
14963
|
+
const slotId = String(params.slot_id ?? "").trim();
|
|
14964
|
+
return (!deviceId || deviceId === (this._deviceId ?? "")) && (!slotId || slotId === (this._slotId ?? ""));
|
|
14965
|
+
}
|
|
14966
|
+
async _rawGroupAckMessages(params) {
|
|
14967
|
+
const p = { ...params };
|
|
14968
|
+
return await this._callRawV2Rpc("group.ack_messages", p);
|
|
14969
|
+
}
|
|
14865
14970
|
/**
|
|
14866
14971
|
* 确认 V2 群消息已消费。
|
|
14867
14972
|
*
|
|
@@ -14879,7 +14984,7 @@ var _AUNClient = class _AUNClient {
|
|
|
14879
14984
|
this._clientLog.warn(`ackGroupV2 clamp: group=${gid} up_to_seq=${seq} > max_seen=${maxSeen}, clamp`);
|
|
14880
14985
|
seq = maxSeen;
|
|
14881
14986
|
}
|
|
14882
|
-
return this.
|
|
14987
|
+
return this._callRawV2Rpc("group.v2.ack", { group_id: gid, up_to_seq: seq });
|
|
14883
14988
|
}
|
|
14884
14989
|
// ── V2 thought(per-device wrap,服务端透传,不持久化)──────────
|
|
14885
14990
|
/**
|
|
@@ -15638,8 +15743,8 @@ var _AUNClient = class _AUNClient {
|
|
|
15638
15743
|
return;
|
|
15639
15744
|
}
|
|
15640
15745
|
let signature = "";
|
|
15641
|
-
const
|
|
15642
|
-
if (
|
|
15746
|
+
const currentAid = this._currentAid;
|
|
15747
|
+
if (currentAid?.privateKeyPem) {
|
|
15643
15748
|
try {
|
|
15644
15749
|
const signPayloadObj = {
|
|
15645
15750
|
group_id: groupId,
|
|
@@ -15649,7 +15754,7 @@ var _AUNClient = class _AUNClient {
|
|
|
15649
15754
|
};
|
|
15650
15755
|
const signPayload = stableStringify(signPayloadObj);
|
|
15651
15756
|
const signPayloadBytes = new TextEncoder().encode(signPayload);
|
|
15652
|
-
const privKey = await importPrivateKeyEcdsa(
|
|
15757
|
+
const privKey = await importPrivateKeyEcdsa(currentAid.privateKeyPem);
|
|
15653
15758
|
const sigBytes = await ecdsaSignDer(privKey, signPayloadBytes);
|
|
15654
15759
|
signature = uint8ToBase64(sigBytes);
|
|
15655
15760
|
} catch (sigExc) {
|
|
@@ -15823,7 +15928,7 @@ var _AUNClient = class _AUNClient {
|
|
|
15823
15928
|
if (newContig > 0 && newContig !== contigBefore) {
|
|
15824
15929
|
const maxSeen = this._seqTracker.getMaxSeenSeq(ns);
|
|
15825
15930
|
const ackSeq = maxSeen > 0 ? Math.min(newContig, maxSeen) : newContig;
|
|
15826
|
-
this.
|
|
15931
|
+
this._callRawV2Rpc("message.v2.ack", { up_to_seq: ackSeq }).catch((e) => this._clientLog.debug(`V2 P2P push-ack failed: ${e}`));
|
|
15827
15932
|
}
|
|
15828
15933
|
this._clientLog.debug(
|
|
15829
15934
|
`_onV2PushNotification: push \u5E26 payload \u89E3\u5BC6\u6210\u529F, contiguous_seq=${contigBefore}->${newContig} push_seq=${pushSeq}`
|
|
@@ -16153,10 +16258,6 @@ function parseCertCN(certPem) {
|
|
|
16153
16258
|
return null;
|
|
16154
16259
|
}
|
|
16155
16260
|
}
|
|
16156
|
-
function normalizeSlotId(slotId) {
|
|
16157
|
-
const value = String(slotId ?? "default").trim();
|
|
16158
|
-
return value || "default";
|
|
16159
|
-
}
|
|
16160
16261
|
function issuerFromAid(aid) {
|
|
16161
16262
|
const target = String(aid ?? "").trim();
|
|
16162
16263
|
const dotIdx = target.indexOf(".");
|
|
@@ -16219,7 +16320,10 @@ var AIDStore = class {
|
|
|
16219
16320
|
this._encryptionSeed = String(opts.encryptionSeed ?? "");
|
|
16220
16321
|
this.deviceId = opts.deviceId ? normalizeInstanceId(opts.deviceId, "deviceId", { allowEmpty: true }) : getDeviceId();
|
|
16221
16322
|
this.slotId = normalizeSlotId(opts.slotId);
|
|
16222
|
-
|
|
16323
|
+
if (opts.verifySsl === false) {
|
|
16324
|
+
console.warn("[aun_core.config] verify_ssl=false \u5728\u6D4F\u89C8\u5668\u73AF\u5883\u4E2D\u4E0D\u53D7\u652F\u6301\uFF0CSSL \u8BC1\u4E66\u9A8C\u8BC1\u5C06\u4FDD\u6301\u542F\u7528\u3002");
|
|
16325
|
+
}
|
|
16326
|
+
this._verifySsl = opts.verifySsl === false ? true : opts.verifySsl ?? true;
|
|
16223
16327
|
this._keystore = new IndexedDBKeyStore({ encryptionSeed: this._encryptionSeed || void 0 });
|
|
16224
16328
|
this._crypto = new CryptoProvider();
|
|
16225
16329
|
this._discovery = new GatewayDiscovery();
|