Skip to content

feat: Codex (ChatGPT subscription) provider#16

Merged
FBarrca merged 1 commit into
FBarrca:mainfrom
FelixIsaac:felix/codex-subscription-provider
May 22, 2026
Merged

feat: Codex (ChatGPT subscription) provider#16
FBarrca merged 1 commit into
FBarrca:mainfrom
FelixIsaac:felix/codex-subscription-provider

Conversation

@FelixIsaac

@FelixIsaac FelixIsaac commented May 22, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Adds a new Codex (ChatGPT subscription) provider option that authenticates via OpenAI's official OAuth PKCE flow (same method used by the official Codex CLI)
  • On sign-in, opens a browser window and spins up a local callback server on localhost:1455 to capture the auth code; tokens are stored in plugin settings and auto-refreshed
  • API calls go directly to https://chatgpt.com/backend-api/codex/responses (the responses API) with the required Codex headers, bypassing LangChain for this provider
  • Sign in / Sign out UI in the settings tab

How it works

  1. User selects Codex (ChatGPT subscription) in the provider dropdown
  2. Clicks Sign in with ChatGPT — browser opens to auth.openai.com
  3. After login, callback is captured, tokens stored
  4. All subsequent calls use the OAuth bearer token billed against the ChatGPT subscription

New files

  • src/codex-auth.ts — PKCE OAuth flow, token refresh, token validation
  • src/codex-client.ts — Codex responses API client + SSE parser

Notes

  • Uses the same CLIENT_ID and endpoints as the official openai/codex CLI
  • Intended for personal use with a ChatGPT Plus/Pro subscription; for production/automation use the Platform API key instead
  • Default model is whatever is set in the Model field; suggest gpt-5.1-codex or codex-mini-latest

Test plan

  • Select Codex provider → sign-in button appears
  • Click sign in → browser opens, completes OAuth, notice shows "signed in"
  • Settings shows account ID after sign-in
  • Trigger inline AI action → response generated via Codex
  • Token expiry → auto-refresh works without re-login
  • Sign out → tokens cleared

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features
    • Added Codex (ChatGPT subscription) as a new AI provider option
    • Implemented OAuth-based authentication with automatic access token refresh and session management
    • Added Codex account sign-in and sign-out controls in the settings panel

Review Change Stack

OAuth PKCE flow to auth w/ ChatGPT Plus/Pro; stores tokens in plugin
settings. Calls chatgpt.com/backend-api/codex/responses (responses API)
instead of chat completions. Auto-refreshes tokens. Sign in/out UI in
settings tab.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented May 22, 2026

Copy link
Copy Markdown
📝 Walkthrough

Walkthrough

This PR adds Codex (ChatGPT subscription) as a new provider alongside existing LangChain clients. It includes OAuth PKCE authentication with token refresh, a direct Codex API client for streaming responses, settings UI controls for sign-in/sign-out, and integration into the ChatApiManager request flow.

Changes

Codex Provider Integration

Layer / File(s) Summary
Settings schema and provider configuration
src/settings.ts
InlineAISettings adds Codex token fields (codexAccess, codexRefresh, codexExpires, codexAccountId) and extends provider union to "codex". Settings UI includes Codex sign-in/sign-out controls that invoke OAuth and persist tokens.
OAuth authentication and token lifecycle
src/codex-auth.ts
New module implements PKCE-based OAuth with CodexTokens interface, authorization code exchange, token refresh (preserving account ID), expiry validation via getValidCodexToken, and startCodexOAuthFlow that runs a local callback server on port 1455 with 5-minute timeout.
Codex API client and SSE response parsing
src/codex-client.ts
callCodexApi sends authenticated streaming POST requests to Codex endpoint, normalizes model names, parses SSE responses for output_text deltas from JSON payloads, and throws on errors or empty results.
Chat API manager routing for Codex
src/api.ts
Imports Codex helpers and adds routing: initializeChatClient returns null for "codex", callApi dispatches to new callCodexProvider method which validates credentials, refreshes tokens, invokes callCodexApi, updates settings, and handles errors with user-facing Notices.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Poem

