perf: optimize truncateOutput for large inputs

Use string indices to find line boundaries instead of splitting into array.
This avoids creating large arrays in memory when truncating big inputs.

- Replace split/join with indexOf/lastIndexOf for line counting
- Use slice to extract start/end sections directly from string
- Maintain same 20/80 ratio for before/after content

Signed-off-by: Eric Wheeler <roo-code@z.ewheeler.org>
This commit is contained in:
Eric Wheeler 2025-03-09 15:41:48 -07:00
parent 8b8c4fde50
commit c31a5e5bcd

View file

@ -110,16 +110,42 @@ export function truncateOutput(content: string, lineLimit?: number): string {
return content
}
const lines = content.split("\n")
if (lines.length <= lineLimit) {
// Count total lines
let totalLines = 0
let pos = -1
while ((pos = content.indexOf("\n", pos + 1)) !== -1) {
totalLines++
}
totalLines++ // Account for last line without newline
if (totalLines <= lineLimit) {
return content
}
const beforeLimit = Math.floor(lineLimit * 0.2) // 20% of lines before
const afterLimit = lineLimit - beforeLimit // remaining 80% after
return [
...lines.slice(0, beforeLimit),
`\n[...${lines.length - lineLimit} lines omitted...]\n`,
...lines.slice(-afterLimit),
].join("\n")
// Find start section end position
let startEndPos = -1
let lineCount = 0
pos = 0
while (lineCount < beforeLimit && (pos = content.indexOf("\n", pos)) !== -1) {
startEndPos = pos
lineCount++
pos++
}
// Find end section start position
let endStartPos = content.length
lineCount = 0
pos = content.length
while (lineCount < afterLimit && (pos = content.lastIndexOf("\n", pos - 1)) !== -1) {
endStartPos = pos + 1 // Start after the newline
lineCount++
}
const omittedLines = totalLines - lineLimit
const startSection = content.slice(0, startEndPos + 1)
const endSection = content.slice(endStartPos)
return startSection + `\n[...${omittedLines} lines omitted...]\n\n` + endSection
}