fix: polish hwpod groups and performance probes (#1494)

This commit is contained in:
Lyon
2026-06-18 17:19:03 +08:00
committed by GitHub
parent 1cdf262a80
commit 60d1de1dd7
5 changed files with 361 additions and 16 deletions
+34 -9
View File
@@ -311,6 +311,17 @@ export async function runProbe(args) {
}
};
} catch (error) {
const finalUrl = page ? page.url() : null;
const failureDom = page ? await collectFailureDomEvidence(page).catch((domError) => ({ error: domError instanceof Error ? domError.message : String(domError) })) : null;
let screenshotCapture = null;
if (page && !page.isClosed()) {
try {
await page.screenshot({ path: screenshotPath, fullPage: true });
screenshotCapture = { ok: true };
} catch (screenshotError) {
screenshotCapture = { ok: false, error: screenshotError instanceof Error ? screenshotError.message : String(screenshotError) };
}
}
result = {
ok: false,
status: "blocked",
@@ -322,10 +333,10 @@ export async function runProbe(args) {
actions,
credentials: args.credentials,
error: error instanceof Error ? error.message : String(error),
degradedReason: classifyRunProbeError(error),
finalUrl: page ? page.url() : null,
failureDom: page ? await collectFailureDomEvidence(page).catch((domError) => ({ error: domError instanceof Error ? domError.message : String(domError) })) : null,
artifacts: { reportPath, screenshotPath }
degradedReason: classifyRunProbeError(error, { finalUrl, failureDom }),
finalUrl,
failureDom,
artifacts: { reportPath, screenshotPath, screenshotCapture }
};
} finally {
if (browser) await browser.close().catch(() => {});
@@ -889,12 +900,16 @@ async function submitPrompt(page, args, actions) {
const targetConversationId = firstNonEmpty(fresh?.alignment?.check?.conversationId, fresh?.alignment?.after?.routeConversationId, fresh?.after?.routeConversationId);
if (targetConversationId) await ensureConversationAligned(page, args, targetConversationId, actions, "pre-submit-realign");
await page.locator("#command-input").fill(args.message);
await page.waitForFunction((expected) => {
const enabled = await page.waitForFunction((expected) => {
const input = document.querySelector("#command-input");
const send = document.querySelector("#command-send");
return input?.value === expected && send && !send.disabled;
}, args.message, { timeout: Math.min(args.timeoutMs, 5000) });
}, args.message, { timeout: Math.min(args.timeoutMs, 5000) }).catch(() => null);
const afterFill = await collectCommandState(page);
if (!enabled) {
const session = await collectSessionState(page, args).catch((error) => ({ error: error instanceof Error ? error.message : String(error) }));
throw new Error(`command composer is not ready for submit: ${JSON.stringify({ readyBefore, afterFill, session: compactSessionState(session) })}`);
}
const submittedAt = new Date().toISOString();
await page.locator("#command-send").click();
const afterClick = await collectCommandState(page);
@@ -1132,8 +1147,14 @@ function runProbeDegradedReason({ traceSummary, sessionSummary, promptValidation
return null;
}
function classifyRunProbeError(error) {
function classifyRunProbeError(error, context = {}) {
const message = error instanceof Error ? error.message : String(error);
const finalUrl = typeof context.finalUrl === "string" ? context.finalUrl : "";
const failureDom = context.failureDom && typeof context.failureDom === "object" ? context.failureDom : {};
const login = failureDom.login && typeof failureDom.login === "object" ? failureDom.login : {};
if (/\/login(?:\?|$)/u.test(finalUrl) || failureDom.authState === "login" || login.cardVisible === true) return "auth-redirect-login";
if (/session_required|session-not-selected/u.test(message)) return "session-not-selected";
if (/composer|command-send|command bar|disabledReason|button_disabled/u.test(message)) return "composer-disabled";
if (/fresh session/u.test(message)) return "fresh-session-not-aligned";
if (/login|auth/u.test(message)) return "auth-login-failed";
if (/Timeout|timed out|timeout/u.test(message)) return "browser-timeout";
@@ -1159,12 +1180,13 @@ async function waitForCommandReady(page, args, actions) {
const ready = await page.waitForFunction(() => {
const input = document.querySelector("#command-input");
const send = document.querySelector("#command-send");
return Boolean(input && send && !input.disabled);
const warning = document.querySelector(".composer-warning")?.textContent?.trim() ?? "";
return Boolean(input && send && !input.disabled && !warning);
}, null, { timeout: timeoutMs }).catch(() => null);
const after = await collectCommandState(page);
const result = { action: "command-ready", ready: Boolean(ready), timeoutMs, before, after };
actions.push(result);
if (!ready) throw new Error(`command bar is not ready for submit: ${JSON.stringify(result)}`);
if (!ready) throw new Error(`command composer is not ready for submit: ${JSON.stringify(result)}`);
return after;
}
@@ -1179,6 +1201,9 @@ async function collectCommandState(page) {
inputLength: input && typeof input.value === "string" ? input.value.length : null,
sendVisible: Boolean(send),
sendDisabled: send ? Boolean(send.disabled) : null,
sendAction: send?.getAttribute("data-action") ?? null,
disabledReason: document.querySelector(".composer-warning")?.textContent?.trim() ?? null,
modeText: document.querySelector(".composer-mode")?.textContent?.trim() ?? null,
sendText: send?.textContent?.trim() ?? null,
formTitle: form?.getAttribute("title") ?? null,
messageCount: document.querySelectorAll(".message-card").length,