From 74bfbda9b5879ebb7ff90d53c7f70b616a677393 Mon Sep 17 00:00:00 2001 From: Charlie Marsh Date: Sun, 19 Jul 2026 19:28:59 +0000 Subject: [PATCH] Keep incremental rendering with visualization context (#34217) ## Why Providing an inline visualization context forced every streamed Markdown update to rerender the full response, even when the source contained no visualization directives. ## What changed - Preserve the stable rendered prefix when visualization context is available but no directive is present. - Continue using canonical full rendering when the source contains a visualization directive. ## Testing Added a regression test that verifies directive-free streams match full rendering while advancing the stable source boundary. GitOrigin-RevId: cd70d2ba052db822d474eba8619d04cedf4c0573 --- codex-rs/tui/src/streaming/render.rs | 2 +- codex-rs/tui/src/streaming/render_tests.rs | 34 ++++++++++++++++++++++ 2 files changed, 35 insertions(+), 1 deletion(-) diff --git a/codex-rs/tui/src/streaming/render.rs b/codex-rs/tui/src/streaming/render.rs index 3e889c9478e4..dccc22acd628 100644 --- a/codex-rs/tui/src/streaming/render.rs +++ b/codex-rs/tui/src/streaming/render.rs @@ -102,7 +102,7 @@ impl StreamingRender { return; } - if inline_visualization_context.is_some() || raw_source.contains(DIRECTIVE_PREFIX) { + if raw_source.contains(DIRECTIVE_PREFIX) { self.recompute( raw_source, width, diff --git a/codex-rs/tui/src/streaming/render_tests.rs b/codex-rs/tui/src/streaming/render_tests.rs index 3b699759ea51..925cd02dd362 100644 --- a/codex-rs/tui/src/streaming/render_tests.rs +++ b/codex-rs/tui/src/streaming/render_tests.rs @@ -165,6 +165,40 @@ fn incremental_raw_render_preserves_blank_lines() { ); } +#[test] +fn inline_visualization_context_without_directives_keeps_stable_prefix() { + let cwd = test_cwd(); + let context = InlineVisualizationContext::new(&cwd, ThreadId::new()) + .expect("UUIDv7 thread id should provide a timestamp"); + let width = Some(80); + let mut source = String::new(); + let mut render = StreamingRender::new(); + + for chunk in ["First paragraph.\n\n", "Second paragraph.\n\n"] { + source.push_str(chunk); + render.append( + &source, + chunk, + width, + &cwd, + HistoryRenderMode::Rich, + Some(&context), + ); + assert_eq!( + render.lines, + render_source( + &source, + width, + &cwd, + HistoryRenderMode::Rich, + Some(&context), + ), + ); + } + + assert!(render.stable_source_len > 0); +} + #[test] fn inline_visualizations_use_canonical_full_render() { let cwd = test_cwd();