@agentunion/fastaun-browser 0.4.11 → 0.4.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 +20 -0
- package/_packed_docs/CHANGELOG.md +20 -0
- package/_packed_docs/sdk/05-E2EE/345/212/240/345/257/206/351/200/232/344/277/241.md +4 -2
- package/_packed_docs/sdk/09-group-rpc-manual.md +82 -37
- package/_packed_docs/sdk/09-message-rpc-manual.md +50 -26
- package/_packed_docs/sdk/09-payload-reference.md +1 -1
- package/_packed_docs/sdk/09-storage-rpc-manual.md +12 -9
- package/dist/bundle.js +156 -8
- package/dist/client/delivery.d.ts +6 -0
- package/dist/client/delivery.d.ts.map +1 -1
- package/dist/client/delivery.js +99 -6
- package/dist/client/delivery.js.map +1 -1
- package/dist/client/rpc-pipeline.d.ts.map +1 -1
- package/dist/client/rpc-pipeline.js +2 -1
- package/dist/client/rpc-pipeline.js.map +1 -1
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +18 -0
- package/dist/client.js.map +1 -1
- package/dist/service-proxy.d.ts.map +1 -1
- package/dist/service-proxy.js +17 -2
- package/dist/service-proxy.js.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +1 -1
package/dist/bundle.js
CHANGED
|
@@ -454,7 +454,7 @@ var init_indexeddb_store = __esm({
|
|
|
454
454
|
});
|
|
455
455
|
|
|
456
456
|
// src/version.ts
|
|
457
|
-
var VERSION = "0.4.
|
|
457
|
+
var VERSION = "0.4.12";
|
|
458
458
|
|
|
459
459
|
// src/types.ts
|
|
460
460
|
var ConnectionState = /* @__PURE__ */ ((ConnectionState2) => {
|
|
@@ -3710,6 +3710,53 @@ var ClientRuntime = class {
|
|
|
3710
3710
|
var PUSHED_SEQS_LIMIT = 5e4;
|
|
3711
3711
|
var PENDING_ORDERED_LIMIT = 5e4;
|
|
3712
3712
|
var GROUP_RECALL_SEEN_LIMIT = 1e4;
|
|
3713
|
+
var APP_MESSAGE_ENVELOPE_KEYS = [
|
|
3714
|
+
"module_id",
|
|
3715
|
+
"message_id",
|
|
3716
|
+
"id",
|
|
3717
|
+
"seq",
|
|
3718
|
+
"msg_seq",
|
|
3719
|
+
"message_type",
|
|
3720
|
+
"type",
|
|
3721
|
+
"kind",
|
|
3722
|
+
"version",
|
|
3723
|
+
"from",
|
|
3724
|
+
"from_aid",
|
|
3725
|
+
"sender_aid",
|
|
3726
|
+
"to",
|
|
3727
|
+
"to_aid",
|
|
3728
|
+
"group_id",
|
|
3729
|
+
"timestamp",
|
|
3730
|
+
"created_at",
|
|
3731
|
+
"t_server",
|
|
3732
|
+
"encrypted",
|
|
3733
|
+
"status",
|
|
3734
|
+
"delivery_mode",
|
|
3735
|
+
"dispatch_mode",
|
|
3736
|
+
"dispatch",
|
|
3737
|
+
"device_id",
|
|
3738
|
+
"slot_id"
|
|
3739
|
+
];
|
|
3740
|
+
var APP_GROUP_EVENT_ENVELOPE_KEYS = [
|
|
3741
|
+
"module_id",
|
|
3742
|
+
"event_id",
|
|
3743
|
+
"event_seq",
|
|
3744
|
+
"seq",
|
|
3745
|
+
"event_type",
|
|
3746
|
+
"action",
|
|
3747
|
+
"group_id",
|
|
3748
|
+
"actor_aid",
|
|
3749
|
+
"sender_aid",
|
|
3750
|
+
"member_aid",
|
|
3751
|
+
"target_aid",
|
|
3752
|
+
"operator_aid",
|
|
3753
|
+
"created_at",
|
|
3754
|
+
"timestamp",
|
|
3755
|
+
"t_server",
|
|
3756
|
+
"status",
|
|
3757
|
+
"device_id",
|
|
3758
|
+
"slot_id"
|
|
3759
|
+
];
|
|
3713
3760
|
function formatDeliveryError(error) {
|
|
3714
3761
|
return error instanceof Error ? error : String(error);
|
|
3715
3762
|
}
|
|
@@ -3792,8 +3839,46 @@ var MessageDeliveryEngine = class {
|
|
|
3792
3839
|
return result;
|
|
3793
3840
|
}
|
|
3794
3841
|
normalizePublishedMessagePayload(event, payload) {
|
|
3795
|
-
if (
|
|
3796
|
-
|
|
3842
|
+
if (this.isInstanceScopedMessageEvent(event)) {
|
|
3843
|
+
return this.attachAppMessageEnvelope(this.stripInternalSenderDeviceFields(this.attachCurrentInstanceContext(payload)));
|
|
3844
|
+
}
|
|
3845
|
+
if (this.isGroupScopedEvent(event)) {
|
|
3846
|
+
return this.attachAppGroupEventEnvelope(this.attachCurrentInstanceContext(payload));
|
|
3847
|
+
}
|
|
3848
|
+
return payload;
|
|
3849
|
+
}
|
|
3850
|
+
appMessageEnvelope(payload) {
|
|
3851
|
+
if (!isJsonObject(payload)) return {};
|
|
3852
|
+
const message = payload;
|
|
3853
|
+
const envelope = {};
|
|
3854
|
+
for (const key of APP_MESSAGE_ENVELOPE_KEYS) {
|
|
3855
|
+
if (Object.prototype.hasOwnProperty.call(message, key)) envelope[key] = message[key];
|
|
3856
|
+
}
|
|
3857
|
+
return envelope;
|
|
3858
|
+
}
|
|
3859
|
+
isGroupScopedEvent(event) {
|
|
3860
|
+
return event === "group.changed";
|
|
3861
|
+
}
|
|
3862
|
+
appGroupEventEnvelope(payload) {
|
|
3863
|
+
if (!isJsonObject(payload)) return {};
|
|
3864
|
+
const groupEvent = payload;
|
|
3865
|
+
const envelope = {};
|
|
3866
|
+
for (const key of APP_GROUP_EVENT_ENVELOPE_KEYS) {
|
|
3867
|
+
if (Object.prototype.hasOwnProperty.call(groupEvent, key)) envelope[key] = groupEvent[key];
|
|
3868
|
+
}
|
|
3869
|
+
return envelope;
|
|
3870
|
+
}
|
|
3871
|
+
attachAppMessageEnvelope(payload) {
|
|
3872
|
+
if (!isJsonObject(payload)) return payload;
|
|
3873
|
+
const result = { ...payload };
|
|
3874
|
+
result.envelope = this.appMessageEnvelope(result);
|
|
3875
|
+
return result;
|
|
3876
|
+
}
|
|
3877
|
+
attachAppGroupEventEnvelope(payload) {
|
|
3878
|
+
if (!isJsonObject(payload)) return payload;
|
|
3879
|
+
const result = { ...payload };
|
|
3880
|
+
result.envelope = this.appGroupEventEnvelope(result);
|
|
3881
|
+
return result;
|
|
3797
3882
|
}
|
|
3798
3883
|
stripInternalSenderDeviceFields(payload) {
|
|
3799
3884
|
if (!isJsonObject(payload)) return payload;
|
|
@@ -3813,6 +3898,11 @@ var MessageDeliveryEngine = class {
|
|
|
3813
3898
|
const payloadType = String(payload.type ?? payload.kind ?? "").trim();
|
|
3814
3899
|
if (msgType !== "message.recalled" && payloadType !== "message.recalled") return null;
|
|
3815
3900
|
const event = { ...payload };
|
|
3901
|
+
for (const key of APP_MESSAGE_ENVELOPE_KEYS) {
|
|
3902
|
+
if (Object.prototype.hasOwnProperty.call(msg, key) && !(key in event)) {
|
|
3903
|
+
event[key] = msg[key];
|
|
3904
|
+
}
|
|
3905
|
+
}
|
|
3816
3906
|
const rawIds = event.message_ids;
|
|
3817
3907
|
let messageIds = Array.isArray(rawIds) ? rawIds.map((item) => String(item ?? "").trim()).filter(Boolean) : [];
|
|
3818
3908
|
if (messageIds.length === 0) {
|
|
@@ -3831,7 +3921,10 @@ var MessageDeliveryEngine = class {
|
|
|
3831
3921
|
if (!("to" in event)) event.to = msg.to ?? msg.to_aid ?? "";
|
|
3832
3922
|
if (!("timestamp" in event)) event.timestamp = msg.timestamp ?? msg.t_server ?? event.recalled_at ?? 0;
|
|
3833
3923
|
if ("seq" in msg && !("seq" in event)) event.seq = msg.seq;
|
|
3834
|
-
if ("message_id" in msg
|
|
3924
|
+
if ("message_id" in msg) {
|
|
3925
|
+
event.message_id = msg.message_id;
|
|
3926
|
+
if (!("tombstone_message_id" in event)) event.tombstone_message_id = msg.message_id;
|
|
3927
|
+
}
|
|
3835
3928
|
if ("device_id" in msg && !("device_id" in event)) event.device_id = msg.device_id;
|
|
3836
3929
|
if ("slot_id" in msg && !("slot_id" in event)) event.slot_id = msg.slot_id;
|
|
3837
3930
|
return event;
|
|
@@ -3850,6 +3943,11 @@ var MessageDeliveryEngine = class {
|
|
|
3850
3943
|
const payloadType = String(payload.type ?? payload.kind ?? "").trim();
|
|
3851
3944
|
if (msgType !== "group.message_recalled" && payloadType !== "group.message_recalled") return null;
|
|
3852
3945
|
const event = { ...payload };
|
|
3946
|
+
for (const key of APP_MESSAGE_ENVELOPE_KEYS) {
|
|
3947
|
+
if (Object.prototype.hasOwnProperty.call(msg, key) && !(key in event)) {
|
|
3948
|
+
event[key] = msg[key];
|
|
3949
|
+
}
|
|
3950
|
+
}
|
|
3853
3951
|
const rawIds = event.message_ids;
|
|
3854
3952
|
let messageIds = Array.isArray(rawIds) ? rawIds.map((item) => String(item ?? "").trim()).filter(Boolean) : [];
|
|
3855
3953
|
if (messageIds.length === 0) {
|
|
@@ -3867,7 +3965,10 @@ var MessageDeliveryEngine = class {
|
|
|
3867
3965
|
if (!("group_id" in event)) event.group_id = msg.group_id ?? "";
|
|
3868
3966
|
if (!("timestamp" in event)) event.timestamp = msg.timestamp ?? msg.t_server ?? event.recalled_at ?? 0;
|
|
3869
3967
|
if ("seq" in msg) event.seq = msg.seq;
|
|
3870
|
-
if ("message_id" in msg
|
|
3968
|
+
if ("message_id" in msg) {
|
|
3969
|
+
event.message_id = msg.message_id;
|
|
3970
|
+
if (!("tombstone_message_id" in event)) event.tombstone_message_id = msg.message_id;
|
|
3971
|
+
}
|
|
3871
3972
|
return event;
|
|
3872
3973
|
}
|
|
3873
3974
|
groupRecallDedupKey(groupId, payload) {
|
|
@@ -4357,6 +4458,14 @@ var MessageDeliveryEngine = class {
|
|
|
4357
4458
|
return;
|
|
4358
4459
|
}
|
|
4359
4460
|
const ns = `group_event:${groupId}`;
|
|
4461
|
+
if (this.isSelfJoinGroupChanged(data)) {
|
|
4462
|
+
const contig = client._seqTracker.getContiguousSeq(ns);
|
|
4463
|
+
const maxSeen = client._seqTracker.getMaxSeenSeq(ns);
|
|
4464
|
+
if (contig === 0 && maxSeen === 0 && eventSeq > 1) {
|
|
4465
|
+
client._clientLog.debug(`group.changed self-join baseline: group=${groupId}, event_seq=${eventSeq}, baseline=${eventSeq - 1}`);
|
|
4466
|
+
client._seqTracker.forceContiguousSeq(ns, eventSeq - 1);
|
|
4467
|
+
}
|
|
4468
|
+
}
|
|
4360
4469
|
const contigBefore = client._seqTracker.getContiguousSeq(ns);
|
|
4361
4470
|
if (eventSeq <= contigBefore || client._pushedSeqs.get(ns)?.has(eventSeq)) {
|
|
4362
4471
|
client._clientLog.debug(`group.changed skipped duplicate/stale: group=${groupId}, event_seq=${eventSeq}, contiguous=${contigBefore}`);
|
|
@@ -4382,6 +4491,16 @@ var MessageDeliveryEngine = class {
|
|
|
4382
4491
|
client._safeAsync(this.fillGroupEventGap(groupId));
|
|
4383
4492
|
}
|
|
4384
4493
|
}
|
|
4494
|
+
isSelfJoinGroupChanged(data) {
|
|
4495
|
+
const action = String(data.action ?? "").trim();
|
|
4496
|
+
if (!["member_added", "joined", "join_approved", "invite_code_used"].includes(action)) return false;
|
|
4497
|
+
const selfAid = String(this.runtime.client._aid ?? "").trim();
|
|
4498
|
+
if (!selfAid) return false;
|
|
4499
|
+
const joinedAid = String(data.joined_aid ?? data.member_aid ?? data.aid ?? "").trim();
|
|
4500
|
+
if (joinedAid === selfAid) return true;
|
|
4501
|
+
const actorAid = String(data.actor_aid ?? "").trim();
|
|
4502
|
+
return !joinedAid && ["joined", "invite_code_used"].includes(action) && actorAid === selfAid;
|
|
4503
|
+
}
|
|
4385
4504
|
enqueueOnlineUnreadHint(data) {
|
|
4386
4505
|
const client = this.runtime.client;
|
|
4387
4506
|
const groupId = String(data.group_id ?? "").trim();
|
|
@@ -5482,7 +5601,8 @@ var RpcPipeline = class {
|
|
|
5482
5601
|
if (!client._instanceProtectedHeaders || !PROTECTED_HEADERS_METHODS.has(method)) {
|
|
5483
5602
|
return;
|
|
5484
5603
|
}
|
|
5485
|
-
const
|
|
5604
|
+
const existingValue = params.protected_headers ?? params.headers;
|
|
5605
|
+
const existing = isJsonObject(existingValue) ? existingValue : {};
|
|
5486
5606
|
params.protected_headers = { ...client._instanceProtectedHeaders, ...existing };
|
|
5487
5607
|
}
|
|
5488
5608
|
normalizeOutboundMessagePayload(params, method = "") {
|
|
@@ -16684,6 +16804,21 @@ var _AUNClient = class _AUNClient {
|
|
|
16684
16804
|
if (!this._sessionParams) {
|
|
16685
16805
|
throw new StateError("missing connect params for reconnect");
|
|
16686
16806
|
}
|
|
16807
|
+
{
|
|
16808
|
+
const identity = this._identity;
|
|
16809
|
+
if (identity) {
|
|
16810
|
+
const cachedToken = String(identity.access_token ?? "");
|
|
16811
|
+
const expiresAt = this._auth.getAccessTokenExpiry(identity);
|
|
16812
|
+
if (cachedToken && (expiresAt === null || expiresAt > Date.now() / 1e3 + 30)) {
|
|
16813
|
+
this._sessionParams.access_token = cachedToken;
|
|
16814
|
+
} else {
|
|
16815
|
+
this._clientLog.debug(`reconnect: cached token expired or missing for aid=${this._aid ?? ""}, clearing to trigger re-login`);
|
|
16816
|
+
this._sessionParams.access_token = "";
|
|
16817
|
+
}
|
|
16818
|
+
} else {
|
|
16819
|
+
this._sessionParams.access_token = "";
|
|
16820
|
+
}
|
|
16821
|
+
}
|
|
16687
16822
|
await this._connectOnce(this._sessionParams, true);
|
|
16688
16823
|
this._lastError = null;
|
|
16689
16824
|
this._lastErrorCode = null;
|
|
@@ -19249,6 +19384,8 @@ var ServiceProxyClient = class {
|
|
|
19249
19384
|
const stats = { connection_mode: mode, connections: 0, registered: 0, handled_requests: 0, wakeup_count: 0 };
|
|
19250
19385
|
try {
|
|
19251
19386
|
if (mode === "persistent") {
|
|
19387
|
+
const maxReconnectDelay = 6e4;
|
|
19388
|
+
let _delay = Math.max(0, opts.reconnectDelaySeconds ?? 1) * 1e3;
|
|
19252
19389
|
while (this._running) {
|
|
19253
19390
|
try {
|
|
19254
19391
|
await this._autoRegisterServicesWithGateway();
|
|
@@ -19261,10 +19398,21 @@ var ServiceProxyClient = class {
|
|
|
19261
19398
|
stats.connections = Number(stats.connections) + 1;
|
|
19262
19399
|
stats.registered = Number(result.registered ?? stats.registered);
|
|
19263
19400
|
stats.handled_requests = Number(stats.handled_requests) + Number(result.handled_requests ?? 0);
|
|
19401
|
+
_delay = Math.max(0, opts.reconnectDelaySeconds ?? 1) * 1e3;
|
|
19264
19402
|
} catch (exc) {
|
|
19265
19403
|
if (!this._running) break;
|
|
19266
|
-
|
|
19267
|
-
|
|
19404
|
+
if (exc instanceof AuthError) {
|
|
19405
|
+
this._logWarn(`persistent tunnel auth error, re-authenticating: ${formatError(exc)}`);
|
|
19406
|
+
try {
|
|
19407
|
+
await this._authenticateForAccessToken();
|
|
19408
|
+
} catch (reAuthExc) {
|
|
19409
|
+
this._logWarn(`re-authentication failed: ${formatError(reAuthExc)}`);
|
|
19410
|
+
}
|
|
19411
|
+
} else {
|
|
19412
|
+
this._logWarn(`persistent tunnel reconnect scheduled after error: ${formatError(exc)}`);
|
|
19413
|
+
}
|
|
19414
|
+
await sleep(_delay);
|
|
19415
|
+
_delay = Math.min(_delay * 2, maxReconnectDelay);
|
|
19268
19416
|
} finally {
|
|
19269
19417
|
this._activeTunnel?.close();
|
|
19270
19418
|
this._activeTunnel = null;
|
|
@@ -13,6 +13,11 @@ export declare class MessageDeliveryEngine {
|
|
|
13
13
|
isInstanceScopedMessageEvent(event: string): boolean;
|
|
14
14
|
attachCurrentInstanceContext(payload: EventPayload): EventPayload;
|
|
15
15
|
normalizePublishedMessagePayload(event: string, payload: EventPayload): EventPayload;
|
|
16
|
+
appMessageEnvelope(payload: EventPayload): JsonObject;
|
|
17
|
+
isGroupScopedEvent(event: string): boolean;
|
|
18
|
+
appGroupEventEnvelope(payload: EventPayload): JsonObject;
|
|
19
|
+
attachAppMessageEnvelope(payload: EventPayload): EventPayload;
|
|
20
|
+
attachAppGroupEventEnvelope(payload: EventPayload): EventPayload;
|
|
16
21
|
stripInternalSenderDeviceFields(payload: EventPayload): EventPayload;
|
|
17
22
|
recallEventFromMessage(message: EventPayload): JsonObject | null;
|
|
18
23
|
p2pAppEventForMessage(message: EventPayload): {
|
|
@@ -34,6 +39,7 @@ export declare class MessageDeliveryEngine {
|
|
|
34
39
|
fillGroupGap(groupId: string): Promise<void>;
|
|
35
40
|
fillGroupEventGap(groupId: string): Promise<void>;
|
|
36
41
|
handleGroupChangedEventSeq(data: JsonObject, groupId: string): Promise<void>;
|
|
42
|
+
isSelfJoinGroupChanged(data: JsonObject): boolean;
|
|
37
43
|
enqueueOnlineUnreadHint(data: JsonObject): void;
|
|
38
44
|
drainOnlineUnreadHints(): Promise<void>;
|
|
39
45
|
onRawGroupV2MessageCreated(data: EventPayload): Promise<void>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"delivery.d.ts","sourceRoot":"","sources":["../../src/client/delivery.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAEjD,OAAO,EAAgB,KAAK,UAAU,EAAkB,KAAK,OAAO,EAAE,KAAK,SAAS,EAAE,MAAM,aAAa,CAAC;AAC1G,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"delivery.d.ts","sourceRoot":"","sources":["../../src/client/delivery.ts"],"names":[],"mappings":"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"}
|
package/dist/client/delivery.js
CHANGED
|
@@ -4,6 +4,17 @@ import { isJsonObject } from '../types.js';
|
|
|
4
4
|
const PUSHED_SEQS_LIMIT = 50_000;
|
|
5
5
|
const PENDING_ORDERED_LIMIT = 50_000;
|
|
6
6
|
const GROUP_RECALL_SEEN_LIMIT = 10_000;
|
|
7
|
+
const APP_MESSAGE_ENVELOPE_KEYS = [
|
|
8
|
+
'module_id', 'message_id', 'id', 'seq', 'msg_seq', 'message_type', 'type', 'kind', 'version',
|
|
9
|
+
'from', 'from_aid', 'sender_aid', 'to', 'to_aid', 'group_id',
|
|
10
|
+
'timestamp', 'created_at', 't_server', 'encrypted', 'status', 'delivery_mode',
|
|
11
|
+
'dispatch_mode', 'dispatch', 'device_id', 'slot_id',
|
|
12
|
+
];
|
|
13
|
+
const APP_GROUP_EVENT_ENVELOPE_KEYS = [
|
|
14
|
+
'module_id', 'event_id', 'event_seq', 'seq', 'event_type', 'action', 'group_id',
|
|
15
|
+
'actor_aid', 'sender_aid', 'member_aid', 'target_aid', 'operator_aid',
|
|
16
|
+
'created_at', 'timestamp', 't_server', 'status', 'device_id', 'slot_id',
|
|
17
|
+
];
|
|
7
18
|
function formatDeliveryError(error) {
|
|
8
19
|
return error instanceof Error ? error : String(error);
|
|
9
20
|
}
|
|
@@ -95,9 +106,54 @@ export class MessageDeliveryEngine {
|
|
|
95
106
|
return result;
|
|
96
107
|
}
|
|
97
108
|
normalizePublishedMessagePayload(event, payload) {
|
|
98
|
-
if (
|
|
109
|
+
if (this.isInstanceScopedMessageEvent(event)) {
|
|
110
|
+
return this.attachAppMessageEnvelope(this.stripInternalSenderDeviceFields(this.attachCurrentInstanceContext(payload)));
|
|
111
|
+
}
|
|
112
|
+
if (this.isGroupScopedEvent(event)) {
|
|
113
|
+
return this.attachAppGroupEventEnvelope(this.attachCurrentInstanceContext(payload));
|
|
114
|
+
}
|
|
115
|
+
return payload;
|
|
116
|
+
}
|
|
117
|
+
appMessageEnvelope(payload) {
|
|
118
|
+
if (!isJsonObject(payload))
|
|
119
|
+
return {};
|
|
120
|
+
const message = payload;
|
|
121
|
+
const envelope = {};
|
|
122
|
+
for (const key of APP_MESSAGE_ENVELOPE_KEYS) {
|
|
123
|
+
if (Object.prototype.hasOwnProperty.call(message, key))
|
|
124
|
+
envelope[key] = message[key];
|
|
125
|
+
}
|
|
126
|
+
return envelope;
|
|
127
|
+
}
|
|
128
|
+
isGroupScopedEvent(event) {
|
|
129
|
+
return event === 'group.changed';
|
|
130
|
+
}
|
|
131
|
+
appGroupEventEnvelope(payload) {
|
|
132
|
+
if (!isJsonObject(payload))
|
|
133
|
+
return {};
|
|
134
|
+
const groupEvent = payload;
|
|
135
|
+
const envelope = {};
|
|
136
|
+
for (const key of APP_GROUP_EVENT_ENVELOPE_KEYS) {
|
|
137
|
+
if (Object.prototype.hasOwnProperty.call(groupEvent, key))
|
|
138
|
+
envelope[key] = groupEvent[key];
|
|
139
|
+
}
|
|
140
|
+
return envelope;
|
|
141
|
+
}
|
|
142
|
+
attachAppMessageEnvelope(payload) {
|
|
143
|
+
if (!isJsonObject(payload))
|
|
99
144
|
return payload;
|
|
100
|
-
|
|
145
|
+
const result = { ...payload };
|
|
146
|
+
// 兼容期保留顶层信封字段;下一个大版本 0.5.* 将移除这些顶层别名,请通过 envelope.* 访问。
|
|
147
|
+
result.envelope = this.appMessageEnvelope(result);
|
|
148
|
+
return result;
|
|
149
|
+
}
|
|
150
|
+
attachAppGroupEventEnvelope(payload) {
|
|
151
|
+
if (!isJsonObject(payload))
|
|
152
|
+
return payload;
|
|
153
|
+
const result = { ...payload };
|
|
154
|
+
// 兼容期保留顶层群事件信封字段;下一个大版本 0.5.* 将移除这些顶层别名,请通过 envelope.* 访问。
|
|
155
|
+
result.envelope = this.appGroupEventEnvelope(result);
|
|
156
|
+
return result;
|
|
101
157
|
}
|
|
102
158
|
stripInternalSenderDeviceFields(payload) {
|
|
103
159
|
if (!isJsonObject(payload))
|
|
@@ -120,6 +176,11 @@ export class MessageDeliveryEngine {
|
|
|
120
176
|
if (msgType !== 'message.recalled' && payloadType !== 'message.recalled')
|
|
121
177
|
return null;
|
|
122
178
|
const event = { ...payload };
|
|
179
|
+
for (const key of APP_MESSAGE_ENVELOPE_KEYS) {
|
|
180
|
+
if (Object.prototype.hasOwnProperty.call(msg, key) && !(key in event)) {
|
|
181
|
+
event[key] = msg[key];
|
|
182
|
+
}
|
|
183
|
+
}
|
|
123
184
|
const rawIds = event.message_ids;
|
|
124
185
|
let messageIds = Array.isArray(rawIds)
|
|
125
186
|
? rawIds.map((item) => String(item ?? '').trim()).filter(Boolean)
|
|
@@ -144,8 +205,11 @@ export class MessageDeliveryEngine {
|
|
|
144
205
|
event.timestamp = msg.timestamp ?? msg.t_server ?? event.recalled_at ?? 0;
|
|
145
206
|
if ('seq' in msg && !('seq' in event))
|
|
146
207
|
event.seq = msg.seq;
|
|
147
|
-
if ('message_id' in msg
|
|
148
|
-
event.
|
|
208
|
+
if ('message_id' in msg) {
|
|
209
|
+
event.message_id = msg.message_id;
|
|
210
|
+
if (!('tombstone_message_id' in event))
|
|
211
|
+
event.tombstone_message_id = msg.message_id;
|
|
212
|
+
}
|
|
149
213
|
if ('device_id' in msg && !('device_id' in event))
|
|
150
214
|
event.device_id = msg.device_id;
|
|
151
215
|
if ('slot_id' in msg && !('slot_id' in event))
|
|
@@ -169,6 +233,11 @@ export class MessageDeliveryEngine {
|
|
|
169
233
|
if (msgType !== 'group.message_recalled' && payloadType !== 'group.message_recalled')
|
|
170
234
|
return null;
|
|
171
235
|
const event = { ...payload };
|
|
236
|
+
for (const key of APP_MESSAGE_ENVELOPE_KEYS) {
|
|
237
|
+
if (Object.prototype.hasOwnProperty.call(msg, key) && !(key in event)) {
|
|
238
|
+
event[key] = msg[key];
|
|
239
|
+
}
|
|
240
|
+
}
|
|
172
241
|
const rawIds = event.message_ids;
|
|
173
242
|
let messageIds = Array.isArray(rawIds)
|
|
174
243
|
? rawIds.map((item) => String(item ?? '').trim()).filter(Boolean)
|
|
@@ -191,8 +260,11 @@ export class MessageDeliveryEngine {
|
|
|
191
260
|
event.timestamp = msg.timestamp ?? msg.t_server ?? event.recalled_at ?? 0;
|
|
192
261
|
if ('seq' in msg)
|
|
193
262
|
event.seq = msg.seq;
|
|
194
|
-
if ('message_id' in msg
|
|
195
|
-
event.
|
|
263
|
+
if ('message_id' in msg) {
|
|
264
|
+
event.message_id = msg.message_id;
|
|
265
|
+
if (!('tombstone_message_id' in event))
|
|
266
|
+
event.tombstone_message_id = msg.message_id;
|
|
267
|
+
}
|
|
196
268
|
return event;
|
|
197
269
|
}
|
|
198
270
|
groupRecallDedupKey(groupId, payload) {
|
|
@@ -740,6 +812,14 @@ export class MessageDeliveryEngine {
|
|
|
740
812
|
return;
|
|
741
813
|
}
|
|
742
814
|
const ns = `group_event:${groupId}`;
|
|
815
|
+
if (this.isSelfJoinGroupChanged(data)) {
|
|
816
|
+
const contig = client._seqTracker.getContiguousSeq(ns);
|
|
817
|
+
const maxSeen = client._seqTracker.getMaxSeenSeq(ns);
|
|
818
|
+
if (contig === 0 && maxSeen === 0 && eventSeq > 1) {
|
|
819
|
+
client._clientLog.debug(`group.changed self-join baseline: group=${groupId}, event_seq=${eventSeq}, baseline=${eventSeq - 1}`);
|
|
820
|
+
client._seqTracker.forceContiguousSeq(ns, eventSeq - 1);
|
|
821
|
+
}
|
|
822
|
+
}
|
|
743
823
|
const contigBefore = client._seqTracker.getContiguousSeq(ns);
|
|
744
824
|
if (eventSeq <= contigBefore || client._pushedSeqs.get(ns)?.has(eventSeq)) {
|
|
745
825
|
client._clientLog.debug(`group.changed skipped duplicate/stale: group=${groupId}, event_seq=${eventSeq}, contiguous=${contigBefore}`);
|
|
@@ -766,6 +846,19 @@ export class MessageDeliveryEngine {
|
|
|
766
846
|
client._safeAsync(this.fillGroupEventGap(groupId));
|
|
767
847
|
}
|
|
768
848
|
}
|
|
849
|
+
isSelfJoinGroupChanged(data) {
|
|
850
|
+
const action = String(data.action ?? '').trim();
|
|
851
|
+
if (!['member_added', 'joined', 'join_approved', 'invite_code_used'].includes(action))
|
|
852
|
+
return false;
|
|
853
|
+
const selfAid = String(this.runtime.client._aid ?? '').trim();
|
|
854
|
+
if (!selfAid)
|
|
855
|
+
return false;
|
|
856
|
+
const joinedAid = String(data.joined_aid ?? data.member_aid ?? data.aid ?? '').trim();
|
|
857
|
+
if (joinedAid === selfAid)
|
|
858
|
+
return true;
|
|
859
|
+
const actorAid = String(data.actor_aid ?? '').trim();
|
|
860
|
+
return !joinedAid && ['joined', 'invite_code_used'].includes(action) && actorAid === selfAid;
|
|
861
|
+
}
|
|
769
862
|
enqueueOnlineUnreadHint(data) {
|
|
770
863
|
const client = this.runtime.client;
|
|
771
864
|
const groupId = String(data.group_id ?? '').trim();
|