@agentunion/fastaun-browser 0.4.3 → 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 -178
- 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 -194
- 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 -178
- 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 +1 -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 +1 -0
- 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/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 +237 -149
- package/dist/client.d.ts +7 -1
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +238 -153
- package/dist/client.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) => {
|
|
@@ -3142,6 +3142,9 @@ var _AuthFlow = class _AuthFlow {
|
|
|
3142
3142
|
delete persistedRecord[key];
|
|
3143
3143
|
}
|
|
3144
3144
|
}
|
|
3145
|
+
for (const key of ["private_key_pem", "public_key_der_b64", "curve"]) {
|
|
3146
|
+
delete persistedRecord[key];
|
|
3147
|
+
}
|
|
3145
3148
|
await this._keystore.saveIdentity(aid, persisted);
|
|
3146
3149
|
if (Object.keys(instanceState).length === 0 || typeof this._keystore.updateInstanceState !== "function") {
|
|
3147
3150
|
return;
|
|
@@ -9703,7 +9706,8 @@ var AID = class _AID {
|
|
|
9703
9706
|
__publicField(this, "verifySsl");
|
|
9704
9707
|
__publicField(this, "rootCaPath");
|
|
9705
9708
|
__publicField(this, "debug");
|
|
9706
|
-
|
|
9709
|
+
/** AIDStore 加载时注入的明文私钥 PEM,供 AUNClient 直接使用(无需 seed)。*/
|
|
9710
|
+
__publicField(this, "privateKeyPem");
|
|
9707
9711
|
__publicField(this, "_certValid");
|
|
9708
9712
|
__publicField(this, "_privateKeyValid");
|
|
9709
9713
|
__publicField(this, "_certFingerprint", "");
|
|
@@ -9721,7 +9725,7 @@ var AID = class _AID {
|
|
|
9721
9725
|
this.certIssuer = meta.issuer;
|
|
9722
9726
|
this.certNotBefore = meta.notBefore;
|
|
9723
9727
|
this.certNotAfter = meta.notAfter;
|
|
9724
|
-
this.
|
|
9728
|
+
this.privateKeyPem = params.privateKeyPem ?? "";
|
|
9725
9729
|
this._certValid = params.certValid;
|
|
9726
9730
|
this._privateKeyValid = params.privateKeyValid;
|
|
9727
9731
|
}
|
|
@@ -9740,10 +9744,10 @@ var AID = class _AID {
|
|
|
9740
9744
|
return this._privateKeyValid;
|
|
9741
9745
|
}
|
|
9742
9746
|
async sign(payload) {
|
|
9743
|
-
if (!this._privateKeyValid || !this.
|
|
9747
|
+
if (!this._privateKeyValid || !this.privateKeyPem) return resultErr(PRIVATE_KEY_NOT_VALID, "private key is not valid");
|
|
9744
9748
|
try {
|
|
9745
9749
|
const data = typeof payload === "string" ? new TextEncoder().encode(payload) : payload;
|
|
9746
|
-
return resultOk({ signature: await signBytes(this.
|
|
9750
|
+
return resultOk({ signature: await signBytes(this.privateKeyPem, data) });
|
|
9747
9751
|
} catch (exc) {
|
|
9748
9752
|
return resultErr(SIGNATURE_OPERATION_ERROR, String(exc), exc);
|
|
9749
9753
|
}
|
|
@@ -9758,10 +9762,10 @@ var AID = class _AID {
|
|
|
9758
9762
|
}
|
|
9759
9763
|
}
|
|
9760
9764
|
async signAgentMd(content) {
|
|
9761
|
-
if (!this._privateKeyValid || !this.
|
|
9765
|
+
if (!this._privateKeyValid || !this.privateKeyPem) return resultErr(PRIVATE_KEY_NOT_VALID, "private key is not valid");
|
|
9762
9766
|
try {
|
|
9763
9767
|
const payload = normalizeAgentMdPayload(content);
|
|
9764
|
-
const signature = await signBytes(this.
|
|
9768
|
+
const signature = await signBytes(this.privateKeyPem, new TextEncoder().encode(payload));
|
|
9765
9769
|
return resultOk({ signed: payload + buildAgentMdSignatureBlock(this.certFingerprint, Date.now() / 1e3, signature) });
|
|
9766
9770
|
} catch (exc) {
|
|
9767
9771
|
return resultErr(SIGNATURE_OPERATION_ERROR, String(exc), exc);
|
|
@@ -9809,6 +9813,12 @@ function getV2DeviceId(dev) {
|
|
|
9809
9813
|
}
|
|
9810
9814
|
return { present: false, value: "" };
|
|
9811
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
|
+
}
|
|
9812
9822
|
function sortObjectKeys(obj) {
|
|
9813
9823
|
if (obj === null || obj === void 0 || typeof obj !== "object") return obj;
|
|
9814
9824
|
if (Array.isArray(obj)) return obj.map(sortObjectKeys);
|
|
@@ -9941,6 +9951,20 @@ var DEFAULT_SESSION_OPTIONS = {
|
|
|
9941
9951
|
http: 30
|
|
9942
9952
|
}
|
|
9943
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
|
+
]);
|
|
9944
9968
|
var PROTECTED_HEADERS_METHODS = /* @__PURE__ */ new Set([
|
|
9945
9969
|
"message.send",
|
|
9946
9970
|
"group.send",
|
|
@@ -10358,6 +10382,7 @@ var _AUNClient = class _AUNClient {
|
|
|
10358
10382
|
// V2 E2EE 状态
|
|
10359
10383
|
__publicField(this, "_v2Session");
|
|
10360
10384
|
__publicField(this, "_v2KeyStore");
|
|
10385
|
+
__publicField(this, "_v2SessionInitInFlight", null);
|
|
10361
10386
|
__publicField(this, "_v2BootstrapCache", /* @__PURE__ */ new Map());
|
|
10362
10387
|
__publicField(this, "_v2SenderIKPending", /* @__PURE__ */ new Map());
|
|
10363
10388
|
__publicField(this, "_v2SenderIKFetching", /* @__PURE__ */ new Set());
|
|
@@ -10433,10 +10458,10 @@ var _AUNClient = class _AUNClient {
|
|
|
10433
10458
|
*/
|
|
10434
10459
|
__publicField(this, "_v2PullInflight", false);
|
|
10435
10460
|
__publicField(this, "_v2PullPending", false);
|
|
10436
|
-
|
|
10437
|
-
|
|
10438
|
-
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");
|
|
10439
10463
|
}
|
|
10464
|
+
const inputAid = aid ?? null;
|
|
10440
10465
|
const rawConfig = {};
|
|
10441
10466
|
if (inputAid) rawConfig.aun_path = inputAid.aunPath;
|
|
10442
10467
|
const _debug = inputAid ? inputAid.debug : false;
|
|
@@ -10460,7 +10485,7 @@ var _AUNClient = class _AUNClient {
|
|
|
10460
10485
|
this._clientLog.info(`AUNClient initialized: debug=${_debug} aunPath=${this.configModel.aunPath} aid=${initAid ?? "-"}`);
|
|
10461
10486
|
this._dispatcher = new EventDispatcher();
|
|
10462
10487
|
this._discovery = new GatewayDiscovery();
|
|
10463
|
-
this._keystore = new IndexedDBKeyStore({
|
|
10488
|
+
this._keystore = new IndexedDBKeyStore({});
|
|
10464
10489
|
this._slotId = inputAid?.slotId || "default";
|
|
10465
10490
|
this._connectDeliveryMode = normalizeDeliveryModeConfig({ mode: "fanout" });
|
|
10466
10491
|
this._defaultConnectDeliveryMode = { ...this._connectDeliveryMode };
|
|
@@ -10489,7 +10514,7 @@ var _AUNClient = class _AUNClient {
|
|
|
10489
10514
|
this._currentAid = inputAid;
|
|
10490
10515
|
this._identity = {
|
|
10491
10516
|
aid: inputAid.aid,
|
|
10492
|
-
private_key_pem: inputAid.
|
|
10517
|
+
private_key_pem: inputAid.privateKeyPem,
|
|
10493
10518
|
public_key_der_b64: inputAid.publicKey,
|
|
10494
10519
|
cert: inputAid.certPem
|
|
10495
10520
|
};
|
|
@@ -11215,22 +11240,78 @@ var _AUNClient = class _AUNClient {
|
|
|
11215
11240
|
get lastErrorCode() {
|
|
11216
11241
|
return this._lastErrorCode;
|
|
11217
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
|
+
}
|
|
11218
11300
|
loadIdentity(aid) {
|
|
11219
11301
|
if (!aid?.isPrivateKeyValid()) throw new StateError("loadIdentity requires an AID with a valid private key");
|
|
11220
11302
|
const publicState = this.state;
|
|
11221
11303
|
if (publicState !== "no_identity" /* NO_IDENTITY */ && publicState !== "closed" /* CLOSED */) {
|
|
11222
11304
|
throw new StateError(`loadIdentity not allowed in state ${publicState}`);
|
|
11223
11305
|
}
|
|
11306
|
+
this._applyAidRuntimeContext(aid);
|
|
11224
11307
|
this._currentAid = aid;
|
|
11225
11308
|
this._aid = aid.aid;
|
|
11226
11309
|
this._identity = {
|
|
11227
11310
|
aid: aid.aid,
|
|
11228
|
-
private_key_pem: aid.
|
|
11311
|
+
private_key_pem: aid.privateKeyPem,
|
|
11229
11312
|
public_key_der_b64: aid.publicKey,
|
|
11230
11313
|
cert: aid.certPem
|
|
11231
11314
|
};
|
|
11232
|
-
this._auth._aid = aid.aid;
|
|
11233
|
-
this._slotId = aid.slotId || "default";
|
|
11234
11315
|
this._state = "disconnected";
|
|
11235
11316
|
this._closing = false;
|
|
11236
11317
|
}
|
|
@@ -11274,9 +11355,6 @@ var _AUNClient = class _AUNClient {
|
|
|
11274
11355
|
get gatewayUrl() {
|
|
11275
11356
|
return this._gatewayUrl;
|
|
11276
11357
|
}
|
|
11277
|
-
set gatewayUrl(url) {
|
|
11278
|
-
this._gatewayUrl = url;
|
|
11279
|
-
}
|
|
11280
11358
|
get discovery() {
|
|
11281
11359
|
return this._discovery;
|
|
11282
11360
|
}
|
|
@@ -11317,10 +11395,11 @@ var _AUNClient = class _AUNClient {
|
|
|
11317
11395
|
/** 连接到 Gateway;身份来自构造函数或 loadIdentity(aid),认证由 SDK 内部自动完成。 */
|
|
11318
11396
|
async connect(opts) {
|
|
11319
11397
|
const tStart = Date.now();
|
|
11320
|
-
if (opts !== void 0 && typeof opts === "object") {
|
|
11398
|
+
if (opts !== void 0 && opts !== null && typeof opts === "object") {
|
|
11321
11399
|
const raw = opts;
|
|
11322
|
-
|
|
11323
|
-
|
|
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(", ")}`);
|
|
11324
11403
|
}
|
|
11325
11404
|
}
|
|
11326
11405
|
const target = this._currentAid?.aid ?? this._aid ?? "";
|
|
@@ -11482,6 +11561,12 @@ var _AUNClient = class _AUNClient {
|
|
|
11482
11561
|
}
|
|
11483
11562
|
this._validateOutboundCall(method, p);
|
|
11484
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
|
+
}
|
|
11485
11570
|
if (method.startsWith("group.") && p.group_id !== void 0 && p.group_id !== null) {
|
|
11486
11571
|
const rawGroupId = String(p.group_id);
|
|
11487
11572
|
const normalizedGroupId = normalizeGroupId(rawGroupId);
|
|
@@ -11500,9 +11585,10 @@ var _AUNClient = class _AUNClient {
|
|
|
11500
11585
|
const encrypt = p.encrypt !== void 0 ? p.encrypt : true;
|
|
11501
11586
|
delete p.encrypt;
|
|
11502
11587
|
if (encrypt) {
|
|
11503
|
-
|
|
11504
|
-
|
|
11505
|
-
|
|
11588
|
+
await this._ensureV2SessionReady(
|
|
11589
|
+
"message.send",
|
|
11590
|
+
"V2 session not initialized; encrypted message.send requires V2 (V1 E2EE removed)"
|
|
11591
|
+
);
|
|
11506
11592
|
this._clientLog.debug("call route: message.send \u2192 V2 encrypted send");
|
|
11507
11593
|
return await this._sendV2(String(p.to ?? ""), p.payload ?? {}, {
|
|
11508
11594
|
messageId: String(p.message_id ?? "") || void 0,
|
|
@@ -11517,9 +11603,10 @@ var _AUNClient = class _AUNClient {
|
|
|
11517
11603
|
const encrypt = p.encrypt !== void 0 ? p.encrypt : true;
|
|
11518
11604
|
delete p.encrypt;
|
|
11519
11605
|
if (encrypt) {
|
|
11520
|
-
|
|
11521
|
-
|
|
11522
|
-
|
|
11606
|
+
await this._ensureV2SessionReady(
|
|
11607
|
+
"group.send",
|
|
11608
|
+
"V2 session not initialized; encrypted group.send requires V2 (V1 E2EE removed)"
|
|
11609
|
+
);
|
|
11523
11610
|
this._clientLog.debug("call route: group.send \u2192 V2 encrypted send");
|
|
11524
11611
|
return await this._sendGroupV2(String(p.group_id ?? ""), p.payload ?? {}, {
|
|
11525
11612
|
messageId: String(p.message_id ?? "") || void 0,
|
|
@@ -11534,9 +11621,10 @@ var _AUNClient = class _AUNClient {
|
|
|
11534
11621
|
const encrypt = p.encrypt !== void 0 ? p.encrypt : true;
|
|
11535
11622
|
delete p.encrypt;
|
|
11536
11623
|
if (encrypt) {
|
|
11537
|
-
|
|
11538
|
-
|
|
11539
|
-
|
|
11624
|
+
await this._ensureV2SessionReady(
|
|
11625
|
+
"group.thought.put",
|
|
11626
|
+
"V2 session not initialized; encrypted group.thought.put requires V2 (V1 E2EE removed)"
|
|
11627
|
+
);
|
|
11540
11628
|
this._clientLog.debug("call route: group.thought.put \u2192 V2 encrypted put");
|
|
11541
11629
|
return this._putGroupThoughtEncryptedV2(p);
|
|
11542
11630
|
}
|
|
@@ -11545,9 +11633,10 @@ var _AUNClient = class _AUNClient {
|
|
|
11545
11633
|
const encrypt = p.encrypt !== void 0 ? p.encrypt : true;
|
|
11546
11634
|
delete p.encrypt;
|
|
11547
11635
|
if (encrypt) {
|
|
11548
|
-
|
|
11549
|
-
|
|
11550
|
-
|
|
11636
|
+
await this._ensureV2SessionReady(
|
|
11637
|
+
"message.thought.put",
|
|
11638
|
+
"V2 session not initialized; encrypted message.thought.put requires V2 (V1 E2EE removed)"
|
|
11639
|
+
);
|
|
11551
11640
|
this._clientLog.debug("call route: message.thought.put \u2192 V2 encrypted put");
|
|
11552
11641
|
return this._putMessageThoughtEncryptedV2(p);
|
|
11553
11642
|
}
|
|
@@ -11565,26 +11654,43 @@ var _AUNClient = class _AUNClient {
|
|
|
11565
11654
|
* 拆分出来以便 pull gate 包裹整个操作。
|
|
11566
11655
|
*/
|
|
11567
11656
|
async _callImplInner(method, p) {
|
|
11568
|
-
if (method === "message.pull"
|
|
11657
|
+
if (method === "message.pull") {
|
|
11658
|
+
await this._ensureV2SessionReady("message.pull");
|
|
11569
11659
|
this._clientLog.debug("call route: message.pull \u2192 V2 pull");
|
|
11570
11660
|
const messages = await this._pullV2(Number(p.after_seq ?? 0) || 0, Number(p.limit ?? 50) || 50, { force: p.force === true });
|
|
11571
11661
|
return { messages };
|
|
11572
11662
|
}
|
|
11573
|
-
if (method === "message.ack"
|
|
11663
|
+
if (method === "message.ack") {
|
|
11664
|
+
await this._ensureV2SessionReady("message.ack");
|
|
11574
11665
|
this._clientLog.debug("call route: message.ack \u2192 V2 ack");
|
|
11575
11666
|
return await this._ackV2(Number(p.seq ?? p.up_to_seq ?? 0) || void 0);
|
|
11576
11667
|
}
|
|
11577
|
-
if (method === "group.pull" &&
|
|
11668
|
+
if (method === "group.pull" && p.group_id) {
|
|
11669
|
+
await this._ensureV2SessionReady("group.pull");
|
|
11578
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;
|
|
11579
11678
|
const messages = await this._pullGroupV2(
|
|
11580
11679
|
String(p.group_id),
|
|
11581
11680
|
Number(p.after_seq ?? p.after_message_seq ?? 0) || 0,
|
|
11582
|
-
Number(p.limit ?? 50) || 50
|
|
11681
|
+
Number(p.limit ?? 50) || 50,
|
|
11682
|
+
Object.keys(pullOpts).length > 0 ? pullOpts : void 0
|
|
11583
11683
|
);
|
|
11584
11684
|
return { messages };
|
|
11585
11685
|
}
|
|
11586
|
-
if (method === "group.ack_messages" &&
|
|
11686
|
+
if (method === "group.ack_messages" && p.group_id) {
|
|
11687
|
+
await this._ensureV2SessionReady("group.ack_messages");
|
|
11587
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
|
+
}
|
|
11588
11694
|
return await this._ackGroupV2(
|
|
11589
11695
|
String(p.group_id),
|
|
11590
11696
|
Number(p.seq ?? p.msg_seq ?? p.up_to_seq ?? 0) || void 0
|
|
@@ -11685,6 +11791,7 @@ var _AUNClient = class _AUNClient {
|
|
|
11685
11791
|
delete p._pull_gate_locked;
|
|
11686
11792
|
delete p._skip_auto_ack;
|
|
11687
11793
|
delete p.skip_auto_ack;
|
|
11794
|
+
delete p._group_cursor_params;
|
|
11688
11795
|
if (method.startsWith("group.") && p.group_id !== void 0 && p.group_id !== null) {
|
|
11689
11796
|
p.group_id = normalizeGroupId(String(p.group_id)) || String(p.group_id);
|
|
11690
11797
|
}
|
|
@@ -12014,54 +12121,27 @@ var _AUNClient = class _AUNClient {
|
|
|
12014
12121
|
/** 后台补齐群消息空洞 */
|
|
12015
12122
|
async _fillGroupGap(groupId) {
|
|
12016
12123
|
if (this._state !== "connected" || this._closing) return;
|
|
12124
|
+
groupId = normalizeGroupId(groupId) || String(groupId ?? "").trim();
|
|
12125
|
+
if (!groupId) return;
|
|
12017
12126
|
const ns = `group:${groupId}`;
|
|
12018
12127
|
const afterSeq = this._seqTracker.getContiguousSeq(ns);
|
|
12019
12128
|
const dedupKey = `group_pull:${ns}`;
|
|
12020
12129
|
if (this._gapFillDone.has(dedupKey)) return;
|
|
12021
12130
|
this._gapFillDone.add(dedupKey);
|
|
12022
12131
|
this._gapFillActive = true;
|
|
12132
|
+
let filled = 0;
|
|
12023
12133
|
try {
|
|
12024
|
-
const
|
|
12025
|
-
|
|
12026
|
-
|
|
12027
|
-
device_id: this._deviceId,
|
|
12028
|
-
limit: 50
|
|
12029
|
-
});
|
|
12030
|
-
if (isJsonObject(result)) {
|
|
12031
|
-
const messages = result.messages;
|
|
12032
|
-
if (Array.isArray(messages)) {
|
|
12033
|
-
const pushed = this._pushedSeqs.get(ns);
|
|
12034
|
-
for (const msg of messages) {
|
|
12035
|
-
if (isJsonObject(msg)) {
|
|
12036
|
-
const s = msg.seq;
|
|
12037
|
-
if (pushed && s !== void 0 && s !== null && pushed.has(s)) continue;
|
|
12038
|
-
if (s !== void 0 && s !== null) {
|
|
12039
|
-
await this._publishPulledMessage("group.message_created", ns, s, msg);
|
|
12040
|
-
} else {
|
|
12041
|
-
await this._publishAppEvent("group.message_created", msg);
|
|
12042
|
-
}
|
|
12043
|
-
}
|
|
12044
|
-
}
|
|
12045
|
-
this._prunePushedSeqs(ns);
|
|
12046
|
-
const contig = this._seqTracker.getContiguousSeq(ns);
|
|
12047
|
-
if (contig > 0) {
|
|
12048
|
-
const gid = groupId;
|
|
12049
|
-
this._transport.call("group.ack_messages", {
|
|
12050
|
-
group_id: gid,
|
|
12051
|
-
msg_seq: contig,
|
|
12052
|
-
device_id: this._deviceId,
|
|
12053
|
-
slot_id: this._slotId
|
|
12054
|
-
}).catch((e) => {
|
|
12055
|
-
this._clientLog.warn(`group gap-fill auto-ack failed: group=${gid}`, e);
|
|
12056
|
-
});
|
|
12057
|
-
}
|
|
12058
|
-
}
|
|
12059
|
-
}
|
|
12134
|
+
const messages = await this._pullGroupV2(groupId, afterSeq, 50);
|
|
12135
|
+
filled = messages.length;
|
|
12136
|
+
this._prunePushedSeqs(ns);
|
|
12060
12137
|
} catch (exc) {
|
|
12061
12138
|
this._clientLog.warn(`group message gap-fill failed:${String(exc)}`);
|
|
12062
12139
|
} finally {
|
|
12063
12140
|
this._gapFillDone.delete(dedupKey);
|
|
12064
12141
|
this._gapFillActive = false;
|
|
12142
|
+
if (filled > 0 && this._seqTracker.getContiguousSeq(ns) > afterSeq) {
|
|
12143
|
+
this._safeAsync(this._fillGroupGap(groupId));
|
|
12144
|
+
}
|
|
12065
12145
|
}
|
|
12066
12146
|
}
|
|
12067
12147
|
/** 后台补齐群事件空洞 */
|
|
@@ -12159,44 +12239,19 @@ var _AUNClient = class _AUNClient {
|
|
|
12159
12239
|
if (this._gapFillDone.has(dedupKey)) return;
|
|
12160
12240
|
this._gapFillDone.add(dedupKey);
|
|
12161
12241
|
this._gapFillActive = true;
|
|
12242
|
+
let filled = 0;
|
|
12162
12243
|
try {
|
|
12163
|
-
const
|
|
12164
|
-
|
|
12165
|
-
|
|
12166
|
-
});
|
|
12167
|
-
if (isJsonObject(result)) {
|
|
12168
|
-
const messages = result.messages;
|
|
12169
|
-
if (Array.isArray(messages)) {
|
|
12170
|
-
const pushed = this._pushedSeqs.get(ns);
|
|
12171
|
-
for (const msg of messages) {
|
|
12172
|
-
if (isJsonObject(msg)) {
|
|
12173
|
-
const s = msg.seq;
|
|
12174
|
-
if (pushed && s !== void 0 && s !== null && pushed.has(s)) continue;
|
|
12175
|
-
if (s !== void 0 && s !== null) {
|
|
12176
|
-
await this._publishPulledMessage("message.received", ns, s, msg);
|
|
12177
|
-
} else {
|
|
12178
|
-
await this._publishAppEvent("message.received", msg);
|
|
12179
|
-
}
|
|
12180
|
-
}
|
|
12181
|
-
}
|
|
12182
|
-
this._prunePushedSeqs(ns);
|
|
12183
|
-
const contig = this._seqTracker.getContiguousSeq(ns);
|
|
12184
|
-
if (contig > 0) {
|
|
12185
|
-
this._transport.call("message.ack", {
|
|
12186
|
-
seq: contig,
|
|
12187
|
-
device_id: this._deviceId,
|
|
12188
|
-
slot_id: this._slotId
|
|
12189
|
-
}).catch((e) => {
|
|
12190
|
-
this._clientLog.warn(`P2P gap-fill auto-ack failed:${String(e)}`);
|
|
12191
|
-
});
|
|
12192
|
-
}
|
|
12193
|
-
}
|
|
12194
|
-
}
|
|
12244
|
+
const messages = await this._pullV2(afterSeq, 50);
|
|
12245
|
+
filled = messages.length;
|
|
12246
|
+
this._prunePushedSeqs(ns);
|
|
12195
12247
|
} catch (exc) {
|
|
12196
12248
|
this._clientLog.warn(`P2P message gap-fill failed:${String(exc)}`);
|
|
12197
12249
|
} finally {
|
|
12198
12250
|
this._gapFillDone.delete(dedupKey);
|
|
12199
12251
|
this._gapFillActive = false;
|
|
12252
|
+
if (filled > 0 && this._seqTracker.getContiguousSeq(ns) > afterSeq) {
|
|
12253
|
+
this._safeAsync(this._fillP2pGap());
|
|
12254
|
+
}
|
|
12200
12255
|
}
|
|
12201
12256
|
}
|
|
12202
12257
|
/** 只按硬上限裁剪 published guard,不能按 contiguousSeq 清理。 */
|
|
@@ -13039,10 +13094,10 @@ var _AUNClient = class _AUNClient {
|
|
|
13039
13094
|
* 使用 SubtleCrypto 异步签名。
|
|
13040
13095
|
*/
|
|
13041
13096
|
async _signClientOperation(method, params) {
|
|
13042
|
-
const
|
|
13043
|
-
if (!
|
|
13097
|
+
const currentAid = this._currentAid;
|
|
13098
|
+
if (!currentAid?.privateKeyPem) return;
|
|
13044
13099
|
try {
|
|
13045
|
-
const aid =
|
|
13100
|
+
const aid = currentAid.aid;
|
|
13046
13101
|
const ts = String(Math.floor(Date.now() / 1e3));
|
|
13047
13102
|
const paramsForHash = {};
|
|
13048
13103
|
for (const [k, v] of Object.entries(params)) {
|
|
@@ -13057,7 +13112,7 @@ var _AUNClient = class _AUNClient {
|
|
|
13057
13112
|
);
|
|
13058
13113
|
const paramsHash = Array.from(new Uint8Array(paramsHashBuf)).map((b) => b.toString(16).padStart(2, "0")).join("");
|
|
13059
13114
|
const signData = new TextEncoder().encode(`${method}|${aid}|${ts}|${paramsHash}`);
|
|
13060
|
-
const pkcs8 = pemToArrayBuffer(
|
|
13115
|
+
const pkcs8 = pemToArrayBuffer(currentAid.privateKeyPem);
|
|
13061
13116
|
const cryptoKey = await crypto.subtle.importKey(
|
|
13062
13117
|
"pkcs8",
|
|
13063
13118
|
pkcs8,
|
|
@@ -13072,7 +13127,7 @@ var _AUNClient = class _AUNClient {
|
|
|
13072
13127
|
);
|
|
13073
13128
|
const sigDer = p1363ToDer(new Uint8Array(sigP1363));
|
|
13074
13129
|
let certFingerprint = "";
|
|
13075
|
-
const certPem =
|
|
13130
|
+
const certPem = currentAid.certPem;
|
|
13076
13131
|
if (certPem) {
|
|
13077
13132
|
const certDer = pemToArrayBuffer(certPem);
|
|
13078
13133
|
const fpBuf = await crypto.subtle.digest("SHA-256", certDer);
|
|
@@ -13172,12 +13227,20 @@ var _AUNClient = class _AUNClient {
|
|
|
13172
13227
|
await this._restoreSeqTrackerState();
|
|
13173
13228
|
}
|
|
13174
13229
|
this._startBackgroundTasks();
|
|
13175
|
-
|
|
13176
|
-
|
|
13177
|
-
|
|
13178
|
-
|
|
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");
|
|
13179
13240
|
}
|
|
13180
|
-
|
|
13241
|
+
const hasExplicitBackgroundSync = Object.prototype.hasOwnProperty.call(params, "background_sync");
|
|
13242
|
+
const backgroundSyncEnabled = this._sessionOptions?.background_sync !== false && (!isShortConnection || hasExplicitBackgroundSync);
|
|
13243
|
+
if (backgroundSyncEnabled) {
|
|
13181
13244
|
this._safeAsync(this._fillP2pGap());
|
|
13182
13245
|
}
|
|
13183
13246
|
this._clientLog.debug(`_connectOnce exit: elapsed=${Date.now() - tStart}ms aid=${this._aid ?? "-"}`);
|
|
@@ -14056,6 +14119,19 @@ var _AUNClient = class _AUNClient {
|
|
|
14056
14119
|
);
|
|
14057
14120
|
return repaired;
|
|
14058
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
|
+
}
|
|
14059
14135
|
// ── V2 E2EE API(async,与 Python `client.py` `_init_v2_session` / `send_v2` / `pull_v2` / `ack_v2` 对齐) ──
|
|
14060
14136
|
/**
|
|
14061
14137
|
* 初始化 V2 session:从 AID PEM 私钥提取 raw scalar + DER 公钥,
|
|
@@ -14065,31 +14141,13 @@ var _AUNClient = class _AUNClient {
|
|
|
14065
14141
|
*/
|
|
14066
14142
|
async _initV2Session() {
|
|
14067
14143
|
if (!this._aid) return;
|
|
14068
|
-
|
|
14069
|
-
if (!
|
|
14070
|
-
try {
|
|
14071
|
-
const reloaded = await this._keystore.loadIdentity(this._aid);
|
|
14072
|
-
if (reloaded?.private_key_pem) {
|
|
14073
|
-
this._identity = reloaded;
|
|
14074
|
-
identity = reloaded;
|
|
14075
|
-
this._clientLog.warn("V2 session init: identity cache was stale, reloaded from keystore");
|
|
14076
|
-
try {
|
|
14077
|
-
const persistIdentity = this._auth._persistIdentity;
|
|
14078
|
-
if (typeof persistIdentity === "function") {
|
|
14079
|
-
await persistIdentity.call(this._auth, reloaded);
|
|
14080
|
-
}
|
|
14081
|
-
} catch {
|
|
14082
|
-
}
|
|
14083
|
-
}
|
|
14084
|
-
} catch {
|
|
14085
|
-
}
|
|
14086
|
-
}
|
|
14087
|
-
if (!identity?.private_key_pem) {
|
|
14144
|
+
const currentAid = this._currentAid;
|
|
14145
|
+
if (!currentAid?.privateKeyPem) {
|
|
14088
14146
|
this._clientLog.warn("V2 session init skipped: no AID private key");
|
|
14089
14147
|
return;
|
|
14090
14148
|
}
|
|
14091
14149
|
if (this._v2Session) return;
|
|
14092
|
-
const pem =
|
|
14150
|
+
const pem = currentAid.privateKeyPem.trim();
|
|
14093
14151
|
const pemBody = pem.replace(/-----BEGIN [^-]+-----/g, "").replace(/-----END [^-]+-----/g, "").replace(/\s+/g, "");
|
|
14094
14152
|
const pkcs8Der = _v2B64ToBytes(pemBody);
|
|
14095
14153
|
const privKey = await crypto.subtle.importKey(
|
|
@@ -14461,6 +14519,7 @@ var _AUNClient = class _AUNClient {
|
|
|
14461
14519
|
decrypted.push(plaintext);
|
|
14462
14520
|
}
|
|
14463
14521
|
}
|
|
14522
|
+
const hasServerAckSeq = Object.prototype.hasOwnProperty.call(result, "server_ack_seq");
|
|
14464
14523
|
const serverAckSeq = Number(result.server_ack_seq ?? 0);
|
|
14465
14524
|
if (ns && Number.isFinite(serverAckSeq) && serverAckSeq > 0) {
|
|
14466
14525
|
const contig = this._seqTracker.getContiguousSeq(ns);
|
|
@@ -14476,7 +14535,8 @@ var _AUNClient = class _AUNClient {
|
|
|
14476
14535
|
await this._drainOrderedMessages(ns);
|
|
14477
14536
|
this._saveSeqTrackerState();
|
|
14478
14537
|
}
|
|
14479
|
-
|
|
14538
|
+
const ackNeeded = messages.length > 0 && ackSeq > 0 && (contigAdvanced || hasServerAckSeq && ackSeq > serverAckSeq);
|
|
14539
|
+
if (ackNeeded) {
|
|
14480
14540
|
this._safeAsync(this._ackV2(ackSeq).then(() => void 0));
|
|
14481
14541
|
}
|
|
14482
14542
|
}
|
|
@@ -14505,7 +14565,7 @@ var _AUNClient = class _AUNClient {
|
|
|
14505
14565
|
seq = maxSeen;
|
|
14506
14566
|
}
|
|
14507
14567
|
}
|
|
14508
|
-
const raw = await this.
|
|
14568
|
+
const raw = await this._callRawV2Rpc("message.v2.ack", { up_to_seq: seq });
|
|
14509
14569
|
const result = isJsonObject(raw) ? { ...raw } : { result: raw };
|
|
14510
14570
|
let actualAckSeq = seq;
|
|
14511
14571
|
if ("effective_ack_seq" in result) actualAckSeq = Number(result.effective_ack_seq ?? 0);
|
|
@@ -14775,7 +14835,7 @@ var _AUNClient = class _AUNClient {
|
|
|
14775
14835
|
* @param afterSeq 从此 seq 之后开始拉取(0/省略 = 从当前 contiguous 开始)
|
|
14776
14836
|
* @param limit 最多拉取条数
|
|
14777
14837
|
*/
|
|
14778
|
-
async _pullGroupV2(groupId, afterSeq = 0, limit = 50) {
|
|
14838
|
+
async _pullGroupV2(groupId, afterSeq = 0, limit = 50, opts) {
|
|
14779
14839
|
if (!this._v2Session) {
|
|
14780
14840
|
throw new StateError("V2 session not initialized (not connected?)");
|
|
14781
14841
|
}
|
|
@@ -14783,15 +14843,18 @@ var _AUNClient = class _AUNClient {
|
|
|
14783
14843
|
if (!gid) throw new ValidationError("group.pull requires group_id");
|
|
14784
14844
|
const ns = `group:${gid}`;
|
|
14785
14845
|
const decrypted = [];
|
|
14786
|
-
|
|
14846
|
+
const cursorParams = opts?.cursorParams ?? {};
|
|
14847
|
+
const ownsCursor = opts?.ownsCursor !== false;
|
|
14848
|
+
let nextAfterSeq = opts?.explicitAfterSeq ? afterSeq : afterSeq || this._seqTracker.getContiguousSeq(ns);
|
|
14787
14849
|
let pageCount = 0;
|
|
14788
14850
|
const maxPages = 100;
|
|
14789
14851
|
while (pageCount < maxPages) {
|
|
14790
14852
|
pageCount += 1;
|
|
14791
|
-
const result = await this.
|
|
14853
|
+
const result = await this._callRawV2Rpc("group.v2.pull", {
|
|
14792
14854
|
group_id: gid,
|
|
14793
14855
|
after_seq: nextAfterSeq,
|
|
14794
|
-
limit
|
|
14856
|
+
limit,
|
|
14857
|
+
...cursorParams
|
|
14795
14858
|
});
|
|
14796
14859
|
const messages = Array.isArray(result?.messages) ? result.messages : [];
|
|
14797
14860
|
const seqs = messages.map((msg) => Number(msg.seq ?? 0)).filter((seq) => Number.isFinite(seq) && seq > 0);
|
|
@@ -14853,6 +14916,7 @@ var _AUNClient = class _AUNClient {
|
|
|
14853
14916
|
decrypted.push(plaintext);
|
|
14854
14917
|
}
|
|
14855
14918
|
const cursor = isJsonObject(result.cursor) ? result.cursor : null;
|
|
14919
|
+
const hasServerCursor = cursor !== null && Object.prototype.hasOwnProperty.call(cursor, "current_seq");
|
|
14856
14920
|
const serverAckSeq = Number(cursor?.current_seq ?? 0);
|
|
14857
14921
|
if (Number.isFinite(serverAckSeq) && serverAckSeq > 0) {
|
|
14858
14922
|
const contig = this._seqTracker.getContiguousSeq(ns);
|
|
@@ -14867,10 +14931,12 @@ var _AUNClient = class _AUNClient {
|
|
|
14867
14931
|
await this._drainOrderedMessages(ns);
|
|
14868
14932
|
this._saveSeqTrackerState();
|
|
14869
14933
|
}
|
|
14870
|
-
|
|
14934
|
+
const ackNeeded = messages.length > 0 && ackSeq > 0 && ownsCursor && (contigAdvanced || hasServerCursor && ackSeq > serverAckSeq);
|
|
14935
|
+
if (ackNeeded) {
|
|
14871
14936
|
this._safeAsync(this._ackGroupV2(gid, ackSeq).then(() => void 0));
|
|
14872
14937
|
}
|
|
14873
14938
|
const nextAfter = Math.max(pageMaxSeq, nextAfterSeq);
|
|
14939
|
+
if (!ownsCursor) break;
|
|
14874
14940
|
if (messages.length === 0 || nextAfter <= nextAfterSeq || result.has_more === false) break;
|
|
14875
14941
|
nextAfterSeq = nextAfter;
|
|
14876
14942
|
}
|
|
@@ -14879,6 +14945,28 @@ var _AUNClient = class _AUNClient {
|
|
|
14879
14945
|
}
|
|
14880
14946
|
return decrypted;
|
|
14881
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
|
+
}
|
|
14882
14970
|
/**
|
|
14883
14971
|
* 确认 V2 群消息已消费。
|
|
14884
14972
|
*
|
|
@@ -14896,7 +14984,7 @@ var _AUNClient = class _AUNClient {
|
|
|
14896
14984
|
this._clientLog.warn(`ackGroupV2 clamp: group=${gid} up_to_seq=${seq} > max_seen=${maxSeen}, clamp`);
|
|
14897
14985
|
seq = maxSeen;
|
|
14898
14986
|
}
|
|
14899
|
-
return this.
|
|
14987
|
+
return this._callRawV2Rpc("group.v2.ack", { group_id: gid, up_to_seq: seq });
|
|
14900
14988
|
}
|
|
14901
14989
|
// ── V2 thought(per-device wrap,服务端透传,不持久化)──────────
|
|
14902
14990
|
/**
|
|
@@ -15655,8 +15743,8 @@ var _AUNClient = class _AUNClient {
|
|
|
15655
15743
|
return;
|
|
15656
15744
|
}
|
|
15657
15745
|
let signature = "";
|
|
15658
|
-
const
|
|
15659
|
-
if (
|
|
15746
|
+
const currentAid = this._currentAid;
|
|
15747
|
+
if (currentAid?.privateKeyPem) {
|
|
15660
15748
|
try {
|
|
15661
15749
|
const signPayloadObj = {
|
|
15662
15750
|
group_id: groupId,
|
|
@@ -15666,7 +15754,7 @@ var _AUNClient = class _AUNClient {
|
|
|
15666
15754
|
};
|
|
15667
15755
|
const signPayload = stableStringify(signPayloadObj);
|
|
15668
15756
|
const signPayloadBytes = new TextEncoder().encode(signPayload);
|
|
15669
|
-
const privKey = await importPrivateKeyEcdsa(
|
|
15757
|
+
const privKey = await importPrivateKeyEcdsa(currentAid.privateKeyPem);
|
|
15670
15758
|
const sigBytes = await ecdsaSignDer(privKey, signPayloadBytes);
|
|
15671
15759
|
signature = uint8ToBase64(sigBytes);
|
|
15672
15760
|
} catch (sigExc) {
|
|
@@ -15840,7 +15928,7 @@ var _AUNClient = class _AUNClient {
|
|
|
15840
15928
|
if (newContig > 0 && newContig !== contigBefore) {
|
|
15841
15929
|
const maxSeen = this._seqTracker.getMaxSeenSeq(ns);
|
|
15842
15930
|
const ackSeq = maxSeen > 0 ? Math.min(newContig, maxSeen) : newContig;
|
|
15843
|
-
this.
|
|
15931
|
+
this._callRawV2Rpc("message.v2.ack", { up_to_seq: ackSeq }).catch((e) => this._clientLog.debug(`V2 P2P push-ack failed: ${e}`));
|
|
15844
15932
|
}
|
|
15845
15933
|
this._clientLog.debug(
|
|
15846
15934
|
`_onV2PushNotification: push \u5E26 payload \u89E3\u5BC6\u6210\u529F, contiguous_seq=${contigBefore}->${newContig} push_seq=${pushSeq}`
|