@@ -10,6 +10,7 @@ import {
1010} from '../../../../plus/gk/utils/-webview/mcp.utils' ;
1111import { registerCommand } from '../../../../system/-webview/command' ;
1212import { configuration } from '../../../../system/-webview/configuration' ;
13+ import { setContext } from '../../../../system/-webview/context' ;
1314import { getHostAppName , isHostVSCode } from '../../../../system/-webview/vscode' ;
1415import { openUrl } from '../../../../system/-webview/vscode/uris' ;
1516import { gate } from '../../../../system/decorators/gate' ;
@@ -61,15 +62,18 @@ export class GkCliIntegrationProvider implements Disposable {
6162
6263 this . onConfigurationChanged ( ) ;
6364
65+ const cliInstall = this . container . storage . get ( 'gk:cli:install' ) ;
6466 if ( mcpExtensionRegistrationAllowed ( ) ) {
65- const cliInstall = this . container . storage . get ( 'gk:cli:install' ) ;
6667 if ( ! cliInstall || ( cliInstall . status === 'attempted' && cliInstall . attempts < 5 ) ) {
6768 setTimeout (
6869 ( ) => this . installCLI ( true , 'gk-cli-integration' ) ,
6970 10000 + Math . floor ( Math . random ( ) * 20000 ) ,
7071 ) ;
7172 }
7273 }
74+ if ( cliInstall ?. status === 'completed' ) {
75+ void setContext ( 'gitlens:gk:cli:installed' , true ) ;
76+ }
7377 }
7478
7579 dispose ( ) : void {
@@ -108,7 +112,7 @@ export class GkCliIntegrationProvider implements Disposable {
108112
109113 @gate ( )
110114 @log ( { exit : true } )
111- private async setupMCP ( source ?: Sources ) : Promise < void > {
115+ private async setupMCP ( source ?: Sources , force = false ) : Promise < void > {
112116 const scope = getLogScope ( ) ;
113117
114118 await this . container . storage . store ( 'mcp:banner:dismissed' , true ) ;
@@ -159,7 +163,7 @@ export class GkCliIntegrationProvider implements Disposable {
159163 cliVersion : installedVersion ,
160164 cliPath : installedPath ,
161165 status,
162- } = await this . installCLI ( false , source ) ;
166+ } = await this . installCLI ( false , source , force ) ;
163167 if ( status === 'unsupported' ) {
164168 throw new CLIInstallError ( CLIInstallErrorReason . UnsupportedPlatform ) ;
165169 } else if ( status === 'attempted' ) {
@@ -334,34 +338,39 @@ export class GkCliIntegrationProvider implements Disposable {
334338 private async installCLI (
335339 autoInstall ?: boolean ,
336340 source ?: Sources ,
341+ force = false ,
337342 ) : Promise < { cliVersion ?: string ; cliPath ?: string ; status : 'completed' | 'unsupported' | 'attempted' } > {
338343 const scope = getLogScope ( ) ;
339344
340345 const cliInstall = this . container . storage . get ( 'gk:cli:install' ) ;
341- let cliInstallAttempts = cliInstall ?. attempts ?? 0 ;
346+ let cliInstallAttempts = force ? 0 : ( cliInstall ?. attempts ?? 0 ) ;
342347 let cliInstallStatus = cliInstall ?. status ?? 'attempted' ;
343348 let cliVersion = cliInstall ?. version ;
344349 let cliPath = this . container . storage . get ( 'gk:cli:path' ) ;
345350 const platform = getPlatform ( ) ;
346351
347- if ( cliInstallStatus === 'completed' ) {
348- if ( cliPath == null ) {
349- cliInstallStatus = 'attempted' ;
350- cliVersion = undefined ;
351- } else {
352- cliVersion = cliInstall ?. version ;
353- try {
354- await workspace . fs . stat ( Uri . joinPath ( Uri . file ( cliPath ) , platform === 'windows' ? 'gk.exe' : 'gk' ) ) ;
355- return { cliVersion : cliVersion , cliPath : cliPath , status : 'completed' } ;
356- } catch {
352+ if ( ! force ) {
353+ if ( cliInstallStatus === 'completed' ) {
354+ if ( cliPath == null ) {
357355 cliInstallStatus = 'attempted' ;
358356 cliVersion = undefined ;
357+ } else {
358+ cliVersion = cliInstall ?. version ;
359+ try {
360+ await workspace . fs . stat (
361+ Uri . joinPath ( Uri . file ( cliPath ) , platform === 'windows' ? 'gk.exe' : 'gk' ) ,
362+ ) ;
363+ return { cliVersion : cliVersion , cliPath : cliPath , status : 'completed' } ;
364+ } catch {
365+ cliInstallStatus = 'attempted' ;
366+ cliVersion = undefined ;
367+ }
359368 }
369+ } else if ( cliInstallStatus === 'unsupported' ) {
370+ return { cliVersion : undefined , cliPath : undefined , status : 'unsupported' } ;
371+ } else if ( autoInstall && cliInstallStatus === 'attempted' && cliInstallAttempts >= 5 ) {
372+ return { cliVersion : undefined , cliPath : undefined , status : 'attempted' } ;
360373 }
361- } else if ( cliInstallStatus === 'unsupported' ) {
362- return { cliVersion : undefined , cliPath : undefined , status : 'unsupported' } ;
363- } else if ( autoInstall && cliInstallStatus === 'attempted' && cliInstallAttempts >= 5 ) {
364- return { cliVersion : undefined , cliPath : undefined , status : 'attempted' } ;
365374 }
366375
367376 try {
@@ -587,6 +596,7 @@ export class GkCliIntegrationProvider implements Disposable {
587596 version : cliVersion ,
588597 } )
589598 . catch ( ) ;
599+ void setContext ( 'gitlens:gk:cli:installed' , true ) ;
590600 if ( this . container . telemetry . enabled ) {
591601 this . container . telemetry . sendEvent ( 'cli/install/succeeded' , {
592602 autoInstall : autoInstall ?? false ,
@@ -674,7 +684,10 @@ export class GkCliIntegrationProvider implements Disposable {
674684 }
675685
676686 private registerCommands ( ) : Disposable [ ] {
677- return [ registerCommand ( 'gitlens.ai.mcp.install' , ( src ?: Source ) => this . setupMCP ( src ?. source ) ) ] ;
687+ return [
688+ registerCommand ( 'gitlens.ai.mcp.install' , ( src ?: Source ) => this . setupMCP ( src ?. source ) ) ,
689+ registerCommand ( 'gitlens.ai.mcp.reinstall' , ( src ?: Source ) => this . setupMCP ( src ?. source , true ) ) ,
690+ ] ;
678691 }
679692}
680693
0 commit comments