From 56efbce31ee0d0394afd3f548207d3b7ce69cd38 Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Fri, 16 Jan 2026 20:51:39 +0000 Subject: [PATCH] feat: enable telegram reaction notifications by default --- CHANGELOG.md | 1 + docs/channels/telegram.md | 6 +++--- docs/gateway/configuration.md | 1 + src/telegram/bot.test.ts | 31 +++++++++++++++++++++++++++++++ src/telegram/bot.ts | 4 ++-- 5 files changed, 38 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8dc1258f5..291feb3fa 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,7 @@ - CLI: set process titles to `clawdbot-` for clearer process listings. - CLI/macOS: sync remote SSH target/identity to config and let `gateway status` auto-infer SSH targets (ssh-config aware). - Telegram: scope inline buttons with allowlist default + callback gating in DMs/groups. +- Telegram: default reaction notifications to own. - Heartbeat: tighten prompt guidance + suppress duplicate alerts for 24h. (#980) — thanks @voidserf. - Repo: ignore local identity files to avoid accidental commits. (#1001) — thanks @gerardward2007. - Sessions/Security: add `session.dmScope` for multi-user DM isolation and audit warnings. (#948) — thanks @Alphonse-arianee. diff --git a/docs/channels/telegram.md b/docs/channels/telegram.md index e6c963a19..e50285aac 100644 --- a/docs/channels/telegram.md +++ b/docs/channels/telegram.md @@ -411,8 +411,8 @@ The agent sees reactions as **system notifications** in the conversation history **Configuration:** - `channels.telegram.reactionNotifications`: Controls which reactions trigger notifications - - `"off"` — ignore all reactions (default when not set) - - `"own"` — notify when users react to bot messages (best-effort; in-memory) + - `"off"` — ignore all reactions + - `"own"` — notify when users react to bot messages (best-effort; in-memory) (default) - `"all"` — notify for all reactions - `channels.telegram.reactionLevel`: Controls agent's reaction capability @@ -505,7 +505,7 @@ Provider options: - `channels.telegram.actions.reactions`: gate Telegram tool reactions. - `channels.telegram.actions.sendMessage`: gate Telegram tool message sends. - `channels.telegram.actions.deleteMessage`: gate Telegram tool message deletes. -- `channels.telegram.reactionNotifications`: `off | own | all` — control which reactions trigger system events (default: `off` when not set). +- `channels.telegram.reactionNotifications`: `off | own | all` — control which reactions trigger system events (default: `own` when not set). - `channels.telegram.reactionLevel`: `off | ack | minimal | extensive` — control agent's reaction capability (default: `minimal` when not set). Related global options: diff --git a/docs/gateway/configuration.md b/docs/gateway/configuration.md index e6e30a597..5b9a900fd 100644 --- a/docs/gateway/configuration.md +++ b/docs/gateway/configuration.md @@ -943,6 +943,7 @@ Set `channels.telegram.configWrites: false` to block Telegram-initiated config w breakPreference: "paragraph" // paragraph | newline | sentence }, actions: { reactions: true, sendMessage: true }, // tool action gates (false disables) + reactionNotifications: "own", // off | own | all mediaMaxMb: 5, retry: { // outbound retry policy attempts: 3, diff --git a/src/telegram/bot.test.ts b/src/telegram/bot.test.ts index 00098c1df..bed540797 100644 --- a/src/telegram/bot.test.ts +++ b/src/telegram/bot.test.ts @@ -2247,6 +2247,37 @@ describe("createTelegramBot", () => { expect(enqueueSystemEvent).not.toHaveBeenCalled(); }); + it("defaults reactionNotifications to own", async () => { + onSpy.mockReset(); + enqueueSystemEvent.mockReset(); + wasSentByBot.mockReturnValue(true); + + loadConfig.mockReturnValue({ + channels: { + telegram: { dmPolicy: "open" }, + }, + }); + + createTelegramBot({ token: "tok" }); + const handler = getOnHandler("message_reaction") as ( + ctx: Record, + ) => Promise; + + await handler({ + update: { update_id: 502 }, + messageReaction: { + chat: { id: 1234, type: "private" }, + message_id: 43, + user: { id: 9, first_name: "Ada" }, + date: 1736380800, + old_reaction: [], + new_reaction: [{ type: "emoji", emoji: "👍" }], + }, + }); + + expect(enqueueSystemEvent).toHaveBeenCalledTimes(1); + }); + it("allows reaction in all mode regardless of message sender", async () => { onSpy.mockReset(); enqueueSystemEvent.mockReset(); diff --git a/src/telegram/bot.ts b/src/telegram/bot.ts index 53755ec00..230684d85 100644 --- a/src/telegram/bot.ts +++ b/src/telegram/bot.ts @@ -322,8 +322,8 @@ export function createTelegramBot(opts: TelegramBotOptions) { const messageId = reaction.message_id; const user = reaction.user; - // Resolve reaction notification mode (default: "off") - const reactionMode = telegramCfg.reactionNotifications ?? "off"; + // Resolve reaction notification mode (default: "own") + const reactionMode = telegramCfg.reactionNotifications ?? "own"; if (reactionMode === "off") return; if (user?.is_bot) return; if (reactionMode === "own" && !wasSentByBot(chatId, messageId)) return;