@@ -14,6 +14,73 @@ import type { ToolParamName, ToolResponse, ToolUse, McpToolUse } from "../../sha
1414import { AskIgnoredError } from "../task/AskIgnoredError"
1515import { Task } from "../task/Task"
1616
17+ /**
18+ * Structured error presentation for LLM-guided error recovery.
19+ * Provides WHAT/WHY/NEXT format wrapped in <error_details> XML tags.
20+ */
21+ function formatStructuredError (
22+ details : {
23+ what : string
24+ why : string
25+ next : string [ ]
26+ retryable ?: boolean
27+ pattern ?: string
28+ occurrence ?: number
29+ disposition ?: string
30+ } ,
31+ byteLimit : number = 8000 ,
32+ ) : string {
33+ const version = "1.0"
34+ const status = "error"
35+ const category = details . pattern ? ( details . pattern . split ( "/" ) [ 1 ] ?? "unknown" ) : "unknown"
36+ const type = details . pattern
37+ ? details . pattern . startsWith ( "EI/" )
38+ ? details . pattern . replace ( "EI/" , "guided_" ) . toLowerCase ( ) . replace ( / _ / g, "_" )
39+ : details . pattern . toLowerCase ( ) . replace ( / _ / g, "_" )
40+ : "unclassified_error"
41+ const what = details . what
42+ const why = details . why
43+ const next = details . next ?? [ ]
44+ const retryable = details . retryable ?? true
45+ const occurrence = Math . max ( 1 , details . occurrence ?? 1 )
46+ const patternId = details . pattern ?? "UNCLASSIFIED/000/000"
47+ const recoveryDisposition = details . disposition ?? "correct_once"
48+
49+ const payload = {
50+ version,
51+ status,
52+ type,
53+ category,
54+ what,
55+ why,
56+ next,
57+ retryable,
58+ occurrence,
59+ pattern_id : patternId ,
60+ recovery_disposition : recoveryDisposition ,
61+ }
62+
63+ let json = JSON . stringify ( payload , null , 2 )
64+
65+ if ( json . length > byteLimit && next . length > 0 ) {
66+ // Trim Next items to fit within byte limit, preserving the first one
67+ const firstItem = next [ 0 ]
68+ next . length = 1
69+ const trimmed = {
70+ ...payload ,
71+ next : [ firstItem ] ,
72+ }
73+ json = JSON . stringify ( trimmed , null , 2 )
74+ }
75+
76+ if ( json . length > byteLimit ) {
77+ // Last resort: truncate the JSON string
78+ json = json . substring ( 0 , byteLimit - 3 ) + "..."
79+ }
80+
81+ return `<error_details>\n${ json } \n</error_details>`
82+ }
83+
1784import { listFilesTool } from "../tools/ListFilesTool"
1885import { readFileTool } from "../tools/ReadFileTool"
1986import { readCommandOutputTool } from "../tools/ReadCommandOutputTool"
@@ -225,12 +292,28 @@ export async function presentAssistantMessage(cline: Task) {
225292 if ( error instanceof AskIgnoredError ) {
226293 return
227294 }
228- const errorString = `Error ${ action } : ${ JSON . stringify ( serializeError ( error ) ) } `
295+
296+ // Structured error presentation with WHAT/WHY/NEXT format
297+ const serializedError = serializeError ( error )
298+ const structuredErrorContent = formatStructuredError ( {
299+ what : `An error occurred during ${ action } .` ,
300+ why : error . message || serializedError . message || "An unexpected error occurred." ,
301+ next : [
302+ `Retry the ${ action } operation with corrected parameters if applicable.` ,
303+ `If the error persists, report this issue to the development team with the error details below.` ,
304+ ] ,
305+ pattern : "TOOL_EXECUTION/ERROR_EXECUTION/001" ,
306+ retryable : true ,
307+ occurrence : 1 ,
308+ disposition : "correct_once" ,
309+ } )
310+
311+ pushToolResult ( structuredErrorContent )
312+
229313 await cline . say (
230314 "error" ,
231- `Error ${ action } :\n${ error . message ?? JSON . stringify ( serializeError ( error ) , null , 2 ) } ` ,
315+ `[ ${ action } ] Error during execution :\n${ error . message ?? JSON . stringify ( serializedError , null , 2 ) } \n\n ${ structuredErrorContent } ` ,
232316 )
233- pushToolResult ( formatResponse . toolError ( errorString ) )
234317 }
235318
236319 if ( ! mcpBlock . partial ) {
@@ -543,14 +626,28 @@ export async function presentAssistantMessage(cline: Task) {
543626 if ( error instanceof AskIgnoredError ) {
544627 return
545628 }
546- const errorString = `Error ${ action } : ${ JSON . stringify ( serializeError ( error ) ) } `
629+
630+ // Structured error presentation with WHAT/WHY/NEXT format
631+ const serializedError = serializeError ( error )
632+ const structuredErrorContent = formatStructuredError ( {
633+ what : `An error occurred during ${ action } .` ,
634+ why : error . message || serializedError . message || "An unexpected error occurred." ,
635+ next : [
636+ `Review the error details and retry the ${ action } operation with corrected parameters.` ,
637+ `If the error persists, report this issue to the development team.` ,
638+ ] ,
639+ pattern : "TOOL_EXECUTION/ERROR_EXECUTION/002" ,
640+ retryable : true ,
641+ occurrence : 1 ,
642+ disposition : "correct_once" ,
643+ } )
644+
645+ pushToolResult ( structuredErrorContent )
547646
548647 await cline . say (
549648 "error" ,
550- `Error ${ action } :\n${ error . message ?? JSON . stringify ( serializeError ( error ) , null , 2 ) } ` ,
649+ `[ ${ action } ] Error during execution :\n${ error . message ?? JSON . stringify ( serializedError , null , 2 ) } \n\n ${ structuredErrorContent } ` ,
551650 )
552-
553- pushToolResult ( formatResponse . toolError ( errorString ) )
554651 }
555652
556653 if ( ! block . partial ) {
0 commit comments