@@ -35,6 +35,8 @@ interface FileResult {
3535 notice ?: string
3636 lineRanges ?: LineRange [ ]
3737 xmlContent ?: string // Final XML content for this file
38+ feedbackText ?: string // User feedback text from approval/denial
39+ feedbackImages ?: any [ ] // User feedback images from approval/denial
3840}
3941
4042export async function readFileTool (
@@ -211,14 +213,32 @@ export async function readFileTool(
211213 reason : lineSnippet ,
212214 } satisfies ClineSayTool )
213215
214- const didApprove = await askApproval ( "tool" , completeMessage )
215- if ( ! didApprove ) {
216+ const { response, text, images } = await cline . ask ( "tool" , completeMessage , false )
217+
218+ if ( response !== "yesButtonClicked" ) {
219+ // Handle both messageResponse and noButtonClicked with text
220+ if ( text ) {
221+ await cline . say ( "user_feedback" , text , images )
222+ }
223+ cline . didRejectTool = true
224+
216225 updateFileResult ( relPath , {
217226 status : "denied" ,
218227 xmlContent : `<file><path>${ relPath } </path><status>Denied by user</status></file>` ,
228+ feedbackText : text ,
229+ feedbackImages : images ,
219230 } )
220231 } else {
221- updateFileResult ( relPath , { status : "approved" } )
232+ // Handle yesButtonClicked with text
233+ if ( text ) {
234+ await cline . say ( "user_feedback" , text , images )
235+ }
236+
237+ updateFileResult ( relPath , {
238+ status : "approved" ,
239+ feedbackText : text ,
240+ feedbackImages : images ,
241+ } )
222242 }
223243 }
224244 }
@@ -320,9 +340,51 @@ export async function readFileTool(
320340
321341 // Generate final XML result from all file results
322342 const xmlResults = fileResults . filter ( ( result ) => result . xmlContent ) . map ( ( result ) => result . xmlContent )
343+ const filesXml = `<files>\n${ xmlResults . join ( "\n" ) } \n</files>`
323344
324- // Push combined results
325- pushToolResult ( `<files>\n${ xmlResults . join ( "\n" ) } \n</files>` )
345+ // Process all feedback in a unified way without branching
346+ let statusMessage = ""
347+ let feedbackImages : any [ ] = [ ]
348+
349+ // Handle denial with feedback (highest priority)
350+ const deniedWithFeedback = fileResults . find ( ( result ) => result . status === "denied" && result . feedbackText )
351+
352+ if ( deniedWithFeedback && deniedWithFeedback . feedbackText ) {
353+ statusMessage = formatResponse . toolDeniedWithFeedback ( deniedWithFeedback . feedbackText )
354+ feedbackImages = deniedWithFeedback . feedbackImages || [ ]
355+ }
356+ // Handle generic denial
357+ else if ( cline . didRejectTool ) {
358+ statusMessage = formatResponse . toolDenied ( )
359+ }
360+ // Handle approval with feedback
361+ else {
362+ const approvedWithFeedback = fileResults . find (
363+ ( result ) => result . status === "approved" && result . feedbackText ,
364+ )
365+
366+ if ( approvedWithFeedback && approvedWithFeedback . feedbackText ) {
367+ statusMessage = formatResponse . toolApprovedWithFeedback ( approvedWithFeedback . feedbackText )
368+ feedbackImages = approvedWithFeedback . feedbackImages || [ ]
369+ }
370+ }
371+
372+ // Push the result with appropriate formatting
373+ if ( statusMessage ) {
374+ const result = formatResponse . toolResult ( statusMessage , feedbackImages )
375+
376+ // Handle different return types from toolResult
377+ if ( typeof result === "string" ) {
378+ pushToolResult ( `${ result } \n${ filesXml } ` )
379+ } else {
380+ // For block-based results, we need to convert the filesXml to a text block and append it
381+ const textBlock = { type : "text" as const , text : filesXml }
382+ pushToolResult ( [ ...result , textBlock ] )
383+ }
384+ } else {
385+ // No status message, just push the files XML
386+ pushToolResult ( filesXml )
387+ }
326388 } catch ( error ) {
327389 // Handle all errors using per-file format for consistency
328390 const relPath = fileEntries [ 0 ] ?. path || "unknown"
0 commit comments