mirror of
https://github.com/microsoft/vscode.git
synced 2025-12-24 20:26:08 +00:00
@@ -36,6 +36,8 @@
|
||||
"--vscode-charts-purple",
|
||||
"--vscode-charts-red",
|
||||
"--vscode-charts-yellow",
|
||||
"--vscode-chat-requestBackground",
|
||||
"--vscode-chat-requestBorder",
|
||||
"--vscode-checkbox-background",
|
||||
"--vscode-checkbox-border",
|
||||
"--vscode-checkbox-foreground",
|
||||
@@ -304,8 +306,6 @@
|
||||
"--vscode-inputValidation-warningBackground",
|
||||
"--vscode-inputValidation-warningBorder",
|
||||
"--vscode-inputValidation-warningForeground",
|
||||
"--vscode-interactive-requestBackground",
|
||||
"--vscode-interactive-requestBorder",
|
||||
"--vscode-interactiveEditor-border",
|
||||
"--vscode-interactiveEditor-regionHighlight",
|
||||
"--vscode-interactiveEditor-shadow",
|
||||
|
||||
@@ -69,7 +69,7 @@ export namespace Schemas {
|
||||
|
||||
export const vscodeTerminal = 'vscode-terminal';
|
||||
|
||||
export const vscodeInteractiveSesssion = 'vscode-chat-editor';
|
||||
export const vscodeChatSesssion = 'vscode-chat-editor';
|
||||
|
||||
/**
|
||||
* Scheme used internally for webviews that aren't linked to a resource (i.e. not custom editors)
|
||||
|
||||
@@ -21,8 +21,8 @@ export function getAccessibilityHelpText(accessor: ServicesAccessor, type: 'chat
|
||||
const content = [];
|
||||
content.push(localize('interactiveSession.helpMenuExit', "Exit this menu and return to the input via the Escape key."));
|
||||
if (type === 'chat') {
|
||||
content.push(descriptionForCommand('chat.action.focus', localize('workbench.action.chat.focus', 'The Focus Chat command ({0}) focuses the chat request/response list, which can be navigated with UpArrow/DownArrow.',), localize('workbench.action.chat.focusNoKb', 'The Focus Interactive Session command focuses the chat request/response list, which can be navigated with UpArrow/DownArrow and is currently not triggerable by a keybinding.'), keybindingService));
|
||||
content.push(descriptionForCommand('workbench.action.chat.focusInput', localize('workbench.action.chat.focusInput', 'The Focus Chat Input command ({0}) focuses the input box for chat requests.'), localize('workbench.action.interactiveSession.focusInputNoKb', 'Focus Interactive Session Input command focuses the input box for chat requests and is currently not triggerable by a keybinding.'), keybindingService));
|
||||
content.push(descriptionForCommand('chat.action.focus', localize('workbench.action.chat.focus', 'The Focus Chat command ({0}) focuses the chat request/response list, which can be navigated with UpArrow/DownArrow.',), localize('workbench.action.chat.focusNoKb', 'The Focus Chat List command focuses the chat request/response list, which can be navigated with UpArrow/DownArrow and is currently not triggerable by a keybinding.'), keybindingService));
|
||||
content.push(descriptionForCommand('workbench.action.chat.focusInput', localize('workbench.action.chat.focusInput', 'The Focus Chat Input command ({0}) focuses the input box for chat requests.'), localize('workbench.action.interactiveSession.focusInputNoKb', 'Focus Chat Input command focuses the input box for chat requests and is currently not triggerable by a keybinding.'), keybindingService));
|
||||
} else {
|
||||
content.push(localize('interactiveSession.makeRequest', "Tab once to reach the make request button, which will re-run the request."));
|
||||
const regex = /^(\/fix|\/explain)/;
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
import { Codicon } from 'vs/base/common/codicons';
|
||||
import { KeyCode, KeyMod } from 'vs/base/common/keyCodes';
|
||||
import { ICodeEditor } from 'vs/editor/browser/editorBrowser';
|
||||
import { EditorAction, ServicesAccessor, registerEditorAction } from 'vs/editor/browser/editorExtensions';
|
||||
import { EditorAction, EditorAction2, ServicesAccessor, registerEditorAction } from 'vs/editor/browser/editorExtensions';
|
||||
import { EditorContextKeys } from 'vs/editor/common/editorContextKeys';
|
||||
import { localize } from 'vs/nls';
|
||||
import { Action2, IAction2Options, MenuId, registerAction2 } from 'vs/platform/actions/common/actions';
|
||||
@@ -21,7 +21,7 @@ import { IChatWidgetService } from 'vs/workbench/contrib/chat/browser/chat';
|
||||
import { IChatEditorOptions } from 'vs/workbench/contrib/chat/browser/chatEditor';
|
||||
import { ChatEditorInput } from 'vs/workbench/contrib/chat/browser/chatEditorInput';
|
||||
import { ChatViewPane } from 'vs/workbench/contrib/chat/browser/chatViewPane';
|
||||
import { CONTEXT_IN_INTERACTIVE_INPUT, CONTEXT_IN_INTERACTIVE_SESSION } from 'vs/workbench/contrib/chat/common/chatContextKeys';
|
||||
import { CONTEXT_IN_CHAT_INPUT, CONTEXT_IN_CHAT_SESSION } from 'vs/workbench/contrib/chat/common/chatContextKeys';
|
||||
import { IChatDetail, IChatService } from 'vs/workbench/contrib/chat/common/chatService';
|
||||
import { IChatWidgetHistoryService } from 'vs/workbench/contrib/chat/common/chatWidgetHistoryService';
|
||||
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
|
||||
@@ -35,7 +35,7 @@ export function registerChatActions() {
|
||||
id: 'chat.action.acceptInput',
|
||||
label: localize({ key: 'actions.chat.acceptInput', comment: ['Apply input from the chat input box'] }, "Accept Chat Input"),
|
||||
alias: 'Accept Chat Input',
|
||||
precondition: CONTEXT_IN_INTERACTIVE_INPUT,
|
||||
precondition: CONTEXT_IN_CHAT_INPUT,
|
||||
kbOpts: {
|
||||
kbExpr: EditorContextKeys.textInputFocus,
|
||||
primary: KeyCode.Enter,
|
||||
@@ -101,22 +101,22 @@ export function registerChatActions() {
|
||||
}
|
||||
});
|
||||
|
||||
registerEditorAction(class FocusChatAction extends EditorAction {
|
||||
registerAction2(class FocusChatAction extends EditorAction2 {
|
||||
constructor() {
|
||||
super({
|
||||
id: 'chat.action.focus',
|
||||
label: localize('actions.interactiveSession.focus', "Focus Interactive Session"),
|
||||
alias: 'Focus Interactive Session',
|
||||
precondition: CONTEXT_IN_INTERACTIVE_INPUT,
|
||||
kbOpts: {
|
||||
kbExpr: EditorContextKeys.textInputFocus,
|
||||
title: { value: localize('actions.interactiveSession.focus', "Focus Chat List"), original: 'Focus Chat List' },
|
||||
precondition: CONTEXT_IN_CHAT_INPUT,
|
||||
category: CHAT_CATEGORY,
|
||||
keybinding: {
|
||||
when: EditorContextKeys.textInputFocus,
|
||||
primary: KeyMod.CtrlCmd | KeyCode.UpArrow,
|
||||
weight: KeybindingWeight.EditorContrib
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
run(accessor: ServicesAccessor, editor: ICodeEditor): void | Promise<void> {
|
||||
runEditorCommand(accessor: ServicesAccessor, editor: ICodeEditor): void | Promise<void> {
|
||||
const editorUri = editor.getModel()?.uri;
|
||||
if (editorUri) {
|
||||
const widgetService = accessor.get(IChatWidgetService);
|
||||
@@ -131,7 +131,7 @@ export function registerChatActions() {
|
||||
id: 'chat.action.accessibilityHelp',
|
||||
label: localize('chat.action.accessibiltyHelp', "Chat View Accessibility Help"),
|
||||
alias: 'Chat View Accessibility Help',
|
||||
precondition: CONTEXT_IN_INTERACTIVE_INPUT,
|
||||
precondition: CONTEXT_IN_CHAT_INPUT,
|
||||
kbOpts: {
|
||||
primary: KeyMod.Alt | KeyCode.F1,
|
||||
weight: KeybindingWeight.EditorContrib + 10
|
||||
@@ -148,14 +148,14 @@ export function registerChatActions() {
|
||||
super({
|
||||
id: 'workbench.action.chat.focusInput',
|
||||
title: {
|
||||
value: localize('interactiveSession.focusInput.label', "Focus Input"),
|
||||
original: 'Focus Input'
|
||||
value: localize('interactiveSession.focusInput.label', "Focus Chat Input"),
|
||||
original: 'Focus Chat Input'
|
||||
},
|
||||
f1: false,
|
||||
keybinding: {
|
||||
primary: KeyMod.CtrlCmd | KeyCode.DownArrow,
|
||||
weight: KeybindingWeight.WorkbenchContrib,
|
||||
when: ContextKeyExpr.and(CONTEXT_IN_INTERACTIVE_SESSION, ContextKeyExpr.not(EditorContextKeys.focus.key))
|
||||
when: ContextKeyExpr.and(CONTEXT_IN_CHAT_SESSION, ContextKeyExpr.not(EditorContextKeys.focus.key))
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -179,7 +179,7 @@ export function registerChatActions() {
|
||||
keybinding: {
|
||||
weight: KeybindingWeight.WorkbenchContrib,
|
||||
primary: KeyMod.WinCtrl | KeyCode.KeyL,
|
||||
when: CONTEXT_IN_INTERACTIVE_SESSION,
|
||||
when: CONTEXT_IN_CHAT_SESSION,
|
||||
mac: {
|
||||
primary: KeyMod.WinCtrl | KeyCode.KeyL,
|
||||
secondary: [KeyMod.CtrlCmd | KeyCode.KeyK]
|
||||
|
||||
@@ -21,9 +21,9 @@ import { TerminalLocation } from 'vs/platform/terminal/common/terminal';
|
||||
import { IUntitledTextResourceEditorInput } from 'vs/workbench/common/editor';
|
||||
import { CHAT_CATEGORY } from 'vs/workbench/contrib/chat/browser/actions/chatActions';
|
||||
import { IChatWidgetService } from 'vs/workbench/contrib/chat/browser/chat';
|
||||
import { CONTEXT_IN_INTERACTIVE_SESSION } from 'vs/workbench/contrib/chat/common/chatContextKeys';
|
||||
import { CONTEXT_IN_CHAT_SESSION } from 'vs/workbench/contrib/chat/common/chatContextKeys';
|
||||
import { IChatCopyAction, IChatService, IChatUserActionEvent, InteractiveSessionCopyKind } from 'vs/workbench/contrib/chat/common/chatService';
|
||||
import { IInteractiveResponseViewModel, isResponseVM } from 'vs/workbench/contrib/chat/common/chatViewModel';
|
||||
import { IChatResponseViewModel, isResponseVM } from 'vs/workbench/contrib/chat/common/chatViewModel';
|
||||
import { insertCell } from 'vs/workbench/contrib/notebook/browser/controller/cellOperations';
|
||||
import { INotebookEditor } from 'vs/workbench/contrib/notebook/browser/notebookBrowser';
|
||||
import { CellKind, NOTEBOOK_EDITOR_ID } from 'vs/workbench/contrib/notebook/common/notebookCommon';
|
||||
@@ -35,7 +35,7 @@ export interface IChatCodeBlockActionContext {
|
||||
code: string;
|
||||
languageId: string;
|
||||
codeBlockIndex: number;
|
||||
element: IInteractiveResponseViewModel;
|
||||
element: IChatResponseViewModel;
|
||||
}
|
||||
|
||||
export function isCodeBlockActionContext(thing: unknown): thing is IChatCodeBlockActionContext {
|
||||
@@ -374,7 +374,7 @@ export function registerChatCodeBlockActions() {
|
||||
|
||||
const focusResponse = curCodeBlockInfo ?
|
||||
curCodeBlockInfo.element :
|
||||
widget.viewModel?.getItems().reverse().find((item): item is IInteractiveResponseViewModel => isResponseVM(item));
|
||||
widget.viewModel?.getItems().reverse().find((item): item is IChatResponseViewModel => isResponseVM(item));
|
||||
if (!focusResponse) {
|
||||
return;
|
||||
}
|
||||
@@ -398,7 +398,7 @@ export function registerChatCodeBlockActions() {
|
||||
keybinding: {
|
||||
primary: KeyCode.F9,
|
||||
weight: KeybindingWeight.WorkbenchContrib,
|
||||
when: CONTEXT_IN_INTERACTIVE_SESSION,
|
||||
when: CONTEXT_IN_CHAT_SESSION,
|
||||
},
|
||||
f1: true,
|
||||
category: CHAT_CATEGORY,
|
||||
@@ -421,7 +421,7 @@ export function registerChatCodeBlockActions() {
|
||||
keybinding: {
|
||||
primary: KeyMod.Shift | KeyCode.F9,
|
||||
weight: KeybindingWeight.WorkbenchContrib,
|
||||
when: CONTEXT_IN_INTERACTIVE_SESSION,
|
||||
when: CONTEXT_IN_CHAT_SESSION,
|
||||
},
|
||||
f1: true,
|
||||
category: CHAT_CATEGORY,
|
||||
|
||||
@@ -9,7 +9,7 @@ import { Action2, MenuId, registerAction2 } from 'vs/platform/actions/common/act
|
||||
import { IClipboardService } from 'vs/platform/clipboard/common/clipboardService';
|
||||
import { CHAT_CATEGORY } from 'vs/workbench/contrib/chat/browser/actions/chatActions';
|
||||
import { IChatWidgetService } from 'vs/workbench/contrib/chat/browser/chat';
|
||||
import { IInteractiveRequestViewModel, IInteractiveResponseViewModel, isRequestVM, isResponseVM } from 'vs/workbench/contrib/chat/common/chatViewModel';
|
||||
import { IChatRequestViewModel, IChatResponseViewModel, isRequestVM, isResponseVM } from 'vs/workbench/contrib/chat/common/chatViewModel';
|
||||
|
||||
export function registerChatCopyActions() {
|
||||
registerAction2(class CopyAllAction extends Action2 {
|
||||
@@ -30,12 +30,12 @@ export function registerChatCopyActions() {
|
||||
|
||||
run(accessor: ServicesAccessor, ...args: any[]) {
|
||||
const clipboardService = accessor.get(IClipboardService);
|
||||
const interactiveWidgetService = accessor.get(IChatWidgetService);
|
||||
const widget = interactiveWidgetService.lastFocusedWidget;
|
||||
const chatWidgetService = accessor.get(IChatWidgetService);
|
||||
const widget = chatWidgetService.lastFocusedWidget;
|
||||
if (widget) {
|
||||
const viewModel = widget.viewModel;
|
||||
const sessionAsText = viewModel?.getItems()
|
||||
.filter((item): item is (IInteractiveRequestViewModel | IInteractiveResponseViewModel) => isRequestVM(item) || isResponseVM(item))
|
||||
.filter((item): item is (IChatRequestViewModel | IChatResponseViewModel) => isRequestVM(item) || isResponseVM(item))
|
||||
.map(stringifyItem)
|
||||
.join('\n\n');
|
||||
if (sessionAsText) {
|
||||
@@ -74,7 +74,7 @@ export function registerChatCopyActions() {
|
||||
});
|
||||
}
|
||||
|
||||
function stringifyItem(item: IInteractiveRequestViewModel | IInteractiveResponseViewModel): string {
|
||||
function stringifyItem(item: IChatRequestViewModel | IChatResponseViewModel): string {
|
||||
return isRequestVM(item) ?
|
||||
`${item.username}: ${item.messageText}` : `${item.username}: ${item.response.value}`;
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@ import { localize } from 'vs/nls';
|
||||
import { Action2, MenuId, registerAction2 } from 'vs/platform/actions/common/actions';
|
||||
import { CHAT_CATEGORY } from 'vs/workbench/contrib/chat/browser/actions/chatActions';
|
||||
import { IChatWidget } from 'vs/workbench/contrib/chat/browser/chat';
|
||||
import { CONTEXT_INTERACTIVE_INPUT_HAS_TEXT, CONTEXT_INTERACTIVE_REQUEST_IN_PROGRESS } from 'vs/workbench/contrib/chat/common/chatContextKeys';
|
||||
import { CONTEXT_CHAT_INPUT_HAS_TEXT, CONTEXT_CHAT_REQUEST_IN_PROGRESS } from 'vs/workbench/contrib/chat/common/chatContextKeys';
|
||||
import { IChatService } from 'vs/workbench/contrib/chat/common/chatService';
|
||||
|
||||
export interface IChatExecuteActionContext {
|
||||
@@ -32,10 +32,10 @@ export function registerChatExecuteActions() {
|
||||
f1: false,
|
||||
category: CHAT_CATEGORY,
|
||||
icon: Codicon.send,
|
||||
precondition: CONTEXT_INTERACTIVE_INPUT_HAS_TEXT,
|
||||
precondition: CONTEXT_CHAT_INPUT_HAS_TEXT,
|
||||
menu: {
|
||||
id: MenuId.ChatExecute,
|
||||
when: CONTEXT_INTERACTIVE_REQUEST_IN_PROGRESS.negate(),
|
||||
when: CONTEXT_CHAT_REQUEST_IN_PROGRESS.negate(),
|
||||
group: 'navigation',
|
||||
}
|
||||
});
|
||||
@@ -64,7 +64,7 @@ export function registerChatExecuteActions() {
|
||||
icon: Codicon.debugStop,
|
||||
menu: {
|
||||
id: MenuId.ChatExecute,
|
||||
when: CONTEXT_INTERACTIVE_REQUEST_IN_PROGRESS,
|
||||
when: CONTEXT_CHAT_REQUEST_IN_PROGRESS,
|
||||
group: 'navigation',
|
||||
}
|
||||
});
|
||||
|
||||
@@ -17,7 +17,7 @@ import { IInstantiationService } from 'vs/platform/instantiation/common/instanti
|
||||
import { KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry';
|
||||
import { IQuickInputService, IQuickPick, IQuickPickItem } from 'vs/platform/quickinput/common/quickInput';
|
||||
import { asCssVariable, editorBackground, foreground, inputActiveOptionBackground, inputActiveOptionBorder, inputActiveOptionForeground } from 'vs/platform/theme/common/colorRegistry';
|
||||
import { InteractiveListItemRenderer } from 'vs/workbench/contrib/chat/browser/chatListRenderer';
|
||||
import { ChatListItemRenderer } from 'vs/workbench/contrib/chat/browser/chatListRenderer';
|
||||
import { ChatEditorOptions } from 'vs/workbench/contrib/chat/browser/chatOptions';
|
||||
import { ChatModel } from 'vs/workbench/contrib/chat/common/chatModel';
|
||||
import { IChatReplyFollowup, IChatService } from 'vs/workbench/contrib/chat/common/chatService';
|
||||
@@ -184,7 +184,7 @@ class InteractiveQuickPickSession extends Disposable {
|
||||
this._listDisposable = new DisposableStore();
|
||||
const options = this._listDisposable.add(this._instantiationService.createInstance(ChatEditorOptions, 'quickpick-interactive', foreground, editorBackground, editorBackground));
|
||||
const list = this._listDisposable.add(this._instantiationService.createInstance(
|
||||
InteractiveListItemRenderer,
|
||||
ChatListItemRenderer,
|
||||
options,
|
||||
{
|
||||
getListLength: () => {
|
||||
|
||||
@@ -45,28 +45,28 @@ configurationRegistry.registerConfiguration({
|
||||
properties: {
|
||||
'chat.editor.fontSize': {
|
||||
type: 'number',
|
||||
description: nls.localize('interactiveSession.editor.fontSize', "Controls the font size in pixels in Interactive Sessions."),
|
||||
description: nls.localize('interactiveSession.editor.fontSize', "Controls the font size in pixels in chat codeblocks."),
|
||||
default: isMacintosh ? 12 : 14,
|
||||
},
|
||||
'chat.editor.fontFamily': {
|
||||
type: 'string',
|
||||
description: nls.localize('interactiveSession.editor.fontFamily', "Controls the font family in Interactive Sessions."),
|
||||
description: nls.localize('interactiveSession.editor.fontFamily', "Controls the font family in chat codeblocks."),
|
||||
default: 'default'
|
||||
},
|
||||
'chat.editor.fontWeight': {
|
||||
type: 'string',
|
||||
description: nls.localize('interactiveSession.editor.fontWeight', "Controls the font weight in Interactive Sessions."),
|
||||
description: nls.localize('interactiveSession.editor.fontWeight', "Controls the font weight in chat codeblocks."),
|
||||
default: 'default'
|
||||
},
|
||||
'chat.editor.wordWrap': {
|
||||
type: 'string',
|
||||
description: nls.localize('interactiveSession.editor.wordWrap', "Controls whether lines should wrap in Interactive Sessions."),
|
||||
description: nls.localize('interactiveSession.editor.wordWrap', "Controls whether lines should wrap in chat codeblocks."),
|
||||
default: 'off',
|
||||
enum: ['on', 'off']
|
||||
},
|
||||
'chat.editor.lineHeight': {
|
||||
type: 'number',
|
||||
description: nls.localize('interactiveSession.editor.lineHeight', "Controls the line height in pixels in Interactive Sessions. Use 0 to compute the line height from the font size."),
|
||||
description: nls.localize('interactiveSession.editor.lineHeight', "Controls the line height in pixels in chat codeblocks. Use 0 to compute the line height from the font size."),
|
||||
default: 0
|
||||
},
|
||||
'chat.experimental.quickQuestion.enable': {
|
||||
@@ -98,7 +98,7 @@ class ChatResolverContribution extends Disposable {
|
||||
super();
|
||||
|
||||
this._register(editorResolverService.registerEditor(
|
||||
`${Schemas.vscodeInteractiveSesssion}:**/**`,
|
||||
`${Schemas.vscodeChatSesssion}:**/**`,
|
||||
{
|
||||
id: ChatEditorInput.EditorID,
|
||||
label: nls.localize('chat', "Chat"),
|
||||
@@ -106,7 +106,7 @@ class ChatResolverContribution extends Disposable {
|
||||
},
|
||||
{
|
||||
singlePerResource: true,
|
||||
canSupportResource: resource => resource.scheme === Schemas.vscodeInteractiveSesssion
|
||||
canSupportResource: resource => resource.scheme === Schemas.vscodeChatSesssion
|
||||
},
|
||||
{
|
||||
createEditorInput: ({ resource, options }) => {
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
import { ICodeEditor } from 'vs/editor/browser/editorBrowser';
|
||||
import { ISlashCommand } from 'vs/workbench/contrib/chat/common/chatService';
|
||||
import { IInteractiveResponseViewModel, IChatViewModel } from 'vs/workbench/contrib/chat/common/chatViewModel';
|
||||
import { IChatResponseViewModel, IChatViewModel } from 'vs/workbench/contrib/chat/common/chatViewModel';
|
||||
import { Event } from 'vs/base/common/event';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
|
||||
@@ -31,7 +31,7 @@ export interface IChatWidgetService {
|
||||
|
||||
export interface IChatCodeBlockInfo {
|
||||
codeBlockIndex: number;
|
||||
element: IInteractiveResponseViewModel;
|
||||
element: IChatResponseViewModel;
|
||||
focus(): void;
|
||||
}
|
||||
|
||||
@@ -49,7 +49,7 @@ export interface IChatWidget {
|
||||
focusInput(): void;
|
||||
getSlashCommands(): Promise<ISlashCommand[] | undefined>;
|
||||
getCodeBlockInfoForEditor(uri: URI): IChatCodeBlockInfo | undefined;
|
||||
getCodeBlockInfosForResponse(response: IInteractiveResponseViewModel): IChatCodeBlockInfo[];
|
||||
getCodeBlockInfosForResponse(response: IChatResponseViewModel): IChatCodeBlockInfo[];
|
||||
}
|
||||
|
||||
export interface IChatViewPane {
|
||||
|
||||
@@ -17,7 +17,7 @@ import { Registry } from 'vs/platform/registry/common/platform';
|
||||
import { ViewPaneContainer } from 'vs/workbench/browser/parts/views/viewPaneContainer';
|
||||
import { IViewContainersRegistry, IViewDescriptor, IViewsRegistry, ViewContainer, ViewContainerLocation, Extensions as ViewExtensions } from 'vs/workbench/common/views';
|
||||
import { getClearAction, getHistoryAction, getOpenChatEditorAction } from 'vs/workbench/contrib/chat/browser/actions/chatActions';
|
||||
import { IChatViewOptions, INTERACTIVE_SIDEBAR_PANEL_ID, ChatViewPane } from 'vs/workbench/contrib/chat/browser/chatViewPane';
|
||||
import { IChatViewOptions, CHAT_SIDEBAR_PANEL_ID, ChatViewPane } from 'vs/workbench/contrib/chat/browser/chatViewPane';
|
||||
import { IChatContributionService, IChatProviderContribution, IRawChatProviderContribution } from 'vs/workbench/contrib/chat/common/chatContributionService';
|
||||
import * as extensionsRegistry from 'vs/workbench/services/extensions/common/extensionsRegistry';
|
||||
|
||||
@@ -113,7 +113,7 @@ export class ChatContributionService implements IChatContributionService {
|
||||
|
||||
private registerChatProvider(extension: Readonly<IRelaxedExtensionDescription>, providerDescriptor: IRawChatProviderContribution): IDisposable {
|
||||
// Register View Container
|
||||
const viewContainerId = INTERACTIVE_SIDEBAR_PANEL_ID + '.' + providerDescriptor.id;
|
||||
const viewContainerId = CHAT_SIDEBAR_PANEL_ID + '.' + providerDescriptor.id;
|
||||
const viewContainer: ViewContainer = Registry.as<IViewContainersRegistry>(ViewExtensions.ViewContainersRegistry).registerViewContainer({
|
||||
id: viewContainerId,
|
||||
title: providerDescriptor.label,
|
||||
@@ -140,7 +140,7 @@ export class ChatContributionService implements IChatContributionService {
|
||||
const historyAction = registerAction2(getHistoryAction(viewId, providerDescriptor.id));
|
||||
const clearAction = registerAction2(getClearAction(viewId, providerDescriptor.id));
|
||||
|
||||
// "Open Interactive Session Editor" Action
|
||||
// "Open Chat Editor" Action
|
||||
const openEditor = registerAction2(getOpenChatEditorAction(providerDescriptor.id, providerDescriptor.label, providerDescriptor.when));
|
||||
|
||||
return {
|
||||
|
||||
@@ -88,7 +88,7 @@ export class ChatEditor extends EditorPane {
|
||||
|
||||
const editorModel = await input.resolve();
|
||||
if (!editorModel) {
|
||||
throw new Error(`Failed to get model for interactive session editor. id: ${input.sessionId}`);
|
||||
throw new Error(`Failed to get model for chat editor. id: ${input.sessionId}`);
|
||||
}
|
||||
|
||||
if (!this.widget) {
|
||||
|
||||
@@ -18,8 +18,8 @@ import { IChatModel } from 'vs/workbench/contrib/chat/common/chatModel';
|
||||
import { IChatService } from 'vs/workbench/contrib/chat/common/chatService';
|
||||
|
||||
export class ChatEditorInput extends EditorInput {
|
||||
static readonly TypeID: string = 'workbench.input.interactiveSession';
|
||||
static readonly EditorID: string = 'workbench.editor.interactiveSession';
|
||||
static readonly TypeID: string = 'workbench.input.chatSession';
|
||||
static readonly EditorID: string = 'workbench.editor.chatSession';
|
||||
static count = 0;
|
||||
|
||||
private readonly inputCount: number;
|
||||
@@ -40,7 +40,7 @@ export class ChatEditorInput extends EditorInput {
|
||||
|
||||
const parsed = ChatUri.parse(resource);
|
||||
if (typeof parsed?.handle !== 'number') {
|
||||
throw new Error('Invalid interactive session URI');
|
||||
throw new Error('Invalid chat URI');
|
||||
}
|
||||
|
||||
this.sessionId = 'sessionId' in options.target ? options.target.sessionId : undefined;
|
||||
@@ -126,11 +126,11 @@ export class ChatEditorModel extends Disposable implements IEditorModel {
|
||||
|
||||
export namespace ChatUri {
|
||||
|
||||
export const scheme = Schemas.vscodeInteractiveSesssion;
|
||||
export const scheme = Schemas.vscodeChatSesssion;
|
||||
|
||||
|
||||
export function generate(handle: number): URI {
|
||||
return URI.from({ scheme, path: `interactiveSession-${handle}` });
|
||||
return URI.from({ scheme, path: `chat-${handle}` });
|
||||
}
|
||||
|
||||
export function parse(resource: URI): { handle: number } | undefined {
|
||||
@@ -138,7 +138,7 @@ export namespace ChatUri {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const match = resource.path.match(/interactiveSession-(\d+)/);
|
||||
const match = resource.path.match(/chat-(\d+)/);
|
||||
const handleStr = match?.[1];
|
||||
if (typeof handleStr !== 'string') {
|
||||
return undefined;
|
||||
|
||||
@@ -27,7 +27,7 @@ import { getSimpleCodeEditorWidgetOptions, getSimpleEditorOptions } from 'vs/wor
|
||||
import { IChatExecuteActionContext } from 'vs/workbench/contrib/chat/browser/actions/chatExecuteActions';
|
||||
import { IChatWidget } from 'vs/workbench/contrib/chat/browser/chat';
|
||||
import { ChatFollowups } from 'vs/workbench/contrib/chat/browser/chatFollowups';
|
||||
import { CONTEXT_INTERACTIVE_INPUT_HAS_TEXT, CONTEXT_IN_INTERACTIVE_INPUT } from 'vs/workbench/contrib/chat/common/chatContextKeys';
|
||||
import { CONTEXT_CHAT_INPUT_HAS_TEXT, CONTEXT_IN_CHAT_INPUT } from 'vs/workbench/contrib/chat/common/chatContextKeys';
|
||||
import { IChatReplyFollowup } from 'vs/workbench/contrib/chat/common/chatService';
|
||||
import { IChatWidgetHistoryService } from 'vs/workbench/contrib/chat/common/chatWidgetHistoryService';
|
||||
import { AccessibilityVerbositySettingId } from 'vs/workbench/contrib/accessibility/browser/accessibilityContribution';
|
||||
@@ -37,7 +37,7 @@ const $ = dom.$;
|
||||
const INPUT_EDITOR_MAX_HEIGHT = 250;
|
||||
|
||||
export class ChatInputPart extends Disposable implements IHistoryNavigationWidget {
|
||||
public static readonly INPUT_SCHEME = 'interactiveSessionInput';
|
||||
public static readonly INPUT_SCHEME = 'chatSessionInput';
|
||||
private static _counter = 0;
|
||||
|
||||
private _onDidChangeHeight = this._register(new Emitter<void>());
|
||||
@@ -82,7 +82,7 @@ export class ChatInputPart extends Disposable implements IHistoryNavigationWidge
|
||||
) {
|
||||
super();
|
||||
|
||||
this.inputEditorHasText = CONTEXT_INTERACTIVE_INPUT_HAS_TEXT.bindTo(contextKeyService);
|
||||
this.inputEditorHasText = CONTEXT_CHAT_INPUT_HAS_TEXT.bindTo(contextKeyService);
|
||||
this.history = new HistoryNavigator([], 5);
|
||||
this._register(this.historyService.onDidClearHistory(() => this.history.clear()));
|
||||
this._register(this.configurationService.onDidChangeConfiguration(e => {
|
||||
@@ -159,7 +159,7 @@ export class ChatInputPart extends Disposable implements IHistoryNavigationWidge
|
||||
const inputContainer = dom.append(this.container, $('.interactive-input-and-toolbar'));
|
||||
|
||||
const inputScopedContextKeyService = this._register(this.contextKeyService.createScoped(inputContainer));
|
||||
CONTEXT_IN_INTERACTIVE_INPUT.bindTo(inputScopedContextKeyService).set(true);
|
||||
CONTEXT_IN_CHAT_INPUT.bindTo(inputScopedContextKeyService).set(true);
|
||||
const scopedInstantiationService = this.instantiationService.createChild(new ServiceCollection([IContextKeyService, inputScopedContextKeyService]));
|
||||
|
||||
const { historyNavigationBackwardsEnablement, historyNavigationForwardsEnablement } = this._register(registerAndCreateHistoryNavigationContext(inputScopedContextKeyService, this));
|
||||
|
||||
@@ -56,14 +56,14 @@ import { ChatFollowups } from 'vs/workbench/contrib/chat/browser/chatFollowups';
|
||||
import { ChatEditorOptions } from 'vs/workbench/contrib/chat/browser/chatOptions';
|
||||
import { CONTEXT_RESPONSE_HAS_PROVIDER_ID, CONTEXT_RESPONSE_VOTE } from 'vs/workbench/contrib/chat/common/chatContextKeys';
|
||||
import { IChatReplyFollowup, IChatService, ISlashCommand, InteractiveSessionVoteDirection } from 'vs/workbench/contrib/chat/common/chatService';
|
||||
import { IInteractiveRequestViewModel, IInteractiveResponseViewModel, IInteractiveWelcomeMessageViewModel, isRequestVM, isResponseVM, isWelcomeVM } from 'vs/workbench/contrib/chat/common/chatViewModel';
|
||||
import { IChatRequestViewModel, IChatResponseViewModel, IChatWelcomeMessageViewModel, isRequestVM, isResponseVM, isWelcomeVM } from 'vs/workbench/contrib/chat/common/chatViewModel';
|
||||
import { IWordCountResult, getNWords } from 'vs/workbench/contrib/chat/common/chatWordCounter';
|
||||
|
||||
const $ = dom.$;
|
||||
|
||||
export type InteractiveTreeItem = IInteractiveRequestViewModel | IInteractiveResponseViewModel | IInteractiveWelcomeMessageViewModel;
|
||||
export type ChatTreeItem = IChatRequestViewModel | IChatResponseViewModel | IChatWelcomeMessageViewModel;
|
||||
|
||||
interface IInteractiveListItemTemplate {
|
||||
interface IChatListItemTemplate {
|
||||
rowContainer: HTMLElement;
|
||||
titleToolbar: MenuWorkbenchToolBar;
|
||||
avatar: HTMLElement;
|
||||
@@ -75,7 +75,7 @@ interface IInteractiveListItemTemplate {
|
||||
}
|
||||
|
||||
interface IItemHeightChangeParams {
|
||||
element: InteractiveTreeItem;
|
||||
element: ChatTreeItem;
|
||||
height: number;
|
||||
}
|
||||
|
||||
@@ -86,7 +86,7 @@ export interface IChatRendererDelegate {
|
||||
getSlashCommands(): ISlashCommand[];
|
||||
}
|
||||
|
||||
export class InteractiveListItemRenderer extends Disposable implements ITreeRenderer<InteractiveTreeItem, FuzzyScore, IInteractiveListItemTemplate> {
|
||||
export class ChatListItemRenderer extends Disposable implements ITreeRenderer<ChatTreeItem, FuzzyScore, IChatListItemTemplate> {
|
||||
static readonly cursorCharacter = '\u258c';
|
||||
static readonly ID = 'item';
|
||||
|
||||
@@ -122,14 +122,14 @@ export class InteractiveListItemRenderer extends Disposable implements ITreeRend
|
||||
}
|
||||
|
||||
get templateId(): string {
|
||||
return InteractiveListItemRenderer.ID;
|
||||
return ChatListItemRenderer.ID;
|
||||
}
|
||||
|
||||
private traceLayout(method: string, message: string) {
|
||||
if (forceVerboseLayoutTracing) {
|
||||
this.logService.info(`InteractiveListItemRenderer#${method}: ${message}`);
|
||||
this.logService.info(`ChatListItemRenderer#${method}: ${message}`);
|
||||
} else {
|
||||
this.logService.trace(`InteractiveListItemRenderer#${method}: ${message}`);
|
||||
this.logService.trace(`ChatListItemRenderer#${method}: ${message}`);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -137,7 +137,7 @@ export class InteractiveListItemRenderer extends Disposable implements ITreeRend
|
||||
return !this.configService.getValue('interactive.experimental.disableProgressiveRendering');
|
||||
}
|
||||
|
||||
private getProgressiveRenderRate(element: IInteractiveResponseViewModel): number {
|
||||
private getProgressiveRenderRate(element: IChatResponseViewModel): number {
|
||||
const configuredRate = this.configService.getValue('interactive.experimental.progressiveRenderingRate');
|
||||
if (typeof configuredRate === 'number') {
|
||||
return configuredRate;
|
||||
@@ -158,7 +158,7 @@ export class InteractiveListItemRenderer extends Disposable implements ITreeRend
|
||||
return 8;
|
||||
}
|
||||
|
||||
getCodeBlockInfosForResponse(response: IInteractiveResponseViewModel): IChatCodeBlockInfo[] {
|
||||
getCodeBlockInfosForResponse(response: IChatResponseViewModel): IChatCodeBlockInfo[] {
|
||||
const codeBlocks = this.codeBlocksByResponseId.get(response.id);
|
||||
return codeBlocks ?? [];
|
||||
}
|
||||
@@ -178,7 +178,7 @@ export class InteractiveListItemRenderer extends Disposable implements ITreeRend
|
||||
});
|
||||
}
|
||||
|
||||
renderTemplate(container: HTMLElement): IInteractiveListItemTemplate {
|
||||
renderTemplate(container: HTMLElement): IChatListItemTemplate {
|
||||
const templateDisposables = new DisposableStore();
|
||||
const rowContainer = dom.append(container, $('.interactive-item-container'));
|
||||
const header = dom.append(rowContainer, $('.header'));
|
||||
@@ -204,11 +204,11 @@ export class InteractiveListItemRenderer extends Disposable implements ITreeRend
|
||||
}));
|
||||
|
||||
|
||||
const template: IInteractiveListItemTemplate = { avatar, username, value, rowContainer, elementDisposables, titleToolbar, templateDisposables, contextKeyService };
|
||||
const template: IChatListItemTemplate = { avatar, username, value, rowContainer, elementDisposables, titleToolbar, templateDisposables, contextKeyService };
|
||||
return template;
|
||||
}
|
||||
|
||||
renderElement(node: ITreeNode<InteractiveTreeItem, FuzzyScore>, index: number, templateData: IInteractiveListItemTemplate): void {
|
||||
renderElement(node: ITreeNode<ChatTreeItem, FuzzyScore>, index: number, templateData: IChatListItemTemplate): void {
|
||||
const { element } = node;
|
||||
const kind = isRequestVM(element) ? 'request' :
|
||||
isResponseVM(element) ? 'response' :
|
||||
@@ -272,7 +272,7 @@ export class InteractiveListItemRenderer extends Disposable implements ITreeRend
|
||||
}
|
||||
}
|
||||
|
||||
private basicRenderElement(markdownValue: string, element: InteractiveTreeItem, index: number, templateData: IInteractiveListItemTemplate) {
|
||||
private basicRenderElement(markdownValue: string, element: ChatTreeItem, index: number, templateData: IChatListItemTemplate) {
|
||||
const fillInIncompleteTokens = isResponseVM(element) && (!element.isComplete || element.isCanceled || element.errorDetails?.responseIsFiltered || element.errorDetails?.responseIsIncomplete);
|
||||
const result = this.renderMarkdown(new MarkdownString(markdownValue), element, templateData.elementDisposables, templateData, fillInIncompleteTokens);
|
||||
dom.clearNode(templateData.value);
|
||||
@@ -304,7 +304,7 @@ export class InteractiveListItemRenderer extends Disposable implements ITreeRend
|
||||
}
|
||||
}
|
||||
|
||||
private renderWelcomeMessage(element: IInteractiveWelcomeMessageViewModel, templateData: IInteractiveListItemTemplate) {
|
||||
private renderWelcomeMessage(element: IChatWelcomeMessageViewModel, templateData: IChatListItemTemplate) {
|
||||
dom.clearNode(templateData.value);
|
||||
const slashCommands = this.delegate.getSlashCommands();
|
||||
|
||||
@@ -331,7 +331,7 @@ export class InteractiveListItemRenderer extends Disposable implements ITreeRend
|
||||
/**
|
||||
* @returns true if progressive rendering should be considered complete- the element's data is fully rendered or the view is not visible
|
||||
*/
|
||||
private doNextProgressiveRender(element: IInteractiveResponseViewModel, index: number, templateData: IInteractiveListItemTemplate, isInRenderElement: boolean, disposables: DisposableStore): boolean {
|
||||
private doNextProgressiveRender(element: IChatResponseViewModel, index: number, templateData: IChatListItemTemplate, isInRenderElement: boolean, disposables: DisposableStore): boolean {
|
||||
if (!this._isVisible) {
|
||||
return true;
|
||||
}
|
||||
@@ -369,7 +369,7 @@ export class InteractiveListItemRenderer extends Disposable implements ITreeRend
|
||||
// when the codeblock is the last thing in the response, and that happens often.
|
||||
const plusCursor = renderValue.value.match(/```\s*$/) ?
|
||||
renderValue.value :
|
||||
renderValue.value + ` ${InteractiveListItemRenderer.cursorCharacter}`;
|
||||
renderValue.value + ` ${ChatListItemRenderer.cursorCharacter}`;
|
||||
const result = this.renderMarkdown(new MarkdownString(plusCursor), element, disposables, templateData, true);
|
||||
// Doing the progressive render
|
||||
dom.clearNode(templateData.value);
|
||||
@@ -391,7 +391,7 @@ export class InteractiveListItemRenderer extends Disposable implements ITreeRend
|
||||
return !!isFullyRendered;
|
||||
}
|
||||
|
||||
private renderMarkdown(markdown: IMarkdownString, element: InteractiveTreeItem, disposables: DisposableStore, templateData: IInteractiveListItemTemplate, fillInIncompleteTokens = false): IMarkdownRenderResult {
|
||||
private renderMarkdown(markdown: IMarkdownString, element: ChatTreeItem, disposables: DisposableStore, templateData: IChatListItemTemplate, fillInIncompleteTokens = false): IMarkdownRenderResult {
|
||||
const disposablesList: IDisposable[] = [];
|
||||
let codeBlockIndex = 0;
|
||||
|
||||
@@ -450,7 +450,7 @@ export class InteractiveListItemRenderer extends Disposable implements ITreeRend
|
||||
return result;
|
||||
}
|
||||
|
||||
private renderCodeBlock(data: IInteractiveResultCodeBlockData, disposables: DisposableStore): IDisposableReference<IInteractiveResultCodeBlockPart> {
|
||||
private renderCodeBlock(data: IChatResultCodeBlockData, disposables: DisposableStore): IDisposableReference<IChatResultCodeBlockPart> {
|
||||
const ref = this._editorPool.get();
|
||||
const editorInfo = ref.object;
|
||||
editorInfo.render(data, this._currentLayoutWidth);
|
||||
@@ -458,7 +458,7 @@ export class InteractiveListItemRenderer extends Disposable implements ITreeRend
|
||||
return ref;
|
||||
}
|
||||
|
||||
private getWordsForProgressiveRender(element: IInteractiveResponseViewModel): IWordCountResult | undefined {
|
||||
private getWordsForProgressiveRender(element: IChatResponseViewModel): IWordCountResult | undefined {
|
||||
const renderData = element.renderData ?? { renderedWordCount: 0, lastRenderTime: 0 };
|
||||
const rate = this.getProgressiveRenderRate(element);
|
||||
const numWordsToRender = renderData.lastRenderTime === 0 ?
|
||||
@@ -474,16 +474,16 @@ export class InteractiveListItemRenderer extends Disposable implements ITreeRend
|
||||
return getNWords(element.response.value, numWordsToRender);
|
||||
}
|
||||
|
||||
disposeElement(node: ITreeNode<InteractiveTreeItem, FuzzyScore>, index: number, templateData: IInteractiveListItemTemplate): void {
|
||||
disposeElement(node: ITreeNode<ChatTreeItem, FuzzyScore>, index: number, templateData: IChatListItemTemplate): void {
|
||||
templateData.elementDisposables.clear();
|
||||
}
|
||||
|
||||
disposeTemplate(templateData: IInteractiveListItemTemplate): void {
|
||||
disposeTemplate(templateData: IChatListItemTemplate): void {
|
||||
templateData.templateDisposables.dispose();
|
||||
}
|
||||
}
|
||||
|
||||
export class ChatListDelegate implements IListVirtualDelegate<InteractiveTreeItem> {
|
||||
export class ChatListDelegate implements IListVirtualDelegate<ChatTreeItem> {
|
||||
constructor(
|
||||
@ILogService private readonly logService: ILogService
|
||||
) { }
|
||||
@@ -496,29 +496,29 @@ export class ChatListDelegate implements IListVirtualDelegate<InteractiveTreeIte
|
||||
}
|
||||
}
|
||||
|
||||
getHeight(element: InteractiveTreeItem): number {
|
||||
getHeight(element: ChatTreeItem): number {
|
||||
const kind = isRequestVM(element) ? 'request' : 'response';
|
||||
const height = ('currentRenderedHeight' in element ? element.currentRenderedHeight : undefined) ?? 200;
|
||||
this._traceLayout('getHeight', `${kind}, height=${height}`);
|
||||
return height;
|
||||
}
|
||||
|
||||
getTemplateId(element: InteractiveTreeItem): string {
|
||||
return InteractiveListItemRenderer.ID;
|
||||
getTemplateId(element: ChatTreeItem): string {
|
||||
return ChatListItemRenderer.ID;
|
||||
}
|
||||
|
||||
hasDynamicHeight(element: InteractiveTreeItem): boolean {
|
||||
hasDynamicHeight(element: ChatTreeItem): boolean {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
export class ChatAccessibilityProvider implements IListAccessibilityProvider<InteractiveTreeItem> {
|
||||
export class ChatAccessibilityProvider implements IListAccessibilityProvider<ChatTreeItem> {
|
||||
|
||||
getWidgetRole(): AriaRole {
|
||||
return 'list';
|
||||
}
|
||||
|
||||
getRole(element: InteractiveTreeItem): AriaRole | undefined {
|
||||
getRole(element: ChatTreeItem): AriaRole | undefined {
|
||||
return 'listitem';
|
||||
}
|
||||
|
||||
@@ -526,7 +526,7 @@ export class ChatAccessibilityProvider implements IListAccessibilityProvider<Int
|
||||
return localize('chat', "Chat");
|
||||
}
|
||||
|
||||
getAriaLabel(element: InteractiveTreeItem): string {
|
||||
getAriaLabel(element: ChatTreeItem): string {
|
||||
if (isRequestVM(element)) {
|
||||
return element.messageText;
|
||||
}
|
||||
@@ -543,27 +543,27 @@ export class ChatAccessibilityProvider implements IListAccessibilityProvider<Int
|
||||
}
|
||||
}
|
||||
|
||||
interface IInteractiveResultCodeBlockData {
|
||||
interface IChatResultCodeBlockData {
|
||||
text: string;
|
||||
languageId: string;
|
||||
codeBlockIndex: number;
|
||||
element: InteractiveTreeItem;
|
||||
element: ChatTreeItem;
|
||||
parentContextKeyService: IContextKeyService;
|
||||
}
|
||||
|
||||
interface IInteractiveResultCodeBlockPart {
|
||||
interface IChatResultCodeBlockPart {
|
||||
readonly onDidChangeContentHeight: Event<number>;
|
||||
readonly element: HTMLElement;
|
||||
readonly textModel: ITextModel;
|
||||
layout(width: number): void;
|
||||
render(data: IInteractiveResultCodeBlockData, width: number): void;
|
||||
render(data: IChatResultCodeBlockData, width: number): void;
|
||||
focus(): void;
|
||||
dispose(): void;
|
||||
}
|
||||
|
||||
const defaultCodeblockPadding = 10;
|
||||
|
||||
class CodeBlockPart extends Disposable implements IInteractiveResultCodeBlockPart {
|
||||
class CodeBlockPart extends Disposable implements IChatResultCodeBlockPart {
|
||||
private readonly _onDidChangeContentHeight = this._register(new Emitter<number>());
|
||||
public readonly onDidChangeContentHeight = this._onDidChangeContentHeight.event;
|
||||
|
||||
@@ -683,7 +683,7 @@ class CodeBlockPart extends Disposable implements IInteractiveResultCodeBlockPar
|
||||
this.updatePaddingForLayout();
|
||||
}
|
||||
|
||||
render(data: IInteractiveResultCodeBlockData, width: number): void {
|
||||
render(data: IChatResultCodeBlockData, width: number): void {
|
||||
this.contextKeyService.updateParent(data.parentContextKeyService);
|
||||
|
||||
if (this.options.configuration.resultEditor.wordWrap === 'on') {
|
||||
@@ -725,9 +725,9 @@ class CodeBlockPart extends Disposable implements IInteractiveResultCodeBlockPar
|
||||
}
|
||||
|
||||
let removedChars = 0;
|
||||
if (currentText.endsWith(` ${InteractiveListItemRenderer.cursorCharacter}`)) {
|
||||
if (currentText.endsWith(` ${ChatListItemRenderer.cursorCharacter}`)) {
|
||||
removedChars = 2;
|
||||
} else if (currentText.endsWith(InteractiveListItemRenderer.cursorCharacter)) {
|
||||
} else if (currentText.endsWith(ChatListItemRenderer.cursorCharacter)) {
|
||||
removedChars = 1;
|
||||
}
|
||||
|
||||
@@ -757,9 +757,9 @@ interface IDisposableReference<T> extends IDisposable {
|
||||
}
|
||||
|
||||
class EditorPool extends Disposable {
|
||||
private _pool: ResourcePool<IInteractiveResultCodeBlockPart>;
|
||||
private _pool: ResourcePool<IChatResultCodeBlockPart>;
|
||||
|
||||
public get inUse(): ReadonlySet<IInteractiveResultCodeBlockPart> {
|
||||
public get inUse(): ReadonlySet<IChatResultCodeBlockPart> {
|
||||
return this._pool.inUse;
|
||||
}
|
||||
|
||||
@@ -773,11 +773,11 @@ class EditorPool extends Disposable {
|
||||
// TODO listen to changes on options
|
||||
}
|
||||
|
||||
private editorFactory(): IInteractiveResultCodeBlockPart {
|
||||
private editorFactory(): IChatResultCodeBlockPart {
|
||||
return this.instantiationService.createInstance(CodeBlockPart, this.options);
|
||||
}
|
||||
|
||||
get(): IDisposableReference<IInteractiveResultCodeBlockPart> {
|
||||
get(): IDisposableReference<IChatResultCodeBlockPart> {
|
||||
const object = this._pool.get();
|
||||
return {
|
||||
object,
|
||||
|
||||
@@ -34,9 +34,9 @@ interface IViewPaneState extends IViewState {
|
||||
sessionId?: string;
|
||||
}
|
||||
|
||||
export const INTERACTIVE_SIDEBAR_PANEL_ID = 'workbench.panel.interactiveSessionSidebar';
|
||||
export const CHAT_SIDEBAR_PANEL_ID = 'workbench.panel.chatSidebar';
|
||||
export class ChatViewPane extends ViewPane implements IChatViewPane {
|
||||
static ID = 'workbench.panel.interactiveSession.view';
|
||||
static ID = 'workbench.panel.chat.view';
|
||||
|
||||
private _widget!: ChatWidget;
|
||||
get widget(): ChatWidget { return this._widget; }
|
||||
@@ -46,7 +46,7 @@ export class ChatViewPane extends ViewPane implements IChatViewPane {
|
||||
private viewState: IViewPaneState;
|
||||
|
||||
constructor(
|
||||
private readonly interactiveSessionViewOptions: IChatViewOptions,
|
||||
private readonly chatViewOptions: IChatViewOptions,
|
||||
options: IViewPaneOptions,
|
||||
@IKeybindingService keybindingService: IKeybindingService,
|
||||
@IContextMenuService contextMenuService: IContextMenuService,
|
||||
@@ -64,16 +64,16 @@ export class ChatViewPane extends ViewPane implements IChatViewPane {
|
||||
super(options, keybindingService, contextMenuService, configurationService, contextKeyService, viewDescriptorService, instantiationService, openerService, themeService, telemetryService);
|
||||
|
||||
// View state for the ViewPane is currently global per-provider basically, but some other strictly per-model state will require a separate memento.
|
||||
this.memento = new Memento('interactive-session-view-' + this.interactiveSessionViewOptions.providerId, this.storageService);
|
||||
this.memento = new Memento('interactive-session-view-' + this.chatViewOptions.providerId, this.storageService);
|
||||
this.viewState = this.memento.getMemento(StorageScope.WORKSPACE, StorageTarget.MACHINE) as IViewPaneState;
|
||||
}
|
||||
|
||||
private updateModel(model?: IChatModel | undefined): void {
|
||||
this.modelDisposables.clear();
|
||||
|
||||
model = model ?? this.chatService.startSession(this.interactiveSessionViewOptions.providerId, CancellationToken.None);
|
||||
model = model ?? this.chatService.startSession(this.chatViewOptions.providerId, CancellationToken.None);
|
||||
if (!model) {
|
||||
throw new Error('Could not start interactive session');
|
||||
throw new Error('Could not start chat session');
|
||||
}
|
||||
|
||||
this._widget.setModel(model, { ...this.viewState });
|
||||
|
||||
@@ -25,14 +25,14 @@ import { IViewsService } from 'vs/workbench/common/views';
|
||||
import { clearChatSession } from 'vs/workbench/contrib/chat/browser/actions/chatClear';
|
||||
import { IChatCodeBlockInfo, IChatWidget, IChatWidgetService, IChatWidgetViewContext } from 'vs/workbench/contrib/chat/browser/chat';
|
||||
import { ChatInputPart } from 'vs/workbench/contrib/chat/browser/chatInputPart';
|
||||
import { IChatRendererDelegate, InteractiveListItemRenderer, ChatAccessibilityProvider, ChatListDelegate, InteractiveTreeItem } from 'vs/workbench/contrib/chat/browser/chatListRenderer';
|
||||
import { IChatRendererDelegate, ChatListItemRenderer, ChatAccessibilityProvider, ChatListDelegate, ChatTreeItem } from 'vs/workbench/contrib/chat/browser/chatListRenderer';
|
||||
import { ChatEditorOptions } from 'vs/workbench/contrib/chat/browser/chatOptions';
|
||||
import { ChatViewPane } from 'vs/workbench/contrib/chat/browser/chatViewPane';
|
||||
import { CONTEXT_INTERACTIVE_REQUEST_IN_PROGRESS, CONTEXT_IN_INTERACTIVE_SESSION } from 'vs/workbench/contrib/chat/common/chatContextKeys';
|
||||
import { CONTEXT_CHAT_REQUEST_IN_PROGRESS, CONTEXT_IN_CHAT_SESSION } from 'vs/workbench/contrib/chat/common/chatContextKeys';
|
||||
import { IChatContributionService } from 'vs/workbench/contrib/chat/common/chatContributionService';
|
||||
import { IChatModel } from 'vs/workbench/contrib/chat/common/chatModel';
|
||||
import { IChatReplyFollowup, IChatService, ISlashCommand } from 'vs/workbench/contrib/chat/common/chatService';
|
||||
import { IInteractiveResponseViewModel, ChatViewModel, isRequestVM, isResponseVM, isWelcomeVM } from 'vs/workbench/contrib/chat/common/chatViewModel';
|
||||
import { IChatResponseViewModel, ChatViewModel, isRequestVM, isResponseVM, isWelcomeVM } from 'vs/workbench/contrib/chat/common/chatViewModel';
|
||||
|
||||
const $ = dom.$;
|
||||
|
||||
@@ -61,8 +61,8 @@ export class ChatWidget extends Disposable implements IChatWidget {
|
||||
private _onDidChangeViewModel = this._register(new Emitter<void>());
|
||||
readonly onDidChangeViewModel = this._onDidChangeViewModel.event;
|
||||
|
||||
private tree!: WorkbenchObjectTree<InteractiveTreeItem>;
|
||||
private renderer!: InteractiveListItemRenderer;
|
||||
private tree!: WorkbenchObjectTree<ChatTreeItem>;
|
||||
private renderer!: ChatListItemRenderer;
|
||||
|
||||
private inputPart!: ChatInputPart;
|
||||
private editorOptions!: ChatEditorOptions;
|
||||
@@ -117,8 +117,8 @@ export class ChatWidget extends Disposable implements IChatWidget {
|
||||
@IContextMenuService private readonly contextMenuService: IContextMenuService,
|
||||
) {
|
||||
super();
|
||||
CONTEXT_IN_INTERACTIVE_SESSION.bindTo(contextKeyService).set(true);
|
||||
this.requestInProgress = CONTEXT_INTERACTIVE_REQUEST_IN_PROGRESS.bindTo(contextKeyService);
|
||||
CONTEXT_IN_CHAT_SESSION.bindTo(contextKeyService).set(true);
|
||||
this.requestInProgress = CONTEXT_CHAT_REQUEST_IN_PROGRESS.bindTo(contextKeyService);
|
||||
|
||||
this._register((chatWidgetService as ChatWidgetService).register(this));
|
||||
}
|
||||
@@ -164,7 +164,7 @@ export class ChatWidget extends Disposable implements IChatWidget {
|
||||
if (this.tree && this.visible) {
|
||||
const treeItems = (this.viewModel?.getItems() ?? [])
|
||||
.map(item => {
|
||||
return <ITreeElement<InteractiveTreeItem>>{
|
||||
return <ITreeElement<ChatTreeItem>>{
|
||||
element: item,
|
||||
collapsed: false,
|
||||
collapsible: false
|
||||
@@ -250,24 +250,24 @@ export class ChatWidget extends Disposable implements IChatWidget {
|
||||
getListLength: () => this.tree.getNode(null).visibleChildrenCount,
|
||||
getSlashCommands: () => this.lastSlashCommands ?? [],
|
||||
};
|
||||
this.renderer = this._register(scopedInstantiationService.createInstance(InteractiveListItemRenderer, this.editorOptions, rendererDelegate));
|
||||
this.renderer = this._register(scopedInstantiationService.createInstance(ChatListItemRenderer, this.editorOptions, rendererDelegate));
|
||||
this._register(this.renderer.onDidClickFollowup(item => {
|
||||
this.acceptInput(item);
|
||||
}));
|
||||
|
||||
this.tree = <WorkbenchObjectTree<InteractiveTreeItem>>scopedInstantiationService.createInstance(
|
||||
this.tree = <WorkbenchObjectTree<ChatTreeItem>>scopedInstantiationService.createInstance(
|
||||
WorkbenchObjectTree,
|
||||
'Chat',
|
||||
listContainer,
|
||||
delegate,
|
||||
[this.renderer],
|
||||
{
|
||||
identityProvider: { getId: (e: InteractiveTreeItem) => e.id },
|
||||
identityProvider: { getId: (e: ChatTreeItem) => e.id },
|
||||
horizontalScrolling: false,
|
||||
supportDynamicHeights: true,
|
||||
hideTwistiesOfChildlessElements: true,
|
||||
accessibilityProvider: new ChatAccessibilityProvider(),
|
||||
keyboardNavigationLabelProvider: { getKeyboardNavigationLabel: (e: InteractiveTreeItem) => isRequestVM(e) ? e.message : isResponseVM(e) ? e.response.value : '' }, // TODO
|
||||
keyboardNavigationLabelProvider: { getKeyboardNavigationLabel: (e: ChatTreeItem) => isRequestVM(e) ? e.message : isResponseVM(e) ? e.response.value : '' }, // TODO
|
||||
setRowLineHeight: false,
|
||||
overrideStyles: {
|
||||
listFocusBackground: this.styles.listBackground,
|
||||
@@ -298,7 +298,7 @@ export class ChatWidget extends Disposable implements IChatWidget {
|
||||
}));
|
||||
}
|
||||
|
||||
private onContextMenu(e: ITreeContextMenuEvent<InteractiveTreeItem | null>): void {
|
||||
private onContextMenu(e: ITreeContextMenuEvent<ChatTreeItem | null>): void {
|
||||
e.browserEvent.preventDefault();
|
||||
e.browserEvent.stopPropagation();
|
||||
|
||||
@@ -384,7 +384,7 @@ export class ChatWidget extends Disposable implements IChatWidget {
|
||||
this.inputPart.acceptInput(query);
|
||||
result.responseCompletePromise.then(() => {
|
||||
const responses = this.viewModel?.getItems().filter(isResponseVM);
|
||||
const lastResponse: IInteractiveResponseViewModel | undefined = responses?.[responses.length - 1];
|
||||
const lastResponse = responses?.[responses.length - 1];
|
||||
if (lastResponse) {
|
||||
alert(lastResponse.response.value);
|
||||
}
|
||||
@@ -393,7 +393,7 @@ export class ChatWidget extends Disposable implements IChatWidget {
|
||||
}
|
||||
}
|
||||
|
||||
getCodeBlockInfosForResponse(response: IInteractiveResponseViewModel): IChatCodeBlockInfo[] {
|
||||
getCodeBlockInfosForResponse(response: IChatResponseViewModel): IChatCodeBlockInfo[] {
|
||||
return this.renderer.getCodeBlockInfosForResponse(response);
|
||||
}
|
||||
|
||||
@@ -460,7 +460,7 @@ export class ChatWidgetService implements IChatWidgetService {
|
||||
|
||||
constructor(
|
||||
@IViewsService private readonly viewsService: IViewsService,
|
||||
@IChatContributionService private readonly interactiveSessionContributionService: IChatContributionService,
|
||||
@IChatContributionService private readonly chatContributionService: IChatContributionService,
|
||||
) { }
|
||||
|
||||
getWidgetByInputUri(uri: URI): ChatWidget | undefined {
|
||||
@@ -468,7 +468,7 @@ export class ChatWidgetService implements IChatWidgetService {
|
||||
}
|
||||
|
||||
async revealViewForProvider(providerId: string): Promise<ChatWidget | undefined> {
|
||||
const viewId = this.interactiveSessionContributionService.getViewIdForProvider(providerId);
|
||||
const viewId = this.chatContributionService.getViewIdForProvider(providerId);
|
||||
const view = await this.viewsService.openView<ChatViewPane>(viewId);
|
||||
|
||||
return view?.widget;
|
||||
|
||||
@@ -22,9 +22,9 @@ import { ChatWidget } from 'vs/workbench/contrib/chat/browser/chatWidget';
|
||||
import { LifecyclePhase } from 'vs/workbench/services/lifecycle/common/lifecycle';
|
||||
import { ChatInputPart } from 'vs/workbench/contrib/chat/browser/chatInputPart';
|
||||
|
||||
const decorationDescription = 'interactive session';
|
||||
const slashCommandPlaceholderDecorationType = 'interactive-session-detail';
|
||||
const slashCommandTextDecorationType = 'interactive-session-text';
|
||||
const decorationDescription = 'chat';
|
||||
const slashCommandPlaceholderDecorationType = 'chat-session-detail';
|
||||
const slashCommandTextDecorationType = 'chat-session-text';
|
||||
|
||||
class InputEditorDecorations extends Disposable {
|
||||
|
||||
|
||||
@@ -103,7 +103,7 @@
|
||||
.interactive-item-container .value table,
|
||||
.interactive-item-container .value table td,
|
||||
.interactive-item-container .value table th {
|
||||
border: 1px solid var(--vscode-interactive-requestBorder);
|
||||
border: 1px solid var(--vscode-chat-requestBorder);
|
||||
border-collapse: collapse;
|
||||
padding: 4px 6px;
|
||||
}
|
||||
@@ -122,9 +122,9 @@
|
||||
}
|
||||
|
||||
.interactive-request {
|
||||
background-color: var(--vscode-interactive-requestBackground);
|
||||
border-bottom: 1px solid var(--vscode-interactive-requestBorder);
|
||||
border-top: 1px solid var(--vscode-interactive-requestBorder);
|
||||
background-color: var(--vscode-chat-requestBackground);
|
||||
border-bottom: 1px solid var(--vscode-chat-requestBorder);
|
||||
border-top: 1px solid var(--vscode-chat-requestBorder);
|
||||
}
|
||||
|
||||
.interactive-item-container .value {
|
||||
@@ -222,7 +222,7 @@
|
||||
right: 10px;
|
||||
height: 26px;
|
||||
background-color: var(--vscode-interactive-result-editor-background-color, var(--vscode-editor-background));
|
||||
border: 1px solid var(--vscode-interactive-requestBorder);
|
||||
border: 1px solid var(--vscode-chat-requestBorder);
|
||||
z-index: 100;
|
||||
}
|
||||
|
||||
@@ -279,7 +279,7 @@
|
||||
padding: 12px 0px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
border-top: solid 1px var(--vscode-interactive-requestBorder);
|
||||
border-top: solid 1px var(--vscode-chat-requestBorder);
|
||||
}
|
||||
|
||||
.interactive-session-followups {
|
||||
|
||||
@@ -8,14 +8,14 @@ import { localize } from 'vs/nls';
|
||||
import { registerColor } from 'vs/platform/theme/common/colorRegistry';
|
||||
|
||||
|
||||
export const interactiveRequestBackground = registerColor(
|
||||
'interactive.requestBackground',
|
||||
export const chatRequestBackground = registerColor(
|
||||
'chat.requestBackground',
|
||||
{ dark: new Color(new RGBA(255, 255, 255, 0.03)), light: new Color(new RGBA(0, 0, 0, 0.03)), hcDark: null, hcLight: null, },
|
||||
localize('interactive.requestBackground', 'The background color of an interactive request.')
|
||||
localize('chat.requestBackground', 'The background color of a chat request.')
|
||||
);
|
||||
|
||||
export const interactiveRequestBorder = registerColor(
|
||||
'interactive.requestBorder',
|
||||
export const chatRequestBorder = registerColor(
|
||||
'chat.requestBorder',
|
||||
{ dark: new Color(new RGBA(255, 255, 255, 0.10)), light: new Color(new RGBA(0, 0, 0, 0.10)), hcDark: null, hcLight: null, },
|
||||
localize('interactive.requestBorder', 'The border color of an interactive request.')
|
||||
localize('chat.requestBorder', 'The border color of a chat request.')
|
||||
);
|
||||
|
||||
@@ -6,12 +6,12 @@
|
||||
import { localize } from 'vs/nls';
|
||||
import { RawContextKey } from 'vs/platform/contextkey/common/contextkey';
|
||||
|
||||
export const CONTEXT_RESPONSE_HAS_PROVIDER_ID = new RawContextKey<boolean>('interactiveSessionResponseHasProviderId', false, { type: 'boolean', description: localize('interactiveSessionResponseHasProviderId', "True when the provider has assigned an id to this response.") });
|
||||
export const CONTEXT_RESPONSE_VOTE = new RawContextKey<string>('interactiveSessionResponseVote', '', { type: 'string', description: localize('interactiveSessionResponseVote', "When the response has been voted up, is set to 'up'. When voted down, is set to 'down'. Otherwise an empty string.") });
|
||||
export const CONTEXT_INTERACTIVE_REQUEST_IN_PROGRESS = new RawContextKey<boolean>('interactiveSessionRequestInProgress', false, { type: 'boolean', description: localize('interactiveSessionRequestInProgress', "True when the current request is still in progress.") });
|
||||
export const CONTEXT_RESPONSE_HAS_PROVIDER_ID = new RawContextKey<boolean>('chatSessionResponseHasProviderId', false, { type: 'boolean', description: localize('interactiveSessionResponseHasProviderId', "True when the provider has assigned an id to this response.") });
|
||||
export const CONTEXT_RESPONSE_VOTE = new RawContextKey<string>('chatSessionResponseVote', '', { type: 'string', description: localize('interactiveSessionResponseVote', "When the response has been voted up, is set to 'up'. When voted down, is set to 'down'. Otherwise an empty string.") });
|
||||
export const CONTEXT_CHAT_REQUEST_IN_PROGRESS = new RawContextKey<boolean>('chatSessionRequestInProgress', false, { type: 'boolean', description: localize('interactiveSessionRequestInProgress', "True when the current request is still in progress.") });
|
||||
|
||||
export const CONTEXT_INTERACTIVE_INPUT_HAS_TEXT = new RawContextKey<boolean>('interactiveInputHasText', false, { type: 'boolean', description: localize('interactiveInputHasText', "True when the interactive input has text.") });
|
||||
export const CONTEXT_IN_INTERACTIVE_INPUT = new RawContextKey<boolean>('inInteractiveInput', false, { type: 'boolean', description: localize('inInteractiveInput', "True when focus is in the interactive input, false otherwise.") });
|
||||
export const CONTEXT_IN_INTERACTIVE_SESSION = new RawContextKey<boolean>('inChat', false, { type: 'boolean', description: localize('inChat', "True when focus is in the interactive session widget, false otherwise.") });
|
||||
export const CONTEXT_CHAT_INPUT_HAS_TEXT = new RawContextKey<boolean>('chatInputHasText', false, { type: 'boolean', description: localize('interactiveInputHasText', "True when the chat input has text.") });
|
||||
export const CONTEXT_IN_CHAT_INPUT = new RawContextKey<boolean>('inChatInput', false, { type: 'boolean', description: localize('inInteractiveInput', "True when focus is in the chat input, false otherwise.") });
|
||||
export const CONTEXT_IN_CHAT_SESSION = new RawContextKey<boolean>('inChat', false, { type: 'boolean', description: localize('inChat', "True when focus is in the chat widget, false otherwise.") });
|
||||
|
||||
export const CONTEXT_PROVIDER_EXISTS = new RawContextKey<boolean>('hasChatProvider', false, { type: 'boolean', description: localize('hasChatProvider', "True when some interactive session provider has been registered.") });
|
||||
export const CONTEXT_PROVIDER_EXISTS = new RawContextKey<boolean>('hasChatProvider', false, { type: 'boolean', description: localize('hasChatProvider', "True when some chat provider has been registered.") });
|
||||
|
||||
@@ -12,16 +12,16 @@ import { generateUuid } from 'vs/base/common/uuid';
|
||||
import { ILogService } from 'vs/platform/log/common/log';
|
||||
import { IChatProgress, IChatResponse, IChatResponseErrorDetails, IChat, IChatFollowup, IChatReplyFollowup, InteractiveSessionVoteDirection } from 'vs/workbench/contrib/chat/common/chatService';
|
||||
|
||||
export interface IInteractiveRequestModel {
|
||||
export interface IChatRequestModel {
|
||||
readonly id: string;
|
||||
readonly username: string;
|
||||
readonly avatarIconUri?: URI;
|
||||
readonly session: IChatModel;
|
||||
readonly message: string | IChatReplyFollowup;
|
||||
readonly response: IInteractiveResponseModel | undefined;
|
||||
readonly response: IChatResponseModel | undefined;
|
||||
}
|
||||
|
||||
export interface IInteractiveResponseModel {
|
||||
export interface IChatResponseModel {
|
||||
readonly onDidChange: Event<void>;
|
||||
readonly id: string;
|
||||
readonly providerId: string;
|
||||
@@ -38,18 +38,18 @@ export interface IInteractiveResponseModel {
|
||||
setVote(vote: InteractiveSessionVoteDirection): void;
|
||||
}
|
||||
|
||||
export function isRequest(item: unknown): item is IInteractiveRequestModel {
|
||||
return !!item && typeof (item as IInteractiveRequestModel).message !== 'undefined';
|
||||
export function isRequest(item: unknown): item is IChatRequestModel {
|
||||
return !!item && typeof (item as IChatRequestModel).message !== 'undefined';
|
||||
}
|
||||
|
||||
export function isResponse(item: unknown): item is IInteractiveResponseModel {
|
||||
export function isResponse(item: unknown): item is IChatResponseModel {
|
||||
return !isRequest(item);
|
||||
}
|
||||
|
||||
export class InteractiveRequestModel implements IInteractiveRequestModel {
|
||||
export class ChatRequestModel implements IChatRequestModel {
|
||||
private static nextId = 0;
|
||||
|
||||
public response: InteractiveResponseModel | undefined;
|
||||
public response: ChatResponseModel | undefined;
|
||||
|
||||
private _id: string;
|
||||
public get id(): string {
|
||||
@@ -67,11 +67,11 @@ export class InteractiveRequestModel implements IInteractiveRequestModel {
|
||||
constructor(
|
||||
public readonly session: ChatModel,
|
||||
public readonly message: string | IChatReplyFollowup) {
|
||||
this._id = 'request_' + InteractiveRequestModel.nextId++;
|
||||
this._id = 'request_' + ChatRequestModel.nextId++;
|
||||
}
|
||||
}
|
||||
|
||||
export class InteractiveResponseModel extends Disposable implements IInteractiveResponseModel {
|
||||
export class ChatResponseModel extends Disposable implements IChatResponseModel {
|
||||
private readonly _onDidChange = this._register(new Emitter<void>());
|
||||
readonly onDidChange = this._onDidChange.event;
|
||||
|
||||
@@ -133,7 +133,7 @@ export class InteractiveResponseModel extends Disposable implements IInteractive
|
||||
private _followups?: IChatFollowup[]
|
||||
) {
|
||||
super();
|
||||
this._id = 'response_' + InteractiveResponseModel.nextId++;
|
||||
this._id = 'response_' + ChatResponseModel.nextId++;
|
||||
}
|
||||
|
||||
updateContent(responsePart: string) {
|
||||
@@ -178,7 +178,7 @@ export interface IChatModel {
|
||||
readonly welcomeMessage: IChatWelcomeMessageModel | undefined;
|
||||
readonly requestInProgress: boolean;
|
||||
readonly inputPlaceholder?: string;
|
||||
getRequests(): IInteractiveRequestModel[];
|
||||
getRequests(): IChatRequestModel[];
|
||||
waitForInitialization(): Promise<void>;
|
||||
toExport(): IExportableChatData;
|
||||
toJSON(): ISerializableChatData;
|
||||
@@ -234,12 +234,12 @@ export type IChatChangeEvent = IChatAddRequestEvent | IChatAddResponseEvent | IC
|
||||
|
||||
export interface IChatAddRequestEvent {
|
||||
kind: 'addRequest';
|
||||
request: IInteractiveRequestModel;
|
||||
request: IChatRequestModel;
|
||||
}
|
||||
|
||||
export interface IChatAddResponseEvent {
|
||||
kind: 'addResponse';
|
||||
response: IInteractiveResponseModel;
|
||||
response: IChatResponseModel;
|
||||
}
|
||||
|
||||
export interface IChatInitEvent {
|
||||
@@ -253,7 +253,7 @@ export class ChatModel extends Disposable implements IChatModel {
|
||||
private readonly _onDidChange = this._register(new Emitter<IChatChangeEvent>());
|
||||
readonly onDidChange = this._onDidChange.event;
|
||||
|
||||
private _requests: InteractiveRequestModel[];
|
||||
private _requests: ChatRequestModel[];
|
||||
private _isInitializedDeferred = new DeferredPromise<void>();
|
||||
|
||||
private _session: IChat | undefined;
|
||||
@@ -336,7 +336,7 @@ export class ChatModel extends Disposable implements IChatModel {
|
||||
this._initialResponderAvatarIconUri = initialData?.responderAvatarIconUri && URI.revive(initialData.responderAvatarIconUri);
|
||||
}
|
||||
|
||||
private _deserialize(obj: IExportableChatData): InteractiveRequestModel[] {
|
||||
private _deserialize(obj: IExportableChatData): ChatRequestModel[] {
|
||||
const requests = obj.requests;
|
||||
if (!Array.isArray(requests)) {
|
||||
this.logService.error(`Ignoring malformed session data: ${obj}`);
|
||||
@@ -349,9 +349,9 @@ export class ChatModel extends Disposable implements IChatModel {
|
||||
}
|
||||
|
||||
return requests.map((raw: ISerializableChatRequestData) => {
|
||||
const request = new InteractiveRequestModel(this, raw.message);
|
||||
const request = new ChatRequestModel(this, raw.message);
|
||||
if (raw.response || raw.responseErrorDetails) {
|
||||
request.response = new InteractiveResponseModel(new MarkdownString(raw.response), this, true, raw.isCanceled, raw.vote, raw.providerResponseId, raw.responseErrorDetails, raw.followups);
|
||||
request.response = new ChatResponseModel(new MarkdownString(raw.response), this, true, raw.isCanceled, raw.vote, raw.providerResponseId, raw.responseErrorDetails, raw.followups);
|
||||
}
|
||||
return request;
|
||||
});
|
||||
@@ -389,30 +389,30 @@ export class ChatModel extends Disposable implements IChatModel {
|
||||
return this._isInitializedDeferred.p;
|
||||
}
|
||||
|
||||
getRequests(): InteractiveRequestModel[] {
|
||||
getRequests(): ChatRequestModel[] {
|
||||
return this._requests;
|
||||
}
|
||||
|
||||
addRequest(message: string | IChatReplyFollowup): InteractiveRequestModel {
|
||||
addRequest(message: string | IChatReplyFollowup): ChatRequestModel {
|
||||
if (!this._session) {
|
||||
throw new Error('addRequest: No session');
|
||||
}
|
||||
|
||||
const request = new InteractiveRequestModel(this, message);
|
||||
request.response = new InteractiveResponseModel(new MarkdownString(''), this);
|
||||
const request = new ChatRequestModel(this, message);
|
||||
request.response = new ChatResponseModel(new MarkdownString(''), this);
|
||||
|
||||
this._requests.push(request);
|
||||
this._onDidChange.fire({ kind: 'addRequest', request });
|
||||
return request;
|
||||
}
|
||||
|
||||
acceptResponseProgress(request: InteractiveRequestModel, progress: IChatProgress): void {
|
||||
acceptResponseProgress(request: ChatRequestModel, progress: IChatProgress): void {
|
||||
if (!this._session) {
|
||||
throw new Error('acceptResponseProgress: No session');
|
||||
}
|
||||
|
||||
if (!request.response) {
|
||||
request.response = new InteractiveResponseModel(new MarkdownString(''), this);
|
||||
request.response = new ChatResponseModel(new MarkdownString(''), this);
|
||||
}
|
||||
|
||||
if (request.response.isComplete) {
|
||||
@@ -426,25 +426,25 @@ export class ChatModel extends Disposable implements IChatModel {
|
||||
}
|
||||
}
|
||||
|
||||
cancelRequest(request: InteractiveRequestModel): void {
|
||||
cancelRequest(request: ChatRequestModel): void {
|
||||
if (request.response) {
|
||||
request.response.cancel();
|
||||
}
|
||||
}
|
||||
|
||||
completeResponse(request: InteractiveRequestModel, rawResponse: IChatResponse): void {
|
||||
completeResponse(request: ChatRequestModel, rawResponse: IChatResponse): void {
|
||||
if (!this._session) {
|
||||
throw new Error('completeResponse: No session');
|
||||
}
|
||||
|
||||
if (!request.response) {
|
||||
request.response = new InteractiveResponseModel(new MarkdownString(''), this);
|
||||
request.response = new ChatResponseModel(new MarkdownString(''), this);
|
||||
}
|
||||
|
||||
request.response.complete(rawResponse.errorDetails);
|
||||
}
|
||||
|
||||
setFollowups(request: InteractiveRequestModel, followups: IChatFollowup[] | undefined): void {
|
||||
setFollowups(request: ChatRequestModel, followups: IChatFollowup[] | undefined): void {
|
||||
if (!request.response) {
|
||||
// Maybe something went wrong?
|
||||
return;
|
||||
@@ -453,7 +453,7 @@ export class ChatModel extends Disposable implements IChatModel {
|
||||
request.response.setFollowups(followups);
|
||||
}
|
||||
|
||||
setResponse(request: InteractiveRequestModel, response: InteractiveResponseModel): void {
|
||||
setResponse(request: ChatRequestModel, response: ChatResponseModel): void {
|
||||
request.response = response;
|
||||
this._onDidChange.fire({ kind: 'addResponse', response });
|
||||
}
|
||||
@@ -508,11 +508,11 @@ export class ChatModel extends Disposable implements IChatModel {
|
||||
}
|
||||
}
|
||||
|
||||
export type IInteractiveWelcomeMessageContent = IMarkdownString | IChatReplyFollowup[];
|
||||
export type IChatWelcomeMessageContent = IMarkdownString | IChatReplyFollowup[];
|
||||
|
||||
export interface IChatWelcomeMessageModel {
|
||||
readonly id: string;
|
||||
readonly content: IInteractiveWelcomeMessageContent[];
|
||||
readonly content: IChatWelcomeMessageContent[];
|
||||
readonly username: string;
|
||||
readonly avatarIconUri?: URI;
|
||||
|
||||
@@ -526,7 +526,7 @@ export class ChatWelcomeMessageModel implements IChatWelcomeMessageModel {
|
||||
return this._id;
|
||||
}
|
||||
|
||||
constructor(public readonly content: IInteractiveWelcomeMessageContent[], public readonly username: string, public readonly avatarIconUri?: URI) {
|
||||
constructor(public readonly content: IChatWelcomeMessageContent[], public readonly username: string, public readonly avatarIconUri?: URI) {
|
||||
this._id = 'welcome_' + ChatWelcomeMessageModel.nextId++;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -88,6 +88,7 @@ export interface IChatResponseCommandFollowup {
|
||||
|
||||
export type IChatFollowup = IChatReplyFollowup | IChatResponseCommandFollowup;
|
||||
|
||||
// Name has to match the one in vscode.d.ts for some reason
|
||||
export enum InteractiveSessionVoteDirection {
|
||||
Up = 1,
|
||||
Down = 2
|
||||
|
||||
@@ -467,30 +467,30 @@ export class ChatService extends Disposable implements IChatService {
|
||||
const model = Iterable.first(this._sessionModels.values());
|
||||
if (!model) {
|
||||
// If no session, create one- how and is the service the right place to decide this?
|
||||
this.trace('addInteractiveRequest', 'No session available');
|
||||
this.trace('addRequest', 'No session available');
|
||||
return;
|
||||
}
|
||||
|
||||
const provider = this._providers.get(model.providerId);
|
||||
if (!provider || !provider.resolveRequest) {
|
||||
this.trace('addInteractiveRequest', 'No provider available');
|
||||
this.trace('addRequest', 'No provider available');
|
||||
return undefined;
|
||||
}
|
||||
|
||||
this.trace('addInteractiveRequest', `Calling resolveRequest for session ${model.sessionId}`);
|
||||
this.trace('addRequest', `Calling resolveRequest for session ${model.sessionId}`);
|
||||
const request = await provider.resolveRequest(model.session!, context, CancellationToken.None);
|
||||
if (!request) {
|
||||
this.trace('addInteractiveRequest', `Provider returned no request for session ${model.sessionId}`);
|
||||
this.trace('addRequest', `Provider returned no request for session ${model.sessionId}`);
|
||||
return;
|
||||
}
|
||||
|
||||
// Maybe this API should queue a request after the current one?
|
||||
this.trace('addInteractiveRequest', `Sending resolved request for session ${model.sessionId}`);
|
||||
this.trace('addRequest', `Sending resolved request for session ${model.sessionId}`);
|
||||
this.sendRequest(model.sessionId, request.message);
|
||||
}
|
||||
|
||||
async sendRequestToProvider(sessionId: string, message: IChatDynamicRequest): Promise<void> {
|
||||
this.trace('sendInteractiveRequestToProvider', `sessionId: ${sessionId}`);
|
||||
this.trace('sendRequestToProvider', `sessionId: ${sessionId}`);
|
||||
await this.sendRequest(sessionId, message.message);
|
||||
}
|
||||
|
||||
|
||||
@@ -10,19 +10,19 @@ import { URI } from 'vs/base/common/uri';
|
||||
import { localize } from 'vs/nls';
|
||||
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { ILogService } from 'vs/platform/log/common/log';
|
||||
import { IInteractiveRequestModel, IInteractiveResponseModel, IChatModel, IInteractiveWelcomeMessageContent } from 'vs/workbench/contrib/chat/common/chatModel';
|
||||
import { IChatRequestModel, IChatResponseModel, IChatModel, IChatWelcomeMessageContent } from 'vs/workbench/contrib/chat/common/chatModel';
|
||||
import { IChatResponseErrorDetails, IChatReplyFollowup, IChatResponseCommandFollowup, InteractiveSessionVoteDirection } from 'vs/workbench/contrib/chat/common/chatService';
|
||||
import { countWords } from 'vs/workbench/contrib/chat/common/chatWordCounter';
|
||||
|
||||
export function isRequestVM(item: unknown): item is IInteractiveRequestViewModel {
|
||||
export function isRequestVM(item: unknown): item is IChatRequestViewModel {
|
||||
return !!item && typeof item === 'object' && 'message' in item;
|
||||
}
|
||||
|
||||
export function isResponseVM(item: unknown): item is IInteractiveResponseViewModel {
|
||||
return !!item && typeof (item as IInteractiveResponseViewModel).onDidChange !== 'undefined';
|
||||
export function isResponseVM(item: unknown): item is IChatResponseViewModel {
|
||||
return !!item && typeof (item as IChatResponseViewModel).onDidChange !== 'undefined';
|
||||
}
|
||||
|
||||
export function isWelcomeVM(item: unknown): item is IInteractiveWelcomeMessageViewModel {
|
||||
export function isWelcomeVM(item: unknown): item is IChatWelcomeMessageViewModel {
|
||||
return !!item && typeof item === 'object' && 'content' in item;
|
||||
}
|
||||
|
||||
@@ -34,10 +34,10 @@ export interface IChatViewModel {
|
||||
readonly onDidChange: Event<void>;
|
||||
readonly requestInProgress: boolean;
|
||||
readonly inputPlaceholder?: string;
|
||||
getItems(): (IInteractiveRequestViewModel | IInteractiveResponseViewModel | IInteractiveWelcomeMessageViewModel)[];
|
||||
getItems(): (IChatRequestViewModel | IChatResponseViewModel | IChatWelcomeMessageViewModel)[];
|
||||
}
|
||||
|
||||
export interface IInteractiveRequestViewModel {
|
||||
export interface IChatRequestViewModel {
|
||||
readonly id: string;
|
||||
/** This ID updates every time the underlying data changes */
|
||||
readonly dataId: string;
|
||||
@@ -48,7 +48,7 @@ export interface IInteractiveRequestViewModel {
|
||||
currentRenderedHeight: number | undefined;
|
||||
}
|
||||
|
||||
export interface IInteractiveResponseRenderData {
|
||||
export interface IChatResponseRenderData {
|
||||
renderedWordCount: number;
|
||||
lastRenderTime: number;
|
||||
isFullyRendered: boolean;
|
||||
@@ -61,7 +61,7 @@ export interface IChatLiveUpdateData {
|
||||
impliedWordLoadRate: number;
|
||||
}
|
||||
|
||||
export interface IInteractiveResponseViewModel {
|
||||
export interface IChatResponseViewModel {
|
||||
readonly onDidChange: Event<void>;
|
||||
readonly id: string;
|
||||
/** This ID updates every time the underlying data changes */
|
||||
@@ -79,7 +79,7 @@ export interface IInteractiveResponseViewModel {
|
||||
readonly commandFollowups?: IChatResponseCommandFollowup[];
|
||||
readonly errorDetails?: IChatResponseErrorDetails;
|
||||
readonly contentUpdateTimings?: IChatLiveUpdateData;
|
||||
renderData?: IInteractiveResponseRenderData;
|
||||
renderData?: IChatResponseRenderData;
|
||||
currentRenderedHeight: number | undefined;
|
||||
setVote(vote: InteractiveSessionVoteDirection): void;
|
||||
}
|
||||
@@ -91,7 +91,7 @@ export class ChatViewModel extends Disposable implements IChatViewModel {
|
||||
private readonly _onDidChange = this._register(new Emitter<void>());
|
||||
readonly onDidChange = this._onDidChange.event;
|
||||
|
||||
private readonly _items: (IInteractiveRequestViewModel | IInteractiveResponseViewModel)[] = [];
|
||||
private readonly _items: (IChatRequestViewModel | IChatResponseViewModel)[] = [];
|
||||
|
||||
get inputPlaceholder(): string | undefined {
|
||||
return this._model.inputPlaceholder;
|
||||
@@ -120,7 +120,7 @@ export class ChatViewModel extends Disposable implements IChatViewModel {
|
||||
super();
|
||||
|
||||
_model.getRequests().forEach((request, i) => {
|
||||
this._items.push(new InteractiveRequestViewModel(request));
|
||||
this._items.push(new ChatRequestViewModel(request));
|
||||
if (request.response) {
|
||||
this.onAddResponse(request.response);
|
||||
}
|
||||
@@ -129,7 +129,7 @@ export class ChatViewModel extends Disposable implements IChatViewModel {
|
||||
this._register(_model.onDidDispose(() => this._onDidDisposeModel.fire()));
|
||||
this._register(_model.onDidChange(e => {
|
||||
if (e.kind === 'addRequest') {
|
||||
this._items.push(new InteractiveRequestViewModel(e.request));
|
||||
this._items.push(new ChatRequestViewModel(e.request));
|
||||
if (e.request.response) {
|
||||
this.onAddResponse(e.request.response);
|
||||
}
|
||||
@@ -141,8 +141,8 @@ export class ChatViewModel extends Disposable implements IChatViewModel {
|
||||
}));
|
||||
}
|
||||
|
||||
private onAddResponse(responseModel: IInteractiveResponseModel) {
|
||||
const response = this.instantiationService.createInstance(InteractiveResponseViewModel, responseModel);
|
||||
private onAddResponse(responseModel: IChatResponseModel) {
|
||||
const response = this.instantiationService.createInstance(ChatResponseViewModel, responseModel);
|
||||
this._register(response.onDidChange(() => this._onDidChange.fire()));
|
||||
this._items.push(response);
|
||||
}
|
||||
@@ -154,12 +154,12 @@ export class ChatViewModel extends Disposable implements IChatViewModel {
|
||||
override dispose() {
|
||||
super.dispose();
|
||||
this._items
|
||||
.filter((item): item is InteractiveResponseViewModel => item instanceof InteractiveResponseViewModel)
|
||||
.forEach((item: InteractiveResponseViewModel) => item.dispose());
|
||||
.filter((item): item is ChatResponseViewModel => item instanceof ChatResponseViewModel)
|
||||
.forEach((item: ChatResponseViewModel) => item.dispose());
|
||||
}
|
||||
}
|
||||
|
||||
export class InteractiveRequestViewModel implements IInteractiveRequestViewModel {
|
||||
export class ChatRequestViewModel implements IChatRequestViewModel {
|
||||
get id() {
|
||||
return this._model.id;
|
||||
}
|
||||
@@ -186,10 +186,10 @@ export class InteractiveRequestViewModel implements IInteractiveRequestViewModel
|
||||
|
||||
currentRenderedHeight: number | undefined;
|
||||
|
||||
constructor(readonly _model: IInteractiveRequestModel) { }
|
||||
constructor(readonly _model: IChatRequestModel) { }
|
||||
}
|
||||
|
||||
export class InteractiveResponseViewModel extends Disposable implements IInteractiveResponseViewModel {
|
||||
export class ChatResponseViewModel extends Disposable implements IChatResponseViewModel {
|
||||
private _modelChangeCount = 0;
|
||||
|
||||
private readonly _onDidChange = this._register(new Emitter<void>());
|
||||
@@ -256,7 +256,7 @@ export class InteractiveResponseViewModel extends Disposable implements IInterac
|
||||
return this._model.vote;
|
||||
}
|
||||
|
||||
renderData: IInteractiveResponseRenderData | undefined = undefined;
|
||||
renderData: IChatResponseRenderData | undefined = undefined;
|
||||
|
||||
currentRenderedHeight: number | undefined;
|
||||
|
||||
@@ -266,7 +266,7 @@ export class InteractiveResponseViewModel extends Disposable implements IInterac
|
||||
}
|
||||
|
||||
constructor(
|
||||
private readonly _model: IInteractiveResponseModel,
|
||||
private readonly _model: IChatResponseModel,
|
||||
@ILogService private readonly logService: ILogService
|
||||
) {
|
||||
super();
|
||||
@@ -305,7 +305,7 @@ export class InteractiveResponseViewModel extends Disposable implements IInterac
|
||||
this.trace(`onDidChange`, `Done- got ${wordCount} words over ${timeDiff}ms = ${impliedWordLoadRate} words/s. ${this.renderData?.renderedWordCount} words are rendered.`);
|
||||
}
|
||||
} else {
|
||||
this.logService.warn('InteractiveResponseViewModel#onDidChange: got model update but contentUpdateTimings is not initialized');
|
||||
this.logService.warn('ChatResponseViewModel#onDidChange: got model update but contentUpdateTimings is not initialized');
|
||||
}
|
||||
|
||||
// new data -> new id, new content to render
|
||||
@@ -320,7 +320,7 @@ export class InteractiveResponseViewModel extends Disposable implements IInterac
|
||||
}
|
||||
|
||||
private trace(tag: string, message: string) {
|
||||
this.logService.trace(`InteractiveResponseViewModel#${tag}: ${message}`);
|
||||
this.logService.trace(`ChatResponseViewModel#${tag}: ${message}`);
|
||||
}
|
||||
|
||||
setVote(vote: InteractiveSessionVoteDirection): void {
|
||||
@@ -329,9 +329,9 @@ export class InteractiveResponseViewModel extends Disposable implements IInterac
|
||||
}
|
||||
}
|
||||
|
||||
export interface IInteractiveWelcomeMessageViewModel {
|
||||
export interface IChatWelcomeMessageViewModel {
|
||||
readonly id: string;
|
||||
readonly username: string;
|
||||
readonly avatarIconUri?: URI;
|
||||
readonly content: IInteractiveWelcomeMessageContent[];
|
||||
readonly content: IChatWelcomeMessageContent[];
|
||||
}
|
||||
|
||||
@@ -188,7 +188,7 @@ suite('Chat', () => {
|
||||
assert.strictEqual(commands?.[0].sortText, 'sortText');
|
||||
});
|
||||
|
||||
test('sendInteractiveRequestToProvider', async () => {
|
||||
test('sendRequestToProvider', async () => {
|
||||
const testService = instantiationService.createInstance(ChatService);
|
||||
testService.registerProvider(new SimpleTestProvider('testProvider'));
|
||||
|
||||
|
||||
@@ -307,7 +307,7 @@ export class AskInInteractiveAction extends Action2 {
|
||||
constructor() {
|
||||
super({
|
||||
id: AskInInteractiveAction.ID,
|
||||
title: { value: localize('askInChat', "Ask In Interactive Session"), original: 'Ask In Interactive Session' },
|
||||
title: { value: localize('askInChat', "Ask In Chat"), original: 'Ask In Chat' },
|
||||
f1: false
|
||||
});
|
||||
}
|
||||
@@ -325,12 +325,12 @@ export class AskInInteractiveAction extends Action2 {
|
||||
const providerInfos = chatService.getProviderInfos();
|
||||
switch (providerInfos.length) {
|
||||
case 0:
|
||||
throw new Error('No interactive session provider found.');
|
||||
throw new Error('No chat provider found.');
|
||||
case 1:
|
||||
providerId = providerInfos[0].id;
|
||||
break;
|
||||
default:
|
||||
logService.warn('Multiple interactive session providers found. Using the first one.');
|
||||
logService.warn('Multiple chat providers found. Using the first one.');
|
||||
providerId = providerInfos[0].id;
|
||||
break;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user