Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 0 additions & 15 deletions src/api/providers/gemini.ts
Original file line number Diff line number Diff line change
Expand Up @@ -296,21 +296,6 @@ export class GeminiHandler extends BaseProvider implements SingleCompletionHandl
}
}

// If we had reasoning but no content, emit a placeholder text to prevent "Empty assistant response" errors.
// This typically happens when the model hits max output tokens while reasoning.
if (hasReasoning && !hasContent) {
let message = t("common:errors.gemini.thinking_complete_no_output")
if (finishReason === "MAX_TOKENS") {
message = t("common:errors.gemini.thinking_complete_truncated")
} else if (finishReason === "SAFETY") {
message = t("common:errors.gemini.thinking_complete_safety")
} else if (finishReason === "RECITATION") {
message = t("common:errors.gemini.thinking_complete_recitation")
}

yield { type: "text", text: message }
}

if (finalResponse?.responseId) {
// Capture responseId so Task.addToApiConversationHistory can store it
// alongside the assistant message in api_history.json.
Expand Down
19 changes: 17 additions & 2 deletions src/core/task/Task.ts
Original file line number Diff line number Diff line change
Expand Up @@ -309,6 +309,7 @@ export class Task extends EventEmitter<TaskEvents> implements TaskLike {
consecutiveMistakeCount: number = 0
consecutiveMistakeLimit: number
consecutiveMistakeCountForApplyDiff: Map<string, number> = new Map()
consecutiveNoToolUseCount: number = 0
toolUsage: ToolUsage = {}

// Checkpoints
Expand Down Expand Up @@ -1981,6 +1982,9 @@ export class Task extends EventEmitter<TaskEvents> implements TaskLike {

this.abort = true

// Reset consecutive error counters on abort (manual intervention)
this.consecutiveNoToolUseCount = 0

// Force final token usage update before abort event
this.emitFinalTokenUsageUpdate()

Expand Down Expand Up @@ -2235,7 +2239,6 @@ export class Task extends EventEmitter<TaskEvents> implements TaskLike {
} else {
// Use the task's locked protocol, NOT the current settings (fallback to xml if not set)
nextUserContent = [{ type: "text", text: formatResponse.noToolsUsed(this._taskToolProtocol ?? "xml") }]
this.consecutiveMistakeCount++
}
}
}
Expand Down Expand Up @@ -3236,12 +3239,24 @@ export class Task extends EventEmitter<TaskEvents> implements TaskLike {
)

if (!didToolUse) {
// Increment consecutive no-tool-use counter
this.consecutiveNoToolUseCount++

// Only show error and count toward mistake limit after 2 consecutive failures
if (this.consecutiveNoToolUseCount >= 2) {
await this.say("error", "MODEL_NO_TOOLS_USED")
// Only count toward mistake limit after second consecutive failure
this.consecutiveMistakeCount++
}

// Use the task's locked protocol for consistent behavior
this.userMessageContent.push({
type: "text",
text: formatResponse.noToolsUsed(this._taskToolProtocol ?? "xml"),
})
this.consecutiveMistakeCount++
} else {
// Reset counter when tools are used successfully
this.consecutiveNoToolUseCount = 0
}

// Push to stack if there's content OR if we're paused waiting for a subtask.
Expand Down
17 changes: 16 additions & 1 deletion webview-ui/src/components/chat/ChatRow.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -1259,7 +1259,22 @@ export const ChatRowContent = ({
</div>
)
case "error":
return <ErrorRow type="error" message={t("chat:error")} errorDetails={message.text || undefined} />
// Check if this is a model response error based on marker strings from backend
const isNoToolsUsedError = message.text === "MODEL_NO_TOOLS_USED"

if (isNoToolsUsedError) {
return (
<ErrorRow
type="error"
title={t("chat:modelResponseIncomplete")}
message={t("chat:modelResponseErrors.noToolsUsed")}
errorDetails={t("chat:modelResponseErrors.noToolsUsedDetails")}
/>
)
}

// Fallback for generic errors
return <ErrorRow type="error" message={message.text || t("chat:error")} />
case "completion_result":
return (
<>
Expand Down
5 changes: 5 additions & 0 deletions webview-ui/src/i18n/locales/ca/chat.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions webview-ui/src/i18n/locales/de/chat.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions webview-ui/src/i18n/locales/en/chat.json
Original file line number Diff line number Diff line change
Expand Up @@ -285,6 +285,11 @@
},
"taskCompleted": "Task Completed",
"error": "Error",
"modelResponseIncomplete": "Model Response Incomplete",
"modelResponseErrors": {
"noToolsUsed": "The model failed to use any tools in its response. This typically happens when the model provides only text/reasoning without calling the required tools to complete the task.",
"noToolsUsedDetails": "The model provided text/reasoning but did not call any of the required tools. This usually indicates the model misunderstood the task or is having difficulty determining which tool to use. The model has been automatically prompted to retry with proper tool usage."
},
"errorDetails": {
"title": "Error Details",
"copyToClipboard": "Copy to Clipboard",
Expand Down
5 changes: 5 additions & 0 deletions webview-ui/src/i18n/locales/es/chat.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions webview-ui/src/i18n/locales/fr/chat.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions webview-ui/src/i18n/locales/hi/chat.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions webview-ui/src/i18n/locales/id/chat.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions webview-ui/src/i18n/locales/it/chat.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions webview-ui/src/i18n/locales/ja/chat.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions webview-ui/src/i18n/locales/ko/chat.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions webview-ui/src/i18n/locales/nl/chat.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions webview-ui/src/i18n/locales/pl/chat.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions webview-ui/src/i18n/locales/pt-BR/chat.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions webview-ui/src/i18n/locales/ru/chat.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions webview-ui/src/i18n/locales/tr/chat.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions webview-ui/src/i18n/locales/vi/chat.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions webview-ui/src/i18n/locales/zh-CN/chat.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions webview-ui/src/i18n/locales/zh-TW/chat.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading