Fix issues with subtasks attempting completion along with commands (#3156)

This commit is contained in:
Matt Rubens 2025-05-04 02:57:19 -04:00 committed by GitHub
parent 40ee5cf154
commit 756c0a0014
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
10 changed files with 34 additions and 22 deletions

View file

@ -0,0 +1,5 @@
---
"roo-cline": patch
---
Fix auto-approvals

View file

@ -161,7 +161,7 @@ export class Cline extends EventEmitter<ClineEvents> {
private askResponse?: ClineAskResponse
private askResponseText?: string
private askResponseImages?: string[]
private lastMessageTs?: number
public lastMessageTs?: number
// Not private since it needs to be accessible by tools.
consecutiveMistakeCount: number = 0

View file

@ -76,13 +76,13 @@ export async function attemptCompletionTool(
}
// Complete command message.
const executionId = Date.now().toString()
const didApprove = await askApproval("command", command, { id: executionId })
const didApprove = await askApproval("command", command)
if (!didApprove) {
return
}
const executionId = cline.lastMessageTs?.toString() ?? Date.now().toString()
const options: ExecuteCommandOptions = { executionId, command }
const [userRejected, execCommandResult] = await executeCommand(cline, options)
@ -108,7 +108,7 @@ export async function attemptCompletionTool(
}
// tell the provider to remove the current subtask and resume the previous task in the stack
await cline.providerRef.deref()?.finishSubTask(lastMessage?.text ?? "")
await cline.providerRef.deref()?.finishSubTask(result)
return
}

View file

@ -48,14 +48,14 @@ export async function executeCommandTool(
cline.consecutiveMistakeCount = 0
const executionId = Date.now().toString()
command = unescapeHtmlEntities(command) // Unescape HTML entities.
const didApprove = await askApproval("command", command, { id: executionId })
const didApprove = await askApproval("command", command)
if (!didApprove) {
return
}
const executionId = cline.lastMessageTs?.toString() ?? Date.now().toString()
const clineProvider = await cline.providerRef.deref()
const clineProviderState = await clineProvider?.getState()
const { terminalOutputLineLimit = 500, terminalShellIntegrationDisabled = false } = clineProviderState ?? {}

View file

@ -353,7 +353,6 @@ type ClineMessage = {
| undefined
progressStatus?:
| {
id?: string | undefined
icon?: string | undefined
text?: string | undefined
}
@ -429,7 +428,6 @@ type RooCodeEvents = {
| undefined
progressStatus?:
| {
id?: string | undefined
icon?: string | undefined
text?: string | undefined
}

View file

@ -358,7 +358,6 @@ type ClineMessage = {
| undefined
progressStatus?:
| {
id?: string | undefined
icon?: string | undefined
text?: string | undefined
}
@ -438,7 +437,6 @@ type RooCodeEvents = {
| undefined
progressStatus?:
| {
id?: string | undefined
icon?: string | undefined
text?: string | undefined
}

View file

@ -817,7 +817,6 @@ export type ClineSay = z.infer<typeof clineSaySchema>
*/
export const toolProgressStatusSchema = z.object({
id: z.string().optional(),
icon: z.string().optional(),
text: z.string().optional(),
})

View file

@ -985,7 +985,7 @@ export const ChatRowContent = ({
{icon}
{title}
</div>
<CommandExecution executionId={message.progressStatus?.id} text={message.text} />
<CommandExecution executionId={message.ts.toString()} text={message.text} />
</>
)
case "use_mcp_server":

View file

@ -735,7 +735,9 @@ const ChatViewComponent: React.ForwardRefRenderFunction<ChatViewRef, ChatViewPro
const isAutoApproved = useCallback(
(message: ClineMessage | undefined) => {
if (!autoApprovalEnabled || !message || message.type !== "ask") return false
if (!autoApprovalEnabled || !message || message.type !== "ask") {
return false
}
if (message.ask === "browser_action_launch") {
return alwaysAllowBrowser
@ -749,7 +751,8 @@ const ChatViewComponent: React.ForwardRefRenderFunction<ChatViewRef, ChatViewPro
return alwaysAllowExecute && isAllowedCommand(message)
}
// For read/write operations, check if it's outside workspace and if we have permission for that
// For read/write operations, check if it's outside workspace and if
// we have permission for that.
if (message.ask === "tool") {
let tool: any = {}
@ -1114,13 +1117,26 @@ const ChatViewComponent: React.ForwardRefRenderFunction<ChatViewRef, ChatViewPro
}
const autoApprove = async () => {
if (isAutoApproved(lastMessage)) {
if (lastMessage?.ask && isAutoApproved(lastMessage)) {
// Note that `isAutoApproved` can only return true if
// lastMessage is an ask of type "browser_action_launch",
// "use_mcp_server", "command", or "tool".
// Add delay for write operations.
if (lastMessage?.ask === "tool" && isWriteToolAction(lastMessage)) {
if (lastMessage.ask === "tool" && isWriteToolAction(lastMessage)) {
await new Promise((resolve) => setTimeout(resolve, writeDelayMs))
}
handlePrimaryButtonClick()
vscode.postMessage({ type: "askResponse", askResponse: "yesButtonClicked" })
// This is copied from `handlePrimaryButtonClick`, which we used
// to call from `autoApprove`. I'm not sure how many of these
// things are actually needed.
setInputValue("")
setSelectedImages([])
setTextAreaDisabled(true)
setClineAsk(undefined)
setEnableButtons(false)
}
}
autoApprove()

View file

@ -14,7 +14,7 @@ import { cn } from "@src/lib/utils"
import { Button } from "@src/components/ui"
interface CommandExecutionProps {
executionId?: string
executionId: string
text?: string
}
@ -36,10 +36,6 @@ export const CommandExecution = ({ executionId, text }: CommandExecutionProps) =
const onMessage = useCallback(
(event: MessageEvent) => {
if (!executionId) {
return
}
const message: ExtensionMessage = event.data
if (message.type === "commandExecutionStatus") {