40 lines
1.2 KiB
TypeScript
40 lines
1.2 KiB
TypeScript
|
|
// 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 };
|
||
|
|
}
|