🐰 A rabbit hops through OAuth flows,
With PKCE magic, token grows.
Codex awakes through settings' gate,
Fresh access tokens validate,
ChatGPT now plays along!

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'feat: Codex (ChatGPT subscription) provider' directly and clearly summarizes the main change—adding a new Codex provider with ChatGPT subscription support, which aligns with the PR's primary objective and all the file changes.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
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.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

@coderabbitai coderabbitai 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.

Actionable comments posted: 5

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/api.ts`:
- Around line 237-241: The token refresh updates
(this.settings.codexAccess/codexRefresh/codexExpires) but aren't persisted;
modify ChatApiManager to accept a persist callback (e.g., onPersist or
saveSettingsCallback) in its constructor or init, pass () => this.saveSettings()
from main.ts, and invoke that callback inside the getValidCodexToken refresh
handler used by callCodexProvider (immediately after updating this.settings.*)
so refreshed Codex tokens are saved to disk via
plugin.saveSettings()/saveData().

In `@src/codex-auth.ts`:
- Around line 100-108: The refresh response handling currently computes expires
as Date.now() + json.expires_in * 1000 without validating expires_in, which can
produce NaN; update the refresh flow (the same block that reads json and returns
{ access, refresh, expires }) to validate json.expires_in (e.g. typeof
json.expires_in === 'number' && Number.isFinite(json.expires_in') or parse and
check) and return null if it's missing/invalid, mirroring the initial token
acquisition guard so expires is always a valid timestamp.
- Around line 81-86: The token factory returns expires based on json.expires_in
without validation, causing NaN if expires_in is missing; update the code that
builds the token object (the return block in the function that constructs
access/refresh/expires/accountId used by getValidCodexToken) to validate and
normalize json.expires_in (e.g., ensure it's a finite positive number via
Number(...) check or default to 0 or a conservative TTL) before computing
Date.now() + expires_in*1000, and if it's invalid consider either throwing a
clear error or setting expires to Date.now() (or Date.now() + 0) so subsequent
getValidCodexToken logic behaves predictably. Ensure you reference the same
returned fields (access, refresh, expires, accountId) so callers remain
unchanged.

In `@src/settings.ts`:
- Around line 90-93: The UI's isSignedIn calculation (variable isSignedIn using
this.plugin.settings.codexAccess and codexAccountId) is inconsistent with API
validation in callCodexProvider which also requires codexRefresh; update the
sign-in check to include this.plugin.settings.codexRefresh so the UI only
reports signed-in when codexAccess, codexAccountId and codexRefresh are present,
and ensure any related UI text/flows that rely on isSignedIn still behave
correctly.
- Around line 113-125: Wrap the call to startCodexOAuthFlow() in a try/catch
inside the block where you open the browser for sign-in; if it throws, catch the
error, log it (e.g., console.error or process/plugin logger) and show a
user-facing Notice with an error message, and return or abort without mutating
settings. Keep the existing logic that, on success, assigns tokens to
this.plugin.settings.codexAccess/codexRefresh/codexExpires/codexAccountId, calls
await this.saveSettings(), shows the success Notice, and calls this.display();
ensure any cleanup or UI state update still happens in the error path as
appropriate.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 1a1c9c46-8b60-463e-b445-690cfd14f027

📥 Commits

Reviewing files that changed from the base of the PR and between 3912da8 and 6880043.

📒 Files selected for processing (4)
  • src/api.ts
  • src/codex-auth.ts
  • src/codex-client.ts
  • src/settings.ts

Comment thread src/api.ts
Comment thread src/codex-auth.ts
Comment thread src/codex-auth.ts
Comment thread src/settings.ts
Comment thread src/settings.ts
@FBarrca

FBarrca commented May 22, 2026

Copy link
Copy Markdown
Owner

Thanks for this PR.

I'm probably going to use this myself!

There are some issues highlighted by Code Rabbit, but they are more code quality things that are not really needed rn.

@FBarrca FBarrca merged commit 5f21d0b into FBarrca:main May 22, 2026
1 check passed
@FelixIsaac

Copy link
Copy Markdown
Contributor Author

Thanks for the super quick merge! 🙏 Found a couple of bugs while testing locally — opened #17 with fixes (Obsidian CSP blocks native fetch so switched to requestUrl, SSE delta parsing fix, and a model dropdown for Codex). Working well now!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants