Skip to content

Commit

Permalink
Cleanup and prepare inline chat for UI updates (#215420)
Browse files Browse the repository at this point in the history
* 💄

* debt - remove `trackEdits` because we have fixup
debt - don't compute diff twice

* allow to pass/use all chat widget options when creating an inline chat widget
  • Loading branch information
jrieken committed Jun 13, 2024
1 parent f942605 commit c0bbf04
Show file tree
Hide file tree
Showing 8 changed files with 54 additions and 75 deletions.
9 changes: 9 additions & 0 deletions src/vs/workbench/contrib/chat/browser/chat.ts
Original file line number Diff line number Diff line change
Expand Up @@ -107,8 +107,17 @@ export interface IChatWidgetViewOptions {
filter?: (item: ChatTreeItem) => boolean;
rendererOptions?: IChatListItemRendererOptions;
menus?: {
/**
* The menu that is inside the input editor, use for send, dictation
*/
executeToolbar?: MenuId;
/**
* The menu that next to the input editor, use for close, config etc
*/
inputSideToolbar?: MenuId;
/**
* The telemetry source for all commands of this widget
*/
telemetrySource?: string;
};
defaultElementHeight?: number;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ export class StartSessionAction extends EditorAction2 {

let options: InlineChatRunOptions | undefined;
const arg = _args[0];
if (arg && InlineChatRunOptions.isInteractiveEditorOptions(arg)) {
if (arg && InlineChatRunOptions.isInlineChatRunOptions(arg)) {
options = arg;
}
InlineChatController.get(editor)?.run({ ...options });
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ export abstract class InlineChatRunOptions {
position?: IPosition;
withIntentDetection?: boolean;

static isInteractiveEditorOptions(options: any): options is InlineChatRunOptions {
static isInlineChatRunOptions(options: any): options is InlineChatRunOptions {
const { initialSelection, initialRange, message, autoSend, position, existingSession } = <InlineChatRunOptions>options;
if (
typeof message !== 'undefined' && typeof message !== 'string'
Expand All @@ -106,8 +106,6 @@ export class InlineChatController implements IEditorContribution {

private _isDisposed: boolean = false;
private readonly _store = new DisposableStore();
// private readonly _input: Lazy<InlineChatContentWidget>;
// private readonly _zone: Lazy<InlineChatZoneWidget>;

private readonly _ui: Lazy<{ content: InlineChatContentWidget; zone: InlineChatZoneWidget }>;

Expand Down Expand Up @@ -745,11 +743,9 @@ export class InlineChatController implements IEditorContribution {

store.dispose();

// todo@jrieken we can likely remove 'trackEdit'
const diff = await this._editorWorkerService.computeDiff(this._session.textModel0.uri, this._session.textModelN.uri, { computeMoves: false, maxComputationTimeMs: Number.MAX_SAFE_INTEGER, ignoreTrimWhitespace: false }, 'advanced');
this._session.wholeRange.fixup(diff?.changes ?? []);

await this._session.hunkData.recompute(editState);
await this._session.hunkData.recompute(editState, diff);

this._ui.value.zone.widget.updateToolbar(true);
this._ui.value.zone.widget.updateProgress(false);
Expand Down Expand Up @@ -898,13 +894,6 @@ export class InlineChatController implements IEditorContribution {
} else if (initialRender) {
const selection = this._editor.getSelection();
widgetPosition = selection.getStartPosition();
// TODO@jrieken we are not ready for this
// widgetPosition = selection.getEndPosition();
// if (Range.spansMultipleLines(selection) && widgetPosition.column === 1) {
// // selection ends on "nothing" -> move up to match the
// // rendered/visible part of the selection
// widgetPosition = this._editor.getModel().validatePosition(widgetPosition.delta(-1, Number.MAX_SAFE_INTEGER));
// }
this._ui.value.content.show(widgetPosition);

} else {
Expand Down Expand Up @@ -958,7 +947,6 @@ export class InlineChatController implements IEditorContribution {
};

this._inlineChatSavingService.markChanged(this._session);
this._session.wholeRange.trackEdits(editOperations);
if (opts) {
await this._strategy.makeProgressiveChanges(editOperations, editsObserver, opts, undoStopBefore);
} else {
Expand Down
14 changes: 3 additions & 11 deletions src/vs/workbench/contrib/inlineChat/browser/inlineChatSession.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ import { ILogService } from 'vs/platform/log/common/log';
import { ChatModel, IChatRequestModel, IChatResponseModel, IChatTextEditGroupState } from 'vs/workbench/contrib/chat/common/chatModel';
import { ExtensionIdentifier } from 'vs/platform/extensions/common/extensions';
import { IChatAgent } from 'vs/workbench/contrib/chat/common/chatAgents';
import { IDocumentDiff } from 'vs/editor/common/diff/documentDiffProvider';


export type TelemetryData = {
Expand Down Expand Up @@ -88,15 +89,6 @@ export class SessionWholeRange {
}
}

trackEdits(edits: ISingleEditOperation[]): void {
const newDeco: IModelDeltaDecoration[] = [];
for (const edit of edits) {
newDeco.push({ range: edit.range, options: SessionWholeRange._options });
}
this._decorationIds.push(...this._textModel.deltaDecorations([], newDeco));
this._onDidChange.fire(this);
}

fixup(changes: readonly DetailedLineRangeMapping[]): void {

const newDeco: IModelDeltaDecoration[] = [];
Expand Down Expand Up @@ -555,9 +547,9 @@ export class HunkData {
this._textModel0.pushEditOperations(null, edits, () => null);
}

async recompute(editState: IChatTextEditGroupState) {
async recompute(editState: IChatTextEditGroupState, diff?: IDocumentDiff | null) {

const diff = await this._editorWorkerService.computeDiff(this._textModel0.uri, this._textModelN.uri, { ignoreTrimWhitespace: false, maxComputationTimeMs: Number.MAX_SAFE_INTEGER, computeMoves: false }, 'advanced');
diff ??= await this._editorWorkerService.computeDiff(this._textModel0.uri, this._textModelN.uri, { ignoreTrimWhitespace: false, maxComputationTimeMs: Number.MAX_SAFE_INTEGER, computeMoves: false }, 'advanced');

if (!diff || diff.changes.length === 0) {
// return new HunkData([], session);
Expand Down
36 changes: 9 additions & 27 deletions src/vs/workbench/contrib/inlineChat/browser/inlineChatWidget.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ import { IChatService } from 'vs/workbench/contrib/chat/common/chatService';
import { getDefaultHoverDelegate } from 'vs/base/browser/ui/hover/hoverDelegateFactory';
import { ServiceCollection } from 'vs/platform/instantiation/common/serviceCollection';
import { IHoverService } from 'vs/platform/hover/browser/hover';
import { IChatListItemRendererOptions } from 'vs/workbench/contrib/chat/browser/chat';
import { IChatWidgetViewOptions } from 'vs/workbench/contrib/chat/browser/chat';


export interface InlineChatWidgetViewState {
Expand All @@ -57,18 +57,7 @@ export interface InlineChatWidgetViewState {
}

export interface IInlineChatWidgetConstructionOptions {
/**
* The telemetry source for all commands of this widget
*/
telemetrySource: string;
/**
* The menu that is inside the input editor, use for send, dictation
*/
inputMenuId: MenuId;
/**
* The menu that next to the input editor, use for close, config etc
*/
widgetMenuId: MenuId;

/**
* The menu that rendered as button bar, use for accept, discard etc
*/
Expand All @@ -78,9 +67,10 @@ export interface IInlineChatWidgetConstructionOptions {
*/
feedbackMenuId?: MenuId;

editorOverflowWidgetsDomNode?: HTMLElement;

rendererOptions?: IChatListItemRendererOptions;
/**
* The options for the chat widget
*/
chatWidgetViewOptions?: IChatWidgetViewOptions;
}

export interface IInlineChatMessage {
Expand Down Expand Up @@ -170,13 +160,7 @@ export class InlineChatWidget {
renderInputOnTop: true,
renderFollowups: true,
supportsFileReferences: true,
editorOverflowWidgetsDomNode: options.editorOverflowWidgetsDomNode,
rendererOptions: options.rendererOptions,
menus: {
executeToolbar: options.inputMenuId,
inputSideToolbar: options.widgetMenuId,
telemetrySource: options.telemetrySource
},
// editorOverflowWidgetsDomNode: options.editorOverflowWidgetsDomNode,
filter: item => {
if (isWelcomeVM(item)) {
return false;
Expand All @@ -186,6 +170,7 @@ export class InlineChatWidget {
}
return true;
},
...options.chatWidgetViewOptions
},
{
listForeground: editorForeground,
Expand Down Expand Up @@ -464,9 +449,6 @@ export class InlineChatWidget {
return tail(requests)?.response?.response.asString();
}

get usesDefaultChatModel(): boolean {
return this.getChatModel() === this._defaultChatModel;
}

getChatModel(): IChatModel {
return this._chatWidget.viewModel?.model ?? this._defaultChatModel;
Expand Down Expand Up @@ -608,7 +590,7 @@ export class EditorBasedInlineChatWidget extends InlineChatWidget {
@IChatService chatService: IChatService,
@IHoverService hoverService: IHoverService,
) {
super(location, { ...options, editorOverflowWidgetsDomNode: _parentEditor.getOverflowWidgetsDomNode() }, instantiationService, contextKeyService, keybindingService, accessibilityService, configurationService, accessibleViewService, textModelResolverService, chatService, hoverService);
super(location, { ...options, chatWidgetViewOptions: { editorOverflowWidgetsDomNode: _parentEditor.getOverflowWidgetsDomNode() } }, instantiationService, contextKeyService, keybindingService, accessibilityService, configurationService, accessibleViewService, textModelResolverService, chatService, hoverService);
}

// --- layout
Expand Down
22 changes: 12 additions & 10 deletions src/vs/workbench/contrib/inlineChat/browser/inlineChatZoneWidget.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ import { IContextKey, IContextKeyService } from 'vs/platform/contextkey/common/c
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { ACTION_ACCEPT_CHANGES, ACTION_REGENERATE_RESPONSE, ACTION_TOGGLE_DIFF, CTX_INLINE_CHAT_OUTER_CURSOR_POSITION, EditMode, InlineChatConfigKeys, MENU_INLINE_CHAT_WIDGET, MENU_INLINE_CHAT_WIDGET_STATUS } from 'vs/workbench/contrib/inlineChat/common/inlineChat';
import { EditorBasedInlineChatWidget } from './inlineChatWidget';
import { MenuId } from 'vs/platform/actions/common/actions';
import { isEqual } from 'vs/base/common/resources';
import { StableEditorBottomScrollState } from 'vs/editor/browser/stableEditorScroll';
import { ScrollType } from 'vs/editor/common/editorCommon';
Expand Down Expand Up @@ -47,9 +46,6 @@ export class InlineChatZoneWidget extends ZoneWidget {
}));

this.widget = this._instaService.createInstance(EditorBasedInlineChatWidget, location, this.editor, {
telemetrySource: 'interactiveEditorWidget-toolbar',
inputMenuId: MenuId.ChatExecute,
widgetMenuId: MENU_INLINE_CHAT_WIDGET,
statusMenuId: {
menu: MENU_INLINE_CHAT_WIDGET_STATUS,
options: {
Expand All @@ -64,13 +60,19 @@ export class InlineChatZoneWidget extends ZoneWidget {
}
}
},
rendererOptions: {
renderTextEditsAsSummary: (uri) => {
// render edits as summary only when using Live mode and when
// dealing with the current file in the editor
return isEqual(uri, editor.getModel()?.uri)
&& configurationService.getValue<EditMode>(InlineChatConfigKeys.Mode) === EditMode.Live;
chatWidgetViewOptions: {
menus: {
inputSideToolbar: MENU_INLINE_CHAT_WIDGET,
telemetrySource: 'interactiveEditorWidget-toolbar',
},
rendererOptions: {
renderTextEditsAsSummary: (uri) => {
// render edits as summary only when using Live mode and when
// dealing with the current file in the editor
return isEqual(uri, editor.getModel()?.uri)
&& configurationService.getValue<EditMode>(InlineChatConfigKeys.Mode) === EditMode.Live;
},
}
}
});
this._disposables.add(this.widget.onDidChangeHeight(() => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ import { ICursorStateComputer, ITextModel } from 'vs/editor/common/model';
import { IEditorWorkerService } from 'vs/editor/common/services/editorWorker';
import { IModelService } from 'vs/editor/common/services/model';
import { localize } from 'vs/nls';
import { MenuId } from 'vs/platform/actions/common/actions';
import { IContextKey, IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { IStorageService, StorageScope, StorageTarget } from 'vs/platform/storage/common/storage';
Expand Down Expand Up @@ -415,14 +414,17 @@ export class NotebookChatController extends Disposable implements INotebookEdito
InlineChatWidget,
ChatAgentLocation.Notebook,
{
telemetrySource: 'notebook-generate-cell',
inputMenuId: MenuId.ChatExecute,
widgetMenuId: MENU_INLINE_CHAT_WIDGET,
statusMenuId: MENU_CELL_CHAT_WIDGET_STATUS,
rendererOptions: {
renderTextEditsAsSummary: (uri) => {
return isEqual(uri, this._widget?.parentEditor.getModel()?.uri)
|| isEqual(uri, this._notebookEditor.textModel?.uri);
chatWidgetViewOptions: {
rendererOptions: {
renderTextEditsAsSummary: (uri) => {
return isEqual(uri, this._widget?.parentEditor.getModel()?.uri)
|| isEqual(uri, this._notebookEditor.textModel?.uri);
}
},
menus: {
telemetrySource: 'notebook-generate-cell',
inputSideToolbar: MENU_INLINE_CHAT_WIDGET,
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,6 @@ export class TerminalChatWidget extends Disposable {
InlineChatWidget,
ChatAgentLocation.Terminal,
{
inputMenuId: MENU_TERMINAL_CHAT_INPUT,
widgetMenuId: MENU_TERMINAL_CHAT_WIDGET,
statusMenuId: {
menu: MENU_TERMINAL_CHAT_WIDGET_STATUS,
options: {
Expand All @@ -72,8 +70,14 @@ export class TerminalChatWidget extends Disposable {
}
}
},
telemetrySource: 'terminal-inline-chat',
rendererOptions: { editableCodeBlock: true }
chatWidgetViewOptions: {
rendererOptions: { editableCodeBlock: true },
menus: {
telemetrySource: 'terminal-inline-chat',
executeToolbar: MENU_TERMINAL_CHAT_INPUT,
inputSideToolbar: MENU_TERMINAL_CHAT_WIDGET,
}
}
}
);
this._register(Event.any(
Expand Down

0 comments on commit c0bbf04

Please sign in to comment.