Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
microsoft
GitHub Repository: microsoft/vscode
Path: blob/main/src/vs/workbench/contrib/chat/browser/modelPicker/modePickerActionItem.ts
3296 views
1
/*---------------------------------------------------------------------------------------------
2
* Copyright (c) Microsoft Corporation. All rights reserved.
3
* Licensed under the MIT License. See License.txt in the project root for license information.
4
*--------------------------------------------------------------------------------------------*/
5
6
import * as dom from '../../../../../base/browser/dom.js';
7
import { renderLabelWithIcons } from '../../../../../base/browser/ui/iconLabel/iconLabels.js';
8
import { IAction } from '../../../../../base/common/actions.js';
9
import { IDisposable } from '../../../../../base/common/lifecycle.js';
10
import { autorun, IObservable } from '../../../../../base/common/observable.js';
11
import { localize } from '../../../../../nls.js';
12
import { ActionWidgetDropdownActionViewItem } from '../../../../../platform/actions/browser/actionWidgetDropdownActionViewItem.js';
13
import { getFlatActionBarActions } from '../../../../../platform/actions/browser/menuEntryActionViewItem.js';
14
import { IMenuService, MenuId, MenuItemAction } from '../../../../../platform/actions/common/actions.js';
15
import { IActionWidgetService } from '../../../../../platform/actionWidget/browser/actionWidget.js';
16
import { IActionWidgetDropdownAction, IActionWidgetDropdownActionProvider, IActionWidgetDropdownOptions } from '../../../../../platform/actionWidget/browser/actionWidgetDropdown.js';
17
import { ICommandService } from '../../../../../platform/commands/common/commands.js';
18
import { IContextKeyService } from '../../../../../platform/contextkey/common/contextkey.js';
19
import { IKeybindingService } from '../../../../../platform/keybinding/common/keybinding.js';
20
import { IChatAgentService } from '../../common/chatAgents.js';
21
import { IChatMode, IChatModeService } from '../../common/chatModes.js';
22
import { ChatAgentLocation } from '../../common/constants.js';
23
import { getOpenChatActionIdForMode } from '../actions/chatActions.js';
24
import { IToggleChatModeArgs, ToggleAgentModeActionId } from '../actions/chatExecuteActions.js';
25
26
export interface IModePickerDelegate {
27
readonly currentMode: IObservable<IChatMode>;
28
}
29
30
export class ModePickerActionItem extends ActionWidgetDropdownActionViewItem {
31
constructor(
32
action: MenuItemAction,
33
private readonly delegate: IModePickerDelegate,
34
@IActionWidgetService actionWidgetService: IActionWidgetService,
35
@IChatAgentService chatAgentService: IChatAgentService,
36
@IKeybindingService keybindingService: IKeybindingService,
37
@IContextKeyService private readonly contextKeyService: IContextKeyService,
38
@IChatModeService chatModeService: IChatModeService,
39
@IMenuService private readonly menuService: IMenuService,
40
@ICommandService commandService: ICommandService
41
) {
42
const makeAction = (mode: IChatMode, currentMode: IChatMode): IActionWidgetDropdownAction => ({
43
...action,
44
id: getOpenChatActionIdForMode(mode),
45
label: mode.label,
46
class: undefined,
47
enabled: true,
48
checked: currentMode.id === mode.id,
49
tooltip: chatAgentService.getDefaultAgent(ChatAgentLocation.Panel, mode.kind)?.description ?? action.tooltip,
50
run: async () => {
51
const result = await commandService.executeCommand(ToggleAgentModeActionId, { modeId: mode.id } satisfies IToggleChatModeArgs);
52
this.renderLabel(this.element!);
53
return result;
54
},
55
category: { label: localize('built-in', "Built-In"), order: 0 }
56
});
57
58
const makeActionFromCustomMode = (mode: IChatMode, currentMode: IChatMode): IActionWidgetDropdownAction => ({
59
...action,
60
id: getOpenChatActionIdForMode(mode),
61
label: mode.label,
62
class: undefined,
63
enabled: true,
64
checked: currentMode.id === mode.id,
65
tooltip: mode.description.get() ?? chatAgentService.getDefaultAgent(ChatAgentLocation.Panel, mode.kind)?.description ?? action.tooltip,
66
run: async () => {
67
const result = await commandService.executeCommand(ToggleAgentModeActionId, { modeId: mode.id } satisfies IToggleChatModeArgs);
68
this.renderLabel(this.element!);
69
return result;
70
},
71
category: { label: localize('custom', "Custom"), order: 1 }
72
});
73
74
const actionProvider: IActionWidgetDropdownActionProvider = {
75
getActions: () => {
76
const modes = chatModeService.getModes();
77
const currentMode = delegate.currentMode.get();
78
const agentStateActions: IActionWidgetDropdownAction[] = modes.builtin.map(mode => makeAction(mode, currentMode));
79
if (modes.custom) {
80
agentStateActions.push(...modes.custom.map(mode => makeActionFromCustomMode(mode, currentMode)));
81
}
82
83
return agentStateActions;
84
}
85
};
86
87
const modePickerActionWidgetOptions: Omit<IActionWidgetDropdownOptions, 'label' | 'labelRenderer'> = {
88
actionProvider,
89
actionBarActionProvider: {
90
getActions: () => this.getModePickerActionBarActions()
91
},
92
showItemKeybindings: true
93
};
94
95
super(action, modePickerActionWidgetOptions, actionWidgetService, keybindingService, contextKeyService);
96
97
// Listen to changes in the current mode and its properties
98
this._register(autorun(reader => {
99
this.renderLabel(this.element!, this.delegate.currentMode.read(reader));
100
}));
101
}
102
103
private getModePickerActionBarActions(): IAction[] {
104
const menuActions = this.menuService.createMenu(MenuId.ChatModePicker, this.contextKeyService);
105
const menuContributions = getFlatActionBarActions(menuActions.getActions({ renderShortTitle: true }));
106
menuActions.dispose();
107
108
return menuContributions;
109
}
110
111
protected override renderLabel(element: HTMLElement, mode: IChatMode = this.delegate.currentMode.get()): IDisposable | null {
112
if (!this.element) {
113
return null;
114
}
115
this.setAriaLabelAttributes(element);
116
const state = this.delegate.currentMode.get().label;
117
dom.reset(element, dom.$('span.chat-model-label', undefined, state), ...renderLabelWithIcons(`$(chevron-down)`));
118
return null;
119
}
120
121
override render(container: HTMLElement): void {
122
super.render(container);
123
container.classList.add('chat-modelPicker-item');
124
}
125
}
126
127