Skip to content

feat(codex): quota-driven desktop-authless auto failover - #5879

Draft
MateuszJuszczyk wants to merge 1 commit into
lidge-jun:devfrom
MateuszJuszczyk:feat/quota-driven-desktop-authless-auto
Draft

MateuszJuszczyk wants to merge 1 commit into
lidge-jun:devfrom
MateuszJuszczyk:feat/quota-driven-desktop-authless-auto

Conversation

@MateuszJuszczyk

@MateuszJuszczyk MateuszJuszczyk commented Sep 25, 2026 •

Copy link
Copy Markdown

Summary

Recent Codex Desktop builds (observed with bundled codex-cli 0.158.x) disable the composer
account-wide while the ChatGPT 5h quota reports exhausted — including for independently
credentialed routed models that consume none of that quota. Because every ocx-routed model
reaches Desktop through the same provider, and a disabled Send button means no request ever
leaves the client, proxy-side routing cannot help once this state latches. The only working
lever is the provider form: with requires_openai_auth = false Desktop skips the ChatGPT
login/account gate, the composer stays enabled, and routed models submit with their own
credentials.

This PR automates the manual workaround (ocx system settings --desktop-authless on) behind
a new opt-in setting, codexDesktopAuthlessAuto (default off):

  • While the main-account Codex quota reports exhausted, authless routing is engaged.
  • Recovery is confirmed against a forced upstream quota read — never a stale cache — before
    authenticated routing is restored.
  • Each transition persists with settings-route semantics (true sets the key, false deletes
    it), re-runs applyCodexConfigInjection to rewrite ~/.codex/config.toml, and restarts
    Codex clients so the new routing takes effect.
  • Only transitions act: a sweep that finds the desired state already stored is a no-op, and
    every failure path returns for the next sweep instead of throwing.

Design notes:

  • The worker runs on the shared minute sweep (registerStateSweepAfterTick), next to the
    quota-window worker — no new timers, no hooks on the request hot path, and the quota
    boundary guards (reset-observer lazy-import discipline) are untouched.
  • Deliberately no quota-header spoofing: reporting healthy usage for an exhausted account
    would mask genuine exhaustion and mislead every other consumer of that snapshot.
  • No GUI switch in this change: adding one requires all ten locale catalogs (parity-tested),
    while the manual switch already exists in the dashboard. CLI (ocx system settings --desktop-authless-auto on), PUT /api/settings, and config.json all expose it.
  • The src/server/index.ts registration is folded into a new registerCodexSweepWorkers
    helper because that file sits exactly at its file-size cap (remedy by move, not by number).

Related #4878 (same Send-disabled family; this mitigates the observable state via failover
and does not change native quota accounting).

Verification

  • bun run typecheck — clean.
  • New tests/codex-integration/codex-desktop-authless-auto.test.ts — 7/7 pass (engage on
    exhaustion, no-op when already engaged, release on refresh-confirmed recovery, stay engaged
    when refresh still reports exhausted, skip non-pool modes and client role, apply/restart
    failures contained).
  • Neighboring suites green in isolation: settings-desktop-switch-apply, codex-quota-auto-refresh,
    quota-reset-observation, quota-reset-notify, quota-reset-core-boundary, core-lab-boundary
    (25/25, including the updated UNRESOLVED_CALLEES entry for the renamed cleanup binding),
    full tests/cli (1278 pass), skill:surface:check, privacy:scan, structure:check.
  • bun run test:changed (24,972 tests): 24,909 pass; 19 failures, all in
    service/WSL/ownership/native-toggle areas that pass in isolation on this machine (live proxy
    and installed service interfere with the parallel run) — none touch the changed behavior.
  • Live incident test (manual precursor of this automation): with 5h at 100% and Send disabled
    for every model, flipping desktop-authless on re-enabled submission for routed models, and
    the natural reset restored normal mode. No GUI files changed, so no screenshot applies.

