Skip to content

Commit b8b5a4a

Browse files
authored
Move hunk computation into sessions, let strategies render them (microsoft#202578)
* chore - move chat session service implementation and interface into their own files * chore - move chat saving service implementation and interface into their own files * - move hunks into session (instead of strategy) - recompute them after receiving AI changes - accept& discard moves hunks from textModelN to textModel0 and vice versa - service renames - tests * - session doesn't know about an editor, only service does - allow to "move" session to a different editor - let controller pickup session after move to its editor - session saving picks up orphand sessions * try to restore editors when group is still valid * ctrl - don't pause when cancellation happens during session create * fix tests
1 parent 48bc94d commit b8b5a4a

16 files changed

+1113
-579
lines changed

src/vs/workbench/contrib/codeEditor/browser/emptyTextEditorHint/emptyTextEditorHint.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
2121
import { IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService';
2222
import { IContentActionHandler, renderFormattedText } from 'vs/base/browser/formattedTextRenderer';
2323
import { ApplyFileSnippetAction } from 'vs/workbench/contrib/snippets/browser/commands/fileTemplateSnippets';
24-
import { IInlineChatSessionService } from 'vs/workbench/contrib/inlineChat/browser/inlineChatSession';
24+
import { IInlineChatSessionService } from 'vs/workbench/contrib/inlineChat/browser/inlineChatSessionService';
2525
import { IInlineChatService, IInlineChatSessionProvider } from 'vs/workbench/contrib/inlineChat/common/inlineChat';
2626
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
2727
import { WorkbenchActionExecutedClassification, WorkbenchActionExecutedEvent } from 'vs/base/common/actions';

src/vs/workbench/contrib/inlineChat/browser/inlineChat.contribution.ts

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,17 +10,19 @@ import * as InlineChatActions from 'vs/workbench/contrib/inlineChat/browser/inli
1010
import { IInlineChatService, INLINE_CHAT_ID, INTERACTIVE_EDITOR_ACCESSIBILITY_HELP_ID } from 'vs/workbench/contrib/inlineChat/common/inlineChat';
1111
import { InstantiationType, registerSingleton } from 'vs/platform/instantiation/common/extensions';
1212
import { InlineChatServiceImpl } from 'vs/workbench/contrib/inlineChat/common/inlineChatServiceImpl';
13-
import { IInlineChatSessionService, InlineChatSessionService } from 'vs/workbench/contrib/inlineChat/browser/inlineChatSession';
13+
import { InlineChatSessionServiceImpl } from './inlineChatSessionServiceImpl';
14+
import { IInlineChatSessionService } from './inlineChatSessionService';
1415
import { Registry } from 'vs/platform/registry/common/platform';
1516
import { LifecyclePhase } from 'vs/workbench/services/lifecycle/common/lifecycle';
1617
import { InlineChatNotebookContribution } from 'vs/workbench/contrib/inlineChat/browser/inlineChatNotebook';
1718
import { IWorkbenchContributionsRegistry, Extensions as WorkbenchExtensions } from 'vs/workbench/common/contributions';
1819
import { InlineChatAccessibleViewContribution } from './inlineChatAccessibleView';
19-
import { IInlineChatSavingService, InlineChatSavingService } from 'vs/workbench/contrib/inlineChat/browser/inlineChatSaving';
20+
import { InlineChatSavingServiceImpl } from 'vs/workbench/contrib/inlineChat/browser/inlineChatSavingServiceImpl';
21+
import { IInlineChatSavingService } from './inlineChatSavingService';
2022

2123
registerSingleton(IInlineChatService, InlineChatServiceImpl, InstantiationType.Delayed);
22-
registerSingleton(IInlineChatSessionService, InlineChatSessionService, InstantiationType.Delayed);
23-
registerSingleton(IInlineChatSavingService, InlineChatSavingService, InstantiationType.Delayed);
24+
registerSingleton(IInlineChatSessionService, InlineChatSessionServiceImpl, InstantiationType.Delayed);
25+
registerSingleton(IInlineChatSavingService, InlineChatSavingServiceImpl, InstantiationType.Delayed);
2426

2527
registerEditorContribution(INLINE_CHAT_ID, InlineChatController, EditorContributionInstantiation.Eager); // EAGER because of notebook dispose/create of editors
2628
registerEditorContribution(INTERACTIVE_EDITOR_ACCESSIBILITY_HELP_ID, InlineChatActions.InlineAccessibilityHelpContribution, EditorContributionInstantiation.Eventually);

src/vs/workbench/contrib/inlineChat/browser/inlineChatActions.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ import { IEditorService, SIDE_GROUP } from 'vs/workbench/services/editor/common/
2222
import { IUntitledTextResourceEditorInput } from 'vs/workbench/common/editor';
2323
import { ICodeEditorService } from 'vs/editor/browser/services/codeEditorService';
2424
import { fromNow } from 'vs/base/common/date';
25-
import { IInlineChatSessionService, Recording } from 'vs/workbench/contrib/inlineChat/browser/inlineChatSession';
25+
import { IInlineChatSessionService, Recording } from './inlineChatSessionService';
2626
import { runAccessibilityHelpAction } from 'vs/workbench/contrib/chat/browser/actions/chatAccessibilityHelp';
2727
import { CONTEXT_ACCESSIBILITY_MODE_ENABLED } from 'vs/platform/accessibility/common/accessibility';
2828
import { Disposable } from 'vs/base/common/lifecycle';

src/vs/workbench/contrib/inlineChat/browser/inlineChatController.ts

Lines changed: 49 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,9 @@ import { IChatAccessibilityService, IChatWidgetService } from 'vs/workbench/cont
3939
import { IChatAgentService } from 'vs/workbench/contrib/chat/common/chatAgents';
4040
import { chatAgentLeader, chatSubcommandLeader } from 'vs/workbench/contrib/chat/common/chatParserTypes';
4141
import { IChatService } from 'vs/workbench/contrib/chat/common/chatService';
42-
import { IInlineChatSavingService } from 'vs/workbench/contrib/inlineChat/browser/inlineChatSaving';
43-
import { EmptyResponse, ErrorResponse, ExpansionState, IInlineChatSessionService, ReplyResponse, Session, SessionExchange, SessionPrompt } from 'vs/workbench/contrib/inlineChat/browser/inlineChatSession';
42+
import { IInlineChatSavingService } from './inlineChatSavingService';
43+
import { EmptyResponse, ErrorResponse, ExpansionState, ReplyResponse, Session, SessionExchange, SessionPrompt } from 'vs/workbench/contrib/inlineChat/browser/inlineChatSession';
44+
import { IInlineChatSessionService } from './inlineChatSessionService';
4445
import { EditModeStrategy, LivePreviewStrategy, LiveStrategy, PreviewStrategy, ProgressingEditsOptions } from 'vs/workbench/contrib/inlineChat/browser/inlineChatStrategies';
4546
import { IInlineChatMessageAppender, InlineChatZoneWidget } from 'vs/workbench/contrib/inlineChat/browser/inlineChatWidget';
4647
import { CTX_INLINE_CHAT_DID_EDIT, CTX_INLINE_CHAT_HAS_ACTIVE_REQUEST, CTX_INLINE_CHAT_LAST_FEEDBACK, CTX_INLINE_CHAT_RESPONSE_TYPES, CTX_INLINE_CHAT_SUPPORT_ISSUE_REPORTING, CTX_INLINE_CHAT_USER_DID_EDIT, EditMode, IInlineChatProgressItem, IInlineChatRequest, IInlineChatResponse, INLINE_CHAT_ID, InlineChatConfigKeys, InlineChatResponseFeedbackKind, InlineChatResponseTypes } from 'vs/workbench/contrib/inlineChat/common/inlineChat';
@@ -122,7 +123,7 @@ export class InlineChatController implements IEditorContribution {
122123
readonly onDidCancelInput = Event.filter(this._messages.event, m => m === Message.CANCEL_INPUT || m === Message.CANCEL_SESSION, this._store);
123124

124125
private readonly _sessionStore: DisposableStore = this._store.add(new DisposableStore());
125-
private readonly _pausedStrategies = new Map<Session, EditModeStrategy>();
126+
126127
private _session?: Session;
127128
private _strategy?: EditModeStrategy;
128129
private _ignoreModelContentChanged = false;
@@ -161,17 +162,19 @@ export class InlineChatController implements IEditorContribution {
161162
return;
162163
}
163164

164-
this._log('session RESUMING', e);
165+
this._log('session RESUMING after model change', e);
165166
await this.run({ existingSession });
166-
this._log('session done or paused');
167167
}));
168-
this._log('NEW controller');
169168

