Compact tool output improvements

- Rename take_screenshot -> screenshot, code_coverage -> coverage (shorter names)
- Align | character across all compact tools (pad to 11 chars for str_replace)
- Make code_search a compact tool with summary display
- Show language and search name in code_search output (e.g., rust:"find structs")
- Add format_code_search_summary() to extract match/file counts from JSON response
This commit is contained in:
Dhanji R. Prasanna
2026-01-14 08:12:50 +05:30
parent bd25d7dace
commit dea0e6b1ca
7 changed files with 77 additions and 22 deletions

View File

@@ -2047,7 +2047,7 @@ Skip if nothing new. Be brief."#;
}
// Check if this is a compact tool (file operations)
let is_compact_tool = matches!(tool_call.tool.as_str(), "read_file" | "write_file" | "str_replace" | "remember" | "take_screenshot" | "code_coverage" | "rehydrate");
let is_compact_tool = matches!(tool_call.tool.as_str(), "read_file" | "write_file" | "str_replace" | "remember" | "screenshot" | "coverage" | "rehydrate" | "code_search");
// Only print output header for non-compact tools
if !is_compact_tool && !is_todo_tool {
@@ -2120,11 +2120,11 @@ Skip if nothing new. Be brief."#;
// Extract size from result like "Memory updated. Size: 1.2k"
Some(streaming::format_remember_summary(&tool_result))
}
"take_screenshot" => {
"screenshot" => {
// Extract path from result
Some(streaming::format_screenshot_summary(&tool_result))
}
"code_coverage" => {
"coverage" => {
// Show coverage summary
Some(streaming::format_coverage_summary(&tool_result))
}
@@ -2132,6 +2132,10 @@ Skip if nothing new. Be brief."#;
// Show fragment info
Some(streaming::format_rehydrate_summary(&tool_result))
}
"code_search" => {
// Show search summary (matches and files)
Some(streaming::format_code_search_summary(&tool_result))
}
_ => Some(format!("✅ completed"))
}
}

View File

@@ -386,6 +386,25 @@ pub fn format_rehydrate_summary(result: &str) -> String {
}
}
/// Format a code_search result summary.
pub fn format_code_search_summary(result: &str) -> String {
// Result format: "✅ Code search completed\n{json}"
// JSON contains: {"searches": [...], "total_matches": N, "total_files_searched": M}
if result.contains("") {
"❌ failed".to_string()
} else if let Some(json_start) = result.find('{') {
// Try to parse the JSON to extract summary stats
if let Ok(parsed) = serde_json::from_str::<serde_json::Value>(&result[json_start..]) {
let matches = parsed.get("total_matches").and_then(|v| v.as_u64()).unwrap_or(0);
let files = parsed.get("total_files_searched").and_then(|v| v.as_u64()).unwrap_or(0);
return format!("🔍 {} matches in {} files", matches, files);
}
"🔍 search complete".to_string()
} else {
"🔍 search complete".to_string()
}
}
// =============================================================================
// Tool Call Deduplication
// =============================================================================

View File

@@ -9,7 +9,7 @@ mod take_screenshot_tests {
fn test_take_screenshot_requires_window_id() {
// Create a tool call without window_id
let tool_call = ToolCall {
tool: "take_screenshot".to_string(),
tool: "screenshot".to_string(),
args: json!({
"path": "test.png"
}),
@@ -23,7 +23,7 @@ mod take_screenshot_tests {
fn test_take_screenshot_with_window_id() {
// Create a tool call with window_id
let tool_call = ToolCall {
tool: "take_screenshot".to_string(),
tool: "screenshot".to_string(),
args: json!({
"path": "test.png",
"window_id": "Safari"

View File

@@ -167,7 +167,7 @@ fn create_core_tools(exclude_research: bool) -> Vec<Tool> {
}),
},
Tool {
name: "take_screenshot".to_string(),
name: "screenshot".to_string(),
description: "Capture a screenshot of a specific application window. You MUST specify the window_id parameter with the application name (e.g., 'Safari', 'Terminal', 'Google Chrome'). The tool will automatically use the native screencapture command with the application's window ID for a clean capture. Use list_windows first to identify available windows.".to_string(),
input_schema: json!({
"type": "object",
@@ -217,7 +217,7 @@ fn create_core_tools(exclude_research: bool) -> Vec<Tool> {
}),
},
Tool {
name: "code_coverage".to_string(),
name: "coverage".to_string(),
description: "Generate a code coverage report for the entire workspace using cargo llvm-cov. This runs all tests with coverage instrumentation and returns a summary of coverage statistics. Requires llvm-tools-preview and cargo-llvm-cov to be installed (they will be auto-installed if missing).".to_string(),
input_schema: json!({
"type": "object",
@@ -508,8 +508,8 @@ mod tests {
fn test_core_tools_count() {
let tools = create_core_tools(false);
// Should have the core tools: shell, background_process, read_file, read_image,
// write_file, str_replace, take_screenshot,
// todo_read, todo_write, code_coverage, code_search, research, remember
// write_file, str_replace, screenshot,
// todo_read, todo_write, coverage, code_search, research, remember
// (13 total - memory is auto-loaded, only remember tool needed)
assert_eq!(tools.len(), 14);
}

View File

@@ -37,8 +37,8 @@ pub async fn dispatch_tool<W: UiWriter>(
"todo_write" => todo::execute_todo_write(tool_call, ctx).await,
// Miscellaneous tools
"take_screenshot" => misc::execute_take_screenshot(tool_call, ctx).await,
"code_coverage" => misc::execute_code_coverage(tool_call, ctx).await,
"screenshot" => misc::execute_take_screenshot(tool_call, ctx).await,
"coverage" => misc::execute_code_coverage(tool_call, ctx).await,
"code_search" => misc::execute_code_search(tool_call, ctx).await,
// Research tool