@@ -122,7 +122,9 @@ export class MultiPassProcessor {
122122 issueTitle ,
123123 issueBody ,
124124 branchName ,
125- authToken
125+ authToken ,
126+ undefined , // baseBranch
127+ this . createProgressCallbackHandler ( mode ) // Add progress callback
126128 ) ;
127129
128130 return {
@@ -183,7 +185,9 @@ export class MultiPassProcessor {
183185 issueTitle ,
184186 issueBody ,
185187 primaryBranchName ,
186- authToken
188+ authToken ,
189+ undefined , // baseBranch
190+ this . createProgressCallbackHandler ( primaryMode ) // Add progress callback
187191 ) ;
188192
189193 if ( ! primaryResult . success ) {
@@ -232,7 +236,8 @@ export class MultiPassProcessor {
232236 `${ issueBody } \n\n---\n\n${ contextMessage } ` ,
233237 finalBranchName ,
234238 authToken ,
235- primaryBranchName
239+ primaryBranchName ,
240+ this . createProgressCallbackHandler ( secondaryMode ) // Add progress callback
236241 ) ;
237242
238243 // Combine the changes from both passes
@@ -265,4 +270,127 @@ export class MultiPassProcessor {
265270 } ;
266271 }
267272 }
273+
274+ /**
275+ * Creates a progress callback handler function for streaming Aider output to console
276+ */
277+ private createProgressCallbackHandler ( mode : string ) : ( status : string , data ?: any ) => void {
278+ let lastActivityTimestamp = Date . now ( ) ;
279+ let stuckWarningIssued = false ;
280+
281+ return ( status : string , data ?: any ) => {
282+ switch ( status ) {
283+ case 'starting' :
284+ console . log ( `🚀 [${ mode } ] Starting Aider process: ${ data ?. title || '' } ` ) ;
285+ break ;
286+
287+ case 'cloning' :
288+ console . log ( `📥 [${ mode } ] Cloning repository: ${ data ?. repo || '' } ` ) ;
289+ break ;
290+
291+ case 'checkout' :
292+ console . log ( `🔀 [${ mode } ] Checking out branch: ${ data ?. branch || '' } ` ) ;
293+ break ;
294+
295+ case 'branch' :
296+ console . log ( `🌿 [${ mode } ] Creating branch: ${ data ?. name || '' } ` ) ;
297+ break ;
298+
299+ case 'aider_start' :
300+ console . log ( `⚙️ [${ mode } ] Starting Aider with model: ${ data ?. model || '' } ` ) ;
301+ console . log ( ` Mode: ${ data ?. mode || 'unknown' } ` ) ;
302+ lastActivityTimestamp = Date . now ( ) ;
303+ break ;
304+
305+ case 'output' :
306+ // Only log non-empty output that's not too long for readability
307+ if ( data ?. text && data . text . trim ( ) && data . text . length < 500 ) {
308+ // Remove redundant newlines for cleaner logs
309+ const cleanedText = data . text . replace ( / \n { 3 , } / g, '\n\n' ) . trim ( ) ;
310+ console . log ( `🔄 [${ mode } ] ${ cleanedText } ` ) ;
311+ }
312+ lastActivityTimestamp = Date . now ( ) ;
313+ stuckWarningIssued = false ;
314+ break ;
315+
316+ case 'url_detected' :
317+ console . log ( `🔗 [${ mode } ] URLs detected in Aider output:` ) ;
318+ if ( data ?. urls && Array . isArray ( data . urls ) ) {
319+ data . urls . forEach ( ( url : string ) => console . log ( ` ${ url } ` ) ) ;
320+ }
321+ lastActivityTimestamp = Date . now ( ) ;
322+ break ;
323+
324+ case 'auto_response' :
325+ console . log ( `🤖 [${ mode } ] Auto-responded "${ data ?. response } " to Aider's "${ data ?. prompt } " prompt` ) ;
326+ lastActivityTimestamp = Date . now ( ) ;
327+ break ;
328+
329+ case 'health_check' :
330+ console . log ( `💓 [${ mode } ] Health check sent to Aider (inactive for ${ data ?. inactive_seconds || 0 } s, check #${ data ?. consecutive_checks || 1 } )` ) ;
331+ break ;
332+
333+ case 'forced_termination' :
334+ console . error ( `⚠️ [${ mode } ] Forcefully terminating Aider process: ${ data ?. reason || 'unknown reason' } ` ) ;
335+ console . error ( ` Inactive for ${ data ?. inactive_seconds || 0 } seconds` ) ;
336+ break ;
337+
338+ case 'max_time_reached' :
339+ console . error ( `⏰ [${ mode } ] Maximum time limit of ${ data ?. minutes || 30 } minutes reached. Force terminating Aider.` ) ;
340+ break ;
341+
342+ case 'error' :
343+ console . error ( `❌ [${ mode } ] Error: ${ data ?. text || data ?. message || 'Unknown error' } ` ) ;
344+ lastActivityTimestamp = Date . now ( ) ;
345+ break ;
346+
347+ case 'status' :
348+ if ( data ?. status === 'working' ) {
349+ const inactiveSeconds = data ?. inactive_seconds || 0 ;
350+ // Check if Aider might be stuck
351+ if ( inactiveSeconds > 120 && ! stuckWarningIssued ) { // 2 minutes of inactivity
352+ console . warn ( `⚠️ [${ mode } ] Warning: Aider has been inactive for ${ inactiveSeconds } seconds, it may be stuck` ) ;
353+ console . warn ( ` Last output: ${ data ?. last_output || 'none' } ` ) ;
354+ stuckWarningIssued = true ;
355+ }
356+ } else {
357+ console . log ( `ℹ️ [${ mode } ] Status: ${ data ?. status || 'unknown' } ` ) ;
358+ lastActivityTimestamp = Date . now ( ) ;
359+ stuckWarningIssued = false ;
360+ }
361+ break ;
362+
363+ case 'timeout' :
364+ console . warn ( `⏰ [${ mode } ] Timeout reached after ${ data ?. seconds || 'unknown' } seconds` ) ;
365+ break ;
366+
367+ case 'aider_complete' :
368+ console . log ( `✅ [${ mode } ] Aider completed with exit code: ${ data ?. exitCode } ` ) ;
369+ break ;
370+
371+ case 'no_changes' :
372+ console . log ( `ℹ️ [${ mode } ] No changes were made by Aider` ) ;
373+ break ;
374+
375+ case 'committing' :
376+ console . log ( `📝 [${ mode } ] Committing changes` ) ;
377+ break ;
378+
379+ case 'pushing' :
380+ console . log ( `📤 [${ mode } ] Pushing changes to remote` ) ;
381+ break ;
382+
383+ case 'complete' :
384+ console . log ( `🎉 [${ mode } ] Processing complete with ${ data ?. files ?. length || 0 } changed files` ) ;
385+ if ( data ?. files ?. length > 0 ) {
386+ console . log ( ` Changed files: ${ data . files . join ( ', ' ) } ` ) ;
387+ }
388+ break ;
389+
390+ default :
391+ // For any other events, just log them with data
392+ console . log ( `[${ mode } ] ${ status } : ${ JSON . stringify ( data || { } ) } ` ) ;
393+ }
394+ } ;
395+ }
268396}
0 commit comments