@agentunion/fastaun 0.5.15 → 0.5.17
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 +311 -271
- package/_packed_docs/CHANGELOG.md +311 -271
- package/_packed_docs/INDEX.md +8 -2
- package/_packed_docs/KITE_DOCS_GUIDE.md +2 -0
- package/_packed_docs/agent.md/SCHEMA.md +7 -0
- package/_packed_docs/aun/345/210/206/345/270/203/345/274/217/346/265/213/350/257/225/350/277/220/350/241/214/346/214/207/345/215/227.md +1178 -1178
- package/_packed_docs/aun/346/265/213/350/257/225/350/277/220/350/241/214/346/214/207/345/215/227.md +1213 -1213
- package/_packed_docs/protocol/06-/346/234/215/345/212/241/345/215/217/350/256/256.md +58 -43
- package/_packed_docs/protocol/10-Group-/345/255/220/345/215/217/350/256/256.md +80 -17
- package/_packed_docs/sdk/06-API/346/211/213/345/206/214.md +27 -6
- package/_packed_docs/sdk/07-/351/224/231/350/257/257/345/244/204/347/220/206.md +7 -4
- package/_packed_docs/sdk/09-group-rpc-manual.md +167 -35
- package/_packed_docs/sdk/09-message-rpc-manual.md +72 -42
- package/_packed_docs/sdk/09-storage-rpc-manual.md +23 -14
- package/_packed_docs/sdk/AUN_DOCS_GUIDE.md +16 -12
- package/_packed_docs/sdk/INDEX.md +12 -12
- package/dist/agent-md-schema.js +6 -0
- package/dist/agent-md-schema.js.map +1 -1
- package/dist/agent-md.d.ts +3 -0
- package/dist/agent-md.js +9 -1
- package/dist/agent-md.js.map +1 -1
- package/dist/client/delivery.d.ts +17 -0
- package/dist/client/delivery.js +140 -12
- package/dist/client/delivery.js.map +1 -1
- package/dist/client/group-state.d.ts +4 -0
- package/dist/client/group-state.js +63 -0
- package/dist/client/group-state.js.map +1 -1
- package/dist/client/rpc-pipeline.js +22 -5
- package/dist/client/rpc-pipeline.js.map +1 -1
- package/dist/client/v2-e2ee.d.ts +10 -1
- package/dist/client/v2-e2ee.js +187 -36
- package/dist/client/v2-e2ee.js.map +1 -1
- package/dist/client.js +56 -13
- package/dist/client.js.map +1 -1
- package/dist/facades.d.ts +5 -0
- package/dist/facades.js +5 -0
- package/dist/facades.js.map +1 -1
- package/dist/group-fs.js +7 -5
- package/dist/group-fs.js.map +1 -1
- package/dist/storage/vfs.d.ts +1 -0
- package/dist/storage/vfs.js +61 -6
- package/dist/storage/vfs.js.map +1 -1
- package/dist/tools/cross-sdk-agent.js +31 -1
- package/dist/tools/cross-sdk-agent.js.map +1 -1
- package/dist/types.d.ts +16 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +8 -8
package/dist/client/delivery.js
CHANGED
|
@@ -7,6 +7,7 @@ const PUSHED_SEQS_LIMIT = 50_000;
|
|
|
7
7
|
const PENDING_ORDERED_LIMIT = 50_000;
|
|
8
8
|
const MESSAGE_RECALL_SEEN_LIMIT = 10_000;
|
|
9
9
|
const GROUP_RECALL_SEEN_LIMIT = 10_000;
|
|
10
|
+
const VOLATILE_SEEN_LIMIT = 10_000;
|
|
10
11
|
const SEQ_TRACKER_PERSIST_FLUSH_DELAY_MS = 200;
|
|
11
12
|
const DELIVERY_CHANGED_MESSAGE_EVENTS = new Set([
|
|
12
13
|
'message.received',
|
|
@@ -35,7 +36,7 @@ const APP_SEND_ENVELOPE_METHODS = new Set([
|
|
|
35
36
|
const APP_GROUP_EVENT_ENVELOPE_KEYS = [
|
|
36
37
|
'module_id', 'event_id', 'event_seq', 'seq', 'event_type', 'action', 'group_id',
|
|
37
38
|
'actor_aid', 'sender_aid', 'member_aid', 'target_aid', 'operator_aid',
|
|
38
|
-
'created_at', 'timestamp', 't_server', 'status', 'device_id',
|
|
39
|
+
'created_at', 'timestamp', 't_server', 'status', 'device_id',
|
|
39
40
|
];
|
|
40
41
|
function isPromiseLike(value) {
|
|
41
42
|
return Boolean(value && typeof value.then === 'function');
|
|
@@ -87,6 +88,10 @@ export class MessageDeliveryEngine {
|
|
|
87
88
|
deliveryChangedGeneration = 0;
|
|
88
89
|
syncRun = 0;
|
|
89
90
|
syncSessions = null;
|
|
91
|
+
volatileContext = '';
|
|
92
|
+
volatileCursor = '';
|
|
93
|
+
volatileSeenMessages = new Map();
|
|
94
|
+
volatileInFlightMessages = new Set();
|
|
90
95
|
// 同一实例的 tracker 写入必须串行,避免旧的延迟 flush 覆盖新的 Forward 提交。
|
|
91
96
|
seqTrackerWriteChain = Promise.resolve();
|
|
92
97
|
constructor(runtime) {
|
|
@@ -157,9 +162,13 @@ export class MessageDeliveryEngine {
|
|
|
157
162
|
throw new Error(`${method} response must be an object`);
|
|
158
163
|
}
|
|
159
164
|
const client = this.runtime.client;
|
|
165
|
+
const response = result;
|
|
166
|
+
const volatileMessages = method === 'message.pull' ? this.volatileMessages(response.messages) : [];
|
|
167
|
+
if (volatileMessages.length > 0) {
|
|
168
|
+
await this.publishPlainVolatileMessages(volatileMessages, 'pull', true);
|
|
169
|
+
}
|
|
160
170
|
this.ensurePullOperationCurrent(ns);
|
|
161
171
|
this.syncStarted(ns);
|
|
162
|
-
const response = result;
|
|
163
172
|
const messages = deduplicatePlainForwardPageMessages(response.messages, afterSeq);
|
|
164
173
|
const coordinator = this.forwardCoordinator();
|
|
165
174
|
const pageContigBefore = client._seqTracker.getContiguousSeq(ns);
|
|
@@ -279,8 +288,121 @@ export class MessageDeliveryEngine {
|
|
|
279
288
|
hasMore: typeof response.has_more === 'boolean' ? response.has_more : undefined,
|
|
280
289
|
currentSeq: client._seqTracker.getContiguousSeq(ns),
|
|
281
290
|
});
|
|
291
|
+
response.messages = (Array.isArray(response.messages) ? response.messages : [])
|
|
292
|
+
.map((message) => this.stripInternalSenderDeviceFields(message));
|
|
282
293
|
return { rawCount: messages.length, publishedCount };
|
|
283
294
|
}
|
|
295
|
+
isVolatileMessage(message) {
|
|
296
|
+
return isJsonObject(message)
|
|
297
|
+
&& String(message.storage ?? '') === 'volatile';
|
|
298
|
+
}
|
|
299
|
+
volatileMessages(value) {
|
|
300
|
+
if (!Array.isArray(value))
|
|
301
|
+
return [];
|
|
302
|
+
return value.filter((item) => this.isVolatileMessage(item)).map((item) => ({ ...item }));
|
|
303
|
+
}
|
|
304
|
+
ensureVolatileContext() {
|
|
305
|
+
const client = this.runtime.client;
|
|
306
|
+
const context = JSON.stringify([client._aid ?? '', client._deviceId ?? '', client._slotId ?? '']);
|
|
307
|
+
if (context === this.volatileContext)
|
|
308
|
+
return;
|
|
309
|
+
this.volatileContext = context;
|
|
310
|
+
this.volatileCursor = '';
|
|
311
|
+
this.volatileSeenMessages.clear();
|
|
312
|
+
this.volatileInFlightMessages.clear();
|
|
313
|
+
}
|
|
314
|
+
volatilePullCursor() {
|
|
315
|
+
this.ensureVolatileContext();
|
|
316
|
+
return this.volatileCursor;
|
|
317
|
+
}
|
|
318
|
+
resetVolatilePullCursor() {
|
|
319
|
+
this.ensureVolatileContext();
|
|
320
|
+
this.volatileCursor = '';
|
|
321
|
+
}
|
|
322
|
+
volatileSeenKey(message) {
|
|
323
|
+
const messageId = String(message.message_id ?? '').trim();
|
|
324
|
+
const sender = String(message.from_aid ?? message.from ?? '').trim();
|
|
325
|
+
const cursor = String(message.volatile_cursor ?? '').trim();
|
|
326
|
+
return `${sender}|${messageId || cursor}`;
|
|
327
|
+
}
|
|
328
|
+
isVolatileSeen(message) {
|
|
329
|
+
this.ensureVolatileContext();
|
|
330
|
+
const now = Date.now();
|
|
331
|
+
for (const [key, expiresAt] of this.volatileSeenMessages) {
|
|
332
|
+
if (expiresAt <= now)
|
|
333
|
+
this.volatileSeenMessages.delete(key);
|
|
334
|
+
}
|
|
335
|
+
return this.volatileSeenMessages.has(this.volatileSeenKey(message));
|
|
336
|
+
}
|
|
337
|
+
markVolatileSeen(message) {
|
|
338
|
+
this.ensureVolatileContext();
|
|
339
|
+
const now = Date.now();
|
|
340
|
+
const expiresAt = Math.max(now + 60_000, Number(message.expires_at ?? now + 1_800_000) || now + 1_800_000);
|
|
341
|
+
this.volatileSeenMessages.set(this.volatileSeenKey(message), expiresAt);
|
|
342
|
+
while (this.volatileSeenMessages.size > VOLATILE_SEEN_LIMIT) {
|
|
343
|
+
const first = this.volatileSeenMessages.keys().next().value;
|
|
344
|
+
if (first === undefined)
|
|
345
|
+
break;
|
|
346
|
+
this.volatileSeenMessages.delete(first);
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
beginVolatileDelivery(message) {
|
|
350
|
+
if (this.isVolatileSeen(message))
|
|
351
|
+
return 'seen';
|
|
352
|
+
const key = this.volatileSeenKey(message);
|
|
353
|
+
if (this.volatileInFlightMessages.has(key))
|
|
354
|
+
return 'inflight';
|
|
355
|
+
this.volatileInFlightMessages.add(key);
|
|
356
|
+
return 'claimed';
|
|
357
|
+
}
|
|
358
|
+
finishVolatileDelivery(message) {
|
|
359
|
+
this.ensureVolatileContext();
|
|
360
|
+
this.volatileInFlightMessages.delete(this.volatileSeenKey(message));
|
|
361
|
+
}
|
|
362
|
+
publicVolatileMessage(message) {
|
|
363
|
+
const result = this.stripInternalSenderDeviceFields(message);
|
|
364
|
+
delete result.seq;
|
|
365
|
+
return result;
|
|
366
|
+
}
|
|
367
|
+
async ackVolatileMessages(messages, v2, advanceCursor) {
|
|
368
|
+
const cursors = [...new Set(messages
|
|
369
|
+
.map((message) => String(message.volatile_cursor ?? '').trim())
|
|
370
|
+
.filter(Boolean))];
|
|
371
|
+
if (cursors.length === 0)
|
|
372
|
+
return undefined;
|
|
373
|
+
const result = await this.runtime.client._callRawV2Rpc(v2 ? 'message.v2.ack' : 'message.ack', { volatile_cursors: cursors, _rpc_background: true });
|
|
374
|
+
if (advanceCursor) {
|
|
375
|
+
this.ensureVolatileContext();
|
|
376
|
+
this.volatileCursor = cursors[cursors.length - 1] ?? '';
|
|
377
|
+
}
|
|
378
|
+
return result;
|
|
379
|
+
}
|
|
380
|
+
async publishPlainVolatileMessages(messages, source, advanceCursor) {
|
|
381
|
+
const processed = [];
|
|
382
|
+
for (const rawMessage of messages) {
|
|
383
|
+
const message = this.publicVolatileMessage(rawMessage);
|
|
384
|
+
const claim = this.beginVolatileDelivery(message);
|
|
385
|
+
if (claim === 'seen') {
|
|
386
|
+
processed.push(rawMessage);
|
|
387
|
+
continue;
|
|
388
|
+
}
|
|
389
|
+
if (claim === 'inflight')
|
|
390
|
+
continue;
|
|
391
|
+
try {
|
|
392
|
+
const appEvent = this.p2pAppEventForMessage(message);
|
|
393
|
+
await this.runtime.client._publishAppEvent(appEvent.event, appEvent.payload, source);
|
|
394
|
+
this.markVolatileSeen(message);
|
|
395
|
+
}
|
|
396
|
+
finally {
|
|
397
|
+
this.finishVolatileDelivery(message);
|
|
398
|
+
}
|
|
399
|
+
processed.push(rawMessage);
|
|
400
|
+
}
|
|
401
|
+
if (processed.length > 0) {
|
|
402
|
+
await this.ackVolatileMessages(processed, false, advanceCursor);
|
|
403
|
+
}
|
|
404
|
+
return processed.map((message) => this.publicVolatileMessage(message));
|
|
405
|
+
}
|
|
284
406
|
resetInlineAckState() {
|
|
285
407
|
this.syncStopped('aborted');
|
|
286
408
|
this.deliveryChangedGeneration += 1;
|
|
@@ -714,9 +836,6 @@ export class MessageDeliveryEngine {
|
|
|
714
836
|
if (!('device_id' in result)) {
|
|
715
837
|
result.device_id = client._deviceId;
|
|
716
838
|
}
|
|
717
|
-
if (!('slot_id' in result)) {
|
|
718
|
-
result.slot_id = client._slotId;
|
|
719
|
-
}
|
|
720
839
|
return result;
|
|
721
840
|
}
|
|
722
841
|
normalizePublishedMessagePayload(event, payload, source = 'direct') {
|
|
@@ -728,7 +847,7 @@ export class MessageDeliveryEngine {
|
|
|
728
847
|
normalized = this.attachAppMessageEnvelope(this.stripInternalSenderDeviceFields(this.attachCurrentInstanceContext(payload)));
|
|
729
848
|
}
|
|
730
849
|
else if (this.isGroupScopedEvent(event)) {
|
|
731
|
-
normalized = this.attachAppGroupEventEnvelope(this.attachCurrentInstanceContext(payload));
|
|
850
|
+
normalized = this.attachAppGroupEventEnvelope(this.stripInternalSenderDeviceFields(this.attachCurrentInstanceContext(payload)));
|
|
732
851
|
}
|
|
733
852
|
else {
|
|
734
853
|
normalized = payload;
|
|
@@ -901,7 +1020,7 @@ export class MessageDeliveryEngine {
|
|
|
901
1020
|
const authoritativeSource = hasGroupMentionModeField(serverSource) ? serverSource : out;
|
|
902
1021
|
out = normalizeGroupMentionMode(out, authoritativeSource);
|
|
903
1022
|
}
|
|
904
|
-
return out;
|
|
1023
|
+
return this.stripInternalSenderDeviceFields(out);
|
|
905
1024
|
}
|
|
906
1025
|
attachAppGroupEventEnvelope(payload) {
|
|
907
1026
|
if (!isJsonObject(payload))
|
|
@@ -915,10 +1034,13 @@ export class MessageDeliveryEngine {
|
|
|
915
1034
|
if (!isJsonObject(payload))
|
|
916
1035
|
return payload;
|
|
917
1036
|
const result = { ...payload };
|
|
918
|
-
delete result.sender_device_id;
|
|
919
1037
|
delete result._sender_device_id;
|
|
920
1038
|
delete result.from_device_id;
|
|
921
1039
|
delete result.from_device;
|
|
1040
|
+
delete result.slot_id;
|
|
1041
|
+
delete result.sender_slot_id;
|
|
1042
|
+
delete result.target_slot_id;
|
|
1043
|
+
delete result.owner_slot_id;
|
|
922
1044
|
return result;
|
|
923
1045
|
}
|
|
924
1046
|
recallEventFromMessage(message) {
|
|
@@ -973,9 +1095,7 @@ export class MessageDeliveryEngine {
|
|
|
973
1095
|
}
|
|
974
1096
|
if ('device_id' in msg && !('device_id' in event))
|
|
975
1097
|
event.device_id = msg.device_id;
|
|
976
|
-
|
|
977
|
-
event.slot_id = msg.slot_id;
|
|
978
|
-
return event;
|
|
1098
|
+
return this.stripInternalSenderDeviceFields(event);
|
|
979
1099
|
}
|
|
980
1100
|
p2pAppEventForMessage(message) {
|
|
981
1101
|
const recall = this.recallEventFromMessage(message);
|
|
@@ -1082,7 +1202,7 @@ export class MessageDeliveryEngine {
|
|
|
1082
1202
|
if (!('tombstone_message_id' in event))
|
|
1083
1203
|
event.tombstone_message_id = msg.message_id;
|
|
1084
1204
|
}
|
|
1085
|
-
return event;
|
|
1205
|
+
return this.stripInternalSenderDeviceFields(event);
|
|
1086
1206
|
}
|
|
1087
1207
|
groupRecallDedupKey(groupId, payload) {
|
|
1088
1208
|
// 群撤回去重键:group_id + 原始消息标识。
|
|
@@ -1460,6 +1580,10 @@ export class MessageDeliveryEngine {
|
|
|
1460
1580
|
client._clientLog.debug(`P2P push filtered by instance: message_id=${String(msg.message_id ?? '')}, seq=${String(msg.seq ?? '')}, target_device=${String(msg.device_id ?? '')}, target_slot=${String(msg.slot_id ?? '')}, local_device=${client._deviceId}, local_slot=${client._slotId}`);
|
|
1461
1581
|
return;
|
|
1462
1582
|
}
|
|
1583
|
+
if (this.isVolatileMessage(msg)) {
|
|
1584
|
+
await this.publishPlainVolatileMessages([msg], 'push', false);
|
|
1585
|
+
return;
|
|
1586
|
+
}
|
|
1463
1587
|
// 新 SDK 的所有带合法 seq P2P Push 都只作为 Head 通知处理。
|
|
1464
1588
|
// 新服务端为兼容旧 SDK 仍可能发送 message.received;V2 会话下必须
|
|
1465
1589
|
// 在旧 seq tracking / ordered publish 之前转入前台 Tail 协调器。
|
|
@@ -2923,6 +3047,10 @@ export class MessageDeliveryEngine {
|
|
|
2923
3047
|
const ns = client._aid ? `p2p:${client._aid}` : '';
|
|
2924
3048
|
if (!pushData || !ns)
|
|
2925
3049
|
return;
|
|
3050
|
+
if (this.isVolatileMessage(pushData)) {
|
|
3051
|
+
await client._v2E2EE.publishV2VolatileMessages([pushData], 'push', false);
|
|
3052
|
+
return;
|
|
3053
|
+
}
|
|
2926
3054
|
if (String(pushData.kind ?? '').trim() === 'message.online_unread_hint') {
|
|
2927
3055
|
if (client._sessionOptions?.background_sync === false)
|
|
2928
3056
|
return;
|