fix: improve code agent trace visibility

This commit is contained in:
lyon
2026-06-20 00:04:23 +08:00
parent fa7252449a
commit c2629c5ebf
3 changed files with 26 additions and 2 deletions
+9 -2
View File
@@ -1,6 +1,7 @@
import { createHash, randomBytes } from "node:crypto";
const OTLP_TIMEOUT_MS = 1500;
const MIN_VALID_EPOCH_MS = Date.UTC(2020, 0, 1);
const ZERO_TRACE_ID = "00000000000000000000000000000000";
const ZERO_SPAN_ID = "0000000000000000";
@@ -36,8 +37,9 @@ export async function emitCodeAgentOtelSpan(name, traceId, env = process.env, op
const endpoint = resolveOtlpTracesEndpoint(env);
if (!endpoint || typeof fetch !== "function") return { ok: false, skipped: true, reason: "otlp-endpoint-missing", valuesPrinted: false };
const context = codeAgentOtelTraceContext(traceId);
const startedAtMs = Number.isFinite(Number(options.startTimeMs)) ? Number(options.startTimeMs) : Date.now();
const endedAtMs = Number.isFinite(Number(options.endTimeMs)) ? Number(options.endTimeMs) : Date.now();
const now = Date.now();
const startedAtMs = epochUnixMs(options.startTimeMs, now);
const endedAtMs = epochUnixMs(options.endTimeMs, now);
const spanId = nonZeroHex(String(options.spanId ?? randomBytes(8).toString("hex")).slice(0, 16), ZERO_SPAN_ID);
const parentSpanId = typeof options.parentSpanId === "string" && /^[0-9a-f]{16}$/u.test(options.parentSpanId) ? options.parentSpanId : context.parentSpanId;
const statusCode = options.status === "error" || options.error ? 2 : 1;
@@ -120,6 +122,11 @@ function unixNano(ms) {
return String(Math.trunc(ms * 1_000_000));
}
function epochUnixMs(value, fallback) {
const numeric = Number(value);
return Number.isFinite(numeric) && numeric >= MIN_VALID_EPOCH_MS ? numeric : fallback;
}
function firstNonEmpty(...values) {
for (const value of values) {
const text = String(value ?? "").trim();
+13
View File
@@ -68,6 +68,8 @@ export function traceDisplayRows(trace: Record<string, unknown> = {}, events: Tr
if (lastAssistantRow) rows[lastAssistantRowIndex] = markAssistantRowTerminal(effectiveTrace, lastAssistantRow, completionEvent);
else rows.push(traceCompletionSummaryRow(effectiveTrace, completionEvent));
}
const progressRow = traceBackendProgressSummaryRow(effectiveTrace, rows, events);
if (progressRow) rows.push(progressRow);
if (rows.length > 0) return rows;
if (events.length === 0) return [];
return events.filter((event) => !isSuppressedTraceEvent(event)).map((event) => traceDisplayRow(effectiveTrace, event));
@@ -373,6 +375,17 @@ function traceNoiseSummaryRow(trace: Record<string, unknown>, events: TraceEvent
};
}
function traceBackendProgressSummaryRow(trace: Record<string, unknown>, rows: TraceEventRow[], events: TraceEvent[]): TraceEventRow | null {
if (!Array.isArray(events) || events.length === 0) return null;
if (rows.some((row) => row.rowId.startsWith("tool:") || /|/u.test(row.header))) return null;
const lastRenderedSeq = Math.max(0, ...rows.map((row) => row.seq ?? 0).filter(Number.isFinite));
const hiddenProgress = events.filter((event) => {
const seq = numberOrNull(event.seq) ?? 0;
return seq > lastRenderedSeq && (isRequestTraceEvent(event) || isSetupTraceEvent(event) || isNoisyTraceEvent(event));
});
return hiddenProgress.length > 0 ? traceNoiseSummaryRow(trace, hiddenProgress) : null;
}
function traceDisplayRow(trace: Record<string, unknown>, event: TraceEvent): TraceEventRow {
const label = readableTraceLabel(event);
return {
@@ -366,6 +366,7 @@ export const useWorkbenchStore = defineStore("workbench", () => {
function applyTurnStatusSnapshot(traceId: string, result: AgentChatResultResponse | TraceSnapshot): void {
if (!shouldApplyActiveTraceAuthority(traceId, traceResultSessionId(result))) return;
recordActivity(`turn:${firstNonEmptyString(result.lastEventLabel, result.status, result.waitingFor, "status") ?? "status"}`);
rememberTurnStatus(traceId, result);
syncTurnStatusToMessage(traceId, result);
}
@@ -572,6 +573,8 @@ export const useWorkbenchStore = defineStore("workbench", () => {
const authoritySessionId = traceResultSessionId(result);
if (!shouldApplyActiveTraceAuthority(traceId, authoritySessionId)) return;
const events = Array.isArray(result.events) ? result.events : Array.isArray(result.traceEvents) ? result.traceEvents : [];
const activityLabel = firstNonEmptyString(result.lastEventLabel, events.at(-1)?.label, events.at(-1)?.type, result.status);
if (events.length > 0 || result.terminal === true || isTerminalMessageStatus(result.status)) recordActivity(`trace:${activityLabel ?? "hydrated"}`);
markWorkbenchTraceEventsReceived({ traceId, events, transport: "rest_gap" });
updateActiveMessages((source) => source.map((message) => {
if (!shouldApplyTraceToMessage(message, traceId, authoritySessionId)) return message;
@@ -912,6 +915,7 @@ export const useWorkbenchStore = defineStore("workbench", () => {
function completeTrace(traceId: string, result: AgentChatResultResponse): void {
const authoritySessionId = traceResultSessionId(result);
if (!shouldApplyActiveTraceAuthority(traceId, authoritySessionId)) return;
recordActivity(`trace:terminal:${firstNonEmptyString(result.lastEventLabel, result.status, "completed") ?? "completed"}`);
const terminalStatus = result.status === "completed" ? "completed" : statusFromResult(result.status);
const finalText = finalResponseText(result.finalResponse);
const errorText = agentErrorDisplayText(result.error);