Inline chat fixes/feature (#208393)

* only show slash command as detected when not having typed one

* use clearer message that hunks need to be accepted or discard, also add hover with more details

fixes https://github.com/microsoft/vscode/issues/206939
This commit is contained in:
Johannes Rieken 2024-03-22 13:24:07 +01:00 committed by GitHub
parent a00f2e64f4
commit ad5a40fb18
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 43 additions and 65 deletions

View file

@ -93,7 +93,8 @@ class BridgeAgent implements IChatAgentImplementation {
// if (data.message) {
// progress({ kind: 'progressMessage', content: new MarkdownString(data.message) });
// }
if (data.slashCommand) {
// TODO@ulugbekna,jrieken should we only send data.slashCommand when having detected one?
if (data.slashCommand && !inlineRequest.prompt.startsWith('/')) {
const command = this._data.slashCommands.find(c => c.name === data.slashCommand);
progress({ kind: 'agentDetection', agentId: this._data.id, command });
}

View file

@ -551,7 +551,7 @@ export class LiveStrategy extends EditModeStrategy {
this._editor.revealPositionInCenterIfOutsideViewport(widgetData.position);
const remainingHunks = this._session.hunkData.pending;
this._updateSummaryMessage(remainingHunks);
this._updateSummaryMessage(remainingHunks, this._session.hunkData.size);
const mode = this._configService.getValue<'on' | 'off' | 'auto'>(InlineChatConfigKeys.AccessibleDiffView);
@ -587,16 +587,28 @@ export class LiveStrategy extends EditModeStrategy {
return renderHunks()?.position;
}
protected _updateSummaryMessage(hunkCount: number) {
private _updateSummaryMessage(remaining: number, total: number) {
const needsReview = this._configService.getValue<boolean>(InlineChatConfigKeys.AcceptedOrDiscardBeforeSave);
let message: string;
if (hunkCount === 0) {
message = localize('change.0', "Nothing changed");
} else if (hunkCount === 1) {
message = localize('change.1', "1 change");
if (total === 0) {
message = localize('change.0', "Nothing changed.");
} else if (remaining === 1) {
message = needsReview
? localize('review.1', "$(info) Accept or Discard 1 change.")
: localize('change.1', "1 change");
} else {
message = localize('lines.NM', "{0} changes", hunkCount);
message = needsReview
? localize('review.N', "$(info) Accept or Discard {0} changes.", remaining)
: localize('change.N', "{0} changes", total);
}
this._zone.widget.updateStatus(message);
let title: string | undefined;
if (needsReview) {
title = localize('review', "Review (accept or discard) all changes before continuing.");
}
this._zone.widget.updateStatus(message, { title });
}
hasFocus(): boolean {

View file

@ -52,6 +52,8 @@ import { ICodeEditorWidgetOptions } from 'vs/editor/browser/widget/codeEditor/co
import { SnippetController2 } from 'vs/editor/contrib/snippet/browser/snippetController2';
import { SuggestController } from 'vs/editor/contrib/suggest/browser/suggestController';
import { IChatService } from 'vs/workbench/contrib/chat/common/chatService';
import { setupCustomHover } from 'vs/base/browser/ui/hover/updatableHoverWidget';
import { getDefaultHoverDelegate } from 'vs/base/browser/ui/hover/hoverDelegateFactory';
export interface InlineChatWidgetViewState {
@ -281,9 +283,13 @@ export class InlineChatWidget {
this._elements.followUps.tabIndex = 0;
this._elements.followUps.ariaLabel = this._accessibleViewService.getOpenAriaHint(AccessibilityVerbositySettingId.InlineChat);
this._elements.statusLabel.tabIndex = 0;
// this._elements.status
this._store.add(setupCustomHover(getDefaultHoverDelegate('element'), this._elements.statusLabel, () => {
return this._elements.statusLabel.dataset['title'];
}));
this._store.add(this._chatService.onDidPerformUserAction(e => {
if (e.sessionId === this._chatWidget.viewModel?.model.sessionId && e.action.kind === 'vote') {
this.updateStatus('Thank you for your feedback!', { resetAfter: 1250 });
@ -525,7 +531,7 @@ export class InlineChatWidget {
this._onDidChangeHeight.fire();
}
updateStatus(message: string, ops: { classes?: string[]; resetAfter?: number; keepMessage?: boolean } = {}) {
updateStatus(message: string, ops: { classes?: string[]; resetAfter?: number; keepMessage?: boolean; title?: string } = {}) {
const isTempMessage = typeof ops.resetAfter === 'number';
if (isTempMessage && !this._elements.statusLabel.dataset['state']) {
const statusLabel = this._elements.statusLabel.innerText;
@ -534,7 +540,8 @@ export class InlineChatWidget {
this.updateStatus(statusLabel, { classes, keepMessage: true });
}, ops.resetAfter);
}
reset(this._elements.statusLabel, message);
const renderedMessage = renderLabelWithIcons(message);
reset(this._elements.statusLabel, ...renderedMessage);
this._elements.statusLabel.className = `label status ${(ops.classes ?? []).join(' ')}`;
this._elements.statusLabel.classList.toggle('hidden', !message);
if (isTempMessage) {
@ -542,6 +549,8 @@ export class InlineChatWidget {
} else {
delete this._elements.statusLabel.dataset['state'];
}
this._elements.statusLabel.dataset['title'] = ops.title;
this._onDidChangeHeight.fire();
}

View file

@ -61,59 +61,28 @@
color: var(--vscode-descriptionForeground);
font-size: 11px;
align-self: baseline;
display: inline-flex;
padding-left: 10px;
margin-left: auto;
}
.monaco-workbench .inline-chat .status .label.hidden {
display: none;
}
.monaco-workbench .inline-chat .status .label.info {
margin-right: auto;
padding-left: 2px;
.monaco-workbench .inline-chat .status .label.error {
color: var(--vscode-errorForeground);
}
.monaco-workbench .inline-chat .status .label.info > .codicon {
.monaco-workbench .inline-chat .status .label.warn {
color: var(--vscode-editorWarning-foreground);
}
.monaco-workbench .inline-chat .status .label > .codicon {
padding: 0 5px;
font-size: 12px;
line-height: 18px;
}
.monaco-workbench .inline-chat .status .label.status {
padding-left: 10px;
padding-right: 4px;
margin-left: auto;
}
.monaco-workbench .inline-chat .status .label .slash-command-pill CODE {
border-radius: 3px;
padding: 0 1px;
background-color: var(--vscode-chat-slashCommandBackground);
color: var(--vscode-chat-slashCommandForeground);
}
.monaco-workbench .inline-chat .detectedIntent {
color: var(--vscode-descriptionForeground);
padding: 5px 0px 5px 5px;
}
.monaco-workbench .inline-chat .detectedIntent.hidden {
display: none;
}
.monaco-workbench .inline-chat .detectedIntent .slash-command-pill CODE {
border-radius: 3px;
padding: 0 1px;
background-color: var(--vscode-chat-slashCommandBackground);
color: var(--vscode-chat-slashCommandForeground);
}
.monaco-workbench .inline-chat .detectedIntent .slash-command-pill a {
color: var(--vscode-textLink-foreground);
cursor: pointer;
}
.monaco-workbench .inline-chat .chatMessage .chatMessageContent .value {
overflow: hidden;
-webkit-user-select: text;
@ -146,19 +115,6 @@
display: none;
}
.monaco-workbench .inline-chat .status .label A {
color: var(--vscode-textLink-foreground);
cursor: pointer;
}
.monaco-workbench .inline-chat .status .label.error {
color: var(--vscode-errorForeground);
}
.monaco-workbench .inline-chat .status .label.warn {
color: var(--vscode-editorWarning-foreground);
}
.monaco-workbench .inline-chat .status .actions {
display: flex;
}