feat: max value of maxOutputTokens is model's maxTokens + adding more tests

This commit is contained in:
Ton Hoang Nguyen (Bill) 2025-06-27 00:13:14 +01:00
parent 24e8ed57a1
commit 98e813d1d3
3 changed files with 114 additions and 2 deletions

View file

@ -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)

View file

@ -198,7 +198,7 @@ export const Gemini = ({
<div className="flex items-center space-x-2">
<Slider
min={3000}
max={8192}
max={modelInfo.maxTokens}
step={1}
value={[apiConfiguration.maxOutputTokens ?? 0]}
onValueChange={(values: number[]) => 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"
/>
</div>

View file

@ -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) => (
<div>
{children}
<input type={type} value={value} onChange={(e) => onInput(e)} />
</div>
),
}))
vi.mock("vscrui", () => ({
Checkbox: ({ children, checked, onChange }: any) => (
<label data-testid="checkbox-custom-context-limit">
<input type="checkbox" checked={checked} onChange={(e) => onChange(e.target.checked)} />
{children}
</label>
),
}))
vi.mock("@src/components/ui", () => ({
Slider: ({ min, max, step, value, onValueChange }: any) => (
<input
data-testid="slider"
type="range"
min={min}
max={max}
step={step}
value={value[0]}
onChange={(e) => 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) => <a href={href}>{children}</a>,
}))
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(
<Gemini apiConfiguration={config} setApiConfigurationField={setApiField} currentModelId={defaultModelId} />,
)
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(
<Gemini apiConfiguration={config} setApiConfigurationField={setApiField} currentModelId={defaultModelId} />,
)
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(
<Gemini apiConfiguration={config} setApiConfigurationField={setApiField} currentModelId={defaultModelId} />,
)
const slider = screen.getByTestId("slider")
expect(slider).toHaveValue(initialLimit.toString())
fireEvent.change(slider, { target: { value: "50000" } })
expect(setApiField).toHaveBeenCalledWith("contextLimit", 50000)
})
})