@llblab/pi-telegram 0.2.9 → 0.3.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.
package/lib/preview.ts CHANGED
@@ -3,15 +3,30 @@
3
3
  * Owns preview transport selection, runtime updates, and preview finalization
4
4
  */
5
5
 
6
+ import type {
7
+ TelegramEditMessageTextBody,
8
+ TelegramReplyParameters,
9
+ TelegramSendMessageBody,
10
+ TelegramSentMessage,
11
+ } from "./api.ts";
6
12
  import {
7
13
  buildTelegramPreviewSnapshot,
14
+ MAX_MESSAGE_LENGTH,
15
+ renderMarkdownPreviewText,
16
+ renderTelegramMessage,
8
17
  type TelegramPreviewRenderStrategy,
9
18
  type TelegramPreviewSnapshot,
10
19
  type TelegramRenderedChunk,
11
20
  type TelegramRenderMode,
12
21
  } from "./rendering.ts";
22
+ import { buildTelegramReplyParameters } from "./replies.ts";
13
23
 
14
- export interface TelegramPreviewStateLike {
24
+ const TELEGRAM_PREVIEW_THROTTLE_MS = 750;
25
+ const TELEGRAM_DRAFT_ID_MAX = 2_147_483_647;
26
+
27
+ export type TelegramDraftSupport = "unknown" | "supported" | "unsupported";
28
+
29
+ export interface TelegramPreviewState {
15
30
  mode: "draft" | "message";
16
31
  draftId?: number;
17
32
  messageId?: number;
@@ -21,13 +36,13 @@ export interface TelegramPreviewStateLike {
21
36
  lastSentStrategy?: TelegramPreviewRenderStrategy;
22
37
  }
23
38
 
24
- export interface TelegramPreviewRuntimeState extends TelegramPreviewStateLike {
39
+ export interface TelegramPreviewRuntimeState extends TelegramPreviewState {
25
40
  flushTimer?: ReturnType<typeof setTimeout>;
41
+ flushPromise?: Promise<void>;
42
+ flushRequested?: boolean;
26
43
  }
27
44
 
28
- export interface TelegramSentPreviewMessageLike {
29
- message_id: number;
30
- }
45
+ export type TelegramSentPreviewMessage = TelegramSentMessage;
31
46
 
32
47
  export interface TelegramPreviewRuntimeDeps {
33
48
  getState: () => TelegramPreviewRuntimeState | undefined;
@@ -35,21 +50,25 @@ export interface TelegramPreviewRuntimeDeps {
35
50
  clearScheduledFlush: (state: TelegramPreviewRuntimeState) => void;
36
51
  maxMessageLength: number;
37
52
  renderPreviewText: (markdown: string) => string;
38
- getDraftSupport: () => "unknown" | "supported" | "unsupported";
39
- setDraftSupport: (support: "unknown" | "supported" | "unsupported") => void;
53
+ getDraftSupport: () => TelegramDraftSupport;
54
+ setDraftSupport: (support: TelegramDraftSupport) => void;
40
55
  allocateDraftId: () => number;
41
- sendDraft: (chatId: number, draftId: number, text: string) => Promise<void>;
56
+ sendDraft: (
57
+ chatId: number,
58
+ draftId: number,
59
+ text: string,
60
+ ) => Promise<unknown>;
42
61
  sendMessage: (
43
62
  chatId: number,
44
63
  text: string,
45
64
  options?: { parseMode?: "HTML" },
46
- ) => Promise<TelegramSentPreviewMessageLike>;
65
+ ) => Promise<TelegramSentPreviewMessage>;
47
66
  editMessageText: (
48
67
  chatId: number,
49
68
  messageId: number,
50
69
  text: string,
51
70
  options?: { parseMode?: "HTML" },
52
- ) => Promise<void>;
71
+ ) => Promise<unknown>;
53
72
  renderTelegramMessage: (
54
73
  text: string,
55
74
  options?: { mode?: TelegramRenderMode },
@@ -65,8 +84,381 @@ export interface TelegramPreviewRuntimeDeps {
65
84
  ) => Promise<number | undefined>;
66
85
  }
67
86
 
87
+ export interface TelegramPreviewActiveTurn {
88
+ chatId: number;
89
+ }
90
+
91
+ export interface TelegramAssistantMessagePreviewStartDeps<TMessage> {
92
+ getActiveTurn: () => TelegramPreviewActiveTurn | undefined;
93
+ isAssistantMessage: (message: TMessage) => boolean;
94
+ getState: () => TelegramPreviewRuntimeState | undefined;
95
+ setState: (state: TelegramPreviewRuntimeState | undefined) => void;
96
+ createPreviewState: () => TelegramPreviewRuntimeState;
97
+ finalizePreview: (chatId: number) => Promise<boolean>;
98
+ finalizeMarkdownPreview: (
99
+ chatId: number,
100
+ markdown: string,
101
+ ) => Promise<boolean>;
102
+ }
103
+
104
+ export interface TelegramAssistantMessagePreviewUpdateDeps<TMessage> {
105
+ getActiveTurn: () => TelegramPreviewActiveTurn | undefined;
106
+ isAssistantMessage: (message: TMessage) => boolean;
107
+ getState: () => TelegramPreviewRuntimeState | undefined;
108
+ setState: (state: TelegramPreviewRuntimeState | undefined) => void;
109
+ createPreviewState: () => TelegramPreviewRuntimeState;
110
+ getMessageText: (message: TMessage) => string;
111
+ schedulePreviewFlush: (chatId: number) => void;
112
+ }
113
+
114
+ export type TelegramAssistantMessagePreviewHookDeps<TMessage> =
115
+ TelegramAssistantMessagePreviewStartDeps<TMessage> &
116
+ TelegramAssistantMessagePreviewUpdateDeps<TMessage>;
117
+
118
+ export interface TelegramAssistantMessagePreviewHookEvent<TMessage> {
119
+ message: TMessage;
120
+ }
121
+
122
+ export interface TelegramAssistantMessagePreviewHooks<TMessage> {
123
+ onMessageStart: (
124
+ event: TelegramAssistantMessagePreviewHookEvent<TMessage>,
125
+ ) => Promise<void>;
126
+ onMessageUpdate: (
127
+ event: TelegramAssistantMessagePreviewHookEvent<TMessage>,
128
+ ) => Promise<void>;
129
+ }
130
+
131
+ export interface TelegramPreviewControllerDeps {
132
+ getDefaultReplyToMessageId?: () => number | undefined;
133
+ maxMessageLength?: number;
134
+ renderPreviewText?: (markdown: string) => string;
135
+ initialDraftSupport?: TelegramDraftSupport;
136
+ sendDraft: (
137
+ chatId: number,
138
+ draftId: number,
139
+ text: string,
140
+ ) => Promise<unknown>;
141
+ sendMessage: (
142
+ chatId: number,
143
+ text: string,
144
+ options: { parseMode?: "HTML" } | undefined,
145
+ replyToMessageId: number | undefined,
146
+ ) => Promise<TelegramSentPreviewMessage>;
147
+ editMessageText: (
148
+ chatId: number,
149
+ messageId: number,
150
+ text: string,
151
+ options?: { parseMode?: "HTML" },
152
+ ) => Promise<unknown>;
153
+ renderTelegramMessage?: (
154
+ text: string,
155
+ options?: { mode?: TelegramRenderMode },
156
+ ) => TelegramRenderedChunk[];
157
+ sendRenderedChunks: (
158
+ chatId: number,
159
+ chunks: TelegramRenderedChunk[],
160
+ replyToMessageId: number | undefined,
161
+ ) => Promise<number | undefined>;
162
+ editRenderedMessage: (
163
+ chatId: number,
164
+ messageId: number,
165
+ chunks: TelegramRenderedChunk[],
166
+ ) => Promise<number | undefined>;
167
+ throttleMs?: number;
168
+ maxDraftId?: number;
169
+ setTimer?: (
170
+ callback: () => void,
171
+ ms: number,
172
+ ) => ReturnType<typeof setTimeout>;
173
+ clearTimer?: (timer: ReturnType<typeof setTimeout>) => void;
174
+ }
175
+
176
+ export interface TelegramPreviewController {
177
+ getState: () => TelegramPreviewRuntimeState | undefined;
178
+ setState: (state: TelegramPreviewRuntimeState | undefined) => void;
179
+ setPendingText: (text: string) => void;
180
+ createState: () => TelegramPreviewRuntimeState;
181
+ resetState: () => void;
182
+ clear: (chatId: number) => Promise<void>;
183
+ flush: (chatId: number) => Promise<void>;
184
+ scheduleFlush: (chatId: number) => void;
185
+ finalize: (chatId: number, replyToMessageId?: number) => Promise<boolean>;
186
+ finalizeMarkdown: (
187
+ chatId: number,
188
+ markdown: string,
189
+ replyToMessageId?: number,
190
+ ) => Promise<boolean>;
191
+ }
192
+
193
+ export interface TelegramPreviewMessageTransportDeps {
194
+ sendMessage: (body: TelegramSendMessageBody) => Promise<TelegramSentMessage>;
195
+ editMessageText: (body: TelegramEditMessageTextBody) => Promise<unknown>;
196
+ buildReplyParameters?: (
197
+ replyToMessageId: number | undefined,
198
+ ) => TelegramReplyParameters | undefined;
199
+ }
200
+
201
+ export function createTelegramPreviewMessageTransport(
202
+ deps: TelegramPreviewMessageTransportDeps,
203
+ ): Pick<TelegramPreviewControllerDeps, "sendMessage" | "editMessageText"> {
204
+ const getReplyParameters =
205
+ deps.buildReplyParameters ?? buildTelegramReplyParameters;
206
+ return {
207
+ sendMessage: (chatId, text, options, replyToMessageId) => {
208
+ const replyParameters = getReplyParameters(replyToMessageId);
209
+ return deps.sendMessage({
210
+ chat_id: chatId,
211
+ text,
212
+ parse_mode: options?.parseMode,
213
+ ...(replyParameters ? { reply_parameters: replyParameters } : {}),
214
+ });
215
+ },
216
+ editMessageText: (chatId, messageId, text, options) =>
217
+ deps.editMessageText({
218
+ chat_id: chatId,
219
+ message_id: messageId,
220
+ text,
221
+ parse_mode: options?.parseMode,
222
+ }),
223
+ };
224
+ }
225
+
226
+ export interface TelegramPreviewRenderedChunkTransportDeps {
227
+ sendRenderedChunks: (
228
+ chatId: number,
229
+ chunks: TelegramRenderedChunk[],
230
+ options?: { replyToMessageId?: number },
231
+ ) => Promise<number | undefined>;
232
+ editRenderedMessage: (
233
+ chatId: number,
234
+ messageId: number,
235
+ chunks: TelegramRenderedChunk[],
236
+ ) => Promise<number | undefined>;
237
+ }
238
+
239
+ export function createTelegramPreviewRenderedChunkTransport(
240
+ deps: TelegramPreviewRenderedChunkTransportDeps,
241
+ ): Pick<
242
+ TelegramPreviewControllerDeps,
243
+ "sendRenderedChunks" | "editRenderedMessage"
244
+ > {
245
+ return {
246
+ sendRenderedChunks: (chatId, chunks, replyToMessageId) =>
247
+ deps.sendRenderedChunks(chatId, chunks, { replyToMessageId }),
248
+ editRenderedMessage: deps.editRenderedMessage,
249
+ };
250
+ }
251
+
252
+ export type TelegramPreviewControllerRuntimeDeps = Omit<
253
+ TelegramPreviewControllerDeps,
254
+ | "sendMessage"
255
+ | "editMessageText"
256
+ | "sendRenderedChunks"
257
+ | "editRenderedMessage"
258
+ > &
259
+ TelegramPreviewMessageTransportDeps &
260
+ TelegramPreviewRenderedChunkTransportDeps;
261
+
262
+ export function createTelegramPreviewControllerRuntime(
263
+ deps: TelegramPreviewControllerRuntimeDeps,
264
+ ): TelegramPreviewController {
265
+ return createTelegramPreviewController({
266
+ getDefaultReplyToMessageId: deps.getDefaultReplyToMessageId,
267
+ maxMessageLength: deps.maxMessageLength,
268
+ renderPreviewText: deps.renderPreviewText,
269
+ initialDraftSupport: deps.initialDraftSupport,
270
+ sendDraft: deps.sendDraft,
271
+ ...createTelegramPreviewMessageTransport({
272
+ sendMessage: deps.sendMessage,
273
+ editMessageText: deps.editMessageText,
274
+ buildReplyParameters: deps.buildReplyParameters,
275
+ }),
276
+ renderTelegramMessage: deps.renderTelegramMessage,
277
+ ...createTelegramPreviewRenderedChunkTransport({
278
+ sendRenderedChunks: deps.sendRenderedChunks,
279
+ editRenderedMessage: deps.editRenderedMessage,
280
+ }),
281
+ throttleMs: deps.throttleMs,
282
+ maxDraftId: deps.maxDraftId,
283
+ setTimer: deps.setTimer,
284
+ clearTimer: deps.clearTimer,
285
+ });
286
+ }
287
+
288
+ export interface TelegramAssistantPreviewRuntimeDeps<
289
+ TMessage,
290
+ > extends TelegramPreviewControllerRuntimeDeps {
291
+ getActiveTurn: () => TelegramPreviewActiveTurn | undefined;
292
+ isAssistantMessage: (message: TMessage) => boolean;
293
+ getMessageText: (message: TMessage) => string;
294
+ }
295
+
296
+ export type TelegramAssistantPreviewRuntime<TMessage> =
297
+ TelegramPreviewController & TelegramAssistantMessagePreviewHooks<TMessage>;
298
+
299
+ export function createTelegramAssistantPreviewRuntime<TMessage>(
300
+ deps: TelegramAssistantPreviewRuntimeDeps<TMessage>,
301
+ ): TelegramAssistantPreviewRuntime<TMessage> {
302
+ const controller = createTelegramPreviewControllerRuntime(deps);
303
+ return {
304
+ ...controller,
305
+ ...createTelegramAssistantMessagePreviewHooks({
306
+ getActiveTurn: deps.getActiveTurn,
307
+ isAssistantMessage: deps.isAssistantMessage,
308
+ getState: controller.getState,
309
+ setState: controller.setState,
310
+ createPreviewState: controller.createState,
311
+ finalizePreview: controller.finalize,
312
+ finalizeMarkdownPreview: controller.finalizeMarkdown,
313
+ getMessageText: deps.getMessageText,
314
+ schedulePreviewFlush: controller.scheduleFlush,
315
+ }),
316
+ };
317
+ }
318
+
319
+ export function createTelegramPreviewController(
320
+ deps: TelegramPreviewControllerDeps,
321
+ ): TelegramPreviewController {
322
+ let state: TelegramPreviewRuntimeState | undefined;
323
+ const clearTimer = deps.clearTimer ?? clearTimeout;
324
+ const setTimer =
325
+ deps.setTimer ??
326
+ ((callback: () => void, ms: number): ReturnType<typeof setTimeout> =>
327
+ setTimeout(callback, ms));
328
+ const throttleMs = deps.throttleMs ?? TELEGRAM_PREVIEW_THROTTLE_MS;
329
+ const maxDraftId = deps.maxDraftId ?? TELEGRAM_DRAFT_ID_MAX;
330
+ const maxMessageLength = deps.maxMessageLength ?? MAX_MESSAGE_LENGTH;
331
+ const renderPreview = deps.renderPreviewText ?? renderMarkdownPreviewText;
332
+ const renderMessage = deps.renderTelegramMessage ?? renderTelegramMessage;
333
+ let draftSupport = deps.initialDraftSupport ?? "unknown";
334
+ let nextDraftId = 0;
335
+ const getRuntimeDeps = (
336
+ replyToMessageId?: number,
337
+ ): TelegramPreviewRuntimeDeps => ({
338
+ getState: () => state,
339
+ setState: (nextState) => {
340
+ state = nextState;
341
+ },
342
+ clearScheduledFlush: (nextState) => {
343
+ if (!nextState.flushTimer) return;
344
+ clearTimer(nextState.flushTimer);
345
+ nextState.flushTimer = undefined;
346
+ },
347
+ maxMessageLength,
348
+ renderPreviewText: renderPreview,
349
+ getDraftSupport: () => draftSupport,
350
+ setDraftSupport: (support) => {
351
+ draftSupport = support;
352
+ },
353
+ allocateDraftId: () => {
354
+ nextDraftId = allocateTelegramDraftId(nextDraftId, maxDraftId);
355
+ return nextDraftId;
356
+ },
357
+ sendDraft: deps.sendDraft,
358
+ sendMessage: (chatId, text, options) =>
359
+ deps.sendMessage(
360
+ chatId,
361
+ text,
362
+ options,
363
+ replyToMessageId ?? deps.getDefaultReplyToMessageId?.(),
364
+ ),
365
+ editMessageText: deps.editMessageText,
366
+ renderTelegramMessage: renderMessage,
367
+ sendRenderedChunks: (chatId, chunks) =>
368
+ deps.sendRenderedChunks(
369
+ chatId,
370
+ chunks,
371
+ replyToMessageId ?? deps.getDefaultReplyToMessageId?.(),
372
+ ),
373
+ editRenderedMessage: deps.editRenderedMessage,
374
+ });
375
+ return {
376
+ getState: () => state,
377
+ setState: (nextState) => {
378
+ state = nextState;
379
+ },
380
+ setPendingText: (text) => {
381
+ if (state) state.pendingText = text;
382
+ },
383
+ createState: () => createTelegramPreviewRuntimeState(draftSupport),
384
+ resetState: () => {
385
+ state = createTelegramPreviewRuntimeState(draftSupport);
386
+ },
387
+ clear: (chatId) => clearTelegramPreview(chatId, getRuntimeDeps()),
388
+ flush: (chatId) => flushTelegramPreview(chatId, getRuntimeDeps()),
389
+ scheduleFlush: (chatId) => {
390
+ if (!state || state.flushTimer) return;
391
+ state.flushTimer = setTimer(() => {
392
+ void flushTelegramPreview(chatId, getRuntimeDeps());
393
+ }, throttleMs);
394
+ },
395
+ finalize: (chatId, replyToMessageId) =>
396
+ finalizeTelegramPreview(chatId, getRuntimeDeps(replyToMessageId)),
397
+ finalizeMarkdown: (chatId, markdown, replyToMessageId) =>
398
+ finalizeTelegramMarkdownPreview(
399
+ chatId,
400
+ markdown,
401
+ getRuntimeDeps(replyToMessageId),
402
+ ),
403
+ };
404
+ }
405
+
406
+ export function createTelegramAssistantMessagePreviewHooks<TMessage>(
407
+ deps: TelegramAssistantMessagePreviewHookDeps<TMessage>,
408
+ ): TelegramAssistantMessagePreviewHooks<TMessage> {
409
+ return {
410
+ onMessageStart: async (
411
+ event: TelegramAssistantMessagePreviewHookEvent<TMessage>,
412
+ ): Promise<void> => {
413
+ await handleTelegramAssistantMessagePreviewStart(event.message, deps);
414
+ },
415
+ onMessageUpdate: async (
416
+ event: TelegramAssistantMessagePreviewHookEvent<TMessage>,
417
+ ): Promise<void> => {
418
+ await handleTelegramAssistantMessagePreviewUpdate(event.message, deps);
419
+ },
420
+ };
421
+ }
422
+
423
+ export async function handleTelegramAssistantMessagePreviewStart<TMessage>(
424
+ message: TMessage,
425
+ deps: TelegramAssistantMessagePreviewStartDeps<TMessage>,
426
+ ): Promise<void> {
427
+ const turn = deps.getActiveTurn();
428
+ if (!turn || !deps.isAssistantMessage(message)) return;
429
+ const state = deps.getState();
430
+ if (
431
+ state &&
432
+ (state.pendingText.trim().length > 0 ||
433
+ state.lastSentText.trim().length > 0)
434
+ ) {
435
+ const previousText = state.pendingText.trim();
436
+ if (previousText.length > 0) {
437
+ await deps.finalizeMarkdownPreview(turn.chatId, previousText);
438
+ } else {
439
+ await deps.finalizePreview(turn.chatId);
440
+ }
441
+ }
442
+ deps.setState(deps.createPreviewState());
443
+ }
444
+
445
+ export async function handleTelegramAssistantMessagePreviewUpdate<TMessage>(
446
+ message: TMessage,
447
+ deps: TelegramAssistantMessagePreviewUpdateDeps<TMessage>,
448
+ ): Promise<void> {
449
+ const turn = deps.getActiveTurn();
450
+ if (!turn || !deps.isAssistantMessage(message)) return;
451
+ let state = deps.getState();
452
+ if (!state) {
453
+ state = deps.createPreviewState();
454
+ deps.setState(state);
455
+ }
456
+ state.pendingText = deps.getMessageText(message);
457
+ deps.schedulePreviewFlush(turn.chatId);
458
+ }
459
+
68
460
  export function buildTelegramPreviewFinalText(
69
- state: TelegramPreviewStateLike,
461
+ state: TelegramPreviewState,
70
462
  ): string | undefined {
71
463
  const finalText = state.pendingText.trim();
72
464
  if (finalText) return finalText;
@@ -79,8 +471,25 @@ export function buildTelegramPreviewFinalText(
79
471
  return state.lastSentText.trim() || undefined;
80
472
  }
81
473
 
474
+ export function createTelegramPreviewRuntimeState(
475
+ draftSupport: TelegramDraftSupport,
476
+ ): TelegramPreviewRuntimeState {
477
+ return {
478
+ mode: draftSupport === "unsupported" ? "message" : "draft",
479
+ pendingText: "",
480
+ lastSentText: "",
481
+ };
482
+ }
483
+
484
+ export function allocateTelegramDraftId(
485
+ currentDraftId: number,
486
+ maxDraftId: number,
487
+ ): number {
488
+ return currentDraftId >= maxDraftId ? 1 : currentDraftId + 1;
489
+ }
490
+
82
491
  export function shouldUseTelegramDraftPreview(options: {
83
- draftSupport: "unknown" | "supported" | "unsupported";
492
+ draftSupport: TelegramDraftSupport;
84
493
  snapshot?: TelegramPreviewSnapshot;
85
494
  }): boolean {
86
495
  return (
@@ -93,25 +502,18 @@ export async function clearTelegramPreview(
93
502
  chatId: number,
94
503
  deps: TelegramPreviewRuntimeDeps,
95
504
  ): Promise<void> {
505
+ void chatId;
96
506
  const state = deps.getState();
97
507
  if (!state) return;
98
508
  deps.clearScheduledFlush(state);
99
509
  deps.setState(undefined);
100
- if (state.mode !== "draft" || state.draftId === undefined) return;
101
- try {
102
- await deps.sendDraft(chatId, state.draftId, "");
103
- } catch {
104
- // ignore
105
- }
106
510
  }
107
511
 
108
- export async function flushTelegramPreview(
512
+ async function performTelegramPreviewFlush(
109
513
  chatId: number,
514
+ state: TelegramPreviewRuntimeState,
110
515
  deps: TelegramPreviewRuntimeDeps,
111
516
  ): Promise<void> {
112
- const state = deps.getState();
113
- if (!state) return;
114
- state.flushTimer = undefined;
115
517
  const snapshot = buildTelegramPreviewSnapshot({
116
518
  state,
117
519
  maxMessageLength: deps.maxMessageLength,
@@ -139,13 +541,6 @@ export async function flushTelegramPreview(
139
541
  deps.setDraftSupport("unsupported");
140
542
  }
141
543
  }
142
- if (state.mode === "draft" && state.draftId !== undefined) {
143
- try {
144
- await deps.sendDraft(chatId, state.draftId, "");
145
- } catch {
146
- // ignore
147
- }
148
- }
149
544
  if (state.messageId === undefined) {
150
545
  const sent = await deps.sendMessage(chatId, snapshot.text, {
151
546
  parseMode: snapshot.parseMode,
@@ -166,6 +561,33 @@ export async function flushTelegramPreview(
166
561
  state.lastSentStrategy = snapshot.strategy;
167
562
  }
168
563
 
564
+ export async function flushTelegramPreview(
565
+ chatId: number,
566
+ deps: TelegramPreviewRuntimeDeps,
567
+ ): Promise<void> {
568
+ const state = deps.getState();
569
+ if (!state) return;
570
+ if (state.flushPromise) {
571
+ state.flushRequested = true;
572
+ await state.flushPromise;
573
+ return;
574
+ }
575
+ state.flushTimer = undefined;
576
+ state.flushPromise = (async () => {
577
+ do {
578
+ state.flushRequested = false;
579
+ await performTelegramPreviewFlush(chatId, state, deps);
580
+ } while (deps.getState() === state && state.flushRequested);
581
+ })();
582
+ try {
583
+ await state.flushPromise;
584
+ } finally {
585
+ if (deps.getState() === state) {
586
+ state.flushPromise = undefined;
587
+ }
588
+ }
589
+ }
590
+
169
591
  export async function finalizeTelegramPreview(
170
592
  chatId: number,
171
593
  deps: TelegramPreviewRuntimeDeps,