@llblab/pi-telegram 0.2.10 → 0.4.0

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 (47) hide show
  1. package/README.md +52 -19
  2. package/docs/README.md +2 -3
  3. package/docs/architecture.md +62 -31
  4. package/docs/locks.md +136 -0
  5. package/index.ts +323 -1880
  6. package/lib/api.ts +396 -60
  7. package/lib/attachments.ts +128 -16
  8. package/lib/commands.ts +648 -14
  9. package/lib/config.ts +169 -0
  10. package/lib/handlers.ts +474 -0
  11. package/lib/locks.ts +306 -0
  12. package/lib/media.ts +196 -46
  13. package/lib/menu.ts +920 -338
  14. package/lib/model.ts +647 -0
  15. package/lib/pi.ts +90 -0
  16. package/lib/polling.ts +240 -14
  17. package/lib/preview.ts +420 -25
  18. package/lib/queue.ts +1137 -110
  19. package/lib/registration.ts +214 -31
  20. package/lib/rendering.ts +560 -366
  21. package/lib/replies.ts +198 -8
  22. package/lib/routing.ts +217 -0
  23. package/lib/runtime.ts +475 -0
  24. package/lib/setup.ts +143 -1
  25. package/lib/status.ts +432 -13
  26. package/lib/turns.ts +217 -36
  27. package/lib/updates.ts +340 -109
  28. package/package.json +18 -3
  29. package/AGENTS.md +0 -91
  30. package/BACKLOG.md +0 -5
  31. package/CHANGELOG.md +0 -34
  32. package/lib/model-switch.ts +0 -62
  33. package/lib/types.ts +0 -137
  34. package/tests/api.test.ts +0 -331
  35. package/tests/attachments.test.ts +0 -132
  36. package/tests/commands.test.ts +0 -85
  37. package/tests/config.test.ts +0 -80
  38. package/tests/media.test.ts +0 -166
  39. package/tests/menu.test.ts +0 -676
  40. package/tests/polling.test.ts +0 -202
  41. package/tests/preview.test.ts +0 -480
  42. package/tests/queue.test.ts +0 -3245
  43. package/tests/registration.test.ts +0 -268
  44. package/tests/rendering.test.ts +0 -526
  45. package/tests/replies.test.ts +0 -142
  46. package/tests/turns.test.ts +0 -247
  47. package/tests/updates.test.ts +0 -416
package/lib/replies.ts CHANGED
@@ -3,10 +3,75 @@
3
3
  * Owns rendered-message delivery, reply transport wiring, and plain or markdown final replies
4
4
  */
5
5
 
6
- import type { TelegramRenderedChunk, TelegramRenderMode } from "./rendering.ts";
6
+ import type { TelegramReplyParameters, TelegramSentMessage } from "./api.ts";
7
+ import {
8
+ renderTelegramMessage,
9
+ type TelegramRenderedChunk,
10
+ type TelegramRenderMode,
11
+ } from "./rendering.ts";
7
12
 
