33 * Licensed under the MIT License. See License.txt in the project root for license information.
44 *--------------------------------------------------------------------------------------------*/
55
6- import * as nodePath from 'path' ;
6+ import * as pathLib from 'path' ;
77import vscode from 'vscode' ;
88import { parseSessionLogs , parseToolCallDetails } from '../../common/sessionParsing' ;
99import { COPILOT_ACCOUNTS } from '../common/comment' ;
@@ -24,11 +24,12 @@ import { CopilotPRWatcher, CopilotStateModel } from './copilotPrWatcher';
2424import { ChatSessionContentBuilder } from './copilotRemoteAgent/chatSessionContentBuilder' ;
2525import { GitOperationsManager } from './copilotRemoteAgent/gitOperationsManager' ;
2626import { CredentialStore } from './credentials' ;
27- import { ReposManagerState } from './folderRepositoryManager' ;
27+ import { FolderRepositoryManager , ReposManagerState } from './folderRepositoryManager' ;
2828import { GitHubRepository } from './githubRepository' ;
2929import { GithubItemStateEnum } from './interface' ;
3030import { issueMarkdown } from './markdownUtils' ;
3131import { PullRequestModel } from './pullRequestModel' ;
32+ import { chooseItem } from './quickPicks' ;
3233import { RepositoriesManager } from './repositoriesManager' ;
3334
3435const LEARN_MORE = vscode . l10n . t ( 'Learn about coding agent' ) ;
@@ -166,6 +167,11 @@ export class CopilotRemoteAgentManager extends Disposable {
166167 return false ;
167168 }
168169
170+ if ( ! this . credentialStore . isAnyAuthenticated ( ) ) {
171+ // If not signed in, then we optimistically say it's available.
172+ return true ;
173+ }
174+
169175 const repoInfo = await this . repoInfo ( ) ;
170176 if ( ! repoInfo ) {
171177 return false ;
@@ -189,14 +195,18 @@ export class CopilotRemoteAgentManager extends Disposable {
189195 }
190196 }
191197
192- async repoInfo ( ) : Promise < RepoInfo | undefined > {
193- if ( ! this . repositoriesManager . folderManagers . length ) {
194- return ;
195- }
196- const fm = this . repositoriesManager . folderManagers [ 0 ] ;
198+ private chooseFolderManager ( ) : Promise < FolderRepositoryManager | undefined > {
199+ return chooseItem < FolderRepositoryManager > (
200+ this . repositoriesManager . folderManagers ,
201+ itemValue => pathLib . basename ( itemValue . repository . rootUri . fsPath ) ,
202+ ) ;
203+ }
204+
205+ async repoInfo ( fm ?: FolderRepositoryManager ) : Promise < RepoInfo | undefined > {
206+ fm = fm || ( await this . chooseFolderManager ( ) ) ;
197207 const repository = fm ?. repository ;
198208 const ghRepository = fm ?. gitHubRepositories . find ( repo => repo . remote instanceof GitHubRemote ) as GitHubRepository | undefined ;
199- if ( ! repository || ! ghRepository ) {
209+ if ( ! fm || ! repository || ! ghRepository ) {
200210 return ;
201211 }
202212
@@ -246,11 +256,37 @@ export class CopilotRemoteAgentManager extends Disposable {
246256 }
247257 }
248258
259+ private async tryAcquireAuth ( ) : Promise < FolderRepositoryManager | undefined > {
260+ if ( this . credentialStore . isAnyAuthenticated ( ) ) {
261+ return undefined ;
262+ }
263+
264+ const result = await this . credentialStore . create ( { createIfNone : { detail : vscode . l10n . t ( 'Sign in to start delegating tasks to the GitHub coding agent.' ) } } ) ;
265+
266+ /* __GDPR__
267+ "remoteAgent.command.auth" : {
268+ "succeeded" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" }
269+ }
270+ */
271+ this . telemetry . sendTelemetryEvent ( 'remoteAgent.command.auth' , {
272+ succeeded : result . canceled ? 'false' : 'true'
273+ } ) ;
274+
275+ if ( result . canceled ) {
276+ return undefined ;
277+ }
278+ // Wait for repos to update
279+ const fm = await this . chooseFolderManager ( ) ;
280+ await fm ?. updateRepositories ( ) ;
281+ return fm ;
282+ }
283+
249284 async commandImpl ( args ?: ICopilotRemoteAgentCommandArgs ) : Promise < string | ICopilotRemoteAgentCommandResponse | undefined > {
250285 if ( ! args ) {
251286 return ;
252287 }
253288 const { userPrompt, summary, source, followup, _version } = args ;
289+ const fm = await this . tryAcquireAuth ( ) ;
254290
255291 /* __GDPR__
256292 "remoteAgent.command.args" : {
@@ -273,7 +309,7 @@ export class CopilotRemoteAgentManager extends Disposable {
273309 return ;
274310 }
275311
276- const repoInfo = await this . repoInfo ( ) ;
312+ const repoInfo = await this . repoInfo ( fm ) ;
277313 if ( ! repoInfo ) {
278314 /* __GDPR__
279315 "remoteAgent.command.result" : {
@@ -1062,7 +1098,7 @@ export class CopilotRemoteAgentManager extends Disposable {
10621098 if ( toolDetails . toolSpecificData ) {
10631099 if ( 'command' in toolDetails . toolSpecificData ) {
10641100 if ( ( toolDetails . toolSpecificData . command === 'view' || toolDetails . toolSpecificData . command === 'edit' ) && toolDetails . toolSpecificData . fileLabel ) {
1065- const uri = vscode . Uri . file ( nodePath . join ( pullRequest . githubRepository . rootUri . fsPath , toolDetails . toolSpecificData . fileLabel ) ) ;
1101+ const uri = vscode . Uri . file ( pathLib . join ( pullRequest . githubRepository . rootUri . fsPath , toolDetails . toolSpecificData . fileLabel ) ) ;
10661102 toolPart . invocationMessage = new vscode . MarkdownString ( `${ toolPart . toolName } [](${ uri . toString ( ) } )` ) ;
10671103 toolPart . invocationMessage . supportHtml = true ;
10681104 toolPart . pastTenseMessage = new vscode . MarkdownString ( `${ toolPart . toolName } [](${ uri . toString ( ) } )` ) ;
0 commit comments