Skip to content
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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 11 additions & 12 deletions src/vs/workbench/contrib/chat/browser/actions/chatExecuteActions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import { KeybindingWeight } from '../../../../../platform/keybinding/common/keyb
import { IViewsService } from '../../../../services/views/common/viewsService.js';
import { IChatAgentService } from '../../common/chatAgents.js';
import { ChatContextKeyExprs, ChatContextKeys } from '../../common/chatContextKeys.js';
import { IChatEditingService, IChatEditingSession, WorkingSetEntryState } from '../../common/chatEditingService.js';
import { WorkingSetEntryState } from '../../common/chatEditingService.js';
import { chatVariableLeader } from '../../common/chatParserTypes.js';
import { IChatService } from '../../common/chatService.js';
import { ChatAgentLocation, ChatConfiguration, ChatMode } from '../../common/constants.js';
Expand Down Expand Up @@ -492,8 +492,14 @@ class SendToChatEditingAction extends Action2 {

const viewsService = accessor.get(IViewsService);
const dialogService = accessor.get(IDialogService);
const chatEditingService = accessor.get(IChatEditingService);
const currentEditingSession: IChatEditingSession | undefined = chatEditingService.editingSessionsObs.get().at(0);
const { widget: editingWidget } = await viewsService.openView(EditsViewId) as ChatViewPane;
if (!editingWidget.viewModel?.sessionId) {
return;
}
const currentEditingSession = editingWidget.viewModel.model.editingSession;
if (!currentEditingSession) {
return;
}

const currentEditCount = currentEditingSession?.entries.get().length;
if (currentEditCount) {
Expand All @@ -510,17 +516,10 @@ class SendToChatEditingAction extends Action2 {
return;
}

await currentEditingSession?.stop();
await currentEditingSession.stop(true);
editingWidget.clear();
}

const { widget: editingWidget } = await viewsService.openView(EditsViewId) as ChatViewPane;
if (!editingWidget.viewModel?.sessionId) {
return;
}
const chatEditingSession = editingWidget.viewModel.model.editingSession;
if (!chatEditingSession) {
return;
}
for (const attachment of widget.attachmentModel.attachments) {
editingWidget.attachmentModel.addContext(attachment);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -604,11 +604,6 @@ export class ChatEditingSession extends Disposable implements IChatEditingSessio
}
});
}));

if (this._state.get() !== ChatEditingSessionState.Disposed) {
// session got disposed while we were closing editors and clearing state
this.dispose();
}
}

override dispose() {
Expand Down
17 changes: 9 additions & 8 deletions src/vs/workbench/contrib/chat/common/chatModel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ import { IOffsetRange, OffsetRange } from '../../../../editor/common/core/offset
import { IRange } from '../../../../editor/common/core/range.js';
import { Location, SymbolKind, TextEdit } from '../../../../editor/common/languages.js';
import { localize } from '../../../../nls.js';
import { IConfigurationService } from '../../../../platform/configuration/common/configuration.js';
import { ILogService } from '../../../../platform/log/common/log.js';
import { IMarker, MarkerSeverity } from '../../../../platform/markers/common/markers.js';
import { CellUri, ICellEditOperation } from '../../notebook/common/notebookCommon.js';
Expand All @@ -30,7 +29,7 @@ import { IChatEditingService, IChatEditingSession } from './chatEditingService.j
import { ChatRequestTextPart, IParsedChatRequest, reviveParsedChatRequest } from './chatParserTypes.js';
import { ChatAgentVoteDirection, ChatAgentVoteDownReason, IChatAgentMarkdownContentWithVulnerability, IChatCodeCitation, IChatCommandButton, IChatConfirmation, IChatContentInlineReference, IChatContentReference, IChatFollowup, IChatLocationData, IChatMarkdownContent, IChatNotebookEdit, IChatProgress, IChatProgressMessage, IChatResponseCodeblockUriPart, IChatResponseProgressFileTreeData, IChatTask, IChatTextEdit, IChatToolInvocation, IChatToolInvocationSerialized, IChatTreeData, IChatUndoStop, IChatUsedContext, IChatWarningMessage, isIUsedContext } from './chatService.js';
import { IChatRequestVariableValue } from './chatVariables.js';
import { ChatAgentLocation, ChatConfiguration } from './constants.js';
import { ChatAgentLocation } from './constants.js';

export interface IBaseChatRequestVariableEntry {
id: string;
Expand Down Expand Up @@ -1317,8 +1316,7 @@ export class ChatModel extends Disposable implements IChatModel {
private readonly _initialLocation: ChatAgentLocation,
@ILogService private readonly logService: ILogService,
@IChatAgentService private readonly chatAgentService: IChatAgentService,
@IChatEditingService chatEditingService: IChatEditingService,
@IConfigurationService configurationService: IConfigurationService,
@IChatEditingService private readonly chatEditingService: IChatEditingService,
) {
super();

Expand All @@ -1336,11 +1334,14 @@ export class ChatModel extends Disposable implements IChatModel {

this._initialRequesterAvatarIconUri = initialData?.requesterAvatarIconUri && URI.revive(initialData.requesterAvatarIconUri);
this._initialResponderAvatarIconUri = isUriComponents(initialData?.responderAvatarIconUri) ? URI.revive(initialData.responderAvatarIconUri) : initialData?.responderAvatarIconUri;
}

if (this._initialLocation === ChatAgentLocation.EditingSession || (configurationService.getValue(ChatConfiguration.UnifiedChatView) && this._initialLocation === ChatAgentLocation.Panel)) {
this._editingSession = new ObservablePromise(chatEditingService.startOrContinueGlobalEditingSession(this));
this._editingSession.promise.then(editingSession => this._register(editingSession));
}
startEditingSession(isGlobalEditingSession?: boolean): void {
const editingSessionPromise = isGlobalEditingSession ?
this.chatEditingService.startOrContinueGlobalEditingSession(this) :
this.chatEditingService.createEditingSession(this);
this._editingSession = new ObservablePromise(editingSessionPromise);
this._editingSession.promise.then(editingSession => this._store.isDisposed ? editingSession.dispose() : this._register(editingSession));
}

private _deserialize(obj: IExportableChatData): ChatRequestModel[] {
Expand Down
2 changes: 1 addition & 1 deletion src/vs/workbench/contrib/chat/common/chatService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -491,7 +491,7 @@ export interface IChatService {

isEnabled(location: ChatAgentLocation): boolean;
hasSessions(): boolean;
startSession(location: ChatAgentLocation, token: CancellationToken): ChatModel;
startSession(location: ChatAgentLocation, token: CancellationToken, isGlobalEditingSession?: boolean): ChatModel;
getSession(sessionId: string): IChatModel | undefined;
getOrRestoreSession(sessionId: string): Promise<IChatModel | undefined>;
isPersistedSessionEmpty(sessionId: string): boolean;
Expand Down
14 changes: 9 additions & 5 deletions src/vs/workbench/contrib/chat/common/chatServiceImpl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -469,13 +469,17 @@ export class ChatService extends Disposable implements IChatService {
this.saveState();
}

startSession(location: ChatAgentLocation, token: CancellationToken): ChatModel {
startSession(location: ChatAgentLocation, token: CancellationToken, isGlobalEditingSession: boolean = true): ChatModel {
this.trace('startSession');
return this._startSession(undefined, location, token);
return this._startSession(undefined, location, isGlobalEditingSession, token);
}

private _startSession(someSessionHistory: IExportableChatData | ISerializableChatData | undefined, location: ChatAgentLocation, token: CancellationToken): ChatModel {
private _startSession(someSessionHistory: IExportableChatData | ISerializableChatData | undefined, location: ChatAgentLocation, isGlobalEditingSession: boolean, token: CancellationToken): ChatModel {
const model = this.instantiationService.createInstance(ChatModel, someSessionHistory, location);
if (location === ChatAgentLocation.EditingSession || (this.unifiedViewEnabled && location === ChatAgentLocation.Panel)) {
model.startEditingSession(isGlobalEditingSession);
}

this._sessionModels.set(model.sessionId, model);
this.initializeSession(model, token);
return model;
Expand Down Expand Up @@ -528,7 +532,7 @@ export class ChatService extends Disposable implements IChatService {
return undefined;
}

const session = this._startSession(sessionData, sessionData.initialLocation ?? ChatAgentLocation.Panel, CancellationToken.None);
const session = this._startSession(sessionData, sessionData.initialLocation ?? ChatAgentLocation.Panel, true, CancellationToken.None);

const isTransferred = this.transferredSessionData?.sessionId === sessionId;
if (isTransferred) {
Expand All @@ -553,7 +557,7 @@ export class ChatService extends Disposable implements IChatService {
}

loadSessionFromContent(data: IExportableChatData | ISerializableChatData): IChatModel | undefined {
return this._startSession(data, data.initialLocation ?? ChatAgentLocation.Panel, CancellationToken.None);
return this._startSession(data, data.initialLocation ?? ChatAgentLocation.Panel, true, CancellationToken.None);
}

async resendRequest(request: IChatRequestModel, options?: IChatSendRequestOptions): Promise<void> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,10 @@ suite('ChatEditingService', function () {
const uri = URI.from({ scheme: 'test', path: 'HelloWorld' });

const model = chatService.startSession(ChatAgentLocation.EditingSession, CancellationToken.None);
const session = await editingService.createEditingSession(model, true);
const session = await model.editingSessionObs?.promise;
if (!session) {
assert.fail('session not created');
}

const chatRequest = model?.addRequest({ text: '', parts: [] }, { variables: [] }, 0);
assertType(chatRequest.response);
Expand All @@ -159,7 +162,6 @@ suite('ChatEditingService', function () {

await entry.reject(undefined);

session.dispose();
model.dispose();
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1422,7 +1422,7 @@ export async function reviewEdits(accessor: ServicesAccessor, editor: ICodeEdito
const chatEditingService = accessor.get(IChatEditingService);

const uri = editor.getModel().uri;
const chatModel = chatService.startSession(ChatAgentLocation.Editor, token);
const chatModel = chatService.startSession(ChatAgentLocation.Editor, token, false);

const editSession = await chatEditingService.createEditingSession(chatModel);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,16 @@
import { CancellationToken } from '../../../../base/common/cancellation.js';
import { Emitter, Event } from '../../../../base/common/event.js';
import { DisposableStore, IDisposable, MutableDisposable, toDisposable } from '../../../../base/common/lifecycle.js';
import { ResourceMap } from '../../../../base/common/map.js';
import { Schemas } from '../../../../base/common/network.js';
import { autorun } from '../../../../base/common/observable.js';
import { isEqual } from '../../../../base/common/resources.js';
import { assertType } from '../../../../base/common/types.js';
import { URI } from '../../../../base/common/uri.js';
import { generateUuid } from '../../../../base/common/uuid.js';
import { IActiveCodeEditor, ICodeEditor, isCodeEditor, isCompositeEditor, isDiffEditor } from '../../../../editor/browser/editorBrowser.js';
import { Range } from '../../../../editor/common/core/range.js';
import { ILanguageService } from '../../../../editor/common/languages/language.js';
import { IValidEditOperation } from '../../../../editor/common/model.js';
import { createTextBufferFactoryFromSnapshot } from '../../../../editor/common/model/textModel.js';
import { IEditorWorkerService } from '../../../../editor/common/services/editorWorker.js';
Expand All @@ -20,22 +25,17 @@ import { IInstantiationService } from '../../../../platform/instantiation/common
import { ILogService } from '../../../../platform/log/common/log.js';
import { ITelemetryService } from '../../../../platform/telemetry/common/telemetry.js';
import { DEFAULT_EDITOR_ASSOCIATION } from '../../../common/editor.js';
import { IEditorService } from '../../../services/editor/common/editorService.js';
import { ITextFileService } from '../../../services/textfile/common/textfiles.js';
import { UntitledTextEditorInput } from '../../../services/untitled/common/untitledTextEditorInput.js';
import { IChatWidgetService } from '../../chat/browser/chat.js';
import { IChatAgentService } from '../../chat/common/chatAgents.js';
import { WorkingSetEntryState } from '../../chat/common/chatEditingService.js';
import { IChatService } from '../../chat/common/chatService.js';
import { ChatAgentLocation } from '../../chat/common/constants.js';
import { CTX_INLINE_CHAT_HAS_AGENT, CTX_INLINE_CHAT_HAS_AGENT2, CTX_INLINE_CHAT_POSSIBLE } from '../common/inlineChat.js';
import { IEditorService } from '../../../services/editor/common/editorService.js';
import { UntitledTextEditorInput } from '../../../services/untitled/common/untitledTextEditorInput.js';
import { HunkData, Session, SessionWholeRange, StashedSession, TelemetryData, TelemetryDataClassification } from './inlineChatSession.js';
import { IInlineChatSession2, IInlineChatSessionEndEvent, IInlineChatSessionEvent, IInlineChatSessionService, ISessionKeyComputer } from './inlineChatSessionService.js';
import { isEqual } from '../../../../base/common/resources.js';
import { ILanguageService } from '../../../../editor/common/languages/language.js';
import { ITextFileService } from '../../../services/textfile/common/textfiles.js';
import { IChatEditingService, WorkingSetEntryState } from '../../chat/common/chatEditingService.js';
import { assertType } from '../../../../base/common/types.js';
import { autorun } from '../../../../base/common/observable.js';
import { ResourceMap } from '../../../../base/common/map.js';
import { IChatWidgetService } from '../../chat/browser/chat.js';
import { ChatAgentLocation } from '../../chat/common/constants.js';


type SessionData = {
Expand Down Expand Up @@ -86,7 +86,6 @@ export class InlineChatSessionServiceImpl implements IInlineChatSessionService {
@ILanguageService private readonly _languageService: ILanguageService,
@IChatService private readonly _chatService: IChatService,
@IChatAgentService private readonly _chatAgentService: IChatAgentService,
@IChatEditingService private readonly _chatEditingService: IChatEditingService,
@IChatWidgetService private readonly _chatWidgetService: IChatWidgetService,
) { }

Expand Down Expand Up @@ -338,9 +337,9 @@ export class InlineChatSessionServiceImpl implements IInlineChatSessionService {

this._onWillStartSession.fire(editor as IActiveCodeEditor);

const chatModel = this._chatService.startSession(ChatAgentLocation.EditingSession, token);
const chatModel = this._chatService.startSession(ChatAgentLocation.EditingSession, token, false);

const editingSession = await this._chatEditingService.createEditingSession(chatModel);
const editingSession = await chatModel.editingSessionObs?.promise!;
const widget = this._chatWidgetService.getWidgetBySessionId(chatModel.sessionId);
widget?.attachmentModel.addFile(uri);

Expand All @@ -351,7 +350,6 @@ export class InlineChatSessionServiceImpl implements IInlineChatSessionService {
this._sessions2.delete(uri);
this._onDidChangeSessions.fire(this);
}));
store.add(editingSession);
store.add(chatModel);

store.add(autorun(r => {
Expand Down
Loading