8
- export interface TelegramSentMessageLike {
9
- message_id: number;
13
+ export function buildTelegramReplyParameters(
14
+ messageId: number | undefined,
15
+ ): TelegramReplyParameters | undefined {
16
+ if (messageId === undefined) return undefined;
17
+ return { message_id: messageId, allow_sending_without_reply: true };
18
+ }
19
+
20
+ export function buildTelegramMultipartReplyParameters(
21
+ messageId: number | undefined,
22
+ ): string | undefined {
23
+ const parameters = buildTelegramReplyParameters(messageId);
24
+ return parameters ? JSON.stringify(parameters) : undefined;
25
+ }
26
+
27
+ function getAgentMessageField(message: unknown, field: string): unknown {
28
+ if (typeof message !== "object" || message === null || !(field in message)) {
29
+ return undefined;
30
+ }
31
+ return Reflect.get(message, field);
32
+ }
33
+
34
+ export function isAssistantAgentMessage(message: unknown): boolean {
35
+ return getAgentMessageField(message, "role") === "assistant";
36
+ }
37
+
38
+ function extractAgentTextContent(content: unknown): string {
39
+ const blocks = Array.isArray(content) ? content : [];
40
+ return blocks
41
+ .filter(
42
+ (block): block is { type: string; text?: string } =>
43
+ typeof block === "object" && block !== null && "type" in block,
44
+ )
45
+ .filter((block) => block.type === "text" && typeof block.text === "string")
46
+ .map((block) => block.text as string)
47
+ .join("")
48
+ .trim();
49
+ }
50
+
51
+ export function getAgentMessageText(message: unknown): string {
52
+ return extractAgentTextContent(getAgentMessageField(message, "content"));
53
+ }
54
+
55
+ export function extractLatestAssistantMessageText(
56
+ messages: readonly unknown[],
57
+ ): {
58
+ text?: string;
59
+ stopReason?: string;
60
+ errorMessage?: string;
61
+ } {
62
+ for (let i = messages.length - 1; i >= 0; i--) {
63
+ const message = messages[i];
64
+ if (!message || !isAssistantAgentMessage(message)) continue;
65
+ const rawStopReason = getAgentMessageField(message, "stopReason");
66
+ const rawErrorMessage = getAgentMessageField(message, "errorMessage");
67
+ const stopReason =
68
+ typeof rawStopReason === "string" ? rawStopReason : undefined;
69
+ const errorMessage =
70
+ typeof rawErrorMessage === "string" ? rawErrorMessage : undefined;
71
+ const text = getAgentMessageText(message);
72
+ return { text: text || undefined, stopReason, errorMessage };
73
+ }
74
+ return {};
10
75
  }
11
76
 
12
77
  export interface TelegramReplyDeliveryDeps<TReplyMarkup> {
@@ -15,21 +80,22 @@ export interface TelegramReplyDeliveryDeps<TReplyMarkup> {
15
80
  text: string;
16
81
  parse_mode?: "HTML";
17
82
  reply_markup?: TReplyMarkup;
18
- }) => Promise<TelegramSentMessageLike>;
83
+ reply_parameters?: TelegramReplyParameters;
84
+ }) => Promise<TelegramSentMessage>;
19
85
  editMessage: (body: {
20
86
  chat_id: number;
21
87
  message_id: number;
22
88
  text: string;
23
89
  parse_mode?: "HTML";
24
90
  reply_markup?: TReplyMarkup;
25
- }) => Promise<void>;
91
+ }) => Promise<unknown>;
26
92
  }
27
93
 
28
94
  export interface TelegramReplyTransport<TReplyMarkup> {
29
95
  sendRenderedChunks: (
30
96
  chatId: number,
31
97
  chunks: TelegramRenderedChunk[],
32
- options?: { replyMarkup?: TReplyMarkup },
98
+ options?: { replyMarkup?: TReplyMarkup; replyToMessageId?: number },
33
99
  ) => Promise<number | undefined>;
34
100
  editRenderedMessage: (
35
101
  chatId: number,
@@ -62,16 +128,21 @@ export async function sendTelegramRenderedChunks<TReplyMarkup>(
62
128
  chatId: number,
63
129
  chunks: TelegramRenderedChunk[],
64
130
  deps: TelegramReplyDeliveryDeps<TReplyMarkup>,
65
- options?: { replyMarkup?: TReplyMarkup },
131
+ options?: { replyMarkup?: TReplyMarkup; replyToMessageId?: number },
66
132
  ): Promise<number | undefined> {
67
133
  let lastMessageId: number | undefined;
68
134
  for (const [index, chunk] of chunks.entries()) {
135
+ const replyParameters =
136
+ index === 0
137
+ ? buildTelegramReplyParameters(options?.replyToMessageId)
138
+ : undefined;
69
139
  const sent = await deps.sendMessage({
70
140
  chat_id: chatId,
71
141
  text: chunk.text,
72
142
  parse_mode: chunk.parseMode,
73
143
  reply_markup:
74
144
  index === chunks.length - 1 ? options?.replyMarkup : undefined,
145
+ ...(replyParameters ? { reply_parameters: replyParameters } : {}),
75
146
  });
76
147
  lastMessageId = sent.message_id;
77
148
  }
@@ -96,7 +167,9 @@ export async function editTelegramRenderedMessage<TReplyMarkup>(
96
167
  remainingChunks.length === 0 ? options?.replyMarkup : undefined,
97
168
  });
98
169
  if (remainingChunks.length > 0) {
99
- return sendTelegramRenderedChunks(chatId, remainingChunks, deps, options);
170
+ return sendTelegramRenderedChunks(chatId, remainingChunks, deps, {
171
+ replyMarkup: options?.replyMarkup,
172
+ });
100
173
  }
101
174
  return messageId;
102
175
  }
@@ -132,3 +205,120 @@ export async function sendTelegramMarkdownReply(
132
205
  }
133
206
  return deps.sendRenderedChunks(chunks);
134
207
  }
