@@ -73,7 +73,7 @@ export async function executeCommand(
7373 cline : Cline ,
7474 command : string ,
7575 customCwd ?: string ,
76- terminalProvider : "vscode" | "execa" = "vscode " ,
76+ terminalProvider : "vscode" | "execa" = "execa " ,
7777) : Promise < [ boolean , ToolResponse ] > {
7878 let workingDir : string
7979
@@ -98,69 +98,50 @@ export async function executeCommand(
9898 // workingDir = terminalInfo.getCurrentWorkingDirectory()
9999 const workingDirInfo = workingDir ? ` from '${ workingDir . toPosix ( ) } '` : ""
100100
101- let userFeedback : { text ?: string ; images ?: string [ ] } | undefined
102- let runInBackground : boolean | undefined = undefined
101+ let message : { text ?: string ; images ?: string [ ] } | undefined
102+ let runInBackground = false
103103 let completed = false
104104 let result : string = ""
105105 let exitDetails : ExitCodeDetails | undefined
106106 const { terminalOutputLineLimit = 500 } = ( await cline . providerRef . deref ( ) ?. getState ( ) ) ?? { }
107107
108- const debounceLineLimit = 100 // Flush after this many lines.
109- const debounceTimeoutMs = 200 // Flush after this much time inactivity (ms).
110- let buffer : string [ ] = [ ]
111- let debounceTimer : NodeJS . Timeout | null = null
112-
113- async function flush ( process ?: RooTerminalProcess ) {
114- if ( debounceTimer ) {
115- clearTimeout ( debounceTimer )
116- debounceTimer = null
117- }
118-
119- if ( buffer . length === 0 ) {
120- return
121- }
122-
123- const output = buffer . join ( "\n" )
124- buffer = [ ]
125-
126- result = Terminal . compressTerminalOutput ( result + output , terminalOutputLineLimit )
127- const compressed = Terminal . compressTerminalOutput ( output , terminalOutputLineLimit )
128- cline . say ( "command_output" , compressed )
129-
130- if ( typeof runInBackground !== "undefined" ) {
131- return
132- }
133-
134- console . log ( `ask command_output: waiting for response` )
135- const { response, text, images } = await cline . ask ( "command_output" , compressed )
136- console . log ( `ask command_output =>` , response )
137-
138- if ( response === "yesButtonClicked" ) {
139- runInBackground = false
140- } else {
141- runInBackground = true
142- userFeedback = { text, images }
143- }
144-
145- process ?. continue ( )
146- }
147-
148108 const callbacks = {
149- onLine : async ( line : string , process : RooTerminalProcess ) => {
150- buffer . push ( line )
151-
152- if ( buffer . length >= debounceLineLimit ) {
153- await flush ( process )
154- } else {
155- if ( debounceTimer ) {
156- clearTimeout ( debounceTimer )
157- }
109+ onLine : async ( output : string , process : RooTerminalProcess ) => {
110+ const compressed = Terminal . compressTerminalOutput ( output , terminalOutputLineLimit )
111+ cline . say ( "command_output" , compressed )
158112
159- debounceTimer = setTimeout ( ( ) => flush ( process ) , debounceTimeoutMs )
113+ if ( runInBackground ) {
114+ return
160115 }
116+
117+ try {
118+ const { response, text, images } = await cline . ask ( "command_output" , compressed )
119+ console . log ( `ask command_output =>` , response )
120+ runInBackground = true
121+
122+ if ( response === "yesButtonClicked" ) {
123+ // Continue running the command in the background.
124+ process . continue ( )
125+ } else if ( response === "noButtonClicked" ) {
126+ // Abort the command with a SIGINT.
127+ process . abort ( )
128+ } else {
129+ // Continue running the command in the background, but inject
130+ // the message into the context.
131+ message = { text, images }
132+ process . continue ( )
133+ }
134+ } catch ( _error ) { }
135+ } ,
136+ onCompleted : ( output : string | undefined ) => {
137+ console . log ( `onCompleted =>` , output )
138+ result = Terminal . compressTerminalOutput ( output ?? "" , terminalOutputLineLimit )
139+ completed = true
140+ } ,
141+ onShellExecutionComplete : ( details : ExitCodeDetails ) => {
142+ console . log ( `onShellExecutionComplete =>` , details )
143+ exitDetails = details
161144 } ,
162- onCompleted : ( ) => ( completed = true ) ,
163- onShellExecutionComplete : ( details : ExitCodeDetails ) => ( exitDetails = details ) ,
164145 onNoShellIntegration : async ( message : string ) => {
165146 telemetryService . captureShellIntegrationError ( cline . taskId )
166147 await cline . say ( "shell_integration_warning" , message )
@@ -178,39 +159,32 @@ export async function executeCommand(
178159
179160 await terminal . runCommand ( command , callbacks )
180161
181- if ( debounceTimer ) {
182- clearTimeout ( debounceTimer )
183- debounceTimer = null
184- }
185-
186- // If there are any lines in the buffer, flush them to `result`.
187- await flush ( )
188-
189162 // Wait for a short delay to ensure all messages are sent to the webview.
190163 // This delay allows time for non-awaited promises to be created and
191164 // for their associated messages to be sent to the webview, maintaining
192165 // the correct order of messages (although the webview is smart about
193166 // grouping command_output messages despite any gaps anyways).
194167 await delay ( 50 )
195168
196- if ( userFeedback ) {
197- await cline . say ( "user_feedback" , userFeedback . text , userFeedback . images )
169+ if ( message ) {
170+ const { text, images } = message
171+ await cline . say ( "user_feedback" , text , images )
198172
199173 return [
200174 true ,
201175 formatResponse . toolResult (
202176 `Command is still running in terminal ${ workingDirInfo } .${
203177 result . length > 0 ? `\nHere's the output so far:\n${ result } ` : ""
204- } \n\nThe user provided the following feedback:\n<feedback>\n${ userFeedback . text } \n</feedback>`,
205- userFeedback . images ,
178+ } \n\nThe user provided the following feedback:\n<feedback>\n${ text } \n</feedback>`,
179+ images ,
206180 ) ,
207181 ]
208- } else if ( completed ) {
182+ } else if ( completed || exitDetails ) {
209183 let exitStatus : string = ""
210184
211185 if ( exitDetails !== undefined ) {
212- if ( exitDetails . signal ) {
213- exitStatus = `Process terminated by signal ${ exitDetails . signal } ( ${ exitDetails . signalName } ) `
186+ if ( exitDetails . signalName ) {
187+ exitStatus = `Process terminated by signal ${ exitDetails . signalName } `
214188
215189 if ( exitDetails . coreDumpPossible ) {
216190 exitStatus += " - core dump possible"
@@ -238,8 +212,15 @@ export async function executeCommand(
238212 // }
239213
240214 const outputInfo = `\nOutput:\n${ result } `
215+ console . log ( `Command executed in terminal ${ workingDirInfo } . ${ exitStatus } ${ outputInfo } ` )
241216 return [ false , `Command executed in terminal ${ workingDirInfo } . ${ exitStatus } ${ outputInfo } ` ]
242217 } else {
218+ console . log (
219+ `Command is still running in terminal ${ workingDirInfo } .${
220+ result . length > 0 ? `\nHere's the output so far:\n${ result } ` : ""
221+ } \n\nYou will be updated on the terminal status and new output in the future.`,
222+ )
223+
243224 return [
244225 false ,
245226 `Command is still running in terminal ${ workingDirInfo } .${
0 commit comments