From 51b031b60f3b589db0b8ca5d0b70d4113097344c Mon Sep 17 00:00:00 2001 From: Rob Lourens Date: Fri, 2 Aug 2024 17:51:05 -0700 Subject: [PATCH] Add a notification when loading a version of the chat extension that has a proposed API incompatibility (#224649) * Add a notification when loading a version of the chat extension that has a proposed API incompatibility Fix #218646 * Fix activation phase --- .../contrib/chat/browser/chat.contribution.ts | 3 +- .../browser/chatParticipantContributions.ts | 33 +++++++++++++++++++ 2 files changed, 35 insertions(+), 1 deletion(-) diff --git a/src/vs/workbench/contrib/chat/browser/chat.contribution.ts b/src/vs/workbench/contrib/chat/browser/chat.contribution.ts index d2f8311dd0ab3..9a3fadd1e8aa4 100644 --- a/src/vs/workbench/contrib/chat/browser/chat.contribution.ts +++ b/src/vs/workbench/contrib/chat/browser/chat.contribution.ts @@ -34,7 +34,7 @@ import { ChatAccessibilityService } from 'vs/workbench/contrib/chat/browser/chat import { ChatEditor, IChatEditorOptions } from 'vs/workbench/contrib/chat/browser/chatEditor'; import { ChatEditorInput, ChatEditorInputSerializer } from 'vs/workbench/contrib/chat/browser/chatEditorInput'; import { agentSlashCommandToMarkdown, agentToMarkdown } from 'vs/workbench/contrib/chat/browser/chatMarkdownDecorationsRenderer'; -import { ChatExtensionPointHandler } from 'vs/workbench/contrib/chat/browser/chatParticipantContributions'; +import { ChatCompatibilityNotifier, ChatExtensionPointHandler } from 'vs/workbench/contrib/chat/browser/chatParticipantContributions'; import { QuickChatService } from 'vs/workbench/contrib/chat/browser/chatQuick'; import { ChatResponseAccessibleView } from 'vs/workbench/contrib/chat/browser/chatResponseAccessibleView'; import { ChatVariablesService } from 'vs/workbench/contrib/chat/browser/chatVariables'; @@ -255,6 +255,7 @@ registerWorkbenchContribution2(ChatResolverContribution.ID, ChatResolverContribu workbenchContributionsRegistry.registerWorkbenchContribution(ChatSlashStaticSlashCommandsContribution, LifecyclePhase.Eventually); Registry.as(EditorExtensions.EditorFactory).registerEditorSerializer(ChatEditorInput.TypeID, ChatEditorInputSerializer); registerWorkbenchContribution2(ChatExtensionPointHandler.ID, ChatExtensionPointHandler, WorkbenchPhase.BlockStartup); +registerWorkbenchContribution2(ChatCompatibilityNotifier.ID, ChatCompatibilityNotifier, WorkbenchPhase.Eventually); registerWorkbenchContribution2(LanguageModelToolsExtensionPointHandler.ID, LanguageModelToolsExtensionPointHandler, WorkbenchPhase.BlockRestore); registerChatActions(); diff --git a/src/vs/workbench/contrib/chat/browser/chatParticipantContributions.ts b/src/vs/workbench/contrib/chat/browser/chatParticipantContributions.ts index b4d532e3d1894..aa461ef6572e3 100644 --- a/src/vs/workbench/contrib/chat/browser/chatParticipantContributions.ts +++ b/src/vs/workbench/contrib/chat/browser/chatParticipantContributions.ts @@ -3,14 +3,17 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ +import { Action } from 'vs/base/common/actions'; import { isNonEmptyArray } from 'vs/base/common/arrays'; import { Codicon } from 'vs/base/common/codicons'; import { Disposable, DisposableMap, DisposableStore, IDisposable, toDisposable } from 'vs/base/common/lifecycle'; import * as strings from 'vs/base/common/strings'; import { localize, localize2 } from 'vs/nls'; +import { ICommandService } from 'vs/platform/commands/common/commands'; import { ExtensionIdentifier } from 'vs/platform/extensions/common/extensions'; import { SyncDescriptor } from 'vs/platform/instantiation/common/descriptors'; import { ILogService } from 'vs/platform/log/common/log'; +import { INotificationService, Severity } from 'vs/platform/notification/common/notification'; import { Registry } from 'vs/platform/registry/common/platform'; import { ViewPaneContainer } from 'vs/workbench/browser/parts/views/viewPaneContainer'; import { IWorkbenchContribution } from 'vs/workbench/common/contributions'; @@ -19,6 +22,7 @@ import { CHAT_VIEW_ID } from 'vs/workbench/contrib/chat/browser/chat'; import { CHAT_SIDEBAR_PANEL_ID, ChatViewPane } from 'vs/workbench/contrib/chat/browser/chatViewPane'; import { ChatAgentLocation, IChatAgentData, IChatAgentService } from 'vs/workbench/contrib/chat/common/chatAgents'; import { IRawChatParticipantContribution } from 'vs/workbench/contrib/chat/common/chatParticipantContribTypes'; +import { IExtensionsWorkbenchService } from 'vs/workbench/contrib/extensions/common/extensions'; import { isProposedApiEnabled } from 'vs/workbench/services/extensions/common/extensions'; import * as extensionsRegistry from 'vs/workbench/services/extensions/common/extensionsRegistry'; @@ -104,6 +108,35 @@ const chatParticipantExtensionPoint = extensionsRegistry.ExtensionsRegistry.regi }, }); +export class ChatCompatibilityNotifier implements IWorkbenchContribution { + static readonly ID = 'workbench.contrib.chatCompatNotifier'; + + constructor( + @IExtensionsWorkbenchService extensionsWorkbenchService: IExtensionsWorkbenchService, + @INotificationService notificationService: INotificationService, + @ICommandService commandService: ICommandService + ) { + // It may be better to have some generic UI for this, for any extension that is incompatible, + // but this is only enabled for Copilot Chat now and it needs to be obvious. + extensionsWorkbenchService.queryLocal().then(exts => { + const chat = exts.find(ext => ext.identifier.id === 'github.copilot-chat'); + if (chat?.local?.validations.some(v => v[0] === Severity.Error)) { + notificationService.notify({ + severity: Severity.Error, + message: localize('chatFailErrorMessage', "Chat failed to load. Please ensure that the GitHub Copilot Chat extension is up to date."), + actions: { + primary: [ + new Action('showExtension', localize('action.showExtension', "Show Extension"), undefined, true, () => { + return commandService.executeCommand('workbench.extensions.action.showExtensionsWithIds', ['GitHub.copilot-chat']); + }) + ] + } + }); + } + }); + } +} + export class ChatExtensionPointHandler implements IWorkbenchContribution { static readonly ID = 'workbench.contrib.chatExtensionPointHandler';