|
3 | 3 | * Licensed under the MIT License. See License.txt in the project root for license information. |
4 | 4 | *--------------------------------------------------------------------------------------------*/ |
5 | 5 |
|
| 6 | +import './media/chat.css'; |
| 7 | +import './media/chatAgentHover.css'; |
| 8 | +import './media/chatViewWelcome.css'; |
6 | 9 | import * as dom from '../../../../base/browser/dom.js'; |
7 | 10 | import { IMouseWheelEvent } from '../../../../base/browser/mouseEvent.js'; |
8 | 11 | import { Button } from '../../../../base/browser/ui/button/button.js'; |
@@ -50,11 +53,10 @@ import { ITelemetryService } from '../../../../platform/telemetry/common/telemet |
50 | 53 | import { buttonSecondaryBackground, buttonSecondaryForeground, buttonSecondaryHoverBackground } from '../../../../platform/theme/common/colorRegistry.js'; |
51 | 54 | import { asCssVariable } from '../../../../platform/theme/common/colorUtils.js'; |
52 | 55 | import { IThemeService } from '../../../../platform/theme/common/themeService.js'; |
53 | | -import { IWorkspaceContextService, WorkbenchState } from '../../../../platform/workspace/common/workspace.js'; |
54 | 56 | import { EditorResourceAccessor } from '../../../../workbench/common/editor.js'; |
55 | 57 | import { IEditorService } from '../../../../workbench/services/editor/common/editorService.js'; |
56 | 58 | import { ViewContainerLocation } from '../../../common/views.js'; |
57 | | -import { ChatEntitlement, IChatEntitlementService } from '../../../services/chat/common/chatEntitlementService.js'; |
| 59 | +import { IChatEntitlementService } from '../../../services/chat/common/chatEntitlementService.js'; |
58 | 60 | import { IWorkbenchLayoutService, Position } from '../../../services/layout/browser/layoutService.js'; |
59 | 61 | import { IViewsService } from '../../../services/views/common/viewsService.js'; |
60 | 62 | import { checkModeOption } from '../common/chat.js'; |
@@ -90,10 +92,8 @@ import { ChatInputPart, IChatInputPartOptions, IChatInputStyles } from './chatIn |
90 | 92 | import { ChatListDelegate, ChatListItemRenderer, IChatListItemTemplate, IChatRendererDelegate } from './chatListRenderer.js'; |
91 | 93 | import { ChatEditorOptions } from './chatOptions.js'; |
92 | 94 | import { ChatViewPane } from './chatViewPane.js'; |
93 | | -import './media/chat.css'; |
94 | | -import './media/chatAgentHover.css'; |
95 | | -import './media/chatViewWelcome.css'; |
96 | 95 | import { ChatViewWelcomePart, IChatSuggestedPrompts, IChatViewWelcomeContent } from './viewsWelcome/chatViewWelcomeController.js'; |
| 96 | +import { IWorkspaceContextService, WorkbenchState } from '../../../../platform/workspace/common/workspace.js'; |
97 | 97 |
|
98 | 98 | const $ = dom.$; |
99 | 99 |
|
@@ -379,7 +379,6 @@ export class ChatWidget extends Disposable implements IChatWidget { |
379 | 379 | private readonly _lockedToCodingAgentContextKey: IContextKey<boolean>; |
380 | 380 | private readonly _agentSupportsAttachmentsContextKey: IContextKey<boolean>; |
381 | 381 | private _attachmentCapabilities: IChatAgentAttachmentCapabilities = supportsAllAttachments; |
382 | | - private lastWelcomeViewChatMode: ChatModeKind | undefined; |
383 | 382 |
|
384 | 383 | // Cache for prompt file descriptions to avoid async calls during rendering |
385 | 384 | private readonly promptDescriptionsCache = new Map<string, string>(); |
@@ -455,12 +454,6 @@ export class ChatWidget extends Disposable implements IChatWidget { |
455 | 454 |
|
456 | 455 | readonly viewContext: IChatWidgetViewContext; |
457 | 456 |
|
458 | | - private shouldShowChatSetup(): boolean { |
459 | | - // Check if chat is not installed OR user can sign up for free |
460 | | - // Equivalent to: ChatContextKeys.Setup.installed.negate() OR ChatContextKeys.Entitlement.canSignUp |
461 | | - return !this.chatEntitlementService.sentiment.installed || this.chatEntitlementService.entitlement === ChatEntitlement.Available; |
462 | | - } |
463 | | - |
464 | 457 | get supportsChangingModes(): boolean { |
465 | 458 | return !!this.viewOptions.supportsChangingModes; |
466 | 459 | } |
@@ -495,14 +488,14 @@ export class ChatWidget extends Disposable implements IChatWidget { |
495 | 488 | @ITelemetryService private readonly telemetryService: ITelemetryService, |
496 | 489 | @IPromptsService private readonly promptsService: IPromptsService, |
497 | 490 | @ILanguageModelToolsService private readonly toolsService: ILanguageModelToolsService, |
498 | | - @IWorkspaceContextService private readonly contextService: IWorkspaceContextService, |
499 | 491 | @IChatModeService private readonly chatModeService: IChatModeService, |
500 | 492 | @IChatLayoutService private readonly chatLayoutService: IChatLayoutService, |
501 | 493 | @IChatEntitlementService private readonly chatEntitlementService: IChatEntitlementService, |
502 | 494 | @ICommandService private readonly commandService: ICommandService, |
503 | 495 | @IHoverService private readonly hoverService: IHoverService, |
504 | 496 | @IChatSessionsService private readonly chatSessionsService: IChatSessionsService, |
505 | | - @IChatTodoListService private readonly chatTodoListService: IChatTodoListService |
| 497 | + @IChatTodoListService private readonly chatTodoListService: IChatTodoListService, |
| 498 | + @IWorkspaceContextService private readonly contextService: IWorkspaceContextService, |
506 | 499 | ) { |
507 | 500 | super(); |
508 | 501 | this._lockedToCodingAgentContextKey = ChatContextKeys.lockedToCodingAgent.bindTo(this.contextKeyService); |
@@ -692,35 +685,13 @@ export class ChatWidget extends Disposable implements IChatWidget { |
692 | 685 |
|
693 | 686 | this._register(this.onDidChangeParsedInput(() => this.updateChatInputContext())); |
694 | 687 |
|
695 | | - // Listen to entitlement and sentiment changes instead of context keys |
696 | | - this._register(this.chatEntitlementService.onDidChangeEntitlement(() => { |
697 | | - if (!this.shouldShowChatSetup()) { |
698 | | - this.resetWelcomeViewInput(); |
699 | | - } |
700 | | - })); |
701 | | - this._register(this.chatEntitlementService.onDidChangeSentiment(() => { |
702 | | - if (!this.shouldShowChatSetup()) { |
703 | | - this.resetWelcomeViewInput(); |
704 | | - } |
705 | | - })); |
706 | 688 | this._register(this.chatTodoListService.onDidUpdateTodos((sessionId) => { |
707 | 689 | if (this.viewModel?.sessionId === sessionId) { |
708 | 690 | this.inputPart.renderChatTodoListWidget(sessionId); |
709 | 691 | } |
710 | 692 | })); |
711 | 693 | } |
712 | 694 |
|
713 | | - private resetWelcomeViewInput(): void { |
714 | | - // reset the input in welcome view if it was rendered in experimental mode |
715 | | - if (this.container.classList.contains('new-welcome-view')) { |
716 | | - this.container.classList.remove('new-welcome-view'); |
717 | | - const renderFollowups = this.viewOptions.renderFollowups ?? false; |
718 | | - const renderStyle = this.viewOptions.renderStyle; |
719 | | - this.createInput(this.container, { renderFollowups, renderStyle }); |
720 | | - this.input.setChatMode(this.lastWelcomeViewChatMode ?? ChatModeKind.Agent); |
721 | | - } |
722 | | - } |
723 | | - |
724 | 695 | private _lastSelectedAgent: IChatAgentData | undefined; |
725 | 696 | set lastSelectedAgent(agent: IChatAgentData | undefined) { |
726 | 697 | this.parsedChatRequest = undefined; |
@@ -1004,13 +975,6 @@ export class ChatWidget extends Disposable implements IChatWidget { |
1004 | 975 | }); |
1005 | 976 |
|
1006 | 977 |
|
1007 | | - // reset the input in welcome view if it was rendered in experimental mode |
1008 | | - if (this.viewModel?.getItems().length) { |
1009 | | - this.resetWelcomeViewInput(); |
1010 | | - // TODO@bhavyaus |
1011 | | - // this.focusInput(); |
1012 | | - } |
1013 | | - |
1014 | 978 | if (treeItems.length > 0) { |
1015 | 979 | this.updateChatViewVisibility(); |
1016 | 980 | } else { |
@@ -1089,14 +1053,16 @@ export class ChatWidget extends Disposable implements IChatWidget { |
1089 | 1053 |
|
1090 | 1054 | let welcomeContent: IChatViewWelcomeContent; |
1091 | 1055 | const defaultAgent = this.chatAgentService.getDefaultAgent(this.location, this.input.currentModeKind); |
1092 | | - let additionalMessage = defaultAgent?.metadata.additionalWelcomeMessage; |
| 1056 | + let additionalMessage: string | IMarkdownString | undefined; |
| 1057 | + if (this.chatEntitlementService.anonymous && !this.chatEntitlementService.sentiment.installed) { |
| 1058 | + additionalMessage = new MarkdownString(localize({ key: 'settings', comment: ['{Locked="]({2})"}', '{Locked="]({3})"}'] }, "By continuing with {0} Copilot, you agree to {1}'s [Terms]({2}) and [Privacy Statement]({3}).", defaultChat.provider.default.name, defaultChat.provider.default.name, defaultChat.termsStatementUrl, defaultChat.privacyStatementUrl), { isTrusted: true }); |
| 1059 | + } else { |
| 1060 | + additionalMessage = defaultAgent?.metadata.additionalWelcomeMessage; |
| 1061 | + } |
1093 | 1062 | if (!additionalMessage && !this._lockedAgent) { |
1094 | 1063 | additionalMessage = this._getGenerateInstructionsMessage(); |
1095 | 1064 | } |
1096 | | - if (this.shouldShowChatSetup()) { |
1097 | | - welcomeContent = this.getNewWelcomeViewContent(); |
1098 | | - this.container.classList.add('new-welcome-view'); |
1099 | | - } else if (expEmptyState) { |
| 1065 | + if (expEmptyState) { |
1100 | 1066 | welcomeContent = this.getWelcomeViewContent(additionalMessage, expEmptyState); |
1101 | 1067 | } else { |
1102 | 1068 | const defaultTips = this.input.currentModeKind === ChatModeKind.Ask |
@@ -1440,71 +1406,40 @@ export class ChatWidget extends Disposable implements IChatWidget { |
1440 | 1406 | } |
1441 | 1407 | } |
1442 | 1408 |
|
1443 | | - private getNewWelcomeViewContent(): IChatViewWelcomeContent { |
1444 | | - let additionalMessage: string | IMarkdownString | undefined = undefined; |
1445 | | - if (this.chatEntitlementService.anonymous) { |
1446 | | - additionalMessage = new MarkdownString(localize({ key: 'settings', comment: ['{Locked="]({2})"}', '{Locked="]({3})"}'] }, "AI responses may be inaccurate.\nBy continuing with {0} Copilot, you agree to {1}'s [Terms]({2}) and [Privacy Statement]({3}).", defaultChat.provider.default.name, defaultChat.provider.default.name, defaultChat.termsStatementUrl, defaultChat.privacyStatementUrl), { isTrusted: true }); |
1447 | | - } else { |
1448 | | - additionalMessage = localize('expChatAdditionalMessage', "AI responses may be inaccurate."); |
1449 | | - } |
1450 | | - |
1451 | | - // Check for provider-specific customizations |
1452 | | - const providerIcon = this._lockedAgent?.id ? this.chatSessionsService.getIconForSessionType(this._lockedAgent.id) : undefined; |
1453 | | - const providerTitle = this._lockedAgent ? this.chatSessionsService.getWelcomeTitleForSessionType(this._lockedAgent.id) : undefined; |
1454 | | - const providerMessage = this._lockedAgent ? this.chatSessionsService.getWelcomeMessageForSessionType(this._lockedAgent.id) : undefined; |
1455 | | - const providerTips = this._lockedAgent ? this.chatSessionsService.getWelcomeTipsForSessionType(this._lockedAgent.id) : undefined; |
1456 | | - const suggestedPrompts = this._lockedAgent ? undefined : this.getNewSuggestedPrompts(); |
1457 | | - const welcomeContent: IChatViewWelcomeContent = { |
1458 | | - title: providerTitle ?? localize('expChatTitle', 'Build with agents'), |
1459 | | - message: providerMessage ? new MarkdownString(providerMessage) : new MarkdownString(localize('expchatMessage', "Let's get started")), |
1460 | | - icon: providerIcon ?? Codicon.chatSparkle, |
1461 | | - inputPart: this.inputPart.element, |
1462 | | - additionalMessage, |
1463 | | - isNew: true, |
1464 | | - suggestedPrompts, |
1465 | | - useLargeIcon: !!providerIcon, |
1466 | | - }; |
1467 | | - |
1468 | | - // Add contributed tips if available |
1469 | | - if (providerTips) { |
1470 | | - welcomeContent.tips = new MarkdownString(providerTips, { supportThemeIcons: true }); |
1471 | | - } |
1472 | | - return welcomeContent; |
1473 | | - } |
| 1409 | + private getPromptFileSuggestions(): IChatSuggestedPrompts[] { |
1474 | 1410 |
|
1475 | | - private getNewSuggestedPrompts(): IChatSuggestedPrompts[] { |
1476 | | - // Check if the workbench is empty |
1477 | | - const isEmpty = this.contextService.getWorkbenchState() === WorkbenchState.EMPTY; |
1478 | | - if (isEmpty) { |
1479 | | - return [ |
1480 | | - { |
1481 | | - icon: Codicon.vscode, |
1482 | | - label: localize('chatWidget.suggestedPrompts.gettingStarted', "Ask @vscode"), |
1483 | | - prompt: localize('chatWidget.suggestedPrompts.gettingStartedPrompt', "@vscode How do I change the theme to light mode?"), |
1484 | | - }, |
1485 | | - { |
1486 | | - icon: Codicon.newFolder, |
1487 | | - label: localize('chatWidget.suggestedPrompts.newProject', "Create Project"), |
1488 | | - prompt: localize('chatWidget.suggestedPrompts.newProjectPrompt', "Create a #new Hello World project in TypeScript"), |
1489 | | - } |
1490 | | - ]; |
1491 | | - } else { |
1492 | | - return [ |
1493 | | - { |
1494 | | - icon: Codicon.debugAlt, |
1495 | | - label: localize('chatWidget.suggestedPrompts.buildWorkspace', "Build Workspace"), |
1496 | | - prompt: localize('chatWidget.suggestedPrompts.buildWorkspacePrompt', "How do I build this workspace?"), |
1497 | | - }, |
1498 | | - { |
1499 | | - icon: Codicon.gear, |
1500 | | - label: localize('chatWidget.suggestedPrompts.findConfig', "Show Config"), |
1501 | | - prompt: localize('chatWidget.suggestedPrompts.findConfigPrompt', "Where is the configuration for this project defined?"), |
1502 | | - } |
1503 | | - ]; |
| 1411 | + // Use predefined suggestions for new users |
| 1412 | + if (!this.chatEntitlementService.sentiment.installed) { |
| 1413 | + const isEmpty = this.contextService.getWorkbenchState() === WorkbenchState.EMPTY; |
| 1414 | + if (isEmpty) { |
| 1415 | + return [ |
| 1416 | + { |
| 1417 | + icon: Codicon.vscode, |
| 1418 | + label: localize('chatWidget.suggestedPrompts.gettingStarted', "Ask @vscode"), |
| 1419 | + prompt: localize('chatWidget.suggestedPrompts.gettingStartedPrompt', "@vscode How do I change the theme to light mode?"), |
| 1420 | + }, |
| 1421 | + { |
| 1422 | + icon: Codicon.newFolder, |
| 1423 | + label: localize('chatWidget.suggestedPrompts.newProject', "Create Project"), |
| 1424 | + prompt: localize('chatWidget.suggestedPrompts.newProjectPrompt', "Create a #new Hello World project in TypeScript"), |
| 1425 | + } |
| 1426 | + ]; |
| 1427 | + } else { |
| 1428 | + return [ |
| 1429 | + { |
| 1430 | + icon: Codicon.debugAlt, |
| 1431 | + label: localize('chatWidget.suggestedPrompts.buildWorkspace', "Build Workspace"), |
| 1432 | + prompt: localize('chatWidget.suggestedPrompts.buildWorkspacePrompt', "How do I build this workspace?"), |
| 1433 | + }, |
| 1434 | + { |
| 1435 | + icon: Codicon.gear, |
| 1436 | + label: localize('chatWidget.suggestedPrompts.findConfig', "Show Config"), |
| 1437 | + prompt: localize('chatWidget.suggestedPrompts.findConfigPrompt', "Where is the configuration for this project defined?"), |
| 1438 | + } |
| 1439 | + ]; |
| 1440 | + } |
1504 | 1441 | } |
1505 | | - } |
1506 | 1442 |
|
1507 | | - private getPromptFileSuggestions(): IChatSuggestedPrompts[] { |
1508 | 1443 | // Get the current workspace folder context if available |
1509 | 1444 | const activeEditor = this.editorService.activeEditor; |
1510 | 1445 | const resource = activeEditor ? EditorResourceAccessor.getOriginalUri(activeEditor) : undefined; |
@@ -2268,7 +2203,6 @@ export class ChatWidget extends Disposable implements IChatWidget { |
2268 | 2203 | this._welcomeRenderScheduler.schedule(); |
2269 | 2204 | })); |
2270 | 2205 | this._register(this.input.onDidChangeCurrentChatMode(() => { |
2271 | | - this.lastWelcomeViewChatMode = this.input.currentModeKind; |
2272 | 2206 | this._welcomeRenderScheduler.schedule(); |
2273 | 2207 | this.refreshParsedInput(); |
2274 | 2208 | this.renderFollowups(); |
@@ -2757,11 +2691,7 @@ export class ChatWidget extends Disposable implements IChatWidget { |
2757 | 2691 | this.inlineInputPart?.layout(layoutHeight, width); |
2758 | 2692 | } |
2759 | 2693 |
|
2760 | | - if (this.container.classList.contains('new-welcome-view')) { |
2761 | | - this.inputPart.layout(layoutHeight, Math.min(width, 650)); |
2762 | | - } else { |
2763 | | - this.inputPart.layout(layoutHeight, width); |
2764 | | - } |
| 2694 | + this.inputPart.layout(layoutHeight, width); |
2765 | 2695 |
|
2766 | 2696 | const inputHeight = this.inputPart.inputPartHeight; |
2767 | 2697 | const chatSuggestNextWidgetHeight = this.chatSuggestNextWidget.height; |
|
0 commit comments