mirror of
https://github.com/openclaw/openclaw.git
synced 2026-08-24 03:15:46 -06:00
3932f4abb4
Peter isolated the on-off focus-jump precisely: when a durable 🧠 posts BELOW the streaming window, the window (now above the reasoning) is repositioned to stay newest by DELETING it and reposting below. Telegram cannot move messages, so the delete-then-repost order scroll-jumps the client. Root cause: rotateAnswerLaneAfterToolProgress rewound the tool-progress window with stream.clear(), which deletes the old message IMMEDIATELY when it has been on screen past the dwell — before the replacement message is sent. Delete-first, post-second. Fix — invert the order, preserving arrival order: - draft-stream: new rotateToNewMessageDeferringDelete() rewinds the stream so the NEXT update creates a fresh message, and schedules the superseded message's delete for AFTER it (detached, floored at 1.5s so the new message lands first). Extracted the shared deferred-delete scheduler (scheduleDetachedDelete) used by both clear() and the reposition. (draft-stream.ts) - dispatch: rotateAnswerLaneAfterToolProgress now repositions via that method instead of clear()+forceNewMessage, so no window reposition deletes before the replacement lands. (bot-message-dispatch.ts:1259) Tests: draft-stream unit tests prove the sequencing (new message sent before the old is deleted; delete deferred; no-op with no live message). Added a dispatch repro (durable 🧠 then answer text mid-turn -> reposition, no clear). Updated the predating tool-progress-rotation tests to assert the deferred-delete reposition and that any deliverer-cleanup clear() runs only AFTER the rewind. 228 green across bot-message-dispatch, draft-stream, progress-summary; extensions/telegram typechecks clean. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>