@agentunion/fastaun 0.5.10 → 0.5.12
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 +62 -0
- package/_packed_docs/CHANGELOG.md +62 -0
- package/_packed_docs/INDEX.md +3 -3
- package/_packed_docs/KITE_DOCS_GUIDE.md +1 -1
- package/_packed_docs/protocol/10-Group-/345/255/220/345/215/217/350/256/256.md +21 -3
- package/_packed_docs/sdk/06-API/346/211/213/345/206/214.md +59 -0
- package/_packed_docs/sdk/09-group-rpc-manual.md +29 -2
- package/_packed_docs/sdk/AUN_DOCS_GUIDE.md +3 -2
- package/_packed_docs/sdk/INDEX.md +2 -1
- package/dist/client/delivery.d.ts +20 -7
- package/dist/client/delivery.js +248 -251
- package/dist/client/delivery.js.map +1 -1
- package/dist/client/group-state.js +1 -0
- package/dist/client/group-state.js.map +1 -1
- package/dist/client/rpc-pipeline.js +36 -12
- package/dist/client/rpc-pipeline.js.map +1 -1
- package/dist/client/v2-e2ee.d.ts +2 -1
- package/dist/client/v2-e2ee.js +229 -97
- package/dist/client/v2-e2ee.js.map +1 -1
- package/dist/client.d.ts +18 -0
- package/dist/client.js +332 -19
- package/dist/client.js.map +1 -1
- package/dist/facades.d.ts +6 -0
- package/dist/facades.js +66 -0
- package/dist/facades.js.map +1 -1
- package/dist/seq-tracker.d.ts +2 -2
- package/dist/seq-tracker.js +11 -17
- package/dist/seq-tracker.js.map +1 -1
- package/dist/tools/cross-sdk-agent.js +50 -20
- package/dist/tools/cross-sdk-agent.js.map +1 -1
- package/dist/transport.d.ts +4 -0
- package/dist/transport.js +141 -44
- 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
|
@@ -60,11 +60,16 @@ function deduplicateForwardPageMessages(value, afterSeq) {
|
|
|
60
60
|
}
|
|
61
61
|
return [...bySeq.entries()].sort(([a], [b]) => a - b).map(([, row]) => row);
|
|
62
62
|
}
|
|
63
|
-
function
|
|
63
|
+
function contiguousPullSeq(afterSeq, seqs, proof) {
|
|
64
|
+
const pulledMax = seqs.length > 0 ? Math.max(...seqs) : 0;
|
|
65
|
+
const serverProof = safeNonNegativeSeq(proof);
|
|
66
|
+
return Math.max(afterSeq, pulledMax, serverProof ?? 0);
|
|
67
|
+
}
|
|
68
|
+
function shouldContinueForwardPage({ rawCount, nextAfterSeq, nextAfter, limit, hasMoreField, hasMore, serverHead, observedUpper, pendingAckSeq, }) {
|
|
64
69
|
// 无新 seq 或游标未前进时必须停止,避免错误元数据造成循环。
|
|
65
70
|
if (rawCount <= 0 || nextAfter <= nextAfterSeq)
|
|
66
71
|
return false;
|
|
67
|
-
if (hasMore || serverHead > nextAfter || pendingAckSeq > 0)
|
|
72
|
+
if (hasMore || serverHead > nextAfter || observedUpper > nextAfter || pendingAckSeq > 0)
|
|
68
73
|
return true;
|
|
69
74
|
// 仅旧服务缺失 has_more 时,以满页保留兼容续拉。
|
|
70
75
|
return !hasMoreField && limit > 0 && rawCount >= limit;
|
|
@@ -734,7 +739,7 @@ export class V2E2EECoordinator {
|
|
|
734
739
|
let plaintext = null;
|
|
735
740
|
const retryStatus = {};
|
|
736
741
|
try {
|
|
737
|
-
plaintext = await client._decryptV2Message(entry.msg, false, true, true, true, retryStatus);
|
|
742
|
+
plaintext = await client._decryptV2Message(entry.msg, false, true, true, true, retryStatus, false, 'pending_retry');
|
|
738
743
|
}
|
|
739
744
|
catch (exc) {
|
|
740
745
|
client._clientLog.warn(`V2 sender IK pending retry raised: key=${key} err=${formatE2EEError(exc)}`);
|
|
@@ -767,12 +772,14 @@ export class V2E2EECoordinator {
|
|
|
767
772
|
pending.delete(key);
|
|
768
773
|
const seq = Number(entry.msg.seq ?? 0);
|
|
769
774
|
if (entry.groupId) {
|
|
775
|
+
if (client._delivery.isSelfSentGroupMessage?.(entry.msg))
|
|
776
|
+
continue;
|
|
770
777
|
plaintext = normalizeGroupMentionMode(plaintext, entry.msg, entry.msg.envelope_json);
|
|
771
778
|
plaintext.group_id = entry.groupId;
|
|
772
|
-
await client._publishPulledMessage('group.message_created', `group:${entry.groupId}`, seq, plaintext);
|
|
779
|
+
await client._publishPulledMessage('group.message_created', `group:${entry.groupId}`, seq, plaintext, false, 'pending_retry');
|
|
773
780
|
}
|
|
774
781
|
else {
|
|
775
|
-
await client._publishPulledMessage('message.received', `p2p:${client._aid ?? ''}`, seq, plaintext);
|
|
782
|
+
await client._publishPulledMessage('message.received', `p2p:${client._aid ?? ''}`, seq, plaintext, false, 'pending_retry');
|
|
776
783
|
}
|
|
777
784
|
client._clientLog.debug(`V2 sender IK pending retry delivered: key=${key}`);
|
|
778
785
|
}
|
|
@@ -1018,10 +1025,10 @@ export class V2E2EECoordinator {
|
|
|
1018
1025
|
if (String(msg.version ?? '') === 'v1') {
|
|
1019
1026
|
const legacy = isJsonObject(msg.legacy_v1)
|
|
1020
1027
|
? msg.legacy_v1 : {};
|
|
1021
|
-
const payload = legacy.payload;
|
|
1028
|
+
const payload = legacy.payload !== undefined ? legacy.payload : msg.payload;
|
|
1022
1029
|
const payloadType = isJsonObject(payload)
|
|
1023
1030
|
? String(payload.type ?? '').trim() : '';
|
|
1024
|
-
if (payload !== undefined && payload !== null && !['e2ee.encrypted', 'e2ee.group_encrypted'].includes(payloadType)) {
|
|
1031
|
+
if (payload !== undefined && payload !== null && !['e2ee.encrypted', 'e2ee.group_encrypted', 'e2ee.p2p_encrypted'].includes(payloadType)) {
|
|
1025
1032
|
plaintext = {
|
|
1026
1033
|
message_id: String(msg.message_id ?? ''),
|
|
1027
1034
|
from: String(msg.from_aid ?? ''),
|
|
@@ -1034,9 +1041,14 @@ export class V2E2EECoordinator {
|
|
|
1034
1041
|
};
|
|
1035
1042
|
attachGatewayProximity(plaintext, msg);
|
|
1036
1043
|
}
|
|
1044
|
+
else if (isJsonObject(payload)
|
|
1045
|
+
&& ['e2ee.p2p_encrypted', 'e2ee.encrypted'].includes(payloadType)) {
|
|
1046
|
+
msg = { ...msg, envelope_json: JSON.stringify(payload) };
|
|
1047
|
+
plaintext = await client._decryptV2Message(msg, false, !history, true, true, undefined, false, source);
|
|
1048
|
+
}
|
|
1037
1049
|
}
|
|
1038
1050
|
else {
|
|
1039
|
-
plaintext = await client._decryptV2Message(msg, false, !history);
|
|
1051
|
+
plaintext = await client._decryptV2Message(msg, false, !history, true, true, undefined, false, source);
|
|
1040
1052
|
}
|
|
1041
1053
|
if (!plaintext) {
|
|
1042
1054
|
if (history)
|
|
@@ -1046,12 +1058,7 @@ export class V2E2EECoordinator {
|
|
|
1046
1058
|
}
|
|
1047
1059
|
if (publish) {
|
|
1048
1060
|
const event = client._delivery.p2pAppEventForMessage(plaintext);
|
|
1049
|
-
|
|
1050
|
-
await client._delivery.publishOrderedMessage(event.event, client._aid ? `p2p:${client._aid}` : '', seq, event.payload, source);
|
|
1051
|
-
}
|
|
1052
|
-
else {
|
|
1053
|
-
await client._publishAppEvent(event.event, event.payload, source);
|
|
1054
|
-
}
|
|
1061
|
+
await client._publishAppEvent(event.event, event.payload, source);
|
|
1055
1062
|
}
|
|
1056
1063
|
return plaintext;
|
|
1057
1064
|
}
|
|
@@ -1061,35 +1068,52 @@ export class V2E2EECoordinator {
|
|
|
1061
1068
|
let plaintext = null;
|
|
1062
1069
|
if (String(msg.version ?? '') === 'v1') {
|
|
1063
1070
|
const payload = msg.payload;
|
|
1071
|
+
const recall = typeof client._delivery?.recallEventFromGroupMessage === 'function'
|
|
1072
|
+
? client._delivery.recallEventFromGroupMessage(msg)
|
|
1073
|
+
: null;
|
|
1074
|
+
if (recall) {
|
|
1075
|
+
const recallPayload = {
|
|
1076
|
+
...recall,
|
|
1077
|
+
group_id: groupId,
|
|
1078
|
+
group_aid: groupAid,
|
|
1079
|
+
seq,
|
|
1080
|
+
};
|
|
1081
|
+
if (publish) {
|
|
1082
|
+
await client._publishAppEvent('group.message_recalled', recallPayload, source);
|
|
1083
|
+
}
|
|
1084
|
+
return recallPayload;
|
|
1085
|
+
}
|
|
1064
1086
|
if (payload === undefined || payload === null) {
|
|
1065
1087
|
if (history)
|
|
1066
1088
|
return this.historyDecryptFailure(msg, 'legacy payload is missing');
|
|
1067
1089
|
client._clientLog.warn(`Group Tail 缺少 payload 的 V1 行已跳过,连续性证明仍保留: group=${groupId}, seq=${seq}`);
|
|
1068
1090
|
return null;
|
|
1069
1091
|
}
|
|
1092
|
+
const payloadType = isJsonObject(payload)
|
|
1093
|
+
? String(payload.type ?? '').trim() : '';
|
|
1070
1094
|
if (isJsonObject(payload)
|
|
1071
|
-
&& ['e2ee.
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1095
|
+
&& ['e2ee.group_encrypted', 'e2ee.p2p_encrypted', 'e2ee.encrypted'].includes(payloadType)) {
|
|
1096
|
+
msg = { ...msg, envelope_json: JSON.stringify(payload) };
|
|
1097
|
+
plaintext = await client._decryptV2Message(msg, false, !history, true, true, undefined, false, source);
|
|
1098
|
+
}
|
|
1099
|
+
else {
|
|
1100
|
+
plaintext = {
|
|
1101
|
+
message_id: String(msg.message_id ?? ''),
|
|
1102
|
+
from: String(msg.from_aid ?? ''),
|
|
1103
|
+
group_id: groupId,
|
|
1104
|
+
group_aid: groupAid,
|
|
1105
|
+
seq,
|
|
1106
|
+
type: String(msg.type ?? ''),
|
|
1107
|
+
timestamp: msg.t_server,
|
|
1108
|
+
payload: payload,
|
|
1109
|
+
encrypted: false,
|
|
1110
|
+
};
|
|
1111
|
+
plaintext = normalizeGroupMentionMode(plaintext, msg, msg.envelope_json);
|
|
1112
|
+
attachGatewayProximity(plaintext, msg);
|
|
1076
1113
|
}
|
|
1077
|
-
plaintext = {
|
|
1078
|
-
message_id: String(msg.message_id ?? ''),
|
|
1079
|
-
from: String(msg.from_aid ?? ''),
|
|
1080
|
-
group_id: groupId,
|
|
1081
|
-
group_aid: groupAid,
|
|
1082
|
-
seq,
|
|
1083
|
-
type: String(msg.type ?? ''),
|
|
1084
|
-
timestamp: msg.t_server,
|
|
1085
|
-
payload: payload,
|
|
1086
|
-
encrypted: false,
|
|
1087
|
-
};
|
|
1088
|
-
plaintext = normalizeGroupMentionMode(plaintext, msg, msg.envelope_json);
|
|
1089
|
-
attachGatewayProximity(plaintext, msg);
|
|
1090
1114
|
}
|
|
1091
1115
|
else {
|
|
1092
|
-
plaintext = await client._decryptV2Message(msg, false, !history);
|
|
1116
|
+
plaintext = await client._decryptV2Message(msg, false, !history, true, true, undefined, false, source);
|
|
1093
1117
|
if (plaintext) {
|
|
1094
1118
|
plaintext.group_id = groupId;
|
|
1095
1119
|
plaintext.group_aid = groupAid;
|
|
@@ -1102,24 +1126,14 @@ export class V2E2EECoordinator {
|
|
|
1102
1126
|
client._clientLog.warn(`Group Tail 单条消息解密失败,连续性证明仍保留: group=${groupId}, seq=${seq}`);
|
|
1103
1127
|
return null;
|
|
1104
1128
|
}
|
|
1129
|
+
if (publish && !history && client._delivery.isSelfSentGroupMessage?.(msg)) {
|
|
1130
|
+
return plaintext;
|
|
1131
|
+
}
|
|
1105
1132
|
if (publish) {
|
|
1106
|
-
|
|
1107
|
-
await client._delivery.publishOrderedMessage('group.message_created', `group:${groupId}`, seq, plaintext, source);
|
|
1108
|
-
}
|
|
1109
|
-
else {
|
|
1110
|
-
await client._publishAppEvent('group.message_created', plaintext, source);
|
|
1111
|
-
}
|
|
1133
|
+
await client._publishAppEvent('group.message_created', plaintext, source);
|
|
1112
1134
|
}
|
|
1113
1135
|
return plaintext;
|
|
1114
1136
|
}
|
|
1115
|
-
async applyTailFloor(ns, floor) {
|
|
1116
|
-
const client = this.client;
|
|
1117
|
-
if (!ns || floor <= 0 || client._seqTracker.getContiguousSeq(ns) >= floor)
|
|
1118
|
-
return;
|
|
1119
|
-
client._seqTracker.forceContiguousSeq(ns, floor);
|
|
1120
|
-
client._persistSeq(ns);
|
|
1121
|
-
await client._saveSeqTrackerState?.();
|
|
1122
|
-
}
|
|
1123
1137
|
async pullV2TailInternal(params, deferPublish = false) {
|
|
1124
1138
|
const client = this.client;
|
|
1125
1139
|
if (params.window_mode !== 'tail')
|
|
@@ -1129,10 +1143,9 @@ export class V2E2EECoordinator {
|
|
|
1129
1143
|
const afterSeq = strictWindowSeq(params.after_seq ?? 0, 'after_seq');
|
|
1130
1144
|
const limit = strictWindowLimit(params.limit ?? V2_PULL_DEFAULT_PAGE_LIMIT);
|
|
1131
1145
|
const ns = client._aid ? `p2p:${client._aid}` : '';
|
|
1146
|
+
if (ns)
|
|
1147
|
+
client._delivery.syncStarted(ns);
|
|
1132
1148
|
const result = await client._callRawV2Rpc('message.v2.pull', { window_mode: 'tail', after_seq: afterSeq, limit, _rpc_foreground: true });
|
|
1133
|
-
const floor = Number(result.retention_floor_seq ?? 0);
|
|
1134
|
-
const previous = ns ? client._seqTracker.getSyncState(ns) : null;
|
|
1135
|
-
await this.applyTailFloor(ns, Number.isSafeInteger(floor) ? floor : 0);
|
|
1136
1149
|
const page = validateTailPage(result, afterSeq, limit);
|
|
1137
1150
|
if (ns) {
|
|
1138
1151
|
client._seqTracker.commitTailWindow(ns, {
|
|
@@ -1151,8 +1164,15 @@ export class V2E2EECoordinator {
|
|
|
1151
1164
|
decoded.push(plaintext);
|
|
1152
1165
|
}
|
|
1153
1166
|
const ack = ns ? client._seqTracker.getContiguousSeq(ns) : 0;
|
|
1154
|
-
if (
|
|
1155
|
-
|
|
1167
|
+
if (ns)
|
|
1168
|
+
client._delivery.syncProgress(ns, {
|
|
1169
|
+
rawCount: page.messages.length,
|
|
1170
|
+
pulledCount: decoded.length,
|
|
1171
|
+
remaining: result.remaining,
|
|
1172
|
+
hasMore: typeof result.has_more === 'boolean' ? result.has_more : undefined,
|
|
1173
|
+
currentSeq: ack,
|
|
1174
|
+
targetSeq: page.head,
|
|
1175
|
+
});
|
|
1156
1176
|
return { ...result, messages: decoded, raw_count: page.messages.length };
|
|
1157
1177
|
}
|
|
1158
1178
|
async historyV2Internal(params) {
|
|
@@ -1169,21 +1189,23 @@ export class V2E2EECoordinator {
|
|
|
1169
1189
|
}
|
|
1170
1190
|
return { ...result, messages: decoded };
|
|
1171
1191
|
}
|
|
1172
|
-
async
|
|
1192
|
+
async pullV2Impl(afterSeq = 0, limit = 50, opts) {
|
|
1173
1193
|
const client = this.client;
|
|
1174
1194
|
await client._ensureV2SessionReady('message.pull');
|
|
1175
1195
|
const ns = client._aid ? `p2p:${client._aid}` : '';
|
|
1196
|
+
if (ns)
|
|
1197
|
+
client._delivery.syncStarted(ns);
|
|
1176
1198
|
if (opts?.windowMode === 'tail') {
|
|
1177
1199
|
if (!opts.gateLocked) {
|
|
1178
1200
|
const key = `${ns}|tail|after=${afterSeq}|limit=${limit}`;
|
|
1179
|
-
return (await client._runPullSerialized(key, () => this.
|
|
1201
|
+
return (await client._runPullSerialized(key, () => this.pullV2Impl(afterSeq, limit, { ...opts, gateLocked: true }), false));
|
|
1180
1202
|
}
|
|
1181
1203
|
const result = await this.pullV2TailInternal({ window_mode: 'tail', after_seq: afterSeq, limit });
|
|
1182
1204
|
return (Array.isArray(result.messages) ? result.messages : []);
|
|
1183
1205
|
}
|
|
1184
1206
|
if (ns && !opts?.gateLocked) {
|
|
1185
1207
|
const key = `${ns}|forward|after=${afterSeq}|force=${String(Boolean(opts?.force))}|limit=${limit}`;
|
|
1186
|
-
return await client._runPullSerialized(key, async () => this.
|
|
1208
|
+
return await client._runPullSerialized(key, async () => this.pullV2Impl(afterSeq, limit, {
|
|
1187
1209
|
...(opts ?? {}),
|
|
1188
1210
|
gateLocked: true,
|
|
1189
1211
|
scheduleFollowup: true,
|
|
@@ -1251,8 +1273,10 @@ export class V2E2EECoordinator {
|
|
|
1251
1273
|
if (seqs.length > 0) {
|
|
1252
1274
|
pageMaxSeq = Math.max(...seqs);
|
|
1253
1275
|
}
|
|
1276
|
+
const pageContiguousSeq = contiguousPullSeq(pageContigBefore, seqs, result.contiguous_seq);
|
|
1254
1277
|
const deferredKeyFetches = new Map();
|
|
1255
1278
|
let blockedSeq = 0;
|
|
1279
|
+
const pageDecryptedBefore = decrypted.length;
|
|
1256
1280
|
for (const msg of messages) {
|
|
1257
1281
|
const seq = Number(msg.seq ?? 0);
|
|
1258
1282
|
if (!Number.isFinite(seq) || seq <= 0)
|
|
@@ -1260,11 +1284,12 @@ export class V2E2EECoordinator {
|
|
|
1260
1284
|
const version = String(msg.version ?? 'v2');
|
|
1261
1285
|
if (version === 'v1') {
|
|
1262
1286
|
const legacy = isJsonObject(msg.legacy_v1) ? msg.legacy_v1 : {};
|
|
1263
|
-
const legacyPayload = legacy.payload;
|
|
1287
|
+
const legacyPayload = legacy.payload !== undefined ? legacy.payload : msg.payload;
|
|
1264
1288
|
const payloadType = isJsonObject(legacyPayload)
|
|
1265
1289
|
? String(legacyPayload.type ?? '').trim()
|
|
1266
1290
|
: '';
|
|
1267
|
-
if (legacyPayload !== undefined && legacyPayload !== null
|
|
1291
|
+
if (legacyPayload !== undefined && legacyPayload !== null
|
|
1292
|
+
&& !['e2ee.encrypted', 'e2ee.group_encrypted', 'e2ee.p2p_encrypted'].includes(payloadType)) {
|
|
1268
1293
|
const v1Msg = {
|
|
1269
1294
|
message_id: String(msg.message_id ?? ''),
|
|
1270
1295
|
from: String(msg.from_aid ?? ''),
|
|
@@ -1286,6 +1311,25 @@ export class V2E2EECoordinator {
|
|
|
1286
1311
|
decrypted.push(v1Msg);
|
|
1287
1312
|
client._clientLog.debug(`message.v2.pull plaintext V1 delivered: seq=${seq}, ns=${ns || '<none>'}`);
|
|
1288
1313
|
}
|
|
1314
|
+
else if (isJsonObject(legacyPayload)
|
|
1315
|
+
&& ['e2ee.p2p_encrypted', 'e2ee.encrypted'].includes(payloadType)) {
|
|
1316
|
+
const deferStatus = {};
|
|
1317
|
+
const plaintext = await client._decryptV2Message({ ...msg, envelope_json: JSON.stringify(legacyPayload) }, true, true, true, true, deferStatus, true, 'pull');
|
|
1318
|
+
if (deferStatus.deferred) {
|
|
1319
|
+
blockedSeq = blockedSeq > 0 ? Math.min(blockedSeq, seq) : seq;
|
|
1320
|
+
if (deferStatus.fromAid) {
|
|
1321
|
+
const key = `${deferStatus.fromAid}\u0000${deferStatus.senderDeviceId ?? ''}\u0000${deferStatus.groupId ?? ''}`;
|
|
1322
|
+
deferredKeyFetches.set(key, { fromAid: deferStatus.fromAid, senderDeviceId: deferStatus.senderDeviceId ?? '', groupId: deferStatus.groupId ?? '' });
|
|
1323
|
+
}
|
|
1324
|
+
}
|
|
1325
|
+
if (plaintext) {
|
|
1326
|
+
if (ns)
|
|
1327
|
+
await client._publishPulledMessage('message.received', ns, seq, plaintext, false);
|
|
1328
|
+
else
|
|
1329
|
+
await client._publishAppEvent('message.received', plaintext, 'pull');
|
|
1330
|
+
decrypted.push(plaintext);
|
|
1331
|
+
}
|
|
1332
|
+
}
|
|
1289
1333
|
else {
|
|
1290
1334
|
client._clientLog.debug(`message.v2.pull skipping V1 envelope seq=${seq} payload_type=${payloadType || '<none>'} (V1 E2EE removed)`);
|
|
1291
1335
|
}
|
|
@@ -1300,7 +1344,7 @@ export class V2E2EECoordinator {
|
|
|
1300
1344
|
client._v2Session.trackOldSPKMaxSeq(spkId, seq);
|
|
1301
1345
|
}
|
|
1302
1346
|
const deferStatus = {};
|
|
1303
|
-
const plaintext = await client._decryptV2Message(msg, true, true, true, true, deferStatus, true);
|
|
1347
|
+
const plaintext = await client._decryptV2Message(msg, true, true, true, true, deferStatus, true, 'pull');
|
|
1304
1348
|
if (deferStatus.deferred) {
|
|
1305
1349
|
blockedSeq = blockedSeq > 0 ? Math.min(blockedSeq, seq) : seq;
|
|
1306
1350
|
}
|
|
@@ -1330,7 +1374,7 @@ export class V2E2EECoordinator {
|
|
|
1330
1374
|
const serverAckSeq = parsedServerAckSeq ?? 0;
|
|
1331
1375
|
const retentionFloor = Math.max(0, Number(result.retention_floor_seq ?? 0));
|
|
1332
1376
|
if (ns) {
|
|
1333
|
-
const commitTarget = Math.max(pageContigBefore, Number.isFinite(retentionFloor) ? retentionFloor : 0, pageCount === 1 ? deferredServerCursor : 0, blockedSeq > 0 ? blockedSeq - 1 :
|
|
1377
|
+
const commitTarget = Math.max(pageContigBefore, Number.isFinite(retentionFloor) ? retentionFloor : 0, pageCount === 1 ? deferredServerCursor : 0, serverAckSeq, blockedSeq > 0 ? blockedSeq - 1 : pageContiguousSeq);
|
|
1334
1378
|
let ackSeq = pageContigBefore;
|
|
1335
1379
|
let contigAdvanced = false;
|
|
1336
1380
|
try {
|
|
@@ -1380,7 +1424,7 @@ export class V2E2EECoordinator {
|
|
|
1380
1424
|
|| (contigAdvanced && ackSeq > knownServerAckSeq));
|
|
1381
1425
|
if (ackNeeded) {
|
|
1382
1426
|
this.recordForwardAck(ns, ackSeq);
|
|
1383
|
-
const nextAfter = Math.max(
|
|
1427
|
+
const nextAfter = Math.max(pageContiguousSeq, nextAfterSeq);
|
|
1384
1428
|
const canContinuePage = blockedSeq <= 0 && messages.length > 0 && nextAfter > nextAfterSeq;
|
|
1385
1429
|
if (canContinuePage) {
|
|
1386
1430
|
pendingAckSeq = Math.max(pendingAckSeq, ackSeq);
|
|
@@ -1399,8 +1443,19 @@ export class V2E2EECoordinator {
|
|
|
1399
1443
|
this.scheduleSenderIKFetch(fetch.fromAid, fetch.senderDeviceId, fetch.groupId);
|
|
1400
1444
|
}
|
|
1401
1445
|
}
|
|
1402
|
-
|
|
1446
|
+
if (ns)
|
|
1447
|
+
client._delivery.syncProgress(ns, {
|
|
1448
|
+
rawCount: messages.length,
|
|
1449
|
+
pulledCount: decrypted.length - pageDecryptedBefore,
|
|
1450
|
+
remaining: result.remaining,
|
|
1451
|
+
hasMore: hasMoreField ? hasMore : undefined,
|
|
1452
|
+
currentSeq: client._seqTracker.getContiguousSeq(ns),
|
|
1453
|
+
targetSeq: serverHead,
|
|
1454
|
+
});
|
|
1455
|
+
const nextAfter = Math.max(pageContiguousSeq, nextAfterSeq);
|
|
1403
1456
|
const rawCount = messages.length;
|
|
1457
|
+
if (blockedSeq > 0)
|
|
1458
|
+
break;
|
|
1404
1459
|
const shouldContinue = shouldContinueForwardPage({
|
|
1405
1460
|
rawCount,
|
|
1406
1461
|
nextAfterSeq,
|
|
@@ -1409,6 +1464,7 @@ export class V2E2EECoordinator {
|
|
|
1409
1464
|
hasMoreField,
|
|
1410
1465
|
hasMore,
|
|
1411
1466
|
serverHead,
|
|
1467
|
+
observedUpper: Math.max(client._seqTracker.getMaxSeenSeq(ns), Number(client._pendingP2pPullUpper?.get?.(ns) ?? 0)),
|
|
1412
1468
|
pendingAckSeq,
|
|
1413
1469
|
});
|
|
1414
1470
|
if (!shouldContinue)
|
|
@@ -1434,6 +1490,19 @@ export class V2E2EECoordinator {
|
|
|
1434
1490
|
client._clientLog.debug(`message.v2.pull done: requested_after_seq=${afterSeq}, pages=${pageCount}, decrypted=${decrypted.length}, ns=${ns || '<none>'}`);
|
|
1435
1491
|
return decrypted;
|
|
1436
1492
|
}
|
|
1493
|
+
async pullV2(afterSeq = 0, limit = 50, opts) {
|
|
1494
|
+
const ns = this.client._aid ? `p2p:${this.client._aid}` : '';
|
|
1495
|
+
if (!ns)
|
|
1496
|
+
return await this.pullV2Impl(afterSeq, limit, opts);
|
|
1497
|
+
this.client._delivery.syncStarted(ns);
|
|
1498
|
+
try {
|
|
1499
|
+
return await this.pullV2Impl(afterSeq, limit, opts);
|
|
1500
|
+
}
|
|
1501
|
+
catch (error) {
|
|
1502
|
+
this.client._delivery.onPullAborted?.();
|
|
1503
|
+
throw error;
|
|
1504
|
+
}
|
|
1505
|
+
}
|
|
1437
1506
|
async confirmForwardP2PAck(upToSeq) {
|
|
1438
1507
|
const ns = this.client._aid ? `p2p:${this.client._aid}` : '';
|
|
1439
1508
|
try {
|
|
@@ -1536,22 +1605,8 @@ export class V2E2EECoordinator {
|
|
|
1536
1605
|
client._clientLog.debug(`group.v2.send ok: group=${gid}, use_cache=${useCache}, seq=${String((isJsonObject(result) ? result.seq : '') ?? '')}`);
|
|
1537
1606
|
return result;
|
|
1538
1607
|
};
|
|
1539
|
-
const markSentSeq = async (result) => {
|
|
1540
|
-
if (!isJsonObject(result))
|
|
1541
|
-
return;
|
|
1542
|
-
const obj = result;
|
|
1543
|
-
const seq = Number(obj.seq ?? 0);
|
|
1544
|
-
if (!Number.isFinite(seq) || seq <= 0)
|
|
1545
|
-
return;
|
|
1546
|
-
const ns = `group:${gid}`;
|
|
1547
|
-
client._seqTracker.onMessageSeq(ns, seq);
|
|
1548
|
-
client._markPublishedSeq(ns, seq);
|
|
1549
|
-
await client._saveSeqTrackerState();
|
|
1550
|
-
client._clientLog.debug(`group.v2.send marked own seq: group=${gid}, ns=${ns}, seq=${seq}`);
|
|
1551
|
-
};
|
|
1552
1608
|
try {
|
|
1553
1609
|
const result = await attempt(true);
|
|
1554
|
-
await markSentSeq(result);
|
|
1555
1610
|
return client._delivery.attachSendResultEnvelope('group.send', withExplicitGroupAid({
|
|
1556
1611
|
group_id: gid,
|
|
1557
1612
|
payload,
|
|
@@ -1567,7 +1622,6 @@ export class V2E2EECoordinator {
|
|
|
1567
1622
|
client._clientLog.debug(`V2 group speculative send rejected (code=${String(excCode)}), refreshing bootstrap`);
|
|
1568
1623
|
this.deleteBootstrapCacheEntry(`group:${gid}`);
|
|
1569
1624
|
const result = await attempt(false);
|
|
1570
|
-
await markSentSeq(result);
|
|
1571
1625
|
return client._delivery.attachSendResultEnvelope('group.send', withExplicitGroupAid({
|
|
1572
1626
|
group_id: gid,
|
|
1573
1627
|
payload,
|
|
@@ -1739,6 +1793,14 @@ export class V2E2EECoordinator {
|
|
|
1739
1793
|
const afterSeq = strictWindowSeq(params.after_seq ?? 0, 'after_seq');
|
|
1740
1794
|
const limit = strictWindowLimit(params.limit ?? V2_PULL_DEFAULT_PAGE_LIMIT);
|
|
1741
1795
|
const ns = `group:${groupId}`;
|
|
1796
|
+
const cursorParams = isJsonObject(params._group_cursor_params)
|
|
1797
|
+
? params._group_cursor_params : params;
|
|
1798
|
+
const requestDeviceId = String(cursorParams.device_id ?? '').trim();
|
|
1799
|
+
const requestSlotId = String(cursorParams.slot_id ?? '').trim();
|
|
1800
|
+
const ownsCursor = (!requestDeviceId || requestDeviceId === String(client._deviceId ?? ''))
|
|
1801
|
+
&& (!requestSlotId || requestSlotId === String(client._slotId ?? ''));
|
|
1802
|
+
if (ownsCursor)
|
|
1803
|
+
client._delivery.syncStarted(ns);
|
|
1742
1804
|
const result = await client._callRawV2Rpc('group.v2.pull', withExplicitGroupAid({
|
|
1743
1805
|
group_id: groupId,
|
|
1744
1806
|
window_mode: 'tail',
|
|
@@ -1749,9 +1811,6 @@ export class V2E2EECoordinator {
|
|
|
1749
1811
|
const resultAid = String(result.group_aid ?? result.groupAid ?? '').trim();
|
|
1750
1812
|
if (resultAid)
|
|
1751
1813
|
groupAid = resultAid;
|
|
1752
|
-
const floor = Number(result.retention_floor_message_seq ?? result.retention_floor_seq ?? 0);
|
|
1753
|
-
const previous = client._seqTracker.getSyncState(ns);
|
|
1754
|
-
await this.applyTailFloor(ns, Number.isSafeInteger(floor) ? floor : 0);
|
|
1755
1814
|
const page = validateTailPage(result, afterSeq, limit);
|
|
1756
1815
|
client._seqTracker.commitTailWindow(ns, {
|
|
1757
1816
|
windowStartSeq: page.windowStart,
|
|
@@ -1769,8 +1828,15 @@ export class V2E2EECoordinator {
|
|
|
1769
1828
|
decoded.push(plaintext);
|
|
1770
1829
|
}
|
|
1771
1830
|
const ack = client._seqTracker.getContiguousSeq(ns);
|
|
1772
|
-
if (
|
|
1773
|
-
|
|
1831
|
+
if (ownsCursor)
|
|
1832
|
+
client._delivery.syncProgress(ns, {
|
|
1833
|
+
rawCount: page.messages.length,
|
|
1834
|
+
pulledCount: decoded.length,
|
|
1835
|
+
remaining: result.remaining,
|
|
1836
|
+
hasMore: typeof result.has_more === 'boolean' ? result.has_more : undefined,
|
|
1837
|
+
currentSeq: ack,
|
|
1838
|
+
targetSeq: page.head,
|
|
1839
|
+
});
|
|
1774
1840
|
return { ...result, messages: decoded, raw_count: page.messages.length };
|
|
1775
1841
|
}
|
|
1776
1842
|
async historyGroupV2Internal(params) {
|
|
@@ -1806,7 +1872,7 @@ export class V2E2EECoordinator {
|
|
|
1806
1872
|
force: params.force === true,
|
|
1807
1873
|
});
|
|
1808
1874
|
}
|
|
1809
|
-
async
|
|
1875
|
+
async pullGroupV2Impl(groupId, afterSeq = 0, limit = 50, opts) {
|
|
1810
1876
|
const client = this.client;
|
|
1811
1877
|
await client._ensureV2SessionReady('group.pull');
|
|
1812
1878
|
const gid = String(groupId ?? '').trim();
|
|
@@ -1814,15 +1880,18 @@ export class V2E2EECoordinator {
|
|
|
1814
1880
|
throw new ValidationError('group.pull requires group_id');
|
|
1815
1881
|
let groupAid = String(opts?.groupAid ?? '').trim();
|
|
1816
1882
|
const ns = `group:${gid}`;
|
|
1883
|
+
if (opts?.ownsCursor !== false)
|
|
1884
|
+
client._delivery.syncStarted(ns);
|
|
1817
1885
|
if (opts?.windowMode === 'tail') {
|
|
1818
1886
|
if (!opts.gateLocked) {
|
|
1819
1887
|
const key = `${ns}|tail|after=${afterSeq}|limit=${limit}`;
|
|
1820
|
-
return (await client._runPullSerialized(key, () => this.
|
|
1888
|
+
return (await client._runPullSerialized(key, () => this.pullGroupV2Impl(gid, afterSeq, limit, {
|
|
1821
1889
|
...opts,
|
|
1822
1890
|
gateLocked: true,
|
|
1823
1891
|
}), false));
|
|
1824
1892
|
}
|
|
1825
1893
|
const result = await this.pullGroupV2TailInternal({
|
|
1894
|
+
...(opts?.cursorParams ?? {}),
|
|
1826
1895
|
group_id: String(opts.wireGroupId ?? gid),
|
|
1827
1896
|
group_aid: groupAid || undefined,
|
|
1828
1897
|
window_mode: 'tail',
|
|
@@ -1833,7 +1902,7 @@ export class V2E2EECoordinator {
|
|
|
1833
1902
|
}
|
|
1834
1903
|
if (!opts?.gateLocked) {
|
|
1835
1904
|
const key = `${ns}|forward|after=${afterSeq}|force=${opts?.force === true}|limit=${limit}`;
|
|
1836
|
-
return await client._runPullSerialized(key, async () => this.
|
|
1905
|
+
return await client._runPullSerialized(key, async () => this.pullGroupV2Impl(gid, afterSeq, limit, {
|
|
1837
1906
|
...(opts ?? {}),
|
|
1838
1907
|
gateLocked: true,
|
|
1839
1908
|
scheduleFollowup: true,
|
|
@@ -1914,30 +1983,34 @@ export class V2E2EECoordinator {
|
|
|
1914
1983
|
if (seqs.length > 0) {
|
|
1915
1984
|
pageMaxSeq = Math.max(...seqs);
|
|
1916
1985
|
}
|
|
1986
|
+
const pageContiguousSeq = contiguousPullSeq(pageContigBefore, seqs, result.contiguous_seq);
|
|
1917
1987
|
const deferredKeyFetches = new Map();
|
|
1918
1988
|
let blockedSeq = 0;
|
|
1989
|
+
const pageDecryptedBefore = decrypted.length;
|
|
1919
1990
|
for (const msg of messages) {
|
|
1920
1991
|
const seq = Number(msg.seq ?? 0);
|
|
1921
1992
|
if (!Number.isFinite(seq) || seq <= 0)
|
|
1922
1993
|
continue;
|
|
1923
1994
|
const version = String(msg.version ?? 'v2');
|
|
1924
1995
|
if (version === 'v1') {
|
|
1925
|
-
const
|
|
1996
|
+
const legacy = isJsonObject(msg.legacy_v1) ? msg.legacy_v1 : {};
|
|
1997
|
+
const payload = msg.payload !== undefined ? msg.payload : legacy.payload;
|
|
1926
1998
|
const payloadObj = isJsonObject(payload) ? payload : null;
|
|
1999
|
+
const payloadType = payloadObj ? String(payloadObj.type ?? '').trim() : '';
|
|
1927
2000
|
// 群撤回 tombstone(占位 / 通知):归一化为 group.message_recalled 事件,仍占 seq。
|
|
1928
|
-
if (client._delivery
|
|
2001
|
+
if (typeof client._delivery?.recallEventFromGroupMessage === 'function'
|
|
2002
|
+
&& client._delivery.recallEventFromGroupMessage(msg)) {
|
|
1929
2003
|
await client._delivery.publishGroupRecallTombstone(gid, seq, {
|
|
1930
2004
|
...msg,
|
|
1931
2005
|
group_id: gid,
|
|
1932
2006
|
group_aid: eventGroupAid,
|
|
1933
|
-
});
|
|
2007
|
+
}, 'pull');
|
|
1934
2008
|
client._markPublishedSeq(ns, seq);
|
|
1935
2009
|
client._clientLog.debug(`group.v2.pull recall tombstone delivered: group=${gid}, seq=${seq}`);
|
|
1936
2010
|
continue;
|
|
1937
2011
|
}
|
|
1938
2012
|
if (payloadObj) {
|
|
1939
|
-
|
|
1940
|
-
if (payloadType !== 'e2ee.encrypted' && payloadType !== 'e2ee.group_encrypted') {
|
|
2013
|
+
if (!['e2ee.encrypted', 'e2ee.group_encrypted', 'e2ee.p2p_encrypted'].includes(payloadType)) {
|
|
1941
2014
|
let v1Msg = {
|
|
1942
2015
|
message_id: String(msg.message_id ?? ''),
|
|
1943
2016
|
from: String(msg.from_aid ?? ''),
|
|
@@ -1951,7 +2024,12 @@ export class V2E2EECoordinator {
|
|
|
1951
2024
|
};
|
|
1952
2025
|
v1Msg = normalizeGroupMentionMode(v1Msg, msg, msg.envelope_json);
|
|
1953
2026
|
attachGatewayProximity(v1Msg, msg);
|
|
1954
|
-
|
|
2027
|
+
if (!client._delivery.isSelfSentGroupMessage?.(msg)) {
|
|
2028
|
+
await client._publishPulledMessage('group.message_created', ns, seq, v1Msg, false);
|
|
2029
|
+
}
|
|
2030
|
+
else {
|
|
2031
|
+
client._markPublishedSeq(ns, seq);
|
|
2032
|
+
}
|
|
1955
2033
|
decrypted.push(v1Msg);
|
|
1956
2034
|
client._clientLog.debug(`group.v2.pull plaintext V1 delivered: group=${gid}, seq=${seq}`);
|
|
1957
2035
|
continue;
|
|
@@ -1976,7 +2054,31 @@ export class V2E2EECoordinator {
|
|
|
1976
2054
|
client._clientLog.debug(`group.v2.pull plaintext V1 delivered: group=${gid}, seq=${seq}`);
|
|
1977
2055
|
continue;
|
|
1978
2056
|
}
|
|
1979
|
-
|
|
2057
|
+
if (payloadObj && ['e2ee.group_encrypted', 'e2ee.p2p_encrypted', 'e2ee.encrypted'].includes(payloadType)) {
|
|
2058
|
+
const deferStatus = {};
|
|
2059
|
+
const plaintext = await client._decryptV2Message({ ...msg, envelope_json: JSON.stringify(payloadObj) }, true, true, true, true, deferStatus, true, 'pull');
|
|
2060
|
+
if (deferStatus.deferred) {
|
|
2061
|
+
blockedSeq = blockedSeq > 0 ? Math.min(blockedSeq, seq) : seq;
|
|
2062
|
+
if (deferStatus.fromAid) {
|
|
2063
|
+
const key = `${deferStatus.fromAid}\u0000${deferStatus.senderDeviceId ?? ''}\u0000${deferStatus.groupId ?? ''}`;
|
|
2064
|
+
deferredKeyFetches.set(key, { fromAid: deferStatus.fromAid, senderDeviceId: deferStatus.senderDeviceId ?? '', groupId: deferStatus.groupId ?? '' });
|
|
2065
|
+
}
|
|
2066
|
+
}
|
|
2067
|
+
if (plaintext) {
|
|
2068
|
+
plaintext.group_id = gid;
|
|
2069
|
+
plaintext.group_aid = eventGroupAid;
|
|
2070
|
+
if (!client._delivery.isSelfSentGroupMessage?.(msg)) {
|
|
2071
|
+
await client._publishPulledMessage('group.message_created', ns, seq, plaintext, false);
|
|
2072
|
+
}
|
|
2073
|
+
else {
|
|
2074
|
+
client._markPublishedSeq(ns, seq);
|
|
2075
|
+
}
|
|
2076
|
+
decrypted.push(plaintext);
|
|
2077
|
+
}
|
|
2078
|
+
}
|
|
2079
|
+
else {
|
|
2080
|
+
client._clientLog.debug(`group.v2.pull skipping V1 envelope group=${gid} seq=${seq} payload_type=${payloadObj ? String(payloadObj.type ?? '') : '<none>'} (V1 E2EE removed)`);
|
|
2081
|
+
}
|
|
1980
2082
|
continue;
|
|
1981
2083
|
}
|
|
1982
2084
|
if (version !== 'v2') {
|
|
@@ -1984,7 +2086,7 @@ export class V2E2EECoordinator {
|
|
|
1984
2086
|
continue;
|
|
1985
2087
|
}
|
|
1986
2088
|
const deferStatus = {};
|
|
1987
|
-
let plaintext = await client._decryptV2Message(msg, true, true, true, true, deferStatus, true);
|
|
2089
|
+
let plaintext = await client._decryptV2Message(msg, true, true, true, true, deferStatus, true, 'pull');
|
|
1988
2090
|
if (deferStatus.deferred) {
|
|
1989
2091
|
blockedSeq = blockedSeq > 0 ? Math.min(blockedSeq, seq) : seq;
|
|
1990
2092
|
}
|
|
@@ -2003,7 +2105,12 @@ export class V2E2EECoordinator {
|
|
|
2003
2105
|
plaintext = normalizeGroupMentionMode(plaintext, msg, msg.envelope_json);
|
|
2004
2106
|
plaintext.group_id = gid;
|
|
2005
2107
|
plaintext.group_aid = eventGroupAid;
|
|
2006
|
-
|
|
2108
|
+
if (!client._delivery.isSelfSentGroupMessage?.(msg)) {
|
|
2109
|
+
await client._publishPulledMessage('group.message_created', ns, seq, plaintext, false);
|
|
2110
|
+
}
|
|
2111
|
+
else {
|
|
2112
|
+
client._markPublishedSeq(ns, seq);
|
|
2113
|
+
}
|
|
2007
2114
|
decrypted.push(plaintext);
|
|
2008
2115
|
client._logMessageDebug('decrypt-ok', 'group.v2.pull', 'group.message_created', plaintext);
|
|
2009
2116
|
}
|
|
@@ -2013,7 +2120,7 @@ export class V2E2EECoordinator {
|
|
|
2013
2120
|
const retentionFloor = Math.max(client._pullRetentionFloor(result, 'retention_floor_message_seq', 'retention_floor_message_seq'));
|
|
2014
2121
|
const visibilityFloor = Math.max(0, Math.max(0, Number(result.earliest_available_message_seq ?? 1) - 1), Number(cursor?.join_seq ?? 0));
|
|
2015
2122
|
const effectiveFloor = Math.max(retentionFloor, visibilityFloor);
|
|
2016
|
-
const commitTarget = Math.max(pageContigBefore, effectiveFloor, ownsCursor && pageCount === 1 ? deferredServerCursor : 0, blockedSeq > 0 ? blockedSeq - 1 :
|
|
2123
|
+
const commitTarget = Math.max(pageContigBefore, effectiveFloor, ownsCursor && pageCount === 1 ? deferredServerCursor : 0, ownsCursor ? cursorCurrentSeq : 0, blockedSeq > 0 ? blockedSeq - 1 : pageContiguousSeq);
|
|
2017
2124
|
let ackSeq = pageContigBefore;
|
|
2018
2125
|
let contigAdvanced = false;
|
|
2019
2126
|
if (ownsCursor) {
|
|
@@ -2066,7 +2173,7 @@ export class V2E2EECoordinator {
|
|
|
2066
2173
|
|| (contigAdvanced && ackSeq > knownServerCursorSeq));
|
|
2067
2174
|
if (ackNeeded) {
|
|
2068
2175
|
this.recordForwardAck(ns, ackSeq);
|
|
2069
|
-
const nextAfter = Math.max(
|
|
2176
|
+
const nextAfter = Math.max(pageContiguousSeq, nextAfterSeq);
|
|
2070
2177
|
const canContinuePage = blockedSeq <= 0 && messages.length > 0 && nextAfter > nextAfterSeq && ownsCursor;
|
|
2071
2178
|
if (canContinuePage) {
|
|
2072
2179
|
pendingAckSeq = Math.max(pendingAckSeq, ackSeq);
|
|
@@ -2079,10 +2186,20 @@ export class V2E2EECoordinator {
|
|
|
2079
2186
|
lastAutoAckSeq = Math.max(lastAutoAckSeq, ackSeq);
|
|
2080
2187
|
}
|
|
2081
2188
|
}
|
|
2082
|
-
|
|
2189
|
+
client._delivery.syncProgress(ns, {
|
|
2190
|
+
rawCount: messages.length,
|
|
2191
|
+
pulledCount: decrypted.length - pageDecryptedBefore,
|
|
2192
|
+
remaining: result.remaining,
|
|
2193
|
+
hasMore: hasMoreField ? hasMore : undefined,
|
|
2194
|
+
currentSeq: client._seqTracker.getContiguousSeq(ns),
|
|
2195
|
+
targetSeq: serverHead,
|
|
2196
|
+
});
|
|
2197
|
+
const nextAfter = Math.max(pageContiguousSeq, nextAfterSeq);
|
|
2083
2198
|
if (!ownsCursor)
|
|
2084
2199
|
break;
|
|
2085
2200
|
const rawCount = messages.length;
|
|
2201
|
+
if (blockedSeq > 0)
|
|
2202
|
+
break;
|
|
2086
2203
|
const shouldContinue = shouldContinueForwardPage({
|
|
2087
2204
|
rawCount,
|
|
2088
2205
|
nextAfterSeq,
|
|
@@ -2091,6 +2208,7 @@ export class V2E2EECoordinator {
|
|
|
2091
2208
|
hasMoreField,
|
|
2092
2209
|
hasMore,
|
|
2093
2210
|
serverHead,
|
|
2211
|
+
observedUpper: Math.max(client._seqTracker.getMaxSeenSeq(ns), Number(client._delivery.pendingPullUpper?.(ns) ?? 0)),
|
|
2094
2212
|
pendingAckSeq,
|
|
2095
2213
|
});
|
|
2096
2214
|
if (!shouldContinue)
|
|
@@ -2116,6 +2234,20 @@ export class V2E2EECoordinator {
|
|
|
2116
2234
|
client._clientLog.debug(`group.v2.pull done: group=${gid}, requested_after_seq=${afterSeq}, pages=${pageCount}, decrypted=${decrypted.length}, ns=${ns}`);
|
|
2117
2235
|
return decrypted;
|
|
2118
2236
|
}
|
|
2237
|
+
async pullGroupV2(groupId, afterSeq = 0, limit = 50, opts) {
|
|
2238
|
+
if (opts?.ownsCursor === false) {
|
|
2239
|
+
return await this.pullGroupV2Impl(groupId, afterSeq, limit, opts);
|
|
2240
|
+
}
|
|
2241
|
+
const ns = `group:${String(groupId ?? '').trim()}`;
|
|
2242
|
+
this.client._delivery.syncStarted(ns);
|
|
2243
|
+
try {
|
|
2244
|
+
return await this.pullGroupV2Impl(groupId, afterSeq, limit, opts);
|
|
2245
|
+
}
|
|
2246
|
+
catch (error) {
|
|
2247
|
+
this.client._delivery.onPullAborted?.();
|
|
2248
|
+
throw error;
|
|
2249
|
+
}
|
|
2250
|
+
}
|
|
2119
2251
|
async confirmForwardGroupAck(groupId, upToSeq, groupAid) {
|
|
2120
2252
|
const ns = `group:${String(groupId ?? '').trim()}`;
|
|
2121
2253
|
try {
|
|
@@ -2675,7 +2807,7 @@ export class V2E2EECoordinator {
|
|
|
2675
2807
|
async decryptV2PushMessage(data) {
|
|
2676
2808
|
if (!isJsonObject(data))
|
|
2677
2809
|
return null;
|
|
2678
|
-
return await this.client._decryptV2Message(data, false, false, false, false);
|
|
2810
|
+
return await this.client._decryptV2Message(data, false, false, false, false, undefined, false, 'inline_push');
|
|
2679
2811
|
}
|
|
2680
2812
|
handleGroupChangedSpk(data, groupId, action) {
|
|
2681
2813
|
if (!this.client._v2Session || !groupId || !MEMBERSHIP_ACTIONS.has(action))
|