fix(render): restore trailing newlines stripped by markdown_to_ansi in stream#3043
Open
np6126 wants to merge 1 commit into
Open
fix(render): restore trailing newlines stripped by markdown_to_ansi in stream#3043np6126 wants to merge 1 commit into
np6126 wants to merge 1 commit into
Conversation
…n stream
MarkdownStreamState::push calls markdown_to_ansi on each ready chunk, but
markdown_to_ansi (via the underlying markdown renderer) strips trailing
newlines with trim_end(). When the next streamed chunk arrives, its rendered
output runs into the tail of the previous chunk in the terminal, producing
visibly merged lines on streamed output.
Restore the trailing newline(s) on the rendered output when the input chunk
had them and the renderer ate them, matching the input's level of trailing
whitespace ('\n' vs '\n\n'). flush() is unaffected since it returns the final
chunk where trailing whitespace is irrelevant.
Repro: any OpenAI-compatible streaming endpoint where deltas arrive separated
by '\n' (most providers).
np6126
pushed a commit
to np6126/tank-agent-os
that referenced
this pull request
May 17, 2026
…am-drop The two patches we ship in bootc/patches/ each contained an experimental mix of changes that aren't all needed in this setup. Splitting them into intent-aligned files makes it possible to drop them individually as upstream merges happen, without having to surgically extract pieces. - claw-fix-stream-newlines.patch: now contains only the trailing-newline restoration in MarkdownStreamState::push. Matches the change in ultraworkers/claw-code#3043 1:1, so the file drops out the moment that PR lands and CLAW_CODE_REF is bumped. - claw-fix-openai-prefix-strip.patch: now contains only the "local/" routing-prefix additions in metadata_for_model and wire_model_for_base_url. The dead-code edit to strip_routing_prefix and the OpenRouter slug-preservation removal are gone — both were experimental and unneeded for this setup (we use "local/" prefix, not "openai/"). Matches ultraworkers/claw-code#3044 1:1, drops out when that PR lands. - claw-add-think-block-filter.patch (new): isolates the <think>...</think> block filtering for thinking models (Qwen3 et al). Applied on top of the newlines patch since both touch MarkdownStreamState::push. Stays as a local patch until ultraworkers/claw-code#3045 resolves; the filter remains usable as a standalone patch against post-#3043 upstream because its context lines reference the newlines-applied state. Containerfile applies the three patches in order: newlines → think → local-prefix. Verified: all three apply cleanly to the pinned CLAW_CODE_REF and the resulting tree compiles (cargo check --workspace).
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
MarkdownStreamState::pushcallsmarkdown_to_ansion each ready chunk, butrender_markdownstrips trailing newlines viatrim_end()(seerender.rsline 270). When the next streamed chunk arrives, its rendered output runs into the tail of the previous chunk in the terminal — adjacent paragraphs / list items / code blocks visibly merge into each other.This PR restores the trailing newline(s) on the rendered output when the input chunk had them, matching the input's level of trailing whitespace (
\nvs\n\n).flush()is unaffected since it returns the final chunk where trailing whitespace is irrelevant.Diff
Repro
Any OpenAI-compatible streaming endpoint whose deltas are separated by
\nreproduces this — most providers do. Visual repro: stream a multi-line response with numbered lists or fenced code blocks and observe items concatenating without a visible separator.Test plan
cargo check --workspacecleancargo test -p rusty-claude-cli