From 6874fed05c2df749c4c6c9165375bd115333be64 Mon Sep 17 00:00:00 2001 From: Devin Foley Date: Mon, 26 Oct 2026 16:32:13 -0700 Subject: [PATCH] feat(adapters): refresh model catalogs and sandbox CLI pins (Oct 23 audit) (#17809) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit https://entire.com/gh/paperclipai/-/trails/26/changes/paperclip/26 ## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work. > - Agents run on coding harnesses. Each adapter has a model catalog, and sandboxes contain pinned CLIs. > - Upstream providers released new CLI versions and new models. OpenAI retired some Codex models for ChatGPT sign-in. > - A stale catalog hides valid models. A misleading error makes operators upgrade a CLI that is already current. > - This pull request adds verified OpenCode model IDs, names Codex ChatGPT retirements in the environment Test, and refreshes the sandbox CLI pins. > - The benefit is that operators can select current models and get the correct reason when a retired model fails. ## Linked Issues or Issue Description Refs #16708 (adds Claude Haiku 5.5 to `claude_local`; this PR does not duplicate it). Refs #17245 (moves the Codex runtime to 0.163.0; this PR does not change Codex pins). **What happened?** OpenAI retired `gpt-5.5` (October 14, 2026) and `gpt-5.4` / `gpt-5.4-mini` (August 31, 2026) from Codex with ChatGPT sign-in. A saved agent with one of these models and ChatGPT sign-in now fails. The legacy environment Test says that the plan, the rollout, or an old CLI can be the cause. The Paperclip Runner Test gives generic account and runtime advice. The real cause is the retirement. **Expected behavior** Both Tests give the retirement date and the documented replacement. API-key users keep the models. **Proposed change** Record the verified retirements. Add the new verified OpenCode IDs. Refresh the sandbox CLI pins with verified digests. Record the audit. ## What Changed - Codex: add a table of models retired from Codex with ChatGPT sign-in (`gpt-5.5` → `gpt-6.1-sol`, or `gpt-6-luna` on Free and Go; `gpt-5.4` → `gpt-6-sol`; `gpt-5.4-mini` → `gpt-6-luna`). The shared `codexChatGptRetirementHint` builds the hint. The legacy CLI Test (`codexHelloProbeModelRejectionCheck`) and the Paperclip Runner Test (`testNativeRunnerAuthentication`) both use it when the backend rejects one of these models. For other failures, the Paperclip Runner Test hint stays the same. The picker keeps the models for API-key users. - OpenCode: add `anthropic/claude-haiku-5-5` and `google/gemini-4-argon` to the remote fallback catalog. The Paperclip Runner OpenCode picker also uses this catalog. - Evaluation image sandbox layer (`docker/daytona-runner`): | CLI | Before | After | | --- | --- | --- | | Grok CLI | 1.0.46 | 1.0.70 | | Gemini CLI | 0.62.0 | 0.65.0 | | Kimi Code | 2.1.1 | 2.3.3 | | Cursor CLI | 2026.10.01-e373342 | 2026.10.22-27dcf5f | | GitHub CLI | 2.102.0 | 2.103.3 | - Add `doc/adapter-model-audit-2026-10-23.md` with sources, compatibility findings, and deferred items. No model in this PR needs a newer Codex, Claude, or OpenCode runtime than the current pins. Claude Haiku 5.5 needs Claude Code 2.1.293 or later; #16708 records that floor, and this PR does not add it. ## Verification - `vitest run src/index.test.ts src/server/test.remote.test.ts src/server/acp.cli-version.test.ts` in `packages/adapters/codex-local`: 41 passed. - `vitest run src/services/native-runtime/setup-readiness.test.ts` in `server`: 98 passed. These include the two new Paperclip Runner Test cases: a retired model shows the retirement hint, and a model that is not retired keeps the generic hint. The retirement case fails on the earlier code. Run with the host's empty `ANTHROPIC_BASE_URL` unset; see the baseline note in the audit doc. - `vitest run` in `packages/adapters/opencode-local`: 87 passed. - `vitest run src/__tests__/adapter-models.test.ts` in `server`: 27 passed. - `tsc --noEmit` in `packages/adapters/codex-local` and `packages/adapters/opencode-local`: passed. - Cursor archive SHA-256 `85296944e4600a83c4b764f578d1502bf9c416db200d33a593e8f3ecabfdc294` is computed from the versioned Linux x64 tarball. The extracted binary reports `2026.10.22-27dcf5f`. On October 26, 2026, `https://cursor.com/install` still resolves this version. - GitHub CLI SHA-256 `4c806978ffce1cec70853302a56d70ac6da4f19bae7adca4e1a8ab00633dd91d` matches `gh_2.103.3_checksums.txt`. - Grok CLI 1.0.70 and Kimi Code 2.3.3 installed from npm report those versions. The flags that Paperclip uses (`-m`, `--effort`, `grok models`; `-m`, `-p`, `--output-format`, `acp`) are present in `--help`. - `git merge-tree` with #16708 (head `3a06740e9`) and #17245 (head `41f9c611f`): this PR shares no files with either PR. The two PRs can merge in any order. - Not run in the authoring environment: the full `pnpm -r typecheck` and `pnpm build` (no Rust toolchain), the full server `tsc` (memory limit), and the image build. CI runs these. ## Risks - Low risk for catalogs: the IDs are additive suggestions. No saved selection, default, or spending setting changes. - The Paperclip Runner Test changes only the hint text, and only for a ChatGPT rejection of a retired model. Check codes and pass/fail results do not change. - Sandbox CLI pins: - Kimi Code 2.2.0 and 2.3.0 remove the `kaos` MCP executor and require qualified plugin skill names. Paperclip uses neither. Kimi Code 2.3.2 stops automatic swarms in `kimi -p` and ACP sessions. - Gemini CLI 0.65.0 makes workspace settings read-only in untrusted folders. Paperclip writes home settings and sets `GEMINI_CLI_TRUST_WORKSPACE` for remote runs. - xAI publishes no Grok CLI changelog. Grok 1.0.70 behavior changes are verified only against the CLI reference and `--help`. - The pins apply only after a new image is built and promoted. The fleet sandbox image definition must get the same pins. - Rollback: revert this PR. ## Model Used - Claude Opus 5.5 (`claude-opus-5-5`), Anthropic, with tool use (shell, web research, repository search). ## Checklist - [x] I have included a thinking path that traces from project context to this change - [x] I have specified the model used (with version and capability details) - [x] I have checked ROADMAP.md and confirmed this PR does not duplicate planned core work - [x] I have searched GitHub for duplicate or related PRs and linked them above - [x] I have either (a) linked existing issues with `Fixes: #` / `Closes #` / `Refs #` OR (b) described the issue in-PR following the relevant issue template - [x] I have not referenced internal/instance-local Paperclip issues or links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip` URLs) - [x] My branch name describes the change (e.g. `docs/...`, `fix/...`) and contains no internal Paperclip ticket id or instance-derived details - [x] I have run tests locally and they pass - [x] I have added or updated tests where applicable - [x] I have updated relevant documentation to reflect my changes - [x] I have considered and documented any risks above - [ ] All Paperclip CI gates are green - [ ] Greptile is 5/5 with no open P2s, recommendations, or follow-ups - [x] I will address all Greptile and reviewer comments before requesting merge 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude Opus 5.5 Co-authored-by: Paperclip --- doc/adapter-model-audit-2026-10-23.md | 126 ++++++++++++++++++ docker/daytona-runner/Dockerfile | 14 +- docker/daytona-runner/README.md | 10 +- .../adapters/codex-local/src/index.test.ts | 15 +++ packages/adapters/codex-local/src/index.ts | 26 ++++ .../codex-local/src/server/cli-version.ts | 6 +- .../src/server/test.remote.test.ts | 29 ++++ packages/adapters/opencode-local/src/index.ts | 2 + .../native-runtime/setup-readiness.test.ts | 14 ++ .../native-runtime/setup-readiness.ts | 5 +- 10 files changed, 232 insertions(+), 15 deletions(-) create mode 100644 doc/adapter-model-audit-2026-10-23.md diff --git a/doc/adapter-model-audit-2026-10-23.md b/doc/adapter-model-audit-2026-10-23.md new file mode 100644 index 00000000000..8f63cf14deb --- /dev/null +++ b/doc/adapter-model-audit-2026-10-23.md @@ -0,0 +1,126 @@ +# Adapter model and harness audit: October 23, 2026 + +This audit follows the [October 2, 2026 audit](adapter-model-audit-2026-10-02.md). +It covers model selection in the coding-agent adapters and the CLI pins in the +evaluation sandbox image. Catalog entries identify models; provider accounts +and installed CLIs determine access. No agent defaults or saved model +selections are migrated. + +## Model changes + +| Adapter | Changes from the audit | +| --- | --- | +| Codex | No new selectable model IDs. Codex 0.160.0 through 0.164.0 ship the same bundled model set, which the picker already lists (including GPT-6 Astra, GPT-5.6 Terra, and GPT-5.6 Luna). OpenAI retired `gpt-5.5` (October 14, 2026) and `gpt-5.4` / `gpt-5.4-mini` (August 31, 2026) from Codex with ChatGPT sign-in. The API and API-key Codex sessions still serve them, so they stay in the picker. When the backend rejects one of them for a ChatGPT account, the environment Test (legacy CLI and Paperclip Runner) now names the retirement and the documented replacement instead of suggesting a stale CLI, a plan restriction, or generic account checks. | +| OpenCode | Add `anthropic/claude-haiku-5-5` and `google/gemini-4-argon` to the static fallback used by remote environments and the Paperclip Runner picker. Both IDs are in the OpenCode model registry (models.dev). | +| Claude Code (direct and Bedrock) | Claude Haiku 5.5 is covered by [#16708](https://github.com/paperclipai/paperclip/pull/16708); this audit does not duplicate it. Haiku 5.5 needs Claude Code 2.1.293 or later and supports all five effort levels. | +| Gemini CLI | Gemini 4 Argon (`gemini-4-argon`) is generally available on the Gemini API, but Gemini CLI 0.65.0 does not register it. Deferred. | +| Grok Build, Kimi Code, Cursor | No new verified model IDs. Grok 4.7 and Kimi K3 remain the newest documented models. | + +## Harness changes + +| Harness | Before | After | +| --- | --- | --- | +| Grok CLI (`@xai-official/grok`) | 1.0.46 | 1.0.70 | +| Gemini CLI | 0.62.0 | 0.65.0 | +| Kimi Code CLI | 2.1.1 | 2.3.3 | +| Cursor CLI (sandbox layer) | 2026.10.01-e373342 | 2026.10.22-27dcf5f | +| GitHub CLI | 2.102.0 | 2.103.3 | +| Codex CLI (shared provider pack) | 0.160.0 | Unchanged here; [#17245](https://github.com/paperclipai/paperclip/pull/17245) moves it to 0.163.0 | +| Claude Agent SDK / Claude Code | 0.3.286 / 2.1.286 | Unchanged; see "Deferred items" | +| OpenCode (shared provider pack) | 1.18.34 | Unchanged; see "Deferred items" | +| Hermes | 0.19.0 | 0.19.0 (newest on PyPI) | + +These pins change only the evaluation image's sandbox layer. They must stay +aligned with the fleet sandbox image definition. + +## Sources and verification + +Research date: October 23, 2026. Harness pins rechecked October 26, 2026. + +- [Codex models](https://learn.chatgpt.com/docs/models) states the GPT-5.5 + retirement ("Effective October 14, 2026 ... GPT-5.5 retires from Codex for + users signed in with ChatGPT"), its replacements (GPT-6.1 Sol on paid plans, + GPT-6 Luna on Free and Go), the GPT-5.4 retirement and its replacements + (`gpt-6-sol`, `gpt-6-luna`), and that API-key sessions are not affected. +- The bundled `codex-rs/models-manager/models.json` is unchanged in model set + from [rust-v0.160.0](https://github.com/openai/codex/releases/tag/rust-v0.160.0) + to [rust-v0.164.0](https://github.com/openai/codex/releases/tag/rust-v0.164.0), + the npm `latest` release on October 26, 2026. +- [Claude Haiku 5.5](https://platform.claude.com/docs/en/models/haiku-5-5/overview) + was released October 7, 2026. The + [Claude Code changelog](https://github.com/anthropics/claude-code/blob/main/CHANGELOG.md) + entry for 2.1.293 adds `claude-haiku-5-5`. +- [models.dev](https://models.dev/api.json) lists `anthropic/claude-haiku-5-5` + and `google/gemini-4-argon`. The OpenCode 1.18.34 executable's bundled + snapshot predates both. Paperclip Runner binds the selected model into the + OpenCode provider configuration, so the snapshot does not limit it. +- [Gemini 4 Argon](https://ai.google.dev/gemini-api/docs/models/gemini-4-argon) + is generally available since October 13, 2026. Gemini CLI 0.65.0 + (`packages/core/src/config/models.ts`) has no entry for it, and pull requests + adding it to the CLI are still open. +- Grok CLI 1.0.70, Gemini CLI 0.65.0, and Kimi Code 2.3.3 are the npm `latest` + tags on October 26, 2026. xAI publishes no Grok CLI changelog; `-m`, + `--effort`, and `grok models` are unchanged in the + [CLI reference](https://docs.x.ai/build/cli/reference.md) and in + `grok --help` from 1.0.70. + [Kimi Code 2.2.0 and 2.3.0](https://github.com/MoonshotAI/kimi-code/releases) + remove the `kaos` MCP executor and require qualified plugin skill names; + Paperclip uses neither. Kimi Code 2.3.2 stops the agent from launching + swarms by itself, so `kimi -p` and ACP sessions no longer start swarms; + 2.3.1 and 2.3.3 are fixes and prompt changes. `-m`, `-p`, + `--output-format`, and `acp` are unchanged in `kimi --help` from 2.3.3. + Gemini CLI 0.65.0 makes workspace settings read-only in untrusted folders; + Paperclip writes only home settings and sets `GEMINI_CLI_TRUST_WORKSPACE` + for remote runs. +- Cursor CLI 2026.10.22-27dcf5f is the version `https://cursor.com/install` + resolves. The archive SHA-256 was computed from the versioned Linux x64 + tarball, and the extracted executable reports that version. +- [GitHub CLI 2.103.3](https://github.com/cli/cli/releases/tag/v2.103.3): the + pinned digest matches the release `checksums.txt`. 2.103.1 through 2.103.3 + are fixes on top of 2.103.0. +- [Hermes on PyPI](https://pypi.org/project/hermes-agent/) remains at 0.19.0. + Newer Hermes releases (v0.22.4) are published only through GitHub, the + installer, and Docker. + +## Deferred items + +- **Claude runtime 2.1.286 → 2.1.308.** Claude Code's `stable` channel is + 2.1.308 (`latest` is 2.1.309), with Agent SDK 0.3.308. The range changes + headless defaults that Paperclip runs depend on: fork subagents are on by + default in `-p` and the Agent SDK (2.1.302), sessions with no permission + mode start in `default` mode on third-party providers (2.1.302), and MCP + allow rules match whole server names (2.1.299). This needs a separate runner + qualification together with the patched `claude-agent-acp` bridge. Until then, + Haiku 5.5 on the CLI lane needs a 2.1.293+ CLI. Once #16708 records that + minimum, sandbox runs on an older image prepare a private CLI at the model + minimum before launch. +- **OpenCode 1.19.x and 2.x.** OpenCode 1.19.3 generates reasoning variants + from model options instead of catalog variants, which affects the variants + Paperclip Runner binds. OpenCode 2 changes the SDK, event, and plugin + contracts. Both need qualification. +- **ACP bridges.** ACPX 0.20.0, `claude-agent-acp` 0.94.0 (ACP SDK 2.0), and + `codex-acp` 2.2.2 (breaking tool-call contract in 2.0.0) need a + qualification campaign rather than a pin bump. +- **GitHub Copilot CLI 1.0.103.** The qualified Copilot profile binds + Copilot 1.0.88 by immutable identity; a new profile version needs its own + qualification. Copilot discovers models from the ACP session, so new Copilot + models need no catalog change. +- **Pi 1.4.0** and **Hermes 0.22.x** need runtime qualification; Hermes no + longer publishes to PyPI. +- **Gemini 4 Argon** in the Gemini CLI and Cursor catalogs: the CLI does not + register it yet, and Cursor documents display names only. +- **Codex default model.** Codex 0.161.0 makes `gpt-6.1-sol` its default. + Paperclip keeps `gpt-5.6-sol` so saved agents and spending do not change. +- **Hidden Codex aliases** (`gpt-daybreak-*`) are restricted to eligible + accounts. +- **Claude Sonnet 4.5** is deprecated and retires November 30, 2026. It stays + in the picker until then. +- **Claude Mythos 5.1** remains restricted to verified organizations. + +## Host-environment baseline failures + +Recorded once for this audit on the unchanged base (`c5ca29d`), Node 25.9.0: + +- `server/src/__tests__/agent-hire-ai-connections.test.ts` fails at import + with `AI_InvalidArgumentError: baseURL must be a non-empty string.` because + the host injects an empty AI provider URL. Unrelated to this change. diff --git a/docker/daytona-runner/Dockerfile b/docker/daytona-runner/Dockerfile index 39b606cd0c5..cb791d6acac 100644 --- a/docker/daytona-runner/Dockerfile +++ b/docker/daytona-runner/Dockerfile @@ -65,9 +65,9 @@ ENV PATH=${PAPERCLIP_RUNNER_PROVIDER_PACK_ROOT}/node_modules/.bin:/usr/local/sha # Never add a second CLI version to work around a runner compatibility pin. RUN npm uninstall -g @anthropic-ai/claude-code @openai/codex opencode-ai \ && npm install -g \ - @xai-official/grok@1.0.46 \ - @google/gemini-cli@0.62.0 \ - @moonshot-ai/kimi-code@2.1.1 \ + @xai-official/grok@1.0.70 \ + @google/gemini-cli@0.65.0 \ + @moonshot-ai/kimi-code@2.3.3 \ && npm cache clean --force # Hermes requires Python >=3.11,<3.14; the image's default Python is newer. @@ -78,8 +78,8 @@ RUN /usr/bin/python3 -m venv /opt/hermes \ && /opt/hermes/bin/pip install --no-cache-dir hermes-agent==0.19.0 \ && ln -sf /opt/hermes/bin/hermes /usr/local/bin/hermes -ARG CURSOR_VERSION=2026.10.01-e373342 -ARG CURSOR_SHA256_AMD64=a79726c6e644520e993970be4c45775a6889802b67abe461a677a53219ae28e8 +ARG CURSOR_VERSION=2026.10.22-27dcf5f +ARG CURSOR_SHA256_AMD64=85296944e4600a83c4b764f578d1502bf9c416db200d33a593e8f3ecabfdc294 RUN set -eu; \ arch="$(dpkg --print-architecture)"; \ [ "$arch" = "amd64" ] || { echo "FATAL: cursor pin only covers amd64, not $arch" >&2; exit 1; }; \ @@ -93,8 +93,8 @@ RUN set -eu; \ ln -sf /usr/local/bin/cursor-agent /usr/local/bin/agent; \ chmod -R a+rX /opt/cursor -ARG GH_VERSION=2.102.0 -ARG GH_SHA256_AMD64=bb766f710eef8ede859c18578c72c327597cd4c8a85b06001b1f3843c6019386 +ARG GH_VERSION=2.103.3 +ARG GH_SHA256_AMD64=4c806978ffce1cec70853302a56d70ac6da4f19bae7adca4e1a8ab00633dd91d RUN set -eu; \ arch="$(dpkg --print-architecture)"; \ [ "$arch" = "amd64" ] || { echo "FATAL: gh pin only covers amd64, not $arch" >&2; exit 1; }; \ diff --git a/docker/daytona-runner/README.md b/docker/daytona-runner/README.md index 6b56a538f91..70e1ca7ea19 100644 --- a/docker/daytona-runner/README.md +++ b/docker/daytona-runner/README.md @@ -27,11 +27,11 @@ pack. Claude Code 2.1.280 is the minimum for minimum for Sonnet 5.5; the pinned runtime also supports Fable 5.1. Codex 0.160.0 ships bundled metadata for the current [GPT-6.1 Sol, GPT-6 Sol, and GPT-6 Luna model IDs](https://learn.chatgpt.com/docs/models). -The same refresh pins Grok CLI 1.0.46, Gemini CLI 0.62.0, Kimi Code 2.1.1, -Cursor CLI 2026.10.01-e373342, and GitHub CLI 2.102.0 in the sandbox layer. -The native Cursor provider uses its separately verified distribution, pinned to -2026.09.26-dd393fe; it does not use the sandbox layer’s global Cursor executable. -Grok CLI 1.0.46 supports the current +The sandbox layer pins Grok CLI 1.0.70, Gemini CLI 0.65.0, Kimi Code 2.3.3, +Cursor CLI 2026.10.22-27dcf5f, and GitHub CLI 2.103.3 (October 2026 +refresh). The native Cursor provider uses its separately verified distribution, +pinned to 2026.09.26-dd393fe; it does not use the sandbox layer’s global Cursor +executable. Grok CLI 1.0.70 supports the current [Grok 4.7](https://docs.x.ai/developers/grok-4-7) model family. Hermes stays at 0.19.0, the newest release on PyPI. diff --git a/packages/adapters/codex-local/src/index.test.ts b/packages/adapters/codex-local/src/index.test.ts index fcb53825d60..7976cab2e32 100644 --- a/packages/adapters/codex-local/src/index.test.ts +++ b/packages/adapters/codex-local/src/index.test.ts @@ -1,6 +1,7 @@ import { describe, expect, it } from "vitest"; import { CODEX_CHATGPT_MODEL_REJECTION_RE, + codexChatGptRetirementForModel, codexCliVersionAtLeast, codexLocalReasoningEffortsForModel, DEFAULT_CODEX_LOCAL_MODEL, @@ -25,6 +26,20 @@ describe("codex model CLI floors", () => { }, ); + it("records models retired from Codex with ChatGPT sign-in and keeps them selectable for API keys", () => { + expect(codexChatGptRetirementForModel("gpt-5.5")).toEqual({ + retiredOn: "2026-10-14", + replacement: "gpt-6.1-sol (gpt-6-luna on Free and Go plans)", + }); + expect(codexChatGptRetirementForModel(" gpt-5.4 ")).toEqual({ retiredOn: "2026-08-31", replacement: "gpt-6-sol" }); + expect(codexChatGptRetirementForModel("gpt-5.4-mini")).toEqual({ retiredOn: "2026-08-31", replacement: "gpt-6-luna" }); + for (const model of [DEFAULT_CODEX_LOCAL_MODEL, "gpt-6.1-sol", "custom-model", "", null, undefined]) { + expect(codexChatGptRetirementForModel(model)).toBeNull(); + } + const modelIds = models.map((model) => model.id); + expect(modelIds).toEqual(expect.arrayContaining(["gpt-5.5", "gpt-5.4", "gpt-5.4-mini"])); + }); + it("compares stable versions numerically and rejects prerelease or ambiguous input", () => { expect(codexCliVersionAtLeast("0.159.0", "0.159.0")).toBe(true); expect(codexCliVersionAtLeast("0.160.1", "0.159.0")).toBe(true); diff --git a/packages/adapters/codex-local/src/index.ts b/packages/adapters/codex-local/src/index.ts index c06e881c729..c5bb78db66a 100644 --- a/packages/adapters/codex-local/src/index.ts +++ b/packages/adapters/codex-local/src/index.ts @@ -129,6 +129,31 @@ export function minimumCodexCliVersionForModel(model: string | null | undefined) return CODEX_LOCAL_MODEL_MINIMUM_CLI_VERSIONS[normalizeCodexModel(model)] ?? null; } +export interface CodexChatGptRetirement { + retiredOn: string; + replacement: string; +} + +// Models OpenAI retired from Codex with ChatGPT sign-in (https://learn.chatgpt.com/docs/models). +// The OpenAI API and API-key Codex sessions still serve them, so they stay in the picker; the +// Test names the retirement instead of suggesting a stale CLI or a plan restriction. +const CODEX_LOCAL_CHATGPT_RETIRED_MODELS: Readonly> = { + "gpt-5.5": { retiredOn: "2026-10-14", replacement: "gpt-6.1-sol (gpt-6-luna on Free and Go plans)" }, + "gpt-5.4": { retiredOn: "2026-08-31", replacement: "gpt-6-sol" }, + "gpt-5.4-mini": { retiredOn: "2026-08-31", replacement: "gpt-6-luna" }, +}; + +export function codexChatGptRetirementForModel(model: string | null | undefined): CodexChatGptRetirement | null { + return CODEX_LOCAL_CHATGPT_RETIRED_MODELS[normalizeCodexModel(model)] ?? null; +} + +/** Test hint for a ChatGPT-account rejection of a retired model; shared by the legacy and native Tests. */ +export function codexChatGptRetirementHint(model: string | null | undefined): string | null { + const retirement = codexChatGptRetirementForModel(model); + if (!retirement) return null; + return `OpenAI retired ${normalizeCodexModel(model)} from Codex with ChatGPT sign-in on ${retirement.retiredOn}. Choose ${retirement.replacement}, or use an OpenAI API key; API-key sessions are not affected.`; +} + const STABLE_CODEX_CLI_VERSION = /^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)$/; function stableCodexCliVersionParts(version: string): number[] | null { @@ -257,6 +282,7 @@ Notes: - Paperclip injects desired local skills into the effective CODEX_HOME/skills/ directory at execution time so Codex can discover "$paperclip" and related skills without polluting the project working directory. For new and updated agents, Paperclip assigns an isolated managed home at ~/.paperclip/instances//companies//agents//codex-home/skills/; when CODEX_HOME is explicitly overridden in adapter config, that override is used instead. - New and updated codex_local agents persist an empty OPENAI_API_KEY override by default so a host-level OPENAI_API_KEY cannot leak into Codex runs through process inheritance. Explicit CODEX_HOME overrides must not point at the shared company codex-home, $CODEX_HOME, or ~/.codex. - Some model/tool combinations reject certain effort levels (for example minimal with web search enabled). +- OpenAI retired gpt-5.5 (October 14, 2026), gpt-5.4 and gpt-5.4-mini (August 31, 2026) from Codex with ChatGPT sign-in. They remain selectable for OpenAI API-key sessions; with ChatGPT sign-in the Test names the retirement and its replacement. - With ChatGPT sign-in, model availability depends on the installed Codex capabilities. Legacy setup reports known model/version mismatches. Native setup tests the actual app-server and selected model; a version number alone does not reject or replace an installed CLI. If the provider rejects the model, select an available model or update Codex in the execution environment. - Fast mode is supported on GPT-6 (astra/sol/luna), GPT-6.1 Sol, GPT-5.6 (sol/terra/luna), GPT-5.5, GPT-5.4 and manual model IDs. When enabled for those models, Paperclip applies \`service_tier="fast"\` and \`features.fast_mode=true\`. - When Paperclip realizes a workspace/runtime for a run, it injects PAPERCLIP_WORKSPACE_* and PAPERCLIP_RUNTIME_* env vars for agent-side tooling. diff --git a/packages/adapters/codex-local/src/server/cli-version.ts b/packages/adapters/codex-local/src/server/cli-version.ts index aaafc9479af..097242acfe5 100644 --- a/packages/adapters/codex-local/src/server/cli-version.ts +++ b/packages/adapters/codex-local/src/server/cli-version.ts @@ -3,6 +3,7 @@ import type { AdapterExecutionTarget } from "@paperclipai/adapter-utils/executio import { runAdapterExecutionTargetProcess } from "@paperclipai/adapter-utils/execution-target"; import { CODEX_CHATGPT_MODEL_REJECTION_RE, + codexChatGptRetirementHint, codexCliVersionAtLeast, minimumCodexCliVersionForModel, normalizeCodexModel, @@ -110,6 +111,7 @@ export function codexHelloProbeModelRejectionCheck(input: { if (!match) return null; const model = match[1]!; const minimum = minimumCodexCliVersionForModel(model); + const retirementHint = codexChatGptRetirementHint(model); const versionNote = input.detectedVersion ? ` Detected Codex CLI ${input.detectedVersion}.` : ""; @@ -118,8 +120,8 @@ export function codexHelloProbeModelRejectionCheck(input: { level: "error", message: `The Codex backend rejected ${model} for this ChatGPT account.`, detail: `${match[0]}${versionNote}`, - hint: minimum + hint: retirementHint ?? (minimum ? `${model} needs Codex CLI ${minimum} or newer with ChatGPT sign-in. ${sandboxUpgradeHint(input.targetIsSandbox)} If the CLI is already new enough, the plan does not include this model (Enterprise and Edu administrators must enable it) or the rollout has not reached the account; choose another model or use an OpenAI API key.` - : `The ChatGPT plan does not include ${model}, the rollout has not reached the account, or the installed Codex CLI is older than the model requires. ${sandboxUpgradeHint(input.targetIsSandbox)} Otherwise choose another model or use an OpenAI API key.`, + : `The ChatGPT plan does not include ${model}, the rollout has not reached the account, or the installed Codex CLI is older than the model requires. ${sandboxUpgradeHint(input.targetIsSandbox)} Otherwise choose another model or use an OpenAI API key.`), }; } diff --git a/packages/adapters/codex-local/src/server/test.remote.test.ts b/packages/adapters/codex-local/src/server/test.remote.test.ts index 9efe9ebfd90..4cab7a6d0cb 100644 --- a/packages/adapters/codex-local/src/server/test.remote.test.ts +++ b/packages/adapters/codex-local/src/server/test.remote.test.ts @@ -372,6 +372,35 @@ describe("codex remote environment diagnostics", () => { expect(result.checks.some((check) => check.code === "codex_hello_probe_auth_required")).toBe(false); }); + it("names the ChatGPT retirement when the backend rejects a retired model", async () => { + runAdapterExecutionTargetProcess.mockResolvedValueOnce({ + exitCode: 1, + signal: null, + timedOut: false, + stdout: "", + stderr: "ERROR: {\"type\":\"error\",\"status\":400,\"error\":{\"type\":\"invalid_request_error\",\"message\":\"The 'gpt-5.5' model is not supported when using Codex with a ChatGPT account.\"}}", + pid: 223, + startedAt: new Date().toISOString(), + }); + + const result = await testEnvironment({ + companyId: "company-1", + adapterType: "codex_local", + config: { engine: "cli", command: "codex", model: "gpt-5.5" }, + executionTarget: sandboxTarget(), + environmentName: "QA Daytona", + }); + + expect(result.status).toBe("fail"); + const rejected = result.checks.find((check) => check.code === "codex_hello_probe_model_rejected"); + expect(rejected).toMatchObject({ + level: "error", + message: "The Codex backend rejected gpt-5.5 for this ChatGPT account.", + hint: "OpenAI retired gpt-5.5 from Codex with ChatGPT sign-in on 2026-10-14. Choose gpt-6.1-sol (gpt-6-luna on Free and Go plans), or use an OpenAI API key; API-key sessions are not affected.", + }); + expect(rejected?.hint).not.toContain("Upgrade Codex"); + }); + it("emits the canonical adapter_auth_missing check when a sandbox hello probe reports missing auth", async () => { // The sandbox has no seedable credentials, so the hello probe returns an // authentication-required error. The Test must emit the neutral canonical diff --git a/packages/adapters/opencode-local/src/index.ts b/packages/adapters/opencode-local/src/index.ts index 6d4d08a89c0..c32d9417a8d 100644 --- a/packages/adapters/opencode-local/src/index.ts +++ b/packages/adapters/opencode-local/src/index.ts @@ -65,6 +65,8 @@ export const models: Array<{ id: string; label: string }> = [ { id: "anthropic/claude-fable-5-1", label: "anthropic/claude-fable-5-1" }, { id: "anthropic/claude-sonnet-5-5", label: "anthropic/claude-sonnet-5-5" }, { id: "anthropic/claude-sonnet-5", label: "anthropic/claude-sonnet-5" }, + { id: "anthropic/claude-haiku-5-5", label: "anthropic/claude-haiku-5-5" }, + { id: "google/gemini-4-argon", label: "google/gemini-4-argon" }, { id: "google/gemini-3.8-flash", label: "google/gemini-3.8-flash" }, { id: "xai/grok-4.7", label: "xai/grok-4.7" }, { id: "openai/gpt-5.5", label: "openai/gpt-5.5" }, diff --git a/server/src/services/native-runtime/setup-readiness.test.ts b/server/src/services/native-runtime/setup-readiness.test.ts index cffe993feb4..139cdcde839 100644 --- a/server/src/services/native-runtime/setup-readiness.test.ts +++ b/server/src/services/native-runtime/setup-readiness.test.ts @@ -432,6 +432,20 @@ describe("Codex selected native account verification", () => { expect(nativeProbe).toHaveBeenCalledOnce(); expect(execute).not.toHaveBeenCalled(); }); + it("names the ChatGPT retirement when the backend rejects a retired model", async () => { + nativeProbe.mockRejectedValue(new Error(JSON.stringify({ type: "error", status: 400, + error: { type: "invalid_request_error", message: "The 'gpt-5.5' model is not supported when using Codex with a ChatGPT account." } }))); + const result = await testNativeRunnerAuthentication(context, "codex", "gpt-5.5"); + expect(result.status).toBe("fail"); + expect(result.checks[0]).toMatchObject({ code: "codex_hello_probe_failed", level: "error" }); + expect(result.checks[0].hint).toContain("OpenAI retired gpt-5.5 from Codex with ChatGPT sign-in on 2026-10-14"); + expect(result.checks[0].hint).toContain("gpt-6.1-sol"); + }); + it("keeps the generic hint when the backend rejects a model that is not retired", async () => { + nativeProbe.mockRejectedValue(new Error("The 'gpt-6.1-sol' model is not supported when using Codex with a ChatGPT account.")); + const result = await testNativeRunnerAuthentication(context, "codex", "gpt-6.1-sol"); + expect(result.checks[0].hint).toBe("Check the selected account, model access, and native runtime prerequisites, then retry. Legacy runner is available explicitly in Advanced."); + }); it.each([ ["authentication required: selected-account", true], ["Model is unavailable", false], diff --git a/server/src/services/native-runtime/setup-readiness.ts b/server/src/services/native-runtime/setup-readiness.ts index dc83185de53..bad070d1266 100644 --- a/server/src/services/native-runtime/setup-readiness.ts +++ b/server/src/services/native-runtime/setup-readiness.ts @@ -2,6 +2,7 @@ import { constants } from "node:fs"; import { lstat, mkdir, mkdtemp, open, realpath, rm, stat, writeFile } from "node:fs/promises"; import { tmpdir } from "node:os"; import { join, posix } from "node:path"; +import { CODEX_CHATGPT_MODEL_REJECTION_RE, codexChatGptRetirementHint } from "@paperclipai/adapter-codex-local"; import { copyBackCodexAuth } from "@paperclipai/adapter-codex-local/server"; import type { AdapterEnvironmentTestContext, AdapterEnvironmentTestResult } from "@paperclipai/adapter-utils"; import { ADAPTER_AUTH_MISSING_CHECK_CODE } from "@paperclipai/shared"; @@ -255,8 +256,10 @@ export async function testNativeRunnerAuthentication(context: AdapterEnvironment } catch (error) { const message = redactNativeProbeMessage(error instanceof Error ? error.message : "The selected native runtime could not verify this account.", { ...environment, ...(sourceAuthJson ? { [authKey]: sourceAuthJson } : {}) }); const authentication = /(?:invalid (?:api[- ]?key|auth(?:entication)? token)|authentication (?:failed|required)|unauthenticated|unauthorized|not authenticated|please (?:log|sign) in|not logged in|\b(?:401|403)\b)/i.test(message); + const rejectedModel = provider === "codex" ? CODEX_CHATGPT_MODEL_REJECTION_RE.exec(message)?.[1] : undefined; + const retirementHint = rejectedModel ? codexChatGptRetirementHint(rejectedModel) : null; return { adapterType: "paperclip_runner", status: "fail", testedAt: new Date().toISOString(), checks: [{ code: `${provider}_hello_probe_${authentication ? "auth_required" : /timed out/i.test(message) ? "timeout" : "failed"}`, level: "error", message, - hint: "Check the selected account, model access, and native runtime prerequisites, then retry. Legacy runner is available explicitly in Advanced." }, + hint: retirementHint ?? "Check the selected account, model access, and native runtime prerequisites, then retry. Legacy runner is available explicitly in Advanced." }, ...(authentication && provider === "codex" ? [{ code: ADAPTER_AUTH_MISSING_CHECK_CODE, level: "error" as const, message: "The selected Codex account needs authentication.", hint: "Sign in to Codex or choose an authenticated account, then test again." }] : [])] };