@agentunion/fastaun-browser 0.5.13 → 0.5.15

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 (43) hide show
  1. package/CHANGELOG.md +39 -0
  2. package/_packed_docs/CHANGELOG.md +39 -0
  3. 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 +85 -4
  4. package/_packed_docs/aun/346/265/213/350/257/225/350/277/220/350/241/214/346/214/207/345/215/227.md +1 -1
  5. package/dist/bundle.js +474 -321
  6. package/dist/client/delivery.d.ts +1 -0
  7. package/dist/client/delivery.d.ts.map +1 -1
  8. package/dist/client/delivery.js +55 -37
  9. package/dist/client/delivery.js.map +1 -1
  10. package/dist/client/lifecycle.d.ts.map +1 -1
  11. package/dist/client/lifecycle.js +5 -1
  12. package/dist/client/lifecycle.js.map +1 -1
  13. package/dist/client/rpc-pipeline.d.ts +3 -3
  14. package/dist/client/rpc-pipeline.d.ts.map +1 -1
  15. package/dist/client/rpc-pipeline.js +31 -39
  16. package/dist/client/rpc-pipeline.js.map +1 -1
  17. package/dist/client/v2-e2ee.d.ts.map +1 -1
  18. package/dist/client/v2-e2ee.js +24 -13
  19. package/dist/client/v2-e2ee.js.map +1 -1
  20. package/dist/client.d.ts.map +1 -1
  21. package/dist/client.js +43 -27
  22. package/dist/client.js.map +1 -1
  23. package/dist/events.d.ts +25 -12
  24. package/dist/events.d.ts.map +1 -1
  25. package/dist/events.js +164 -79
  26. package/dist/events.js.map +1 -1
  27. package/dist/group-index.js +1 -1
  28. package/dist/group-index.js.map +1 -1
  29. package/dist/logger.d.ts +9 -1
  30. package/dist/logger.d.ts.map +1 -1
  31. package/dist/logger.js +29 -7
  32. package/dist/logger.js.map +1 -1
  33. package/dist/result.d.ts +1 -2
  34. package/dist/result.d.ts.map +1 -1
  35. package/dist/result.js +2 -2
  36. package/dist/result.js.map +1 -1
  37. package/dist/transport.d.ts +5 -1
  38. package/dist/transport.d.ts.map +1 -1
  39. package/dist/transport.js +57 -32
  40. package/dist/transport.js.map +1 -1
  41. package/dist/version.d.ts +1 -1
  42. package/dist/version.js +1 -1
  43. package/package.json +1 -1
package/dist/bundle.js CHANGED
@@ -460,7 +460,7 @@ var init_indexeddb_store = __esm({
460
460
  });
461
461
 
462
462
  // src/version.ts
463
- var VERSION = "0.5.13";
463
+ var VERSION = "0.5.15";
464
464
 
465
465
  // src/types.ts
