@agentunion/fastaun 0.5.9 → 0.5.10

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 (38) hide show
  1. package/CHANGELOG.md +32 -0
  2. package/_packed_docs/CHANGELOG.md +32 -0
  3. package/_packed_docs/sdk/04-/350/277/236/346/216/245/344/270/216/350/256/244/350/257/201.md +6 -5
  4. package/_packed_docs/sdk/06-API/346/211/213/345/206/214.md +43 -8
  5. package/_packed_docs/sdk/09-group-rpc-manual.md +18 -3
  6. package/_packed_docs/sdk/09-message-rpc-manual.md +34 -10
  7. package/dist/agent-md.js +5 -1
  8. package/dist/agent-md.js.map +1 -1
  9. package/dist/auth.d.ts +2 -1
  10. package/dist/auth.js +30 -44
  11. package/dist/auth.js.map +1 -1
  12. package/dist/client/delivery.d.ts +21 -5
  13. package/dist/client/delivery.js +236 -52
  14. package/dist/client/delivery.js.map +1 -1
  15. package/dist/client/group-state.js +6 -6
  16. package/dist/client/group-state.js.map +1 -1
  17. package/dist/client/lifecycle.js +5 -14
  18. package/dist/client/lifecycle.js.map +1 -1
  19. package/dist/client/rpc-pipeline.d.ts +4 -0
  20. package/dist/client/rpc-pipeline.js +33 -1
  21. package/dist/client/rpc-pipeline.js.map +1 -1
  22. package/dist/client/v2-e2ee.d.ts +1 -0
  23. package/dist/client/v2-e2ee.js +43 -17
  24. package/dist/client/v2-e2ee.js.map +1 -1
  25. package/dist/client.js +21 -27
  26. package/dist/client.js.map +1 -1
  27. package/dist/events.d.ts +23 -8
  28. package/dist/events.js +120 -26
  29. package/dist/events.js.map +1 -1
  30. package/dist/register-flow.js +15 -111
  31. package/dist/register-flow.js.map +1 -1
  32. package/dist/transport.d.ts +32 -3
  33. package/dist/transport.js +758 -33
  34. package/dist/transport.js.map +1 -1
  35. package/dist/version.d.ts +1 -1
  36. package/dist/version.js +1 -1
  37. package/dist/version.js.map +1 -1
  38. package/package.json +1 -1
@@ -1,11 +1,16 @@
1
1
  import { slotIsolationKey } from '../config.js';
2
2
  import { ConnectionState, isJsonObject } from '../types.js';
3
+ import { validateGroupAIDFormat } from '../validators.js';
3
4
  import { hasGroupMentionModeField, normalizeGroupMentionMode } from './mention-mode.js';
4
5
  const PUSHED_SEQS_LIMIT = 50_000;
5
6
  const PENDING_ORDERED_LIMIT = 50_000;
6
7
  const MESSAGE_RECALL_SEEN_LIMIT = 10_000;
7
8
  const GROUP_RECALL_SEEN_LIMIT = 10_000;
8
9
  const SEQ_TRACKER_PERSIST_FLUSH_DELAY_MS = 200;
10
+ const DELIVERY_CHANGED_MESSAGE_EVENTS = new Set([
11
+ 'message.received',
12
+ 'group.message_created',
13
+ ]);
9
14
  const MAX_INLINE_PENDING_ACK_NAMESPACES = 4096;
