mirror of
https://github.com/Microsoft/vscode
synced 2024-08-27 13:00:58 +00:00
Move rerun request back to prime spot, return with intent detection back as link (#212775)
* Bring back "Rerun Request" to its prominent spot https://github.com/microsoft/vscode-copilot/issues/5604 * move rerun without gesture back into title fixes https://github.com/microsoft/vscode-copilot/issues/5275
This commit is contained in:
parent
5e68ffd760
commit
7680db2a11
|
@ -8,15 +8,14 @@ import { KeyCode, KeyMod } from 'vs/base/common/keyCodes';
|
|||
import { marked } from 'vs/base/common/marked/marked';
|
||||
import { ServicesAccessor } from 'vs/editor/browser/editorExtensions';
|
||||
import { IBulkEditService } from 'vs/editor/browser/services/bulkEditService';
|
||||
import { localize, localize2 } from 'vs/nls';
|
||||
import { Action2, MenuId, MenuRegistry, registerAction2 } from 'vs/platform/actions/common/actions';
|
||||
import { localize2 } from 'vs/nls';
|
||||
import { Action2, MenuId, registerAction2 } from 'vs/platform/actions/common/actions';
|
||||
import { ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey';
|
||||
import { KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry';
|
||||
import { ResourceNotebookCellEdit } from 'vs/workbench/contrib/bulkEdit/browser/bulkCellEdits';
|
||||
import { CHAT_CATEGORY } from 'vs/workbench/contrib/chat/browser/actions/chatActions';
|
||||
import { ChatTreeItem, IChatWidgetService } from 'vs/workbench/contrib/chat/browser/chat';
|
||||
import { ChatAgentLocation } from 'vs/workbench/contrib/chat/common/chatAgents';
|
||||
import { CONTEXT_CHAT_LOCATION, CONTEXT_CHAT_RESPONSE_SUPPORT_ISSUE_REPORTING, CONTEXT_IN_CHAT_INPUT, CONTEXT_IN_CHAT_SESSION, CONTEXT_REQUEST, CONTEXT_RESPONSE, CONTEXT_RESPONSE_DETECTED_AGENT_COMMAND, CONTEXT_RESPONSE_FILTERED, CONTEXT_RESPONSE_VOTE } from 'vs/workbench/contrib/chat/common/chatContextKeys';
|
||||
import { IChatWidgetService } from 'vs/workbench/contrib/chat/browser/chat';
|
||||
import { CONTEXT_CHAT_RESPONSE_SUPPORT_ISSUE_REPORTING, CONTEXT_IN_CHAT_INPUT, CONTEXT_IN_CHAT_SESSION, CONTEXT_REQUEST, CONTEXT_RESPONSE, CONTEXT_RESPONSE_FILTERED, CONTEXT_RESPONSE_VOTE } from 'vs/workbench/contrib/chat/common/chatContextKeys';
|
||||
import { IChatService, ChatAgentVoteDirection } from 'vs/workbench/contrib/chat/common/chatService';
|
||||
import { isRequestVM, isResponseVM } from 'vs/workbench/contrib/chat/common/chatViewModel';
|
||||
import { INotebookEditor } from 'vs/workbench/contrib/notebook/browser/notebookBrowser';
|
||||
|
@ -254,89 +253,6 @@ export function registerChatTitleActions() {
|
|||
}
|
||||
}
|
||||
});
|
||||
|
||||
const rerunMenu = MenuId.for('ChatMessageTitle#Rerun');
|
||||
|
||||
MenuRegistry.appendMenuItem(MenuId.ChatMessageTitle, {
|
||||
submenu: rerunMenu,
|
||||
title: localize('reunmenu', "Rerun..."),
|
||||
icon: Codicon.refresh,
|
||||
group: 'navigation',
|
||||
order: -10,
|
||||
when: ContextKeyExpr.and(CONTEXT_RESPONSE, CONTEXT_CHAT_LOCATION.isEqualTo(ChatAgentLocation.Editor)) // TODO@jrieken needs extension adoption
|
||||
|
||||
});
|
||||
|
||||
registerAction2(class RerunAction extends Action2 {
|
||||
constructor() {
|
||||
super({
|
||||
id: 'workbench.action.chat.rerun',
|
||||
title: localize2('chat.rerun.label', "Rerun Request"),
|
||||
f1: false,
|
||||
category: CHAT_CATEGORY,
|
||||
icon: Codicon.refresh,
|
||||
precondition: CONTEXT_CHAT_LOCATION.isEqualTo(ChatAgentLocation.Editor), // TODO@jrieken needs extension adoption
|
||||
menu: {
|
||||
id: rerunMenu,
|
||||
group: 'navigation',
|
||||
order: -1,
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
async run(accessor: ServicesAccessor, ...args: [ChatTreeItem | unknown]) {
|
||||
const chatWidgetService = accessor.get(IChatWidgetService);
|
||||
const chatService = accessor.get(IChatService);
|
||||
const widget = chatWidgetService.lastFocusedWidget;
|
||||
let item = args[0];
|
||||
if (!isResponseVM(item)) {
|
||||
item = widget?.getFocus();
|
||||
}
|
||||
if (!isResponseVM(item) || !widget) {
|
||||
return;
|
||||
}
|
||||
const request = chatService.getSession(item.sessionId)?.getRequests().find(candidate => candidate.id === item.requestId);
|
||||
if (request) {
|
||||
await chatService.resendRequest(request, { noCommandDetection: false, attempt: request.attempt + 1, location: widget.location });
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
registerAction2(class RerunWithoutCommandDetectionAction extends Action2 {
|
||||
constructor() {
|
||||
super({
|
||||
id: 'workbench.action.chat.rerunWithoutCommandDetection',
|
||||
title: localize2('chat.rerunWithoutCommandDetection.label', "Rerun without Command Detection"),
|
||||
f1: false,
|
||||
category: CHAT_CATEGORY,
|
||||
icon: Codicon.refresh,
|
||||
precondition: CONTEXT_CHAT_LOCATION.isEqualTo(ChatAgentLocation.Editor), // TODO@jrieken needs extension adoption
|
||||
menu: {
|
||||
when: CONTEXT_RESPONSE_DETECTED_AGENT_COMMAND,
|
||||
id: rerunMenu,
|
||||
group: 'navigation',
|
||||
order: -1,
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
async run(accessor: ServicesAccessor, ...args: any[]) {
|
||||
const chatWidgetService = accessor.get(IChatWidgetService);
|
||||
const chatService = accessor.get(IChatService);
|
||||
const widget = chatWidgetService.lastFocusedWidget;
|
||||
let item = args[0];
|
||||
if (!isResponseVM(item)) {
|
||||
item = widget?.getFocus();
|
||||
}
|
||||
if (!isResponseVM(item) || !widget) {
|
||||
return;
|
||||
}
|
||||
const request = chatService.getSession(item.sessionId)?.getRequests().find(candidate => candidate.id === item.requestId);
|
||||
if (request) {
|
||||
await chatService.resendRequest(request, { noCommandDetection: true, attempt: request.attempt, location: widget.location });
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
interface MarkdownContent {
|
||||
|
|
|
@ -78,6 +78,7 @@ import { ITrustedDomainService } from 'vs/workbench/contrib/url/browser/trustedD
|
|||
import { IMarkdownVulnerability, annotateSpecialMarkdownContent } from '../common/annotations';
|
||||
import { CodeBlockModelCollection } from '../common/codeBlockModelCollection';
|
||||
import { IChatListItemRendererOptions } from './chat';
|
||||
import { renderFormattedText } from 'vs/base/browser/formattedTextRenderer';
|
||||
|
||||
const $ = dom.$;
|
||||
|
||||
|
@ -124,6 +125,9 @@ export class ChatListItemRenderer extends Disposable implements ITreeRenderer<Ch
|
|||
protected readonly _onDidClickFollowup = this._register(new Emitter<IChatFollowup>());
|
||||
readonly onDidClickFollowup: Event<IChatFollowup> = this._onDidClickFollowup.event;
|
||||
|
||||
private readonly _onDidClickRerunWithAgentOrCommandDetection = new Emitter<IChatResponseViewModel>();
|
||||
readonly onDidClickRerunWithAgentOrCommandDetection: Event<IChatResponseViewModel> = this._onDidClickRerunWithAgentOrCommandDetection.event;
|
||||
|
||||
protected readonly _onDidChangeItemHeight = this._register(new Emitter<IItemHeightChangeParams>());
|
||||
readonly onDidChangeItemHeight: Event<IItemHeightChangeParams> = this._onDidChangeItemHeight.event;
|
||||
|
||||
|
@ -396,19 +400,31 @@ export class ChatListItemRenderer extends Disposable implements ITreeRenderer<Ch
|
|||
}
|
||||
|
||||
private _renderDetail(element: IChatResponseViewModel, templateData: IChatListItemTemplate): void {
|
||||
let progressMsg: string = '';
|
||||
|
||||
dom.clearNode(templateData.detail);
|
||||
|
||||
if (element.slashCommand && element.agentOrSlashCommandDetected) {
|
||||
let msg: string = '';
|
||||
const usingMsg = `${chatSubcommandLeader}${element.slashCommand.name}`;
|
||||
if (element.isComplete) {
|
||||
progressMsg = localize('usedAgent', "used {0}", usingMsg);
|
||||
msg = localize('usedAgent', "used {0} [[(rerun without)]]", usingMsg);
|
||||
} else {
|
||||
progressMsg = localize('usingAgent', "using {0}", usingMsg);
|
||||
msg = localize('usingAgent', "using {0}", usingMsg);
|
||||
}
|
||||
} else if (!element.isComplete) {
|
||||
progressMsg = GeneratingPhrase;
|
||||
}
|
||||
dom.reset(templateData.detail, renderFormattedText(msg, {
|
||||
className: 'agentOrSlashCommandDetected',
|
||||
inline: true,
|
||||
actionHandler: {
|
||||
disposables: templateData.elementDisposables,
|
||||
callback: (content) => {
|
||||
this._onDidClickRerunWithAgentOrCommandDetection.fire(element);
|
||||
},
|
||||
}
|
||||
}));
|
||||
|
||||
templateData.detail.textContent = progressMsg;
|
||||
} else if (!element.isComplete) {
|
||||
templateData.detail.textContent = GeneratingPhrase;
|
||||
}
|
||||
}
|
||||
|
||||
private renderAvatar(element: ChatTreeItem, templateData: IChatListItemTemplate): void {
|
||||
|
|
|
@ -436,6 +436,12 @@ export class ChatWidget extends Disposable implements IChatWidget {
|
|||
// is this used anymore?
|
||||
this.acceptInput(item.message);
|
||||
}));
|
||||
this._register(this.renderer.onDidClickRerunWithAgentOrCommandDetection(item => {
|
||||
const request = this.chatService.getSession(item.sessionId)?.getRequests().find(candidate => candidate.id === item.requestId);
|
||||
if (request) {
|
||||
this.chatService.resendRequest(request, { noCommandDetection: true, attempt: request.attempt, location: this.location }).catch(e => this.logService.error('FAILED to rerun request', e));
|
||||
}
|
||||
}));
|
||||
|
||||
this.tree = <WorkbenchObjectTree<ChatTreeItem>>scopedInstantiationService.createInstance(
|
||||
WorkbenchObjectTree,
|
||||
|
|
|
@ -53,6 +53,11 @@
|
|||
color: var(--vscode-descriptionForeground);
|
||||
}
|
||||
|
||||
.interactive-item-container .header .detail-container .detail .agentOrSlashCommandDetected A {
|
||||
cursor: pointer;
|
||||
color: var(--vscode-textLink-foreground);
|
||||
}
|
||||
|
||||
.interactive-item-container .chat-animated-ellipsis {
|
||||
display: inline-block;
|
||||
width: 11px;
|
||||
|
|
|
@ -40,6 +40,7 @@ registerAction2(InlineChatActions.DiscardHunkAction);
|
|||
registerAction2(InlineChatActions.DiscardAction);
|
||||
registerAction2(InlineChatActions.DiscardToClipboardAction);
|
||||
registerAction2(InlineChatActions.DiscardUndoToNewFileAction);
|
||||
registerAction2(InlineChatActions.RerunAction);
|
||||
registerAction2(InlineChatActions.CancelSessionAction);
|
||||
registerAction2(InlineChatActions.MoveToNextHunk);
|
||||
registerAction2(InlineChatActions.MoveToPreviousHunk);
|
||||
|
|
|
@ -11,7 +11,7 @@ import { EmbeddedDiffEditorWidget } from 'vs/editor/browser/widget/diffEditor/em
|
|||
import { EmbeddedCodeEditorWidget } from 'vs/editor/browser/widget/codeEditor/embeddedCodeEditorWidget';
|
||||
import { EditorContextKeys } from 'vs/editor/common/editorContextKeys';
|
||||
import { InlineChatController, InlineChatRunOptions } from 'vs/workbench/contrib/inlineChat/browser/inlineChatController';
|
||||
import { CTX_INLINE_CHAT_FOCUSED, CTX_INLINE_CHAT_HAS_PROVIDER, CTX_INLINE_CHAT_INNER_CURSOR_FIRST, CTX_INLINE_CHAT_INNER_CURSOR_LAST, CTX_INLINE_CHAT_OUTER_CURSOR_POSITION, CTX_INLINE_CHAT_VISIBLE, MENU_INLINE_CHAT_WIDGET_DISCARD, MENU_INLINE_CHAT_WIDGET_STATUS, CTX_INLINE_CHAT_EDIT_MODE, EditMode, CTX_INLINE_CHAT_DOCUMENT_CHANGED, CTX_INLINE_CHAT_DID_EDIT, CTX_INLINE_CHAT_HAS_STASHED_SESSION, ACTION_ACCEPT_CHANGES, CTX_INLINE_CHAT_RESPONSE_TYPES, InlineChatResponseTypes, ACTION_VIEW_IN_CHAT, CTX_INLINE_CHAT_USER_DID_EDIT, CTX_INLINE_CHAT_CHANGE_SHOWS_DIFF, CTX_INLINE_CHAT_CHANGE_HAS_DIFF, MENU_INLINE_CHAT_WIDGET, ACTION_TOGGLE_DIFF } from 'vs/workbench/contrib/inlineChat/common/inlineChat';
|
||||
import { CTX_INLINE_CHAT_FOCUSED, CTX_INLINE_CHAT_HAS_PROVIDER, CTX_INLINE_CHAT_INNER_CURSOR_FIRST, CTX_INLINE_CHAT_INNER_CURSOR_LAST, CTX_INLINE_CHAT_OUTER_CURSOR_POSITION, CTX_INLINE_CHAT_VISIBLE, MENU_INLINE_CHAT_WIDGET_DISCARD, MENU_INLINE_CHAT_WIDGET_STATUS, CTX_INLINE_CHAT_EDIT_MODE, EditMode, CTX_INLINE_CHAT_DOCUMENT_CHANGED, CTX_INLINE_CHAT_DID_EDIT, CTX_INLINE_CHAT_HAS_STASHED_SESSION, ACTION_ACCEPT_CHANGES, CTX_INLINE_CHAT_RESPONSE_TYPES, InlineChatResponseTypes, ACTION_VIEW_IN_CHAT, CTX_INLINE_CHAT_USER_DID_EDIT, CTX_INLINE_CHAT_CHANGE_SHOWS_DIFF, CTX_INLINE_CHAT_CHANGE_HAS_DIFF, MENU_INLINE_CHAT_WIDGET, ACTION_TOGGLE_DIFF, ACTION_REGENERATE_RESPONSE } from 'vs/workbench/contrib/inlineChat/common/inlineChat';
|
||||
import { localize, localize2 } from 'vs/nls';
|
||||
import { Action2, IAction2Options, MenuRegistry } from 'vs/platform/actions/common/actions';
|
||||
import { IClipboardService } from 'vs/platform/clipboard/common/clipboardService';
|
||||
|
@ -29,6 +29,7 @@ import { CommandsRegistry } from 'vs/platform/commands/common/commands';
|
|||
import { registerIcon } from 'vs/platform/theme/common/iconRegistry';
|
||||
import { IPreferencesService } from 'vs/workbench/services/preferences/common/preferences';
|
||||
import { ILogService } from 'vs/platform/log/common/log';
|
||||
import { IChatService } from 'vs/workbench/contrib/chat/common/chatService';
|
||||
|
||||
CommandsRegistry.registerCommandAlias('interactiveEditor.start', 'inlineChat.start');
|
||||
CommandsRegistry.registerCommandAlias('interactive.acceptChanges', ACTION_ACCEPT_CHANGES);
|
||||
|
@ -356,7 +357,8 @@ export class ToggleDiffForChange extends AbstractInlineChatAction {
|
|||
{
|
||||
id: MENU_INLINE_CHAT_WIDGET_STATUS,
|
||||
group: '1_main',
|
||||
when: ContextKeyExpr.and(CTX_INLINE_CHAT_EDIT_MODE.isEqualTo(EditMode.Live), CTX_INLINE_CHAT_CHANGE_HAS_DIFF)
|
||||
when: ContextKeyExpr.and(CTX_INLINE_CHAT_EDIT_MODE.isEqualTo(EditMode.Live), CTX_INLINE_CHAT_CHANGE_HAS_DIFF),
|
||||
order: 10,
|
||||
}
|
||||
]
|
||||
});
|
||||
|
@ -564,3 +566,28 @@ export class ViewInChatAction extends AbstractInlineChatAction {
|
|||
}
|
||||
}
|
||||
|
||||
export class RerunAction extends AbstractInlineChatAction {
|
||||
constructor() {
|
||||
super({
|
||||
id: ACTION_REGENERATE_RESPONSE,
|
||||
title: localize2('chat.rerun.label', "Rerun Request"),
|
||||
f1: false,
|
||||
icon: Codicon.refresh,
|
||||
menu: {
|
||||
id: MENU_INLINE_CHAT_WIDGET_STATUS,
|
||||
group: '0_main',
|
||||
order: 5,
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
override async runInlineChatCommand(accessor: ServicesAccessor, ctrl: InlineChatController, _editor: ICodeEditor, ..._args: any[]): Promise<void> {
|
||||
const chatService = accessor.get(IChatService);
|
||||
const model = ctrl.chatWidget.viewModel?.model;
|
||||
|
||||
const lastRequest = model?.getRequests().at(-1);
|
||||
if (lastRequest) {
|
||||
await chatService.resendRequest(lastRequest, { noCommandDetection: false, attempt: lastRequest.attempt + 1, location: ctrl.chatWidget.location });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue