8000 add additional entry point to edits by justschen · Pull Request #252380 · microsoft/vscode · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

add additional entry point to edits #252380

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

Draft
wants to merge 3 commits into
base: main
Choose a base branch
from
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
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import { ActiveEditorContext } from '../../../../common/contextkeys.js';
import { ChatContextKeys } from '../../common/chatContextKeys.js';
import { IChatEditingSession } from '../../common/chatEditingService.js';
import { ChatMode } from '../../common/constants.js';
import { ChatViewId, IChatWidget } from '../chat.js';
import { ChatViewId, IChatWidget, IChatWidgetService } from '../chat.js';
import { EditingSessionAction } from '../chatEditing/chatEditingActions.js';
import { ChatEditorInput } from '../chatEditorInput.js';
import { ACTION_ID_NEW_CHAT, ACTION_ID_NEW_EDIT_SESSION, CHAT_CATEGORY, handleCurrentEditingS 10000 ession } from './chatActions.js';
Expand Down Expand Up @@ -60,6 +60,14 @@ export function registerNewChatActions() {
}
async run(accessor: ServicesAccessor, ...args: any[]) {
announceChatCleared(accessor.get(IAccessibilitySignalService));
const widgetService = accessor.get(IChatWidgetService);
const widget = widgetService.lastFocusedWidget;
if (!widget) {
return;
}
if (widget.viewModel?.editing) {
widget.handleDispose();
}
await clearChatEditor(accessor);
}
});
Expand Down Expand Up @@ -107,6 +115,9 @@ export function registerNewChatActions() {
}

announceChatCleared(accessibilitySignalService);
if (widget.viewModel?.editing) {
widget.handleDispose();
}

await editingSession.stop();
widget.clear();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,9 @@ abstract class SubmitAction extends Action2 {
// Restore the snapshot to what it was before the request(s) that we deleted
const snapshotRequestId = chatRequests[itemIndex].id;
await session.restoreSnapshot(snapshotRequestId, undefined);
if (configurationService.getValue<string>('chat.editRequests') === 'input') {
widget?.handleDispose();
}
}
}
widget?.acceptInput(context?.inputValue);
Expand Down Expand Up @@ -228,8 +231,8 @@ class ToggleChatModeAction extends Action2 {
context.chatWidget.input.setChatMode2(switchToMode);

if (chatModeCheck.needToClearSession) {
if (context.chatWidget.viewModel?.editing) {
context.chatWidget.input.dispose();
if (context.chatWidget.viewModel?.editing && configurationService.getValue<string>(ChatConfiguration.EditRequests) !== 'input') {
context.chatWidget.handleDispose();
}
await commandService.executeCommand(ACTION_ID_NEW_CHAT);
}
Expand Down Expand Up @@ -709,12 +712,22 @@ export class CancelEdit extends Action2 {
title: localize2('interactive.cancelEdit.label', "Cancel Edit"),
f1: false,
category: CHAT_CATEGORY,
icon: Codicon.x,
menu: [
{
id: MenuId.ChatMessageTitle,
group: 'navigation',
order: 1,
when: ContextKeyExpr.and(ChatContextKeys.isRequest, ChatContextKeys.currentlyEditing, ContextKeyExpr.equals(`config.${ChatConfiguration.EditRequests}`, 'input'))
}
],
keybinding: {
primary: KeyCode.Escape,
when: ContextKeyExpr.and(ChatContextKeys.inChatInput,
EditorContextKeys.hoverVisible.toNegated(),
EditorContextKeys.hasNonEmptySelection.toNegated(),
EditorContextKeys.hasMultipleSelections.toNegated()),
EditorContextKeys.hasMultipleSelections.toNegated(),
ContextKeyExpr.or(ChatContextKeys.currentlyEditing, ChatContextKeys.currentlyEditingInput)),
weight: KeybindingWeight.EditorContrib - 5
}
});
Expand All @@ -728,7 +741,7 @@ export class CancelEdit extends Action2 {
if (!widget) {
return;
}
widget.input.dispose();
widget.handleDispose();
}
}

