From ee9acdb49d65fcdc0d1cf9cff7da10f4f7916600 Mon Sep 17 00:00:00 2001 From: Mario Zechner Date: Tue, 9 Dec 2025 17:06:29 +0100 Subject: [PATCH] Fix hardcoded truncation limits in tool output display - Add maxLines and maxBytes fields to TruncationResult to track actual limits used - Update tool-execution.ts to use actual limits from truncation result - Add fallbacks to DEFAULT_MAX_* for backward compatibility with old sessions - Fix outdated comments that said 30KB when default is 50KB --- .../coding-agent/src/core/tools/truncate.ts | 18 +++++++++++-- .../interactive/components/tool-execution.ts | 27 ++++++++++++++----- 2 files changed, 36 insertions(+), 9 deletions(-) diff --git a/packages/coding-agent/src/core/tools/truncate.ts b/packages/coding-agent/src/core/tools/truncate.ts index cf297555..12d618eb 100644 --- a/packages/coding-agent/src/core/tools/truncate.ts +++ b/packages/coding-agent/src/core/tools/truncate.ts @@ -3,7 +3,7 @@ * * Truncation is based on two independent limits - whichever is hit first wins: * - Line limit (default: 2000 lines) - * - Byte limit (default: 30KB) + * - Byte limit (default: 50KB) * * Never returns partial lines (except bash tail truncation edge case). */ @@ -31,12 +31,16 @@ export interface TruncationResult { lastLinePartial: boolean; /** Whether the first line exceeded the byte limit (for head truncation) */ firstLineExceedsLimit: boolean; + /** The max lines limit that was applied */ + maxLines: number; + /** The max bytes limit that was applied */ + maxBytes: number; } export interface TruncationOptions { /** Maximum number of lines (default: 2000) */ maxLines?: number; - /** Maximum number of bytes (default: 30KB) */ + /** Maximum number of bytes (default: 50KB) */ maxBytes?: number; } @@ -80,6 +84,8 @@ export function truncateHead(content: string, options: TruncationOptions = {}): outputBytes: totalBytes, lastLinePartial: false, firstLineExceedsLimit: false, + maxLines, + maxBytes, }; } @@ -96,6 +102,8 @@ export function truncateHead(content: string, options: TruncationOptions = {}): outputBytes: 0, lastLinePartial: false, firstLineExceedsLimit: true, + maxLines, + maxBytes, }; } @@ -135,6 +143,8 @@ export function truncateHead(content: string, options: TruncationOptions = {}): outputBytes: finalOutputBytes, lastLinePartial: false, firstLineExceedsLimit: false, + maxLines, + maxBytes, }; } @@ -164,6 +174,8 @@ export function truncateTail(content: string, options: TruncationOptions = {}): outputBytes: totalBytes, lastLinePartial: false, firstLineExceedsLimit: false, + maxLines, + maxBytes, }; } @@ -212,6 +224,8 @@ export function truncateTail(content: string, options: TruncationOptions = {}): outputBytes: finalOutputBytes, lastLinePartial, firstLineExceedsLimit: false, + maxLines, + maxBytes, }; } diff --git a/packages/coding-agent/src/modes/interactive/components/tool-execution.ts b/packages/coding-agent/src/modes/interactive/components/tool-execution.ts index e0071806..305e1927 100644 --- a/packages/coding-agent/src/modes/interactive/components/tool-execution.ts +++ b/packages/coding-agent/src/modes/interactive/components/tool-execution.ts @@ -1,6 +1,7 @@ import * as os from "node:os"; import { Container, Spacer, Text } from "@mariozechner/pi-tui"; import stripAnsi from "strip-ansi"; +import { DEFAULT_MAX_BYTES, DEFAULT_MAX_LINES, formatSize } from "../../../core/tools/truncate.js"; import { theme } from "../theme/theme.js"; /** @@ -140,7 +141,9 @@ export class ToolExecutionComponent extends Container { if (truncation.truncatedBy === "lines") { warnings.push(`Truncated: showing ${truncation.outputLines} of ${truncation.totalLines} lines`); } else { - warnings.push(`Truncated: ${truncation.outputLines} lines shown (30KB limit)`); + warnings.push( + `Truncated: ${truncation.outputLines} lines shown (${formatSize(truncation.maxBytes ?? DEFAULT_MAX_BYTES)} limit)`, + ); } } text += "\n" + theme.fg("warning", `[${warnings.join(". ")}]`); @@ -178,16 +181,26 @@ export class ToolExecutionComponent extends Container { const truncation = this.result.details?.truncation; if (truncation?.truncated) { if (truncation.firstLineExceedsLimit) { - text += "\n" + theme.fg("warning", `[First line exceeds 30KB limit]`); + text += + "\n" + + theme.fg( + "warning", + `[First line exceeds ${formatSize(truncation.maxBytes ?? DEFAULT_MAX_BYTES)} limit]`, + ); } else if (truncation.truncatedBy === "lines") { text += "\n" + theme.fg( "warning", - `[Truncated: showing ${truncation.outputLines} of ${truncation.totalLines} lines]`, + `[Truncated: showing ${truncation.outputLines} of ${truncation.totalLines} lines (${truncation.maxLines ?? DEFAULT_MAX_LINES} line limit)]`, ); } else { - text += "\n" + theme.fg("warning", `[Truncated: ${truncation.outputLines} lines shown (30KB limit)]`); + text += + "\n" + + theme.fg( + "warning", + `[Truncated: ${truncation.outputLines} lines shown (${formatSize(truncation.maxBytes ?? DEFAULT_MAX_BYTES)} limit)]`, + ); } } } @@ -277,7 +290,7 @@ export class ToolExecutionComponent extends Container { warnings.push(`${entryLimit} entries limit`); } if (truncation?.truncated) { - warnings.push("30KB limit"); + warnings.push(`${formatSize(truncation.maxBytes ?? DEFAULT_MAX_BYTES)} limit`); } text += "\n" + theme.fg("warning", `[Truncated: ${warnings.join(", ")}]`); } @@ -319,7 +332,7 @@ export class ToolExecutionComponent extends Container { warnings.push(`${resultLimit} results limit`); } if (truncation?.truncated) { - warnings.push("30KB limit"); + warnings.push(`${formatSize(truncation.maxBytes ?? DEFAULT_MAX_BYTES)} limit`); } text += "\n" + theme.fg("warning", `[Truncated: ${warnings.join(", ")}]`); } @@ -366,7 +379,7 @@ export class ToolExecutionComponent extends Container { warnings.push(`${matchLimit} matches limit`); } if (truncation?.truncated) { - warnings.push("30KB limit"); + warnings.push(`${formatSize(truncation.maxBytes ?? DEFAULT_MAX_BYTES)} limit`); } if (linesTruncated) { warnings.push("some lines truncated");