fix(ui): strip reply directive tags from assistant messages in WebChat (#23053)#23144
fix(ui): strip reply directive tags from assistant messages in WebChat (#23053)#23144echoVic wants to merge 2 commits into
Conversation
When WebChat loads chat history, assistant messages containing [[reply_to_current]] or [[reply_to:<id>]] tags were rendered with the raw tag text visible. This happened because extractText() only stripped thinking tags for assistant messages but not inline directive tags. During streaming, server-chat.ts correctly strips these tags via stripInlineDirectiveTagsForDisplay(). However, when the message finalizes and history is reloaded from the session store, the UI's extractText() path did not apply the same stripping. Fix: apply stripInlineDirectiveTagsForDisplay() alongside stripThinkingTags() for assistant messages in extractText(). Closes openclaw#23053
whynice724-cell
left a comment
There was a problem hiding this comment.
Code Review ✅
PR #23144 - Fix for reply directive tags leaking in WebChat
Summary
The fix correctly addresses the issue where tags appear as raw text in WebChat after message streaming completes.
Analysis
- Root cause correctly identified - extractText() only calls stripThinkingTags() but not stripInlineDirectiveTagsForDisplay()
- Solution cleanly reuses the existing utility already used in the gateway streaming path
- Testing: Added 6 new test cases covering various scenarios
Changes Review
- message-extract.ts - Import and apply stripInlineDirectiveTagsForDisplay() ✅
- message-extract.test.ts - Comprehensive test coverage ✅
Verdict
Approve - The fix is minimal, targeted, and reuses existing utilities correctly. No security concerns. Mergeable.
| function stripAssistantDirectives(text: string): string { | ||
| return stripInlineDirectiveTagsForDisplay(stripThinkingTags(text)).text; | ||
| } |
There was a problem hiding this comment.
Potential whitespace issue: stripInlineDirectiveTagsForDisplay removes tags but doesn't trim the result. For input like "[[reply_to_current]] Hello", this produces " Hello" with a leading space. The gateway code (server-chat.ts:329) explicitly calls .trim() after stripping. Consider adding .trimStart() here to match the trim: "start" behavior of stripThinkingTags and ensure consistency:
| function stripAssistantDirectives(text: string): string { | |
| return stripInlineDirectiveTagsForDisplay(stripThinkingTags(text)).text; | |
| } | |
| function stripAssistantDirectives(text: string): string { | |
| return stripInlineDirectiveTagsForDisplay(stripThinkingTags(text)).text.trimStart(); | |
| } |
(Markdown renderers may normalize this, but direct consumers of extractText() could see the leading space)
Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!
Prompt To Fix With AI
This is a comment left during a code review.
Path: ui/src/ui/chat/message-extract.ts
Line: 6-8
Comment:
Potential whitespace issue: `stripInlineDirectiveTagsForDisplay` removes tags but doesn't trim the result. For input like `"[[reply_to_current]] Hello"`, this produces `" Hello"` with a leading space. The gateway code (`server-chat.ts:329`) explicitly calls `.trim()` after stripping. Consider adding `.trimStart()` here to match the `trim: "start"` behavior of `stripThinkingTags` and ensure consistency:
```suggestion
function stripAssistantDirectives(text: string): string {
return stripInlineDirectiveTagsForDisplay(stripThinkingTags(text)).text.trimStart();
}
```
(Markdown renderers may normalize this, but direct consumers of `extractText()` could see the leading space)
<sub>Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!</sub>
How can I resolve this? If you propose a fix, please make it concise.|
Addressed greptile's review — added |
|
Closing — issue #23053 has been resolved in main. |
Summary
Fixes #23053 —
[[reply_to_current]](and[[reply_to:<id>]],[[audio_as_voice]]) tags appear as raw text in WebChat after a message finishes streaming.Root Cause
Two code paths render assistant messages in WebChat:
src/gateway/server-chat.ts):emitChatDeltaandemitChatFinalboth callstripInlineDirectiveTagsForDisplay()before broadcasting — tags are stripped ✅ui/src/ui/chat/message-extract.ts):extractText()only callsstripThinkingTags()for assistant messages — tags are not stripped ❌When streaming completes, WebChat reloads history from the session store. The raw messages (with reply tags) pass through
extractText()→extractTextCached()→grouped-render.tswithout stripping, so[[reply_to_current]]becomes visible.Fix
Apply
stripInlineDirectiveTagsForDisplay()alongsidestripThinkingTags()for assistant messages inextractText(). This reuses the same utility already used by the gateway streaming path.Changes
ui/src/ui/chat/message-extract.ts— importstripInlineDirectiveTagsForDisplay, apply to all three assistant text extraction branchesui/src/ui/chat/message-extract.test.ts— 6 new test cases covering string content, content array, explicit reply ID, audio tag,.textfield, and user messages (no-op)Testing
[[reply_to_current]] Hello→ assistant rendersHello[[reply_to: msg_123]] Hello→ assistant rendersHello[[audio_as_voice]] Hello→ assistant rendersHelloGreptile Summary
Fixes
[[reply_to_current]]and related directive tags appearing as raw text in WebChat after message streaming completes.Root Cause: The streaming path (
server-chat.ts) strips directive tags before broadcasting, but the history/render path (message-extract.ts) only stripped thinking tags. When WebChat reloads history from session store after streaming, raw directive tags become visible.Solution: Applied
stripInlineDirectiveTagsForDisplay()alongsidestripThinkingTags()for all assistant message extraction paths (string content, content array, and.textfield), reusing the same utility as the gateway streaming path.Test Coverage: Added 6 test cases covering string content, content arrays, explicit reply IDs, audio tags,
.textfield, and verification that user messages are unaffected.Minor Note: One style suggestion regarding whitespace normalization consistency with the gateway code pattern.
Confidence Score: 4/5
Last reviewed commit: aa76e1e