Skip to content

Feature/codex OpenAI auth#33

Merged
b3nw merged 11 commits intodevfrom
feature/codex-openai-auth
Feb 14, 2026
Merged

Feature/codex OpenAI auth#33
b3nw merged 11 commits intodevfrom
feature/codex-openai-auth

Conversation

@b3nw
Copy link
Owner

@b3nw b3nw commented Feb 14, 2026

Adds a new provider for OpenAI Codex models (GPT-5, GPT-5.1, GPT-5.2, Codex, Codex Mini)
via the ChatGPT Responses API with OAuth PKCE authentication.

Key features:

  • OAuth base class for OpenAI authentication with PKCE flow and token refresh
  • Responses API streaming with SSE event handling
  • Reasoning/thinking output with configurable effort levels (minimal to xhigh)
  • Tool calling support translated from OpenAI format
  • System prompt validation using official opencode prompt
  • Usage tracking with proper litellm.Usage objects

Files added:

  • codex_provider.py: Main provider implementation
  • openai_oauth_base.py: OAuth base class with PKCE support
  • codex_prompt.txt: Required system prompt for API validation

based on Mirrowel#73

FammasMaz and others added 10 commits February 14, 2026 03:38
… support

Adds a new provider for OpenAI Codex models (GPT-5, GPT-5.1, GPT-5.2, Codex, Codex Mini)
via the ChatGPT Responses API with OAuth PKCE authentication.

Key features:
- OAuth base class for OpenAI authentication with PKCE flow and token refresh
- Responses API streaming with SSE event handling
- Reasoning/thinking output with configurable effort levels (minimal to xhigh)
- Tool calling support translated from OpenAI format
- System prompt validation using official opencode prompt
- Usage tracking with proper litellm.Usage objects

Files added:
- codex_provider.py: Main provider implementation
- openai_oauth_base.py: OAuth base class with PKCE support
- codex_prompt.txt: Required system prompt for API validation
Models must be returned with the 'codex/' prefix (e.g., 'codex/gpt-5.2')
to match the convention used by other providers like antigravity.
This ensures proper provider routing in the RotatingClient.
Exposes reasoning effort levels as model variants:
- codex/gpt-5.2:low, :medium, :high, :xhigh
- codex/gpt-5.1:low, :medium, :high
- And similar for all codex models

This allows clients to control reasoning effort by model name,
similar to how gemini models use :thinking suffix.

Total models: 9 base + 30 reasoning variants = 39 models
Injects an identity override as the first user message that tells the model
to prioritize user-provided system prompts over the required opencode
instructions. This mirrors the pattern used by Antigravity provider.

Message order:
1. Identity override (<system_override> tag)
2. User's system message (converted to user message)
3. Rest of conversation

Controlled by CODEX_INJECT_IDENTITY_OVERRIDE env var (default: true)
Documents all Codex environment variables:
- CODEX_REASONING_EFFORT: low/medium/high/xhigh
- CODEX_REASONING_SUMMARY: auto/concise/detailed/none
- CODEX_REASONING_COMPAT: think-tags/raw/none
- CODEX_INJECT_IDENTITY_OVERRIDE: true/false
- CODEX_INJECT_INSTRUCTION: true/false
- CODEX_EMPTY_RESPONSE_ATTEMPTS: retry count
- CODEX_EMPTY_RESPONSE_RETRY_DELAY: seconds
- CODEX_OAUTH_PORT: callback port
Adds Codex to PROVIDER_MAP so it appears in the credential tool's
"Add OAuth Credential" menu alongside other OAuth providers.
Integrate CodexQuotaTracker mixin into CodexProvider to track API usage
via response headers and periodic quota API calls. Enables smart
credential selection based on remaining quota and automatic cooldowns
when limits are approached.

Signed-off-by: Moeeze Hassan <fammas.maz@gmail.com>
- Add set_usage_manager() to CodexQuotaTracker mixin
- Push parsed rate limit headers to UsageManager via update_quota_baseline
- Inject UsageManager reference during RotatingClient initialization
- Enables quota status display in TUI after each Codex API response
…hing

Sequential mode reuses the same credential across requests, enabling
upstream token caching on the Codex API.
@gemini-code-assist
Copy link

Summary of Changes

Hello @b3nw, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request significantly expands the application's capabilities by integrating a new provider for OpenAI's Codex models. It introduces a sophisticated OAuth 2.0 with PKCE authentication mechanism, enabling secure and managed access to these models. The changes also incorporate advanced features like configurable reasoning levels and tool calling, alongside a robust system for tracking API quotas and usage. This enhancement allows for more diverse and powerful AI model interactions within the system, with improved credential management and operational visibility.

