fix(telegram): skip send_chat_action for DM topic reply-fallback lanes

The send path uses Hermes' reply-anchor fallback for DM topic lanes
(message_thread_id + reply_to_message_id), but send_chat_action only
accepts message_thread_id — Telegram's Bot API 10.0 rejects it for
these lanes. Without this short-circuit, every typing tick (~every 2s
during agent runs) makes a doomed API call that gets logged as a
'thread not found' debug warning. Skip the call entirely when the
metadata indicates a DM topic reply-fallback lane; the user-visible
behavior is unchanged (no typing indicator either way for these
lanes), but the logs stay clean.

Identified during salvage review of #22053.
This commit is contained in:
kshitijk4poor 2026-05-09 14:04:17 +05:30 committed by kshitij
parent b3239572f0
commit aef297a45e
2 changed files with 38 additions and 0 deletions

View file

@ -2860,6 +2860,14 @@ class TelegramAdapter(BasePlatformAdapter):
if self._bot: if self._bot:
try: try:
_typing_thread = self._metadata_thread_id(metadata) _typing_thread = self._metadata_thread_id(metadata)
# Skip the Bot API call entirely for Hermes-created DM topic
# lanes: send_chat_action only accepts message_thread_id, which
# Telegram's Bot API 10.0 rejects for these lanes. The send
# path uses the reply-anchor fallback instead, but typing has
# no equivalent — skipping avoids noisy "thread not found"
# debug logs on every typing tick.
if metadata and metadata.get("telegram_dm_topic_reply_fallback"):
return
message_thread_id = self._message_thread_id_for_typing(_typing_thread) message_thread_id = self._message_thread_id_for_typing(_typing_thread)
# No retry-without-thread fallback here: _message_thread_id_for_typing # No retry-without-thread fallback here: _message_thread_id_for_typing
# already maps the forum General topic to None, so any non-None value # already maps the forum General topic to None, so any non-None value

View file

@ -235,6 +235,36 @@ async def test_send_typing_does_not_fall_back_to_root_for_dm_topic():
] ]
@pytest.mark.asyncio
async def test_send_typing_skips_api_call_for_dm_topic_reply_fallback():
"""Hermes-created DM topic lanes have no working Bot API typing route.
``send_chat_action`` only accepts ``message_thread_id``, which Telegram's
Bot API 10.0 rejects for these lanes the call would silently fail and
log a "thread not found" warning every typing tick (every 2s). Skipping
the call entirely keeps logs clean while preserving the user-visible
behavior (no typing indicator either way for these lanes).
"""
adapter = _make_adapter()
call_log = []
async def mock_send_chat_action(**kwargs):
call_log.append(dict(kwargs))
adapter._bot = SimpleNamespace(send_chat_action=mock_send_chat_action)
await adapter.send_typing(
"12345",
metadata={
"thread_id": "20197",
"telegram_dm_topic_reply_fallback": True,
"telegram_reply_to_message_id": "462",
},
)
assert call_log == []
@pytest.mark.asyncio @pytest.mark.asyncio
async def test_send_retries_without_thread_on_thread_not_found(): async def test_send_retries_without_thread_on_thread_not_found():
"""When message_thread_id causes 'thread not found', retry without it.""" """When message_thread_id causes 'thread not found', retry without it."""