fix(telegram): fix streaming with extended thinking models overwriting previous messages/ also happens to Execution error#17973
Merged
obviyus merged 5 commits intoFeb 16, 2026
Conversation
Comment on lines
+174
to
+178
| const forceNewMessage = () => { | ||
| streamMessageId = undefined; | ||
| lastSentText = ""; | ||
| pendingText = ""; | ||
| }; |
Contributor
There was a problem hiding this comment.
stopped flag not reset
forceNewMessage() resets streamMessageId, lastSentText, and pendingText, but does not reset the stopped flag. If the stream was previously stopped (e.g., text exceeded 4096 chars or an API error occurred), subsequent update() calls after forceNewMessage() will silently no-op because update() checks stopped first at line 150. Consider also resetting stopped = false here so the stream can resume after a buffer reset.
Suggested change
| const forceNewMessage = () => { | |
| streamMessageId = undefined; | |
| lastSentText = ""; | |
| pendingText = ""; | |
| }; | |
| const forceNewMessage = () => { | |
| streamMessageId = undefined; | |
| lastSentText = ""; | |
| pendingText = ""; | |
| stopped = false; | |
| }; |
Prompt To Fix With AI
This is a comment left during a code review.
Path: src/telegram/draft-stream.ts
Line: 174:178
Comment:
**`stopped` flag not reset**
`forceNewMessage()` resets `streamMessageId`, `lastSentText`, and `pendingText`, but does not reset the `stopped` flag. If the stream was previously stopped (e.g., text exceeded 4096 chars or an API error occurred), subsequent `update()` calls after `forceNewMessage()` will silently no-op because `update()` checks `stopped` first at line 150. Consider also resetting `stopped = false` here so the stream can resume after a buffer reset.
```suggestion
const forceNewMessage = () => {
streamMessageId = undefined;
lastSentText = "";
pendingText = "";
stopped = false;
};
```
How can I resolve this? If you propose a fix, please make it concise.489236e to
fa63a74
Compare
418815b to
58c5405
Compare
eb736bd to
4802017
Compare
23693af to
50ca6cb
Compare
… message starts When using extended thinking models with Telegram streaming, text output after a thinking block was overwriting the previous message instead of creating a new one. Root cause: The draft stream kept editing the same message because streamMessageId was never reset after reasoning completed. Fix: 1. Add forceNewMessage() to TelegramDraftStream that resets internal state 2. Add onReasoningEnd callback that fires when </think> tag is processed 3. Add onAssistantMessageStart callback exposure through ReplyOptions 4. When either callback fires AND we've already streamed content, call forceNewMessage() to ensure the next output creates a new message This covers two scenarios: - Tool call followed by new assistant message (onAssistantMessageStart) - Thinking block within same message (onReasoningEnd) Tests added: - forces new message when new assistant message starts after previous output - does not force new message on first assistant message start - forces new message when reasoning ends after previous output - does not force new message on reasoning end without previous output - creates new message after forceNewMessage is called (draft-stream.test.ts) Fixes openclaw#17935
…iting When a tool execution fails, the error payload would previously overwrite the streaming preview message, hiding the original response text. Changes: 1. Error payloads (isError: true) skip preview edit path 2. onAssistantMessageStart forces new message after tool calls 3. onReasoningEnd forces new message after thinking blocks This ensures thinking, text, and errors appear as separate messages. Added test: error payloads not editing preview messages
… blocks) Extended thinking from API (thinking content blocks) wasn't triggering onReasoningEnd because it doesn't go through </think> tag processing. This caused reasoning to be displayed briefly then overwritten by the final reply in draft streaming mode. Now we explicitly call onReasoningEnd in handleAssistantMessageEnd when reasoning came from API blocks (extended thinking), while avoiding double-calling when using <think> tags which already trigger it.
…ing (API blocks)" This reverts commit 3f8fc4d0c38ccca1fab836d55390073e475d9023.
50ca6cb to
34b52ee
Compare
Contributor
This was referenced Feb 16, 2026
Closed
6 tasks
archerhpagent
pushed a commit
to howardpark/openclaw
that referenced
this pull request
Feb 18, 2026
…g previous messages/ also happens to Execution error (openclaw#17973) Merged via /review-pr -> /prepare-pr -> /merge-pr. Prepared head SHA: 34b52ee Co-authored-by: Marvae <11957602+Marvae@users.noreply.github.com> Co-authored-by: obviyus <22031114+obviyus@users.noreply.github.com> Reviewed-by: @obviyus
18 tasks
lovewanwan
pushed a commit
to lovewanwan/openclaw
that referenced
this pull request
Apr 28, 2026
…g previous messages/ also happens to Execution error (openclaw#17973) Merged via /review-pr -> /prepare-pr -> /merge-pr. Prepared head SHA: 34b52ee Co-authored-by: Marvae <11957602+Marvae@users.noreply.github.com> Co-authored-by: obviyus <22031114+obviyus@users.noreply.github.com> Reviewed-by: @obviyus
ogt-redknie
pushed a commit
to ogt-redknie/OPENX
that referenced
this pull request
May 2, 2026
…g previous messages/ also happens to Execution error (openclaw#17973) Merged via /review-pr -> /prepare-pr -> /merge-pr. Prepared head SHA: 34b52ee Co-authored-by: Marvae <11957602+Marvae@users.noreply.github.com> Co-authored-by: obviyus <22031114+obviyus@users.noreply.github.com> Reviewed-by: @obviyus
github-actions Bot
pushed a commit
to Desicool/openclaw
that referenced
this pull request
May 9, 2026
…g previous messages/ also happens to Execution error (openclaw#17973) Merged via /review-pr -> /prepare-pr -> /merge-pr. Prepared head SHA: 34b52ee Co-authored-by: Marvae <11957602+Marvae@users.noreply.github.com> Co-authored-by: obviyus <22031114+obviyus@users.noreply.github.com> Reviewed-by: @obviyus
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Fix for Telegram streaming with extended thinking models overwriting previous messages. Execution error will also ovrrerwritng normal message. Manually tested.
Close: #17935 #17883
Problem
When using extended thinking models (e.g. Claude Opus) with Telegram streaming enabled, text output after a thinking block overwrites the previous message instead of creating a new one.
An alternative solution is to provide an option for user to decide, some app like chatGPT or gemini, only shows think process before reply.
Root Cause
The draft stream kept editing the same message because
streamMessageIdwas never reset after a streaming buffer reset. This reset happens when the new partial text is not a continuation of the previous text (e.g., after a thinking block ends).Fix
forceNewMessage()method toTelegramDraftStreamthat resets internal state (streamMessageId,lastSentText,pendingText)forceNewMessage()inbot-message-dispatch.tswhen a streaming buffer reset is detectedChanges
src/telegram/draft-stream.ts: AddforceNewMessage()methodsrc/telegram/bot-message-dispatch.ts: CallforceNewMessage()on buffer resetsrc/telegram/draft-stream.test.ts: Add test case forforceNewMessage()Testing
forceNewMessage()causes a new message to be sentAI usage
Greptile Summary
This PR fixes Telegram streaming with extended thinking models by forcing a new message when a streaming buffer reset is detected (e.g., after a thinking block ends). Previously, the draft stream kept editing the same message because
streamMessageIdwas never cleared on buffer reset.forceNewMessage()toTelegramDraftStreamthat resetsstreamMessageId,lastSentText, andpendingTextforceNewMessage()in the buffer reset branch ofupdateDraftFromPartialinbot-message-dispatch.tsforceNewMessage()causes a newsendMessagecall instead of editing the existing messageConfidence Score: 4/5
stoppedflag, which could prevent streaming from resuming in edge cases where the stream was previously stopped. This is unlikely to cause issues in the primary thinking-block scenario but is worth addressing for completeness.src/telegram/draft-stream.ts— consider whetherstoppedshould also be reset inforceNewMessage().Last reviewed commit: b974057