Skip to content
Draft
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
24 changes: 23 additions & 1 deletion src/core/task/Task.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3501,7 +3501,29 @@ export class Task extends EventEmitter<TaskEvents> implements TaskLike {

// Only show error and count toward mistake limit after 2 consecutive failures
if (this.consecutiveNoToolUseCount >= 2) {
await this.say("error", "MODEL_NO_TOOLS_USED")
// Create diagnostic information for the details popup
const diagnosticInfo = [
"Diagnostic Information:",
"",
`Tool Protocol: ${this._taskToolProtocol ?? "unknown"}`,
`Consecutive No-Tool-Use Count: ${this.consecutiveNoToolUseCount}`,
`Assistant Message Length: ${assistantMessage.length} characters`,
"",
"Assistant Message Content Blocks:",
this.assistantMessageContent.length > 0
? this.assistantMessageContent
.map(
(block, i) =>
` ${i + 1}. Type: ${block.type}${block.type === "text" ? `, Length: ${(block as any).content?.length ?? 0} chars` : ""}`,
)
.join("\n")
: " (none)",
"",
"Raw Assistant Message:",
assistantMessage || "(empty)",
].join("\n")

await this.say("error", `MODEL_NO_TOOLS_USED\n${diagnosticInfo}`)
// Only count toward mistake limit after second consecutive failure
this.consecutiveMistakeCount++
}
Expand Down
28 changes: 24 additions & 4 deletions webview-ui/src/components/chat/ChatRow.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -1310,27 +1310,47 @@ export const ChatRowContent = ({
)
case "error":
// Check if this is a model response error based on marker strings from backend
const isNoToolsUsedError = message.text === "MODEL_NO_TOOLS_USED"
const isNoAssistantMessagesError = message.text === "MODEL_NO_ASSISTANT_MESSAGES"
// The format is "MARKER\nDiagnostic Info" where diagnostic info is optional
const messageText = message.text || ""
const isNoToolsUsedError = messageText.startsWith("MODEL_NO_TOOLS_USED")
const isNoAssistantMessagesError = messageText.startsWith("MODEL_NO_ASSISTANT_MESSAGES")

if (isNoToolsUsedError) {
// Extract diagnostic info if present (after the marker and newline)
const parts = messageText.split("\n")
const diagnosticInfo = parts.length > 1 ? parts.slice(1).join("\n") : undefined

// Combine i18n detailed explanation with diagnostic info
const fullDetails = diagnosticInfo
? `${t("chat:modelResponseErrors.noToolsUsedDetails")}\n\n${diagnosticInfo}`
: t("chat:modelResponseErrors.noToolsUsedDetails")

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

if (isNoAssistantMessagesError) {
// Extract diagnostic info if present (after the marker and newline)
const parts = messageText.split("\n")
const diagnosticInfo = parts.length > 1 ? parts.slice(1).join("\n") : undefined

// Combine i18n detailed explanation with diagnostic info
const fullDetails = diagnosticInfo
? `${t("chat:modelResponseErrors.noAssistantMessagesDetails")}\n\n${diagnosticInfo}`
: t("chat:modelResponseErrors.noAssistantMessagesDetails")

return (
<ErrorRow
type="error"
title={t("chat:modelResponseIncomplete")}
message={t("chat:modelResponseErrors.noAssistantMessages")}
errorDetails={t("chat:modelResponseErrors.noAssistantMessagesDetails")}
errorDetails={fullDetails}
/>
)
}
Expand Down
Loading