























@@ -275,6 +275,12 @@ type WhatsAppCredentialLease = Awaited<
275275ReturnType<typeof acquireQaCredentialLease<WhatsAppQaRuntimeEnv>>
276276>;
277277type WhatsAppCredentialHeartbeat = ReturnType<typeof startQaCredentialLeaseHeartbeat>;
278+type WhatsAppQaPreScenarioPhase =
279+| "auth archive unpack"
280+| "credential heartbeat start"
281+| "credential lease acquisition"
282+| "driver session start"
283+| "scenario execution";
278284279285const WHATSAPP_QA_CAPTURE_CONTENT_ENV = "OPENCLAW_QA_WHATSAPP_CAPTURE_CONTENT";
280286const QA_REDACT_PUBLIC_METADATA_ENV = "OPENCLAW_QA_REDACT_PUBLIC_METADATA";
@@ -2890,6 +2896,12 @@ function redactWhatsAppQaScenarioResults(
2890289628912897const SAFE_WHATSAPP_DRIVER_DIAGNOSTICS_PATTERN =
28922898/observed \d+ WhatsApp driver message\(s\) after (?:(?:pending|resolved) approval )?wait lower bound(?:: [-A-Za-z0-9_#:=()., +;/]+)?/u;
2899+const SAFE_WHATSAPP_PRE_SCENARIO_FAILURE_PATTERN =
2900+/^WhatsApp QA failed during (?:auth archive unpack|credential heartbeat start|credential lease acquisition|driver session start|scenario execution)$/u;
2901+2902+function formatWhatsAppPreScenarioFailureLabel(phase: WhatsAppQaPreScenarioPhase) {
2903+return `WhatsApp QA failed during ${phase}`;
2904+}
2893290528942906function isRedactionSafeWhatsAppScenarioDetailSegment(segment: string) {
28952907return (
@@ -2901,6 +2913,13 @@ function isRedactionSafeWhatsAppScenarioDetailSegment(segment: string) {
2901291329022914function redactWhatsAppQaScenarioDetails(details: string) {
29032915const normalized = details.trim();
2916+const firstLine = normalized.split(/\r?\n/u, 1)[0] ?? "";
2917+const separatorIndex = firstLine.indexOf(":");
2918+const preScenarioFailureLabel =
2919+separatorIndex < 0 ? firstLine.trim() : firstLine.slice(0, separatorIndex).trim();
2920+if (SAFE_WHATSAPP_PRE_SCENARIO_FAILURE_PATTERN.test(preScenarioFailureLabel)) {
2921+return preScenarioFailureLabel;
2922+}
29042923const safeDriverDiagnostics = normalized.match(SAFE_WHATSAPP_DRIVER_DIAGNOSTICS_PATTERN);
29052924if (safeDriverDiagnostics) {
29062925return safeDriverDiagnostics[0];
@@ -3051,6 +3070,7 @@ export async function runWhatsAppQaLive(params: {
30513070let runtimeEnv: WhatsAppQaRuntimeEnv | undefined;
30523071let tempAuthRoot: string | undefined;
30533072let closeDriverSession: (() => Promise<void>) | undefined;
3073+let preScenarioPhase: WhatsAppQaPreScenarioPhase = "credential lease acquisition";
3054307430553075try {
30563076credentialLease = await acquireQaCredentialLease({
@@ -3060,6 +3080,7 @@ export async function runWhatsAppQaLive(params: {
30603080resolveEnvPayload: () => resolveWhatsAppQaRuntimeEnv(),
30613081parsePayload: parseWhatsAppQaCredentialPayload,
30623082});
3083+preScenarioPhase = "credential heartbeat start";
30633084leaseHeartbeat = startQaCredentialLeaseHeartbeat(credentialLease);
30643085const assertLeaseHealthy = () => {
30653086leaseHeartbeat?.throwIfFailed();
@@ -3068,6 +3089,7 @@ export async function runWhatsAppQaLive(params: {
30683089tempAuthRoot = await fs.mkdtemp(
30693090path.join(resolvePreferredOpenClawTmpDir(), "openclaw-whatsapp-qa-"),
30703091);
3092+preScenarioPhase = "auth archive unpack";
30713093const [driverAuthDir, sutAuthDir] = await Promise.all([
30723094unpackWhatsAppAuthArchive({
30733095archiveBase64: runtimeEnv.driverAuthArchiveBase64,
@@ -3080,8 +3102,10 @@ export async function runWhatsAppQaLive(params: {
30803102parentDir: tempAuthRoot,
30813103}),
30823104]);
3105+preScenarioPhase = "driver session start";
30833106let activeDriver = await startWhatsAppQaDriverSessionWithRetry({ authDir: driverAuthDir });
30843107closeDriverSession = () => activeDriver.close();
3108+preScenarioPhase = "scenario execution";
3085310930863110for (const [scenarioIndex, scenario] of scenarios.entries()) {
30873111const progressIndex = scenarioIndex + 1;
@@ -3207,9 +3231,10 @@ export async function runWhatsAppQaLive(params: {
32073231}
32083232}
32093233} catch (error) {
3210-appendLiveLaneIssue(cleanupIssues, "WhatsApp QA failed before scenario completion", error);
3234+const failureLabel = formatWhatsAppPreScenarioFailureLabel(preScenarioPhase);
3235+appendLiveLaneIssue(cleanupIssues, failureLabel, error);
32113236appendPreScenarioFailureResults({
3212-details: formatErrorMessage(error),
3237+details: `${failureLabel}: ${formatErrorMessage(error)}`,
32133238 scenarioResults,
32143239 scenarios,
32153240});
@@ -3320,6 +3345,7 @@ export const testing = {
33203345 findUnexpectedWhatsAppNoReplyMessage,
33213346 formatWhatsAppApprovalWaitDiagnostics,
33223347 formatWhatsAppBatchMessageDiagnostics,
3348+ formatWhatsAppPreScenarioFailureLabel,
33233349 formatWhatsAppScenarioProgressDetails,
33243350 formatWhatsAppScenarioProgressLine,
33253351fingerprintWhatsAppCredentialId: fingerprintQaCredentialId,
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。