diff --git a/src/core/sliding-window/__tests__/sliding-window.spec.ts b/src/core/sliding-window/__tests__/sliding-window.spec.ts
index 3bda5351d4..d3837c7a23 100644
--- a/src/core/sliding-window/__tests__/sliding-window.spec.ts
+++ b/src/core/sliding-window/__tests__/sliding-window.spec.ts
@@ -250,6 +250,30 @@ describe("Sliding Window", () => {
{ role: "assistant", content: "Fourth message" },
{ role: "user", content: "Fifth message" },
]
+ it("should use contextLimit as contextWindow when apiProvider is gemini", async () => {
+ const contextLimit = 2
+ const messages: ApiMessage[] = [
+ { role: "user", content: "First message" },
+ { role: "assistant", content: "Second message" },
+ { role: "user", content: "Third message" },
+ { role: "assistant", content: "Fourth message" },
+ { role: "user", content: "" },
+ ]
+ const result = await truncateConversationIfNeeded({
+ messages,
+ totalTokens: 2,
+ contextWindow: contextLimit,
+ maxTokens: null,
+ apiHandler: mockApiHandler,
+ autoCondenseContext: false,
+ autoCondenseContextPercent: 100,
+ systemPrompt: "",
+ taskId,
+ profileThresholds: {},
+ currentProfileId: "default",
+ })
+ expect(result.messages).toEqual([messages[0], messages[3], messages[4]])
+ })
it("should not truncate if tokens are below max tokens threshold", async () => {
const modelInfo = createModelInfo(100000, 30000)
diff --git a/webview-ui/src/components/settings/providers/Gemini.tsx b/webview-ui/src/components/settings/providers/Gemini.tsx
index 8f3f2b536b..54df49c392 100644
--- a/webview-ui/src/components/settings/providers/Gemini.tsx
+++ b/webview-ui/src/components/settings/providers/Gemini.tsx
@@ -198,7 +198,7 @@ export const Gemini = ({
setApiConfigurationField("maxOutputTokens", values[0])}
@@ -208,7 +208,10 @@ export const Gemini = ({
value={(apiConfiguration.maxOutputTokens ?? 0).toString()}
type="text"
inputMode="numeric"
- onInput={handleInputChange("maxOutputTokens", (e) => parseInt((e as any).target.value, 10))}
+ onInput={handleInputChange("maxOutputTokens", (e) => {
+ const val = parseInt((e as any).target.value, 10)
+ return Number.isNaN(val) ? 0 : Math.min(val, modelInfo.maxTokens)
+ })}
className="w-16"
/>
diff --git a/webview-ui/src/components/settings/providers/__tests__/Gemini.spec.tsx b/webview-ui/src/components/settings/providers/__tests__/Gemini.spec.tsx
new file mode 100644
index 0000000000..7b69538ff9
--- /dev/null
+++ b/webview-ui/src/components/settings/providers/__tests__/Gemini.spec.tsx
@@ -0,0 +1,85 @@
+import React from "react"
+import { render, screen, fireEvent } from "@testing-library/react"
+import { Gemini } from "../Gemini"
+import type { ProviderSettings } from "@roo-code/types"
+import { geminiModels, geminiDefaultModelId, type GeminiModelId } from "@roo-code/types"
+
+vi.mock("@vscode/webview-ui-toolkit/react", () => ({
+ VSCodeTextField: ({ children, value, onInput, type }: any) => (
+
+ {children}
+ onInput(e)} />
+
+ ),
+}))
+
+vi.mock("vscrui", () => ({
+ Checkbox: ({ children, checked, onChange }: any) => (
+
+ ),
+}))
+
+vi.mock("@src/components/ui", () => ({
+ Slider: ({ min, max, step, value, onValueChange }: any) => (
+ onValueChange([Number(e.target.value)])}
+ />
+ ),
+}))
+
+vi.mock("@src/i18n/TranslationContext", () => ({
+ useAppTranslation: () => ({ t: (key: string) => key }),
+}))
+
+vi.mock("@src/components/common/VSCodeButtonLink", () => ({
+ VSCodeButtonLink: ({ children, href }: any) => {children},
+}))
+
+const defaultModelId: GeminiModelId = geminiDefaultModelId
+const defaultContextWindow = geminiModels[defaultModelId].contextWindow
+
+describe("Gemini provider settings", () => {
+ it("does not render context limit slider when custom context limit is not enabled", () => {
+ const setApiField = vi.fn()
+ const config: ProviderSettings = {}
+ render(
+ ,
+ )
+ expect(screen.queryByTestId("slider")).toBeNull()
+ })
+
+ it("enables custom context limit on checkbox toggle and shows slider with default value", () => {
+ const setApiField = vi.fn()
+ const config: ProviderSettings = {}
+ render(
+ ,
+ )
+ const checkbox = screen.getByTestId("checkbox-custom-context-limit")
+ fireEvent.click(checkbox)
+ expect(setApiField).toHaveBeenCalledWith("contextLimit", defaultContextWindow)
+ const slider = screen.getByTestId("slider")
+ expect(slider).toHaveValue(defaultContextWindow.toString())
+ })
+
+ it("renders slider when contextLimit already set and updates on slider change", () => {
+ const setApiField = vi.fn()
+ const initialLimit = 100000
+ const config: ProviderSettings = { contextLimit: initialLimit }
+ render(
+ ,
+ )
+ const slider = screen.getByTestId("slider")
+ expect(slider).toHaveValue(initialLimit.toString())
+ fireEvent.change(slider, { target: { value: "50000" } })
+ expect(setApiField).toHaveBeenCalledWith("contextLimit", 50000)
+ })
+})