Conversation
… 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.
Summary of ChangesHello @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
Changelog
Activity
Using Gemini Code AssistThe 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
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 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
|
There was a problem hiding this comment.
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.
| 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 |
There was a problem hiding this comment.
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.
| 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" |
There was a problem hiding this comment.
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.
| 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) |
There was a problem hiding this comment.
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.
| 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. |
There was a problem hiding this comment.
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.
| and credits info. | |
| headers["ChatGPT-Account-Id"] = account_id |
Code Review SummaryStatus: 1 Issue Found | Recommendation: Address before merge Overview
Issue Details (click to expand)WARNING
Other Observations (not in diff)Additional notes that don't require inline comments:
Files Reviewed (9 files)
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.
… 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.
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:
Files added:
based on Mirrowel#73