Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
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
11 changes: 11 additions & 0 deletions .changeset/gpt5-support.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
---
"@roo-code/types": minor
"roo-cline": minor
---

Add GPT-5 model support

- Added GPT-5 models (gpt-5-2025-08-07, gpt-5-mini-2025-08-07, gpt-5-nano-2025-08-07) to OpenAI Native provider
- Added nectarine-alpha-new-reasoning-effort-2025-07-25 experimental model
- Set gpt-5-2025-08-07 as the new default OpenAI Native model
- Implemented GPT-5 specific handling with streaming and reasoning effort support
Copy link
Contributor Author

Choose a reason for hiding this comment

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

The changeset mentions 'reasoning effort support' but I don't see the flag set for GPT-5 models like it is for o3/o4 models. Should we either add the flag or remove this from the description?

51 changes: 50 additions & 1 deletion packages/types/src/providers/openai.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,55 @@ import type { ModelInfo } from "../model.js"
// https://openai.com/api/pricing/
export type OpenAiNativeModelId = keyof typeof openAiNativeModels

export const openAiNativeDefaultModelId: OpenAiNativeModelId = "gpt-4.1"
export const openAiNativeDefaultModelId: OpenAiNativeModelId = "gpt-5-2025-08-07"

export const openAiNativeModels = {
"gpt-5-2025-08-07": {
maxTokens: 128000,
contextWindow: 256000,
supportsImages: true,
supportsPromptCache: true,
supportsReasoningEffort: true,
inputPrice: 1.25,
outputPrice: 10.0,
cacheReadsPrice: 0.125,
},
"gpt-5-mini-2025-08-07": {
maxTokens: 128000,
contextWindow: 256000,
supportsImages: true,
supportsPromptCache: true,
supportsReasoningEffort: true,
inputPrice: 0.25,
outputPrice: 2.0,
cacheReadsPrice: 0.025,
},
"gpt-5-nano-2025-08-07": {
maxTokens: 128000,
contextWindow: 256000,
supportsImages: true,
supportsPromptCache: true,
supportsReasoningEffort: true,
inputPrice: 0.05,
outputPrice: 0.4,
cacheReadsPrice: 0.005,
},
"nectarine-alpha-new-reasoning-effort-2025-07-25": {
maxTokens: 128000,
contextWindow: 256000,
supportsImages: true,
supportsPromptCache: true,
supportsReasoningEffort: true,
inputPrice: 0,
outputPrice: 0,
cacheReadsPrice: 0,
},
"gpt-4.1": {
maxTokens: 32_768,
contextWindow: 1_047_576,
supportsImages: true,
supportsPromptCache: true,
supportsReasoningEffort: true,
inputPrice: 2,
outputPrice: 8,
cacheReadsPrice: 0.5,
Expand All @@ -20,6 +61,7 @@ export const openAiNativeModels = {
contextWindow: 1_047_576,
supportsImages: true,
supportsPromptCache: true,
supportsReasoningEffort: true,
inputPrice: 0.4,
outputPrice: 1.6,
cacheReadsPrice: 0.1,
Expand All @@ -29,6 +71,7 @@ export const openAiNativeModels = {
contextWindow: 1_047_576,
supportsImages: true,
supportsPromptCache: true,
supportsReasoningEffort: true,
inputPrice: 0.1,
outputPrice: 0.4,
cacheReadsPrice: 0.025,
Expand Down Expand Up @@ -131,6 +174,7 @@ export const openAiNativeModels = {
contextWindow: 200_000,
supportsImages: true,
supportsPromptCache: true,
supportsReasoningEffort: true,
inputPrice: 15,
outputPrice: 60,
cacheReadsPrice: 7.5,
Expand All @@ -140,6 +184,7 @@ export const openAiNativeModels = {
contextWindow: 128_000,
supportsImages: true,
supportsPromptCache: true,
supportsReasoningEffort: true,
inputPrice: 15,
outputPrice: 60,
cacheReadsPrice: 7.5,
Expand All @@ -149,6 +194,7 @@ export const openAiNativeModels = {
contextWindow: 128_000,
supportsImages: true,
supportsPromptCache: true,
supportsReasoningEffort: true,
inputPrice: 1.1,
outputPrice: 4.4,
cacheReadsPrice: 0.55,
Expand All @@ -158,6 +204,7 @@ export const openAiNativeModels = {
contextWindow: 128_000,
supportsImages: true,
supportsPromptCache: true,
supportsReasoningEffort: true,
inputPrice: 75,
outputPrice: 150,
cacheReadsPrice: 37.5,
Expand All @@ -167,6 +214,7 @@ export const openAiNativeModels = {
contextWindow: 128_000,
supportsImages: true,
supportsPromptCache: true,
supportsReasoningEffort: true,
inputPrice: 2.5,
outputPrice: 10,
cacheReadsPrice: 1.25,
Expand All @@ -176,6 +224,7 @@ export const openAiNativeModels = {
contextWindow: 128_000,
supportsImages: true,
supportsPromptCache: true,
supportsReasoningEffort: true,
inputPrice: 0.15,
outputPrice: 0.6,
cacheReadsPrice: 0.075,
Expand Down
2 changes: 1 addition & 1 deletion src/api/providers/__tests__/openai-native.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -455,7 +455,7 @@ describe("OpenAiNativeHandler", () => {
openAiNativeApiKey: "test-api-key",
})
const modelInfo = handlerWithoutModel.getModel()
expect(modelInfo.id).toBe("gpt-4.1") // Default model
expect(modelInfo.id).toBe("gpt-5-2025-08-07") // Default model
expect(modelInfo.info).toBeDefined()
})
})
Expand Down
31 changes: 31 additions & 0 deletions src/api/providers/openai-native.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,8 @@ export class OpenAiNativeHandler extends BaseProvider implements SingleCompletio
yield* this.handleReasonerMessage(model, id, systemPrompt, messages)
} else if (model.id.startsWith("o1")) {
yield* this.handleO1FamilyMessage(model, systemPrompt, messages)
} else if (this.isGPT5Model(model.id)) {
yield* this.handleGPT5Message(model, systemPrompt, messages)
} else {
yield* this.handleDefaultModelMessage(model, systemPrompt, messages)
}
Expand All @@ -66,6 +68,8 @@ export class OpenAiNativeHandler extends BaseProvider implements SingleCompletio
// o1 supports developer prompt with formatting
// o1-preview and o1-mini only support user messages
const isOriginalO1 = model.id === "o1"
const { reasoning } = this.getModel()

const response = await this.client.chat.completions.create({
model: model.id,
messages: [
Expand All @@ -77,6 +81,7 @@ export class OpenAiNativeHandler extends BaseProvider implements SingleCompletio
],
stream: true,
stream_options: { include_usage: true },
...(reasoning && reasoning),
})

yield* this.handleStreamResponse(response, model)
Expand Down Expand Up @@ -112,17 +117,43 @@ export class OpenAiNativeHandler extends BaseProvider implements SingleCompletio
systemPrompt: string,
messages: Anthropic.Messages.MessageParam[],
): ApiStream {
const { reasoning } = this.getModel()

const stream = await this.client.chat.completions.create({
model: model.id,
temperature: this.options.modelTemperature ?? OPENAI_NATIVE_DEFAULT_TEMPERATURE,
messages: [{ role: "system", content: systemPrompt }, ...convertToOpenAiMessages(messages)],
stream: true,
stream_options: { include_usage: true },
...(reasoning && reasoning),
})

yield* this.handleStreamResponse(stream, model)
}

private async *handleGPT5Message(
model: OpenAiNativeModel,
systemPrompt: string,
messages: Anthropic.Messages.MessageParam[],
): ApiStream {
const { reasoning } = this.getModel()

const stream = await this.client.chat.completions.create({
model: model.id,
temperature: this.options.modelTemperature ?? OPENAI_NATIVE_DEFAULT_TEMPERATURE,
messages: [{ role: "developer", content: systemPrompt }, ...convertToOpenAiMessages(messages)],
stream: true,
stream_options: { include_usage: true },
...(reasoning && reasoning),
})

yield* this.handleStreamResponse(stream, model)
}

private isGPT5Model(modelId: string): boolean {
return modelId.includes("gpt-5") || modelId.includes("gpt5") || modelId.includes("nectarine")
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This detection logic is quite broad - any model containing 'nectarine' would be treated as GPT-5. Could we be more explicit?

}

private async *handleStreamResponse(
stream: AsyncIterable<OpenAI.Chat.Completions.ChatCompletionChunk>,
model: OpenAiNativeModel,
Expand Down
Loading