| File: Providers\CopilotCliDetectionProvider.cs | Web Access |
| Project: Microsoft.DotNet.Cli.InternalMicrosoft.csproj (Microsoft.DotNet.Cli.InternalMicrosoft) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. namespace Microsoft.DotNet.Cli.InternalMicrosoft; /// <summary> /// Checks supported GitHub tokens from Copilot CLI settings. /// The detector reuses this stateless provider for process-wide detection. /// </summary> internal sealed class CopilotCliDetectionProvider : IInternalMicrosoftDetectionProvider { private const int MaxTokenCandidates = 5; public string Name => "Copilot CLI GitHub org membership"; public int Stage => 2; public bool IsSupported(InternalMicrosoftDetectionContext context) => !context.IsCIEnvironment; public Task<InternalMicrosoftProbeResult> DetectAsync( InternalMicrosoftDetectionContext context, CancellationToken cancellationToken) => new GitHubMembershipClient(context).CheckAnyAsync(GetCandidates(context), cancellationToken); private static IEnumerable<GitHubTokenCandidate> GetCandidates(InternalMicrosoftDetectionContext context) { var seen = new HashSet<string>(StringComparer.Ordinal); var count = 0; foreach (var (name, value) in context.GetEnvironmentVariables() .Where(variable => variable.Name.StartsWith( "COPILOT_GH_ACCOUNT_", StringComparison.OrdinalIgnoreCase)) .OrderBy(variable => variable.Name, StringComparer.OrdinalIgnoreCase)) { if (InternalMicrosoftDetectionUtilities.IsGitHubToken(value) && seen.Add(value!) && count++ < MaxTokenCandidates) { yield return new(name, value!); } } foreach (var fileName in new[] { "config.json", "settings.json" }) { if (count >= MaxTokenCandidates) { yield break; } var path = Path.Combine(context.HomeDirectory, ".copilot", fileName); foreach (var token in InternalMicrosoftDetectionUtilities.ReadGitHubTokensFromJsonFile(path)) { if (seen.Add(token) && count++ < MaxTokenCandidates) { yield return new(fileName, token); } } } } }