import type { QuietToolsConfig } from "./config"; export interface CompactPolicy { headLines: number; tailLines: number; maxChars: number; } export interface CompactResult { text: string; originalChars: number; originalLines: number; previewChars: number; previewLines: number; } export function countLines(text: string): number { if (text.length === 0) return 0; return text.endsWith("\n") ? text.split("\n").length - 1 : text.split("\n").length; } export function shouldCompact(text: string, config: QuietToolsConfig): boolean { return text.length > config.maxChars || countLines(text) > config.maxLines; } export function policyFor(config: QuietToolsConfig, isError: boolean): CompactPolicy { return isError ? { headLines: config.errorHeadLines, tailLines: config.errorTailLines, maxChars: config.maxChars } : { headLines: config.headLines, tailLines: config.tailLines, maxChars: config.maxChars }; } export function compactText(text: string, policy: CompactPolicy): CompactResult { const originalChars = text.length; const originalLines = countLines(text); const lines = text.split("\n"); let preview: string; if (lines.length <= policy.headLines + policy.tailLines) { if (text.length <= policy.maxChars) { preview = text; } else { const headChars = Math.max(1, Math.floor(policy.maxChars * 0.6)); const tailChars = Math.max(1, policy.maxChars - headChars); preview = `${text.slice(0, headChars)}\n\n... omitted ${text.length - headChars - tailChars} characters ...\n\n${text.slice(-tailChars)}`; } } else { const head = lines.slice(0, policy.headLines); const tail = lines.slice(-policy.tailLines); const omitted = lines.length - head.length - tail.length; preview = [...head, ``, `... omitted ${omitted} lines ...`, ``, ...tail].join("\n"); } return { text: preview, originalChars, originalLines, previewChars: preview.length, previewLines: countLines(preview), }; }