Skip to content

refactor(gui): react-doctor cleanup for Codex accounts#475

Merged
Wibias merged 7 commits into
lidge-jun:devfrom
Wibias:fix/react-doctor-codex-accounts
Jul 26, 2026
Merged

refactor(gui): react-doctor cleanup for Codex accounts#475
Wibias merged 7 commits into
lidge-jun:devfrom
Wibias:fix/react-doctor-codex-accounts

Conversation

@Wibias

@Wibias Wibias commented Jul 25, 2026

Copy link
Copy Markdown
Collaborator

Summary

  • Split CodexAccountPool + AddCodexAccountModal into sibling modules.
  • Fix impure poll streak updater (pollErrorStreakRef), fetch status checks, native dialogs, type="button".
  • Keeps inline pool load/polling contract (no resurrected hook).

Stack

Test plan

  • bun x tsc -b in gui/
  • Codex pool: switch/reset/add account OAuth flow

Summary by CodeRabbit

  • New Features
    • Added a streamlined flow for adding Codex accounts using OAuth or manual codes.
    • Added support for copying login links, entering authentication codes, and reauthenticating accounts.
    • Improved account pool presentation with clearer account status, quota details, reauthentication prompts, and account switching.
    • Added reset-credit details, confirmation, redemption, and success/error feedback.
    • Updated dialogs with improved focus management, cancellation, and accessibility behavior.

@coderabbitai

coderabbitai Bot commented Jul 25, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@Wibias, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 40 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 9c79141b-689b-4133-976d-89bb5e302b01

📥 Commits

Reviewing files that changed from the base of the PR and between 6b0ca63 and 3fcdd96.

📒 Files selected for processing (28)
  • gui/src/components/AddCodexAccountModal.tsx
  • gui/src/components/CodexAccountPool.tsx
  • gui/src/components/add-codex-account-pick-step.tsx
  • gui/src/components/add-codex-account-reducer.ts
  • gui/src/components/add-codex-account-waiting-step.tsx
  • gui/src/components/codex-account-pool-cards.tsx
  • gui/src/components/codex-account-pool-handlers.ts
  • gui/src/components/codex-account-pool-helpers.tsx
  • gui/src/components/codex-account-pool-main-card.tsx
  • gui/src/components/codex-account-pool-types.ts
  • gui/src/components/codex-account-pool-utils.ts
  • gui/src/components/codex-account-reset-modal.tsx
  • gui/src/components/codex-account-switch-modal.tsx
  • gui/src/components/use-add-codex-account-oauth.ts
  • gui/src/i18n/de.ts
  • gui/src/i18n/en.ts
  • gui/src/i18n/ja.ts
  • gui/src/i18n/ko.ts
  • gui/src/i18n/ru.ts
  • gui/src/i18n/zh.ts
  • gui/tests/add-codex-account-oauth.test.tsx
  • gui/tests/codex-account-pool-handlers.test.ts
  • gui/tests/codex-account-pool-toast-tone.test.tsx
  • src/codex/auth-api.ts
  • tests/codex-auth-api.test.ts
  • tests/codex-auth-modal-status.test.ts
  • tests/provider-workspace-auth.test.ts
  • tests/rate-limit-reset-credits.test.ts
📝 Walkthrough

Walkthrough

The PR decomposes Codex account OAuth and pool management into reducer-driven state, dedicated OAuth and modal components, reusable account-pool presentation components, and centralized reset-credit handling.

Changes

Codex account OAuth flow

Layer / File(s) Summary
Reducer state and modal steps
gui/src/components/add-codex-account-reducer.ts, gui/src/components/add-codex-account-pick-step.tsx, gui/src/components/add-codex-account-waiting-step.tsx
Defines reducer state/actions for account ID, OAuth, manual codes, status notices, and the pick/waiting steps.
OAuth lifecycle integration
gui/src/components/use-add-codex-account-oauth.ts, gui/src/components/AddCodexAccountModal.tsx
Moves OAuth start, polling, cancellation, timeout, reauthentication, manual-code submission, link copying, and callback wiring into a dedicated hook and native dialog modal.

Codex account pool

