import { closeSync, openSync, readSync, statSync } from "node:fs"; const DEFAULT_TAIL_BYTES = 1_048_576; // #1571 — bounded tail read for potentially large log files: reads at most `maxBytes` from the // end of the file instead of the whole thing, since callers only ever want the last N lines and // agent session/mirror logs can grow unbounded over a long-running process. export function readLogTail(path: string, maxBytes = DEFAULT_TAIL_BYTES): string { const size = statSync(path).size; const readSize = Math.min(size, maxBytes); if (readSize === 0) return ""; const buffer = Buffer.alloc(readSize); const fd = openSync(path, "r"); try { readSync(fd, buffer, 0, readSize, size - readSize); } finally { closeSync(fd); } return buffer.toString("utf8"); } export function logLines(content: string, sanitize = true): string[] { const text = sanitize ? sanitizeLogText(content) : content.replace(/\r\n/g, "\n").replace(/\r/g, "\n"); return text .split("\n") .map((line) => line.trimEnd()) .filter((line) => line.trim().length > 0); } export function sanitizeLogText(content: string): string { return content .replace(/\x1B\][^\x07\x1B]*(?:\x07|\x1B\\)/g, "") .replace(/\x1B[PX^_][\s\S]*?\x1B\\/g, "") .replace(/\x1B\[(\d*)C/g, (_match, count: string) => " ".repeat(Math.min(Number(count || "1"), 120))) .replace(/\x1B\[[0-?]*[ -/]*[@-~]/g, "") .replace(/\x1B[()#%*+\-.\/ ][ -~]/g, "") .replace(/\x1B[ -/]*[@-~]/g, "") .replace(/\x9B[0-?]*[ -/]*[@-~]/g, "") .replace(/\x1B.?/g, "") .replace(/\r\n/g, "\n") .replace(/\r/g, "\n") .replace(/[\x00-\x08\x0B\x0C\x0E-\x1F\x7F]/g, ""); }