#21346: [AI-assisted] Telegram: add reaction state machine with fallback and cleanup
channel: telegram
size: M
Cluster:
Reaction Event Handling Enhancements
## Summary
This PR adds a Telegram-side status reaction state machine with compatibility fallbacks and cleanup on completion.
For Telegram message processing, the bot now transitions reaction states through:
- queued
- thinking
- tool execution
- done / error
It also clears the reaction after response completion, so reactions do not linger on user messages.
## Why
In Telegram DM/group usage, status visibility was limited (often only initial 👀), and reactions could remain after completion.
This change improves UX by:
- showing clearer progress states during execution
- handling emoji compatibility limits in Telegram via fallback candidates
- cleaning reactions after final reply
## What Changed
### `src/telegram/bot-message-dispatch.ts`
- Added Telegram status reaction controller with phase transitions.
- Switched from single emoji to ordered fallback emoji candidates per state.
- Added terminal hold windows (`done` / `error`) and explicit reaction cleanup (`[]`) after completion.
- Kept behavior gated to existing reaction capability path.
### `src/telegram/bot-message-dispatch.test.ts`
- Added/updated tests for:
- queued -> thinking -> tool -> done flow
- error flow
- disabled-ack path (no status reactions)
- terminal cleanup call (`setMessageReaction(..., [])`)
## Behavior Notes
- If a Telegram chat does not accept a preferred emoji for a state, the controller automatically tries fallback emojis.
- After completion (success or failure), reaction is cleared to avoid stale status.
- Existing draft streaming behavior remains unchanged.
## Testing
### Automated
- `pnpm vitest run --config vitest.unit.config.ts src/telegram/bot-message-dispatch.test.ts`
- Result: 17 passed / 17 total
### Manual
- Verified in local Telegram runtime:
- status reactions appear during processing
- reactions are removed after bot reply
## Scope
Focused change in Telegram dispatch only:
- no schema/API changes
- no unrelated subsystem refactors
## AI Assistance Disclosure
- [x] Marked as AI-assisted in title/description
- [x] Degree of testing noted (lightly tested)
- [ ] Prompts/session logs attached
- [x] Confirmed understanding of changed code paths
<!-- greptile_comment -->
<h3>Greptile Summary</h3>
adds telegram reaction state machine with queued → thinking → tool → done/error transitions, fallback emoji support for compatibility, and automatic cleanup after completion. improves UX by showing clearer progress states during bot execution.
**major changes:**
- new `createTelegramStatusReactionController` manages reaction lifecycle with promise chaining
- emoji fallback arrays per state (thinking, tool, coding, web, done, error) with 👀 as universal fallback
- tool-specific emoji selection based on tool name tokens (web_search → 🌐, bash → 💻, etc.)
- terminal states hold for 1.2s (done) or 1.8s (error) before cleanup
- reaction cleanup in finally block ensures removal after completion or error
**found issues:**
- fallback logic has edge case where early return can skip preferred emojis when current emoji appears later in fallback list
<h3>Confidence Score: 4/5</h3>
- safe to merge with one logical edge case in fallback emoji handling
- comprehensive test coverage (17 passing tests including state transitions, error handling, and disabled-ack path), well-structured state machine with clear separation of concerns, but contains minor fallback logic issue where early return can skip preferred emoji attempts if activeEmoji matches a later fallback candidate. implementation is sound overall with proper error handling and promise chaining. no security concerns, no breaking changes, focused scope limited to telegram dispatch only.
- pay attention to `src/telegram/bot-message-dispatch.ts` lines 117-118 for the fallback logic edge case
<sub>Last reviewed commit: 8a61d47</sub>
<!-- greptile_other_comments_section -->
<sub>(2/5) Greptile learns from your feedback when you react with thumbs up/down!</sub>
<!-- /greptile_comment -->
Most Similar PRs
#7980: feat(telegram): multi-stage reaction system for message pipeline vi...
by macmimi23 · 2026-02-03
84.8%
#20236: fix(telegram): make reaction handling soft-fail and message-id resi...
by PeterShanxin · 2026-02-18
84.0%
#23728: fix(telegram): clear done reaction when removeAckAfterReply is true
by kevinWangSheng · 2026-02-22
82.7%
#17316: fix: ack reaction not removed when block streaming is enabled (Tele...
by czmathew · 2026-02-15
80.7%
#22331: Fix Telegram reaction emoji normalization
by AIflow-Labs · 2026-02-21
80.6%
#19213: Telegram: preserve DM topic thread in direct replies
by Kemalau · 2026-02-17
80.2%
#20860: feat(reactions): add configurable immediate reaction dispatch system
by davidrudduck · 2026-02-19
79.3%
#17953: fix(telegram): prevent silent message loss and duplicate messages i...
by zuyan9 · 2026-02-16
78.8%
#19816: feat(slack): add typingReaction config for DM typing indicator fall...
by dalefrieswthat · 2026-02-18
78.0%
#6790: Messages: randomize ack reactions
by ihciah · 2026-02-02
77.5%