@@ -16,6 +16,10 @@ import { Terminal } from "./Terminal"
1616
1717export class TerminalProcess extends BaseTerminalProcess {
1818 private terminalRef : WeakRef < Terminal >
19+ private commandTimeout ?: NodeJS . Timeout
20+ private commandMaxWaitTime : number = 30000 // Default 30 seconds
21+ private autoSkippedCommands : string [ ] = [ ]
22+ private isBackgroundCommand : boolean = false
1923
2024 constructor ( terminal : Terminal ) {
2125 super ( )
@@ -44,9 +48,20 @@ export class TerminalProcess extends BaseTerminalProcess {
4448 return terminal
4549 }
4650
47- public override async run ( command : string ) {
51+ public override async run ( command : string , commandMaxWaitTime ?: number , autoSkippedCommands ?: string [ ] ) {
4852 this . command = command
4953
54+ // Update settings if provided
55+ if ( commandMaxWaitTime !== undefined ) {
56+ this . commandMaxWaitTime = commandMaxWaitTime * 1000 // Convert to milliseconds
57+ }
58+ if ( autoSkippedCommands !== undefined ) {
59+ this . autoSkippedCommands = autoSkippedCommands
60+ }
61+
62+ // Check if this command should run in background
63+ this . isBackgroundCommand = this . shouldRunInBackground ( command )
64+
5065 const terminal = this . terminal . terminal
5166
5267 const isShellIntegrationAvailable = terminal . shellIntegration && terminal . shellIntegration . executeCommand
@@ -134,6 +149,30 @@ export class TerminalProcess extends BaseTerminalProcess {
134149
135150 this . isHot = true
136151
152+ // Set up timeout for long-running commands if not a background command
153+ if ( ! this . isBackgroundCommand && this . commandMaxWaitTime > 0 ) {
154+ this . commandTimeout = setTimeout ( ( ) => {
155+ console . log (
156+ `[TerminalProcess] Command timeout reached after ${ this . commandMaxWaitTime / 1000 } seconds for: ${ command } ` ,
157+ )
158+
159+ // Emit event to allow Roo to continue with other tasks
160+ this . emit ( "command_timeout" , command )
161+
162+ // Don't abort the command, just allow Roo to continue
163+ // The command will continue running in the background
164+ this . isBackgroundCommand = true
165+ } , this . commandMaxWaitTime )
166+ }
167+
168+ // If it's a background command, emit immediately to allow Roo to continue
169+ if ( this . isBackgroundCommand ) {
170+ console . log ( `[TerminalProcess] Running command in background: ${ command } ` )
171+ setTimeout ( ( ) => {
172+ this . emit ( "background_command" , command )
173+ } , 100 ) // Small delay to ensure command starts
174+ }
175+
137176 // Wait for stream to be available
138177 let stream : AsyncIterable < string >
139178
@@ -208,6 +247,12 @@ export class TerminalProcess extends BaseTerminalProcess {
208247 // Set streamClosed immediately after stream ends.
209248 this . terminal . setActiveStream ( undefined )
210249
250+ // Clear timeout if command completed before timeout
251+ if ( this . commandTimeout ) {
252+ clearTimeout ( this . commandTimeout )
253+ this . commandTimeout = undefined
254+ }
255+
211256 // Wait for shell execution to complete.
212257 await shellExecutionComplete
213258
@@ -464,4 +509,24 @@ export class TerminalProcess extends BaseTerminalProcess {
464509
465510 return match133 !== undefined ? match133 : match633
466511 }
512+
513+ /**
514+ * Check if a command should run in the background based on patterns
515+ */
516+ private shouldRunInBackground ( command : string ) : boolean {
517+ if ( ! this . autoSkippedCommands || this . autoSkippedCommands . length === 0 ) {
518+ return false
519+ }
520+
521+ const lowerCommand = command . toLowerCase ( )
522+ return this . autoSkippedCommands . some ( ( pattern ) => {
523+ const lowerPattern = pattern . toLowerCase ( )
524+ // Support wildcards in patterns
525+ if ( lowerPattern . includes ( "*" ) ) {
526+ const regex = new RegExp ( lowerPattern . replace ( / \* / g, ".*" ) )
527+ return regex . test ( lowerCommand )
528+ }
529+ return lowerCommand . includes ( lowerPattern )
530+ } )
531+ }
467532}
0 commit comments