@agentunion/fastaun-browser 0.5.2 → 0.5.3
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 +36 -0
- package/_packed_docs/CHANGELOG.md +36 -0
- package/_packed_docs/INDEX.md +16 -10
- package/_packed_docs/KITE_DOCS_GUIDE.md +4 -2
- package/_packed_docs/protocol/10-Group-/345/255/220/345/215/217/350/256/256.md +202 -75
- package/_packed_docs/protocol/README.md +3 -2
- package/_packed_docs/protocol/aun-docs-guide.md +3 -2
- package/_packed_docs/protocol/index.md +6 -5
- package/_packed_docs/sdk/03-/346/240/270/345/277/203/346/246/202/345/277/265.md +20 -1
- package/_packed_docs/sdk/06-API/346/211/213/345/206/214.md +289 -24
- package/_packed_docs/sdk/07-/351/224/231/350/257/257/345/244/204/347/220/206.md +30 -6
- package/_packed_docs/sdk/08-/346/234/200/344/275/263/345/256/236/350/267/265.md +28 -12
- package/_packed_docs/sdk/09-group-rpc-manual.md +102 -28
- package/_packed_docs/sdk/AUN_DOCS_GUIDE.md +6 -4
- package/_packed_docs/sdk/INDEX.md +17 -17
- package/dist/bundle.js +982 -250
- package/dist/client/delivery.d.ts +4 -0
- package/dist/client/delivery.d.ts.map +1 -1
- package/dist/client/delivery.js +174 -7
- package/dist/client/delivery.js.map +1 -1
- package/dist/client/v2-e2ee.js +2 -2
- package/dist/client/v2-e2ee.js.map +1 -1
- package/dist/client.d.ts +27 -1
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +118 -12
- package/dist/client.js.map +1 -1
- package/dist/facades.d.ts +6 -0
- package/dist/facades.d.ts.map +1 -1
- package/dist/facades.js +213 -33
- package/dist/facades.js.map +1 -1
- package/dist/group-index.d.ts +105 -0
- package/dist/group-index.d.ts.map +1 -0
- package/dist/group-index.js +252 -0
- package/dist/group-index.js.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/keystore/index.d.ts +15 -0
- package/dist/keystore/index.d.ts.map +1 -1
- package/dist/keystore/indexeddb-shared.d.ts +7 -1
- package/dist/keystore/indexeddb-shared.d.ts.map +1 -1
- package/dist/keystore/indexeddb-shared.js +63 -2
- package/dist/keystore/indexeddb-shared.js.map +1 -1
- package/dist/keystore/indexeddb-token-store.d.ts +3 -1
- package/dist/keystore/indexeddb-token-store.d.ts.map +1 -1
- package/dist/keystore/indexeddb-token-store.js +22 -1
- package/dist/keystore/indexeddb-token-store.js.map +1 -1
- package/dist/tools/cross-sdk-agent.js +3 -1
- package/dist/tools/cross-sdk-agent.js.map +1 -1
- package/dist/transport.d.ts +2 -1
- package/dist/transport.d.ts.map +1 -1
- package/dist/transport.js +17 -31
- 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
|
@@ -29,13 +29,17 @@ export declare class MessageDeliveryEngine {
|
|
|
29
29
|
event: string;
|
|
30
30
|
payload: EventPayload;
|
|
31
31
|
};
|
|
32
|
+
messageRecallDedupKey(payload: JsonObject): string;
|
|
33
|
+
publishMessageRecallTombstone(seq: unknown, message: EventPayload): Promise<boolean>;
|
|
32
34
|
recallEventFromGroupMessage(message: EventPayload): JsonObject | null;
|
|
33
35
|
groupRecallDedupKey(groupId: string, payload: JsonObject): string;
|
|
34
36
|
publishGroupRecallTombstone(groupId: string, seq: unknown, message: EventPayload): Promise<boolean>;
|
|
35
37
|
onRawGroupMessageRecalled(data: EventPayload): Promise<void>;
|
|
36
38
|
publishAppEvent(event: string, payload: EventPayload): Promise<void>;
|
|
37
39
|
messageTargetsCurrentInstance(message: EventPayload): boolean;
|
|
40
|
+
runPushProcessSerialized(ns: string, operation: () => Promise<void>): Promise<void>;
|
|
38
41
|
onRawMessageReceived(data: EventPayload): void;
|
|
42
|
+
onRawMessageRecalled(data: EventPayload): Promise<void>;
|
|
39
43
|
processAndPublishMessage(data: EventPayload): Promise<void>;
|
|
40
44
|
onRawGroupMessageCreated(data: EventPayload): void;
|
|
41
45
|
processAndPublishGroupMessage(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,EAAiC,KAAK,UAAU,EAAkB,KAAK,OAAO,EAAE,KAAK,SAAS,EAAE,MAAM,aAAa,CAAC;AAC3H,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
|
@@ -3,6 +3,7 @@ import { normalizeGroupId } from '../group-id.js';
|
|
|
3
3
|
import { ConnectionState, isJsonObject } from '../types.js';
|
|
4
4
|
const PUSHED_SEQS_LIMIT = 50_000;
|
|
5
5
|
const PENDING_ORDERED_LIMIT = 50_000;
|
|
6
|
+
const MESSAGE_RECALL_SEEN_LIMIT = 10_000;
|
|
6
7
|
const GROUP_RECALL_SEEN_LIMIT = 10_000;
|
|
7
8
|
const SEQ_TRACKER_PERSIST_FLUSH_DELAY_MS = 200;
|
|
8
9
|
const P2P_GAP_FILL_RETRY_LIMIT = 12;
|
|
@@ -14,6 +15,13 @@ const APP_MESSAGE_ENVELOPE_KEYS = [
|
|
|
14
15
|
'timestamp', 'created_at', 'encrypted',
|
|
15
16
|
'context', 'protected_headers', 'headers', 'payload_type',
|
|
16
17
|
];
|
|
18
|
+
const RECALL_PAYLOAD_KEYS = [
|
|
19
|
+
'message_ids', 'target_message_seqs',
|
|
20
|
+
'recalled_message_id', 'target_message_id', 'original_message_id',
|
|
21
|
+
'target_seq', 'original_seq',
|
|
22
|
+
'notice_message_id', 'notice_seq', 'event_seq',
|
|
23
|
+
'sender_aid', 'recalled_by', 'recalled_at', 'reason',
|
|
24
|
+
];
|
|
17
25
|
const APP_SEND_ENVELOPE_METHODS = new Set([
|
|
18
26
|
'message.send',
|
|
19
27
|
'group.send',
|
|
@@ -134,6 +142,10 @@ export class MessageDeliveryEngine {
|
|
|
134
142
|
await this.publishOrderedGroupChanged(payload);
|
|
135
143
|
return;
|
|
136
144
|
}
|
|
145
|
+
if (event === 'message.recalled') {
|
|
146
|
+
await this.publishMessageRecallTombstone(seq, payload);
|
|
147
|
+
return;
|
|
148
|
+
}
|
|
137
149
|
await client._publishAppEvent(event, payload);
|
|
138
150
|
}
|
|
139
151
|
async publishOrderedGroupChanged(payload) {
|
|
@@ -351,6 +363,11 @@ export class MessageDeliveryEngine {
|
|
|
351
363
|
event[key] = msg[key];
|
|
352
364
|
}
|
|
353
365
|
}
|
|
366
|
+
for (const key of RECALL_PAYLOAD_KEYS) {
|
|
367
|
+
if (Object.prototype.hasOwnProperty.call(msg, key) && !(key in event)) {
|
|
368
|
+
event[key] = msg[key];
|
|
369
|
+
}
|
|
370
|
+
}
|
|
354
371
|
const rawIds = event.message_ids;
|
|
355
372
|
let messageIds = Array.isArray(rawIds)
|
|
356
373
|
? rawIds.map((item) => String(item ?? '').trim()).filter(Boolean)
|
|
@@ -392,6 +409,57 @@ export class MessageDeliveryEngine {
|
|
|
392
409
|
return { event: 'message.recalled', payload: recall };
|
|
393
410
|
return { event: 'message.received', payload: message };
|
|
394
411
|
}
|
|
412
|
+
messageRecallDedupKey(payload) {
|
|
413
|
+
const ids = payload.message_ids;
|
|
414
|
+
const idPart = Array.isArray(ids)
|
|
415
|
+
? ids.map((i) => String(i ?? '').trim()).filter(Boolean).sort().join(',')
|
|
416
|
+
: String(ids ?? '').trim();
|
|
417
|
+
if (idPart)
|
|
418
|
+
return `p2p|id:${idPart}`;
|
|
419
|
+
for (const key of ['recalled_message_id', 'target_message_id', 'original_message_id']) {
|
|
420
|
+
const value = String(payload[key] ?? '').trim();
|
|
421
|
+
if (value)
|
|
422
|
+
return `p2p|id:${value}`;
|
|
423
|
+
}
|
|
424
|
+
const rawSeqs = payload.target_message_seqs;
|
|
425
|
+
const seqPart = Array.isArray(rawSeqs)
|
|
426
|
+
? rawSeqs.map((seq) => String(seq ?? '').trim()).filter(Boolean).sort().join(',')
|
|
427
|
+
: String(rawSeqs ?? payload.target_seq ?? payload.original_seq ?? '').trim();
|
|
428
|
+
if (seqPart) {
|
|
429
|
+
const fromAid = String(payload.from ?? payload.from_aid ?? payload.sender_aid ?? '').trim();
|
|
430
|
+
const toAid = String(payload.to ?? payload.to_aid ?? '').trim();
|
|
431
|
+
return `p2p|from:${fromAid}|to:${toAid}|seq:${seqPart}`;
|
|
432
|
+
}
|
|
433
|
+
const tombstoneId = String(payload.tombstone_message_id ?? payload.message_id ?? '').trim();
|
|
434
|
+
if (tombstoneId)
|
|
435
|
+
return `p2p|tombstone:${tombstoneId}`;
|
|
436
|
+
return `p2p|unknown:${Date.now()}:${Math.random()}`;
|
|
437
|
+
}
|
|
438
|
+
async publishMessageRecallTombstone(seq, message) {
|
|
439
|
+
const client = this.runtime.client;
|
|
440
|
+
const eventPayload = this.recallEventFromMessage(message);
|
|
441
|
+
if (!eventPayload)
|
|
442
|
+
return false;
|
|
443
|
+
const dedupKey = this.messageRecallDedupKey(eventPayload);
|
|
444
|
+
let seen = client._messageRecallSeen;
|
|
445
|
+
if (!seen) {
|
|
446
|
+
seen = new Map();
|
|
447
|
+
client._messageRecallSeen = seen;
|
|
448
|
+
}
|
|
449
|
+
if (seen.has(dedupKey)) {
|
|
450
|
+
client._clientLog.debug(`message.recalled dedup suppressed: seq=${String(seq)} key=${dedupKey}`);
|
|
451
|
+
return false;
|
|
452
|
+
}
|
|
453
|
+
seen.set(dedupKey, Date.now());
|
|
454
|
+
if (seen.size > MESSAGE_RECALL_SEEN_LIMIT) {
|
|
455
|
+
const drop = [...seen.entries()].sort((a, b) => a[1] - b[1]).slice(0, seen.size - MESSAGE_RECALL_SEEN_LIMIT);
|
|
456
|
+
for (const [oldKey] of drop)
|
|
457
|
+
seen.delete(oldKey);
|
|
458
|
+
}
|
|
459
|
+
await client._publishAppEvent('message.recalled', eventPayload);
|
|
460
|
+
client._clientLog.debug(`message.recalled published: seq=${String(seq)} ids=${JSON.stringify(eventPayload.message_ids)}`);
|
|
461
|
+
return true;
|
|
462
|
+
}
|
|
395
463
|
recallEventFromGroupMessage(message) {
|
|
396
464
|
if (!isJsonObject(message))
|
|
397
465
|
return null;
|
|
@@ -408,6 +476,11 @@ export class MessageDeliveryEngine {
|
|
|
408
476
|
event[key] = msg[key];
|
|
409
477
|
}
|
|
410
478
|
}
|
|
479
|
+
for (const key of RECALL_PAYLOAD_KEYS) {
|
|
480
|
+
if (Object.prototype.hasOwnProperty.call(msg, key) && !(key in event)) {
|
|
481
|
+
event[key] = msg[key];
|
|
482
|
+
}
|
|
483
|
+
}
|
|
411
484
|
const rawIds = event.message_ids;
|
|
412
485
|
let messageIds = Array.isArray(rawIds)
|
|
413
486
|
? rawIds.map((item) => String(item ?? '').trim()).filter(Boolean)
|
|
@@ -438,23 +511,44 @@ export class MessageDeliveryEngine {
|
|
|
438
511
|
return event;
|
|
439
512
|
}
|
|
440
513
|
groupRecallDedupKey(groupId, payload) {
|
|
441
|
-
// 群撤回去重键:group_id +
|
|
514
|
+
// 群撤回去重键:group_id + 原始消息标识。
|
|
442
515
|
// 一条消息只能被撤回一次(服务端 group_message_recalls uk_recall_msg_id 唯一约束),
|
|
443
|
-
// (group_id, sorted message_ids)
|
|
516
|
+
// (group_id, sorted message_ids) 已能唯一标识一次撤回;缺 message_ids 时按原消息 id/seq 兜底。
|
|
444
517
|
// 去重键不含 recalled_at:占位/通知 tombstone(pull)与在线 push 三条通道对同一次撤回
|
|
445
518
|
// 可能携带不同来源的时间戳(push 在事务后重取),纳入 recalled_at 会使去重失效、回调多次。
|
|
519
|
+
const normalizedGroupId = normalizeGroupId(groupId) || String(groupId ?? '').trim();
|
|
446
520
|
const ids = payload.message_ids;
|
|
447
521
|
const idPart = Array.isArray(ids)
|
|
448
522
|
? ids.map((i) => String(i ?? '').trim()).filter(Boolean).sort().join(',')
|
|
449
|
-
: String(ids ?? '');
|
|
450
|
-
|
|
523
|
+
: String(ids ?? '').trim();
|
|
524
|
+
if (idPart)
|
|
525
|
+
return `${normalizedGroupId}|id:${idPart}`;
|
|
526
|
+
for (const key of ['recalled_message_id', 'target_message_id', 'original_message_id']) {
|
|
527
|
+
const value = String(payload[key] ?? '').trim();
|
|
528
|
+
if (value)
|
|
529
|
+
return `${normalizedGroupId}|id:${value}`;
|
|
530
|
+
}
|
|
531
|
+
const rawSeqs = payload.target_message_seqs;
|
|
532
|
+
const seqPart = Array.isArray(rawSeqs)
|
|
533
|
+
? rawSeqs.map((seq) => String(seq ?? '').trim()).filter(Boolean).sort().join(',')
|
|
534
|
+
: String(rawSeqs ?? payload.original_seq ?? '').trim();
|
|
535
|
+
if (seqPart)
|
|
536
|
+
return `${normalizedGroupId}|seq:${seqPart}`;
|
|
537
|
+
const tombstoneId = String(payload.tombstone_message_id ?? payload.message_id ?? '').trim();
|
|
538
|
+
if (tombstoneId)
|
|
539
|
+
return `${normalizedGroupId}|tombstone:${tombstoneId}`;
|
|
540
|
+
return `${normalizedGroupId}|unknown:${Date.now()}:${Math.random()}`;
|
|
451
541
|
}
|
|
452
542
|
async publishGroupRecallTombstone(groupId, seq, message) {
|
|
453
543
|
const client = this.runtime.client;
|
|
454
544
|
const eventPayload = this.recallEventFromGroupMessage(message);
|
|
455
545
|
if (!eventPayload)
|
|
456
546
|
return false;
|
|
457
|
-
const
|
|
547
|
+
const rawGroupId = String(eventPayload.group_id ?? groupId ?? '').trim();
|
|
548
|
+
const dedupGroupId = normalizeGroupId(rawGroupId) || rawGroupId;
|
|
549
|
+
if (dedupGroupId)
|
|
550
|
+
eventPayload.group_id = dedupGroupId;
|
|
551
|
+
const dedupKey = this.groupRecallDedupKey(dedupGroupId, eventPayload);
|
|
458
552
|
let seen = client._groupRecallSeen;
|
|
459
553
|
if (!seen) {
|
|
460
554
|
seen = new Map();
|
|
@@ -585,12 +679,75 @@ export class MessageDeliveryEngine {
|
|
|
585
679
|
}
|
|
586
680
|
return true;
|
|
587
681
|
}
|
|
682
|
+
async runPushProcessSerialized(ns, operation) {
|
|
683
|
+
const client = this.runtime.client;
|
|
684
|
+
if (!ns) {
|
|
685
|
+
await operation();
|
|
686
|
+
return;
|
|
687
|
+
}
|
|
688
|
+
let queues = client._pushProcessQueues;
|
|
689
|
+
if (!queues) {
|
|
690
|
+
queues = new Map();
|
|
691
|
+
client._pushProcessQueues = queues;
|
|
692
|
+
}
|
|
693
|
+
const previous = queues.get(ns) ?? Promise.resolve();
|
|
694
|
+
const current = previous.catch(() => undefined).then(operation);
|
|
695
|
+
const stored = current.then(() => undefined, () => undefined);
|
|
696
|
+
queues.set(ns, stored);
|
|
697
|
+
try {
|
|
698
|
+
await current;
|
|
699
|
+
}
|
|
700
|
+
finally {
|
|
701
|
+
if (queues.get(ns) === stored)
|
|
702
|
+
queues.delete(ns);
|
|
703
|
+
}
|
|
704
|
+
}
|
|
588
705
|
onRawMessageReceived(data) {
|
|
589
706
|
const client = this.runtime.client;
|
|
590
707
|
client._clientLog.debug(`_onRawMessageReceived enter: from=${data?.from ?? '-'} mid=${data?.message_id ?? '-'} seq=${data?.seq ?? '-'}`);
|
|
591
|
-
client.
|
|
708
|
+
const ns = isJsonObject(data) && client._aid && data.seq !== undefined
|
|
709
|
+
? `p2p:${client._aid}`
|
|
710
|
+
: '';
|
|
711
|
+
client._safeAsync(this.runPushProcessSerialized(ns, () => this.processAndPublishMessage(data)));
|
|
592
712
|
client._clientLog.debug('_onRawMessageReceived exit: elapsed=0ms (dispatched async)');
|
|
593
713
|
}
|
|
714
|
+
async onRawMessageRecalled(data) {
|
|
715
|
+
const client = this.runtime.client;
|
|
716
|
+
if (!isJsonObject(data))
|
|
717
|
+
return;
|
|
718
|
+
const msg = { ...data };
|
|
719
|
+
if (!('type' in msg))
|
|
720
|
+
msg.type = 'message.recalled';
|
|
721
|
+
if (!this.messageTargetsCurrentInstance(msg))
|
|
722
|
+
return;
|
|
723
|
+
const seq = msg.seq;
|
|
724
|
+
if (seq !== undefined && seq !== null && client._aid) {
|
|
725
|
+
const ns = `p2p:${client._aid}`;
|
|
726
|
+
if (seq > 0)
|
|
727
|
+
client._seqTracker.updateMaxSeen(ns, seq);
|
|
728
|
+
const contigBefore = client._seqTracker.getContiguousSeq(ns);
|
|
729
|
+
const seqNeedsPull = client._seqTracker.onMessageSeq(ns, seq);
|
|
730
|
+
const published = await this.publishOrderedMessage('message.recalled', ns, seq, msg);
|
|
731
|
+
const contigAfter = client._seqTracker.getContiguousSeq(ns);
|
|
732
|
+
if (seqNeedsPull && !published) {
|
|
733
|
+
client._safeAsync(this.fillP2pGap());
|
|
734
|
+
}
|
|
735
|
+
const contig = client._seqTracker.getContiguousSeq(ns);
|
|
736
|
+
if (contig > 0) {
|
|
737
|
+
const ackSeq = this.clampAckSeq('message.ack', 'seq', ns, contig);
|
|
738
|
+
client._transport.call('message.ack', {
|
|
739
|
+
seq: ackSeq,
|
|
740
|
+
device_id: client._deviceId,
|
|
741
|
+
slot_id: client._slotId,
|
|
742
|
+
_rpc_background: true,
|
|
743
|
+
}).catch((e) => { client._clientLog.warn(`P2P recall auto-ack failed:${String(e)}`); });
|
|
744
|
+
}
|
|
745
|
+
if (contigAfter !== contigBefore)
|
|
746
|
+
this.persistSeq(ns);
|
|
747
|
+
return;
|
|
748
|
+
}
|
|
749
|
+
await this.publishMessageRecallTombstone(seq, msg);
|
|
750
|
+
}
|
|
594
751
|
async processAndPublishMessage(data) {
|
|
595
752
|
const client = this.runtime.client;
|
|
596
753
|
try {
|
|
@@ -661,7 +818,8 @@ export class MessageDeliveryEngine {
|
|
|
661
818
|
onRawGroupMessageCreated(data) {
|
|
662
819
|
const client = this.runtime.client;
|
|
663
820
|
client._clientLog.debug(`_onRawGroupMessageCreated enter: group_id=${data?.group_id ?? '-'} from=${data?.from ?? '-'} seq=${data?.seq ?? '-'}`);
|
|
664
|
-
|
|
821
|
+
const groupId = isJsonObject(data) ? String(data.group_id ?? '').trim() : '';
|
|
822
|
+
client._safeAsync(this.runPushProcessSerialized(groupId ? `group:${groupId}` : '', () => this.processAndPublishGroupMessage(data)));
|
|
665
823
|
client._clientLog.debug('_onRawGroupMessageCreated exit: elapsed=0ms (dispatched async)');
|
|
666
824
|
}
|
|
667
825
|
async processAndPublishGroupMessage(data) {
|
|
@@ -1690,6 +1848,9 @@ export class MessageDeliveryEngine {
|
|
|
1690
1848
|
const client = this.runtime.client;
|
|
1691
1849
|
const seqNum = Number(seq);
|
|
1692
1850
|
if (!Number.isFinite(seqNum) || !Number.isInteger(seqNum) || seqNum <= 0 || !ns) {
|
|
1851
|
+
if (event === 'message.recalled') {
|
|
1852
|
+
return this.publishMessageRecallTombstone(seq, payload);
|
|
1853
|
+
}
|
|
1693
1854
|
await client._publishAppEvent(event, payload);
|
|
1694
1855
|
return true;
|
|
1695
1856
|
}
|
|
@@ -1700,9 +1861,15 @@ export class MessageDeliveryEngine {
|
|
|
1700
1861
|
client._pendingOrderedMsgs.delete(ns);
|
|
1701
1862
|
return false;
|
|
1702
1863
|
}
|
|
1864
|
+
await this.drainOrderedMessages(ns, seqNum);
|
|
1703
1865
|
queue?.delete(seqNum);
|
|
1704
1866
|
if (queue && queue.size === 0)
|
|
1705
1867
|
client._pendingOrderedMsgs.delete(ns);
|
|
1868
|
+
if (event === 'message.recalled') {
|
|
1869
|
+
const published = await this.publishMessageRecallTombstone(seqNum, payload);
|
|
1870
|
+
this.markPublishedSeq(ns, seqNum);
|
|
1871
|
+
return published;
|
|
1872
|
+
}
|
|
1706
1873
|
await client._publishAppEvent(event, payload);
|
|
1707
1874
|
this.markPublishedSeq(ns, seqNum);
|
|
1708
1875
|
return true;
|