80237bcabc
CI / Adapter unit tests (push) Successful in 35s
CI / Template validation (static) (push) Successful in 40s
CI / Adapter unit tests (pull_request) Successful in 32s
CI / Template validation (static) (pull_request) Successful in 1m25s
CI / Template validation (runtime) (push) Successful in 2m43s
CI / T4 tier-4 conformance (live) (push) Successful in 2m40s
CI / T4 tier-4 conformance (live) (pull_request) Successful in 50s
CI / validate (push) Successful in 9s
CI / Template validation (runtime) (pull_request) Successful in 3m13s
CI / validate (pull_request) Successful in 4s
Replace the hardcoded codex_minimax_config.sh single-provider routing
with a generic providers: registry in config.yaml and a Python adapter
layer (provider_config.py) that resolves the picked provider against
the env + writes ~/.codex/config.toml accordingly. Shape mirrors the
claude-code template's provider registry / _resolve_provider /
_project_vendor_auth pattern (PR template-claude-code#24), adapted to
codex's file-based config (config.toml + auth.json) rather than the
Anthropic SDK's env-var contract.
Three auth modes supported in the registry:
- chatgpt_subscription (CODEX_AUTH_JSON / CODEX_CHATGPT_AUTH_JSON)
- openai_api (OPENAI_API_KEY)
- openai_compat_responses (third-party Responses-API endpoints +
vendor env key, e.g. MiniMax token-plan)
Resolution honors the verified prod precedence from PR#11: when a
subscription credential is present it wins over a model-prefix match,
so prod-Reviewer / prod-Researcher workspaces with both CODEX_AUTH_JSON
and MINIMAX_API_KEY set continue to route through the subscription
(NO model_provider override → built-in OpenAI/Responses path). The
verified gpt-5.5 + 5.4 + 5.3-codex roster is preserved unchanged.
Backward compat: codex_minimax_config.sh stays in the image as a
fallback for one release so external ops scripts + the existing test
fixtures that exec it directly keep working; start.sh prefers the new
python helper when available.
Adding a new codex-compatible provider is now a one-entry config.yaml
edit instead of a code change in the boot scripts.
Tests:
- tests/test_provider_abstraction.py (new, 16 cases) — registry load,
resolution precedence (subscription / explicit / model-prefix /
credential-aware), render output for each auth mode, idempotent
write + stale-override cleanup, fail-closed on misconfigured entry.
- tests/test_modernization_pr1.py updated: roster assertion relaxed
from equality to "verified OpenAI set is a subset of the model
list" (the multi-provider abstraction adds third-party entries
alongside the OpenAI roster); per-model required_env validated
against the providers registry rather than hardcoded to
OPENAI_API_KEY.
Prior art:
- template-claude-code config.yaml providers registry +
adapter.py _load_providers / _resolve_provider / _project_vendor_auth
- OpenClaw multi-provider routing (internal#440)
- PR#11 subscription-wins-over-minimax precedence (internal#513)
Tracks internal#514. NOT a fix for the MiniMax Chat-vs-Responses
incompatibility on CLI 0.130 — that remains a downstream-vendor gap
and is now data in the YAML registry (wire_api: responses) so a future
shim flips a YAML field rather than touching boot scripts.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
197 lines
8.8 KiB
YAML
197 lines
8.8 KiB
YAML
name: OpenAI Codex CLI
|
|
description: >-
|
|
OpenAI Codex CLI (@openai/codex) wrapped as a Molecule workspace runtime.
|
|
Each session holds a long-lived `codex app-server` child + one thread,
|
|
so A2A messages process in-order with full conversation continuity —
|
|
no fresh subprocess per turn.
|
|
|
|
Three auth paths are supported (adapter picks at boot via the
|
|
`providers:` registry below):
|
|
A. Codex/ChatGPT subscription via CODEX_AUTH_JSON (auth.json blob;
|
|
preferred when present — overrides the model-prefix match so a
|
|
workspace with both a subscription and a vendor key like
|
|
MINIMAX_API_KEY routes to the subscription as intended).
|
|
B. Direct OpenAI API key via OPENAI_API_KEY (codex's documented
|
|
pay-as-you-go fallback).
|
|
C. Third-party endpoint serving the OpenAI Responses API on a
|
|
vendor-specific base_url + env key (e.g. MiniMax token-plan).
|
|
Add a new such provider by appending one entry to `providers:` —
|
|
no adapter or boot-script code changes needed.
|
|
version: 0.2.0
|
|
tier: 2
|
|
|
|
# Provider registry — single source of truth for codex provider routing.
|
|
# The adapter reads this list at boot, resolves the picked model + env
|
|
# credentials to a provider entry, and renders ~/.codex/config.toml
|
|
# accordingly (no override for built-in OpenAI auth modes; a
|
|
# [model_providers.<slug>] block for openai_compat_responses).
|
|
#
|
|
# Adding a new provider = one entry below. The boot scripts stay
|
|
# generic and open-source-friendly: vendor URLs and env-var names are
|
|
# public/documented (e.g. api.openai.com, api.minimax.io), with no
|
|
# deployer-specific infrastructure baked into the template.
|
|
#
|
|
# Schema per entry:
|
|
# name : human-readable label (used in boot banner).
|
|
# auth_mode : one of
|
|
# chatgpt_subscription — auth.json blob via CODEX_AUTH_JSON
|
|
# (or CODEX_CHATGPT_AUTH_JSON alias);
|
|
# no config.toml model_provider override
|
|
# so codex uses its native OpenAI/Responses
|
|
# provider, with the model picked via
|
|
# thread/start from runtime_config.model.
|
|
# openai_api — direct OpenAI key via OPENAI_API_KEY;
|
|
# same "no override" shape as above.
|
|
# openai_compat_responses — third-party Responses-API endpoint;
|
|
# adapter renders a [model_providers.<slug>]
|
|
# block + model_provider = "<slug>" pin.
|
|
# model_prefixes : lowercase model-id prefixes for routing match.
|
|
# model_aliases : exact lowercase model ids for routing match.
|
|
# base_url : null for built-in OpenAI modes; HTTPS URL for
|
|
# openai_compat_responses.
|
|
# auth_env : env-var names the adapter checks for satisfied
|
|
# credentials. First non-built-in entry is the
|
|
# "env_key" emitted to config.toml for compat
|
|
# providers.
|
|
# wire_api : optional; defaults to "responses". CLI 0.130
|
|
# removed the "chat" variant — only "responses"
|
|
# is parse-valid today. Left in registry so a
|
|
# future shim re-introducing a chat-style wire
|
|
# is a YAML edit.
|
|
# model_provider_slug : optional TOML slug; defaults to `name` if
|
|
# absent.
|
|
# model_id_override : optional model id to write into config.toml
|
|
# when the wire-protocol model name differs
|
|
# from the canvas-shown id (e.g. MiniMax's
|
|
# codex-MiniMax-M2.7 vs the generic gpt-* line).
|
|
providers:
|
|
- name: openai-subscription
|
|
auth_mode: chatgpt_subscription
|
|
model_prefixes: [gpt-]
|
|
model_aliases: []
|
|
base_url: null
|
|
# CODEX_AUTH_JSON wins over the older CODEX_CHATGPT_AUTH_JSON alias
|
|
# when both are set (preserves the pre-existing precedence).
|
|
auth_env: [CODEX_AUTH_JSON, CODEX_CHATGPT_AUTH_JSON]
|
|
|
|
- name: openai-api
|
|
auth_mode: openai_api
|
|
model_prefixes: [gpt-]
|
|
model_aliases: []
|
|
base_url: null
|
|
auth_env: [OPENAI_API_KEY]
|
|
|
|
# MiniMax token-plan codex CLI route. The endpoint is documented at
|
|
# platform.minimax.io/docs/token-plan/codex-cli. KNOWN LIMITATION:
|
|
# MiniMax's token-plan endpoint serves OpenAI Chat-Completions, NOT
|
|
# the Responses API. CLI 0.130 hard-removed the `chat` wire variant,
|
|
# so this leg parses + boots cleanly under wire_api = "responses" but
|
|
# the runtime call to /v1/responses 404s on MiniMax's side. The
|
|
# registry entry stays in the open-source default so any deployer
|
|
# that adds a Responses-supporting MiniMax variant (proxy / future
|
|
# MiniMax feature) just sets MINIMAX_API_KEY and works — no code
|
|
# change. Tracked as a downstream-vendor gap, not a template defect.
|
|
- name: minimax-token-plan
|
|
auth_mode: openai_compat_responses
|
|
model_prefixes: [codex-minimax-, minimax-codex-, minimax-]
|
|
model_aliases: []
|
|
base_url: https://api.minimax.io/v1
|
|
auth_env: [MINIMAX_API_KEY]
|
|
wire_api: responses
|
|
model_provider_slug: minimax
|
|
model_id_override: codex-MiniMax-M2.7
|
|
|
|
runtime: codex
|
|
runtime_config:
|
|
# Default codex model. Pass-through to `thread/start`'s `model`
|
|
# field; codex resolves the rest. `gpt-5.5` is codex 0.130's own
|
|
# `thread/start` default (verified live 2026-05-17 against
|
|
# codex-cli 0.130.0 linux/amd64: thread/start returned
|
|
# "model":"gpt-5.5"). The prior `gpt-5` default was a DEAD id —
|
|
# there is no plain `gpt-5` in the May-2026 codex roster, so a
|
|
# workspace on the OpenAI leg failed/hung the first turn. Roster
|
|
# below is the verified May-2026 set (OpenAI Codex Models +
|
|
# Configuration Reference). Tracks codex CLI releases — bump
|
|
# deliberately alongside the @openai/codex pin (RFC §1, §6).
|
|
model: gpt-5.5
|
|
|
|
# Models surfaced in the canvas Config tab dropdown. Per-entry
|
|
# required_env follows the picked auth path: gpt-* lines accept
|
|
# either CODEX_AUTH_JSON (subscription) or OPENAI_API_KEY (direct).
|
|
# MiniMax codex entries route through the `minimax-token-plan`
|
|
# provider (see top-level `providers:` registry) and require
|
|
# MINIMAX_API_KEY only. The adapter resolves the actual provider
|
|
# from this list + the env at boot; required_env here drives the
|
|
# canvas validation hint, not the resolution itself.
|
|
models:
|
|
- id: gpt-5.5
|
|
name: GPT-5.5 (OpenAI subscription or API key)
|
|
required_env: [OPENAI_API_KEY]
|
|
- id: gpt-5.4
|
|
name: GPT-5.4 (OpenAI subscription or API key)
|
|
required_env: [OPENAI_API_KEY]
|
|
- id: gpt-5.4-mini
|
|
name: GPT-5.4 mini (OpenAI subscription or API key)
|
|
required_env: [OPENAI_API_KEY]
|
|
- id: gpt-5.3-codex
|
|
name: GPT-5.3 Codex (OpenAI subscription or API key)
|
|
required_env: [OPENAI_API_KEY]
|
|
- id: gpt-5.3-codex-spark
|
|
name: GPT-5.3 Codex Spark (OpenAI subscription or API key)
|
|
required_env: [OPENAI_API_KEY]
|
|
- id: gpt-5.2
|
|
name: GPT-5.2 (OpenAI subscription or API key)
|
|
required_env: [OPENAI_API_KEY]
|
|
|
|
# MiniMax token-plan codex route — public endpoint
|
|
# (api.minimax.io). See `providers:` registry note on the
|
|
# Chat-vs-Responses compatibility gap; entries kept so the
|
|
# canvas surfaces the option for any deployer that adds a
|
|
# Responses-supporting variant.
|
|
- id: codex-minimax-m2.7
|
|
name: MiniMax M2.7 codex (third-party token-plan)
|
|
required_env: [MINIMAX_API_KEY]
|
|
|
|
# Default required_env — the canvas surfaces this when no model is
|
|
# picked. OPENAI_API_KEY is the documented direct path; subscription
|
|
# and MiniMax paths are validated by the adapter via the registry.
|
|
required_env: [OPENAI_API_KEY]
|
|
|
|
# Provider names surfaced in the canvas Config tab dropdown. The
|
|
# actual routing decision is made in adapter.setup() against the
|
|
# top-level `providers:` registry; this list is the UI surface.
|
|
providers:
|
|
- openai-subscription
|
|
- openai-api
|
|
- minimax-token-plan
|
|
|
|
# 0 = no executor-side timeout. Per-turn timeout is enforced inside
|
|
# executor.py at _TURN_TIMEOUT (currently 600s).
|
|
timeout: 0
|
|
|
|
# codex's tool set is built-in (file ops, terminal, apply_patch, web
|
|
# fetch). No extension surface from our side today.
|
|
skills: []
|
|
|
|
a2a:
|
|
port: 8000
|
|
streaming: true
|
|
push_notifications: true
|
|
|
|
# Bridge config — consumed by executor.py.
|
|
bridge:
|
|
# codex app-server is a stdio child, not a network service. No URL
|
|
# or port to configure. Listed here for symmetry with hermes' bridge
|
|
# block; when we add overrides (e.g. custom codex binary path) they
|
|
# land here.
|
|
app_server_command: codex
|
|
app_server_args: ["app-server"]
|
|
|
|
delegation:
|
|
retry_attempts: 3
|
|
retry_delay: 5
|
|
timeout: 120
|
|
escalate: true
|
|
|
|
template_schema_version: 1
|