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
5 changes: 5 additions & 0 deletions .changeset/friendly-yaks-float.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"kilo-code": patch
---

Prevent sending thinkingLevel to unsupporting Gemini models
59 changes: 59 additions & 0 deletions src/api/transform/__tests__/reasoning.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -838,6 +838,65 @@ describe("reasoning.ts", () => {
const result = getGeminiReasoning(options) as GeminiReasoningParams | undefined
expect(result).toEqual({ thinkingLevel: "medium", includeThoughts: true })
})

// kilocode_change start
it("should return undefined for budget-only models when budget is not enabled (fixes issue #4490)", () => {
// This test covers the bug where gemini-2.5-flash would fail with
// "Thinking level is not supported for this model" because thinkingLevel
// was being sent to a model that only supports thinkingBudget
const geminiFlashModel: ModelInfo = {
...baseModel,
// gemini-2.5-flash supports budget but NOT effort-based reasoning
supportsReasoningBudget: true,
// Note: no supportsReasoningEffort, no requiredReasoningBudget
}

const settings: ProviderSettings = {
apiProvider: "gemini",
// User may have a reasoningEffort set from a different model
reasoningEffort: "high",
// But enableReasoningEffort is not true, so budget won't be used
}

const options: GetModelReasoningOptions = {
model: geminiFlashModel,
reasoningBudget: 4096,
reasoningEffort: "high",
settings,
}

const result = getGeminiReasoning(options)
// Should return undefined, NOT { thinkingLevel: "high", includeThoughts: true }
// because this model doesn't support thinkingLevel
expect(result).toBeUndefined()
})

it("should return undefined for budget-only models even with explicit effort setting", () => {
// Models like gemini-2.5-flash only support budget-based reasoning
const budgetOnlyModel: ModelInfo = {
...baseModel,
supportsReasoningBudget: true,
maxThinkingTokens: 24576,
// Critically: no supportsReasoningEffort
}

const settings: ProviderSettings = {
apiProvider: "gemini",
reasoningEffort: "medium",
}

const options: GetModelReasoningOptions = {
model: budgetOnlyModel,
reasoningBudget: 8192,
reasoningEffort: "medium",
settings,
}

const result = getGeminiReasoning(options)
// Must not send thinkingLevel to a model that doesn't support it
expect(result).toBeUndefined()
})
// kilocode_change end
})

describe("Integration scenarios", () => {
Expand Down
6 changes: 6 additions & 0 deletions src/api/transform/reasoning.ts
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,12 @@ export const getGeminiReasoning = ({
return { thinkingBudget: reasoningBudget!, includeThoughts: true }
}

// kilocode_change start
if (!model.supportsReasoningEffort) {
return undefined
}
// kilocode_change end

// For effort-based Gemini models, rely directly on the selected effort value.
// We intentionally ignore enableReasoningEffort here so that explicitly chosen
// efforts in the UI (e.g. "High" for gemini-3-pro-preview) always translate
Expand Down
Loading