fix: Re-create workflow terminal when closed
Issue [VS Code] Closing Duo's terminal prevents tool ... (#2048 - closed)
Description
This change improves how the terminal manager handles terminals that get closed by users. Previously, if someone manually closed a terminal window, the system would still think it existed and try to reuse it, which could cause errors.
The update adds a listener that watches for when terminals are closed and automatically removes them from the internal tracking system. This means when a user closes a terminal and then runs another command with the same workflow, the system will create a fresh terminal instead of trying to use the closed one.
The code also switches from using a simple object to a Map for better terminal tracking, and consolidates all cleanup operations into a single disposal system for more reliable resource management.
Related Issues
Resolves #[issue_number]
How has this been tested?
-
If src/browserorsrc/commonhas been modified, please consider interoperability with the Web IDE. See Running the Extension in WebIDE. -
Consider an end-to-end test for significant new features that aren't covered by integration tests.
As usual, it's challenging to reproduce bugs that are triggered by the non-deterministic responses of agents. There are two ways of reproducing this bug:
- Come up with a prompt that makes the agentic tool two execute two terminal commands.
- Apply the following patch that simulates the execution of two commands in a time frame:
-
Apply the following patch
diff --git a/src/common/duo_workflow/terminal_manager.ts b/src/common/duo_workflow/terminal_manager.ts index 51fc756b..ac56f89b 100644 --- a/src/common/duo_workflow/terminal_manager.ts +++ b/src/common/duo_workflow/terminal_manager.ts @@ -20,6 +20,14 @@ export class TerminalManager implements Disposable { return this.#executeCommand(workflowId, command, args); }, ); + + setTimeout(() => { + this.#executeCommand('123', 'ls', ['$(pwd)']).catch(log.error); + }, 5000); + + setTimeout(() => { + this.#executeCommand('123', 'echo', ['Hello!']).catch(log.error); + }, 10000); } async #executeCommand(workflowId: string, command: string, args: string[]) { -
Start the extension. You should see the same behavior demonstrated in the videos below.
-
Screenshots (if appropriate)
| Before | After |
|---|---|
| before_fix.mov | after_fix.mov |
What CHANGELOG entry will this MR create?
-
fix:Bug fix fixes - a user-facing issue in production - included in changelog -
feature:New feature - a user-facing change which adds functionality - included in changelog -
BREAKING CHANGE:(fix or feature that would cause existing functionality to change) - should bump major version, mentioned in the changelog -
None - other non-user-facing changes