Files
cline/src/core/controller/account/openAiCodexSignIn.ts
T
Saoud Rizwan b2634d2276 feat: add OpenAI Codex provider for ChatGPT Plus/Pro subscriptions (#8664)
* feat: add OpenAI Codex provider for ChatGPT Plus/Pro subscriptions

Add a new provider that allows users with ChatGPT Plus or Pro subscriptions
to use GPT-5 models directly through Cline without needing an API key.

Key features:
- OAuth authentication via OpenAI (PKCE flow)
- Routes requests to chatgpt.com/backend-api/codex/responses
- Subscription-based pricing (no per-token costs)
- Models: gpt-5.2-codex, gpt-5.1-codex-max, gpt-5.1-codex-mini, gpt-5.2

New files:
- src/integrations/openai-codex/oauth.ts: OAuth manager with PKCE, token storage/refresh
- src/core/api/providers/openai-codex.ts: API handler for Codex backend
- src/core/controller/account/openAiCodexSignIn.ts: Sign-in RPC handler
- src/core/controller/account/openAiCodexSignOut.ts: Sign-out RPC handler
- webview-ui/src/components/settings/providers/OpenAiCodexProvider.tsx: Settings UI

* fix: force native tool calling for Responses API providers

Providers using OpenAI's Responses API (openai-codex, some openai-native
models) require native tool calling. XML tools don't work with these APIs,
causing duplicate tool calls and malformed arguments.

Changes:
- Add openai-codex to isNextGenModelProvider() list so native variant
  matchers recognize it
- Force enableNativeToolCalls=true when model uses ApiFormat.OPENAI_RESPONSES,
  regardless of user setting
- Document Responses API provider requirements in CLAUDE.md

* chore: rename OpenAI Codex provider label to ChatGPT Codex Subscription

* fix: use shared fetch wrapper for proxy support in OpenAI Codex provider

* revert: remove CLAUDE.md changes from this PR

* fix: restore .clinerules/general.md to match main

* chore: rename provider label to OpenAI Codex (ChatGPT Plus/Pro)

* chore: add network.md reference to clinerules

* feat: show VS Code notifications for OpenAI Codex OAuth success/failure
2026-01-19 16:34:50 -08:00

51 lines
1.7 KiB
TypeScript

import { Empty, EmptyRequest } from "@shared/proto/cline/common"
import { openAiCodexOAuthManager } from "@/integrations/openai-codex/oauth"
import { HostProvider } from "@/hosts/host-provider"
import { openExternal } from "@/utils/env"
import { ShowMessageType } from "@shared/proto/host/window"
import { Controller } from ".."
/**
* Initiates OpenAI Codex OAuth authentication flow
* Opens the authorization URL in the user's browser
*/
export async function openAiCodexSignIn(controller: Controller, _: EmptyRequest): Promise<Empty> {
try {
// Start the authorization flow and get the auth URL
const authUrl = openAiCodexOAuthManager.startAuthorizationFlow()
// Open the auth URL in the browser
await openExternal(authUrl)
// Wait for the OAuth callback in the background
// The callback will save credentials when complete
openAiCodexOAuthManager
.waitForCallback()
.then(async () => {
HostProvider.window.showMessage({
type: ShowMessageType.INFORMATION,
message: "Successfully signed in to OpenAI Codex",
})
await controller.postStateToWebview()
})
.catch((error) => {
console.error("[openAiCodexSignIn] OAuth callback failed:", error)
openAiCodexOAuthManager.cancelAuthorizationFlow()
// Don't show notification for timeouts (user likely just abandoned)
const errorMessage = error instanceof Error ? error.message : String(error)
if (!errorMessage.includes("timed out")) {
HostProvider.window.showMessage({
type: ShowMessageType.ERROR,
message: `OpenAI Codex sign in failed: ${errorMessage}`,
})
}
})
} catch (error) {
console.error("[openAiCodexSignIn] Failed to start OAuth flow:", error)
openAiCodexOAuthManager.cancelAuthorizationFlow()
throw error
}
return {}
}