fix: display search pattern and match count in read_command_output UI

When using search mode, the UI now shows the search pattern and match count
instead of the misleading byte range (0 B - totalSize).

- Added searchPattern and matchCount fields to ClineSayTool type
- Updated ReadCommandOutputTool to return match count from search operations
- Updated ChatRow to display 'search: "pattern" • N matches' for search mode
This commit is contained in:
Hannes Rudolph 2026-01-27 18:17:40 -07:00
parent f15bea2c59
commit d6aab9fcaf
2 changed files with 11 additions and 4 deletions

View file

@ -161,10 +161,13 @@ export class ReadCommandOutputTool extends BaseTool<"read_command_output"> {
let result: string
let readStart = 0
let readEnd = 0
let matchCount: number | undefined
if (search) {
// Search mode: filter lines matching the pattern
result = await this.searchInArtifact(artifactPath, search, totalSize, limit)
const searchResult = await this.searchInArtifact(artifactPath, search, totalSize, limit)
result = searchResult.content
matchCount = searchResult.matchCount
// For search, we're scanning the whole file
readStart = 0
readEnd = totalSize
@ -184,6 +187,7 @@ export class ReadCommandOutputTool extends BaseTool<"read_command_output"> {
readStart,
readEnd,
totalBytes: totalSize,
...(search && { searchPattern: search, matchCount }),
}),
)
@ -292,7 +296,7 @@ export class ReadCommandOutputTool extends BaseTool<"read_command_output"> {
pattern: string,
totalSize: number,
limit: number,
): Promise<string> {
): Promise<{ content: string; matchCount: number }> {
const CHUNK_SIZE = 64 * 1024 // 64KB chunks for bounded memory
// Create case-insensitive regex for search
@ -368,23 +372,25 @@ export class ReadCommandOutputTool extends BaseTool<"read_command_output"> {
const artifactId = path.basename(artifactPath)
if (matches.length === 0) {
return [
const content = [
`[Command Output: ${artifactId}] (search: "${pattern}")`,
`Total size: ${this.formatBytes(totalSize)}`,
"",
"No matches found for the search pattern.",
].join("\n")
return { content, matchCount: 0 }
}
// Format matches with line numbers
const matchedLines = matches.map((m) => `${String(m.lineNumber).padStart(5)} | ${m.content}`).join("\n")
return [
const content = [
`[Command Output: ${artifactId}] (search: "${pattern}")`,
`Total matches: ${matches.length} | Showing first ${matches.length}`,
"",
matchedLines,
].join("\n")
return { content, matchCount: matches.length }
}
/**

View file

@ -1470,6 +1470,7 @@ export const ChatRowContent = ({
if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`
return `${(bytes / (1024 * 1024)).toFixed(1)} MB`
}
// Determine if this is a search operation
const isSearch = sayTool.searchPattern !== undefined