208
+
209
+ export interface TelegramRenderedMessageRuntimeDeps<TReplyMarkup> {
210
+ renderTelegramMessage: (
211
+ text: string,
212
+ options?: { mode?: TelegramRenderMode },
213
+ ) => TelegramRenderedChunk[];
214
+ replyTransport: TelegramReplyTransport<TReplyMarkup>;
215
+ }
216
+
217
+ export interface TelegramRenderedMessageRuntime<TReplyMarkup> {
218
+ sendTextReply: (
219
+ chatId: number,
220
+ replyToMessageId: number,
221
+ text: string,
222
+ options?: { parseMode?: "HTML" },
223
+ ) => Promise<number | undefined>;
224
+ sendMarkdownReply: (
225
+ chatId: number,
226
+ replyToMessageId: number,
227
+ markdown: string,
228
+ ) => Promise<number | undefined>;
229
+ editInteractiveMessage: (
230
+ chatId: number,
231
+ messageId: number,
232
+ text: string,
233
+ mode: TelegramRenderMode,
234
+ replyMarkup: TReplyMarkup,
235
+ ) => Promise<void>;
236
+ sendInteractiveMessage: (
237
+ chatId: number,
238
+ text: string,
239
+ mode: TelegramRenderMode,
240
+ replyMarkup: TReplyMarkup,
241
+ ) => Promise<number | undefined>;
242
+ }
243
+
244
+ export interface TelegramRenderedMessageDeliveryRuntime<
245
+ TReplyMarkup,
246
+ > extends TelegramRenderedMessageRuntime<TReplyMarkup> {
247
+ replyTransport: TelegramReplyTransport<TReplyMarkup>;
248
+ }
249
+
250
+ export interface TelegramRenderedMessageDeliveryRuntimeDeps<
251
+ TReplyMarkup,
252
+ > extends TelegramReplyDeliveryDeps<TReplyMarkup> {
253
+ renderTelegramMessage?: (
254
+ text: string,
255
+ options?: { mode?: TelegramRenderMode },
256
+ ) => TelegramRenderedChunk[];
257
+ }
258
+
259
+ export function createTelegramRenderedMessageDeliveryRuntime<TReplyMarkup>(
260
+ deps: TelegramRenderedMessageDeliveryRuntimeDeps<TReplyMarkup>,
261
+ ): TelegramRenderedMessageDeliveryRuntime<TReplyMarkup> {
262
+ const replyTransport = buildTelegramReplyTransport({
263
+ sendMessage: deps.sendMessage,
264
+ editMessage: deps.editMessage,
265
+ });
266
+ return {
267
+ replyTransport,
268
+ ...createTelegramRenderedMessageRuntime({
269
+ renderTelegramMessage:
270
+ deps.renderTelegramMessage ?? renderTelegramMessage,
271
+ replyTransport,
272
+ }),
273
+ };
274
+ }
275
+
276
+ export function createTelegramRenderedMessageRuntime<TReplyMarkup>(
277
+ deps: TelegramRenderedMessageRuntimeDeps<TReplyMarkup>,
278
+ ): TelegramRenderedMessageRuntime<TReplyMarkup> {
279
+ return {
280
+ sendTextReply: async (chatId, replyToMessageId, text, options) => {
281
+ return sendTelegramPlainReply(
282
+ text,
283
+ {
284
+ renderTelegramMessage: deps.renderTelegramMessage,
285
+ sendRenderedChunks: (chunks) =>
286
+ deps.replyTransport.sendRenderedChunks(chatId, chunks, {
287
+ replyToMessageId,
288
+ }),
289
+ },
290
+ options,
291
+ );
292
+ },
293
+ sendMarkdownReply: async (chatId, replyToMessageId, markdown) => {
294
+ return sendTelegramMarkdownReply(markdown, {
295
+ renderTelegramMessage: deps.renderTelegramMessage,
296
+ sendRenderedChunks: (chunks) =>
297
+ deps.replyTransport.sendRenderedChunks(chatId, chunks, {
298
+ replyToMessageId,
299
+ }),
300
+ });
301
+ },
302
+ editInteractiveMessage: async (
303
+ chatId,
304
+ messageId,
305
+ text,
306
+ mode,
307
+ replyMarkup,
308
+ ) => {
309
+ await deps.replyTransport.editRenderedMessage(
310
+ chatId,
311
+ messageId,
312
+ deps.renderTelegramMessage(text, { mode }),
313
+ { replyMarkup },
314
+ );
315
+ },
316
+ sendInteractiveMessage: async (chatId, text, mode, replyMarkup) => {
317
+ return deps.replyTransport.sendRenderedChunks(
318
+ chatId,
319
+ deps.renderTelegramMessage(text, { mode }),
320
+ { replyMarkup },
321
+ );
322
+ },
323
+ };
324
+ }
package/lib/routing.ts ADDED
@@ -0,0 +1,217 @@
1
+ /**
2
+ * Telegram inbound routing composition
3
+ * Wires authorized updates into menus, commands, media grouping, and prompt queueing
4
+ */
5
+
6
+ import * as Commands from "./commands.ts";
7
+ import type { TelegramConfigStore } from "./config.ts";
8
+ import type { TelegramAttachmentHandlerRuntime } from "./handlers.ts";
9
+ import * as Media from "./media.ts";
10
+ import * as Menu from "./menu.ts";
11
+ import * as Model from "./model.ts";
12
+ import * as Queue from "./queue.ts";
13
+ import type { TelegramBridgeRuntime } from "./runtime.ts";
14
+ import * as Turns from "./turns.ts";
15
+ import * as Updates from "./updates.ts";
16
+
17
+ export type TelegramRoutedMessage = Updates.TelegramUpdateMessage &
18
+ Media.TelegramMediaMessage &
19
+ Media.TelegramMediaGroupMessage &
20
+ Commands.TelegramCommandRuntimeMessage &
21
+ Turns.TelegramTurnMessage;
22
+
23
+ export type TelegramRoutedCallbackQuery = Updates.TelegramCallbackQuery &
24
+ Menu.MenuCallbackQuery;
25
+
26
+ export interface TelegramInboundRouteRuntimeDeps<
27
+ TUpdate extends Updates.TelegramUpdateFlow & {
28
+ message?: TMessage;
29
+ edited_message?: TMessage;
30
+ callback_query?: TCallbackQuery;
31
+ },
32
+ TMessage extends TelegramRoutedMessage,
33
+ TCallbackQuery extends TelegramRoutedCallbackQuery,
34
+ TContext,
35
+ TModel extends Model.MenuModel,
36
+ > {
37
+ configStore: Pick<
38
+ TelegramConfigStore,
39
+ "getAllowedUserId" | "setAllowedUserId" | "persist"
40
+ >;
41
+ bridgeRuntime: TelegramBridgeRuntime;
42
+ activeTurnRuntime: Queue.TelegramActiveTurnStore;
43
+ mediaGroupRuntime: Media.TelegramMediaGroupController<TMessage>;
44
+ telegramQueueStore: Queue.TelegramQueueStateStore<TContext>;
45
+ queueMutationRuntime: Queue.TelegramQueueMutationController<TContext>;
46
+ modelMenuRuntime: Menu.TelegramModelMenuRuntime<TModel>;
47
+ currentModelRuntime: Model.CurrentModelRuntime<TContext, TModel>;
48
+ modelSwitchController: Model.TelegramModelSwitchController<
49
+ TContext,
50
+ Model.ScopedTelegramModel<TModel>
51
+ >;
52
+ menuActions: Menu.TelegramMenuActionRuntime<TContext, TModel>;
53
+ attachmentHandlerRuntime: TelegramAttachmentHandlerRuntime<TContext>;
54
+ updateStatus: (ctx: TContext, error?: string) => void;
55
+ dispatchNextQueuedTelegramTurn: (ctx: TContext) => void;
56
+ answerCallbackQuery: (
57
+ callbackQueryId: string,
58
+ text?: string,
59
+ ) => Promise<void>;
60
+ sendTextReply: (
61
+ chatId: number,
62
+ replyToMessageId: number,
63
+ text: string,
64
+ ) => Promise<number | undefined>;
65
+ setMyCommands: Commands.TelegramBotCommandRegistrationDeps["setMyCommands"];
66
+ downloadFile: Media.DownloadTelegramMessageFilesDeps["downloadFile"];
67
+ getThinkingLevel: () => Model.ThinkingLevel;
68
+ setThinkingLevel: (level: Model.ThinkingLevel) => void;
69
+ setModel: (model: TModel) => Promise<boolean>;
70
+ isIdle: (ctx: TContext) => boolean;
71
+ hasPendingMessages: (ctx: TContext) => boolean;
72
+ compact: (
73
+ ctx: TContext,
74
+ callbacks: { onComplete: () => void; onError: (error: unknown) => void },
75
+ ) => void;
76
+ recordRuntimeEvent?: (
77
+ category: string,
78
+ error: unknown,
79
+ details?: Record<string, unknown>,
80
+ ) => void;
81
+ }
82
+
83
+ export function createTelegramInboundRouteRuntime<
84
+ TUpdate extends Updates.TelegramUpdateFlow & {
85
+ message?: TMessage;
86
+ edited_message?: TMessage;
87
+ callback_query?: TCallbackQuery;
88
+ },
89
+ TMessage extends TelegramRoutedMessage,
90
+ TCallbackQuery extends TelegramRoutedCallbackQuery,
91
+ TContext,
92
+ TModel extends Model.MenuModel,
93
+ >(
94
+ deps: TelegramInboundRouteRuntimeDeps<
95
+ TUpdate,
96
+ TMessage,
97
+ TCallbackQuery,
98
+ TContext,
99
+ TModel
100
+ >,
101
+ ): Updates.TelegramUpdateRuntimeController<TContext, TUpdate> {
102
+ const callbackHandler = Menu.createTelegramMenuCallbackHandlerForContext<
103
+ TCallbackQuery,
104
+ TContext,
105
+ TModel
106
+ >({
107
+ getStoredModelMenuState: deps.modelMenuRuntime.getState,
108
+ getActiveModel: deps.currentModelRuntime.get,
109
+ getThinkingLevel: deps.getThinkingLevel,
110
+ setThinkingLevel: deps.setThinkingLevel,
111
+ updateStatus: deps.updateStatus,
112
+ updateModelMenuMessage: deps.menuActions.updateModelMenuMessage,
113
+ updateThinkingMenuMessage: deps.menuActions.updateThinkingMenuMessage,
114
+ updateStatusMessage: deps.menuActions.updateStatusMessage,
115
+ answerCallbackQuery: deps.answerCallbackQuery,
116
+ isIdle: deps.isIdle,
117
+ hasActiveTelegramTurn: deps.activeTurnRuntime.has,
118
+ hasAbortHandler: deps.bridgeRuntime.abort.hasHandler,
119
+ getActiveToolExecutions: deps.bridgeRuntime.lifecycle.getActiveToolExecutions,
120
+ setModel: deps.setModel,
121
+ setCurrentModel: deps.currentModelRuntime.setCurrentModel,
122
+ stagePendingModelSwitch: deps.modelSwitchController.stagePendingSwitch,
123
+ restartInterruptedTelegramTurn:
124
+ deps.modelSwitchController.restartInterruptedTurn,
125
+ });
126
+ const commandHandler = Commands.createTelegramCommandHandlerTargetRuntime<
127
+ TMessage,
128
+ TContext
129
+ >({
130
+ hasAbortHandler: deps.bridgeRuntime.abort.hasHandler,
131
+ clearPendingModelSwitch: deps.modelSwitchController.clearPendingSwitch,
132
+ hasQueuedTelegramItems: deps.telegramQueueStore.hasQueuedItems,
133
+ setPreserveQueuedTurnsAsHistory:
134
+ deps.bridgeRuntime.lifecycle.setPreserveQueuedTurnsAsHistory,
135
+ abortCurrentTurn: deps.bridgeRuntime.abort.abortTurn,
136
+ isIdle: deps.isIdle,
137
+ hasPendingMessages: deps.hasPendingMessages,
138
+ hasActiveTelegramTurn: deps.activeTurnRuntime.has,
139
+ hasDispatchPending: deps.bridgeRuntime.lifecycle.hasDispatchPending,
140
+ isCompactionInProgress: deps.bridgeRuntime.lifecycle.isCompactionInProgress,
141
+ setCompactionInProgress: deps.bridgeRuntime.lifecycle.setCompactionInProgress,
142
+ updateStatus: deps.updateStatus,
143
+ dispatchNextQueuedTelegramTurn: deps.dispatchNextQueuedTelegramTurn,
144
+ compact: deps.compact,
145
+ allocateItemOrder: deps.bridgeRuntime.queue.allocateItemOrder,
146
+ allocateControlOrder: deps.bridgeRuntime.queue.allocateControlOrder,
147
+ appendControlItem: deps.queueMutationRuntime.append,
148
+ showStatus: deps.menuActions.sendStatusMessage,
149
+ openModelMenu: deps.menuActions.openModelMenu,
150
+ getAllowedUserId: deps.configStore.getAllowedUserId,
151
+ setAllowedUserId: deps.configStore.setAllowedUserId,
152
+ setMyCommands: deps.setMyCommands,
153
+ persistConfig: deps.configStore.persist,
154
+ sendTextReply: deps.sendTextReply,
155
+ recordRuntimeEvent: deps.recordRuntimeEvent,
156
+ });
157
+ const promptEnqueue = Queue.createTelegramPromptEnqueueController<
158
+ TMessage,
159
+ TContext
160
+ >({
161
+ ...deps.telegramQueueStore,
162
+ getPreserveQueuedTurnsAsHistory:
163
+ deps.bridgeRuntime.lifecycle.shouldPreserveQueuedTurnsAsHistory,
164
+ setPreserveQueuedTurnsAsHistory:
165
+ deps.bridgeRuntime.lifecycle.setPreserveQueuedTurnsAsHistory,
166
+ createTurn: Turns.createTelegramPromptTurnRuntimeBuilder<
167
+ TMessage,
168
+ TContext
169
+ >({
170
+ allocateQueueOrder: deps.bridgeRuntime.queue.allocateItemOrder,
171
+ downloadFile: deps.downloadFile,
172
+ processAttachments: deps.attachmentHandlerRuntime.process,
173
+ }),
174
+ updateStatus: deps.updateStatus,
175
+ dispatchNextQueuedTelegramTurn: deps.dispatchNextQueuedTelegramTurn,
176
+ }).enqueue;
177
+ const commandOrPrompt = Commands.createTelegramCommandOrPromptRuntime<
178
+ TMessage,
179
+ TContext
180
+ >({
181
+ extractRawText: Media.extractFirstTelegramMessageText,
182
+ handleCommand: commandHandler,
183
+ enqueueTurn: promptEnqueue,
184
+ });
185
+ const mediaDispatch = Media.createTelegramMediaGroupDispatchRuntime<
186
+ TMessage,
187
+ TContext
188
+ >({
189
+ mediaGroups: deps.mediaGroupRuntime,
190
+ dispatchMessages: commandOrPrompt.dispatchMessages,
191
+ });
192
+ const editRuntime = Turns.createTelegramQueuedPromptEditRuntime<
193
+ TMessage,
194
+ TContext
195
+ >({
196
+ ...deps.telegramQueueStore,
197
+ updateStatus: deps.updateStatus,
198
+ });
199
+ return Updates.createTelegramPairedUpdateRuntime<TContext, TUpdate>({
200
+ getAllowedUserId: deps.configStore.getAllowedUserId,
201
+ setAllowedUserId: deps.configStore.setAllowedUserId,
202
+ persistConfig: deps.configStore.persist,
203
+ updateStatus: deps.updateStatus,
204
+ removePendingMediaGroupMessages: deps.mediaGroupRuntime.removeMessages,
205
+ removeQueuedTelegramTurnsByMessageIds:
206
+ deps.queueMutationRuntime.removeByMessageIds,
207
+ clearQueuedTelegramTurnPriorityByMessageId:
208
+ deps.queueMutationRuntime.clearPriorityByMessageId,
209
+ prioritizeQueuedTelegramTurnByMessageId:
210
+ deps.queueMutationRuntime.prioritizeByMessageId,
211
+ answerCallbackQuery: deps.answerCallbackQuery,
212
+ handleAuthorizedTelegramCallbackQuery: callbackHandler,
213
+ sendTextReply: deps.sendTextReply,
214
+ handleAuthorizedTelegramMessage: mediaDispatch.handleMessage,
215
+ handleAuthorizedTelegramEditedMessage: editRuntime.updateFromEditedMessage,
216
+ });
217
+ }