Skip to content

Commit 233b4e0

Browse files
authored
Properly wait for interactive session to load before adding request/response from inline editor to it (microsoft#178178)
1 parent deedbd3 commit 233b4e0

File tree

4 files changed

+46
-24
lines changed

4 files changed

+46
-24
lines changed

src/vs/workbench/contrib/interactiveSession/browser/interactiveSession.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,4 +15,5 @@ export interface IInteractiveSessionWidget {
1515

1616
acceptInput(): void;
1717
getSlashCommands(): Promise<IInteractiveSlashCommand[] | undefined>;
18+
waitForViewModel(): Promise<IInteractiveSessionViewModel | undefined>;
1819
}

src/vs/workbench/contrib/interactiveSession/browser/interactiveSessionSidebar.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import { IThemeService } from 'vs/platform/theme/common/themeService';
1616
import { IViewPaneOptions, ViewPane } from 'vs/workbench/browser/parts/views/viewPane';
1717
import { IViewDescriptorService } from 'vs/workbench/common/views';
1818
import { InteractiveSessionWidget } from 'vs/workbench/contrib/interactiveSession/browser/interactiveSessionWidget';
19+
import { IInteractiveSessionViewModel } from 'vs/workbench/contrib/interactiveSession/common/interactiveSessionViewModel';
1920

2021
export interface IInteractiveSessionViewOptions {
2122
readonly providerId: string;
@@ -58,6 +59,10 @@ export class InteractiveSessionViewPane extends ViewPane {
5859
this.view.acceptInput(query);
5960
}
6061

62+
waitForViewModel(): Promise<IInteractiveSessionViewModel | undefined> {
63+
return this.view.waitForViewModel();
64+
}
65+
6166
async clear(): Promise<void> {
6267
await this.view.clear();
6368
}

src/vs/workbench/contrib/interactiveSession/browser/interactiveSessionWidget.ts

Lines changed: 34 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,8 @@ export class InteractiveSessionWidget extends Disposable implements IInteractive
114114

115115
private previousTreeScrollHeight: number = 0;
116116

117+
private currentViewModelPromise: Promise<IInteractiveSessionViewModel | undefined> | undefined;
118+
117119
private viewModelDisposables = new DisposableStore();
118120
private _viewModel: InteractiveSessionViewModel | undefined;
119121
private set viewModel(viewModel: InteractiveSessionViewModel | undefined) {
@@ -506,34 +508,39 @@ export class InteractiveSessionWidget extends Disposable implements IInteractive
506508
}
507509

508510
private async initializeSessionModel(initial = false) {
509-
if (this.viewModel) {
511+
if (this.currentViewModelPromise) {
510512
return;
511513
}
512514

513-
await this.extensionService.whenInstalledExtensionsRegistered();
514-
const model = await this.interactiveSessionService.startSession(this.providerId, initial, CancellationToken.None);
515-
if (!model) {
516-
throw new Error('Failed to start session');
517-
}
518-
519-
if (this.viewModel) {
520-
// Oops, created two. TODO this could be better
521-
return;
522-
}
515+
const doInitializeSessionModel = async () => {
516+
await this.extensionService.whenInstalledExtensionsRegistered();
517+
const model = await this.interactiveSessionService.startSession(this.providerId, initial, CancellationToken.None);
518+
if (!model) {
519+
throw new Error('Failed to start session');
520+
}
523521

524-
this.viewModel = this.instantiationService.createInstance(InteractiveSessionViewModel, model);
525-
this.viewModelDisposables.add(this.viewModel.onDidChange(() => {
526-
this.slashCommandsPromise = undefined;
527-
this.onDidChangeItems();
528-
}));
529-
this.viewModelDisposables.add(this.viewModel.onDidDisposeModel(() => {
530-
this.viewModel = undefined;
531-
this.onDidChangeItems();
532-
}));
522+
if (this.viewModel) {
523+
// Oops, created two. TODO this could be better
524+
return;
525+
}
533526

534-
if (this.tree) {
535-
this.onDidChangeItems();
536-
}
527+
this.viewModel = this.instantiationService.createInstance(InteractiveSessionViewModel, model);
528+
this.viewModelDisposables.add(this.viewModel.onDidChange(() => {
529+
this.slashCommandsPromise = undefined;
530+
this.onDidChangeItems();
531+
}));
532+
this.viewModelDisposables.add(this.viewModel.onDidDisposeModel(() => {
533+
this.viewModel = undefined;
534+
this.onDidChangeItems();
535+
}));
536+
537+
if (this.tree) {
538+
this.onDidChangeItems();
539+
}
540+
};
541+
this.currentViewModelPromise = doInitializeSessionModel()
542+
.then(() => this.viewModel);
543+
await this.currentViewModelPromise;
537544
}
538545

539546
async acceptInput(query?: string | IInteractiveSessionReplyFollowup): Promise<void> {
@@ -571,6 +578,10 @@ export class InteractiveSessionWidget extends Disposable implements IInteractive
571578
}
572579
}
573580

581+
async waitForViewModel(): Promise<IInteractiveSessionViewModel | undefined> {
582+
return this.currentViewModelPromise;
583+
}
584+
574585
focusLastMessage(): void {
575586
if (!this.viewModel) {
576587
return;

src/vs/workbench/contrib/interactiveSession/common/interactiveSessionServiceImpl.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -345,7 +345,12 @@ export class InteractiveSessionService extends Disposable implements IInteractiv
345345
}
346346

347347
const viewId = this.interactiveSessionContributionService.getViewIdForProvider(providerId);
348-
await this.viewsService.openView(viewId);
348+
const view = await this.viewsService.openView(viewId);
349+
350+
if ((view as any).waitForViewModel) {
351+
// TODO The ViewPane type is in /browser/, and the flow is a bit weird, rethink this
352+
await (view as any).waitForViewModel();
353+
}
349354

350355
// Currently we only support one session per provider
351356
const modelForProvider = Iterable.find(this._sessionModels.values(), model => model.providerId === providerId);

0 commit comments

Comments
 (0)