Files
Thefool bbe8bb93ab fix(codex): reconcile edit form key with live bearer token (#6534)
* fix(codex): keep provider's own key on switch-away backfill

When switching away from a Codex provider, cc-switch backfills the
outgoing provider's stored config from the live ~/.codex files so that
in-app changes are captured. restore_codex_provider_token_for_backfill
decides what to persist as the provider's auth.OPENAI_API_KEY:

- When the live config.toml carries a per-provider
  experimental_bearer_token, that token is provider-scoped and is lifted
  back into the stored auth. Correct.

- When it does NOT (the default preserve_codex_official_auth_on_switch
  = false mode keeps the active key in the shared auth.json), the
  function returned early and the caller adopted the live auth.json
  wholesale as the provider's stored auth.

The problem: auth.json is a single-slot shared file with no provider
identity; it always holds the most-recently-activated provider's key.
Any time it holds ANOTHER provider's key (after a proxy-takeover
backup/restore cycle, an in-app ChatGPT login overwriting auth.json,
a cloud-sync current/live divergence, or any current-vs-live mismatch),
the switch-away backfill overwrote the outgoing provider's stored key
with another's. Repeated switches made keys silently converge across
providers that share a base URL, surfacing as "model xxx not found"
because the wrong key reached a model it was not entitled to.

Fix: in the no-bearer branch, preserve the provider's own DB-stored
auth instead of adopting the shared live auth.json. Live config.toml
changes (model/base_url/mcp/env) are still captured by the caller; only
the credential slot is no longer taken from the shared file. This
mirrors the #6277 restore-side rule of never letting the shared live
credential clobber per-provider storage.

Adds two regression tests:
- backfill_keeps_provider_own_key_when_live_auth_holds_another_key
  (the failing case under the old code)
- backfill_restores_key_from_live_bearer_token_when_present
  (positive control for the already-correct bearer path)

Fixes #6414.

* Revert "fix(codex): keep provider's own key on switch-away backfill"

This reverts commit 4ddf304eca.

* fix(codex): reconcile edit form key with live bearer token

In bearer-token mode (preserveCodexOfficialAuthOnSwitch enabled — used to
keep a ChatGPT login while routing third-party providers), switching to a
provider writes its key to config.toml's experimental_bearer_token and
preserves the shared ~/.codex/auth.json. auth.json is a single shared slot
with no provider identity, so it may hold ANOTHER provider's stale key
(left over from a previous default-mode switch or a different provider).

When the user then opened the edit dialog for the current provider,
EditProviderDialog loaded liveSettings as the form base, and
useCodexConfigState initialized codexAuth from the stale auth.json while
pickCodexApiKey preferred auth.OPENAI_API_KEY over the bearer token. The
form therefore displayed — and on save persisted — the stale key back
into the provider's DB record. Repeated edits made keys silently converge
across providers that share a base URL, surfacing as "model xxx not found"
once the wrong key reached a model it was not entitled to (#6414).

Fix: when loading Codex config into the form, lift the config's
experimental_bearer_token into auth.OPENAI_API_KEY (when present and
differing) so both the displayed key and the saved auth carry the
correct per-provider key. This mirrors the backend
restore_codex_provider_token_for_backfill lift and is a no-op when the
config has no bearer (default mode keeps auth.json as the active key
slot, and manual live auth edits are preserved exactly — covered by
existing tests).

Adds 4 regression tests in tests/hooks/useCodexConfigState.bearer.test.ts.

Fixes #6414.

* style: prettier-format useCodexConfigState.ts

Fixes the frontend CI "Check formatting" failure on the previous commit.
Pure formatting (collapses a multi-line call to one line); no behavior
change.

* fix(codex): scope bearer reconciliation to live edits
2026-08-26 17:21:30 +08:00
..