Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions .changeset/eight-pots-shout.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
"kilo-code": minor
---

Add support for OpenAI Codex subscriptions (thanks Roo)

- Fix: Reset invalid model selection when using OpenAI Codex provider (PR #10777 by @hannesrudolph)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

these PR numbers dont make a lot of sense in our repo, should these be urls?

- Add OpenAI - ChatGPT Plus/Pro Provider that gives subscription-based access to Codex models without per-token costs (PR #10736 by @hannesrudolph)
1 change: 1 addition & 0 deletions cli/src/constants/providers/labels.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ export const PROVIDER_LABELS: Record<ProviderName, string> = {
kilocode: "Kilo Code",
anthropic: "Anthropic",
"openai-native": "OpenAI",
"openai-codex": "OpenAI - ChatGPT Plus/Pro",
openrouter: "OpenRouter",
bedrock: "Amazon Bedrock",
gemini: "Google Gemini",
Expand Down
2 changes: 2 additions & 0 deletions cli/src/constants/providers/models.ts
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,7 @@ export const PROVIDER_TO_ROUTER_NAME: Record<ProviderName, RouterName | null> =
"vscode-lm": null,
gemini: null,
"openai-native": null,
"openai-codex": null,
mistral: null,
moonshot: null,
deepseek: null,
Expand Down Expand Up @@ -193,6 +194,7 @@ export const PROVIDER_MODEL_FIELD: Record<ProviderName, string | null> = {
"vscode-lm": "vsCodeLmModelSelector",
gemini: null,
"openai-native": null,
"openai-codex": null,
mistral: null,
moonshot: null,
deepseek: null,
Expand Down
4 changes: 4 additions & 0 deletions cli/src/constants/providers/settings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -810,6 +810,9 @@ export const getProviderSettings = (provider: ProviderName, config: ProviderSett
createFieldConfig("openAiNativeBaseUrl", config, "Default"),
]

case "openai-codex":
return [createFieldConfig("apiModelId", config, "gpt-4o")]

case "bedrock":
return [
createFieldConfig("awsAccessKey", config),
Expand Down Expand Up @@ -1055,6 +1058,7 @@ export const PROVIDER_DEFAULT_MODELS: Record<ProviderName, string> = {
kilocode: "anthropic/claude-sonnet-4",
anthropic: "claude-3-5-sonnet-20241022",
"openai-native": "gpt-4o",
"openai-codex": "gpt-4o",
openrouter: "anthropic/claude-3-5-sonnet",
bedrock: "anthropic.claude-3-5-sonnet-20241022-v2:0",
gemini: "gemini-1.5-pro-latest",
Expand Down
1 change: 1 addition & 0 deletions cli/src/constants/providers/validation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ export const PROVIDER_REQUIRED_FIELDS: Record<ProviderName, string[]> = {
kilocode: ["kilocodeToken", "kilocodeModel"],
anthropic: ["apiKey", "apiModelId"],
"openai-native": ["openAiNativeApiKey", "apiModelId"],
"openai-codex": ["apiModelId"],
openrouter: ["openRouterApiKey", "openRouterModelId"],
ollama: ["ollamaBaseUrl", "ollamaModelId"],
lmstudio: ["lmStudioBaseUrl", "lmStudioModelId"],
Expand Down
14 changes: 14 additions & 0 deletions packages/types/src/provider-settings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import {
ioIntelligenceModels,
mistralModels,
moonshotModels,
openAiCodexModels,
openAiNativeModels,
qwenCodeModels,
sambaNovaModels,
Expand Down Expand Up @@ -147,6 +148,7 @@ export const providerNames = [
"mistral",
"moonshot",
"minimax",
"openai-codex",
"openai-native",
"qwen-code",
"roo",
Expand Down Expand Up @@ -341,6 +343,10 @@ const geminiCliSchema = apiModelIdProviderModelSchema.extend({
})
// kilocode_change end

const openAiCodexSchema = apiModelIdProviderModelSchema.extend({
// No additional settings needed - uses OAuth authentication
})

const openAiNativeSchema = apiModelIdProviderModelSchema.extend({
openAiNativeApiKey: z.string().optional(),
openAiNativeBaseUrl: z.string().optional(),
Expand Down Expand Up @@ -551,6 +557,7 @@ export const providerSettingsSchemaDiscriminated = z.discriminatedUnion("apiProv
vsCodeLmSchema.merge(z.object({ apiProvider: z.literal("vscode-lm") })),
lmStudioSchema.merge(z.object({ apiProvider: z.literal("lmstudio") })),
geminiSchema.merge(z.object({ apiProvider: z.literal("gemini") })),
openAiCodexSchema.merge(z.object({ apiProvider: z.literal("openai-codex") })),
openAiNativeSchema.merge(z.object({ apiProvider: z.literal("openai-native") })),
ovhcloudSchema.merge(z.object({ apiProvider: z.literal("ovhcloud") })), // kilocode_change
mistralSchema.merge(z.object({ apiProvider: z.literal("mistral") })),
Expand Down Expand Up @@ -611,6 +618,7 @@ export const providerSettingsSchema = z.object({
...ovhcloudSchema.shape,
...inceptionSchema.shape,
// kilocode_change end
...openAiCodexSchema.shape,
...openAiNativeSchema.shape,
...mistralSchema.shape,
...deepSeekSchema.shape,
Expand Down Expand Up @@ -704,6 +712,7 @@ export const modelIdKeysByProvider: Record<TypicalProvider, ModelIdKey> = {
kilocode: "kilocodeModel",
bedrock: "apiModelId",
vertex: "apiModelId",
"openai-codex": "apiModelId",
"openai-native": "openAiModelId",
ollama: "ollamaModelId",
lmstudio: "lmStudioModelId",
Expand Down Expand Up @@ -843,6 +852,11 @@ export const MODELS_BY_PROVIDER: Record<
label: "MiniMax",
models: Object.keys(minimaxModels),
},
"openai-codex": {
id: "openai-codex",
label: "OpenAI - ChatGPT Plus/Pro",
models: Object.keys(openAiCodexModels),
},
"openai-native": {
id: "openai-native",
label: "OpenAI",
Expand Down
4 changes: 4 additions & 0 deletions packages/types/src/providers/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ export * from "./moonshot.js"
export * from "./nano-gpt.js" // kilocode_change
export * from "./ollama.js"
export * from "./openai.js"
export * from "./openai-codex.js"
export * from "./openrouter.js"
export * from "./qwen-code.js"
export * from "./requesty.js"
Expand Down Expand Up @@ -58,6 +59,7 @@ import { ioIntelligenceDefaultModelId } from "./io-intelligence.js"
import { litellmDefaultModelId } from "./lite-llm.js"
import { mistralDefaultModelId } from "./mistral.js"
import { moonshotDefaultModelId } from "./moonshot.js"
import { openAiCodexDefaultModelId } from "./openai-codex.js"
import { openRouterDefaultModelId } from "./openrouter.js"
import { qwenCodeDefaultModelId } from "./qwen-code.js"
import { requestyDefaultModelId } from "./requesty.js"
Expand Down Expand Up @@ -125,6 +127,8 @@ export function getProviderDefaultModelId(
return options?.isChina ? mainlandZAiDefaultModelId : internationalZAiDefaultModelId
case "openai-native":
return "gpt-4o" // Based on openai-native patterns
case "openai-codex":
return openAiCodexDefaultModelId
case "mistral":
return mistralDefaultModelId
case "openai":
Expand Down
179 changes: 179 additions & 0 deletions packages/types/src/providers/openai-codex.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,179 @@
import type { ModelInfo } from "../model.js"

/**
* OpenAI Codex Provider
*
* This provider uses OAuth authentication via ChatGPT Plus/Pro subscription
* instead of direct API keys. Requests are routed to the Codex backend at
* https://chatgpt.com/backend-api/codex/responses
*
* Key differences from openai-native:
* - Uses OAuth Bearer tokens instead of API keys
* - Subscription-based pricing (no per-token costs)
* - Limited model subset available
* - Custom routing to Codex backend
*/

export type OpenAiCodexModelId = keyof typeof openAiCodexModels

export const openAiCodexDefaultModelId: OpenAiCodexModelId = "gpt-5.2-codex"

/**
* Models available through the Codex OAuth flow.
* These models are accessible to ChatGPT Plus/Pro subscribers.
* Costs are 0 as they are covered by the subscription.
*/
export const openAiCodexModels = {
"gpt-5.1-codex-max": {
maxTokens: 128000,
contextWindow: 400000,
supportsNativeTools: true,
defaultToolProtocol: "native",
includedTools: ["apply_patch"],
excludedTools: ["apply_diff", "write_to_file"],
supportsImages: true,
supportsPromptCache: true,
supportsReasoningEffort: ["low", "medium", "high", "xhigh"],
reasoningEffort: "xhigh",
// Subscription-based: no per-token costs
inputPrice: 0,
outputPrice: 0,
supportsTemperature: false,
description: "GPT-5.1 Codex Max: Maximum capability coding model via ChatGPT subscription",
},
"gpt-5.1-codex": {
maxTokens: 128000,
contextWindow: 400000,
supportsNativeTools: true,
defaultToolProtocol: "native",
includedTools: ["apply_patch"],
excludedTools: ["apply_diff", "write_to_file"],
supportsImages: true,
supportsPromptCache: true,
supportsReasoningEffort: ["low", "medium", "high"],
reasoningEffort: "medium",
// Subscription-based: no per-token costs
inputPrice: 0,
outputPrice: 0,
supportsTemperature: false,
description: "GPT-5.1 Codex: GPT-5.1 optimized for agentic coding via ChatGPT subscription",
},
"gpt-5.2-codex": {
maxTokens: 128000,
contextWindow: 400000,
supportsNativeTools: true,
defaultToolProtocol: "native",
includedTools: ["apply_patch"],
excludedTools: ["apply_diff", "write_to_file"],
supportsImages: true,
supportsPromptCache: true,
supportsReasoningEffort: ["low", "medium", "high", "xhigh"],
reasoningEffort: "medium",
inputPrice: 0,
outputPrice: 0,
supportsTemperature: false,
description: "GPT-5.2 Codex: OpenAI's flagship coding model via ChatGPT subscription",
},
"gpt-5.1": {
maxTokens: 128000,
contextWindow: 400000,
supportsNativeTools: true,
defaultToolProtocol: "native",
includedTools: ["apply_patch"],
excludedTools: ["apply_diff", "write_to_file"],
supportsImages: true,
supportsPromptCache: true,
supportsReasoningEffort: ["none", "low", "medium", "high"],
reasoningEffort: "medium",
// Subscription-based: no per-token costs
inputPrice: 0,
outputPrice: 0,
supportsVerbosity: true,
supportsTemperature: false,
description: "GPT-5.1: General GPT-5.1 model via ChatGPT subscription",
},
"gpt-5": {
maxTokens: 128000,
contextWindow: 400000,
supportsNativeTools: true,
defaultToolProtocol: "native",
includedTools: ["apply_patch"],
excludedTools: ["apply_diff", "write_to_file"],
supportsImages: true,
supportsPromptCache: true,
supportsReasoningEffort: ["minimal", "low", "medium", "high"],
reasoningEffort: "medium",
// Subscription-based: no per-token costs
inputPrice: 0,
outputPrice: 0,
supportsVerbosity: true,
supportsTemperature: false,
description: "GPT-5: General GPT-5 model via ChatGPT subscription",
},
"gpt-5-codex": {
maxTokens: 128000,
contextWindow: 400000,
supportsNativeTools: true,
defaultToolProtocol: "native",
includedTools: ["apply_patch"],
excludedTools: ["apply_diff", "write_to_file"],
supportsImages: true,
supportsPromptCache: true,
supportsReasoningEffort: ["low", "medium", "high"],
reasoningEffort: "medium",
// Subscription-based: no per-token costs
inputPrice: 0,
outputPrice: 0,
supportsTemperature: false,
description: "GPT-5 Codex: GPT-5 optimized for agentic coding via ChatGPT subscription",
},
"gpt-5-codex-mini": {
maxTokens: 128000,
contextWindow: 400000,
supportsNativeTools: true,
defaultToolProtocol: "native",
includedTools: ["apply_patch"],
excludedTools: ["apply_diff", "write_to_file"],
supportsImages: true,
supportsPromptCache: true,
supportsReasoningEffort: ["low", "medium", "high"],
reasoningEffort: "medium",
// Subscription-based: no per-token costs
inputPrice: 0,
outputPrice: 0,
supportsTemperature: false,
description: "GPT-5 Codex Mini: Faster coding model via ChatGPT subscription",
},
"gpt-5.1-codex-mini": {
maxTokens: 128000,
contextWindow: 400000,
supportsNativeTools: true,
defaultToolProtocol: "native",
includedTools: ["apply_patch"],
excludedTools: ["apply_diff", "write_to_file"],
supportsImages: true,
supportsPromptCache: true,
supportsReasoningEffort: ["low", "medium", "high"],
reasoningEffort: "medium",
inputPrice: 0,
outputPrice: 0,
supportsTemperature: false,
description: "GPT-5.1 Codex Mini: Faster version for coding tasks via ChatGPT subscription",
},
"gpt-5.2": {
maxTokens: 128000,
contextWindow: 400000,
supportsNativeTools: true,
defaultToolProtocol: "native",
includedTools: ["apply_patch"],
excludedTools: ["apply_diff", "write_to_file"],
supportsImages: true,
supportsPromptCache: true,
supportsReasoningEffort: ["none", "low", "medium", "high", "xhigh"],
reasoningEffort: "medium",
inputPrice: 0,
outputPrice: 0,
supportsTemperature: false,
description: "GPT-5.2: Latest GPT model via ChatGPT subscription",
},
} as const satisfies Record<string, ModelInfo>
3 changes: 3 additions & 0 deletions src/api/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import {
VertexHandler,
AnthropicVertexHandler,
OpenAiHandler,
OpenAiCodexHandler,
LmStudioHandler,
GeminiHandler,
OpenAiNativeHandler,
Expand Down Expand Up @@ -186,6 +187,8 @@ export function buildApiHandler(configuration: ProviderSettings): ApiHandler {
return new LmStudioHandler(options)
case "gemini":
return new GeminiHandler(options)
case "openai-codex":
return new OpenAiCodexHandler(options)
case "openai-native":
return new OpenAiNativeHandler(options)
case "deepseek":
Expand Down
Loading