Expand Down
7 changes: 4 additions & 3 deletions src/vs/workbench/contrib/chat/browser/chat.contribution.ts
8000
Original file line number Diff line number Diff line change
Expand Up @@ -246,10 +246,11 @@ configurationRegistry.registerConfiguration({
tags: ['experimental']
},
'chat.editRequests': {
default: true,
markdownDescription: nls.localize('chat.editRequests', "Enables editing of requests in the chat. This allows you to change the request content and resubmit it to the model."),
type: 'boolean',
tags: ['experimental']
type: 'string',
enum: ['inline', 'hover', 'input', 'none'],
default: 'inline',
tags: ['experimental'],
},
[mcpEnabledSection]: {
type: 'boolean',
Expand Down
2 changes: 2 additions & 0 deletions src/vs/workbench/contrib/chat/browser/chat.ts
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,8 @@ export interface IChatWidget {
refreshParsedInput(): void;
logInputHistory(): void;
acceptInput(query?: string, options?: IChatAcceptInputOptions): Promise<IChatResponseModel | undefined>;
startEditing(requestId: string): void;
handleDispose(): void;
rerunLastRequest(): Promise<void>;
setInputPlaceholder(placeholder: string): void;
resetInputPlaceholder(): void;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ import { ChatContextKeys } from '../../common/chatContextKeys.js';
import { applyingChatEditsFailedContextKey, CHAT_EDITING_MULTI_DIFF_SOURCE_RESOLVER_SCHEME, chatEditingResourceContextKey, chatEditingWidgetFileStateContextKey, decidedChatEditingResourceContextKey, hasAppliedChatEditsContextKey, hasUndecidedChatEditingResourceContextKey, IChatEditingService, IChatEditingSession, ModifiedFileEntryState } from '../../common/chatEditingService.js';
import { IChatService } from '../../common/chatService.js';
import { isRequestVM, isResponseVM } from '../../common/chatViewModel.js';
import { ChatAgentLocation, ChatMode } from '../../common/constants.js';
import { ChatAgentLocation, ChatConfiguration, ChatMode } from '../../common/constants.js';
import { CHAT_CATEGORY } from '../actions/chatActions.js';
import { ChatTreeItem, IChatWidget, IChatWidgetService } from '../chat.js';

Expand Down Expand Up @@ -326,20 +326,25 @@ registerAction2(class RemoveAction extends Action2 {
id: MenuId.ChatMessageTitle,
group: 'navigation',
order: 2,
when: ChatContextKeys.isRequest
when: ContextKeyExpr.and(ChatContextKeys.isRequest, ChatContextKeys.currentlyEditing.negate(), ContextKeyExpr.equals(`config.${ChatConfiguration.EditRequests}`, 'input').negate())
}
]
});
}

async run(accessor: ServicesAccessor, ...args: any[]) {
let item: ChatTreeItem | undefined = args[0];
if (!item) {
return;
}

const chatWidgetService = accessor.get(IChatWidgetService);
const widget = chatWidgetService.lastFocusedWidget;
if (!isResponseVM(item) && !isRequestVM(item)) {
item = widget?.getFocus();
}


if (!item) {
return;
}
Expand Down Expand Up @@ -417,6 +422,42 @@ registerAction2(class RemoveAction extends Action2 {
}
});

registerAction2(class EditAction extends Action2 {
constructor() {
super({
id: 'workbench.action.chat.editRequests',
title: localize2('chat.editRequests.label', "Edit Request"),
f1: false,
category: CHAT_CATEGORY,
icon: Codicon.edit,
menu: [
{
id: MenuId.ChatMessageTitle,
group: 'navigation',
order: 2,
when: ContextKeyExpr.and(ChatContextKeys.isRequest, ChatContextKeys.currentlyEditing.negate(), ContextKeyExpr.or(ContextKeyExpr.equals(`config.${ChatConfiguration.EditRequests}`, 'hover'), ContextKeyExpr.equals(`config.${ChatConfiguration.EditRequests}`, 'input')))
}
]
});
}

async run(accessor: ServicesAccessor, ...args: any[]) {
let item: ChatTreeItem | undefined = args[0];
if (!item) {
return;
}
const chatWidgetService = accessor.get(IChatWidgetService);
const widget = chatWidgetService.lastFocusedWidget;
if (!isResponseVM(item) && !isRequestVM(item)) {
item = widget?.getFocus();
}

if (isRequestVM(item)) {
widget?.startEditing(item.id);
}
}
});

registerAction2(class OpenWorkingSetHistoryAction extends Action2 {

static readonly id = 'chat.openFileUpdatedBySnapshot';
Expand Down
9 changes: 0 additions & 9 deletions src/vs/workbench/contrib/chat/browser/chatInputPart.ts
Original file line number Diff line number Diff line change
Expand Up @@ -150,9 +150,6 @@ export class ChatInputPart extends Disposable implements IHistoryNavigationWidge
private _onDidBlur: Emitter<void>;
readonly onDidBlur: Event<void>;

private _onDidDispose: Emitter<void>;
readonly onDidDispose: Event<void>;

private _onDidChangeContext: Emitter<{ removed?: IChatRequestVariableEntry[]; added?: IChatRequestVariableEntry[] }>;
readonly onDidChangeContext: Event<{ removed?: IChatRequestVariableEntry[]; added?: IChatRequestVariableEntry[] }>;

Expand Down Expand Up @@ -375,8 +372,6 @@ export class ChatInputPart extends Disposable implements IHistoryNavigationWidge
this.>
this._onDidBlur = this._register(new Emitter<void>());
this.>
this._onDidDispose = this._register(new Emitter<void>());
this.>
this._onDidChangeContext = this._register(new Emitter<{ removed?: IChatRequestVariableEntry[]; added?: IChatRequestVariableEntry[] }>());
this.>
this._onDidAcceptFollowup = this._register(new Emitter<{ followup: IChatFollowup; response: IChatResponseViewModel | undefined }>());
Expand Down Expand Up @@ -452,10 +447,6 @@ export class ChatInputPart extends Disposable implements IHistoryNavigationWidge
}));
this._register(this.chatModeService.onDidChangeChatModes(() => this.validateCurrentChatMode()));
}
public override dispose(): void {
this._onDidDispose.fire();
super.dispose();
}

private getSelectedModelStorageKey(): string {
return `chat.currentLanguageModel.${this.location}`;
Expand Down
36 changes: 32 additions & 4 deletions src/vs/workbench/contrib/chat/browser/chatListRenderer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,8 @@ export class ChatListItemRenderer extends Disposable implements ITreeRenderer<Ch
private readonly fileTreesByResponseId = new Map<string, IChatFileTreeInfo[]>();
private readonly focusedFileTreesByResponseId = new Map<string, number>();

private readonly templateDataByRequestId = new Map<string, IChatListItemTemplate>();

private readonly renderer: MarkdownRenderer;
private readonly markdownDecorationsRenderer: ChatMarkdownDecorationsRenderer;

Expand Down Expand Up @@ -281,6 +283,17 @@ export class ChatListItemRenderer extends Disposable implements ITreeRenderer<Ch
return undefined;
}

getTemplateDataForRequestId(requestId: string): IChatListItemTemplate | undefined {
const templateData = this.templateDataByRequestId.get(requestId);
if (templateData && templateData.currentElement?.id === requestId) {
return templateData;
}
if (templateData) {
this.templateDataByRequestId.delete(requestId);
}
return undefined;
}

