Skip to content
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
83 changes: 83 additions & 0 deletions src/core/assistant-message/presentAssistantMessage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -279,6 +279,89 @@ export async function presentAssistantMessage(cline: Task) {
progressStatus?: ToolProgressStatus,
isProtected?: boolean,
) => {
// Check auto-approval settings before asking user
const state = await cline.providerRef.deref()?.getState()

// Check if we should auto-approve based on tool type and settings
if (state) {
let shouldAutoApprove = false

// Handle tool approval
if (type === "tool" && partialMessage) {
try {
const toolInfo = JSON.parse(partialMessage)
const toolName = toolInfo.tool || block.name

// Check for read-only file operations
if (
toolName === "readFile" ||
toolName === "list_files" ||
toolName === "search_files" ||
toolName === "list_code_definition_names"
) {
Comment on lines +296 to +301
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Critical Bug: Tool name mismatch will prevent auto-approval from ever working

The tool names checked here use camelCase (e.g., readFile, writeFile) but the actual tool names in this codebase use snake_case (e.g., read_file, write_to_file).

Evidence from the same file:

  • Line 160: case "execute_command":
  • Line 162: case "read_file":
  • Line 171: case "write_to_file":
  • Line 173: case "apply_diff":
  • Line 196: case "insert_content":
  • Line 198: case "search_and_replace":

This means the conditions will never match, and auto-approval will never trigger. All tool names in the checks should use snake_case to match the actual tool names used throughout the codebase.

if (toolInfo.isOutsideWorkspace) {
shouldAutoApprove = state.alwaysAllowReadOnlyOutsideWorkspace ?? false
Comment on lines +302 to +303
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Logic Error: toolInfo.isOutsideWorkspace property doesn't exist in the parsed JSON

The code checks toolInfo.isOutsideWorkspace to determine which auto-approval setting to use, but this property is never set in the JSON passed to askApproval.

Looking at how askApproval is called throughout the codebase, the partialMessage parameter is either:

  1. A tool description string like "[read_file for 'path']" (from toolDescription() calls)
  2. A simple JSON like {"tool": "finishTask"} (from askFinishSubTaskApproval)

Neither includes an isOutsideWorkspace property. This means:

  • Lines 302-306: The condition if (toolInfo.isOutsideWorkspace) will never be true
  • Lines 318-320: The condition else if (toolInfo.isOutsideWorkspace) will never be true

The workspace context needs to be determined differently, likely by examining the tool's parameters or the file path being operated on.

} else {
shouldAutoApprove = state.alwaysAllowReadOnly ?? false
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Type Safety Issue: State properties used here are not defined in the state type

The code references several auto-approval properties on state that don't appear to be defined in the ProviderSettings type or related state types:

  • alwaysAllowReadOnly
  • alwaysAllowReadOnlyOutsideWorkspace
  • alwaysAllowWrite
  • alwaysAllowWriteOutsideWorkspace
  • alwaysAllowWriteProtected
  • alwaysAllowExecute
  • alwaysAllowBrowser
  • alwaysAllowFollowupQuestions
  • alwaysAllowUpdateTodoList
  • alwaysAllowMcp

These properties should either:

  1. Be added to the appropriate type definitions (likely in packages/types/src/provider-settings.ts or the state type)
  2. Or be accessed from a different location if they exist elsewhere

Without these properties being properly typed and available in the state object, TypeScript may not catch errors and the feature won't work at runtime.

}
}
// Check for write file operations
else if (
toolName === "writeFile" ||
toolName === "write_to_file" ||
toolName === "apply_diff" ||
toolName === "insert_content" ||
toolName === "search_and_replace"
) {
if (isProtected) {
shouldAutoApprove = state.alwaysAllowWriteProtected ?? false
} else if (toolInfo.isOutsideWorkspace) {
shouldAutoApprove = state.alwaysAllowWriteOutsideWorkspace ?? false
} else {
shouldAutoApprove = state.alwaysAllowWrite ?? false
}
}
// Check for command execution
else if (toolName === "execute_command") {
shouldAutoApprove = state.alwaysAllowExecute ?? false
}
// Check for browser actions
else if (toolName === "browser_action") {
shouldAutoApprove = state.alwaysAllowBrowser ?? false
}
// Check for follow-up questions
else if (toolName === "ask_followup_question") {
shouldAutoApprove = state.alwaysAllowFollowupQuestions ?? false
}
// Check for todo list updates
else if (toolName === "update_todo_list") {
shouldAutoApprove = state.alwaysAllowUpdateTodoList ?? false
}
} catch (error) {
// If parsing fails or any error occurs, fall through to normal approval flow
console.debug("Error checking auto-approval settings for tool:", error)
}
}
// Handle command approval
else if (type === "command") {
shouldAutoApprove = state.alwaysAllowExecute ?? false
}
// Handle browser action launch
else if (type === "browser_action_launch") {
shouldAutoApprove = state.alwaysAllowBrowser ?? false
}
// Handle MCP server usage
else if (type === "use_mcp_server") {
shouldAutoApprove = state.alwaysAllowMcp ?? false
}

if (shouldAutoApprove) {
// Auto-approve without asking user
return true
}
}

// Normal approval flow - ask the user
const { response, text, images } = await cline.ask(
type,
partialMessage,
Expand Down