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

Properly wait for interactive session to load before adding request/response from inline editor to it #178178

Merged
merged 1 commit into from Mar 23, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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 @@ -15,4 +15,5 @@ export interface IInteractiveSessionWidget {

acceptInput(): void;
getSlashCommands(): Promise<IInteractiveSlashCommand[] | undefined>;
waitForViewModel(): Promise<IInteractiveSessionViewModel | undefined>;
}
Expand Up @@ -16,6 +16,7 @@ import { IThemeService } from 'vs/platform/theme/common/themeService';
import { IViewPaneOptions, ViewPane } from 'vs/workbench/browser/parts/views/viewPane';
import { IViewDescriptorService } from 'vs/workbench/common/views';
import { InteractiveSessionWidget } from 'vs/workbench/contrib/interactiveSession/browser/interactiveSessionWidget';
import { IInteractiveSessionViewModel } from 'vs/workbench/contrib/interactiveSession/common/interactiveSessionViewModel';

export interface IInteractiveSessionViewOptions {
readonly providerId: string;
Expand Down Expand Up @@ -58,6 +59,10 @@ export class InteractiveSessionViewPane extends ViewPane {
this.view.acceptInput(query);
}

waitForViewModel(): Promise<IInteractiveSessionViewModel | undefined> {
return this.view.waitForViewModel();
}

async clear(): Promise<void> {
await this.view.clear();
}
Expand Down
Expand Up @@ -114,6 +114,8 @@ export class InteractiveSessionWidget extends Disposable implements IInteractive

private previousTreeScrollHeight: number = 0;

private currentViewModelPromise: Promise<IInteractiveSessionViewModel | undefined> | undefined;

private viewModelDisposables = new DisposableStore();
private _viewModel: InteractiveSessionViewModel | undefined;
private set viewModel(viewModel: InteractiveSessionViewModel | undefined) {
Expand Down Expand Up @@ -506,34 +508,39 @@ export class InteractiveSessionWidget extends Disposable implements IInteractive
}

private async initializeSessionModel(initial = false) {
if (this.viewModel) {
if (this.currentViewModelPromise) {
return;
}

await this.extensionService.whenInstalledExtensionsRegistered();
const model = await this.interactiveSessionService.startSession(this.providerId, initial, CancellationToken.None);
if (!model) {
throw new Error('Failed to start session');
}

if (this.viewModel) {
// Oops, created two. TODO this could be better
return;
}
const doInitializeSessionModel = async () => {
await this.extensionService.whenInstalledExtensionsRegistered();
const model = await this.interactiveSessionService.startSession(this.providerId, initial, CancellationToken.None);
if (!model) {
throw new Error('Failed to start session');
}

this.viewModel = this.instantiationService.createInstance(InteractiveSessionViewModel, model);
this.viewModelDisposables.add(this.viewModel.onDidChange(() => {
this.slashCommandsPromise = undefined;
this.onDidChangeItems();
}));
this.viewModelDisposables.add(this.viewModel.onDidDisposeModel(() => {
this.viewModel = undefined;
this.onDidChangeItems();
}));
if (this.viewModel) {
// Oops, created two. TODO this could be better
return;
}

if (this.tree) {
this.onDidChangeItems();
}
this.viewModel = this.instantiationService.createInstance(InteractiveSessionViewModel, model);
this.viewModelDisposables.add(this.viewModel.onDidChange(() => {
this.slashCommandsPromise = undefined;
this.onDidChangeItems();
}));
this.viewModelDisposables.add(this.viewModel.onDidDisposeModel(() => {
this.viewModel = undefined;
this.onDidChangeItems();
}));

if (this.tree) {
this.onDidChangeItems();
}
};
this.currentViewModelPromise = doInitializeSessionModel()
.then(() => this.viewModel);
await this.currentViewModelPromise;
}

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

async waitForViewModel(): Promise<IInteractiveSessionViewModel | undefined> {
return this.currentViewModelPromise;
}

focusLastMessage(): void {
if (!this.viewModel) {
return;
Expand Down
Expand Up @@ -345,7 +345,12 @@ export class InteractiveSessionService extends Disposable implements IInteractiv
}

const viewId = this.interactiveSessionContributionService.getViewIdForProvider(providerId);
await this.viewsService.openView(viewId);
const view = await this.viewsService.openView(viewId);

if ((view as any).waitForViewModel) {
// TODO The ViewPane type is in /browser/, and the flow is a bit weird, rethink this
await (view as any).waitForViewModel();
}

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