Skip to main content

vtcode_core/core/agent/
display.rs

1use crate::config::constants::tools;
2use crate::tools::tool_intent;
3use serde_json::Value;
4
5/// Format tool result for display in the TUI.
6/// Limits verbose output from web_fetch to avoid overwhelming the terminal.
7#[inline]
8pub fn format_tool_result_for_display(tool_name: &str, result: &Value) -> String {
9    let display_tool_name = tool_intent::canonical_command_session_tool_name(tool_name).unwrap_or(tool_name);
10    let is_command_session_tool = display_tool_name == tools::UNIFIED_EXEC;
11
12    if is_command_session_tool {
13        // Extract errors + 2 context lines for build output
14        if let Some(obj) = result.as_object()
15            && let Some(stdout) = obj.get("stdout").or_else(|| obj.get("output")).and_then(|v| v.as_str())
16            && stdout.len() > 2000
17            && (stdout.contains("error") || stdout.contains("Error"))
18        {
19            let lines: Vec<&str> = stdout.lines().collect();
20            let mut extracted = Vec::new();
21            for (i, line) in lines.iter().enumerate() {
22                if line.to_lowercase().contains("error") {
23                    let start = i.saturating_sub(2);
24                    let end = (i + 3).min(lines.len());
25                    extracted.extend_from_slice(&lines[start..end]);
26                    extracted.push("...");
27                }
28            }
29            if !extracted.is_empty() {
30                let compact = serde_json::json!({
31                    "exit_code": obj.get("exit_code"),
32                    "errors": extracted.join("\n"),
33                    "note": "Showing error lines + context only"
34                });
35                return format!("Tool {display_tool_name} result: {compact}");
36            }
37        }
38        return format!("Tool {display_tool_name} result: {result}");
39    }
40
41    format!("Tool {display_tool_name} result: {result}")
42}