From 88995f3c5dae576a3c1fec8b874b684ec43821b2 Mon Sep 17 00:00:00 2001 From: Walter Date: Fri, 30 Jan 2026 12:55:13 +0800 Subject: [PATCH] feat(telegram): add topic name support for forum topics - Add 'name' field to TelegramTopicConfig for human-readable topic names - Update buildGroupLabel to display topic name instead of just ID when configured - Add TopicName field to MsgContext for agent visibility - Update Zod schema for config validation This allows users to configure meaningful names for Telegram forum topics: channels: telegram: groups: "-1234567890": topics: "37": name: "General Discussion" The agent will now see 'topic:General Discussion' instead of 'topic:37' in the conversation context. --- src/auto-reply/templating.ts | 2 ++ src/config/types.telegram.ts | 2 ++ src/config/zod-schema.providers-core.ts | 1 + src/telegram/bot-message-context.ts | 6 +++++- src/telegram/bot/helpers.ts | 9 ++++++++- 5 files changed, 18 insertions(+), 2 deletions(-) diff --git a/src/auto-reply/templating.ts b/src/auto-reply/templating.ts index 1e07f6a32..47aed376e 100644 --- a/src/auto-reply/templating.ts +++ b/src/auto-reply/templating.ts @@ -103,6 +103,8 @@ export type MsgContext = { CommandTargetSessionKey?: string; /** Thread identifier (Telegram topic id or Matrix thread event id). */ MessageThreadId?: string | number; + /** Topic name from config (Telegram forum topics). */ + TopicName?: string; /** Telegram forum supergroup marker. */ IsForum?: boolean; /** diff --git a/src/config/types.telegram.ts b/src/config/types.telegram.ts index 9a96bce45..820b61473 100644 --- a/src/config/types.telegram.ts +++ b/src/config/types.telegram.ts @@ -133,6 +133,8 @@ export type TelegramAccountConfig = { }; export type TelegramTopicConfig = { + /** Human-readable name for this topic (displayed in conversation context). */ + name?: string; requireMention?: boolean; /** If specified, only load these skills for this topic. Omit = all skills; empty = no skills. */ skills?: string[]; diff --git a/src/config/zod-schema.providers-core.ts b/src/config/zod-schema.providers-core.ts index ed7dda22a..6029d11e0 100644 --- a/src/config/zod-schema.providers-core.ts +++ b/src/config/zod-schema.providers-core.ts @@ -37,6 +37,7 @@ const TelegramCapabilitiesSchema = z.union([ export const TelegramTopicSchema = z .object({ + name: z.string().optional(), requireMention: z.boolean().optional(), skills: z.array(z.string()).optional(), enabled: z.boolean().optional(), diff --git a/src/telegram/bot-message-context.ts b/src/telegram/bot-message-context.ts index 9696e4f1b..7f6cc9ebc 100644 --- a/src/telegram/bot-message-context.ts +++ b/src/telegram/bot-message-context.ts @@ -495,7 +495,9 @@ export const buildTelegramMessageContext = async ({ forwardOrigin.date ? ` at ${new Date(forwardOrigin.date * 1000).toISOString()}` : "" }]\n` : ""; - const groupLabel = isGroup ? buildGroupLabel(msg, chatId, resolvedThreadId) : undefined; + const groupLabel = isGroup + ? buildGroupLabel(msg, chatId, resolvedThreadId, topicConfig?.name) + : undefined; const senderName = buildSenderName(msg); const conversationLabel = isGroup ? (groupLabel ?? `group:${chatId}`) @@ -605,6 +607,8 @@ export const buildTelegramMessageContext = async ({ CommandAuthorized: commandAuthorized, // For groups: use resolvedThreadId (forum topics only); for DMs: use raw messageThreadId MessageThreadId: isGroup ? resolvedThreadId : messageThreadId, + // Topic name from config (if configured) + TopicName: isGroup && resolvedThreadId != null ? topicConfig?.name : undefined, IsForum: isForum, // Originating channel for reply routing. OriginatingChannel: "telegram" as const, diff --git a/src/telegram/bot/helpers.ts b/src/telegram/bot/helpers.ts index cd57392c0..771a585fc 100644 --- a/src/telegram/bot/helpers.ts +++ b/src/telegram/bot/helpers.ts @@ -106,9 +106,16 @@ export function buildGroupLabel( msg: TelegramMessage, chatId: number | string, messageThreadId?: number, + topicName?: string, ) { const title = msg.chat?.title; - const topicSuffix = messageThreadId != null ? ` topic:${messageThreadId}` : ""; + // Include topic name if available, otherwise just show topic ID + const topicSuffix = + messageThreadId != null + ? topicName + ? ` topic:${topicName}` + : ` topic:${messageThreadId}` + : ""; if (title) return `${title} id:${chatId}${topicSuffix}`; return `group:${chatId}${topicSuffix}`; }