@@ -59,6 +59,7 @@ import { mainWindow } from '../../../../base/browser/window.js';
59
59
import { IOpenerService } from '../../../../platform/opener/common/opener.js' ;
60
60
import { URI } from '../../../../base/common/uri.js' ;
61
61
import { IHostService } from '../../../services/host/browser/host.js' ;
62
+ import Severity from '../../../../base/common/severity.js' ;
62
63
63
64
const defaultChat = {
64
65
extensionId : product . defaultChatAgent ?. extensionId ?? '' ,
@@ -365,6 +366,8 @@ class ChatSetupRequests extends Disposable {
365
366
@ILogService private readonly logService : ILogService ,
366
367
@IRequestService private readonly requestService : IRequestService ,
367
368
@IChatQuotasService private readonly chatQuotasService : IChatQuotasService ,
369
+ @IDialogService private readonly dialogService : IDialogService ,
370
+ @IOpenerService private readonly openerService : IOpenerService
368
371
) {
369
372
super ( ) ;
370
373
@@ -486,7 +489,12 @@ class ChatSetupRequests extends Disposable {
486
489
return { entitlement : ChatEntitlement . Unresolved } ;
487
490
}
488
491
489
- const responseText = await asText ( response ) ;
492
+ let responseText : string | null = null ;
493
+ try {
494
+ responseText = await asText ( response ) ;
495
+ } catch ( error ) {
496
+ // ignore - handled below
497
+ }
490
498
if ( token . isCancellationRequested ) {
491
499
return undefined ;
492
500
}
@@ -589,18 +597,38 @@ class ChatSetupRequests extends Disposable {
589
597
590
598
const response = await this . request ( defaultChat . entitlementSignupLimitedUrl , 'POST' , body , session , CancellationToken . None ) ;
591
599
if ( ! response ) {
592
- this . logService . error ( '[chat setup] sign-up: no response' ) ;
600
+ this . onUnknownSignUpError ( '[chat setup] sign-up: no response' ) ;
593
601
return false ;
594
602
}
595
603
596
604
if ( response . res . statusCode && response . res . statusCode !== 200 ) {
597
- this . logService . error ( `[chat setup] sign-up: unexpected status code ${ response . res . statusCode } ` ) ;
605
+ if ( response . res . statusCode === 422 ) {
606
+ try {
607
+ const responseText = await asText ( response ) ;
608
+ if ( responseText ) {
609
+ const responseError : { message : string } = JSON . parse ( responseText ) ;
610
+ if ( typeof responseError . message === 'string' && responseError . message ) {
611
+ this . onUnprocessableSignUpError ( `[chat setup] sign-up: unprocessable entity (${ responseError . message } )` , responseError . message ) ;
612
+ return false ;
613
+ }
614
+ }
615
+ } catch ( error ) {
616
+ // ignore - handled below
617
+ }
618
+ }
619
+ this . onUnknownSignUpError ( `[chat setup] sign-up: unexpected status code ${ response . res . statusCode } ` ) ;
598
620
return false ;
599
621
}
600
622
601
- const responseText = await asText ( response ) ;
623
+ let responseText : string | null = null ;
624
+ try {
625
+ responseText = await asText ( response ) ;
626
+ } catch ( error ) {
627
+ // ignore - handled below
628
+ }
629
+
602
630
if ( ! responseText ) {
603
- this . logService . error ( '[chat setup] sign-up: response has no content' ) ;
631
+ this . onUnknownSignUpError ( '[chat setup] sign-up: response has no content' ) ;
604
632
return false ;
605
633
}
606
634
@@ -609,7 +637,7 @@ class ChatSetupRequests extends Disposable {
609
637
parsedResult = JSON . parse ( responseText ) ;
610
638
this . logService . trace ( `[chat setup] sign-up: response is ${ responseText } ` ) ;
611
639
} catch ( err ) {
612
- this . logService . error ( `[chat setup] sign-up: error parsing response (${ err } )` ) ;
640
+ this . onUnknownSignUpError ( `[chat setup] sign-up: error parsing response (${ err } )` ) ;
613
641
}
614
642
615
643
const subscribed = Boolean ( parsedResult ?. subscribed ) ;
@@ -626,6 +654,30 @@ class ChatSetupRequests extends Disposable {
626
654
return subscribed ;
627
655
}
628
656
657
+ private onUnknownSignUpError ( logMessage : string ) : void {
658
+ this . dialogService . error ( localize ( 'unknownSignUpError' , "An error occurred while signing up for Copilot Free." ) , localize ( 'unknownSignUpErrorDetail' , "Please try again." ) ) ;
659
+ this . logService . error ( logMessage ) ;
660
+ }
661
+
662
+ private onUnprocessableSignUpError ( logMessage : string , logDetails : string ) : void {
663
+ this . dialogService . prompt ( {
664
+ type : Severity . Error ,
665
+ message : localize ( 'unprocessableSignUpError' , "An error occurred while signing up for Copilot Free." ) ,
666
+ detail : logDetails ,
667
+ buttons : [
668
+ {
669
+ label : localize ( 'ok' , "OK" ) ,
670
+ run : ( ) => { /* noop */ }
671
+ } ,
672
+ {
673
+ label : localize ( 'learnMore' , "Learn More" ) ,
674
+ run : ( ) => this . openerService . open ( URI . parse ( defaultChat . upgradePlanUrl ) )
675
+ }
676
+ ] ,
677
+ } ) ;
678
+ this . logService . error ( logMessage ) ;
679
+ }
680
+
629
681
override dispose ( ) : void {
630
682
this . pendingResolveCts . dispose ( true ) ;
631
683
@@ -644,7 +696,7 @@ type InstallChatClassification = {
644
696
signedIn : { classification : 'SystemMetaData' ; purpose : 'FeatureInsight' ; comment : 'Whether the user did sign in prior to installing the extension.' } ;
645
697
} ;
646
698
type InstallChatEvent = {
647
- installResult : 'installed' | 'cancelled' | 'failedInstall' | 'failedNotSignedIn' ;
699
+ installResult : 'installed' | 'cancelled' | 'failedInstall' | 'failedNotSignedIn' | 'failedSignUp' ;
648
700
signedIn : boolean ;
649
701
} ;
650
702
@@ -790,6 +842,10 @@ class ChatSetupController extends Disposable {
790
842
791
843
if ( entitlement !== ChatEntitlement . Limited && entitlement !== ChatEntitlement . Pro && entitlement !== ChatEntitlement . Unavailable ) {
792
844
didSignUp = await this . requests . signUpLimited ( session ) ;
845
+
846
+ if ( ! didSignUp ) {
847
+ this . telemetryService . publicLog2 < InstallChatEvent , InstallChatClassification > ( 'commandCenter.chatInstall' , { installResult : 'failedSignUp' , signedIn } ) ;
848
+ }
793
849
}
794
850
795
851
await this . extensionsWorkbenchService . install ( defaultChat . extensionId , {
0 commit comments