Layer / File(s) Summary
Pool presentation composition
gui/src/components/CodexAccountPool.tsx, gui/src/components/codex-account-pool-*.tsx
Extracts page header, load states, main account card, account cards, reauthentication banner, ticket badges, and shared account types into separate components.
Reset-credit and switch dialogs
gui/src/components/codex-account-reset-modal.tsx, gui/src/components/codex-account-switch-modal.tsx, gui/src/components/codex-account-pool-handlers.ts
Adds native dialog components, credit date helpers, typed reset-credit parsing, and centralized redemption handling while preserving pool callbacks and state.

Estimated code review effort: 4 (Complex) | ~60 minutes

Sequence Diagram(s)

sequenceDiagram
  participant AddCodexAccountModal
  participant useAddCodexAccountOAuth
  participant CodexAuthAPI
  AddCodexAccountModal->>useAddCodexAccountOAuth: startOAuth(requestedId)
  useAddCodexAccountOAuth->>CodexAuthAPI: POST start login
  CodexAuthAPI-->>useAddCodexAccountOAuth: flowId and authUrl
  useAddCodexAccountOAuth->>CodexAuthAPI: poll login status
  CodexAuthAPI-->>useAddCodexAccountOAuth: login status
  useAddCodexAccountOAuth-->>AddCodexAccountModal: update reducer UI state
Loading

Possibly related PRs

Suggested reviewers: ingwannu, lidge-jun

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title is concise and accurately reflects the main change: a GUI refactor/cleanup for Codex accounts.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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

@github-actions github-actions Bot added the chore label Jul 25, 2026

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 6d35e51525

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".


useEffect(() => () => {
clearManualCode();
aliveRef.current = false;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Make the OAuth cleanup replay-safe under StrictMode

In the default development render, gui/src/main.tsx wraps the app in React.StrictMode, so React runs this effect's cleanup and setup again on mount. The first cleanup permanently sets aliveRef.current to false and aborts the initial reauthentication request; the replayed auto-start is then skipped because startedReauthRef still contains the account ID, while manually started add flows discard their responses at the subsequent liveness check. Consequently, adding or reauthenticating an account never progresses in the development app. Restore liveness during effect setup and reset or otherwise make the reauthentication guard safe to replay.

AGENTS.md reference: AGENTS.md:L65-L68

Useful? React with 👍 / 👎.

});
type LoginResponse = { url?: string; flowId?: string; error?: string; status?: string };
let resp = await requestLogin();
let data = await readJsonIfOk<LoginResponse>(resp);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Preserve structured login errors on non-2xx responses

readJsonIfOk returns null without consuming the body for every non-2xx response, so the structured errors returned by src/codex/auth-api.ts for invalid IDs, duplicate IDs, unknown reauthentication accounts, and server-side OAuth failures are now replaced with the misleading modal.networkError message. These are expected 400/404/500 API outcomes rather than connectivity failures; check the status while still parsing and displaying the response's error field.

Useful? React with 👍 / 👎.

<>
<div style={{ textAlign: "center", padding: "12px 0" }}>
<div className="confirm-icon"><IconAlert width={22} /></div>
<h3>{t("codexAuth.confirmResetTitle")}</h3>

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Keep the reset dialog labelled during confirmation

When resetConfirm becomes true, the element carrying id="codex-reset-title" is removed, but the native dialog continues to use aria-labelledby="codex-reset-title". The destructive confirmation step therefore has no accessible dialog name for screen-reader users. Give the confirmation heading the referenced ID as well, or switch aria-labelledby to an ID that remains mounted across both steps.

Useful? React with 👍 / 👎.

@Wibias

Wibias commented Jul 26, 2026

Copy link
Copy Markdown
Collaborator Author

Codex review follow-up (6b0ca63)

Addressed all three findings after rebase onto upstream/dev:

  1. StrictMode OAuth cleanupaliveRef is set back to true on effect setup so remount after the first cleanup remains live.
  2. Structured login errors — login start now uses readJsonOrThrow (after 409 retry handling) so non-2xx { error } bodies are preserved instead of collapsing to a generic network error.
  3. Reset dialog labelling — confirm-step h3 keeps id=codex-reset-title so aria-labelledby still resolves when resetConfirm is true.

