mirror of
https://github.com/pchuan98/codex.git
synced 2026-07-01 00:31:56 +08:00
4c07dd4d25006a41d35872f520aa2e18bc3200e7
2 Commits
-
fix(tui): reduce startup and new-session latency (#17039)
## TL;DR - Fetches account/rateLimits/read asynchronously so the TUI can continue starting without waiting for the rate-limit response. - Fixes the /status card so it no longer leaves a stale “refreshing cached limits...” notice in terminal history. ## Problem The TUI bootstrap path fetched account rate limits synchronously (`account/rateLimits/read`) before the event loop started for ChatGPT/OpenAI-authenticated startups. This added ~670 ms of blocking latency in the measured hot-start case, even though rate-limit data is not needed to render the initial UI or accept user input. The delay was especially noticeable on hot starts where every other RPC (`account/read`, `model/list`, `thread/start`) completed in under 70 ms total. Moving that fetch to the background also exposed a `/status` UI bug: the status card is flattened into terminal scrollback when it is inserted. A transient "refreshing limits in background..." line could not be cleared later, because the async completion updated the retained `HistoryCell`, not the already-written terminal history. ## Mental model Before this change, `AppServerSession::bootstrap()` performed three sequential RPCs: `account/read` → `model/list` → `account/rateLimits/read`. The result of the third call was baked into `AppServerBootstrap` and applied to the chat widget before the event loop began. After this change, `bootstrap()` only performs two RPCs (`account/read` + `model/list`), and rate-limit fetching is kicked off as an async background task immediately after the first frame is scheduled. A new enum, `RateLimitRefreshOrigin`, tags each fetch so the event handler knows whether the result came from the startup prefetch or from a user-initiated `/status` command; they have different completion side-effects. The `get_login_status()` helper (used outside the main app flow) was also decoupled: it previously called the full `bootstrap()` just to check auth mode, wasting model-list and rate-limit work. It now calls the narrower `read_account()` directly. For `/status`, this PR keeps the background refresh request but stops printing transient refresh notices into status history when cached limits are already available. If a refresh updates the cache, the next `/status` command will render the new values. ## Non-goals - This change does not alter the rate-limit data itself. - This change does not introduce caching, retries, or staleness management for rate limits. - This change does not affect the `model/list` or `thread/start` RPCs; they remain on the critical startup path. ## Tradeoffs - **Stale-on-first-render**: The status bar will briefly show no rate-limit info until the background fetch completes; observed background fetches landed roughly in the 400-900 ms range after the UI appeared. This is acceptable because the user cannot meaningfully act on rate-limit data in the first fraction of a second. - **Error silence on startup prefetch**: If the startup prefetch fails, the error is logged but the UI is not notified (unlike `/status` refresh failures, which go through the status-command completion path). This avoids surfacing transient network errors as a startup blocker. - **Static `/status` history**: `/status` output is terminal history, not a live widget. The card now avoids progress-style language that would appear stuck in scrollback; users can run `/status` again to see newly cached values. - **`account_auth_mode` field removed from `AppServerBootstrap`**: The only consumer was `get_login_status()`, which no longer goes through `bootstrap()`. The field was dead weight. ## Architecture ### New types - `RateLimitRefreshOrigin` (in `app_event.rs`): A `Copy` enum distinguishing `StartupPrefetch` from `StatusCommand { request_id }`. Carried through `RefreshRateLimits` and `RateLimitsLoaded` events so the handler applies the right completion behavior. ### Modified types - `AppServerBootstrap`: Lost `account_auth_mode` and `rate_limit_snapshots`; gained `requires_openai_auth: bool` (passed through from the account response so the caller can decide whether to fire the prefetch). ### Control flow 1. `bootstrap()` returns with `requires_openai_auth` and `has_chatgpt_account`. 2. After scheduling the first frame, `App::run_inner` fires `refresh_rate_limits(StartupPrefetch)` if both flags are true. 3. When `RateLimitsLoaded { StartupPrefetch, Ok(..) }` arrives, snapshots are applied and a frame is scheduled to repaint the status bar. 4. When `RateLimitsLoaded { StartupPrefetch, Err(..) }` arrives, the error is logged and no UI update occurs. 5. `/status`-initiated refreshes continue to use `StatusCommand { request_id }` and call `finish_status_rate_limit_refresh` on completion (success or failure). 6. `/status` history cells with cached rate-limit rows no longer render an additional "refreshing limits" notice; the async refresh updates the cache for future status output. ### Extracted method - `AppServerSession::read_account()`: Factored out of `bootstrap()` so that `get_login_status()` can call it independently without triggering model-list or rate-limit work. ## Observability - The existing `tracing::warn!` for rate-limit fetch failures is preserved for the startup path. - No new metrics or spans are introduced. The startup-time improvement is observable via the existing `ready` timestamp in TUI startup logs. ## Tests - Existing tests in `status_command_tests.rs` are updated to match on `RateLimitRefreshOrigin::StatusCommand { request_id }` instead of a bare `request_id`. - Focused `/status` tests now assert that status history avoids transient refresh text, continues to request an async refresh, and uses refreshed cached limits in future status output. - No new tests are added for the startup prefetch path because it is a fire-and-forget spawn with no observable side-effect other than the widget state update, which is already covered by the snapshot-application tests. --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>Felipe Coury ·
2026-04-07 22:16:09 -03:00 -
Fix stale /status rate limits in active TUI sessions (#16201)
Fix stale weekly limit in `/status` (#16194): /status reused the session’s cached rate-limit snapshot, so the weekly remaining limit could stay frozen within an active session. With this change, we now dynamically update the rate limits after status is displayed. I needed to delete a few low-value test cases from the chatWidget tests because the test.rs file is really large, and the new tests in this PR pushed us over the 512K mandated limit. I'm working on a separate PR to refactor that test file.
Eric Traut ·
2026-03-31 17:03:05 -06:00