This commit fixes an issue where subtasks weren't properly reporting back to parent tasks when cancelled and resumed. Previously, when a subtask was cancelled and a new task was started with the same message, the parent task would incorrectly resume, causing unexpected behavior.
The fix:
1. Stores parent-child relationship information before cancelling a task
2. Restores this relationship after task reinitialization
3. Ensures parent tasks only resume when explicitly instructed to do so
This approach maintains the correct task hierarchy throughout the cancellation and resumption process, preventing parent tasks from automatically resuming when unrelated tasks with similar messages are started.
Fix issue where background processes (like compilers) couldn't broadcast their
output to new tasks after the launching task was closed. Previously commit
851a4cd prevented terminals from responding to any task except the one that
started them.
The fix allows background terminals (taskId undefined) to act as broadcast
sources that can update any task through getEnvironmentDetails, while still
maintaining proper isolation for task-specific terminals. This enables common
workflows where:
1. A task launches a background compiler
2. That task is closed and a new task is started
3. The new task can still receive compiler errors when making changes
This gives us the best of both worlds:
- Task isolation: Active tasks only see their own terminal output
- Background broadcasting: Background processes can inform any task that needs
their output
Signed-off-by: Eric Wheeler <roo-code@z.ewheeler.org>
Add Terminal.compressTerminalOutput static method to apply run-length encoding
before truncating terminal output. This significantly reduces output size for
repeated lines while maintaining readability.
- Add compressTerminalOutput static method to Terminal class
- Replace all truncateOutput calls with Terminal.compressTerminalOutput
- Import required functions from extract-text
Test program demonstrating compression:
```python
def generate_repeats():
patterns = [
("A\n", 10), # 10 lines
("AA\n", 100), # 100 lines
("AAA\n", 1000), # 1K lines
("AAAA\n", 10000), # 10K lines
("AAAAA\n", 100000), # 100K lines
("AAAAAA\n", 1000000) # 1M lines
]
for text, count in patterns:
print(text * count, end="")
```
Sample output showing compression:
```
A
A
A
A
A
A
A
A
A
A
AA
<previous line repeated 99 additional times>
AAA
<previous line repeated 999 additional times>
AAAA
<previous line repeated 9999 additional times>
AAAAA
<previous line repeated 99999 additional times>
AAAAAA
<previous line repeated 999999 additional times>
```
Signed-off-by: Eric Wheeler <roo-code@z.ewheeler.org>
Optimize terminal output handling to reduce memory pressure by:
- Remove continuous result accumulation during line processing
- Only store the same final output from the "completed" event that came from TerminalProcess
Also:
- Add clear error messages for undefined exit details
Signed-off-by: Eric Wheeler <roo-code@z.ewheeler.org>
Apply terminalOutputLineLimit to command output lines as they are received,
rather than only at the end of command execution. Also apply the limit to
terminal output shown in environment details.
This ensures consistent output truncation behavior across all terminal
output paths, preventing potential memory issues from large outputs.
Signed-off-by: Eric Wheeler <roo-code@z.ewheeler.org>
When a terminal command completes with an undefined exit code:
- Add explicit handling for undefined exit code case
- Include clear message in output that exit code is undefined
- Notify user to help diagnose potential terminal issues
This helps identify and debug cases where the terminal process
completes but the exit code is not properly captured.
Signed-off-by: Eric Wheeler <roo-code@z.ewheeler.org>
Add descriptive messages to shell integration failures to help users
understand and resolve integration issues more effectively. This improves
the debugging experience by providing specific details about why shell
integration failed.
- Add message parameter to no_shell_integration event
- Update UI to display specific error messages
- Update troubleshooting documentation link
Signed-off-by: Eric Wheeler <roo-code@z.ewheeler.org>
As pointed out by @cte, passing and checking terminal IDs in events is
unnecessary since a TerminalProcess instance can never be associated with a
different Terminal instance. The event handling is already properly scoped
to the specific TerminalProcess instance.
- Remove terminal ID parameter from shell_execution_complete event
- Remove terminal ID parameter from stream_available event
- Update all event handlers to remove ID checks
- Update all test cases to match new event signatures
Signed-off-by: Eric Wheeler <roo-code@z.ewheeler.org>
Use a string instead of array for terminal output since it is faster
than splitting and joining. Also note that 'line' events may contain
multiple lines, so concatenating directly is more efficient.
Signed-off-by: Eric Wheeler <roo-code@z.ewheeler.org>
Notice: this comment required updating system test snapshots with new
execute_command XML schema feature `cwd`
- Add required cwd parameter to Terminal constructor calls in tests
- Use './' for TerminalProcess.test.ts
- Use '/test/path' for TerminalProcessExec.test.ts to match shellIntegration.cwd
Signed-off-by: Eric Wheeler <roo-code@z.ewheeler.org>
Forcing terminals to `cd` back to the project directory was disrupting
shell state without providing feedback to the model. This caused issues
with capturing output from subsequent commands, particularly with custom
shell prompts.
Instead of forcing directory changes, we now track terminal state
through shell integration with a fallback mechanism, and provide
explicit working directory feedback to the model. This allows terminals
to maintain their natural state while ensuring accurate command output
capture.
Changes:
- Remove forced `cd` commands that were disrupting terminal state
- Add getCurrentWorkingDirectory() method with shell integration fallback
- Add customCwd parameter to executeCommandTool for flexible directory handling
- Add requiredCwd parameter to control terminal selection behavior
- Refactor terminal selection logic for more consistent state management
- Modify environment details to include terminal working directory feedback
- Update XML schema to include optional working directory parameter in execute_command
The environment details now provide explicit feedback about terminal state:
Command executed in terminal N from '/path/to/dir'. Exit code: 0
Fixes: #1388
Signed-off-by: Eric Wheeler <roo-code@z.ewheeler.org>
These changes ensure proper isolation by preventing terminal process
output from one Cline task appearing in another task's context when
multiple Cline instances are running in parallel.
- Add taskId parameter to TerminalRegistry.getTerminals to filter terminals by Cline task ID
- Update Cline.ts to use taskId-filtered terminals
Signed-off-by: Eric Wheeler <roo-code@z.ewheeler.org>
Fix an issue where background running terminals that complete their
execution do not report the final output of their command. Previously,
output was reported while the command was active, but after termination
the remaining output was not provided within the 'inactive terminals'
section of environment details.
- Implement terminal process queue system to track completed processes
- Store command and output retrieval state per process
- Add helper methods to manage the process queue efficiently
- Update getEnvironmentDetails to properly display output from completed processes
Signed-off-by: Eric Wheeler <roo-code@z.ewheeler.org>
This change improves terminal management by tracking which task owns
each terminal and prioritizing terminal selection based on task
ownership.
Terminal selection now follows a priority order:
1. First try to find a terminal already assigned to this task with matching directory
2. If not found, try to find any available terminal with matching directory
3. If still not found, try to find any non-busy terminal
4. Only create a new terminal as a last resort
When a task ends, all terminals associated with it are released for use
by other tasks.
This prevents the issue where multiple Roo task instances could
inadvertently share terminals, which could lead to confusion when
terminal output from one task appears in another task's context.
Signed-off-by: Eric Wheeler <roo-code@z.ewheeler.org>
Move terminal lifecycle management to improve organization:
1. Move runCommand to Terminal class
2. Move getOrCreateTerminal to TerminalRegistry
Signed-off-by: Eric Wheeler <roo-code@z.ewheeler.org>
Move terminal state access from TerminalManager to TerminalRegistry to establish
a clear hierarchical relationship between components. This change centralizes
terminal management in TerminalRegistry and eliminates duplicate state tracking
in TerminalManager.
The hierarchy flows from TerminalRegistry (managing all terminals) to Terminal
(encapsulating a terminal instance) to TerminalProcess (running within a terminal).
Key changes:
- Remove `processes` map from TerminalManager
- Add static getUnretrievedOutput and isProcessHot methods to TerminalRegistry, which manages all terminals globally
Test updates:
- Modify test setup to create Terminal instances
- Remove processes map usage from tests
- Update process creation and command execution flow in tests
Signed-off-by: Eric Wheeler <roo-code@z.ewheeler.org>
This commit moves the interpretExitCode method from TerminalManager to
TerminalProcess class, as part of the terminal refactoring effort. The
method is responsible for translating exit codes into detailed results,
including signal information.
Changes include:
- Moved interpretExitCode method to TerminalProcess class
- Updated imports in TerminalManager and Cline to reference
ExitCodeDetails from TerminalProcess
- Added findTerminalIdByVscodeTerminal helper method in TerminalManager
- Added comprehensive unit tests for interpretExitCode in
TerminalProcess
- Tests cover undefined exit codes, normal exit codes (0-127), and
signal exit codes (128+)
This change improves code organization by placing the exit code
interpretation logic closer to where it's primarily used, in the
TerminalProcess class.
Signed-off-by: Eric Wheeler <roo-code@z.ewheeler.org>
This reverts commit 7eee3e0878.
Middle-out truncation is a really great feature and it should still be
implemented, however it unnecessarily interferes with #1365 because it
hooked into the low-level chunk management that comes directly from VSCE
shell integration.
The best place to hook OutputBuilder is as follows depending on the
state of terminal interaction:
1. Foreground terminals:
Cline.ts:
executeCommandTool(...) {
process.on("line", (line) => {
lines.push(line)
...
}
}
2. For background terminals: hook in at the point that getUnretrievedOutput is consumed for active or
inactive terminals in Cline.ts:getEnvironmentDetails()
Please note:
The Terminal classes are very sensitive to change, partially because of
the complicated way that shell integration works with VSCE, and
partially because of the way that Cline interacts with the Terminal*
class abstractions that make VSCE shell integration easier to work with.
At the point that PR#1365 is merged, it is unlikely that any Terminal*
classes will need to be modified substantially. Generally speaking, we
should think of this is a stable interface and minimize changes.
Reverts: #1390