// Truncation logic derived from opencode (MIT) — https://github.com/sst/opencode const MAX_LINES = 2000; const MAX_BYTES = 50 * 1024; // 50 KB export interface ITruncateResult { content: string; truncated: boolean; /** Set when truncated: describes what was dropped */ notice?: string; } export function truncateOutput( text: string, options?: { maxLines?: number; maxBytes?: number }, ): ITruncateResult { const maxLines = options?.maxLines ?? MAX_LINES; const maxBytes = options?.maxBytes ?? MAX_BYTES; const lines = text.split('\n'); const totalBytes = Buffer.byteLength(text, 'utf-8'); if (lines.length <= maxLines && totalBytes <= maxBytes) { return { content: text, truncated: false }; } const out: string[] = []; let bytes = 0; for (let i = 0; i < lines.length && i < maxLines; i++) { const size = Buffer.byteLength(lines[i], 'utf-8') + (i > 0 ? 1 : 0); if (bytes + size > maxBytes) break; out.push(lines[i]); bytes += size; } const kept = out.length; const dropped = lines.length - kept; const notice = `\n[Output truncated: showing ${kept}/${lines.length} lines. ${dropped} lines omitted.]`; return { content: out.join('\n') + notice, truncated: true, notice }; }