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

Improving the accessibility of interactive editor #180427

Merged
merged 23 commits into from Apr 24, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
876f79c
applying the css style on the whole .label.message, not on the children
aiday-mar Apr 20, 2023
0be3a24
Making the interactive editor accessible
aiday-mar Apr 20, 2023
db06368
focus the last message when there is a widget which can be viewed
aiday-mar Apr 20, 2023
0efe1e6
removing the question mark
aiday-mar Apr 20, 2023
5749ccb
focus the last message only after the addCompleteRequest has finished
aiday-mar Apr 20, 2023
3b9dea8
adding an action for going to the inline chat when the view in chat b…
aiday-mar Apr 20, 2023
d9da1b6
removing console logs
aiday-mar Apr 20, 2023
a18e1ac
changed the weight to workbench contrib
aiday-mar Apr 21, 2023
8a7df61
Merge branch 'main' into aiday/improvingInteractiveEditor
aiday-mar Apr 21, 2023
d912be6
changing the code so that view in chat is an additional button in the…
aiday-mar Apr 21, 2023
3ad6291
adding the context key while waiting for the merge
aiday-mar Apr 21, 2023
43ca3ee
changing the css
aiday-mar Apr 21, 2023
a7e2047
Merge branch 'main' into aiday/improvingInteractiveEditor
aiday-mar Apr 21, 2023
337ae07
cleaning the code
aiday-mar Apr 21, 2023
b87ccca
cleaning the code
aiday-mar Apr 21, 2023
05244e2
work in propgress, adding the fix for the feedback bug also
aiday-mar Apr 24, 2023
1334160
cleaning the code
aiday-mar Apr 24, 2023
db73884
using the toggle functionality instead
aiday-mar Apr 24, 2023
7a4984d
pre saving the old data
aiday-mar Apr 24, 2023
21c7b95
polishing the code
aiday-mar Apr 24, 2023
193bec8
remove true
aiday-mar Apr 24, 2023
df75e71
add some padding to MD message, restore right alignment of status label
jrieken Apr 24, 2023
638b02a
show accept/discard btns even when last response was a message response
jrieken Apr 24, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Expand Up @@ -24,6 +24,7 @@ registerAction2(interactiveEditorActions.ArrowOutDownAction);
registerAction2(interactiveEditorActions.FocusInteractiveEditor);
registerAction2(interactiveEditorActions.PreviousFromHistory);
registerAction2(interactiveEditorActions.NextFromHistory);
registerAction2(interactiveEditorActions.ViewInChatAction);

registerAction2(interactiveEditorActions.UndoToClipboard);
registerAction2(interactiveEditorActions.UndoToNewFile);
Expand Down
Expand Up @@ -100,36 +100,34 @@
display: none;
}

.monaco-editor .interactive-editor .status .link {
color: var(--vscode-textLink-foreground);
cursor: pointer;
font-size: 12px;
white-space: nowrap;
/* margin-top: auto; */
}

.monaco-editor .interactive-editor .status .label {
overflow: hidden;
font-size: 12px;
padding-left: 10px;
margin-left: auto;
}

.monaco-editor .interactive-editor .status .label.message>span>p {
margin: 0px;
.monaco-editor .interactive-editor .markdownMessage {
padding-top: 10px;
}

.monaco-editor .interactive-editor .markdownMessage.hidden {
display: none;
}

.monaco-editor .interactive-editor .markdownMessage .message * {
margin: unset;
}

.monaco-editor .interactive-editor .markdownMessage .message {
margin-left: 5px;
-webkit-line-clamp: 3;
-webkit-box-orient: vertical;
overflow: hidden;
display: -webkit-box;
}

.monaco-editor .interactive-editor .status .link .status-link {
padding-left: 10px;
}

.monaco-editor .interactive-editor .status .link .status-link .codicon {
line-height: unset;
font-size: 12px;
padding-right: 4px;
.monaco-editor .interactive-editor .markdownMessage .messageActions {
direction: rtl;
}

.monaco-editor .interactive-editor .status .label A {
Expand Down
Expand Up @@ -10,7 +10,7 @@ import { EditorAction2 } from 'vs/editor/browser/editorExtensions';
import { EmbeddedCodeEditorWidget, EmbeddedDiffEditorWidget } from 'vs/editor/browser/widget/embeddedCodeEditorWidget';
import { EditorContextKeys } from 'vs/editor/common/editorContextKeys';
import { InteractiveEditorController, InteractiveEditorRunOptions, Recording } from 'vs/workbench/contrib/interactiveEditor/browser/interactiveEditorController';
import { CTX_INTERACTIVE_EDITOR_FOCUSED, CTX_INTERACTIVE_EDITOR_HAS_ACTIVE_REQUEST, CTX_INTERACTIVE_EDITOR_HAS_PROVIDER, CTX_INTERACTIVE_EDITOR_INNER_CURSOR_FIRST, CTX_INTERACTIVE_EDITOR_INNER_CURSOR_LAST, CTX_INTERACTIVE_EDITOR_EMPTY, CTX_INTERACTIVE_EDITOR_OUTER_CURSOR_POSITION, CTX_INTERACTIVE_EDITOR_VISIBLE, MENU_INTERACTIVE_EDITOR_WIDGET, CTX_INTERACTIVE_EDITOR_LAST_EDIT_TYPE, MENU_INTERACTIVE_EDITOR_WIDGET_UNDO, MENU_INTERACTIVE_EDITOR_WIDGET_STATUS, CTX_INTERACTIVE_EDITOR_LAST_FEEDBACK, CTX_INTERACTIVE_EDITOR_INLNE_DIFF, CTX_INTERACTIVE_EDITOR_EDIT_MODE, EditMode, CTX_INTERACTIVE_EDITOR_LAST_RESPONSE_TYPE } from 'vs/workbench/contrib/interactiveEditor/common/interactiveEditor';
import { CTX_INTERACTIVE_EDITOR_FOCUSED, CTX_INTERACTIVE_EDITOR_HAS_ACTIVE_REQUEST, CTX_INTERACTIVE_EDITOR_HAS_PROVIDER, CTX_INTERACTIVE_EDITOR_INNER_CURSOR_FIRST, CTX_INTERACTIVE_EDITOR_INNER_CURSOR_LAST, CTX_INTERACTIVE_EDITOR_EMPTY, CTX_INTERACTIVE_EDITOR_OUTER_CURSOR_POSITION, CTX_INTERACTIVE_EDITOR_VISIBLE, MENU_INTERACTIVE_EDITOR_WIDGET, CTX_INTERACTIVE_EDITOR_LAST_EDIT_TYPE, MENU_INTERACTIVE_EDITOR_WIDGET_UNDO, MENU_INTERACTIVE_EDITOR_WIDGET_STATUS, CTX_INTERACTIVE_EDITOR_LAST_FEEDBACK, CTX_INTERACTIVE_EDITOR_INLNE_DIFF, CTX_INTERACTIVE_EDITOR_EDIT_MODE, EditMode, CTX_INTERACTIVE_EDITOR_LAST_RESPONSE_TYPE, MENU_INTERACTIVE_EDITOR_WIDGET_MARKDOWN_MESSAGE } from 'vs/workbench/contrib/interactiveEditor/common/interactiveEditor';
import { localize } from 'vs/nls';
import { IAction2Options } from 'vs/platform/actions/common/actions';
import { IClipboardService } from 'vs/platform/clipboard/common/clipboardService';
Expand Down Expand Up @@ -413,7 +413,6 @@ export class ApplyPreviewEdits extends AbstractInteractiveEditorAction {
},
menu: {
id: MENU_INTERACTIVE_EDITOR_WIDGET_STATUS,
when: CTX_INTERACTIVE_EDITOR_LAST_RESPONSE_TYPE.notEqualsTo('message'),
group: '0_main',
order: 0
}
Expand Down Expand Up @@ -449,7 +448,6 @@ export class CancelSessionAction extends AbstractInteractiveEditorAction {
},
menu: {
id: MENU_INTERACTIVE_EDITOR_WIDGET_STATUS,
when: CTX_INTERACTIVE_EDITOR_LAST_RESPONSE_TYPE.notEqualsTo('message'),
group: '0_main',
order: 1
}
Expand Down Expand Up @@ -501,3 +499,23 @@ export class CopyRecordings extends AbstractInteractiveEditorAction {
}
}
}

export class ViewInChatAction extends AbstractInteractiveEditorAction {
constructor() {
super({
id: 'interactiveEditor.viewInChat',
title: localize('viewInChat', 'View in Chat'),
icon: Codicon.commentDiscussion,
precondition: CTX_INTERACTIVE_EDITOR_VISIBLE,
menu: {
id: MENU_INTERACTIVE_EDITOR_WIDGET_MARKDOWN_MESSAGE,
when: CTX_INTERACTIVE_EDITOR_LAST_RESPONSE_TYPE.isEqualTo('message'),
group: 'viewInChat',
order: 1
}
});
}
override runInteractiveEditorCommand(_accessor: ServicesAccessor, ctrl: InteractiveEditorController, _editor: ICodeEditor, ..._args: any[]): void {
ctrl.viewInChat();
}
}
Expand Up @@ -40,7 +40,7 @@ import { IStorageService, StorageScope, StorageTarget } from 'vs/platform/storag
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import { InteractiveEditorDiffWidget } from 'vs/workbench/contrib/interactiveEditor/browser/interactiveEditorDiffWidget';
import { InteractiveEditorZoneWidget } from 'vs/workbench/contrib/interactiveEditor/browser/interactiveEditorWidget';
import { CTX_INTERACTIVE_EDITOR_HAS_ACTIVE_REQUEST, CTX_INTERACTIVE_EDITOR_INLNE_DIFF, CTX_INTERACTIVE_EDITOR_LAST_EDIT_TYPE as CTX_INTERACTIVE_EDITOR_LAST_EDIT_KIND, CTX_INTERACTIVE_EDITOR_LAST_FEEDBACK as CTX_INTERACTIVE_EDITOR_LAST_FEEDBACK_KIND, IInteractiveEditorBulkEditResponse, IInteractiveEditorEditResponse, IInteractiveEditorRequest, IInteractiveEditorResponse, IInteractiveEditorService, IInteractiveEditorSession, IInteractiveEditorSessionProvider, IInteractiveEditorSlashCommand, INTERACTIVE_EDITOR_ID, EditMode, InteractiveEditorResponseFeedbackKind, CTX_INTERACTIVE_EDITOR_LAST_RESPONSE_TYPE, InteractiveEditorResponseType } from 'vs/workbench/contrib/interactiveEditor/common/interactiveEditor';
import { CTX_INTERACTIVE_EDITOR_HAS_ACTIVE_REQUEST, CTX_INTERACTIVE_EDITOR_INLNE_DIFF, CTX_INTERACTIVE_EDITOR_LAST_EDIT_TYPE as CTX_INTERACTIVE_EDITOR_LAST_EDIT_KIND, CTX_INTERACTIVE_EDITOR_LAST_FEEDBACK as CTX_INTERACTIVE_EDITOR_LAST_FEEDBACK_KIND, IInteractiveEditorBulkEditResponse, IInteractiveEditorEditResponse, IInteractiveEditorRequest, IInteractiveEditorResponse, IInteractiveEditorService, IInteractiveEditorSession, IInteractiveEditorSessionProvider, IInteractiveEditorSlashCommand, INTERACTIVE_EDITOR_ID, EditMode, InteractiveEditorResponseFeedbackKind, CTX_INTERACTIVE_EDITOR_LAST_RESPONSE_TYPE, InteractiveEditorResponseType, IInteractiveEditorMessageResponse } from 'vs/workbench/contrib/interactiveEditor/common/interactiveEditor';
import { IInteractiveSessionWidgetService } from 'vs/workbench/contrib/interactiveSession/browser/interactiveSessionWidget';
import { IInteractiveSessionService } from 'vs/workbench/contrib/interactiveSession/common/interactiveSessionService';
import { INotebookEditorService } from 'vs/workbench/contrib/notebook/browser/services/notebookEditorService';
Expand Down Expand Up @@ -216,7 +216,7 @@ export class EditResponse {

class Session {

private readonly _responses: EditResponse[] = [];
private readonly _responses: (EditResponse | IInteractiveEditorMessageResponse)[] = [];

readonly teldata: TelemetryData;

Expand All @@ -239,12 +239,12 @@ class Session {
};
}

addResponse(response: EditResponse): void {
addResponse(response: EditResponse | IInteractiveEditorMessageResponse): void {
const newLen = this._responses.push(response);
this.teldata.rounds += `${newLen}|`;
}

get lastResponse(): EditResponse | undefined {
get lastResponse(): EditResponse | IInteractiveEditorMessageResponse | undefined {
return this._responses[this._responses.length - 1];
}
}
Expand Down Expand Up @@ -296,6 +296,9 @@ export class InteractiveEditorController implements IEditorContribution {
private _ctsSession: CancellationTokenSource = new CancellationTokenSource();
private _ctsRequest?: CancellationTokenSource;

private _requestPrompt: string | undefined;
private _messageReply: string | undefined;

constructor(
private readonly _editor: ICodeEditor,
@IInstantiationService private readonly _instaService: IInstantiationService,
Expand Down Expand Up @@ -332,6 +335,12 @@ export class InteractiveEditorController implements IEditorContribution {
return this._configurationService.getValue('interactiveEditor.editMode');
}

viewInChat() {
if (this._messageReply && this._requestPrompt) {
this._instaService.invokeFunction(showMessageResponse, this._requestPrompt, this._messageReply);
}
}

async run(options: InteractiveEditorRunOptions | undefined): Promise<void> {

const editMode = this._getMode();
Expand Down Expand Up @@ -399,7 +408,7 @@ export class InteractiveEditorController implements IEditorContribution {
store.add(this._instaService.invokeFunction(installSlashCommandSupport, this._zone.widget.inputEditor as IActiveCodeEditor, session.slashCommands));
}

this._zone.widget.updateMessage(session.message ?? localize('welcome.1', "AI-generated code may be incorrect."));
this._zone.widget.updateStatus(session.message ?? localize('welcome.1', "AI-generated code may be incorrect."));

// CANCEL when input changes
this._editor.onDidChangeModel(this.cancelSession, this, store);
Expand Down Expand Up @@ -531,7 +540,7 @@ export class InteractiveEditorController implements IEditorContribution {
if (!isCancellationError(e)) {
this._logService.error('[IE] ERROR during request', provider.debugName);
this._logService.error(e);
this._zone.widget.updateMessage(toErrorMessage(e), { classes: ['error'] });
this._zone.widget.updateStatus(toErrorMessage(e), { classes: ['error'] });
// statusWidget
continue;
}
Expand All @@ -549,7 +558,7 @@ export class InteractiveEditorController implements IEditorContribution {

if (!reply) {
this._logService.trace('[IE] NO reply or edits', provider.debugName);
this._zone.widget.updateMessage(localize('empty', "No results, please refine your input and try again."), { classes: ['warn'] });
this._zone.widget.updateStatus(localize('empty', "No results, please refine your input and try again."), { classes: ['warn'] });
continue;
}

Expand All @@ -559,9 +568,11 @@ export class InteractiveEditorController implements IEditorContribution {

if (reply.type === 'message') {
this._logService.info('[IE] received a MESSAGE, continuing outside editor', provider.debugName);
const messageReply = reply.message;
const renderedMarkdown = renderMarkdown(messageReply, { inline: true });
this._zone.widget.updateMessage(renderedMarkdown.element, { linkListener: () => this._instaService.invokeFunction(showMessageResponse, request.prompt, messageReply.value), isMessageReply: true });
this._messageReply = reply.message.value;
this._requestPrompt = request.prompt;
const renderedMarkdown = renderMarkdown(reply.message, { inline: true });
this._zone.widget.updateMarkdownMessage(renderedMarkdown.element);
this._currentSession.addResponse(reply);
continue;
}

Expand Down Expand Up @@ -651,7 +662,7 @@ export class InteractiveEditorController implements IEditorContribution {
} else {
message = localize('lines.N', "Generated reply and changed {0} lines.", linesChanged);
}
this._zone.widget.updateMessage(message);
this._zone.widget.updateStatus(message);
}


Expand Down Expand Up @@ -773,7 +784,7 @@ export class InteractiveEditorController implements IEditorContribution {
}

undoLast(): string | void {
if (this._currentSession?.lastResponse) {
if (this._currentSession?.lastResponse instanceof EditResponse) {
this._currentSession.modelN.undo();
return this._currentSession.lastResponse.localEdits[0].text;
}
Expand All @@ -782,14 +793,14 @@ export class InteractiveEditorController implements IEditorContribution {
feedbackLast(helpful: boolean) {
if (this._currentSession?.lastResponse) {
const kind = helpful ? InteractiveEditorResponseFeedbackKind.Helpful : InteractiveEditorResponseFeedbackKind.Unhelpful;
this._currentSession.provider.handleInteractiveEditorResponseFeedback?.(this._currentSession.session, this._currentSession.lastResponse.raw, kind);
this._currentSession.provider.handleInteractiveEditorResponseFeedback?.(this._currentSession.session, this._currentSession.lastResponse instanceof EditResponse ? this._currentSession.lastResponse.raw : this._currentSession.lastResponse, kind);
this._ctxLastFeedbackKind.set(helpful ? 'helpful' : 'unhelpful');
this._zone.widget.updateMessage('Thank you for your feedback!', { resetAfter: 1250 });
this._zone.widget.updateStatus('Thank you for your feedback!', { resetAfter: 1250 });
}
}

async applyChanges(): Promise<EditResponse | void> {
if (this._currentSession?.lastResponse) {
if (this._currentSession?.lastResponse instanceof EditResponse) {
const { lastResponse } = this._currentSession;
await this._strategy?.apply();
this._ctsSession.cancel();
Expand Down Expand Up @@ -841,7 +852,7 @@ class PreviewStrategy extends EditModeStrategy {
async apply() {

const response = this._session.lastResponse;
if (!response) {
if (!(response instanceof EditResponse)) {
return;
}

Expand Down Expand Up @@ -1003,7 +1014,8 @@ async function showMessageResponse(accessor: ServicesAccessor, query: string, re
const interactiveSessionWidgetService = accessor.get(IInteractiveSessionWidgetService);
const widget = await interactiveSessionWidgetService.revealViewForProvider(providerId);
if (widget && widget.viewModel) {
interactiveSessionService.addCompleteRequest(widget.viewModel.sessionId, query, { message: response });
await interactiveSessionService.addCompleteRequest(widget.viewModel.sessionId, query, { message: response });
widget.focusLastMessage();
}
}

Expand Down