@agentunion/fastaun 0.3.4 → 0.3.6
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 +126 -106
- package/_packed_docs/CHANGELOG.md +126 -106
- package/_packed_docs/INDEX.md +16 -16
- package/_packed_docs/KITE_DOCS_GUIDE.md +7 -7
- 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 -0
- package/_packed_docs/sdk/04-/350/277/236/346/216/245/344/270/216/350/256/244/350/257/201.md +469 -454
- package/_packed_docs/sdk/06-API/346/211/213/345/206/214.md +1494 -1410
- package/_packed_docs/sdk/09-storage-rpc-manual.md +89 -0
- package/dist/auth.d.ts +18 -1
- package/dist/auth.js +28 -9
- package/dist/auth.js.map +1 -1
- package/dist/client.d.ts +14 -0
- package/dist/client.js +242 -10
- package/dist/client.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/namespaces/auth.d.ts +2 -0
- package/dist/namespaces/auth.js +7 -0
- package/dist/namespaces/auth.js.map +1 -1
- package/dist/secret-store/file-store.d.ts +5 -0
- package/dist/secret-store/file-store.js +32 -13
- package/dist/secret-store/file-store.js.map +1 -1
- package/dist/transport.js +1 -1
- package/dist/transport.js.map +1 -1
- package/dist/v2/e2ee/encrypt-p2p.js +1 -1
- package/package.json +1 -1
package/dist/client.js
CHANGED
|
@@ -444,6 +444,8 @@ export class AUNClient {
|
|
|
444
444
|
_pushedSeqs = new Map();
|
|
445
445
|
/** 已解密但因 seq 空洞暂缓发布的应用层消息(按 namespace -> seq) */
|
|
446
446
|
_pendingOrderedMsgs = new Map();
|
|
447
|
+
/** P2P pull 进行中到达的纯通知 push 上界;pull gate 释放后需要补拉一次。 */
|
|
448
|
+
_pendingP2pPullUpper = new Map();
|
|
447
449
|
/** 缺 sender IK 时暂存原始 V2 消息,后台补齐 IK 后重试解密。 */
|
|
448
450
|
_v2SenderIKPending = new Map();
|
|
449
451
|
/** sender IK 后台补齐任务去重。 */
|
|
@@ -1491,11 +1493,12 @@ export class AUNClient {
|
|
|
1491
1493
|
if (method === 'message.pull' || method === 'message.v2.pull') {
|
|
1492
1494
|
await this._ensureV2SessionReady('message.pull');
|
|
1493
1495
|
const skipAutoAck = p._skip_auto_ack === true || p.skip_auto_ack === true;
|
|
1496
|
+
const force = p.force === true;
|
|
1494
1497
|
const afterSeq = Number(p.after_seq ?? 0) || 0;
|
|
1495
1498
|
const limit = Number(p.limit ?? 50) || 50;
|
|
1496
1499
|
const messages = skipAutoAck
|
|
1497
|
-
? await runWithRpcPriority(() => this.pullV2(afterSeq, limit, { skipAutoAck: true, gateLocked: true }))
|
|
1498
|
-
: await runWithRpcPriority(() => this.pullV2(afterSeq, limit, { gateLocked: true }));
|
|
1500
|
+
? await runWithRpcPriority(() => this.pullV2(afterSeq, limit, { skipAutoAck: true, gateLocked: true, force }))
|
|
1501
|
+
: await runWithRpcPriority(() => this.pullV2(afterSeq, limit, { gateLocked: true, force }));
|
|
1499
1502
|
return { messages };
|
|
1500
1503
|
}
|
|
1501
1504
|
if (method === 'message.ack' || method === 'message.v2.ack') {
|
|
@@ -1760,6 +1763,7 @@ export class AUNClient {
|
|
|
1760
1763
|
this._clientLog.debug(`P2P push filtered by instance: message_id=${String(msg.message_id ?? '')}, seq=${String(msg.seq ?? '')}, target_device=${String(msg.device_id ?? '')}, target_slot=${String(msg.slot_id ?? '')}, local_device=${this._deviceId}, local_slot=${this._slotId}`);
|
|
1761
1764
|
return;
|
|
1762
1765
|
}
|
|
1766
|
+
const encryptedPush = this._isEncryptedPushMessage(msg);
|
|
1763
1767
|
// P2P 空洞检测
|
|
1764
1768
|
const seq = msg.seq;
|
|
1765
1769
|
if (seq !== undefined && seq !== null && this._aid) {
|
|
@@ -1768,7 +1772,9 @@ export class AUNClient {
|
|
|
1768
1772
|
if (seq > 0)
|
|
1769
1773
|
this._seqTracker.updateMaxSeen(ns, seq);
|
|
1770
1774
|
const contigBefore = this._seqTracker.getContiguousSeq(ns);
|
|
1771
|
-
const published =
|
|
1775
|
+
const published = encryptedPush
|
|
1776
|
+
? await this._publishEncryptedPushMessage('message.received', 'message.undecryptable', ns, seq, msg, false)
|
|
1777
|
+
: await this._publishOrderedMessage('message.received', ns, seq, msg);
|
|
1772
1778
|
const contigAfter = this._seqTracker.getContiguousSeq(ns);
|
|
1773
1779
|
const needPull = Number(seq) > contigAfter && !published;
|
|
1774
1780
|
if (needPull) {
|
|
@@ -1788,8 +1794,14 @@ export class AUNClient {
|
|
|
1788
1794
|
// 即时持久化 cursor,异常断连后不回退
|
|
1789
1795
|
if (contigAfter !== contigBefore)
|
|
1790
1796
|
this._saveSeqTrackerState();
|
|
1797
|
+
if (encryptedPush)
|
|
1798
|
+
return;
|
|
1791
1799
|
}
|
|
1792
1800
|
else {
|
|
1801
|
+
if (encryptedPush) {
|
|
1802
|
+
await this._publishEncryptedPushMessage('message.received', 'message.undecryptable', '', seq ?? 0, msg, false);
|
|
1803
|
+
return;
|
|
1804
|
+
}
|
|
1793
1805
|
// V2-only:普通 _raw.message.received 只承载明文;V2 密文由 peer.v2.message_received 通知触发 pull。
|
|
1794
1806
|
await this._publishAppEvent('message.received', msg, 'push');
|
|
1795
1807
|
}
|
|
@@ -1848,13 +1860,16 @@ export class AUNClient {
|
|
|
1848
1860
|
});
|
|
1849
1861
|
return;
|
|
1850
1862
|
}
|
|
1863
|
+
const encryptedPush = this._isEncryptedPushMessage(msg);
|
|
1851
1864
|
if (groupId && seq !== undefined && seq !== null) {
|
|
1852
1865
|
const ns = `group:${groupId}`;
|
|
1853
1866
|
// Push 只先更新 maxSeenSeq;contiguous_seq 是已交付游标,必须等应用层发布返回后再推进。
|
|
1854
1867
|
if (seq > 0)
|
|
1855
1868
|
this._seqTracker.updateMaxSeen(ns, seq);
|
|
1856
1869
|
const contigBefore = this._seqTracker.getContiguousSeq(ns);
|
|
1857
|
-
const published =
|
|
1870
|
+
const published = encryptedPush
|
|
1871
|
+
? await this._publishEncryptedPushMessage('group.message_created', 'group.message_undecryptable', ns, seq, msg, true)
|
|
1872
|
+
: await this._publishOrderedMessage('group.message_created', ns, seq, msg);
|
|
1858
1873
|
const contigAfter = this._seqTracker.getContiguousSeq(ns);
|
|
1859
1874
|
const needPull = Number(seq) > contigAfter && !published;
|
|
1860
1875
|
if (needPull) {
|
|
@@ -1872,8 +1887,14 @@ export class AUNClient {
|
|
|
1872
1887
|
}
|
|
1873
1888
|
if (contigAfter !== contigBefore)
|
|
1874
1889
|
this._saveSeqTrackerState();
|
|
1890
|
+
if (encryptedPush)
|
|
1891
|
+
return;
|
|
1875
1892
|
}
|
|
1876
1893
|
else {
|
|
1894
|
+
if (encryptedPush) {
|
|
1895
|
+
await this._publishEncryptedPushMessage('group.message_created', 'group.message_undecryptable', '', seq ?? 0, msg, true);
|
|
1896
|
+
return;
|
|
1897
|
+
}
|
|
1877
1898
|
// V2-only:普通 group.message_created 只承载明文;V2 密文由 group.v2.message_created 通知触发 pull。
|
|
1878
1899
|
await this._publishAppEvent('group.message_created', msg, 'group-push');
|
|
1879
1900
|
}
|
|
@@ -1992,6 +2013,38 @@ export class AUNClient {
|
|
|
1992
2013
|
this._pushedSeqs.set(ns, new Set(keep));
|
|
1993
2014
|
}
|
|
1994
2015
|
}
|
|
2016
|
+
_recordPendingP2pPull(ns, seq) {
|
|
2017
|
+
if (!ns || seq <= 0)
|
|
2018
|
+
return;
|
|
2019
|
+
const previous = this._pendingP2pPullUpper.get(ns) ?? 0;
|
|
2020
|
+
if (seq > previous) {
|
|
2021
|
+
this._pendingP2pPullUpper.set(ns, seq);
|
|
2022
|
+
}
|
|
2023
|
+
this._clientLog.debug(`P2P pending pull upper recorded: ns=${ns}, seq=${seq}, previous=${previous}, contiguous=${this._seqTracker.getContiguousSeq(ns)}`);
|
|
2024
|
+
}
|
|
2025
|
+
_schedulePendingP2pPullIfNeeded(ns, reason) {
|
|
2026
|
+
if (!ns)
|
|
2027
|
+
return false;
|
|
2028
|
+
const upperSeq = this._pendingP2pPullUpper.get(ns) ?? 0;
|
|
2029
|
+
if (upperSeq <= 0) {
|
|
2030
|
+
this._pendingP2pPullUpper.delete(ns);
|
|
2031
|
+
return false;
|
|
2032
|
+
}
|
|
2033
|
+
const contig = this._seqTracker.getContiguousSeq(ns);
|
|
2034
|
+
if (upperSeq <= contig) {
|
|
2035
|
+
this._pendingP2pPullUpper.delete(ns);
|
|
2036
|
+
this._clientLog.debug(`P2P pending pull upper already covered: ns=${ns}, upper_seq=${upperSeq}, contiguous=${contig}, reason=${reason}`);
|
|
2037
|
+
return false;
|
|
2038
|
+
}
|
|
2039
|
+
if (this._state !== 'connected' || this._closing) {
|
|
2040
|
+
this._clientLog.debug(`P2P pending pull postponed: ns=${ns}, upper_seq=${upperSeq}, contiguous=${contig}, state=${this._state}, closing=${this._closing}, reason=${reason}`);
|
|
2041
|
+
return false;
|
|
2042
|
+
}
|
|
2043
|
+
this._pendingP2pPullUpper.delete(ns);
|
|
2044
|
+
this._clientLog.info(`P2P pending push follow-up pull scheduled: ns=${ns}, upper_seq=${upperSeq}, contiguous=${contig}, reason=${reason}`);
|
|
2045
|
+
void this._fillP2pGap();
|
|
2046
|
+
return true;
|
|
2047
|
+
}
|
|
1995
2048
|
_markPublishedSeq(ns, seq) {
|
|
1996
2049
|
let pushed = this._pushedSeqs.get(ns);
|
|
1997
2050
|
if (!pushed) {
|
|
@@ -2242,6 +2295,9 @@ export class AUNClient {
|
|
|
2242
2295
|
return;
|
|
2243
2296
|
gate.inflight = false;
|
|
2244
2297
|
gate.startedAt = 0;
|
|
2298
|
+
if (key.startsWith('p2p:')) {
|
|
2299
|
+
this._schedulePendingP2pPullIfNeeded(key, 'pull-gate-release');
|
|
2300
|
+
}
|
|
2245
2301
|
}
|
|
2246
2302
|
_pullGateKeyForCall(method, params) {
|
|
2247
2303
|
if (method === 'message.pull' || method === 'message.v2.pull') {
|
|
@@ -2423,12 +2479,16 @@ export class AUNClient {
|
|
|
2423
2479
|
this._releasePullGate(key, token);
|
|
2424
2480
|
}
|
|
2425
2481
|
}
|
|
2426
|
-
async _tryRunBackgroundPull(key, operation, followupOnMessages = false) {
|
|
2427
|
-
if (key && this._isPullResponseProcessing(key))
|
|
2482
|
+
async _tryRunBackgroundPull(key, operation, followupOnMessages = false, onBusy) {
|
|
2483
|
+
if (key && this._isPullResponseProcessing(key)) {
|
|
2484
|
+
onBusy?.();
|
|
2428
2485
|
return false;
|
|
2486
|
+
}
|
|
2429
2487
|
const token = this._tryAcquirePullGate(key);
|
|
2430
|
-
if (token === null)
|
|
2488
|
+
if (token === null) {
|
|
2489
|
+
onBusy?.();
|
|
2431
2490
|
return false;
|
|
2491
|
+
}
|
|
2432
2492
|
let count = 0;
|
|
2433
2493
|
try {
|
|
2434
2494
|
count = await this._withBackgroundRpc(operation);
|
|
@@ -3420,6 +3480,7 @@ export class AUNClient {
|
|
|
3420
3480
|
this._gapFillDone.clear();
|
|
3421
3481
|
this._pushedSeqs.clear();
|
|
3422
3482
|
this._pendingOrderedMsgs.clear();
|
|
3483
|
+
this._pendingP2pPullUpper.clear();
|
|
3423
3484
|
this._v2SenderIKPending.clear();
|
|
3424
3485
|
this._v2SenderIKFetching.clear();
|
|
3425
3486
|
this._groupSynced.clear();
|
|
@@ -3432,6 +3493,7 @@ export class AUNClient {
|
|
|
3432
3493
|
this._gapFillDone.clear();
|
|
3433
3494
|
this._pushedSeqs.clear();
|
|
3434
3495
|
this._pendingOrderedMsgs.clear();
|
|
3496
|
+
this._pendingP2pPullUpper.clear();
|
|
3435
3497
|
this._v2SenderIKPending.clear();
|
|
3436
3498
|
this._v2SenderIKFetching.clear();
|
|
3437
3499
|
this._groupSynced.clear();
|
|
@@ -3706,6 +3768,27 @@ export class AUNClient {
|
|
|
3706
3768
|
identity = null;
|
|
3707
3769
|
}
|
|
3708
3770
|
}
|
|
3771
|
+
if (!identity?.private_key_pem) {
|
|
3772
|
+
// fallback:缓存的 identity 可能被 instanceState 污染,重新从 keystore 加载
|
|
3773
|
+
try {
|
|
3774
|
+
identity = this._keystore.loadIdentity(this._aid);
|
|
3775
|
+
if (identity?.private_key_pem) {
|
|
3776
|
+
this._identity = identity;
|
|
3777
|
+
this._clientLog.warn('V2 session init: identity cache was stale, reloaded from keystore');
|
|
3778
|
+
// 重新持久化 instance_state,清理脏数据
|
|
3779
|
+
const persistIdentity = this._auth._persistIdentity;
|
|
3780
|
+
if (typeof persistIdentity === 'function') {
|
|
3781
|
+
try {
|
|
3782
|
+
persistIdentity.call(this._auth, identity);
|
|
3783
|
+
}
|
|
3784
|
+
catch { /* best-effort */ }
|
|
3785
|
+
}
|
|
3786
|
+
}
|
|
3787
|
+
}
|
|
3788
|
+
catch {
|
|
3789
|
+
identity = null;
|
|
3790
|
+
}
|
|
3791
|
+
}
|
|
3709
3792
|
if (!identity?.private_key_pem) {
|
|
3710
3793
|
this._clientLog.warn('V2 session init skipped: no AID private key');
|
|
3711
3794
|
return;
|
|
@@ -4169,7 +4252,7 @@ export class AUNClient {
|
|
|
4169
4252
|
}
|
|
4170
4253
|
const decrypted = [];
|
|
4171
4254
|
let totalRawCount = 0;
|
|
4172
|
-
let nextAfterSeq = afterSeq || (ns ? this._seqTracker.getContiguousSeq(ns) : 0);
|
|
4255
|
+
let nextAfterSeq = opts?.force ? afterSeq : (afterSeq || (ns ? this._seqTracker.getContiguousSeq(ns) : 0));
|
|
4173
4256
|
let pageCount = 0;
|
|
4174
4257
|
const maxPages = 100;
|
|
4175
4258
|
while (pageCount < maxPages) {
|
|
@@ -4178,6 +4261,7 @@ export class AUNClient {
|
|
|
4178
4261
|
const result = await this._callRawV2Rpc('message.v2.pull', {
|
|
4179
4262
|
after_seq: nextAfterSeq,
|
|
4180
4263
|
limit,
|
|
4264
|
+
...(opts?.force ? { force: true } : {}),
|
|
4181
4265
|
});
|
|
4182
4266
|
const messages = (Array.isArray(result?.messages) ? result.messages : []);
|
|
4183
4267
|
totalRawCount += messages.length;
|
|
@@ -4844,6 +4928,12 @@ export class AUNClient {
|
|
|
4844
4928
|
encrypted: true,
|
|
4845
4929
|
e2ee,
|
|
4846
4930
|
};
|
|
4931
|
+
const explicitDirection = String(msg.direction ?? '').trim();
|
|
4932
|
+
result.direction = explicitDirection || (fromAid && fromAid === this._aid ? 'outbound_sync' : 'inbound');
|
|
4933
|
+
if (msg.device_id !== undefined)
|
|
4934
|
+
result.device_id = msg.device_id;
|
|
4935
|
+
if (msg.slot_id !== undefined)
|
|
4936
|
+
result.slot_id = msg.slot_id;
|
|
4847
4937
|
this._attachV2EnvelopeMetadata(result, e2ee);
|
|
4848
4938
|
this._logMessageDebug('decrypt-ok', 'v2.decrypt', groupIdForKeys ? 'group.message_created' : 'message.received', result);
|
|
4849
4939
|
return result;
|
|
@@ -4910,6 +5000,146 @@ export class AUNClient {
|
|
|
4910
5000
|
}
|
|
4911
5001
|
return null;
|
|
4912
5002
|
}
|
|
5003
|
+
_truthyBool(value) {
|
|
5004
|
+
if (value === true || value === 1)
|
|
5005
|
+
return true;
|
|
5006
|
+
if (typeof value === 'string') {
|
|
5007
|
+
const normalized = value.trim().toLowerCase();
|
|
5008
|
+
return normalized === 'true' || normalized === '1' || normalized === 'yes' || normalized === 'on';
|
|
5009
|
+
}
|
|
5010
|
+
return false;
|
|
5011
|
+
}
|
|
5012
|
+
_encryptedPushEnvelope(msg) {
|
|
5013
|
+
const payload = msg.payload;
|
|
5014
|
+
if (this._isEncryptedEnvelopePayload(payload))
|
|
5015
|
+
return payload;
|
|
5016
|
+
if (typeof msg.envelope_json === 'string' && msg.envelope_json.trim()) {
|
|
5017
|
+
try {
|
|
5018
|
+
const parsed = JSON.parse(msg.envelope_json);
|
|
5019
|
+
if (this._isEncryptedEnvelopePayload(parsed))
|
|
5020
|
+
return parsed;
|
|
5021
|
+
}
|
|
5022
|
+
catch {
|
|
5023
|
+
return null;
|
|
5024
|
+
}
|
|
5025
|
+
}
|
|
5026
|
+
return null;
|
|
5027
|
+
}
|
|
5028
|
+
_isEncryptedPushMessage(msg) {
|
|
5029
|
+
if (this._truthyBool(msg.encrypted))
|
|
5030
|
+
return true;
|
|
5031
|
+
return this._encryptedPushEnvelope(msg) !== null;
|
|
5032
|
+
}
|
|
5033
|
+
_isEncryptedEnvelopePayload(payload) {
|
|
5034
|
+
if (!isJsonObject(payload))
|
|
5035
|
+
return false;
|
|
5036
|
+
const envelope = payload;
|
|
5037
|
+
const payloadType = String(envelope.type ?? '').trim();
|
|
5038
|
+
if (payloadType.startsWith('e2ee.'))
|
|
5039
|
+
return true;
|
|
5040
|
+
if (!String(envelope.ciphertext ?? '').trim())
|
|
5041
|
+
return false;
|
|
5042
|
+
return envelope.nonce !== undefined
|
|
5043
|
+
|| envelope.tag !== undefined
|
|
5044
|
+
|| envelope.recipient !== undefined
|
|
5045
|
+
|| envelope.recipients !== undefined
|
|
5046
|
+
|| envelope.wrapped_key !== undefined
|
|
5047
|
+
|| envelope.recipients_digest !== undefined;
|
|
5048
|
+
}
|
|
5049
|
+
_isV2EncryptedEnvelopePayload(envelope) {
|
|
5050
|
+
if (!envelope)
|
|
5051
|
+
return false;
|
|
5052
|
+
const payloadType = String(envelope.type ?? '').trim();
|
|
5053
|
+
if (payloadType === 'e2ee.p2p_encrypted' || payloadType === 'e2ee.group_encrypted')
|
|
5054
|
+
return true;
|
|
5055
|
+
return String(envelope.version ?? '').trim().toLowerCase() === 'v2' && payloadType.startsWith('e2ee.');
|
|
5056
|
+
}
|
|
5057
|
+
_safeUndecryptablePushEvent(msg, group) {
|
|
5058
|
+
const event = {
|
|
5059
|
+
message_id: msg.message_id,
|
|
5060
|
+
from: msg.from,
|
|
5061
|
+
seq: msg.seq,
|
|
5062
|
+
timestamp: (msg.timestamp ?? msg.t_server),
|
|
5063
|
+
device_id: msg.device_id,
|
|
5064
|
+
slot_id: msg.slot_id,
|
|
5065
|
+
_decrypt_error: 'encrypted push payload is not decryptable on raw push path',
|
|
5066
|
+
_decrypt_stage: 'push_envelope',
|
|
5067
|
+
};
|
|
5068
|
+
if (group) {
|
|
5069
|
+
event.group_id = msg.group_id;
|
|
5070
|
+
}
|
|
5071
|
+
else {
|
|
5072
|
+
event.to = msg.to;
|
|
5073
|
+
}
|
|
5074
|
+
const envelope = this._encryptedPushEnvelope(msg);
|
|
5075
|
+
if (envelope) {
|
|
5076
|
+
event._envelope_type = String(envelope.type ?? '');
|
|
5077
|
+
event._suite = String(envelope.suite ?? '');
|
|
5078
|
+
if (this._isV2EncryptedEnvelopePayload(envelope)) {
|
|
5079
|
+
this._attachV2EnvelopeMetadata(event, this._v2E2eeMeta(envelope));
|
|
5080
|
+
}
|
|
5081
|
+
}
|
|
5082
|
+
return event;
|
|
5083
|
+
}
|
|
5084
|
+
async _decryptEncryptedPushPayload(msg, group) {
|
|
5085
|
+
const envelope = this._encryptedPushEnvelope(msg);
|
|
5086
|
+
if (!this._isV2EncryptedEnvelopePayload(envelope))
|
|
5087
|
+
return null;
|
|
5088
|
+
const aad = isJsonObject(envelope.aad) ? envelope.aad : {};
|
|
5089
|
+
const fromAid = String(msg.from_aid ?? msg.from ?? msg.sender_aid ?? aad.from ?? '').trim();
|
|
5090
|
+
const plaintext = await this._decryptV2EnvelopeForThought({ envelope, fromAid });
|
|
5091
|
+
if (!plaintext)
|
|
5092
|
+
return null;
|
|
5093
|
+
const e2ee = this._v2E2eeMeta(envelope);
|
|
5094
|
+
const result = {
|
|
5095
|
+
message_id: String(msg.message_id ?? ''),
|
|
5096
|
+
from: fromAid,
|
|
5097
|
+
seq: msg.seq,
|
|
5098
|
+
timestamp: (msg.t_server ?? msg.timestamp),
|
|
5099
|
+
payload: plaintext,
|
|
5100
|
+
encrypted: true,
|
|
5101
|
+
e2ee,
|
|
5102
|
+
};
|
|
5103
|
+
result.direction = fromAid && fromAid === this._aid ? 'outbound_sync' : 'inbound';
|
|
5104
|
+
if (msg.t_server !== undefined)
|
|
5105
|
+
result.t_server = msg.t_server;
|
|
5106
|
+
if (msg.device_id !== undefined)
|
|
5107
|
+
result.device_id = msg.device_id;
|
|
5108
|
+
if (msg.slot_id !== undefined)
|
|
5109
|
+
result.slot_id = msg.slot_id;
|
|
5110
|
+
if (group) {
|
|
5111
|
+
result.group_id = (msg.group_id ?? aad.group_id ?? envelope.group_id);
|
|
5112
|
+
}
|
|
5113
|
+
else {
|
|
5114
|
+
result.to = (msg.to ?? this._aid ?? '');
|
|
5115
|
+
}
|
|
5116
|
+
this._attachV2EnvelopeMetadata(result, e2ee);
|
|
5117
|
+
this._logMessageDebug('decrypt-ok', 'push.encrypted', group ? 'group.message_created' : 'message.received', result);
|
|
5118
|
+
return result;
|
|
5119
|
+
}
|
|
5120
|
+
async _publishEncryptedPushAsUndecryptable(event, ns, seq, msg, group) {
|
|
5121
|
+
const safeEvent = this._safeUndecryptablePushEvent(msg, group);
|
|
5122
|
+
this._logMessageDebug('decrypt-fail', 'push.encrypted', event, safeEvent);
|
|
5123
|
+
if (ns) {
|
|
5124
|
+
return await this._publishOrderedMessage(event, ns, seq, safeEvent);
|
|
5125
|
+
}
|
|
5126
|
+
const published = this._publishAppEvent(event, safeEvent, 'push');
|
|
5127
|
+
if (isPromiseLike(published))
|
|
5128
|
+
await published;
|
|
5129
|
+
return true;
|
|
5130
|
+
}
|
|
5131
|
+
async _publishEncryptedPushMessage(normalEvent, undecryptableEvent, ns, seq, msg, group) {
|
|
5132
|
+
const decrypted = await this._decryptEncryptedPushPayload(msg, group);
|
|
5133
|
+
if (decrypted) {
|
|
5134
|
+
if (ns)
|
|
5135
|
+
return await this._publishOrderedMessage(normalEvent, ns, seq, decrypted);
|
|
5136
|
+
const published = this._publishAppEvent(normalEvent, decrypted, 'push');
|
|
5137
|
+
if (isPromiseLike(published))
|
|
5138
|
+
await published;
|
|
5139
|
+
return true;
|
|
5140
|
+
}
|
|
5141
|
+
return await this._publishEncryptedPushAsUndecryptable(undecryptableEvent, ns, seq, msg, group);
|
|
5142
|
+
}
|
|
4913
5143
|
_metadataWithoutAuth(value) {
|
|
4914
5144
|
const candidate = value;
|
|
4915
5145
|
if (!isJsonObject(candidate))
|
|
@@ -5694,8 +5924,10 @@ export class AUNClient {
|
|
|
5694
5924
|
void this._tryRunBackgroundPull(ns, async () => {
|
|
5695
5925
|
const operationBefore = this._seqTracker.getContiguousSeq(ns);
|
|
5696
5926
|
const dedupKey = `p2p_pull:${ns}`;
|
|
5697
|
-
if (this._gapFillDone.has(dedupKey))
|
|
5927
|
+
if (this._gapFillDone.has(dedupKey)) {
|
|
5928
|
+
this._recordPendingP2pPull(ns, pushSeq);
|
|
5698
5929
|
return 0;
|
|
5930
|
+
}
|
|
5699
5931
|
this._gapFillDone.set(dedupKey, Date.now());
|
|
5700
5932
|
try {
|
|
5701
5933
|
const pulled = await this.pullV2(0, 50, { gateLocked: true });
|
|
@@ -5708,7 +5940,7 @@ export class AUNClient {
|
|
|
5708
5940
|
finally {
|
|
5709
5941
|
this._gapFillDone.delete(dedupKey);
|
|
5710
5942
|
}
|
|
5711
|
-
}, true).catch((exc) => {
|
|
5943
|
+
}, true, () => this._recordPendingP2pPull(ns, pushSeq)).catch((exc) => {
|
|
5712
5944
|
const newContig = this._seqTracker.getContiguousSeq(ns);
|
|
5713
5945
|
this._clientLog.warn(`V2 push auto-pull failed: contiguous_seq=${contigBefore}->${newContig} err=${formatCaughtError(exc)}`);
|
|
5714
5946
|
});
|