From 12c84c6d0a01aa478be5f8238a0446c915e4486a Mon Sep 17 00:00:00 2001 From: Charles Packer Date: Wed, 14 Jan 2026 12:00:49 -0800 Subject: [PATCH] feat: prettify tool result rendering (#538) Co-authored-by: Letta --- src/cli/components/ToolCallMessageRich.tsx | 93 ++++++++++++++++++++++ src/cli/helpers/toolNameMapping.ts | 26 ++++++ 2 files changed, 119 insertions(+) diff --git a/src/cli/components/ToolCallMessageRich.tsx b/src/cli/components/ToolCallMessageRich.tsx index 0912841..7bf6d47 100644 --- a/src/cli/components/ToolCallMessageRich.tsx +++ b/src/cli/components/ToolCallMessageRich.tsx @@ -15,9 +15,11 @@ import { isFileEditTool, isFileReadTool, isFileWriteTool, + isGlobTool, isMemoryTool, isPatchTool, isPlanTool, + isSearchTool, isTaskTool, isTodoTool, } from "../helpers/toolNameMapping.js"; @@ -614,6 +616,97 @@ export const ToolCallMessage = memo( ); } + // Check if this is a search/grep tool - show line/file count summary + if (isSearchTool(rawName) && line.resultOk !== false && line.resultText) { + const text = line.resultText; + // Match "Found N file(s)" at start of output (files_with_matches mode) + const filesMatch = text.match(/^Found (\d+) files?/); + const noFilesMatch = text === "No files found"; + const noMatchesMatch = text === "No matches found"; + + if (filesMatch?.[1]) { + const count = parseInt(filesMatch[1], 10); + return ( + + + {prefix} + + + + Found {count} file{count !== 1 ? "s" : ""} + + + + ); + } else if (noFilesMatch || noMatchesMatch) { + return ( + + + {prefix} + + + + Found 0 {noFilesMatch ? "files" : "matches"} + + + + ); + } else { + // Content mode - count lines in the output + const lineCount = text.split("\n").length; + return ( + + + {prefix} + + + + Found {lineCount} line + {lineCount !== 1 ? "s" : ""} + + + + ); + } + } + + // Check if this is a glob tool - show file count summary + if (isGlobTool(rawName) && line.resultOk !== false && line.resultText) { + const text = line.resultText; + const filesMatch = text.match(/^Found (\d+) files?/); + const noFilesMatch = text === "No files found"; + + if (filesMatch?.[1]) { + const count = parseInt(filesMatch[1], 10); + return ( + + + {prefix} + + + + Found {count} file{count !== 1 ? "s" : ""} + + + + ); + } else if (noFilesMatch) { + return ( + + + {prefix} + + + + Found 0 files + + + + ); + } + // Fall through to default if no match pattern found + } + // Regular result handling const isError = line.resultOk === false; diff --git a/src/cli/helpers/toolNameMapping.ts b/src/cli/helpers/toolNameMapping.ts index c25c355..4b9d043 100644 --- a/src/cli/helpers/toolNameMapping.ts +++ b/src/cli/helpers/toolNameMapping.ts @@ -210,3 +210,29 @@ export function isShellTool(name: string): boolean { n === "runshellcommand" ); } + +/** + * Checks if a tool is a search/grep tool + */ +export function isSearchTool(name: string): boolean { + return ( + name === "grep" || + name === "Grep" || + name === "grep_files" || + name === "GrepFiles" || + name === "search_file_content" || + name === "SearchFileContent" + ); +} + +/** + * Checks if a tool is a glob tool + */ +export function isGlobTool(name: string): boolean { + return ( + name === "glob" || + name === "Glob" || + name === "glob_gemini" || + name === "GlobGemini" + ); +}