Verification: related Codex GUI tests 41/41 pass; tsc -p gui --noEmit clean; lint:gui clean.

@Wibias
Wibias force-pushed the fix/react-doctor-codex-accounts branch from 6d35e51 to 6b0ca63 Compare July 26, 2026 01:49
coderabbitai[bot]

This comment was marked as resolved.

@Wibias

Wibias commented Jul 26, 2026

Copy link
Copy Markdown
Collaborator Author

Addressed open CodeRabbit findings on fix/react-doctor-codex-accounts (3b7719fa):

Fixed

  1. Reset credit toast math — no invented prevCredits - 1 on already_redeemed; prefer server remaining when present; generic / already-redeemed copy when count unknown; error paths return { toast } instead of alert()
  2. handleRedeem sets toastError from result.ok
  3. OAuth status polling — in-flight guard + AbortSignal.timeout(10s)
  4. Localized codexAuth.loginFailed (en/de/ja/ko/ru/zh)
  5. Import StatusTone / ManualCodeState / AddCodexAccountStep from reducer
  6. Main card / switch modal — i18n fallbacks (codexAuth.codexApp / codexAuth.appLogin); empty mainEmail no longer blanks <strong>

Skipped

  • Outdated Codex threads (StrictMode aliveRef, readJsonOrThrow, reset title a11y) — already fixed earlier
  • Shared dialog wrapper refactor — low value

Verified

  • bun x tsc -p gui --noEmit
  • bun run lint:gui
  • bun test ./gui/tests/codex-account-*.ts* + ./tests/codex-auth-api.test.ts (97 pass)

@Wibias

Wibias commented Jul 26, 2026

Copy link
Copy Markdown
Collaborator Author

Remaining blockers addressed (25abf85d)

Started from tip 3b7719fa (did not reset to 1811a003).

Already done at tip

  • Login-status single-flight (pollInFlightRef) + 10s timeout
  • Authoritative already_redeemed remaining (no invented decrement)
  • setToastError(!result.ok) on redeem
  • aliveRef.current = true on effect setup

Still missing → fixed

  1. StrictMode reauth latch: cleanup now clears startedReauthRef so remount can start OAuth again
  2. Poll abort on cancel/cleanup: stopPolling aborts the active poll session (AbortSignal.any with session + timeout)
  3. Required tests (were absent):
    • gui/tests/add-codex-account-oauth.test.tsx — StrictMode reauth replay + slow-poll single-flight/abort
    • gui/tests/codex-account-pool-handlers.test.tsalready_redeemed remaining contracts
    • gui/tests/codex-account-pool-toast-tone.test.tsx — stale error tone cleared on successful redeem

Verification

  • bun x tsc -b (gui) ✅
  • Codex GUI tests: 48 pass ✅
  • bun run privacy:scan

@Wibias
Wibias force-pushed the fix/react-doctor-codex-accounts branch from 3853728 to 236ba2c Compare July 26, 2026 04:05
Wibias added 7 commits July 26, 2026 06:06
Make aliveRef StrictMode-replay-safe, preserve structured login errors on non-2xx, and keep the reset dialog labelled during confirmation.
Guard undefined login JSON bodies and point source-contract tests at the extracted OAuth/card modules.
Avoid inventing reset-credit counts, clear toast error tone on redeem, guard OAuth status polling, and localize leftover English fallbacks.
Clear startedReauthRef on cleanup so StrictMode remount can restart OAuth, abort in-flight login-status polls on cancel, and add focused regression tests for reauth, single-flight polling, already_redeemed, and toast tone.
Refresh WHAM quota after reset/already_redeemed and return remaining from stored quota. Drop GUI knownCredits-1 and modal-snapshot arithmetic so toasts never invent a decrement.
After reset/already_redeemed, return remaining only from a freshly parsed
rate_limit_reset_credits.available_count so stale cached credits never leak.
@Wibias
Wibias force-pushed the fix/react-doctor-codex-accounts branch from 236ba2c to 3fcdd96 Compare July 26, 2026 04:07
@Wibias
Wibias merged commit ac3af3e into lidge-jun:dev Jul 26, 2026
9 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant