diff --git a/README.md b/README.md index cc7380273..af056f1be 100644 --- a/README.md +++ b/README.md @@ -152,7 +152,7 @@ In chat, send `/status` to see if the agent is reachable, how much context the s - Inbound contexts carry a `Surface` hint (e.g., `whatsapp`, `webchat`, `telegram`) for logging; replies still go back to the originating surface deterministically. - Every inbound message is wrapped for the agent as `[Surface FROM HOST/IP TIMESTAMP] body`: - WhatsApp: `[WhatsApp +15551234567 2025-12-09 12:34] …` - - Telegram: `[Telegram telegram:123456789 2025-12-09 12:34] …` +- Telegram: `[Telegram Ada Lovelace (@ada_bot) id:123456789 2025-12-09 12:34] …` - WebChat: `[WebChat my-mac.local 10.0.0.5 2025-12-09 12:34] …` This keeps the model aware of the transport, sender, host, and time without relying on implicit context. diff --git a/src/telegram/bot.test.ts b/src/telegram/bot.test.ts index e4282b1e6..c578f8fc4 100644 --- a/src/telegram/bot.test.ts +++ b/src/telegram/bot.test.ts @@ -53,6 +53,11 @@ describe("createTelegramBot", () => { chat: { id: 1234, type: "private" }, text: "hello world", date: 1736380800, // 2025-01-09T00:00:00Z + from: { + first_name: "Ada", + last_name: "Lovelace", + username: "ada_bot", + }, }; await handler({ message, @@ -62,7 +67,9 @@ describe("createTelegramBot", () => { expect(replySpy).toHaveBeenCalledTimes(1); const payload = replySpy.mock.calls[0][0]; - expect(payload.Body).toMatch(/^\[Telegram telegram:1234 2025-01-09 00:00]/); + expect(payload.Body).toMatch( + /^\[Telegram Ada Lovelace \(@ada_bot\) id:1234 2025-01-09 00:00]/, + ); expect(payload.Body).toContain("hello world"); }); }); diff --git a/src/telegram/bot.ts b/src/telegram/bot.ts index b9f86aaa6..3bc0b0394 100644 --- a/src/telegram/bot.ts +++ b/src/telegram/bot.ts @@ -104,7 +104,9 @@ export function createTelegramBot(opts: TelegramBotOptions) { const body = formatAgentEnvelope({ surface: "Telegram", - from: isGroup ? `group:${chatId}` : `telegram:${chatId}`, + from: isGroup + ? buildGroupLabel(msg, chatId) + : buildSenderLabel(msg, chatId), timestamp: msg.date ? msg.date * 1000 : undefined, body: rawBody, }); @@ -208,6 +210,25 @@ function buildSenderName(msg: TelegramMessage) { return name || undefined; } +function buildSenderLabel(msg: TelegramMessage, chatId: number | string) { + const name = buildSenderName(msg); + const username = msg.from?.username ? `@${msg.from.username}` : undefined; + let label = name; + if (name && username) { + label = `${name} (${username})`; + } else if (!name && username) { + label = username; + } + const idPart = `id:${chatId}`; + return label ? `${label} ${idPart}` : idPart; +} + +function buildGroupLabel(msg: TelegramMessage, chatId: number | string) { + const title = msg.chat?.title; + if (title) return `${title} id:${chatId}`; + return `group:${chatId}`; +} + function hasBotMention(msg: TelegramMessage, botUsername: string) { const text = (msg.text ?? msg.caption ?? "").toLowerCase(); if (text.includes(`@${botUsername}`)) return true;