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
19 changes: 16 additions & 3 deletions src/api/providers/__tests__/openai.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -409,13 +409,15 @@ describe("OpenAiHandler", () => {
expect(callArgs).not.toHaveProperty("temperature")
})

it("should include temperature by default when supportsTemperature is not set", async () => {
it("should omit temperature by default when no custom temperature is set", async () => {
// Option A: when "use custom temperature" is off (modelTemperature unset) and the model has no
// required default, omit `temperature` so the server's own default applies instead of forcing 0.
const stream = handler.createMessage(systemPrompt, messages)
for await (const _chunk of stream) {
}
expect(mockCreate).toHaveBeenCalled()
const callArgs = mockCreate.mock.calls[0][0]
expect(callArgs).toHaveProperty("temperature")
expect(callArgs).not.toHaveProperty("temperature")
})

it("should use the configured modelTemperature when supportsTemperature is not false", async () => {
Expand All @@ -438,6 +440,17 @@ describe("OpenAiHandler", () => {
expect(callArgs.temperature).toBe(DEEP_SEEK_DEFAULT_TEMPERATURE)
})

it("should still send temperature when the user sets a custom value of 0", async () => {
// A deliberate 0 must be distinguished from "unset" — it is sent, not omitted.
const zeroTempHandler = new OpenAiHandler({ ...mockOptions, modelTemperature: 0 })
const stream = zeroTempHandler.createMessage(systemPrompt, messages)
for await (const _chunk of stream) {
}
expect(mockCreate).toHaveBeenCalled()
const callArgs = mockCreate.mock.calls[0][0]
expect(callArgs.temperature).toBe(0)
})

it("should include max_tokens when includeMaxTokens is true", async () => {
const optionsWithMaxTokens: ApiHandlerOptions = {
...mockOptions,
Expand Down Expand Up @@ -679,7 +692,7 @@ describe("OpenAiHandler", () => {
],
stream: true,
stream_options: { include_usage: true },
temperature: 0,
// No custom temperature set → `temperature` is omitted.
tools: undefined,
tool_choice: undefined,
parallel_tool_calls: true,
Expand Down
15 changes: 8 additions & 7 deletions src/api/providers/openai.ts
Original file line number Diff line number Diff line change
Expand Up @@ -155,13 +155,14 @@ export class OpenAiHandler extends BaseProvider implements SingleCompletionHandl
const requestOptions: OpenAI.Chat.Completions.ChatCompletionCreateParamsStreaming = {
model: modelId,
// Some OpenAI-Compatible models (e.g. claude-opus-4-7, claude-opus-4-8) reject
// `temperature` as deprecated/unsupported. Honor the model's `supportsTemperature`
// flag and omit it when explicitly set to false (undefined still sends temperature,
// preserving behavior).
...(modelInfo.supportsTemperature !== false && {
temperature:
this.options.modelTemperature ?? (deepseekReasoner ? DEEP_SEEK_DEFAULT_TEMPERATURE : 0),
}),
// `temperature` as deprecated/unsupported, so honor the model's `supportsTemperature`
// flag and omit it when that flag is false. Beyond that, only send `temperature` when
// the user set a custom value or the model needs a specific default (deepseek-reasoner);
// otherwise omit it so the server's own default applies instead of forcing 0.
...(modelInfo.supportsTemperature !== false &&
(this.options.modelTemperature != null || deepseekReasoner) && {
temperature: this.options.modelTemperature ?? DEEP_SEEK_DEFAULT_TEMPERATURE,
}),
messages: convertedMessages,
stream: true as const,
...(isGrokXAI ? {} : { stream_options: { include_usage: true } }),
Expand Down
Loading