Skip to content

fix(cron): route Telegram forum topics via message_thread_id, gate DM-topic heuristic (#52060) - #52079

Closed
Tranquil-Flow wants to merge 1 commit into
NousResearch:mainfrom
Tranquil-Flow:fix/52060-cron-tg-forum-topic
Closed

fix(cron): route Telegram forum topics via message_thread_id, gate DM-topic heuristic (#52060)#52079
Tranquil-Flow wants to merge 1 commit into
NousResearch:mainfrom
Tranquil-Flow:fix/52060-cron-tg-forum-topic

Conversation

@Tranquil-Flow

Copy link
Copy Markdown
Contributor

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 cron deliver target is correct and last_status=ok; only the routing is wrong.

Root cause

The is_private_dm_topic heuristic added in #22773 synthesizes direct_messages_topic_id for any telegram:<positive_chat_id>:<numeric_thread_id> deliver target:

is_private_dm_topic = (
    platform == Platform.TELEGRAM
    and thread_id is not None
    and _looks_like_telegram_private_chat_id(str(chat_id))   # positive → True
    and _looks_like_int(str(thread_id))                       # numeric → True
)

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_id is placed in route_metadata, and the Telegram adapter nulls message_thread_id in response, causing the message to fall back to General.

Fix

Replace the inference heuristic with explicit-signal gating:

Putting thread_id directly in route_metadata (not just the DeliveryTarget) is deliberate: gateway/delivery.py private-chat topic detection demands a reply anchor when thread_id is absent from metadata. Cron deliveries have no inbound reply anchor, so the metadata key bypasses that check and lets the adapter route via a plain message_thread_id.

Tests

Regression tests added in tests/cron/test_scheduler.py:

Test Scenario Expected routing
test_live_adapter_forum_topic_in_private_chat_routes_via_message_thread_id Positive chat + numeric thread (forum) message_thread_id, no direct_messages_topic_id
test_live_adapter_forum_topic_media_routes_via_message_thread_id Same, media path thread_id in media metadata
test_live_adapter_explicit_dm_topic_routes_via_direct_messages_topic_id Explicit direct_messages_topic_id in origin direct_messages_topic_id routing
test_live_adapter_forum_thread_fallback_records_delivery_error Negative chat (supergroup forum) — unchanged fallback error path

All 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, no delivery.py changes.

…-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.
@alt-glitch alt-glitch added type/bug Something isn't working comp/cron Cron scheduler and job management comp/gateway Gateway runner, session dispatch, delivery platform/telegram Telegram bot adapter sweeper:risk-message-delivery Sweeper risk: may drop, duplicate, misroute, or suppress messages P2 Medium — degraded but workaround exists labels Jun 24, 2026
@kshitijk4poor

Copy link
Copy Markdown
Collaborator

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 target.get("direct_messages_topic_id") or origin.get("direct_messages_topic_id"), but no code path ever writes direct_messages_topic_id onto a cron job's origin or target (_origin_from_env in tools/cronjob_tools.py captures only platform/chat_id/chat_name/thread_id/user_id, and the deliver string carries no such key). So that branch was effectively dead — it fixed the forum-topic case by routing everything via message_thread_id, but dropped support for genuine Bot API channel Direct-Messages topics.

#58165 disambiguates with a real runtime signal instead: it probes the live adapter's get_chat_info() once at delivery time and routes via direct_messages_topic_id only when the chat is actually a channel, falling back to message_thread_id otherwise. That fixes your forum-topic regression and makes genuine channel DM-topic cron delivery work.

You're credited in the #58165 body. Closing this in favor of it — thanks again!

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

Labels

comp/cron Cron scheduler and job management comp/gateway Gateway runner, session dispatch, delivery P2 Medium — degraded but workaround exists platform/telegram Telegram bot adapter sweeper:risk-message-delivery Sweeper risk: may drop, duplicate, misroute, or suppress messages type/bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants