Path: blob/main/src/vs/workbench/contrib/chat/browser/chatContentParts/chatQuotaExceededPart.ts
3296 views
/*---------------------------------------------------------------------------------------------1* Copyright (c) Microsoft Corporation. All rights reserved.2* Licensed under the MIT License. See License.txt in the project root for license information.3*--------------------------------------------------------------------------------------------*/45import * as dom from '../../../../../base/browser/dom.js';6import { Button } from '../../../../../base/browser/ui/button/button.js';7import { WorkbenchActionExecutedClassification, WorkbenchActionExecutedEvent } from '../../../../../base/common/actions.js';8import { Codicon } from '../../../../../base/common/codicons.js';9import { Emitter } from '../../../../../base/common/event.js';10import { MarkdownString } from '../../../../../base/common/htmlContent.js';11import { Disposable, IDisposable } from '../../../../../base/common/lifecycle.js';12import { ThemeIcon } from '../../../../../base/common/themables.js';13import { assertType } from '../../../../../base/common/types.js';14import { MarkdownRenderer } from '../../../../../editor/browser/widget/markdownRenderer/browser/markdownRenderer.js';15import { localize } from '../../../../../nls.js';16import { ICommandService } from '../../../../../platform/commands/common/commands.js';17import { ITelemetryService } from '../../../../../platform/telemetry/common/telemetry.js';18import { defaultButtonStyles } from '../../../../../platform/theme/browser/defaultStyles.js';19import { asCssVariable, textLinkForeground } from '../../../../../platform/theme/common/colorRegistry.js';20import { ChatEntitlement, IChatEntitlementService } from '../../common/chatEntitlementService.js';21import { IChatErrorDetailsPart, IChatRendererContent, IChatResponseViewModel } from '../../common/chatViewModel.js';22import { IChatWidgetService } from '../chat.js';23import { IChatContentPart } from './chatContentParts.js';2425const $ = dom.$;2627/**28* Once the sign up button is clicked, and the retry button has been shown, it should be shown every time.29*/30let shouldShowRetryButton = false;3132/**33* Once the 'retry' button is clicked, the wait warning should be shown every time.34*/35let shouldShowWaitWarning = false;3637export class ChatQuotaExceededPart extends Disposable implements IChatContentPart {38public readonly domNode: HTMLElement;3940private readonly _onDidChangeHeight = this._register(new Emitter<void>());41public readonly onDidChangeHeight = this._onDidChangeHeight.event;4243constructor(44element: IChatResponseViewModel,45private readonly content: IChatErrorDetailsPart,46renderer: MarkdownRenderer,47@IChatWidgetService chatWidgetService: IChatWidgetService,48@ICommandService commandService: ICommandService,49@ITelemetryService telemetryService: ITelemetryService,50@IChatEntitlementService chatEntitlementService: IChatEntitlementService51) {52super();5354const errorDetails = element.errorDetails;55assertType(!!errorDetails, 'errorDetails');5657this.domNode = $('.chat-quota-error-widget');58const icon = dom.append(this.domNode, $('span'));59icon.classList.add(...ThemeIcon.asClassNameArray(Codicon.warning));6061const messageContainer = dom.append(this.domNode, $('.chat-quota-error-message'));62const markdownContent = renderer.render(new MarkdownString(errorDetails.message));63dom.append(messageContainer, markdownContent.element);6465let button1Label = '';66switch (chatEntitlementService.entitlement) {67case ChatEntitlement.Pro:68case ChatEntitlement.ProPlus:69button1Label = localize('enableAdditionalUsage', "Manage paid premium requests");70break;71case ChatEntitlement.Free:72button1Label = localize('upgradeToCopilotPro', "Upgrade to GitHub Copilot Pro");73break;74default:75button1Label = '';76}7778let hasAddedWaitWarning = false;79const addWaitWarningIfNeeded = () => {80if (!shouldShowWaitWarning || hasAddedWaitWarning) {81return;82}8384hasAddedWaitWarning = true;85dom.append(messageContainer, $('.chat-quota-wait-warning', undefined, localize('waitWarning', "Changes may take a few minutes to take effect.")));86};8788let hasAddedRetryButton = false;89const addRetryButtonIfNeeded = () => {90if (!shouldShowRetryButton || hasAddedRetryButton) {91return;92}9394hasAddedRetryButton = true;95const button2 = this._register(new Button(messageContainer, {96buttonBackground: undefined,97buttonForeground: asCssVariable(textLinkForeground)98}));99button2.element.classList.add('chat-quota-error-secondary-button');100button2.label = localize('clickToContinue', "Click to retry.");101this._onDidChangeHeight.fire();102this._register(button2.onDidClick(() => {103const widget = chatWidgetService.getWidgetBySessionId(element.sessionId);104if (!widget) {105return;106}107108widget.rerunLastRequest();109110shouldShowWaitWarning = true;111addWaitWarningIfNeeded();112}));113};114115if (button1Label) {116const button1 = this._register(new Button(messageContainer, { ...defaultButtonStyles, supportIcons: true }));117button1.label = button1Label;118button1.element.classList.add('chat-quota-error-button');119this._register(button1.onDidClick(async () => {120const commandId = chatEntitlementService.entitlement === ChatEntitlement.Free ? 'workbench.action.chat.upgradePlan' : 'workbench.action.chat.manageOverages';121telemetryService.publicLog2<WorkbenchActionExecutedEvent, WorkbenchActionExecutedClassification>('workbenchActionExecuted', { id: commandId, from: 'chat-response' });122await commandService.executeCommand(commandId);123124shouldShowRetryButton = true;125addRetryButtonIfNeeded();126}));127}128129addRetryButtonIfNeeded();130addWaitWarningIfNeeded();131}132133hasSameContent(other: IChatRendererContent): boolean {134return other.kind === this.content.kind && !!other.errorDetails.isQuotaExceeded;135}136137addDisposable(disposable: IDisposable): void {138this._register(disposable);139}140}141142143