From 38d461b784eee2ffafd691d125cfca8196cf971b Mon Sep 17 00:00:00 2001 From: Saoud Rizwan <7799382+saoudrizwan@users.noreply.github.com> Date: Sun, 4 Aug 2024 19:32:45 -0400 Subject: [PATCH] Fix edge case issues when running commands with long outputs or as completion command --- package-lock.json | 16 ++++++++++++++-- package.json | 3 ++- src/ClaudeDev.ts | 9 ++++++++- webview-ui/src/components/ChatView.tsx | 7 +++++++ 4 files changed, 31 insertions(+), 4 deletions(-) diff --git a/package-lock.json b/package-lock.json index b6ab91d..3307102 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,18 +1,19 @@ { "name": "claude-dev", - "version": "1.0.86", + "version": "1.0.91", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "claude-dev", - "version": "1.0.86", + "version": "1.0.91", "license": "MIT", "dependencies": { "@anthropic-ai/bedrock-sdk": "^0.10.2", "@anthropic-ai/sdk": "^0.24.3", "@vscode/codicons": "^0.0.36", "default-shell": "^2.2.0", + "delay": "^6.0.0", "diff": "^5.2.0", "execa": "^9.3.0", "globby": "^14.0.2", @@ -5549,6 +5550,17 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/delay": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/delay/-/delay-6.0.0.tgz", + "integrity": "sha512-2NJozoOHQ4NuZuVIr5CWd0iiLVIRSDepakaovIN+9eIDHEhdCAEvSy2cuf1DCrPPQLvHmbqTHODlhHg8UCy4zw==", + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/delayed-stream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", diff --git a/package.json b/package.json index 53846af..9ffaa53 100644 --- a/package.json +++ b/package.json @@ -127,6 +127,7 @@ "@anthropic-ai/sdk": "^0.24.3", "@vscode/codicons": "^0.0.36", "default-shell": "^2.2.0", + "delay": "^6.0.0", "diff": "^5.2.0", "execa": "^9.3.0", "globby": "^14.0.2", @@ -138,4 +139,4 @@ "tree-sitter-wasms": "^0.1.11", "web-tree-sitter": "^0.22.6" } -} \ No newline at end of file +} diff --git a/src/ClaudeDev.ts b/src/ClaudeDev.ts index 5bf750e..ebc1f26 100644 --- a/src/ClaudeDev.ts +++ b/src/ClaudeDev.ts @@ -19,6 +19,7 @@ import { DEFAULT_MAX_REQUESTS_PER_TASK } from "./shared/Constants" import { ClaudeAsk, ClaudeMessage, ClaudeSay, ClaudeSayTool } from "./shared/ExtensionMessage" import { Tool, ToolName } from "./shared/Tool" import { ClaudeAskResponse } from "./shared/WebviewMessage" +import delay from "delay" const SYSTEM_PROMPT = () => `You are Claude Dev, a highly skilled software developer with extensive knowledge in many programming languages, frameworks, design patterns, and best practices. @@ -676,13 +677,19 @@ export class ClaudeDev { } } catch (e) { if ((e as ExecaError).signal === "SIGINT") { - const line = `\nUser exited command...` + const line = `\nUser terminated process via SIGINT...` await this.say("command_output", line) result += line } else { throw e // if the command was not terminated by user, let outer catch handle it as a real error } } + // Wait for the next event loop tick to ensure all promises from the loop are created + // This is necessary because the non-awaited promises in the loop might not be + // created until the next Node.js event loop cycle. We want to make sure all + // promises are at least created before proceeding, to maintain the correct + // order of messages and avoid potential race conditions. + await delay(0) // for attemptCompletion, we don't want to return the command output if (returnEmptyStringOnSuccess) { return "" diff --git a/webview-ui/src/components/ChatView.tsx b/webview-ui/src/components/ChatView.tsx index 2f98592..e9db13c 100644 --- a/webview-ui/src/components/ChatView.tsx +++ b/webview-ui/src/components/ChatView.tsx @@ -132,6 +132,13 @@ const ChatView = ({ messages, isHidden, vscodeThemeName, showAnnouncement, hideA case "error": break case "api_req_started": + if (claudeAsk === "command_output") { + // if the last ask is a command_output, and we receive an api_req_started, then that means the command has finished and we don't need input from the user anymore (in every other case, the user has to interact with input field or buttons to continue, which does the following automatically) + setInputValue("") + setTextAreaDisabled(true) + setClaudeAsk(undefined) + setEnableButtons(false) + } break case "api_req_finished": break