#19213: Telegram: preserve DM topic thread in direct replies
channel: telegram
size: S
Cluster:
Messaging Platform Improvements
## Summary
Describe the problem and fix in 2–5 bullets:
- Problem: Telegram DM topics lost thread context in several direct-reply paths, so replies could land in the main chat instead of the topic thread.
- Why it matters: users see broken conversation continuity and replies in the wrong place.
- What changed: preserved `message_thread_id` in callback fallback replies, pairing replies, and native-command auth/not-found replies; added regression tests.
- What did NOT change (scope boundary): no config schema changes, no behavior changes for non-topic DMs, no changes outside Telegram paths.
## Change Type (select all)
- [x] Bug fix
- [ ] Feature
- [ ] Refactor
- [ ] Docs
- [ ] Security hardening
- [ ] Chore/infra
## Scope (select all touched areas)
- [ ] Gateway / orchestration
- [ ] Skills / tool execution
- [ ] Auth / tokens
- [ ] Memory / storage
- [x] Integrations
- [ ] API / contracts
- [ ] UI / DX
- [ ] CI/CD / infra
## Linked Issue/PR
- Closes #19144
- Related #N/A
## User-visible / Behavior Changes
- Telegram DM topic replies now stay in the same topic thread for:
- callback fallback sends,
- pairing replies,
- native command unauthorized/not-found replies.
- None for non-topic DMs.
## Security Impact (required)
- New permissions/capabilities? (`No`)
- Secrets/tokens handling changed? (`No`)
- New/changed network calls? (`No`)
- Command/tool execution surface changed? (`No`)
- Data access scope changed? (`No`)
- If any `Yes`, explain risk + mitigation: `N/A`
## Repro + Verification
### Environment
- OS: Windows (local dev, PowerShell)
- Runtime/container: Node 22 + Vitest
- Model/provider: N/A
- Integration/channel (if any): Telegram (DM topics)
- Relevant config (redacted): `channels.telegram.dmPolicy=pairing` (test scenarios)
### Steps
1. Use Telegram DM with topic thread enabled.
2. Trigger one of: callback fallback, pairing response, or unauthorized native command response.
3. Observe where the bot message is posted.
### Expected
- Bot reply is posted in the same DM topic thread (`message_thread_id` preserved).
### Actual
- Before fix, some replies could be posted in the main DM chat (thread context lost).
## Evidence
Attach at least one:
- [ ] Failing test/log before + passing after
- [x] Trace/log snippets
- [ ] Screenshot/recording
- [ ] Perf numbers (if relevant)
Verification command and result:
`npx pnpm@10.23.0 exec vitest run src/telegram/bot.test.ts src/telegram/bot.create-telegram-bot.test.ts`
`Test Files: 2 passed, Tests: 93 passed`
## Human Verification (required)
What you personally verified (not just CI), and how:
- Verified scenarios: added and ran regression tests for callback fallback threading, pairing threading, and unauthorized native command threading in DM topics.
- Edge cases checked: non-topic DM behavior remains unchanged.
- What you did **not** verify: live manual Telegram E2E run against a real bot account.
## Compatibility / Migration
- Backward compatible? (`Yes`)
- Config/env changes? (`No`)
- Migration needed? (`No`)
- If yes, exact upgrade steps: `N/A`
## Failure Recovery (if this breaks)
- How to disable/revert this change quickly: revert commit `ae9dccc24`.
- Files/config to restore: `src/telegram/bot-handlers.ts`, `src/telegram/bot-message-context.ts`, `src/telegram/bot-native-commands.ts`, `src/telegram/bot.test.ts`, `src/telegram/bot.create-telegram-bot.test.ts`.
- Known bad symptoms reviewers should watch for: DM topic replies appearing in main chat, or new `message thread not found` errors in Telegram logs.
## Risks and Mitigations
List only real risks for this PR. Add/remove entries as needed. If none, write `None`.
- Risk: stale/invalid thread IDs from Telegram events could cause send failures in edge cases.
- Mitigation: existing Telegram send/retry behavior remains unchanged; scope is limited and covered by regression tests.
<!-- greptile_comment -->
<h3>Greptile Summary</h3>
This PR fixes a bug where Telegram DM topic thread context (`message_thread_id`) was lost in several reply paths, causing bot responses to land in the main chat instead of the correct topic thread. The fix applies the existing `buildTelegramThreadParams`/`resolveTelegramThreadSpec` helpers to three previously-missed code paths: callback fallback replies (model selection), pairing code replies, and native command auth/not-found responses.
- Callback fallback in `bot-handlers.ts`: `replyToCallbackChat` now resolves and merges thread params from `callbackMessage`, so fallback sends after failed edits stay in the correct DM topic.
- Pairing replies in `bot-message-context.ts`: `messageThreadParams` is computed from the thread spec and passed to `sendMessage` when sending pairing codes in DM topics.
- Native command responses in `bot-native-commands.ts`: Both the auth rejection (`sendAuthMessage`) and "command not found" paths now include thread params.
- Regression tests added for all three paths, verifying `message_thread_id` is preserved in the `sendMessage` call.
<h3>Confidence Score: 5/5</h3>
- This PR is safe to merge — it is a narrowly scoped, well-tested bug fix that only adds thread context to existing send paths.
- The changes are minimal and follow established patterns already used elsewhere in the codebase. The fix correctly uses existing helper functions (buildTelegramThreadParams, resolveTelegramThreadSpec) that are well-tested. The null/undefined fallback behavior is correct: non-topic DMs are unaffected since buildTelegramThreadParams returns undefined when there is no thread ID. Three regression tests cover the exact scenarios fixed. No config, schema, or behavioral changes for non-topic DMs.
- No files require special attention.
<sub>Last reviewed commit: f51c307</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
#17952: fix(telegram): support message_thread_id for DM topics
by timbrinded · 2026-02-16
90.5%
#17968: fix(telegram): restore DM topic thread ids with send-path fallback
by Leonccaa · 2026-02-16
89.3%
#3368: fix: sessions navigation, DM thread display, and DM thread delivery...
by Lukavyi · 2026-01-28
88.7%
#7261: fix(telegram): preserve DM topic thread id for outbound media
by ViffyGwaanl · 2026-02-02
88.1%
#14443: fix(telegram): skip General topic thread ID for all chat types (#14...
by lailoo · 2026-02-12
87.8%
#12936: fix(telegram): omit message_thread_id for private DM chats
by omair445 · 2026-02-09
87.0%
#8985: fix(telegram): preserve forum topic context for pairing auto-replies
by lailoo · 2026-02-04
85.8%
#6192: Telegram: fix DM Topics thread routing
by ViffyGwaanl · 2026-02-01
85.6%
#19050: fix(telegram): skip message_thread_id for private chats to prevent ...
by Limitless2023 · 2026-02-17
84.5%
#19274: feat(mattermost): enable threaded replies in channels
by rockinyp · 2026-02-17
83.9%