test: tolerate unavailable release agent turn

This commit is contained in:
Peter Steinberger
2026-05-02 17:52:06 +01:00
parent e5851cfcc2
commit 30e05211c1
2 changed files with 72 additions and 10 deletions

View File

@@ -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",

View File

@@ -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", {