From 30e05211c14807a00ddfe6a32dff486454d45241 Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Sat, 2 May 2026 17:52:06 +0100 Subject: [PATCH] test: tolerate unavailable release agent turn --- scripts/openclaw-cross-os-release-checks.ts | 40 +++++++++++++----- .../openclaw-cross-os-release-checks.test.ts | 42 +++++++++++++++++++ 2 files changed, 72 insertions(+), 10 deletions(-) diff --git a/scripts/openclaw-cross-os-release-checks.ts b/scripts/openclaw-cross-os-release-checks.ts index 59ecd510284..12f10003e44 100644 --- a/scripts/openclaw-cross-os-release-checks.ts +++ b/scripts/openclaw-cross-os-release-checks.ts @@ -36,7 +36,7 @@ const SUPPORTED_SUITES = new Set([ export const CROSS_OS_AGENT_TURN_TIMEOUT_SECONDS = parsePositiveIntegerEnv( "OPENCLAW_CROSS_OS_AGENT_TURN_TIMEOUT_SECONDS", - 1200, + 600, ); const CROSS_OS_AGENT_TURN_OPTIONAL = parseBooleanEnv("OPENCLAW_CROSS_OS_AGENT_TURN_OPTIONAL", true); @@ -1962,11 +1962,11 @@ async function runInstalledAgentTurn(params) { return result; } catch (error) { lastError = error; + const skipped = maybeBuildOptionalAgentTurnSkipResult(error, params.logPath); + if (skipped) { + return skipped; + } if (attempt >= 2 || !shouldRetryCrossOsAgentTurnError(error)) { - const skipped = maybeBuildOptionalAgentTurnSkipResult(error, params.logPath); - if (skipped) { - return skipped; - } throw error; } appendFileSync( @@ -2763,11 +2763,11 @@ async function runAgentTurn(params) { return result; } catch (error) { lastError = error; + const skipped = maybeBuildOptionalAgentTurnSkipResult(error, params.logPath); + if (skipped) { + return skipped; + } if (attempt >= 2 || !shouldRetryCrossOsAgentTurnError(error)) { - const skipped = maybeBuildOptionalAgentTurnSkipResult(error, params.logPath); - if (skipped) { - return skipped; - } throw error; } appendFileSync( @@ -2782,7 +2782,7 @@ async function runAgentTurn(params) { } function maybeBuildOptionalAgentTurnSkipResult(error, logPath) { - if (!CROSS_OS_AGENT_TURN_OPTIONAL || !shouldRetryCrossOsAgentTurnError(error)) { + if (!CROSS_OS_AGENT_TURN_OPTIONAL || !shouldSkipOptionalCrossOsAgentTurnError(error, logPath)) { return null; } const message = error instanceof Error ? error.message : String(error); @@ -2800,6 +2800,26 @@ function maybeBuildOptionalAgentTurnSkipResult(error, logPath) { }; } +export function shouldSkipOptionalCrossOsAgentTurnError(error, logPath) { + const message = error instanceof Error ? error.message : String(error); + if ( + /model idle timeout|did not produce a response before the model idle timeout|gateway request timeout for agent|Command timed out|timed out and could not be terminated cleanly/u.test( + message, + ) + ) { + return true; + } + if (!/Agent output did not contain the expected OK marker/u.test(message)) { + return false; + } + try { + const log = readFileSync(logPath, "utf8"); + return /"status"\s*:\s*"timeout"|Request timed out before a response was generated/u.test(log); + } catch { + return false; + } +} + function buildReleaseAgentTurnArgs(sessionId) { return [ "agent", diff --git a/test/scripts/openclaw-cross-os-release-checks.test.ts b/test/scripts/openclaw-cross-os-release-checks.test.ts index 31d69a95ef5..8160b76feca 100644 --- a/test/scripts/openclaw-cross-os-release-checks.test.ts +++ b/test/scripts/openclaw-cross-os-release-checks.test.ts @@ -56,6 +56,7 @@ import { shouldStopManagedGatewayBeforeManualFallback, shouldRunMainChannelDevUpdate, shouldRetryCrossOsAgentTurnError, + shouldSkipOptionalCrossOsAgentTurnError, shouldUseManagedGatewayForInstallerRuntime, shouldUseManagedGatewayService, verifyDevUpdateStatus, @@ -124,6 +125,47 @@ describe("scripts/openclaw-cross-os-release-checks", () => { ).toBe(true); }); + it("skips optional live agent turns only for model availability failures", () => { + const dir = mkdtempSync(join(tmpdir(), "openclaw-cross-os-agent-skip-")); + try { + const logPath = join(dir, "agent.log"); + writeFileSync( + logPath, + JSON.stringify({ + status: "timeout", + result: { + payloads: [ + { + text: "Request timed out before a response was generated.", + }, + ], + }, + }), + ); + + expect( + shouldSkipOptionalCrossOsAgentTurnError( + new Error("Agent output did not contain the expected OK marker."), + logPath, + ), + ).toBe(true); + expect( + shouldSkipOptionalCrossOsAgentTurnError( + new Error("document-extract: failed to install bundled runtime deps"), + logPath, + ), + ).toBe(false); + expect( + shouldSkipOptionalCrossOsAgentTurnError( + new Error("Agent output did not contain the expected OK marker."), + join(dir, "missing.log"), + ), + ).toBe(false); + } finally { + rmSync(dir, { recursive: true, force: true }); + } + }); + it("allows cross-OS provider smoke models to use faster CI overrides", () => { expect( resolveProviderConfig("openai", {