@llblab/pi-telegram 0.52.2 → 0.53.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/AGENTS.md +9 -7
- package/BACKLOG.md +1 -18
- package/CHANGELOG.md +11 -0
- package/README.md +7 -11
- package/api/commands.ts +3 -0
- package/dist/api/commands.d.ts +1 -1
- package/dist/lib/activity-verbosity.d.ts +1 -5
- package/dist/lib/activity-verbosity.js +15 -42
- package/dist/lib/activity.d.ts +9 -0
- package/dist/lib/activity.js +39 -10
- package/dist/lib/agent-messages.js +7 -3
- package/dist/lib/bindings.d.ts +43 -5
- package/dist/lib/bindings.js +163 -20
- package/dist/lib/bus-api.d.ts +12 -0
- package/dist/lib/bus-api.js +182 -79
- package/dist/lib/bus-follower.d.ts +111 -31
- package/dist/lib/bus-follower.js +1324 -359
- package/dist/lib/bus-leader.d.ts +41 -91
- package/dist/lib/bus-leader.js +969 -637
- package/dist/lib/bus-transport.js +16 -9
- package/dist/lib/bus.d.ts +215 -18
- package/dist/lib/bus.js +1048 -327
- package/dist/lib/channel-posts.d.ts +5 -0
- package/dist/lib/channel-posts.js +434 -261
- package/dist/lib/command-templates.d.ts +26 -5
- package/dist/lib/command-templates.js +92 -176
- package/dist/lib/commands.d.ts +168 -82
- package/dist/lib/commands.js +1409 -291
- package/dist/lib/config.d.ts +1 -8
- package/dist/lib/config.js +34 -76
- package/dist/lib/delivery.d.ts +2 -2
- package/dist/lib/delivery.js +16 -16
- package/dist/lib/extension.js +639 -171
- package/dist/lib/generative-app-worker.mjs +19 -7
- package/dist/lib/generative-apps.d.ts +0 -5
- package/dist/lib/generative-apps.js +61 -49
- package/dist/lib/inbound.d.ts +5 -0
- package/dist/lib/inbound.js +35 -59
- package/dist/lib/journal.d.ts +33 -3
- package/dist/lib/journal.js +2063 -782
- package/dist/lib/lifecycle.d.ts +2 -6
- package/dist/lib/lifecycle.js +75 -58
- package/dist/lib/locks.d.ts +29 -3
- package/dist/lib/locks.js +289 -108
- package/dist/lib/logging.js +50 -14
- package/dist/lib/media.d.ts +22 -1
- package/dist/lib/media.js +46 -28
- package/dist/lib/menu-model.d.ts +19 -5
- package/dist/lib/menu-model.js +53 -11
- package/dist/lib/menu-queue.d.ts +5 -4
- package/dist/lib/menu-queue.js +45 -63
- package/dist/lib/menu-settings.d.ts +5 -4
- package/dist/lib/menu-settings.js +114 -78
- package/dist/lib/menu-status.d.ts +1 -1
- package/dist/lib/menu-status.js +8 -25
- package/dist/lib/menu-thinking.d.ts +6 -1
- package/dist/lib/menu-thinking.js +14 -21
- package/dist/lib/menu.d.ts +8 -61
- package/dist/lib/menu.js +92 -164
- package/dist/lib/model.d.ts +1 -1
- package/dist/lib/model.js +2 -16
- package/dist/lib/outbound-attachments.d.ts +6 -27
- package/dist/lib/outbound-attachments.js +45 -38
- package/dist/lib/outbound-buttons.js +22 -16
- package/dist/lib/outbound-markup.d.ts +0 -2
- package/dist/lib/outbound-markup.js +51 -64
- package/dist/lib/outbound-voice.js +6 -3
- package/dist/lib/outbound.d.ts +6 -6
- package/dist/lib/outbound.js +61 -51
- package/dist/lib/ownership.js +6 -2
- package/dist/lib/paths.d.ts +5 -0
- package/dist/lib/paths.js +37 -21
- package/dist/lib/pi.d.ts +2 -0
- package/dist/lib/pi.js +8 -1
- package/dist/lib/polling.d.ts +21 -37
- package/dist/lib/polling.js +59 -50
- package/dist/lib/preview.js +39 -19
- package/dist/lib/process-identity.d.ts +24 -0
- package/dist/lib/process-identity.js +133 -0
- package/dist/lib/prompts.js +2 -7
- package/dist/lib/queue.d.ts +14 -16
- package/dist/lib/queue.js +249 -126
- package/dist/lib/recovery.d.ts +2 -83
- package/dist/lib/recovery.js +20 -274
- package/dist/lib/replies.d.ts +16 -24
- package/dist/lib/replies.js +99 -116
- package/dist/lib/routing.d.ts +120 -7
- package/dist/lib/routing.js +4667 -1152
- package/dist/lib/runtime.d.ts +1 -11
- package/dist/lib/sections.d.ts +4 -29
- package/dist/lib/sections.js +7 -20
- package/dist/lib/skills.js +4 -3
- package/dist/lib/status.js +86 -57
- package/dist/lib/sync.d.ts +1 -3
- package/dist/lib/sync.js +67 -43
- package/dist/lib/target.d.ts +4 -0
- package/dist/lib/target.js +18 -0
- package/dist/lib/telegram-api.d.ts +18 -13
- package/dist/lib/telegram-api.js +148 -53
- package/dist/lib/text-groups.js +4 -39
- package/dist/lib/thread-cleanup-manager.d.ts +6 -27
- package/dist/lib/thread-cleanup-manager.js +369 -186
- package/dist/lib/thread-display.d.ts +1 -2
- package/dist/lib/thread-display.js +58 -38
- package/dist/lib/thread-naming.d.ts +28 -8
- package/dist/lib/thread-naming.js +175 -66
- package/dist/lib/thread-reconciler.d.ts +42 -16
- package/dist/lib/thread-reconciler.js +90 -50
- package/dist/lib/threads.d.ts +82 -20
- package/dist/lib/threads.js +2247 -855
- package/dist/lib/time-injection.js +1 -2
- package/dist/lib/turns.js +1 -19
- package/dist/lib/updates.d.ts +169 -80
- package/dist/lib/updates.js +2418 -641
- package/dist/lib/voice.d.ts +7 -22
- package/dist/lib/voice.js +7 -22
- package/dist/lib/wire.js +1 -1
- package/dist/lib/workspace-admission.d.ts +3 -1
- package/dist/lib/workspace-admission.js +425 -211
- package/dist/lib/workspace-identity.js +8 -13
- package/dist/lib/workspace-retirement.d.ts +1 -1
- package/dist/lib/workspace-retirement.js +328 -140
- package/dist/lib/workspace-slots.js +8 -4
- package/dist/package.json +1 -1
- package/docs/architecture.md +31 -29
- package/docs/inbound.md +1 -1
- package/docs/multi-instance-bus.md +15 -3
- package/docs/outbound.md +1 -1
- package/docs/public-api.md +29 -1
- package/docs/ui-style.md +25 -8
- package/lib/activity-verbosity.ts +59 -82
- package/lib/activity.ts +146 -102
- package/lib/agent-messages.ts +12 -5
- package/lib/bindings.ts +389 -82
- package/lib/bus-api.ts +263 -102
- package/lib/bus-follower.ts +2440 -601
- package/lib/bus-leader.ts +2209 -1290
- package/lib/bus-transport.ts +46 -12
- package/lib/bus.ts +1673 -444
- package/lib/channel-posts.ts +848 -327
- package/lib/command-templates.ts +152 -265
- package/lib/commands.ts +2398 -555
- package/lib/config.ts +177 -170
- package/lib/delivery.ts +41 -29
- package/lib/extension.ts +1206 -433
- package/lib/generative-app-worker.mjs +19 -7
- package/lib/generative-apps.ts +324 -211
- package/lib/inbound.ts +95 -97
- package/lib/journal.ts +5311 -1763
- package/lib/keyboard.ts +1 -3
- package/lib/lifecycle.ts +128 -78
- package/lib/locks.ts +677 -203
- package/lib/logging.ts +147 -58
- package/lib/media.ts +82 -43
- package/lib/menu-model.ts +85 -18
- package/lib/menu-queue.ts +88 -129
- package/lib/menu-settings.ts +260 -155
- package/lib/menu-status.ts +20 -60
- package/lib/menu-thinking.ts +41 -56
- package/lib/menu.ts +112 -285
- package/lib/model.ts +8 -22
- package/lib/outbound-attachments.ts +156 -125
- package/lib/outbound-buttons.ts +76 -49
- package/lib/outbound-markup.ts +96 -94
- package/lib/outbound-voice.ts +33 -27
- package/lib/outbound.ts +125 -125
- package/lib/ownership.ts +19 -10
- package/lib/paths.ts +148 -49
- package/lib/pi.ts +35 -15
- package/lib/polling.ts +144 -147
- package/lib/preview.ts +93 -40
- package/lib/process-identity.ts +164 -0
- package/lib/prompts.ts +4 -11
- package/lib/queue.ts +511 -300
- package/lib/recovery.ts +50 -454
- package/lib/rendering.ts +1 -3
- package/lib/replies.ts +248 -209
- package/lib/routing.ts +8509 -2186
- package/lib/runtime.ts +1 -12
- package/lib/sections.ts +24 -89
- package/lib/setup.ts +1 -3
- package/lib/skills.ts +9 -4
- package/lib/status.ts +215 -110
- package/lib/sync.ts +448 -361
- package/lib/target.ts +22 -3
- package/lib/telegram-api.ts +302 -127
- package/lib/text-groups.ts +5 -39
- package/lib/thread-cleanup-manager.ts +833 -331
- package/lib/thread-display.ts +213 -97
- package/lib/thread-naming.ts +232 -87
- package/lib/thread-reconciler.ts +155 -72
- package/lib/threads.ts +5318 -1845
- package/lib/time-injection.ts +1 -4
- package/lib/turns.ts +15 -28
- package/lib/updates.ts +5184 -1612
- package/lib/voice.ts +7 -35
- package/lib/wire.ts +1 -1
- package/lib/workspace-admission.ts +996 -416
- package/lib/workspace-identity.ts +14 -17
- package/lib/workspace-retirement.ts +878 -376
- package/lib/workspace-slots.ts +22 -13
- package/package.json +1 -1
- package/scripts/check-downgrade.mjs +0 -472
- package/scripts/measure-workspace.mjs +0 -108
|
@@ -37,8 +37,8 @@ export interface TelegramOutboundMessagePlan {
|
|
|
37
37
|
markdown: string;
|
|
38
38
|
replyMarkup?: unknown;
|
|
39
39
|
}
|
|
40
|
-
export interface
|
|
41
|
-
getDefaultChatId
|
|
40
|
+
export interface TelegramOutboundMessageDeliveryPorts {
|
|
41
|
+
getDefaultChatId?: () => number | undefined;
|
|
42
42
|
getDefaultTarget?: () => TelegramTarget | undefined;
|
|
43
43
|
getActiveTurn?: () => {
|
|
44
44
|
chatId: number;
|
|
@@ -63,6 +63,9 @@ export interface TelegramOutboundMessageToolRegistrationDeps extends TelegramOut
|
|
|
63
63
|
replyMarkup?: unknown;
|
|
64
64
|
}) => Promise<number | undefined>;
|
|
65
65
|
}
|
|
66
|
+
export interface TelegramOutboundMessageToolRegistrationDeps extends TelegramOutboundMessageDeliveryPorts, TelegramOutboundAttachmentRuntimeEventRecorderPort {
|
|
67
|
+
getDefaultChatId: () => number | undefined;
|
|
68
|
+
}
|
|
66
69
|
export interface TelegramQueuedOutboundAttachmentView {
|
|
67
70
|
path: string;
|
|
68
71
|
fileName: string;
|
|
@@ -169,7 +172,7 @@ export declare function deliverTelegramGuestCachedAttachment(options: {
|
|
|
169
172
|
deleteMessage: (chatId: number, messageId: number) => Promise<void>;
|
|
170
173
|
recordRuntimeEvent?: TelegramOutboundAttachmentRuntimeEventRecorderPort["recordRuntimeEvent"];
|
|
171
174
|
}): Promise<void>;
|
|
172
|
-
export declare function sendTelegramOutboundMessage(options: {
|
|
175
|
+
export declare function sendTelegramOutboundMessage(options: TelegramOutboundMessageDeliveryPorts & {
|
|
173
176
|
text: string;
|
|
174
177
|
media?: string;
|
|
175
178
|
operationId?: string;
|
|
@@ -178,30 +181,6 @@ export declare function sendTelegramOutboundMessage(options: {
|
|
|
178
181
|
threadId?: number;
|
|
179
182
|
agentThread?: string | number;
|
|
180
183
|
target?: TelegramTarget;
|
|
181
|
-
getDefaultChatId?: () => number | undefined;
|
|
182
|
-
getDefaultTarget?: () => TelegramTarget | undefined;
|
|
183
|
-
getActiveTurn?: () => {
|
|
184
|
-
chatId: number;
|
|
185
|
-
target?: TelegramTarget;
|
|
186
|
-
} | undefined;
|
|
187
|
-
resolveAgentTarget?: (selector: TelegramBusAgentTargetSelector) => Promise<TelegramTarget & {
|
|
188
|
-
threadId: number;
|
|
189
|
-
}>;
|
|
190
|
-
routeAgentMessage?: (message: TelegramBusAgentMessage) => Promise<void>;
|
|
191
|
-
canSendDirect: () => boolean;
|
|
192
|
-
planMessage: (markdown: string) => TelegramOutboundMessagePlan;
|
|
193
|
-
sendMarkdownMessage: (chatId: number, markdown: string, options?: {
|
|
194
|
-
replyMarkup?: unknown;
|
|
195
|
-
target?: TelegramTarget;
|
|
196
|
-
}) => Promise<number | undefined>;
|
|
197
|
-
sendChannelMarkdownMessage?: (channel: number | string, markdown: string, options: {
|
|
198
|
-
operationId: string;
|
|
199
|
-
replyMarkup?: unknown;
|
|
200
|
-
}) => Promise<number | undefined>;
|
|
201
|
-
sendChannelMediaMessage?: (channel: number | string, mediaPath: string, markdown: string, options: {
|
|
202
|
-
operationId: string;
|
|
203
|
-
replyMarkup?: unknown;
|
|
204
|
-
}) => Promise<number | undefined>;
|
|
205
184
|
}): Promise<{
|
|
206
185
|
content: Array<{
|
|
207
186
|
type: "text";
|
|
@@ -8,10 +8,11 @@ import { basename } from "node:path";
|
|
|
8
8
|
import { Type } from "@sinclair/typebox";
|
|
9
9
|
import { isTelegramChannelPostValidationError, TelegramChannelPostValidationError, } from "./channel-posts.js";
|
|
10
10
|
import { TELEGRAM_ATTACH_PROMPT_GUIDELINES, TELEGRAM_ATTACH_PROMPT_SNIPPET, TELEGRAM_MESSAGE_PROMPT_GUIDELINES, TELEGRAM_MESSAGE_PROMPT_SNIPPET, } from "./prompts.js";
|
|
11
|
-
import {
|
|
11
|
+
import { normalizeTelegramNativeMarkdown, withTelegramReplyParameters, } from "./replies.js";
|
|
12
12
|
import { getTelegramTargetThreadParams, } from "./target.js";
|
|
13
13
|
const MAX_ATTACHMENTS_PER_TURN = 10;
|
|
14
14
|
export const TELEGRAM_OUTBOUND_ATTACHMENT_DEFAULT_MAX_BYTES = 50 * 1024 * 1024;
|
|
15
|
+
// Deliberately local: outbound attachment delivery stays decoupled from Bot API helpers.
|
|
15
16
|
export function getTelegramOutboundAttachmentByteLimitFromEnv(env, names, defaultValue = TELEGRAM_OUTBOUND_ATTACHMENT_DEFAULT_MAX_BYTES) {
|
|
16
17
|
for (const name of names) {
|
|
17
18
|
const rawValue = env[name]?.trim();
|
|
@@ -102,8 +103,14 @@ export function createTelegramRichOutboundAttachmentSender(deps) {
|
|
|
102
103
|
if (!plan)
|
|
103
104
|
return false;
|
|
104
105
|
try {
|
|
105
|
-
const result = await withTelegramReplyParameters(turn.chatId, turn.replyToMessageId, turn.target, (replyParameters) => deps.sendMultipart(plan.method, {
|
|
106
|
-
|
|
106
|
+
const result = await withTelegramReplyParameters(turn.chatId, turn.replyToMessageId, turn.target, (replyParameters) => deps.sendMultipart(plan.method, {
|
|
107
|
+
...plan.fields,
|
|
108
|
+
...(replyParameters
|
|
109
|
+
? { reply_parameters: JSON.stringify(replyParameters) }
|
|
110
|
+
: {}),
|
|
111
|
+
}, plan.fileField, plan.filePath, plan.fileName));
|
|
112
|
+
const messageId = result &&
|
|
113
|
+
typeof result === "object" &&
|
|
107
114
|
Number.isInteger(result.message_id)
|
|
108
115
|
? result.message_id
|
|
109
116
|
: undefined;
|
|
@@ -162,8 +169,16 @@ function formatTelegramOutboundAttachmentToolResultText(count, mode = "queued")
|
|
|
162
169
|
const verb = mode === "queued" ? "Queued" : "Sent";
|
|
163
170
|
return ["", `${verb} ${count} Telegram attachment(s).`].join("\n");
|
|
164
171
|
}
|
|
165
|
-
function
|
|
166
|
-
return
|
|
172
|
+
function buildTelegramOutboundMessageToolResult(chatId, messageId) {
|
|
173
|
+
return {
|
|
174
|
+
content: [
|
|
175
|
+
{
|
|
176
|
+
type: "text",
|
|
177
|
+
text: ["", `Sent Telegram message to ${chatId}.`].join("\n"),
|
|
178
|
+
},
|
|
179
|
+
],
|
|
180
|
+
details: { chatId, messageId },
|
|
181
|
+
};
|
|
167
182
|
}
|
|
168
183
|
function getTelegramMultipartTargetFields(target) {
|
|
169
184
|
if (!target)
|
|
@@ -280,10 +295,9 @@ export function registerTelegramOutboundMessageTool(pi, deps) {
|
|
|
280
295
|
minLength: 1,
|
|
281
296
|
description: "Local single-file channel upload: .jpg/.jpeg/.png/.webp photo or .mp4 video; the text becomes its caption (max 1024 characters). Albums and other media types are rejected.",
|
|
282
297
|
})),
|
|
283
|
-
chat_id: Type.Optional(Type.Union([
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
], { description: "Optional exact Telegram chat id or public channel @username" })),
|
|
298
|
+
chat_id: Type.Optional(Type.Union([Type.Number(), Type.String({ pattern: "^@[A-Za-z0-9_]{5,32}$" })], {
|
|
299
|
+
description: "Optional exact Telegram chat id or public channel @username",
|
|
300
|
+
})),
|
|
287
301
|
thread_id: Type.Optional(Type.Number({
|
|
288
302
|
description: "Optional Telegram topic thread id with chat_id",
|
|
289
303
|
})),
|
|
@@ -318,11 +332,12 @@ export function registerTelegramOutboundMessageTool(pi, deps) {
|
|
|
318
332
|
}
|
|
319
333
|
catch (error) {
|
|
320
334
|
const isChannelTarget = typeof params.chat_id === "string" || params.channel === true;
|
|
321
|
-
const reportableError = isChannelTarget &&
|
|
322
|
-
!isTelegramChannelPostValidationError(error)
|
|
335
|
+
const reportableError = isChannelTarget && !isTelegramChannelPostValidationError(error)
|
|
323
336
|
? new Error("Telegram channel publication failed; inspect the retained local record before retrying.")
|
|
324
337
|
: error;
|
|
325
|
-
deps.recordRuntimeEvent?.("message", reportableError, {
|
|
338
|
+
deps.recordRuntimeEvent?.("message", reportableError, {
|
|
339
|
+
phase: "direct",
|
|
340
|
+
});
|
|
326
341
|
throw formatTelegramOutboundToolError(reportableError);
|
|
327
342
|
}
|
|
328
343
|
},
|
|
@@ -435,9 +450,7 @@ export async function deliverTelegramGuestCachedAttachment(options) {
|
|
|
435
450
|
await options.answerGuestQuery(options.guestQueryId, result);
|
|
436
451
|
}
|
|
437
452
|
catch (error) {
|
|
438
|
-
if (!answerAttempted &&
|
|
439
|
-
options.answerGuestText &&
|
|
440
|
-
options.fallbackText) {
|
|
453
|
+
if (!answerAttempted && options.answerGuestText && options.fallbackText) {
|
|
441
454
|
answerAttempted = true;
|
|
442
455
|
await options.answerGuestText(options.guestQueryId, options.fallbackText);
|
|
443
456
|
}
|
|
@@ -464,10 +477,14 @@ export async function sendTelegramOutboundMessage(options) {
|
|
|
464
477
|
assertTelegramDirectDeliveryAllowed(options.canSendDirect);
|
|
465
478
|
const activeTurn = options.getActiveTurn?.();
|
|
466
479
|
if (typeof options.chatId === "string" || options.channel === true) {
|
|
467
|
-
if (!((typeof options.chatId === "string" &&
|
|
468
|
-
|
|
480
|
+
if (!((typeof options.chatId === "string" &&
|
|
481
|
+
/^@[A-Za-z0-9_]{5,32}$/u.test(options.chatId)) ||
|
|
482
|
+
(typeof options.chatId === "number" &&
|
|
483
|
+
Number.isSafeInteger(options.chatId) &&
|
|
484
|
+
options.chatId < 0)) ||
|
|
469
485
|
options.threadId !== undefined ||
|
|
470
|
-
options.target !== undefined ||
|
|
486
|
+
options.target !== undefined ||
|
|
487
|
+
options.agentThread !== undefined) {
|
|
471
488
|
throw new Error("Telegram channel delivery requires one exact @username or negative numeric channel ID without a thread target.");
|
|
472
489
|
}
|
|
473
490
|
const plan = options.planMessage(options.text);
|
|
@@ -476,18 +493,13 @@ export async function sendTelegramOutboundMessage(options) {
|
|
|
476
493
|
throw new TelegramChannelPostValidationError("Telegram channel media delivery requires direct leader transport ownership and operation identity.");
|
|
477
494
|
}
|
|
478
495
|
const messageId = await options.sendChannelMediaMessage(options.chatId, options.media, plan.markdown, { operationId: options.operationId, replyMarkup: plan.replyMarkup });
|
|
479
|
-
return
|
|
480
|
-
text: formatTelegramOutboundMessageToolResultText(options.chatId) }],
|
|
481
|
-
details: { chatId: options.chatId, messageId } };
|
|
496
|
+
return buildTelegramOutboundMessageToolResult(options.chatId, messageId);
|
|
482
497
|
}
|
|
483
498
|
if (!options.sendChannelMarkdownMessage || !options.operationId) {
|
|
484
499
|
throw new Error("Telegram channel delivery requires direct leader transport ownership and operation identity.");
|
|
485
500
|
}
|
|
486
|
-
const messageId = await options.sendChannelMarkdownMessage(options.chatId, plan.markdown, { operationId: options.operationId,
|
|
487
|
-
|
|
488
|
-
return { content: [{ type: "text",
|
|
489
|
-
text: formatTelegramOutboundMessageToolResultText(options.chatId) }],
|
|
490
|
-
details: { chatId: options.chatId, messageId } };
|
|
501
|
+
const messageId = await options.sendChannelMarkdownMessage(options.chatId, plan.markdown, { operationId: options.operationId, replyMarkup: plan.replyMarkup });
|
|
502
|
+
return buildTelegramOutboundMessageToolResult(options.chatId, messageId);
|
|
491
503
|
}
|
|
492
504
|
if (options.media !== undefined) {
|
|
493
505
|
throw new TelegramChannelPostValidationError("telegram_message media uploads require channel delivery with an exact @username or negative numeric channel ID and channel: true.");
|
|
@@ -499,7 +511,7 @@ export async function sendTelegramOutboundMessage(options) {
|
|
|
499
511
|
: activeTurn &&
|
|
500
512
|
options.resolveAgentTarget &&
|
|
501
513
|
options.routeAgentMessage &&
|
|
502
|
-
(
|
|
514
|
+
(options.target?.threadId !== undefined ||
|
|
503
515
|
(options.chatId !== undefined && options.threadId !== undefined))
|
|
504
516
|
? {
|
|
505
517
|
chatId: options.target?.chatId ?? options.chatId,
|
|
@@ -547,15 +559,7 @@ export async function sendTelegramOutboundMessage(options) {
|
|
|
547
559
|
text: options.text,
|
|
548
560
|
});
|
|
549
561
|
}
|
|
550
|
-
return
|
|
551
|
-
content: [
|
|
552
|
-
{
|
|
553
|
-
type: "text",
|
|
554
|
-
text: formatTelegramOutboundMessageToolResultText(chatId),
|
|
555
|
-
},
|
|
556
|
-
],
|
|
557
|
-
details: { chatId, messageId },
|
|
558
|
-
};
|
|
562
|
+
return buildTelegramOutboundMessageToolResult(chatId, messageId);
|
|
559
563
|
}
|
|
560
564
|
export async function sendTelegramOutboundFiles(options) {
|
|
561
565
|
assertTelegramDirectDeliveryAllowed(options.canSendDirect);
|
|
@@ -599,7 +603,8 @@ export function createTelegramQueuedOutboundAttachmentSender(deps) {
|
|
|
599
603
|
return async (turn, options) => {
|
|
600
604
|
await sendQueuedTelegramOutboundAttachments(turn, {
|
|
601
605
|
...deps,
|
|
602
|
-
isDeliveryActive: () => deps.isDeliveryActive?.() !== false &&
|
|
606
|
+
isDeliveryActive: () => deps.isDeliveryActive?.() !== false &&
|
|
607
|
+
options?.isDeliveryActive?.() !== false,
|
|
603
608
|
maxAttachmentSizeBytes: deps.maxAttachmentSizeBytes ?? TELEGRAM_OUTBOUND_ATTACHMENT_MAX_BYTES,
|
|
604
609
|
});
|
|
605
610
|
};
|
|
@@ -622,7 +627,9 @@ export async function sendQueuedTelegramOutboundAttachments(turn, deps) {
|
|
|
622
627
|
const fieldName = isPhoto ? "photo" : "document";
|
|
623
628
|
await withTelegramReplyParameters(turn.chatId, turn.replyToMessageId, turn.target, (replyParameters) => deps.sendMultipart(method, {
|
|
624
629
|
chat_id: String(turn.chatId),
|
|
625
|
-
...(replyParameters
|
|
630
|
+
...(replyParameters
|
|
631
|
+
? { reply_parameters: JSON.stringify(replyParameters) }
|
|
632
|
+
: {}),
|
|
626
633
|
...getTelegramMultipartTargetFields(turn.target),
|
|
627
634
|
}, fieldName, attachment.path, attachment.fileName));
|
|
628
635
|
}
|
|
@@ -83,12 +83,14 @@ function escapeTelegramRichButtonText(text) {
|
|
|
83
83
|
return text.replace(/[&<>"'`\\*_\[\]{}$~\r\n]/g, (character) => `&#${character.charCodeAt(0)};`);
|
|
84
84
|
}
|
|
85
85
|
function renderTelegramRichButtonRow(row) {
|
|
86
|
-
return `<tg-button-row>${row
|
|
86
|
+
return `<tg-button-row>${row
|
|
87
|
+
.map((button) => {
|
|
87
88
|
const attributes = button.disabled
|
|
88
89
|
? 'type="disabled"'
|
|
89
90
|
: `type="callback_data" data="${escapeTelegramRichButtonText(button.callback_data)}"`;
|
|
90
91
|
return `<tg-button ${attributes}>${escapeTelegramRichButtonText(button.text)}</tg-button>`;
|
|
91
|
-
})
|
|
92
|
+
})
|
|
93
|
+
.join("")}</tg-button-row>`;
|
|
92
94
|
}
|
|
93
95
|
export function planTelegramButtonReply(markdown, deps) {
|
|
94
96
|
const keyboard = [];
|
|
@@ -96,12 +98,14 @@ export function planTelegramButtonReply(markdown, deps) {
|
|
|
96
98
|
const actions = payloadRows.map((row) => row.map(parseTelegramButtonAction));
|
|
97
99
|
if (actions.some((row) => row.some((action) => !action)))
|
|
98
100
|
return undefined;
|
|
99
|
-
if (rich &&
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
101
|
+
if (rich &&
|
|
102
|
+
actions.some((row) => {
|
|
103
|
+
const projected = row.map((action) => action.disabled
|
|
104
|
+
? { text: action.text || "\u00a0", disabled: {} }
|
|
105
|
+
: { text: action.text, callback_data: "x".repeat(64) });
|
|
106
|
+
return (row.length > 8 ||
|
|
107
|
+
renderTelegramRichButtonRow(projected).length > 32768);
|
|
108
|
+
}))
|
|
105
109
|
return undefined;
|
|
106
110
|
return actions.map((row) => row.map((action) => action.disabled
|
|
107
111
|
? { text: action.text || "\u00a0", disabled: {} }
|
|
@@ -131,7 +135,9 @@ export function planTelegramButtonReply(markdown, deps) {
|
|
|
131
135
|
});
|
|
132
136
|
const stripped = replaceTopLevelHtmlComments(withRichButtons, (comment) => {
|
|
133
137
|
const command = "telegram_button";
|
|
134
|
-
const normalizedContent = comment.content
|
|
138
|
+
const normalizedContent = comment.content
|
|
139
|
+
.replace(/^\s+/, "")
|
|
140
|
+
.replace(/^!/, "");
|
|
135
141
|
if (!normalizedContent.startsWith(command))
|
|
136
142
|
return comment.raw;
|
|
137
143
|
const payloadRows = parseTelegramActionPayloadRows(comment, command);
|
|
@@ -186,19 +192,19 @@ export async function handleTelegramButtonCallbackQuery(query, ctx, deps) {
|
|
|
186
192
|
const action = deps.resolveAction(query.data);
|
|
187
193
|
if (!action) {
|
|
188
194
|
if (query.data?.startsWith(`${TELEGRAM_BUTTON_CALLBACK_PREFIX}:`)) {
|
|
189
|
-
await deps.answerCallbackQuery(query.id, "Button action expired
|
|
195
|
+
await deps.answerCallbackQuery(query.id, "Button action expired");
|
|
190
196
|
return true;
|
|
191
197
|
}
|
|
192
198
|
return false;
|
|
193
199
|
}
|
|
194
200
|
if (action.disabled) {
|
|
195
|
-
await deps.answerCallbackQuery(query.id, "Button action unavailable
|
|
201
|
+
await deps.answerCallbackQuery(query.id, "Button action unavailable");
|
|
196
202
|
return true;
|
|
197
203
|
}
|
|
198
204
|
const chatId = query.message?.chat?.id;
|
|
199
205
|
const messageId = query.message?.message_id;
|
|
200
206
|
if (typeof chatId !== "number" || typeof messageId !== "number") {
|
|
201
|
-
await deps.answerCallbackQuery(query.id, "Button action expired
|
|
207
|
+
await deps.answerCallbackQuery(query.id, "Button action expired");
|
|
202
208
|
return true;
|
|
203
209
|
}
|
|
204
210
|
if (deps.invokeBoundAction) {
|
|
@@ -216,18 +222,18 @@ export async function handleTelegramButtonCallbackQuery(query, ctx, deps) {
|
|
|
216
222
|
}
|
|
217
223
|
}
|
|
218
224
|
}
|
|
219
|
-
await deps.answerCallbackQuery(query.id, "Done
|
|
225
|
+
await deps.answerCallbackQuery(query.id, "Done");
|
|
220
226
|
return true;
|
|
221
227
|
}
|
|
222
228
|
}
|
|
223
229
|
catch (error) {
|
|
224
|
-
await deps.answerCallbackQuery(query.id, "Generative App action failed
|
|
230
|
+
await deps.answerCallbackQuery(query.id, "Generative App action failed");
|
|
225
231
|
throw error;
|
|
226
232
|
}
|
|
227
233
|
}
|
|
228
234
|
const enqueued = deps.enqueueButtonPrompt(query, action, ctx);
|
|
229
235
|
if (enqueued === false) {
|
|
230
|
-
await deps.answerCallbackQuery(query.id, "Already queued
|
|
236
|
+
await deps.answerCallbackQuery(query.id, "Already queued");
|
|
231
237
|
return true;
|
|
232
238
|
}
|
|
233
239
|
const selectedMarkup = query.data && query.message?.reply_markup
|
|
@@ -236,6 +242,6 @@ export async function handleTelegramButtonCallbackQuery(query, ctx, deps) {
|
|
|
236
242
|
if (selectedMarkup && deps.editMessageReplyMarkup) {
|
|
237
243
|
await deps.editMessageReplyMarkup(chatId, messageId, selectedMarkup);
|
|
238
244
|
}
|
|
239
|
-
await deps.answerCallbackQuery(query.id, "Queued
|
|
245
|
+
await deps.answerCallbackQuery(query.id, "Queued");
|
|
240
246
|
return true;
|
|
241
247
|
}
|
|
@@ -17,10 +17,8 @@ export declare function replaceTelegramButtonFences(markdown: string, replace: (
|
|
|
17
17
|
export declare function replaceTopLevelHtmlComments(markdown: string, replacer: (comment: TelegramTopLevelHtmlComment) => string): string;
|
|
18
18
|
export declare function parseTelegramButtonPayloadRows(source: string): Record<string, unknown>[][] | undefined;
|
|
19
19
|
export declare function parseTelegramActionPayloadRows(comment: TelegramTopLevelHtmlComment, command: string): Record<string, unknown>[][] | undefined;
|
|
20
|
-
export declare function normalizeMarkdownAfterVoiceExtraction(markdown: string): string;
|
|
21
20
|
export declare function stripTelegramCommentMarkupForPreview(markdown: string): string;
|
|
22
21
|
export declare function stripTelegramCommentMarkupForDelivery(markdown: string): string;
|
|
23
|
-
export declare function stripTelegramVoiceMarkupForPreview(markdown: string): string;
|
|
24
22
|
export interface TelegramVoiceReplyItem {
|
|
25
23
|
text: string;
|
|
26
24
|
lang?: string;
|
|
@@ -192,7 +192,9 @@ function removeTelegramJsonTrailingCommas(source) {
|
|
|
192
192
|
}
|
|
193
193
|
function parseTelegramJsonObjectCandidate(source) {
|
|
194
194
|
const normalized = removeTelegramJsonTrailingCommas(source);
|
|
195
|
-
for (const candidate of normalized === source
|
|
195
|
+
for (const candidate of normalized === source
|
|
196
|
+
? [source]
|
|
197
|
+
: [source, normalized]) {
|
|
196
198
|
try {
|
|
197
199
|
const value = JSON.parse(candidate);
|
|
198
200
|
if (isTelegramActionPayload(value))
|
|
@@ -207,36 +209,46 @@ function parseTelegramJsonObjectCandidate(source) {
|
|
|
207
209
|
function looksLikeTelegramNamedJsonObject(source, offset) {
|
|
208
210
|
return /^\{\s*"(?:[^"\\]|\\.)*"\s*:/u.test(source.slice(offset));
|
|
209
211
|
}
|
|
210
|
-
|
|
212
|
+
/** Blank one structured span so tolerant attribute parsing never reads keys inside rejected JSON or matrices. */
|
|
213
|
+
function blankTelegramActionSpan(text, start, end) {
|
|
214
|
+
return `${text.slice(0, start)}${" ".repeat(end - start)}${text.slice(end)}`;
|
|
215
|
+
}
|
|
216
|
+
/**
|
|
217
|
+
* Scans one action comment for its first accepted structured payload. Otherwise returns the attribute envelope
|
|
218
|
+
* with every structured span blanked; implausible `[` starts are skipped without a parse attempt.
|
|
219
|
+
*/
|
|
220
|
+
function scanTelegramActionComment(comment, command, parseStructured) {
|
|
211
221
|
let content = comment.content.replace(/^\s+/, "").replace(/^!/, "");
|
|
212
222
|
if (!content.startsWith(command))
|
|
213
223
|
return undefined;
|
|
214
224
|
content = content.slice(command.length);
|
|
215
225
|
let attributeEnvelope = content;
|
|
216
226
|
for (let offset = 0; offset < content.length; offset += 1) {
|
|
217
|
-
|
|
227
|
+
const char = content[offset];
|
|
228
|
+
if (char !== "{" && char !== "[")
|
|
218
229
|
continue;
|
|
219
|
-
if (
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
attributeEnvelope = `${attributeEnvelope.slice(0, offset)}${" ".repeat(noiseEnd - offset)}${attributeEnvelope.slice(noiseEnd)}`;
|
|
224
|
-
offset = noiseEnd - 1;
|
|
225
|
-
}
|
|
226
|
-
continue;
|
|
227
|
-
}
|
|
228
|
-
if (content[offset] === "{") {
|
|
229
|
-
const parsed = parseTelegramAdaptiveActionPayloadRows(content.slice(offset), parseTelegramVoiceCompactActionPayload, { allowTrailing: true });
|
|
230
|
-
if (parsed)
|
|
231
|
-
return parsed.rows[0][0];
|
|
230
|
+
if (char === "{" || isPlausibleTelegramMatrixStart(content, offset)) {
|
|
231
|
+
const payload = parseStructured(content, offset);
|
|
232
|
+
if (payload !== undefined)
|
|
233
|
+
return { payload };
|
|
232
234
|
}
|
|
233
235
|
const end = findTelegramStructuredPayloadEnd(content, offset);
|
|
234
236
|
if (end === undefined)
|
|
235
237
|
continue;
|
|
236
|
-
attributeEnvelope =
|
|
238
|
+
attributeEnvelope = blankTelegramActionSpan(attributeEnvelope, offset, end);
|
|
237
239
|
offset = end - 1;
|
|
238
240
|
}
|
|
239
|
-
return
|
|
241
|
+
return { attributeEnvelope };
|
|
242
|
+
}
|
|
243
|
+
function parseTelegramActionPayload(comment, command) {
|
|
244
|
+
const scanned = scanTelegramActionComment(comment, command, (content, offset) => content[offset] === "{"
|
|
245
|
+
? parseTelegramAdaptiveActionPayloadRows(content.slice(offset), parseTelegramVoiceCompactActionPayload, { allowTrailing: true })?.rows[0][0]
|
|
246
|
+
: undefined);
|
|
247
|
+
if (!scanned)
|
|
248
|
+
return undefined;
|
|
249
|
+
if ("payload" in scanned)
|
|
250
|
+
return scanned.payload;
|
|
251
|
+
return parseTolerantTelegramAttributes(scanned.attributeEnvelope, [
|
|
240
252
|
"text",
|
|
241
253
|
"value",
|
|
242
254
|
"lang",
|
|
@@ -259,7 +271,10 @@ function parseTelegramButtonCompactActionPayload(atoms) {
|
|
|
259
271
|
selectedStyle !== "danger" &&
|
|
260
272
|
!(atoms.length === 4 && selectedStyle === ""))
|
|
261
273
|
return undefined;
|
|
262
|
-
if (atoms.length === 4 &&
|
|
274
|
+
if (atoms.length === 4 &&
|
|
275
|
+
!isDisabled &&
|
|
276
|
+
disabled !== "0" &&
|
|
277
|
+
disabled !== "false") {
|
|
263
278
|
return undefined;
|
|
264
279
|
}
|
|
265
280
|
return {
|
|
@@ -464,9 +479,7 @@ function parseTelegramAdaptiveActionPayloadRows(source, parseCompactPayload, opt
|
|
|
464
479
|
return rows.length > 0 ? rows : undefined;
|
|
465
480
|
};
|
|
466
481
|
skipWhitespace();
|
|
467
|
-
const rows = source[offset] === "{"
|
|
468
|
-
? parseVerticalSequence()
|
|
469
|
-
: parseMatrix();
|
|
482
|
+
const rows = source[offset] === "{" ? parseVerticalSequence() : parseMatrix();
|
|
470
483
|
if (!rows)
|
|
471
484
|
return undefined;
|
|
472
485
|
skipWhitespace();
|
|
@@ -511,57 +524,32 @@ function isPlausibleTelegramMatrixStart(source, start) {
|
|
|
511
524
|
let offset = start + 1;
|
|
512
525
|
while (/\s/u.test(source[offset] ?? ""))
|
|
513
526
|
offset += 1;
|
|
514
|
-
return (source[offset] === "{" ||
|
|
515
|
-
source[offset] === "[" ||
|
|
516
|
-
source[offset] === "]");
|
|
527
|
+
return (source[offset] === "{" || source[offset] === "[" || source[offset] === "]");
|
|
517
528
|
}
|
|
518
529
|
export function parseTelegramButtonPayloadRows(source) {
|
|
519
530
|
return parseTelegramAdaptiveActionPayloadRows(source.trim(), parseTelegramButtonCompactActionPayload, { maxCompactAtoms: 4 })?.rows;
|
|
520
531
|
}
|
|
521
532
|
export function parseTelegramActionPayloadRows(comment, command) {
|
|
522
|
-
|
|
523
|
-
if (!
|
|
533
|
+
const scanned = scanTelegramActionComment(comment, command, (content, offset) => parseTelegramAdaptiveActionPayloadRows(content.slice(offset), parseTelegramButtonCompactActionPayload, { allowTrailing: true, maxCompactAtoms: 4 })?.rows);
|
|
534
|
+
if (!scanned)
|
|
524
535
|
return undefined;
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
if (content[offset] !== "[" && content[offset] !== "{")
|
|
529
|
-
continue;
|
|
530
|
-
if (content[offset] === "[" &&
|
|
531
|
-
!isPlausibleTelegramMatrixStart(content, offset)) {
|
|
532
|
-
const noiseEnd = findTelegramStructuredPayloadEnd(content, offset);
|
|
533
|
-
if (noiseEnd !== undefined) {
|
|
534
|
-
attributeEnvelope = `${attributeEnvelope.slice(0, offset)}${" ".repeat(noiseEnd - offset)}${attributeEnvelope.slice(noiseEnd)}`;
|
|
535
|
-
offset = noiseEnd - 1;
|
|
536
|
-
}
|
|
537
|
-
continue;
|
|
538
|
-
}
|
|
539
|
-
const parsed = parseTelegramAdaptiveActionPayloadRows(content.slice(offset), parseTelegramButtonCompactActionPayload, { allowTrailing: true, maxCompactAtoms: 4 });
|
|
540
|
-
if (parsed)
|
|
541
|
-
return parsed.rows;
|
|
542
|
-
const end = findTelegramStructuredPayloadEnd(content, offset);
|
|
543
|
-
if (end === undefined)
|
|
544
|
-
continue;
|
|
545
|
-
attributeEnvelope = `${attributeEnvelope.slice(0, offset)}${" ".repeat(end - offset)}${attributeEnvelope.slice(end)}`;
|
|
546
|
-
offset = end - 1;
|
|
547
|
-
}
|
|
548
|
-
const attributes = parseTolerantTelegramAttributes(attributeEnvelope, [
|
|
549
|
-
"label",
|
|
550
|
-
"prompt",
|
|
551
|
-
"value",
|
|
552
|
-
"selected_style",
|
|
553
|
-
"disabled",
|
|
554
|
-
]);
|
|
536
|
+
if ("payload" in scanned)
|
|
537
|
+
return scanned.payload;
|
|
538
|
+
const attributes = parseTolerantTelegramAttributes(scanned.attributeEnvelope, ["label", "prompt", "value", "selected_style", "disabled"]);
|
|
555
539
|
if (!attributes)
|
|
556
540
|
return undefined;
|
|
557
|
-
return [
|
|
541
|
+
return [
|
|
542
|
+
[
|
|
543
|
+
{
|
|
558
544
|
...attributes,
|
|
559
545
|
...(attributes.disabled === "true" || attributes.disabled === "false"
|
|
560
546
|
? { disabled: attributes.disabled === "true" }
|
|
561
547
|
: {}),
|
|
562
|
-
}
|
|
548
|
+
},
|
|
549
|
+
],
|
|
550
|
+
];
|
|
563
551
|
}
|
|
564
|
-
|
|
552
|
+
function normalizeMarkdownAfterVoiceExtraction(markdown) {
|
|
565
553
|
return markdown.replace(/\n{3,}/g, "\n\n").trim();
|
|
566
554
|
}
|
|
567
555
|
function isTelegramCommentOnlyLinePrefix(value) {
|
|
@@ -608,9 +596,6 @@ export function stripTelegramCommentMarkupForDelivery(markdown) {
|
|
|
608
596
|
: withoutClosedBlocks;
|
|
609
597
|
return normalizeMarkdownAfterVoiceExtraction(deliveryMarkdown);
|
|
610
598
|
}
|
|
611
|
-
export function stripTelegramVoiceMarkupForPreview(markdown) {
|
|
612
|
-
return stripTelegramCommentMarkupForPreview(markdown);
|
|
613
|
-
}
|
|
614
599
|
export function getTelegramActionString(payload, key) {
|
|
615
600
|
const value = payload[key];
|
|
616
601
|
if (typeof value !== "string")
|
|
@@ -624,7 +609,9 @@ export function planTelegramVoiceReply(markdown) {
|
|
|
624
609
|
let rate;
|
|
625
610
|
const stripped = replaceTopLevelHtmlComments(markdown, (comment) => {
|
|
626
611
|
const command = "telegram_voice";
|
|
627
|
-
const normalizedContent = comment.content
|
|
612
|
+
const normalizedContent = comment.content
|
|
613
|
+
.replace(/^\s+/, "")
|
|
614
|
+
.replace(/^!/, "");
|
|
628
615
|
if (!normalizedContent.startsWith(command))
|
|
629
616
|
return comment.raw;
|
|
630
617
|
const payload = parseTelegramActionPayload(comment, command);
|
|
@@ -8,8 +8,8 @@ import { basename, extname } from "node:path";
|
|
|
8
8
|
import { assertTelegramInlineKeyboardCallbackData } from "./keyboard.js";
|
|
9
9
|
import { withTelegramReplyParameters } from "./replies.js";
|
|
10
10
|
import { getTelegramTargetThreadParams, } from "./target.js";
|
|
11
|
-
import { getTelegramVoiceSynthesisProviders } from "./voice.js";
|
|
12
11
|
import { isTelegramApiCommitUnknownError } from "./telegram-api.js";
|
|
12
|
+
import { getTelegramVoiceSynthesisProviders } from "./voice.js";
|
|
13
13
|
async function ensureTelegramVoiceFileFormat(filePath) {
|
|
14
14
|
const ext = extname(filePath).toLowerCase();
|
|
15
15
|
if (ext === ".opus" || ext === ".ogg")
|
|
@@ -38,11 +38,14 @@ export function createTelegramVoiceReplySender(deps, ports = {}) {
|
|
|
38
38
|
return;
|
|
39
39
|
await withTelegramReplyParameters(turn.chatId, options?.replyToPrompt === false ? undefined : turn.replyToMessageId, turn.target, (replyParameters) => deps.sendMultipart("sendVoice", {
|
|
40
40
|
chat_id: String(turn.chatId),
|
|
41
|
-
...(replyParameters
|
|
41
|
+
...(replyParameters
|
|
42
|
+
? { reply_parameters: JSON.stringify(replyParameters) }
|
|
43
|
+
: {}),
|
|
42
44
|
...(turn.target
|
|
43
45
|
? Object.fromEntries(Object.entries(getTelegramTargetThreadParams(turn.target)).map(([key, value]) => [key, String(value)]))
|
|
44
46
|
: {}),
|
|
45
|
-
...(options?.replyMarkup !== undefined &&
|
|
47
|
+
...(options?.replyMarkup !== undefined &&
|
|
48
|
+
options.replyMarkup !== null
|
|
46
49
|
? {
|
|
47
50
|
reply_markup: typeof options.replyMarkup === "string"
|
|
48
51
|
? options.replyMarkup
|
package/dist/lib/outbound.d.ts
CHANGED
|
@@ -4,12 +4,12 @@
|
|
|
4
4
|
* Owns configured outbound handler execution, text transforms, public assistant-output reply composition and mutation fencing, voice-file generation/delivery, runtime-event bridge, and compatibility re-exports; assistant markup parsing lives in outbound-markup and button callback actions live in outbound-buttons
|
|
5
5
|
*/
|
|
6
6
|
import type { TelegramAssistantSegmentEvent } from "./activity.ts";
|
|
7
|
-
import * as Replies from "./replies.ts";
|
|
8
|
-
import type { TelegramPreparedPreviewDelivery } from "./preview.ts";
|
|
9
|
-
import type { TelegramEditMessageTextBody, TelegramSendMessageBody, TelegramSendRichMessageBody, TelegramSentMessage } from "./telegram-api.ts";
|
|
10
7
|
import { type TelegramButtonActionStore, type TelegramOutboundButtonBinding, type TelegramOutboundButtonMarkup } from "./outbound-buttons.ts";
|
|
11
8
|
import { type TelegramVoiceReplyItem } from "./outbound-markup.ts";
|
|
9
|
+
import type { TelegramPreparedPreviewDelivery } from "./preview.ts";
|
|
10
|
+
import * as Replies from "./replies.ts";
|
|
12
11
|
import type { TelegramTarget } from "./target.ts";
|
|
12
|
+
import type { TelegramEditMessageTextBody, TelegramSendMessageBody, TelegramSendRichMessageBody, TelegramSentMessage } from "./telegram-api.ts";
|
|
13
13
|
import { type CommandTemplateObjectConfig } from "./command-templates.ts";
|
|
14
14
|
/**
|
|
15
15
|
* Record a runtime event that appears in `/telegram-status`.
|
|
@@ -27,13 +27,13 @@ export interface TelegramOutboundHandlerConfig extends CommandTemplateObjectConf
|
|
|
27
27
|
output?: string;
|
|
28
28
|
timeout?: number | string;
|
|
29
29
|
}
|
|
30
|
-
export { normalizeMarkdownAfterVoiceExtraction, planTelegramVoiceReply, stripTelegramCommentMarkupForDelivery, stripTelegramCommentMarkupForPreview, stripTelegramVoiceMarkupForPreview, type TelegramVoiceReplyItem, type TelegramVoiceReplyPlan, } from "./outbound-markup.ts";
|
|
31
30
|
export interface TelegramVoiceExecOptions {
|
|
32
31
|
cwd?: string;
|
|
33
32
|
timeout?: number;
|
|
34
33
|
signal?: AbortSignal;
|
|
35
34
|
stdin?: string;
|
|
36
35
|
retry?: number;
|
|
36
|
+
recover?: () => Promise<void>;
|
|
37
37
|
}
|
|
38
38
|
export interface TelegramVoiceExecResult {
|
|
39
39
|
stdout: string;
|
|
@@ -74,11 +74,11 @@ export interface TelegramOutboundTextReplyRuntimeDeps<TReplyMarkup = unknown> {
|
|
|
74
74
|
sendTextReply: (chatId: number, replyToMessageId: number | undefined, text: string, options?: {
|
|
75
75
|
parseMode?: "HTML";
|
|
76
76
|
target?: TelegramTarget;
|
|
77
|
-
}) => Promise<number | undefined>;
|
|
77
|
+
} & Pick<Replies.TelegramReplyTargetOptions, "assertAuthority">) => Promise<number | undefined>;
|
|
78
78
|
sendMarkdownReply: (chatId: number, replyToMessageId: number | undefined, markdown: string, options?: {
|
|
79
79
|
replyMarkup?: TReplyMarkup;
|
|
80
80
|
target?: TelegramTarget;
|
|
81
|
-
}) => Promise<number | undefined>;
|
|
81
|
+
} & Pick<Replies.TelegramReplyTargetOptions, "assertAuthority">) => Promise<number | undefined>;
|
|
82
82
|
cwd?: string;
|
|
83
83
|
recordRuntimeEvent?: TelegramVoiceReplySenderDeps["recordRuntimeEvent"];
|
|
84
84
|
}
|