Add Antigravity account switching - #937
Conversation
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 19e9365428
ℹ️ 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".
| if let tokenValue = environment[AntigravityOAuthCredentialsStore.environmentCredentialsKey] { | ||
| guard let credentials = AntigravityOAuthCredentialsStore.credentials(fromTokenAccountValue: tokenValue) else { | ||
| throw AntigravityRemoteFetchError.parseFailed("Could not decode selected account credentials.") | ||
| } | ||
| return (credentials, nil) |
There was a problem hiding this comment.
Persist selected-account credential updates
When credentials come from ANTIGRAVITY_OAUTH_CREDENTIALS_JSON, this path returns store: nil, so later refresh/project updates are never persisted (refreshAccessToken only saves when a store exists). On the next fetch, the provider re-reads the same stale token-account JSON and must refresh again, which can cause repeated OAuth refresh calls every cycle after first expiry and can break account usage if the refresh token/client fields ever rotate.
Useful? React with 👍 / 👎.
| let index = data.accounts.firstIndex(where: { account in | ||
| account.externalIdentifier == email || account.label == label | ||
| }) |
There was a problem hiding this comment.
Avoid merging distinct accounts on fallback label
This upsert match treats account.label == "Google Account" as identity, so any login where credentials.email is missing will overwrite an existing unlabeled account instead of creating a new one. Since email is optional in the OAuth credentials model, this can collapse multiple real accounts into one entry and defeats the new quick-switching behavior for those logins.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Pull request overview
This PR adds Antigravity to CodexBar’s token-account quick switching system so multiple Google OAuth accounts can be saved, selected, and used for remote usage fetching via an explicit environment override.
Changes:
- Adds Antigravity token-account support metadata and wiring so selected accounts inject credentials via
ANTIGRAVITY_OAUTH_CREDENTIALS_JSON. - Updates Antigravity remote usage fetching to prefer selected token-account credentials (and to fail on invalid selected-account JSON instead of silently falling back).
- Adds/updates tests and documentation describing the multi-account OAuth flow and expected behavior.
Reviewed changes
Copilot reviewed 10 out of 10 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| Tests/CodexBarTests/SettingsStoreCoverageTests.swift | Adds coverage for Antigravity OAuth upsert behavior into token accounts. |
| Tests/CodexBarTests/AntigravityRemoteUsageFetcherTests.swift | Adds tests for token-account injection, selection precedence, refresh isolation, and invalid selected-account handling. |
| Sources/CodexBarCore/TokenAccountSupportCatalog+Data.swift | Registers Antigravity as a token-account-capable provider and defines env injection key/UX strings. |
| Sources/CodexBarCore/Providers/Antigravity/AntigravityRemoteUsageFetcher.swift | Adds environment-driven credential selection and isolates persistence based on credential source. |
| Sources/CodexBarCore/Providers/Antigravity/AntigravityProviderDescriptor.swift | Passes provider fetch context environment into the Antigravity remote fetcher. |
| Sources/CodexBarCore/Providers/Antigravity/AntigravityOAuthCredentialsStore.swift | Adds env key constant and JSON (de)serialization helpers for token-account values. |
| Sources/CodexBar/Providers/Antigravity/AntigravitySettingsStore.swift | Adds Antigravity OAuth account upsert into token accounts after login. |
| Sources/CodexBar/Providers/Antigravity/AntigravityProviderImplementation.swift | Observes token accounts, adjusts settings action labeling, and adds a login menu override. |
| Sources/CodexBar/Providers/Antigravity/AntigravityLoginFlow.swift | Upserts shared credentials into a token account after a successful Antigravity login flow. |
| docs/antigravity.md | Documents OAuth multi-account switching and remote OAuth endpoints. |
Comments suppressed due to low confidence (1)
Sources/CodexBar/Providers/Antigravity/AntigravitySettingsStore.swift:41
- The upsert path always passes
organizationID: .some(nil)when updating an existing Antigravity token account, which forcibly clears any previously stored organization/workspace value. If Antigravity doesn’t useorganizationID, it’s safer to leave it unchanged by omitting the parameter (or only setting it when you intentionally want to change it).
self.updateTokenAccount(
provider: .antigravity,
accountID: account.id,
label: label,
token: token,
externalIdentifier: .some(email),
organizationID: .some(nil))
self.setActiveTokenAccountIndex(index, for: .antigravity)
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| let email = credentials.email?.trimmingCharacters(in: .whitespacesAndNewlines) | ||
| let label = (email?.isEmpty == false) ? email! : "Google Account" | ||
| let data = self.tokenAccountsData(for: .antigravity) | ||
| if let data, | ||
| let index = data.accounts.firstIndex(where: { account in | ||
| account.externalIdentifier == email || account.label == label |
| if let tokenValue = environment[AntigravityOAuthCredentialsStore.environmentCredentialsKey] { | ||
| guard let credentials = AntigravityOAuthCredentialsStore.credentials(fromTokenAccountValue: tokenValue) else { | ||
| throw AntigravityRemoteFetchError.parseFailed("Could not decode selected account credentials.") | ||
| } | ||
| return (credentials, nil) | ||
| } |
| let accountCount = context.settings.tokenAccounts(for: .antigravity).count | ||
| let loginTitle = accountCount > 0 ? "Add Google Account" : "Login with Google" | ||
| let subtitle = """ | ||
| Stores credentials in ~/.codexbar/antigravity/oauth_creds.json. Uses Antigravity.app OAuth when available, \ | ||
| Stores each signed-in Google account for quick Antigravity switching. Uses Antigravity.app OAuth when available, \ | ||
| or ANTIGRAVITY_OAUTH_CLIENT_ID and ANTIGRAVITY_OAUTH_CLIENT_SECRET as an override. | ||
| """ |
| ## Data sources + fallback order | ||
|
|
* Improve Kiro credits UX * Add provider changelog links * Fix changelog menu test * feat: gate provider changelog links behind setting * Address Kiro review feedback * Polish Kiro credit detail styling * fix: repair stale managed Codex account removal * fix: handle Claude enterprise web accounts (#941) Fixes Claude Enterprise/organization web accounts by tolerating null session-window usage and exposing an optional organization ID field for Claude token accounts. Local verification: - swift test --filter 'ClaudeWebEnterpriseUsageTests|ProvidersPaneCoverageTests|ClaudeUsageTests' - make check Co-authored-by: Claude <noreply@anthropic.com> * docs: update changelog for Claude enterprise fix * fix: handle quota and usage edge cases * Rebalance Kimi provider icon (#912) * Add zh-Hans translations for Claude peak hour labels (#921) * docs: update changelog for recent contributor fixes * Add Tahoe menu bar visibility guidance Co-authored-by: Piotr Durlej <pdurlej@users.noreply.github.com> * Coalesce historical pace reset buckets Co-authored-by: zhulijin1991 <zhulijin1991@users.noreply.github.com> * Add Codex priority cost pricing Co-authored-by: Bryan Font <bfont@me.com> * fix: parse Claude web spend limits * fix: refresh Gemini credentials without access token * refactor: split Claude web extra usage helpers * fix: defer account switcher menu rebuilds Fixes #944. Refs #946. Co-authored-by: Jakub Hašek <kubahasek@users.noreply.github.com> * docs: fix changelog spacing * fix: handle unavailable Codex limits gracefully * docs: update unreleased changelog * fix: repair update and account menu paths Co-authored-by: Radek Sienkiewicz <mail@velvetshark.com> * fix: handle account-scoped usage and menu login bugs * Add Antigravity account switching (#937) * Add Antigravity account switching * Force Antigravity account chooser * Persist Antigravity selected account updates * docs: add Antigravity account switching changelog --------- Co-authored-by: thiagocaltoe <thiago12_fera@hotmail.com> Co-authored-by: Peter Steinberger <steipete@gmail.com> Co-authored-by: Clint Andrew Hall <clint@clintandrewhall.com> Co-authored-by: Claude <noreply@anthropic.com> Co-authored-by: Giuseppe Bisemi <giuseppe.bisemi@gmail.com> Co-authored-by: HaiTao Wu <whtis@users.noreply.github.com> Co-authored-by: Piotr Durlej <pdurlej@users.noreply.github.com> Co-authored-by: zhulijin1991 <167979819+zhulijin1991@users.noreply.github.com> Co-authored-by: zhulijin1991 <zhulijin1991@users.noreply.github.com> Co-authored-by: iam-brain <94809115+iam-brain@users.noreply.github.com> Co-authored-by: Bryan Font <bfont@me.com> Co-authored-by: Jakub Hašek <kubahasek@users.noreply.github.com> Co-authored-by: Radek Sienkiewicz <mail@velvetshark.com> Co-authored-by: Larry Hao(郝卓远) <107194248+hhh2210@users.noreply.github.com>
* Add Antigravity account switching * Force Antigravity account chooser * Persist Antigravity selected account updates
* Improve Kiro credits UX * Add provider changelog links * Fix changelog menu test * feat: gate provider changelog links behind setting * Address Kiro review feedback * Polish Kiro credit detail styling * fix: repair stale managed Codex account removal * fix: handle Claude enterprise web accounts (steipete#941) Fixes Claude Enterprise/organization web accounts by tolerating null session-window usage and exposing an optional organization ID field for Claude token accounts. Local verification: - swift test --filter 'ClaudeWebEnterpriseUsageTests|ProvidersPaneCoverageTests|ClaudeUsageTests' - make check Co-authored-by: Claude <noreply@anthropic.com> * docs: update changelog for Claude enterprise fix * fix: handle quota and usage edge cases * Rebalance Kimi provider icon (steipete#912) * Add zh-Hans translations for Claude peak hour labels (steipete#921) * docs: update changelog for recent contributor fixes * Add Tahoe menu bar visibility guidance Co-authored-by: Piotr Durlej <pdurlej@users.noreply.github.com> * Coalesce historical pace reset buckets Co-authored-by: zhulijin1991 <zhulijin1991@users.noreply.github.com> * Add Codex priority cost pricing Co-authored-by: Bryan Font <bfont@me.com> * fix: parse Claude web spend limits * fix: refresh Gemini credentials without access token * refactor: split Claude web extra usage helpers * fix: defer account switcher menu rebuilds Fixes steipete#944. Refs steipete#946. Co-authored-by: Jakub Hašek <kubahasek@users.noreply.github.com> * docs: fix changelog spacing * fix: handle unavailable Codex limits gracefully * docs: update unreleased changelog * fix: repair update and account menu paths Co-authored-by: Radek Sienkiewicz <mail@velvetshark.com> * fix: handle account-scoped usage and menu login bugs * Add Antigravity account switching (steipete#937) * Add Antigravity account switching * Force Antigravity account chooser * Persist Antigravity selected account updates * docs: add Antigravity account switching changelog --------- Co-authored-by: thiagocaltoe <thiago12_fera@hotmail.com> Co-authored-by: Peter Steinberger <steipete@gmail.com> Co-authored-by: Clint Andrew Hall <clint@clintandrewhall.com> Co-authored-by: Claude <noreply@anthropic.com> Co-authored-by: Giuseppe Bisemi <giuseppe.bisemi@gmail.com> Co-authored-by: HaiTao Wu <whtis@users.noreply.github.com> Co-authored-by: Piotr Durlej <pdurlej@users.noreply.github.com> Co-authored-by: zhulijin1991 <167979819+zhulijin1991@users.noreply.github.com> Co-authored-by: zhulijin1991 <zhulijin1991@users.noreply.github.com> Co-authored-by: iam-brain <94809115+iam-brain@users.noreply.github.com> Co-authored-by: Bryan Font <bfont@me.com> Co-authored-by: Jakub Hašek <kubahasek@users.noreply.github.com> Co-authored-by: Radek Sienkiewicz <mail@velvetshark.com> Co-authored-by: Larry Hao(郝卓远) <107194248+hhh2210@users.noreply.github.com>

Summary
~/.codexbar/antigravity/oauth_creds.jsonfallback when no token account is selected.ANTIGRAVITY_OAUTH_CREDENTIALS_JSON, with invalid selected-account JSON failing closed instead of silently falling back to shared credentials.Review feedback addressed
ProviderFetchContextinto the Antigravity fetcher.Google Accountlabel. Fixed by matching only non-empty email identifiers and using numbered fallback labels.organizationIDis no longer cleared during Antigravity account updates.Testing
./Scripts/lint.sh format && ./Scripts/lint.sh lintpassed, 0 violations.swift test --filter AntigravityRemoteUsageFetcherTestspassed, 16 tests.swift test --filter SettingsStoreCoverageTestspassed, 28 tests.swift test --filter AntigravityLoginAlertTestspassed, 5 tests.swift testpassed, 2356 tests in 292 suites../Scripts/compile_and_run.shpassed, built the production app, packagedCodexBar.app, launched it, and verifiedOK: CodexBar is running.Closes #936