mirror of
https://github.com/RooVetGit/Roo-Code.git
synced 2026-08-28 05:27:24 +00:00
fix: ensure reasoning_content is always present for DeepSeek thinking mode
When using DeepSeek reasoner models with context condense, the API returns 400 error "Missing reasoning_content field in the assistant message" because condensed summary messages lack the reasoning_content field. DeepSeek's API requires ALL assistant messages to have reasoning_content when using thinking mode. This fix ensures reasoning_content is always included (even if empty string) on assistant messages when mergeToolResultText is enabled (which indicates thinking mode). Fixes #10175
This commit is contained in:
parent
06c5c7f980
commit
0fb47f252f
2 changed files with 98 additions and 2 deletions
|
|
@ -614,6 +614,86 @@ describe("convertToR1Format", () => {
|
|||
// Most importantly: NO user message after tool message
|
||||
expect(result.filter((m) => m.role === "user")).toHaveLength(1)
|
||||
})
|
||||
|
||||
it("should always include empty reasoning_content on assistant messages when mergeToolResultText is true", () => {
|
||||
// This simulates a condensed summary message that has no reasoning_content
|
||||
const input: Anthropic.Messages.MessageParam[] = [
|
||||
{ role: "user", content: "Start" },
|
||||
{
|
||||
role: "assistant",
|
||||
content: "This is a condensed summary of the previous conversation.",
|
||||
},
|
||||
]
|
||||
|
||||
const result = convertToR1Format(input, { mergeToolResultText: true })
|
||||
|
||||
expect(result).toHaveLength(2)
|
||||
expect(result[0]).toEqual({ role: "user", content: "Start" })
|
||||
// Should have empty reasoning_content for thinking models
|
||||
expect((result[1] as any).reasoning_content).toBe("")
|
||||
expect(result[1]).toEqual({
|
||||
role: "assistant",
|
||||
content: "This is a condensed summary of the previous conversation.",
|
||||
reasoning_content: "",
|
||||
})
|
||||
})
|
||||
|
||||
it("should NOT add reasoning_content on assistant messages when mergeToolResultText is false", () => {
|
||||
// For non-thinking models, reasoning_content should not be added
|
||||
const input: Anthropic.Messages.MessageParam[] = [
|
||||
{ role: "user", content: "Start" },
|
||||
{
|
||||
role: "assistant",
|
||||
content: "This is a regular response.",
|
||||
},
|
||||
]
|
||||
|
||||
// Without mergeToolResultText option (default behavior)
|
||||
const result = convertToR1Format(input)
|
||||
|
||||
expect(result).toHaveLength(2)
|
||||
// Should NOT have reasoning_content for non-thinking models
|
||||
expect((result[1] as any).reasoning_content).toBeUndefined()
|
||||
expect(result[1]).toEqual({
|
||||
role: "assistant",
|
||||
content: "This is a regular response.",
|
||||
})
|
||||
})
|
||||
|
||||
it("should include empty reasoning_content on assistant messages with array content when mergeToolResultText is true", () => {
|
||||
const input: Anthropic.Messages.MessageParam[] = [
|
||||
{ role: "user", content: "Start" },
|
||||
{
|
||||
role: "assistant",
|
||||
content: [{ type: "text", text: "Array content response without reasoning" }],
|
||||
},
|
||||
]
|
||||
|
||||
const result = convertToR1Format(input, { mergeToolResultText: true })
|
||||
|
||||
expect(result).toHaveLength(2)
|
||||
// Should have empty reasoning_content for thinking models even with array content
|
||||
expect((result[1] as any).reasoning_content).toBe("")
|
||||
})
|
||||
|
||||
it("should preserve existing reasoning_content when present even with mergeToolResultText", () => {
|
||||
const input = [
|
||||
{ role: "user" as const, content: "Start" },
|
||||
{
|
||||
role: "assistant" as const,
|
||||
content: "Response with reasoning",
|
||||
reasoning_content: "My actual reasoning process",
|
||||
},
|
||||
]
|
||||
|
||||
const result = convertToR1Format(input as Anthropic.Messages.MessageParam[], {
|
||||
mergeToolResultText: true,
|
||||
})
|
||||
|
||||
expect(result).toHaveLength(2)
|
||||
// Should preserve the actual reasoning_content, not replace with empty
|
||||
expect((result[1] as any).reasoning_content).toBe("My actual reasoning process")
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
|
|
|
|||
|
|
@ -190,12 +190,21 @@ export function convertToR1Format(
|
|||
// Use reasoning from content blocks if not provided at top level
|
||||
const finalReasoning = reasoningContent || extractedReasoning
|
||||
|
||||
// For thinking models (indicated by mergeToolResultText), always include reasoning_content
|
||||
// DeepSeek's reasoner API requires this field to be present on all assistant messages
|
||||
const shouldAlwaysIncludeReasoningContent = options?.mergeToolResultText === true
|
||||
|
||||
const assistantMessage: DeepSeekAssistantMessage = {
|
||||
role: "assistant",
|
||||
content: textParts.length > 0 ? textParts.join("\n") : null,
|
||||
...(toolCalls.length > 0 && { tool_calls: toolCalls }),
|
||||
// Preserve reasoning_content for DeepSeek interleaved thinking
|
||||
...(finalReasoning && { reasoning_content: finalReasoning }),
|
||||
// Always include for thinking models (even if empty) to satisfy DeepSeek's API requirement
|
||||
...(finalReasoning
|
||||
? { reasoning_content: finalReasoning }
|
||||
: shouldAlwaysIncludeReasoningContent
|
||||
? { reasoning_content: "" }
|
||||
: {}),
|
||||
}
|
||||
|
||||
// Check if we can merge with the last message (only if no tool calls)
|
||||
|
|
@ -229,10 +238,17 @@ export function convertToR1Format(
|
|||
;(lastMessage as DeepSeekAssistantMessage).reasoning_content = reasoningContent
|
||||
}
|
||||
} else {
|
||||
// For thinking models (indicated by mergeToolResultText), always include reasoning_content
|
||||
const shouldAlwaysIncludeReasoningContent = options?.mergeToolResultText === true
|
||||
const assistantMessage: DeepSeekAssistantMessage = {
|
||||
role: "assistant",
|
||||
content: message.content,
|
||||
...(reasoningContent && { reasoning_content: reasoningContent }),
|
||||
// Always include for thinking models (even if empty) to satisfy DeepSeek's API requirement
|
||||
...(reasoningContent
|
||||
? { reasoning_content: reasoningContent }
|
||||
: shouldAlwaysIncludeReasoningContent
|
||||
? { reasoning_content: "" }
|
||||
: {}),
|
||||
}
|
||||
result.push(assistantMessage)
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue