1+ import { homedir } from 'os' ;
12import { arch } from 'process' ;
23import type { ConfigurationChangeEvent } from 'vscode' ;
34import { Disposable , env , ProgressLocation , Uri , window , workspace } from 'vscode' ;
45import type { Container } from '../../../../container' ;
6+ import type { SubscriptionChangeEvent } from '../../../../plus/gk/subscriptionService' ;
57import { registerCommand } from '../../../../system/-webview/command' ;
68import { configuration } from '../../../../system/-webview/configuration' ;
79import { getContext } from '../../../../system/-webview/context' ;
@@ -26,6 +28,7 @@ export class GkCliIntegrationProvider implements Disposable {
2628 constructor ( private readonly container : Container ) {
2729 this . _disposable = Disposable . from (
2830 configuration . onDidChange ( e => this . onConfigurationChanged ( e ) ) ,
31+ this . container . subscription . onDidChange ( this . onSubscriptionChanged , this ) ,
2932 ...this . registerCommands ( ) ,
3033 ) ;
3134
@@ -260,7 +263,7 @@ export class GkCliIntegrationProvider implements Disposable {
260263
261264 // Configure the MCP server in settings.json
262265 try {
263- const installOutput = await run ( mcpFileName , [ 'install' ] , 'utf8' , { cwd : mcpExtractedFolderPath . fsPath } ) ;
266+ const installOutput = await run ( platform === 'windows' ? mcpFileName : `./ ${ mcpFileName } ` , [ 'install' ] , 'utf8' , { cwd : mcpExtractedFolderPath . fsPath } ) ;
264267 const directory = installOutput . match ( / D i r e c t o r y : ( .* ) / ) ;
265268 if ( directory != null ) {
266269 try {
@@ -276,60 +279,57 @@ export class GkCliIntegrationProvider implements Disposable {
276279 'utf8' ,
277280 ) ;
278281 } else {
279- await run (
280- 'export' ,
281- [ `PATH=$PATH:${ directoryPath } ` ] ,
282- 'utf8' ,
283- ) ;
282+ // For Unix-like systems, detect and modify the appropriate shell profile
283+ const homeDir = homedir ( ) ;
284+ // Try to detect which shell profile exists and is in use
285+ const possibleProfiles = [
286+ { path : `${ homeDir } /.zshrc` , shell : 'zsh' } ,
287+ { path : `${ homeDir } /.zprofile` , shell : 'zsh' } ,
288+ { path : `${ homeDir } /.bashrc` , shell : 'bash' } ,
289+ { path : `${ homeDir } /.profile` , shell : 'sh' }
290+ ] ;
291+
292+ // Find the first profile that exists
293+ let shellProfile ;
294+ for ( const profile of possibleProfiles ) {
295+ try {
296+ await workspace . fs . stat ( Uri . file ( profile . path ) ) ;
297+ shellProfile = profile . path ;
298+ break ;
299+ } catch {
300+ // Profile doesn't exist, try next one
301+ }
302+ }
303+
304+ if ( shellProfile != null ) {
305+ await run (
306+ 'sh' ,
307+ [ '-c' , `echo '# Added by GitLens for MCP support' >> ${ shellProfile } && echo 'export PATH="$PATH:${ directoryPath } "' >> ${ shellProfile } ` ] ,
308+ 'utf8' ,
309+ ) ;
310+ } else {
311+ Logger . warn ( 'MCP Install: Failed to find shell profile to update PATH' ) ;
312+ }
284313 }
285314 } catch ( error ) {
286- Logger . warn ( `Failed to add GK directory to PATH: ${ error } ` ) ;
315+ Logger . warn ( `MCP Install: Failed to add directory to PATH: ${ error } ` ) ;
287316 }
288317 } else {
289- Logger . warn ( 'Failed to find directory in GK install output' ) ;
318+ Logger . warn ( 'MCP Install: Failed to find directory in install output' ) ;
290319 }
291320
292- await run ( mcpFileName , [ 'mcp' , 'install' , appName , ...isInsiders ? [ '--file-path' , settingsPath ] : [ ] ] , 'utf8' , { cwd : mcpExtractedFolderPath . fsPath } ) ;
293-
321+ await run ( platform === 'windows' ? mcpFileName : `./${ mcpFileName } ` , [ 'mcp' , 'install' , appName , ...isInsiders ? [ '--file-path' , settingsPath ] : [ ] ] , 'utf8' , { cwd : mcpExtractedFolderPath . fsPath } ) ;
294322 const gkAuth = ( await this . container . subscription . getAuthenticationSession ( ) ) ?. accessToken ;
295323 if ( gkAuth != null ) {
296- await run ( mcpFileName , [ 'auth' , 'login' , '-t' , gkAuth ] , 'utf8' , { cwd : mcpExtractedFolderPath . fsPath } ) ;
297- }
298- } catch {
299- // Try alternative execution methods based on platform
300- try {
301- Logger . log ( 'Attempting alternative execution method for MCP install...' ) ;
302- if ( platform === 'windows' ) {
303- // On Windows, try running with cmd.exe
304- await run (
305- 'cmd.exe' ,
306- [
307- '/c' ,
308- `"${ mcpExtractedPath . fsPath } "` ,
309- 'mcp' ,
310- 'install' ,
311- appName ,
312- ...isInsiders ? [ '--file-path' , settingsPath ] : [ ] ,
313- ] ,
314- 'utf8' ,
315- ) ;
316- } else {
317- // On Unix-like systems, try running with sh
318- await run (
319- '/bin/sh' ,
320- // ['-c', `"${mcpExtractedPath.fsPath}" mcp install vscode --file-path "${settingsPath}"`],
321- [ '-c' , `"${ mcpExtractedPath . fsPath } " mcp install ${ appName } ${ isInsiders ? `--file-path ${ settingsPath } ` : '' } ` ] ,
322- 'utf8' ,
323- ) ;
324- }
325- } catch ( altError ) {
326- const errorMsg = `MCP server configuration failed: ${ altError } ` ;
327- Logger . error ( errorMsg ) ;
328- throw new Error ( errorMsg ) ;
324+ await run ( platform === 'windows' ? mcpFileName : `./${ mcpFileName } ` , [ 'auth' , 'login' , '-t' , gkAuth ] , 'utf8' , { cwd : mcpExtractedFolderPath . fsPath } ) ;
329325 }
330- }
331326
332- Logger . log ( 'MCP configuration completed' ) ;
327+ Logger . log ( 'MCP configuration completed' ) ;
328+ } catch ( error ) {
329+ const errorMsg = `MCP server configuration failed: ${ error } ` ;
330+ Logger . error ( errorMsg ) ;
331+ throw new Error ( errorMsg ) ;
332+ }
333333 } finally {
334334 // Always clean up downloaded/extracted files, even if something failed
335335 if ( mcpInstallerPath != null ) {
@@ -388,6 +388,21 @@ export class GkCliIntegrationProvider implements Disposable {
388388 }
389389 }
390390
391+ private async onSubscriptionChanged ( e : SubscriptionChangeEvent ) : Promise < void > {
392+ const mcpInstallStatus = this . container . storage . get ( 'ai:mcp:attemptInstall' ) ;
393+ const mcpDirectoryPath = this . container . storage . get ( 'gk:cli:installedPath' ) ;
394+ const platform = getPlatform ( ) ;
395+ if ( e . current ?. account ?. id != null && e . current . account . id !== e . previous ?. account ?. id && mcpInstallStatus === 'completed' && mcpDirectoryPath != null ) {
396+ const currentSessionToken = ( await this . container . subscription . getAuthenticationSession ( ) ) ?. accessToken ;
397+ if ( currentSessionToken != null ) {
398+ try {
399+ await run ( platform === 'windows' ? 'gk.exe' : './gk' , [ 'auth' , 'login' , '-t' , currentSessionToken ] , 'utf8' , { cwd : mcpDirectoryPath } ) ;
400+ } catch { }
401+ }
402+ }
403+ }
404+
405+
391406 private registerCommands ( ) : Disposable [ ] {
392407 return [ registerCommand ( 'gitlens.ai.mcp.install' , ( ) => this . installMCPIfNeeded ( ) ) ] ;
393408 }
0 commit comments