Files
2026-07-13 12:22:33 +08:00

102 lines
5.1 KiB
Markdown

---
summary: "Gemini provider data sources: OAuth-backed quota APIs, token refresh, and tier detection."
read_when:
- Debugging Gemini quota fetch or auth issues
- Updating Gemini CLI OAuth integration
- Adjusting tier detection or model mapping
---
# Gemini provider
Gemini uses the Gemini CLI OAuth credentials and private quota APIs. No browser cookies.
## Data sources + fallback order
1) **OAuth-backed quota API** (only path used in `fetch()`)
- Reads auth type from `~/.gemini/settings.json`.
- Supported: `oauth-personal` (or unknown → try OAuth creds).
- Unsupported: `api-key`, `vertex-ai` (hard error).
2) **Legacy CLI parsing** (parser exists but not used in current fetch path)
- `GeminiStatusProbe.parse(text:)` can parse `/stats` output.
## OAuth credentials
- File: `~/.gemini/oauth_creds.json`.
- Required fields: `access_token`, `refresh_token` (optional), `id_token`, `expiry_date`.
- If access token is expired, we refresh via Google OAuth using client ID/secret extracted
from the Gemini CLI install (see below).
## OAuth client ID/secret extraction
- Resolution order:
1. `GEMINI_OAUTH_CLIENT_ID` + `GEMINI_OAUTH_CLIENT_SECRET` environment override.
2. `GEMINI_OAUTH2_JS_PATH` pointing at a readable `oauth2.js` file.
3. Installed Gemini CLI package (`oauth2.js` / bundle regex extraction).
4. Known global Gemini CLI install paths (Homebrew npm prefix layouts, then
Homebrew Cellar/`opt` `libexec` package roots when the GUI cannot resolve
the `gemini` binary).
- We locate the installed `gemini` binary, then search for:
- Homebrew nested path:
- `.../libexec/lib/node_modules/@google/gemini-cli/node_modules/@google/gemini-cli-core/dist/src/code_assist/oauth2.js`
- Homebrew Cellar/opt package root (no-binary fallback):
- `/opt/homebrew/Cellar/gemini-cli/<version>/libexec/lib/node_modules/@google/gemini-cli`
- `/opt/homebrew/opt/gemini-cli/libexec/lib/node_modules/@google/gemini-cli`
- same under `/usr/local`
- Bun/npm sibling path:
- `.../node_modules/@google/gemini-cli-core/dist/src/code_assist/oauth2.js`
- Regex extraction:
- `OAUTH_CLIENT_ID` and `OAUTH_CLIENT_SECRET` from `oauth2.js` or Homebrew bundle chunks.
## API endpoints
- Quota:
- `POST https://cloudcode-pa.googleapis.com/v1internal:retrieveUserQuota`
- Body: `{ "project": "<projectId>" }` (or `{}` if unknown)
- Header: `Authorization: Bearer <access_token>`
- Project discovery (quota project ID):
- Primary: `cloudaicompanionProject` from `loadCodeAssist`.
- Fallback: `GET https://cloudresourcemanager.googleapis.com/v1/projects`
- Picks `gen-lang-client*` or label `generative-language`.
- Tier detection:
- `POST https://cloudcode-pa.googleapis.com/v1internal:loadCodeAssist`
- Body: `{ "metadata": { "ideType": "GEMINI_CLI", "pluginType": "GEMINI" } }`
- Token refresh:
- `POST https://oauth2.googleapis.com/token`
- Form body: `client_id`, `client_secret`, `refresh_token`, `grant_type=refresh_token`.
## Parsing + mapping
- Quota buckets:
- `remainingFraction`, `resetTime`, `modelId`.
- For each model, lowest `remainingFraction` wins.
- `percentLeft = remainingFraction * 100`.
- Reset:
- `resetTime` parsed as ISO-8601, formatted as "Resets in Xh Ym".
- UI mapping:
- Primary: Pro models (lowest percent left).
- Secondary: Flash models (lowest percent left).
## Plan detection
- Tier from `loadCodeAssist`:
- `paidTier.name` → paid subscription label from Google, preferred whenever present
- `standard-tier` → "Paid" (fallback when `paidTier.name` is absent)
- `free-tier` + `hd` claim → "Workspace" (fallback when `paidTier.name` is absent)
- `free-tier` → "Free"
- `legacy-tier` → "Legacy"
- Email from `id_token` JWT claims.
## Consumer-tier migration (June 2026)
- [Google stopped serving](https://developers.google.com/gemini-code-assist/docs/deprecations/code-assist-individuals)
Gemini CLI OAuth for individual, AI Pro, and Ultra accounts on 2026-06-18. Standard and Enterprise
subscriptions remain supported; paid API-key access is outside CodexBar's OAuth-backed Gemini provider.
- When quota, `loadCodeAssist`, or token-refresh responses include Google's unsupported-client
migration signal (`UNSUPPORTED_CLIENT`, `IneligibleTierError`, or Antigravity migration copy),
CodexBar surfaces `consumerTierDeprecated` with guidance to use the Antigravity provider.
- Settings shows an **Enable Antigravity provider** action only after CodexBar observes
`consumerTierDeprecated` during a Gemini refresh (typed sentinel state, not user-facing text matching).
- The action is explicit: CodexBar never automatically enables Antigravity or falls back to it.
- Ordinary Gemini login, `notLoggedIn`, and Antigravity setup errors remain unchanged. CodexBar does not
capture Terminal `gemini` OAuth output, so Terminal-only failures cannot activate the migration action.
- Workspace and education Google accounts are outside the June 2026 consumer shutdown; keep using the
Gemini provider. Antigravity remains the consumer replacement path for individual, AI Pro, and Ultra.
## Key files
- `Sources/CodexBarCore/Providers/Gemini/GeminiStatusProbe.swift`