From ce465f5411b02a708090ae1834116da9ed42ef50 Mon Sep 17 00:00:00 2001 From: np Date: Sun, 17 May 2026 10:16:13 +0200 Subject: [PATCH] fix(render): restore trailing newlines stripped by markdown_to_ansi in 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). --- rust/crates/rusty-claude-cli/src/render.rs | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/rust/crates/rusty-claude-cli/src/render.rs b/rust/crates/rusty-claude-cli/src/render.rs index 24b77d095e..4468bff9c0 100644 --- a/rust/crates/rusty-claude-cli/src/render.rs +++ b/rust/crates/rusty-claude-cli/src/render.rs @@ -609,7 +609,15 @@ impl MarkdownStreamState { let split = find_stream_safe_boundary(&self.pending)?; let ready = self.pending[..split].to_string(); self.pending.drain(..split); - Some(renderer.markdown_to_ansi(&ready)) + let rendered = renderer.markdown_to_ansi(&ready); + // markdown_to_ansi strips trailing newlines via trim_end(); restore them + // so consecutive streamed chunks are separated in the terminal output. + let trailing = if ready.ends_with("\n\n") { "\n\n" } else { "\n" }; + Some(if rendered.ends_with('\n') { + rendered + } else { + rendered + trailing + }) } #[must_use]