Checklist

  • Scope stays focused and avoids unrelated cleanup.
  • Docs or release notes were updated when needed (docs-site reference + guide, structure/config.md).
  • Security-sensitive changes were reviewed for secrets, auth, and unsafe defaults (no credential handling touched; the worker only flips a routing switch, restarts clients loudly, and logs static strings).

Review readiness checklist

This PR stays in draft until every box below is ticked. Tick all four boxes once the requirements are met:

  • Required local validation passed; commands, results, and any full-suite exception are documented.

  • I pushed my PR to a recent dev commit (at most 10 behind; a maintainer may still ask for the exact tip before merge).

  • I resolved all correct Codex and CodeRabbit findings.

  • My PR is ready for review.

While the main Codex 5h quota reports exhausted, recent Desktop builds
disable the composer account-wide, including for independently
credentialed routed models. Opt-in 'codexDesktopAuthlessAuto' engages
desktop-authless routing on exhaustion and releases it on forced-
refresh-confirmed recovery, rewriting config.toml and restarting Codex
clients per transition. Related lidge-jun#4878.
@coderabbitai

coderabbitai Bot commented Sep 25, 2026

Copy link
Copy Markdown
Contributor

Important

Draft PR not reviewed

Draft PRs are not automatically reviewed by default.

  • Trigger a manual review

To automatically review draft PRs, update your CodeRabbit configuration:

reviews:
  auto_review:
    drafts: true

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions

Copy link
Copy Markdown
Contributor

✅ Deterministic PR hygiene checks passed.

@github-actions github-actions Bot added the enhancement New feature or request label Sep 25, 2026
@github-actions

Copy link
Copy Markdown
Contributor

⏳ DRAFT

  • review readiness checklist open (0/4 boxes ticked).

What to do

  • Tick all four boxes in the PR description once you're done (currently 0/4).

Review readiness checklist

  • ⬜ Required local validation passed; commands, results, and any full-suite exception are documented.
  • ⬜ I pushed my PR to a recent dev commit (at most 10 behind; a maintainer may still ask for the exact tip before merge).
  • ⬜ I resolved all correct Codex and CodeRabbit findings.
  • ⬜ My PR is ready for review.

0/4 boxes ticked.

This PR stays in draft until every box above is ticked.

@lidge-jun

Copy link
Copy Markdown
Owner

리뷰 · 우선순위 53 / 80

Codex 데스크톱은 본 계정의 5시간 한도가 다 차면, 그 한도를 안 쓰는 다른 모델까지 보내기 버튼을 꺼 버립니다. 요청이 프록시까지 오지 않아서, 프록시 안에서 길을 바꿔도 늦습니다. 이 PR은 한도가 다 찬 동안만 데스크톱 로그인을 끄는 스위치(codexDesktopAuthless)를 알아서 켰다가, 한도가 돌아오면 다시 끕니다.

기본은 꺼져 있습니다. ocx system settings --desktop-authless-auto on 이나 설정 API로 켭니다. 1분마다 도는 기존 점검에 붙습니다. 상태가 바뀔 때만 config.json을 고치고, ~/.codex/config.toml을 다시 쓰고, Codex를 재시작합니다. 베이스는 dev입니다. 아직 초안입니다.

라인 - src/codex/desktop-authless-auto.ts runDesktopAuthlessAuto. 설정 저장이 성공하면, Codex 설정 파일 다시 쓰기가 실패해도 acted: true로 끝납니다. 다음 1분 점검은 이미 맞춰져 있다고 보고 다시 쓰지 않습니다. apply가 retryable: true(프록시 포트가 아직 없음, 파일 잠금이 바쁨)여도 같습니다. 재시작은 그 실패 뒤에도 돌아갑니다. 저장만 되고 데스크톱 파일은 옛 상태인 채로 Codex가 한 번 죽었다 살아납니다. 테스트 a failed apply or restart still reports the persisted transition이 그 끝을 맞다고 고정합니다.

