Skip to content

fix(telegram): honour reply_to_mode="off" in DM topic fallback path#24060

Closed
KenjiChao wants to merge 1 commit into
NousResearch:mainfrom
KenjiChao:fix/telegram-reply-to-mode-off-respects-dm-topics
Closed

fix(telegram): honour reply_to_mode="off" in DM topic fallback path#24060
KenjiChao wants to merge 1 commit into
NousResearch:mainfrom
KenjiChao:fix/telegram-reply-to-mode-off-respects-dm-topics

Conversation

@KenjiChao

Copy link
Copy Markdown

Problem

Since b323957 ("fix(telegram): preserve DM topic routing via reply fallback"), the telegram.reply_to_mode = "off" user setting has been silently ignored whenever the user has DM topics configured (platforms.telegram.extra.dm_topics). Every bot reply gets a quote bubble of the user's message attached, even though the user explicitly opted out.

The DM-topic-fallback path in send(), _reply_to_message_id_for_send, and _thread_kwargs_for_send unconditionally injects reply_to_message_id so the message visually lands in the right private-chat "topic" (Telegram DMs don't have native forum topics — Hermes fakes them via reply chains). That override breaks the user preference.

Reproduction:

# ~/.hermes/config.yaml
telegram:
  reply_to_mode: "off"
platforms:
  telegram:
    extra:
      dm_topics:
        - chat_id: <your-id>
          topics:
            - name: Daily chat
              thread_id: <thread-id>

→ Every bot reply still attaches a quote bubble of the user's message.

Fix

When reply_to_mode == "off", skip the reply anchor and rely on message_thread_id alone for DM-topic routing. Verified live on python-telegram-bot's reference client — messages still land in the correct private topic, quote bubble gone.

Two private helpers (_reply_to_message_id_for_send, _thread_kwargs_for_send) become instance methods (were @classmethod) so they can read self._reply_to_mode. All call sites already use self.xxx(...) — no caller changes needed.

Trade-off

b323957's commit message notes "either parameter alone can render outside the visible lane" on some clients. In practice on python-telegram-bot's reference client message_thread_id alone is sufficient. If a client genuinely needs the reply anchor for routing, users can keep reply_to_mode = "first" (the default) — only users who explicitly opt out are affected by this change.

Tests

New TestDmTopicReplyFallback class in tests/gateway/test_telegram_reply_mode.py:

  • mode=off drops the implicit DM-topic reply anchor
  • mode=first / mode=all keep it (existing behavior preserved)
  • mode=off honours an explicitly provided reply_to (media reply path)
  • thread kwargs emit message_thread_id alone under mode=off
  • end-to-end send() verifies no quote bubble, topic still routed
  • regression guard for the b323957 DM-topic-anchor behavior
$ pytest tests/gateway/test_telegram_reply_mode.py tests/gateway/test_telegram_thread_fallback.py
72 passed in 5.08s

Also verified live in production DM topic for ~30 minutes — quote bubbles gone, no message lost to wrong topic.

Since b323957 ("fix(telegram): preserve DM topic routing via reply
fallback"), the `telegram.reply_to_mode = "off"` user setting has been
silently ignored whenever the user has DM topics configured
(`platforms.telegram.extra.dm_topics`). Every bot reply gets a quote
bubble of the user's message attached, even though the user explicitly
opted out.

The DM-topic-fallback path in `send()`, `_reply_to_message_id_for_send`,
and `_thread_kwargs_for_send` unconditionally injected
`reply_to_message_id` so the message would visually land in the right
private-chat "topic" (Telegram DMs don't have native forum topics —
Hermes fakes them via reply chains). That overrode the user preference.

Fix: when `reply_to_mode == "off"`, skip the reply anchor and rely on
`message_thread_id` alone for DM-topic routing. Verified live on
python-telegram-bot's reference client — messages still land in the
correct private topic, quote bubble gone.

Two private helpers (`_reply_to_message_id_for_send`,
`_thread_kwargs_for_send`) become instance methods (were @classmethod)
so they can read `self._reply_to_mode`. All call sites already use
`self.xxx(...)` — no caller changes needed.

Tests added under `TestDmTopicReplyFallback`:
  - mode=off drops the implicit DM-topic reply anchor
  - mode=first / mode=all keep it (existing behavior preserved)
  - mode=off honours an explicitly provided reply_to (media reply path)
  - thread kwargs emit message_thread_id alone under mode=off
  - end-to-end send() verifies no quote bubble, topic still routed
  - regression guard for the b323957 DM-topic-anchor behavior

Trade-off: b323957's commit message notes "either parameter alone can
render outside the visible lane" on some clients. In practice on
python-telegram-bot's reference client `message_thread_id` alone is
sufficient. If a client genuinely needs the reply anchor for routing,
users can keep `reply_to_mode = "first"` (the default) — only users who
explicitly opt out are affected.
@alt-glitch alt-glitch added type/bug Something isn't working P2 Medium — degraded but workaround exists comp/gateway Gateway runner, session dispatch, delivery platform/telegram Telegram bot adapter labels May 12, 2026
@alt-glitch

Copy link
Copy Markdown
Collaborator

Related: #24004 (competing fix for the same issue #23994 — both address reply_to_mode: 'off' being ignored in DM topic fallback path, touching the same files).

@teknium1

Copy link
Copy Markdown
Contributor

Closing in favor of #24004 — both fix the same bug (reply_to_mode: off ignored by DM-topic reply fallback path introduced in b3239572f). #24004 was submitted first, has a slightly more thorough writeup of the bypass through _reply_to_message_id_for_send() and _thread_kwargs_for_send(), and similar diff size. Same fix overall. Thanks for the parallel work.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

comp/gateway Gateway runner, session dispatch, delivery P2 Medium — degraded but workaround exists platform/telegram Telegram bot adapter type/bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants