fix(web-probe): attribute final responses by trace role (#763)

Co-authored-by: Codex <codex@noreply.local>
This commit is contained in:
Lyon
2026-06-24 00:36:37 +08:00
committed by GitHub
parent 5673a9e39b
commit 3b6190959b
@@ -5293,11 +5293,12 @@ function buildRoundCompletionMetrics(samples, timeline, turnTiming) {
const timelineItem = timeline[index] || {};
for (const event of roundCompletionEventsForSample(sample, timelineItem)) events.push(event);
}
const completionEvents = dedupeRoundCompletionEvents(events);
const elapsedMismatches = [];
const finalResponseMissing = [];
const postCompletionTimingChanges = [];
const postCompletionRecentUpdateVisible = [];
for (const event of events) {
for (const event of completionEvents) {
const sampleIndex = samples.findIndex((sample) => sample?.seq === event.seq && sample?.pageRole === event.pageRole && sample?.pageId === event.pageId);
const sameSample = sampleIndex >= 0 ? samples[sampleIndex] : null;
const sameTimelineItem = sampleIndex >= 0 ? timeline[sampleIndex] || {} : {};
@@ -5318,10 +5319,11 @@ function buildRoundCompletionMetrics(samples, timeline, turnTiming) {
});
}
}
if (!hasFinalResponseAfterCompletion(samples, timeline, event)) {
if (!(sameSample && sampleHasTerminalAgentResultCard(sameSample, event)) && !(sameSample && sampleHasVisibleFinalResponse(sameSample, event)) && !hasFinalResponseAfterCompletion(samples, timeline, event)) {
finalResponseMissing.push({
...eventRef(event),
completionElapsedSeconds: event.elapsedSeconds,
finalResponseProbe: sameSample ? terminalAgentResultProbe(sameSample, event) : { ok: false, reason: "sample-not-found" },
valuesRedacted: true
});
}
@@ -5330,7 +5332,7 @@ function buildRoundCompletionMetrics(samples, timeline, turnTiming) {
postCompletionRecentUpdateVisible.push(...postTiming.recentUpdateVisible);
}
return {
events: dedupeRoundCompletionRows(events).slice(0, 200),
events: completionEvents.slice(0, 200),
elapsedMismatches: dedupeRoundCompletionRows(elapsedMismatches).slice(0, 200),
finalResponseMissing: dedupeRoundCompletionRows(finalResponseMissing).slice(0, 200),
postCompletionTimingChanges: dedupeRoundCompletionRows(postCompletionTimingChanges).slice(0, 200),
@@ -5414,17 +5416,65 @@ function hasFinalResponseAfterCompletion(samples, timeline, event) {
if (sampleSession && eventSession && sampleSession !== eventSession) continue;
const promptIndex = timeline[index]?.promptIndex ?? 0;
if (!event.traceId && !event.messageId && event.promptIndex && promptIndex !== event.promptIndex) continue;
if (sampleHasTerminalAgentResultCard(sample, event)) return true;
if (sampleHasVisibleFinalResponse(sample, event)) return true;
}
return false;
}
function sampleHasTerminalAgentResultCard(sample, event = {}) {
return terminalAgentResultProbe(sample, event).ok === true;
}
function terminalAgentResultProbe(sample, event = {}) {
const decisions = [];
for (const item of codeAgentCardsForSample(sample)) {
const text = normalizedText(codeAgentCardText(item));
const traceMatched = Boolean(event.traceId && item?.traceId && item.traceId === event.traceId);
const decision = {
source: item?.source || null,
role: item?.role ?? null,
dataRole: item?.dataRole ?? null,
status: item?.status ?? null,
traceId: item?.traceId ?? null,
messageId: item?.messageId ?? null,
textBytes: Buffer.byteLength(text),
valuesRedacted: true
};
if (event.traceId && item?.traceId && item.traceId !== event.traceId) {
decisions.push({ ...decision, decision: "skip-trace" });
continue;
}
if (!traceMatched && event.messageId && item?.messageId && item.messageId !== event.messageId) {
decisions.push({ ...decision, decision: "skip-message" });
continue;
}
if (!isAssistantFinalResponseCandidate(item, item?.source || "turn")) {
decisions.push({ ...decision, decision: "skip-role" });
continue;
}
if (!isCodeAgentCardTerminal(item)) {
decisions.push({ ...decision, decision: "skip-non-terminal" });
continue;
}
if (text.length < 24) {
decisions.push({ ...decision, decision: "skip-short" });
continue;
}
decisions.push({ ...decision, decision: "accept-terminal-agent-card" });
return { ok: true, decisions: decisions.slice(-8), valuesRedacted: true };
}
return { ok: false, decisions: decisions.slice(-8), valuesRedacted: true };
}
function sampleHasVisibleFinalResponse(sample, event = {}) {
for (const [groupName, group] of [["messages", sample?.messages], ["turns", sample?.turns]]) {
if (!Array.isArray(group)) continue;
for (const item of group) {
const traceMatched = Boolean(event.traceId && item?.traceId && item.traceId === event.traceId);
if (event.traceId && item?.traceId && item.traceId !== event.traceId) continue;
if (event.messageId && item?.messageId && item.messageId !== event.messageId) continue;
if (!traceMatched && event.messageId && item?.messageId && item.messageId !== event.messageId) continue;
if (!isAssistantFinalResponseCandidate(item, groupName)) continue;
const text = normalizedText([item?.text, item?.textPreview].filter(Boolean).join(" "));
if (text.length < 24) continue;
if (groupName === "messages" && isTerminalTurnStatus(item?.status)) return true;
@@ -5436,6 +5486,23 @@ function sampleHasVisibleFinalResponse(sample, event = {}) {
return false;
}
function normalizedDomRole(item) {
return String(item?.dataRole ?? item?.role ?? item?.ariaRole ?? "")
.trim()
.toLowerCase()
.replace(/[_\s]+/gu, "-");
}
function isAssistantFinalResponseCandidate(item, groupName) {
const role = normalizedDomRole(item);
if (/agent|assistant|code-agent|bot/iu.test(role)) return true;
if (/user|human|client|prompt/iu.test(role)) return false;
if (groupName === "turns") return isCodeAgentCardLike(item);
const text = codeAgentCardText(item);
if (isTerminalTurnStatus(item?.status) && /Code Agent||assistant|agent/iu.test(text)) return true;
return false;
}
function detectPostCompletionTimingChanges(turnTiming, event) {
const timingChanges = [];
const recentUpdateVisible = [];
@@ -5520,6 +5587,26 @@ function detectPostCompletionTimingChanges(turnTiming, event) {
return { timingChanges, recentUpdateVisible };
}
function dedupeRoundCompletionEvents(rows) {
const result = [];
const seen = new Set();
for (const row of Array.isArray(rows) ? rows : []) {
const key = [
row?.pageRole ?? "",
row?.pageId ?? "",
row?.promptIndex ?? "",
row?.traceId ?? "",
row?.messageId ?? "",
row?.textHash ?? "",
row?.elapsedSeconds ?? ""
].join("|");
if (seen.has(key)) continue;
seen.add(key);
result.push(row);
}
return result;
}
function eventRef(event) {
return {
seq: event?.seq ?? null,
@@ -5531,6 +5618,7 @@ function eventRef(event) {
activeSessionId: event?.activeSessionId ?? null,
promptIndex: event?.promptIndex ?? null,
traceId: event?.traceId ?? null,
messageId: event?.messageId ?? null,
};
}