라인 - src/codex/desktop-authless-auto.ts의 isCodexQuotaExhausted 호출. 타입 설명과 가이드는 5시간 창만 말합니다. 이 함수는 주간 막대나 월간 막대도 100이면 참입니다. 5시간은 남았는데 주간이 다 차도 로그인을 끄고 Codex를 재시작합니다. 테스트는 shortPercent: 100만 봅니다.

메인테이너의 판단이 필요한 지점

켜는 쪽은 캐시에 적힌 숫자를 그대로 믿습니다. 끄는 쪽만 서버에 다시 물어봅니다. 캐시가 옛 100이면, 한도가 이미 돌아와도 먼저 로그인을 끄고 재시작합니다. 그 방향을 유지할지 정해 주세요.

자동이 켜져 있는 동안, 사람이 codexDesktopAuthless를 직접 바꿔도 다음 점검이 덮어씁니다. 문서에 그렇게 적혀 있습니다. 사람이 켠 값을 다음 한도 변화 전까지 둘지는 정해 주세요.

준비 체크 네 칸은 비어 있습니다. test:changed 19건 실패는 작성자가 다른 영역이라고 적었습니다. 이 리뷰는 그 실패를 다시 돌리지 않았습니다.

너의 추천

바탕 dev가 맞습니다. types.ts와 config.ts를 나누는 일과 겹쳐서 닫을 중복은 없습니다. 닫지 마세요. 합치기 전에, 설정 파일 쓰기가 안 됐거나 retryable이면 다음 점검이 다시 쓰게 하세요. 재시작은 쓰기가 된 뒤에만 하세요. 트리거는 문서대로 5시간 막대만 보게 하거나, 주간·월간도 켠다는 문장으로 설명과 가이드를 맞추세요.

이 댓글은 grok-bot이 작성했습니다

@lidge-jun

Copy link
Copy Markdown
Owner

Thanks for this, @MateuszJuszczyk. Release train 4 reviewed it against current dev and is holding it open rather than carrying it this train.

The direction is reasonable: an opt-in, transition-only toggle on the existing minute sweep, with no quota spoofing. Before a carry it needs:

  1. Separate desired and applied state. runDesktopAuthlessAuto reports acted: true once the setting persists, even if applyCodexConfigInjection fails or returns retryable. The next sweep then sees the desired value and never retries, and the restart still runs. Track the applied state, or retry until injection succeeds, before restarting Codex.
  2. Recover only on a fresh, credential-bound reading. Leaving authless mode must depend on a newly fetched quota for the current main credential. A missing or cached value must not count as recovery.
  3. Manual override ownership. Define what happens when an operator sets --desktop-authless by hand while auto mode is active, and whether auto mode may undo it.
  4. Reserve coupling. Because Reserve eligibility currently rides the same flag (Luna Reserve capability is bound to codexDesktopAuthless, a flag documented as controlling Codex app sign-in #4961), an automatic toggle also grants or removes Reserve. That needs a product decision or the decoupling first.
  5. Tests that drive the failure paths: injection failure, absent quota read, a manual override during auto mode, and catalog/injector convergence after each transition.

It is also conflicting with dev now. #4878 stays open separately, because nobody has shown this change repairs the both-exhausted Send state.

@lidge-jun

Copy link
Copy Markdown
Owner

Status after #6361 (squash fcbfb16c00): an opt-in, macOS-only app-server shim on dev now covers the Desktop Send gate. It clears the plain-quota gate on the app-server's rate-limit messages, without switching the provider form or restarting clients. The window-aware 98% main-account lock (#6363) is still open. Neither change covers Windows and Linux Desktop, or users who don't opt into the shim, and that is exactly the case this PR's codexDesktopAuthlessAuto handles. I'm keeping this PR open, and the earlier review points still apply: separate the desired state from the applied state, and keep the forced-recovery read.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants