Repository navigation
Conversation
Self-Review (
|
The ChatGPT picker offered a built-in list that went stale as OpenAI added models and retired others for ChatGPT sign-in, so a fresh login could default to a model its account no longer serves. The backend returns no models to client_version 0.50.0, so requests now send the current Codex CLI version, including the sign-in scope check.
9ca662d to
a5f74c3
Compare
|
Stack merge order: #1580 → #1581 → #1579. This repo keeps merged branches, so GitHub does not retarget the next PR on its own:
|
There was a problem hiding this comment.
Review · Request changes
A ChatGPT profile fetches the models that account can use and shows those in the picker. The first one is the default. A failed fetch is supposed to keep the last good list, or the built-in list if there has never been one.
-
The fetched list is saved under the account id from the first token read (
src/provider/codex-model-catalog.ts:119). If that read fails, the list is saved under "no account." The fetch then reads the token again, succeeds, and learns the real account id. The picker looks the list up under that new id, finds nothing, and shows the built-in models instead of the ones just fetched. The comment on that function says the second read fails the same way. It does not. A temporary test of this sequence failed and was removed. Save the list under the account id the successful fetch used. Startup only fetches once, so the picker stays on the built-in list until something fetches again. -
Two logins that have no account id share one saved list. Switch accounts and have the new fetch fail or come back empty, and the picker still shows the previous account's models, while the request uses the new account's token. Logins that both have account ids do not share a list.
-
The models shown while connecting are not saved. That fetch builds a throwaway list (
src/provider/codex-model-catalog.ts:140). If the fetch after connect then fails, the fallback is the built-in list, not the models just shown.
The fetched list was saved under the account from a token read made before the request. When that read failed, the request's own read could still succeed and name the account, so the picker looked under that account, found nothing, and showed the built-in models. The token that makes the request now picks where its list is kept, and a failed read gets one more try. Two logins with no account id shared one saved list, so a reconnect whose fetch failed or came back empty showed the previous login's models while requests used the new token. Such a login is now told apart by its creation time, which a token refresh keeps and a new sign-in changes. The list shown while connecting was thrown away, so a failed fetch after connecting fell back to the built-in models. It is now kept once the submit saves the profile, before the picker reads it.
|
All three findings fixed in 75655fe. Each had a test that failed first. List saved under the wrong account. The token that makes the request now decides where its list is kept, so there is no separate earlier read to disagree with it. Your sequence (first read fails, next read succeeds and names the account) now ends with the fetched list in the picker. A failed read gets one more try, which matches the two reads the old code made. If both fail, the fetch counts as failed and logs why, and the picker stays on its current list until the next fetch. Two logins with no account id sharing a list. A login with no account id is now told apart by its Models shown while connecting. The list is now kept once the submit saves the profile, before setup returns and the picker reads it. A failed fetch after connecting leaves those models, and a later successful fetch replaces them. A failed submit keeps nothing, and neither does a step that only showed the built-in list. Two things to look at:
Stack note: this still conflicts with #1580's
|
TheGreatAxios
left a comment
There was a problem hiding this comment.
A ChatGPT sign-in fetches the models that account serves, keeps the list with that login, and uses the first entry as the default. A failed fetch is supposed to keep that login's own last list.
- should-fix — The fetch stores the list under the account id on the token that served it, but the picker and the save after connect read the id on the profile. A refresh can learn an id the profile did not have yet. A later fetch that fails does not move the earlier entry, so the profile shows the built-in list while the real one is still stored under the old key. The save after connect has the same split: the scope check can refresh that token before the list is stored, and the models just shown are kept under an id that did not serve them.
src/provider/codex-model-catalog.ts:102-173 - should-fix — Overlapping fetches for one login are unordered. A startup prefetch that returns after connect has already stored the list just shown replaces it with the older response, so a model picked from that list can disappear from the picker.
src/provider/codex-model-catalog.ts:119-136 - should-fix — Confirming the model step before the fetch returns saves the built-in default and drops the live list when it arrives. That first live model never becomes the saved default, and the catalog refresh that follows does not rewrite the saved id.
src/tui/provider/discovery.ts:227-238 - informational — A blank account id counts as an identity. Two sign-ins of the same profile name with an empty id share one list, while a missing id is separated by sign-in time.
src/provider/codex-model-catalog.ts:102-107
…live-codex-model-catalog-fetch-for-chatgpt The comment above CODEX_DEFAULT_MODELS conflicted with #1580; this keeps both: the live-catalog fallback role and the Plus-catalog provenance. The list is unchanged.
|
Triage: Fail Asking a maintainer about:
Notes:
|
Nothing triage asked to change still fails, so this request no longer stands.
A fetch stored its list under the account id on the token that served it, while the picker and the save after connecting read the id on the stored profile. A refresh that taught the profile its id, followed by a failed fetch, left the live list under the old key and showed the built-in one. Lists are now keyed by profile name and creation time, which a token refresh keeps and a reconnect changes, so every reader and writer agrees and a blank account id no longer counts as an identity. Overlapping fetches could answer in any order, so a startup fetch that returned after the list shown at connect was kept replaced it with an older view. Each request now takes a ticket when it starts, and an older answer never replaces a newer list. The connect list is newer than every fetch started before it was kept. Confirming the connect model step before the fetch returned saved the built-in default and dropped the live list, so the account's first model never became the saved one. Confirming now waits for the fetch in flight, bounded by its own timeout, then saves the pick made against the list.
|
All four items from the review of 75655fe are fixed in 75fa109, each with a test that failed first. This also includes the merge of main (e1df050), which cleared the conflict with #1580. Key mismatch (should-fix). The fetch stored the list under the account id on the token that served it, while the picker and the save after connecting read the id on the profile. Lists are now keyed by profile name and creation time. A refresh keeps the creation time even when it teaches the profile its account id, and a reconnect changes it, so every reader and writer uses the same key. A test covers a refresh that learns the id followed by a failed fetch, which now keeps the live list. Blank account id (informational). The account id is no longer part of the key, so a blank id is not an identity. Two sign-ins of one profile name with blank ids no longer share a list, and a test pins that. Overlapping fetches (should-fix). Each request now takes a ticket when it starts, and an older answer never replaces a newer list. The list kept at connect counts as newer than every fetch that started before it, so a startup fetch returning late cannot replace the list the operator picked from. Tests cover that case, an earlier request answering after a later one, and a later answer replacing an earlier one. Confirming before the fetch returns (should-fix). Confirming the model step now waits for the fetch in flight, bounded by its own 10 second timeout, then saves the pick made against the account's list. A model the operator moved to is kept when the list has it. A failed fetch saves the built-in default, and cancelling while it waits saves nothing. I chose waiting over saving at once and rewriting later, because that would change a model the operator had already confirmed. Say so if you would rather not block on the network there.
|
Summary
GET /codex/modelsafter startup and after/connect, keeps the listed entries in the backend's priority order, and makes the first one the profile's default. Requests sendclient_version0.165.0; the backend returns no models to the previous 0.50.0.Verification
bun run checkpasses.codex/pluswithgpt-6.1-solcompletes.Fixes CL-11727