From 3c6117b73e43a380f891ef6c548ac57952f05572 Mon Sep 17 00:00:00 2001 From: Codex Date: Sat, 27 Jun 2026 08:20:33 +0000 Subject: [PATCH] fix: bind workbench terminal api lag to trace ids --- .../hwlab-node-web-observe-analyzer-source.ts | 5 +++- .../hwlab-node-web-observe-runner-source.ts | 25 +++++++++++++++++-- 2 files changed, 27 insertions(+), 3 deletions(-) diff --git a/scripts/src/hwlab-node-web-observe-analyzer-source.ts b/scripts/src/hwlab-node-web-observe-analyzer-source.ts index c721a9e0..5d27c4a3 100644 --- a/scripts/src/hwlab-node-web-observe-analyzer-source.ts +++ b/scripts/src/hwlab-node-web-observe-analyzer-source.ts @@ -2324,6 +2324,8 @@ function compactWorkbenchTerminalApiEvent(item) { if (!summary || Number(summary.terminalEvidenceCount ?? 0) <= 0) return null; const parsed = parseApiDomLagUrl(item.url); if (!String(parsed.path || "").startsWith("/v1/workbench/") && parsed.path !== "/v1/agent/chat" && parsed.path !== "/v1/agent/chat/steer") return null; + const terminalTraceIds = uniqueSorted(Array.isArray(summary.terminalTraceIds) ? summary.terminalTraceIds : []).slice(0, 12); + if (terminalTraceIds.length === 0) return null; const tsMs = Date.parse(item.ts || ""); if (!Number.isFinite(tsMs)) return null; return { @@ -2335,7 +2337,8 @@ function compactWorkbenchTerminalApiEvent(item) { method: String(item.method || "GET").toUpperCase(), path: parsed.path, routeKind: summary.pathKind ?? apiDomLagRouteKind(parsed.path), - traceIds: uniqueSorted([...(Array.isArray(summary.traceIds) ? summary.traceIds : []), parsed.traceId].filter(Boolean)).slice(0, 12), + traceIds: terminalTraceIds, + observedTraceIds: uniqueSorted([...(Array.isArray(summary.traceIds) ? summary.traceIds : []), parsed.traceId].filter(Boolean)).slice(0, 12), sessionIds: uniqueSorted([...(Array.isArray(summary.sessionIds) ? summary.sessionIds : []), parsed.sessionId].filter(Boolean)).slice(0, 12), terminalEvidenceCount: Number(summary.terminalEvidenceCount ?? 0), terminalStatusCount: Number(summary.terminalStatusCount ?? 0), diff --git a/scripts/src/hwlab-node-web-observe-runner-source.ts b/scripts/src/hwlab-node-web-observe-runner-source.ts index 8b9336ae..01da4208 100644 --- a/scripts/src/hwlab-node-web-observe-runner-source.ts +++ b/scripts/src/hwlab-node-web-observe-runner-source.ts @@ -3929,6 +3929,7 @@ function shouldSummarizeWorkbenchResponseBody({ method, path, resourceType, stat function summarizeWorkbenchJsonBody(value, path) { const traceIds = new Set(); const sessionIds = new Set(); + const terminalTraceIds = new Set(); const statusCounts = {}; const counters = { objectCount: 0, @@ -3953,10 +3954,14 @@ function summarizeWorkbenchJsonBody(value, path) { if (isWorkbenchTerminalStatus(normalizedStatus)) counters.terminalStatusCount += 1; if (isWorkbenchRunningStatus(normalizedStatus)) counters.runningStatusCount += 1; } - if (isWorkbenchTerminalText(node)) counters.terminalTextCount += 1; + if (isWorkbenchTerminalText(node)) { + counters.terminalTextCount += 1; + for (const traceId of workbenchTraceIdsFromRecord(parent)) terminalTraceIds.add(traceId); + } if (isLikelyWorkbenchFinalTextField(key, parent, node)) { counters.finalTextFieldCount += 1; counters.finalTextByteCount += Buffer.byteLength(node); + for (const traceId of workbenchTraceIdsFromRecord(parent)) terminalTraceIds.add(traceId); } return; } @@ -3968,6 +3973,7 @@ function summarizeWorkbenchJsonBody(value, path) { } counters.objectCount += 1; const record = node; + const recordTraceIds = workbenchTraceIdsFromRecord(record); for (const raw of [record.traceId, record.trace_id, record.id, record.turnId, record.messageId]) { if (typeof raw === "string") collectWorkbenchIdsFromText(raw, traceIds, sessionIds); } @@ -3979,7 +3985,10 @@ function summarizeWorkbenchJsonBody(value, path) { const normalizedStatus = normalizeWorkbenchStatus("status", statusValue); if (normalizedStatus) { statusCounts[normalizedStatus] = (statusCounts[normalizedStatus] || 0) + 1; - if (isWorkbenchTerminalStatus(normalizedStatus)) counters.terminalStatusCount += 1; + if (isWorkbenchTerminalStatus(normalizedStatus)) { + counters.terminalStatusCount += 1; + for (const traceId of recordTraceIds) terminalTraceIds.add(traceId); + } if (isWorkbenchRunningStatus(normalizedStatus)) counters.runningStatusCount += 1; } } @@ -3992,6 +4001,7 @@ function summarizeWorkbenchJsonBody(value, path) { return { pathKind: workbenchBodyPathKind(path), traceIds: Array.from(traceIds).sort().slice(0, 12), + terminalTraceIds: Array.from(terminalTraceIds).sort().slice(0, 12), sessionIds: Array.from(sessionIds).sort().slice(0, 12), statusCounts, ...counters, @@ -4006,6 +4016,17 @@ function collectWorkbenchIdsFromText(value, traceIds, sessionIds) { for (const match of text.matchAll(/\bses_[A-Za-z0-9_-]+\b/gu)) sessionIds.add(match[0]); } +function workbenchTraceIdsFromRecord(record) { + if (!record || typeof record !== "object") return []; + const values = [record.traceId, record.trace_id, record.turnId, record.turn_id, record.messageId, record.message_id, record.id]; + const ids = new Set(); + for (const raw of values) { + if (typeof raw !== "string") continue; + for (const match of raw.matchAll(/\btrc_[A-Za-z0-9_-]+\b/gu)) ids.add(match[0]); + } + return Array.from(ids).sort(); +} + function normalizeWorkbenchStatus(key, value) { if (!/status|state|phase|result|lifecycle/iu.test(String(key || ""))) return null; const text = String(value || "").toLowerCase().replace(/[^a-z0-9_-]+/gu, "-").replace(/^-+|-+$/gu, "");