@llblab/pi-telegram 0.19.3 → 0.20.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.
- package/AGENTS.md +6 -3
- package/BACKLOG.md +7 -6
- package/CHANGELOG.md +14 -2
- package/README.md +8 -5
- package/docs/README.md +2 -2
- package/docs/architecture.md +6 -1
- package/docs/command-templates.md +7 -7
- package/docs/inbound.md +11 -11
- package/docs/multi-instance-bus.md +2 -0
- package/docs/outbound.md +5 -5
- package/docs/public-api.md +1 -1
- package/index.ts +95 -26
- package/lib/bindings.ts +61 -11
- package/lib/bus-follower.ts +37 -13
- package/lib/bus-leader.ts +28 -43
- package/lib/bus-transport.ts +28 -4
- package/lib/bus.ts +66 -43
- package/lib/commands.ts +41 -8
- package/lib/config.ts +165 -26
- package/lib/locks.ts +78 -25
- package/lib/{runtime-log.ts → logs.ts} +58 -27
- package/lib/media.ts +97 -4
- package/lib/outbound-buttons.ts +1 -1
- package/lib/outbound.ts +5 -8
- package/lib/paths.ts +77 -0
- package/lib/prompt-templates.ts +3 -1
- package/lib/prompts.ts +1 -1
- package/lib/queue.ts +32 -1
- package/lib/routing.ts +106 -41
- package/lib/status.ts +6 -1
- package/lib/sync.ts +22 -17
- package/lib/telegram-api.ts +13 -14
- package/lib/threads.ts +142 -55
- package/lib/turns.ts +47 -13
- package/package.json +3 -3
- /package/{banner.png → screenshot.png} +0 -0
package/lib/routing.ts
CHANGED
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
7
|
import { readFile } from "node:fs/promises";
|
|
8
|
+
import { basename, dirname } from "node:path";
|
|
8
9
|
import * as Commands from "./commands.ts";
|
|
9
10
|
import type { TelegramConfigStore } from "./config.ts";
|
|
10
11
|
import type { TelegramSectionRegistry } from "./sections.ts";
|
|
@@ -20,6 +21,31 @@ import * as TextGroups from "./text-groups.ts";
|
|
|
20
21
|
import * as ThreadReconciler from "./thread-reconciler.ts";
|
|
21
22
|
import * as Turns from "./turns.ts";
|
|
22
23
|
|
|
24
|
+
function formatTelegramPromptPeer(user: { id?: unknown; username?: unknown } | undefined): string | undefined {
|
|
25
|
+
if (!user) return undefined;
|
|
26
|
+
if (typeof user.username === "string" && user.username.length > 0) return user.username;
|
|
27
|
+
return typeof user.id === "number" ? String(user.id) : undefined;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function appendTelegramSourceAttachmentSection(
|
|
31
|
+
text: string,
|
|
32
|
+
from: string | undefined,
|
|
33
|
+
files: Pick<Media.DownloadedTelegramFile, "path">[],
|
|
34
|
+
): string {
|
|
35
|
+
if (files.length === 0) return text;
|
|
36
|
+
const dirs = [...new Set(files.map((file) => dirname(file.path)))];
|
|
37
|
+
const sameDir = dirs.length === 1;
|
|
38
|
+
const source = from ? `|from:${from}` : "";
|
|
39
|
+
const header = sameDir
|
|
40
|
+
? `[attachments${source}] ${dirs[0]}`
|
|
41
|
+
: `[attachments${source}]`;
|
|
42
|
+
const items = sameDir
|
|
43
|
+
? files.map((file) => `/${basename(file.path)}`)
|
|
44
|
+
: files.map((file) => file.path);
|
|
45
|
+
const prefix = text.length > 0 ? `${text}\n\n` : "";
|
|
46
|
+
return `${prefix}${header}\n${items.map((item) => `- ${item}`).join("\n")}`;
|
|
47
|
+
}
|
|
48
|
+
|
|
23
49
|
function getContextCwd(ctx: unknown): string | undefined {
|
|
24
50
|
if (!ctx || typeof ctx !== "object") return undefined;
|
|
25
51
|
const cwd = (ctx as { cwd?: unknown }).cwd;
|
|
@@ -1248,22 +1274,25 @@ export function createTelegramInboundRouteRuntime<
|
|
|
1248
1274
|
if (typeof chatId !== "number" || typeof messageId !== "number")
|
|
1249
1275
|
return;
|
|
1250
1276
|
const queueOrder = deps.bridgeRuntime.queue.allocateItemOrder();
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
|
|
1257
|
-
|
|
1258
|
-
|
|
1259
|
-
|
|
1260
|
-
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
|
|
1264
|
-
|
|
1265
|
-
|
|
1277
|
+
const turn = OutboundHandlers.createTelegramButtonPromptTurn({
|
|
1278
|
+
chatId,
|
|
1279
|
+
target:
|
|
1280
|
+
typeof buttonQuery.message?.message_thread_id === "number"
|
|
1281
|
+
? {
|
|
1282
|
+
chatId,
|
|
1283
|
+
threadId: buttonQuery.message.message_thread_id,
|
|
1284
|
+
}
|
|
1285
|
+
: { chatId },
|
|
1286
|
+
replyToMessageId: messageId,
|
|
1287
|
+
queueOrder,
|
|
1288
|
+
action,
|
|
1289
|
+
});
|
|
1290
|
+
const result = Queue.appendTelegramPromptTurnOnce(
|
|
1291
|
+
deps.telegramQueueStore.getQueuedItems(),
|
|
1292
|
+
turn,
|
|
1266
1293
|
);
|
|
1294
|
+
if (!result.appended) return;
|
|
1295
|
+
deps.telegramQueueStore.setQueuedItems(result.items);
|
|
1267
1296
|
deps.updateStatus(context);
|
|
1268
1297
|
requestDispatchNextQueuedTelegramTurn(context);
|
|
1269
1298
|
},
|
|
@@ -1323,15 +1352,39 @@ export function createTelegramInboundRouteRuntime<
|
|
|
1323
1352
|
);
|
|
1324
1353
|
if (handledBySettings) return;
|
|
1325
1354
|
const callbackData = query.data;
|
|
1326
|
-
if (
|
|
1327
|
-
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
|
|
1331
|
-
|
|
1332
|
-
|
|
1333
|
-
|
|
1334
|
-
|
|
1355
|
+
if (callbackData && !isTelegramOwnedCallbackData(callbackData)) {
|
|
1356
|
+
const chatId = query.message?.chat?.id;
|
|
1357
|
+
const messageId = query.message?.message_id;
|
|
1358
|
+
if (typeof chatId === "number" && typeof messageId === "number") {
|
|
1359
|
+
const queueOrder = deps.bridgeRuntime.queue.allocateItemOrder();
|
|
1360
|
+
const target =
|
|
1361
|
+
typeof query.message?.message_thread_id === "number"
|
|
1362
|
+
? { chatId, threadId: query.message.message_thread_id }
|
|
1363
|
+
: { chatId };
|
|
1364
|
+
const turn: Queue.PendingTelegramTurn = {
|
|
1365
|
+
kind: "prompt",
|
|
1366
|
+
chatId,
|
|
1367
|
+
target,
|
|
1368
|
+
replyToMessageId: messageId,
|
|
1369
|
+
sourceMessageIds: [messageId],
|
|
1370
|
+
queueOrder,
|
|
1371
|
+
queueLane: "priority",
|
|
1372
|
+
laneOrder: queueOrder,
|
|
1373
|
+
queuedAttachments: [],
|
|
1374
|
+
content: [{ type: "text", text: `[callback] ${callbackData}` }],
|
|
1375
|
+
historyText: callbackData,
|
|
1376
|
+
statusSummary: callbackData,
|
|
1377
|
+
};
|
|
1378
|
+
const result = Queue.appendTelegramPromptTurnOnce(
|
|
1379
|
+
deps.telegramQueueStore.getQueuedItems(),
|
|
1380
|
+
turn,
|
|
1381
|
+
);
|
|
1382
|
+
if (result.appended) {
|
|
1383
|
+
deps.telegramQueueStore.setQueuedItems(result.items);
|
|
1384
|
+
deps.updateStatus(ctx);
|
|
1385
|
+
requestDispatchNextQueuedTelegramTurn(ctx);
|
|
1386
|
+
}
|
|
1387
|
+
}
|
|
1335
1388
|
await deps.answerCallbackQuery(query.id);
|
|
1336
1389
|
return;
|
|
1337
1390
|
}
|
|
@@ -1345,6 +1398,7 @@ export function createTelegramInboundRouteRuntime<
|
|
|
1345
1398
|
downloadFile: deps.downloadFile,
|
|
1346
1399
|
processAttachments: deps.inboundHandlerRuntime.process,
|
|
1347
1400
|
resolveTimeLine: deps.resolveTimeLine,
|
|
1401
|
+
getAllowedUserId: deps.configStore.getAllowedUserId,
|
|
1348
1402
|
|
|
1349
1403
|
// Voice policy for the current turn. Missing config still behaves as manual,
|
|
1350
1404
|
// but only explicit telegram.json voice.replyMode is shown in prompt context.
|
|
@@ -1757,30 +1811,37 @@ export function createTelegramInboundRouteRuntime<
|
|
|
1757
1811
|
const text = guestMessage.text ?? "";
|
|
1758
1812
|
const gm = guestMessage as unknown as Record<string, unknown>;
|
|
1759
1813
|
// Build telegram prefix with guest context
|
|
1760
|
-
const fromRaw = gm.from as Record<string, unknown> | undefined;
|
|
1761
|
-
const fromName =
|
|
1762
|
-
(fromRaw?.username as string) || (fromRaw?.first_name as string) || "";
|
|
1763
1814
|
const chatRaw = gm.chat as Record<string, unknown>;
|
|
1764
1815
|
const chatTitle = chatRaw?.title as string | undefined;
|
|
1765
1816
|
const chatType = chatRaw?.type as string;
|
|
1817
|
+
const fromRaw = gm.from as Record<string, unknown> | undefined;
|
|
1818
|
+
const replyMsg = gm.reply_to_message as Record<string, unknown> | undefined;
|
|
1819
|
+
const replyFromRaw = replyMsg?.from as Record<string, unknown> | undefined;
|
|
1820
|
+
const fromPeer = formatTelegramPromptPeer(fromRaw);
|
|
1821
|
+
const replyPeer = formatTelegramPromptPeer(replyFromRaw);
|
|
1822
|
+
const fromIsOwner = fromRaw?.id === deps.configStore.getAllowedUserId();
|
|
1823
|
+
const guestPeer = chatType === "private" && fromIsOwner && replyPeer
|
|
1824
|
+
? replyPeer
|
|
1825
|
+
: fromPeer;
|
|
1766
1826
|
const prefixParts = ["telegram"];
|
|
1767
|
-
if (fromName) prefixParts.push(`from:${fromName}`);
|
|
1768
1827
|
if (chatType !== "private" && chatTitle) {
|
|
1769
1828
|
prefixParts.push(`guest:${chatTitle}`);
|
|
1829
|
+
} else if (chatType === "private" && guestPeer) {
|
|
1830
|
+
prefixParts.push(`guest:${guestPeer}`);
|
|
1770
1831
|
}
|
|
1771
1832
|
const telegramPrefix = `[${prefixParts.join("|")}]`;
|
|
1772
1833
|
// Extract reply context
|
|
1773
|
-
const replyMsg = gm.reply_to_message as Record<string, unknown> | undefined;
|
|
1774
1834
|
const replyText = replyMsg
|
|
1775
1835
|
? ((replyMsg.text as string) || (replyMsg.caption as string) || "").trim()
|
|
1776
1836
|
: "";
|
|
1777
|
-
const replyFrom = replyMsg
|
|
1778
|
-
? ((replyMsg.from as Record<string, unknown> | undefined)?.username as
|
|
1779
|
-
| string
|
|
1780
|
-
| undefined)
|
|
1781
|
-
: undefined;
|
|
1782
1837
|
// Download files, run inbound handlers
|
|
1783
1838
|
const guestMsg = guestMessage as unknown as Media.TelegramMediaMessage;
|
|
1839
|
+
const replyFiles = guestMsg.reply_to_message
|
|
1840
|
+
? await Media.downloadTelegramMessageFiles(
|
|
1841
|
+
[guestMsg.reply_to_message as Media.TelegramMediaMessage],
|
|
1842
|
+
{ downloadFile: deps.downloadFile },
|
|
1843
|
+
)
|
|
1844
|
+
: [];
|
|
1784
1845
|
const files = await Media.downloadTelegramMessageFiles([guestMsg], {
|
|
1785
1846
|
downloadFile: deps.downloadFile,
|
|
1786
1847
|
});
|
|
@@ -1789,13 +1850,16 @@ export function createTelegramInboundRouteRuntime<
|
|
|
1789
1850
|
text,
|
|
1790
1851
|
ctx,
|
|
1791
1852
|
);
|
|
1792
|
-
|
|
1793
|
-
|
|
1794
|
-
if (
|
|
1795
|
-
const
|
|
1796
|
-
|
|
1797
|
-
|
|
1798
|
-
|
|
1853
|
+
const rawText = processed.rawText || text;
|
|
1854
|
+
let sourceContext = "";
|
|
1855
|
+
if (replyMsg) {
|
|
1856
|
+
const replyHeader = replyPeer ? `[reply|from:${replyPeer}]` : "[reply]";
|
|
1857
|
+
const replyBlock = replyText ? `${replyHeader} ${replyText}` : replyHeader;
|
|
1858
|
+
sourceContext = appendTelegramSourceAttachmentSection(
|
|
1859
|
+
replyBlock,
|
|
1860
|
+
replyPeer,
|
|
1861
|
+
replyFiles,
|
|
1862
|
+
);
|
|
1799
1863
|
}
|
|
1800
1864
|
const promptText = Turns.buildTelegramTurnPrompt({
|
|
1801
1865
|
telegramPrefix,
|
|
@@ -1803,6 +1867,7 @@ export function createTelegramInboundRouteRuntime<
|
|
|
1803
1867
|
files,
|
|
1804
1868
|
promptFiles: processed.promptFiles,
|
|
1805
1869
|
handlerOutputs: processed.handlerOutputs,
|
|
1870
|
+
sourceContext,
|
|
1806
1871
|
});
|
|
1807
1872
|
const order = deps.bridgeRuntime.queue.allocateItemOrder();
|
|
1808
1873
|
const content: Queue.TelegramPromptContent[] = [
|
package/lib/status.ts
CHANGED
|
@@ -180,6 +180,7 @@ export type TelegramBridgeBusLifecyclePhase = "electing";
|
|
|
180
180
|
export interface TelegramBridgeStatusLineState {
|
|
181
181
|
hasBotToken?: boolean;
|
|
182
182
|
botUsername?: string;
|
|
183
|
+
activeProfileName?: string;
|
|
183
184
|
allowedUserId?: number;
|
|
184
185
|
botThreadMode?: "unknown" | "enabled" | "disabled";
|
|
185
186
|
botThreadModeUpdatedAtMs?: number;
|
|
@@ -257,6 +258,7 @@ export interface TelegramBridgeStatusRuntimeDeps<
|
|
|
257
258
|
> {
|
|
258
259
|
statusKey?: string;
|
|
259
260
|
getConfig: () => TelegramBridgeStatusConfig;
|
|
261
|
+
getActiveProfileName?: () => string | undefined;
|
|
260
262
|
isPollingActive: () => boolean;
|
|
261
263
|
getActiveSourceMessageIds: () => number[] | undefined;
|
|
262
264
|
hasActiveTurn: () => boolean;
|
|
@@ -621,6 +623,7 @@ export function createTelegramBridgeStatusRuntime<
|
|
|
621
623
|
return {
|
|
622
624
|
hasBotToken: Boolean(config.botToken),
|
|
623
625
|
botUsername: config.botUsername,
|
|
626
|
+
activeProfileName: deps.getActiveProfileName?.(),
|
|
624
627
|
allowedUserId: config.allowedUserId,
|
|
625
628
|
botThreadMode: botThreadMode?.threadMode,
|
|
626
629
|
botThreadModeUpdatedAtMs: botThreadMode?.updatedAtMs,
|
|
@@ -770,7 +773,7 @@ export function buildTelegramStatusBarText(
|
|
|
770
773
|
if (state.busLifecyclePhase === "electing")
|
|
771
774
|
return `${label} ${theme.fg("warning", "electing")}${queued}`;
|
|
772
775
|
if (!state.pollingActive && state.busRole !== "follower")
|
|
773
|
-
return `${
|
|
776
|
+
return `${theme.fg("accent", "telegram")} ${theme.fg("muted", "disconnected")}${queued}`;
|
|
774
777
|
if (state.compactionInProgress) {
|
|
775
778
|
return `${label} ${theme.fg("warning", "compacting")}${queued}`;
|
|
776
779
|
}
|
|
@@ -1065,6 +1068,7 @@ function buildTelegramBridgeCompactStatusLines(
|
|
|
1065
1068
|
return [
|
|
1066
1069
|
"connection:",
|
|
1067
1070
|
`- bot: ${formatTelegramBridgeBotStatus(state)}`,
|
|
1071
|
+
...(state.activeProfileName ? [`- profile: ${state.activeProfileName}`] : []),
|
|
1068
1072
|
`- user: ${state.allowedUserId ?? "not paired"}`,
|
|
1069
1073
|
...(state.botThreadMode ? [`- thread mode: ${state.botThreadMode}`] : []),
|
|
1070
1074
|
...(state.busRole ? [`- role: ${state.busRole}`] : []),
|
|
@@ -1119,6 +1123,7 @@ export function buildTelegramBridgeDiagnosticStatusLines(
|
|
|
1119
1123
|
return [
|
|
1120
1124
|
"connection:",
|
|
1121
1125
|
`- bot: ${formatTelegramBridgeBotStatus(state)}`,
|
|
1126
|
+
...(state.activeProfileName ? [`- profile: ${state.activeProfileName}`] : []),
|
|
1122
1127
|
`- allowed user: ${state.allowedUserId ?? "not paired"}`,
|
|
1123
1128
|
...(state.botThreadMode
|
|
1124
1129
|
? [
|
package/lib/sync.ts
CHANGED
|
@@ -24,6 +24,7 @@ export interface TelegramLeaderThreadSyncDeps {
|
|
|
24
24
|
getAllowedUserId: () => number | undefined;
|
|
25
25
|
instanceId: string;
|
|
26
26
|
cwd?: string;
|
|
27
|
+
telegramProfile?: string;
|
|
27
28
|
forceFreshUnnamed?: boolean;
|
|
28
29
|
getNowMs?: () => number;
|
|
29
30
|
getRandom?: () => number;
|
|
@@ -110,7 +111,7 @@ export interface TelegramLeaderHealthRuntime {
|
|
|
110
111
|
export interface TelegramManualThreadDisconnectDeps<TSyncState> {
|
|
111
112
|
instanceId: string;
|
|
112
113
|
getCurrentThreadRecord: () =>
|
|
113
|
-
| { target: TelegramTarget; instanceId?: string }
|
|
114
|
+
| { target: TelegramTarget; instanceId?: string; owner?: { kind?: string } }
|
|
114
115
|
| undefined;
|
|
115
116
|
topicTargetStore: Pick<
|
|
116
117
|
TelegramTopicTargetStore,
|
|
@@ -160,23 +161,26 @@ export function createTelegramManualThreadDisconnectHandler<
|
|
|
160
161
|
return async () => {
|
|
161
162
|
const currentRecord = deps.getCurrentThreadRecord();
|
|
162
163
|
if (currentRecord?.target.threadId) {
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
164
|
+
const isManualFollower = currentRecord.owner?.kind === "manual-follower";
|
|
165
|
+
if (!isManualFollower) {
|
|
166
|
+
await ThreadReconciler.applyThreadReconciliationPlan(
|
|
167
|
+
ThreadReconciler.planDisconnectedInstanceThreadCleanup({
|
|
168
|
+
target: currentRecord.target as TelegramTarget & { threadId: number },
|
|
169
|
+
instanceId: deps.instanceId,
|
|
170
|
+
}),
|
|
171
|
+
{
|
|
172
|
+
callApi(method, body) {
|
|
173
|
+
return deps.callApi(method, body);
|
|
174
|
+
},
|
|
175
|
+
persist() {
|
|
176
|
+
return deps.topicTargetStore.persist();
|
|
177
|
+
},
|
|
178
|
+
recordRuntimeEvent: deps.recordRuntimeEvent,
|
|
174
179
|
},
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
await deps.topicTargetStore.persist();
|
|
180
|
+
);
|
|
181
|
+
if (deps.topicTargetStore.markOfflineByInstanceId(deps.instanceId) > 0) {
|
|
182
|
+
await deps.topicTargetStore.persist();
|
|
183
|
+
}
|
|
180
184
|
}
|
|
181
185
|
const leaderTarget = deps.getLeaderTarget();
|
|
182
186
|
if (
|
|
@@ -360,6 +364,7 @@ export async function ensureTelegramLeaderThreadBinding(
|
|
|
360
364
|
getAllowedUserId: deps.getAllowedUserId,
|
|
361
365
|
instanceId: deps.instanceId,
|
|
362
366
|
cwd: deps.cwd,
|
|
367
|
+
telegramProfile: deps.telegramProfile,
|
|
363
368
|
getCurrentLeaderEpoch: deps.getCurrentLeaderEpoch,
|
|
364
369
|
getThreadReconciliationMachineState:
|
|
365
370
|
deps.getThreadReconciliationMachineState,
|
package/lib/telegram-api.ts
CHANGED
|
@@ -10,8 +10,8 @@ import { randomUUID } from "node:crypto";
|
|
|
10
10
|
import { createWriteStream, openAsBlob } from "node:fs";
|
|
11
11
|
import { mkdir, readdir, stat, unlink, writeFile } from "node:fs/promises";
|
|
12
12
|
import { request as requestHttps } from "node:https";
|
|
13
|
-
import {
|
|
14
|
-
import {
|
|
13
|
+
import { join } from "node:path";
|
|
14
|
+
import { resolveTelegramTempDir } from "./paths.ts";
|
|
15
15
|
import { Readable, Transform } from "node:stream";
|
|
16
16
|
import { pipeline } from "node:stream/promises";
|
|
17
17
|
|
|
@@ -34,10 +34,7 @@ export function getTelegramInboundFileByteLimitFromEnv(
|
|
|
34
34
|
}
|
|
35
35
|
|
|
36
36
|
function getTelegramApiTempDir(): string {
|
|
37
|
-
|
|
38
|
-
? resolve(process.env.PI_CODING_AGENT_DIR)
|
|
39
|
-
: join(homedir(), ".pi", "agent");
|
|
40
|
-
return join(agentDir, "tmp", "telegram");
|
|
37
|
+
return resolveTelegramTempDir();
|
|
41
38
|
}
|
|
42
39
|
const TELEGRAM_TEMP_FILE_MAX_AGE_MS = 24 * 60 * 60 * 1000;
|
|
43
40
|
const TELEGRAM_INBOUND_FILE_MAX_BYTES = getTelegramInboundFileByteLimitFromEnv(
|
|
@@ -47,10 +44,7 @@ const TELEGRAM_INBOUND_FILE_MAX_BYTES = getTelegramInboundFileByteLimitFromEnv(
|
|
|
47
44
|
);
|
|
48
45
|
|
|
49
46
|
export type TelegramNetworkFamilyPolicy =
|
|
50
|
-
| "
|
|
51
|
-
| "ipv4"
|
|
52
|
-
| "ipv6"
|
|
53
|
-
| "ipv4-fallback";
|
|
47
|
+
"auto" | "ipv4" | "ipv6" | "ipv4-fallback";
|
|
54
48
|
|
|
55
49
|
const TELEGRAM_NETWORK_FAMILY_ENV = "PI_TELEGRAM_NETWORK_FAMILY";
|
|
56
50
|
const TELEGRAM_NETWORK_FAMILY_VALUES = new Set<TelegramNetworkFamilyPolicy>([
|
|
@@ -1123,10 +1117,15 @@ export function createTelegramAssistantDraftSender(deps: {
|
|
|
1123
1117
|
if (text === undefined || deps.getAssistantRenderingMode() === "rich") {
|
|
1124
1118
|
return sendNativeDraft(chatId, draftId, text, options);
|
|
1125
1119
|
}
|
|
1126
|
-
return deps.sendMessageDraft(
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1120
|
+
return deps.sendMessageDraft(
|
|
1121
|
+
chatId,
|
|
1122
|
+
draftId,
|
|
1123
|
+
deps.renderMarkdownToHtmlDraft(text),
|
|
1124
|
+
{
|
|
1125
|
+
...options,
|
|
1126
|
+
parse_mode: "HTML",
|
|
1127
|
+
},
|
|
1128
|
+
);
|
|
1130
1129
|
};
|
|
1131
1130
|
}
|
|
1132
1131
|
|