diff --git a/src/core/Cline.ts b/src/core/Cline.ts index 4bfcf59520..acecbd4fe6 100644 --- a/src/core/Cline.ts +++ b/src/core/Cline.ts @@ -1539,33 +1539,44 @@ export class Cline { this.didAlreadyUseTool = true } + // The user can approve, reject, or provide feedback (rejection). However the user may also send a message along with an approval, in which case we add a separate user message with this feedback. + const pushAdditionalToolFeedback = (feedback?: string, images?: string[]) => { + if (!feedback && !images) { + return + } + const content = formatResponse.toolResult( + `The user provided the following feedback:\n\n${feedback}\n`, + images, + ) + if (typeof content === "string") { + this.userMessageContent.push({ + type: "text", + text: content, + }) + } else { + this.userMessageContent.push(...content) + } + } + const askApproval = async (type: ClineAsk, partialMessage?: string) => { const { response, text, images } = await this.ask(type, partialMessage, false) if (response !== "yesButtonClicked") { - // User did NOT approve (rejected) - if (response === "messageResponse") { - // Rejection WITH feedback - await this.say("user_feedback", text, images) - pushToolResult(formatResponse.toolResult(formatResponse.toolDeniedWithFeedback(text), images)) - - this.didRejectTool = true - return false - } - // Rejection WITHOUT explicit feedback + // User pressed reject button or responded with a message, which we treat as a rejection pushToolResult(formatResponse.toolDenied()) - + if (text || images?.length) { + pushAdditionalToolFeedback(text, images) + await this.say("user_feedback", text, images) + } this.didRejectTool = true // Prevent further tool uses in this message return false + } else { + // User hit the approve button, and may have provided feedback + if (text || images?.length) { + pushAdditionalToolFeedback(text, images) + await this.say("user_feedback", text, images) + } + return true } - - // Handle yesButtonClicked with text (Acceptance WITH feedback) - if (text) { - await this.say("user_feedback", text, images) - pushToolResult(formatResponse.toolResult(formatResponse.toolApprovedWithFeedback(text), images)) // Structured feedback to model on approval - } - - // User approved without feedback - return true } const showNotificationForApprovalIfAutoApprovalEnabled = (message: string) => { @@ -1804,37 +1815,23 @@ export class Cline { let didApprove = true const { response, text, images } = await this.ask("tool", completeMessage, false) if (response !== "yesButtonClicked") { - // User did NOT approve (rejected) - + // User either sent a message or pressed reject button // TODO: add similar context for other tool denial responses, to emphasize ie that a command was not run const fileDeniedNote = fileExists ? "The file was not updated, and maintains its original contents." : "The file was not created." - if (response === "messageResponse") { - // Rejection WITH feedback + pushToolResult(`The user denied this operation. ${fileDeniedNote}`) + if (text || images?.length) { + pushAdditionalToolFeedback(text, images) await this.say("user_feedback", text, images) - pushToolResult( - formatResponse.toolResult( - `The user denied this operation. ${fileDeniedNote}\nThe user provided the following feedback:\n\n${text}\n`, - images, - ), - ) - this.didRejectTool = true - didApprove = false - } else { - pushToolResult(`The user denied this operation. ${fileDeniedNote}`) - this.didRejectTool = true - didApprove = false } + this.didRejectTool = true + didApprove = false } else { - // User approved - - // Handle yesButtonClicked with text (Acceptance WITH feedback) - if (text) { + // User hit the approve button, and may have provided feedback + if (text || images?.length) { + pushAdditionalToolFeedback(text, images) await this.say("user_feedback", text, images) - pushToolResult( - formatResponse.toolResult(formatResponse.toolApprovedWithFeedback(text), images), - ) } } diff --git a/src/core/prompts/responses.ts b/src/core/prompts/responses.ts index 8a14acc02b..bf5db6bbe7 100644 --- a/src/core/prompts/responses.ts +++ b/src/core/prompts/responses.ts @@ -6,12 +6,6 @@ import { ClineIgnoreController, LOCK_TEXT_SYMBOL } from "../ignore/ClineIgnoreCo export const formatResponse = { toolDenied: () => `The user denied this operation.`, - toolDeniedWithFeedback: (feedback?: string) => - `The user denied this operation and provided the following feedback:\n\n${feedback}\n`, - - toolApprovedWithFeedback: (feedback?: string) => - `The user approved this operation and provided the following feedback:\n\n${feedback}\n`, - toolError: (error?: string) => `The tool execution failed with the following error:\n\n${error}\n`, clineIgnoreError: (path: string) =>