#18072: fix(Telegram): usage footer not sent to Telegram when blockStreaming is enabled (#17832)
stale
size: M
trusted-contributor
Cluster:
Telegram Message Handling Fixes
## Summary
When `blockStreaming: true` is set, the usage footer (`/usage full` or `/usage tokens`) never gets sent to the channel. TUI shows it fine, but Telegram/Discord/etc don't.
Closes #17832
lobster-biscuit
## Root Cause
`buildReplyPayloads` in `agent-runner-payloads.ts` sets `replyPayloads` to `[]` when block streaming succeeded (via `shouldDropFinalPayloads`). Back in `agent-runner.ts`, the `replyPayloads.length === 0` early return fires before the usage footer computation — so `appendUsageLine` is never reached.
## Changes
- Before: usage footer computation happens after the empty-payloads early return — gets skipped when block streaming drops final payloads
- After: usage footer is computed before the early return; if payloads are empty but a footer exists, it's sent as a standalone payload
Only `agent-runner.ts` changed (code motion + 4 new lines at the early return).
## Tests
- `agent-runner.misc.runreplyagent.test.ts` — 4 new tests covering the block streaming + usage footer interaction:
- `responseUsage=full`: footer sent with session key
- `responseUsage=tokens`: footer sent without session key
- `responseUsage=off`: returns undefined, no footer
- zero usage: returns undefined, no footer
- All 4 fail before fix, pass after
- All 386 tests in `src/auto-reply/reply/` pass
<!-- greptile_comment -->
<h3>Greptile Summary</h3>
Fixes the bug where usage footers (`/usage full` or `/usage tokens`) were not sent to Telegram/Discord when `blockStreaming: true` is enabled. The fix moves the usage footer computation logic before the empty-payloads early return, allowing it to be sent as a standalone payload when block streaming drops final payloads.
- Moved usage footer computation (lines 421-446) to execute before the `replyPayloads.length === 0` check
- Added logic to send usage footer as standalone payload when block streaming succeeded but dropped final payloads (lines 450-451)
- Added 4 comprehensive tests covering all usage footer scenarios with block streaming enabled
<h3>Confidence Score: 5/5</h3>
- This PR is safe to merge with minimal risk
- The fix is a clean code motion that addresses the exact root cause described in the PR. The logic is moved from after the early return to before it, with a simple 4-line addition to handle the edge case. The change is well-tested with 4 new tests covering all scenarios (responseUsage=full/tokens/off, zero usage), and all 386 existing tests pass.
- No files require special attention
<sub>Last reviewed commit: 4917272</sub>
<!-- greptile_other_comments_section -->
<!-- /greptile_comment -->
Most Similar PRs
#22701: fix(reply): make usage footer reflect full turn usage and avoid tra...
by artwalker · 2026-02-21
80.5%
#14977: fix(telegram): remove ack reaction after block-streamed replies
by Diaspar4u · 2026-02-12
80.1%
#19673: fix(telegram): avoid starting streaming replies with only 1-2 words
by emanuelst · 2026-02-18
78.3%
#17953: fix(telegram): prevent silent message loss and duplicate messages i...
by zuyan9 · 2026-02-16
77.6%
#17316: fix: ack reaction not removed when block streaming is enabled (Tele...
by czmathew · 2026-02-15
77.4%
#19235: fix(telegram): tool error warnings no longer overwrite streamed rep...
by gatewaybuddy · 2026-02-17
76.0%
#8205: fix: flush followup messages incrementally
by hanxiao · 2026-02-03
75.9%
#18187: fix: tool summaries silently dropped when reasoningLevel is stream
by ayanesakura · 2026-02-16
75.2%
#19648: fix: suppress silent-reply partial tokens during streaming
by bradleypriest · 2026-02-18
75.0%
#18460: fix(telegram): send fallback when streamMode partial drops all mess...
by BinHPdev · 2026-02-16
74.9%