mirror of
https://github.com/RooVetGit/Roo-Code.git
synced 2026-09-07 08:26:51 +00:00
Fix #5179: Add timeout to shell execution complete event
- Add timeout mechanism to shellExecutionComplete promise in TerminalProcess - Prevents indefinite hanging when VSCode's onDidEndTerminalShellExecution event doesn't fire - Common issue on Mac systems where commands complete but event is not emitted - Assumes success (exitCode: 0) after timeout to allow execution to proceed - Add comprehensive test coverage for timeout scenario - Uses existing shell integration timeout configuration
This commit is contained in:
parent
3a8ba27615
commit
fd95eb9962
2 changed files with 58 additions and 1 deletions
|
|
@ -101,7 +101,18 @@ export class TerminalProcess extends BaseTerminalProcess {
|
|||
|
||||
// Create promise that resolves when shell execution completes for this terminal
|
||||
const shellExecutionComplete = new Promise<ExitCodeDetails>((resolve) => {
|
||||
this.once("shell_execution_complete", (details: ExitCodeDetails) => resolve(details))
|
||||
const timeoutId = setTimeout(() => {
|
||||
console.warn(
|
||||
"[TerminalProcess] Shell execution complete event not received within timeout, assuming success. This may indicate a VSCode shell integration issue on this platform.",
|
||||
)
|
||||
// Assume success if we don't get the event (common on Mac)
|
||||
resolve({ exitCode: 0 })
|
||||
}, Terminal.getShellIntegrationTimeout())
|
||||
|
||||
this.once("shell_execution_complete", (details: ExitCodeDetails) => {
|
||||
clearTimeout(timeoutId)
|
||||
resolve(details)
|
||||
})
|
||||
})
|
||||
|
||||
// Execute command
|
||||
|
|
|
|||
|
|
@ -165,6 +165,52 @@ describe("TerminalProcess", () => {
|
|||
await completePromise
|
||||
expect(terminalProcess.isHot).toBe(false)
|
||||
})
|
||||
|
||||
it("handles missing shell_execution_complete event with timeout", async () => {
|
||||
// Temporarily suppress the expected console.warn for this test
|
||||
const consoleWarnSpy = vi.spyOn(console, "warn").mockImplementation(() => {})
|
||||
|
||||
let completedOutput: string | undefined
|
||||
|
||||
terminalProcess.on("completed", (output) => {
|
||||
completedOutput = output
|
||||
})
|
||||
|
||||
// Mock stream data with shell integration sequences but NO shell_execution_complete event
|
||||
mockStream = (async function* () {
|
||||
yield "\x1b]633;C\x07" // Command start sequence
|
||||
yield "Command output\n"
|
||||
yield "More output"
|
||||
yield "\x1b]633;D\x07" // Command end sequence
|
||||
// NOTE: We intentionally do NOT emit "shell_execution_complete" to simulate the Mac issue
|
||||
})()
|
||||
|
||||
mockTerminal.shellIntegration.executeCommand.mockReturnValue({
|
||||
read: vi.fn().mockReturnValue(mockStream),
|
||||
})
|
||||
|
||||
// Set a very short timeout for testing (override the default)
|
||||
vi.spyOn(Terminal, "getShellIntegrationTimeout").mockReturnValue(100)
|
||||
|
||||
const runPromise = terminalProcess.run("test command")
|
||||
terminalProcess.emit("stream_available", mockStream)
|
||||
|
||||
// Wait for the command to complete via timeout
|
||||
await runPromise
|
||||
|
||||
// Verify the command completed successfully despite missing event
|
||||
expect(completedOutput).toBe("Command output\nMore output")
|
||||
expect(terminalProcess.isHot).toBe(false)
|
||||
|
||||
// Verify warning was logged
|
||||
expect(consoleWarnSpy).toHaveBeenCalledWith(
|
||||
"[TerminalProcess] Shell execution complete event not received within timeout, assuming success. This may indicate a VSCode shell integration issue on this platform.",
|
||||
)
|
||||
|
||||
// Restore mocks
|
||||
consoleWarnSpy.mockRestore()
|
||||
vi.restoreAllMocks()
|
||||
})
|
||||
})
|
||||
|
||||
describe("continue", () => {
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue