mirror of
https://github.com/RooVetGit/Roo-Code.git
synced 2026-09-05 08:10:14 +00:00
fix: handle reasoning-only responses from Gemini 3 Pro Preview
When using Gemini 3 Pro Preview with high reasoning effort and native tool calling enabled, the model sometimes returns ONLY reasoning content without any text or tool uses. This caused the "Unexpected API Response: The language model did not provide any assistant messages" error. Changes: - Add reasoningOnlyResponse() helper to responses.ts that prompts the model to continue with actionable output after a reasoning-only response - Add hasReasoning check in Task.ts validation logic (line 3219) - Handle reasoning-only responses by saving the assistant message with reasoning to history and prompting the model to continue with tools/text This fix allows the task loop to continue instead of failing when the model produces a reasoning-only response. Fixes #10422
This commit is contained in:
parent
2068531801
commit
54a840cb70
2 changed files with 53 additions and 2 deletions
|
|
@ -74,6 +74,24 @@ ${instructions}
|
|||
If you have completed the user's task, use the attempt_completion tool.
|
||||
If you require additional information from the user, use the ask_followup_question tool.
|
||||
Otherwise, if you have not completed the task and do not need additional information, then proceed with the next step of the task.
|
||||
(This is an automated message, so do not respond to it conversationally.)`
|
||||
},
|
||||
|
||||
reasoningOnlyResponse: (protocol?: ToolProtocol) => {
|
||||
const instructions = getToolInstructionsReminder(protocol)
|
||||
|
||||
return `[CONTINUE] Your previous response contained only reasoning/thinking without any text content or tool use. While your reasoning process is valuable, you must now provide actionable output.
|
||||
|
||||
${instructions}
|
||||
|
||||
# Next Steps
|
||||
|
||||
Based on your reasoning, please now:
|
||||
1. If you have completed the user's task, use the attempt_completion tool.
|
||||
2. If you need to perform an action, use the appropriate tool.
|
||||
3. If you require additional information from the user, use the ask_followup_question tool.
|
||||
4. If you need to communicate something to the user, include text content in your response.
|
||||
|
||||
(This is an automated message, so do not respond to it conversationally.)`
|
||||
},
|
||||
|
||||
|
|
|
|||
|
|
@ -3209,13 +3209,16 @@ export class Task extends EventEmitter<TaskEvents> implements TaskLike {
|
|||
// tool use since user can exit at any moment and we wouldn't be
|
||||
// able to save the assistant's response.
|
||||
|
||||
// Check if we have any content to process (text or tool uses)
|
||||
// Check if we have any content to process (text, tool uses, or reasoning)
|
||||
const hasTextContent = assistantMessage.length > 0
|
||||
|
||||
const hasToolUses = this.assistantMessageContent.some(
|
||||
(block) => block.type === "tool_use" || block.type === "mcp_tool_use",
|
||||
)
|
||||
|
||||
// Check if we have reasoning content (models like Gemini 3 may return ONLY reasoning)
|
||||
const hasReasoning = reasoningMessage.length > 0
|
||||
|
||||
if (hasTextContent || hasToolUses) {
|
||||
// Reset counter when we get a successful response with content
|
||||
this.consecutiveNoAssistantMessagesCount = 0
|
||||
|
|
@ -3345,7 +3348,37 @@ export class Task extends EventEmitter<TaskEvents> implements TaskLike {
|
|||
// Add periodic yielding to prevent blocking
|
||||
await new Promise((resolve) => setImmediate(resolve))
|
||||
}
|
||||
|
||||
|
||||
continue
|
||||
} else if (hasReasoning) {
|
||||
// Handle reasoning-only response (e.g., Gemini 3 with high reasoning effort)
|
||||
// The model returned reasoning/thinking content but no text or tool uses.
|
||||
// This is a valid response that needs prompting to continue with actionable output.
|
||||
// Reset error counters since we got a valid response (just not actionable yet)
|
||||
this.consecutiveNoAssistantMessagesCount = 0
|
||||
this.consecutiveNoToolUseCount = 0
|
||||
|
||||
// Save the assistant message with reasoning to history (empty content with reasoning attached)
|
||||
await this.addToApiConversationHistory(
|
||||
{ role: "assistant", content: [] },
|
||||
reasoningMessage || undefined,
|
||||
)
|
||||
|
||||
TelemetryService.instance.captureConversationMessage(this.taskId, "assistant")
|
||||
|
||||
// Prompt the model to continue with actionable output
|
||||
// Use the task's locked protocol for consistent tool instructions
|
||||
this.userMessageContent.push({
|
||||
type: "text",
|
||||
text: formatResponse.reasoningOnlyResponse(this._taskToolProtocol ?? "xml"),
|
||||
})
|
||||
|
||||
// Continue the loop with the prompting message
|
||||
stack.push({
|
||||
userContent: [...this.userMessageContent],
|
||||
includeFileDetails: false,
|
||||
})
|
||||
|
||||
continue
|
||||
} else {
|
||||
// If there's no assistant_responses, that means we got no text
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue