


























@@ -10,6 +10,8 @@ const DEFAULT_CONCURRENCY = 6;
1010const DEFAULT_TIMEOUT_MS = 90_000;
1111const DEFAULT_COMBINED_TIMEOUT_MS = 180_000;
1212const DEFAULT_TOP = 10;
13+const OUTPUT_CAPTURE_MAX_CHARS = 128 * 1024;
14+const STDERR_PREVIEW_MAX_CHARS = 8 * 1024;
1315const RSS_MARKER = "__OPENCLAW_MAX_RSS_KB__=";
14161517function printHelp() {
@@ -120,8 +122,49 @@ function parseMaxRssMb(stderr) {
120122return last ? Number(last[1]) / 1024 : null;
121123}
122124123-function summarizeStderr(stderr, lines = 8) {
124-return stderr.trim().split("\n").filter(Boolean).slice(0, lines).join("\n");
125+function createOutputCapture() {
126+return { text: "", truncatedChars: 0 };
127+}
128+129+function appendBoundedOutput(capture, chunk, maxChars = OUTPUT_CAPTURE_MAX_CHARS) {
130+const nextText = capture.text + String(chunk);
131+if (nextText.length <= maxChars) {
132+return capture.truncatedChars === 0
133+ ? { text: nextText, truncatedChars: 0 }
134+ : { text: nextText, truncatedChars: capture.truncatedChars };
135+}
136+const truncatedChars = capture.truncatedChars + nextText.length - maxChars;
137+return { text: nextText.slice(-maxChars), truncatedChars };
138+}
139+140+function formatCapturedOutput(capture) {
141+if (capture.truncatedChars === 0) {
142+return capture.text;
143+}
144+return `[output truncated ${capture.truncatedChars} chars; showing tail]\n${capture.text}`;
145+}
146+147+function scanMaxRssMb(tail, chunk, current) {
148+const text = `${tail}${String(chunk)}`;
149+const parsed = parseMaxRssMb(text);
150+const lineBreakIndex = Math.max(text.lastIndexOf("\n"), text.lastIndexOf("\r"));
151+const openLine = lineBreakIndex === -1 ? text : text.slice(lineBreakIndex + 1);
152+return {
153+maxRssMb: parsed ?? current,
154+tail: openLine.slice(-(RSS_MARKER.length + 32)),
155+};
156+}
157+158+function summarizeStderr(stderr, lines = 8, maxChars = STDERR_PREVIEW_MAX_CHARS) {
159+const text = stderr.trim().split("\n").filter(Boolean).slice(0, lines).join("\n");
160+if (text.length <= maxChars) {
161+return text;
162+}
163+const firstLine = text.split("\n", 1)[0] ?? "";
164+const prefix = firstLine.startsWith("[output truncated") ? `${firstLine}\n` : "";
165+return `${prefix}[stderr preview truncated ${text.length - maxChars} chars; showing tail]\n${text.slice(
166+ -maxChars,
167+ )}`;
125168}
126169127170async function runCase({ repoRoot, env, hookPath, name, body, timeoutMs }) {
@@ -136,30 +179,36 @@ async function runCase({ repoRoot, env, hookPath, name, body, timeoutMs }) {
136179},
137180);
138181139-let stdout = "";
140-let stderr = "";
182+let stdout = createOutputCapture();
183+let stderr = createOutputCapture();
184+let stderrRssTail = "";
185+let maxRssMb = null;
141186let timedOut = false;
142187const timer = setTimeout(() => {
143188timedOut = true;
144189child.kill("SIGKILL");
145190}, timeoutMs);
146191147192child.stdout.on("data", (chunk) => {
148-stdout += String(chunk);
193+stdout = appendBoundedOutput(stdout, chunk);
149194});
150195child.stderr.on("data", (chunk) => {
151-stderr += String(chunk);
196+const rssScan = scanMaxRssMb(stderrRssTail, chunk, maxRssMb);
197+stderrRssTail = rssScan.tail;
198+maxRssMb = rssScan.maxRssMb;
199+stderr = appendBoundedOutput(stderr, chunk);
152200});
153201child.on("close", (code, signal) => {
154202clearTimeout(timer);
203+const stderrText = formatCapturedOutput(stderr);
155204resolve({
156205 name,
157206 code,
158207 signal,
159208 timedOut,
160- stdout,
161- stderr,
162-maxRssMb: parseMaxRssMb(stderr),
209+stdout: formatCapturedOutput(stdout),
210+stderr: stderrText,
211+maxRssMb: maxRssMb ?? parseMaxRssMb(stderrText),
163212});
164213});
165214});
@@ -213,9 +262,10 @@ async function main() {
213262writeFileSync(
214263hookPath,
215264[
265+"import { writeSync } from 'node:fs';",
216266"process.on('exit', () => {",
217267" const usage = typeof process.resourceUsage === 'function' ? process.resourceUsage() : null;",
218-` if (usage && typeof usage.maxRSS === 'number') console.error('${RSS_MARKER}' + String(usage.maxRSS));`,
268+` if (usage && typeof usage.maxRSS === 'number') writeSync(2, '${RSS_MARKER}' + String(usage.maxRSS) + '\\n');`,
219269"});",
220270"",
221271].join("\n"),
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。