* test(telegram): add regression test for forum topic message_thread_id with streamed reasoning
After thorough code tracing of all delivery paths (draft stream, durable,
non-durable, preview hooks), the current main branch already correctly
passes message_thread_id through all paths for the streaming reasoning +
final answer scenario in forum topics. The bug reported in #89352 may have
been resolved by earlier merged changes (media-path preservation,
draft/progress streaming, etc.).
This commit adds a focused regression test covering the combined
scenario to prevent future regressions.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix(telegram): assert forum thread at draft-stream boundary for both lanes
---------
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Preserve shared reasoning suppression by default while letting Telegram opt into durable reasoning payloads only when it has a deliverable reasoning lane. Covers persistent /reasoning on, separate reasoning stream lanes, and progress-stream suppression.\n\nVerification:\n- node scripts/run-vitest.mjs src/auto-reply/reply/dispatch-from-config.test.ts extensions/telegram/src/bot-message-dispatch.test.ts\n- git diff --check upstream/main...HEAD\n- .agents/skills/autoreview/scripts/autoreview --mode branch --base upstream/main --stream-engine-output\n- CI run 28411526182 green, including QA Smoke CI and check-test-types\n- Real behavior proof run 28411676681 passed\n\nPR: #97875
When Telegram rejects a rich message with RICH_MESSAGE_*_INVALID
(e.g., RICH_MESSAGE_EMAIL_INVALID on /status replies), the delivery
path now falls back to a plain text sendMessage instead of dropping
the reply.
Fixes#96363
reactMessageTelegram and deleteMessageTelegram passed context: "send" to
isRecoverableTelegramNetworkError, which disables message-snippet matching
(allowMessageMatch defaults to false only for "send"). Both operations are
idempotent (setMessageReaction / deleteMessage are safe to repeat), yet a
transient snippet-only network error (e.g. "socket hang up", "undici network
error" with no error code) was not retried — stricter than polling/webhook/
unknown, which all default allowMessageMatch to true. Users saw spurious
reaction/delete failures on transient network errors.
Add delete | react to TelegramNetworkErrorContext (additive) and use them at
the two callers. The helper default (context !== "send") is unchanged, so
delete/react now match polling/webhook/unknown. sendMessage keeps "send".
Co-authored-by: Claude <noreply@anthropic.com>
Wake the isolated polling drain immediately after a worker-spooled
update is written to channel_ingress_events, instead of waiting for
the next drain interval.
- Add requestImmediateDrain() calls after worker write and spooled message
- Track pending drain requests while drain is active (fix race condition)
- Add regression test for updates arriving during active drain
Fixes#86957.