Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/vs/platform/accessibility/browser/accessibleView.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ export const enum AccessibleViewProviderId {
InlineChat = 'inlineChat',
AgentChat = 'agentChat',
QuickChat = 'quickChat',
ChatInputWindow = 'chatInputWindow',
InlineCompletions = 'inlineCompletions',
KeybindingsEditor = 'keybindingsEditor',
Notebook = 'notebook',
Expand Down
1 change: 1 addition & 0 deletions src/vs/platform/actions/common/actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -265,6 +265,7 @@ export class MenuId {
static readonly ChatInputSecondary = new MenuId('ChatInputSecondary');
static readonly ChatInputStatus = new MenuId('ChatInputStatus');
static readonly ChatInputSide = new MenuId('ChatInputSide');
static readonly ChatInputWindowSide = new MenuId('ChatInputWindowSide');
static readonly AutomationsDialogInput = new MenuId('AutomationsDialogInput');
static readonly ChatModePicker = new MenuId('ChatModePicker');
static readonly ChatEditingWidgetToolbar = new MenuId('ChatEditingWidgetToolbar');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,16 @@ export class QuickChatAccessibilityHelp implements IAccessibleViewImplementation
}
}

export class ChatInputWindowAccessibilityHelp implements IAccessibleViewImplementation {
readonly priority = 121;
readonly name = 'chatInputWindow';
readonly type = AccessibleViewType.Help;
readonly when = ChatContextKeys.inChatInputWindow;
getProvider(accessor: ServicesAccessor) {
return getChatAccessibilityHelpProvider(accessor, undefined, 'chatInputWindow');
}
}

export class EditsChatAccessibilityHelp implements IAccessibleViewImplementation {
readonly priority = 119;
readonly name = 'editsView';
Expand All @@ -60,8 +70,17 @@ export class AgentChatAccessibilityHelp implements IAccessibleViewImplementation
}
}

