@llblab/pi-telegram 0.50.1 → 0.51.1

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 (73) hide show
  1. package/AGENTS.md +10 -8
  2. package/BACKLOG.md +13 -32
  3. package/CHANGELOG.md +16 -0
  4. package/README.md +4 -3
  5. package/dist/lib/bindings.d.ts +4 -2
  6. package/dist/lib/bindings.js +5 -5
  7. package/dist/lib/bus-follower.d.ts +4 -2
  8. package/dist/lib/bus-follower.js +99 -10
  9. package/dist/lib/bus-leader.d.ts +9 -3
  10. package/dist/lib/bus-leader.js +231 -71
  11. package/dist/lib/bus.d.ts +4 -0
  12. package/dist/lib/bus.js +34 -7
  13. package/dist/lib/commands.d.ts +5 -0
  14. package/dist/lib/commands.js +9 -0
  15. package/dist/lib/extension.js +68 -3
  16. package/dist/lib/journal.d.ts +3 -0
  17. package/dist/lib/journal.js +13 -0
  18. package/dist/lib/lifecycle.d.ts +2 -0
  19. package/dist/lib/lifecycle.js +25 -4
  20. package/dist/lib/locks.d.ts +1 -0
  21. package/dist/lib/locks.js +32 -12
  22. package/dist/lib/paths.d.ts +10 -0
  23. package/dist/lib/paths.js +22 -1
  24. package/dist/lib/polling.js +2 -2
  25. package/dist/lib/queue.d.ts +9 -1
  26. package/dist/lib/queue.js +64 -13
  27. package/dist/lib/replies.d.ts +4 -0
  28. package/dist/lib/replies.js +14 -0
  29. package/dist/lib/routing.d.ts +1 -0
  30. package/dist/lib/routing.js +5 -0
  31. package/dist/lib/sync.d.ts +9 -0
  32. package/dist/lib/sync.js +41 -1
  33. package/dist/lib/telegram-api.d.ts +9 -1
  34. package/dist/lib/telegram-api.js +23 -3
  35. package/dist/lib/thread-cleanup-manager.js +7 -2
  36. package/dist/lib/threads.d.ts +2 -0
  37. package/dist/lib/threads.js +68 -37
  38. package/dist/lib/updates.d.ts +6 -4
  39. package/dist/lib/updates.js +134 -61
  40. package/dist/lib/workspace-admission.d.ts +9 -0
  41. package/dist/lib/workspace-admission.js +49 -3
  42. package/dist/lib/workspace-retirement.d.ts +77 -6
  43. package/dist/lib/workspace-retirement.js +384 -8
  44. package/dist/lib/workspace-slots.d.ts +3 -0
  45. package/dist/lib/workspace-slots.js +6 -0
  46. package/dist/package.json +1 -1
  47. package/docs/architecture.md +22 -15
  48. package/docs/multi-instance-bus.md +32 -11
  49. package/docs/public-api.md +1 -1
  50. package/docs/updates.md +2 -0
  51. package/lib/bindings.ts +12 -7
  52. package/lib/bus-follower.ts +82 -14
  53. package/lib/bus-leader.ts +236 -94
  54. package/lib/bus.ts +39 -9
  55. package/lib/commands.ts +19 -0
  56. package/lib/extension.ts +78 -2
  57. package/lib/journal.ts +14 -0
  58. package/lib/lifecycle.ts +23 -4
  59. package/lib/locks.ts +32 -13
  60. package/lib/paths.ts +29 -1
  61. package/lib/polling.ts +2 -2
  62. package/lib/queue.ts +77 -19
  63. package/lib/replies.ts +18 -0
  64. package/lib/routing.ts +7 -0
  65. package/lib/sync.ts +45 -1
  66. package/lib/telegram-api.ts +30 -2
  67. package/lib/thread-cleanup-manager.ts +11 -3
  68. package/lib/threads.ts +73 -36
  69. package/lib/updates.ts +145 -78
  70. package/lib/workspace-admission.ts +67 -4
  71. package/lib/workspace-retirement.ts +465 -7
  72. package/lib/workspace-slots.ts +7 -0
  73. package/package.json +1 -1
@@ -9,6 +9,7 @@ import { basename } from "node:path";
9
9
  import * as Sync from "./sync.js";
10
10
  import * as Threads from "./threads.js";
11
11
  import { parseTelegramUpdateJournalQueueOwner } from "./journal.js";
12
+ import { TELEGRAM_BUS_LEADER_STALE_HEARTBEAT_MS, } from "./locks.js";
12
13
  import { isTelegramApiMethodRetrySafe, TelegramApiCommitUnknownError, TelegramApiStaleTargetError, } from "./telegram-api.js";
13
14
  import { createTelegramBusFollowerDeliveryIdentity, createTelegramBusFollowerTargetController, createTelegramBusForeignOwnedUpdateForwarder, createTelegramBusLocalServer, createTelegramBusRequestIdFactory, createUnauthorizedBusAck, getTelegramBusProtocolCompatibility, getTelegramBusSocketPath, hasTelegramBusCapability, isTelegramBusEnvelopeAuthorized, resolveTelegramBusSocketPath, sendTelegramBusLocalEnvelope, TELEGRAM_BUS_CAPABILITY_WORKSPACE_THREAD_RENAME, TELEGRAM_BUS_CAPABILITY_THREAD_DISPLAY_MODE, TELEGRAM_BUS_CAPABILITY_DIRECTORY_DISPLAY_FORMAT, } from "./bus.js";
14
15
  import { getTelegramBusTransportRetryPolicy, TELEGRAM_BUS_REGISTRATION_RETRY, } from "./bus-transport.js";
@@ -17,6 +18,7 @@ export const TELEGRAM_BUS_FOLLOWER_PROMOTION_GRACE_MS = 2_500;
17
18
  export const TELEGRAM_FOLLOWER_SESSION_HANDOFF_TTL_MS = 30_000;
18
19
  export const TELEGRAM_BUS_FOLLOWER_CLIENT_TIMEOUT_MS = 30_000;
19
20
  export const TELEGRAM_BUS_FOLLOWER_REGISTRATION_WAIT_MS = 30_000;
21
+ export const TELEGRAM_BUS_FOLLOWER_HEARTBEAT_TIMEOUT_MS = TELEGRAM_BUS_LEADER_STALE_HEARTBEAT_MS;
20
22
  export const TELEGRAM_BUS_FOLLOWER_REGISTRATION_RETRY_ATTEMPTS = TELEGRAM_BUS_REGISTRATION_RETRY.attempts;
21
23
  export const TELEGRAM_BUS_FOLLOWER_REGISTRATION_RETRY_DELAY_MS = TELEGRAM_BUS_REGISTRATION_RETRY.delayMs;
22
24
  const TELEGRAM_FOLLOWER_SESSION_HANDOFF_KEY = "__piTelegramFollowerSessionHandoff";
@@ -139,6 +141,23 @@ export function createTelegramBusFollowerPromotionHandler(input) {
139
141
  });
140
142
  }
