mirror of
https://github.com/microsoft/vscode.git
synced 2026-02-20 17:59:17 +00:00
Chat sign-in: auto-enable GitHub Authentication extension if silently disabled (#296303)
* Initial plan * Auto-enable GitHub Authentication extension during chat sign-in if disabled Co-authored-by: TylerLeonhardt <2644648+TylerLeonhardt@users.noreply.github.com> * Apply during the chat request * feedback * delete the tests that didn't exist in the first place --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: TylerLeonhardt <2644648+TylerLeonhardt@users.noreply.github.com> Co-authored-by: Tyler Leonhardt <tyleonha@microsoft.com>
This commit is contained in:
@@ -116,6 +116,7 @@
|
||||
"name": "Apple"
|
||||
}
|
||||
},
|
||||
"providerExtensionId": "vscode.github-authentication",
|
||||
"providerUriSetting": "github-enterprise.uri",
|
||||
"providerScopes": [
|
||||
[
|
||||
|
||||
@@ -360,6 +360,7 @@ export interface IDefaultChatAgent {
|
||||
apple: { id: string; name: string };
|
||||
};
|
||||
|
||||
readonly providerExtensionId: string;
|
||||
readonly providerUriSetting: string;
|
||||
readonly providerScopes: string[][];
|
||||
|
||||
|
||||
@@ -4,11 +4,17 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { ICommandService } from '../../../../../platform/commands/common/commands.js';
|
||||
import { ExtensionIdentifier } from '../../../../../platform/extensions/common/extensions.js';
|
||||
import { ILogService } from '../../../../../platform/log/common/log.js';
|
||||
import product from '../../../../../platform/product/common/product.js';
|
||||
import { localize } from '../../../../../nls.js';
|
||||
import { EnablementState } from '../../../../services/extensionManagement/common/extensionManagement.js';
|
||||
import { IExtensionsWorkbenchService } from '../../../extensions/common/extensions.js';
|
||||
|
||||
const defaultChat = {
|
||||
completionsRefreshTokenCommand: product.defaultChatAgent?.completionsRefreshTokenCommand ?? '',
|
||||
chatRefreshTokenCommand: product.defaultChatAgent?.chatRefreshTokenCommand ?? '',
|
||||
providerExtensionId: product.defaultChatAgent?.providerExtensionId ?? '',
|
||||
};
|
||||
|
||||
export type InstallChatClassification = {
|
||||
@@ -59,3 +65,44 @@ export function refreshTokens(commandService: ICommandService): void {
|
||||
commandService.executeCommand(defaultChat.completionsRefreshTokenCommand);
|
||||
commandService.executeCommand(defaultChat.chatRefreshTokenCommand);
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensures the authentication provider extension is enabled.
|
||||
* If the extension is found locally but disabled, it will be
|
||||
* re-enabled and running extensions will be updated.
|
||||
*
|
||||
* @returns `true` if the extension was re-enabled, `false` otherwise.
|
||||
*/
|
||||
export async function maybeEnableAuthExtension(
|
||||
extensionsWorkbenchService: IExtensionsWorkbenchService,
|
||||
logService: ILogService
|
||||
): Promise<boolean> {
|
||||
if (!defaultChat.providerExtensionId) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const providerExtension = extensionsWorkbenchService.local.find(
|
||||
e => ExtensionIdentifier.equals(e.identifier.id, defaultChat.providerExtensionId)
|
||||
);
|
||||
|
||||
if (!providerExtension) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (
|
||||
providerExtension.enablementState === EnablementState.DisabledGlobally ||
|
||||
providerExtension.enablementState === EnablementState.DisabledWorkspace
|
||||
) {
|
||||
logService.info(`[chat setup] auth provider extension '${defaultChat.providerExtensionId}' is disabled, re-enabling it`);
|
||||
try {
|
||||
await extensionsWorkbenchService.setEnablement([providerExtension], EnablementState.EnabledGlobally);
|
||||
await extensionsWorkbenchService.updateRunningExtensions(localize('enableAuthExtension', "Enabling GitHub Authentication"));
|
||||
return true;
|
||||
} catch (error) {
|
||||
logService.error(`[chat setup] failed to re-enable auth provider extension '${defaultChat.providerExtensionId}'`, error);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -28,7 +28,7 @@ import { IExtensionsWorkbenchService } from '../../../extensions/common/extensio
|
||||
import { ChatEntitlement, ChatEntitlementContext, ChatEntitlementRequests, isProUser } from '../../../../services/chat/common/chatEntitlementService.js';
|
||||
import { CHAT_OPEN_ACTION_ID } from '../actions/chatActions.js';
|
||||
import { ChatViewId, ChatViewContainerId } from '../chat.js';
|
||||
import { ChatSetupAnonymous, ChatSetupStep, ChatSetupResultValue, InstallChatEvent, InstallChatClassification, refreshTokens } from './chatSetup.js';
|
||||
import { ChatSetupAnonymous, ChatSetupStep, ChatSetupResultValue, InstallChatEvent, InstallChatClassification, refreshTokens, maybeEnableAuthExtension } from './chatSetup.js';
|
||||
import { IDefaultAccount } from '../../../../../base/common/defaultAccount.js';
|
||||
import { IDefaultAccountService } from '../../../../../platform/defaultAccount/common/defaultAccount.js';
|
||||
|
||||
@@ -153,6 +153,11 @@ export class ChatSetupController extends Disposable {
|
||||
}
|
||||
|
||||
private async signIn(options: IChatSetupControllerOptions): Promise<{ defaultAccount: IDefaultAccount | undefined; entitlement: ChatEntitlement | undefined }> {
|
||||
const authExtensionReEnabled = await maybeEnableAuthExtension(this.extensionsWorkbenchService, this.logService);
|
||||
if (authExtensionReEnabled) {
|
||||
refreshTokens(this.commandService);
|
||||
}
|
||||
|
||||
let entitlements;
|
||||
let defaultAccount;
|
||||
try {
|
||||
|
||||
@@ -47,13 +47,14 @@ import { ACTION_START as INLINE_CHAT_START } from '../../../inlineChat/common/in
|
||||
import { IPosition } from '../../../../../editor/common/core/position.js';
|
||||
import { IMarker, IMarkerService, MarkerSeverity } from '../../../../../platform/markers/common/markers.js';
|
||||
import { ChatSetupController } from './chatSetupController.js';
|
||||
import { ChatSetupAnonymous, ChatSetupStep, IChatSetupResult } from './chatSetup.js';
|
||||
import { ChatSetupAnonymous, ChatSetupStep, IChatSetupResult, maybeEnableAuthExtension, refreshTokens } from './chatSetup.js';
|
||||
import { ChatSetup } from './chatSetupRunner.js';
|
||||
import { chatViewsWelcomeRegistry } from '../viewsWelcome/chatViewsWelcome.js';
|
||||
import { CommandsRegistry, ICommandService } from '../../../../../platform/commands/common/commands.js';
|
||||
import { IDefaultAccountService } from '../../../../../platform/defaultAccount/common/defaultAccount.js';
|
||||
import { IHostService } from '../../../../services/host/browser/host.js';
|
||||
import { IOutputService } from '../../../../services/output/common/output.js';
|
||||
import { IExtensionsWorkbenchService } from '../../../extensions/common/extensions.js';
|
||||
|
||||
const defaultChat = {
|
||||
extensionId: product.defaultChatAgent?.extensionId ?? '',
|
||||
@@ -197,6 +198,8 @@ export class SetupAgent extends Disposable implements IChatAgentImplementation {
|
||||
@IViewsService private readonly viewsService: IViewsService,
|
||||
@IContextKeyService private readonly contextKeyService: IContextKeyService,
|
||||
@IOutputService private readonly outputService: IOutputService,
|
||||
@IExtensionsWorkbenchService private readonly extensionsWorkbenchService: IExtensionsWorkbenchService,
|
||||
@ICommandService private readonly commandService: ICommandService,
|
||||
) {
|
||||
super();
|
||||
|
||||
@@ -315,6 +318,15 @@ export class SetupAgent extends Disposable implements IChatAgentImplementation {
|
||||
}
|
||||
|
||||
private async doForwardRequestToChatWhenReady(requestModel: IChatRequestModel, progress: (part: IChatProgress) => void, chatService: IChatService, languageModelsService: ILanguageModelsService, chatAgentService: IChatAgentService, chatWidgetService: IChatWidgetService, languageModelToolsService: ILanguageModelToolsService): Promise<void> {
|
||||
|
||||
// Ensure auth extension is enabled before waiting for chat readiness.
|
||||
// This must run before the readiness event listeners are set up because
|
||||
// updateRunningExtensions restarts all extension hosts.
|
||||
const authExtensionReEnabled = await maybeEnableAuthExtension(this.extensionsWorkbenchService, this.logService);
|
||||
if (authExtensionReEnabled) {
|
||||
refreshTokens(this.commandService);
|
||||
}
|
||||
|
||||
const widget = chatWidgetService.getWidgetBySessionResource(requestModel.session.sessionResource);
|
||||
const modeInfo = widget?.input.currentModeInfo;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user