From 19161b5f829e2fa048d140d0b1cc49b1cedea748 Mon Sep 17 00:00:00 2001 From: Codex Agent Date: Mon, 8 Jun 2026 13:13:48 +0800 Subject: [PATCH] fix: preserve full web trace details --- tools/src/hwlab-cli-lib.ts | 9 ++--- tools/src/hwlab-cli/trace-renderer.ts | 48 ++++++++++++++++++--------- 2 files changed, 38 insertions(+), 19 deletions(-) diff --git a/tools/src/hwlab-cli-lib.ts b/tools/src/hwlab-cli-lib.ts index e8e57e35..21264658 100644 --- a/tools/src/hwlab-cli-lib.ts +++ b/tools/src/hwlab-cli-lib.ts @@ -3146,7 +3146,7 @@ function webTraceRenderBody(traceObject: any, parsed: ParsedArgs) { loaded: events.length } : undefined, assistantText: assistantText(traceObject), - rows: rowTail.map(compactTraceRenderRow), + rows: rowTail.map((row) => compactTraceRenderRow(row, { full: parsed.full === true })), retention: traceObject?.retention, terminalEvidence: traceObject?.terminalEvidence, finalResponse: traceObject?.finalResponse, @@ -3211,7 +3211,8 @@ function traceResponseAliases(traceBody: any, parsed: ParsedArgs) { }; } -function compactTraceRenderRow(row: any) { +function compactTraceRenderRow(row: any, options: { full?: boolean } = {}) { + const body = row?.body === undefined || row?.body === null ? undefined : String(row.body); return pruneUndefined({ rowId: row?.rowId ?? null, seq: row?.seq ?? null, @@ -3219,8 +3220,8 @@ function compactTraceRenderRow(row: any) { header: row?.header ?? null, bodyFormat: row?.bodyFormat ?? null, terminal: row?.terminal === true ? true : undefined, - body: row?.body - ? (row?.terminal === true ? String(row.body) : preview(String(row.body), 1200)) + body: body + ? (options.full === true || row?.terminal === true ? body : preview(body, 1200)) : undefined }); } diff --git a/tools/src/hwlab-cli/trace-renderer.ts b/tools/src/hwlab-cli/trace-renderer.ts index e1699538..cb6607ec 100644 --- a/tools/src/hwlab-cli/trace-renderer.ts +++ b/tools/src/hwlab-cli/trace-renderer.ts @@ -146,12 +146,12 @@ function traceToolCallRow(trace: Record, event: TraceEvent): Tr function traceToolCallBody(event: TraceEvent, command: string | null): string | null { const lines = [ command, - event.stdoutSummary ? `stdout:\n${compactTraceOneLine(event.stdoutSummary, 1200)}` : null, - event.stderrSummary ? `stderr:\n${compactTraceOneLine(event.stderrSummary, 800)}` : null, - command ? null : event.outputSummary, + traceDetailBlock("stdout", traceEventText(event, ["stdout", "stdoutText", "stdoutSummary"])), + traceDetailBlock("stderr", traceEventText(event, ["stderr", "stderrText", "stderrSummary"])), + command ? null : traceEventText(event, ["output", "outputText", "outputSummary"]), event.exitCode !== undefined ? `exitCode=${event.exitCode}` : null - ].map(cleanTraceText).filter(Boolean); - return lines.length > 0 ? lines.join("\n").slice(0, 1400) : null; + ].map(cleanTraceDetailText).filter(Boolean); + return lines.length > 0 ? lines.join("\n") : null; } export function traceNoiseEventCount(events: TraceEvent[] = []): number { @@ -456,14 +456,14 @@ function traceDisplayBody(event: TraceEvent): string | null { const command = cleanShellCommand(event.command); const lines = [ command, - event.stdoutSummary ? `stdout:\n${compactTraceOneLine(event.stdoutSummary, 1200)}` : null, - event.stderrSummary ? `stderr:\n${compactTraceOneLine(event.stderrSummary, 800)}` : null, - event.outputSummary, - event.promptSummary, - event.message, - event.chunk - ].map(cleanTraceText).filter(Boolean); - return lines.length > 0 ? lines.join("\n").slice(0, 1400) : null; + traceDetailBlock("stdout", traceEventText(event, ["stdout", "stdoutText", "stdoutSummary"])), + traceDetailBlock("stderr", traceEventText(event, ["stderr", "stderrText", "stderrSummary"])), + traceEventText(event, ["output", "outputText", "outputSummary"]), + traceEventText(event, ["prompt", "promptText", "promptSummary"]), + traceEventText(event, ["message"]), + traceEventText(event, ["chunk"]) + ].map(cleanTraceDetailText).filter(Boolean); + return lines.length > 0 ? lines.join("\n") : null; } function traceMarkdownPreviewLines(body: string | null | undefined): string[] { @@ -560,12 +560,30 @@ function cleanTraceText(value: unknown): string { return String(value ?? "").replace(/\u0000/gu, "").replace(/\r\n|\r/gu, "\n").replace(/[ \t]{2,}/gu, " ").replace(/\n{3,}/gu, "\n\n").trim(); } +function cleanTraceDetailText(value: unknown): string { + return String(value ?? "").replace(/\u0000/gu, "").replace(/\r\n|\r/gu, "\n").replace(/\n{4,}/gu, "\n\n\n").trim(); +} + +function traceEventText(event: TraceEvent, keys: string[]): string | null { + for (const key of keys) { + const value = event[key]; + if (value === undefined || value === null) continue; + const body = cleanTraceDetailText(value); + if (body) return body; + } + return null; +} + +function traceDetailBlock(label: string, value: string | null): string | null { + return value ? `${label}:\n${value}` : null; +} + function cleanShellCommand(value: unknown): string | null { - const raw = cleanTraceText(value); + const raw = cleanTraceDetailText(value); if (!raw) return null; const stripped = stripShellWrapper(raw); const unescaped = stripped.replace(/\\(["`$\\])/gu, "$1"); - return compactTraceOneLine(unescaped, 900); + return cleanTraceDetailText(unescaped); } function stripShellWrapper(value: string): string {