mirror of
https://github.com/RooVetGit/Roo-Code.git
synced 2026-09-11 22:51:26 +00:00
fix: handle thinking model reasoning-only responses as valid content
Thinking models (Kimi K2.5, DeepSeek-R1, QwQ) may produce only reasoning_content with no regular text content or tool calls. Previously this was treated as an empty/failed response, triggering the "language model did not provide any assistant messages" error and unnecessary retries. Changes: - Task.ts: Include reasoningMessage in the content check so reasoning-only responses are recognized as valid model output instead of triggering the empty response error path - openai.ts: Handle both "reasoning_content" (standard) and "reasoning" (Ollama /v1/) field names in streaming responses - openai.ts: Yield reasoning content from non-streaming responses Fixes #10603 Related: #9959, #10064, #9551 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
6ef149d567
commit
61778d2ad9
2 changed files with 27 additions and 4 deletions
|
|
@ -199,10 +199,16 @@ export class OpenAiHandler extends BaseProvider implements SingleCompletionHandl
|
|||
}
|
||||
}
|
||||
|
||||
if ("reasoning_content" in delta && delta.reasoning_content) {
|
||||
// Handle reasoning/thinking tokens from various providers:
|
||||
// - reasoning_content: DeepSeek, OpenAI (standard)
|
||||
// - reasoning: Ollama /v1/ (non-standard, used by Kimi K2.5, etc.)
|
||||
const reasoningText =
|
||||
("reasoning_content" in delta && (delta as any).reasoning_content) ||
|
||||
("reasoning" in delta && (delta as any).reasoning)
|
||||
if (reasoningText) {
|
||||
yield {
|
||||
type: "reasoning",
|
||||
text: (delta.reasoning_content as string | undefined) || "",
|
||||
text: String(reasoningText),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -260,6 +266,18 @@ export class OpenAiHandler extends BaseProvider implements SingleCompletionHandl
|
|||
}
|
||||
}
|
||||
|
||||
// Yield reasoning content from non-streaming responses
|
||||
// Thinking models (Kimi K2.5, DeepSeek-R1) may return reasoning
|
||||
// in the message alongside (or instead of) regular content
|
||||
const messageAny = message as any
|
||||
const nonStreamReasoning = messageAny?.reasoning_content || messageAny?.reasoning
|
||||
if (nonStreamReasoning) {
|
||||
yield {
|
||||
type: "reasoning",
|
||||
text: String(nonStreamReasoning),
|
||||
}
|
||||
}
|
||||
|
||||
yield {
|
||||
type: "text",
|
||||
text: message?.content || "",
|
||||
|
|
|
|||
|
|
@ -3401,14 +3401,19 @@ export class Task extends EventEmitter<TaskEvents> implements TaskLike {
|
|||
// the assistant message is already in history. Otherwise, tool_result blocks would appear
|
||||
// BEFORE their corresponding tool_use blocks, causing API errors.
|
||||
|
||||
// Check if we have any content to process (text or tool uses)
|
||||
// Check if we have any content to process (text, reasoning, or tool uses)
|
||||
// Thinking models (e.g., Kimi K2, DeepSeek-R1, QwQ) may produce only
|
||||
// reasoning_content with no regular text content. This should not be
|
||||
// treated as an empty/failed response — the model did respond, just
|
||||
// entirely in reasoning tokens.
|
||||
const hasTextContent = assistantMessage.length > 0
|
||||
const hasReasoningContent = reasoningMessage.length > 0
|
||||
|
||||
const hasToolUses = this.assistantMessageContent.some(
|
||||
(block) => block.type === "tool_use" || block.type === "mcp_tool_use",
|
||||
)
|
||||
|
||||
if (hasTextContent || hasToolUses) {
|
||||
if (hasTextContent || hasToolUses || hasReasoningContent) {
|
||||
// Reset counter when we get a successful response with content
|
||||
this.consecutiveNoAssistantMessagesCount = 0
|
||||
// Display grounding sources to the user if they exist
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue