Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 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
60 changes: 59 additions & 1 deletion src/api/transform/__tests__/reasoning.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -838,8 +838,66 @@ 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", () => {
it("should handle model with requiredReasoningBudget across all providers", () => {
const modelWithRequired: ModelInfo = {
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 @@ -137,6 +137,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