FMG-11: Add ChatGPT as a third usage provider #1

Open
butterrobot wants to merge 3 commits from butterrobot/fmg-11-chatgpt-provider into main AGit

2026-09-11

Fix the app-server handshake against the documented protocol
The previous commit's messages were rejected by Codex. Checked against the
app-server documentation rather than guessing again:

- app-server omits the `"jsonrpc": "2.0"` header on the wire; we were sending
  it on every message.
- `initialize` takes `params.capabilities.experimentalApi`, which part of the
  server's surface is gated behind. We sent only `clientInfo`.
- The documented invocation is a bare `codex app-server`. The `-s read-only
  -a never` prefix was defensive but undocumented, and nothing here starts a
  thread or runs a turn for it to constrain.

Also fixed alongside:

- A PATH-only install was unreachable: `URL(fileURLWithPath: "codex")`
  resolves against the working directory, so the fallback now goes through
  `/usr/bin/env`.
- stdout and stderr are drained as they fill instead of after exit, which
  removes both the pipe-buffer deadlock and the full timeout wait for a
  server that outlives its stdin. The request returns as soon as its
  response lands.
- Failures now carry the exit status and the stderr tail instead of a bare
  "could not parse", so the next report says what actually happened.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-11 09:03:59 +00:00
Read ChatGPT usage through the Codex CLI only
The ChatGPT provider no longer touches credentials at all. Usage now comes
from `codex app-server`, the CLI's stdio JSON-RPC interface: handshake, then
`account/rateLimits/read`. Codex owns authentication end to end, so this works
wherever it keeps its credentials — file, keyring or ephemeral — and the app
never reads, stores or forwards a token.

Removed accordingly:

- Reading ~/.codex/auth.json and the CODEX_HOME environment variable.
- The manual-token and Admin API key modes for this provider, along with the
  OpenAI organization usage/cost metrics. ChatGPT now offers Auto only, and
  Settings no longer queries the Keychain for a provider that cannot use it.
- The shared JWT helper, which existed only to read claims out of Codex
  tokens; CursorAuthService is back to its original form.

This also drops the HTTP path, whose endpoint was wrong: the earlier commit
used /backend-api/codex/usage, while Codex actually polls
/backend-api/wham/usage with a different response shape.

The app-server command is documented as experimental and
`account/rateLimits/read` is undocumented, so the decoder accepts the windows
wrapped in `rateLimits` or inlined at the root, and an absolute `resetsAt` or
a `resetsInSeconds` countdown.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-11 06:41:59 +00:00
Add ChatGPT as a third usage provider
Adds a ChatGPT provider alongside Cursor and Claude, following the same
provider/auth/metric structure:

- Auto mode reads the Codex CLI session from ~/.codex/auth.json (CODEX_HOME
  aware) and queries the ChatGPT usage endpoint for the 5-hour and weekly
  rate-limit windows.
- Manual mode accepts a pasted ChatGPT access token; the account id and plan
  are recovered from the token's own claims.
- Admin mode reports 7-day input/output tokens and cost from the OpenAI
  organization usage and costs APIs.

Supporting changes:

- Extract base64url JWT payload decoding into a shared JWT helper, reused by
  CursorAuthService.
- Replace the duplicated provider lookup in UsageRefreshService and
  SettingsView with ProviderID.provider.
- Build the Settings provider tabs from ProviderID.allCases.
- Providers missing from previously saved settings now start disabled, so the
  upgrade does not add an unconfigured indicator to an existing menu bar.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-11 06:21:57 +00:00