feat: add diagnostic details to tool call error messages (ROO-495)

- Include diagnostic information in MODEL_NO_TOOLS_USED error
- Include diagnostic information in MODEL_NO_ASSISTANT_MESSAGES error
- Update ChatRow to extract and display diagnostic details in error popup
- Diagnostic details include: tool protocol, consecutive error count, message length, content blocks, and raw assistant message
This commit is contained in:
Roo Code 2026-01-12 17:05:23 +00:00
parent 4c2d1f0c68
commit 19573887c1
2 changed files with 47 additions and 5 deletions

View file

@ -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++
}

View file

@ -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}
/>
)
}