Highlights

  • New OpenAI Codex Provider: Introduced a new provider, CodexProvider, to support OpenAI Codex models (GPT-5, GPT-5.1, GPT-5.2, Codex, Codex Mini) via the ChatGPT Responses API.
  • OAuth PKCE Authentication: Implemented a robust OAuth 2.0 with PKCE (Proof Key for Code Exchange) authentication flow for OpenAI, including token refresh and API key exchange, encapsulated in a new OpenAIOAuthBase.
  • Advanced Model Features: Added support for reasoning/thinking output with configurable effort levels (low, medium, high, xhigh), tool calling, and system prompt validation using a dedicated codex_prompt.txt.
  • Quota and Usage Tracking: Integrated comprehensive quota tracking for the Codex API, including primary/secondary rate limit windows and credit balance, with updates from response headers and a background refresh mechanism via CodexQuotaTracker.
  • Configuration Options: Exposed various configuration options in .env.example for reasoning effort, summary, output format, identity override, instruction injection, empty response handling, and OAuth port.
Changelog
  • .env.example
    • Added extensive configuration options for the new OpenAI Codex provider, including reasoning effort, summary, output format, identity override, instruction injection, empty response handling, and OAuth port.
  • src/rotator_library/client/rotating_client.py
    • Modified the initialize_usage_managers method to inject usage manager references into providers that support it, specifically for the new Codex provider.
  • src/rotator_library/credential_manager.py
    • Updated the PROVIDER_CLI_PATHS and PROVIDER_ENV_PREFIXES dictionaries to include the 'codex' provider.
  • src/rotator_library/credential_tool.py
    • Added 'OpenAI Codex' to the PROVIDER_NAMES mapping for credential management.
  • src/rotator_library/provider_factory.py
    • Mapped the 'codex' provider name to the new OpenAIOAuthBase class in the PROVIDER_MAP.
  • src/rotator_library/providers/codex_prompt.txt
    • Added a new file containing the official system prompt for OpenAI Codex models, detailing agent capabilities, personality, planning, task execution, sandboxing, validation, and communication guidelines.
  • src/rotator_library/providers/codex_provider.py
    • Added a new file implementing the CodexProvider class, which handles chat completion requests for OpenAI Codex models using the Responses API, OAuth authentication, reasoning parameters, tool calling, and integrates with the CodexQuotaTracker.
  • src/rotator_library/providers/openai_oauth_base.py
    • Added a new file defining OpenAIOAuthBase, a base class for OpenAI OAuth2 authentication, managing PKCE flow, token refresh, API key exchange, and interactive authentication.
  • src/rotator_library/providers/utilities/codex_quota_tracker.py
    • Added a new file containing the CodexQuotaTracker mixin, responsible for fetching and parsing rate limit information from the Codex API, updating quota baselines, and integrating with the UsageManager.
Activity
  • No human activity (comments, reviews, progress updates) was provided in the context for this pull request.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request introduces a new codex provider for OpenAI models, using OAuth with PKCE for authentication. The implementation is comprehensive, adding a new base class for OpenAI OAuth, a quota tracking mixin, and the provider logic itself. The changes are well-structured, with new functionality encapsulated in separate modules. The code also includes updates to configuration, credential management, and the client to support the new provider. My review focuses on improving maintainability and configuration practices. I've identified a few areas for improvement, including a hardcoded client ID and a redundant timeout, which should be addressed. Overall, this is a solid contribution that significantly extends the library's capabilities.

Comment on lines +182 to +196
def _allowed_efforts_for_model(model: str) -> set:
"""Get allowed reasoning effort levels for a model."""
base = (model or "").strip().lower()
if not base:
return REASONING_EFFORTS

normalized = base.split(":")[0]
if normalized.startswith("gpt-5.2"):
return {"low", "medium", "high", "xhigh"}
if normalized.startswith("gpt-5.1-codex-max"):
return {"low", "medium", "high", "xhigh"}
if normalized.startswith("gpt-5.1"):
return {"low", "medium", "high"}

return REASONING_EFFORTS

Choose a reason for hiding this comment

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

medium

The function _allowed_efforts_for_model uses a series of hardcoded startswith checks to determine the allowed reasoning efforts for a model. This logic is disconnected from the REASONING_MODEL_EFFORTS dictionary defined earlier, which can lead to maintenance issues. If REASONING_MODEL_EFFORTS is updated, this function would also need to be updated manually. To improve maintainability and keep a single source of truth, this function should be refactored to derive the allowed efforts directly from the REASONING_MODEL_EFFORTS dictionary by finding the longest matching prefix from its keys.

Suggested change
def _allowed_efforts_for_model(model: str) -> set:
"""Get allowed reasoning effort levels for a model."""
base = (model or "").strip().lower()
if not base:
return REASONING_EFFORTS
normalized = base.split(":")[0]
if normalized.startswith("gpt-5.2"):
return {"low", "medium", "high", "xhigh"}
if normalized.startswith("gpt-5.1-codex-max"):
return {"low", "medium", "high", "xhigh"}
if normalized.startswith("gpt-5.1"):
return {"low", "medium", "high"}
return REASONING_EFFORTS
def _allowed_efforts_for_model(model: str) -> set:
"""Get allowed reasoning effort levels for a model."""
base = (model or "").strip().lower()
if not base:
return REASONING_EFFORTS
normalized = base.split(":")[0]
# Find the best matching model from REASONING_MODEL_EFFORTS keys
# to avoid hardcoding and improve maintainability.
best_match = ""
for m in REASONING_MODEL_EFFORTS:
if normalized.startswith(m) and len(m) > len(best_match):
best_match = m
if best_match:
return REASONING_MODEL_EFFORTS[best_match]
return REASONING_EFFORTS

"""

# Subclasses MUST override these
CLIENT_ID: str = "app_EMoamEEZ73f0CkXaXp7hrann"

Choose a reason for hiding this comment

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

medium

The CLIENT_ID is hardcoded in the OpenAIOAuthBase class. While OAuth client IDs for public clients are often not secret, hardcoding this value makes the code less flexible and harder to maintain. For instance, if the client ID needs to be rotated or if a fork of this project needs to use a different client ID, the code would have to be changed. It is a best practice to make such configurations external, for example, by loading them from an environment variable with a sensible default.

Suggested change
CLIENT_ID: str = "app_EMoamEEZ73f0CkXaXp7hrann"
CLIENT_ID: str = os.getenv("OPENAI_OAUTH_CLIENT_ID", "app_EMoamEEZ73f0CkXaXp7hrann")

"[bold green]Waiting for you to complete authentication in the browser...[/bold green]",
spinner="dots",
):
auth_code = await asyncio.wait_for(auth_code_future, timeout=310)

Choose a reason for hiding this comment

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

medium

There is a redundant asyncio.wait_for with a hardcoded timeout of 310 seconds inside the _perform_interactive_oauth method. The calling function, initialize_token, already wraps the re-authentication flow in a timeout of 300 seconds via the ReauthCoordinator. This means the outer timeout will always trigger before this inner one, making it ineffective and potentially confusing. The inner wait_for should be removed to rely on the single, configurable timeout managed by the coordinator.

Suggested change
auth_code = await asyncio.wait_for(auth_code_future, timeout=310)
auth_code = await auth_code_future

Get remaining quota info for a credential.

This returns the rate limit status including primary/secondary windows
and credits info.
Copy link

Choose a reason for hiding this comment

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

WARNING: Inconsistent header case for account ID

The header uses lowercase chatgpt-account-id, but in codex_quota_tracker.py line 3174 (in the same PR), the same header uses ChatGPT-Account-Id with the comment "Exact capitalization from Codex CLI". This inconsistency could cause account identification issues with the Codex API.

Suggested change
and credits info.
headers["ChatGPT-Account-Id"] = account_id

@kiloconnect
Copy link

kiloconnect bot commented Feb 14, 2026

Code Review Summary

Status: 1 Issue Found | Recommendation: Address before merge

Overview

Severity Count
CRITICAL 0
WARNING 1
SUGGESTION 0
Issue Details (click to expand)

WARNING

File Line Issue
src/rotator_library/providers/codex_provider.py 1107 Inconsistent header case for account ID - uses lowercase chatgpt-account-id but quota tracker uses ChatGPT-Account-Id
Other Observations (not in diff)

Additional notes that don't require inline comments:

Item Note
OAuth Port Default Code defaults to port 1455 but .env.example suggests 8086. Minor inconsistency - users can override via CODEX_OAUTH_PORT env var.
Files Reviewed (9 files)
  • .env.example - Codex environment configuration
  • src/rotator_library/client/rotating_client.py - Usage manager injection
  • src/rotator_library/credential_manager.py - Codex credential path and env prefix
  • src/rotator_library/credential_tool.py - Codex display name mapping
  • src/rotator_library/provider_factory.py - Codex provider mapping
  • src/rotator_library/providers/codex_prompt.txt - Codex system prompt
  • src/rotator_library/providers/codex_provider.py - Main Codex provider implementation
  • src/rotator_library/providers/openai_oauth_base.py - OAuth base class
  • src/rotator_library/providers/utilities/codex_quota_tracker.py - Quota tracking

Overall: The PR introduces a new Codex provider with OAuth authentication and quota tracking. The main issue is the inconsistent header case for the account ID header between the provider and quota tracker. Once this is addressed, the implementation looks solid.

Match the exact capitalization used by the Codex CLI, consistent with
codex_quota_tracker.py. Addresses PR review feedback.
@b3nw b3nw merged commit 256aac7 into dev Feb 14, 2026
b3nw added a commit that referenced this pull request Feb 15, 2026
… support (#33)

* feat(rotator_library): ✨ add OpenAI Codex provider with Responses API support

Adds a new provider for OpenAI Codex models (GPT-5, GPT-5.1, GPT-5.2, Codex, Codex Mini)
via the ChatGPT Responses API with OAuth PKCE authentication.

Key features:
- OAuth base class for OpenAI authentication with PKCE flow and token refresh
- Responses API streaming with SSE event handling
- Reasoning/thinking output with configurable effort levels (minimal to xhigh)
- Tool calling support translated from OpenAI format
- System prompt validation using official opencode prompt
- Usage tracking with proper litellm.Usage objects

Files added:
- codex_provider.py: Main provider implementation
- openai_oauth_base.py: OAuth base class with PKCE support
- codex_prompt.txt: Required system prompt for API validation

* fix(codex): 🐛 prefix model names with provider identifier

Models must be returned with the 'codex/' prefix (e.g., 'codex/gpt-5.2')
to match the convention used by other providers like antigravity.
This ensures proper provider routing in the RotatingClient.

* feat(codex): ✨ add reasoning effort model variants

Exposes reasoning effort levels as model variants:
- codex/gpt-5.2:low, :medium, :high, :xhigh
- codex/gpt-5.1:low, :medium, :high
- And similar for all codex models

This allows clients to control reasoning effort by model name,
similar to how gemini models use :thinking suffix.

Total models: 9 base + 30 reasoning variants = 39 models

* feat(codex): ✨ add identity override for user system prompt precedence

Injects an identity override as the first user message that tells the model
to prioritize user-provided system prompts over the required opencode
instructions. This mirrors the pattern used by Antigravity provider.

Message order:
1. Identity override (<system_override> tag)
2. User's system message (converted to user message)
3. Rest of conversation

Controlled by CODEX_INJECT_IDENTITY_OVERRIDE env var (default: true)

* docs: 📝 add Codex provider configuration to .env.example

Documents all Codex environment variables:
- CODEX_REASONING_EFFORT: low/medium/high/xhigh
- CODEX_REASONING_SUMMARY: auto/concise/detailed/none
- CODEX_REASONING_COMPAT: think-tags/raw/none
- CODEX_INJECT_IDENTITY_OVERRIDE: true/false
- CODEX_INJECT_INSTRUCTION: true/false
- CODEX_EMPTY_RESPONSE_ATTEMPTS: retry count
- CODEX_EMPTY_RESPONSE_RETRY_DELAY: seconds
- CODEX_OAUTH_PORT: callback port

* fix(codex): 🐛 register Codex in provider factory for OAuth TUI

Adds Codex to PROVIDER_MAP so it appears in the credential tool's
"Add OAuth Credential" menu alongside other OAuth providers.

* feat(codex): ✨ add quota tracking with rate limit header parsing

Integrate CodexQuotaTracker mixin into CodexProvider to track API usage
via response headers and periodic quota API calls. Enables smart
credential selection based on remaining quota and automatic cooldowns
when limits are approached.

Signed-off-by: Moeeze Hassan <fammas.maz@gmail.com>

* feat(codex): add gpt-5.3-codex to model list and reasoning config

* feat(codex): wire quota header updates to UsageManager for TUI display

- Add set_usage_manager() to CodexQuotaTracker mixin
- Push parsed rate limit headers to UsageManager via update_quota_baseline
- Inject UsageManager reference during RotatingClient initialization
- Enables quota status display in TUI after each Codex API response

* feat(codex): default to sequential credential selection for token caching

Sequential mode reuses the same credential across requests, enabling
upstream token caching on the Codex API.

* fix(codex): standardize ChatGPT-Account-Id header casing

Match the exact capitalization used by the Codex CLI, consistent with
codex_quota_tracker.py. Addresses PR review feedback.
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