10
15
  const APP_MESSAGE_ENVELOPE_KEYS = [
11
16
  'module_id', 'message_type', 'type', 'kind', 'version',
@@ -73,6 +78,8 @@ export class MessageDeliveryEngine {
73
78
  pendingGroupInlineAcks = null;
74
79
  pendingGroupInlineAckNamespaces = null;
75
80
  inlineAckGeneration = 0;
81
+ pendingDeliveryChanges = null;
82
+ deliveryChangedGeneration = 0;
76
83
  // 同一实例的 tracker 写入必须串行,避免旧的延迟 flush 覆盖新的 Forward 提交。
77
84
  seqTrackerWriteChain = Promise.resolve();
78
85
  constructor(runtime) {
@@ -207,7 +214,7 @@ export class MessageDeliveryEngine {
207
214
  }
208
215
  if (client._seqTracker.getContiguousSeq(ns) !== pageContigBefore) {
209
216
  this.ensurePullOperationCurrent();
210
- await this.drainOrderedMessages(ns, undefined, false, false);
217
+ await this.drainOrderedMessages(ns, undefined, false, false, 'pull');
211
218
  this.ensurePullOperationCurrent();
212
219
  await client._commitSeqTrackerState(ns);
213
220
  }
@@ -257,6 +264,8 @@ export class MessageDeliveryEngine {
257
264
  return { rawCount: messages.length, publishedCount };
258
265
  }
259
266
  resetInlineAckState() {
267
+ this.deliveryChangedGeneration += 1;
268
+ this.pendingDeliveryChanges = null;
260
269
  this.inlineAckGeneration += 1;
261
270
  void this.runtime.client._rpcPipeline?.invalidatePulls?.();
262
271
  this.pendingP2PInlineAcks = null;
@@ -268,6 +277,113 @@ export class MessageDeliveryEngine {
268
277
  this.onlineUnreadHintTasks = null;
269
278
  this.realtimeTailHeads = null;
270
279
  }
280
+ deliveryChangedNamespace(event, payload) {
281
+ if (event === 'group.message_created' && isJsonObject(payload)) {
282
+ const aid = String(this.runtime.client._aid ?? '').trim();
283
+ const dot = aid.indexOf('.');
284
+ try {
285
+ const groupAid = validateGroupAIDFormat(payload.group_aid ?? payload.group_id, { localIssuer: dot >= 0 ? aid.slice(dot + 1) : '' });
286
+ return groupAid.includes('.') ? `group:${groupAid}` : '';
287
+ }
288
+ catch {
289
+ return '';
290
+ }
291
+ }
292
+ return 'p2p';
293
+ }
294
+ isDeliveryChangedMessage(event, payload) {
295
+ if (!DELIVERY_CHANGED_MESSAGE_EVENTS.has(event)
296
+ || !isJsonObject(payload))
297
+ return false;
298
+ const messageId = payload.message_id;
299
+ const seq = payload.seq;
300
+ return (typeof messageId === 'string' && messageId.trim().length > 0)
301
+ || (typeof seq === 'number' && Number.isSafeInteger(seq) && seq > 0);
302
+ }
303
+ deliveryChangedTrigger(source) {
304
+ if (source === 'inline-push')
305
+ return 'inline_push';
306
+ if (source === 'pull' || source === 'tail')
307
+ return 'pull_drained';
308
+ if (source === 'push' || source === 'group-push' || source === 'ordered')
309
+ return 'push';
310
+ return null;
311
+ }
312
+ noteDeliveryChanged(event, payload, source, context) {
313
+ if (!this.isDeliveryChangedMessage(event, payload))
314
+ return;
315
+ const trigger = this.deliveryChangedTrigger(source);
316
+ const namespace = this.deliveryChangedNamespace(event, payload);
317
+ if (!trigger || !namespace)
318
+ return;
319
+ const pending = trigger === 'pull_drained'
320
+ ? this.pendingDeliveryChanges ?? new Map()
321
+ : context?.changes ?? this.pendingDeliveryChanges ?? new Map();
322
+ if (trigger === 'pull_drained' || !context)
323
+ this.pendingDeliveryChanges = pending;
324
+ pending.set(namespace, (pending.get(namespace) ?? 0) + 1);
325
+ if (!context && trigger !== 'pull_drained')
326
+ this.flushDeliveryChanged(trigger);
327
+ }
328
+ flushDeliveryChanged(trigger) {
329
+ const pending = this.pendingDeliveryChanges;
330
+ if (!pending || pending.size === 0)
331
+ return;
332
+ const changes = [...pending.entries()]
333
+ .filter(([, deliveredCount]) => deliveredCount > 0)
334
+ .sort(([left], [right]) => left.localeCompare(right))
335
+ .map(([namespace, deliveredCount]) => ({ namespace, delivered_count: deliveredCount }));
336
+ pending.clear();
337
+ if (changes.length === 0)
338
+ return;
339
+ const payload = { trigger, changes };
340
+ const dispatcher = this.runtime.client._dispatcher;
341
+ const published = typeof dispatcher.enqueue === 'function'
342
+ ? (dispatcher.enqueue('delivery.changed', payload), undefined)
343
+ : typeof dispatcher.publishSyncAware === 'function'
344
+ ? dispatcher.publishSyncAware('delivery.changed', payload)
345
+ : dispatcher.publish?.('delivery.changed', payload);
346
+ if (isPromiseLike(published))
347
+ void Promise.resolve(published).catch((exc) => {
348
+ this.runtime.client._clientLog.warn(`delivery.changed handler failed: ${formatDeliveryError(exc)}`);
349
+ });
350
+ }
351
+ onPullDrained() {
352
+ this.flushDeliveryChanged('pull_drained');
353
+ }
354
+ flushDeliveryChangedContext(context, trigger) {
355
+ if (context.generation !== this.deliveryChangedGeneration || context.changes.size === 0)
356
+ return;
357
+ const pending = this.pendingDeliveryChanges;
358
+ if (pending) {
359
+ for (const [namespace, count] of pending) {
360
+ context.changes.set(namespace, (context.changes.get(namespace) ?? 0) + count);
361
+ }
362
+ pending.clear();
363
+ }
364
+ const changes = [...context.changes.entries()]
365
+ .filter(([, count]) => count > 0)
366
+ .sort(([left], [right]) => left.localeCompare(right))
367
+ .map(([namespace, delivered_count]) => ({ namespace, delivered_count }));
368
+ context.changes.clear();
369
+ if (changes.length === 0)
370
+ return;
371
+ const dispatcher = this.runtime.client._dispatcher;
372
+ const payload = { trigger, changes };
373
+ const published = typeof dispatcher.enqueue === 'function'
374
+ ? (dispatcher.enqueue('delivery.changed', payload), undefined)
375
+ : typeof dispatcher.publishSyncAware === 'function'
376
+ ? dispatcher.publishSyncAware('delivery.changed', payload)
377
+ : dispatcher.publish?.('delivery.changed', payload);
378
+ if (isPromiseLike(published))
379
+ void Promise.resolve(published).catch((exc) => {
380
+ this.runtime.client._clientLog.warn(`delivery.changed handler failed: ${formatDeliveryError(exc)}`);
381
+ });
382
+ }
383
+ invalidateDeliveryChanges() {
384
+ this.deliveryChangedGeneration += 1;
385
+ this.pendingDeliveryChanges = null;
386
+ }
271
387
  inlineGenerationIsCurrent(generation) {
272
388
  return this.inlineAckGeneration === generation;
273
389
  }
@@ -310,10 +426,17 @@ export class MessageDeliveryEngine {
310
426
  }
311
427
  endRealtimeSync(ns) {
312
428
  this.realtimeSyncing?.delete(ns);
429
+ this.runtime.client._rpcPipeline?.requestPullDrainedCheck?.();
313
430
  }
314
431
  hasPendingPull(ns) {
315
432
  return (this.pendingGroupPullUpper?.get(ns) ?? 0) > 0;
316
433
  }
434
+ hasAnyPendingPull() {
435
+ return [...(this.pendingGroupPullUpper?.values() ?? [])].some((seq) => seq > 0)
436
+ || Boolean(this.onlineUnreadHintTasks?.size)
437
+ || Boolean(this.realtimeSyncing?.size)
438
+ || Boolean(this.runtime.client._v2E2EE?.hasPendingSenderIKWork?.());
439
+ }
317
440
  onPullGateIdle(ns) {
318
441
  if (!ns)
319
442
  return;
@@ -378,14 +501,14 @@ export class MessageDeliveryEngine {
378
501
  client._pushedSeqs.set(ns, new Set(keep));
379
502
  }
380
503
  }
381
- enqueueOrderedMessage(ns, event, seq, payload) {
504
+ enqueueOrderedMessage(ns, event, seq, payload, source = 'push') {
382
505
  const client = this.runtime.client;
383
506
  let queue = client._pendingOrderedMsgs.get(ns);
384
507
  if (!queue) {
385
508
  queue = new Map();
386
509
  client._pendingOrderedMsgs.set(ns, queue);
387
510
  }
388
- queue.set(seq, { event, payload });
511
+ queue.set(seq, { event, payload, source });
389
512
  if (queue.size > PENDING_ORDERED_LIMIT) {
390
513
  const drop = [...queue.keys()].sort((a, b) => a - b).slice(0, queue.size - PENDING_ORDERED_LIMIT);
391
514
  for (const oldSeq of drop)
@@ -395,7 +518,7 @@ export class MessageDeliveryEngine {
395
518
  isGroupEventNamespace(ns) {
396
519
  return ns.startsWith('group_event:');
397
520
  }
398
- async publishOrderedQueueItem(ns, event, seq, payload, source, pullResponse = false) {
521
+ async publishOrderedQueueItem(ns, event, seq, payload, source, pullResponse = false, deliveryContext) {
399
522
  const client = this.runtime.client;
400
523
  this.ensurePullOperationCurrent();
401
524
  if (event === 'group.changed' && this.isGroupEventNamespace(ns)) {
@@ -409,12 +532,12 @@ export class MessageDeliveryEngine {
409
532
  return;
410
533
  }
411
534
  if (pullResponse) {
412
- const published = client._withPullResponseProcessing(ns, () => client._publishAppEvent(event, payload, source));
535
+ const published = client._withPullResponseProcessing(ns, () => this.publishAppEvent(event, payload, source, deliveryContext));
413
536
  if (isPromiseLike(published))
414
537
  await published;
415
538
  }
416
539
  else {
417
- const published = client._publishAppEvent(event, payload, source);
540
+ const published = this.publishAppEvent(event, payload, source, deliveryContext);
418
541
  if (isPromiseLike(published))
419
542
  await published;
420
543
  }
@@ -934,7 +1057,7 @@ export class MessageDeliveryEngine {
934
1057
  if (contig !== contigBefore)
935
1058
  this.persistSeq(ns);
936
1059
  }
937
- publishAppEvent(event, payload, source = 'direct') {
1060
+ publishAppEvent(event, payload, source = 'direct', deliveryContext) {
938
1061
  const client = this.runtime.client;
939
1062
  if ((event === 'message.received' || event === 'group.message_created') && isJsonObject(payload)) {
940
1063
  client._maybeAppendEchoTraceReceive(payload);
@@ -954,7 +1077,23 @@ export class MessageDeliveryEngine {
954
1077
  client._clientLog.debug(`agent_md etag inject skipped: ${err instanceof Error ? err.message : String(err)}`);
955
1078
  }
956
1079
  }
957
- return client._dispatcher.publishSyncAware(event, this.normalizePublishedMessagePayload(event, payload));
1080
+ const generation = this.deliveryChangedGeneration;
1081
+ const normalized = this.normalizePublishedMessagePayload(event, payload);
1082
+ const dispatcher = client._dispatcher;
1083
+ const result = typeof dispatcher.enqueue === 'function'
1084
+ ? (dispatcher.enqueue(event, normalized), undefined)
1085
+ : typeof dispatcher.publishSyncAware === 'function'
1086
+ ? dispatcher.publishSyncAware(event, normalized)
1087
+ : dispatcher.publish?.(event, normalized);
1088
+ const note = () => {
1089
+ if (generation === this.deliveryChangedGeneration) {
1090
+ this.noteDeliveryChanged(event, payload, source, deliveryContext);
1091
+ }
1092
+ };
1093
+ if (isPromiseLike(result))
1094
+ return Promise.resolve(result).then(note);
1095
+ note();
1096
+ return result;
958
1097
  }
959
1098
  messagePayloadForDebug(message) {
960
1099
  if (!isJsonObject(message))
@@ -2845,6 +2984,7 @@ export class MessageDeliveryEngine {
2845
2984
  targets.delete(ns);
2846
2985
  if (tasks.get(ns) === task)
2847
2986
  tasks.delete(ns);
2987
+ client._rpcPipeline?.requestPullDrainedCheck?.();
2848
2988
  }
2849
2989
  });
2850
2990
  tasks.set(ns, task);
@@ -2975,13 +3115,13 @@ export class MessageDeliveryEngine {
2975
3115
  catch (exc) {
2976
3116
  const error = formatDeliveryError(exc);
2977
3117
  client._clientLog.warn(`restore SeqTracker state failed: ${error}`);
2978
- client._dispatcher.publish('seq_tracker.persist_error', {
3118
+ client._dispatcher.enqueue('seq_tracker.persist_error', {
2979
3119
  phase: 'restore',
2980
3120
  aid: client._aid,
2981
3121
  device_id: client._deviceId,
2982
3122
  slot_id: client._slotId,
2983
3123
  error: String(error),
2984
- }).catch(() => { });
3124
+ });
2985
3125
  }
2986
3126
  }
2987
3127
  migrateSeqStateGroupIds(state) {
@@ -3200,13 +3340,13 @@ export class MessageDeliveryEngine {
3200
3340
  catch (exc) {
3201
3341
  const error = formatDeliveryError(exc);
3202
3342
  client._clientLog.warn(`save SeqTracker state failed: ${error}`);
3203
- client._dispatcher.publish('seq_tracker.persist_error', {
3343
+ client._dispatcher.enqueue('seq_tracker.persist_error', {
3204
3344
  phase: 'save',
3205
3345
  aid,
3206
3346
  device_id: deviceId,
3207
3347
  slot_id: slotId,
3208
3348
  error: String(error),
3209
- }).catch(() => { });
3349
+ });
3210
3350
  if (throwOnError)
3211
3351
  throw exc;
3212
3352
  }
@@ -3324,45 +3464,67 @@ export class MessageDeliveryEngine {
3324
3464
  }
3325
3465
  return params;
3326
3466
  }
3327
- async drainOrderedMessages(ns, beforeSeq, pullResponse = false, persist = true) {
3467
+ async drainOrderedMessages(ns, beforeSeq, pullResponse = false, persist = true, source = 'push', context) {
3328
3468
  const client = this.runtime.client;
3329
3469
  this.ensurePullOperationCurrent();
3330
3470
  const queue = client._pendingOrderedMsgs.get(ns);
3331
3471
  if (!queue || queue.size === 0)
3332
3472
  return;
3333
3473
  let delivered = false;
3334
- while (true) {
3335
- this.ensurePullOperationCurrent();
3336
- const contig = client._seqTracker.getContiguousSeq(ns);
3337
- const ready = [...queue.keys()]
3338
- .filter((seq) => seq <= contig && (beforeSeq === undefined || seq < beforeSeq))
3339
- .sort((a, b) => a - b);
3340
- let seq = ready[0];
3341
- if (seq === undefined) {
3342
- const nextSeq = contig + 1;
3343
- if (beforeSeq !== undefined && nextSeq >= beforeSeq)
3344
- break;
3345
- if (!queue.has(nextSeq))
3346
- break;
3347
- seq = nextSeq;
3348
- }
3349
- if (seq === undefined)
3350
- continue;
3351
- const item = queue.get(seq);
3352
- queue.delete(seq);
3353
- if (!item)
3354
- continue;
3355
- if (client._pushedSeqs.get(ns)?.has(seq)) {
3356
- client._clientLog.debug(`publish ordered drain skipped duplicate: ns=${ns}, seq=${seq}, event=${item.event}`);
3474
+ const rootTrigger = this.deliveryChangedTrigger(source);
3475
+ const drainContexts = new Map();
3476
+ try {
3477
+ while (true) {
3478
+ this.ensurePullOperationCurrent();
3479
+ const contig = client._seqTracker.getContiguousSeq(ns);
3480
+ const ready = [...queue.keys()]
3481
+ .filter((seq) => seq <= contig && (beforeSeq === undefined || seq < beforeSeq))
3482
+ .sort((a, b) => a - b);
3483
+ let seq = ready[0];
3484
+ if (seq === undefined) {
3485
+ const nextSeq = contig + 1;
3486
+ if (beforeSeq !== undefined && nextSeq >= beforeSeq)
3487
+ break;
3488
+ if (!queue.has(nextSeq))
3489
+ break;
3490
+ seq = nextSeq;
3491
+ }
3492
+ if (seq === undefined)
3493
+ continue;
3494
+ const item = queue.get(seq);
3495
+ queue.delete(seq);
3496
+ if (!item)
3497
+ continue;
3498
+ if (client._pushedSeqs.get(ns)?.has(seq)) {
3499
+ client._clientLog.debug(`publish ordered drain skipped duplicate: ns=${ns}, seq=${seq}, event=${item.event}`);
3500
+ client._markOrderedSeqDelivered(ns, seq);
3501
+ continue;
3502
+ }
3503
+ const itemSource = item.source ?? source;
3504
+ const itemTrigger = this.deliveryChangedTrigger(itemSource);
3505
+ let itemContext = itemTrigger === rootTrigger ? context : undefined;
3506
+ if (itemTrigger === 'push' || itemTrigger === 'inline_push') {
3507
+ if (!itemContext) {
3508
+ itemContext = drainContexts.get(itemTrigger);
3509
+ if (!itemContext) {
3510
+ itemContext = { generation: this.deliveryChangedGeneration, changes: new Map() };
3511
+ drainContexts.set(itemTrigger, itemContext);
3512
+ }
3513
+ }
3514
+ }
3515
+ await this.publishOrderedQueueItem(ns, item.event, seq, item.payload, itemSource, pullResponse, itemContext);
3516
+ this.ensurePullOperationCurrent();
3517
+ this.markPublishedSeq(ns, seq);
3357
3518
  client._markOrderedSeqDelivered(ns, seq);
3358
- continue;
3519
+ delivered = true;
3520
+ client._clientLog.debug(`publish ordered drain delivered: ns=${ns}, seq=${seq}, event=${item.event}`);
3521
+ }
3522
+ }
3523
+ finally {
3524
+ for (const [trigger, drainContext] of drainContexts) {
3525
+ if (drainContext !== context)
3526
+ this.flushDeliveryChangedContext(drainContext, trigger);
3359
3527
  }
3360
- await this.publishOrderedQueueItem(ns, item.event, seq, item.payload, 'ordered-drain', pullResponse);
3361
- this.ensurePullOperationCurrent();
3362
- this.markPublishedSeq(ns, seq);
3363
- client._markOrderedSeqDelivered(ns, seq);
3364
- delivered = true;
3365
- client._clientLog.debug(`publish ordered drain delivered: ns=${ns}, seq=${seq}, event=${item.event}`);
3366
3528
  }
3367
3529
  if (queue.size === 0) {
3368
3530
  client._pendingOrderedMsgs.delete(ns);
@@ -3372,13 +3534,35 @@ export class MessageDeliveryEngine {
3372
3534
  }
3373
3535
  }
3374
3536
  }
3375
- async publishOrderedMessage(event, ns, seq, payload) {
3537
+ async publishOrderedMessage(event, ns, seq, payload, source = 'push') {
3538
+ const context = {
3539
+ generation: this.deliveryChangedGeneration,
3540
+ changes: new Map(),
3541
+ };
3542
+ try {
3543
+ return await this.publishOrderedMessageInternal(event, ns, seq, payload, source, context);
3544
+ }
3545
+ finally {
3546
+ const trigger = this.deliveryChangedTrigger(source);
3547
+ if (trigger === 'pull_drained' && context.generation === this.deliveryChangedGeneration) {
3548
+ const pending = this.pendingDeliveryChanges ?? new Map();
3549
+ this.pendingDeliveryChanges = pending;
3550
+ for (const [namespace, count] of context.changes) {
3551
+ pending.set(namespace, (pending.get(namespace) ?? 0) + count);
3552
+ }
3553
+ }
3554
+ else if (trigger && trigger !== 'pull_drained') {
3555
+ this.flushDeliveryChangedContext(context, trigger);
3556
+ }
3557
+ }
3558
+ }
3559
+ async publishOrderedMessageInternal(event, ns, seq, payload, source, context) {
3376
3560
  const client = this.runtime.client;
3377
3561
  this.ensurePullOperationCurrent();
3378
3562
  const seqNum = Number(seq);
3379
3563
  if (!Number.isFinite(seqNum) || !Number.isInteger(seqNum) || seqNum <= 0) {
3380
3564
  client._clientLog.debug(`publish ordered direct(no-seq): event=${event}, ns=${ns || '<none>'}, seq=${String(seq)}`);
3381
- await this.publishOrderedQueueItem(ns, event, seqNum, payload, 'ordered');
3565
+ await this.publishOrderedQueueItem(ns, event, seqNum, payload, source, false, context);
3382
3566
  this.ensurePullOperationCurrent();
3383
3567
  return true;
3384
3568
  }
@@ -3393,10 +3577,10 @@ export class MessageDeliveryEngine {
3393
3577
  const contig = client._seqTracker.getContiguousSeq(ns);
3394
3578
  if (seqNum > contig && seqNum !== contig + 1) {
3395
3579
  client._clientLog.debug(`publish ordered enqueue(gap): event=${event}, ns=${ns}, seq=${seqNum}, contiguous=${contig}`);
3396
- this.enqueueOrderedMessage(ns, event, seqNum, payload);
3580
+ this.enqueueOrderedMessage(ns, event, seqNum, payload, source);
3397
3581
  return false;
3398
3582
  }
3399
- await this.drainOrderedMessages(ns, seqNum);
3583
+ await this.drainOrderedMessages(ns, seqNum, false, true, source, context);
3400
3584
  this.ensurePullOperationCurrent();
3401
3585
  if (client._pushedSeqs.get(ns)?.has(seqNum)) {
3402
3586
  client._clientLog.debug(`publish ordered skipped after-drain duplicate: event=${event}, ns=${ns}, seq=${seqNum}`);
@@ -3406,12 +3590,12 @@ export class MessageDeliveryEngine {
3406
3590
  queue?.delete(seqNum);
3407
3591
  if (queue && queue.size === 0)
3408
3592
  client._pendingOrderedMsgs.delete(ns);
3409
- await this.publishOrderedQueueItem(ns, event, seqNum, payload, 'ordered');
3593
+ await this.publishOrderedQueueItem(ns, event, seqNum, payload, source, false, context);
3410
3594
  this.ensurePullOperationCurrent();
3411
3595
  this.markPublishedSeq(ns, seqNum);
3412
3596
  client._markOrderedSeqDelivered(ns, seqNum);
3413
3597
  client._clientLog.debug(`publish ordered delivered: event=${event}, ns=${ns}, seq=${seqNum}`);
3414
- await this.drainOrderedMessages(ns);
3598
+ await this.drainOrderedMessages(ns, undefined, false, true, source, context);
3415
3599
  if (!client._pendingOrderedMsgs.get(ns)) {
3416
3600
  this.ensurePullOperationCurrent();
3417
3601
  await this.saveSeqTrackerState();
@@ -3469,7 +3653,7 @@ export class MessageDeliveryEngine {
3469
3653
  client._pendingOrderedMsgs.delete(ns);
3470
3654
  return false;
3471
3655
  }
3472
- await this.drainOrderedMessages(ns, seqNum, true, persist);
3656
+ await this.drainOrderedMessages(ns, seqNum, true, persist, 'pull');
3473
3657
  this.ensurePullOperationCurrent();
3474
3658
  queue?.delete(seqNum);
3475
3659
  if (queue && queue.size === 0)
@@ -3479,7 +3663,7 @@ export class MessageDeliveryEngine {
3479
3663
  this.ensurePullOperationCurrent();
3480
3664
  this.markPublishedSeq(ns, seqNum);
3481
3665
  client._clientLog.debug(`publish pulled delivered: event=${event}, ns=${ns}, seq=${seqNum}`);
3482
- await this.drainOrderedMessages(ns, undefined, true, persist);
3666
+ await this.drainOrderedMessages(ns, undefined, true, persist, 'pull');
3483
3667
  this.ensurePullOperationCurrent();
3484
3668
  return recallPublished;
3485
3669
  }
@@ -3489,7 +3673,7 @@ export class MessageDeliveryEngine {
3489
3673
  this.ensurePullOperationCurrent();
3490
3674
  this.markPublishedSeq(ns, seqNum);
3491
3675
  client._clientLog.debug(`publish pulled delivered: event=${event}, ns=${ns}, seq=${seqNum}`);
3492
- await this.drainOrderedMessages(ns, undefined, true, persist);
3676
+ await this.drainOrderedMessages(ns, undefined, true, persist, 'pull');
3493
3677
  this.ensurePullOperationCurrent();
3494
3678
  return true;
3495
3679
  }