diff --git a/scripts/e2e/codex-npm-plugin-live-docker.sh b/scripts/e2e/codex-npm-plugin-live-docker.sh index bd5617ef928f..fa3320d55c5f 100644 --- a/scripts/e2e/codex-npm-plugin-live-docker.sh +++ b/scripts/e2e/codex-npm-plugin-live-docker.sh @@ -153,7 +153,7 @@ if ! docker_e2e_run_with_harness \ -e COREPACK_ENABLE_DOWNLOAD_PROMPT=0 \ -e OPENCLAW_CODEX_NPM_PLUGIN_ALLOW_BETA_COMPAT_DIAGNOSTICS="${OPENCLAW_CODEX_NPM_PLUGIN_ALLOW_BETA_COMPAT_DIAGNOSTICS:-0}" \ -e OPENCLAW_CODEX_NPM_PLUGIN_FORCE_UNSAFE_INSTALL="${OPENCLAW_CODEX_NPM_PLUGIN_FORCE_UNSAFE_INSTALL:-1}" \ - -e OPENCLAW_CODEX_NPM_PLUGIN_MODEL="${OPENCLAW_CODEX_NPM_PLUGIN_MODEL:-codex/gpt-5.4}" \ + -e OPENCLAW_CODEX_NPM_PLUGIN_MODEL="${OPENCLAW_CODEX_NPM_PLUGIN_MODEL:-openai/gpt-5.4}" \ -e OPENCLAW_CODEX_NPM_PLUGIN_SPEC="$CODEX_PLUGIN_SPEC" \ -e OPENCLAW_CODEX_NPM_PLUGIN_SESSION_STORE_CONTRACT="$SESSION_STORE_CONTRACT" \ -e "OPENCLAW_CODEX_NPM_PLUGIN_ASSERT_MAX_TEXT_FILE_BYTES=$ASSERT_MAX_TEXT_FILE_BYTES" \ @@ -201,7 +201,7 @@ fi CODEX_PLUGIN_SPEC="${OPENCLAW_CODEX_NPM_PLUGIN_SPEC:?missing OPENCLAW_CODEX_NPM_PLUGIN_SPEC}" MODEL_REF="${OPENCLAW_CODEX_NPM_PLUGIN_MODEL:?missing OPENCLAW_CODEX_NPM_PLUGIN_MODEL}" -POST_UNINSTALL_MODEL_REF="codex/${MODEL_REF#*/}" +POST_UNINSTALL_MODEL_REF="$MODEL_REF" SESSION_ID="codex-npm-plugin-live" SUCCESS_MARKER="OPENCLAW-CODEX-NPM-PLUGIN-LIVE-OK" AGENT_TURN_TIMEOUT_SECONDS="${OPENCLAW_CODEX_NPM_PLUGIN_AGENT_TIMEOUT_SECONDS:-420}" @@ -355,15 +355,11 @@ if openclaw agent --local \ --thinking low \ --timeout 120 \ --json >/tmp/openclaw-codex-agent-after-uninstall.json 2>/tmp/openclaw-codex-agent-after-uninstall.err; then - echo "Expected OpenClaw agent to fail after Codex uninstall, got status 0" >&2 - exit 1 -fi -if ! grep -Fq 'Requested agent harness "codex" is not registered' /tmp/openclaw-codex-agent-after-uninstall.err && - ! grep -Fq 'Unknown model: codex/' /tmp/openclaw-codex-agent-after-uninstall.err; then - echo "Unexpected post-uninstall agent error:" >&2 - tail -n 120 /tmp/openclaw-codex-agent-after-uninstall.err >&2 || true - exit 1 + post_uninstall_status=0 +else + post_uninstall_status=$? fi +node scripts/e2e/lib/codex-npm-plugin-live/assertions.mjs assert-agent-error "$post_uninstall_status" echo "Codex npm plugin live Docker E2E passed" EOF diff --git a/scripts/e2e/lib/codex-npm-plugin-live/assertions.mjs b/scripts/e2e/lib/codex-npm-plugin-live/assertions.mjs index df39c043b45a..1de2cbc45696 100644 --- a/scripts/e2e/lib/codex-npm-plugin-live/assertions.mjs +++ b/scripts/e2e/lib/codex-npm-plugin-live/assertions.mjs @@ -205,7 +205,7 @@ function readSessionEntry(sessionId) { } function configure() { - const modelRef = process.argv[3] || "codex/gpt-5.4"; + const modelRef = process.argv[3] || "openai/gpt-5.4"; const state = stateDir(); const cfgPath = configPath(); const cfg = fs.existsSync(cfgPath) ? readJson(cfgPath) : {}; diff --git a/test/scripts/codex-install-assertions.test.ts b/test/scripts/codex-install-assertions.test.ts index 5c3ec6a63852..e5999afd19ab 100644 --- a/test/scripts/codex-install-assertions.test.ts +++ b/test/scripts/codex-install-assertions.test.ts @@ -1,7 +1,7 @@ // Codex Install Assertions tests cover Codex plugin install E2E helpers. import { spawnSync } from "node:child_process"; import { createHash } from "node:crypto"; -import { chmodSync, mkdirSync, rmSync, writeFileSync } from "node:fs"; +import { chmodSync, mkdirSync, readFileSync, rmSync, writeFileSync } from "node:fs"; import os from "node:os"; import path from "node:path"; import { DatabaseSync } from "node:sqlite"; @@ -121,6 +121,19 @@ function runCodexNpmPluginLiveAssertions(params: { ); } +function runCodexNpmPluginLiveConfigure(root: string) { + return spawnSync(process.execPath, [CODEX_NPM_PLUGIN_LIVE_ASSERTIONS_SCRIPT, "configure"], { + encoding: "utf8", + env: { + ...process.env, + HOME: path.join(root, "home"), + NODE_OPTIONS: nodeOptionsWithoutExperimentalWarnings(), + OPENCLAW_CONFIG_PATH: path.join(root, "state", "openclaw.json"), + OPENCLAW_STATE_DIR: path.join(root, "state"), + }, + }); +} + function writeCodexBindingStateSqlite(params: { stateDir: string; sessionKey: string; @@ -237,10 +250,10 @@ function createCodexNpmPluginLiveFixture(root: string, storedSessionId?: string) const sessionId = "codex-npm-plugin-live"; const marker = "OPENCLAW-CODEX-NPM-PLUGIN-LIVE-OK"; const threadId = "thread-codex-npm-live"; - const modelRef = "codex/gpt-5.4"; + const modelRef = "openai/gpt-5.4"; writeJson("/tmp/openclaw-codex-agent.json", { payloads: [{ text: marker }], - meta: { executionTrace: { winnerProvider: "codex" } }, + meta: { executionTrace: { winnerProvider: "openai" } }, }); writeSessionStoreSqlite({ stateDir, @@ -323,6 +336,32 @@ function createCodexInstallFixture(root: string) { } describe("Codex install helpers", () => { + it("configures the canonical OpenAI model for the Codex runtime by default", () => { + const root = makeTempDir(tempDirs, "openclaw-codex-npm-configure-"); + + const result = runCodexNpmPluginLiveConfigure(root); + + expect(result.status).toBe(0); + expect(result.stderr).toBe(""); + const config = JSON.parse(readFileSync(path.join(root, "state", "openclaw.json"), "utf8")) as { + agents: { + defaults: { + model: { primary: string; fallbacks: string[] }; + models: Record; + }; + }; + }; + + expect(config.agents.defaults.model).toEqual({ + primary: "openai/gpt-5.4", + fallbacks: [], + }); + expect(config.agents.defaults.models).toMatchObject({ + "openai/gpt-5.4": { agentRuntime: { id: "codex" } }, + }); + expect(config.agents.defaults.models).not.toHaveProperty("codex/gpt-5.4"); + }); + it("resolves package roots and package manifests inside managed npm installs", () => { const root = makeTempDir(tempDirs, "openclaw-codex-install-utils-"); const packageRoot = path.join( diff --git a/test/scripts/docker-build-helper.test.ts b/test/scripts/docker-build-helper.test.ts index 8b4a9b52737b..45705f1eaf74 100644 --- a/test/scripts/docker-build-helper.test.ts +++ b/test/scripts/docker-build-helper.test.ts @@ -2754,7 +2754,11 @@ grep -Fxq preserved "$TMPDIR/caller-fd" expect(assertions).not.toContain('const content = fs.readFileSync(filePath, "utf8")'); expect(runner).toContain("docker_e2e_print_log /tmp/openclaw-codex-plugin-pack.log"); expect(runner).not.toContain("cat /tmp/openclaw-codex-plugin-pack.log"); - expect(runner).toContain("tail -n 120 /tmp/openclaw-codex-agent-after-uninstall.err"); + expect(assertions).toContain( + 'readTextFileTail(\n "/tmp/openclaw-codex-agent-after-uninstall.err",', + ); + expect(runner).toContain('assert-agent-error "$post_uninstall_status"'); + expect(runner).not.toContain("tail -n 120 /tmp/openclaw-codex-agent-after-uninstall.err"); expect(runner).not.toContain("cat /tmp/openclaw-codex-agent-after-uninstall.err"); const earlyAgentTimeoutEnvIndex = runner.indexOf( "docker_e2e_read_positive_int_env OPENCLAW_CODEX_NPM_PLUGIN_AGENT_TIMEOUT_SECONDS 420",