diff --git a/src/core/Cline.ts b/src/core/Cline.ts index 2adc3c86d4..d2588d3fa3 100644 --- a/src/core/Cline.ts +++ b/src/core/Cline.ts @@ -73,6 +73,7 @@ export class Cline { private askResponseText?: string private askResponseImages?: string[] private lastMessageTs?: number + private consecutiveAutoApprovedRequestsCount: number = 0 private consecutiveMistakeCount: number = 0 private providerRef: WeakRef private abort: boolean = false @@ -1192,6 +1193,7 @@ export class Cline { if (this.shouldAutoApproveTool(block.name)) { await this.say("tool", completeMessage, undefined, false) + this.consecutiveAutoApprovedRequestsCount++ } else { const didApprove = await askApproval("tool", completeMessage) if (!didApprove) { @@ -1274,6 +1276,7 @@ export class Cline { } satisfies ClineSayTool) if (this.shouldAutoApproveTool(block.name)) { await this.say("tool", completeMessage, undefined, false) // need to be sending partialValue bool, since undefined has its own purpose in that the message is treated neither as a partial or completion of a partial, but as a single complete message + this.consecutiveAutoApprovedRequestsCount++ } else { const didApprove = await askApproval("tool", completeMessage) if (!didApprove) { @@ -1326,6 +1329,7 @@ export class Cline { } satisfies ClineSayTool) if (this.shouldAutoApproveTool(block.name)) { await this.say("tool", completeMessage, undefined, false) + this.consecutiveAutoApprovedRequestsCount++ } else { const didApprove = await askApproval("tool", completeMessage) if (!didApprove) { @@ -1375,6 +1379,7 @@ export class Cline { } satisfies ClineSayTool) if (this.shouldAutoApproveTool(block.name)) { await this.say("tool", completeMessage, undefined, false) + this.consecutiveAutoApprovedRequestsCount++ } else { const didApprove = await askApproval("tool", completeMessage) if (!didApprove) { @@ -1431,6 +1436,7 @@ export class Cline { } satisfies ClineSayTool) if (this.shouldAutoApproveTool(block.name)) { await this.say("tool", completeMessage, undefined, false) + this.consecutiveAutoApprovedRequestsCount++ } else { const didApprove = await askApproval("tool", completeMessage) if (!didApprove) { @@ -1506,6 +1512,7 @@ export class Cline { if (this.shouldAutoApproveTool(block.name)) { await this.say("browser_action_launch", url, undefined, false) + this.consecutiveAutoApprovedRequestsCount++ } else { const didApprove = await askApproval("browser_action_launch", url) if (!didApprove) { @@ -1649,6 +1656,7 @@ export class Cline { if (!requiresApproval && this.shouldAutoApproveTool(block.name)) { await this.say("command", command, undefined, false) + this.consecutiveAutoApprovedRequestsCount++ } else { const didApprove = await askApproval( "command", @@ -1741,6 +1749,7 @@ export class Cline { if (this.shouldAutoApproveTool(block.name)) { await this.say("use_mcp_server", completeMessage, undefined, false) + this.consecutiveAutoApprovedRequestsCount++ } else { const didApprove = await askApproval("use_mcp_server", completeMessage) if (!didApprove) { @@ -1821,6 +1830,7 @@ export class Cline { if (this.shouldAutoApproveTool(block.name)) { await this.say("use_mcp_server", completeMessage, undefined, false) + this.consecutiveAutoApprovedRequestsCount++ } else { const didApprove = await askApproval("use_mcp_server", completeMessage) if (!didApprove) { @@ -2075,6 +2085,18 @@ export class Cline { this.consecutiveMistakeCount = 0 } + if ( + this.autoApprovalSettings.enabled && + this.consecutiveAutoApprovedRequestsCount >= this.autoApprovalSettings.maxRequests + ) { + await this.ask( + "auto_approval_max_req_reached", + `Cline has auto-approved ${this.autoApprovalSettings.maxRequests.toString()} API requests. Would you like to reset the count and proceed with the task?`, + ) + // if we get past the promise it means the user approved and did not start a new task + this.consecutiveAutoApprovedRequestsCount = 0 + } + // get previous api req's index to check token usage and determine if we need to truncate conversation history const previousApiReqIndex = findLastIndex(this.clineMessages, (m) => m.say === "api_req_started") diff --git a/src/shared/ExtensionMessage.ts b/src/shared/ExtensionMessage.ts index 3ec5e7f098..3889f0e1c6 100644 --- a/src/shared/ExtensionMessage.ts +++ b/src/shared/ExtensionMessage.ts @@ -68,6 +68,7 @@ export type ClineAsk = | "resume_task" | "resume_completed_task" | "mistake_limit_reached" + | "auto_approval_max_req_reached" | "browser_action_launch" | "use_mcp_server" diff --git a/webview-ui/src/components/chat/AutoApproveMenu.tsx b/webview-ui/src/components/chat/AutoApproveMenu.tsx index c2485455c5..35c24830ac 100644 --- a/webview-ui/src/components/chat/AutoApproveMenu.tsx +++ b/webview-ui/src/components/chat/AutoApproveMenu.tsx @@ -267,7 +267,8 @@ const AutoApproveMenu = ({ style }: AutoApproveMenuProps) => { fontSize: "12px", marginBottom: "10px", }}> - Cline will make this many API requests before asking for approval to proceed with the task. + Cline will automatically make this many API requests before asking for approval to proceed with + the task.
, Cline is having trouble..., ] + case "auto_approval_max_req_reached": + return [ + , + Maximum Requests Reached, + ] case "command": return [ isCommandExecuting ? ( @@ -886,7 +893,16 @@ export const ChatRowContent = ({

{message.text}

) - + case "auto_approval_max_req_reached": + return ( + <> +
+ {icon} + {title} +
+

{message.text}

+ + ) case "completion_result": if (message.text) { return ( diff --git a/webview-ui/src/components/chat/ChatView.tsx b/webview-ui/src/components/chat/ChatView.tsx index a7e33df9f2..70a8fcfef6 100644 --- a/webview-ui/src/components/chat/ChatView.tsx +++ b/webview-ui/src/components/chat/ChatView.tsx @@ -89,6 +89,13 @@ const ChatView = ({ isHidden, showAnnouncement, hideAnnouncement, showHistoryVie setPrimaryButtonText("Proceed Anyways") setSecondaryButtonText("Start New Task") break + case "auto_approval_max_req_reached": + setTextAreaDisabled(true) + setClineAsk("auto_approval_max_req_reached") + setEnableButtons(true) + setPrimaryButtonText("Proceed") + setSecondaryButtonText("Start New Task") + break case "followup": setTextAreaDisabled(isPartial) setClineAsk("followup") @@ -305,6 +312,7 @@ const ChatView = ({ isHidden, showAnnouncement, hideAnnouncement, showHistoryVie case "use_mcp_server": case "resume_task": case "mistake_limit_reached": + case "auto_approval_max_req_reached": vscode.postMessage({ type: "askResponse", askResponse: "yesButtonClicked" }) break case "completion_result": @@ -331,6 +339,7 @@ const ChatView = ({ isHidden, showAnnouncement, hideAnnouncement, showHistoryVie switch (clineAsk) { case "api_req_failed": case "mistake_limit_reached": + case "auto_approval_max_req_reached": startNewTask() break case "command":