fix(tui): perbaiki rendering multi-baris pada pesan Tool

Konten Tool sebelumnya didorong sebagai satu Span tanpa split newline,
sehingga output tool multi-baris (stdout bash, hasil grep, diff)
tampil sebagai karakter \n literal alih-alih baris terpisah. Sekarang
mengikuti pola render_markdown + split_spans_into_lines yang sama
dengan role lain.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
asepharyana
2026-07-14 23:41:53 +07:00
co-authored by Claude Sonnet 5
parent e34708a319
commit 2f1a4d85a1
+27 -5
View File
@@ -117,18 +117,40 @@ pub fn draw_chat(frame: &mut Frame, area: Rect, state: &crate::app::state::rest:
let is_last = std::ptr::eq(msg, messages.last().unwrap());
// Tool messages render as a dim sub-line attached to whatever came
// before — no header, no speaker-change bookkeeping.
// before — no header, no speaker-change bookkeeping. Content is run
// through the same render_markdown + split_spans_into_lines pipeline
// as every other role so multi-line tool output (bash stdout, grep
// matches, diffs) becomes real wrapped `Line`s instead of a literal
// `\n` inside one Span; every rendered span is then re-styled dim
// italic to preserve the original single-line look.
if msg.role == Role::Tool {
let content = if msg.content.trim().is_empty() {
"(tool execution)".to_string()
} else {
msg.content.clone()
};
display_lines.push(Line::from(vec![
let dim = Style::default().fg(Theme::TEXT_DIM);
let dim_italic = dim.add_modifier(Modifier::ITALIC);
let content_spans = super::markdown::render_markdown(&content, content_width);
let content_lines = split_spans_into_lines(content_spans);
let mut lines_iter = content_lines.into_iter();
let first_spans = lines_iter.next().map_or_else(Vec::new, |line| {
line.spans.into_iter().map(|s| Span::styled(s.content, dim_italic)).collect()
});
let mut spans = vec![
Span::raw(" ".repeat(PREFIX_WIDTH)),
Span::styled("", Style::default().fg(Theme::TEXT_DIM)),
Span::styled(content, Style::default().fg(Theme::TEXT_DIM).add_modifier(Modifier::ITALIC)),
]));
Span::styled("", dim),
];
spans.extend(first_spans);
display_lines.push(Line::from(spans));
for line in lines_iter {
let mut spans = vec![Span::raw(" ".repeat(PREFIX_WIDTH))];
spans.extend(line.spans.into_iter().map(|s| Span::styled(s.content, dim_italic)));
display_lines.push(Line::from(spans));
}
continue;
}