export function getAccessibilityHelpText(type: 'panelChat' | 'inlineChat' | 'quickChat' | 'editsView' | 'agentView', keybindingService: IKeybindingService): string {
export function getAccessibilityHelpText(type: 'panelChat' | 'inlineChat' | 'quickChat' | 'editsView' | 'agentView' | 'chatInputWindow', keybindingService: IKeybindingService): string {
const content = [];
if (type === 'chatInputWindow') {
content.push(localize('chatInputWindow.overview', 'The floating chat input window is an input-only surface. It has no response list; instead each request you submit is routed to the coding session it best matches, and its response appears in that session rather than here.'));
content.push(localize('chatInputWindow.routing', 'When no existing session is a confident match, a new session is started for the request. When several sessions match with comparable confidence, you are asked to choose one from a picker, which also offers starting a new session.'));
content.push(localize('chatInputWindow.requestHistory', 'In the input box, use up and down arrows to navigate your request history. Edit input and use Enter or the submit button to route a new request.'));
content.push(localize('chatInputWindow.dictate', 'To dictate your request using on-device speech-to-text, invoke the Dictate command{0}. Invoke it again to stop.', '<keybinding:workbench.action.chat.toggleSpeechToText>'));
content.push(localize('chatInputWindow.close', 'To close the floating chat input window, invoke the Close Floating Chat Input Window command, or toggle it with the Toggle Floating Chat Input Window command{0}.', '<keybinding:workbench.action.chat.toggleInputWindow>'));
content.push(localize('chatInputWindow.signals', "Accessibility Signals can be changed via settings with a prefix of signals.chat. By default, if a request takes more than 4 seconds, you will hear a sound indicating that progress is still occurring."));
return content.join('\n');
}
if (type === 'panelChat' || type === 'quickChat' || type === 'editsView' || type === 'agentView') {
content.push(localize('chat.fileChangesDisclosure', 'File change summaries show the total files, additions, and deletions. Focus the disclosure and press Enter or Space to show or hide the individual files.'));
}
Expand Down Expand Up @@ -148,7 +167,7 @@ export function getAccessibilityHelpText(type: 'panelChat' | 'inlineChat' | 'qui
return content.join('\n');
}

export function getChatAccessibilityHelpProvider(accessor: ServicesAccessor, editor: ICodeEditor | undefined, type: 'panelChat' | 'inlineChat' | 'quickChat' | 'editsView' | 'agentView'): AccessibleContentProvider | undefined {
export function getChatAccessibilityHelpProvider(accessor: ServicesAccessor, editor: ICodeEditor | undefined, type: 'panelChat' | 'inlineChat' | 'quickChat' | 'editsView' | 'agentView' | 'chatInputWindow'): AccessibleContentProvider | undefined {
const widgetService = accessor.get(IChatWidgetService);
const keybindingService = accessor.get(IKeybindingService);
const inputEditor: ICodeEditor | undefined = widgetService.lastFocusedWidget?.inputEditor;
Expand All @@ -165,11 +184,11 @@ export function getChatAccessibilityHelpProvider(accessor: ServicesAccessor, edi
inputEditor.getSupportedActions();
const helpText = getAccessibilityHelpText(type, keybindingService);
return new AccessibleContentProvider(
type === 'panelChat' ? AccessibleViewProviderId.PanelChat : type === 'inlineChat' ? AccessibleViewProviderId.InlineChat : type === 'agentView' ? AccessibleViewProviderId.AgentChat : AccessibleViewProviderId.QuickChat,
type === 'panelChat' ? AccessibleViewProviderId.PanelChat : type === 'inlineChat' ? AccessibleViewProviderId.InlineChat : type === 'agentView' ? AccessibleViewProviderId.AgentChat : type === 'chatInputWindow' ? AccessibleViewProviderId.ChatInputWindow : AccessibleViewProviderId.QuickChat,
{ type: AccessibleViewType.Help },
() => helpText,
() => {
if (type === 'quickChat' || type === 'editsView' || type === 'agentView' || type === 'panelChat') {
if (type === 'quickChat' || type === 'editsView' || type === 'agentView' || type === 'panelChat' || type === 'chatInputWindow') {
if (cachedPosition) {
inputEditor.setPosition(cachedPosition);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,8 @@ import { ChatWidgetHistoryService, IChatWidgetHistoryService } from '../common/w
import { BYOKUtilityModelDefault, ChatAgentLocation, ChatConfiguration, ChatDefaultPermissionLevel, ChatNotificationMode, ChatPermissionLevel } from '../common/constants.js';
import { ILanguageModelIgnoredFilesService, LanguageModelIgnoredFilesService } from '../common/ignoredFiles.js';
import { ILanguageModelsService, LanguageModelsService } from '../common/languageModels.js';
import { ISessionRouter } from '../common/sessionRouter.js';
import { SessionRouterService } from './sessionRouter/sessionRouterService.js';
import { ILanguageModelStatsService, LanguageModelStatsService } from '../common/languageModelStats.js';
import { ILanguageModelToolsConfirmationService } from '../common/tools/languageModelToolsConfirmationService.js';
import { ILanguageModelToolsService } from '../common/tools/languageModelToolsService.js';
Expand Down Expand Up @@ -92,7 +94,7 @@ import './voiceClient/ttsPlaybackService.js';
import './voiceClient/voiceToolDispatchService.js';
import './voiceClient/voiceSessionController.js';
import { registerChatAccessibilityActions } from './actions/chatAccessibilityActions.js';
import { AgentChatAccessibilityHelp, EditsChatAccessibilityHelp, PanelChatAccessibilityHelp, QuickChatAccessibilityHelp } from './actions/chatAccessibilityHelp.js';
import { AgentChatAccessibilityHelp, ChatInputWindowAccessibilityHelp, EditsChatAccessibilityHelp, PanelChatAccessibilityHelp, QuickChatAccessibilityHelp } from './actions/chatAccessibilityHelp.js';
import { ModeOpenChatGlobalAction, registerChatActions } from './actions/chatActions.js';
import { CodeBlockActionRendering, registerChatCodeBlockActions, registerChatCodeCompareBlockActions } from './actions/chatCodeblockActions.js';
import { ChatContextContributions } from './actions/chatContext.js';
Expand Down Expand Up @@ -2738,6 +2740,7 @@ AccessibleViewRegistry.register(new PanelChatAccessibilityHelp());
AccessibleViewRegistry.register(new QuickChatAccessibilityHelp());
AccessibleViewRegistry.register(new EditsChatAccessibilityHelp());
AccessibleViewRegistry.register(new AgentChatAccessibilityHelp());
AccessibleViewRegistry.register(new ChatInputWindowAccessibilityHelp());

registerEditorFeature(ChatInputBoxContentProvider);
Registry.as<IEditorFactoryRegistry>(EditorExtensions.EditorFactory).registerEditorSerializer(ChatEditorInput.TypeID, ChatEditorInputSerializer);
Expand Down Expand Up @@ -2839,6 +2842,7 @@ registerSingleton(IChatAccessibilityService, ChatAccessibilityService, Instantia
registerSingleton(IChatWidgetHistoryService, ChatWidgetHistoryService, InstantiationType.Delayed);
registerSingleton(ILanguageModelsConfigurationService, LanguageModelsConfigurationService, InstantiationType.Delayed);
registerSingleton(ILanguageModelsService, LanguageModelsService, InstantiationType.Delayed);
registerSingleton(ISessionRouter, SessionRouterService, InstantiationType.Delayed);
registerSingleton(ILanguageModelStatsService, LanguageModelStatsService, InstantiationType.Delayed);
registerSingleton(IChatSlashCommandService, ChatSlashCommandService, InstantiationType.Delayed);
registerSingleton(IChatAgentService, ChatAgentService, InstantiationType.Delayed);
Expand Down
7 changes: 6 additions & 1 deletion src/vs/workbench/contrib/chat/browser/chat.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import { ChatRequestQueueKind, IChatElicitationRequest, IChatLocationData, IChat
import { IChatRequestViewModel, IChatResponseViewModel, IChatViewModel, IChatPendingDividerViewModel } from '../common/model/chatViewModel.js';
import { ChatAgentLocation, ChatModeKind } from '../common/constants.js';
import { ChatAttachmentModel } from './attachments/chatAttachmentModel.js';
import { IChatRequestVariableEntry } from '../common/attachments/chatVariableEntries.js';
import { IChatEditorOptions } from './widgetHosts/editor/chatEditor.js';
import { ChatInputPart } from './widget/input/chatInputPart.js';
import { ChatWidget, IChatWidgetContrib } from './widget/chatWidget.js';
Expand Down Expand Up @@ -307,8 +308,12 @@ export interface IChatWidgetViewOptions {
* If it returns true (handled), the normal submission is skipped.
* This is useful for contexts like the welcome view where submission should
* redirect to a different workspace rather than executing locally.
*
* `attachedContext` carries the explicit attachments (paste/drop/pick) present
* on the input so a host that routes the request elsewhere can forward them
* instead of silently dropping them.
*/
submitHandler?: (query: string, mode: ChatModeKind) => Promise<boolean>;
submitHandler?: (query: string, mode: ChatModeKind, attachedContext?: IChatRequestVariableEntry[]) => Promise<boolean>;

/**
* Whether we are running in the sessions window.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/

import * as nls from '../../../../../nls.js';
import { Codicon } from '../../../../../base/common/codicons.js';
import { Action2, MenuId, registerAction2 } from '../../../../../platform/actions/common/actions.js';
import { ServicesAccessor } from '../../../../../platform/instantiation/common/instantiation.js';
import { Categories } from '../../../../../platform/action/common/actionCommonCategories.js';
import { ChatContextKeys } from '../../common/actions/chatContextKeys.js';
import { IChatInputWindowService } from '../../common/chatInputWindow.js';

// Registers the singleton implementation (side-effect import).
import './chatInputWindowService.js';

registerAction2(class extends Action2 {
constructor() {
super({
id: 'workbench.action.chat.toggleInputWindow',
title: nls.localize2('chat.toggleInputWindow', "Toggle Floating Chat Input Window"),
category: Categories.View,
f1: true,
precondition: ChatContextKeys.enabled,
});
}
async run(accessor: ServicesAccessor): Promise<void> {
const chatInputWindowService = accessor.get(IChatInputWindowService);
await chatInputWindowService.toggleWindow();
}
});

registerAction2(class extends Action2 {
constructor() {
super({
id: 'workbench.action.chat.closeInputWindow',
title: nls.localize2('chat.closeInputWindow', "Close Floating Chat Input Window"),
category: Categories.View,
f1: false,
icon: Codicon.close,
menu: {
id: MenuId.ChatInputWindowSide,
group: 'navigation',
order: 10
}
});
}
run(accessor: ServicesAccessor): void {
accessor.get(IChatInputWindowService).closeWindow();
}
});
Loading
Loading