sessions: prevent transferring a disposed editing session

Cherry picks https://github.com/microsoft/vscode/pull/292667/files

Closes #292174
This commit is contained in:
Connor Peet 2026-02-03 12:22:43 -08:00
parent f07c55879d
commit e4672417b5
No known key found for this signature in database
GPG Key ID: CF8FD2EA0DBC61BD

View File

@ -417,58 +417,62 @@ export class MainThreadChatSessions extends Disposable implements MainThreadChat
}
const originalEditor = this._editorService.editors.find(editor => editor.resource?.toString() === originalResource.toString());
const originalModel = this._chatService.getSession(originalResource);
const originalModel = this._chatService.getActiveSessionReference(originalResource);
const contribution = this._chatSessionsService.getAllChatSessionContributions().find(c => c.type === chatSessionType);
// Find the group containing the original editor
const originalGroup =
this.editorGroupService.groups.find(group => group.editors.some(editor => isEqual(editor.resource, originalResource)))
?? this.editorGroupService.activeGroup;
try {
// Find the group containing the original editor
const originalGroup =
this.editorGroupService.groups.find(group => group.editors.some(editor => isEqual(editor.resource, originalResource)))
?? this.editorGroupService.activeGroup;
const options: IChatEditorOptions = {
title: {
preferred: originalEditor?.getName() || undefined,
fallback: localize('chatEditorContributionName', "{0}", contribution?.displayName),
}
};
// Prefetch the chat session content to make the subsequent editor swap quick
const newSession = await this._chatSessionsService.getOrCreateChatSession(
URI.revive(modifiedResource),
CancellationToken.None,
);
if (originalEditor) {
newSession.transferredState = originalEditor instanceof ChatEditorInput
? { editingSession: originalEditor.transferOutEditingSession(), inputState: originalModel?.inputModel.toJSON() }
: undefined;
this._editorService.replaceEditors([{
editor: originalEditor,
replacement: {
resource: modifiedResource,
options,
},
}], originalGroup);
return;
}
// If chat editor is in the side panel, then those are not listed as editors.
// In that case we need to transfer editing session using the original model.
if (originalModel) {
newSession.transferredState = {
editingSession: originalModel.editingSession,
inputState: originalModel.inputModel.toJSON()
const options: IChatEditorOptions = {
title: {
preferred: originalEditor?.getName() || undefined,
fallback: localize('chatEditorContributionName', "{0}", contribution?.displayName),
}
};
}
const chatViewWidget = this._chatWidgetService.getWidgetBySessionResource(originalResource);
if (chatViewWidget && isIChatViewViewContext(chatViewWidget.viewContext)) {
await this._chatWidgetService.openSession(modifiedResource, ChatViewPaneTarget, { preserveFocus: true });
} else {
// Loading the session to ensure the session is created and editing session is transferred.
const ref = await this._chatService.loadSessionForResource(modifiedResource, ChatAgentLocation.Chat, CancellationToken.None);
ref?.dispose();
// Prefetch the chat session content to make the subsequent editor swap quick
const newSession = await this._chatSessionsService.getOrCreateChatSession(
URI.revive(modifiedResource),
CancellationToken.None,
);
if (originalEditor) {
newSession.transferredState = originalEditor instanceof ChatEditorInput
? { editingSession: originalEditor.transferOutEditingSession(), inputState: originalModel?.object.inputModel.toJSON() }
: undefined;
await this._editorService.replaceEditors([{
editor: originalEditor,
replacement: {
resource: modifiedResource,
options,
},
}], originalGroup);
return;
}
// If chat editor is in the side panel, then those are not listed as editors.
// In that case we need to transfer editing session using the original model.
if (originalModel) {
newSession.transferredState = {
editingSession: originalModel.object.editingSession,
inputState: originalModel.object.inputModel.toJSON()
};
}
const chatViewWidget = this._chatWidgetService.getWidgetBySessionResource(originalResource);
if (chatViewWidget && isIChatViewViewContext(chatViewWidget.viewContext)) {
await this._chatWidgetService.openSession(modifiedResource, ChatViewPaneTarget, { preserveFocus: true });
} else {
// Loading the session to ensure the session is created and editing session is transferred.
const ref = await this._chatService.loadSessionForResource(modifiedResource, ChatAgentLocation.Chat, CancellationToken.None);
ref?.dispose();
}
} finally {
originalModel?.dispose();
}
}