setVisible(visible: boolean): void {
this._isVisible = visible;
this._onDidChangeVisibility.fire(visible);
Expand Down Expand Up @@ -335,6 +348,8 @@ export class ChatListItemRenderer extends Disposable implements ITreeRenderer<Ch
const scopedInstantiationService = templateDisposables.add(this.instantiationService.createChild(new ServiceCollection([IContextKeyService, contextKeyService])));

const requestHover = dom.append(rowContainer, $('.request-hover'));
requestHover.classList.toggle('expanded', this.configService.getValue<string>('chat.editRequests') === 'hover');

let titleToolbar: MenuWorkbenchToolBar | undefined;
if (this.rendererOptions.noHeader) {
header.classList.add('hidden');
Expand Down Expand Up @@ -414,9 +429,11 @@ export class ChatListItemRenderer extends Disposable implements ITreeRenderer<Ch
if (templateData.currentElement && templateData.currentElement.id !== element.id) {
this.traceLayout('renderChatTreeItem', `Rendering a different element into the template, index=${index}`);
this.clearRenderedParts(templateData);
this.templateDataByRequestId.delete(templateData.currentElement.id);
}

templateData.currentElement = element;
this.templateDataByRequestId.set(element.id, templateData);
const kind = isRequestVM(element) ? 'request' :
isResponseVM(element) ? 'response' :
'welcome';
Expand All @@ -438,6 +455,8 @@ export class ChatListItemRenderer extends Disposable implements ITreeRenderer<Ch
}
templateData.footerToolbar.context = element;

templateData.requestHover.classList.toggle('hidden', !!this.viewModel?.editing && element.id !== this.viewModel?.editing?.id);

ChatContextKeys.responseHasError.bindTo(templateData.contextKeyService).set(isResponseVM(element) && !!element.errorDetails);
const isFiltered = !!(isResponseVM(element) && element.errorDetails?.responseIsFiltered);
ChatContextKeys.responseIsFiltered.bindTo(templateData.contextKeyService).set(isFiltered);
Expand All @@ -462,8 +481,13 @@ export class ChatListItemRenderer extends Disposable implements ITreeRenderer<Ch
this.renderDetail(element, templateData);
}

templateData.disabledOverlay.classList.toggle('disabled', element.shouldBeBlocked);
templateData.rowContainer.classList.toggle('editing', element.id === this.viewModel?.editing?.id);
const editing = element.id === this.viewModel?.editing?.id;
const isInput = this.configService.getValue<string>('chat.editRequests') === 'input';

templateData.disabledOverlay.classList.toggle('disabled', element.shouldBeBlocked && !editing);
templateData.rowContainer.classList.toggle('editing', editing && !isInput);
templateData.rowContainer.classList.toggle('editing-input', editing && isInput);
templateData.requestHover.classList.toggle('editing', editing && isInput);
templateData.elementDisposables.add(dom.addDisposableListener(templateData.rowContainer, dom.EventType.CLICK, () => {
if (this.viewModel?.editing && element.id !== this.viewModel.editing.id) {
this._onDidFocusOutside.fire();
Expand Down Expand Up @@ -604,7 +628,7 @@ export class ChatListItemRenderer extends Disposable implements ITreeRenderer<Ch
this._onDidRerender.fire(templateData);
}

if (this.configService.getValue<boolean>('chat.editRequests') && !this.disableEdits) {
if (this.configService.getValue<string>('chat.editRequests') === 'inline' && !this.disableEdits) {
templateData.elementDisposables.add(dom.addDisposableListener(templateData.rowContainer, dom.EventType.KEY_DOWN, e => {
const ev = new StandardKeyboardEvent(e);
if (ev.equals(KeyCode.Space) || ev.equals(KeyCode.Enter)) {
Expand Down Expand Up @@ -1194,7 +1218,7 @@ export class ChatListItemRenderer extends Disposable implements ITreeRenderer<Ch
const markdownPart = templateData.instantiationService.createInstance(ChatMarkdownContentPart, markdown, context, this._editorPool, fillInIncompleteTokens, codeBlockStartIndex, this.renderer, this._currentLayoutWidth, this.codeBlockModelCollection, {});
if (isRequestVM(element)) {
markdownPart.domNode.tabIndex = 0;
if (this.configService.getValue<boolean>('chat.editRequests') && !this.disableEdits) {
if (this.configService.getValue<string>('chat.editRequests') === 'inline' && !this.disableEdits) {
markdownPart.domNode.classList.add('clickable');
markdownPart.addDisposable(dom.addDisposableListener(markdownPart.domNode, dom.EventType.CLICK, (e: MouseEvent) => {
if (this.viewModel?.editing?.id !== element.id && !this.viewModel?.requestInProgress) {
Expand Down Expand Up @@ -1225,6 +1249,10 @@ export class ChatListItemRenderer extends Disposable implements ITreeRenderer<Ch
this.traceLayout('disposeElement', `Disposing element, index=${index}`);
templateData.elementDisposables.clear();

if (templateData.currentElement) {
this.templateDataByRequestId.delete(templateData.currentElement.id);
}

if (isRequestVM(node.element) && node.element.id === this.viewModel?.editing?.id && details?.onScroll) {
this._onDidDispose.fire(templateData);
}
Expand Down
Loading
Loading
0