Control UI: avoid chat flicker on session reload#66271
Control UI: avoid chat flicker on session reload#66271Schnitzel wants to merge 3 commits intoopenclaw:mainfrom
Conversation
Greptile SummaryThis PR fixes a chat transcript flicker in the Control UI where the Confidence Score: 5/5Safe to merge — narrow, well-targeted bug fix with a direct regression test and no impact on other reload paths. No P0 or P1 issues found. The guard is correctly scoped to only the optimistic user-echo case during an active run; assistant-message echoes and events without an active run still trigger the history reload as expected. All findings are P2 or lower. No files require special attention. Reviews (1): Last reviewed commit: "Control UI: avoid chat flicker on sessio..." | Re-trigger Greptile |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: d7b46f4b94
ℹ️ 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 (host.chatRunId && role === "user") { | ||
| return; |
There was a problem hiding this comment.
Narrow user-message skip to only local optimistic echo
This guard drops all session.message events with role: "user" whenever chatRunId is set, not just the local optimistic message echo. In handleSessionMessageGatewayEvent, that means a real user message from another client/channel in the same active session is ignored and loadChatHistory is never called for it, so the transcript can stay stale until some later unrelated reload trigger. Please scope this suppression to the specific optimistic message being echoed (instead of role-only filtering) so concurrent user updates are not lost.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 97cd4ee1ac
ℹ️ 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".
| const hasStableMessageId = | ||
| message && | ||
| typeof message === "object" && | ||
| (typeof (message as { id?: unknown }).id === "string" || | ||
| typeof (message as { messageId?: unknown }).messageId === "string"); |
There was a problem hiding this comment.
Match optimistic echoes using gateway messageId metadata
matchesOptimisticUserEcho currently requires message.id/message.messageId, but gateway transcript events populate IDs as payload.messageId and message.__openclaw.id (see src/gateway/server-session-events.ts) and the webchat user-turn path emits session.message without a top-level message.id (src/gateway/server-methods/chat.ts around emitSessionTranscriptUpdate). In that common send flow, hasStableMessageId is false, so this branch never suppresses the redundant loadChatHistory call and the user-message flicker remains during active runs.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: ef289388da
ℹ️ 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".
| hasStableMessageId && | ||
| lastRole === "user" && | ||
| !lastHasStableMessageId && | ||
| extractText(lastMessage) === extractText(message); |
There was a problem hiding this comment.
Require unique message match before skipping session reload
Tying matchesOptimisticUserEcho to extractText(lastMessage) === extractText(message) can suppress real remote user updates, not just the local optimistic echo. During an active run, if another client sends a user message with the same visible text (or any image-only message where both sides extract to null), this condition still evaluates true and loadChatHistory is skipped, so the transcript can remain stale until some later unrelated reload. The guard should include a stronger identity check (for example explicit optimistic-message correlation) instead of text-only equality.
Useful? React with 👍 / 👎.
|
Closing this as implemented after Codex review. Current What I checked:
So I’m closing this as already implemented rather than keeping a duplicate issue open. Review notes: reviewed against 9a0b26cafca7; fix evidence: release v2026.4.15. |
Summary
session.message-triggered history reload when it is only echoing the active run's own optimistic user message, and add a regression test.Change Type (select all)
Scope (select all touched areas)
Linked Issue/PR
Root Cause (if applicable)
session.messagehandler that unconditionally reloadedchat.historyfor the active session. The chat UI already renders the user's message optimistically, andloadChatHistoryreplaceschatMessageswholesale, so an early reload can briefly swap in a stale transcript snapshot before persistence catches up.session.messageecho.session.messagereload path in Control UI.Regression Test Plan (if applicable)
ui/src/ui/app-gateway.sessions.node.test.tschatRunIdis active, a same-sessionsession.messageevent carrying a user message should not triggerloadChatHistory.User-visible / Behavior Changes
Diagram (if applicable)
Security Impact (required)
Yes, explain risk + mitigation:Repro + Verification
Environment
Steps
chatRunId.session.messageevent for the same session containing a user message echo.chat.history.Expected
Actual
Evidence
Human Verification (required)
pnpm test ui/src/ui/app-gateway.sessions.node.test.tsand confirmed the new regression test plus existing session-message coverage pass.Review Conversations
Compatibility / Migration
Risks and Mitigations
session.messageevent could be delayed if it arrives whilechatRunIdis active and only exposesrole: user.