@@ -44,6 +44,7 @@ const CONTINUE = vscode.l10n.t('Continue');
4444// With Pending Changes
4545const PUSH_CHANGES = vscode . l10n . t ( 'Include changes' ) ;
4646const CONTINUE_WITHOUT_PUSHING = vscode . l10n . t ( 'Ignore changes' ) ;
47+ const COMMIT_YOUR_CHANGES = vscode . l10n . t ( 'Commit your changes to continue coding agent session. Close integrated terminal to cancel.' ) ;
4748
4849const FOLLOW_UP_REGEX = / o p e n - p u l l - r e q u e s t - w e b v i e w .* ( ( % 7 B .* ?% 7 D ) | ( \{ .* ?\} ) ) / ;
4950const COPILOT = '@copilot' ;
@@ -394,41 +395,47 @@ export class CopilotRemoteAgentManager extends Disposable {
394395 * Opens a terminal and waits for user to successfully commit
395396 * This is a fallback for when the commit cannot be done automatically (eg: GPG signing password needed)
396397 */
397- private async handleInteractiveCommit ( repository : Repository , commitMessage : string ) : Promise < boolean > {
398+ private async handleInteractiveCommit ( repository : Repository , cancellationToken ?: vscode . CancellationToken ) : Promise < boolean > {
398399 return new Promise < boolean > ( ( resolve ) => {
399400 const startingCommit = repository . state . HEAD ?. commit ;
400401
401402 // Create terminal with git commit command
402403 const terminal = vscode . window . createTerminal ( {
403404 name : 'GitHub Coding Agent' ,
404405 cwd : repository . rootUri . fsPath ,
405- message : vscode . l10n . t ( 'Commit your changes to continue coding agent session' )
406+ message : `\x1b[1m ${ vscode . l10n . t ( COMMIT_YOUR_CHANGES ) } \x1b[0m`
406407 } ) ;
407408
408409 // Show terminal and send commit command
409410 terminal . show ( ) ;
410- terminal . sendText ( `# Complete this commit to continue with your coding agent session. Ctrl+C to cancel.` ) ;
411- terminal . sendText ( `git commit -m "${ commitMessage } "` ) ;
412-
413411 let disposed = false ;
414412 let timeoutId : NodeJS . Timeout ;
415413 let stateListener : vscode . Disposable | undefined ;
416414 let disposalListener : vscode . Disposable | undefined ;
415+ let cancellationListener : vscode . Disposable | undefined ;
417416
418417 const cleanup = ( ) => {
419418 if ( disposed ) return ;
420419 disposed = true ;
421420 clearTimeout ( timeoutId ) ;
422421 stateListener ?. dispose ( ) ;
423422 disposalListener ?. dispose ( ) ;
423+ cancellationListener ?. dispose ( ) ;
424424 terminal . dispose ( ) ;
425425 } ;
426426
427+ // Listen for cancellation if token is provided
428+ if ( cancellationToken ) {
429+ cancellationListener = cancellationToken . onCancellationRequested ( ( ) => {
430+ cleanup ( ) ;
431+ resolve ( false ) ;
432+ } ) ;
433+ }
434+
427435 // Listen for repository state changes
428436 stateListener = repository . state . onDidChange ( ( ) => {
429437 // Check if commit was successful (HEAD changed and no more staged changes)
430- if ( repository . state . HEAD ?. commit !== startingCommit &&
431- repository . state . indexChanges . length === 0 ) {
438+ if ( repository . state . HEAD ?. commit !== startingCommit ) {
432439 cleanup ( ) ;
433440 resolve ( true ) ;
434441 }
@@ -437,22 +444,17 @@ export class CopilotRemoteAgentManager extends Disposable {
437444 // Set a timeout to avoid waiting forever
438445 timeoutId = setTimeout ( ( ) => {
439446 cleanup ( ) ;
440- vscode . window . showWarningMessage (
441- vscode . l10n . t ( 'Commit timeout. Please try the operation again after committing your changes.' )
442- ) ;
443447 resolve ( false ) ;
444448 } , 5 * 60 * 1000 ) ; // 5 minutes timeout
445449
446450 // Listen for terminal disposal (user closed it)
447451 disposalListener = vscode . window . onDidCloseTerminal ( ( closedTerminal ) => {
448452 if ( closedTerminal === terminal ) {
449- // Give a brief moment for potential state changes to propagate
450453 setTimeout ( ( ) => {
451454 if ( ! disposed ) {
452455 cleanup ( ) ;
453456 // Check one more time if commit happened just before terminal was closed
454- resolve ( repository . state . HEAD ?. commit !== startingCommit &&
455- repository . state . indexChanges . length === 0 ) ;
457+ resolve ( repository . state . HEAD ?. commit !== startingCommit ) ;
456458 }
457459 } , 1000 ) ;
458460 }
@@ -494,31 +496,20 @@ export class CopilotRemoteAgentManager extends Disposable {
494496 } catch ( e ) {
495497 // Instead of immediately failing, open terminal for interactive commit
496498 const commitSuccessful = await vscode . window . withProgress ( {
497- title : vscode . l10n . t ( 'Waiting for commit to complete in the integrated terminal...' ) ,
499+ title : COMMIT_YOUR_CHANGES ,
498500 cancellable : true ,
499501 location : vscode . ProgressLocation . Notification
500502 } , async ( progress , token ) => {
501- const commitPromise = this . handleInteractiveCommit ( repository , commitMessage ) ;
502- if ( token ) {
503- token . onCancellationRequested ( ( ) => {
504- return false ;
505- } ) ;
506- }
503+ const commitPromise = this . handleInteractiveCommit ( repository , token ) ;
507504 return await commitPromise ;
508505 } ) ;
509506 if ( ! commitSuccessful ) {
510- return { error : vscode . l10n . t ( 'Commit was unsuccessful. Manually commit or stash your changes and try again.' ) , state : 'error' } ;
507+ return { error : vscode . l10n . t ( 'Exclude your uncommitted changes and try again.' ) , state : 'error' } ;
511508 }
512509 }
513510 await repository . push ( remote . remoteName , asyncBranch , true ) ;
514511 ref = asyncBranch ;
515- } catch ( e ) {
516- return { error : vscode . l10n . t ( 'Could not auto-push pending changes. Manually commit or stash your changes and try again. ({0})' , e . message ) , state : 'error' } ;
517- } finally {
518- // Swap back to the original branch without your pending changes
519- // TODO: Better if we show a confirmation dialog in chat
520512 if ( repository . state . HEAD ?. name !== baseRef ) {
521- // show notification asking the user if they want to switch back to the original branch
522513 const SWAP_BACK_TO_ORIGINAL_BRANCH = vscode . l10n . t ( `Swap back to '{0}'` , baseRef ) ;
523514 vscode . window . showInformationMessage (
524515 vscode . l10n . t ( `Pending changes pushed to remote branch '{0}'.` , ref ) ,
@@ -529,6 +520,16 @@ export class CopilotRemoteAgentManager extends Disposable {
529520 }
530521 } ) ;
531522 }
523+ } catch ( e ) {
524+ if ( repository . state . HEAD ?. name !== baseRef ) {
525+ try {
526+ await repository . checkout ( baseRef ) ;
527+ } catch ( checkoutError ) {
528+ Logger . error ( `Failed to checkout back to original branch '${ baseRef } ': ${ checkoutError } ` , CopilotRemoteAgentManager . ID ) ;
529+ }
530+ }
531+ Logger . error ( `Failed to auto-commit and push pending changes: ${ e } ` , CopilotRemoteAgentManager . ID ) ;
532+ return { error : vscode . l10n . t ( 'Could not auto-push pending changes. Manually commit or stash your changes and try again. ({0})' , e . message ) , state : 'error' } ;
532533 }
533534 }
534535
0 commit comments