Skip to content

feat(core): refactor shell execution to use node-pty #6088

Merged
jacob314 merged 8 commits intomainfrom
galzahavi/add/vterminal-shell
Aug 14, 2025
Merged

feat(core): refactor shell execution to use node-pty #6088
jacob314 merged 8 commits intomainfrom
galzahavi/add/vterminal-shell

Conversation

@galz10
Copy link
Copy Markdown
Collaborator

@galz10 galz10 commented Aug 12, 2025

TLDR

This pull request replaces the standard child_process.spawn with node-pty for executing shell commands. This change introduces a pseudo-terminal (pty) that allows for a much more accurate and feature-rich terminal emulation within the Gemini CLI. The primary benefit is the correct handling of complex ANSI escape codes, colors, and cursor movements, which were previously either stripped or not handled correctly.

Dive Deeper

The core of this change is in the ShellExecutionService. Instead of capturing stdout and stderr streams from child_process, we now spawn a pseudo-terminal using node-pty. The output of this pty is then piped into a headless terminal instance from @xterm/headless. This allows us to interpret the raw terminal output stream and get the "rendered" text content, correctly processing complex terminal interactions like cursor movements, screen clearing, and advanced color formatting that a simple strip-ansi call cannot handle.

To ensure the pseudo-terminal behaves as closely as possible to the user's actual terminal, the terminal dimensions (columns and rows) are now detected in the UI layer using a new useTerminalSize hook. These dimensions are then passed down through the tool scheduling layers (useReactToolScheduler, CoreToolScheduler) all the way to the ShellExecutionService when a command is executed.

Since a pty provides a single, unified output stream (just like a real terminal), the distinction between stdout and stderr at the stream handling level has been removed in shellCommandProcessor and ShellExecutionService, simplifying the output processing logic.

Reviewer Test Plan

  1. Setup: Pull this branch and run npm install to fetch the new node-pty and @xterm/headless dependencies. Then, run npm run build.
  2. Basic Commands: Run some basic commands and verify the output is clean and correct.
    • ls -la
    • echo "hello world"
  3. Complex UI Commands: Run commands that are known to produce more complex terminal UIs with colors, progress bars, and overwriting lines.
    • npm run preflight
    • npm install in a project with many dependencies.
    • Run a test suite that uses a "rich" reporter, for example: npx jest --color.
  4. Verification:
    • Confirm that the output is well-formatted and does not contain any raw or garbled ANSI escape codes.
    • Check that colors are displayed correctly (or stripped cleanly if your terminal doesn't support them).
    • Ensure that long-running commands with updating lines (like progress bars) display the final state correctly without showing all the intermediate frames.
  5. Cancellation: Run a long-running command (e.g., sleep 10) and cancel it with Ctrl+C. Verify that the process is terminated correctly.

Testing Matrix

🍏 🪟 🐧
npm run
npx
Docker
Podman - -
Seatbelt - -

Linked issues / bugs

galz10 added 2 commits August 11, 2025 12:07
  This commit refactors the ShellExecutionService to use node-pty and @xterm/headless instead of the native
  child_process.spawn. This change provides a more robust and accurate shell emulation, addressing several
  issues with the previous implementation.

  Key changes:
   - Replaced child_process.spawn with pty.spawn to leverage pseudo-terminals for command execution.
   - Integrated @xterm/headless to correctly parse terminal output, strip ANSI escape codes, and handle complex
     terminal behavior.
   - Unified stdout and stderr into a single, ordered output stream, which simplifies output handling and more
     closely mirrors a real terminal experience.
   - Implemented a promise-based serialization queue for processing data chunks to prevent race conditions
     between text and binary output detection.
   - The ShellTool and UI hooks have been updated to pass terminal dimensions down to the execution service,
     allowing for correctly formatted output from terminal-aware applications.

  This new architecture resolves race conditions, correctly handles binary vs. text data streams, and provides
  a much cleaner and more reliable foundation for shell command execution.
@galz10 galz10 requested a review from a team as a code owner August 12, 2025 22:33
Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Summary of Changes

Hello @galz10, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request significantly refactors the underlying shell execution mechanism by migrating from Node.js's built-in child_process to node-pty. This change improves the reliability and control over spawned shell commands. Additionally, it integrates @xterm/headless to provide advanced terminal output processing, such as automatic ANSI escape code stripping, ensuring cleaner and more readable output. The system now also passes terminal dimensions to shell commands, enabling better adaptation to the display environment. These updates streamline output handling by consolidating stdout and stderr into a single stream, and the necessary changes have been applied across the codebase to support this new architecture.

Highlights

  • Migration to node-pty: The core shell execution mechanism has been refactored to utilize node-pty instead of the native child_process module. This change provides more robust control over spawned processes and their I/O.
  • Enhanced Terminal Output Processing: The @xterm/headless library has been integrated to handle terminal output processing. This includes automatic stripping of ANSI escape codes, ensuring that raw terminal output is cleanly presented as plain text.
  • Terminal Dimension Awareness: The shell execution service now accepts and utilizes terminal dimensions (columns and rows). This allows for more accurate and responsive rendering of shell output, especially for interactive commands or those that adapt to terminal size.
  • Consolidated Output Streams: The internal handling of shell output has been simplified. Instead of separate stdout and stderr streams, all textual output is now consolidated into a single output stream, streamlining data processing and display.
  • System-Wide Integration: Changes have been propagated across various modules, including esbuild configurations, CLI hooks, core tool schedulers, and test suites, to ensure compatibility and proper functioning with the new shell execution architecture.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point in your pull request via creating an issue comment (i.e. comment on the pull request page) using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in issue comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request refactors the shell execution logic to use node-pty instead of child_process, which is a great improvement for emulating a real terminal environment. The changes are mostly well-executed, with updates to dependencies, build configurations, and tests to support this new approach.

However, I've found a critical issue in the implementation of live output streaming. The current logic incorrectly assumes that terminal output is always append-only, which will cause garbled live displays for any command that manipulates the screen, such as those with progress bars or full-screen interfaces. I've provided a set of related comments with suggestions to fix this by sending the full terminal state on each update and having the consumers replace their buffers accordingly.

Once this issue is addressed, the PR will be in excellent shape.

  This commit hardens the ShellExecutionService to prevent crashes from synchronous errors during process spawning and incorporates feedback from a prior code review.

  Previously, if pty.spawn threw an exception (e.g., if the underlying shell executable was not found), the error would not be caught, leading to an unhandled promise
  rejection.

  The pty.spawn call is now wrapped in a try...catch block. If a synchronous error occurs, the service returns a resolved promise with a ShellExecutionResult that
  captures the error, ensuring graceful failure. An accompanying test case has been added to validate this new error handling path, and an obsolete test for the old
  child_process 'error' event has been removed. Minor refactoring was also applied, including removing an unused variable and moving a helper function to the module
  scope.
@galz10 galz10 force-pushed the galzahavi/add/vterminal-shell branch from f140dde to c53a330 Compare August 12, 2025 23:06
@jacob314 jacob314 requested a review from olcan August 12, 2025 23:22
@galz10 galz10 force-pushed the galzahavi/add/vterminal-shell branch 2 times, most recently from ea1308e to 6a9caca Compare August 13, 2025 00:39
@github-actions
Copy link
Copy Markdown

github-actions bot commented Aug 13, 2025

Code Coverage Summary

Package Lines Statements Functions Branches
CLI 73.75% 73.75% 80.11% 81.34%
Core 74.36% 74.36% 74.06% 82.95%
CLI Package - Full Text Report
-------------------|---------|----------|---------|---------|-------------------
File               | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s 
-------------------|---------|----------|---------|---------|-------------------
All files          |   73.75 |    81.34 |   80.11 |   73.75 |                   
 src               |   54.46 |    75.51 |   66.66 |   54.46 |                   
  gemini.tsx       |   31.11 |     62.5 |      50 |   31.11 | ...51-317,327-344 
  ...ractiveCli.ts |   93.22 |    71.42 |     100 |   93.22 | ...,71-73,119,122 
  ...ActiveAuth.ts |     100 |      100 |     100 |     100 |                   
 src/commands      |   94.11 |      100 |      50 |   94.11 |                   
  mcp.ts           |   94.11 |      100 |      50 |   94.11 | 26                
 src/commands/mcp  |   95.49 |    80.43 |    90.9 |   95.49 |                   
  add.ts           |   97.26 |    85.71 |     100 |   97.26 | 109-112,119       
  list.ts          |   90.56 |    80.76 |      80 |   90.56 | ...10-112,137-138 
  remove.ts        |     100 |    66.66 |     100 |     100 | 19-23             
 src/config        |   91.88 |    81.46 |    87.5 |   91.88 |                   
  auth.ts          |     100 |      100 |     100 |     100 |                   
  config.ts        |   97.31 |    89.18 |      70 |   97.31 | ...40,420,570-574 
  extension.ts     |   82.53 |    84.37 |     100 |   82.53 | ...99-103,112-113 
  keyBindings.ts   |     100 |      100 |     100 |     100 |                   
  sandboxConfig.ts |   51.35 |    16.66 |   66.66 |   51.35 | ...43,53-69,74-91 
  settings.ts      |   83.57 |    77.52 |   93.33 |   83.57 | ...91-392,452-453 
  ...ingsSchema.ts |     100 |      100 |     100 |     100 |                   
  ...tedFolders.ts |   90.67 |    76.92 |     100 |   90.67 | ...20,125-130,148 
 src/generated     |     100 |      100 |     100 |     100 |                   
  git-commit.ts    |     100 |      100 |     100 |     100 |                   
 src/patches       |       0 |        0 |       0 |       0 |                   
  is-in-ci.ts      |       0 |        0 |       0 |       0 | 1-17              
 src/services      |   61.42 |    88.13 |   72.22 |   61.42 |                   
  ...mandLoader.ts |     100 |      100 |     100 |     100 |                   
  ...andService.ts |     100 |      100 |     100 |     100 |                   
  ...mandLoader.ts |   92.09 |    91.89 |     100 |   92.09 | 176-181,250-257   
  ...omptLoader.ts |    9.39 |    57.14 |   33.33 |    9.39 | ...44-167,173-230 
  types.ts         |       0 |        0 |       0 |       0 | 1                 
 ...mpt-processors |   95.18 |    94.73 |     100 |   95.18 |                   
  ...tProcessor.ts |     100 |      100 |     100 |     100 |                   
  ...lProcessor.ts |   93.54 |    92.85 |     100 |   93.54 | 67-70             
  types.ts         |     100 |      100 |     100 |     100 |                   
 src/test-utils    |   90.38 |    81.81 |      75 |   90.38 |                   
  ...omMatchers.ts |   69.69 |       50 |      50 |   69.69 | 31-34,36-38,44-46 
  ...andContext.ts |     100 |      100 |     100 |     100 |                   
 src/ui            |   59.01 |    72.53 |   65.78 |   59.01 |                   
  App.tsx          |   57.77 |    61.61 |   38.46 |   57.77 | ...1132,1158-1187 
  ...tionNudge.tsx |    7.89 |      100 |       0 |    7.89 | 26-102            
  colors.ts        |   87.75 |      100 |      80 |   87.75 | 12-13,18-19,48-49 
  constants.ts     |     100 |      100 |     100 |     100 |                   
  keyMatchers.ts   |   95.65 |    95.65 |     100 |   95.65 | 29-30             
  ...tic-colors.ts |   89.47 |      100 |      80 |   89.47 | 15-16             
  types.ts         |     100 |      100 |     100 |     100 |                   
 src/ui/commands   |   85.16 |    83.28 |   87.27 |   85.16 |                   
  aboutCommand.ts  |     100 |    55.55 |     100 |     100 | 23-30             
  authCommand.ts   |     100 |      100 |     100 |     100 |                   
  bugCommand.ts    |   78.46 |    42.85 |     100 |   78.46 | 32-35,72-81       
  chatCommand.ts   |   94.16 |    83.33 |     100 |   94.16 | ...07-208,210-211 
  clearCommand.ts  |     100 |      100 |     100 |     100 |                   
  ...essCommand.ts |     100 |    88.88 |     100 |     100 | 69                
  copyCommand.ts   |     100 |      100 |     100 |     100 |                   
  corgiCommand.ts  |     100 |      100 |     100 |     100 |                   
  ...ryCommand.tsx |   70.12 |    73.07 |     100 |   70.12 | ...22-123,158-166 
  docsCommand.ts   |     100 |      100 |     100 |     100 |                   
  editorCommand.ts |     100 |      100 |     100 |     100 |                   
  ...onsCommand.ts |     100 |      100 |     100 |     100 |                   
  helpCommand.ts   |     100 |      100 |     100 |     100 |                   
  ideCommand.ts    |    55.6 |    77.27 |   44.44 |    55.6 | ...09-219,227-237 
  initCommand.ts   |     100 |      100 |     100 |     100 |                   
  mcpCommand.ts    |   82.29 |    82.95 |   83.33 |   82.29 | ...83-384,437-444 
  memoryCommand.ts |   99.09 |    92.85 |     100 |   99.09 | 93                
  ...acyCommand.ts |     100 |      100 |     100 |     100 |                   
  quitCommand.ts   |     100 |      100 |     100 |     100 |                   
  ...oreCommand.ts |   93.79 |    91.42 |     100 |   93.79 | 54-55,84-89       
  ...ngsCommand.ts |     100 |      100 |     100 |     100 |                   
  ...hubCommand.ts |   79.33 |    46.15 |     100 |   79.33 | ...16-119,122-125 
  statsCommand.ts  |   84.48 |       75 |     100 |   84.48 | 24-32             
  ...tupCommand.ts |     100 |      100 |     100 |     100 |                   
  themeCommand.ts  |     100 |      100 |     100 |     100 |                   
  toolsCommand.ts  |     100 |      100 |     100 |     100 |                   
  types.ts         |     100 |      100 |     100 |     100 |                   
  vimCommand.ts    |   44.44 |      100 |       0 |   44.44 | 14-24             
 src/ui/components |   71.37 |    84.82 |   73.07 |   71.37 |                   
  AboutBox.tsx     |     100 |       50 |     100 |     100 | 102               
  AsciiArt.ts      |     100 |      100 |     100 |     100 |                   
  AuthDialog.tsx   |   90.07 |    96.42 |      75 |   90.07 | 69-74,103-110     
  ...nProgress.tsx |   16.66 |      100 |       0 |   16.66 | 18-62             
  ...Indicator.tsx |   15.15 |      100 |       0 |   15.15 | 17-47             
  ...ryDisplay.tsx |   89.47 |    33.33 |     100 |   89.47 | 20-21             
  ...ryDisplay.tsx |   92.04 |    94.44 |     100 |   92.04 | 79-84,89          
  ...geDisplay.tsx |     100 |      100 |     100 |     100 |                   
  ...gProfiler.tsx |      24 |      100 |       0 |      24 | 13-36             
  ...esDisplay.tsx |   10.52 |      100 |       0 |   10.52 | 24-82             
  ...ngsDialog.tsx |    7.29 |      100 |       0 |    7.29 | 27-172            
  ...ustDialog.tsx |     100 |      100 |     100 |     100 |                   
  Footer.tsx       |   84.68 |    82.35 |     100 |   84.68 | ...,89-91,135-142 
  ...ngSpinner.tsx |      80 |    33.33 |     100 |      80 | 29,31-32          
  Header.tsx       |   78.72 |    57.14 |     100 |   78.72 | 36-39,51-53,60-62 
  Help.tsx         |    3.27 |      100 |       0 |    3.27 | 17-173            
  ...emDisplay.tsx |      70 |    56.25 |     100 |      70 | ...59-64,84-91,94 
  InputPrompt.tsx  |   88.84 |    81.94 |     100 |   88.84 | ...94-496,599-603 
  ...Indicator.tsx |     100 |      100 |     100 |     100 |                   
  ...geDisplay.tsx |   25.92 |      100 |       0 |   25.92 | 14-36             
  ...tsDisplay.tsx |     100 |      100 |     100 |     100 |                   
  PrepareLabel.tsx |      60 |       80 |     100 |      60 | 35-48             
  ...ryDisplay.tsx |     100 |      100 |     100 |     100 |                   
  ...ngsDialog.tsx |   89.94 |    88.31 |     100 |   89.94 | ...23-336,342-358 
  ...ionDialog.tsx |   85.29 |      100 |   33.33 |   85.29 | 36-39,44-51       
  ...Indicator.tsx |   44.44 |      100 |       0 |   44.44 | 12-17             
  ...MoreLines.tsx |      60 |       25 |     100 |      60 | 24-27,33-40       
  StatsDisplay.tsx |   98.39 |    86.66 |     100 |   98.39 | 173-175           
  ...nsDisplay.tsx |   88.05 |    71.42 |     100 |   88.05 | 36-41,96-98       
  ThemeDialog.tsx  |    5.33 |      100 |       0 |    5.33 | 34-310            
  Tips.tsx         |      16 |      100 |       0 |      16 | 17-45             
  ...tsDisplay.tsx |     100 |     87.5 |     100 |     100 | 30-31             
  ...ification.tsx |   36.36 |      100 |       0 |   36.36 | 15-22             
 ...nents/messages |   63.15 |     81.3 |   57.14 |   63.15 |                   
  ...onMessage.tsx |   18.51 |      100 |       0 |   18.51 | 22-49             
  DiffRenderer.tsx |   96.18 |    81.92 |     100 |   96.18 | ...16-217,221,283 
  ErrorMessage.tsx |     100 |      100 |     100 |     100 |                   
  ...niMessage.tsx |   18.51 |      100 |       0 |   18.51 | 20-43             
  ...geContent.tsx |   19.04 |      100 |       0 |   19.04 | 25-43             
  InfoMessage.tsx  |     100 |      100 |     100 |     100 |                   
  ...onMessage.tsx |   35.87 |     62.5 |      20 |   35.87 | ...64-199,238-266 
  ...upMessage.tsx |   10.11 |      100 |       0 |   10.11 | 27-126            
  ToolMessage.tsx  |   87.76 |       80 |     100 |   87.76 | ...,91-95,169-171 
  UserMessage.tsx  |     100 |      100 |     100 |     100 |                   
  ...llMessage.tsx |   36.36 |      100 |       0 |   36.36 | 17-25             
 ...ponents/shared |    80.8 |    76.41 |   95.45 |    80.8 |                   
  MaxSizedBox.tsx  |   81.14 |     82.2 |   88.88 |   81.14 | ...08-509,614-615 
  ...tonSelect.tsx |   80.92 |    65.78 |     100 |   80.92 | ...52,155-156,226 
  text-buffer.ts   |   78.17 |    78.28 |   96.77 |   78.17 | ...1821,1861,1911 
  ...er-actions.ts |   86.71 |    67.79 |     100 |   86.71 | ...08-609,810-812 
 src/ui/contexts   |   86.73 |    76.66 |     100 |   86.73 |                   
  ...owContext.tsx |   91.07 |    81.81 |     100 |   91.07 | 46-47,59-61       
  ...onContext.tsx |   94.11 |      100 |     100 |   94.11 | 101-104           
  ...gsContext.tsx |   83.33 |       50 |     100 |   83.33 | 17-18             
  ...ngContext.tsx |   71.42 |       50 |     100 |   71.42 | 17-20             
  ...deContext.tsx |   76.08 |       50 |     100 |   76.08 | 46-47,51-58,76-77 
 src/ui/editors    |   93.18 |    85.71 |   66.66 |   93.18 |                   
  ...ngsManager.ts |   93.18 |    85.71 |   66.66 |   93.18 | 48,62-63          
 src/ui/hooks      |   78.67 |    82.09 |   83.33 |   78.67 |                   
  ...dProcessor.ts |    78.4 |       79 |     100 |    78.4 | ...55-458,469-487 
  ...dProcessor.ts |   96.23 |    72.97 |     100 |   96.23 | ...10-211,216-217 
  ...dProcessor.ts |   82.16 |    71.42 |   83.33 |   82.16 | ...70-374,440-468 
  ...Completion.ts |   92.73 |    89.47 |     100 |   92.73 | ...85-186,219-222 
  ...uthCommand.ts |    7.46 |      100 |       0 |    7.46 | 18-92             
  ...tIndicator.ts |     100 |      100 |     100 |     100 |                   
  ...ketedPaste.ts |     100 |      100 |     100 |     100 |                   
  ...ompletion.tsx |   94.73 |    81.81 |     100 |   94.73 | ...98-199,201-202 
  useCompletion.ts |    92.4 |     87.5 |     100 |    92.4 | ...,95-96,100-101 
  ...leMessages.ts |   98.68 |       95 |     100 |   98.68 | 55                
  ...orSettings.ts |     100 |      100 |     100 |     100 |                   
  useFocus.ts      |     100 |      100 |     100 |     100 |                   
  ...olderTrust.ts |     100 |      100 |     100 |     100 |                   
  ...miniStream.ts |   73.52 |    71.32 |     100 |   73.52 | ...41-842,872-962 
  ...BranchName.ts |   91.66 |    84.61 |     100 |   91.66 | 57-63             
  ...oryManager.ts |   98.41 |    93.33 |     100 |   98.41 | 43                
  ...putHistory.ts |    92.5 |    85.71 |     100 |    92.5 | 62-63,71,93-95    
  useKeypress.ts   |   57.71 |    86.88 |      80 |   57.71 | ...46-292,399-401 
  ...rdProtocol.ts |     100 |      100 |     100 |     100 |                   
  ...gIndicator.ts |     100 |      100 |     100 |     100 |                   
  useLogger.ts     |      25 |      100 |       0 |      25 | 14-32             
  ...raseCycler.ts |   95.45 |       75 |     100 |   95.45 | ...64-165,183-185 
  ...cySettings.ts |     3.6 |      100 |       0 |     3.6 | 18-139            
  ...lScheduler.ts |   79.29 |    94.59 |     100 |   79.29 | ...06-209,295-305 
  ...oryCommand.ts |       0 |        0 |       0 |       0 | 1-7               
  ...ompletion.tsx |     100 |     92.3 |     100 |     100 | 78                
  ...ngsCommand.ts |    87.5 |      100 |     100 |    87.5 | 13,17             
  ...ellHistory.ts |   91.26 |       80 |     100 |   91.26 | ...67,112-113,123 
  ...oryCommand.ts |       0 |        0 |       0 |       0 | 1-75              
  ...Completion.ts |      94 |    92.53 |     100 |      94 | 58-61,69-72,93    
  ...tateAndRef.ts |   59.09 |      100 |     100 |   59.09 | 23-31             
  ...rminalSize.ts |   18.18 |      100 |       0 |   18.18 | 12-32             
  ...emeCommand.ts |   46.98 |       75 |     100 |   46.98 | ...4,70-71,77-100 
  useTimer.ts      |   88.09 |    85.71 |     100 |   88.09 | 44-45,51-53       
  vim.ts           |   83.57 |     79.5 |     100 |   83.57 | ...38,742-750,759 
 src/ui/privacy    |   14.52 |      100 |       0 |   14.52 |                   
  ...acyNotice.tsx |   10.38 |      100 |       0 |   10.38 | 21-117            
  ...acyNotice.tsx |   14.28 |      100 |       0 |   14.28 | 16-59             
  ...acyNotice.tsx |   12.19 |      100 |       0 |   12.19 | 16-62             
  ...acyNotice.tsx |   30.76 |      100 |       0 |   30.76 | 19-36,39-41       
 src/ui/themes     |   99.48 |    65.38 |     100 |   99.48 |                   
  ansi-light.ts    |     100 |      100 |     100 |     100 |                   
  ansi.ts          |     100 |      100 |     100 |     100 |                   
  atom-one-dark.ts |     100 |      100 |     100 |     100 |                   
  ayu-light.ts     |     100 |      100 |     100 |     100 |                   
  ayu.ts           |     100 |      100 |     100 |     100 |                   
  color-utils.ts   |     100 |      100 |     100 |     100 |                   
  default-light.ts |     100 |      100 |     100 |     100 |                   
  default.ts       |     100 |      100 |     100 |     100 |                   
  dracula.ts       |     100 |      100 |     100 |     100 |                   
  github-dark.ts   |     100 |      100 |     100 |     100 |                   
  github-light.ts  |     100 |      100 |     100 |     100 |                   
  googlecode.ts    |     100 |      100 |     100 |     100 |                   
  no-color.ts      |     100 |      100 |     100 |     100 |                   
  ...tic-tokens.ts |     100 |      100 |     100 |     100 |                   
  ...-of-purple.ts |     100 |      100 |     100 |     100 |                   
  theme-manager.ts |   91.08 |    78.04 |     100 |   91.08 | ...91,195,220-221 
  theme.ts         |     100 |     41.3 |     100 |     100 | 225-240           
  xcode.ts         |     100 |      100 |     100 |     100 |                   
 src/ui/utils      |   62.68 |    85.49 |   81.96 |   62.68 |                   
  ...Colorizer.tsx |   77.24 |       80 |     100 |   77.24 | ...51-154,190-216 
  ...olePatcher.ts |      96 |       75 |     100 |      96 | 59-60             
  ...nRenderer.tsx |   26.51 |       75 |     100 |   26.51 | 32-137            
  ...wnDisplay.tsx |   85.84 |    87.69 |     100 |   85.84 | ...72-280,313-336 
  ...eRenderer.tsx |   78.09 |    76.19 |     100 |   78.09 | 55-83             
  ...boardUtils.ts |   32.25 |     37.5 |     100 |   32.25 | ...55-114,129-145 
  commandUtils.ts  |   97.36 |     92.3 |     100 |   97.36 | 68,72             
  computeStats.ts  |     100 |      100 |     100 |     100 |                   
  displayUtils.ts  |     100 |      100 |     100 |     100 |                   
  formatters.ts    |   90.47 |    95.83 |     100 |   90.47 | 57-60             
  isNarrowWidth.ts |     100 |      100 |     100 |     100 |                   
  ...olDetector.ts |   13.88 |      100 |      50 |   13.88 | 16-97             
  ...nUtilities.ts |   69.84 |    85.71 |     100 |   69.84 | 75-91,100-101     
  ...mConstants.ts |     100 |      100 |     100 |     100 |                   
  terminalSetup.ts |    4.03 |      100 |       0 |    4.03 | 40-340            
  textUtils.ts     |   88.88 |    83.33 |     100 |   88.88 | 14-15             
  updateCheck.ts   |     100 |    80.95 |     100 |     100 | 26-38             
 src/utils         |   45.54 |    92.09 |   85.71 |   45.54 |                   
  checks.ts        |   33.33 |      100 |       0 |   33.33 | 23-28             
  cleanup.ts       |      96 |    85.71 |     100 |      96 | 35                
  ...ScopeUtils.ts |     100 |      100 |     100 |     100 |                   
  events.ts        |     100 |      100 |     100 |     100 |                   
  gitUtils.ts      |   94.66 |    82.35 |     100 |   94.66 | 75-78             
  ...AutoUpdate.ts |   81.14 |    95.23 |   66.66 |   81.14 | 85-99,125-132     
  ...lationInfo.ts |     100 |      100 |     100 |     100 |                   
  package.ts       |   88.88 |       80 |     100 |   88.88 | 33-34             
  readStdin.ts     |    2.43 |      100 |       0 |    2.43 | 7-51              
  resolvePath.ts   |   66.66 |       25 |     100 |   66.66 | 12-13,16,18-19    
  sandbox.ts       |       0 |        0 |       0 |       0 | 1-945             
  settingsUtils.ts |   84.48 |    93.68 |   96.55 |   84.48 | ...05-306,357-401 
  spawnWrapper.ts  |     100 |      100 |     100 |     100 |                   
  ...upWarnings.ts |   23.07 |      100 |       0 |   23.07 | 14-40             
  ...entEmitter.ts |     100 |      100 |     100 |     100 |                   
  ...upWarnings.ts |     100 |      100 |     100 |     100 |                   
  version.ts       |     100 |       50 |     100 |     100 | 11                
 ...ed-integration |   26.06 |        0 |       0 |   26.06 |                   
  acp.ts           |    2.89 |        0 |       0 |    2.89 | ...52-288,291-338 
  schema.ts        |     100 |      100 |     100 |     100 |                   
  ...ntegration.ts |    3.29 |        0 |       0 |    3.29 | ...89-784,799-849 
-------------------|---------|----------|---------|---------|-------------------
Core Package - Full Text Report
-------------------|---------|----------|---------|---------|-------------------
File               | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s 
-------------------|---------|----------|---------|---------|-------------------
All files          |   74.36 |    82.95 |   74.06 |   74.36 |                   
 src               |     100 |      100 |     100 |     100 |                   
  index.ts         |     100 |      100 |     100 |     100 |                   
 src/__mocks__/fs  |     100 |      100 |     100 |     100 |                   
  promises.ts      |     100 |      100 |     100 |     100 |                   
 src/code_assist   |   72.15 |    76.19 |   71.05 |   72.15 |                   
  codeAssist.ts    |   18.51 |      100 |       0 |   18.51 | 13-35             
  converter.ts     |   89.23 |    96.15 |   81.81 |   89.23 | 178-182,201-211   
  oauth2.ts        |   75.23 |     61.7 |      80 |   75.23 | ...03-409,416-417 
  server.ts        |    50.6 |       80 |   53.84 |    50.6 | ...73-214,217-219 
  setup.ts         |   86.66 |    78.94 |     100 |   86.66 | ...,92-94,118-124 
  types.ts         |     100 |      100 |     100 |     100 |                   
 src/config        |   75.72 |     87.5 |    48.1 |   75.72 |                   
  config.ts        |   75.48 |     87.5 |    48.1 |   75.48 | ...31-738,744-745 
  models.ts        |     100 |      100 |     100 |     100 |                   
 src/core          |   75.09 |    77.96 |   73.01 |   75.09 |                   
  client.ts        |   81.29 |    77.48 |   77.77 |   81.29 | ...72,874-875,878 
  ...tGenerator.ts |   91.76 |    78.26 |     100 |   91.76 | 82-83,133,142-145 
  ...lScheduler.ts |   68.07 |    70.83 |   77.27 |   68.07 | ...60-867,870-880 
  geminiChat.ts    |   59.36 |    70.83 |   53.57 |   59.36 | ...06-607,610-611 
  geminiRequest.ts |     100 |      100 |     100 |     100 |                   
  logger.ts        |   85.96 |    83.33 |     100 |   85.96 | ...60-261,277-281 
  ...tGenerator.ts |   15.97 |      100 |      20 |   15.97 | ...51-179,182-183 
  ...olExecutor.ts |   90.07 |       50 |     100 |   90.07 | 84-85,87-96,127   
  prompts.ts       |   95.76 |    96.96 |      50 |   95.76 | 37-38,304-361     
  subagent.ts      |   92.18 |    83.75 |     100 |   92.18 | ...05-613,656-657 
  tokenLimits.ts   |   14.28 |      100 |       0 |   14.28 | 15-32             
  turn.ts          |   83.57 |    83.33 |     100 |   83.57 | ...55-258,271-272 
 src/generated     |     100 |      100 |     100 |     100 |                   
  git-commit.ts    |     100 |      100 |     100 |     100 |                   
 src/ide           |   44.33 |    87.09 |   48.57 |   44.33 |                   
  constants.ts     |     100 |      100 |     100 |     100 |                   
  detect-ide.ts    |   49.35 |      100 |      50 |   49.35 | 23-62             
  ide-client.ts    |   28.97 |    92.85 |    23.8 |   28.97 | ...71-395,398-402 
  ide-installer.ts |   58.76 |    53.33 |     100 |   58.76 | ...82,104-117,126 
  ideContext.ts    |   83.65 |      100 |     100 |   83.65 | 74-90             
  process-utils.ts |   14.28 |      100 |       0 |   14.28 | 21-62             
 src/mcp           |    74.2 |    80.16 |   76.31 |    74.2 |                   
  ...h-provider.ts |   86.36 |      100 |   33.33 |   86.36 | ...85,89,93,97-98 
  ...h-provider.ts |      77 |    65.62 |      90 |      77 | ...61-663,668-670 
  ...en-storage.ts |     100 |      100 |     100 |     100 |                   
  oauth-utils.ts   |   42.85 |     87.5 |      80 |   42.85 | ...32-192,216-252 
 src/mocks         |     100 |      100 |     100 |     100 |                   
  msw.ts           |     100 |      100 |     100 |     100 |                   
 src/prompts       |   26.41 |      100 |      25 |   26.41 |                   
  mcp-prompts.ts   |   18.18 |      100 |       0 |   18.18 | 11-19             
  ...t-registry.ts |   28.57 |      100 |   28.57 |   28.57 | ...42,48-55,68-73 
 src/services      |   94.93 |    94.85 |   86.84 |   94.93 |                   
  ...eryService.ts |   93.33 |    88.46 |   85.71 |   93.33 | 31,39,84,109-110  
  gitService.ts    |   77.52 |      100 |      60 |   77.52 | ...08-112,115-119 
  ...ionService.ts |   99.23 |    97.05 |     100 |   99.23 | 287-288           
  ...ionService.ts |   98.63 |    92.85 |     100 |   98.63 | 163-164           
 src/telemetry     |   62.62 |    73.04 |   67.64 |   62.62 |                   
  constants.ts     |     100 |      100 |     100 |     100 |                   
  ...-exporters.ts |   26.47 |        0 |       0 |   26.47 | ...80,83-84,87-88 
  index.ts         |     100 |      100 |     100 |     100 |                   
  ...t.circular.ts |       0 |        0 |       0 |       0 | 1-62              
  ...t.circular.ts |       0 |        0 |       0 |       0 | 1-125             
  loggers.ts       |   64.61 |    69.56 |   64.28 |   64.61 | ...63-381,384-399 
  metrics.ts       |   61.98 |       96 |    62.5 |   61.98 | ...37-159,162-185 
  sdk.ts           |   73.38 |       25 |     100 |   73.38 | ...48,153-154,156 
  ...l-decision.ts |     100 |      100 |     100 |     100 |                   
  types.ts         |   69.25 |    66.66 |   72.72 |   69.25 | ...38-347,350-361 
  uiTelemetry.ts   |   99.24 |    95.45 |     100 |   99.24 | 118               
 ...learcut-logger |   73.98 |    78.26 |   64.28 |   73.98 |                   
  ...cut-logger.ts |   72.46 |    77.94 |   66.66 |   72.46 | ...82-783,786-789 
  ...tadata-key.ts |   88.05 |      100 |       0 |   88.05 | 234-244           
 src/test-utils    |    98.8 |    91.66 |     100 |    98.8 |                   
  config.ts        |     100 |      100 |     100 |     100 |                   
  ...aceContext.ts |     100 |      100 |     100 |     100 |                   
  tools.ts         |   97.77 |     87.5 |     100 |   97.77 | 61                
 src/tools         |   68.74 |    81.16 |   76.02 |   68.74 |                   
  diffOptions.ts   |     100 |      100 |     100 |     100 |                   
  edit.ts          |   81.45 |    82.89 |   85.71 |   81.45 | ...80-481,503-542 
  glob.ts          |   85.83 |    78.72 |    87.5 |   85.83 | ...29-236,313-314 
  grep.ts          |   58.86 |    78.75 |   78.57 |   58.86 | ...88-592,602-603 
  ls.ts            |   96.81 |    90.16 |     100 |   96.81 | 136-140,323-324   
  mcp-client.ts    |   35.85 |    80.48 |   38.09 |   35.85 | ...1176,1180-1183 
  mcp-tool.ts      |   93.33 |    91.37 |    87.5 |   93.33 | ...55-165,227-228 
  memoryTool.ts    |   83.94 |       82 |   88.88 |   83.94 | ...03-304,388-406 
  ...iable-tool.ts |     100 |    84.61 |     100 |     100 | 94,101            
  read-file.ts     |    95.9 |     92.3 |    87.5 |    95.9 | ...10-112,209-210 
  ...many-files.ts |   79.61 |    72.58 |   85.71 |   79.61 | ...04-505,512-513 
  shell.ts         |   83.87 |    73.13 |   88.88 |   83.87 | ...69-370,381-382 
  tool-error.ts    |     100 |      100 |     100 |     100 |                   
  tool-registry.ts |   49.03 |     67.5 |   70.58 |   49.03 | ...62-364,387-395 
  tools.ts         |   78.57 |    89.18 |   63.63 |   78.57 | ...48-449,465-471 
  web-fetch.ts     |   36.98 |    73.68 |   72.72 |   36.98 | ...53-354,359-360 
  web-search.ts    |   26.05 |      100 |      40 |   26.05 | ...07-108,111-200 
  write-file.ts    |   83.46 |    78.78 |      80 |   83.46 | ...91-392,464-498 
 src/utils         |   85.21 |    86.48 |   88.95 |   85.21 |                   
  LruCache.ts      |   70.96 |     62.5 |     100 |   70.96 | 20-22,28,30-34    
  bfsFileSearch.ts |   89.02 |    90.47 |     100 |   89.02 | 86-94             
  browser.ts       |    8.69 |      100 |       0 |    8.69 | 17-53             
  editCorrector.ts |    77.3 |    61.11 |   91.66 |    77.3 | ...65-677,711,725 
  editor.ts        |   97.63 |    94.54 |     100 |   97.63 | 154,224,227-228   
  ...entContext.ts |     100 |      100 |     100 |     100 |                   
  errorParsing.ts  |     100 |     92.3 |     100 |     100 | 76,80,86          
  ...rReporting.ts |   83.72 |    84.61 |     100 |   83.72 | 82-86,107-115     
  errors.ts        |   39.02 |       60 |      75 |   39.02 | 21-25,41-57,61-67 
  fetch.ts         |   34.04 |      100 |       0 |   34.04 | 22-27,31-57       
  fileUtils.ts     |   95.25 |       90 |     100 |   95.25 | ...05-110,357-363 
  formatters.ts    |   54.54 |       50 |     100 |   54.54 | 12-16             
  ...eUtilities.ts |   96.03 |    95.83 |     100 |   96.03 | 28-29,57-58       
  ...rStructure.ts |   95.96 |    94.93 |     100 |   95.96 | ...14-117,345-347 
  ...noreParser.ts |     100 |    89.47 |     100 |     100 | 27,47             
  gitUtils.ts      |   51.21 |     90.9 |      50 |   51.21 | 40-41,50-73       
  ...yDiscovery.ts |   87.31 |    76.92 |   77.77 |   87.31 | ...33-334,337-338 
  ...tProcessor.ts |   93.63 |    88.75 |   84.61 |   93.63 | ...81-282,385-386 
  ...Inspectors.ts |     100 |      100 |     100 |     100 |                   
  ...kerChecker.ts |   83.33 |    83.33 |     100 |   83.33 | 64-65,75-80,88-94 
  partUtils.ts     |     100 |      100 |     100 |     100 |                   
  paths.ts         |   84.07 |    88.23 |      80 |   84.07 | ...92-193,201-202 
  ...rDetection.ts |    64.4 |    76.19 |     100 |    64.4 | ...4,88-89,99-100 
  retry.ts         |   62.55 |    73.21 |     100 |   62.55 | ...58-278,323-338 
  ...nStringify.ts |     100 |      100 |     100 |     100 |                   
  ...aValidator.ts |      80 |    57.14 |     100 |      80 | 23-24,26-27       
  ...r-launcher.ts |   78.57 |     87.5 |   66.66 |   78.57 | ...33,135,153-188 
  session.ts       |     100 |      100 |     100 |     100 |                   
  shell-utils.ts   |   95.21 |    93.57 |     100 |   95.21 | ...,94-95,142-144 
  summarizer.ts    |     100 |    88.88 |     100 |     100 | 91                
  ...emEncoding.ts |      98 |    94.11 |     100 |      98 | 106-107           
  testUtils.ts     |   84.44 |    72.72 |   83.33 |   84.44 | 27-28,34-35,70-72 
  textUtils.ts     |    12.5 |      100 |       0 |    12.5 | 15-34             
  user_account.ts  |   97.72 |    97.05 |     100 |   97.72 | 102-103           
  user_id.ts       |    75.6 |       60 |      75 |    75.6 | 19-20,28-33,46-48 
  ...aceContext.ts |   80.37 |    74.19 |      80 |   80.37 | ...17-121,149-150 
 ...ils/filesearch |   97.24 |     93.2 |     100 |   97.24 |                   
  crawlCache.ts    |     100 |      100 |     100 |     100 |                   
  fileSearch.ts    |   95.58 |     90.9 |     100 |   95.58 | ...89-190,221-222 
  ignore.ts        |     100 |      100 |     100 |     100 |                   
  result-cache.ts  |     100 |     92.3 |     100 |     100 | 46                
-------------------|---------|----------|---------|---------|-------------------

For detailed HTML reports, please see the 'coverage-reports-22.x-ubuntu-latest' artifact from the main CI run.

Copy link
Copy Markdown
Contributor

@olcan olcan left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm approving this but please see my feedback, mostly about adding some comments and watching out for certain things like the switch to mixed output in model context, and new dependencies (e.g. on python for node-pty) that likely require robust testing across platforms + environments (incl. sandboxes) + terminals + commands, including commands that push terminal features e.g. various editors, gemini-cli itself, other clis, etc. This would be less for the model but more for human dev running these things via shell mode (which shares the shell execution service w/ shell tool iiuc). I would also test robust termination of subprocess hierarchies given the switch in termination logic.

"undici": "^7.10.0",
"ws": "^8.18.0"
"ws": "^8.18.0",
"node-pty": "1.0.0",
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One concern I had with node-pty before, when I was experimenting with interactivity, was that it had a dependency on python, which felt too heavy at the time. Is that still the case, and are we good with it now given the benefits?

Copy link
Copy Markdown
Collaborator Author

@galz10 galz10 Aug 13, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It does depend on python but node-pty has installers and stuff to make sure it is installed correctly on all os's, i think in order to support this feature + better ansi key handling, node-pty is need.

@olcan
Copy link
Copy Markdown
Contributor

olcan commented Aug 13, 2025

I'm approving this but please see my feedback, mostly about adding some comments and watching out for certain things like the switch to mixed output in model context, and new dependencies (e.g. on python for node-pty) that likely require robust testing across platforms + environments (incl. sandboxes) + terminals + commands, including commands that push terminal features e.g. various editors, gemini-cli itself, other clis, etc. This would be less for the model but more for human dev running these things via shell mode (which shares the shell execution service w/ shell tool iiuc). I would also test robust termination of subprocess hierarchies given the switch in termination logic.

One more thing that came to mind is the background PID detection via pgrep, see around

if (pid !== result.pid) {
backgroundPIDs.push(pid);
. Note how we exclude result.pid here because on some platforms (e.g. linux sandbox but not macos host iirc) pgrep returns the shell process pid also, and we don't want to report that as a "background pid" to the model. With this change if there is an additional parent process we may need to exclude that as well since it would not count as a background pid.

I would also make sure that result.pid is still a process group in the new approach (in the old approach the 'detached:true' option would ensure this) as the model is being told it is around

`Process Group PGID: ${result.pid ?? '(none)'}`,
].join('\n');
and this is important because it means the model may try to kill the group via kill -pgid and this is indeed the most robust way for the model to kill a background process group.

Copy link
Copy Markdown
Contributor

@jacob314 jacob314 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm

@jacob314 jacob314 enabled auto-merge August 13, 2025 19:13
@galz10 galz10 force-pushed the galzahavi/add/vterminal-shell branch 3 times, most recently from 2f01a1d to 3fc6ecb Compare August 13, 2025 20:59
@galz10 galz10 force-pushed the galzahavi/add/vterminal-shell branch from 3fc6ecb to d4a69d5 Compare August 14, 2025 17:31
@galz10 galz10 force-pushed the galzahavi/add/vterminal-shell branch from c18a9ca to 2954282 Compare August 14, 2025 20:11
@galz10 galz10 force-pushed the galzahavi/add/vterminal-shell branch from 2954282 to 4d3b018 Compare August 14, 2025 20:29
@galz10 galz10 force-pushed the galzahavi/add/vterminal-shell branch from 664c63b to 307e696 Compare August 14, 2025 20:33
@jacob314 jacob314 added this pull request to the merge queue Aug 14, 2025
Merged via the queue into main with commit 980091c Aug 14, 2025
18 checks passed
@jacob314 jacob314 deleted the galzahavi/add/vterminal-shell branch August 14, 2025 20:47
galz10 added a commit that referenced this pull request Aug 15, 2025
github-merge-queue bot pushed a commit that referenced this pull request Aug 15, 2025
agarwalravikant pushed a commit to agarwalravikant/gemini-cli that referenced this pull request Aug 18, 2025
agarwalravikant pushed a commit to agarwalravikant/gemini-cli that referenced this pull request Aug 18, 2025
acoliver referenced this pull request in vybestack/llxprt-code Aug 18, 2025
This is an empty merge commit to maintain parity with upstream structure.
All changes have already been cherry-picked:
- feat(shell): Include disallowed commands in block reason (#6278)
- Fix license notice generation script (#6272)
- IDE integration multi-folder support (#6265, #6177)
- Show /ide enable & /ide disable commands (#6248)
- Update versioning script (#6075)
- Add eslint as recommended extension (#6196)
- Add recommended extensions list (#5810)
- Generate NOTICES.TXT and surface via command (#5310)
- Stylize diff line numbers & characters (#6269)
- Various other improvements and fixes

Note: feat(core): refactor shell execution to use node-pty (#6088) was cherry-picked
but later reverted upstream in #6328. We kept it as it works well with llxprt.

Maintains llxprt's multi-provider support, branding, ServerToolsProvider,
and authentication differences while staying in sync with upstream improvements.
JeongJaeSoon pushed a commit to JeongJaeSoon/gemini-cli that referenced this pull request Aug 21, 2025
JeongJaeSoon pushed a commit to JeongJaeSoon/gemini-cli that referenced this pull request Aug 21, 2025
involvex pushed a commit to involvex/gemini-cli that referenced this pull request Sep 11, 2025
involvex pushed a commit to involvex/gemini-cli that referenced this pull request Sep 11, 2025
reconsumeralization pushed a commit to reconsumeralization/gemini-cli that referenced this pull request Sep 19, 2025
reconsumeralization pushed a commit to reconsumeralization/gemini-cli that referenced this pull request Sep 19, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Support interaction with terminal windows embedded in Gemini CLI

3 participants