fix(telegram): Fixed duplicate resend/delete behavior in partial streaming mode.#17766
fix(telegram): Fixed duplicate resend/delete behavior in partial streaming mode.#17766v8hid wants to merge 3 commits intoopenclaw:mainfrom
Conversation
…aming mode. Instead of trying to edit a preview message with identical content, finalize the existing preview in place. Editing with the same content can return a Telegram API error, which then triggers failover cleanup/send and may duplicate output. Retain final edit/send for real mutations (formatting pass, buttons, linkPreview) and add dispatch tests for each branch.
0da0427 to
665fbe8
Compare
|
Closing this PR because it looks dirty (too many unrelated commits). Please recreate the PR from a clean branch. |
24 similar comments
|
Closing this PR because it looks dirty (too many unrelated commits). Please recreate the PR from a clean branch. |
|
Closing this PR because it looks dirty (too many unrelated commits). Please recreate the PR from a clean branch. |
|
Closing this PR because it looks dirty (too many unrelated commits). Please recreate the PR from a clean branch. |
|
Closing this PR because it looks dirty (too many unrelated commits). Please recreate the PR from a clean branch. |
|
Closing this PR because it looks dirty (too many unrelated commits). Please recreate the PR from a clean branch. |
|
Closing this PR because it looks dirty (too many unrelated commits). Please recreate the PR from a clean branch. |
|
Closing this PR because it looks dirty (too many unrelated commits). Please recreate the PR from a clean branch. |
|
Closing this PR because it looks dirty (too many unrelated commits). Please recreate the PR from a clean branch. |
|
Closing this PR because it looks dirty (too many unrelated commits). Please recreate the PR from a clean branch. |
|
Closing this PR because it looks dirty (too many unrelated commits). Please recreate the PR from a clean branch. |
|
Closing this PR because it looks dirty (too many unrelated commits). Please recreate the PR from a clean branch. |
|
Closing this PR because it looks dirty (too many unrelated commits). Please recreate the PR from a clean branch. |
|
Closing this PR because it looks dirty (too many unrelated commits). Please recreate the PR from a clean branch. |
|
Closing this PR because it looks dirty (too many unrelated commits). Please recreate the PR from a clean branch. |
|
Closing this PR because it looks dirty (too many unrelated commits). Please recreate the PR from a clean branch. |
|
Closing this PR because it looks dirty (too many unrelated commits). Please recreate the PR from a clean branch. |
|
Closing this PR because it looks dirty (too many unrelated commits). Please recreate the PR from a clean branch. |
|
Closing this PR because it looks dirty (too many unrelated commits). Please recreate the PR from a clean branch. |
|
Closing this PR because it looks dirty (too many unrelated commits). Please recreate the PR from a clean branch. |
|
Closing this PR because it looks dirty (too many unrelated commits). Please recreate the PR from a clean branch. |
|
Closing this PR because it looks dirty (too many unrelated commits). Please recreate the PR from a clean branch. |
|
Closing this PR because it looks dirty (too many unrelated commits). Please recreate the PR from a clean branch. |
|
Closing this PR because it looks dirty (too many unrelated commits). Please recreate the PR from a clean branch. |
|
Closing this PR because it looks dirty (too many unrelated commits). Please recreate the PR from a clean branch. |
|
Rebased cleanly onto main — turns out merging main into a feature branch makes the bot think you're trying to smuggle 200 unrelated commits into your PR. Lesson learned. 2 clean commits now, as intended. |
Summary
message is not modified), which trigger failover cleanup/send and create duplicate visible messages plus producing error logs.lastAppliedText()tracking insrc/telegram/draft-stream.tsand used it insrc/telegram/bot-message-dispatch.tsto short-circuit unchanged final edits when no mutation is needed.linkPreview=false) and expanded tests insrc/telegram/draft-stream.test.tsandsrc/telegram/bot-message-dispatch.test.ts.Change Type
Scope (select all touched areas)
Related Fix
Note: Commit ac2ede5 by @steipete already treats
message is not modifiedAPI errors as success, which prevents the failover/duplicate behavior. This PR adds a complementary optimization that prevents the unnecessary API call from being attempted in the first place by trackinglastAppliedText()and short-circuiting when no edit is needed.Both fixes work together:
ac2ede5bb: Reactive safety net at the API error handling layerBoth fixes work together:
ac2ede5bb: Reactive safety net at the API error handling layerUser-visible / Behavior Changes
Security Impact (required)
No)No)No)No)No)Repro + Verification
Environment
channels.telegram.streamMode=partial,channels.telegram.blockStreaming=falseSteps
Expected
Actual
Evidence
Attach at least one:
Human Verification (required)
What you personally verified (not just CI), and how:
pnpm test src/telegram/bot-message-dispatch.test.ts(8/8 passing).src/telegram/bot-message-dispatch.test.ts:linkPreview=falsemutationFailure Recovery (if this breaks)
channels.telegram.streamMode=off.src/telegram/bot-message-dispatch.tssrc/telegram/draft-stream.tsGreptile Summary
This PR adds a proactive optimization to prevent unnecessary Telegram API calls when finalizing streamed messages. It tracks the last successfully applied text in draft streams and short-circuits final edits when the content hasn't changed, while preserving edits for legitimate mutations (markdown formatting, inline buttons,
linkPreviewsettings).Key changes:
lastAppliedText()method toTelegramDraftStreaminterface that tracks the last successfully applied text (stored only on successful API calls, not on failed edits)bot-message-dispatch.tsthat compares preview text with final text and skips edit when no changes or mutations are neededrenderTelegramHtmlText()to ensure markdown formatting passes still trigger editsThis complements commit ac2ede5 which treats
MESSAGE_NOT_MODIFIEDerrors as success at the API layer. Together they provide defense-in-depth: this PR prevents unnecessary calls, while ac2ede5 provides a safety net if they occur.Confidence Score: 5/5
lastAppliedTexttracking correctly distinguishes between attempted vs. successful edits, comprehensive test coverage validates all edge cases (formatting passes, button mutations, linkPreview changes), and the logic correctly handles the mismatch between plain-text draft previews and HTML-formatted final edits. The change is purely additive (early-return optimization) with no modification to existing success paths, and it works in tandem with existing error handling (ac2ede5) for defense-in-depth.Last reviewed commit: 8a34945
(2/5) Greptile learns from your feedback when you react with thumbs up/down!