fix(telegram): flush buffered final answer when reasoning delivery is skipped [AI-assisted]#53762
fix(telegram): flush buffered final answer when reasoning delivery is skipped [AI-assisted]#53762amitgaur wants to merge 2 commits into
Conversation
Greptile SummaryThis PR fixes a silent message-loss bug in the Telegram integration where, after a tool call in a Root cause: The segment delivery loop in Fix: A single Test: A focused regression test reproduces the exact two-turn tool-boundary scenario — Turn 1 finalises reasoning lifecycle to Key changes:
Confidence Score: 5/5
Reviews (1): Last reviewed commit: "fix(telegram): flush buffered final answ..." | Re-trigger Greptile |
Code reviewNo issues found. Checked for bugs and CLAUDE.md compliance. 🤖 Generated with Claude Code - If this code review was useful, please react with 👍. Otherwise, react with 👎. |
7ea0c67 to
b4bc5b7
Compare
b4bc5b7 to
38d385d
Compare
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 38d385d658
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
| if (info.kind === "final") { | ||
| await flushBufferedFinalAnswer(); | ||
| } |
There was a problem hiding this comment.
Emit message-sent hook when flushing buffered final answers
The new final-segment early-return branch calls flushBufferedFinalAnswer() and then exits, but this flush path drops the deliverLaneText result and never runs emitPreviewFinalizedHook(...) when the buffered answer is finalized via preview edit. In streaming: "partial" flows with sessionKeyForInternalHooks, the user gets the Telegram answer, but the internal message:sent hook is skipped for that turn, unlike the normal segment-delivery path.
Useful? React with 👍 / 👎.
38d385d to
b25e563
Compare
|
Rebased onto the latest
Result: This PR is now mergeable and ready for maintainer review. Relevant reviewers for this area appear to be @vincentkoc and @obviyus. |
|
This pull request has been automatically marked as stale due to inactivity. |
|
Thanks for the context here. I swept through the related work, and this is now duplicate or superseded. This PR has the right visible Telegram fix direction, but it is superseded by the open hook-preserving replacement at #83670, which carries the same final-answer flush plus the missing hook/transcript preservation. Canonical path: Close this branch and review or land the hook-preserving replacement PR at #83670, or an equivalent patch with the same flush, hook, transcript, and regression coverage. So I’m closing this here and keeping the remaining discussion on #83670. Review detailsBest possible solution: Close this branch and review or land the hook-preserving replacement PR at #83670, or an equivalent patch with the same flush, hook, transcript, and regression coverage. Do we have a high-confidence way to reproduce the issue? Yes, from source inspection. Current main can buffer a final answer after a hinted/skipped reasoning segment and then return from the segmented-final branch without draining that buffer. Is this the best way to solve the issue? No, this branch is not the best merge target anymore. The missing flush is the right narrow fix, but the active replacement preserves the normal preview-finalized hook and transcript behavior too. Security review: Security review cleared: The diff only changes Telegram dispatch control flow, a colocated test, and changelog text; it adds no dependency, workflow, permission, secret, or supply-chain surface. What I checked:
Likely related people:
Codex review notes: model gpt-5.5, reasoning high; reviewed against 1c3ff34d752f. |
|
Codex review: found issues before merge. What this changes: This PR adds a Telegram dispatcher flush for buffered final-answer text before the segmented final-delivery early return, adds a regression test for skipped reasoning after a tool boundary, and adds a changelog fix entry. Maintainer follow-up before merge: This is already an open implementation PR for a narrow, real Telegram message-loss bug, but it has a specific unresolved hook-preservation review finding and likely needs maintainer or author follow-up on the branch rather than a separate automated replacement branch. Review findings:
Review detailsBest possible solution: Land this PR or an equivalent Telegram-owned patch after Full review comments:
Overall correctness: patch is incorrect Acceptance criteria:
What I checked:
Likely related people:
Remaining risk / open question:
Codex review notes: model gpt-5.5, reasoning high; reviewed against e46dccb35374. |
|
Adding downstream behavior evidence from an R2/OpenClaw production-style droplet because this PR is the canonical fix path and #83616 was closed as a duplicate of it. Environment:
Observed failure mode before the patch:
After-fix proof:
Additional validation I ran while preparing #83616:
This is not a screenshot/recording, but it is after-fix evidence from a live Telegram outbound path, with private chat details redacted. |
|
I opened a hook-preserving replacement branch/PR here: #83670 Why: this keeps the same buffered-final-answer fix direction, but addresses the unresolved review finding on this PR. The replacement Validation on the replacement branch:
The R2 live Telegram proof remains here: #53762 (comment) |
|
ClawSweeper applied the proposed close for this PR.
|
Summary
streaming: "partial"is enabled for Telegram and the model produces a turn with both a thinking block and a text block after a tool call, OpenClaw silently drops the text block (fixes [Bug]: streaming: partial drops text block when assistant turn contains [thinking, text] #53384).flushBufferedFinalAnswer()call before the earlyreturnin the segment delivery loop (bot-message-dispatch.ts) wheninfo.kind === "final". A matching regression test was added.Change Type (select all)
Scope (select all touched areas)
Linked Issue/PR
Root Cause / Regression History (if applicable)
deliverPayload(bot-message-dispatch.ts) processes reasoning and answer segments from a final payload. When a prior turn setactivePreviewLifecycleByLane.reasoning = "complete"(because the answer segment processing at lines 678–683 sawreasoningLane.hasStreamedMessage = true), the reasoning delivery in the next turn returns"skipped"(lifecycle is "complete" → falls tosendPayloadwhich fails). When reasoning is skipped,noteReasoningDelivered()is never called, soreasoningStatusstays"hinted". The answer segment then hitsshouldBufferFinalAnswer() === trueand is buffered. The loop exits via theif (segments.length > 0) { return; }early-return without flushing the buffer.flushBufferedFinalAnswer()call was missing from this early-return path. It existed in thesuppressedReasoningOnlypath directly below (line 696) but not in the segment-processed path.suppressedReasoningOnlybranch already had the flush, making the omission in the segment branch the gap.Regression Test Plan (if applicable)
extensions/telegram/src/bot-message-dispatch.test.ts— "delivers final answer text when reasoning delivery is skipped in combined think-tag payload after tool boundary"onReasoningStreamthen delivers an answer-only final (marking reasoning lifecycle "complete"). AfteronAssistantMessageStart, Turn 2 delivers<think>…</think>answer. The reasoningsendPayloadis mocked to fail ({ delivered: false }), leaving the answer buffered. Without the fix the test fails (answer never delivered); with the fix it passes.User-visible / Behavior Changes
After a tool call in a Telegram conversation with
streaming: partialand a reasoning-capable model, the assistant's text reply will now be delivered instead of silently dropped.Security Impact (required)
Repro + Verification
Environment
streaming: "partial"channels.telegram.streaming: "partial",reasoningLevel: "stream"Steps
streaming: "partial"and a reasoning-capable model.Expected
Actual (before fix)
Evidence
Test fails before fix:
Test passes after fix:
Tests 1 passed (73)Human Verification (required)
bot-message-dispatchtests still pass;pnpm checkclean.noteReasoningDeliveredpath, not the skipped path).suppressedReasoningOnlypath (already had flush, unchanged).Review Conversations
Compatibility / Migration
Failure Recovery (if this breaks)
fix(telegram): flush buffered final answer when reasoning delivery is skipped.Risks and Mitigations
flushBufferedFinalAnswer()is now called even when the buffer is empty (it returns early iftakeBufferedFinalAnswer()returns undefined), so there is no functional risk for the normal (non-bug) path.flushBufferedFinalAnsweris a no-op when no answer is buffered.AI-Assisted PR Checklist
pnpm test:extension telegram(1020 passed),pnpm check,pnpm buildall greenreasoningStepState,activePreviewLifecycleByLane,flushBufferedFinalAnswer, anddeliverLaneTextcall chain