Truncate tool use.
This commit is contained in:
parent
5a49cba1e6
commit
2eb6720efd
1 changed files with 48 additions and 1 deletions
|
|
@ -8,6 +8,9 @@ use similar::{ChangeTag, TextDiff};
|
||||||
|
|
||||||
use crate::core::types::ToolDisplay;
|
use crate::core::types::ToolDisplay;
|
||||||
|
|
||||||
|
/// Maximum number of output lines shown for a tool result before truncation.
|
||||||
|
const MAX_RESULT_LINES: usize = 10;
|
||||||
|
|
||||||
/// Format a tool that is currently executing (or awaiting approval).
|
/// Format a tool that is currently executing (or awaiting approval).
|
||||||
pub fn format_executing(name: &str, display: &ToolDisplay) -> String {
|
pub fn format_executing(name: &str, display: &ToolDisplay) -> String {
|
||||||
match display {
|
match display {
|
||||||
|
|
@ -31,9 +34,12 @@ pub fn format_executing(name: &str, display: &ToolDisplay) -> String {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Format a tool result after execution completes.
|
/// Format a tool result after execution completes.
|
||||||
|
///
|
||||||
|
/// Output is truncated to [`MAX_RESULT_LINES`] lines to keep the TUI
|
||||||
|
/// responsive for commands that produce large output (e.g. verbose test runs).
|
||||||
pub fn format_result(name: &str, display: &ToolDisplay, is_error: bool) -> String {
|
pub fn format_result(name: &str, display: &ToolDisplay, is_error: bool) -> String {
|
||||||
let prefix = if is_error { "error" } else { "result" };
|
let prefix = if is_error { "error" } else { "result" };
|
||||||
match display {
|
let raw = match display {
|
||||||
ToolDisplay::WriteFile {
|
ToolDisplay::WriteFile {
|
||||||
path,
|
path,
|
||||||
old_content,
|
old_content,
|
||||||
|
|
@ -54,7 +60,19 @@ pub fn format_result(name: &str, display: &ToolDisplay, is_error: bool) -> Strin
|
||||||
ToolDisplay::ListDirectory { path } => format!("ls {path}"),
|
ToolDisplay::ListDirectory { path } => format!("ls {path}"),
|
||||||
ToolDisplay::ReadFile { path } => format!("read {path}"),
|
ToolDisplay::ReadFile { path } => format!("read {path}"),
|
||||||
ToolDisplay::Generic { summary } => format!("[{name} {prefix}] {summary}"),
|
ToolDisplay::Generic { summary } => format!("[{name} {prefix}] {summary}"),
|
||||||
|
};
|
||||||
|
truncate_lines(&raw, MAX_RESULT_LINES)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Keep at most `max` lines, appending a summary if truncated.
|
||||||
|
fn truncate_lines(s: &str, max: usize) -> String {
|
||||||
|
let total = s.lines().count();
|
||||||
|
if total <= max {
|
||||||
|
return s.to_string();
|
||||||
}
|
}
|
||||||
|
let mut out: String = s.lines().take(max).collect::<Vec<_>>().join("\n");
|
||||||
|
out.push_str(&format!("\n... ({} lines truncated)", total - max));
|
||||||
|
out
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Produce a unified diff between `old` and `new` text.
|
/// Produce a unified diff between `old` and `new` text.
|
||||||
|
|
@ -130,4 +148,33 @@ mod tests {
|
||||||
assert!(diff.contains("+line1"));
|
assert!(diff.contains("+line1"));
|
||||||
assert!(diff.contains("+line2"));
|
assert!(diff.contains("+line2"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn truncate_lines_under_limit() {
|
||||||
|
assert_eq!(truncate_lines("a\nb\nc", 5), "a\nb\nc");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn truncate_lines_over_limit() {
|
||||||
|
let input: String = (0..300)
|
||||||
|
.map(|i| format!("line {i}"))
|
||||||
|
.collect::<Vec<_>>()
|
||||||
|
.join("\n");
|
||||||
|
let output = truncate_lines(&input, MAX_RESULT_LINES);
|
||||||
|
assert_eq!(output.lines().count(), MAX_RESULT_LINES + 1); // +1 for summary
|
||||||
|
assert!(output.contains("290 lines truncated"));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn format_result_shell_truncates_large_output() {
|
||||||
|
let big_output = (0..500)
|
||||||
|
.map(|i| format!("line {i}"))
|
||||||
|
.collect::<Vec<_>>()
|
||||||
|
.join("\n");
|
||||||
|
let display = ToolDisplay::ShellExec {
|
||||||
|
command: format!("cargo test\n{big_output}"),
|
||||||
|
};
|
||||||
|
let result = format_result("shell_exec", &display, false);
|
||||||
|
assert!(result.contains("lines truncated"));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue