From fb106fb9aef25967c22b6d8780116587eb8d6192 Mon Sep 17 00:00:00 2001 From: pashpashpash Date: Thu, 7 May 2026 20:10:41 -0700 Subject: [PATCH] fix codex harness service tiers (#79152) --- .../openclaw-live-and-e2e-checks-reusable.yml | 8 +-- CHANGELOG.md | 2 +- docs/plugins/codex-harness.md | 4 +- extensions/codex/openclaw.plugin.json | 4 +- extensions/codex/package.json | 2 +- .../auth-profile-runtime-contract.test.ts | 1 + .../codex/src/app-server/config.test.ts | 19 +++++- extensions/codex/src/app-server/config.ts | 28 +++++++-- .../json/v2/ThreadResumeResponse.json | 22 +++---- .../json/v2/ThreadStartResponse.json | 22 +++---- extensions/codex/src/app-server/protocol.ts | 1 + .../run-attempt.context-engine.test.ts | 1 + .../codex/src/app-server/run-attempt.test.ts | 15 ++--- ...ema-normalization-runtime-contract.test.ts | 26 ++++++++- .../src/app-server/session-binding.test.ts | 20 +++++++ .../codex/src/app-server/session-binding.ts | 3 +- extensions/codex/src/app-server/version.ts | 2 +- extensions/codex/src/command-handlers.ts | 4 +- .../codex/src/conversation-binding.test.ts | 12 ++-- .../codex/src/conversation-control.test.ts | 2 +- extensions/codex/src/conversation-control.ts | 5 +- extensions/openai/cli-backend.ts | 6 +- pnpm-lock.yaml | 58 +++++++++---------- scripts/check-codex-app-server-protocol.ts | 2 +- scripts/docs-i18n/translator.go | 2 +- scripts/docs-i18n/translator_test.go | 2 +- scripts/test-live-cli-backend-docker.sh | 2 +- src/agents/cli-backends.test.ts | 12 ++-- .../package-acceptance-workflow.test.ts | 2 +- 29 files changed, 176 insertions(+), 113 deletions(-) diff --git a/.github/workflows/openclaw-live-and-e2e-checks-reusable.yml b/.github/workflows/openclaw-live-and-e2e-checks-reusable.yml index e389e5fef45d..4a9f0d6cb2a9 100644 --- a/.github/workflows/openclaw-live-and-e2e-checks-reusable.yml +++ b/.github/workflows/openclaw-live-and-e2e-checks-reusable.yml @@ -2135,8 +2135,8 @@ jobs: # inside the already-isolated container to keep MCP cron/tool # execution representative instead of failing on nested sandbox # setup. - echo 'OPENCLAW_LIVE_CLI_BACKEND_ARGS=["exec","--json","--color","never","--sandbox","danger-full-access","-c","service_tier=\"fast\"","--skip-git-repo-check"]' >> "$GITHUB_ENV" - echo 'OPENCLAW_LIVE_CLI_BACKEND_RESUME_ARGS=["exec","resume","{sessionId}","-c","sandbox_mode=\"danger-full-access\"","-c","service_tier=\"fast\"","--skip-git-repo-check"]' >> "$GITHUB_ENV" + echo 'OPENCLAW_LIVE_CLI_BACKEND_ARGS=["exec","--json","--color","never","--sandbox","danger-full-access","-c","service_tier=\"priority\"","--skip-git-repo-check"]' >> "$GITHUB_ENV" + echo 'OPENCLAW_LIVE_CLI_BACKEND_RESUME_ARGS=["exec","resume","{sessionId}","-c","sandbox_mode=\"danger-full-access\"","-c","service_tier=\"priority\"","--skip-git-repo-check"]' >> "$GITHUB_ENV" echo "OPENCLAW_LIVE_CLI_BACKEND_DEBUG=1" >> "$GITHUB_ENV" echo "OPENCLAW_CLI_BACKEND_LOG_OUTPUT=1" >> "$GITHUB_ENV" echo "OPENCLAW_TEST_CONSOLE=1" >> "$GITHUB_ENV" @@ -2354,8 +2354,8 @@ jobs: live-cli-backend-docker) echo "OPENCLAW_LIVE_CLI_BACKEND_MODEL=codex-cli/gpt-5.4" >> "$GITHUB_ENV" echo "OPENCLAW_LIVE_CLI_BACKEND_AUTH=api-key" >> "$GITHUB_ENV" - echo 'OPENCLAW_LIVE_CLI_BACKEND_ARGS=["exec","--json","--color","never","--sandbox","danger-full-access","-c","service_tier=\"fast\"","--skip-git-repo-check"]' >> "$GITHUB_ENV" - echo 'OPENCLAW_LIVE_CLI_BACKEND_RESUME_ARGS=["exec","resume","{sessionId}","-c","sandbox_mode=\"danger-full-access\"","-c","service_tier=\"fast\"","--skip-git-repo-check"]' >> "$GITHUB_ENV" + echo 'OPENCLAW_LIVE_CLI_BACKEND_ARGS=["exec","--json","--color","never","--sandbox","danger-full-access","-c","service_tier=\"priority\"","--skip-git-repo-check"]' >> "$GITHUB_ENV" + echo 'OPENCLAW_LIVE_CLI_BACKEND_RESUME_ARGS=["exec","resume","{sessionId}","-c","sandbox_mode=\"danger-full-access\"","-c","service_tier=\"priority\"","--skip-git-repo-check"]' >> "$GITHUB_ENV" echo "OPENCLAW_LIVE_CLI_BACKEND_DEBUG=1" >> "$GITHUB_ENV" echo "OPENCLAW_CLI_BACKEND_LOG_OUTPUT=1" >> "$GITHUB_ENV" echo "OPENCLAW_TEST_CONSOLE=1" >> "$GITHUB_ENV" diff --git a/CHANGELOG.md b/CHANGELOG.md index c84eb5c3f957..13be662eff99 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,7 +11,7 @@ Docs: https://docs.openclaw.ai - Telegram: preserve the channel-specific 10-option poll cap in the unified outbound adapter so over-limit polls are rejected before send. (#78762) Thanks @obviyus. - Runtime/install: raise the supported Node 22 floor to `22.16+` so native SQLite query handling can rely on the `node:sqlite` statement metadata API while continuing to recommend Node 24. (#78921) - Discord/voice: include a bounded one-line STT transcript preview in verbose voice logs so live voice debugging shows what speakers said before the agent reply. -- Codex app-server: pin the managed Codex harness and Codex CLI smoke package to `@openai/codex@0.129.0-alpha.15` and defer OpenClaw integration dynamic tools behind Codex tool search by default, saving roughly 5.5k upfront dynamic-tool tokens on source-reply Codex turns while keeping `codexDynamicToolsLoading: "direct"` as a compatibility escape hatch. +- Codex app-server: pin the managed Codex harness and Codex CLI smoke package to `@openai/codex@0.129.0`, defer OpenClaw integration dynamic tools behind Codex tool search by default, and accept current Codex service-tier values so legacy `fast` settings survive the stable harness upgrade as `priority`. - Discord/voice: stream ElevenLabs TTS directly into Discord playback and send ElevenLabs latency optimization as the documented query parameter so spoken replies can start sooner. - Discord/voice: keep TTS playback running when another user starts speaking, ignore new capture during playback to avoid feedback loops, and downgrade expected receive-stream aborts to verbose diagnostics. - Telegram: treat successful same-chat `message` tool outbound sends during an inbound telegram turn as delivered when deciding whether to emit the rewritten silent reply fallback (#78685). Thanks @neeravmakwana. diff --git a/docs/plugins/codex-harness.md b/docs/plugins/codex-harness.md index 49ddfc1df879..38da5f67f84d 100644 --- a/docs/plugins/codex-harness.md +++ b/docs/plugins/codex-harness.md @@ -498,7 +498,7 @@ To opt in to Codex guardian-reviewed approvals, set `appServer.mode: config: { appServer: { mode: "guardian", - serviceTier: "fast", + serviceTier: "priority", }, }, }, @@ -650,7 +650,7 @@ Supported `appServer` fields: | `approvalPolicy` | `"never"` | Native Codex approval policy sent to thread start/resume/turn. | | `sandbox` | `"danger-full-access"` | Native Codex sandbox mode sent to thread start/resume. | | `approvalsReviewer` | `"user"` | Use `"auto_review"` to let Codex review native approval prompts. `guardian_subagent` remains a legacy alias. | -| `serviceTier` | unset | Optional Codex app-server service tier: `"fast"`, `"flex"`, or `null`. Invalid legacy values are ignored. | +| `serviceTier` | unset | Optional Codex app-server service tier. `"priority"` enables fast-mode routing, `"flex"` requests flex processing, `null` clears the override, and legacy `"fast"` is accepted as `"priority"`. | OpenClaw-owned dynamic tool calls are bounded independently from `appServer.requestTimeoutMs`: each Codex `item/tool/call` request must receive diff --git a/extensions/codex/openclaw.plugin.json b/extensions/codex/openclaw.plugin.json index e13aebf3f6fe..1367f6427136 100644 --- a/extensions/codex/openclaw.plugin.json +++ b/extensions/codex/openclaw.plugin.json @@ -188,7 +188,7 @@ "type": "string", "enum": ["user", "auto_review", "guardian_subagent"] }, - "serviceTier": { "type": ["string", "null"], "enum": ["fast", "flex", null] }, + "serviceTier": { "type": ["string", "null"] }, "defaultWorkspaceDir": { "type": "string" } @@ -363,7 +363,7 @@ }, "appServer.serviceTier": { "label": "Service Tier", - "help": "Optional Codex app-server service tier. Use fast, flex, or null.", + "help": "Optional Codex app-server service tier. Use priority, flex, or null. Legacy fast is accepted as priority.", "advanced": true }, "appServer.defaultWorkspaceDir": { diff --git a/extensions/codex/package.json b/extensions/codex/package.json index 41b4b0b3abaf..2394d5be68b7 100644 --- a/extensions/codex/package.json +++ b/extensions/codex/package.json @@ -9,7 +9,7 @@ "type": "module", "dependencies": { "@mariozechner/pi-coding-agent": "0.73.0", - "@openai/codex": "0.129.0-alpha.15", + "@openai/codex": "0.129.0", "ajv": "^8.20.0", "ws": "^8.20.0" }, diff --git a/extensions/codex/src/app-server/auth-profile-runtime-contract.test.ts b/extensions/codex/src/app-server/auth-profile-runtime-contract.test.ts index 3addb3353df5..6269bc432f92 100644 --- a/extensions/codex/src/app-server/auth-profile-runtime-contract.test.ts +++ b/extensions/codex/src/app-server/auth-profile-runtime-contract.test.ts @@ -35,6 +35,7 @@ function threadStartResult(threadId = "thread-auth-contract") { return { thread: { id: threadId, + sessionId: "session-1", forkedFromId: null, preview: "", ephemeral: false, diff --git a/extensions/codex/src/app-server/config.test.ts b/extensions/codex/src/app-server/config.test.ts index 90585e623aa7..4b36fcdd4daf 100644 --- a/extensions/codex/src/app-server/config.test.ts +++ b/extensions/codex/src/app-server/config.test.ts @@ -82,14 +82,14 @@ describe("Codex app-server config", () => { ); }); - it("drops invalid legacy service tiers without discarding the rest of the config", () => { + it("normalizes legacy service tiers without discarding the rest of the config", () => { const runtime = resolveCodexAppServerRuntimeOptions({ pluginConfig: { appServer: { mode: "guardian", approvalPolicy: "on-request", sandbox: "read-only", - serviceTier: "priority", + serviceTier: "fast", }, }, env: {}, @@ -100,9 +100,22 @@ describe("Codex app-server config", () => { approvalPolicy: "on-request", sandbox: "read-only", approvalsReviewer: "auto_review", + serviceTier: "priority", }), ); - expect(runtime).not.toHaveProperty("serviceTier"); + }); + + it("passes through non-empty Codex app-server service tiers for forward compatibility", () => { + const runtime = resolveCodexAppServerRuntimeOptions({ + pluginConfig: { + appServer: { + serviceTier: "batch-preview", + }, + }, + env: {}, + }); + + expect(runtime.serviceTier).toBe("batch-preview"); }); it("rejects malformed plugin config instead of treating freeform strings as control values", () => { diff --git a/extensions/codex/src/app-server/config.ts b/extensions/codex/src/app-server/config.ts index 2ffac0d81ccd..e3134637147c 100644 --- a/extensions/codex/src/app-server/config.ts +++ b/extensions/codex/src/app-server/config.ts @@ -188,8 +188,8 @@ const codexDynamicToolsProfileSchema = z.enum(["native-first", "openclaw-compat" const codexDynamicToolsLoadingSchema = z.enum(["searchable", "direct"]); const codexAppServerServiceTierSchema = z .preprocess( - (value) => (value === null ? null : resolveServiceTier(value)), - z.enum(["fast", "flex"]).nullable().optional(), + (value) => (value === null ? null : normalizeCodexServiceTier(value)), + z.string().trim().min(1).nullable().optional(), ) .optional(); @@ -327,7 +327,7 @@ export function resolveCodexAppServerRuntimeOptions( resolvePolicyMode(config.mode) ?? resolvePolicyMode(env.OPENCLAW_CODEX_APP_SERVER_MODE) ?? "yolo"; - const serviceTier = resolveServiceTier(config.serviceTier); + const serviceTier = normalizeCodexServiceTier(config.serviceTier); if (transport === "websocket" && !url) { throw new Error( "plugins.entries.codex.config.appServer.url is required when appServer.transport is websocket", @@ -523,8 +523,26 @@ function resolveApprovalsReviewer(value: unknown): CodexAppServerApprovalsReview : undefined; } -function resolveServiceTier(value: unknown): CodexServiceTier | undefined { - return value === "fast" || value === "flex" ? value : undefined; +export function normalizeCodexServiceTier(value: unknown): CodexServiceTier | undefined { + if (typeof value !== "string") { + return undefined; + } + const trimmed = value.trim(); + if (!trimmed) { + return undefined; + } + const normalized = trimmed.toLowerCase(); + if (normalized === "fast" || normalized === "priority") { + return "priority"; + } + if (normalized === "flex") { + return "flex"; + } + return trimmed; +} + +export function isCodexFastServiceTier(value: unknown): boolean { + return normalizeCodexServiceTier(value) === "priority"; } function normalizePositiveNumber(value: unknown, fallback: number): number { diff --git a/extensions/codex/src/app-server/protocol-generated/json/v2/ThreadResumeResponse.json b/extensions/codex/src/app-server/protocol-generated/json/v2/ThreadResumeResponse.json index d4800805328f..540e6d7d6349 100644 --- a/extensions/codex/src/app-server/protocol-generated/json/v2/ThreadResumeResponse.json +++ b/extensions/codex/src/app-server/protocol-generated/json/v2/ThreadResumeResponse.json @@ -83,13 +83,9 @@ ] }, "serviceTier": { - "anyOf": [ - { - "$ref": "#/definitions/ServiceTier" - }, - { - "type": "null" - } + "type": [ + "string", + "null" ] }, "thread": { @@ -1273,13 +1269,6 @@ } ] }, - "ServiceTier": { - "type": "string", - "enum": [ - "fast", - "flex" - ] - }, "SessionSource": { "oneOf": [ { @@ -1429,6 +1418,7 @@ "id", "modelProvider", "preview", + "sessionId", "source", "status", "turns", @@ -1513,6 +1503,10 @@ "description": "Usually the first user message in the thread, if available.", "type": "string" }, + "sessionId": { + "description": "Session id shared by threads that belong to the same session tree.", + "type": "string" + }, "source": { "description": "Origin of the thread (CLI, VSCode, codex exec, codex app-server, etc.).", "allOf": [ diff --git a/extensions/codex/src/app-server/protocol-generated/json/v2/ThreadStartResponse.json b/extensions/codex/src/app-server/protocol-generated/json/v2/ThreadStartResponse.json index f052ccbe76d4..5be568c051ce 100644 --- a/extensions/codex/src/app-server/protocol-generated/json/v2/ThreadStartResponse.json +++ b/extensions/codex/src/app-server/protocol-generated/json/v2/ThreadStartResponse.json @@ -83,13 +83,9 @@ ] }, "serviceTier": { - "anyOf": [ - { - "$ref": "#/definitions/ServiceTier" - }, - { - "type": "null" - } + "type": [ + "string", + "null" ] }, "thread": { @@ -1273,13 +1269,6 @@ } ] }, - "ServiceTier": { - "type": "string", - "enum": [ - "fast", - "flex" - ] - }, "SessionSource": { "oneOf": [ { @@ -1429,6 +1418,7 @@ "id", "modelProvider", "preview", + "sessionId", "source", "status", "turns", @@ -1513,6 +1503,10 @@ "description": "Usually the first user message in the thread, if available.", "type": "string" }, + "sessionId": { + "description": "Session id shared by threads that belong to the same session tree.", + "type": "string" + }, "source": { "description": "Origin of the thread (CLI, VSCode, codex exec, codex app-server, etc.).", "allOf": [ diff --git a/extensions/codex/src/app-server/protocol.ts b/extensions/codex/src/app-server/protocol.ts index 2036a79a890b..6142db6628ef 100644 --- a/extensions/codex/src/app-server/protocol.ts +++ b/extensions/codex/src/app-server/protocol.ts @@ -140,6 +140,7 @@ export type CodexTurn = { export type CodexThread = { id: string; + sessionId?: string; name?: string | null; cwd?: string | null; }; diff --git a/extensions/codex/src/app-server/run-attempt.context-engine.test.ts b/extensions/codex/src/app-server/run-attempt.context-engine.test.ts index a088abc2c886..b7e3d8cce082 100644 --- a/extensions/codex/src/app-server/run-attempt.context-engine.test.ts +++ b/extensions/codex/src/app-server/run-attempt.context-engine.test.ts @@ -67,6 +67,7 @@ function threadStartResult(threadId = "thread-1") { return { thread: { id: threadId, + sessionId: "session-1", forkedFromId: null, preview: "", ephemeral: false, diff --git a/extensions/codex/src/app-server/run-attempt.test.ts b/extensions/codex/src/app-server/run-attempt.test.ts index 00b40b9cf5a2..dbf0693d27c2 100644 --- a/extensions/codex/src/app-server/run-attempt.test.ts +++ b/extensions/codex/src/app-server/run-attempt.test.ts @@ -87,6 +87,7 @@ function threadStartResult(threadId = "thread-1") { return { thread: { id: threadId, + sessionId: "session-1", forkedFromId: null, preview: "", ephemeral: false, @@ -4006,7 +4007,7 @@ describe("runCodexAppServerAttempt", () => { approvalPolicy: "on-request", approvalsReviewer: "guardian_subagent", sandbox: "danger-full-access", - serviceTier: "fast", + serviceTier: "priority", developerInstructions: expect.stringContaining(CODEX_GPT5_BEHAVIOR_CONTRACT), persistExtendedHistory: true, }); @@ -4018,7 +4019,7 @@ describe("runCodexAppServerAttempt", () => { approvalPolicy: "on-request", approvalsReviewer: "guardian_subagent", sandboxPolicy: { type: "dangerFullAccess" }, - serviceTier: "fast", + serviceTier: "priority", model: "gpt-5.4-codex", }), }, @@ -4026,7 +4027,7 @@ describe("runCodexAppServerAttempt", () => { ); }); - it("drops invalid legacy service tiers before app-server resume and turn requests", async () => { + it("passes current Codex service tier request values through app-server resume and turn requests", async () => { const sessionFile = path.join(tempDir, "session.jsonl"); const workspaceDir = path.join(tempDir, "workspace"); await writeExistingBinding(sessionFile, workspaceDir, { model: "gpt-5.2" }); @@ -4046,13 +4047,9 @@ describe("runCodexAppServerAttempt", () => { await run; const resumeRequest = requests.find((request) => request.method === "thread/resume"); - expect(resumeRequest?.params).toEqual( - expect.not.objectContaining({ serviceTier: expect.anything() }), - ); + expect(resumeRequest?.params).toEqual(expect.objectContaining({ serviceTier: "priority" })); const turnRequest = requests.find((request) => request.method === "turn/start"); - expect(turnRequest?.params).toEqual( - expect.not.objectContaining({ serviceTier: expect.anything() }), - ); + expect(turnRequest?.params).toEqual(expect.objectContaining({ serviceTier: "priority" })); }); it("keys plugin app inventory by websocket credentials without exposing them", () => { diff --git a/extensions/codex/src/app-server/schema-normalization-runtime-contract.test.ts b/extensions/codex/src/app-server/schema-normalization-runtime-contract.test.ts index 1eaf50766454..b66a9bd69c42 100644 --- a/extensions/codex/src/app-server/schema-normalization-runtime-contract.test.ts +++ b/extensions/codex/src/app-server/schema-normalization-runtime-contract.test.ts @@ -49,10 +49,11 @@ function createAppServerOptions(): Parameters[0]["ap }; } -function threadStartResult(threadId = "thread-1") { +function threadStartResult(threadId = "thread-1", serviceTier: string | null = null) { return { thread: { id: threadId, + sessionId: "session-1", forkedFromId: null, preview: "", ephemeral: false, @@ -72,7 +73,7 @@ function threadStartResult(threadId = "thread-1") { }, model: "gpt-5.4", modelProvider: "openai", - serviceTier: null, + serviceTier, cwd: tempDir, instructionSources: [], approvalPolicy: "never", @@ -125,6 +126,27 @@ describe("Codex app-server dynamic tool schema boundary contract", () => { ); }); + it("accepts Codex app-server priority service tier responses", async () => { + const sessionFile = path.join(tempDir, "session.jsonl"); + const workspaceDir = path.join(tempDir, "workspace"); + const request = vi.fn(async (method: string) => { + if (method === "thread/start") { + return threadStartResult("thread-priority", "priority"); + } + throw new Error(`unexpected method: ${method}`); + }); + + const binding = await startOrResumeThread({ + client: { request } as never, + params: createParams(sessionFile, workspaceDir), + cwd: workspaceDir, + dynamicTools: [], + appServer: createAppServerOptions(), + }); + + expect(binding.threadId).toBe("thread-priority"); + }); + it("treats dynamic tool schema changes as thread-fingerprint changes", async () => { const sessionFile = path.join(tempDir, "session.jsonl"); const workspaceDir = path.join(tempDir, "workspace"); diff --git a/extensions/codex/src/app-server/session-binding.test.ts b/extensions/codex/src/app-server/session-binding.test.ts index e771c56f19bd..9a41542d533b 100644 --- a/extensions/codex/src/app-server/session-binding.test.ts +++ b/extensions/codex/src/app-server/session-binding.test.ts @@ -172,6 +172,26 @@ describe("codex app-server session binding", () => { expect(binding?.modelProvider).toBeUndefined(); }); + it("normalizes legacy fast service tier bindings to Codex priority", async () => { + const sessionFile = path.join(tempDir, "session.json"); + await fs.writeFile( + resolveCodexAppServerBindingPath(sessionFile), + `${JSON.stringify({ + schemaVersion: 1, + threadId: "thread-123", + sessionFile, + cwd: tempDir, + serviceTier: "fast", + createdAt: "2026-05-03T00:00:00.000Z", + updatedAt: "2026-05-03T00:00:00.000Z", + })}\n`, + ); + + const binding = await readCodexAppServerBinding(sessionFile); + + expect(binding?.serviceTier).toBe("priority"); + }); + it("does not infer native Codex auth from the profile id prefix", async () => { const sessionFile = path.join(tempDir, "session.json"); await writeCodexAppServerBinding( diff --git a/extensions/codex/src/app-server/session-binding.ts b/extensions/codex/src/app-server/session-binding.ts index 4074d8213f69..392db234834b 100644 --- a/extensions/codex/src/app-server/session-binding.ts +++ b/extensions/codex/src/app-server/session-binding.ts @@ -8,6 +8,7 @@ import { } from "openclaw/plugin-sdk/agent-runtime"; import { CODEX_PLUGINS_MARKETPLACE_NAME, + normalizeCodexServiceTier, type CodexAppServerApprovalPolicy, type CodexAppServerSandboxMode, } from "./config.js"; @@ -311,5 +312,5 @@ function readSandboxMode(value: unknown): CodexAppServerSandboxMode | undefined } function readServiceTier(value: unknown): CodexServiceTier | undefined { - return value === "fast" || value === "flex" ? value : undefined; + return normalizeCodexServiceTier(value); } diff --git a/extensions/codex/src/app-server/version.ts b/extensions/codex/src/app-server/version.ts index 1b07ad3c7dfd..da75c4d13af9 100644 --- a/extensions/codex/src/app-server/version.ts +++ b/extensions/codex/src/app-server/version.ts @@ -1,3 +1,3 @@ export const MIN_CODEX_APP_SERVER_VERSION = "0.125.0"; export const MANAGED_CODEX_APP_SERVER_PACKAGE = "@openai/codex"; -export const MANAGED_CODEX_APP_SERVER_PACKAGE_VERSION = "0.129.0-alpha.15"; +export const MANAGED_CODEX_APP_SERVER_PACKAGE_VERSION = "0.129.0"; diff --git a/extensions/codex/src/command-handlers.ts b/extensions/codex/src/command-handlers.ts index 4dcbf577c7e3..a02576c65621 100644 --- a/extensions/codex/src/command-handlers.ts +++ b/extensions/codex/src/command-handlers.ts @@ -6,7 +6,7 @@ import { readCodexComputerUseStatus, type CodexComputerUseSetupParams, } from "./app-server/computer-use.js"; -import type { CodexComputerUseConfig } from "./app-server/config.js"; +import { isCodexFastServiceTier, type CodexComputerUseConfig } from "./app-server/config.js"; import { listAllCodexAppServerModels } from "./app-server/models.js"; import { isJsonObject, type JsonValue } from "./app-server/protocol.js"; import { rememberCodexRateLimits } from "./app-server/rate-limit-cache.js"; @@ -447,7 +447,7 @@ async function describeConversationBinding( `- Thread: ${formatCodexDisplayText(threadBinding?.threadId ?? "unknown")}`, `- Workspace: ${formatCodexDisplayText(data.workspaceDir)}`, `- Model: ${formatCodexDisplayText(threadBinding?.model ?? "default")}`, - `- Fast: ${threadBinding?.serviceTier === "fast" ? "on" : "off"}`, + `- Fast: ${isCodexFastServiceTier(threadBinding?.serviceTier) ? "on" : "off"}`, `- Permissions: ${threadBinding ? formatPermissionsMode(threadBinding) : "default"}`, `- Active run: ${formatCodexDisplayText(active ? active.turnId : "none")}`, `- Session: ${formatCodexDisplayText(data.sessionFile)}`, diff --git a/extensions/codex/src/conversation-binding.test.ts b/extensions/codex/src/conversation-binding.test.ts index 1d0b4b2839ee..b143d3023bfe 100644 --- a/extensions/codex/src/conversation-binding.test.ts +++ b/extensions/codex/src/conversation-binding.test.ts @@ -78,7 +78,7 @@ describe("codex conversation binding", () => { request: vi.fn(async (method: string, requestParams: Record) => { requests.push({ method, params: requestParams }); return { - thread: { id: "thread-new", cwd: tempDir }, + thread: { id: "thread-new", sessionId: "session-1", cwd: tempDir }, model: "gpt-5.4-mini", }; }), @@ -138,7 +138,7 @@ describe("codex conversation binding", () => { request: vi.fn(async (method: string, requestParams: Record) => { requests.push({ method, params: requestParams }); return { - thread: { id: "thread-new", cwd: tempDir }, + thread: { id: "thread-new", sessionId: "session-1", cwd: tempDir }, model: "gpt-5.4-mini", modelProvider: "openai", }; @@ -261,7 +261,7 @@ describe("codex conversation binding", () => { } if (method === "thread/start") { return { - thread: { id: "thread-new", cwd: tempDir }, + thread: { id: "thread-new", sessionId: "session-1", cwd: tempDir }, model: "gpt-5.4-mini", }; } @@ -340,13 +340,13 @@ describe("codex conversation binding", () => { model: "gpt-5.4-mini", approvalPolicy: "on-request", sandbox: "workspace-write", - serviceTier: "fast", + serviceTier: "priority", }); expect(requests[1]?.params).not.toHaveProperty("modelProvider"); expect(requests[2]?.params).toMatchObject({ threadId: "thread-new", approvalPolicy: "on-request", - serviceTier: "fast", + serviceTier: "priority", }); const savedBinding = JSON.parse( await fs.readFile(`${sessionFile}.codex-app-server.json`, "utf8"), @@ -356,7 +356,7 @@ describe("codex conversation binding", () => { authProfileId: "work", approvalPolicy: "on-request", sandbox: "workspace-write", - serviceTier: "fast", + serviceTier: "priority", }); expect(savedBinding).not.toHaveProperty("modelProvider"); }); diff --git a/extensions/codex/src/conversation-control.test.ts b/extensions/codex/src/conversation-control.test.ts index e5e9a7fced70..460227542973 100644 --- a/extensions/codex/src/conversation-control.test.ts +++ b/extensions/codex/src/conversation-control.test.ts @@ -55,7 +55,7 @@ describe("codex conversation controls", () => { await expect(readCodexAppServerBinding(sessionFile)).resolves.toMatchObject({ threadId: "thread-1", - serviceTier: "fast", + serviceTier: "priority", approvalPolicy: "on-request", sandbox: "workspace-write", }); diff --git a/extensions/codex/src/conversation-control.ts b/extensions/codex/src/conversation-control.ts index 8fedfb295d03..e64682530555 100644 --- a/extensions/codex/src/conversation-control.ts +++ b/extensions/codex/src/conversation-control.ts @@ -1,5 +1,6 @@ import { CODEX_CONTROL_METHODS } from "./app-server/capabilities.js"; import { + isCodexFastServiceTier, resolveCodexAppServerRuntimeOptions, type CodexAppServerApprovalPolicy, type CodexAppServerSandboxMode, @@ -139,9 +140,9 @@ export async function setCodexConversationFastMode(params: { }): Promise { const binding = await requireThreadBinding(params.sessionFile); if (params.enabled == null) { - return `Codex fast mode: ${binding.serviceTier === "fast" ? "on" : "off"}.`; + return `Codex fast mode: ${isCodexFastServiceTier(binding.serviceTier) ? "on" : "off"}.`; } - const serviceTier: CodexServiceTier = params.enabled ? "fast" : "flex"; + const serviceTier: CodexServiceTier = params.enabled ? "priority" : "flex"; // Fast mode is sent on each later turn; do not require Codex to accept an // immediate thread/resume control request just to persist the preference. await writeCodexAppServerBinding(params.sessionFile, { diff --git a/extensions/openai/cli-backend.ts b/extensions/openai/cli-backend.ts index 8818f14e7683..79a6988adff7 100644 --- a/extensions/openai/cli-backend.ts +++ b/extensions/openai/cli-backend.ts @@ -5,7 +5,7 @@ import { } from "openclaw/plugin-sdk/cli-backend"; const CODEX_CLI_DEFAULT_MODEL_REF = "codex-cli/gpt-5.5"; -const CODEX_CLI_NPM_PACKAGE = "@openai/codex@0.129.0-alpha.15"; +const CODEX_CLI_NPM_PACKAGE = "@openai/codex@0.129.0"; export function buildOpenAICodexCliBackend(): CliBackendPlugin { return { @@ -32,7 +32,7 @@ export function buildOpenAICodexCliBackend(): CliBackendPlugin { "--sandbox", "workspace-write", "-c", - 'service_tier="fast"', + 'service_tier="priority"', "--skip-git-repo-check", ], resumeArgs: [ @@ -42,7 +42,7 @@ export function buildOpenAICodexCliBackend(): CliBackendPlugin { "-c", 'sandbox_mode="workspace-write"', "-c", - 'service_tier="fast"', + 'service_tier="priority"', "--skip-git-repo-check", ], output: "jsonl", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 687c402bcc45..4d16ebc67ad0 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -496,8 +496,8 @@ importers: specifier: 0.73.0 version: 0.73.0(@modelcontextprotocol/sdk@1.29.0(zod@4.4.3))(ws@8.20.0)(zod@4.4.3) '@openai/codex': - specifier: 0.129.0-alpha.15 - version: 0.129.0-alpha.15 + specifier: 0.129.0 + version: 0.129.0 ajv: specifier: ^8.20.0 version: 8.20.0 @@ -3198,43 +3198,43 @@ packages: resolution: {integrity: sha512-tlc/FcYIv5i8RYsl2iDil4A0gOihaas1R5jPcIC4Zw3GhjKsVilw90aHcVlhZPTBLGBzd379S+VcnsDjd9ChiA==} engines: {node: '>=12.4.0'} - '@openai/codex@0.129.0-alpha.15': - resolution: {integrity: sha512-OQLHP6rjcINfe/L0N/u9q/f0XhbV4JmzgWeEgks03gLQZuI/G0CPO2gVfJk27Eg8UEhEdz0YyeIuPCZP293XDg==} + '@openai/codex@0.129.0': + resolution: {integrity: sha512-8zZlcO4ploUzULJ3xT5qx8eOCL/L7gOrpWXCtr2kP568idZjWhbz3L2WE8BvjBDUF17WMDhjOklCj6DGd1cKfQ==} engines: {node: '>=16'} hasBin: true - '@openai/codex@0.129.0-alpha.15-darwin-arm64': - resolution: {integrity: sha512-w4hHyBuasNrewr1cNRUcwWWXgTrLPYCtFJl+YvpADdgFw0iA1xlymRASfCf5BCkKdonW427tL0pD/jYBkOJnsQ==} + '@openai/codex@0.129.0-darwin-arm64': + resolution: {integrity: sha512-tVFwzbh612oip/yZMeQziMtUWLz08A8ChhS6U/bNZjCKWD11bQvDZjxZJNzhWvmom/gKeXstwoUp9u1S8eCcnA==} engines: {node: '>=16'} cpu: [arm64] os: [darwin] - '@openai/codex@0.129.0-alpha.15-darwin-x64': - resolution: {integrity: sha512-G35Mr4pxUm9Lqe88uycW8dlGNW0SDu+/oQSvlYFYfNeLAjlmLPZ1hpraQoLMiQHc649F9SA+mEtSNfkKs+jB4A==} + '@openai/codex@0.129.0-darwin-x64': + resolution: {integrity: sha512-BtGc4ujzxRVIB0DcpiehP7/aQeAGEi0pNd9C98rtIqy1OBMwhOZ3ri/achzP0lxw8LWWFp8sL+hQdTGze6SGwg==} engines: {node: '>=16'} cpu: [x64] os: [darwin] - '@openai/codex@0.129.0-alpha.15-linux-arm64': - resolution: {integrity: sha512-HXFTHxj51vZtBgtsO7RL6v/nbB3K+Hkp71pJqgWR3qGsY00nNeM40bx1e0P0SS6VkCBJEHVE6i3y9yaIFhZMtg==} + '@openai/codex@0.129.0-linux-arm64': + resolution: {integrity: sha512-VnjI4Xla4uwaAqYCekwBm4dlucvaduTdhVr3bqU+6qfG5N9yn1bR7ZS7xMRlaRgS0oIst9fgYyC2niSYPOzuDA==} engines: {node: '>=16'} cpu: [arm64] os: [linux] - '@openai/codex@0.129.0-alpha.15-linux-x64': - resolution: {integrity: sha512-0UNw7e+BW5gXNsdg7Y/hoim9rrAL+bsKXGUXODsX+aPYRBpLOZT/SDlj/a3wvXk4uzxQ2OQWZqmk3E/VNNo/4g==} + '@openai/codex@0.129.0-linux-x64': + resolution: {integrity: sha512-YwkJtcHXeXdI+cfdv7qKGfafwePEEbSCRL5Z++/8djnI+iBj6nIMz4ouhe12yvsMccVqNTtCH8H0QrygHARpNg==} engines: {node: '>=16'} cpu: [x64] os: [linux] - '@openai/codex@0.129.0-alpha.15-win32-arm64': - resolution: {integrity: sha512-d5TedgG1pGYji26EZt2dAaPbpdgp3DSjIheEG84lzNcMyW2kma0Q2YK+PnQo0d+SVgRszdLHluBSQQaKRfdsNw==} + '@openai/codex@0.129.0-win32-arm64': + resolution: {integrity: sha512-8rwpYBKg/vI3IHZB2ggFmIDz+4slG7mfYTFoQtRw2m2KMS1g1XMOJK9heM80NMiCY3hqmyMN81bOQ7aKAmgFLg==} engines: {node: '>=16'} cpu: [arm64] os: [win32] - '@openai/codex@0.129.0-alpha.15-win32-x64': - resolution: {integrity: sha512-LtZZBiqyhC2q5PYZEiKuyp9wNO4vck93krBTwqp5/nSMTRAkDRgGpjMVWG1Fz7iJLuy9IbQwVncrkd3hWhGZig==} + '@openai/codex@0.129.0-win32-x64': + resolution: {integrity: sha512-yP59c7O3J8zZ/eyN6HXMeeZ2xksJE8/Xy9kn3qznC7jCN3GEtM7B6Wv4gEY5F/jzik+B+tU71rmkGmqzQjfVVQ==} engines: {node: '>=16'} cpu: [x64] os: [win32] @@ -10015,31 +10015,31 @@ snapshots: '@nolyfill/domexception@1.0.28': {} - '@openai/codex@0.129.0-alpha.15': + '@openai/codex@0.129.0': optionalDependencies: - '@openai/codex-darwin-arm64': '@openai/codex@0.129.0-alpha.15-darwin-arm64' - '@openai/codex-darwin-x64': '@openai/codex@0.129.0-alpha.15-darwin-x64' - '@openai/codex-linux-arm64': '@openai/codex@0.129.0-alpha.15-linux-arm64' - '@openai/codex-linux-x64': '@openai/codex@0.129.0-alpha.15-linux-x64' - '@openai/codex-win32-arm64': '@openai/codex@0.129.0-alpha.15-win32-arm64' - '@openai/codex-win32-x64': '@openai/codex@0.129.0-alpha.15-win32-x64' + '@openai/codex-darwin-arm64': '@openai/codex@0.129.0-darwin-arm64' + '@openai/codex-darwin-x64': '@openai/codex@0.129.0-darwin-x64' + '@openai/codex-linux-arm64': '@openai/codex@0.129.0-linux-arm64' + '@openai/codex-linux-x64': '@openai/codex@0.129.0-linux-x64' + '@openai/codex-win32-arm64': '@openai/codex@0.129.0-win32-arm64' + '@openai/codex-win32-x64': '@openai/codex@0.129.0-win32-x64' - '@openai/codex@0.129.0-alpha.15-darwin-arm64': + '@openai/codex@0.129.0-darwin-arm64': optional: true - '@openai/codex@0.129.0-alpha.15-darwin-x64': + '@openai/codex@0.129.0-darwin-x64': optional: true - '@openai/codex@0.129.0-alpha.15-linux-arm64': + '@openai/codex@0.129.0-linux-arm64': optional: true - '@openai/codex@0.129.0-alpha.15-linux-x64': + '@openai/codex@0.129.0-linux-x64': optional: true - '@openai/codex@0.129.0-alpha.15-win32-arm64': + '@openai/codex@0.129.0-win32-arm64': optional: true - '@openai/codex@0.129.0-alpha.15-win32-x64': + '@openai/codex@0.129.0-win32-x64': optional: true '@openclaw/fs-safe@https://codeload.github.com/openclaw/fs-safe/tar.gz/c7ccb99d3058f2acf2ad2758ad2470c7e113a53c': diff --git a/scripts/check-codex-app-server-protocol.ts b/scripts/check-codex-app-server-protocol.ts index 2f5e75e0e6b4..954b1a68b8c2 100644 --- a/scripts/check-codex-app-server-protocol.ts +++ b/scripts/check-codex-app-server-protocol.ts @@ -54,7 +54,7 @@ const checks: Array<{ file: string; snippets: string[] }> = [ file: "v2/TurnStartParams.ts", snippets: [ "permissions?: PermissionProfileSelectionParams | null", - "serviceTier?: ServiceTier | null", + "serviceTier?: string | null", ], }, { diff --git a/scripts/docs-i18n/translator.go b/scripts/docs-i18n/translator.go index 9e8294935314..495d26297ce1 100644 --- a/scripts/docs-i18n/translator.go +++ b/scripts/docs-i18n/translator.go @@ -208,7 +208,7 @@ func runCodexExecPrompt(ctx context.Context, req codexPromptRequest) (string, er "exec", "--model", req.Model, "-c", fmt.Sprintf("model_reasoning_effort=%q", normalizeThinking(req.Thinking)), - "-c", `service_tier="fast"`, + "-c", `service_tier="priority"`, "--sandbox", "read-only", "--ignore-rules", "--skip-git-repo-check", diff --git a/scripts/docs-i18n/translator_test.go b/scripts/docs-i18n/translator_test.go index fcd3d1d80302..531f33bacd03 100644 --- a/scripts/docs-i18n/translator_test.go +++ b/scripts/docs-i18n/translator_test.go @@ -183,7 +183,7 @@ while [ "$#" -gt 0 ]; do model_reasoning_effort=\"high\") saw_effort=1 ;; - service_tier=\"fast\") + service_tier=\"priority\") saw_service=1 ;; esac diff --git a/scripts/test-live-cli-backend-docker.sh b/scripts/test-live-cli-backend-docker.sh index 2f9de4c4f608..6f4ca7544c32 100644 --- a/scripts/test-live-cli-backend-docker.sh +++ b/scripts/test-live-cli-backend-docker.sh @@ -420,7 +420,7 @@ if [ "$provider" = "codex-cli" ] && [ "${OPENCLAW_LIVE_CLI_BACKEND_AUTH:-auto}" --sandbox \ danger-full-access \ -c \ - 'service_tier="fast"' \ + 'service_tier="priority"' \ --skip-git-repo-check \ --model \ "$codex_probe_model" \ diff --git a/src/agents/cli-backends.test.ts b/src/agents/cli-backends.test.ts index 8bc0a7c92e8e..537e635c49bd 100644 --- a/src/agents/cli-backends.test.ts +++ b/src/agents/cli-backends.test.ts @@ -67,7 +67,7 @@ function createBackendEntry(params: { params.id === "claude-cli" ? "@anthropic-ai/claude-code" : params.id === "codex-cli" - ? "@openai/codex@0.129.0-alpha.15" + ? "@openai/codex@0.129.0" : params.id === "google-gemini-cli" ? "@google/gemini-cli" : undefined, @@ -290,7 +290,7 @@ beforeEach(() => { "--sandbox", "workspace-write", "-c", - 'service_tier="fast"', + 'service_tier="priority"', "--skip-git-repo-check", ], resumeArgs: [ @@ -300,7 +300,7 @@ beforeEach(() => { "-c", 'sandbox_mode="workspace-write"', "-c", - 'service_tier="fast"', + 'service_tier="priority"', "--skip-git-repo-check", ], systemPromptFileConfigArg: "-c", @@ -388,7 +388,7 @@ describe("resolveCliBackendConfig reliability merge", () => { "--sandbox", "workspace-write", "-c", - 'service_tier="fast"', + 'service_tier="priority"', "--skip-git-repo-check", ]); expect(resolved?.config.resumeArgs).toEqual([ @@ -398,7 +398,7 @@ describe("resolveCliBackendConfig reliability merge", () => { "-c", 'sandbox_mode="workspace-write"', "-c", - 'service_tier="fast"', + 'service_tier="priority"', "--skip-git-repo-check", ]); }); @@ -493,7 +493,7 @@ describe("resolveCliBackendLiveTest", () => { defaultModelRef: "codex-cli/gpt-5.5", defaultImageProbe: true, defaultMcpProbe: true, - dockerNpmPackage: "@openai/codex@0.129.0-alpha.15", + dockerNpmPackage: "@openai/codex@0.129.0", dockerBinaryName: "codex", }); }); diff --git a/test/scripts/package-acceptance-workflow.test.ts b/test/scripts/package-acceptance-workflow.test.ts index c31f07f9797f..0b80a06d6b9c 100644 --- a/test/scripts/package-acceptance-workflow.test.ts +++ b/test/scripts/package-acceptance-workflow.test.ts @@ -361,7 +361,7 @@ describe("package artifact reuse", () => { expect(workflow).toContain("OPENCLAW_LIVE_CLI_BACKEND_MODEL=codex-cli/gpt-5.4"); expect(workflow).toContain("OPENCLAW_LIVE_CLI_BACKEND_AUTH=api-key"); expect(workflow).toContain("OPENCLAW_LIVE_CLI_BACKEND_USE_CI_SAFE_CODEX_CONFIG=1"); - expect((workflow.match(/service_tier=\\"fast\\"/g) ?? []).length).toBeGreaterThanOrEqual(2); + expect((workflow.match(/service_tier=\\"priority\\"/g) ?? []).length).toBeGreaterThanOrEqual(2); expect(workflow).not.toContain( 'OPENCLAW_LIVE_CLI_BACKEND_ARGS=["exec","--json","--color","never","--sandbox","danger-full-access","--skip-git-repo-check"]', );