From 86b429ae2d83e0351486b7b5359f537586d15c03 Mon Sep 17 00:00:00 2001 From: Lyon <88232613+pikasTech@users.noreply.github.com> Date: Mon, 22 Jun 2026 18:33:56 +0800 Subject: [PATCH] fix: scope web-probe final flicker analysis (#670) Co-authored-by: Codex --- .../hwlab-node-web-observe-runner-source.ts | 35 ++++++++++++++++--- 1 file changed, 31 insertions(+), 4 deletions(-) diff --git a/scripts/src/hwlab-node-web-observe-runner-source.ts b/scripts/src/hwlab-node-web-observe-runner-source.ts index 6318841b..897366f4 100644 --- a/scripts/src/hwlab-node-web-observe-runner-source.ts +++ b/scripts/src/hwlab-node-web-observe-runner-source.ts @@ -3662,18 +3662,45 @@ function buildTransitions(samples) { function detectFinalFlicker(samples) { const flickers = []; - let lastNonEmpty = null; + const lastNonEmptyByScope = new Map(); for (const sample of samples) { + const scope = finalFlickerScope(sample); + if (!scope) continue; const messageText = Array.isArray(sample.messages) ? sample.messages.map((item) => item.textPreview || "").join("\n") : ""; const nonEmpty = messageText.trim().length > 0; const finalLike = /轮次完成|已记录|已完成第\d+轮|final response|terminal result/iu.test(messageText); - if (nonEmpty && finalLike && !/temporarily|timeout|无法连接|暂时|error|failed|超时/iu.test(messageText)) lastNonEmpty = { sample, messageText }; - if (lastNonEmpty && nonEmpty && /temporarily|timeout|无法连接|暂时|error|failed|超时/iu.test(messageText)) flickers.push({ from: ref(lastNonEmpty.sample), to: ref(sample) }); - if (lastNonEmpty && !nonEmpty) flickers.push({ from: ref(lastNonEmpty.sample), to: ref(sample), reason: "text-disappeared" }); + const diagnosticLike = /temporarily|timeout|无法连接|暂时|error|failed|超时/iu.test(messageText); + const lastNonEmpty = lastNonEmptyByScope.get(scope); + if (nonEmpty && finalLike && !diagnosticLike) lastNonEmptyByScope.set(scope, { sample, messageText }); + if (lastNonEmpty && nonEmpty && diagnosticLike) flickers.push({ scope, from: ref(lastNonEmpty.sample), to: ref(sample) }); + if (lastNonEmpty && !nonEmpty) flickers.push({ scope, from: ref(lastNonEmpty.sample), to: ref(sample), reason: "text-disappeared" }); } return flickers; } +function finalFlickerScope(sample) { + const pathname = samplePathname(sample); + const sessionId = sample?.routeSessionId || sample?.activeSessionId || workbenchSessionIdFromPath(pathname); + if (!sessionId) return null; + if (!pathname.startsWith(`/workbench/sessions/${sessionId}`)) return null; + return `${sample?.pageRole || "control"}:${sessionId}`; +} + +function samplePathname(sample) { + const raw = String(sample?.path || sample?.url || "").trim(); + if (!raw) return ""; + try { + return new URL(raw, "http://hwlab.local").pathname || raw; + } catch { + return raw.split(/[?#]/u, 1)[0] || raw; + } +} + +function workbenchSessionIdFromPath(pathname) { + const match = String(pathname || "").match(/^\/workbench\/sessions\/([^/?#]+)/u); + return match ? match[1] : null; +} + function detectTerminalZeroElapsed(samples) { const rows = []; for (const sample of samples) {