fix(cron): route Telegram forum topics via message_thread_id, gate DM-topic heuristic (#52060) - #52079
Conversation
…-topic heuristic (NousResearch#52060) The is_private_dm_topic heuristic added in NousResearch#22773 (commit 4cc28aa) synthesized direct_messages_topic_id for ANY telegram deliver target with a positive chat_id and numeric thread_id. This false positive mis-routed forum topics inside private chats to General — the adapter nulls message_thread_id whenever direct_messages_topic_id is present. Replace the inference heuristic with explicit-signal gating: route via direct_messages_topic_id only when the job origin/target explicitly carries that key. All other Telegram topic routing defaults to thread_id (message_thread_id), restoring pre-NousResearch#22773 parity and matching live reply routing. Putting thread_id in route_metadata bypasses delivery.py's private-chat reply-anchor demand, which cron deliveries cannot satisfy.
|
Thanks for reporting and diagnosing this (#52060) — your root-cause analysis was spot on. We went with a runtime-signal fix in #58165 rather than the explicit-key gate here. The gate in this PR keyed on #58165 disambiguates with a real runtime signal instead: it probes the live adapter's You're credited in the #58165 body. Closing this in favor of it — thanks again! |
What
Since #22773 (commit
4cc28aa3b), proactive cron deliveries to a Telegram forum topic inside a private chat land in General instead of the target thread. The crondelivertarget is correct andlast_status=ok; only the routing is wrong.Root cause
The
is_private_dm_topicheuristic added in #22773 synthesizesdirect_messages_topic_idfor anytelegram:<positive_chat_id>:<numeric_thread_id>deliver target:This shape matches both genuine Bot API Direct-Messages topics and regular forum topics inside private chats — the heuristic cannot distinguish them. When it fires,
direct_messages_topic_idis placed inroute_metadata, and the Telegram adapter nullsmessage_thread_idin response, causing the message to fall back to General.Fix
Replace the inference heuristic with explicit-signal gating:
direct_messages_topic_idonly when the job origin or target explicitly carries adirect_messages_topic_idkey.thread_id→message_thread_id— parity with pre-Cron delivery to private DM topics broken after PR #22410 — send_message_tool.py missing three-mode routing #22773 behavior and with live reply routing.Putting
thread_iddirectly inroute_metadata(not just theDeliveryTarget) is deliberate:gateway/delivery.pyprivate-chat topic detection demands a reply anchor whenthread_idis absent from metadata. Cron deliveries have no inbound reply anchor, so the metadata key bypasses that check and lets the adapter route via a plainmessage_thread_id.Tests
Regression tests added in
tests/cron/test_scheduler.py:test_live_adapter_forum_topic_in_private_chat_routes_via_message_thread_idmessage_thread_id, nodirect_messages_topic_idtest_live_adapter_forum_topic_media_routes_via_message_thread_idthread_idin media metadatatest_live_adapter_explicit_dm_topic_routes_via_direct_messages_topic_iddirect_messages_topic_idin origindirect_messages_topic_idroutingtest_live_adapter_forum_thread_fallback_records_delivery_errorAll tests fail on upstream/main (RED) and pass with the fix (GREEN). Full scheduler suite: 164 passed, 0 failures.
Scope
One logical change in
cron/scheduler.py— no new dependencies, nodelivery.pychanges.