feat(cli): support OAuth login in setup - #4665
Conversation
23053f0 to
33ccb3b
Compare
Generated-by: Codex
33ccb3b to
6f5f23f
Compare
# Conflicts: # packages/cli/src/runtime-host-tui-command.ts # packages/runtime-host/src/protocol/index.ts
Generated-by: Codex
Bound cancellation and shutdown observation, retain the Host attempt for reconciliation, and republish OAuth presentation capabilities before a retried start on each physical connection. Generated-by: Codex
Resolve the OAuth setup copy against the current TUI catalog and advance the Runtime Host compatibility epoch to 142. Generated-by: Codex
Resolve the Runtime Host compatibility epoch collision by assigning the OAuth create-target protocol epoch 143 and repinning the compatible Base64 allocation declaration. Generated-by: Codex
Return authenticated setup to provider selection while keeping the saved connection. Refresh providers without blocking navigation, and ignore superseded model discovery and catalog results. Cover loading, failure, and model-selection return paths.
Resolve the independent epoch-143 changes by retaining session bundle support at 143 and advancing the OAuth identity extension to 144. Generated-by: Codex
Preselect gpt-6-astra, gpt-5.6-sol, gpt-5.6-terra, and gpt-5.6-luna from the shared provider baseline. Preserve existing accounts' saved model selections. Generated-by: Codex
Retain the Antigravity and session bundle protocol additions from main and advance the OAuth identity extension to compatibility epoch 146. Generated-by: Codex
There was a problem hiding this comment.
I found no blocking correctness issue in the reviewed implementation.
Merge note — assign a new Runtime Host compatibility epoch when updating to current main
packages/runtime-host/src/protocol/index.ts:104
This branch assigns epoch 146 to the OAuth wire change: create targets may now carry a caller-selected Connection name and slug, and slug collisions add a closed typed result. Current main independently assigns epoch 146 to the Code Mode settings and Session tool-mode contract. The combined protocol cannot continue advertising 146, because a Client or Host that implements only one of those contracts could pass the compatibility handshake with a peer that implements the other.
I reproduced the conflict by merging current origin/main (3cfcb09fd903bfbf94cbc4684b78c67be616342a) into the reviewed head (72ad69ea41d10d110a6546c377a56f09a7a76e0e). Resolving the combined declaration to epoch 147 makes the repository guard pass:
Protocol epoch guard: Protocol changed and the epoch moved: 146 -> 147.
When updating the currently conflicting branch, please set RUNTIME_HOST_COMPATIBILITY_EPOCH to 147, retain the epoch-146 Code Mode note, add the OAuth contract as the epoch-147 note, and rerun CI on the new exact head.
I found no other blocking correctness issue. The design follows the Desktop boundary: the CLI presents the device login and drives interaction, while the Runtime Host owns authorization exchange, credential persistence, Connection commit, cancellation races, and durable recovery. The CLI additionally covers terminal-specific loss and reconnect cases, including re-observing the same attempt after an SSH disconnect and refusing to attach it to a different Host root.
The reviewed head passed clean install, full workspace build/typecheck/format, and 432 focused CLI, OAuth protocol/coordinator, and Runtime Policy storage tests.
中文说明
已审查的功能实现没有发现阻塞正确性问题。
合并提示 — 更新到当前 main 时为组合后的 Runtime Host 协议分配新 epoch
packages/runtime-host/src/protocol/index.ts:104
该分支把 epoch 146 用于 OAuth 协议变化:创建 Connection 时可以携带用户选择的 name/slug,slug 冲突也新增了闭合的类型化结果。当前 main 又独立把 epoch 146 用于 Code Mode 设置和 Session tool mode。合并后的协议不能继续使用 146,否则只实现其中一套协议的 Client 与 Host 可能通过兼容握手,却在实际请求时使用不同的 wire contract。
我在精确 head 72ad69ea41d10d110a6546c377a56f09a7a76e0e 上合并当前 origin/main 3cfcb09fd903bfbf94cbc4684b78c67be616342a 复现了冲突。把组合结果改为 epoch 147 后,仓库协议守卫通过并报告:
Protocol epoch guard: Protocol changed and the epoch moved: 146 -> 147.
更新当前有冲突的分支时,请将兼容 epoch 改为 147,保留 146 的 Code Mode 说明,并把 OAuth identity/slug contract 记录为 147,然后在新的精确 head 上重跑 CI。
除此之外没有发现阻塞正确性问题。设计沿用了 Desktop 的边界:CLI 展示设备登录信息并承载交互,Runtime Host 负责授权交换、凭据持久化、Connection 提交、取消竞态和持久恢复。CLI 还覆盖了终端特有的断线与重连,包括 SSH 断开后继续查询同一个 attempt,以及拒绝把旧 attempt 接到不同的 Host root。
已审查 head 通过干净安装、全仓 build/typecheck/format,以及 432 个 CLI、OAuth 协议/协调器和 Runtime Policy 存储测试。
Retain the Code Mode protocol contract at epoch 146 and advance the OAuth identity extension to compatibility epoch 147. Allow required unified-diff context markers in the imported patch files during whitespace checks. Generated-by: Codex
Summary
Add OpenAI OAuth (ChatGPT / Codex) sign-in to the CLI
/setupwizard, so terminal and SSH users can configure anopenai-codexConnection. The flow reuses the provider picker, editable name/slug fields, and model selector described in #4606.OAuth entries appear when the Runtime Host enables
openai-codexenrollment. OAuth exchange and credential storage remain owned by the Host. The API-key transaction is unchanged.New OAuth accounts preselect
gpt-6-astra,gpt-5.6-sol,gpt-5.6-terra, andgpt-5.6-luna. Existing accounts retain their saved model selections.Fixes #4606
The blocks below describe keyboard interactions; they are not recordings of a live login.
Complete example: configure Work Codex
This example runs
/setupinside an existing TUI session, with OAuth enabled and no existing Codex account. It createsWork Codexwith slugcodex-work, then enables four models. The device code and model list are illustrative; use the values shown by your Host.<cursor>indicates the active editing position and is not literal terminal text. Colors and borders are omitted.1. Choose the provider
Run
/setup, then typecodexto filter the list.Press Enter to choose this provider.
2. Edit the account name
Replace the default Name with
Work Codex.Press Enter to move focus to Slug.
3. Edit the account slug
Replace the default slug with
codex-work.Press Enter to start sign-in with this name and slug.
4. Authorize in the browser
Open the displayed URL in a browser and enter the sign-in code.
Complete authorization in the browser. The CLI advances automatically after sign-in and model loading finish.
5. Review the discovered models
Press Enter to save the four selected models.
6. Wait for the save
7. Close the completed setup
After the save completes:
Press Enter (or Esc) to return to the session.
The result is one OAuth Connection named
Work Codex, with slugcodex-workand the four selected models enabled. To use it in the current session, run/modeland select an enabled model belonging to that account. Reopening/setuplists it as an existing account, so selecting it follows the three-step reauthorization flow below.New OAuth account
Provider selection
Identity — Name field
Identity — Slug field
Browser authorization
Model selection
Completion
Name and slug can be edited or left at their defaults. Invalid input stays in the identity step. A requested slug that is already taken also returns to that step for correction. The authenticated account and the model selection belong to the same Connection.
Existing OAuth account
Select an existing account
Reauthorize that account
Choose its enabled models
The name/slug step is skipped. Reauthorization preserves the Connection's identity, and model selection starts from its enabled models that are still available.
Enter / Esc while authorization is pending
Preparing or waiting for authorization
Waiting for cancellation
The Host's result determines the next screen:
Esc requests cancellation; it does not assume cancellation won a race with a completed login.
Sign-in failure or an unconfirmed result
Confirmed failure
Unconfirmed result
After checking again:
An unconfirmed result does not imply that the account was never created. Checking again retains the sign-in attempt's identity so a lost response does not create a second independent login.
Enter / Esc after authentication
Model loading in progress
Model loading failed
Return from model selection
Already signed in
Back at provider selection
Returning keeps the saved Connection and credentials. Enter on the signed-in page only reloads models; selecting an existing account from the provider list starts reauthorization. Reloading models within the same flow preserves selections for models that remain available.
The provider list remains usable while refreshing and retains its cached entries if refresh fails. Late model-loading or catalog results do not interrupt subsequent navigation.
Model validation, save failure, and leaving during a save
Empty selection
Save failure
Save in progress
Leaving during a save does not undo a write that the Host has already accepted. A late result cannot pull the wizard back to an abandoned screen. A successful save refreshes the running TUI's model choices without switching the current session's account/model. If that refresh fails, setup reports that the account was saved and the model list needs reloading.
Closing setup and first-run onboarding
Close from any step
Return to an existing session
First-run onboarding
Verification
For the latest commit,
72ad69ea4(including the merge oforigin/main):origin/mainpassed. The merged protocol uses compatibility epoch 146.The full workspace suite was not rerun for the main-branch merge and default-model update. The earlier validation recorded in this PR reported one Runtime Host failure in
production Host executes Bash against the current live sandbox boundary, outside the changed implementation. A recording of a real OpenAI device login remains pending; the interaction blocks above are illustrative.AI use
Tool(s) and scope: Codex assisted with implementation, tests, localized copy, review, and verification.
Checklist
Does this PR entail a change in behavior?