141
143
  export function createTelegramBusFollowerRuntimeAssembly(ports) {
144
+ // Binding startup needs registration identity before it can grant inbound authority.
145
+ let readyContext;
146
+ const isReadyContext = (ctx) => Boolean(readyContext &&
147
+ (ctx === undefined || readyContext.ctx === ctx) &&
148
+ ports.registrationState.getGeneration() === readyContext.generation &&
149
+ ports.registration.getSessionGeneration?.() === readyContext.sessionGeneration &&
150
+ ports.registration.isContextActive?.(readyContext.ctx) !== false);
151
+ const prepareContext = async (ctx) => {
152
+ const generation = ports.registrationState.getGeneration();
153
+ const sessionGeneration = ports.registration.getSessionGeneration?.();
154
+ readyContext = undefined;
155
+ await ports.registration.onRegistered?.(ctx);
156
+ if (generation && ports.registrationState.getGeneration() === generation &&
157
+ ports.registration.getSessionGeneration?.() === sessionGeneration &&
158
+ ports.registration.isContextActive?.(ctx) !== false)
159
+ readyContext = { generation, ctx, sessionGeneration };
160
+ };
142
161
  const sharedRuntimeDeps = {
143
162
  instanceId: ports.instanceId,
144
163
  registrationState: ports.registrationState,
@@ -148,7 +167,9 @@ export function createTelegramBusFollowerRuntimeAssembly(ports) {
148
167
  ...ports.receiver,
149
168
  instanceId: ports.instanceId,
150
169
  recordRuntimeEvent: ports.recordRuntimeEvent,
151
- getRegistrationGeneration: ports.registrationState.getGeneration,
170
+ getRegistrationGeneration() {
171
+ return isReadyContext() ? readyContext?.generation : undefined;
172
+ },
152
173
  handleReplaceTarget: createTelegramBusFollowerTargetReplacementHandler({
153
174
  ...ports.targetReplacement,
154
175
  ...sharedRuntimeDeps,
@@ -166,8 +187,24 @@ export function createTelegramBusFollowerRuntimeAssembly(ports) {
166
187
  ...sharedRuntimeDeps,
167
188
  startReceiving: receiver.start,
168
189
  stopReceiving: receiver.stop,
190
+ onRegistered: prepareContext,
169
191
  onHeartbeatFailure: recovery,
170
192
  });
193
+ const baseRegistration = registration;
194
+ registration = {
195
+ ...baseRegistration,
196
+ async setContext(ctx) {
197
+ const sessionGeneration = ports.registration.getSessionGeneration?.();
198
+ if (ports.registration.isContextActive?.(ctx) === false)
199
+ return;
200
+ await baseRegistration.setContext(ctx);
201
+ if (ports.registration.getSessionGeneration?.() !== sessionGeneration ||
202
+ ports.registration.isContextActive?.(ctx) === false)
203
+ return;
204
+ if (!isReadyContext(ctx))
205
+ await prepareContext(ctx);
206
+ },
207
+ };
171
208
  return { receiver, registration };
172
209
  }
173
210
  export function createTelegramBusFollowerTargetReplacementHandler(deps) {
@@ -575,7 +612,15 @@ export function createTelegramBusFollowerSessionRefreshHook(deps) {
575
612
  return;
576
613
  if (deps.isSessionActive && !deps.isSessionActive(ctx))
577
614
  return;
578
- deps.registrationRuntime.setContext(ctx);
615
+ try {
616
+ await deps.registrationRuntime.setContext(ctx);
617
+ }
618
+ catch (error) {
619
+ deps.recordRuntimeEvent("bus", error, { phase: "follower-session-refresh" });
620
+ return;
621
+ }
622
+ if (deps.isSessionActive && !deps.isSessionActive(ctx))
623
+ return;
579
624
  deps.updateStatus(ctx);
580
625
  deps.recordRuntimeEvent("bus", "Telegram follower session context refreshed", { phase: "follower-session-refresh" });
581
626
  };
@@ -877,6 +922,9 @@ export function createTelegramBusFollowerRegistrationRuntime(deps) {
877
922
  const getNowMs = deps.getNowMs ?? Date.now;
878
923
  const getPid = deps.getPid ?? (() => process.pid);
879
924
  const heartbeatMs = deps.heartbeatMs ?? 1000;
925
+ const heartbeatTimeoutMs = deps.heartbeatTimeoutMs ??
926
+ deps.timeoutMs ??
927
+ TELEGRAM_BUS_FOLLOWER_HEARTBEAT_TIMEOUT_MS;
880
928
  const registrationTimeoutMs = deps.registrationTimeoutMs ?? deps.timeoutMs ?? 30000;
881
929
  const registrationRetryAttempts = deps.registrationRetryAttempts ??
882
930
  TELEGRAM_BUS_FOLLOWER_REGISTRATION_RETRY_ATTEMPTS;
@@ -888,6 +936,7 @@ export function createTelegramBusFollowerRegistrationRuntime(deps) {
888
936
  let activeLeaderSocketPath;
889
937
  let activeAuthSecret;
890
938
  let activeRegistrationGeneration;
939
+ let registrationAttempt;
891
940
  let activeContext;
892
941
  let lastKnownTarget;
893
942
  let lastKnownSlot;
@@ -899,6 +948,7 @@ export function createTelegramBusFollowerRegistrationRuntime(deps) {
899
948
  heartbeatInterval = undefined;
900
949
  };
901
950
  const stop = () => {
951
+ registrationAttempt = undefined;
902
952
  stopHeartbeat();
903
953
  activeAuthSecret = undefined;
904
954
  activeRegistrationGeneration = undefined;
@@ -934,7 +984,7 @@ export function createTelegramBusFollowerRegistrationRuntime(deps) {
934
984
  try {
935
985
  const response = await sendTelegramBusLocalEnvelope({
936
986
  socketPath: leaderSocketPath,
937
- timeoutMs: deps.timeoutMs,
987
+ timeoutMs: heartbeatTimeoutMs,
938
988
  retry: getTelegramBusTransportRetryPolicy({
939
989
  endpoint: leaderSocketPath,
940
990
  operation: "operation",
@@ -1027,6 +1077,26 @@ export function createTelegramBusFollowerRegistrationRuntime(deps) {
1027
1077
  };
1028
1078
  return {
1029
1079
  registerWithLeader: async (ctx, leader, options) => {
1080
+ if (deps.isContextActive?.(ctx) === false)
1081
+ return false;
1082
+ const sessionGeneration = deps.getSessionGeneration?.();
1083
+ const attempt = { ctx, sessionGeneration };
1084
+ registrationAttempt = attempt;
1085
+ const isCurrentRequest = () => registrationAttempt === attempt &&
1086
+ deps.getSessionGeneration?.() === sessionGeneration && deps.isContextActive?.(ctx) !== false;
1087
+ const abandonOwnedRequest = async () => {
1088
+ if (registrationAttempt !== attempt)
1089
+ return;
1090
+ registrationAttempt = undefined;
1091
+ stopHeartbeat();
1092
+ activeLeaderSocketPath = undefined;
1093
+ activeAuthSecret = undefined;
1094
+ activeRegistrationGeneration = undefined;
1095
+ activeContext = undefined;
1096
+ deps.registrationState?.setRegistered(false);
1097
+ deps.setActiveAuthSecret?.(undefined);
1098
+ await deps.stopReceiving?.();
1099
+ };
1030
1100
  const pendingHandoff = options
1031
1101
  ? undefined
1032
1102
  : getTelegramFollowerSessionHandoff();
@@ -1041,6 +1111,10 @@ export function createTelegramBusFollowerRegistrationRuntime(deps) {
1041
1111
  deps.getLeaderSocketPath?.() ??
1042
1112
  getTelegramBusSocketPath();
1043
1113
  await deps.startReceiving?.();
1114
+ if (!isCurrentRequest()) {
1115
+ await abandonOwnedRequest();
1116
+ return false;
1117
+ }
1044
1118
  activeAuthSecret = deps.getLeaderAuthSecret
1045
1119
  ? deps.getLeaderAuthSecret(leader)
1046
1120
  : leader?.busSecret;
@@ -1070,7 +1144,7 @@ export function createTelegramBusFollowerRegistrationRuntime(deps) {
1070
1144
  sessionId: deps.getSessionId?.(ctx),
1071
1145
  pid: getPid(),
1072
1146
  processBirthId: deps.getProcessBirthId?.(),
1073
- sessionGeneration: deps.getSessionGeneration?.(),
1147
+ sessionGeneration,
1074
1148
  target: registrationOptions?.target ??
1075
1149
  deps.registrationState?.getTarget() ??
1076
1150
  lastKnownTarget,
@@ -1103,6 +1177,10 @@ export function createTelegramBusFollowerRegistrationRuntime(deps) {
1103
1177
  });
1104
1178
  }
1105
1179
  catch (error) {
1180
+ if (!isCurrentRequest()) {
1181
+ await abandonOwnedRequest();
1182
+ return false;
1183
+ }
1106
1184
  stopHeartbeat();
1107
1185
  activeLeaderSocketPath = undefined;
1108
1186
  activeAuthSecret = undefined;
@@ -1111,12 +1189,8 @@ export function createTelegramBusFollowerRegistrationRuntime(deps) {
1111
1189
  await deps.stopReceiving?.();
1112
1190
  throw error;
1113
1191
  }
1114
- if (deps.isContextActive && !deps.isContextActive(ctx)) {
1115
- stopHeartbeat();
1116
- activeLeaderSocketPath = undefined;
1117
- activeAuthSecret = undefined;
1118
- deps.setActiveAuthSecret?.(undefined);
1119
- await deps.stopReceiving?.();
1192
+ if (!isCurrentRequest()) {
1193
+ await abandonOwnedRequest();
1120
1194
  return false;
1121
1195
  }
1122
1196
  const compatibility = getTelegramBusProtocolCompatibility({
@@ -1164,6 +1238,10 @@ export function createTelegramBusFollowerRegistrationRuntime(deps) {
1164
1238
  await deps.onRegistered?.(ctx);
1165
1239
  }
1166
1240
  catch (error) {
1241
+ if (!isCurrentRequest()) {
1242
+ await abandonOwnedRequest();
1243
+ return false;
1244
+ }
1167
1245
  stopHeartbeat();
1168
1246
  activeLeaderSocketPath = undefined;
1169
1247
  activeAuthSecret = undefined;
@@ -1173,7 +1251,15 @@ export function createTelegramBusFollowerRegistrationRuntime(deps) {
1173
1251
  await deps.stopReceiving?.();
1174
1252
  throw error;
1175
1253
  }
1254
+ if (!isCurrentRequest()) {
1255
+ await abandonOwnedRequest();
1256
+ return false;
1257
+ }
1176
1258
  await requestHeartbeat();
1259
+ if (!isCurrentRequest()) {
1260
+ await abandonOwnedRequest();
1261
+ return false;
1262
+ }
1177
1263
  startHeartbeat(leaderSocketPath);
1178
1264
  if (pendingHandoffOptions &&
1179
1265
  getTelegramFollowerSessionHandoff()?.instanceId ===
@@ -1191,6 +1277,9 @@ export function createTelegramBusFollowerRegistrationRuntime(deps) {
1191
1277
  return false;
1192
1278
  },
1193
1279
  setContext(ctx) {
1280
+ if (registrationAttempt && (registrationAttempt.ctx !== ctx ||
1281
+ registrationAttempt.sessionGeneration !== deps.getSessionGeneration?.()))
1282
+ registrationAttempt = undefined;
1194
1283
  activeContext = ctx;
1195
1284
  },
1196
1285
  async setThreadDisplayMode(mode) {
@@ -12,7 +12,7 @@ import type { TelegramTarget } from "./target.ts";
12
12
  import * as Threads from "./threads.ts";
13
13
  import { type TelegramBusEnvelope, type TelegramBusFollowerRegistry, type TelegramBusFollowerView, type TelegramBusInstanceRegistration, type TelegramBusProtocolIdentity, type TelegramBusSocketPathSource } from "./bus.ts";
14
14
  import type { TelegramQueueHandoffPayload } from "./queue.ts";
15
- import { type TelegramWorkspaceOperationRunner } from "./workspace-retirement.ts";
15
+ import { type TelegramWorkspaceCapacityRunner, type TelegramWorkspaceSlotRotationPorts, type TelegramWorkspaceOperationRunner } from "./workspace-retirement.ts";
16
16
  import { type TelegramWorkspaceAdmissionLedger } from "./workspace-admission.ts";
17
17
  export declare const TELEGRAM_BUS_FOLLOWER_STALE_AFTER_MS = 15000;
18
18
  export type TelegramBusWorkspaceAdmissionRunner = TelegramWorkspaceOperationRunner;
@@ -90,7 +90,7 @@ export interface TelegramBusFollowerTargetProvisionerDeps {
90
90
  recordRuntimeEvent: (category: string, error: unknown, details?: Record<string, unknown>) => void;
91
91
  }
92
92
  export interface TelegramBusFollowerDisconnectHandlerDeps {
93
- topicTargetStore: Pick<Threads.TelegramTopicTargetStore, "list" | "markStaleByTarget" | "markWorkspaceBindingInactiveByTarget" | "persist" | "upsertPendingCleanup" | "removePendingCleanup">;
93
+ topicTargetStore: Pick<Threads.TelegramTopicTargetStore, "list" | "markStaleByTarget" | "persist" | "upsertPendingCleanup" | "removePendingCleanup">;
94
94
  callApi: <TResponse>(method: string, body: Record<string, unknown>) => Promise<TResponse>;
95
95
  getCurrentLeaderEpoch?: () => number | string | undefined;
96
96
  getSyncState: () => Sync.TelegramSyncState;
@@ -108,7 +108,7 @@ export interface TelegramBusLeaderRuntimeAssemblyDeps<TContext> {
108
108
  getThreadDisplayMode?: () => TelegramThreadDisplayMode;
109
109
  persistThreadDisplayMode?: (mode: TelegramThreadDisplayMode, isCurrent: () => boolean) => Promise<void>;
110
110
  onThreadDisplayChanged?: () => void;
111
- runtime: Omit<TelegramBusLeaderRuntimeDeps<TContext>, "callApi" | "onFollowerDisconnected" | "onFollowerConfirmedDead" | "provisionFollowerTarget" | "provisionLeaderTarget" | "recordRuntimeEvent">;
111
+ runtime: Omit<TelegramBusLeaderRuntimeDeps<TContext>, "callApi" | "onFollowerDisconnected" | "onFollowerConfirmedDead" | "onFollowerConfirmedDeadPreserved" | "getTelegramProfile" | "provisionFollowerTarget" | "provisionLeaderTarget" | "recordRuntimeEvent">;
112
112
  getAllowedUserId: () => number | undefined;
113
113
  instanceId: string;
114
114
  getCwd?: (ctx: TContext) => string | undefined;
@@ -133,6 +133,7 @@ export interface TelegramBusLeaderRuntimeAssemblyDeps<TContext> {
133
133
  captureWorkspaceExternalProtection?: (binding: Threads.TelegramWorkspaceThreadBinding) => Threads.TelegramWorkspaceExternalProtectionEvidence;
134
134
  getWorkspaceAdmission?: () => Pick<TelegramWorkspaceAdmissionLedger, "acquireAdmission" | "releaseAdmission"> | undefined;
135
135
  runWorkspaceOperation?: TelegramBusWorkspaceAdmissionRunner;
136
+ workspaceRotation?: TelegramWorkspaceSlotRotationPorts;
136
137
  }
137
138
  export declare function createTelegramBusLeaderRuntimeAssembly<TContext>(deps: TelegramBusLeaderRuntimeAssemblyDeps<TContext>): TelegramBusLeaderRuntime<TContext> & {
138
139
  renameLeaderThreadAdmitted: (threadName: string, expectedTarget?: Threads.TelegramTopicTargetRecord["target"]) => Promise<Threads.TelegramTopicTargetRecord>;
@@ -192,8 +193,10 @@ export interface TelegramBusLeaderRuntimeDeps<TContext> {
192
193
  applyThreadDisplayMode?: (mode: TelegramThreadDisplayMode, isCurrent: () => boolean) => Promise<void>;
193
194
  getThreadDisplayMode?: () => TelegramThreadDisplayMode;
194
195
  getCurrentLeaderEpoch?: () => number | string | undefined;
196
+ getTelegramProfile?: () => string | undefined;
195
197
  provisionLeaderTarget?: (ctx: TContext) => Promise<void> | void;
196
198
  runWorkspaceAdmission?: TelegramBusWorkspaceAdmissionRunner;
199
+ runWithWorkspaceCapacity?: TelegramWorkspaceCapacityRunner;
197
200
  getNowMs?: () => number;
198
201
  timeoutMs?: number;
199
202
  followerPruneIntervalMs?: number;
@@ -202,6 +205,8 @@ export interface TelegramBusLeaderRuntimeDeps<TContext> {
202
205
  shouldCleanupConfirmedDeadFollower?: () => Promise<boolean> | boolean;
203
206
  onFollowerDisconnected?: (follower: TelegramBusFollowerView) => Promise<void> | void;
204
207
  onFollowerConfirmedDead?: (follower: TelegramBusFollowerView) => Promise<void> | void;
208
+ /** True settles this observation; false needs fresh proof before another attempt. */
209
+ onFollowerConfirmedDeadPreserved?: (follower: TelegramBusFollowerView, isDetached: () => boolean, operationId: string) => Promise<boolean> | boolean;
205
210
  recordRuntimeEvent?: (category: string, error: unknown, details?: Record<string, unknown>) => void;
206
211
  }
207
212
  export declare function createTelegramBusInstanceLifecycleAnnouncement(input: {
@@ -275,6 +280,7 @@ export declare function createTelegramBusLeaderEnvelopeHandler(deps: {
275
280
  getCurrentLeaderEpoch?: () => number | string | undefined;
276
281
  runFollowerMutation?: TelegramBusFollowerMutationRunner;
277
282
  runWorkspaceAdmission?: TelegramBusWorkspaceAdmissionRunner;
283
+ runWithWorkspaceCapacity?: TelegramWorkspaceCapacityRunner;
278
284
  }): (envelope: TelegramBusEnvelope) => Promise<TelegramBusEnvelope> | TelegramBusEnvelope;
279
285
  export interface TelegramBusLeaderActivationSchedulerDeps<TContext> {
280
286
  isBusEnabled: () => boolean;