fix: make codex harness live test portable

This commit is contained in:
Peter Steinberger
2026-05-13 08:16:07 +01:00
parent 984981832e
commit f5be0d1406
4 changed files with 41 additions and 2 deletions

View File

@@ -11,6 +11,7 @@ Docs: https://docs.openclaw.ai
- Telegram: detect polling stalls from `getUpdates` liveness only, so outbound API calls no longer mask dead inbound polling; log polling-cycle starts after transport rebuilds. Fixes #78473.
- fix(plugins): scan installed dependency runtime code [AI]. (#81066) Thanks @pgondhi987.
- Inherit tool restrictions for delegated sessions [AI]. (#80979) Thanks @pgondhi987.
- Codex harness: make the live test wrapper portable to Windows and defer locked temp cleanup so native Windows and WSL2 live runs complete.
- Telegram: discard legacy long-poll update offsets that cannot be tied to the current bot token, so token rotation no longer leaves bots silently skipping new messages. (#80671) Thanks @sxxtony.
- browser: enforce navigation checks for act interactions [AI]. (#81070) Thanks @pgondhi987.
- Validate node exec event provenance [AI]. (#81071) Thanks @pgondhi987.

View File

@@ -1643,7 +1643,7 @@
"test:install:smoke": "bash scripts/test-install-sh-docker.sh",
"test:live": "node scripts/test-live.mjs",
"test:live:cache": "node --import tsx scripts/check-live-cache.ts",
"test:live:codex-harness": "OPENCLAW_LIVE_CODEX_HARNESS=1 node scripts/test-live.mjs -- src/gateway/gateway-codex-harness.live.test.ts",
"test:live:codex-harness": "node scripts/test-live.mjs --codex-harness -- src/gateway/gateway-codex-harness.live.test.ts",
"test:live:crestodian-rescue-channel": "OPENCLAW_LIVE_CRESTODIAN_RESCUE_CHANNEL=1 node scripts/test-live.mjs -- src/crestodian/rescue-channel.live.test.ts",
"test:live:gateway-profiles": "node scripts/test-live.mjs -- src/gateway/gateway-models.profiles.live.test.ts",
"test:live:media": "node --import tsx scripts/test-live-media.ts",

View File

@@ -2,11 +2,16 @@ import { spawnPnpmRunner } from "./pnpm-runner.mjs";
const forwardedArgs = [];
let quietOverride;
let forceCodexHarness = false;
for (const arg of process.argv.slice(2)) {
if (arg === "--") {
continue;
}
if (arg === "--codex-harness") {
forceCodexHarness = true;
continue;
}
if (arg === "--quiet" || arg === "--quiet-live") {
quietOverride = "1";
continue;
@@ -25,6 +30,7 @@ const env = {
pnpm_config_verify_deps_before_run: process.env.pnpm_config_verify_deps_before_run || "false",
OPENCLAW_LIVE_TEST: process.env.OPENCLAW_LIVE_TEST || "1",
OPENCLAW_LIVE_TEST_QUIET: quietOverride ?? process.env.OPENCLAW_LIVE_TEST_QUIET ?? "1",
...(forceCodexHarness ? { OPENCLAW_LIVE_CODEX_HARNESS: "1" } : {}),
};
function parsePositiveInt(value, fallback) {

View File

@@ -162,6 +162,31 @@ async function createLiveWorkspace(tempDir: string): Promise<string> {
return workspace;
}
async function removeLiveTempDir(dir: string): Promise<void> {
let lastError: unknown;
for (let attempt = 0; attempt < 100; attempt += 1) {
try {
await fs.rm(dir, { recursive: true, force: true });
return;
} catch (error) {
lastError = error;
const code = (error as { code?: unknown } | null)?.code;
if (code !== "EBUSY" && code !== "ENOTEMPTY" && code !== "EPERM" && code !== "EACCES") {
throw error;
}
await delay(100);
}
}
if (process.platform === "win32") {
logCodexLiveStep("temp-cleanup-deferred", {
dir,
error: lastError instanceof Error ? lastError.message : String(lastError),
});
return;
}
await fs.rm(dir, { recursive: true, force: true });
}
function parseModelKey(modelKey: string): { provider: string; modelId: string } {
const [provider, ...modelParts] = modelKey.split("/");
const modelId = modelParts.join("/");
@@ -935,8 +960,15 @@ describeLive("gateway live (Codex harness)", () => {
clearRuntimeConfigSnapshot();
await client.stopAndWait();
await server.close();
const [{ resetTaskRegistryForTests }, { resetTaskFlowRegistryForTests }] =
await Promise.all([
import("../tasks/runtime-internal.js"),
import("../tasks/task-flow-runtime-internal.js"),
]);
resetTaskRegistryForTests({ persist: false });
resetTaskFlowRegistryForTests({ persist: false });
restoreEnv(previousEnv);
await fs.rm(tempDir, { recursive: true, force: true, maxRetries: 5, retryDelay: 100 });
await removeLiveTempDir(tempDir);
}
},
CODEX_HARNESS_TIMEOUT_MS,