#16733: fix(ui): avoid injected newlines when tool output is hidden
app: web-ui
stale
size: XS
Cluster:
Model Reasoning Fixes
## Summary
- Problem: assistant text in the web UI gets split by an extra
newline when thinking/tool output is hidden and content is
segmented.
- Why it matters: chat output formatting changes based on
thinking toggle state.
- What changed: in `extractText`, assistant text blocks are
concatenated without forced newline insertion; added regression
test.
- What did NOT change (scope boundary): no protocol, routing,
backend, or tool execution behavior changes.
## Change Type (select all)
- [x] Bug fix
## Scope (select all touched areas)
- [x] UI / DX
## Linked Issue/PR
- Closes #16636
## User-visible / Behavior Changes
Assistant messages no longer gain artificial line breaks around
hidden tool output blocks.
## Security Impact (required)
- New permissions/capabilities? (No)
- Secrets/tokens handling changed? (No)
- New/changed network calls? (No)
- Command/tool execution surface changed? (No)
- Data access scope changed? (No)
## Repro + Verification
### Environment
- OS: macOS
- Runtime/container: Node 24 / pnpm
- Model/provider: N/A
- Integration/channel (if any): Control UI web chat
- Relevant config (redacted): thinking/working output toggle off
### Steps
1. Render assistant message content containing text, tool block,
text.
2. With thinking/tool output hidden, view assistant text.
3. Confirm no artificial newline is inserted between text blocks.
### Expected
- Assistant text renders continuously unless newline is present
in original text.
### Actual
- Before fix, a newline was injected between text blocks (`"Hello
\nworld"`).
## Evidence
- [x] Failing test/log before + passing after
## Human Verification (required)
- Verified scenarios: new regression case in `ui/src/ui/chat/
message-extract.test.ts` plus targeted and full test runs.
- Edge cases checked: non-assistant join behavior unchanged.
- What you did **not** verify: manual browser walkthrough on all
providers/channels.
## Compatibility / Migration
- Backward compatible? (Yes)
- Config/env changes? (No)
- Migration needed? (No)
## Failure Recovery (if this breaks)
- How to disable/revert this change quickly: revert this commit.
- Files/config to restore: `ui/src/ui/chat/message-extract.ts`,
`ui/src/ui/chat/message-extract.test.ts`
- Known bad symptoms reviewers should watch for: unexpected
spacing differences in assistant message rendering.
## Risks and Mitigations
- Risk: assistant text concatenation could alter spacing in rare
segmented-message cases.
- Mitigation: regression test added; all local checks and tests
pass.
AI-assisted: Yes
Testing level: Fully tested locally (`pnpm check`, `pnpm
protocol:check`, `pnpm test`).
first attempt at contributing to openclaw, if this is not the correct way to do it, please let me know.
<!-- greptile_comment -->
<h3>Greptile Summary</h3>
This PR fixes an issue where assistant text in the web UI gained artificial newlines when thinking/tool output was hidden and the message content was segmented into multiple text blocks separated by tool blocks.
- **Core fix** (`message-extract.ts`): Changes `parts.join("\n")` to `parts.join("")` for assistant role messages, preventing injected newlines between text blocks. Non-assistant messages retain the original `"\n"` join behavior.
- **Inlined `stripEnvelope`**: The import from the shared module `src/shared/chat-envelope.js` was replaced with a local implementation in the UI. However, the inlined `ENVELOPE_CHANNELS` list is **missing `"Google Chat"`** — this entry is present in the original shared module and in `src/gateway/chat-sanitize.ts`.
- **Removed `stripDirectiveTags`**: The UI-side stripping of `[[reply_to_current]]`, `[[reply_to:<id>]]`, and `[[audio_as_voice]]` directive tags was removed. These tags are processed server-side in the auto-reply pipeline, so this is likely safe but worth verifying that stored transcripts don't contain raw directive tags.
- **Test deflake** (`gateway-lock.test.ts`): The "proc access fails" test case was simplified to use real timers with short timeouts instead of fake timers, reducing CI flakiness.
- **Regression test**: A new test validates the newline fix for assistant messages with interleaved tool blocks.
<h3>Confidence Score: 3/5</h3>
- PR is mostly safe but has a missing channel entry in the inlined envelope stripping logic that could cause a minor UI rendering regression for Google Chat users.
- The core newline fix is correct and well-tested. However, the inlined `ENVELOPE_CHANNELS` array drops "Google Chat" which exists in the original shared module and the gateway's chat-sanitize.ts. This is a data loss bug that could cause envelope prefixes to render visibly for Google Chat channel messages. The `stripDirectiveTags` removal is likely safe but adds some uncertainty. The gateway-lock test deflake changes are reasonable.
- Pay close attention to `ui/src/ui/chat/message-extract.ts` — the inlined `ENVELOPE_CHANNELS` is missing "Google Chat" compared to the authoritative copies in the codebase.
<sub>Last reviewed commit: 7be5f96</sub>
<!-- greptile_other_comments_section -->
<sub>(2/5) Greptile learns from your feedback when you react with thumbs up/down!</sub>
<!-- /greptile_comment -->
Most Similar PRs
#23073: fix(ui): strip reply directive tags from assistant messages in WebC...
by x4v13r1120 · 2026-02-22
85.2%
#23144: fix(ui): strip reply directive tags from assistant messages in WebC...
by echoVic · 2026-02-22
82.4%
#12974: fix: intermittent (no output) reported by users
by vincentkoc · 2026-02-10
82.1%
#14309: fix(ui): resolve chat event session key mismatch
by justonlyforyou · 2026-02-11
81.7%
#20050: fix: Telegram polling regression and thinking blocks corruption (AI...
by Vaibhavee89 · 2026-02-18
81.4%
#17552: fix(agents): suppress tool error warnings when assistant already re...
by AytuncYildizli · 2026-02-15
81.3%
#14328: fix: strip incomplete tool_use blocks from errored/aborted messages...
by Kropiunig · 2026-02-12
81.3%
#20164: fix(webchat): strip reply directive tags before rendering assistant...
by Limitless2023 · 2026-02-18
81.2%
#3721: fix(ui): webchat not displaying chat responses
by maxmaxrouge-rgb · 2026-01-29
80.6%
#15050: fix: transcript corruption resilience — strip aborted tool_use bloc...
by yashchitneni · 2026-02-12
80.4%