170-
this._store.add(this._inlineChatSessionService.onDidEndSession(e => {
171-
this._pausedStrategies.get(e.session)?.dispose();
172-
this._pausedStrategies.delete(e.session);
169+
this._store.add(this._inlineChatSessionService.onDidMoveSession(async e => {
170+
if (e.editor === this._editor) {
171+
this._log('session RESUMING after move', e);
172+
await this.run({ existingSession: e.session });
173+
}
173174
}));
174175

176+
this._log('NEW controller');
177+
175178
InlineChatController._promptHistory = JSON.parse(_storageService.get(InlineChatController._storageKey, StorageScope.PROFILE, '[]'));
176179
this._historyUpdate = (prompt: string) => {
177180
const idx = InlineChatController._promptHistory.indexOf(prompt);
@@ -264,7 +267,7 @@ export class InlineChatController implements IEditorContribution {
264267
}
265268
}
266269

267-
private async [State.CREATE_SESSION](options: InlineChatRunOptions): Promise<State.CANCEL | State.INIT_UI | State.PAUSE> {
270+
private async [State.CREATE_SESSION](options: InlineChatRunOptions): Promise<State.CANCEL | State.INIT_UI> {
268271
assertType(this._session === undefined);
269272
assertType(this._editor.hasModel());
270273

@@ -305,7 +308,10 @@ export class InlineChatController implements IEditorContribution {
305308
msgListener.dispose();
306309

307310
if (createSessionCts.token.isCancellationRequested) {
308-
return State.PAUSE;
311+
if (session) {
312+
this._inlineChatSessionService.releaseSession(session);
313+
}
314+
return State.CANCEL;
309315
}
310316
}
311317

@@ -317,24 +323,18 @@ export class InlineChatController implements IEditorContribution {
317323
return State.CANCEL;
318324
}
319325

320-
if (this._pausedStrategies.has(session)) {
321-
// maybe a strategy was previously paused, use it
322-
this._strategy = this._pausedStrategies.get(session)!;
323-
this._pausedStrategies.delete(session);
324-
} else {
325-
// create a new strategy
326-
switch (session.editMode) {
327-
case EditMode.Live:
328-
this._strategy = this._instaService.createInstance(LiveStrategy, session, this._editor, this._zone.value);
329-
break;
330-
case EditMode.Preview:
331-
this._strategy = this._instaService.createInstance(PreviewStrategy, session, this._zone.value);
332-
break;
333-
case EditMode.LivePreview:
334-
default:
335-
this._strategy = this._instaService.createInstance(LivePreviewStrategy, session, this._editor, this._zone.value);
336-
break;
337-
}
326+
// create a new strategy
327+
switch (session.editMode) {
328+
case EditMode.Live:
329+
this._strategy = this._instaService.createInstance(LiveStrategy, session, this._editor, this._zone.value);
330+
break;
331+
case EditMode.Preview:
332+
this._strategy = this._instaService.createInstance(PreviewStrategy, session, this._zone.value);
333+
break;
334+
case EditMode.LivePreview:
335+
default:
336+
this._strategy = this._instaService.createInstance(LivePreviewStrategy, session, this._editor, this._zone.value);
337+
break;
338338
}
339339

340340
this._session = session;
@@ -690,7 +690,13 @@ export class InlineChatController implements IEditorContribution {
690690
msgListener.dispose();
691691
typeListener.dispose();
692692

693-
if (request.live && !(response instanceof ReplyResponse)) {
693+
if (response instanceof ReplyResponse) {
694+
// update hunks after a reply response
695+
await this._session.hunkData.recompute();
696+
697+
} else if (request.live) {
698+
// undo changes that might have been made when not
699+
// having a reply response
694700
this._strategy?.undoChanges(modelAltVersionIdNow);
695701
}
696702

@@ -803,7 +809,6 @@ export class InlineChatController implements IEditorContribution {
803809

804810
this._resetWidget();
805811

806-
this._pausedStrategies.set(this._session, this._strategy);
807812
this._strategy.pause?.();
808813
this._session = undefined;
809814
}
@@ -831,21 +836,22 @@ export class InlineChatController implements IEditorContribution {
831836
}
832837

833838
private async[State.CANCEL]() {
834-
assertType(this._session);
835-
assertType(this._strategy);
836-
this._sessionStore.clear();
837-
838-
try {
839-
await this._strategy.cancel();
840-
} catch (err) {
841-
this._dialogService.error(localize('err.discard', "Failed to discard changes.", toErrorMessage(err)));
842-
this._log('FAILED to discard changes');
843-
this._log(err);
839+
if (this._session) {
840+
// assertType(this._session);
841+
assertType(this._strategy);
842+
this._sessionStore.clear();
843+
844+
try {
845+
await this._strategy.cancel();
846+
} catch (err) {
847+
this._dialogService.error(localize('err.discard', "Failed to discard changes.", toErrorMessage(err)));
848+
this._log('FAILED to discard changes');
849+
this._log(err);
850+
}
851+
this._inlineChatSessionService.releaseSession(this._session);
844852
}
845853

846854
this._resetWidget();
847-
this._inlineChatSessionService.releaseSession(this._session);
848-
849855

850856
this._strategy?.dispose();
851857
this._strategy = undefined;

src/vs/workbench/contrib/inlineChat/browser/inlineChatNotebook.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import { Schemas } from 'vs/base/common/network';
99
import { isEqual } from 'vs/base/common/resources';
1010
import { ICodeEditor } from 'vs/editor/browser/editorBrowser';
1111
import { InlineChatController } from 'vs/workbench/contrib/inlineChat/browser/inlineChatController';
12-
import { IInlineChatSessionService } from 'vs/workbench/contrib/inlineChat/browser/inlineChatSession';
12+
import { IInlineChatSessionService } from './inlineChatSessionService';
1313
import { INotebookEditorService } from 'vs/workbench/contrib/notebook/browser/services/notebookEditorService';
1414
import { CellUri } from 'vs/workbench/contrib/notebook/common/notebookCommon';
1515

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
/*---------------------------------------------------------------------------------------------
2+
* Copyright (c) Microsoft Corporation. All rights reserved.
3+
* Licensed under the MIT License. See License.txt in the project root for license information.
4+
*--------------------------------------------------------------------------------------------*/
5+
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
6+
import { Session } from 'vs/workbench/contrib/inlineChat/browser/inlineChatSession';
7+
8+
9+
export const IInlineChatSavingService = createDecorator<IInlineChatSavingService>('IInlineChatSavingService ');
10+
11+
export interface IInlineChatSavingService {
12+
_serviceBrand: undefined;
13+
14+
markChanged(session: Session): void;
15+
16+
}

0 commit comments

Comments
 (0)