From 1c5dca9346929c64b7b54c4bb4b8de841c8b8fab Mon Sep 17 00:00:00 2001 From: Saoud Rizwan <7799382+saoudrizwan@users.noreply.github.com> Date: Sat, 5 Oct 2024 03:26:47 -0400 Subject: [PATCH] Send command output for attempt completion commands --- src/core/ClaudeDev.ts | 53 ++++++++++++++++++++++++++----------------- 1 file changed, 32 insertions(+), 21 deletions(-) diff --git a/src/core/ClaudeDev.ts b/src/core/ClaudeDev.ts index 31ed4a5..428379b 100644 --- a/src/core/ClaudeDev.ts +++ b/src/core/ClaudeDev.ts @@ -623,10 +623,7 @@ export class ClaudeDev { // Tools - async executeCommandTool( - command: string, - returnEmptyStringOnSuccess: boolean = false - ): Promise<[boolean, ToolResponse]> { + async executeCommandTool(command: string): Promise<[boolean, ToolResponse]> { const terminalInfo = await this.terminalManager.getOrCreateTerminal(cwd) terminalInfo.terminal.show() // weird visual bug when creating new terminals (even manually) where there's an empty space at the top. const process = this.terminalManager.runCommand(terminalInfo, command) @@ -691,10 +688,6 @@ export class ClaudeDev { ] } - // for attemptCompletion, we don't want to return the command output - if (returnEmptyStringOnSuccess) { - return [false, ""] - } if (completed) { return [false, `Command executed.${result.length > 0 ? `\nOutput:\n${result}` : ""}`] } else { @@ -1000,6 +993,9 @@ export class ClaudeDev { // it's important to note how this function works, you can't make the assumption that the block.partial conditional will always be called since it may immediately get complete, non-partial data. So this part of the logic will always be called. // in other words, you must always repeat the block.partial logic here if (!this.diffViewProvider.isEditing) { + // show gui message before showing edit animation + const partialMessage = JSON.stringify(sharedMessageProps) + await this.ask("tool", partialMessage, true).catch(() => {}) // sending true for partial even though it's not a partial, this shows the edit row before the content is streamed into the editor await this.diffViewProvider.open(relPath) } await this.diffViewProvider.update(newContent, true) @@ -1339,7 +1335,7 @@ export class ClaudeDev { } const [userRejected, result] = await this.executeCommandTool(command) if (userRejected) { - this.didRejectTool = true // test whats going on here + this.didRejectTool = true } pushToolResult(result) break @@ -1450,6 +1446,7 @@ export class ClaudeDev { } this.consecutiveMistakeCount = 0 + let commandResult: ToolResponse | undefined if (command) { if (lastMessage && lastMessage.ask !== "command") { // havent sent a command message yet so first send completion_result then command @@ -1461,14 +1458,14 @@ export class ClaudeDev { if (!didApprove) { break } - const [userRejected, commandResult] = await this.executeCommandTool(command!, true) - if (commandResult) { - if (userRejected) { - this.didRejectTool = true // test whats going on here - } - pushToolResult(commandResult) + const [userRejected, execCommandResult] = await this.executeCommandTool(command!) + if (userRejected) { + this.didRejectTool = true + pushToolResult(execCommandResult) break } + // user didn't reject, but the command may have output + commandResult = execCommandResult } else { await this.say("completion_result", result, undefined, false) } @@ -1480,12 +1477,26 @@ export class ClaudeDev { break } await this.say("user_feedback", text ?? "", images) - pushToolResult( - formatResponse.toolResult( - `The user has provided feedback on the results. Consider their input to continue the task, and then attempt completion again.\n\n${text}\n`, - images - ) - ) + + const toolResults: (Anthropic.TextBlockParam | Anthropic.ImageBlockParam)[] = [] + if (commandResult) { + if (typeof commandResult === "string") { + toolResults.push({ type: "text", text: commandResult }) + } else if (Array.isArray(commandResult)) { + toolResults.push(...commandResult) + } + } + toolResults.push({ + type: "text", + text: `The user has provided feedback on the results. Consider their input to continue the task, and then attempt completion again.\n\n${text}\n`, + }) + toolResults.push(...formatResponse.imageBlocks(images)) + this.userMessageContent.push({ + type: "text", + text: `${toolDescription()} Result:`, + }) + this.userMessageContent.push(...toolResults) + break } } catch (error) {