fix: auto-enable R1 format for models with preserveReasoning in preset picker

When selecting a model preset with preserveReasoning (e.g. Kimi K2.5,
Kimi K2 thinking), the R1 format setting is now automatically enabled
so reasoning/thinking blocks work correctly via OpenAI Compatible endpoints.

Also adds visual indicator showing applied capability flags after
selecting a preset, and new tests covering the auto-enable behavior.
This commit is contained in:
Roo Code 2026-03-10 11:16:54 +00:00
parent 2005379780
commit c43a5a8e35
3 changed files with 77 additions and 1 deletions

View file

@ -64,6 +64,22 @@ export const OpenAICompatible = ({
const [openAiModels, setOpenAiModels] = useState<Record<string, ModelInfo> | null>(null)
// Compute applied capability flags for the selected preset
const appliedCapabilityFlags = useMemo(() => {
if (!selectedPresetId) return null
const preset = modelCapabilityPresets.find((p) => `${p.provider}/${p.modelId}` === selectedPresetId)
if (!preset) return null
const flags: string[] = []
if (preset.info.preserveReasoning)
flags.push(t("settings:providers.customModel.capabilityPreset.flags.reasoning"))
if (preset.info.supportsImages) flags.push(t("settings:providers.customModel.capabilityPreset.flags.images"))
if (preset.info.supportsPromptCache)
flags.push(t("settings:providers.customModel.capabilityPreset.flags.promptCache"))
if (preset.info.supportsTemperature)
flags.push(t("settings:providers.customModel.capabilityPreset.flags.temperature"))
return flags.length > 0 ? flags : null
}, [selectedPresetId, t])
// Group presets by provider for organized display
const groupedPresets = useMemo(() => {
const groups: Record<string, typeof modelCapabilityPresets> = {}
@ -81,11 +97,17 @@ export const OpenAICompatible = ({
if (presetKey === "custom") {
setSelectedPresetId(null)
setApiConfigurationField("openAiCustomModelInfo", openAiModelInfoSaneDefaults)
setApiConfigurationField("openAiR1FormatEnabled", false)
} else {
const preset = modelCapabilityPresets.find((p) => `${p.provider}/${p.modelId}` === presetKey)
if (preset) {
setSelectedPresetId(presetKey)
setApiConfigurationField("openAiCustomModelInfo", { ...preset.info })
// Auto-enable R1 format for models that use reasoning/thinking blocks
if (preset.info.preserveReasoning) {
setApiConfigurationField("openAiR1FormatEnabled", true)
}
}
}
setPresetPickerOpen(false)
@ -398,6 +420,12 @@ export const OpenAICompatible = ({
</Command>
</PopoverContent>
</Popover>
{appliedCapabilityFlags && (
<div className="text-xs text-vscode-descriptionForeground mt-1">
{t("settings:providers.customModel.capabilityPreset.appliedFlags")}:{" "}
{appliedCapabilityFlags.join(", ")}
</div>
)}
</div>
<div className="text-sm text-vscode-descriptionForeground whitespace-pre-line">

View file

@ -430,4 +430,45 @@ describe("OpenAICompatible Component - Model Capability Presets", () => {
}),
)
})
it("should reset openAiR1FormatEnabled when selecting custom preset", () => {
const apiConfiguration: Partial<ProviderSettings> = {}
render(
<OpenAICompatible
apiConfiguration={apiConfiguration as ProviderSettings}
setApiConfigurationField={mockSetApiConfigurationField}
organizationAllowList={mockOrganizationAllowList}
/>,
)
const customItem = screen.getByTestId("command-item-custom")
fireEvent.click(customItem)
expect(mockSetApiConfigurationField).toHaveBeenCalledWith("openAiR1FormatEnabled", false)
})
it("should auto-enable openAiR1FormatEnabled when selecting a model with preserveReasoning", () => {
const apiConfiguration: Partial<ProviderSettings> = {}
render(
<OpenAICompatible
apiConfiguration={apiConfiguration as ProviderSettings}
setApiConfigurationField={mockSetApiConfigurationField}
organizationAllowList={mockOrganizationAllowList}
/>,
)
// Click on a Kimi K2.5 model which has preserveReasoning: true
const kimiItem = screen.getByTestId("command-item-Moonshot (Kimi)/kimi-k2.5")
fireEvent.click(kimiItem)
expect(mockSetApiConfigurationField).toHaveBeenCalledWith("openAiR1FormatEnabled", true)
expect(mockSetApiConfigurationField).toHaveBeenCalledWith(
"openAiCustomModelInfo",
expect.objectContaining({
preserveReasoning: true,
}),
)
})
})

View file

@ -549,7 +549,14 @@
"custom": "Custom (configure manually)",
"searchPlaceholder": "Search models...",
"noResults": "No matching models found.",
"applied": "Applied capabilities from {{model}}"
"applied": "Applied capabilities from {{model}}",
"appliedFlags": "Applied capabilities",
"flags": {
"reasoning": "Reasoning/Thinking",
"images": "Image Support",
"promptCache": "Prompt Cache",
"temperature": "Temperature Control"
}
},
"capabilities": "Configure the capabilities and pricing for your custom OpenAI-compatible model. Be careful when specifying the model capabilities, as they can affect how Roo Code performs.",
"maxTokens": {