diff --git a/scripts/web-live-dom-probe.mjs b/scripts/web-live-dom-probe.mjs index 9acd7e7e..c27d5065 100644 --- a/scripts/web-live-dom-probe.mjs +++ b/scripts/web-live-dom-probe.mjs @@ -608,6 +608,10 @@ async function createFreshSession(page, args, actions) { } const shellReady = await waitForSessionShellReady(page, args, actions); const before = await collectSessionState(page); + if (before.messageCount === 0 && before.command?.inputDisabled === false) { + actions.push({ action: "fresh-session", selector, reusedExistingEmptySession: true, shellReady, before }); + return true; + } await locator.click(); const timeoutMs = Math.min(args.timeoutMs, 30000); const settled = await page.waitForFunction((initial) => { @@ -689,8 +693,10 @@ async function sampleTraceTimeline(page, args, actions) { async function collectTraceTimelineSample(page, index) { return page.evaluate((sampleIndex) => { + const cardRole = (card) => card.getAttribute("data-role") ?? card.getAttribute("data-message-role") ?? [...card.classList].find((item) => item === "message-agent" || item === "message-user" || item === "message-system")?.replace(/^message-/, "") ?? null; + const cardStatus = (card) => card.getAttribute("data-status") ?? card.getAttribute("data-message-status") ?? null; const cards = [...document.querySelectorAll(".message-card")]; - const latestAgent = [...cards].reverse().find((card) => card.getAttribute("data-message-role") === "agent" || card.classList.contains("message-agent")); + const latestAgent = [...cards].reverse().find((card) => cardRole(card) === "agent" || card.classList.contains("message-agent")); const trace = latestAgent?.querySelector(".trace-timeline") ?? null; const details = trace?.querySelector("details") ?? null; const rows = latestAgent ? [...latestAgent.querySelectorAll(".trace-render-row")] : []; @@ -701,7 +707,7 @@ async function collectTraceTimelineSample(page, index) { index: sampleIndex, sampledAt: new Date().toISOString(), messageCount: cards.length, - agentStatus: latestAgent?.getAttribute("data-message-status") ?? null, + agentStatus: latestAgent ? cardStatus(latestAgent) : null, tracePresent: Boolean(trace), traceStatus: trace?.getAttribute("data-status") ?? null, traceOpen: details instanceof HTMLDetailsElement ? details.open : null, @@ -822,10 +828,12 @@ async function waitForAgentTerminal(page, args, actions) { const timeoutMs = Math.min(args.waitAgentTerminalMs, args.timeoutMs); const before = await collectLatestAgentMessageState(page); const terminal = await page.waitForFunction(() => { + const cardRole = (card) => card.getAttribute("data-role") ?? card.getAttribute("data-message-role") ?? [...card.classList].find((item) => item === "message-agent" || item === "message-user" || item === "message-system")?.replace(/^message-/, "") ?? null; + const cardStatus = (card) => card.getAttribute("data-status") ?? card.getAttribute("data-message-status") ?? null; const cards = [...document.querySelectorAll(".message-card")]; - const latestAgent = [...cards].reverse().find((card) => card.getAttribute("data-message-role") === "agent" || card.classList.contains("message-agent")); + const latestAgent = [...cards].reverse().find((card) => cardRole(card) === "agent" || card.classList.contains("message-agent")); if (!latestAgent) return false; - const status = latestAgent.getAttribute("data-message-status") ?? ""; + const status = cardStatus(latestAgent) ?? ""; const finalResponse = latestAgent.querySelector(".message-final-response"); const text = finalResponse?.textContent?.trim() ?? ""; return status && status !== "running" && text.length > 0; @@ -837,12 +845,14 @@ async function waitForAgentTerminal(page, args, actions) { async function collectLatestAgentMessageState(page) { return page.evaluate(() => { + const cardRole = (card) => card.getAttribute("data-role") ?? card.getAttribute("data-message-role") ?? [...card.classList].find((item) => item === "message-agent" || item === "message-user" || item === "message-system")?.replace(/^message-/, "") ?? null; + const cardStatus = (card) => card.getAttribute("data-status") ?? card.getAttribute("data-message-status") ?? null; const cards = [...document.querySelectorAll(".message-card")]; - const latestAgent = [...cards].reverse().find((card) => card.getAttribute("data-message-role") === "agent" || card.classList.contains("message-agent")); + const latestAgent = [...cards].reverse().find((card) => cardRole(card) === "agent" || card.classList.contains("message-agent")); const finalResponse = latestAgent?.querySelector(".message-final-response"); return { messageCount: cards.length, - status: latestAgent?.getAttribute("data-message-status") ?? null, + status: latestAgent ? cardStatus(latestAgent) : null, textChars: finalResponse?.textContent?.trim().length ?? 0, textPreview: (finalResponse?.textContent ?? "").replace(/\s+/gu, " ").trim().slice(0, 240) }; @@ -851,6 +861,8 @@ async function collectLatestAgentMessageState(page) { async function collectDomEvidence(page, args) { return page.evaluate(async ({ projectId }) => { + const cardRole = (card) => card.getAttribute("data-role") ?? card.getAttribute("data-message-role") ?? [...card.classList].find((item) => item === "message-user" || item === "message-agent" || item === "message-system")?.replace(/^message-/, "") ?? null; + const cardStatus = (card) => card.getAttribute("data-status") ?? card.getAttribute("data-message-status") ?? null; const workspace = document.querySelector("#workspace"); const list = document.querySelector("#conversation-list"); const cards = [...document.querySelectorAll(".message-card")]; @@ -889,19 +901,19 @@ async function collectDomEvidence(page, args) { conversationsCount: conversations.length }, messageCount: cards.length, - messageRoles: cards.map((card) => card.getAttribute("data-message-role") ?? [...card.classList].find((item) => item === "message-user" || item === "message-agent" || item === "message-system") ?? "unknown"), + messageRoles: cards.map((card) => cardRole(card) ?? "unknown"), messages: cards.map((card) => { - const trace = card.querySelector(".message-trace"); - const traceEvents = card.querySelector(".message-trace-events"); - const finalResponse = card.querySelector(".message-final-response"); + const trace = card.querySelector(".trace-timeline, .message-trace"); + const traceEvents = card.querySelector(".trace-disclosure-body ol, .message-trace-events"); + const finalResponse = card.querySelector(".message-final-response, .message-text"); const traceStyle = traceEvents ? getComputedStyle(traceEvents) : null; const finalStyle = finalResponse ? getComputedStyle(finalResponse) : null; const traceRect = traceEvents?.getBoundingClientRect(); const finalRect = finalResponse?.getBoundingClientRect(); const finalBody = finalResponse?.querySelector(".message-body"); return { - status: card.getAttribute("data-message-status") ?? null, - role: card.getAttribute("data-message-role") ?? [...card.classList].find((item) => item === "message-user" || item === "message-agent" || item === "message-system")?.replace(/^message-/, "") ?? null, + status: cardStatus(card), + role: cardRole(card), className: card.className, trace: trace ? { present: true,