Skip to content

fixing the problem where roo thinks a multiline terminal command is hanging after execution is done #7123

@cissna

Description

@cissna

What specific problem does this solve?

#4384

Additional context (optional)

No response

Roo Code Task Links (Optional)

No response

Request checklist

  • I've searched existing Issues and Discussions for duplicates
  • This describes a specific problem with clear impact and context

Interested in implementing this?

  • Yes, I'd like to help implement this feature

Implementation requirements

  • I understand this needs approval before implementation begins

How should this be solved? (REQUIRED if contributing, optional otherwise)

1. Desired Behavior

When the AI generates a command that spans multiple lines, Roo should intelligently convert it into a single, functionally identical line before execution. The end user should experience the exact same outcome as if they had pasted the original multiline command directly into a terminal, with the exception of unconvertible cases like Here Documents.

2. General Approach

The core of this feature is a pre-execution parsing and transformation step. Roo will analyze the complete, AI-generated command block and apply a series of shell-specific rules to flatten it. This process must be aware of the user's target shell (POSIX-like vs. PowerShell) to apply the correct syntax.

The transformation will follow these general principles:

  1. Concatenate Simple Continuations: Lines explicitly continued with an escape character (\ or ```) or an operator (|, `&&`, `||`) will be joined together.

  2. Flatten Compound Commands: For control structures like loops, conditionals, and command groupings ((...), {...}), required newlines will be replaced with the appropriate command separator (almost always a semicolon ;).

  3. Convert Multiline Strings: String literals that span multiple lines will be converted into a valid single-line equivalent. This involves replacing physical newlines with their escaped counterparts (e.g., \n or ``n`). The most complex part of this is safely handling strictly literal single-quoted strings by converting them to a type that supports escape sequences.

  4. Identify and Bypass Unconvertible Cases: If the command uses a structure that cannot be converted to a single line (e.g., a Here Document), the transformation will be aborted, and the command will be executed in its original multiline form.

3. Platform-Specific Implementation

POSIX Shells (bash, zsh)

These shells share a common syntax for multiline commands. The transformation logic will proceed as follows:

  • Continuation Characters: If a line ends with a backslash (\), the backslash and newline are removed to join the lines. If a line ends with a pipe (|) or a logical operator (&&, ||), the newline character is simply removed.

  • Compound Commands: For structures like if...fi, for...do...done, while...do...done, and command groupings in parentheses (...) or braces {...}, newlines separating commands within the block will be replaced with a semicolon (;).

  • String Conversion:

    • Double-Quoted ("...") and ANSI-C Quoted ($'...') Strings: Physical newlines within the string will be replaced with the literal escape sequence \n.

    • Single-Quoted ('...') Strings: These are strictly literal and require conversion. A multiline single-quoted string will be transformed into an ANSI-C quoted string ($'...') using the following steps:

      1. Prepend a $ to the opening '.

      2. Within the string content, replace every literal backslash \ with an escaped backslash \\.

      3. Replace every physical newline with the literal escape sequence \n.

Note on fish Shell

The fish shell follows the same general principles as bash and zsh but uses different keywords for its compound commands. The logic for semicolon replacement is identical, but the parser must recognize that blocks are terminated with the end keyword (e.g., if...end, for...end) instead of fi or done.

Windows PowerShell (pwsh)

PowerShell has a distinct syntax that requires its own transformation logic.

  • Continuation Characters: If a line ends with a backtick (```), the backtick and newline are removed to join the lines. PowerShell also implicitly continues a line if it ends with a pipe (|), a comma (`,`), or an operator (e.g., `-and`, `+`, `-eq`). In these cases, the newline character is simply removed.

  • Compound Commands: For script blocks enclosed in braces ({...}) and sub-expressions in parentheses (...), such as in foreach loops or if statements, newlines separating commands will be replaced with a semicolon (;).

  • String Conversion:

    • Double-Quoted ("...") Strings: Physical newlines will be replaced with the literal escape sequence ``n`.

    • Single-Quoted ('...') Strings: These are strictly literal and must be safely converted to an expandable, double-quoted string. This is a sensitive operation to prevent accidental variable expansion.

      1. First, process the raw string content that was inside the single quotes. Replace any escaped single quotes ('') with a single literal apostrophe (').

      2. Escape all characters that have special meaning inside a PowerShell double-quoted string:

        • $ becomes ``$`

        • ``` becomes ` ``

        • " becomes ``"`

      3. Replace every physical newline with the literal escape sequence ``n`.

      4. Finally, wrap the fully escaped and converted content in double quotes (").

How will we know it works? (Acceptance Criteria - REQUIRED if contributing, optional otherwise)

This PR must include a comprehensive testing suite for a huge number of weird terminal command formatting edge cases, as there are many, and it has to do so by emulating unix,

with a good tesitng suite, it should be easy to verify success — you just check that before and after this change, the terminal command executes in the same way.

Technical considerations (REQUIRED if contributing, optional otherwise)

We should consider at what stage of terminal execution this change is applied. which of these 3 is it?

  • editing roo's output directly to change the context we move forward with?
  • not doing the above, but showing the terminal command as the edited version in roo's UI
  • showing the original command roo outputted in its UI, but then executing the one-line-ified version. [My personal recommendation]

Trade-offs and risks (REQUIRED if contributing, optional otherwise)

Minimal upside and VERY easy for a bug to be missed (hopefully good testing mitigates this risk). I'm also not sure if this is necessary on windows, as i'm on macos, so it could be overcomplicating things for them.

Metadata

Metadata

Assignees

Labels

Issue - In ProgressSomeone is actively working on this. Should link to a PR soon.bugSomething isn't workingenhancementNew feature or requestproposal

Type

No type

Projects

Status

Issue [In Progress]

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions