Compact single-line tool output for file operations and shell

Implement compact display format for read_file, write_file, str_replace, and shell:

- read_file/write_file/str_replace: Single line with dimmed summary and timing
  Format: ● tool_name | path [range] | summary | tokens ◉ time

- shell: Two-line format with command header and dimmed output
  Format: ● shell | command
          └─ output (N lines) | tokens ◉ time

Changes:
- Add print_tool_compact() method to UiWriter trait
- Add is_shell_compact state tracking in ConsoleUiWriter
- Add format_write_file_summary() and format_str_replace_summary() helpers
- Fix duplicate response output by checking if response is empty before printing
- Add finish_streaming_markdown() call before return to flush markdown buffer
This commit is contained in:
Dhanji R. Prasanna
2026-01-12 14:37:47 +05:30
parent 8d5dd9f84a
commit 2c411c058a
7 changed files with 242 additions and 26 deletions

View File

@@ -289,7 +289,28 @@ pub fn format_read_file_summary(line_count: usize, char_count: usize) -> String
} else {
format!("{}", char_count)
};
format!("🔍 {} lines read ({} chars)", line_count, char_display)
format!("{} lines ({} chars)", line_count, char_display)
}
/// Format a write_file result summary.
pub fn format_write_file_summary(line_count: usize, char_count: usize) -> String {
let char_display = if char_count >= 1000 {
format!("{:.1}k", char_count as f64 / 1000.0)
} else {
format!("{}", char_count)
};
format!("✏️ {} lines ({} chars)", line_count, char_display)
}
/// Format a str_replace result summary.
pub fn format_str_replace_summary(insertions: i32, deletions: i32) -> String {
if insertions > 0 && deletions > 0 {
format!("\x1b[32m+{}\x1b[0m \x1b[2m|\x1b[0m \x1b[31m-{}\x1b[0m", insertions, deletions)
} else if insertions > 0 {
format!("\x1b[32m+{}\x1b[0m", insertions)
} else {
format!("\x1b[31m-{}\x1b[0m", deletions)
}
}
/// Determine if a response is essentially empty (whitespace or timing only)
@@ -367,8 +388,8 @@ mod tests {
#[test]
fn test_format_read_file_summary() {
assert_eq!(format_read_file_summary(42, 500), "🔍 42 lines read (500 chars)");
assert_eq!(format_read_file_summary(100, 1500), "🔍 100 lines read (1.5k chars)");
assert_eq!(format_read_file_summary(42, 500), "42 lines (500 chars)");
assert_eq!(format_read_file_summary(100, 1500), "100 lines (1.5k chars)");
}
#[test]