feat: expand R1 format auto-detection for thinking/reasoning models

- Auto-detect models with "-thinking" suffix (e.g., kimi-k2-thinking)
- Auto-detect DeepSeek R1 models (deepseek-r1, deepseek/deepseek-r1)
- Auto-detect QWQ models
- Renamed deepseekReasoner to useR1Format for clarity
- Users can still manually enable R1 format via the toggle

This improves support for reasoning/thinking models like Kimi-K2 that
require R1 format for proper response handling.
This commit is contained in:
Roo Code 2026-01-26 12:50:28 +00:00
parent 1b599a6eaa
commit 9287b9276d

View file

@ -89,7 +89,20 @@ export class OpenAiHandler extends BaseProvider implements SingleCompletionHandl
const modelId = this.options.openAiModelId ?? ""
const enabledR1Format = this.options.openAiR1FormatEnabled ?? false
const isAzureAiInference = this._isAzureAiInference(modelUrl)
const deepseekReasoner = modelId.includes("deepseek-reasoner") || enabledR1Format
// Auto-detect reasoning/thinking models that require R1 format:
// - DeepSeek Reasoner models
// - Models with "thinking" suffix (e.g., kimi-k2-thinking)
// - DeepSeek R1 models (deepseek-r1, deepseek/deepseek-r1)
// - QWQ models
// - Or when user explicitly enables R1 format
const modelIdLower = modelId.toLowerCase()
const useR1Format =
enabledR1Format ||
modelIdLower.includes("deepseek-reasoner") ||
modelIdLower.includes("-thinking") ||
modelIdLower.includes("deepseek-r1") ||
modelIdLower.includes("/deepseek-r1") ||
modelIdLower.includes("qwq")
if (modelId.includes("o1") || modelId.includes("o3") || modelId.includes("o4")) {
yield* this.handleO3FamilyMessage(modelId, systemPrompt, messages, metadata)
@ -104,7 +117,7 @@ export class OpenAiHandler extends BaseProvider implements SingleCompletionHandl
if (this.options.openAiStreamingEnabled ?? true) {
let convertedMessages
if (deepseekReasoner) {
if (useR1Format) {
convertedMessages = convertToR1Format([{ role: "user", content: systemPrompt }, ...messages])
} else {
if (modelInfo.supportsPromptCache) {
@ -154,7 +167,7 @@ export class OpenAiHandler extends BaseProvider implements SingleCompletionHandl
const requestOptions: OpenAI.Chat.Completions.ChatCompletionCreateParamsStreaming = {
model: modelId,
temperature: this.options.modelTemperature ?? (deepseekReasoner ? DEEP_SEEK_DEFAULT_TEMPERATURE : 0),
temperature: this.options.modelTemperature ?? (useR1Format ? DEEP_SEEK_DEFAULT_TEMPERATURE : 0),
messages: convertedMessages,
stream: true as const,
...(isGrokXAI ? {} : { stream_options: { include_usage: true } }),
@ -223,7 +236,7 @@ export class OpenAiHandler extends BaseProvider implements SingleCompletionHandl
} else {
const requestOptions: OpenAI.Chat.Completions.ChatCompletionCreateParamsNonStreaming = {
model: modelId,
messages: deepseekReasoner
messages: useR1Format
? convertToR1Format([{ role: "user", content: systemPrompt }, ...messages])
: [systemMessage, ...convertToOpenAiMessages(messages)],
// Tools are always present (minimum ALWAYS_AVAILABLE_TOOLS)