mirror of
https://github.com/RooVetGit/Roo-Code.git
synced 2026-08-28 05:27:24 +00:00
fix: webview terminal output processing error (#3028)
This commit is contained in:
parent
4f727142ae
commit
7d75536741
2 changed files with 38 additions and 50 deletions
|
|
@ -149,9 +149,12 @@ export async function executeCommand(
|
|||
const terminalProvider = terminalShellIntegrationDisabled ? "execa" : "vscode"
|
||||
const clineProvider = await cline.providerRef.deref()
|
||||
|
||||
let accumulatedOutput = ""
|
||||
const callbacks: RooTerminalCallbacks = {
|
||||
onLine: async (output: string, process: RooTerminalProcess) => {
|
||||
const status: CommandExecutionStatus = { executionId, status: "output", output }
|
||||
onLine: async (lines: string, process: RooTerminalProcess) => {
|
||||
accumulatedOutput += lines
|
||||
const compressedOutput = Terminal.compressTerminalOutput(accumulatedOutput, terminalOutputLineLimit)
|
||||
const status: CommandExecutionStatus = { executionId, status: "output", output: compressedOutput }
|
||||
clineProvider?.postMessageToWebview({ type: "commandExecutionStatus", text: JSON.stringify(status) })
|
||||
|
||||
if (runInBackground) {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
import { HTMLAttributes, useCallback, useEffect, useMemo, useState } from "react"
|
||||
import { useCallback, useState, memo } from "react"
|
||||
import { useEvent } from "react-use"
|
||||
import { Virtuoso } from "react-virtuoso"
|
||||
import { ChevronDown, Skull } from "lucide-react"
|
||||
|
||||
import { CommandExecutionStatus, commandExecutionStatusSchema } from "@roo/schemas"
|
||||
|
|
@ -19,6 +18,17 @@ interface CommandExecutionProps {
|
|||
text?: string
|
||||
}
|
||||
|
||||
const parseCommandAndOutput = (text: string) => {
|
||||
const index = text.indexOf(COMMAND_OUTPUT_STRING)
|
||||
if (index === -1) {
|
||||
return { command: text, output: "" }
|
||||
}
|
||||
return {
|
||||
command: text.slice(0, index),
|
||||
output: text.slice(index + COMMAND_OUTPUT_STRING.length),
|
||||
}
|
||||
}
|
||||
|
||||
export const CommandExecution = ({ executionId, text }: CommandExecutionProps) => {
|
||||
const { terminalShellIntegrationDisabled = false } = useExtensionState()
|
||||
|
||||
|
|
@ -27,13 +37,11 @@ export const CommandExecution = ({ executionId, text }: CommandExecutionProps) =
|
|||
const [isExpanded, setIsExpanded] = useState(terminalShellIntegrationDisabled)
|
||||
|
||||
const [status, setStatus] = useState<CommandExecutionStatus | null>(null)
|
||||
const [output, setOutput] = useState("")
|
||||
const [command, setCommand] = useState(text)
|
||||
|
||||
const lines = useMemo(
|
||||
() => [`$ ${command}`, ...output.split("\n").filter((line) => line.trim() !== "")],
|
||||
[output, command],
|
||||
)
|
||||
const { command: initialCommand, output: initialOutput } = text
|
||||
? parseCommandAndOutput(text)
|
||||
: { command: "", output: "" }
|
||||
const [output, setOutput] = useState(initialOutput)
|
||||
const [command, setCommand] = useState(initialCommand)
|
||||
|
||||
const onMessage = useCallback(
|
||||
(event: MessageEvent) => {
|
||||
|
|
@ -55,7 +63,7 @@ export const CommandExecution = ({ executionId, text }: CommandExecutionProps) =
|
|||
setStatus(data)
|
||||
break
|
||||
case "output":
|
||||
setOutput((output) => output + data.output)
|
||||
setOutput(data.output)
|
||||
break
|
||||
case "fallback":
|
||||
setIsExpanded(true)
|
||||
|
|
@ -72,22 +80,9 @@ export const CommandExecution = ({ executionId, text }: CommandExecutionProps) =
|
|||
|
||||
useEvent("message", onMessage)
|
||||
|
||||
useEffect(() => {
|
||||
if (!status && text) {
|
||||
const index = text.indexOf(COMMAND_OUTPUT_STRING)
|
||||
|
||||
if (index === -1) {
|
||||
setCommand(text)
|
||||
} else {
|
||||
setCommand(text.slice(0, index))
|
||||
setOutput(text.slice(index + COMMAND_OUTPUT_STRING.length))
|
||||
}
|
||||
}
|
||||
}, [status, text])
|
||||
|
||||
return (
|
||||
<div className="w-full bg-vscode-editor-background border border-vscode-border rounded-xs p-2">
|
||||
<CodeBlock source={command} language="shell" />
|
||||
<CodeBlock source={text ? parseCommandAndOutput(text).command : command} language="shell" />
|
||||
<div className="flex flex-row items-center justify-between gap-2 px-1">
|
||||
<div className="flex flex-row items-center gap-1">
|
||||
{status?.status === "started" && (
|
||||
|
|
@ -116,7 +111,7 @@ export const CommandExecution = ({ executionId, text }: CommandExecutionProps) =
|
|||
<div className="whitespace-nowrap">Exited ({status.exitCode})</div>
|
||||
</div>
|
||||
)}
|
||||
{lines.length > 0 && (
|
||||
{output.length > 0 && (
|
||||
<Button variant="ghost" size="icon" onClick={() => setIsExpanded(!isExpanded)}>
|
||||
<ChevronDown
|
||||
className={cn("size-4 transition-transform duration-300", {
|
||||
|
|
@ -127,31 +122,21 @@ export const CommandExecution = ({ executionId, text }: CommandExecutionProps) =
|
|||
)}
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className={cn("mt-1 pt-1 border-t border-border/25", { hidden: !isExpanded })}
|
||||
style={{ height: Math.min((lines.length + 1) * 16, 200) }}>
|
||||
{lines.length > 0 && (
|
||||
<Virtuoso
|
||||
className="h-full"
|
||||
totalCount={lines.length}
|
||||
itemContent={(i) => <Line className="text-sm">{lines[i]}</Line>}
|
||||
followOutput="auto"
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
<MemoizedOutputContainer isExpanded={isExpanded} output={output} />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
type LineProps = HTMLAttributes<HTMLDivElement>
|
||||
|
||||
const Line = ({ className, ...props }: LineProps) => {
|
||||
return (
|
||||
<div
|
||||
className={cn("font-mono text-vscode-editor-foreground whitespace-pre-wrap break-words", className)}
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
CommandExecution.displayName = "CommandExecution"
|
||||
|
||||
const OutputContainer = ({ isExpanded, output }: { isExpanded: boolean; output: string }) => (
|
||||
<div
|
||||
className={cn("mt-1 pt-1 border-t border-border/25 overflow-hidden transition-[max-height] duration-300", {
|
||||
"max-h-0": !isExpanded,
|
||||
"max-h-[100%]": isExpanded,
|
||||
})}>
|
||||
{output.length > 0 && <CodeBlock source={output} language="log" />}
|
||||
</div>
|
||||
)
|
||||
|
||||
const MemoizedOutputContainer = memo(OutputContainer)
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue