UNPKG

openclaw

Version:

Multi-channel AI gateway with extensible messaging integrations

558 lines (557 loc) 26.2 kB
import { u as resolveStorePath } from "./paths-NEwU8m3X.js"; import { f as renderMessagePresentationFallbackText, l as normalizeMessagePresentation } from "./payload-CZlThETZ.js"; import { _ as readReactionParams, b as readStringParam, g as readPositiveIntegerParam, l as jsonResult, v as readStringArrayParam, y as readStringOrNumberParam } from "./common-C4yy9V-D.js"; import { t as buildOutboundSessionContext } from "./session-context-Bz96-75Y.js"; import { r as resolvePollMaxSelections } from "./polls-C-v11_tu.js"; import { t as readBooleanParam } from "./boolean-param-K-k-cDXs.js"; import { t as resolveTelegramToken } from "./token-B4yhWKGC.js"; import { n as sendDurableMessageBatch } from "./channel-outbound-B3_Zy-kG.js"; import { r as resolveReactionMessageId } from "./channel-actions-BOfvC-Gl.js"; import "./session-store-runtime-rvUx2Fil.js"; import { a as resolveDefaultTelegramAccountId, c as resolveTelegramPollActionGateState, t as createTelegramActionGate } from "./accounts-blCxAL9j.js"; import { a as parseTelegramTarget, i as normalizeTelegramOutboundTarget, o as resolveTelegramTargetChatType } from "./targets-CDtCx0Zi.js"; import { r as resolveTelegramInlineButtonsScope } from "./inline-buttons-4xnM1eKI.js"; import { t as resolveTelegramInlineButtons } from "./button-types-Di5CvasV.js"; import { t as resolveTelegramInteractiveTextFallback } from "./interactive-fallback-BQgyaNXo.js"; import { t as resolveTelegramReactionLevel } from "./reaction-level-Dx393P0D.js"; import { a as getCacheStats, c as searchStickers } from "./sticker-cache-store-mh6jiBwt.js"; import { o as resolveTopicNameCacheScope, s as updateTopicName } from "./topic-name-cache-B2kWKFCe.js"; import "./sticker-cache-BFNVd7JL.js"; import { a as editMessageTelegram, d as sendPollTelegram, f as sendStickerTelegram, i as editMessageReplyMarkupTelegram, n as deleteMessageTelegram, o as pinMessageTelegram, r as editForumTopicTelegram, s as reactMessageTelegram, t as createForumTopicTelegram, u as sendMessageTelegram } from "./send-f0zZCDGg.js"; import { t as resolveTelegramPollVisibility } from "./poll-visibility-Ds4ydsWS.js"; import { n as notifyTelegramInboundEventOutboundSuccess } from "./inbound-event-delivery-CNR-dgbp.js"; //#region extensions/telegram/src/action-runtime.ts const telegramActionRuntime = { createForumTopicTelegram, deleteMessageTelegram, editForumTopicTelegram, editMessageReplyMarkupTelegram, editMessageTelegram, getCacheStats, pinMessageTelegram, reactMessageTelegram, searchStickers, sendDurableMessageBatch, sendMessageTelegram, sendPollTelegram, sendStickerTelegram }; const TELEGRAM_FORUM_TOPIC_ICON_COLORS = [ 7322096, 16766590, 13338331, 9367192, 16749490, 16478047 ]; const TELEGRAM_ACTION_ALIASES = { createForumTopic: "createForumTopic", delete: "deleteMessage", deleteMessage: "deleteMessage", edit: "editMessage", editForumTopic: "editForumTopic", editMessage: "editMessage", poll: "poll", react: "react", searchSticker: "searchSticker", send: "sendMessage", sendMessage: "sendMessage", sendSticker: "sendSticker", sticker: "sendSticker", stickerCacheStats: "stickerCacheStats", "sticker-search": "searchSticker", "topic-create": "createForumTopic", "topic-edit": "editForumTopic" }; function readTelegramForumTopicIconColor(params) { const iconColor = readPositiveIntegerParam(params, "iconColor", { message: "iconColor must be one of Telegram's supported forum topic colors." }); if (iconColor == null) return; if (!TELEGRAM_FORUM_TOPIC_ICON_COLORS.includes(iconColor)) throw new Error("iconColor must be one of Telegram's supported forum topic colors."); return iconColor; } function normalizeTelegramActionName(action) { const normalized = TELEGRAM_ACTION_ALIASES[action]; if (!normalized) throw new Error(`Unsupported Telegram action: ${action}`); return normalized; } function readTelegramChatId(params) { return readStringOrNumberParam(params, "chatId") ?? readStringOrNumberParam(params, "channelId") ?? readStringOrNumberParam(params, "to", { required: true }); } function readTelegramThreadId(params) { return readPositiveIntegerParam(params, "messageThreadId", { message: "messageThreadId must be a positive integer." }) ?? readPositiveIntegerParam(params, "threadId", { message: "threadId must be a positive integer." }); } function resolveActionTopicNameCacheScope(cfg, accountId) { return resolveTopicNameCacheScope(resolveStorePath(cfg.session?.store, { agentId: accountId ?? resolveDefaultTelegramAccountId(cfg) })); } function formatTelegramDeliveryTarget(to, messageThreadId) { const parsed = parseTelegramTarget(to); const topicId = parsed.messageThreadId ?? messageThreadId; if (topicId == null) return to; return `${parsed.chatId}:topic:${topicId}`; } function readTelegramReplyToMessageId(params) { return readPositiveIntegerParam(params, "replyToMessageId", { message: "replyToMessageId must be a positive integer." }) ?? readPositiveIntegerParam(params, "replyTo", { message: "replyTo must be a positive integer." }); } function pushTelegramMediaUrl(mediaUrls, seen, value) { if (typeof value !== "string") return; const normalized = value.trim(); if (!normalized || seen.has(normalized)) return; seen.add(normalized); mediaUrls.push(normalized); } function readTelegramSendMediaUrls(params) { const mediaUrls = []; const seen = /* @__PURE__ */ new Set(); pushTelegramMediaUrl(mediaUrls, seen, params.mediaUrl); pushTelegramMediaUrl(mediaUrls, seen, params.media); pushTelegramMediaUrl(mediaUrls, seen, params.path); pushTelegramMediaUrl(mediaUrls, seen, params.filePath); pushTelegramMediaUrl(mediaUrls, seen, params.fileUrl); if (Array.isArray(params.mediaUrls)) for (const mediaUrl of params.mediaUrls) pushTelegramMediaUrl(mediaUrls, seen, mediaUrl); if (Array.isArray(params.attachments)) for (const attachment of params.attachments) { if (!attachment || typeof attachment !== "object" || Array.isArray(attachment)) continue; const record = attachment; pushTelegramMediaUrl(mediaUrls, seen, record.media); pushTelegramMediaUrl(mediaUrls, seen, record.mediaUrl); pushTelegramMediaUrl(mediaUrls, seen, record.path); pushTelegramMediaUrl(mediaUrls, seen, record.filePath); pushTelegramMediaUrl(mediaUrls, seen, record.fileUrl); pushTelegramMediaUrl(mediaUrls, seen, record.url); } return mediaUrls; } function resolveTelegramButtonsFromParams(params, presentation = normalizeMessagePresentation(params.presentation)) { return resolveTelegramInlineButtons({ presentation, interactive: params.interactive }); } function readTelegramSendContent(params) { const explicitContent = readStringParam(params.args, "content", { allowEmpty: true }) ?? readStringParam(params.args, "message", { allowEmpty: true }) ?? readStringParam(params.args, "caption", { allowEmpty: true }); const presentationText = explicitContent == null && params.presentation ? renderMessagePresentationFallbackText({ presentation: params.presentation }) : void 0; const interactiveText = explicitContent == null && !params.presentation ? resolveTelegramInteractiveTextFallback({ interactive: params.interactive }) : void 0; let content = explicitContent ?? (presentationText?.trim() ? presentationText : void 0) ?? (interactiveText?.trim() ? interactiveText : void 0); if ((content == null || content.trim().length === 0) && !params.mediaUrl && params.hasButtons) { const fallback = presentationText?.trim() ? presentationText : interactiveText; if (fallback?.trim()) content = fallback; } if (content == null && !params.mediaUrl && !params.hasButtons) throw new Error("content required."); return content ?? ""; } function normalizeTelegramDeliveryPin(params) { const delivery = params.delivery; const pin = delivery && typeof delivery === "object" && !Array.isArray(delivery) ? delivery.pin : params.pin === true ? true : void 0; if (pin === true) return { enabled: true }; if (!pin || typeof pin !== "object" || Array.isArray(pin)) return; const raw = pin; if (raw.enabled !== true) return; return { enabled: true, ...raw.notify === true ? { notify: true } : {}, ...raw.required === true ? { required: true } : {} }; } function buildTelegramActionSendPayload(params) { const telegramData = params.buttons || params.quoteText ? { ...params.buttons ? { buttons: params.buttons } : {}, ...params.quoteText ? { quoteText: params.quoteText } : {} } : void 0; return { text: params.content, ...params.mediaUrls.length > 0 ? { mediaUrls: params.mediaUrls } : {}, ...params.asVoice === true ? { audioAsVoice: true } : {}, ...params.pin ? { delivery: { pin: params.pin } } : {}, ...telegramData ? { channelData: { telegram: telegramData } } : {} }; } function getLastDurableTelegramActionResult(result) { const lastResult = result.results.at(-1); const receipt = result.receipt; return { messageId: lastResult?.messageId ?? receipt.primaryPlatformMessageId ?? receipt.platformMessageIds.at(-1), chatId: lastResult?.chatId }; } async function handleTelegramAction(params, cfg, options) { const { action, accountId } = { action: normalizeTelegramActionName(readStringParam(params, "action", { required: true })), accountId: readStringParam(params, "accountId") }; const isActionEnabled = createTelegramActionGate({ cfg, accountId }); const notifyVisibleOutboundSuccess = (to, messageThreadId) => { notifyTelegramInboundEventOutboundSuccess({ sessionKey: options?.sessionKey ?? void 0, to: formatTelegramDeliveryTarget(to, messageThreadId), accountId, inboundEventKind: options?.inboundEventKind }); }; if (action === "react") { const reactionLevelInfo = resolveTelegramReactionLevel({ cfg, accountId: accountId ?? void 0 }); if (!reactionLevelInfo.agentReactionsEnabled) return jsonResult({ ok: false, reason: "disabled", hint: `Telegram agent reactions disabled (reactionLevel="${reactionLevelInfo.level}"). Do not retry.` }); if (!isActionEnabled("reactions")) return jsonResult({ ok: false, reason: "disabled", hint: "Telegram reactions are disabled via actions.reactions. Do not retry." }); const chatId = readTelegramChatId(params); let explicitMessageId; try { explicitMessageId = readPositiveIntegerParam(params, "messageId", { message: "messageId must be a positive integer." }); } catch { return jsonResult({ ok: false, reason: "missing_message_id", hint: "Telegram reaction requires a valid messageId (or inbound context fallback). Do not retry." }); } const messageId = explicitMessageId ?? resolveReactionMessageId({ args: params }); if (typeof messageId !== "number" || !Number.isFinite(messageId) || messageId <= 0) return jsonResult({ ok: false, reason: "missing_message_id", hint: "Telegram reaction requires a valid messageId (or inbound context fallback). Do not retry." }); const { emoji, remove, isEmpty } = readReactionParams(params, { removeErrorMessage: "Emoji is required to remove a Telegram reaction." }); const token = resolveTelegramToken(cfg, { accountId }).token; if (!token) return jsonResult({ ok: false, reason: "missing_token", hint: "Telegram bot token missing. Do not retry." }); let reactionResult; try { reactionResult = await telegramActionRuntime.reactMessageTelegram(chatId ?? "", messageId ?? 0, emoji ?? "", { cfg, token, remove, accountId: accountId ?? void 0, gatewayClientScopes: options?.gatewayClientScopes }); } catch (err) { const isInvalid = String(err).includes("REACTION_INVALID"); return jsonResult({ ok: false, reason: isInvalid ? "REACTION_INVALID" : "error", emoji, hint: isInvalid ? "This emoji is not supported for Telegram reactions. Add it to your reaction disallow list so you do not try it again." : "Reaction failed. Do not retry." }); } if (!reactionResult.ok) return jsonResult({ ok: false, warning: reactionResult.warning, ...remove || isEmpty ? { removed: true } : { added: emoji } }); if (!remove && !isEmpty) return jsonResult({ ok: true, added: emoji }); return jsonResult({ ok: true, removed: true }); } if (action === "sendMessage") { if (!isActionEnabled("sendMessage")) throw new Error("Telegram sendMessage is disabled."); const to = normalizeTelegramOutboundTarget(readStringParam(params, "to", { required: true })); const mediaUrls = readTelegramSendMediaUrls(params); const firstMediaUrl = mediaUrls[0]; const presentation = normalizeMessagePresentation(params.presentation); const buttons = resolveTelegramButtonsFromParams(params, presentation); const content = readTelegramSendContent({ args: params, mediaUrl: firstMediaUrl, hasButtons: Array.isArray(buttons) && buttons.length > 0, interactive: params.interactive, presentation }); if (buttons) { const inlineButtonsScope = resolveTelegramInlineButtonsScope({ cfg, accountId: accountId ?? void 0 }); if (inlineButtonsScope === "off") throw new Error("Telegram inline buttons are disabled. Set channels.telegram.capabilities.inlineButtons to \"dm\", \"group\", \"all\", or \"allowlist\"."); if (inlineButtonsScope === "dm" || inlineButtonsScope === "group") { const targetType = resolveTelegramTargetChatType(to); if (targetType === "unknown") throw new Error(`Telegram inline buttons require a numeric chat id when inlineButtons="${inlineButtonsScope}".`); if (inlineButtonsScope === "dm" && targetType !== "direct") throw new Error("Telegram inline buttons are limited to DMs when inlineButtons=\"dm\"."); if (inlineButtonsScope === "group" && targetType !== "group") throw new Error("Telegram inline buttons are limited to groups when inlineButtons=\"group\"."); } } const replyToMessageId = readTelegramReplyToMessageId(params); const messageThreadId = readTelegramThreadId(params); const quoteText = readStringParam(params, "quoteText"); if (!resolveTelegramToken(cfg, { accountId }).token) throw new Error("Telegram bot token missing. Set TELEGRAM_BOT_TOKEN or channels.telegram.botToken."); const sendOptions = { cfg, accountId: accountId ?? void 0, gatewayClientScopes: options?.gatewayClientScopes, replyToMessageId: replyToMessageId ?? void 0, messageThreadId: messageThreadId ?? void 0, quoteText: quoteText ?? void 0, asVoice: readBooleanParam(params, "asVoice"), silent: readBooleanParam(params, "silent"), forceDocument: readBooleanParam(params, "forceDocument") ?? readBooleanParam(params, "asDocument") ?? false }; const payload = buildTelegramActionSendPayload({ content, mediaUrls, asVoice: sendOptions.asVoice, pin: normalizeTelegramDeliveryPin(params), buttons, quoteText }); const mediaAccess = options?.mediaLocalRoots || options?.mediaReadFile ? { ...options.mediaLocalRoots ? { localRoots: options.mediaLocalRoots } : {}, ...options.mediaReadFile ? { readFile: options.mediaReadFile } : {} } : void 0; const outboundSession = buildOutboundSessionContext({ cfg, sessionKey: options?.sessionKey, requesterAccountId: accountId }); const durableResult = await telegramActionRuntime.sendDurableMessageBatch({ cfg, channel: "telegram", to, accountId: accountId ?? void 0, payloads: [payload], replyToId: replyToMessageId == null ? void 0 : String(replyToMessageId), threadId: messageThreadId, forceDocument: sendOptions.forceDocument, silent: sendOptions.silent, durability: "required", gatewayClientScopes: options?.gatewayClientScopes, ...mediaAccess ? { mediaAccess } : {}, ...outboundSession ? { session: outboundSession } : {} }); if (durableResult.status === "failed" || durableResult.status === "partial_failed") throw durableResult.error; if (durableResult.status === "suppressed") throw new Error("Telegram sendMessage was suppressed before delivery."); const result = getLastDurableTelegramActionResult(durableResult); notifyVisibleOutboundSuccess(to, messageThreadId); return jsonResult({ ok: true, messageId: result.messageId, chatId: result.chatId }); } if (action === "poll") { const pollActionState = resolveTelegramPollActionGateState(isActionEnabled); if (!pollActionState.sendMessageEnabled) throw new Error("Telegram sendMessage is disabled."); if (!pollActionState.pollEnabled) throw new Error("Telegram polls are disabled."); const to = readStringParam(params, "to", { required: true }); const question = readStringParam(params, "question") ?? readStringParam(params, "pollQuestion", { required: true }); const answers = readStringArrayParam(params, "answers") ?? readStringArrayParam(params, "pollOption", { required: true }); const allowMultiselect = readBooleanParam(params, "allowMultiselect") ?? readBooleanParam(params, "pollMulti"); const durationSeconds = readPositiveIntegerParam(params, "durationSeconds", { message: "durationSeconds must be a positive integer." }) ?? readPositiveIntegerParam(params, "pollDurationSeconds", { message: "pollDurationSeconds must be a positive integer." }); const durationHours = readPositiveIntegerParam(params, "durationHours", { message: "durationHours must be a positive integer." }) ?? readPositiveIntegerParam(params, "pollDurationHours", { message: "pollDurationHours must be a positive integer." }); const replyToMessageId = readTelegramReplyToMessageId(params); const messageThreadId = readTelegramThreadId(params); const isAnonymous = readBooleanParam(params, "isAnonymous") ?? resolveTelegramPollVisibility({ pollAnonymous: readBooleanParam(params, "pollAnonymous"), pollPublic: readBooleanParam(params, "pollPublic") }); const silent = readBooleanParam(params, "silent"); const token = resolveTelegramToken(cfg, { accountId }).token; if (!token) throw new Error("Telegram bot token missing. Set TELEGRAM_BOT_TOKEN or channels.telegram.botToken."); const result = await telegramActionRuntime.sendPollTelegram(to, { question, options: answers, maxSelections: resolvePollMaxSelections(answers.length, allowMultiselect ?? false), durationSeconds: durationSeconds ?? void 0, durationHours: durationHours ?? void 0 }, { cfg, token, accountId: accountId ?? void 0, replyToMessageId: replyToMessageId ?? void 0, messageThreadId: messageThreadId ?? void 0, isAnonymous: isAnonymous ?? void 0, silent: silent ?? void 0, gatewayClientScopes: options?.gatewayClientScopes }); notifyVisibleOutboundSuccess(to, messageThreadId); return jsonResult({ ok: true, messageId: result.messageId, chatId: result.chatId, pollId: result.pollId }); } if (action === "deleteMessage") { if (!isActionEnabled("deleteMessage")) throw new Error("Telegram deleteMessage is disabled."); const chatId = readTelegramChatId(params); const messageId = readPositiveIntegerParam(params, "messageId", { message: "messageId must be a positive integer." }); if (messageId === void 0) throw new Error("messageId required"); const token = resolveTelegramToken(cfg, { accountId }).token; if (!token) throw new Error("Telegram bot token missing. Set TELEGRAM_BOT_TOKEN or channels.telegram.botToken."); const result = await telegramActionRuntime.deleteMessageTelegram(chatId ?? "", messageId ?? 0, { cfg, token, accountId: accountId ?? void 0, gatewayClientScopes: options?.gatewayClientScopes }); if (!result.ok) return jsonResult({ ok: false, deleted: false, warning: result.warning }); return jsonResult({ ok: true, deleted: true }); } if (action === "editMessage") { if (!isActionEnabled("editMessage")) throw new Error("Telegram editMessage is disabled."); const chatId = readTelegramChatId(params); const messageId = readPositiveIntegerParam(params, "messageId", { message: "messageId must be a positive integer." }); if (messageId === void 0) throw new Error("messageId required"); const content = readStringParam(params, "content", { allowEmpty: false }) ?? readStringParam(params, "message", { allowEmpty: false }); const caption = readStringParam(params, "caption", { allowEmpty: false }); const buttons = resolveTelegramButtonsFromParams(params); if (content == null && caption == null && buttons === void 0) throw new Error("content required."); if (buttons !== void 0) { if (resolveTelegramInlineButtonsScope({ cfg, accountId: accountId ?? void 0 }) === "off") throw new Error("Telegram inline buttons are disabled. Set channels.telegram.capabilities.inlineButtons to \"dm\", \"group\", \"all\", or \"allowlist\"."); } const token = resolveTelegramToken(cfg, { accountId }).token; if (!token) throw new Error("Telegram bot token missing. Set TELEGRAM_BOT_TOKEN or channels.telegram.botToken."); if (content == null && caption == null && buttons !== void 0) { const result = await telegramActionRuntime.editMessageReplyMarkupTelegram(chatId ?? "", messageId ?? 0, buttons, { cfg, token, accountId: accountId ?? void 0, gatewayClientScopes: options?.gatewayClientScopes }); return jsonResult({ ok: true, messageId: result.messageId, chatId: result.chatId }); } const result = await telegramActionRuntime.editMessageTelegram(chatId ?? "", messageId ?? 0, caption ?? content ?? "", { cfg, token, accountId: accountId ?? void 0, buttons, editMode: caption != null ? "caption" : "auto", gatewayClientScopes: options?.gatewayClientScopes }); return jsonResult({ ok: true, messageId: result.messageId, chatId: result.chatId }); } if (action === "sendSticker") { if (!isActionEnabled("sticker", false)) throw new Error("Telegram sticker actions are disabled. Set channels.telegram.actions.sticker to true."); const to = readStringParam(params, "to") ?? readStringParam(params, "target", { required: true }); const fileId = readStringParam(params, "fileId") ?? readStringArrayParam(params, "stickerId")?.[0]; if (!fileId) throw new Error("fileId is required."); const replyToMessageId = readTelegramReplyToMessageId(params); const messageThreadId = readTelegramThreadId(params); const token = resolveTelegramToken(cfg, { accountId }).token; if (!token) throw new Error("Telegram bot token missing. Set TELEGRAM_BOT_TOKEN or channels.telegram.botToken."); const result = await telegramActionRuntime.sendStickerTelegram(to, fileId, { cfg, token, accountId: accountId ?? void 0, replyToMessageId: replyToMessageId ?? void 0, messageThreadId: messageThreadId ?? void 0, gatewayClientScopes: options?.gatewayClientScopes }); notifyVisibleOutboundSuccess(to, messageThreadId); return jsonResult({ ok: true, messageId: result.messageId, chatId: result.chatId }); } if (action === "searchSticker") { if (!isActionEnabled("sticker", false)) throw new Error("Telegram sticker actions are disabled. Set channels.telegram.actions.sticker to true."); const query = readStringParam(params, "query", { required: true }); const limit = readPositiveIntegerParam(params, "limit", { message: "limit must be a positive integer." }) ?? 5; const results = telegramActionRuntime.searchStickers(query, limit); return jsonResult({ ok: true, count: results.length, stickers: results.map((s) => ({ fileId: s.fileId, emoji: s.emoji, description: s.description, setName: s.setName })) }); } if (action === "stickerCacheStats") return jsonResult({ ok: true, ...telegramActionRuntime.getCacheStats() }); if (action === "createForumTopic") { if (!isActionEnabled("createForumTopic")) throw new Error("Telegram createForumTopic is disabled."); const chatId = readTelegramChatId(params); const name = readStringParam(params, "name", { required: true }); const iconColor = readTelegramForumTopicIconColor(params); const iconCustomEmojiId = readStringParam(params, "iconCustomEmojiId"); const token = resolveTelegramToken(cfg, { accountId }).token; if (!token) throw new Error("Telegram bot token missing. Set TELEGRAM_BOT_TOKEN or channels.telegram.botToken."); const result = await telegramActionRuntime.createForumTopicTelegram(chatId ?? "", name, { cfg, token, accountId: accountId ?? void 0, iconColor, iconCustomEmojiId: iconCustomEmojiId ?? void 0, gatewayClientScopes: options?.gatewayClientScopes }); if (result.topicId != null && result.chatId) await updateTopicName(result.chatId, result.topicId, { name, ...iconColor != null ? { iconColor } : {}, ...iconCustomEmojiId ? { iconCustomEmojiId } : {} }, resolveActionTopicNameCacheScope(cfg, accountId)).catch(() => {}); return jsonResult({ ok: true, topicId: result.topicId, name: result.name, chatId: result.chatId }); } if (action === "editForumTopic") { if (!isActionEnabled("editForumTopic")) throw new Error("Telegram editForumTopic is disabled."); const chatId = readTelegramChatId(params); const messageThreadId = readTelegramThreadId(params); if (typeof messageThreadId !== "number") throw new Error("messageThreadId or threadId is required."); const name = readStringParam(params, "name"); const iconCustomEmojiId = readStringParam(params, "iconCustomEmojiId"); const token = resolveTelegramToken(cfg, { accountId }).token; if (!token) throw new Error("Telegram bot token missing. Set TELEGRAM_BOT_TOKEN or channels.telegram.botToken."); const result = await telegramActionRuntime.editForumTopicTelegram(chatId ?? "", messageThreadId, { cfg, token, accountId: accountId ?? void 0, name: name ?? void 0, iconCustomEmojiId: iconCustomEmojiId ?? void 0, gatewayClientScopes: options?.gatewayClientScopes }); if (result.chatId) { const patch = {}; if (name) patch.name = name; if (iconCustomEmojiId) patch.iconCustomEmojiId = iconCustomEmojiId; if (Object.keys(patch).length > 0) await updateTopicName(result.chatId, result.messageThreadId, patch, resolveActionTopicNameCacheScope(cfg, accountId)).catch(() => {}); } return jsonResult(result); } throw new Error(`Unsupported Telegram action: ${String(action)}`); } //#endregion export { handleTelegramAction, telegramActionRuntime };