@agentunion/fastaun 0.5.16 → 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.
Files changed (46) hide show
  1. package/CHANGELOG.md +311 -276
  2. package/_packed_docs/CHANGELOG.md +311 -276
  3. package/_packed_docs/INDEX.md +8 -2
  4. package/_packed_docs/KITE_DOCS_GUIDE.md +2 -0
  5. package/_packed_docs/agent.md/SCHEMA.md +15 -15
  6. 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
  7. 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
  8. package/_packed_docs/protocol/06-/346/234/215/345/212/241/345/215/217/350/256/256.md +58 -43
  9. package/_packed_docs/protocol/10-Group-/345/255/220/345/215/217/350/256/256.md +80 -17
  10. package/_packed_docs/sdk/06-API/346/211/213/345/206/214.md +27 -6
  11. package/_packed_docs/sdk/07-/351/224/231/350/257/257/345/244/204/347/220/206.md +7 -4
  12. package/_packed_docs/sdk/09-group-rpc-manual.md +167 -35
  13. package/_packed_docs/sdk/09-message-rpc-manual.md +72 -42
  14. package/_packed_docs/sdk/09-storage-rpc-manual.md +23 -14
  15. package/_packed_docs/sdk/AUN_DOCS_GUIDE.md +16 -12
  16. package/_packed_docs/sdk/INDEX.md +12 -12
  17. package/dist/agent-md.d.ts +2 -0
  18. package/dist/agent-md.js +7 -1
  19. package/dist/agent-md.js.map +1 -1
  20. package/dist/client/delivery.d.ts +17 -0
  21. package/dist/client/delivery.js +140 -12
  22. package/dist/client/delivery.js.map +1 -1
  23. package/dist/client/group-state.d.ts +4 -0
  24. package/dist/client/group-state.js +63 -0
  25. package/dist/client/group-state.js.map +1 -1
  26. package/dist/client/rpc-pipeline.js +22 -5
  27. package/dist/client/rpc-pipeline.js.map +1 -1
  28. package/dist/client/v2-e2ee.d.ts +10 -1
  29. package/dist/client/v2-e2ee.js +187 -36
  30. package/dist/client/v2-e2ee.js.map +1 -1
  31. package/dist/client.js +53 -12
  32. package/dist/client.js.map +1 -1
  33. package/dist/facades.d.ts +5 -0
  34. package/dist/facades.js +5 -0
  35. package/dist/facades.js.map +1 -1
  36. package/dist/group-fs.js +7 -5
  37. package/dist/group-fs.js.map +1 -1
  38. package/dist/storage/vfs.d.ts +1 -0
  39. package/dist/storage/vfs.js +61 -6
  40. package/dist/storage/vfs.js.map +1 -1
  41. package/dist/tools/cross-sdk-agent.js +31 -1
  42. package/dist/tools/cross-sdk-agent.js.map +1 -1
  43. package/dist/types.d.ts +16 -1
  44. package/dist/version.d.ts +1 -1
  45. package/dist/version.js +1 -1
  46. package/package.json +8 -8
@@ -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', 'slot_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
- if ('slot_id' in msg && !('slot_id' in event))
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;