Add requires_approval param to execute_command

This commit is contained in:
Saoud Rizwan 2024-12-15 21:46:34 -08:00
parent 44f70c1102
commit f468968b44
5 changed files with 44 additions and 5 deletions

View file

@ -20,7 +20,7 @@ import { parseSourceCodeForDefinitionsTopLevel } from "../services/tree-sitter"
import { ApiConfiguration } from "../shared/api"
import { findLastIndex } from "../shared/array"
import { combineApiRequests } from "../shared/combineApiRequests"
import { combineCommandSequences } from "../shared/combineCommandSequences"
import { combineCommandSequences, COMMAND_REQ_APP_STRING } from "../shared/combineCommandSequences"
import {
BrowserAction,
BrowserActionResult,
@ -1538,6 +1538,9 @@ export class Cline {
}
case "execute_command": {
const command: string | undefined = block.params.command
const requiresApprovalRaw: string | undefined = block.params.requires_approval
const requiresApproval = requiresApprovalRaw?.toLowerCase() === "true"
try {
if (block.partial) {
await this.ask("command", removeClosingTag("command", command), block.partial).catch(
@ -1552,8 +1555,21 @@ export class Cline {
)
break
}
if (!requiresApprovalRaw) {
this.consecutiveMistakeCount++
pushToolResult(
await this.sayAndCreateMissingParamError(
"execute_command",
"requires_approval",
),
)
break
}
this.consecutiveMistakeCount = 0
const didApprove = await askApproval("command", command)
const didApprove = await askApproval(
"command",
command + `${requiresApproval ? COMMAND_REQ_APP_STRING : ""}`, // ugly hack until we refactor combineCommandSequences
)
if (!didApprove) {
break
}

View file

@ -27,6 +27,7 @@ export type ToolUseName = (typeof toolUseNames)[number]
export const toolParamNames = [
"command",
"requires_approval",
"path",
"diff",
"regex",
@ -57,7 +58,7 @@ export interface ToolUse {
export interface ExecuteCommandToolUse extends ToolUse {
name: "execute_command"
// Pick<Record<ToolParamName, string>, "command"> makes "command" required, but Partial<> makes it optional
params: Partial<Pick<Record<ToolParamName, string>, "command">>
params: Partial<Pick<Record<ToolParamName, string>, "command" | "requires_approval">>
}
export interface ReadFileToolUse extends ToolUse {

View file

@ -39,9 +39,11 @@ Always adhere to this format for the tool use to ensure proper parsing and execu
Description: Request to execute a CLI command on the system. Use this when you need to perform system operations or run specific commands to accomplish any step in the user's task. You must tailor your command to the user's system and provide a clear explanation of what the command does. Prefer to execute complex CLI commands over creating executable scripts, as they are more flexible and easier to run. Commands will be executed in the current working directory: ${cwd.toPosix()}
Parameters:
- command: (required) The CLI command to execute. This should be valid for the current operating system. Ensure the command is properly formatted and does not contain any harmful instructions.
- requires_approval: (required) A boolean indicating whether this command requires explicit user approval before execution in case the user has auto-approve mode enabled. Set to 'true' for potentially impactful operations like installing/uninstalling packages, deleting/overwriting files, system configuration changes, network operations, or any commands that could have unintended side effects. Set to 'false' for safe operations like reading files/directories, running development servers, building projects, and other non-destructive operations.
Usage:
<execute_command>
<command>Your command here</command>
<requires_approval>true or false</requires_approval>
</execute_command>
## read_file
@ -219,6 +221,7 @@ Your final result description here
<execute_command>
<command>npm run dev</command>
<requires_approval>false</requires_approval>
</execute_command>
## Example 2: Requesting to use an MCP tool

View file

@ -71,3 +71,4 @@ export function combineCommandSequences(messages: ClineMessage[]): ClineMessage[
})
}
export const COMMAND_OUTPUT_STRING = "Output:"
export const COMMAND_REQ_APP_STRING = "REQ_APP"

View file

@ -8,7 +8,7 @@ import {
ClineMessage,
ClineSayTool,
} from "../../../../src/shared/ExtensionMessage"
import { COMMAND_OUTPUT_STRING } from "../../../../src/shared/combineCommandSequences"
import { COMMAND_OUTPUT_STRING, COMMAND_REQ_APP_STRING } from "../../../../src/shared/combineCommandSequences"
import { useExtensionState } from "../../context/ExtensionStateContext"
import { findMatchingResourceOrTemplate } from "../../utils/mcp"
import { vscode } from "../../utils/vscode"
@ -732,7 +732,11 @@ export const ChatRowContent = ({
}
}
const { command, output } = splitMessage(message.text || "")
const { command: rawCommand, output } = splitMessage(message.text || "")
const requestsApproval = rawCommand.endsWith(COMMAND_REQ_APP_STRING)
const command = requestsApproval ? rawCommand.slice(0, -COMMAND_REQ_APP_STRING.length) : rawCommand
return (
<>
<div style={headerStyle}>
@ -772,6 +776,20 @@ export const ChatRowContent = ({
</div>
)}
</div>
{requestsApproval && (
<div
style={{
display: "flex",
alignItems: "center",
gap: 10,
padding: 8,
fontSize: "12px",
color: "var(--vscode-errorForeground)",
}}>
<i className="codicon codicon-warning"></i>
<span>The model has determined this command requires explicit approval</span>
</div>
)}
</>
)
case "use_mcp_server":