Просмотр исходного кода

Fix command display in the approval required case (#3636)

Chris Estreich 7 месяцев назад
Родитель
Сommit
95da34d3da

+ 5 - 0
.changeset/seven-ghosts-tan.md

@@ -0,0 +1,5 @@
+---
+"roo-cline": patch
+---
+
+Fix command display in the approval required case

+ 55 - 4
webview-ui/package-lock.json

@@ -50,6 +50,7 @@
 				"remove-markdown": "^0.6.0",
 				"shell-quote": "^1.8.2",
 				"shiki": "^3.2.1",
+				"source-map": "^0.7.4",
 				"styled-components": "^6.1.13",
 				"tailwind-merge": "^2.6.0",
 				"tailwindcss": "^4.0.0",
@@ -9373,6 +9374,15 @@
 				"node": ">=8.0.0"
 			}
 		},
+		"node_modules/css-tree/node_modules/source-map": {
+			"version": "0.6.1",
+			"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+			"integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+			"license": "BSD-3-Clause",
+			"engines": {
+				"node": ">=0.10.0"
+			}
+		},
 		"node_modules/css.escape": {
 			"version": "1.5.1",
 			"resolved": "https://registry.npmjs.org/css.escape/-/css.escape-1.5.1.tgz",
@@ -10607,6 +10617,17 @@
 				"source-map": "~0.6.1"
 			}
 		},
+		"node_modules/escodegen/node_modules/source-map": {
+			"version": "0.6.1",
+			"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+			"integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+			"dev": true,
+			"license": "BSD-3-Clause",
+			"optional": true,
+			"engines": {
+				"node": ">=0.10.0"
+			}
+		},
 		"node_modules/eslint": {
 			"version": "8.57.1",
 			"resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.1.tgz",
@@ -13700,6 +13721,16 @@
 				"node": ">=10"
 			}
 		},
+		"node_modules/istanbul-lib-source-maps/node_modules/source-map": {
+			"version": "0.6.1",
+			"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+			"integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+			"dev": true,
+			"license": "BSD-3-Clause",
+			"engines": {
+				"node": ">=0.10.0"
+			}
+		},
 		"node_modules/istanbul-reports": {
 			"version": "3.1.7",
 			"resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.7.tgz",
@@ -19023,6 +19054,16 @@
 				"node": ">= 4"
 			}
 		},
+		"node_modules/recast/node_modules/source-map": {
+			"version": "0.6.1",
+			"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+			"integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+			"dev": true,
+			"license": "BSD-3-Clause",
+			"engines": {
+				"node": ">=0.10.0"
+			}
+		},
 		"node_modules/redent": {
 			"version": "3.0.0",
 			"resolved": "https://registry.npmjs.org/redent/-/redent-3.0.0.tgz",
@@ -20043,12 +20084,12 @@
 			}
 		},
 		"node_modules/source-map": {
-			"version": "0.6.1",
-			"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
-			"integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+			"version": "0.7.4",
+			"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz",
+			"integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==",
 			"license": "BSD-3-Clause",
 			"engines": {
-				"node": ">=0.10.0"
+				"node": ">= 8"
 			}
 		},
 		"node_modules/source-map-js": {
@@ -20071,6 +20112,16 @@
 				"source-map": "^0.6.0"
 			}
 		},
+		"node_modules/source-map-support/node_modules/source-map": {
+			"version": "0.6.1",
+			"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+			"integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+			"dev": true,
+			"license": "BSD-3-Clause",
+			"engines": {
+				"node": ">=0.10.0"
+			}
+		},
 		"node_modules/space-separated-tokens": {
 			"version": "1.1.5",
 			"resolved": "https://registry.npmjs.org/space-separated-tokens/-/space-separated-tokens-1.1.5.tgz",

+ 14 - 11
webview-ui/src/components/chat/CommandExecution.tsx

@@ -23,19 +23,19 @@ interface CommandExecutionProps {
 export const CommandExecution = ({ executionId, text, icon, title }: CommandExecutionProps) => {
 	const { terminalShellIntegrationDisabled = false } = useExtensionState()
 
+	const { command, output: parsedOutput } = useMemo(() => parseCommandAndOutput(text), [text])
+
 	// If we aren't opening the VSCode terminal for this command then we default
 	// to expanding the command execution output.
 	const [isExpanded, setIsExpanded] = useState(terminalShellIntegrationDisabled)
-
-	const { command: initialCommand, output: initialOutput } = useMemo(
-		() => (text ? parseCommandAndOutput(text) : { command: "", output: "" }),
-		[text],
-	)
-
-	const [output, setOutput] = useState(initialOutput)
-	const [command, setCommand] = useState(initialCommand)
+	const [streamingOutput, setStreamingOutput] = useState("")
 	const [status, setStatus] = useState<CommandExecutionStatus | null>(null)
 
+	// The command's output can either come from the text associated with the
+	// task message (this is the case for completed commands) or from the
+	// streaming output (this is the case for running commands).
+	const output = streamingOutput || parsedOutput
+
 	const onMessage = useCallback(
 		(event: MessageEvent) => {
 			const message: ExtensionMessage = event.data
@@ -52,11 +52,10 @@ export const CommandExecution = ({ executionId, text, icon, title }: CommandExec
 
 					switch (data.status) {
 						case "started":
-							setCommand(data.command)
 							setStatus(data)
 							break
 						case "output":
-							setOutput(data.output)
+							setStreamingOutput(data.output)
 							break
 						case "fallback":
 							setIsExpanded(true)
@@ -143,7 +142,11 @@ const OutputContainerInternal = ({ isExpanded, output }: { isExpanded: boolean;
 
 const OutputContainer = memo(OutputContainerInternal)
 
-const parseCommandAndOutput = (text: string) => {
+const parseCommandAndOutput = (text: string | undefined) => {
+	if (!text) {
+		return { command: "", output: "" }
+	}
+
 	const index = text.indexOf(COMMAND_OUTPUT_STRING)
 
 	if (index === -1) {