Skip to content

fix(service-tier): make /fast work on ChatGPT-subscription Codex models - #547

Merged
code-yeongyu merged 2 commits into
code-yeongyu:mainfrom
eddieparc:fix/issue-545-codex-fast-session-tier
Jul 31, 2026
Merged

fix(service-tier): make /fast work on ChatGPT-subscription Codex models#547
code-yeongyu merged 2 commits into
code-yeongyu:mainfrom
eddieparc:fix/issue-545-codex-fast-session-tier

Conversation

@eddieparc

@eddieparc eddieparc commented Jul 30, 2026

Copy link
Copy Markdown
Contributor

Fixes #545. Reverses the conclusion of my own #503: the ChatGPT Codex backend does offer a priority ("Fast") tier to subscription accounts, so /fast should work there.

Why the previous notice was wrong

/fast is registered for openai-codex but switches through an openai-codex/<id>-fast catalog sibling that generate-models.ts only emits for the direct openai provider. #503 turned that dead end into a notice claiming priority tier is unavailable on a ChatGPT subscription. Its evidence was the SSE service_tier echo — and that echo carries no information:

sent response.created echo response.completed echo status
priority auto default 200
(absent) auto default 200
default auto default 200
auto / flex / scale 400 Unsupported service_tier

Identical echoes for priority and for sending nothing, so the echo cannot distinguish the tier that served the request.

What the backend and the first-party client actually do

GET https://chatgpt.com/backend-api/codex/models?client_version=0.145.0 with originator: codex_cli_rs and a live ChatGPT Pro token (chatgpt_plan_type: pro) returns, per model:

model service_tiers additional_speed_tiers
gpt-5.6-sol / -terra / -luna, gpt-5.5, gpt-5.4 [{"id":"priority","name":"Fast","description":"1.5x speed, increased usage"}] ["fast"]
gpt-5.4-mini, gpt-5.3-codex-spark, codex-auto-review [] []

"1.5x speed, increased usage" is the backend's own description of the tier, returned to a subscription account.

Official @openai/codex 0.145.0 on ChatGPT OAuth (requires_openai_auth = true), routed through a local logging proxy to chatgpt.com:

  • service_tier = "priority" in config.tomlPOST /backend-api/codex/responses body contains "service_tier": "priority", turn completes (200)
  • line removed → body has no service_tier

So this is not an API-key-only field.

The change

When an openai-codex model has no compatible -fast catalog sibling, /fast now flips a session-scoped priority tier instead of reporting the feature unavailable. The existing before_provider_request handler injects it — addServiceTierToPayload already whitelists openai-codex-responses and api/openai-codex-responses.ts already forwards options.serviceTier — so there is no core or provider change. The catalog-variant path for the direct openai provider is untouched.

Semantics:

  • session-only, never persisted, reset on session_start
  • an explicit model/scoped serviceTier (models.json, provider/id:tier) still wins
  • non-Codex providers keep the existing "only available for OpenAI Codex models" warning, and a mid-session hop to a non-OpenAI model stops sending the field

Tests

test/suite/service-tier-extension.test.ts (11 cases, all green) now covers the toggle payload, a mid-session switch to another Codex model keeping the tier, a hop to an Anthropic model dropping it, explicit-tier precedence, and the session_start reset. Each new assertion was mutation-proved — removing the injection fails 3 cases, leaking the tier to every api fails 2, inverting precedence fails 1, dropping the reset fails 1.

Manual QA

Real TUI, subscription OAuth, provider baseUrl pointed at a logging proxy, request bodies decoded:

turn 1 "reply with exactly: one"    -> one    | gpt-5.6-sol  service_tier=<absent>
/fast                               -> Fast mode enabled: gpt-5.6-sol
turn 2 "reply with exactly: two"    -> two    | gpt-5.6-sol  service_tier=priority
/model openai-codex/gpt-5.5         -> Model: gpt-5.5
turn 3 "reply with exactly: three"  -> three  | gpt-5.5      service_tier=priority
/fast                               -> Fast mode disabled: gpt-5.5
turn 4 "reply with exactly: four"   -> four   | gpt-5.5      service_tier=<absent>

npm run check clean; packages/coding-agent test/suite green apart from a pre-existing app-server-thread-handlers-archive timestamp-monotonicity flake that also fails with this change stashed.

Open question

getServiceTierCostMultiplier() in api/openai-codex-responses.ts multiplies displayed cost by 2 (2.5 for gpt-5.5) for priority. On a subscription the dollar figure is notional ((sub) in the footer) but the backend does say "increased usage", so I left the multiplier alone rather than guessing a subscription-specific number. Happy to change it if you have a preference.


Summary by cubic

Enables Fast mode on ChatGPT-subscription Codex models by toggling a session-scoped priority tier when no -fast catalog variant exists. This makes /fast work on openai-codex models and replaces the incorrect “unavailable on subscription” notice. Fixes #545.

  • Bug Fixes
    • /fast now toggles a session priority tier for openai-codex models without a -fast sibling, with notify messages for enabled/disabled.
    • Injects the tier in before_provider_request for openai-codex-responses; other providers unchanged.
    • Semantics: session-only and reset on session_start; explicit model serviceTier still wins; switching between Codex models keeps the tier; moving to non-OpenAI drops it.
    • Tests cover payload injection, mid-session model switches, dropping on non-OpenAI, explicit-tier precedence, and session reset.

Written for commit 144048a. Summary will update on new commits.

Review in cubic

…dex /fast (LAB-12)

`/fast` on an `openai-codex` model looks for a `-fast` catalog sibling that
`generate-models.ts` only emits for the direct `openai` provider, so the command
always fell through to the "not available on a ChatGPT subscription" notice added
in code-yeongyu#503. That notice was wrong.

Measured with a live ChatGPT Pro token:
`chatgpt.com/backend-api/codex/models?client_version=0.145.0` advertises
`service_tiers: [{ id: "priority", name: "Fast", description: "1.5x speed,
increased usage" }]` for gpt-5.4/5.5/5.6-*, and the first-party Codex CLI sends
`service_tier: "priority"` on subscription OAuth. The SSE echo that code-yeongyu#503 relied
on reports `auto`/`default` whether or not a tier was sent, so it proves nothing.

The no-variant branch now flips a session-scoped priority tier that the existing
`before_provider_request` handler injects into the Codex payload. Session-only,
reset on `session_start`, and an explicit model/scoped tier still wins.

Fixes code-yeongyu#545
The session toggle added in the previous commit had one payload assertion. Cover
the transitions that a real session actually goes through:

- switching to another Codex model mid-session keeps sending the tier, since fast
  mode is a session intent rather than a property of the selected model
- hopping to a non-OpenAI model stops sending it
- an explicitly configured model tier still wins over the toggle
- `session_start` drops the toggle so a fresh session never inherits it

Each assertion was mutation-proved: removing the injection fails three cases,
whitelisting anthropic-messages fails two, inverting precedence fails one, and
dropping the `session_start` reset fails one.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Bug: /fast still unavailable on ChatGPT-subscription Codex models — the backend does offer a priority tier (correcting #499/#503)

2 participants