466
466
  var ConnectionState = /* @__PURE__ */ ((ConnectionState2) => {
@@ -778,36 +778,59 @@ var _noopLog = { error: () => {
778
778
  }, info: () => {
779
779
  }, debug: () => {
780
780
  } };
781
+ function createQueueState() {
782
+ return {
783
+ handlers: /* @__PURE__ */ new Map(),
784
+ queue: [],
785
+ draining: false,
786
+ drainScheduled: false,
787
+ handlerDepth: 0,
788
+ synchronousHandlerDepth: 0,
789
+ drainPromise: null,
790
+ drainResolve: null,
791
+ closing: false,
792
+ closed: false
793
+ };
794
+ }
795
+ function cloneEventPayload(value) {
796
+ if (Array.isArray(value)) return value.map((item) => cloneEventPayload(item));
797
+ if (value instanceof Error) {
798
+ const error = value;
799
+ const rawCode = error.localCode ?? error.stringCode ?? error.code;
800
+ const code = rawCode === void 0 || rawCode === null || rawCode === "" || rawCode === -1 ? "INTERNAL_ERROR" : rawCode;
801
+ return { code, message: error.message || error.name };
802
+ }
803
+ if (value !== null && typeof value === "object") {
804
+ const clone = {};
805
+ for (const [key, item] of Object.entries(value)) clone[key] = cloneEventPayload(item);
806
+ return clone;
807
+ }
808
+ return value;
809
+ }
781
810
  var Subscription = class {
782
- constructor(dispatcher, event, handler) {
811
+ constructor(dispatcher, event, handler, protocol = false) {
783
812
  __publicField(this, "_dispatcher");
784
813
  __publicField(this, "_event");
785
814
  __publicField(this, "_handler");
815
+ __publicField(this, "_protocol");
786
816
  __publicField(this, "_active", true);
787
817
  this._dispatcher = dispatcher;
788
818
  this._event = event;
789
819
  this._handler = handler;
820
+ this._protocol = protocol;
790
821
  }
791
822
  /** 取消订阅 */
792
823
  unsubscribe() {
793
824
  if (!this._active) return;
794
- this._dispatcher.unsubscribe(this._event, this._handler);
825
+ this._dispatcher.unsubscribe(this._event, this._handler, this._protocol);
795
826
  this._active = false;
796
827
  }
797
828
  };
798
829
  var EventDispatcher = class {
799
830
  constructor() {
800
831
  __publicField(this, "_log", _noopLog);
801
- __publicField(this, "_handlers", /* @__PURE__ */ new Map());
802
- __publicField(this, "_queue", []);
803
- __publicField(this, "_draining", false);
804
- __publicField(this, "_drainScheduled", false);
805
- __publicField(this, "_handlerDepth", 0);
806
- __publicField(this, "_synchronousHandlerDepth", 0);
807
- __publicField(this, "_drainPromise", null);
808
- __publicField(this, "_drainResolve", null);
809
- __publicField(this, "_closing", false);
810
- __publicField(this, "_closed", false);
832
+ __publicField(this, "_app", createQueueState());
833
+ __publicField(this, "_protocol", createQueueState());
811
834
  }
812
835
  setLogger(log) {
813
836
  this._log = log;
@@ -820,99 +843,148 @@ var EventDispatcher = class {
820
843
  * 对象调用 unsubscribe() 来取消。
821
844
  */
822
845
  subscribe(event, handler) {
823
- const list = this._handlers.get(event) ?? [];
846
+ return this._subscribe(this._app, event, handler, false);
847
+ }
848
+ /** 订阅 SDK 内部协议事件。 */
849
+ subscribeProtocol(event, handler) {
850
+ return this._subscribe(this._protocol, event, handler, true);
851
+ }
852
+ _subscribe(state, event, handler, protocol) {
853
+ const list = state.handlers.get(event) ?? [];
824
854
  list.push(handler);
825
- this._handlers.set(event, list);
826
- return new Subscription(this, event, handler);
855
+ state.handlers.set(event, list);
856
+ return new Subscription(this, event, handler, protocol);
827
857
  }
828
858
  /** 取消订阅 */
829
- unsubscribe(event, handler) {
830
- const list = this._handlers.get(event);
859
+ unsubscribe(event, handler, protocol = false) {
860
+ const state = protocol ? this._protocol : this._app;
861
+ const list = state.handlers.get(event);
831
862
  if (!list) return;
832
863
  const filtered = list.filter((h) => h !== handler);
833
864
  if (filtered.length > 0) {
834
- this._handlers.set(event, filtered);
865
+ state.handlers.set(event, filtered);
835
866
  } else {
836
- this._handlers.delete(event);
867
+ state.handlers.delete(event);
837
868
  }
838
869
  }
870
+ /** 取消协议事件订阅。 */
871
+ unsubscribeProtocol(event, handler) {
872
+ this.unsubscribe(event, handler, true);
873
+ }
839
874
  /**
840
875
  * 发布事件。事件总是异步进入 FIFO 队列;调用方 await 时等待该事件处理完成。
841
876
  * drain 中派生事件只入队,不等待自身,避免事件处理器互相等待形成死锁。
842
877
  */
843
878
  async publish(event, payload) {
844
- if (this._closed || this._closing) return;
879
+ await this._publish(this._app, event, payload);
880
+ }
881
+ /** 发布协议事件。调用方 await 时等待协议处理完成。 */
882
+ async publishProtocol(event, payload) {
883
+ await this._publish(this._protocol, event, payload);
884
+ }
885
+ async _publish(state, event, payload) {
886
+ if (state.closed || state.closing) return;
845
887
  let resolveItem;
846
888
  const itemDone = new Promise((resolve) => {
847
889
  resolveItem = resolve;
848
890
  });
849
- this._queue.push({
850
- run: () => this.dispatchNow(event, payload),
891
+ state.queue.push({
892
+ run: () => this.dispatchNow(state, event, payload),
851
893
  resolve: resolveItem
852
894
  });
853
- if (this._handlerDepth > 0) return;
854
- if (this._drainPromise === null) {
855
- this._drainPromise = new Promise((resolve) => {
856
- this._drainResolve = resolve;
895
+ if (state.handlerDepth > 0) return;
896
+ if (state.drainPromise === null) {
897
+ state.drainPromise = new Promise((resolve) => {
898
+ state.drainResolve = resolve;
857
899
  });
858
900
  }
859
- this.scheduleDrain();
901
+ this.scheduleDrain(state);
902
+ if (state === this._app && this._protocol.handlerDepth > 0) return;
860
903
  await itemDone;
861
904
  }
862
905
  /** 将事件放入异步 FIFO 队列,不等待处理器执行完成。 */
863
906
  enqueue(event, payload) {
864
- void this.publish(event, payload).catch((exc) => {
907
+ this._enqueue(this._app, event, payload);
908
+ }
909
+ /** 将协议事件放入独立异步 FIFO 队列,不等待处理器执行完成。 */
910
+ enqueueProtocol(event, payload) {
911
+ this._enqueue(this._protocol, event, payload);
912
+ }
913
+ _enqueue(state, event, payload) {
914
+ const publish = state === this._protocol ? this.publishProtocol(event, payload) : this.publish(event, payload);
915
+ void publish.catch((exc) => {
865
916
  this._log.warn(`event ${event} enqueue failed:`, exc);
866
917
  });
867
918
  }
868
919
  /** 将非事件 observer 放入同一 FIFO 队列。 */
869
920
  enqueueTask(task) {
870
- if (this._closed || this._closing) return;
871
- this._queue.push({
872
- run: () => this.dispatchTask(task),
921
+ this._enqueueTask(this._app, task);
922
+ }
923
+ /** 将协议层 observer 放入协议 FIFO 队列。 */
924
+ enqueueProtocolTask(task) {
925
+ this._enqueueTask(this._protocol, task);
926
+ }
927
+ _enqueueTask(state, task) {
928
+ if (state.closed || state.closing) return;
929
+ state.queue.push({
930
+ run: () => this.dispatchTask(state, task),
873
931
  resolve: () => {
874
932
  }
875
933
  });
876
- if (this._drainPromise === null) {
877
- this._drainPromise = new Promise((resolve) => {
878
- this._drainResolve = resolve;
934
+ if (state.drainPromise === null) {
935
+ state.drainPromise = new Promise((resolve) => {
936
+ state.drainResolve = resolve;
879
937
  });
880
938
  }
881
- this.scheduleDrain();
939
+ this.scheduleDrain(state);
882
940
  }
883
941
  /** 关闭调度器,排空已经入队的应用事件后拒绝后续事件。 */
884
942
  async close() {
885
- if (this._closed) return;
886
- this._closing = true;
887
- if (this._synchronousHandlerDepth > 0) return;
888
- if (this._drainPromise !== null) await this._drainPromise;
889
- this.finishClose();
943
+ await this._close(this._app);
944
+ }
945
+ /** 关闭协议调度器,排空已经入队的协议事件后拒绝后续事件。 */
946
+ async closeProtocol() {
947
+ await this._close(this._protocol);
948
+ }
949
+ async _close(state) {
950
+ if (state.closed) return;
951
+ state.closing = true;
952
+ if (state.synchronousHandlerDepth > 0) return;
953
+ if (state.drainPromise !== null) await state.drainPromise;
954
+ this.finishClose(state);
890
955
  }
891
956
  /** 等待当前队列排空;事件 handler 重入时直接返回,避免自等待。 */
892
957
  async flush() {
893
- if (this._synchronousHandlerDepth > 0) return;
894
- if (this._drainPromise !== null) await this._drainPromise;
958
+ await this._flush(this._app);
959
+ }
960
+ /** 等待协议层当前队列排空。 */
961
+ async flushProtocol() {
962
+ await this._flush(this._protocol);
963
+ }
964
+ async _flush(state) {
965
+ if (state.synchronousHandlerDepth > 0) return;
966
+ if (state.drainPromise !== null) await state.drainPromise;
895
967
  await Promise.resolve();
896
968
  }
897
- finishClose() {
898
- if (!this._closing || this._closed || this._draining || this._drainScheduled || this._queue.length > 0) return;
899
- this._closed = true;
900
- this._handlers.clear();
969
+ finishClose(state) {
970
+ if (!state.closing || state.closed || state.draining || state.drainScheduled || state.queue.length > 0) return;
971
+ state.closed = true;
972
+ state.handlers.clear();
901
973
  }
902
- scheduleDrain() {
903
- if (this._draining || this._drainScheduled || this._queue.length === 0) return;
904
- this._drainScheduled = true;
974
+ scheduleDrain(state) {
975
+ if (state.draining || state.drainScheduled || state.queue.length === 0) return;
976
+ state.drainScheduled = true;
905
977
  queueMicrotask(() => {
906
- this._drainScheduled = false;
907
- void this._drain();
978
+ state.drainScheduled = false;
979
+ void this._drain(state);
908
980
  });
909
981
  }
910
- async _drain() {
911
- if (this._draining) return;
912
- this._draining = true;
982
+ async _drain(state) {
983
+ if (state.draining) return;
984
+ state.draining = true;
913
985
  try {
914
- while (this._queue.length > 0) {
915
- const item = this._queue.shift();
986
+ while (state.queue.length > 0) {
987
+ const item = state.queue.shift();
916
988
  try {
917
989
  await item.run();
918
990
  } catch (exc) {
@@ -922,70 +994,74 @@ var EventDispatcher = class {
922
994
  }
923
995
  }
924
996
  } finally {
925
- this._draining = false;
926
- const resolve = this._drainResolve;
927
- this._drainResolve = null;
928
- this._drainPromise = null;
997
+ state.draining = false;
998
+ const resolve = state.drainResolve;
999
+ state.drainResolve = null;
1000
+ state.drainPromise = null;
929
1001
  resolve?.();
930
- this.finishClose();
931
- if (this._queue.length > 0 && !this._closed) {
932
- if (this._drainPromise === null) {
933
- this._drainPromise = new Promise((nextResolve) => {
934
- this._drainResolve = nextResolve;
1002
+ this.finishClose(state);
1003
+ if (state.queue.length > 0 && !state.closed) {
1004
+ if (state.drainPromise === null) {
1005
+ state.drainPromise = new Promise((nextResolve) => {
1006
+ state.drainResolve = nextResolve;
935
1007
  });
936
1008
  }
937
- this.scheduleDrain();
1009
+ this.scheduleDrain(state);
938
1010
  }
939
1011
  }
940
1012
  }
941
1013
  /** 当前是否正在调用应用 handler 或 observer。供生命周期入口识别重入。 */
942
1014
  isDispatchingHandler() {
943
- return this._handlerDepth > 0;
1015
+ return this._app.handlerDepth > 0 || this._protocol.handlerDepth > 0;
944
1016
  }
945
- async dispatchTask(task) {
1017
+ async dispatchTask(state, task) {
946
1018
  let result;
947
- this._handlerDepth += 1;
1019
+ state.handlerDepth += 1;
948
1020
  try {
949
- this._synchronousHandlerDepth += 1;
1021
+ state.synchronousHandlerDepth += 1;
950
1022
  result = task();
951
1023
  } catch (exc) {
952
1024
  this._log.warn("event task execution exception:", exc);
953
- this._handlerDepth -= 1;
1025
+ state.handlerDepth -= 1;
954
1026
  return;
955
1027
  } finally {
956
- this._synchronousHandlerDepth -= 1;
1028
+ state.synchronousHandlerDepth -= 1;
957
1029
  }
958
1030
  try {
959
1031
  await result;
960
1032
  } catch (exc) {
961
1033
  this._log.warn("event task execution exception:", exc);
962
1034
  } finally {
963
- this._handlerDepth -= 1;
1035
+ state.handlerDepth -= 1;
964
1036
  }
965
1037
  }
966
- async dispatchNow(event, payload) {
967
- const handlers = [...this._handlers.get(event) ?? []];
1038
+ async dispatchNow(state, event, payload) {
1039
+ const handlers = [...state.handlers.get(event) ?? []];
1040
+ const applicationPayload = state === this._protocol && this._app.handlers.has(event) ? cloneEventPayload(payload) : void 0;
968
1041
  for (const handler of handlers) {
969
1042
  let result;
970
- this._handlerDepth += 1;
1043
+ state.handlerDepth += 1;
971
1044
  try {
972
- this._synchronousHandlerDepth += 1;
1045
+ state.synchronousHandlerDepth += 1;
973
1046
  result = handler(payload);
974
1047
  } catch (exc) {
975
1048
  this._log.warn(`event ${event} handler execution exception:`, exc);
976
- this._handlerDepth -= 1;
1049
+ state.handlerDepth -= 1;
977
1050
  continue;
978
1051
  } finally {
979
- this._synchronousHandlerDepth -= 1;
1052
+ state.synchronousHandlerDepth -= 1;
980
1053
  }
981
1054
  try {
982
1055
  await result;
983
1056
  } catch (exc) {
984
1057
  this._log.warn(`event ${event} handler execution exception:`, exc);
985
1058
  } finally {
986
- this._handlerDepth -= 1;
1059
+ state.handlerDepth -= 1;
987
1060
  }
988
1061
  }
1062
+ if (applicationPayload !== void 0) {
1063
+ this.enqueue(event, applicationPayload);
1064
+ }
989
1065
  }
990
1066
  };
991
1067
 
@@ -1292,6 +1368,119 @@ var GatewayDiscovery = class {
1292
1368
  }
1293
1369
  };
1294
1370
 
1371
+ // src/logger.ts
1372
+ function trafficLogContext(direction, data) {
1373
+ const params2 = data && typeof data === "object" && !Array.isArray(data) ? data : {};
1374
+ const target = params2.target && typeof params2.target === "object" ? params2.target : {};
1375
+ const notify = params2._notify && typeof params2._notify === "object" ? params2._notify : {};
1376
+ const text3 = (value) => typeof value === "string" ? value.trim() : "";
1377
+ const group = text3(params2.group_aid) || text3(params2.group_id) || text3(target.group_aid) || text3(target.group_id);
1378
+ const groupAid = normalizeGroupAid(group);
1379
+ const peerAid = group ? groupAid.includes(".") && !groupAid.includes("/") ? groupAid : "" : direction === "outbound" ? text3(target.aid) || text3(params2.to) || text3(params2.to_aid) || text3(params2.peer_aid) : text3(notify.from_aid) || text3(params2.from_aid) || text3(params2.sender_aid) || text3(params2.from);
1380
+ return { direction, peerAid };
1381
+ }
1382
+ function withLogContext(logger, context) {
1383
+ return logger.withContext?.(context) ?? logger;
1384
+ }
1385
+ var LEVEL_ORDER = { DEBUG: 0, INFO: 1, WARN: 2, ERROR: 3 };
1386
+ function formatMessage(template, args) {
1387
+ if (args.length === 0) return template;
1388
+ let i = 0;
1389
+ let result = "";
1390
+ let consumed = 0;
1391
+ for (let p = 0; p < template.length; p++) {
1392
+ const ch = template[p];
1393
+ if (ch === "%" && template[p + 1] === "s" && i < args.length) {
1394
+ result += String(args[i++]);
1395
+ consumed++;
1396
+ p++;
1397
+ } else {
1398
+ result += ch;
1399
+ }
1400
+ }
1401
+ if (i < args.length) {
1402
+ const tail = args.slice(i).map((a) => a instanceof Error ? a.message : String(a)).join(" ");
1403
+ if (tail) result += " " + tail;
1404
+ }
1405
+ return result;
1406
+ }
1407
+ var AUNLogger = class {
1408
+ constructor(opts) {
1409
+ __publicField(this, "_debug");
1410
+ __publicField(this, "_aunPath");
1411
+ __publicField(this, "_deviceId", "-");
1412
+ __publicField(this, "_aid", null);
1413
+ __publicField(this, "_minLevel");
1414
+ this._debug = opts.debug;
1415
+ this._aunPath = String(opts.aunPath || "-");
1416
+ this._minLevel = this._debug ? LEVEL_ORDER.DEBUG : LEVEL_ORDER.INFO;
1417
+ }
1418
+ for(module, context) {
1419
+ const snapshot = context ? { ...context, aid: context.aid ?? this._aid ?? "" } : void 0;
1420
+ return {
1421
+ error: (msg, ...args) => this._emit("ERROR", module, msg, args, snapshot),
1422
+ warn: (msg, ...args) => this._emit("WARN", module, msg, args, snapshot),
1423
+ info: (msg, ...args) => this._emit("INFO", module, msg, args, snapshot),
1424
+ debug: (msg, ...args) => this._emit("DEBUG", module, msg, args, snapshot),
1425
+ isDebugEnabled: () => this.isDebugEnabled(),
1426
+ withContext: (next) => this.for(module, { ...next, aid: next.aid ?? snapshot?.aid })
1427
+ };
1428
+ }
1429
+ isDebugEnabled() {
1430
+ return this._debug && this._minLevel <= LEVEL_ORDER.DEBUG;
1431
+ }
1432
+ bindAid(aid) {
1433
+ this._aid = aid || null;
1434
+ }
1435
+ bindDeviceId(deviceId) {
1436
+ this._deviceId = String(deviceId || "").trim() || "-";
1437
+ }
1438
+ close() {
1439
+ }
1440
+ _emit(level, module, msg, args, context) {
1441
+ if (LEVEL_ORDER[level] < this._minLevel) return;
1442
+ if (level === "DEBUG" && !this._debug) return;
1443
+ const { date, time, ms } = this._now();
1444
+ const head = `[${date} ${time}.${ms}][${level}][${module}][aun_path=${this._aunPath || "-"}][device_id=${this._deviceId || "-"}]`;
1445
+ const aidPart = context ? ` [${context.aid || "-"} ${context.direction === "outbound" ? "->" : "<-"} ${context.peerAid || "-"}]` : this._aid ? ` [${this._aid}]` : "";
1446
+ const formatted = formatMessage(msg, args);
1447
+ const line = `${head}${aidPart} ${formatted}`;
1448
+ let errArg;
1449
+ for (let i = args.length - 1; i >= 0; i--) {
1450
+ if (args[i] instanceof Error) {
1451
+ errArg = args[i];
1452
+ break;
1453
+ }
1454
+ }
1455
+ switch (level) {
1456
+ case "ERROR":
1457
+ if (errArg) {
1458
+ console.error(line, errArg);
1459
+ } else {
1460
+ console.error(line);
1461
+ }
1462
+ break;
1463
+ case "WARN":
1464
+ console.warn(line);
1465
+ break;
1466
+ case "INFO":
1467
+ console.info(line);
1468
+ break;
1469
+ case "DEBUG":
1470
+ console.debug(line);
1471
+ break;
1472
+ }
1473
+ }
1474
+ _now() {
1475
+ const d = /* @__PURE__ */ new Date();
1476
+ const pad = (n, w = 2) => String(n).padStart(w, "0");
1477
+ const date = `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())}`;
1478
+ const time = `${pad(d.getHours())}:${pad(d.getMinutes())}:${pad(d.getSeconds())}`;
1479
+ const ms = pad(d.getMilliseconds(), 3);
1480
+ return { date, time, ms };
1481
+ }
1482
+ };
1483
+
1295
1484
  // src/transport.ts
1296
1485
  var MAX_WS_PAYLOAD_SIZE = 1e6;
1297
1486
  var MAX_RPC_INFLIGHT = 16;
@@ -1835,6 +2024,7 @@ var RPCTransport = class {
1835
2024
  __publicField(this, "_timeout");
1836
2025
  __publicField(this, "_connectTimeout");
1837
2026
  __publicField(this, "_onDisconnect");
2027
+ __publicField(this, "_onDisconnectIsProtocol", false);
1838
2028
  __publicField(this, "_ws", null);
1839
2029
  __publicField(this, "_closed", true);
1840
2030
  __publicField(this, "_lastCloseCode", null);
@@ -1852,6 +2042,7 @@ var RPCTransport = class {
1852
2042
  // Gateway 在 RPC envelope 注入 _meta 字段(与 result 同级),由 client 层 observer 接收。
1853
2043
  // 注入失败 / 字段缺失时 observer 不会被调用,不影响业务路径。
1854
2044
  __publicField(this, "_metaObserver", null);
2045
+ __publicField(this, "_metaObserverIsProtocol", false);
1855
2046
  // Trace 模式:off / log / diag
1856
2047
  __publicField(this, "_traceMode", "off");
1857
2048
  // Trace observer:observer(traceInfo) 在每次 RPC/事件携带 _trace 时调用
@@ -1861,13 +2052,17 @@ var RPCTransport = class {
1861
2052
  __publicField(this, "_actorTail", Promise.resolve());
1862
2053
  __publicField(this, "_actorBusy", false);
1863
2054
  this._dispatcher = opts.eventDispatcher;
1864
- this._timeout = opts.timeout ?? 10;
2055
+ this._timeout = opts.timeout ?? 35;
1865
2056
  this._connectTimeout = opts.timeout ?? 10;
1866
2057
  this._onDisconnect = opts.onDisconnect ?? null;
1867
2058
  }
1868
2059
  setLogger(log) {
1869
2060
  this._log = log;
1870
2061
  }
2062
+ setProtocolDisconnectCallback(callback) {
2063
+ this._onDisconnect = callback;
2064
+ this._onDisconnectIsProtocol = true;
2065
+ }
1871
2066
  /** 设置默认超时(秒) */
1872
2067
  setTimeout(timeout) {
1873
2068
  this._timeout = timeout;
@@ -1888,19 +2083,26 @@ var RPCTransport = class {
1888
2083
  */
1889
2084
  setMetaObserver(observer) {
1890
2085
  this._metaObserver = observer;
2086
+ this._metaObserverIsProtocol = false;
2087
+ }
2088
+ setProtocolMetaObserver(observer) {
2089
+ this._metaObserver = observer;
2090
+ this._metaObserverIsProtocol = true;
1891
2091
  }
1892
2092
  _notifyMetaObserver(message) {
1893
2093
  const observer = this._metaObserver;
1894
2094
  if (observer === null) return;
1895
2095
  const meta = message._meta;
1896
2096
  if (!isJsonObject(meta)) return;
1897
- this._dispatcher.enqueueTask(async () => {
2097
+ const task = async () => {
1898
2098
  try {
1899
2099
  await observer(meta);
1900
2100
  } catch (exc) {
1901
2101
  this._log.debug(`meta_observer raised: ${String(exc)}`);
1902
2102
  }
1903
- });
2103
+ };
2104
+ if (this._metaObserverIsProtocol) this._dispatcher.enqueueProtocolTask(task);
2105
+ else this._dispatcher.enqueueTask(task);
1904
2106
  }
1905
2107
  /** 设置 trace 模式:off / log / diag */
1906
2108
  setTraceMode(mode) {
@@ -2170,6 +2372,9 @@ var RPCTransport = class {
2170
2372
  const localParams = sendParams;
2171
2373
  const backgroundRpc = background || localParams._rpc_background === true;
2172
2374
  delete localParams._rpc_background;
2375
+ const requestContext = trafficLogContext("outbound", sendParams);
2376
+ const requestLog = withLogContext(this._log, requestContext);
2377
+ const responseLog = withLogContext(requestLog, { direction: "inbound", peerAid: requestContext.peerAid });
2173
2378
  if (effectiveTraceMode !== "off") {
2174
2379
  traceId = typeof crypto !== "undefined" && crypto.randomUUID ? crypto.randomUUID().replace(/-/g, "") : Array.from({ length: 32 }, () => Math.floor(Math.random() * 16).toString(16)).join("");
2175
2380
  const tracePayload = { trace_id: traceId, mode: effectiveTraceMode };
@@ -2177,7 +2382,7 @@ var RPCTransport = class {
2177
2382
  tracePayload.spans = [{ node: "sdk", ts: tStart, action: "send" }];
2178
2383
  }
2179
2384
  localParams._trace = tracePayload;
2180
- this._log.info(`[trace=${traceId}] rpc_send method=${method} rpc_id=${rpcId}`);
2385
+ requestLog.info(`[trace=${traceId}] rpc_send method=${method} rpc_id=${rpcId}`);
2181
2386
  }
2182
2387
  const payload = JSON.stringify({
2183
2388
  jsonrpc: "2.0",
@@ -2193,7 +2398,7 @@ var RPCTransport = class {
2193
2398
  const promise = new Promise((resolve, reject) => {
2194
2399
  const timer = globalThis.setTimeout(() => {
2195
2400
  this._removeRpc(rpcId, pending);
2196
- this._log.warn(`RPC timeout: method=${method}, id=${rpcId}, elapsed=${Date.now() - tStart}ms, timeout=${effectiveTimeout}ms`);
2401
+ requestLog.warn(`RPC timeout: method=${method}, id=${rpcId}, elapsed=${Date.now() - tStart}ms, timeout=${effectiveTimeout}ms`);
2197
2402
  reject(new TimeoutError(`rpc timeout: ${method}`, { retryable: true }));
2198
2403
  this._drainRpcQueue();
2199
2404
  }, effectiveTimeout);
@@ -2202,28 +2407,28 @@ var RPCTransport = class {
2202
2407
  clearTimeout(timer);
2203
2408
  const elapsed = Date.now() - tStart;
2204
2409
  if (response.error !== void 0) {
2205
- this._log.debug(`RPC error response: method=${method}, id=${rpcId}, elapsed=${elapsed}ms, error=${JSON.stringify(response.error)}`);
2410
+ responseLog.debug(`RPC error response: method=${method}, id=${rpcId}, elapsed=${elapsed}ms, error=${JSON.stringify(response.error)}`);
2206
2411
  if (traceId) {
2207
- this._log.info(`[trace=${traceId}] rpc_recv method=${method} rpc_id=${rpcId} duration_ms=${elapsed} status=error`);
2412
+ responseLog.info(`[trace=${traceId}] rpc_recv method=${method} rpc_id=${rpcId} duration_ms=${elapsed} status=error`);
2208
2413
  }
2209
2414
  const respTrace = response._trace;
2210
2415
  if (respTrace && typeof respTrace === "object" && !Array.isArray(respTrace)) {
2211
- this._handleResponseTrace(method, "error", elapsed, respTrace);
2416
+ this._handleResponseTrace(method, "error", elapsed, respTrace, responseLog);
2212
2417
  }
2213
2418
  reject(mapRemoteError(response.error));
2214
2419
  } else if (response.result !== void 0) {
2215
- this._log.debug(`RPC response ok: method=${method}, id=${rpcId}, elapsed=${elapsed}ms ${summarizeDict(response.result, DIAG_RESULT_FIELDS)}`);
2420
+ responseLog.debug(`RPC response ok: method=${method}, id=${rpcId}, elapsed=${elapsed}ms ${summarizeDict(response.result, DIAG_RESULT_FIELDS)}`);
2216
2421
  if (traceId) {
2217
- this._log.info(`[trace=${traceId}] rpc_recv method=${method} rpc_id=${rpcId} duration_ms=${elapsed} status=ok`);
2422
+ responseLog.info(`[trace=${traceId}] rpc_recv method=${method} rpc_id=${rpcId} duration_ms=${elapsed} status=ok`);
2218
2423
  }
2219
2424
  this._notifyMetaObserver(response);
2220
2425
  const respTrace = response._trace;
2221
2426
  if (respTrace && typeof respTrace === "object" && !Array.isArray(respTrace)) {
2222
- this._handleResponseTrace(method, "ok", elapsed, respTrace);
2427
+ this._handleResponseTrace(method, "ok", elapsed, respTrace, responseLog);
2223
2428
  }
2224
2429
  resolve(response.result);
2225
2430
  } else {
2226
- this._log.warn(`RPC response missing result or error: method=${method}, id=${rpcId}, elapsed=${elapsed}ms`);
2431
+ responseLog.warn(`RPC response missing result or error: method=${method}, id=${rpcId}, elapsed=${elapsed}ms`);
2227
2432
  reject(new SerializationError(`rpc response missing result and error: ${method}`));
2228
2433
  }
2229
2434
  },
@@ -2246,7 +2451,8 @@ var RPCTransport = class {
2246
2451
  pending,
2247
2452
  tStart,
2248
2453
  timeoutMs: effectiveTimeout,
2249
- background: true
2454
+ background: true,
2455
+ logger: requestLog
2250
2456
  });
2251
2457
  } else {
2252
2458
  this._rpcQueue.push({
@@ -2256,7 +2462,8 @@ var RPCTransport = class {
2256
2462
  pending,
2257
2463
  tStart,
2258
2464
  timeoutMs: effectiveTimeout,
2259
- background: false
2465
+ background: false,
2466
+ logger: requestLog
2260
2467
  });
2261
2468
  }
2262
2469
  this._drainRpcQueue();
@@ -2287,8 +2494,9 @@ var RPCTransport = class {
2287
2494
  if (payloadSize > MAX_WS_PAYLOAD_SIZE) {
2288
2495
  throw new ValidationError("payload is too large");
2289
2496
  }
2497
+ const notifyLog = withLogContext(this._log, trafficLogContext("outbound", params2 ?? {}));
2290
2498
  await this._sendText(payload, `notification ${normalizedMethod}`);
2291
- this._log.debug(`notification sent: method=${normalizedMethod}, size=${payloadSize}`);
2499
+ notifyLog.debug(`notification sent: method=${normalizedMethod}, size=${payloadSize}`);
2292
2500
  }
2293
2501
  _enqueueSend(task) {
2294
2502
  const run = this._sendChain.then(() => Promise.resolve(task()), () => Promise.resolve(task()));
@@ -2440,7 +2648,7 @@ var RPCTransport = class {
2440
2648
  const elapsed = Date.now() - entry.tStart;
2441
2649
  if (elapsed >= entry.timeoutMs) {
2442
2650
  clearTimeout(entry.pending.timer);
2443
- this._log.warn(`RPC queue timeout: method=${entry.method}, id=${entry.rpcId}, elapsed=${elapsed}ms, timeout=${entry.timeoutMs}ms`);
2651
+ entry.logger.warn(`RPC queue timeout: method=${entry.method}, id=${entry.rpcId}, elapsed=${elapsed}ms, timeout=${entry.timeoutMs}ms`);
2444
2652
  entry.pending.reject(new TimeoutError(`rpc timeout before send: ${entry.method}`, { retryable: true }));
2445
2653
  continue;
2446
2654
  }
@@ -2453,11 +2661,11 @@ var RPCTransport = class {
2453
2661
  `rpc ${entry.method}`,
2454
2662
  () => this._pending.get(entry.rpcId) === entry.pending
2455
2663
  ).then(() => {
2456
- this._log.debug(`RPC request sent: method=${entry.method}, id=${entry.rpcId}, background=${entry.background}`);
2664
+ entry.logger.debug(`RPC request sent: method=${entry.method}, id=${entry.rpcId}, background=${entry.background}`);
2457
2665
  }).catch((err) => {
2458
2666
  if (this._pending.get(entry.rpcId) !== entry.pending) return;
2459
2667
  this._removeRpc(entry.rpcId, entry.pending);
2460
- this._log.error(`RPC send failed: method=${entry.method}, id=${entry.rpcId}, error=${String(err)}`, err instanceof Error ? err : void 0);
2668
+ entry.logger.error(`RPC send failed: method=${entry.method}, id=${entry.rpcId}, error=${String(err)}`, err instanceof Error ? err : void 0);
2461
2669
  entry.pending.reject(
2462
2670
  err instanceof ConnectionError ? err : new ConnectionError(`failed to send rpc ${entry.method}: ${err instanceof Error ? err.message : String(err)}`)
2463
2671
  );
@@ -2469,7 +2677,7 @@ var RPCTransport = class {
2469
2677
  }
2470
2678
  }
2471
2679
  /** 处理 RPC 响应中的 _trace 字段:追加 sdk.recv span,格式化输出,通知 observer */
2472
- _handleResponseTrace(method, status, elapsedMs, respTrace) {
2680
+ _handleResponseTrace(method, status, elapsedMs, respTrace, logger = this._log) {
2473
2681
  try {
2474
2682
  const sdkRecvSpan = {
2475
2683
  node: "sdk",
@@ -2480,7 +2688,7 @@ var RPCTransport = class {
2480
2688
  const existingSpans = Array.isArray(respTrace.spans) ? respTrace.spans : [];
2481
2689
  const spans = [...existingSpans, sdkRecvSpan];
2482
2690
  const enriched = { ...respTrace, spans };
2483
- this._log.info(traceDisplay(method, status, elapsedMs, respTrace, spans));
2691
+ logger.info(traceDisplay(method, status, elapsedMs, respTrace, spans));
2484
2692
  if (this._traceObserver !== null) {
2485
2693
  const observer = this._traceObserver;
2486
2694
  this._dispatcher.enqueueTask(async () => {
@@ -2492,7 +2700,7 @@ var RPCTransport = class {
2492
2700
  });
2493
2701
  }
2494
2702
  } catch (err) {
2495
- this._log.debug(`trace handling raised: ${err instanceof Error ? err.message : String(err)}`);
2703
+ logger.debug(`trace handling raised: ${err instanceof Error ? err.message : String(err)}`);
2496
2704
  }
2497
2705
  }
2498
2706
  // ── 内部消息处理 ──────────────────────────────────
@@ -2532,15 +2740,17 @@ var RPCTransport = class {
2532
2740
  const error = new ConnectionError(`websocket closed: code=${event.code} reason=${event.reason}`);
2533
2741
  if (this._onDisconnect) {
2534
2742
  const onDisconnect = this._onDisconnect;
2535
- this._dispatcher.enqueueTask(async () => {
2743
+ const task = async () => {
2536
2744
  try {
2537
2745
  await onDisconnect(error, event.code);
2538
2746
  } catch (exc) {
2539
2747
  this._log.warn("[aun_core.transport] disconnect callback exception:", exc);
2540
2748
  }
2541
- });
2749
+ };
2750
+ if (this._onDisconnectIsProtocol) this._dispatcher.enqueueProtocolTask(task);
2751
+ else this._dispatcher.enqueueTask(task);
2542
2752
  }
2543
- this._dispatcher.enqueue("connection.error", { error });
2753
+ this._dispatcher.enqueueProtocol("connection.error", { error });
2544
2754
  }
2545
2755
  }
2546
2756
  _notConnectedError() {
@@ -2560,21 +2770,22 @@ var RPCTransport = class {
2560
2770
  pending.resolve(message);
2561
2771
  this._drainRpcQueue();
2562
2772
  } else {
2563
- this._log.warn("[aun_core.transport] recv unknown rpc response (maybe arrived after timeout): id=" + rpcId);
2773
+ withLogContext(this._log, { direction: "inbound", peerAid: "" }).warn("[aun_core.transport] recv unknown rpc response (maybe arrived after timeout): id=" + rpcId);
2564
2774
  }
2565
2775
  return;
2566
2776
  }
2567
2777
  const method = String(message.method ?? "");
2568
2778
  if (method === "challenge") {
2569
2779
  this._challenge = message;
2570
- this._log.debug("challenge received");
2571
- this._dispatcher.enqueue("connection.challenge", message.params ?? {});
2780
+ withLogContext(this._log, trafficLogContext("inbound", message.params ?? message)).debug("challenge received");
2781
+ this._dispatcher.enqueueProtocol("connection.challenge", message.params ?? {});
2572
2782
  return;
2573
2783
  }
2574
2784
  if (method.startsWith("event/")) {
2575
2785
  const protocolEvent = method.slice(6);
2576
2786
  const sdkEvent = EVENT_NAME_MAP[protocolEvent] ?? protocolEvent;
2577
- this._log.debug(`event recv: event=${sdkEvent} ${summarizeDict(message.params, DIAG_RESULT_FIELDS)}`);
2787
+ const eventLog = withLogContext(this._log, trafficLogContext("inbound", message.params ?? message));
2788
+ eventLog.debug(`event recv: event=${sdkEvent} ${summarizeDict(message.params, DIAG_RESULT_FIELDS)}`);
2578
2789
  this._notifyMetaObserver(message);
2579
2790
  const params2 = message.params ?? {};
2580
2791
  if ("_trace" in params2) {
@@ -2592,19 +2803,19 @@ var RPCTransport = class {
2592
2803
  });
2593
2804
  }
2594
2805
  const traceObj = eventTrace;
2595
- this._log.info(`[trace=${String(traceObj.trace_id ?? "")}] event_recv event=${sdkEvent}`);
2806
+ eventLog.info(`[trace=${String(traceObj.trace_id ?? "")}] event_recv event=${sdkEvent}`);
2596
2807
  }
2597
2808
  }
2598
2809
  if (sdkEvent.startsWith("app.")) {
2599
2810
  this._dispatcher.enqueue(sdkEvent, params2);
2600
2811
  return;
2601
2812
  }
2602
- this._dispatcher.enqueue(`_raw.${sdkEvent}`, params2);
2813
+ this._dispatcher.enqueueProtocol(`_raw.${sdkEvent}`, params2);
2603
2814
  return;
2604
2815
  }
2605
2816
  this._notifyMetaObserver(message);
2606
- this._log.debug(`notification recv: method=${method || "<no-method>"}`);
2607
- this._dispatcher.enqueue("notification", message);
2817
+ withLogContext(this._log, trafficLogContext("inbound", message.params ?? {})).debug(`notification recv: method=${method || "<no-method>"}`);
2818
+ this._dispatcher.enqueueProtocol("notification", message);
2608
2819
  }
2609
2820
  _decodeMessage(raw) {
2610
2821
  if (isJsonObject(raw)) {
@@ -5111,15 +5322,15 @@ var MessageDeliveryEngine = class {
5111
5322
  isInlineGenerationCurrent(generation) {
5112
5323
  return generation === this.inlineGeneration;
5113
5324
  }
5114
- isPullOperationCurrent() {
5115
- const client = this.runtime.client;
5116
- const generation = client._pullOperationGeneration;
5117
- if (generation === void 0) return true;
5118
- const pipeline = client._rpcPipeline;
5119
- return typeof pipeline?.isPullGenerationCurrent === "function" ? pipeline.isPullGenerationCurrent(generation) : true;
5325
+ isPullOperationCurrent(namespace = "") {
5326
+ const pipeline = this.runtime.client._rpcPipeline;
5327
+ return typeof pipeline?.isPullNamespaceCurrent === "function" ? pipeline.isPullNamespaceCurrent(namespace) : true;
5328
+ }
5329
+ ensurePullOperationCurrent(namespace = "") {
5330
+ if (!this.isPullOperationCurrent(namespace)) throw new Error("pull invalidated");
5120
5331
  }
5121
- ensurePullOperationCurrent() {
5122
- if (!this.isPullOperationCurrent()) throw new Error("pull invalidated");
5332
+ isPullScopedSource(source) {
5333
+ return source === "pull";
5123
5334
  }
5124
5335
  captureInlineGeneration() {
5125
5336
  return this.inlineGeneration;
@@ -5723,7 +5934,7 @@ var MessageDeliveryEngine = class {
5723
5934
  }
5724
5935
  async confirmPlainForwardAck(ns, method, ackSeq, groupId = "") {
5725
5936
  const client = this.runtime.client;
5726
- this.ensurePullOperationCurrent();
5937
+ this.ensurePullOperationCurrent(ns);
5727
5938
  const coordinator = this.forwardCoordinator();
5728
5939
  const generation = this.captureInlineGeneration();
5729
5940
  coordinator.recordForwardAck(ns, ackSeq);
@@ -5740,7 +5951,7 @@ var MessageDeliveryEngine = class {
5740
5951
  _rpc_background: true
5741
5952
  };
5742
5953
  const result = await client._rpcPipeline.rawCall(method, params2, { background: true });
5743
- this.ensurePullOperationCurrent();
5954
+ this.ensurePullOperationCurrent(ns);
5744
5955
  const actualAckSeq = this.resolveForwardAckSeq(result, ackSeq);
5745
5956
  if (actualAckSeq < ackSeq) {
5746
5957
  throw new Error(`${method} server ACK watermark ${actualAckSeq} is below requested ${ackSeq}`);
@@ -5757,7 +5968,7 @@ var MessageDeliveryEngine = class {
5757
5968
  throw new Error(`${method} response must be an object`);
5758
5969
  }
5759
5970
  const client = this.runtime.client;
5760
- this.ensurePullOperationCurrent();
5971
+ this.ensurePullOperationCurrent(ns);
5761
5972
  const response = result;
5762
5973
  const messages = deduplicatePlainForwardPageMessages(response.messages, afterSeq);
5763
5974
  const coordinator = this.forwardCoordinator();
@@ -5785,31 +5996,31 @@ var MessageDeliveryEngine = class {
5785
5996
  let committed = false;
5786
5997
  try {
5787
5998
  for (const rawMessage of messages) {
5788
- this.ensurePullOperationCurrent();
5999
+ this.ensurePullOperationCurrent(ns);
5789
6000
  const seq2 = positiveSafeSequenceHint(rawMessage.seq);
5790
6001
  if (method === "message.pull") {
5791
6002
  const appEvent = p2pAppEventFromPlainPullMessage(rawMessage);
5792
6003
  if (await this.publishPulledMessage(appEvent.event, ns, seq2, appEvent.payload, false)) {
5793
6004
  publishedCount += 1;
5794
6005
  }
5795
- this.ensurePullOperationCurrent();
6006
+ this.ensurePullOperationCurrent(ns);
5796
6007
  continue;
5797
6008
  }
5798
6009
  const message = normalizeGroupMentionMode(rawMessage);
5799
6010
  if (this.recallEventFromGroupMessage(message)) {
5800
6011
  if (await this.publishGroupRecallTombstone(groupId, seq2, message, "pull")) {
5801
- this.ensurePullOperationCurrent();
6012
+ this.ensurePullOperationCurrent(ns);
5802
6013
  this.markPublishedSeq(ns, seq2);
5803
6014
  publishedCount += 1;
5804
6015
  }
5805
6016
  } else if (this.isSelfSentGroupMessage(message)) {
5806
6017
  this.markPublishedSeq(ns, seq2);
5807
6018
  } else if (await this.publishPulledMessage("group.message_created", ns, seq2, message, false)) {
5808
- this.ensurePullOperationCurrent();
6019
+ this.ensurePullOperationCurrent(ns);
5809
6020
  publishedCount += 1;
5810
6021
  }
5811
6022
  }
5812
- this.ensurePullOperationCurrent();
6023
+ this.ensurePullOperationCurrent(ns);
5813
6024
  const contiguousSeq = Number.isSafeInteger(result.contiguous_seq) ? result.contiguous_seq : void 0;
5814
6025
  if (contiguousSeq === void 0) client._seqTracker.onPullResult(ns, messages, afterSeq);
5815
6026
  else client._seqTracker.onPullResult(ns, messages, afterSeq, contiguousSeq);
@@ -5823,20 +6034,20 @@ var MessageDeliveryEngine = class {
5823
6034
  client._seqTracker.forceContiguousSeq(ns, commitTarget);
5824
6035
  }
5825
6036
  if (client._seqTracker.getContiguousSeq(ns) !== pageContigBefore) {
5826
- this.ensurePullOperationCurrent();
6037
+ this.ensurePullOperationCurrent(ns);
5827
6038
  await this.drainOrderedMessages(ns, void 0, false, false);
5828
- this.ensurePullOperationCurrent();
6039
+ this.ensurePullOperationCurrent(ns);
5829
6040
  await client._commitSeqTrackerState(ns);
5830
6041
  }
5831
6042
  committed = true;
5832
6043
  } catch (exc) {
5833
- if (this.isPullOperationCurrent() && !committed && typeof client._seqTracker.restoreNamespaceSnapshot === "function") {
6044
+ if (this.isPullOperationCurrent(ns) && !committed && typeof client._seqTracker.restoreNamespaceSnapshot === "function") {
5834
6045
  client._seqTracker.restoreNamespaceSnapshot(ns, pageTrackerSnapshot);
5835
6046
  this.dropSeqTrackerPending(ns);
5836
6047
  }
5837
6048
  throw exc;
5838
6049
  }
5839
- this.ensurePullOperationCurrent();
6050
+ this.ensurePullOperationCurrent(ns);
5840
6051
  const committedAck = client._seqTracker.getContiguousSeq(ns);
5841
6052
  if (deferredServerCursor > 0 && committedAck >= deferredServerCursor) {
5842
6053
  coordinator.clearForwardCursor(ns, committedAck);
@@ -5869,7 +6080,7 @@ var MessageDeliveryEngine = class {
5869
6080
  if (clampedAckSeq < pendingAckSeq) {
5870
6081
  throw new Error(`${ackMethod} cannot confirm pending Forward watermark ${pendingAckSeq}`);
5871
6082
  }
5872
- this.ensurePullOperationCurrent();
6083
+ this.ensurePullOperationCurrent(ns);
5873
6084
  await this.confirmPlainForwardAck(ns, ackMethod, pendingAckSeq, groupId);
5874
6085
  }
5875
6086
  const remaining = typeof response.remaining === "number" && Number.isSafeInteger(response.remaining) && response.remaining >= 0 ? response.remaining : null;
@@ -5903,12 +6114,16 @@ var MessageDeliveryEngine = class {
5903
6114
  }
5904
6115
  async publishOrderedQueueItem(ns, event, seq2, payload, pullResponse = false, source = "push", batch) {
5905
6116
  const client = this.runtime.client;
6117
+ const pullScoped = this.isPullScopedSource(source);
6118
+ if (pullScoped) this.ensurePullOperationCurrent(ns);
5906
6119
  if (event === "group.changed" && this.isGroupEventNamespace(ns)) {
5907
6120
  await this.publishOrderedGroupChanged(payload, source);
6121
+ if (pullScoped) this.ensurePullOperationCurrent(ns);
5908
6122
  return;
5909
6123
  }
5910
6124
  if (event === "message.recalled") {
5911
6125
  await this.publishMessageRecallTombstone(seq2, payload, source);
6126
+ if (pullScoped) this.ensurePullOperationCurrent(ns);
5912
6127
  return;
5913
6128
  }
5914
6129
  if (pullResponse) {
@@ -5916,6 +6131,7 @@ var MessageDeliveryEngine = class {
5916
6131
  return;
5917
6132
  }
5918
6133
  await client._publishAppEvent(event, payload, source, ns, batch);
6134
+ if (pullScoped) this.ensurePullOperationCurrent(ns);
5919
6135
  }
5920
6136
  async publishOrderedGroupChanged(payload, source = "ordered") {
5921
6137
  const client = this.runtime.client;
@@ -7023,8 +7239,7 @@ var MessageDeliveryEngine = class {
7023
7239
  max_pages: 1
7024
7240
  };
7025
7241
  const invoke = async () => {
7026
- const after = this.syncState(ns).ack;
7027
- const messages = await client._pullV2(after, pageLimit, { gateLocked: true, maxPages: 1 });
7242
+ const messages = await client._pullV2(Number(request.after_seq), pageLimit, { gateLocked: true, maxPages: 1 });
7028
7243
  return { messages, raw_count: messages.length };
7029
7244
  };
7030
7245
  const pipeline = client._rpcPipeline;
@@ -7043,8 +7258,7 @@ var MessageDeliveryEngine = class {
7043
7258
  max_pages: maxPages
7044
7259
  };
7045
7260
  const invoke = async () => {
7046
- const after = this.syncState(ns).ack;
7047
- const messages = await client._pullGroupV2(groupId, after, pageLimit, { gateLocked: true, maxPages });
7261
+ const messages = await client._pullGroupV2(groupId, Number(request.after_seq), pageLimit, { gateLocked: true, maxPages });
7048
7262
  return { messages, raw_count: messages.length };
7049
7263
  };
7050
7264
  const pipeline = client._rpcPipeline;
@@ -8039,7 +8253,8 @@ var MessageDeliveryEngine = class {
8039
8253
  }
8040
8254
  async drainOrderedMessages(ns, beforeSeq, pullResponse = false, persist = true, batch, source = "pull") {
8041
8255
  const client = this.runtime.client;
8042
- this.ensurePullOperationCurrent();
8256
+ const pullScoped = this.isPullScopedSource(source);
8257
+ if (pullScoped) this.ensurePullOperationCurrent(ns);
8043
8258
  const queue = client._pendingOrderedMsgs.get(ns);
8044
8259
  if (!queue || queue.size === 0) return;
8045
8260
  const contig = client._seqTracker.getContiguousSeq(ns);
@@ -8048,7 +8263,7 @@ var MessageDeliveryEngine = class {
8048
8263
  const drainBatches = /* @__PURE__ */ new Map();
8049
8264
  try {
8050
8265
  for (const seq2 of ready) {
8051
- this.ensurePullOperationCurrent();
8266
+ if (pullScoped) this.ensurePullOperationCurrent(ns);
8052
8267
  const item = queue.get(seq2);
8053
8268
  queue.delete(seq2);
8054
8269
  if (!item || client._pushedSeqs.get(ns)?.has(seq2)) continue;
@@ -8070,7 +8285,7 @@ var MessageDeliveryEngine = class {
8070
8285
  itemSource,
8071
8286
  itemBatch
8072
8287
  );
8073
- this.ensurePullOperationCurrent();
8288
+ if (pullScoped) this.ensurePullOperationCurrent(ns);
8074
8289
  this.markPublishedSeq(ns, seq2);
8075
8290
  delivered = true;
8076
8291
  }
@@ -8082,7 +8297,7 @@ var MessageDeliveryEngine = class {
8082
8297
  if (queue.size === 0) {
8083
8298
  client._pendingOrderedMsgs.delete(ns);
8084
8299
  if (delivered && persist) {
8085
- this.ensurePullOperationCurrent();
8300
+ if (pullScoped) this.ensurePullOperationCurrent(ns);
8086
8301
  await this.saveSeqTrackerState();
8087
8302
  }
8088
8303
  }
@@ -8126,8 +8341,9 @@ var MessageDeliveryEngine = class {
8126
8341
  const client = this.runtime.client;
8127
8342
  const ownsBatch = !operationBatch && (source === "push" || source === "inline_push");
8128
8343
  const batch = operationBatch ?? (ownsBatch ? this.createDeliveryChangeBatch(source) : void 0);
8344
+ const pullScoped = this.isPullScopedSource(source);
8129
8345
  try {
8130
- this.ensurePullOperationCurrent();
8346
+ if (pullScoped) this.ensurePullOperationCurrent(ns);
8131
8347
  const seqNum = Number(seq2);
8132
8348
  if (!Number.isFinite(seqNum) || !Number.isInteger(seqNum) || seqNum <= 0 || !ns) {
8133
8349
  if (event === "message.recalled") {
@@ -8135,11 +8351,11 @@ var MessageDeliveryEngine = class {
8135
8351
  ns,
8136
8352
  () => this.publishMessageRecallTombstone(seq2, payload, source)
8137
8353
  );
8138
- this.ensurePullOperationCurrent();
8354
+ if (pullScoped) this.ensurePullOperationCurrent(ns);
8139
8355
  return published;
8140
8356
  }
8141
8357
  await client._withPullResponseProcessing(ns, () => client._publishAppEvent(event, payload, source, ns, batch));
8142
- this.ensurePullOperationCurrent();
8358
+ if (pullScoped) this.ensurePullOperationCurrent(ns);
8143
8359
  return true;
8144
8360
  }
8145
8361
  const queue = client._pendingOrderedMsgs.get(ns);
@@ -8149,7 +8365,7 @@ var MessageDeliveryEngine = class {
8149
8365
  return false;
8150
8366
  }
8151
8367
  await this.drainOrderedMessages(ns, seqNum, false, persist, batch, source);
8152
- this.ensurePullOperationCurrent();
8368
+ if (pullScoped) this.ensurePullOperationCurrent(ns);
8153
8369
  queue?.delete(seqNum);
8154
8370
  if (queue && queue.size === 0) client._pendingOrderedMsgs.delete(ns);
8155
8371
  if (event === "message.recalled") {
@@ -8157,12 +8373,12 @@ var MessageDeliveryEngine = class {
8157
8373
  ns,
8158
8374
  () => this.publishMessageRecallTombstone(seqNum, payload, source)
8159
8375
  );
8160
- this.ensurePullOperationCurrent();
8376
+ if (pullScoped) this.ensurePullOperationCurrent(ns);
8161
8377
  this.markPublishedSeq(ns, seqNum);
8162
8378
  return published;
8163
8379
  }
8164
8380
  await client._withPullResponseProcessing(ns, () => client._publishAppEvent(event, payload, source, ns, batch));
8165
- this.ensurePullOperationCurrent();
8381
+ if (pullScoped) this.ensurePullOperationCurrent(ns);
8166
8382
  this.markPublishedSeq(ns, seqNum);
8167
8383
  return true;
8168
8384
  } finally {
@@ -8776,7 +8992,9 @@ var LifecycleController = class {
8776
8992
  client._resetSeqTrackingState();
8777
8993
  client._clientLog.debug(`close exit: elapsed=${Date.now() - tStart}ms`);
8778
8994
  } finally {
8779
- const closing = client._dispatcher.close();
8995
+ const closeProtocol = client._dispatcher.closeProtocol;
8996
+ const protocolClosing = typeof closeProtocol === "function" ? closeProtocol.call(client._dispatcher) : Promise.resolve();
8997
+ const closing = protocolClosing.then(() => client._dispatcher.close());
8780
8998
  if (!calledFromHandler) await closing;
8781
8999
  }
8782
9000
  }, "close");
@@ -15377,8 +15595,8 @@ function validateAgentMdCertificate(certPem, expectedAid, timestamp2, now, requi
15377
15595
  function resultOk(data) {
15378
15596
  return { ok: true, data };
15379
15597
  }
15380
- function resultErr(code, message, cause) {
15381
- return { ok: false, error: { code, message, ...cause !== void 0 ? { cause } : {} } };
15598
+ function resultErr(code, message, _cause) {
15599
+ return { ok: false, error: { code, message } };
15382
15600
  }
15383
15601
 
15384
15602
  // src/aid.ts
@@ -15748,8 +15966,8 @@ async function signingCertFingerprint(certPem) {
15748
15966
  }
15749
15967
  return await cached;
15750
15968
  }
15751
- var PULL_GATE_STALE_MS = 3e4;
15752
- var PULL_GATE_OPERATION_TIMEOUT_MS = 3e3;
15969
+ var PULL_GATE_STALE_MS = 35e3;
15970
+ var PULL_GATE_OPERATION_TIMEOUT_MS = 35e3;
15753
15971
  function sameIdentityAdmissionRejection(error, original) {
15754
15972
  const errorCode2 = Number(error?.code);
15755
15973
  const originalCode = Number(original?.code);
@@ -15856,7 +16074,6 @@ var RpcPipeline = class {
15856
16074
  __publicField(this, "pullGateStates", /* @__PURE__ */ new Map());
15857
16075
  __publicField(this, "inlineRealtimeScopes", /* @__PURE__ */ new Set());
15858
16076
  __publicField(this, "pullWorkTokens", /* @__PURE__ */ new Set());
15859
- __publicField(this, "pullGeneration", 0);
15860
16077
  __publicField(this, "pullInvalidationWait", null);
15861
16078
  this.runtime = runtime;
15862
16079
  }
@@ -15951,13 +16168,19 @@ var RpcPipeline = class {
15951
16168
  if (pullGateKey) {
15952
16169
  return await this.runPullSerialized(
15953
16170
  pullGateKey,
15954
- async () => await this.callImplInner(method, p, skipSendResultEnvelope, deferGroupReadyPostprocess),
16171
+ async () => await this.callImplInner(
16172
+ method,
16173
+ p,
16174
+ skipSendResultEnvelope,
16175
+ deferGroupReadyPostprocess,
16176
+ this.pullScopeKey(pullGateKey)
16177
+ ),
15955
16178
  rpcBackground && this.pullGateBackgroundForCall(method, p)
15956
16179
  );
15957
16180
  }
15958
16181
  return await runWithRpcPriority(() => this.callImplInner(method, p, skipSendResultEnvelope, deferGroupReadyPostprocess));
15959
16182
  }
15960
- async callImplInner(method, p, skipSendResultEnvelope = false, deferGroupReadyPostprocess = false) {
16183
+ async callImplInner(method, p, skipSendResultEnvelope = false, deferGroupReadyPostprocess = false, pullNamespace = "") {
15961
16184
  const client = this.runtime.client;
15962
16185
  if (method === "message.v2.pull" || method === "message.pull" && hasMatchingV2Session(client)) {
15963
16186
  try {
@@ -16037,7 +16260,10 @@ var RpcPipeline = class {
16037
16260
  };
16038
16261
  let result = await this.transportCallWithIdentityRecovery(invokeTransport, method, p);
16039
16262
  const sendResultModeSource = result;
16040
- result = await this.postprocessResult(method, p, result, { skipGroupState: deferGroupReadyPostprocess });
16263
+ result = await this.postprocessResult(method, p, result, {
16264
+ skipGroupState: deferGroupReadyPostprocess,
16265
+ pullNamespace
16266
+ });
16041
16267
  if (!skipSendResultEnvelope) {
16042
16268
  result = client._delivery.attachSendResultEnvelope(
16043
16269
  method,
@@ -16231,7 +16457,8 @@ var RpcPipeline = class {
16231
16457
  if (!client._aid) return "";
16232
16458
  const mode = method === "message.history" ? "history" : params2.window_mode === "tail" ? "tail" : "forward";
16233
16459
  const cursor = mode === "history" ? `before=${String(params2.before_seq)}` : `after=${String(params2.after_seq ?? 0)}`;
16234
- return `p2p:${client._aid}|mode=${mode}|cursor=${cursor}|force=${String(Boolean(params2.force))}|limit=${String(params2.limit)}`;
16460
+ const limit = mode === "forward" ? Number(params2.limit ?? 50) || 50 : params2.limit;
16461
+ return `p2p:${client._aid}|mode=${mode}|cursor=${cursor}|force=${String(Boolean(params2.force))}|limit=${String(limit)}`;
16235
16462
  }
16236
16463
  if (method === "group.pull" || method === "group.v2.pull" || method === "group.history") {
16237
16464
  const gid = String(params2.group_id ?? params2.group_aid ?? "").trim();
@@ -16240,7 +16467,8 @@ var RpcPipeline = class {
16240
16467
  const cursor = mode === "history" ? `before=${String(params2.before_seq)}` : `after=${String(params2.after_seq ?? params2.after_message_seq ?? 0)}`;
16241
16468
  const explicitCursor = this.explicitGroupCursorParams(params2);
16242
16469
  const cursorSuffix = Object.keys(explicitCursor).length > 0 ? `|cursor_params=${stableStringify(explicitCursor)}` : "";
16243
- return `group:${gid}|mode=${mode}|cursor=${cursor}${cursorSuffix}|force=${String(Boolean(params2.force))}|limit=${String(params2.limit)}`;
16470
+ const limit = mode === "forward" ? Number(params2.limit ?? 50) || 50 : params2.limit;
16471
+ return `group:${gid}|mode=${mode}|cursor=${cursor}${cursorSuffix}|force=${String(Boolean(params2.force))}|limit=${String(limit)}`;
16244
16472
  }
16245
16473
  if (method === "group.pull_events") {
16246
16474
  const gid = String(params2.group_id ?? params2.group_aid ?? "").trim();
@@ -16299,7 +16527,6 @@ var RpcPipeline = class {
16299
16527
  if (active.timedOut) return;
16300
16528
  active.timedOut = true;
16301
16529
  active.invalidated = true;
16302
- this.pullGeneration += 1;
16303
16530
  active.cancel?.();
16304
16531
  const err = new TimeoutError(`pull gate timeout: ${active.namespace}`, { retryable: true });
16305
16532
  this.runtime.client._clientLog?.warn(`pull gate watchdog timeout: gate=${name} key=${active.key}`);
@@ -16316,9 +16543,9 @@ var RpcPipeline = class {
16316
16543
  const index = key.indexOf("|");
16317
16544
  return index < 0 ? key : key.slice(0, index);
16318
16545
  }
16319
- bindActivePullCancellation(method, params2, request) {
16546
+ bindActivePullCancellation(method, params2, request, gateKey = "") {
16320
16547
  const cancel = request.cancel;
16321
- const key = this.pullGateKeyForCall(method, params2);
16548
+ const key = gateKey || this.pullGateKeyForCall(method, params2);
16322
16549
  if (typeof cancel !== "function" || !key) return request;
16323
16550
  const state = this.pullGateStates.get(this.pullGateName(key));
16324
16551
  const active = state?.active;
@@ -16474,12 +16701,14 @@ var RpcPipeline = class {
16474
16701
  gate.inflight = false;
16475
16702
  gate.startedAt = 0;
16476
16703
  }
16477
- isPullGenerationCurrent(generation) {
16478
- return generation === this.pullGeneration;
16704
+ isPullNamespaceCurrent(namespace) {
16705
+ const ns = this.pullScopeKey(namespace);
16706
+ if (!ns) return true;
16707
+ const active = this.pullGateStates.get(this.pullGateName(ns))?.active;
16708
+ return !active || active.namespace !== ns || !active.timedOut && !active.invalidated;
16479
16709
  }
16480
16710
  invalidatePulls() {
16481
16711
  if (this.pullInvalidationWait) return this.pullInvalidationWait;
16482
- this.pullGeneration += 1;
16483
16712
  const error = new Error("pull invalidated");
16484
16713
  const waits = [];
16485
16714
  for (const state of this.pullGateStates.values()) {
@@ -16592,23 +16821,11 @@ var RpcPipeline = class {
16592
16821
  }
16593
16822
  async executePullOperation(operation, background) {
16594
16823
  const client = this.runtime.client;
16595
- const hadPrevious = Object.prototype.hasOwnProperty.call(client, "_pullOperationGeneration");
16596
- const previous = client._pullOperationGeneration;
16597
- client._pullOperationGeneration = this.pullGeneration;
16598
- try {
16599
- if (background) return await client._withBackgroundRpc(operation);
16600
- return await operation();
16601
- } finally {
16602
- if (hadPrevious) client._pullOperationGeneration = previous;
16603
- else delete client._pullOperationGeneration;
16604
- }
16824
+ if (background) return await client._withBackgroundRpc(operation);
16825
+ return await operation();
16605
16826
  }
16606
- pullOperationIsCurrent() {
16607
- const generation = this.runtime.client._pullOperationGeneration;
16608
- return generation === void 0 || this.isPullGenerationCurrent(generation);
16609
- }
16610
- throwIfPullInvalidated() {
16611
- if (!this.pullOperationIsCurrent()) throw new Error("pull invalidated");
16827
+ throwIfPullInvalidated(namespace) {
16828
+ if (!this.isPullNamespaceCurrent(namespace)) throw new Error("pull invalidated");
16612
16829
  }
16613
16830
  async yieldPullGate(key, nextKey, background) {
16614
16831
  if (!key) return;
@@ -16710,10 +16927,10 @@ var RpcPipeline = class {
16710
16927
  else if (options?.trace !== void 0) request = client._transport.call(method, payload, timeout, options.trace);
16711
16928
  else if (timeout !== void 0) request = client._transport.call(method, payload, timeout);
16712
16929
  else request = client._transport.call(method, payload);
16713
- return this.bindActivePullCancellation(method, payload, request);
16930
+ return this.bindActivePullCancellation(method, payload, request, options?.pullGateKey ?? "");
16714
16931
  };
16715
16932
  const result = await this.transportCallWithIdentityRecovery(invokeTransport, method, payload);
16716
- this.throwIfPullInvalidated();
16933
+ this.throwIfPullInvalidated(this.pullScopeKey(options?.pullGateKey || this.pullGateKeyForCall(method, payload)));
16717
16934
  return result;
16718
16935
  }
16719
16936
  async transportCallWithIdentityRecovery(operation, method, params2) {
@@ -16737,7 +16954,8 @@ var RpcPipeline = class {
16737
16954
  }
16738
16955
  async postprocessResult(method, params2, result, options = {}) {
16739
16956
  const client = this.runtime.client;
16740
- this.throwIfPullInvalidated();
16957
+ const pullNamespace = this.pullScopeKey(options.pullNamespace || this.pullGateKeyForCall(method, params2));
16958
+ this.throwIfPullInvalidated(pullNamespace);
16741
16959
  let next = result;
16742
16960
  if ((method === "group.send" || method === "group.v2.send") && isJsonObject(next)) {
16743
16961
  next = normalizeGroupMentionMode(next);
@@ -16756,7 +16974,7 @@ var RpcPipeline = class {
16756
16974
  if (method === "message.pull" && isJsonObject(next)) {
16757
16975
  const isTail = String(next.window_mode ?? params2.window_mode ?? "").trim().toLowerCase() === "tail";
16758
16976
  if (!isTail && client._aid && client._seqTracker) {
16759
- const ns = `p2p:${client._aid}`;
16977
+ const ns = pullNamespace || `p2p:${client._aid}`;
16760
16978
  const afterSeq = Math.max(0, Number(params2.after_seq ?? 0) || 0);
16761
16979
  await client._delivery.commitPlainForwardPage(ns, afterSeq, "message.pull", next);
16762
16980
  } else {
@@ -16774,7 +16992,7 @@ var RpcPipeline = class {
16774
16992
  if (!ownsCursor) {
16775
16993
  client._clientLog.debug(`group.pull external cursor skips local Forward commit: group=${gid}`);
16776
16994
  } else if (!isTail && gid && client._seqTracker) {
16777
- const ns = `group:${gid}`;
16995
+ const ns = pullNamespace || `group:${gid}`;
16778
16996
  const afterSeq = Math.max(0, Number(params2.after_message_seq ?? params2.after_seq ?? 0) || 0);
16779
16997
  await client._delivery.commitPlainForwardPage(ns, afterSeq, "group.pull", next, gid);
16780
16998
  } else {
@@ -18217,7 +18435,7 @@ async function verifyGroupIndex(body, signer) {
18217
18435
  return resultOk({ valid: false, reason: "etag mismatch" });
18218
18436
  }
18219
18437
  const verified = await signer.verify(groupIndexSigningPayload(parsed.meta, parsed.entries), signature);
18220
- if (!verified.ok) return resultErr(verified.error.code, verified.error.message || "group index verify failed", verified.error.cause);
18438
+ if (!verified.ok) return resultErr(verified.error.code, verified.error.message || "group index verify failed");
18221
18439
  if (!verified.data.valid) return resultOk({ valid: false, reason: "signature verification failed" });
18222
18440
  return resultOk({ valid: true, meta: parsed.meta, entries: canonicalEntries(parsed.entries) });
18223
18441
  } catch (exc) {
@@ -24951,7 +25169,16 @@ var V2E2EECoordinator = class {
24951
25169
  const limit = strictWindowLimit(params2.limit ?? V2_PULL_DEFAULT_PAGE_LIMIT);
24952
25170
  const ns = client._aid ? `p2p:${client._aid}` : "";
24953
25171
  if (ns) client._delivery.onPullStarted?.(ns);
24954
- const result = await client._callRawV2Rpc("message.v2.pull", { window_mode: "tail", after_seq: afterSeq, limit, _rpc_foreground: true });
25172
+ const pullGateKey = pullGateKeyForClient(client, "message.v2.pull", {
25173
+ window_mode: "tail",
25174
+ after_seq: afterSeq,
25175
+ limit
25176
+ }, `${ns}|tail|after=${afterSeq}|limit=${limit}`);
25177
+ const result = await client._callRawV2Rpc(
25178
+ "message.v2.pull",
25179
+ { window_mode: "tail", after_seq: afterSeq, limit, _rpc_foreground: true },
25180
+ pullGateKey
25181
+ );
24955
25182
  const page = validateTailPage(result, afterSeq, limit);
24956
25183
  if (ns) {
24957
25184
  client._seqTracker.commitTailWindow(ns, {
@@ -25060,7 +25287,7 @@ var V2E2EECoordinator = class {
25060
25287
  limit,
25061
25288
  ...opts?.force ? { force: true } : {},
25062
25289
  ...ackUpToSeq > 0 ? { ack_up_to_seq: ackUpToSeq } : {}
25063
- });
25290
+ }, pullGateKey);
25064
25291
  if (ackUpToSeq > 0) {
25065
25292
  const actualAckSeq = client._delivery?.resolveP2PPullAckSeq?.(result, ackUpToSeq) ?? 0;
25066
25293
  if (actualAckSeq >= ackUpToSeq) {
@@ -25418,18 +25645,27 @@ var V2E2EECoordinator = class {
25418
25645
  const afterSeq = strictWindowSeq(params2.after_seq ?? 0, "after_seq");
25419
25646
  const limit = strictWindowLimit(params2.limit ?? V2_PULL_DEFAULT_PAGE_LIMIT);
25420
25647
  const ns = `group:${groupId}`;
25421
- const cursorParams = isJsonObject(params2._group_cursor_params) ? params2._group_cursor_params : params2;
25648
+ const explicitCursorParams = isJsonObject(params2._group_cursor_params) ? params2._group_cursor_params : {};
25649
+ const cursorParams = Object.keys(explicitCursorParams).length > 0 ? explicitCursorParams : params2;
25422
25650
  const requestDeviceId = String(cursorParams.device_id ?? "").trim();
25423
25651
  const requestSlotId = String(cursorParams.slot_id ?? "").trim();
25424
25652
  const ownsCursor = (!requestDeviceId || requestDeviceId === String(client._deviceId ?? "")) && (!requestSlotId || requestSlotId === String(client._slotId ?? ""));
25425
25653
  if (ownsCursor) client._delivery.onPullStarted?.(ns);
25654
+ const pullGateKey = pullGateKeyForClient(client, "group.v2.pull", {
25655
+ group_id: groupId,
25656
+ window_mode: "tail",
25657
+ after_seq: afterSeq,
25658
+ limit,
25659
+ _group_cursor_params: explicitCursorParams
25660
+ }, `${ns}|tail|after=${afterSeq}|limit=${limit}`);
25426
25661
  const result = await client._callRawV2Rpc("group.v2.pull", withExplicitGroupAid({
25427
25662
  group_id: groupId,
25428
25663
  window_mode: "tail",
25429
25664
  after_seq: afterSeq,
25430
25665
  limit,
25666
+ _group_cursor_params: explicitCursorParams,
25431
25667
  _rpc_foreground: true
25432
- }, groupAid));
25668
+ }, groupAid), pullGateKey);
25433
25669
  const resultAid = String(result.group_aid ?? result.groupAid ?? "").trim();
25434
25670
  if (resultAid) groupAid = resultAid;
25435
25671
  const page = validateTailPage(result, afterSeq, limit);
@@ -25520,6 +25756,7 @@ var V2E2EECoordinator = class {
25520
25756
  }
25521
25757
  const result = await this.pullGroupV2TailInternal({
25522
25758
  ...opts?.cursorParams ?? {},
25759
+ _group_cursor_params: opts?.cursorParams,
25523
25760
  group_id: String(opts.wireGroupId ?? gid),
25524
25761
  group_aid: groupAid || void 0,
25525
25762
  window_mode: "tail",
@@ -25546,13 +25783,13 @@ var V2E2EECoordinator = class {
25546
25783
  const cursorParams = opts?.cursorParams ?? {};
25547
25784
  const ownsCursor = opts?.ownsCursor !== false;
25548
25785
  if (ownsCursor) client._delivery.onPullStarted?.(ns);
25549
- let pullGateKey = ownsCursor ? pullGateKeyForClient(client, "group.v2.pull", {
25786
+ let pullGateKey = pullGateKeyForClient(client, "group.v2.pull", {
25550
25787
  group_id: gid,
25551
25788
  after_seq: afterSeq,
25552
25789
  force: opts?.force === true,
25553
25790
  limit,
25554
25791
  _group_cursor_params: cursorParams
25555
- }, `${ns}|forward|after=${afterSeq}|force=${String(Boolean(opts?.force))}|limit=${limit}`) : "";
25792
+ }, `${ns}|forward|after=${afterSeq}|force=${String(Boolean(opts?.force))}|limit=${limit}`);
25556
25793
  let nextAfterSeq = opts?.explicitAfterSeq || opts?.force ? afterSeq : afterSeq || client._seqTracker.getContiguousSeq(ns);
25557
25794
  const deferredServerCursor = ownsCursor ? this.pendingForwardCursor(ns, client._seqTracker.getContiguousSeq(ns)) : 0;
25558
25795
  const deferredForwardAck = ownsCursor ? this.pendingForwardAck(ns, client._seqTracker.getContiguousSeq(ns)) : 0;
@@ -25571,7 +25808,7 @@ var V2E2EECoordinator = class {
25571
25808
  ...cursorParams,
25572
25809
  ...opts?.force ? { force: true } : {},
25573
25810
  ...ackUpToSeq > 0 ? { ack_up_to_seq: ackUpToSeq } : {}
25574
- }, groupAid));
25811
+ }, groupAid), pullGateKey);
25575
25812
  if (ackUpToSeq > 0) {
25576
25813
  const actualAckSeq = client._delivery?.resolveGroupPullAckSeq?.(result, ackUpToSeq) ?? 0;
25577
25814
  if (actualAckSeq >= ackUpToSeq) {
@@ -28375,104 +28612,6 @@ __publicField(_IndexedDBTokenStore, "_TRUST_CERT_PREFIX", "__trust_roots:cert:")
28375
28612
  __publicField(_IndexedDBTokenStore, "_TRUST_ISSUER_PREFIX", "__trust_roots:issuer:");
28376
28613
  var IndexedDBTokenStore = _IndexedDBTokenStore;
28377
28614
 
28378
- // src/logger.ts
28379
- var LEVEL_ORDER = { DEBUG: 0, INFO: 1, WARN: 2, ERROR: 3 };
28380
- function formatMessage(template, args) {
28381
- if (args.length === 0) return template;
28382
- let i = 0;
28383
- let result = "";
28384
- let consumed = 0;
28385
- for (let p = 0; p < template.length; p++) {
28386
- const ch = template[p];
28387
- if (ch === "%" && template[p + 1] === "s" && i < args.length) {
28388
- result += String(args[i++]);
28389
- consumed++;
28390
- p++;
28391
- } else {
28392
- result += ch;
28393
- }
28394
- }
28395
- if (i < args.length) {
28396
- const tail = args.slice(i).map((a) => a instanceof Error ? a.message : String(a)).join(" ");
28397
- if (tail) result += " " + tail;
28398
- }
28399
- return result;
28400
- }
28401
- var AUNLogger = class {
28402
- constructor(opts) {
28403
- __publicField(this, "_debug");
28404
- __publicField(this, "_aunPath");
28405
- __publicField(this, "_deviceId", "-");
28406
- __publicField(this, "_aid", null);
28407
- __publicField(this, "_minLevel");
28408
- this._debug = opts.debug;
28409
- this._aunPath = String(opts.aunPath || "-");
28410
- this._minLevel = this._debug ? LEVEL_ORDER.DEBUG : LEVEL_ORDER.INFO;
28411
- }
28412
- for(module) {
28413
- return {
28414
- error: (msg, ...args) => this._emit("ERROR", module, msg, args),
28415
- warn: (msg, ...args) => this._emit("WARN", module, msg, args),
28416
- info: (msg, ...args) => this._emit("INFO", module, msg, args),
28417
- debug: (msg, ...args) => this._emit("DEBUG", module, msg, args),
28418
- isDebugEnabled: () => this.isDebugEnabled()
28419
- };
28420
- }
28421
- isDebugEnabled() {
28422
- return this._debug && this._minLevel <= LEVEL_ORDER.DEBUG;
28423
- }
28424
- bindAid(aid) {
28425
- this._aid = aid || null;
28426
- }
28427
- bindDeviceId(deviceId) {
28428
- this._deviceId = String(deviceId || "").trim() || "-";
28429
- }
28430
- close() {
28431
- }
28432
- _emit(level, module, msg, args) {
28433
- if (LEVEL_ORDER[level] < this._minLevel) return;
28434
- if (level === "DEBUG" && !this._debug) return;
28435
- const { date, time, ms } = this._now();
28436
- const head = `[${date} ${time}.${ms}][${level}][${module}][aun_path=${this._aunPath || "-"}][device_id=${this._deviceId || "-"}]`;
28437
- const aidPart = this._aid ? ` [${this._aid}]` : "";
28438
- const formatted = formatMessage(msg, args);
28439
- const line = `${head}${aidPart} ${formatted}`;
28440
- let errArg;
28441
- for (let i = args.length - 1; i >= 0; i--) {
28442
- if (args[i] instanceof Error) {
28443
- errArg = args[i];
28444
- break;
28445
- }
28446
- }
28447
- switch (level) {
28448
- case "ERROR":
28449
- if (errArg) {
28450
- console.error(line, errArg);
28451
- } else {
28452
- console.error(line);
28453
- }
28454
- break;
28455
- case "WARN":
28456
- console.warn(line);
28457
- break;
28458
- case "INFO":
28459
- console.info(line);
28460
- break;
28461
- case "DEBUG":
28462
- console.debug(line);
28463
- break;
28464
- }
28465
- }
28466
- _now() {
28467
- const d = /* @__PURE__ */ new Date();
28468
- const pad = (n, w = 2) => String(n).padStart(w, "0");
28469
- const date = `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())}`;
28470
- const time = `${pad(d.getHours())}:${pad(d.getMinutes())}:${pad(d.getSeconds())}`;
28471
- const ms = pad(d.getMilliseconds(), 3);
28472
- return { date, time, ms };
28473
- }
28474
- };
28475
-
28476
28615
  // src/agent-md.ts
28477
28616
  var DEFAULT_HTTP_TIMEOUT_MS = 3e4;
28478
28617
  function buildDefaultAgentMd(aid, options = {}) {
@@ -29577,6 +29716,13 @@ function _v2ConcatBytes(...parts) {
29577
29716
  function formatCaughtError2(error) {
29578
29717
  return error instanceof Error ? error : String(error);
29579
29718
  }
29719
+ function publicError(error) {
29720
+ const record = error && typeof error === "object" ? error : null;
29721
+ const rawCode = record?.localCode ?? record?.stringCode ?? record?.code;
29722
+ const code = rawCode === void 0 || rawCode === null || rawCode === "" || rawCode === -1 ? "INTERNAL_ERROR" : typeof rawCode === "string" || typeof rawCode === "number" ? rawCode : "INTERNAL_ERROR";
29723
+ const message = String(record?.message ?? error ?? "internal error").trim() || "internal error";
29724
+ return { code, message };
29725
+ }
29580
29726
  var RELOGIN_REFRESH_ERRORS = /* @__PURE__ */ new Set([
29581
29727
  "missing refresh_token",
29582
29728
  "invalid_or_expired_refresh_token",
@@ -29839,6 +29985,7 @@ var _AUNClient = class _AUNClient {
29839
29985
  this._deviceId = inputAid?.deviceId || getDeviceId();
29840
29986
  this._logger = new AUNLogger({ debug: _debug, aunPath: this.configModel.aunPath });
29841
29987
  this._logger.bindDeviceId(this._deviceId);
29988
+ this._logger.bindAid(initAid ?? "");
29842
29989
  this._clientLog = this._logger.for("aun_core.client");
29843
29990
  this._logAuth = this._logger.for("aun_core.auth");
29844
29991
  this._logTransport = this._logger.for("aun_core.transport");
@@ -29886,10 +30033,10 @@ var _AUNClient = class _AUNClient {
29886
30033
  });
29887
30034
  this._transport = new RPCTransport({
29888
30035
  eventDispatcher: this._dispatcher,
29889
- timeout: DEFAULT_SESSION_OPTIONS.timeouts.call,
29890
- onDisconnect: (error, closeCode) => this._handleTransportDisconnect(error, closeCode)
30036
+ timeout: DEFAULT_SESSION_OPTIONS.timeouts.call
29891
30037
  });
29892
- this._transport.setMetaObserver(
30038
+ this._transport.setProtocolDisconnectCallback((error, closeCode) => this._handleTransportDisconnect(error, closeCode));
30039
+ this._transport.setProtocolMetaObserver(
29893
30040
  (meta) => this._observeRpcMeta(meta).catch((exc) => {
29894
30041
  this._clientLog.debug(`rpc meta observer skipped: ${String(exc)}`);
29895
30042
  })
@@ -29924,54 +30071,54 @@ var _AUNClient = class _AUNClient {
29924
30071
  if (typeof this._tokenStore.setLogger === "function") {
29925
30072
  this._tokenStore.setLogger(this._tokenStoreLog);
29926
30073
  }
29927
- this._dispatcher.subscribe("_raw.message.received", (data) => {
30074
+ this._dispatcher.subscribeProtocol("_raw.message.received", (data) => {
29928
30075
  this._onRawMessageReceived(data);
29929
30076
  });
29930
- this._dispatcher.subscribe("_raw.message.recalled", (data) => {
30077
+ this._dispatcher.subscribeProtocol("_raw.message.recalled", (data) => {
29931
30078
  this._safeAsync(this._onRawMessageRecalled(data));
29932
30079
  });
29933
- this._dispatcher.subscribe("_raw.group.message_created", (data) => {
30080
+ this._dispatcher.subscribeProtocol("_raw.group.message_created", (data) => {
29934
30081
  this._onRawGroupMessageCreated(data);
29935
30082
  });
29936
- this._dispatcher.subscribe("_raw.group.message_recalled", (data) => {
30083
+ this._dispatcher.subscribeProtocol("_raw.group.message_recalled", (data) => {
29937
30084
  this._safeAsync(this._onRawGroupMessageRecalled(data));
29938
30085
  });
29939
- this._dispatcher.subscribe("_raw.group.changed", (data) => {
30086
+ this._dispatcher.subscribeProtocol("_raw.group.changed", (data) => {
29940
30087
  this._onRawGroupChanged(data);
29941
30088
  });
29942
- this._dispatcher.subscribe("_raw.group.invite_created", (data) => {
30089
+ this._dispatcher.subscribeProtocol("_raw.group.invite_created", (data) => {
29943
30090
  this._safeAsync(this._onRawGroupInviteReceived(data, "push"));
29944
30091
  });
29945
- this._dispatcher.subscribe("_raw.group.invite_received", (data) => {
30092
+ this._dispatcher.subscribeProtocol("_raw.group.invite_received", (data) => {
29946
30093
  this._safeAsync(this._onRawGroupInviteReceived(data, "push"));
29947
30094
  });
29948
- this._dispatcher.subscribe("_raw.group.invite_finalized", (data) => {
30095
+ this._dispatcher.subscribeProtocol("_raw.group.invite_finalized", (data) => {
29949
30096
  this._safeAsync(this._onRawGroupInviteFinalized(data));
29950
30097
  });
29951
- this._dispatcher.subscribe("_raw.peer.v2.message_received", (data) => {
30098
+ this._dispatcher.subscribeProtocol("_raw.peer.v2.message_received", (data) => {
29952
30099
  this._safeAsync(this._onV2PushNotification(data));
29953
30100
  });
29954
- this._dispatcher.subscribe("_raw.group.v2.message_created", (data) => {
30101
+ this._dispatcher.subscribeProtocol("_raw.group.v2.message_created", (data) => {
29955
30102
  this._safeAsync(this._onRawGroupV2MessageCreated(data));
29956
30103
  });
29957
- this._dispatcher.subscribe("_raw.group.v2.state_proposed", (data) => {
30104
+ this._dispatcher.subscribeProtocol("_raw.group.v2.state_proposed", (data) => {
29958
30105
  this._safeAsync(this._onV2StateProposed(data));
29959
30106
  });
29960
- this._dispatcher.subscribe("_raw.group.v2.state_retry_needed", (data) => {
30107
+ this._dispatcher.subscribeProtocol("_raw.group.v2.state_retry_needed", (data) => {
29961
30108
  this._safeAsync(this._onV2StateRetryNeeded(data));
29962
30109
  });
29963
- this._dispatcher.subscribe("_raw.group.v2.state_confirmed", (data) => {
30110
+ this._dispatcher.subscribeProtocol("_raw.group.v2.state_confirmed", (data) => {
29964
30111
  this._safeAsync(this._onV2StateConfirmed(data));
29965
30112
  });
29966
- this._dispatcher.subscribe("_raw.group.state_committed", (data) => {
30113
+ this._dispatcher.subscribeProtocol("_raw.group.state_committed", (data) => {
29967
30114
  this._safeAsync(this._onGroupStateCommitted(data));
29968
30115
  });
29969
30116
  for (const evt of ["message.ack", "storage.object_changed", "stream/created", "stream/closed"]) {
29970
- this._dispatcher.subscribe(`_raw.${evt}`, (data) => {
30117
+ this._dispatcher.subscribeProtocol(`_raw.${evt}`, (data) => {
29971
30118
  this._dispatcher.enqueue(evt, data);
29972
30119
  });
29973
30120
  }
29974
- this._dispatcher.subscribe("_raw.gateway.disconnect", async (data) => {
30121
+ this._dispatcher.subscribeProtocol("_raw.gateway.disconnect", async (data) => {
29975
30122
  await this._onGatewayDisconnect(data);
29976
30123
  });
29977
30124
  }
@@ -30244,6 +30391,7 @@ var _AUNClient = class _AUNClient {
30244
30391
  this._slotId = aid.slotId || "default";
30245
30392
  this._logger = new AUNLogger({ debug: aid.debug, aunPath: nextConfig.aunPath });
30246
30393
  this._logger.bindDeviceId(this._deviceId);
30394
+ this._logger.bindAid(aid.aid);
30247
30395
  this._clientLog = this._logger.for("aun_core.client");
30248
30396
  this._logAuth = this._logger.for("aun_core.auth");
30249
30397
  this._logTransport = this._logger.for("aun_core.transport");
@@ -30285,10 +30433,10 @@ var _AUNClient = class _AUNClient {
30285
30433
  });
30286
30434
  this._transport = new RPCTransport({
30287
30435
  eventDispatcher: this._dispatcher,
30288
- timeout: DEFAULT_SESSION_OPTIONS.timeouts.call,
30289
- onDisconnect: (error, closeCode) => this._handleTransportDisconnect(error, closeCode)
30436
+ timeout: DEFAULT_SESSION_OPTIONS.timeouts.call
30290
30437
  });
30291
- this._transport.setMetaObserver(
30438
+ this._transport.setProtocolDisconnectCallback((error, closeCode) => this._handleTransportDisconnect(error, closeCode));
30439
+ this._transport.setProtocolMetaObserver(
30292
30440
  (meta) => this._observeRpcMeta(meta).catch((exc) => {
30293
30441
  this._clientLog.debug(`rpc meta observer skipped: ${String(exc)}`);
30294
30442
  })
@@ -31048,7 +31196,7 @@ var _AUNClient = class _AUNClient {
31048
31196
  }
31049
31197
  await this._transport.notify(directMethod, payload);
31050
31198
  }
31051
- async _callRawV2Rpc(method, params2) {
31199
+ async _callRawV2Rpc(method, params2, pullGateKey = "") {
31052
31200
  const p = { ...params2 ?? {} };
31053
31201
  const forceForeground = Boolean(p._rpc_foreground);
31054
31202
  const rpcBackground = !forceForeground && (Boolean(p._rpc_background) || this._backgroundRpcDepth > 0);
@@ -31073,7 +31221,10 @@ var _AUNClient = class _AUNClient {
31073
31221
  if (method.startsWith("group.") && p.slot_id === void 0) {
31074
31222
  p.slot_id = this._slotId;
31075
31223
  }
31076
- return await this._rpcPipeline.rawCall(method, p, { background: rpcBackground });
31224
+ return await this._rpcPipeline.rawCall(method, p, {
31225
+ background: rpcBackground,
31226
+ ...pullGateKey ? { pullGateKey } : {}
31227
+ });
31077
31228
  }
31078
31229
  // ── 事件 ──────────────────────────────────────────
31079
31230
  /**
@@ -31667,6 +31818,7 @@ ${invitee}` : "";
31667
31818
  if (identity && isJsonObject(identity)) {
31668
31819
  this._identity = identity;
31669
31820
  this._aid = String(identity.aid ?? this._aid ?? "");
31821
+ this._logger.bindAid(this._aid);
31670
31822
  if (this._sessionParams) {
31671
31823
  this._sessionParams.access_token = String(auth.token ?? params2.access_token ?? "");
31672
31824
  }
@@ -31867,6 +32019,7 @@ ${invitee}` : "";
31867
32019
  identity.access_token = accessToken;
31868
32020
  this._identity = identity;
31869
32021
  this._aid = String(identity.aid ?? this._aid ?? "");
32022
+ this._logger.bindAid(this._aid);
31870
32023
  if (identity.aid) {
31871
32024
  const persistIdentity = this._auth._persistIdentity;
31872
32025
  if (typeof persistIdentity === "function") {
@@ -32086,7 +32239,7 @@ ${invitee}` : "";
32086
32239
  }
32087
32240
  this._clientLog.warn(`token refresh failed (${this._tokenRefreshFailures}/3), next retry: ${String(exc)}`);
32088
32241
  } else {
32089
- this._dispatcher.enqueue("connection.error", { error: formatCaughtError2(exc) });
32242
+ this._dispatcher.enqueue("connection.error", { error: publicError(exc) });
32090
32243
  }
32091
32244
  }
32092
32245
  scheduleRefresh();
@@ -32136,7 +32289,7 @@ ${invitee}` : "";
32136
32289
  }
32137
32290
  this._dispatcher.enqueue("state_change", {
32138
32291
  state: this._publicState(this._state),
32139
- error
32292
+ error: error ? publicError(error) : null
32140
32293
  });
32141
32294
  if (reconnectAbort.signal.aborted || this._reconnectAbort !== reconnectAbort || this._closing) {
32142
32295
  if (this._reconnectAbort === reconnectAbort) {
@@ -32160,7 +32313,7 @@ ${invitee}` : "";
32160
32313
  const disconnectInfo = this._lastDisconnectInfo ?? {};
32161
32314
  const eventPayload = {
32162
32315
  state: this._publicState(this._state),
32163
- error,
32316
+ error: error ? publicError(error) : null,
32164
32317
  reason
32165
32318
  };
32166
32319
  const detail = disconnectInfo.detail;
@@ -32363,7 +32516,7 @@ ${invitee}` : "";
32363
32516
  this._lastError = exc instanceof Error ? exc : new Error(String(exc));
32364
32517
  this._lastErrorCode = "reconnect_failed";
32365
32518
  if (!reconnectAbort || !await this._publishReconnectEvent(reconnectAbort, "connection.error", {
32366
- error: formatCaughtError2(exc),
32519
+ error: publicError(exc),
32367
32520
  attempt
32368
32521
  })) return;
32369
32522
  if (!this._shouldRetryReconnect(exc)) {
@@ -32371,7 +32524,7 @@ ${invitee}` : "";
32371
32524
  this._nextRetryAt = null;
32372
32525
  if (reconnectAbort) await this._publishReconnectEvent(reconnectAbort, "state_change", {
32373
32526
  state: this._publicState(this._state),
32374
- error: formatCaughtError2(exc),
32527
+ error: publicError(exc),
32375
32528
  attempt
32376
32529
  });
32377
32530
  return;