Streaming markdown (#1920)

We wait until we have an entire newline, then format it with markdown and stream in to the UI. This reduces time to first token but is the right thing to do with our current rendering model IMO. Also lets us add word wrapping!
This commit is contained in:
easong-openai
2025-08-07 18:26:47 -07:00
committed by GitHub
parent fa0051190b
commit 2b7139859e
14 changed files with 1940 additions and 481 deletions

View File

@@ -1,5 +1,6 @@
use crate::exec_command::relativize_to_home;
use crate::exec_command::strip_bash_lc_and_escape;
use crate::insert_history::word_wrap_lines;
use crate::slash_command::SlashCommand;
use crate::text_block::TextBlock;
use crate::text_formatting::format_and_truncate_tool_result;
@@ -30,7 +31,6 @@ use ratatui::text::Line as RtLine;
use ratatui::text::Span as RtSpan;
use ratatui::widgets::Paragraph;
use ratatui::widgets::WidgetRef;
use ratatui::widgets::Wrap;
use std::collections::HashMap;
use std::io::Cursor;
use std::path::PathBuf;
@@ -187,11 +187,8 @@ impl HistoryCell {
}
pub(crate) fn desired_height(&self, width: u16) -> u16 {
Paragraph::new(Text::from(self.plain_lines()))
.wrap(Wrap { trim: false })
.line_count(width)
.try_into()
.unwrap_or(0)
let wrapped = word_wrap_lines(&self.plain_lines(), width);
wrapped.len() as u16
}
pub(crate) fn new_session_info(
@@ -821,9 +818,8 @@ impl HistoryCell {
impl WidgetRef for &HistoryCell {
fn render_ref(&self, area: Rect, buf: &mut Buffer) {
Paragraph::new(Text::from(self.plain_lines()))
.wrap(Wrap { trim: false })
.render(area, buf);
let wrapped = word_wrap_lines(&self.plain_lines(), area.width);
Paragraph::new(Text::from(wrapped)).render(area, buf);
}
}