@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/bundle.js
CHANGED
|
@@ -460,7 +460,7 @@ var init_indexeddb_store = __esm({
|
|
|
460
460
|
});
|
|
461
461
|
|
|
462
462
|
// src/version.ts
|
|
463
|
-
var VERSION = "0.5.
|
|
463
|
+
var VERSION = "0.5.11";
|
|
464
464
|
|
|
465
465
|
// src/types.ts
|
|
466
466
|
var ConnectionState = /* @__PURE__ */ ((ConnectionState2) => {
|
|
@@ -1296,6 +1296,8 @@ var GatewayDiscovery = class {
|
|
|
1296
1296
|
var MAX_WS_PAYLOAD_SIZE = 1e6;
|
|
1297
1297
|
var MAX_RPC_INFLIGHT = 16;
|
|
1298
1298
|
var MAX_BACKGROUND_RPC_INFLIGHT = 8;
|
|
1299
|
+
var WORKER_START_TIMEOUT_MS = 2e3;
|
|
1300
|
+
var WORKER_OPEN_TIMEOUT_MS = 2e3;
|
|
1299
1301
|
var _noopLog3 = { error: () => {
|
|
1300
1302
|
}, warn: () => {
|
|
1301
1303
|
}, info: () => {
|
|
@@ -1304,6 +1306,7 @@ var _noopLog3 = { error: () => {
|
|
|
1304
1306
|
var _rpcIdCounter = 0;
|
|
1305
1307
|
var WORKER_WEBSOCKET_SOURCE = `
|
|
1306
1308
|
let socket = null;
|
|
1309
|
+
self.postMessage({ type: 'ready' });
|
|
1307
1310
|
self.onmessage = (event) => {
|
|
1308
1311
|
const command = event.data || {};
|
|
1309
1312
|
if (command.type === 'connect') {
|
|
@@ -1343,11 +1346,19 @@ var _WorkerWebSocketProxy = class _WorkerWebSocketProxy {
|
|
|
1343
1346
|
__publicField(this, "onmessage", null);
|
|
1344
1347
|
__publicField(this, "onerror", null);
|
|
1345
1348
|
__publicField(this, "onclose", null);
|
|
1349
|
+
__publicField(this, "_url");
|
|
1346
1350
|
__publicField(this, "_worker");
|
|
1347
1351
|
__publicField(this, "_workerUrl");
|
|
1352
|
+
__publicField(this, "_nativeSocket", null);
|
|
1353
|
+
__publicField(this, "_workerReady", false);
|
|
1354
|
+
__publicField(this, "_opened", false);
|
|
1355
|
+
__publicField(this, "_closedEventEmitted", false);
|
|
1356
|
+
__publicField(this, "_workerStartTimer", null);
|
|
1357
|
+
__publicField(this, "_workerOpenTimer", null);
|
|
1348
1358
|
__publicField(this, "_listeners", /* @__PURE__ */ new Map());
|
|
1349
1359
|
__publicField(this, "_pendingSends", /* @__PURE__ */ new Map());
|
|
1350
1360
|
__publicField(this, "_sendSeq", 0);
|
|
1361
|
+
this._url = url;
|
|
1351
1362
|
this._workerUrl = URL.createObjectURL(new Blob([WORKER_WEBSOCKET_SOURCE], { type: "text/javascript" }));
|
|
1352
1363
|
try {
|
|
1353
1364
|
this._worker = new Worker(this._workerUrl);
|
|
@@ -1355,17 +1366,35 @@ var _WorkerWebSocketProxy = class _WorkerWebSocketProxy {
|
|
|
1355
1366
|
URL.revokeObjectURL(this._workerUrl);
|
|
1356
1367
|
throw error;
|
|
1357
1368
|
}
|
|
1358
|
-
|
|
1359
|
-
|
|
1360
|
-
|
|
1369
|
+
const worker = this._worker;
|
|
1370
|
+
worker.onmessage = (event) => this._handleWorkerMessage(event.data);
|
|
1371
|
+
worker.onerror = (event) => {
|
|
1372
|
+
event.preventDefault?.();
|
|
1373
|
+
if (!this._opened) {
|
|
1374
|
+
this._fallbackToNative();
|
|
1375
|
+
return;
|
|
1376
|
+
}
|
|
1377
|
+
this._fallbackToNative(true);
|
|
1378
|
+
};
|
|
1379
|
+
this._workerStartTimer = globalThis.setTimeout(() => this._fallbackToNative(), WORKER_START_TIMEOUT_MS);
|
|
1361
1380
|
}
|
|
1362
1381
|
send(data) {
|
|
1363
1382
|
if (this.readyState !== _WorkerWebSocketProxy.OPEN) return Promise.reject(new Error("websocket is not open"));
|
|
1383
|
+
if (this._nativeSocket) {
|
|
1384
|
+
try {
|
|
1385
|
+
this._nativeSocket.send(data);
|
|
1386
|
+
return Promise.resolve();
|
|
1387
|
+
} catch (error) {
|
|
1388
|
+
return Promise.reject(error instanceof Error ? error : new Error(String(error)));
|
|
1389
|
+
}
|
|
1390
|
+
}
|
|
1391
|
+
const worker = this._worker;
|
|
1392
|
+
if (!worker) return Promise.reject(new Error("websocket worker is not available"));
|
|
1364
1393
|
const id = ++this._sendSeq;
|
|
1365
1394
|
return new Promise((resolve, reject) => {
|
|
1366
1395
|
this._pendingSends.set(id, { resolve, reject });
|
|
1367
1396
|
try {
|
|
1368
|
-
|
|
1397
|
+
worker.postMessage({ type: "send", id, data });
|
|
1369
1398
|
} catch (error) {
|
|
1370
1399
|
this._pendingSends.delete(id);
|
|
1371
1400
|
reject(error instanceof Error ? error : new Error(String(error)));
|
|
@@ -1375,7 +1404,24 @@ var _WorkerWebSocketProxy = class _WorkerWebSocketProxy {
|
|
|
1375
1404
|
close(code, reason) {
|
|
1376
1405
|
if (this.readyState === _WorkerWebSocketProxy.CLOSED) return;
|
|
1377
1406
|
this.readyState = _WorkerWebSocketProxy.CLOSING;
|
|
1378
|
-
this.
|
|
1407
|
+
if (this._nativeSocket) {
|
|
1408
|
+
try {
|
|
1409
|
+
this._nativeSocket.close(code, reason);
|
|
1410
|
+
} catch {
|
|
1411
|
+
this._emitClose(new CloseEvent("close", { code: code ?? 1e3, reason: reason ?? "", wasClean: true }));
|
|
1412
|
+
}
|
|
1413
|
+
return;
|
|
1414
|
+
}
|
|
1415
|
+
if (!this._workerReady || !this._worker) {
|
|
1416
|
+
this._disposeWorker();
|
|
1417
|
+
this._emitClose(new CloseEvent("close", { code: code ?? 1e3, reason: reason ?? "", wasClean: true }));
|
|
1418
|
+
return;
|
|
1419
|
+
}
|
|
1420
|
+
try {
|
|
1421
|
+
this._worker.postMessage({ type: "close", code, reason });
|
|
1422
|
+
} catch {
|
|
1423
|
+
this._fallbackToNative();
|
|
1424
|
+
}
|
|
1379
1425
|
}
|
|
1380
1426
|
addEventListener(type, listener) {
|
|
1381
1427
|
const callback = typeof listener === "function" ? listener : (event) => listener.handleEvent(event);
|
|
@@ -1387,6 +1433,21 @@ var _WorkerWebSocketProxy = class _WorkerWebSocketProxy {
|
|
|
1387
1433
|
if (typeof listener === "function") this._listeners.get(type)?.delete(listener);
|
|
1388
1434
|
}
|
|
1389
1435
|
_handleWorkerMessage(reply) {
|
|
1436
|
+
if (reply.type === "ready") {
|
|
1437
|
+
if (this._workerReady || !this._worker) return;
|
|
1438
|
+
this._workerReady = true;
|
|
1439
|
+
this._clearWorkerStartTimer();
|
|
1440
|
+
try {
|
|
1441
|
+
this._worker.postMessage({ type: "connect", url: this._url });
|
|
1442
|
+
this._workerOpenTimer = globalThis.setTimeout(
|
|
1443
|
+
() => this._fallbackToNative(),
|
|
1444
|
+
WORKER_OPEN_TIMEOUT_MS
|
|
1445
|
+
);
|
|
1446
|
+
} catch {
|
|
1447
|
+
this._fallbackToNative();
|
|
1448
|
+
}
|
|
1449
|
+
return;
|
|
1450
|
+
}
|
|
1390
1451
|
if (reply.type === "send_result" && reply.id !== void 0) {
|
|
1391
1452
|
const pending = this._pendingSends.get(reply.id);
|
|
1392
1453
|
if (!pending) return;
|
|
@@ -1396,6 +1457,8 @@ var _WorkerWebSocketProxy = class _WorkerWebSocketProxy {
|
|
|
1396
1457
|
return;
|
|
1397
1458
|
}
|
|
1398
1459
|
if (reply.type === "open") {
|
|
1460
|
+
this._clearWorkerOpenTimer();
|
|
1461
|
+
this._opened = true;
|
|
1399
1462
|
this.readyState = _WorkerWebSocketProxy.OPEN;
|
|
1400
1463
|
const event = new Event("open");
|
|
1401
1464
|
this.onopen?.(event);
|
|
@@ -1409,24 +1472,94 @@ var _WorkerWebSocketProxy = class _WorkerWebSocketProxy {
|
|
|
1409
1472
|
return;
|
|
1410
1473
|
}
|
|
1411
1474
|
if (reply.type === "error") {
|
|
1475
|
+
if (!this._opened && this.readyState === _WorkerWebSocketProxy.CONNECTING) {
|
|
1476
|
+
this._fallbackToNative();
|
|
1477
|
+
return;
|
|
1478
|
+
}
|
|
1412
1479
|
this._emitError(reply.message || "websocket worker error");
|
|
1413
1480
|
return;
|
|
1414
1481
|
}
|
|
1415
1482
|
if (reply.type === "close") {
|
|
1416
|
-
this.readyState
|
|
1417
|
-
|
|
1418
|
-
|
|
1419
|
-
|
|
1483
|
+
if (!this._opened && this.readyState === _WorkerWebSocketProxy.CONNECTING) {
|
|
1484
|
+
this._fallbackToNative();
|
|
1485
|
+
return;
|
|
1486
|
+
}
|
|
1487
|
+
this._emitClose(new CloseEvent("close", {
|
|
1420
1488
|
code: reply.code ?? 1006,
|
|
1421
1489
|
reason: reply.reason ?? "",
|
|
1422
1490
|
wasClean: reply.wasClean === true
|
|
1423
|
-
});
|
|
1424
|
-
this.onclose?.(event);
|
|
1425
|
-
this._emit("close", event);
|
|
1426
|
-
this._worker.terminate();
|
|
1427
|
-
URL.revokeObjectURL(this._workerUrl);
|
|
1491
|
+
}));
|
|
1428
1492
|
}
|
|
1429
1493
|
}
|
|
1494
|
+
_fallbackToNative(force = false) {
|
|
1495
|
+
if (this._nativeSocket || this.readyState === _WorkerWebSocketProxy.CLOSED) return;
|
|
1496
|
+
if (!force && (this.readyState !== _WorkerWebSocketProxy.CONNECTING || this._opened)) return;
|
|
1497
|
+
const wasOpened = this._opened;
|
|
1498
|
+
this._opened = false;
|
|
1499
|
+
this.readyState = _WorkerWebSocketProxy.CONNECTING;
|
|
1500
|
+
this._disposeWorker();
|
|
1501
|
+
try {
|
|
1502
|
+
const socket = new WebSocket(this._url);
|
|
1503
|
+
this._nativeSocket = socket;
|
|
1504
|
+
socket.onopen = (event) => {
|
|
1505
|
+
this._opened = true;
|
|
1506
|
+
this.readyState = _WorkerWebSocketProxy.OPEN;
|
|
1507
|
+
if (!wasOpened) {
|
|
1508
|
+
this.onopen?.(event);
|
|
1509
|
+
this._emit("open", event);
|
|
1510
|
+
}
|
|
1511
|
+
};
|
|
1512
|
+
socket.onmessage = (event) => {
|
|
1513
|
+
this.onmessage?.(event);
|
|
1514
|
+
this._emit("message", event);
|
|
1515
|
+
};
|
|
1516
|
+
socket.onerror = (event) => {
|
|
1517
|
+
this.onerror?.(event);
|
|
1518
|
+
this._emit("error", event);
|
|
1519
|
+
};
|
|
1520
|
+
socket.onclose = (event) => this._emitClose(event);
|
|
1521
|
+
} catch (error) {
|
|
1522
|
+
this.readyState = _WorkerWebSocketProxy.CLOSED;
|
|
1523
|
+
this._emitError(error instanceof Error ? error.message : String(error));
|
|
1524
|
+
}
|
|
1525
|
+
}
|
|
1526
|
+
_emitClose(event) {
|
|
1527
|
+
if (this._closedEventEmitted) return;
|
|
1528
|
+
this._closedEventEmitted = true;
|
|
1529
|
+
this.readyState = _WorkerWebSocketProxy.CLOSED;
|
|
1530
|
+
for (const pending of this._pendingSends.values()) pending.reject(new Error("websocket closed"));
|
|
1531
|
+
this._pendingSends.clear();
|
|
1532
|
+
this.onclose?.(event);
|
|
1533
|
+
this._emit("close", event);
|
|
1534
|
+
this._disposeWorker();
|
|
1535
|
+
this._nativeSocket = null;
|
|
1536
|
+
}
|
|
1537
|
+
_clearWorkerStartTimer() {
|
|
1538
|
+
if (this._workerStartTimer === null) return;
|
|
1539
|
+
globalThis.clearTimeout(this._workerStartTimer);
|
|
1540
|
+
this._workerStartTimer = null;
|
|
1541
|
+
}
|
|
1542
|
+
_clearWorkerOpenTimer() {
|
|
1543
|
+
if (this._workerOpenTimer === null) return;
|
|
1544
|
+
globalThis.clearTimeout(this._workerOpenTimer);
|
|
1545
|
+
this._workerOpenTimer = null;
|
|
1546
|
+
}
|
|
1547
|
+
_disposeWorker() {
|
|
1548
|
+
this._clearWorkerStartTimer();
|
|
1549
|
+
this._clearWorkerOpenTimer();
|
|
1550
|
+
for (const pending of this._pendingSends.values()) pending.reject(new Error("websocket worker unavailable"));
|
|
1551
|
+
this._pendingSends.clear();
|
|
1552
|
+
const worker = this._worker;
|
|
1553
|
+
this._worker = null;
|
|
1554
|
+
if (worker) {
|
|
1555
|
+
worker.onmessage = null;
|
|
1556
|
+
worker.onerror = null;
|
|
1557
|
+
worker.terminate();
|
|
1558
|
+
}
|
|
1559
|
+
const workerUrl = this._workerUrl;
|
|
1560
|
+
this._workerUrl = null;
|
|
1561
|
+
if (workerUrl && typeof URL.revokeObjectURL === "function") URL.revokeObjectURL(workerUrl);
|
|
1562
|
+
}
|
|
1430
1563
|
_emitError(message) {
|
|
1431
1564
|
const event = new ErrorEvent("error", { message });
|
|
1432
1565
|
this.onerror?.(event);
|
|
@@ -4877,6 +5010,26 @@ function nonNegativeSafeSequenceHint(value) {
|
|
|
4877
5010
|
if (typeof value !== "number" || !Number.isSafeInteger(value) || value < 0) return null;
|
|
4878
5011
|
return value;
|
|
4879
5012
|
}
|
|
5013
|
+
function canonicalDeliverySource(source) {
|
|
5014
|
+
switch (String(source ?? "").trim()) {
|
|
5015
|
+
case "group-push":
|
|
5016
|
+
case "ordered":
|
|
5017
|
+
case "legacy":
|
|
5018
|
+
return "push";
|
|
5019
|
+
case "tail":
|
|
5020
|
+
case "pull-drained":
|
|
5021
|
+
case "pull_drained":
|
|
5022
|
+
return "pull";
|
|
5023
|
+
case "inline-push":
|
|
5024
|
+
return "inline_push";
|
|
5025
|
+
case "pending-retry":
|
|
5026
|
+
return "pending_retry";
|
|
5027
|
+
case "":
|
|
5028
|
+
return "direct";
|
|
5029
|
+
default:
|
|
5030
|
+
return String(source).trim();
|
|
5031
|
+
}
|
|
5032
|
+
}
|
|
4880
5033
|
function deduplicatePlainForwardPageMessages(value, afterSeq) {
|
|
4881
5034
|
if (!Array.isArray(value)) return [];
|
|
4882
5035
|
const bySeq = /* @__PURE__ */ new Map();
|
|
@@ -4905,6 +5058,9 @@ function p2pAppEventFromPlainPullMessage(message) {
|
|
|
4905
5058
|
var MessageDeliveryEngine = class {
|
|
4906
5059
|
constructor(runtime) {
|
|
4907
5060
|
__publicField(this, "runtime");
|
|
5061
|
+
__publicField(this, "syncRun", 0);
|
|
5062
|
+
__publicField(this, "syncingNamespaces", /* @__PURE__ */ new Set());
|
|
5063
|
+
__publicField(this, "syncSessions", /* @__PURE__ */ new Map());
|
|
4908
5064
|
__publicField(this, "pendingPullDeliveryChanges", null);
|
|
4909
5065
|
__publicField(this, "deliveryGeneration", 0);
|
|
4910
5066
|
__publicField(this, "realtimeTailResults", null);
|
|
@@ -4925,6 +5081,7 @@ var MessageDeliveryEngine = class {
|
|
|
4925
5081
|
this.runtime = runtime;
|
|
4926
5082
|
}
|
|
4927
5083
|
resetInlineAckState() {
|
|
5084
|
+
this.syncStopped("aborted");
|
|
4928
5085
|
this.inlineGeneration += 1;
|
|
4929
5086
|
this.deliveryGeneration += 1;
|
|
4930
5087
|
this.pendingPullDeliveryChanges = null;
|
|
@@ -4940,6 +5097,8 @@ var MessageDeliveryEngine = class {
|
|
|
4940
5097
|
this.pendingP2PInlineAcks = null;
|
|
4941
5098
|
this.pendingGroupInlineAcks = null;
|
|
4942
5099
|
this.pendingGroupInlineAckNamespaces = null;
|
|
5100
|
+
this.syncingNamespaces.clear();
|
|
5101
|
+
this.syncSessions.clear();
|
|
4943
5102
|
}
|
|
4944
5103
|
isInlineGenerationCurrent(generation) {
|
|
4945
5104
|
return generation === this.inlineGeneration;
|
|
@@ -4967,6 +5126,91 @@ var MessageDeliveryEngine = class {
|
|
|
4967
5126
|
endRealtimeSync(ns) {
|
|
4968
5127
|
this.realtimeSyncing?.delete(ns);
|
|
4969
5128
|
}
|
|
5129
|
+
onPullStarted(ns) {
|
|
5130
|
+
if (!ns || this.syncingNamespaces.has(ns)) return;
|
|
5131
|
+
if (this.syncingNamespaces.size === 0) {
|
|
5132
|
+
this.syncRun += 1;
|
|
5133
|
+
this.syncSessions.clear();
|
|
5134
|
+
this.runtime.client._dispatcher?.enqueue?.("sync.started", {
|
|
5135
|
+
run_id: this.syncRun,
|
|
5136
|
+
source: "pull",
|
|
5137
|
+
syncing: true,
|
|
5138
|
+
namespaces_pending: 1,
|
|
5139
|
+
received_total: 0,
|
|
5140
|
+
namespace: ns,
|
|
5141
|
+
started_at: Date.now()
|
|
5142
|
+
});
|
|
5143
|
+
}
|
|
5144
|
+
this.syncingNamespaces.add(ns);
|
|
5145
|
+
this.syncSessions.set(ns, { pages: 0, raw: 0, pulled: 0 });
|
|
5146
|
+
}
|
|
5147
|
+
onPullPage(ns, pulledCount, hasMore, maxSeen, remaining, rawCount = pulledCount, currentSeq, targetSeq) {
|
|
5148
|
+
this.onPullStarted(ns);
|
|
5149
|
+
if (!ns) return;
|
|
5150
|
+
const session = this.syncSessions.get(ns) ?? { pages: 0, raw: 0, pulled: 0 };
|
|
5151
|
+
session.pages += 1;
|
|
5152
|
+
session.raw += Math.max(0, rawCount);
|
|
5153
|
+
session.pulled += Math.max(0, pulledCount);
|
|
5154
|
+
this.syncSessions.set(ns, session);
|
|
5155
|
+
const received = session.pulled;
|
|
5156
|
+
const progress = {
|
|
5157
|
+
run_id: this.syncRun,
|
|
5158
|
+
source: "pull",
|
|
5159
|
+
namespace: ns,
|
|
5160
|
+
page: session.pages,
|
|
5161
|
+
page_raw_count: Math.max(0, rawCount),
|
|
5162
|
+
page_pulled_count: Math.max(0, pulledCount),
|
|
5163
|
+
pulled_count: received,
|
|
5164
|
+
received_total: received,
|
|
5165
|
+
batch_size: Math.max(0, pulledCount),
|
|
5166
|
+
estimated_remaining: hasMore ? void 0 : 0,
|
|
5167
|
+
max_seen: maxSeen,
|
|
5168
|
+
has_more: hasMore
|
|
5169
|
+
};
|
|
5170
|
+
if (typeof currentSeq === "number" && Number.isSafeInteger(currentSeq) && currentSeq >= 0) {
|
|
5171
|
+
progress.current_seq = currentSeq;
|
|
5172
|
+
}
|
|
5173
|
+
if (typeof targetSeq === "number" && Number.isSafeInteger(targetSeq) && targetSeq >= 0) {
|
|
5174
|
+
progress.target_seq = targetSeq;
|
|
5175
|
+
}
|
|
5176
|
+
if (typeof remaining === "number" && Number.isSafeInteger(remaining) && remaining >= 0) {
|
|
5177
|
+
progress.remaining = remaining;
|
|
5178
|
+
progress.estimated_remaining = progress.remaining;
|
|
5179
|
+
}
|
|
5180
|
+
this.runtime.client._dispatcher?.enqueue?.("sync.progress", progress);
|
|
5181
|
+
}
|
|
5182
|
+
onPullAborted() {
|
|
5183
|
+
this.syncStopped("aborted");
|
|
5184
|
+
}
|
|
5185
|
+
syncStopped(reason = "pull_drained") {
|
|
5186
|
+
if (this.syncingNamespaces.size === 0) return;
|
|
5187
|
+
const sessions = [...this.syncSessions.entries()];
|
|
5188
|
+
const receivedTotal = sessions.reduce((total, [, session]) => total + session.pulled, 0);
|
|
5189
|
+
this.syncingNamespaces.clear();
|
|
5190
|
+
this.syncSessions.clear();
|
|
5191
|
+
const payload = {
|
|
5192
|
+
run_id: this.syncRun,
|
|
5193
|
+
source: "pull",
|
|
5194
|
+
syncing: false,
|
|
5195
|
+
namespaces_pending: 0,
|
|
5196
|
+
received_total: receivedTotal,
|
|
5197
|
+
reason,
|
|
5198
|
+
stopped_at: Date.now()
|
|
5199
|
+
};
|
|
5200
|
+
if (sessions.length === 1) {
|
|
5201
|
+
const [namespace, session] = sessions[0];
|
|
5202
|
+
payload.namespace = namespace;
|
|
5203
|
+
payload.pages = session.pages;
|
|
5204
|
+
payload.pulled_count = session.pulled;
|
|
5205
|
+
} else if (sessions.length > 1) {
|
|
5206
|
+
payload.namespaces = sessions.map(([namespace]) => namespace);
|
|
5207
|
+
payload.pages = sessions.reduce((total, [, session]) => total + session.pages, 0);
|
|
5208
|
+
payload.pulled_count = receivedTotal;
|
|
5209
|
+
}
|
|
5210
|
+
this.runtime.client._dispatcher?.enqueue?.("sync.stopped", {
|
|
5211
|
+
...payload
|
|
5212
|
+
});
|
|
5213
|
+
}
|
|
4970
5214
|
hasPendingPull(ns) {
|
|
4971
5215
|
const pending = ns.startsWith("p2p:") ? this.pendingP2pPullUpper : this.pendingGroupPullUpper;
|
|
4972
5216
|
return (pending?.get(ns) ?? 0) > 0;
|
|
@@ -4978,7 +5222,7 @@ var MessageDeliveryEngine = class {
|
|
|
4978
5222
|
onPullWorkSettled() {
|
|
4979
5223
|
const pipeline = this.runtime.client._rpcPipeline;
|
|
4980
5224
|
if (pipeline?.hasAnyPullActivity?.() === true) return;
|
|
4981
|
-
void this.flushPullDeliveryChanges();
|
|
5225
|
+
void this.flushPullDeliveryChanges().finally(() => this.syncStopped("pull_drained"));
|
|
4982
5226
|
}
|
|
4983
5227
|
deliveryChangeNamespace(event, payload, ns = "") {
|
|
4984
5228
|
if (event === "message.received") return "p2p";
|
|
@@ -5024,7 +5268,11 @@ var MessageDeliveryEngine = class {
|
|
|
5024
5268
|
if (batch.generation !== this.deliveryGeneration) return;
|
|
5025
5269
|
const changes = this.deliveryChangesPayload(batch.changes);
|
|
5026
5270
|
if (changes.length === 0) return;
|
|
5027
|
-
this.runtime.client._dispatcher.enqueue("delivery.changed", {
|
|
5271
|
+
this.runtime.client._dispatcher.enqueue("delivery.changed", {
|
|
5272
|
+
trigger: batch.trigger,
|
|
5273
|
+
source: batch.trigger,
|
|
5274
|
+
changes
|
|
5275
|
+
});
|
|
5028
5276
|
}
|
|
5029
5277
|
async flushPullDeliveryChanges() {
|
|
5030
5278
|
const generation = this.deliveryGeneration;
|
|
@@ -5034,7 +5282,11 @@ var MessageDeliveryEngine = class {
|
|
|
5034
5282
|
if (generation !== this.deliveryGeneration) return;
|
|
5035
5283
|
const changes = this.deliveryChangesPayload(pending);
|
|
5036
5284
|
if (changes.length === 0) return;
|
|
5037
|
-
this.runtime.client._dispatcher.enqueue("delivery.changed", {
|
|
5285
|
+
this.runtime.client._dispatcher.enqueue("delivery.changed", {
|
|
5286
|
+
trigger: "pull_drained",
|
|
5287
|
+
source: "pull",
|
|
5288
|
+
changes
|
|
5289
|
+
});
|
|
5038
5290
|
}
|
|
5039
5291
|
recordPendingPull(ns, seq2) {
|
|
5040
5292
|
if (!ns || !Number.isSafeInteger(seq2) || seq2 <= 0) return;
|
|
@@ -5537,7 +5789,7 @@ var MessageDeliveryEngine = class {
|
|
|
5537
5789
|
}
|
|
5538
5790
|
const message = normalizeGroupMentionMode(rawMessage);
|
|
5539
5791
|
if (this.recallEventFromGroupMessage(message)) {
|
|
5540
|
-
if (await this.publishGroupRecallTombstone(groupId, seq2, message)) {
|
|
5792
|
+
if (await this.publishGroupRecallTombstone(groupId, seq2, message, "pull")) {
|
|
5541
5793
|
this.ensurePullOperationCurrent();
|
|
5542
5794
|
this.markPublishedSeq(ns, seq2);
|
|
5543
5795
|
publishedCount += 1;
|
|
@@ -5608,6 +5860,17 @@ var MessageDeliveryEngine = class {
|
|
|
5608
5860
|
this.ensurePullOperationCurrent();
|
|
5609
5861
|
await this.confirmPlainForwardAck(ns, ackMethod, pendingAckSeq, groupId);
|
|
5610
5862
|
}
|
|
5863
|
+
const remaining = typeof response.remaining === "number" && Number.isSafeInteger(response.remaining) && response.remaining >= 0 ? response.remaining : null;
|
|
5864
|
+
this.onPullPage(
|
|
5865
|
+
ns,
|
|
5866
|
+
publishedCount,
|
|
5867
|
+
response.has_more === true,
|
|
5868
|
+
messages.length > 0 ? Number(messages[messages.length - 1].seq ?? 0) : void 0,
|
|
5869
|
+
remaining,
|
|
5870
|
+
messages.length,
|
|
5871
|
+
client._seqTracker.getContiguousSeq(ns),
|
|
5872
|
+
messages.length > 0 ? Number(messages[messages.length - 1].seq ?? 0) : void 0
|
|
5873
|
+
);
|
|
5611
5874
|
return { rawCount: messages.length, publishedCount };
|
|
5612
5875
|
}
|
|
5613
5876
|
enqueueOrderedMessage(ns, event, seq2, payload, source = "push") {
|
|
@@ -5629,11 +5892,11 @@ var MessageDeliveryEngine = class {
|
|
|
5629
5892
|
async publishOrderedQueueItem(ns, event, seq2, payload, pullResponse = false, source = "push", batch) {
|
|
5630
5893
|
const client = this.runtime.client;
|
|
5631
5894
|
if (event === "group.changed" && this.isGroupEventNamespace(ns)) {
|
|
5632
|
-
await this.publishOrderedGroupChanged(payload);
|
|
5895
|
+
await this.publishOrderedGroupChanged(payload, source);
|
|
5633
5896
|
return;
|
|
5634
5897
|
}
|
|
5635
5898
|
if (event === "message.recalled") {
|
|
5636
|
-
await this.publishMessageRecallTombstone(seq2, payload);
|
|
5899
|
+
await this.publishMessageRecallTombstone(seq2, payload, source);
|
|
5637
5900
|
return;
|
|
5638
5901
|
}
|
|
5639
5902
|
if (pullResponse) {
|
|
@@ -5642,7 +5905,7 @@ var MessageDeliveryEngine = class {
|
|
|
5642
5905
|
}
|
|
5643
5906
|
await client._publishAppEvent(event, payload, source, ns, batch);
|
|
5644
5907
|
}
|
|
5645
|
-
async publishOrderedGroupChanged(payload) {
|
|
5908
|
+
async publishOrderedGroupChanged(payload, source = "ordered") {
|
|
5646
5909
|
const client = this.runtime.client;
|
|
5647
5910
|
if (isJsonObject(payload)) {
|
|
5648
5911
|
const eventPayload = payload;
|
|
@@ -5653,7 +5916,7 @@ var MessageDeliveryEngine = class {
|
|
|
5653
5916
|
if (groupId) client._cleanupDissolvedGroup?.(groupId);
|
|
5654
5917
|
}
|
|
5655
5918
|
}
|
|
5656
|
-
await client._publishAppEvent("group.changed", payload);
|
|
5919
|
+
await client._publishAppEvent("group.changed", payload, source);
|
|
5657
5920
|
}
|
|
5658
5921
|
isInstanceScopedMessageEvent(event) {
|
|
5659
5922
|
return event === "message.received" || event === "message.recalled" || event === "message.undecryptable" || event === "group.message_created" || event === "group.message_recalled" || event === "group.message_undecryptable";
|
|
@@ -5670,17 +5933,22 @@ var MessageDeliveryEngine = class {
|
|
|
5670
5933
|
}
|
|
5671
5934
|
return result;
|
|
5672
5935
|
}
|
|
5673
|
-
normalizePublishedMessagePayload(event, payload) {
|
|
5936
|
+
normalizePublishedMessagePayload(event, payload, source = "direct") {
|
|
5937
|
+
let normalized;
|
|
5674
5938
|
if (this.isInstanceScopedMessageEvent(event)) {
|
|
5675
5939
|
payload = this.stripInlineInternalFields(payload);
|
|
5676
5940
|
if (event === "group.message_created") payload = normalizeGroupMentionMode(payload);
|
|
5677
|
-
|
|
5678
|
-
}
|
|
5679
|
-
if (this.isGroupScopedEvent(event)) {
|
|
5941
|
+
normalized = this.attachAppMessageEnvelope(this.stripInternalSenderDeviceFields(this.attachCurrentInstanceContext(payload)));
|
|
5942
|
+
} else if (this.isGroupScopedEvent(event)) {
|
|
5680
5943
|
payload = this.stripInlineInternalFields(payload);
|
|
5681
|
-
|
|
5944
|
+
normalized = this.attachAppGroupEventEnvelope(this.attachCurrentInstanceContext(payload));
|
|
5945
|
+
} else {
|
|
5946
|
+
normalized = payload;
|
|
5682
5947
|
}
|
|
5683
|
-
|
|
5948
|
+
const canonicalSource = canonicalDeliverySource(source);
|
|
5949
|
+
if (canonicalSource === "direct" || !isJsonObject(normalized)) return normalized;
|
|
5950
|
+
if (!this.isInstanceScopedMessageEvent(event) && !this.isGroupScopedEvent(event)) return normalized;
|
|
5951
|
+
return { ...normalized, source: canonicalSource };
|
|
5684
5952
|
}
|
|
5685
5953
|
stripInlineInternalFields(payload) {
|
|
5686
5954
|
if (!isJsonObject(payload)) return payload;
|
|
@@ -5896,7 +6164,7 @@ var MessageDeliveryEngine = class {
|
|
|
5896
6164
|
if (tombstoneId) return `p2p|tombstone:${tombstoneId}`;
|
|
5897
6165
|
return `p2p|unknown:${Date.now()}:${Math.random()}`;
|
|
5898
6166
|
}
|
|
5899
|
-
async publishMessageRecallTombstone(seq2, message) {
|
|
6167
|
+
async publishMessageRecallTombstone(seq2, message, source = "push") {
|
|
5900
6168
|
const client = this.runtime.client;
|
|
5901
6169
|
const eventPayload = this.recallEventFromMessage(message);
|
|
5902
6170
|
if (!eventPayload) return false;
|
|
@@ -5915,7 +6183,7 @@ var MessageDeliveryEngine = class {
|
|
|
5915
6183
|
const drop = [...seen.entries()].sort((a, b) => a[1] - b[1]).slice(0, seen.size - MESSAGE_RECALL_SEEN_LIMIT);
|
|
5916
6184
|
for (const [oldKey] of drop) seen.delete(oldKey);
|
|
5917
6185
|
}
|
|
5918
|
-
await client._publishAppEvent("message.recalled", eventPayload);
|
|
6186
|
+
await client._publishAppEvent("message.recalled", eventPayload, source);
|
|
5919
6187
|
client._clientLog.debug(`message.recalled published: seq=${String(seq2)} ids=${JSON.stringify(eventPayload.message_ids)}`);
|
|
5920
6188
|
return true;
|
|
5921
6189
|
}
|
|
@@ -5977,7 +6245,7 @@ var MessageDeliveryEngine = class {
|
|
|
5977
6245
|
if (tombstoneId) return `${normalizedGroupId}|tombstone:${tombstoneId}`;
|
|
5978
6246
|
return `${normalizedGroupId}|unknown:${Date.now()}:${Math.random()}`;
|
|
5979
6247
|
}
|
|
5980
|
-
async publishGroupRecallTombstone(groupId, seq2, message) {
|
|
6248
|
+
async publishGroupRecallTombstone(groupId, seq2, message, source = "push") {
|
|
5981
6249
|
const client = this.runtime.client;
|
|
5982
6250
|
const eventPayload = this.recallEventFromGroupMessage(message);
|
|
5983
6251
|
if (!eventPayload) return false;
|
|
@@ -5998,7 +6266,7 @@ var MessageDeliveryEngine = class {
|
|
|
5998
6266
|
const drop = [...seen.entries()].sort((a, b) => a[1] - b[1]).slice(0, seen.size - GROUP_RECALL_SEEN_LIMIT);
|
|
5999
6267
|
for (const [oldKey] of drop) seen.delete(oldKey);
|
|
6000
6268
|
}
|
|
6001
|
-
await client._publishAppEvent("group.message_recalled", eventPayload);
|
|
6269
|
+
await client._publishAppEvent("group.message_recalled", eventPayload, source);
|
|
6002
6270
|
client._clientLog.debug(`group.message_recalled published: group=${groupId} seq=${String(seq2)} ids=${JSON.stringify(eventPayload.message_ids)}`);
|
|
6003
6271
|
return true;
|
|
6004
6272
|
}
|
|
@@ -6061,7 +6329,7 @@ var MessageDeliveryEngine = class {
|
|
|
6061
6329
|
}
|
|
6062
6330
|
if (contig !== contigBefore) this.persistSeq(ns);
|
|
6063
6331
|
}
|
|
6064
|
-
async publishAppEvent(event, payload, source = "", ns = "", batch) {
|
|
6332
|
+
async publishAppEvent(event, payload, source = "direct", ns = "", batch) {
|
|
6065
6333
|
const client = this.runtime.client;
|
|
6066
6334
|
const generation = this.deliveryGeneration;
|
|
6067
6335
|
if ((event === "message.received" || event === "group.message_created") && isJsonObject(payload)) {
|
|
@@ -6082,11 +6350,16 @@ var MessageDeliveryEngine = class {
|
|
|
6082
6350
|
client._clientLog.debug(`agent_md etag inject skipped: ${String(exc)}`);
|
|
6083
6351
|
}
|
|
6084
6352
|
}
|
|
6085
|
-
|
|
6353
|
+
const canonicalSource = canonicalDeliverySource(source);
|
|
6354
|
+
let normalized = this.normalizePublishedMessagePayload(event, payload, source);
|
|
6355
|
+
if (isJsonObject(normalized) && (this.isInstanceScopedMessageEvent(event) || this.isGroupScopedEvent(event)) && canonicalSource !== "direct") {
|
|
6356
|
+
normalized = { ...normalized, source: canonicalSource };
|
|
6357
|
+
}
|
|
6358
|
+
client._dispatcher.enqueue(event, normalized);
|
|
6086
6359
|
if (generation !== this.deliveryGeneration) return;
|
|
6087
|
-
if (
|
|
6088
|
-
if (
|
|
6089
|
-
const localBatch = batch ?? this.createDeliveryChangeBatch(
|
|
6360
|
+
if (canonicalSource !== "pull" && canonicalSource !== "pending_retry" && canonicalSource !== "push" && canonicalSource !== "inline_push") return;
|
|
6361
|
+
if (canonicalSource === "push" || canonicalSource === "inline_push") {
|
|
6362
|
+
const localBatch = batch ?? this.createDeliveryChangeBatch(canonicalSource);
|
|
6090
6363
|
this.recordDeliveryChange(localBatch.changes, event, payload, ns, generation);
|
|
6091
6364
|
if (!batch) await this.flushRealtimeDeliveryChanges(localBatch);
|
|
6092
6365
|
} else {
|
|
@@ -6287,7 +6560,7 @@ var MessageDeliveryEngine = class {
|
|
|
6287
6560
|
_decrypt_error: String(exc)
|
|
6288
6561
|
};
|
|
6289
6562
|
client._attachV2EnvelopeMetadataFromSource(safeEvent, data);
|
|
6290
|
-
await client._publishAppEvent("message.undecryptable", safeEvent);
|
|
6563
|
+
await client._publishAppEvent("message.undecryptable", safeEvent, "push");
|
|
6291
6564
|
}
|
|
6292
6565
|
}
|
|
6293
6566
|
}
|
|
@@ -6398,7 +6671,7 @@ var MessageDeliveryEngine = class {
|
|
|
6398
6671
|
_decrypt_error: String(exc)
|
|
6399
6672
|
};
|
|
6400
6673
|
client._attachV2EnvelopeMetadataFromSource(safeEvent, data);
|
|
6401
|
-
await client._publishAppEvent("group.message_undecryptable", safeEvent);
|
|
6674
|
+
await client._publishAppEvent("group.message_undecryptable", safeEvent, "push");
|
|
6402
6675
|
}
|
|
6403
6676
|
}
|
|
6404
6677
|
}
|
|
@@ -6406,7 +6679,7 @@ var MessageDeliveryEngine = class {
|
|
|
6406
6679
|
const client = this.runtime.client;
|
|
6407
6680
|
const groupId = notification.group_id ?? "";
|
|
6408
6681
|
if (!groupId) {
|
|
6409
|
-
await client._publishAppEvent("group.message_created", notification);
|
|
6682
|
+
await client._publishAppEvent("group.message_created", notification, "push");
|
|
6410
6683
|
return;
|
|
6411
6684
|
}
|
|
6412
6685
|
if (client._sessionOptions?.background_sync === false) {
|
|
@@ -6426,7 +6699,7 @@ var MessageDeliveryEngine = class {
|
|
|
6426
6699
|
return;
|
|
6427
6700
|
} catch (exc) {
|
|
6428
6701
|
client._clientLog.warn(`auto pull group message failed:${String(exc)}`);
|
|
6429
|
-
await client._publishAppEvent("group.message_created", notification);
|
|
6702
|
+
await client._publishAppEvent("group.message_created", notification, "push");
|
|
6430
6703
|
return;
|
|
6431
6704
|
}
|
|
6432
6705
|
}
|
|
@@ -6453,7 +6726,7 @@ var MessageDeliveryEngine = class {
|
|
|
6453
6726
|
} catch (exc) {
|
|
6454
6727
|
client._clientLog.warn(`auto pull group message commit/ack failed:${String(exc)}`);
|
|
6455
6728
|
if (!rawCompleted) {
|
|
6456
|
-
await client._publishAppEvent("group.message_created", notification);
|
|
6729
|
+
await client._publishAppEvent("group.message_created", notification, "push");
|
|
6457
6730
|
}
|
|
6458
6731
|
}
|
|
6459
6732
|
}
|
|
@@ -6581,6 +6854,7 @@ var MessageDeliveryEngine = class {
|
|
|
6581
6854
|
client._gapFillDone.add(dedupKey);
|
|
6582
6855
|
this.runtime.delivery.setGapFillActive(true);
|
|
6583
6856
|
let continuationAfterSeq = 0;
|
|
6857
|
+
let failed = false;
|
|
6584
6858
|
try {
|
|
6585
6859
|
let nextAfterSeq = afterSeq;
|
|
6586
6860
|
const maxPages = singlePage ? 1 : 100;
|
|
@@ -6628,6 +6902,7 @@ var MessageDeliveryEngine = class {
|
|
|
6628
6902
|
}
|
|
6629
6903
|
const eventSeqs = [];
|
|
6630
6904
|
let hasDissolvedEvent = false;
|
|
6905
|
+
let publishedEventCount = 0;
|
|
6631
6906
|
for (const evt of eventObjects) {
|
|
6632
6907
|
const eventSeq = Number(evt.event_seq ?? 0);
|
|
6633
6908
|
if (Number.isFinite(eventSeq) && eventSeq > 0) eventSeqs.push(eventSeq);
|
|
@@ -6645,7 +6920,8 @@ var MessageDeliveryEngine = class {
|
|
|
6645
6920
|
}
|
|
6646
6921
|
}
|
|
6647
6922
|
if (Number.isFinite(eventSeq) && eventSeq > 0 && !client._pushedSeqs.get(ns)?.has(eventSeq)) {
|
|
6648
|
-
this.enqueueOrderedMessage(ns, "group.changed", eventSeq, evt);
|
|
6923
|
+
this.enqueueOrderedMessage(ns, "group.changed", eventSeq, evt, "pull");
|
|
6924
|
+
publishedEventCount += 1;
|
|
6649
6925
|
}
|
|
6650
6926
|
}
|
|
6651
6927
|
const ackContig = client._seqTracker.getContiguousSeq(ns);
|
|
@@ -6670,6 +6946,16 @@ var MessageDeliveryEngine = class {
|
|
|
6670
6946
|
client._clientLog.warn("group event auto-ack failed: group=" + groupId, e);
|
|
6671
6947
|
}
|
|
6672
6948
|
}
|
|
6949
|
+
this.onPullPage(
|
|
6950
|
+
ns,
|
|
6951
|
+
publishedEventCount,
|
|
6952
|
+
result.has_more === true,
|
|
6953
|
+
eventObjects.length > 0 ? Number(eventObjects[eventObjects.length - 1].event_seq ?? 0) : void 0,
|
|
6954
|
+
typeof result.remaining === "number" && Number.isSafeInteger(result.remaining) && result.remaining >= 0 ? result.remaining : null,
|
|
6955
|
+
eventObjects.length,
|
|
6956
|
+
ackContig,
|
|
6957
|
+
eventObjects.length > 0 ? Number(eventObjects[eventObjects.length - 1].event_seq ?? 0) : void 0
|
|
6958
|
+
);
|
|
6673
6959
|
const nextAfter = Math.max(eventSeqs.length > 0 ? Math.max(...eventSeqs) : nextAfterSeq, nextAfterSeq);
|
|
6674
6960
|
if (singlePage && result.has_more === true && nextAfter > nextAfterSeq) {
|
|
6675
6961
|
continuationAfterSeq = nextAfter;
|
|
@@ -6681,10 +6967,12 @@ var MessageDeliveryEngine = class {
|
|
|
6681
6967
|
client._clientLog.warn(`group event gap fill reached max_pages=${maxPages} group=${groupId} after_seq=${nextAfterSeq}`);
|
|
6682
6968
|
}
|
|
6683
6969
|
} catch (exc) {
|
|
6970
|
+
failed = true;
|
|
6684
6971
|
client._clientLog.warn(`group event gap-fill failed:${String(exc)}`);
|
|
6685
6972
|
} finally {
|
|
6686
6973
|
client._gapFillDone.delete(dedupKey);
|
|
6687
6974
|
this.runtime.delivery.setGapFillActive(false);
|
|
6975
|
+
if (!client._rpcPipeline) this.syncStopped(failed ? "aborted" : "pull_drained");
|
|
6688
6976
|
if (singlePage && continuationAfterSeq > afterSeq) {
|
|
6689
6977
|
this.enqueueOnlineUnreadEventHint({
|
|
6690
6978
|
group_id: groupId,
|
|
@@ -7919,7 +8207,7 @@ var MessageDeliveryEngine = class {
|
|
|
7919
8207
|
if (event === "message.recalled") {
|
|
7920
8208
|
const published = await client._withPullResponseProcessing(
|
|
7921
8209
|
ns,
|
|
7922
|
-
() => this.publishMessageRecallTombstone(seq2, payload)
|
|
8210
|
+
() => this.publishMessageRecallTombstone(seq2, payload, source)
|
|
7923
8211
|
);
|
|
7924
8212
|
this.ensurePullOperationCurrent();
|
|
7925
8213
|
return published;
|
|
@@ -7941,7 +8229,7 @@ var MessageDeliveryEngine = class {
|
|
|
7941
8229
|
if (event === "message.recalled") {
|
|
7942
8230
|
const published = await client._withPullResponseProcessing(
|
|
7943
8231
|
ns,
|
|
7944
|
-
() => this.publishMessageRecallTombstone(seqNum, payload)
|
|
8232
|
+
() => this.publishMessageRecallTombstone(seqNum, payload, source)
|
|
7945
8233
|
);
|
|
7946
8234
|
this.ensurePullOperationCurrent();
|
|
7947
8235
|
this.markPublishedSeq(ns, seqNum);
|
|
@@ -16301,9 +16589,13 @@ var RpcPipeline = class {
|
|
|
16301
16589
|
throw new Error("pull invalidated");
|
|
16302
16590
|
}
|
|
16303
16591
|
if (!key) {
|
|
16592
|
+
this.runtime.client._delivery?.onPullStarted?.("");
|
|
16304
16593
|
const releasePullWork = this.reservePullWork();
|
|
16305
16594
|
try {
|
|
16306
16595
|
return await this.executePullOperation(operation, background);
|
|
16596
|
+
} catch (error) {
|
|
16597
|
+
this.runtime.client._delivery?.onPullAborted?.();
|
|
16598
|
+
throw error;
|
|
16307
16599
|
} finally {
|
|
16308
16600
|
releasePullWork();
|
|
16309
16601
|
}
|
|
@@ -16428,6 +16720,7 @@ var RpcPipeline = class {
|
|
|
16428
16720
|
const job = takeRunnable(state.foreground) ?? takeRunnable(state.background);
|
|
16429
16721
|
if (!job) return;
|
|
16430
16722
|
state.active = job;
|
|
16723
|
+
this.runtime.client._delivery?.onPullStarted?.(job.namespace);
|
|
16431
16724
|
if (job.timer) clearTimeout(job.timer);
|
|
16432
16725
|
job.pullingStartedAt = Date.now();
|
|
16433
16726
|
job.timedOut = false;
|
|
@@ -16441,11 +16734,13 @@ var RpcPipeline = class {
|
|
|
16441
16734
|
return;
|
|
16442
16735
|
}
|
|
16443
16736
|
job.running = true;
|
|
16737
|
+
let failed = false;
|
|
16444
16738
|
void this.executePullOperation(job.operation, job.background).then(
|
|
16445
16739
|
(value) => {
|
|
16446
16740
|
if (!job.timedOut && !job.invalidated) job.resolve(value);
|
|
16447
16741
|
},
|
|
16448
16742
|
(error) => {
|
|
16743
|
+
failed = true;
|
|
16449
16744
|
if (!job.timedOut && !job.invalidated) job.reject(error);
|
|
16450
16745
|
}
|
|
16451
16746
|
).finally(() => {
|
|
@@ -16457,6 +16752,7 @@ var RpcPipeline = class {
|
|
|
16457
16752
|
job.settledResolve?.();
|
|
16458
16753
|
job.settledResolve = null;
|
|
16459
16754
|
if (!job.invalidated) this.runtime.client._delivery?.onPullGateIdle?.(job.namespace);
|
|
16755
|
+
if (failed || job.invalidated) this.runtime.client._delivery?.onPullAborted?.();
|
|
16460
16756
|
this.runtime.client._delivery?.onPullWorkSettled?.();
|
|
16461
16757
|
});
|
|
16462
16758
|
}
|
|
@@ -24407,7 +24703,7 @@ var V2E2EECoordinator = class {
|
|
|
24407
24703
|
let plaintext = null;
|
|
24408
24704
|
const retryStatus = {};
|
|
24409
24705
|
try {
|
|
24410
|
-
plaintext = await client._decryptV2Message(entry.msg, false, true, true, true, retryStatus);
|
|
24706
|
+
plaintext = await client._decryptV2Message(entry.msg, false, true, true, true, retryStatus, false, "pending_retry");
|
|
24411
24707
|
} catch (exc) {
|
|
24412
24708
|
if (!generationCurrent()) return;
|
|
24413
24709
|
client._clientLog.warn(`V2 sender IK pending retry raised: key=${key} err=${String(formatE2EEError(exc))}`);
|
|
@@ -24434,9 +24730,9 @@ var V2E2EECoordinator = class {
|
|
|
24434
24730
|
if (entry.groupId) {
|
|
24435
24731
|
plaintext = normalizeGroupMentionMode(plaintext, entry.msg, entry.msg.envelope_json);
|
|
24436
24732
|
plaintext.group_id = entry.groupId;
|
|
24437
|
-
await client._publishPulledMessage("group.message_created", `group:${entry.groupId}`, seq2, plaintext);
|
|
24733
|
+
await client._publishPulledMessage("group.message_created", `group:${entry.groupId}`, seq2, plaintext, false, "pending_retry");
|
|
24438
24734
|
} else {
|
|
24439
|
-
await client._publishPulledMessage("message.received", `p2p:${client._aid ?? ""}`, seq2, plaintext);
|
|
24735
|
+
await client._publishPulledMessage("message.received", `p2p:${client._aid ?? ""}`, seq2, plaintext, false, "pending_retry");
|
|
24440
24736
|
}
|
|
24441
24737
|
client._clientLog.debug(`V2 sender IK pending retry delivered: key=${key}`);
|
|
24442
24738
|
}
|
|
@@ -24513,9 +24809,9 @@ var V2E2EECoordinator = class {
|
|
|
24513
24809
|
let plaintext = null;
|
|
24514
24810
|
if (String(msg.version ?? "") === "v1") {
|
|
24515
24811
|
const legacy = isJsonObject(msg.legacy_v1) ? msg.legacy_v1 : {};
|
|
24516
|
-
const payload = legacy.payload;
|
|
24812
|
+
const payload = legacy.payload !== void 0 ? legacy.payload : msg.payload;
|
|
24517
24813
|
const payloadType = isJsonObject(payload) ? String(payload.type ?? "").trim() : "";
|
|
24518
|
-
if (payload !== void 0 && payload !== null && !["e2ee.encrypted", "e2ee.group_encrypted"].includes(payloadType)) {
|
|
24814
|
+
if (payload !== void 0 && payload !== null && !["e2ee.encrypted", "e2ee.group_encrypted", "e2ee.p2p_encrypted"].includes(payloadType)) {
|
|
24519
24815
|
plaintext = {
|
|
24520
24816
|
message_id: String(msg.message_id ?? ""),
|
|
24521
24817
|
from: String(msg.from_aid ?? ""),
|
|
@@ -24527,6 +24823,9 @@ var V2E2EECoordinator = class {
|
|
|
24527
24823
|
encrypted: false
|
|
24528
24824
|
};
|
|
24529
24825
|
attachGatewayProximity(plaintext, msg);
|
|
24826
|
+
} else if (isJsonObject(payload) && ["e2ee.p2p_encrypted", "e2ee.encrypted"].includes(payloadType)) {
|
|
24827
|
+
msg = { ...msg, envelope_json: JSON.stringify(payload) };
|
|
24828
|
+
plaintext = await client._decryptV2Message(msg, false, !history, true, true, void 0, false, source);
|
|
24530
24829
|
}
|
|
24531
24830
|
} else {
|
|
24532
24831
|
plaintext = source === "inline_push" ? await client._decryptV2Message(msg, false, false, false, false) : await client._decryptV2Message(msg, false);
|
|
@@ -24558,29 +24857,53 @@ var V2E2EECoordinator = class {
|
|
|
24558
24857
|
let plaintext = null;
|
|
24559
24858
|
if (String(msg.version ?? "") === "v1") {
|
|
24560
24859
|
const payload = msg.payload;
|
|
24860
|
+
const recall = typeof client._delivery?.recallEventFromGroupMessage === "function" ? client._delivery.recallEventFromGroupMessage(msg) : null;
|
|
24861
|
+
if (recall) {
|
|
24862
|
+
const recallPayload = {
|
|
24863
|
+
...recall,
|
|
24864
|
+
group_id: groupId,
|
|
24865
|
+
group_aid: groupAid,
|
|
24866
|
+
seq: seq2
|
|
24867
|
+
};
|
|
24868
|
+
if (publish) {
|
|
24869
|
+
if (orderedPublish) {
|
|
24870
|
+
await client._delivery.publishOrderedMessage(
|
|
24871
|
+
"group.message_recalled",
|
|
24872
|
+
`group:${groupId}`,
|
|
24873
|
+
seq2,
|
|
24874
|
+
recallPayload,
|
|
24875
|
+
source
|
|
24876
|
+
);
|
|
24877
|
+
} else {
|
|
24878
|
+
await client._publishAppEvent("group.message_recalled", recallPayload, source);
|
|
24879
|
+
}
|
|
24880
|
+
}
|
|
24881
|
+
return recallPayload;
|
|
24882
|
+
}
|
|
24561
24883
|
if (payload === void 0 || payload === null) {
|
|
24562
24884
|
if (history) return this.historyDecryptFailure(msg, "legacy payload is missing");
|
|
24563
24885
|
client._clientLog.warn(`Group Tail \u7F3A\u5C11 payload \u7684 V1 \u884C\u5DF2\u8DF3\u8FC7\uFF0C\u8FDE\u7EED\u6027\u8BC1\u660E\u4ECD\u4FDD\u7559: group=${groupId}, seq=${seq2}`);
|
|
24564
24886
|
return null;
|
|
24565
24887
|
}
|
|
24566
|
-
|
|
24567
|
-
|
|
24568
|
-
|
|
24569
|
-
|
|
24888
|
+
const payloadType = isJsonObject(payload) ? String(payload.type ?? "").trim() : "";
|
|
24889
|
+
if (isJsonObject(payload) && ["e2ee.group_encrypted", "e2ee.p2p_encrypted", "e2ee.encrypted"].includes(payloadType)) {
|
|
24890
|
+
msg = { ...msg, envelope_json: JSON.stringify(payload) };
|
|
24891
|
+
plaintext = await client._decryptV2Message(msg, false, !history, true, true, void 0, false, source);
|
|
24892
|
+
} else {
|
|
24893
|
+
plaintext = {
|
|
24894
|
+
message_id: String(msg.message_id ?? ""),
|
|
24895
|
+
from: String(msg.from_aid ?? ""),
|
|
24896
|
+
group_id: groupId,
|
|
24897
|
+
group_aid: groupAid,
|
|
24898
|
+
seq: seq2,
|
|
24899
|
+
type: String(msg.type ?? ""),
|
|
24900
|
+
timestamp: msg.t_server,
|
|
24901
|
+
payload,
|
|
24902
|
+
encrypted: false
|
|
24903
|
+
};
|
|
24904
|
+
plaintext = normalizeGroupMentionMode(plaintext, msg, msg.envelope_json);
|
|
24905
|
+
attachGatewayProximity(plaintext, msg);
|
|
24570
24906
|
}
|
|
24571
|
-
plaintext = {
|
|
24572
|
-
message_id: String(msg.message_id ?? ""),
|
|
24573
|
-
from: String(msg.from_aid ?? ""),
|
|
24574
|
-
group_id: groupId,
|
|
24575
|
-
group_aid: groupAid,
|
|
24576
|
-
seq: seq2,
|
|
24577
|
-
type: String(msg.type ?? ""),
|
|
24578
|
-
timestamp: msg.t_server,
|
|
24579
|
-
payload,
|
|
24580
|
-
encrypted: false
|
|
24581
|
-
};
|
|
24582
|
-
plaintext = normalizeGroupMentionMode(plaintext, msg, msg.envelope_json);
|
|
24583
|
-
attachGatewayProximity(plaintext, msg);
|
|
24584
24907
|
} else {
|
|
24585
24908
|
plaintext = source === "inline_push" ? await client._decryptV2Message(msg, false, false, false, false) : await client._decryptV2Message(msg, false);
|
|
24586
24909
|
if (plaintext) {
|
|
@@ -24632,6 +24955,7 @@ var V2E2EECoordinator = class {
|
|
|
24632
24955
|
const afterSeq = strictWindowSeq(params2.after_seq ?? 0, "after_seq");
|
|
24633
24956
|
const limit = strictWindowLimit(params2.limit ?? V2_PULL_DEFAULT_PAGE_LIMIT);
|
|
24634
24957
|
const ns = client._aid ? `p2p:${client._aid}` : "";
|
|
24958
|
+
if (ns) client._delivery.onPullStarted?.(ns);
|
|
24635
24959
|
const result = await client._callRawV2Rpc("message.v2.pull", { window_mode: "tail", after_seq: afterSeq, limit, _rpc_foreground: true });
|
|
24636
24960
|
const floor = Number(result.retention_floor_seq ?? 0);
|
|
24637
24961
|
const previous = ns ? client._seqTracker.getSyncState(ns) : null;
|
|
@@ -24654,6 +24978,17 @@ var V2E2EECoordinator = class {
|
|
|
24654
24978
|
}
|
|
24655
24979
|
const ack = ns ? client._seqTracker.getContiguousSeq(ns) : 0;
|
|
24656
24980
|
if (previous && ack > previous.ack) await this.ackV2(ack);
|
|
24981
|
+
if (ns) client._delivery.onPullPage?.(
|
|
24982
|
+
ns,
|
|
24983
|
+
decoded.length,
|
|
24984
|
+
result.has_more === true,
|
|
24985
|
+
page.head,
|
|
24986
|
+
typeof result.remaining === "number" && Number.isSafeInteger(result.remaining) && result.remaining >= 0 ? result.remaining : null,
|
|
24987
|
+
page.messages.length,
|
|
24988
|
+
ack,
|
|
24989
|
+
page.head
|
|
24990
|
+
);
|
|
24991
|
+
client._delivery.onPullWorkSettled?.();
|
|
24657
24992
|
return { ...result, messages: decoded, raw_count: page.messages.length };
|
|
24658
24993
|
}
|
|
24659
24994
|
async historyV2Internal(params2) {
|
|
@@ -24668,10 +25003,24 @@ var V2E2EECoordinator = class {
|
|
|
24668
25003
|
}
|
|
24669
25004
|
return { ...result, messages: decoded };
|
|
24670
25005
|
}
|
|
25006
|
+
async runPullWithLifecycle(ns, operation) {
|
|
25007
|
+
if (ns) this.client._delivery.onPullStarted?.(ns);
|
|
25008
|
+
try {
|
|
25009
|
+
return await operation();
|
|
25010
|
+
} catch (error) {
|
|
25011
|
+
this.client._delivery.onPullAborted?.();
|
|
25012
|
+
throw error;
|
|
25013
|
+
}
|
|
25014
|
+
}
|
|
24671
25015
|
async pullV2(afterSeq = 0, limit = 50, opts) {
|
|
25016
|
+
const ns = this.client._aid ? `p2p:${this.client._aid}` : "";
|
|
25017
|
+
return await this.runPullWithLifecycle(ns, () => this.pullV2Impl(afterSeq, limit, opts));
|
|
25018
|
+
}
|
|
25019
|
+
async pullV2Impl(afterSeq = 0, limit = 50, opts) {
|
|
24672
25020
|
const client = this.client;
|
|
24673
25021
|
await client._ensureV2SessionReady("message.pull");
|
|
24674
25022
|
const ns = client._aid ? `p2p:${client._aid}` : "";
|
|
25023
|
+
if (ns) client._delivery.onPullStarted?.(ns);
|
|
24675
25024
|
if (opts?.windowMode === "tail") {
|
|
24676
25025
|
if (!opts.gateLocked) {
|
|
24677
25026
|
const key = pullGateKeyForClient(client, "message.v2.pull", {
|
|
@@ -24679,7 +25028,7 @@ var V2E2EECoordinator = class {
|
|
|
24679
25028
|
after_seq: afterSeq,
|
|
24680
25029
|
limit
|
|
24681
25030
|
}, `${ns}|tail|after=${afterSeq}|limit=${limit}`);
|
|
24682
|
-
return await client._runPullSerialized(key, () => this.
|
|
25031
|
+
return await client._runPullSerialized(key, () => this.pullV2Impl(afterSeq, limit, {
|
|
24683
25032
|
...opts ?? {},
|
|
24684
25033
|
gateLocked: true
|
|
24685
25034
|
}), false);
|
|
@@ -24693,7 +25042,7 @@ var V2E2EECoordinator = class {
|
|
|
24693
25042
|
force: opts?.force === true,
|
|
24694
25043
|
limit
|
|
24695
25044
|
}, `${ns}|forward|after=${afterSeq}|force=${String(Boolean(opts?.force))}|limit=${limit}`);
|
|
24696
|
-
return await client._runPullSerialized(key, () => this.
|
|
25045
|
+
return await client._runPullSerialized(key, () => this.pullV2Impl(afterSeq, limit, {
|
|
24697
25046
|
...opts ?? {},
|
|
24698
25047
|
gateLocked: true
|
|
24699
25048
|
}), true);
|
|
@@ -24750,15 +25099,16 @@ var V2E2EECoordinator = class {
|
|
|
24750
25099
|
const pageMaxSeq = seqs.length > 0 ? Math.max(...seqs) : nextAfterSeq;
|
|
24751
25100
|
const deferredKeyFetches = /* @__PURE__ */ new Map();
|
|
24752
25101
|
let blockedSeq = 0;
|
|
25102
|
+
const pageDecryptedBefore = decrypted.length;
|
|
24753
25103
|
for (const msg of messages) {
|
|
24754
25104
|
const seq2 = Number(msg.seq ?? 0);
|
|
24755
25105
|
if (!Number.isFinite(seq2) || seq2 <= 0) continue;
|
|
24756
25106
|
const version = String(msg.version ?? "v2");
|
|
24757
25107
|
if (version === "v1") {
|
|
24758
25108
|
const legacy = isJsonObject(msg.legacy_v1) ? msg.legacy_v1 : {};
|
|
24759
|
-
const legacyPayload = legacy.payload;
|
|
25109
|
+
const legacyPayload = legacy.payload !== void 0 ? legacy.payload : msg.payload;
|
|
24760
25110
|
const payloadType = isJsonObject(legacyPayload) ? String(legacyPayload.type ?? "").trim() : "";
|
|
24761
|
-
if (legacyPayload !== void 0 && legacyPayload !== null &&
|
|
25111
|
+
if (legacyPayload !== void 0 && legacyPayload !== null && !["e2ee.encrypted", "e2ee.group_encrypted", "e2ee.p2p_encrypted"].includes(payloadType)) {
|
|
24762
25112
|
const v1Msg = {
|
|
24763
25113
|
message_id: String(msg.message_id ?? ""),
|
|
24764
25114
|
from: String(msg.from_aid ?? ""),
|
|
@@ -24774,6 +25124,30 @@ var V2E2EECoordinator = class {
|
|
|
24774
25124
|
if (ns) await client._publishPulledMessage(appEvent.event, ns, seq2, appEvent.payload, false);
|
|
24775
25125
|
else await client._publishAppEvent(appEvent.event, appEvent.payload, "pull");
|
|
24776
25126
|
decrypted.push(v1Msg);
|
|
25127
|
+
} else if (isJsonObject(legacyPayload) && ["e2ee.p2p_encrypted", "e2ee.encrypted"].includes(payloadType)) {
|
|
25128
|
+
const deferStatus2 = {};
|
|
25129
|
+
const plaintext2 = await client._decryptV2Message(
|
|
25130
|
+
{ ...msg, envelope_json: JSON.stringify(legacyPayload) },
|
|
25131
|
+
true,
|
|
25132
|
+
true,
|
|
25133
|
+
true,
|
|
25134
|
+
true,
|
|
25135
|
+
deferStatus2,
|
|
25136
|
+
true,
|
|
25137
|
+
"pull"
|
|
25138
|
+
);
|
|
25139
|
+
if (deferStatus2.deferred) {
|
|
25140
|
+
blockedSeq = blockedSeq > 0 ? Math.min(blockedSeq, seq2) : seq2;
|
|
25141
|
+
if (deferStatus2.fromAid) {
|
|
25142
|
+
const key = `${deferStatus2.fromAid}\0${deferStatus2.senderDeviceId ?? ""}\0${deferStatus2.groupId ?? ""}`;
|
|
25143
|
+
deferredKeyFetches.set(key, { fromAid: deferStatus2.fromAid, senderDeviceId: deferStatus2.senderDeviceId ?? "", groupId: deferStatus2.groupId ?? "" });
|
|
25144
|
+
}
|
|
25145
|
+
}
|
|
25146
|
+
if (plaintext2) {
|
|
25147
|
+
if (ns) await client._publishPulledMessage("message.received", ns, seq2, plaintext2, false);
|
|
25148
|
+
else await client._publishAppEvent("message.received", plaintext2, "pull");
|
|
25149
|
+
decrypted.push(plaintext2);
|
|
25150
|
+
}
|
|
24777
25151
|
} else {
|
|
24778
25152
|
client._clientLog.debug(`message.v2.pull skipping V1 envelope seq=${seq2} payload_type=${payloadType || "<none>"} (V1 E2EE removed)`);
|
|
24779
25153
|
}
|
|
@@ -24788,7 +25162,7 @@ var V2E2EECoordinator = class {
|
|
|
24788
25162
|
client._v2Session.trackOldSPKMaxSeq(msgSpkId, seq2);
|
|
24789
25163
|
}
|
|
24790
25164
|
const deferStatus = {};
|
|
24791
|
-
const plaintext = await client._decryptV2Message(msg, true, true, true, true, deferStatus, true);
|
|
25165
|
+
const plaintext = await client._decryptV2Message(msg, true, true, true, true, deferStatus, true, "pull");
|
|
24792
25166
|
if (deferStatus.deferred) {
|
|
24793
25167
|
blockedSeq = blockedSeq > 0 ? Math.min(blockedSeq, seq2) : seq2;
|
|
24794
25168
|
}
|
|
@@ -24860,7 +25234,7 @@ var V2E2EECoordinator = class {
|
|
|
24860
25234
|
if (ackNeeded) {
|
|
24861
25235
|
this.recordForwardAck(ns, ackSeq);
|
|
24862
25236
|
const nextAfter2 = Math.max(pageMaxSeq, nextAfterSeq);
|
|
24863
|
-
const canContinuePage = messages.length > 0 && nextAfter2 > nextAfterSeq;
|
|
25237
|
+
const canContinuePage = blockedSeq <= 0 && messages.length > 0 && nextAfter2 > nextAfterSeq;
|
|
24864
25238
|
if (canContinuePage) {
|
|
24865
25239
|
pendingAckSeq = Math.max(pendingAckSeq, ackSeq);
|
|
24866
25240
|
lastAutoAckSeq = Math.max(lastAutoAckSeq, ackSeq);
|
|
@@ -24870,6 +25244,16 @@ var V2E2EECoordinator = class {
|
|
|
24870
25244
|
}
|
|
24871
25245
|
}
|
|
24872
25246
|
}
|
|
25247
|
+
if (ns) client._delivery.onPullPage?.(
|
|
25248
|
+
ns,
|
|
25249
|
+
decrypted.length - pageDecryptedBefore,
|
|
25250
|
+
hasMore,
|
|
25251
|
+
pageMaxSeq,
|
|
25252
|
+
typeof result.remaining === "number" && Number.isSafeInteger(result.remaining) && result.remaining >= 0 ? result.remaining : null,
|
|
25253
|
+
messages.length,
|
|
25254
|
+
client._seqTracker.getContiguousSeq(ns),
|
|
25255
|
+
pageMaxSeq
|
|
25256
|
+
);
|
|
24873
25257
|
const nextAfter = Math.max(pageMaxSeq, nextAfterSeq);
|
|
24874
25258
|
const rawCount = messages.length;
|
|
24875
25259
|
if (blockedSeq > 0) break;
|
|
@@ -24904,6 +25288,7 @@ var V2E2EECoordinator = class {
|
|
|
24904
25288
|
pendingAckSeq = 0;
|
|
24905
25289
|
}
|
|
24906
25290
|
}
|
|
25291
|
+
client._delivery.onPullWorkSettled?.();
|
|
24907
25292
|
return decrypted;
|
|
24908
25293
|
}
|
|
24909
25294
|
async confirmForwardP2PAck(upToSeq, inlineGeneration) {
|
|
@@ -25041,6 +25426,11 @@ var V2E2EECoordinator = class {
|
|
|
25041
25426
|
const afterSeq = strictWindowSeq(params2.after_seq ?? 0, "after_seq");
|
|
25042
25427
|
const limit = strictWindowLimit(params2.limit ?? V2_PULL_DEFAULT_PAGE_LIMIT);
|
|
25043
25428
|
const ns = `group:${groupId}`;
|
|
25429
|
+
const cursorParams = isJsonObject(params2._group_cursor_params) ? params2._group_cursor_params : params2;
|
|
25430
|
+
const requestDeviceId = String(cursorParams.device_id ?? "").trim();
|
|
25431
|
+
const requestSlotId = String(cursorParams.slot_id ?? "").trim();
|
|
25432
|
+
const ownsCursor = (!requestDeviceId || requestDeviceId === String(client._deviceId ?? "")) && (!requestSlotId || requestSlotId === String(client._slotId ?? ""));
|
|
25433
|
+
if (ownsCursor) client._delivery.onPullStarted?.(ns);
|
|
25044
25434
|
const result = await client._callRawV2Rpc("group.v2.pull", withExplicitGroupAid({
|
|
25045
25435
|
group_id: groupId,
|
|
25046
25436
|
window_mode: "tail",
|
|
@@ -25070,6 +25460,17 @@ var V2E2EECoordinator = class {
|
|
|
25070
25460
|
}
|
|
25071
25461
|
const ack = client._seqTracker.getContiguousSeq(ns);
|
|
25072
25462
|
if (ack > previous.ack) await this.ackGroupV2(groupId, ack, groupAid);
|
|
25463
|
+
if (ownsCursor) client._delivery.onPullPage?.(
|
|
25464
|
+
ns,
|
|
25465
|
+
decoded.length,
|
|
25466
|
+
result.has_more === true,
|
|
25467
|
+
page.head,
|
|
25468
|
+
typeof result.remaining === "number" && Number.isSafeInteger(result.remaining) && result.remaining >= 0 ? result.remaining : null,
|
|
25469
|
+
page.messages.length,
|
|
25470
|
+
ack,
|
|
25471
|
+
page.head
|
|
25472
|
+
);
|
|
25473
|
+
client._delivery.onPullWorkSettled?.();
|
|
25073
25474
|
return { ...result, messages: decoded, raw_count: page.messages.length };
|
|
25074
25475
|
}
|
|
25075
25476
|
async historyGroupV2Internal(params2) {
|
|
@@ -25102,6 +25503,13 @@ var V2E2EECoordinator = class {
|
|
|
25102
25503
|
});
|
|
25103
25504
|
}
|
|
25104
25505
|
async pullGroupV2(groupId, afterSeq = 0, limit = 50, opts) {
|
|
25506
|
+
const lifecycleNs = `group:${String(groupId ?? "").trim()}`;
|
|
25507
|
+
if (opts?.ownsCursor === false) {
|
|
25508
|
+
return await this.pullGroupV2Impl(groupId, afterSeq, limit, opts);
|
|
25509
|
+
}
|
|
25510
|
+
return await this.runPullWithLifecycle(lifecycleNs, () => this.pullGroupV2Impl(groupId, afterSeq, limit, opts));
|
|
25511
|
+
}
|
|
25512
|
+
async pullGroupV2Impl(groupId, afterSeq = 0, limit = 50, opts) {
|
|
25105
25513
|
const client = this.client;
|
|
25106
25514
|
await client._ensureV2SessionReady("group.pull");
|
|
25107
25515
|
const gid = String(groupId ?? "").trim();
|
|
@@ -25117,12 +25525,13 @@ var V2E2EECoordinator = class {
|
|
|
25117
25525
|
limit,
|
|
25118
25526
|
_group_cursor_params: opts?.cursorParams
|
|
25119
25527
|
}, `${ns}|tail|after=${afterSeq}|limit=${limit}`);
|
|
25120
|
-
return await client._runPullSerialized(key, () => this.
|
|
25528
|
+
return await client._runPullSerialized(key, () => this.pullGroupV2Impl(gid, afterSeq, limit, {
|
|
25121
25529
|
...opts ?? {},
|
|
25122
25530
|
gateLocked: true
|
|
25123
25531
|
}), false);
|
|
25124
25532
|
}
|
|
25125
25533
|
const result = await this.pullGroupV2TailInternal({
|
|
25534
|
+
...opts?.cursorParams ?? {},
|
|
25126
25535
|
group_id: String(opts.wireGroupId ?? gid),
|
|
25127
25536
|
group_aid: groupAid || void 0,
|
|
25128
25537
|
window_mode: "tail",
|
|
@@ -25139,7 +25548,7 @@ var V2E2EECoordinator = class {
|
|
|
25139
25548
|
limit,
|
|
25140
25549
|
_group_cursor_params: opts?.cursorParams
|
|
25141
25550
|
}, `${ns}|forward|after=${afterSeq}|force=${String(Boolean(opts?.force))}|limit=${limit}`);
|
|
25142
|
-
return await client._runPullSerialized(key, () => this.
|
|
25551
|
+
return await client._runPullSerialized(key, () => this.pullGroupV2Impl(gid, afterSeq, limit, {
|
|
25143
25552
|
...opts ?? {},
|
|
25144
25553
|
gateLocked: true
|
|
25145
25554
|
}), true);
|
|
@@ -25148,6 +25557,7 @@ var V2E2EECoordinator = class {
|
|
|
25148
25557
|
const wireGroupId = String(opts?.wireGroupId ?? groupId ?? "").trim() || gid;
|
|
25149
25558
|
const cursorParams = opts?.cursorParams ?? {};
|
|
25150
25559
|
const ownsCursor = opts?.ownsCursor !== false;
|
|
25560
|
+
if (ownsCursor) client._delivery.onPullStarted?.(ns);
|
|
25151
25561
|
let pullGateKey = ownsCursor ? pullGateKeyForClient(client, "group.v2.pull", {
|
|
25152
25562
|
group_id: gid,
|
|
25153
25563
|
after_seq: afterSeq,
|
|
@@ -25208,26 +25618,28 @@ var V2E2EECoordinator = class {
|
|
|
25208
25618
|
const pageMaxSeq = seqs.length > 0 ? Math.max(...seqs) : nextAfterSeq;
|
|
25209
25619
|
const deferredKeyFetches = /* @__PURE__ */ new Map();
|
|
25210
25620
|
let blockedSeq = 0;
|
|
25621
|
+
const pageDecryptedBefore = decrypted.length;
|
|
25211
25622
|
for (const msg of messages) {
|
|
25212
25623
|
const seq2 = Number(msg.seq ?? 0);
|
|
25213
25624
|
if (!Number.isFinite(seq2) || seq2 <= 0) continue;
|
|
25214
25625
|
const version = String(msg.version ?? "v2");
|
|
25215
25626
|
if (version === "v1") {
|
|
25216
|
-
const
|
|
25627
|
+
const legacy = isJsonObject(msg.legacy_v1) ? msg.legacy_v1 : {};
|
|
25628
|
+
const payload = msg.payload !== void 0 ? msg.payload : legacy.payload;
|
|
25217
25629
|
const payloadObj = isJsonObject(payload) ? payload : null;
|
|
25218
|
-
if (client._delivery.recallEventFromGroupMessage(msg)) {
|
|
25630
|
+
if (typeof client._delivery?.recallEventFromGroupMessage === "function" && client._delivery.recallEventFromGroupMessage(msg)) {
|
|
25219
25631
|
await client._delivery.publishGroupRecallTombstone(gid, seq2, {
|
|
25220
25632
|
...msg,
|
|
25221
25633
|
group_id: gid,
|
|
25222
25634
|
group_aid: eventGroupAid
|
|
25223
|
-
});
|
|
25635
|
+
}, "pull");
|
|
25224
25636
|
client._markPublishedSeq(ns, seq2);
|
|
25225
25637
|
client._clientLog.debug(`group.v2.pull recall tombstone delivered: group=${gid}, seq=${seq2}`);
|
|
25226
25638
|
continue;
|
|
25227
25639
|
}
|
|
25228
25640
|
if (payloadObj) {
|
|
25229
25641
|
const payloadType = String(payloadObj.type ?? "").trim();
|
|
25230
|
-
if (payloadType !== "e2ee.encrypted" && payloadType !== "e2ee.group_encrypted") {
|
|
25642
|
+
if (payloadType !== "e2ee.encrypted" && payloadType !== "e2ee.group_encrypted" && payloadType !== "e2ee.p2p_encrypted") {
|
|
25231
25643
|
let v1Msg = {
|
|
25232
25644
|
message_id: String(msg.message_id ?? ""),
|
|
25233
25645
|
from: String(msg.from_aid ?? ""),
|
|
@@ -25263,6 +25675,32 @@ var V2E2EECoordinator = class {
|
|
|
25263
25675
|
decrypted.push(v1Msg);
|
|
25264
25676
|
continue;
|
|
25265
25677
|
}
|
|
25678
|
+
if (payloadObj && ["e2ee.group_encrypted", "e2ee.p2p_encrypted", "e2ee.encrypted"].includes(String(payloadObj.type ?? "").trim())) {
|
|
25679
|
+
const deferStatus2 = {};
|
|
25680
|
+
const plaintext2 = await client._decryptV2Message(
|
|
25681
|
+
{ ...msg, envelope_json: JSON.stringify(payloadObj) },
|
|
25682
|
+
true,
|
|
25683
|
+
true,
|
|
25684
|
+
true,
|
|
25685
|
+
true,
|
|
25686
|
+
deferStatus2,
|
|
25687
|
+
true,
|
|
25688
|
+
"pull"
|
|
25689
|
+
);
|
|
25690
|
+
if (deferStatus2.deferred) {
|
|
25691
|
+
blockedSeq = blockedSeq > 0 ? Math.min(blockedSeq, seq2) : seq2;
|
|
25692
|
+
if (deferStatus2.fromAid) {
|
|
25693
|
+
const key = `${deferStatus2.fromAid}\0${deferStatus2.senderDeviceId ?? ""}\0${deferStatus2.groupId ?? ""}`;
|
|
25694
|
+
deferredKeyFetches.set(key, { fromAid: deferStatus2.fromAid, senderDeviceId: deferStatus2.senderDeviceId ?? "", groupId: deferStatus2.groupId ?? "" });
|
|
25695
|
+
}
|
|
25696
|
+
}
|
|
25697
|
+
if (plaintext2) {
|
|
25698
|
+
plaintext2.group_id = gid;
|
|
25699
|
+
plaintext2.group_aid = eventGroupAid;
|
|
25700
|
+
await client._publishPulledMessage("group.message_created", ns, seq2, plaintext2, false);
|
|
25701
|
+
decrypted.push(plaintext2);
|
|
25702
|
+
}
|
|
25703
|
+
}
|
|
25266
25704
|
client._clientLog.debug(`group.v2.pull skipping V1 envelope group=${gid} seq=${seq2} payload_type=${payloadObj ? String(payloadObj.type ?? "") : "<none>"} (V1 E2EE removed)`);
|
|
25267
25705
|
continue;
|
|
25268
25706
|
}
|
|
@@ -25271,7 +25709,7 @@ var V2E2EECoordinator = class {
|
|
|
25271
25709
|
continue;
|
|
25272
25710
|
}
|
|
25273
25711
|
const deferStatus = {};
|
|
25274
|
-
let plaintext = await client._decryptV2Message(msg, true, true, true, true, deferStatus, true);
|
|
25712
|
+
let plaintext = await client._decryptV2Message(msg, true, true, true, true, deferStatus, true, "pull");
|
|
25275
25713
|
if (deferStatus.deferred) {
|
|
25276
25714
|
blockedSeq = blockedSeq > 0 ? Math.min(blockedSeq, seq2) : seq2;
|
|
25277
25715
|
}
|
|
@@ -25343,6 +25781,16 @@ var V2E2EECoordinator = class {
|
|
|
25343
25781
|
for (const fetch2 of deferredKeyFetches.values()) {
|
|
25344
25782
|
this.scheduleSenderIKFetch(fetch2.fromAid, fetch2.senderDeviceId, fetch2.groupId);
|
|
25345
25783
|
}
|
|
25784
|
+
client._delivery.onPullPage?.(
|
|
25785
|
+
ns,
|
|
25786
|
+
decrypted.length - pageDecryptedBefore,
|
|
25787
|
+
hasMore,
|
|
25788
|
+
pageMaxSeq,
|
|
25789
|
+
typeof result.remaining === "number" && Number.isSafeInteger(result.remaining) && result.remaining >= 0 ? result.remaining : null,
|
|
25790
|
+
messages.length,
|
|
25791
|
+
client._seqTracker.getContiguousSeq(ns),
|
|
25792
|
+
pageMaxSeq
|
|
25793
|
+
);
|
|
25346
25794
|
if (ownsCursor && parsedCursorCurrentSeq !== null && cursorCurrentSeq > ackSeq) {
|
|
25347
25795
|
this.recordForwardCursor(ns, cursorCurrentSeq, ackSeq);
|
|
25348
25796
|
}
|
|
@@ -25351,7 +25799,7 @@ var V2E2EECoordinator = class {
|
|
|
25351
25799
|
if (ackNeeded) {
|
|
25352
25800
|
this.recordForwardAck(ns, ackSeq);
|
|
25353
25801
|
const nextAfter2 = Math.max(pageMaxSeq, nextAfterSeq);
|
|
25354
|
-
const canContinuePage = messages.length > 0 && nextAfter2 > nextAfterSeq && ownsCursor;
|
|
25802
|
+
const canContinuePage = blockedSeq <= 0 && messages.length > 0 && nextAfter2 > nextAfterSeq && ownsCursor;
|
|
25355
25803
|
if (canContinuePage) {
|
|
25356
25804
|
pendingAckSeq = Math.max(pendingAckSeq, ackSeq);
|
|
25357
25805
|
lastAutoAckSeq = Math.max(lastAutoAckSeq, ackSeq);
|
|
@@ -25397,6 +25845,7 @@ var V2E2EECoordinator = class {
|
|
|
25397
25845
|
pendingAckSeq = 0;
|
|
25398
25846
|
}
|
|
25399
25847
|
}
|
|
25848
|
+
client._delivery.onPullWorkSettled?.();
|
|
25400
25849
|
return decrypted;
|
|
25401
25850
|
}
|
|
25402
25851
|
async confirmForwardGroupAck(groupId, upToSeq, groupAid) {
|
|
@@ -25906,7 +26355,7 @@ var V2E2EECoordinator = class {
|
|
|
25906
26355
|
}
|
|
25907
26356
|
async decryptV2PushMessage(data) {
|
|
25908
26357
|
if (!isJsonObject(data)) return null;
|
|
25909
|
-
return await this.client._decryptV2Message(data);
|
|
26358
|
+
return await this.client._decryptV2Message(data, false, false, false, false, void 0, false, "inline_push");
|
|
25910
26359
|
}
|
|
25911
26360
|
async buildV2P2PEnvelope(opts) {
|
|
25912
26361
|
const client = this.client;
|
|
@@ -29952,6 +30401,53 @@ var _AUNClient = class _AUNClient {
|
|
|
29952
30401
|
await this._agentMdManager.upload(await this._agentMdManager.readContent(target) ?? buildDefaultAgentMd(target));
|
|
29953
30402
|
return true;
|
|
29954
30403
|
}
|
|
30404
|
+
async _checkIdentityAdmissionAfterConnect() {
|
|
30405
|
+
const aid = String(this._aid ?? this._currentAid?.aid ?? "").trim();
|
|
30406
|
+
if (!aid) return;
|
|
30407
|
+
try {
|
|
30408
|
+
const checked = await this._agentMdManager.check(aid);
|
|
30409
|
+
if (!checked.remote_found) {
|
|
30410
|
+
const content = await this._agentMdManager.readContent(aid) ?? buildDefaultAgentMd(aid);
|
|
30411
|
+
await this._agentMdManager.upload(content);
|
|
30412
|
+
}
|
|
30413
|
+
} catch (exc) {
|
|
30414
|
+
this._clientLog.warn(`post-connect agent.md check failed: ${String(exc)}`);
|
|
30415
|
+
}
|
|
30416
|
+
const store = this._aidStore;
|
|
30417
|
+
if (!store) return;
|
|
30418
|
+
let listed;
|
|
30419
|
+
try {
|
|
30420
|
+
listed = await this.call("group.list_my", {});
|
|
30421
|
+
} catch (exc) {
|
|
30422
|
+
this._clientLog.warn(`post-connect group identity check failed: ${String(exc)}`);
|
|
30423
|
+
return;
|
|
30424
|
+
}
|
|
30425
|
+
const result = isJsonObject(listed) ? listed : {};
|
|
30426
|
+
const groups = Array.isArray(result.groups) ? result.groups : Array.isArray(result.items) ? result.items : [];
|
|
30427
|
+
for (const raw of groups) {
|
|
30428
|
+
if (!isJsonObject(raw)) continue;
|
|
30429
|
+
const role = String(raw.role ?? raw.my_role ?? "").trim().toLowerCase();
|
|
30430
|
+
if (role !== "owner") continue;
|
|
30431
|
+
const groupId = String(raw.group_id ?? raw.groupId ?? raw.group_aid ?? raw.groupAid ?? "").trim();
|
|
30432
|
+
const groupAid = String(raw.group_aid ?? raw.groupAid ?? groupId).trim();
|
|
30433
|
+
if (!groupId || !groupAid) continue;
|
|
30434
|
+
try {
|
|
30435
|
+
await this._runGroupIdentityOperation(groupId, async () => {
|
|
30436
|
+
const loaded = await store.load(groupAid);
|
|
30437
|
+
if (!loaded.ok || !loaded.data?.aid?.isPrivateKeyValid()) {
|
|
30438
|
+
await this.bindGroupAid({ group_id: groupId, group_aid: groupAid }, { aidStore: store });
|
|
30439
|
+
return;
|
|
30440
|
+
}
|
|
30441
|
+
const checked = await this._agentMdManager.check(groupAid);
|
|
30442
|
+
if (!checked.remote_found) {
|
|
30443
|
+
await this._uploadGroupAgentMd(store, groupAid, {}, {}, aid);
|
|
30444
|
+
}
|
|
30445
|
+
});
|
|
30446
|
+
} catch (exc) {
|
|
30447
|
+
this._clientLog.warn(`post-connect group identity check failed: group=${groupId} err=${String(exc)}`);
|
|
30448
|
+
}
|
|
30449
|
+
}
|
|
30450
|
+
}
|
|
29955
30451
|
async _runGroupIdentityOperation(groupId, operation) {
|
|
29956
30452
|
const aid = String(this._aid ?? this._currentAid?.aid ?? "").trim();
|
|
29957
30453
|
const dot = aid.indexOf(".");
|
|
@@ -30585,7 +31081,7 @@ var _AUNClient = class _AUNClient {
|
|
|
30585
31081
|
_markPublishedSeq(ns, seq2) {
|
|
30586
31082
|
this._delivery.markPublishedSeq(ns, seq2);
|
|
30587
31083
|
}
|
|
30588
|
-
async _publishAppEvent(event, payload, source = "", ns = "", batch) {
|
|
31084
|
+
async _publishAppEvent(event, payload, source = "direct", ns = "", batch) {
|
|
30589
31085
|
await this._delivery.publishAppEvent(event, payload, source, ns, batch);
|
|
30590
31086
|
}
|
|
30591
31087
|
_echoTimestamp() {
|
|
@@ -30983,6 +31479,7 @@ var _AUNClient = class _AUNClient {
|
|
|
30983
31479
|
if (backgroundSyncEnabled) {
|
|
30984
31480
|
this._safeAsync(this._fillP2pGap());
|
|
30985
31481
|
}
|
|
31482
|
+
this._safeAsync(this._checkIdentityAdmissionAfterConnect());
|
|
30986
31483
|
this._clientLog.debug(`_connectOnce exit: elapsed=${Date.now() - tStart}ms aid=${this._aid ?? "-"}`);
|
|
30987
31484
|
} catch (err) {
|
|
30988
31485
|
this._clientLog.debug(`_connectOnce exit (error): elapsed=${Date.now() - tStart}ms err=${err instanceof Error ? err.message : String(err)}`);
|
|
@@ -31869,7 +32366,7 @@ var _AUNClient = class _AUNClient {
|
|
|
31869
32366
|
* undecryptable 事件、成功消费后触发 SPK 轮换。inline Push 在游标提交和
|
|
31870
32367
|
* Head/正文绑定校验前调用本入口时必须显式关闭这些副作用。
|
|
31871
32368
|
*/
|
|
31872
|
-
async _decryptV2Message(msg, allowPending = true, emitUndecryptable = true, rotateKeys = true, observeAgentMd = true, deferStatus, deferKeyFetch = false) {
|
|
32369
|
+
async _decryptV2Message(msg, allowPending = true, emitUndecryptable = true, rotateKeys = true, observeAgentMd = true, deferStatus, deferKeyFetch = false, source = "pull") {
|
|
31873
32370
|
const session = this._v2Session;
|
|
31874
32371
|
if (!session) return null;
|
|
31875
32372
|
const envJson = msg.envelope_json;
|
|
@@ -31957,7 +32454,8 @@ var _AUNClient = class _AUNClient {
|
|
|
31957
32454
|
_decrypt_stage: "spk_lookup",
|
|
31958
32455
|
_envelope_type: String(envelope.type ?? ""),
|
|
31959
32456
|
_suite: String(envelope.suite ?? ""),
|
|
31960
|
-
_spk_id: spkId
|
|
32457
|
+
_spk_id: spkId,
|
|
32458
|
+
source
|
|
31961
32459
|
};
|
|
31962
32460
|
attachV2EnvelopeMetadata2(event, e2eeMeta);
|
|
31963
32461
|
this._dispatcher.enqueue(undecryptableEvent, event);
|
|
@@ -31998,7 +32496,8 @@ var _AUNClient = class _AUNClient {
|
|
|
31998
32496
|
_decrypt_error: "sender_ik_not_found",
|
|
31999
32497
|
_decrypt_stage: "sender_ik",
|
|
32000
32498
|
_envelope_type: String(envelope.type ?? ""),
|
|
32001
|
-
_suite: String(envelope.suite ?? "")
|
|
32499
|
+
_suite: String(envelope.suite ?? ""),
|
|
32500
|
+
source
|
|
32002
32501
|
};
|
|
32003
32502
|
attachV2EnvelopeMetadata2(event, e2eeMeta);
|
|
32004
32503
|
this._dispatcher.enqueue(undecryptableEvent, event);
|
|
@@ -32034,7 +32533,8 @@ var _AUNClient = class _AUNClient {
|
|
|
32034
32533
|
_decrypt_error: String(exc),
|
|
32035
32534
|
_decrypt_stage: "decrypt",
|
|
32036
32535
|
_envelope_type: String(envelope.type ?? ""),
|
|
32037
|
-
_suite: String(envelope.suite ?? "")
|
|
32536
|
+
_suite: String(envelope.suite ?? ""),
|
|
32537
|
+
source
|
|
32038
32538
|
};
|
|
32039
32539
|
attachV2EnvelopeMetadata2(event, e2eeMeta);
|
|
32040
32540
|
this._dispatcher.enqueue(undecryptableEvent, event);
|