Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Chat view unification #243285

Draft
wants to merge 12 commits into
base: main
Choose a base branch
from
3 changes: 2 additions & 1 deletion src/vs/workbench/api/browser/mainThreadChatAgents2.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,12 @@ import { ILogService } from '../../../platform/log/common/log.js';
import { IChatWidgetService } from '../../contrib/chat/browser/chat.js';
import { ChatInputPart } from '../../contrib/chat/browser/chatInputPart.js';
import { AddDynamicVariableAction, IAddDynamicVariableContext } from '../../contrib/chat/browser/contrib/chatDynamicVariables.js';
import { ChatAgentLocation, IChatAgentHistoryEntry, IChatAgentImplementation, IChatAgentRequest, IChatAgentService } from '../../contrib/chat/common/chatAgents.js';
import { IChatAgentHistoryEntry, IChatAgentImplementation, IChatAgentRequest, IChatAgentService } from '../../contrib/chat/common/chatAgents.js';
import { IChatEditingService, IChatRelatedFileProviderMetadata } from '../../contrib/chat/common/chatEditingService.js';
import { ChatRequestAgentPart } from '../../contrib/chat/common/chatParserTypes.js';
import { ChatRequestParser } from '../../contrib/chat/common/chatRequestParser.js';
import { IChatContentInlineReference, IChatContentReference, IChatFollowup, IChatNotebookEdit, IChatProgress, IChatService, IChatTask, IChatWarningMessage } from '../../contrib/chat/common/chatService.js';
import { ChatAgentLocation } from '../../contrib/chat/common/constants.js';
import { IExtHostContext, extHostNamedCustomer } from '../../services/extensions/common/extHostCustomers.js';
import { IExtensionService } from '../../services/extensions/common/extensions.js';
import { Dto } from '../../services/extensions/common/proxyIdentifier.js';
Expand Down
3 changes: 2 additions & 1 deletion src/vs/workbench/api/common/extHost.protocol.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,12 +51,13 @@ import { WorkspaceTrustRequestOptions } from '../../../platform/workspace/common
import { SaveReason } from '../../common/editor.js';
import { IRevealOptions, ITreeItem, IViewBadge } from '../../common/views.js';
import { CallHierarchyItem } from '../../contrib/callHierarchy/common/callHierarchy.js';
import { ChatAgentLocation, IChatAgentMetadata, IChatAgentRequest, IChatAgentResult, IChatWelcomeMessageContent } from '../../contrib/chat/common/chatAgents.js';
import { IChatAgentMetadata, IChatAgentRequest, IChatAgentResult, IChatWelcomeMessageContent } from '../../contrib/chat/common/chatAgents.js';
import { ICodeMapperRequest, ICodeMapperResult } from '../../contrib/chat/common/chatCodeMapperService.js';
import { IChatRelatedFile, IChatRelatedFileProviderMetadata as IChatRelatedFilesProviderMetadata, IChatRequestDraft } from '../../contrib/chat/common/chatEditingService.js';
import { IChatProgressHistoryResponseContent } from '../../contrib/chat/common/chatModel.js';
import { IChatContentInlineReference, IChatFollowup, IChatNotebookEdit, IChatProgress, IChatResponseErrorDetails, IChatTask, IChatTaskDto, IChatUserActionEvent, IChatVoteAction } from '../../contrib/chat/common/chatService.js';
import { IChatRequestVariableValue } from '../../contrib/chat/common/chatVariables.js';
import { ChatAgentLocation } from '../../contrib/chat/common/constants.js';
import { IChatMessage, IChatResponseFragment, ILanguageModelChatMetadata, ILanguageModelChatSelector, ILanguageModelsChangeEvent } from '../../contrib/chat/common/languageModels.js';
import { IPreparedToolInvocation, IToolData, IToolInvocation, IToolResult } from '../../contrib/chat/common/languageModelToolsService.js';
import { DebugConfigurationProviderTriggerKind, IAdapterDescriptor, IConfig, IDebugSessionReplMode, IDebugTestRunReference, IDebugVisualization, IDebugVisualizationContext, IDebugVisualizationTreeItem, MainThreadDebugVisualization } from '../../contrib/debug/common/debug.js';
Expand Down
9 changes: 5 additions & 4 deletions src/vs/workbench/api/common/extHostChatAgents2.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,19 +20,20 @@ import { generateUuid } from '../../../base/common/uuid.js';
import { Location } from '../../../editor/common/languages.js';
import { ExtensionIdentifier, IExtensionDescription, IRelaxedExtensionDescription } from '../../../platform/extensions/common/extensions.js';
import { ILogService } from '../../../platform/log/common/log.js';
import { ChatAgentLocation, IChatAgentRequest, IChatAgentResult, IChatAgentResultTimings, IChatWelcomeMessageContent } from '../../contrib/chat/common/chatAgents.js';
import { isChatViewTitleActionContext } from '../../contrib/chat/common/chatActions.js';
import { IChatAgentRequest, IChatAgentResult, IChatAgentResultTimings, IChatWelcomeMessageContent } from '../../contrib/chat/common/chatAgents.js';
import { IChatRelatedFile, IChatRequestDraft } from '../../contrib/chat/common/chatEditingService.js';
import { ChatAgentVoteDirection, IChatContentReference, IChatFollowup, IChatResponseErrorDetails, IChatUserActionEvent, IChatVoteAction } from '../../contrib/chat/common/chatService.js';
import { ChatAgentLocation } from '../../contrib/chat/common/constants.js';
import { checkProposedApiEnabled, isProposedApiEnabled } from '../../services/extensions/common/extensions.js';
import { Dto } from '../../services/extensions/common/proxyIdentifier.js';
import { ExtHostChatAgentsShape2, IChatAgentCompletionItem, IChatAgentHistoryEntryDto, IChatProgressDto, IExtensionChatAgentMetadata, IMainContext, MainContext, MainThreadChatAgentsShape2 } from './extHost.protocol.js';
import { CommandsConverter, ExtHostCommands } from './extHostCommands.js';
import { ExtHostDiagnostics } from './extHostDiagnostics.js';
import { ExtHostDocuments } from './extHostDocuments.js';
import { ExtHostLanguageModels } from './extHostLanguageModels.js';
import * as typeConvert from './extHostTypeConverters.js';
import * as extHostTypes from './extHostTypes.js';
import { isChatViewTitleActionContext } from '../../contrib/chat/common/chatActions.js';
import { IChatRelatedFile, IChatRequestDraft } from '../../contrib/chat/common/chatEditingService.js';
import { ExtHostDiagnostics } from './extHostDiagnostics.js';

class ChatAgentResponseStream {

Expand Down
3 changes: 2 additions & 1 deletion src/vs/workbench/api/common/extHostTypeConverters.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ import { IMarkerData, IRelatedInformation, MarkerSeverity, MarkerTag } from '../
import { ProgressLocation as MainProgressLocation } from '../../../platform/progress/common/progress.js';
import { DEFAULT_EDITOR_ASSOCIATION, SaveReason } from '../../common/editor.js';
import { IViewBadge } from '../../common/views.js';
import { ChatAgentLocation, IChatAgentRequest, IChatAgentResult } from '../../contrib/chat/common/chatAgents.js';
import { IChatAgentRequest, IChatAgentResult } from '../../contrib/chat/common/chatAgents.js';
import { IChatRequestDraft } from '../../contrib/chat/common/chatEditingService.js';
import { IChatRequestVariableEntry } from '../../contrib/chat/common/chatModel.js';
import { IChatAgentMarkdownContentWithVulnerability, IChatCodeCitation, IChatCommandButton, IChatConfirmation, IChatContentInlineReference, IChatContentReference, IChatFollowup, IChatMarkdownContent, IChatMoveMessage, IChatProgressMessage, IChatResponseCodeblockUriPart, IChatTaskDto, IChatTaskResult, IChatTextEdit, IChatTreeData, IChatUserActionEvent, IChatWarningMessage } from '../../contrib/chat/common/chatService.js';
Expand All @@ -62,6 +62,7 @@ import { CommandsConverter } from './extHostCommands.js';
import { getPrivateApiFor } from './extHostTestingPrivateApi.js';
import * as types from './extHostTypes.js';
import { LanguageModelPromptTsxPart, LanguageModelTextPart } from './extHostTypes.js';
import { ChatAgentLocation } from '../../contrib/chat/common/constants.js';

export namespace Command {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ import { IKeybindingService } from '../../../../../platform/keybinding/common/ke
import { ActiveAuxiliaryContext } from '../../../../common/contextkeys.js';
import { AccessibilityVerbositySettingId } from '../../../accessibility/browser/accessibilityConfiguration.js';
import { INLINE_CHAT_ID } from '../../../inlineChat/common/inlineChat.js';
import { ChatAgentLocation } from '../../common/chatAgents.js';
import { ChatContextKeys } from '../../common/chatContextKeys.js';
import { ChatAgentLocation } from '../../common/constants.js';
import { IChatWidgetService } from '../chat.js';

export class PanelChatAccessibilityHelp implements IAccessibleViewImplementation {
Expand Down
3 changes: 2 additions & 1 deletion src/vs/workbench/contrib/chat/browser/actions/chatActions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,8 @@ import { ACTIVE_GROUP, IEditorService } from '../../../../services/editor/common
import { IHostService } from '../../../../services/host/browser/host.js';
import { IViewsService } from '../../../../services/views/common/viewsService.js';
import { EXTENSIONS_CATEGORY, IExtensionsWorkbenchService } from '../../../extensions/common/extensions.js';
import { ChatAgentLocation, IChatAgentService } from '../../common/chatAgents.js';
import { IChatAgentService } from '../../common/chatAgents.js';
import { ChatAgentLocation } from '../../common/constants.js';
import { ChatContextKeys } from '../../common/chatContextKeys.js';
import { extractAgentAndCommand } from '../../common/chatParserTypes.js';
import { IChatDetail, IChatService } from '../../common/chatService.js';
Expand Down
20 changes: 12 additions & 8 deletions src/vs/workbench/contrib/chat/browser/actions/chatClearActions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,9 @@ import { KeybindingWeight } from '../../../../../platform/keybinding/common/keyb
import { ActiveEditorContext } from '../../../../common/contextkeys.js';
import { IViewsService } from '../../../../services/views/common/viewsService.js';
import { isChatViewTitleActionContext } from '../../common/chatActions.js';
import { ChatAgentLocation } from '../../common/chatAgents.js';
import { ChatContextKeys } from '../../common/chatContextKeys.js';
import { hasAppliedChatEditsContextKey, hasUndecidedChatEditingResourceContextKey, IChatEditingSession, WorkingSetEntryState } from '../../common/chatEditingService.js';
import { ChatMode } from '../../common/constants.js';
import { ChatAgentLocation, ChatMode } from '../../common/constants.js';
import { ChatViewId, EditsViewId, IChatWidget, IChatWidgetService } from '../chat.js';
import { EditingSessionAction } from '../chatEditing/chatEditingActions.js';
import { ctxIsGlobalEditingSession } from '../chatEditing/chatEditingEditorContextKeys.js';
Expand Down Expand Up @@ -348,12 +347,16 @@ export function registerNewChatActions() {
precondition: ChatContextKeys.Setup.hidden.toNegated(),
menu: [{
id: MenuId.ViewTitle,
when: ContextKeyExpr.and(ContextKeyExpr.equals('view', ChatViewId), ChatContextKeys.editingParticipantRegistered,
when: ContextKeyExpr.and(
ContextKeyExpr.equals('view', ChatViewId),
ChatContextKeys.editingParticipantRegistered,
ContextKeyExpr.equals(`view.${EditsViewId}.visible`, false),
ContextKeyExpr.or(
ContextKeyExpr.and(ContextKeyExpr.equals(`workbench.panel.chat.defaultViewContainerLocation`, true), ContextKeyExpr.equals(`workbench.panel.chatEditing.defaultViewContainerLocation`, false)),
ContextKeyExpr.and(ContextKeyExpr.equals(`workbench.panel.chat.defaultViewContainerLocation`, false), ContextKeyExpr.equals(`workbench.panel.chatEditing.defaultViewContainerLocation`, true)),
)),
),
ChatContextKeys.inUnifiedChat.negate()
),
group: 'navigation',
order: 1
}, {
Expand All @@ -380,17 +383,18 @@ export function registerNewChatActions() {
async run(accessor: ServicesAccessor, opts?: string | IChatViewOpenOptions) {
opts = typeof opts === 'string' ? { query: opts } : opts;
const viewsService = accessor.get(IViewsService);
const chatView = await viewsService.openView(EditsViewId) as ChatViewPane;
const chatView = await viewsService.openView<ChatViewPane>(EditsViewId)
?? await viewsService.openView<ChatViewPane>(ChatViewId);

if (opts?.query) {
if (opts.isPartialQuery) {
chatView.widget.setInput(opts.query);
chatView?.widget.setInput(opts.query);
} else {
chatView.widget.acceptInput(opts.query);
chatView?.widget.acceptInput(opts.query);
}
}

chatView.widget.focusInput();
chatView?.widget.focusInput();
}
});
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,10 @@ import { IEditorService } from '../../../../services/editor/common/editorService
import { accessibleViewInCodeBlock } from '../../../accessibility/browser/accessibilityConfiguration.js';
import { reviewEdits } from '../../../inlineChat/browser/inlineChatController.js';
import { ITerminalEditorService, ITerminalGroupService, ITerminalService } from '../../../terminal/browser/terminal.js';
import { ChatAgentLocation } from '../../common/chatAgents.js';
import { ChatContextKeys } from '../../common/chatContextKeys.js';
import { ChatCopyKind, IChatService } from '../../common/chatService.js';
import { IChatResponseViewModel, isResponseVM } from '../../common/chatViewModel.js';
import { ChatAgentLocation } from '../../common/constants.js';
import { IChatCodeBlockContextProviderService, IChatWidgetService } from '../chat.js';
import { DefaultChatTextEditor, ICodeBlockActionContext, ICodeCompareBlockActionContext } from '../codeBlockPart.js';
import { CHAT_CATEGORY } from './chatActions.js';
Expand Down
80 changes: 51 additions & 29 deletions src/vs/workbench/contrib/chat/browser/actions/chatExecuteActions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,17 +13,17 @@ import { ContextKeyExpr } from '../../../../../platform/contextkey/common/contex
import { IDialogService } from '../../../../../platform/dialogs/common/dialogs.js';
import { KeybindingWeight } from '../../../../../platform/keybinding/common/keybindingsRegistry.js';
import { IViewsService } from '../../../../services/views/common/viewsService.js';
import { ChatAgentLocation, IChatAgentService } from '../../common/chatAgents.js';
import { ChatContextKeys } from '../../common/chatContextKeys.js';
import { IChatAgentService } from '../../common/chatAgents.js';
import { ChatContextKeyExprs, ChatContextKeys } from '../../common/chatContextKeys.js';
import { IChatEditingService, IChatEditingSession, WorkingSetEntryState } from '../../common/chatEditingService.js';
import { chatAgentLeader, extractAgentAndCommand } from '../../common/chatParserTypes.js';
import { IChatService } from '../../common/chatService.js';
import { ChatMode } from '../../common/constants.js';
import { ChatAgentLocation, ChatMode } from '../../common/constants.js';
import { EditsViewId, IChatWidget, IChatWidgetService } from '../chat.js';
import { discardAllEditsWithConfirmation, EditingSessionAction } from '../chatEditing/chatEditingActions.js';
import { discardAllEditsWithConfirmation, getEditingSessionContext } from '../chatEditing/chatEditingActions.js';
import { ChatViewPane } from '../chatViewPane.js';
import { CHAT_CATEGORY } from './chatActions.js';
import { ChatDoneActionId } from './chatClearActions.js';
import { ACTION_ID_NEW_CHAT, ChatDoneActionId } from './chatClearActions.js';

export interface IVoiceChatExecuteActionContext {
readonly disableTimeout?: boolean;
Expand Down Expand Up @@ -93,63 +93,74 @@ export class ChatSubmitAction extends SubmitAction {

export const ToggleAgentModeActionId = 'workbench.action.chat.toggleAgentMode';

export interface IToggleAgentModeArgs {
agentMode: boolean;
export interface IToggleChatModeArgs {
mode: ChatMode;
}

export class ToggleAgentModeAction extends EditingSessionAction {
class ToggleChatModeAction extends Action2 {

static readonly ID = ToggleAgentModeActionId;

constructor() {
super({
id: ToggleAgentModeAction.ID,
title: localize2('interactive.toggleMode.label', "Toggle Chat Mode (Experimental)"),
id: ToggleChatModeAction.ID,
title: localize2('interactive.toggleAgent.label', "Set Chat Mode (Experimental)"),
f1: true,
category: CHAT_CATEGORY,
precondition: ContextKeyExpr.and(
ChatContextKeys.enabled,
ChatContextKeys.Editing.hasToolsAgent,
ContextKeyExpr.or(
ChatContextKeys.Editing.hasToolsAgent,
ChatContextKeyExprs.unifiedChatEnabled),
ChatContextKeys.requestInProgress.negate()),
tooltip: localize('setChatMode', "Set Mode (Experimental)"),
keybinding: {
when: ContextKeyExpr.and(
ChatContextKeys.inChatInput,
ChatContextKeys.location.isEqualTo(ChatAgentLocation.EditingSession)),
ChatContextKeyExprs.inEditsOrUnified),
primary: KeyMod.CtrlCmd | KeyCode.Period,
weight: KeybindingWeight.EditorContrib
},
menu: [
{
id: MenuId.ChatExecute,
order: 1,
when: ContextKeyExpr.and(
ChatContextKeys.location.isEqualTo(ChatAgentLocation.EditingSession),
ChatContextKeys.Editing.hasToolsAgent),
// Either in edits with agent mode available, or in unified chat view
when: ContextKeyExpr.or(
ContextKeyExpr.and(
ChatContextKeys.location.isEqualTo(ChatAgentLocation.EditingSession),
ChatContextKeys.Editing.hasToolsAgent,
),
ChatContextKeys.inUnifiedChat),
group: 'navigation',
},
]
});
}

override async runEditingSessionAction(accessor: ServicesAccessor, currentEditingSession: IChatEditingSession, chatWidget: IChatWidget, ...args: any[]) {

async run(accessor: ServicesAccessor, ...args: any[]) {
const chatService = accessor.get(IChatService);
const commandService = accessor.get(ICommandService);
const dialogService = accessor.get(IDialogService);

const entries = currentEditingSession.entries.get();
if (entries.length > 0 && entries.some(entry => entry.state.get() === WorkingSetEntryState.Modified)) {
if (!await discardAllEditsWithConfirmation(accessor, currentEditingSession)) {
const context = getEditingSessionContext(accessor, args);
if (!context?.chatWidget) {
return;
}

// TODO will not require discarding the session when we are able to switch modes mid-session
const entries = context.editingSession?.entries.get();
if (context.editingSession && entries && entries.length > 0 && entries.some(entry => entry.state.get() === WorkingSetEntryState.Modified)) {
if (!await discardAllEditsWithConfirmation(accessor, context.editingSession)) {
// User cancelled
return;
}
} else {
const chatSession = chatService.getSession(currentEditingSession.chatSessionId);
const chatSession = context.chatWidget.viewModel?.model;
if (chatSession?.getRequests().length) {
const confirmation = await dialogService.confirm({
title: localize('agent.newSession', "Start new session?"),
message: localize('agent.newSessionMessage', "Toggling agent mode will start a new session. Would you like to continue?"),
message: localize('agent.newSessionMessage', "Changing the chat mode will start a new session. Would you like to continue?"),
primaryButton: localize('agent.newSession.confirm', "Yes"),
type: 'info'
});
Expand All @@ -159,13 +170,24 @@ export class ToggleAgentModeAction extends EditingSessionAction {
}
}

const arg = args[0] as IToggleAgentModeArgs | undefined;
const setTo = arg ?
(arg.agentMode ? ChatMode.Agent : ChatMode.Edit) :
(chatWidget.input.toolsAgentModeEnabled ? ChatMode.Edit : ChatMode.Agent);
chatWidget.input.setChatMode(setTo);
const arg = args[0] as IToggleChatModeArgs | undefined;
if (arg?.mode) {
context.chatWidget.input.setChatMode(arg.mode);
} else {
const modes = [ChatMode.Agent, ChatMode.Edit];
if (context.chatWidget.location === ChatAgentLocation.Panel) {
modes.push(ChatMode.Chat);
}

const modeIndex = modes.indexOf(context.chatWidget.input.currentMode);
const newMode = modes[(modeIndex + 1) % modes.length];
context.chatWidget.input.setChatMode(newMode);
}

await commandService.executeCommand(ChatDoneActionId);
if (context.chatWidget.viewModel?.model.getRequests().length) {
const clearAction = chatService.unifiedViewEnabled ? ACTION_ID_NEW_CHAT : ChatDoneActionId;
await commandService.executeCommand(clearAction);
}
}
}

Expand Down Expand Up @@ -576,7 +598,7 @@ export function registerChatExecuteActions() {
registerAction2(SendToNewChatAction);
registerAction2(ChatSubmitSecondaryAgentAction);
registerAction2(SendToChatEditingAction);
registerAction2(ToggleAgentModeAction);
registerAction2(ToggleChatModeAction);
registerAction2(ToggleRequestPausedAction);
registerAction2(SwitchToNextModelAction);
}
Loading
Loading