Skip to content

Latest commit

 

History

History
51 lines (39 loc) · 5.68 KB

codex-provider.md

File metadata and controls

51 lines (39 loc) · 5.68 KB

OpenAI Codex provider operations

The dashboard is local-only at 127.0.0.1:13000. Browser OAuth returns to 127.0.0.1:1455; do not expose either port on a non-loopback interface without adding authentication, CSRF protection, and TLS. If the callback cannot open, use Device Code or import the official Codex CLI auth.json (normally ~/.codex/auth.json). The importer accepts the official token/account shape and never echoes token contents.

After authentication, fetch the Codex catalog, select a provider model, assign an exact public alias, and import it into the draft. The route automatically includes every enabled account from that provider where discovery currently reports the model as available; adding another matching account does not require editing the route. Identical upstream model names from different providers remain separate sources. Aliases must be unique. Traffic changes only after Publish changes.

Provider model cards expose only metadata returned by discovery: provider, context window, API/tool/function/reasoning support, owner/tier, and active account count. Missing fields are shown as unknown rather than inferred from a model name. The gateway enriches the sparse ChatGPT model payload with a bundled snapshot of the official openai/codex model catalog (internal/adapter/codex/catalog.go, generated by gen_catalog.mjs from codex-rs/models-manager/models.json): display name, description, web search, image input, parallel tool calls, reasoning levels, and available_in_plans. Backend values always win; the catalog only fills gaps. Cards additionally show the discovery freshness (Synced …), a per-card Refresh metadata action, and a plan warning when every mapped account's plan is absent from the model's available_in_plans.

Discovery also runs automatically: the control-plane starts a scheduler (lib/discovery-scheduler.ts via Next instrumentation.ts) that re-discovers all enabled accounts every 6 hours, with an overlap guard and an audit trail. Configure via env: MODEL_DISCOVERY_INTERVAL_MS, MODEL_DISCOVERY_INITIAL_DELAY_MS, MODEL_DISCOVERY_DISABLED=1. Alternate accounts rotates healthy accounts per model and ignores sticky affinity. Switch after quota exhaustion keeps the provider account order and moves away from an account only after an actual upstream 429; cached quota percentages never trigger routing changes. Retry-After, then Codex reset headers, then the configured cooldown determine how long that account is excluded.

Deleting a public model is permanent for the alias and removes it from virtual-key allowlists, while retained discovery data allows a later re-import. The mutation still creates a draft and requires publishing before the gateway traffic configuration changes.

Quota data comes from an upstream ChatGPT endpoint that may change. The dashboard polls the cached state every 60 seconds while visible and automatically refreshes from upstream when the snapshot is older than 5 minutes; the manual refresh button still forces a fetch. Because ChatGPT reports only used_percent (no absolute token limits), the panel shows the upstream percentage plus the actual gateway traffic consumed since the last refresh (local_usage from request_events), instead of inventing a percentage. If the endpoint is unavailable, verify usage on the linked Codex Usage page. Reset credits are non-refundable. A reset is written as pending before dispatch; never retry an unknown operation. Reconcile it first, then verify Codex Usage and record an audited manual resolution only when evidence is conclusive.

OAuth credentials are encrypted separately and excluded from snapshots and logs. After migrating an older installation, rotate legacy API keys because database WAL and backups may retain historic plaintext. Rotate the control-plane encryption key only through the documented credential CAS workflow.

CODEX_TEST_MODE=true permits overriding OAuth, JWKS, model, quota, and reset origins for the deterministic fake upstream. Production must leave test mode disabled; origin override variables are ignored otherwise.

Validation against the built Compose stack:

docker compose -f compose.yaml -f compose.codex-test.yaml up -d --build
cd control-plane
npx playwright install chromium
npx playwright test tests/codex-dashboard.spec.ts
cd ..
node test/e2e-codex.mjs
docker compose up -d --force-recreate control-plane gateway

Image models (vision input and image generation)

  • Vision input: chat completions with image_url content parts are translated into input_image items on the Codex Responses backend, so models that advertise input_modalities: ["text","image"] accept images. Native /v1/responses payloads with input_image pass through unchanged.
  • Image generation: /v1/images/generations routed to a Codex account is served through the ChatGPT backend generate endpoint. The upstream model (e.g. gpt-image-1, dall-e-3) is sent as force_paragen_model_slug, the generated asset is downloaded with the account credentials, and the response returns b64_json (the upstream URL is never exposed). n up to 10 issues one generation per image.
  • Discovery: the ChatGPT models endpoint omits image generation models, so discovery appends them from a supplementary catalog (gpt-image-1, gpt-image-2, gpt-5.5-image, dall-e-3; the official openai/codex models.json does not list them). Appended entries advertise capabilities.image_generation and supported_in_api, appear in the discovery modal for every Codex account, and import as normal provider-backed routes. Backend entries with the same slug always win and are never duplicated. Provider model cards show the "Image generation" capability.