@agentunion/fastaun-browser 0.5.10 → 0.5.11
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 +32 -0
- package/_packed_docs/CHANGELOG.md +32 -0
- package/_packed_docs/INDEX.md +3 -3
- package/_packed_docs/KITE_DOCS_GUIDE.md +1 -1
- package/_packed_docs/sdk/06-API/346/211/213/345/206/214.md +59 -0
- package/_packed_docs/sdk/AUN_DOCS_GUIDE.md +3 -2
- package/_packed_docs/sdk/INDEX.md +2 -1
- package/dist/bundle.js +588 -88
- package/dist/client/delivery.d.ts +11 -4
- package/dist/client/delivery.d.ts.map +1 -1
- package/dist/client/delivery.js +180 -31
- package/dist/client/delivery.js.map +1 -1
- package/dist/client/rpc-pipeline.d.ts.map +1 -1
- package/dist/client/rpc-pipeline.js +14 -2
- package/dist/client/rpc-pipeline.js.map +1 -1
- package/dist/client/v2-e2ee.d.ts +3 -0
- package/dist/client/v2-e2ee.d.ts.map +1 -1
- package/dist/client/v2-e2ee.js +147 -32
- package/dist/client/v2-e2ee.js.map +1 -1
- package/dist/client.d.ts +1 -0
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +61 -2
- package/dist/client.js.map +1 -1
- package/dist/transport.d.ts.map +1 -1
- package/dist/transport.js +159 -15
- package/dist/transport.js.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +1 -1
package/dist/client/v2-e2ee.js
CHANGED
|
@@ -902,7 +902,7 @@ export class V2E2EECoordinator {
|
|
|
902
902
|
let plaintext = null;
|
|
903
903
|
const retryStatus = {};
|
|
904
904
|
try {
|
|
905
|
-
plaintext = await client._decryptV2Message(entry.msg, false, true, true, true, retryStatus);
|
|
905
|
+
plaintext = await client._decryptV2Message(entry.msg, false, true, true, true, retryStatus, false, 'pending_retry');
|
|
906
906
|
}
|
|
907
907
|
catch (exc) {
|
|
908
908
|
if (!generationCurrent())
|
|
@@ -932,10 +932,10 @@ export class V2E2EECoordinator {
|
|
|
932
932
|
if (entry.groupId) {
|
|
933
933
|
plaintext = normalizeGroupMentionMode(plaintext, entry.msg, entry.msg.envelope_json);
|
|
934
934
|
plaintext.group_id = entry.groupId;
|
|
935
|
-
await client._publishPulledMessage('group.message_created', `group:${entry.groupId}`, seq, plaintext);
|
|
935
|
+
await client._publishPulledMessage('group.message_created', `group:${entry.groupId}`, seq, plaintext, false, 'pending_retry');
|
|
936
936
|
}
|
|
937
937
|
else {
|
|
938
|
-
await client._publishPulledMessage('message.received', `p2p:${client._aid ?? ''}`, seq, plaintext);
|
|
938
|
+
await client._publishPulledMessage('message.received', `p2p:${client._aid ?? ''}`, seq, plaintext, false, 'pending_retry');
|
|
939
939
|
}
|
|
940
940
|
client._clientLog.debug(`V2 sender IK pending retry delivered: key=${key}`);
|
|
941
941
|
}
|
|
@@ -1014,10 +1014,10 @@ export class V2E2EECoordinator {
|
|
|
1014
1014
|
if (String(msg.version ?? '') === 'v1') {
|
|
1015
1015
|
const legacy = isJsonObject(msg.legacy_v1)
|
|
1016
1016
|
? msg.legacy_v1 : {};
|
|
1017
|
-
const payload = legacy.payload;
|
|
1017
|
+
const payload = legacy.payload !== undefined ? legacy.payload : msg.payload;
|
|
1018
1018
|
const payloadType = isJsonObject(payload)
|
|
1019
1019
|
? String(payload.type ?? '').trim() : '';
|
|
1020
|
-
if (payload !== undefined && payload !== null && !['e2ee.encrypted', 'e2ee.group_encrypted'].includes(payloadType)) {
|
|
1020
|
+
if (payload !== undefined && payload !== null && !['e2ee.encrypted', 'e2ee.group_encrypted', 'e2ee.p2p_encrypted'].includes(payloadType)) {
|
|
1021
1021
|
plaintext = {
|
|
1022
1022
|
message_id: String(msg.message_id ?? ''), from: String(msg.from_aid ?? ''),
|
|
1023
1023
|
to: String(legacy.to ?? client._aid ?? ''), seq, type: String(msg.type ?? ''),
|
|
@@ -1025,6 +1025,11 @@ export class V2E2EECoordinator {
|
|
|
1025
1025
|
};
|
|
1026
1026
|
attachGatewayProximity(plaintext, msg);
|
|
1027
1027
|
}
|
|
1028
|
+
else if (isJsonObject(payload)
|
|
1029
|
+
&& ['e2ee.p2p_encrypted', 'e2ee.encrypted'].includes(payloadType)) {
|
|
1030
|
+
msg = { ...msg, envelope_json: JSON.stringify(payload) };
|
|
1031
|
+
plaintext = await client._decryptV2Message(msg, false, !history, true, true, undefined, false, source);
|
|
1032
|
+
}
|
|
1028
1033
|
}
|
|
1029
1034
|
else {
|
|
1030
1035
|
plaintext = source === 'inline_push'
|
|
@@ -1054,26 +1059,48 @@ export class V2E2EECoordinator {
|
|
|
1054
1059
|
let plaintext = null;
|
|
1055
1060
|
if (String(msg.version ?? '') === 'v1') {
|
|
1056
1061
|
const payload = msg.payload;
|
|
1062
|
+
const recall = typeof client._delivery?.recallEventFromGroupMessage === 'function'
|
|
1063
|
+
? client._delivery.recallEventFromGroupMessage(msg)
|
|
1064
|
+
: null;
|
|
1065
|
+
if (recall) {
|
|
1066
|
+
const recallPayload = {
|
|
1067
|
+
...recall,
|
|
1068
|
+
group_id: groupId,
|
|
1069
|
+
group_aid: groupAid,
|
|
1070
|
+
seq,
|
|
1071
|
+
};
|
|
1072
|
+
if (publish) {
|
|
1073
|
+
if (orderedPublish) {
|
|
1074
|
+
await client._delivery.publishOrderedMessage('group.message_recalled', `group:${groupId}`, seq, recallPayload, source);
|
|
1075
|
+
}
|
|
1076
|
+
else {
|
|
1077
|
+
await client._publishAppEvent('group.message_recalled', recallPayload, source);
|
|
1078
|
+
}
|
|
1079
|
+
}
|
|
1080
|
+
return recallPayload;
|
|
1081
|
+
}
|
|
1057
1082
|
if (payload === undefined || payload === null) {
|
|
1058
1083
|
if (history)
|
|
1059
1084
|
return this.historyDecryptFailure(msg, 'legacy payload is missing');
|
|
1060
1085
|
client._clientLog.warn(`Group Tail 缺少 payload 的 V1 行已跳过,连续性证明仍保留: group=${groupId}, seq=${seq}`);
|
|
1061
1086
|
return null;
|
|
1062
1087
|
}
|
|
1088
|
+
const payloadType = isJsonObject(payload)
|
|
1089
|
+
? String(payload.type ?? '').trim() : '';
|
|
1063
1090
|
if (isJsonObject(payload)
|
|
1064
|
-
&& ['e2ee.
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1091
|
+
&& ['e2ee.group_encrypted', 'e2ee.p2p_encrypted', 'e2ee.encrypted'].includes(payloadType)) {
|
|
1092
|
+
msg = { ...msg, envelope_json: JSON.stringify(payload) };
|
|
1093
|
+
plaintext = await client._decryptV2Message(msg, false, !history, true, true, undefined, false, source);
|
|
1094
|
+
}
|
|
1095
|
+
else {
|
|
1096
|
+
plaintext = {
|
|
1097
|
+
message_id: String(msg.message_id ?? ''), from: String(msg.from_aid ?? ''),
|
|
1098
|
+
group_id: groupId, group_aid: groupAid, seq, type: String(msg.type ?? ''),
|
|
1099
|
+
timestamp: msg.t_server, payload: payload, encrypted: false,
|
|
1100
|
+
};
|
|
1101
|
+
plaintext = normalizeGroupMentionMode(plaintext, msg, msg.envelope_json);
|
|
1102
|
+
attachGatewayProximity(plaintext, msg);
|
|
1069
1103
|
}
|
|
1070
|
-
plaintext = {
|
|
1071
|
-
message_id: String(msg.message_id ?? ''), from: String(msg.from_aid ?? ''),
|
|
1072
|
-
group_id: groupId, group_aid: groupAid, seq, type: String(msg.type ?? ''),
|
|
1073
|
-
timestamp: msg.t_server, payload: payload, encrypted: false,
|
|
1074
|
-
};
|
|
1075
|
-
plaintext = normalizeGroupMentionMode(plaintext, msg, msg.envelope_json);
|
|
1076
|
-
attachGatewayProximity(plaintext, msg);
|
|
1077
1104
|
}
|
|
1078
1105
|
else {
|
|
1079
1106
|
plaintext = source === 'inline_push'
|
|
@@ -1129,6 +1156,8 @@ export class V2E2EECoordinator {
|
|
|
1129
1156
|
const afterSeq = strictWindowSeq(params.after_seq ?? 0, 'after_seq');
|
|
1130
1157
|
const limit = strictWindowLimit(params.limit ?? V2_PULL_DEFAULT_PAGE_LIMIT);
|
|
1131
1158
|
const ns = client._aid ? `p2p:${client._aid}` : '';
|
|
1159
|
+
if (ns)
|
|
1160
|
+
client._delivery.onPullStarted?.(ns);
|
|
1132
1161
|
const result = await client._callRawV2Rpc('message.v2.pull', { window_mode: 'tail', after_seq: afterSeq, limit, _rpc_foreground: true });
|
|
1133
1162
|
const floor = Number(result.retention_floor_seq ?? 0);
|
|
1134
1163
|
const previous = ns ? client._seqTracker.getSyncState(ns) : null;
|
|
@@ -1150,6 +1179,9 @@ export class V2E2EECoordinator {
|
|
|
1150
1179
|
const ack = ns ? client._seqTracker.getContiguousSeq(ns) : 0;
|
|
1151
1180
|
if (previous && ack > previous.ack)
|
|
1152
1181
|
await this.ackV2(ack);
|
|
1182
|
+
if (ns)
|
|
1183
|
+
client._delivery.onPullPage?.(ns, decoded.length, result.has_more === true, page.head, typeof result.remaining === 'number' && Number.isSafeInteger(result.remaining) && result.remaining >= 0 ? result.remaining : null, page.messages.length, ack, page.head);
|
|
1184
|
+
client._delivery.onPullWorkSettled?.();
|
|
1153
1185
|
return { ...result, messages: decoded, raw_count: page.messages.length };
|
|
1154
1186
|
}
|
|
1155
1187
|
async historyV2Internal(params) {
|
|
@@ -1165,16 +1197,33 @@ export class V2E2EECoordinator {
|
|
|
1165
1197
|
}
|
|
1166
1198
|
return { ...result, messages: decoded };
|
|
1167
1199
|
}
|
|
1200
|
+
async runPullWithLifecycle(ns, operation) {
|
|
1201
|
+
if (ns)
|
|
1202
|
+
this.client._delivery.onPullStarted?.(ns);
|
|
1203
|
+
try {
|
|
1204
|
+
return await operation();
|
|
1205
|
+
}
|
|
1206
|
+
catch (error) {
|
|
1207
|
+
this.client._delivery.onPullAborted?.();
|
|
1208
|
+
throw error;
|
|
1209
|
+
}
|
|
1210
|
+
}
|
|
1168
1211
|
async pullV2(afterSeq = 0, limit = 50, opts) {
|
|
1212
|
+
const ns = this.client._aid ? `p2p:${this.client._aid}` : '';
|
|
1213
|
+
return await this.runPullWithLifecycle(ns, () => this.pullV2Impl(afterSeq, limit, opts));
|
|
1214
|
+
}
|
|
1215
|
+
async pullV2Impl(afterSeq = 0, limit = 50, opts) {
|
|
1169
1216
|
const client = this.client;
|
|
1170
1217
|
await client._ensureV2SessionReady('message.pull');
|
|
1171
1218
|
const ns = client._aid ? `p2p:${client._aid}` : '';
|
|
1219
|
+
if (ns)
|
|
1220
|
+
client._delivery.onPullStarted?.(ns);
|
|
1172
1221
|
if (opts?.windowMode === 'tail') {
|
|
1173
1222
|
if (!opts.gateLocked) {
|
|
1174
1223
|
const key = pullGateKeyForClient(client, 'message.v2.pull', {
|
|
1175
1224
|
window_mode: 'tail', after_seq: afterSeq, limit,
|
|
1176
1225
|
}, `${ns}|tail|after=${afterSeq}|limit=${limit}`);
|
|
1177
|
-
return await client._runPullSerialized(key, () => this.
|
|
1226
|
+
return await client._runPullSerialized(key, () => this.pullV2Impl(afterSeq, limit, {
|
|
1178
1227
|
...(opts ?? {}),
|
|
1179
1228
|
gateLocked: true,
|
|
1180
1229
|
}), false);
|
|
@@ -1186,7 +1235,7 @@ export class V2E2EECoordinator {
|
|
|
1186
1235
|
const key = pullGateKeyForClient(client, 'message.v2.pull', {
|
|
1187
1236
|
after_seq: afterSeq, force: opts?.force === true, limit,
|
|
1188
1237
|
}, `${ns}|forward|after=${afterSeq}|force=${String(Boolean(opts?.force))}|limit=${limit}`);
|
|
1189
|
-
return await client._runPullSerialized(key, () => this.
|
|
1238
|
+
return await client._runPullSerialized(key, () => this.pullV2Impl(afterSeq, limit, {
|
|
1190
1239
|
...(opts ?? {}),
|
|
1191
1240
|
gateLocked: true,
|
|
1192
1241
|
}), true);
|
|
@@ -1250,6 +1299,7 @@ export class V2E2EECoordinator {
|
|
|
1250
1299
|
const pageMaxSeq = seqs.length > 0 ? Math.max(...seqs) : nextAfterSeq;
|
|
1251
1300
|
const deferredKeyFetches = new Map();
|
|
1252
1301
|
let blockedSeq = 0;
|
|
1302
|
+
const pageDecryptedBefore = decrypted.length;
|
|
1253
1303
|
for (const msg of messages) {
|
|
1254
1304
|
const seq = Number(msg.seq ?? 0);
|
|
1255
1305
|
if (!Number.isFinite(seq) || seq <= 0)
|
|
@@ -1257,12 +1307,12 @@ export class V2E2EECoordinator {
|
|
|
1257
1307
|
const version = String(msg.version ?? 'v2');
|
|
1258
1308
|
if (version === 'v1') {
|
|
1259
1309
|
const legacy = isJsonObject(msg.legacy_v1) ? msg.legacy_v1 : {};
|
|
1260
|
-
const legacyPayload = legacy.payload;
|
|
1310
|
+
const legacyPayload = legacy.payload !== undefined ? legacy.payload : msg.payload;
|
|
1261
1311
|
const payloadType = isJsonObject(legacyPayload)
|
|
1262
1312
|
? String(legacyPayload.type ?? '').trim()
|
|
1263
1313
|
: '';
|
|
1264
1314
|
if (legacyPayload !== undefined && legacyPayload !== null
|
|
1265
|
-
&&
|
|
1315
|
+
&& !['e2ee.encrypted', 'e2ee.group_encrypted', 'e2ee.p2p_encrypted'].includes(payloadType)) {
|
|
1266
1316
|
const v1Msg = {
|
|
1267
1317
|
message_id: String(msg.message_id ?? ''),
|
|
1268
1318
|
from: String(msg.from_aid ?? ''),
|
|
@@ -1281,6 +1331,25 @@ export class V2E2EECoordinator {
|
|
|
1281
1331
|
await client._publishAppEvent(appEvent.event, appEvent.payload, 'pull');
|
|
1282
1332
|
decrypted.push(v1Msg);
|
|
1283
1333
|
}
|
|
1334
|
+
else if (isJsonObject(legacyPayload)
|
|
1335
|
+
&& ['e2ee.p2p_encrypted', 'e2ee.encrypted'].includes(payloadType)) {
|
|
1336
|
+
const deferStatus = {};
|
|
1337
|
+
const plaintext = await client._decryptV2Message({ ...msg, envelope_json: JSON.stringify(legacyPayload) }, true, true, true, true, deferStatus, true, 'pull');
|
|
1338
|
+
if (deferStatus.deferred) {
|
|
1339
|
+
blockedSeq = blockedSeq > 0 ? Math.min(blockedSeq, seq) : seq;
|
|
1340
|
+
if (deferStatus.fromAid) {
|
|
1341
|
+
const key = `${deferStatus.fromAid}\u0000${deferStatus.senderDeviceId ?? ''}\u0000${deferStatus.groupId ?? ''}`;
|
|
1342
|
+
deferredKeyFetches.set(key, { fromAid: deferStatus.fromAid, senderDeviceId: deferStatus.senderDeviceId ?? '', groupId: deferStatus.groupId ?? '' });
|
|
1343
|
+
}
|
|
1344
|
+
}
|
|
1345
|
+
if (plaintext) {
|
|
1346
|
+
if (ns)
|
|
1347
|
+
await client._publishPulledMessage('message.received', ns, seq, plaintext, false);
|
|
1348
|
+
else
|
|
1349
|
+
await client._publishAppEvent('message.received', plaintext, 'pull');
|
|
1350
|
+
decrypted.push(plaintext);
|
|
1351
|
+
}
|
|
1352
|
+
}
|
|
1284
1353
|
else {
|
|
1285
1354
|
client._clientLog.debug(`message.v2.pull skipping V1 envelope seq=${seq} payload_type=${payloadType || '<none>'} (V1 E2EE removed)`);
|
|
1286
1355
|
}
|
|
@@ -1295,7 +1364,7 @@ export class V2E2EECoordinator {
|
|
|
1295
1364
|
client._v2Session.trackOldSPKMaxSeq(msgSpkId, seq);
|
|
1296
1365
|
}
|
|
1297
1366
|
const deferStatus = {};
|
|
1298
|
-
const plaintext = await client._decryptV2Message(msg, true, true, true, true, deferStatus, true);
|
|
1367
|
+
const plaintext = await client._decryptV2Message(msg, true, true, true, true, deferStatus, true, 'pull');
|
|
1299
1368
|
if (deferStatus.deferred) {
|
|
1300
1369
|
blockedSeq = blockedSeq > 0 ? Math.min(blockedSeq, seq) : seq;
|
|
1301
1370
|
}
|
|
@@ -1375,7 +1444,7 @@ export class V2E2EECoordinator {
|
|
|
1375
1444
|
if (ackNeeded) {
|
|
1376
1445
|
this.recordForwardAck(ns, ackSeq);
|
|
1377
1446
|
const nextAfter = Math.max(pageMaxSeq, nextAfterSeq);
|
|
1378
|
-
const canContinuePage = messages.length > 0 && nextAfter > nextAfterSeq;
|
|
1447
|
+
const canContinuePage = blockedSeq <= 0 && messages.length > 0 && nextAfter > nextAfterSeq;
|
|
1379
1448
|
if (canContinuePage) {
|
|
1380
1449
|
pendingAckSeq = Math.max(pendingAckSeq, ackSeq);
|
|
1381
1450
|
lastAutoAckSeq = Math.max(lastAutoAckSeq, ackSeq);
|
|
@@ -1386,6 +1455,8 @@ export class V2E2EECoordinator {
|
|
|
1386
1455
|
}
|
|
1387
1456
|
}
|
|
1388
1457
|
}
|
|
1458
|
+
if (ns)
|
|
1459
|
+
client._delivery.onPullPage?.(ns, decrypted.length - pageDecryptedBefore, hasMore, pageMaxSeq, typeof result.remaining === 'number' && Number.isSafeInteger(result.remaining) && result.remaining >= 0 ? result.remaining : null, messages.length, client._seqTracker.getContiguousSeq(ns), pageMaxSeq);
|
|
1389
1460
|
const nextAfter = Math.max(pageMaxSeq, nextAfterSeq);
|
|
1390
1461
|
const rawCount = messages.length;
|
|
1391
1462
|
if (blockedSeq > 0)
|
|
@@ -1421,6 +1492,7 @@ export class V2E2EECoordinator {
|
|
|
1421
1492
|
pendingAckSeq = 0;
|
|
1422
1493
|
}
|
|
1423
1494
|
}
|
|
1495
|
+
client._delivery.onPullWorkSettled?.();
|
|
1424
1496
|
return decrypted;
|
|
1425
1497
|
}
|
|
1426
1498
|
async confirmForwardP2PAck(upToSeq, inlineGeneration) {
|
|
@@ -1574,6 +1646,14 @@ export class V2E2EECoordinator {
|
|
|
1574
1646
|
const afterSeq = strictWindowSeq(params.after_seq ?? 0, 'after_seq');
|
|
1575
1647
|
const limit = strictWindowLimit(params.limit ?? V2_PULL_DEFAULT_PAGE_LIMIT);
|
|
1576
1648
|
const ns = `group:${groupId}`;
|
|
1649
|
+
const cursorParams = isJsonObject(params._group_cursor_params)
|
|
1650
|
+
? params._group_cursor_params : params;
|
|
1651
|
+
const requestDeviceId = String(cursorParams.device_id ?? '').trim();
|
|
1652
|
+
const requestSlotId = String(cursorParams.slot_id ?? '').trim();
|
|
1653
|
+
const ownsCursor = (!requestDeviceId || requestDeviceId === String(client._deviceId ?? ''))
|
|
1654
|
+
&& (!requestSlotId || requestSlotId === String(client._slotId ?? ''));
|
|
1655
|
+
if (ownsCursor)
|
|
1656
|
+
client._delivery.onPullStarted?.(ns);
|
|
1577
1657
|
const result = await client._callRawV2Rpc('group.v2.pull', withExplicitGroupAid({
|
|
1578
1658
|
group_id: groupId, window_mode: 'tail', after_seq: afterSeq, limit, _rpc_foreground: true,
|
|
1579
1659
|
}, groupAid));
|
|
@@ -1599,6 +1679,9 @@ export class V2E2EECoordinator {
|
|
|
1599
1679
|
const ack = client._seqTracker.getContiguousSeq(ns);
|
|
1600
1680
|
if (ack > previous.ack)
|
|
1601
1681
|
await this.ackGroupV2(groupId, ack, groupAid);
|
|
1682
|
+
if (ownsCursor)
|
|
1683
|
+
client._delivery.onPullPage?.(ns, decoded.length, result.has_more === true, page.head, typeof result.remaining === 'number' && Number.isSafeInteger(result.remaining) && result.remaining >= 0 ? result.remaining : null, page.messages.length, ack, page.head);
|
|
1684
|
+
client._delivery.onPullWorkSettled?.();
|
|
1602
1685
|
return { ...result, messages: decoded, raw_count: page.messages.length };
|
|
1603
1686
|
}
|
|
1604
1687
|
async historyGroupV2Internal(params) {
|
|
@@ -1631,6 +1714,13 @@ export class V2E2EECoordinator {
|
|
|
1631
1714
|
});
|
|
1632
1715
|
}
|
|
1633
1716
|
async pullGroupV2(groupId, afterSeq = 0, limit = 50, opts) {
|
|
1717
|
+
const lifecycleNs = `group:${String(groupId ?? '').trim()}`;
|
|
1718
|
+
if (opts?.ownsCursor === false) {
|
|
1719
|
+
return await this.pullGroupV2Impl(groupId, afterSeq, limit, opts);
|
|
1720
|
+
}
|
|
1721
|
+
return await this.runPullWithLifecycle(lifecycleNs, () => this.pullGroupV2Impl(groupId, afterSeq, limit, opts));
|
|
1722
|
+
}
|
|
1723
|
+
async pullGroupV2Impl(groupId, afterSeq = 0, limit = 50, opts) {
|
|
1634
1724
|
const client = this.client;
|
|
1635
1725
|
await client._ensureV2SessionReady('group.pull');
|
|
1636
1726
|
const gid = String(groupId ?? '').trim();
|
|
@@ -1644,12 +1734,13 @@ export class V2E2EECoordinator {
|
|
|
1644
1734
|
group_id: gid, window_mode: 'tail', after_seq: afterSeq, limit,
|
|
1645
1735
|
_group_cursor_params: opts?.cursorParams,
|
|
1646
1736
|
}, `${ns}|tail|after=${afterSeq}|limit=${limit}`);
|
|
1647
|
-
return await client._runPullSerialized(key, () => this.
|
|
1737
|
+
return await client._runPullSerialized(key, () => this.pullGroupV2Impl(gid, afterSeq, limit, {
|
|
1648
1738
|
...(opts ?? {}),
|
|
1649
1739
|
gateLocked: true,
|
|
1650
1740
|
}), false);
|
|
1651
1741
|
}
|
|
1652
1742
|
const result = await this.pullGroupV2TailInternal({
|
|
1743
|
+
...(opts?.cursorParams ?? {}),
|
|
1653
1744
|
group_id: String(opts.wireGroupId ?? gid), group_aid: groupAid || undefined,
|
|
1654
1745
|
window_mode: 'tail', after_seq: afterSeq, limit,
|
|
1655
1746
|
});
|
|
@@ -1660,7 +1751,7 @@ export class V2E2EECoordinator {
|
|
|
1660
1751
|
group_id: gid, after_seq: afterSeq, force: opts?.force === true, limit,
|
|
1661
1752
|
_group_cursor_params: opts?.cursorParams,
|
|
1662
1753
|
}, `${ns}|forward|after=${afterSeq}|force=${String(Boolean(opts?.force))}|limit=${limit}`);
|
|
1663
|
-
return await client._runPullSerialized(key, () => this.
|
|
1754
|
+
return await client._runPullSerialized(key, () => this.pullGroupV2Impl(gid, afterSeq, limit, {
|
|
1664
1755
|
...(opts ?? {}),
|
|
1665
1756
|
gateLocked: true,
|
|
1666
1757
|
}), true);
|
|
@@ -1669,6 +1760,8 @@ export class V2E2EECoordinator {
|
|
|
1669
1760
|
const wireGroupId = String(opts?.wireGroupId ?? groupId ?? '').trim() || gid;
|
|
1670
1761
|
const cursorParams = opts?.cursorParams ?? {};
|
|
1671
1762
|
const ownsCursor = opts?.ownsCursor !== false;
|
|
1763
|
+
if (ownsCursor)
|
|
1764
|
+
client._delivery.onPullStarted?.(ns);
|
|
1672
1765
|
let pullGateKey = ownsCursor
|
|
1673
1766
|
? pullGateKeyForClient(client, 'group.v2.pull', {
|
|
1674
1767
|
group_id: gid, after_seq: afterSeq, force: opts?.force === true, limit,
|
|
@@ -1737,28 +1830,31 @@ export class V2E2EECoordinator {
|
|
|
1737
1830
|
const pageMaxSeq = seqs.length > 0 ? Math.max(...seqs) : nextAfterSeq;
|
|
1738
1831
|
const deferredKeyFetches = new Map();
|
|
1739
1832
|
let blockedSeq = 0;
|
|
1833
|
+
const pageDecryptedBefore = decrypted.length;
|
|
1740
1834
|
for (const msg of messages) {
|
|
1741
1835
|
const seq = Number(msg.seq ?? 0);
|
|
1742
1836
|
if (!Number.isFinite(seq) || seq <= 0)
|
|
1743
1837
|
continue;
|
|
1744
1838
|
const version = String(msg.version ?? 'v2');
|
|
1745
1839
|
if (version === 'v1') {
|
|
1746
|
-
const
|
|
1840
|
+
const legacy = isJsonObject(msg.legacy_v1) ? msg.legacy_v1 : {};
|
|
1841
|
+
const payload = msg.payload !== undefined ? msg.payload : legacy.payload;
|
|
1747
1842
|
const payloadObj = isJsonObject(payload) ? payload : null;
|
|
1748
1843
|
// 群撤回 tombstone(占位 / 通知):归一化为 group.message_recalled 事件,仍占 seq。
|
|
1749
|
-
if (client._delivery
|
|
1844
|
+
if (typeof client._delivery?.recallEventFromGroupMessage === 'function'
|
|
1845
|
+
&& client._delivery.recallEventFromGroupMessage(msg)) {
|
|
1750
1846
|
await client._delivery.publishGroupRecallTombstone(gid, seq, {
|
|
1751
1847
|
...msg,
|
|
1752
1848
|
group_id: gid,
|
|
1753
1849
|
group_aid: eventGroupAid,
|
|
1754
|
-
});
|
|
1850
|
+
}, 'pull');
|
|
1755
1851
|
client._markPublishedSeq(ns, seq);
|
|
1756
1852
|
client._clientLog.debug(`group.v2.pull recall tombstone delivered: group=${gid}, seq=${seq}`);
|
|
1757
1853
|
continue;
|
|
1758
1854
|
}
|
|
1759
1855
|
if (payloadObj) {
|
|
1760
1856
|
const payloadType = String(payloadObj.type ?? '').trim();
|
|
1761
|
-
if (payloadType !== 'e2ee.encrypted' && payloadType !== 'e2ee.group_encrypted') {
|
|
1857
|
+
if (payloadType !== 'e2ee.encrypted' && payloadType !== 'e2ee.group_encrypted' && payloadType !== 'e2ee.p2p_encrypted') {
|
|
1762
1858
|
let v1Msg = {
|
|
1763
1859
|
message_id: String(msg.message_id ?? ''),
|
|
1764
1860
|
from: String(msg.from_aid ?? ''),
|
|
@@ -1795,6 +1891,23 @@ export class V2E2EECoordinator {
|
|
|
1795
1891
|
decrypted.push(v1Msg);
|
|
1796
1892
|
continue;
|
|
1797
1893
|
}
|
|
1894
|
+
if (payloadObj && ['e2ee.group_encrypted', 'e2ee.p2p_encrypted', 'e2ee.encrypted'].includes(String(payloadObj.type ?? '').trim())) {
|
|
1895
|
+
const deferStatus = {};
|
|
1896
|
+
const plaintext = await client._decryptV2Message({ ...msg, envelope_json: JSON.stringify(payloadObj) }, true, true, true, true, deferStatus, true, 'pull');
|
|
1897
|
+
if (deferStatus.deferred) {
|
|
1898
|
+
blockedSeq = blockedSeq > 0 ? Math.min(blockedSeq, seq) : seq;
|
|
1899
|
+
if (deferStatus.fromAid) {
|
|
1900
|
+
const key = `${deferStatus.fromAid}\u0000${deferStatus.senderDeviceId ?? ''}\u0000${deferStatus.groupId ?? ''}`;
|
|
1901
|
+
deferredKeyFetches.set(key, { fromAid: deferStatus.fromAid, senderDeviceId: deferStatus.senderDeviceId ?? '', groupId: deferStatus.groupId ?? '' });
|
|
1902
|
+
}
|
|
1903
|
+
}
|
|
1904
|
+
if (plaintext) {
|
|
1905
|
+
plaintext.group_id = gid;
|
|
1906
|
+
plaintext.group_aid = eventGroupAid;
|
|
1907
|
+
await client._publishPulledMessage('group.message_created', ns, seq, plaintext, false);
|
|
1908
|
+
decrypted.push(plaintext);
|
|
1909
|
+
}
|
|
1910
|
+
}
|
|
1798
1911
|
client._clientLog.debug(`group.v2.pull skipping V1 envelope group=${gid} seq=${seq} payload_type=${payloadObj ? String(payloadObj.type ?? '') : '<none>'} (V1 E2EE removed)`);
|
|
1799
1912
|
continue;
|
|
1800
1913
|
}
|
|
@@ -1803,7 +1916,7 @@ export class V2E2EECoordinator {
|
|
|
1803
1916
|
continue;
|
|
1804
1917
|
}
|
|
1805
1918
|
const deferStatus = {};
|
|
1806
|
-
let plaintext = await client._decryptV2Message(msg, true, true, true, true, deferStatus, true);
|
|
1919
|
+
let plaintext = await client._decryptV2Message(msg, true, true, true, true, deferStatus, true, 'pull');
|
|
1807
1920
|
if (deferStatus.deferred) {
|
|
1808
1921
|
blockedSeq = blockedSeq > 0 ? Math.min(blockedSeq, seq) : seq;
|
|
1809
1922
|
}
|
|
@@ -1867,6 +1980,7 @@ export class V2E2EECoordinator {
|
|
|
1867
1980
|
for (const fetch of deferredKeyFetches.values()) {
|
|
1868
1981
|
this.scheduleSenderIKFetch(fetch.fromAid, fetch.senderDeviceId, fetch.groupId);
|
|
1869
1982
|
}
|
|
1983
|
+
client._delivery.onPullPage?.(ns, decrypted.length - pageDecryptedBefore, hasMore, pageMaxSeq, typeof result.remaining === 'number' && Number.isSafeInteger(result.remaining) && result.remaining >= 0 ? result.remaining : null, messages.length, client._seqTracker.getContiguousSeq(ns), pageMaxSeq);
|
|
1870
1984
|
if (ownsCursor && parsedCursorCurrentSeq !== null && cursorCurrentSeq > ackSeq) {
|
|
1871
1985
|
this.recordForwardCursor(ns, cursorCurrentSeq, ackSeq);
|
|
1872
1986
|
}
|
|
@@ -1884,7 +1998,7 @@ export class V2E2EECoordinator {
|
|
|
1884
1998
|
if (ackNeeded) {
|
|
1885
1999
|
this.recordForwardAck(ns, ackSeq);
|
|
1886
2000
|
const nextAfter = Math.max(pageMaxSeq, nextAfterSeq);
|
|
1887
|
-
const canContinuePage = messages.length > 0 && nextAfter > nextAfterSeq && ownsCursor;
|
|
2001
|
+
const canContinuePage = blockedSeq <= 0 && messages.length > 0 && nextAfter > nextAfterSeq && ownsCursor;
|
|
1888
2002
|
if (canContinuePage) {
|
|
1889
2003
|
pendingAckSeq = Math.max(pendingAckSeq, ackSeq);
|
|
1890
2004
|
lastAutoAckSeq = Math.max(lastAutoAckSeq, ackSeq);
|
|
@@ -1932,6 +2046,7 @@ export class V2E2EECoordinator {
|
|
|
1932
2046
|
pendingAckSeq = 0;
|
|
1933
2047
|
}
|
|
1934
2048
|
}
|
|
2049
|
+
client._delivery.onPullWorkSettled?.();
|
|
1935
2050
|
return decrypted;
|
|
1936
2051
|
}
|
|
1937
2052
|
async confirmForwardGroupAck(groupId, upToSeq, groupAid) {
|
|
@@ -2486,7 +2601,7 @@ export class V2E2EECoordinator {
|
|
|
2486
2601
|
async decryptV2PushMessage(data) {
|
|
2487
2602
|
if (!isJsonObject(data))
|
|
2488
2603
|
return null;
|
|
2489
|
-
return await this.client._decryptV2Message(data);
|
|
2604
|
+
return await this.client._decryptV2Message(data, false, false, false, false, undefined, false, 'inline_push');
|
|
2490
2605
|
}
|
|
2491
2606
|
async buildV2P2PEnvelope(opts) {
|
|
2492
2607
|
const client = this.client;
|