Skip to content

chat: make creation of the edit session sync#277924

Merged
connor4312 merged 1 commit intomainfrom
connor4312/rm-async-edit-session
Nov 17, 2025
Merged

chat: make creation of the edit session sync#277924
connor4312 merged 1 commit intomainfrom
connor4312/rm-async-edit-session

Conversation

@connor4312
Copy link
Member

Uses the session state to wait in cases where it's needed

Refs #277318

Uses the session state to wait in cases where it's needed

Refs #277318
Copilot AI review requested due to automatic review settings November 17, 2025 18:52
@connor4312 connor4312 enabled auto-merge (squash) November 17, 2025 18:52
@connor4312 connor4312 self-assigned this Nov 17, 2025
@vs-code-engineering
Copy link

📬 CODENOTIFY

The following users are being notified based on files changed in this PR:

@jrieken

Matched files:

  • src/vs/workbench/contrib/chat/browser/chatEditing/chatEditingServiceImpl.ts
  • src/vs/workbench/contrib/chat/browser/chatEditing/chatEditingSession.ts
  • src/vs/workbench/contrib/inlineChat/browser/inlineChatController.ts
  • src/vs/workbench/contrib/inlineChat/browser/inlineChatSessionServiceImpl.ts

@bpasero

Matched files:

  • src/vs/workbench/contrib/chat/browser/chatWidget.ts

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR refactors the chat editing session creation from asynchronous to synchronous, using the session's state observable to wait for initialization where needed. The change simplifies the codebase by removing ObservablePromise wrappers and async method signatures throughout the editing service chain.

Key changes:

  • Made IChatEditingService methods synchronous (removed async/Promise returns)
  • Moved session initialization from async init() method to constructor parameter and private _init()
  • Introduced chatEditingSessionIsReady() helper to wait for session state to transition from Initial
  • Updated all usage sites to access editingSession directly instead of awaiting editingSessionObs?.promise

Reviewed Changes

Copilot reviewed 11 out of 11 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
chatEditingService.ts Changed interface methods to synchronous, added chatEditingSessionIsReady() helper function
chatModel.ts Removed ObservablePromise wrapper, changed editingSession to direct property, made startEditingSession() synchronous
chatEditingServiceImpl.ts Removed async methods, removed _restoringEditingSession field, made session creation synchronous
chatEditingSession.ts Moved init() to private _init() called from constructor, added transferFrom constructor parameter, made entries observable state-aware
inlineChatSessionServiceImpl.ts Updated to use direct editingSession property with null-safe access
inlineChatController.ts Removed awaits on editingSessionObs?.promise, updated to use direct editingSession
chatWidget.ts Updated to use chatEditingSessionIsReady() helper when waiting for session
chatMarkdownContentPart.ts Simplified observable logic, removed nested observables
chatChangesSummaryPart.ts Removed nested promise result checks, simplified to direct session access
chatService.test.ts Updated mock to return synchronous session
chatEditingService.test.ts Removed awaits on session creation, updated to use direct editingSession property

Comment on lines +180 to +186
autorunSelfDisposable(reader => {
const state = session.state.read(reader);
if (state !== ChatEditingSessionState.Initial) {
reader.dispose();
resolve();
}
});
Copy link

Copilot AI Nov 17, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The autorunSelfDisposable is never cleaned up if the session is disposed while still in Initial state, leading to a potential memory leak. Consider checking if the session is disposed or handling the onDidDispose event to reject/resolve the promise.

Suggested change
autorunSelfDisposable(reader => {
const state = session.state.read(reader);
if (state !== ChatEditingSessionState.Initial) {
reader.dispose();
resolve();
}
});
let resolved = false;
const autorunDisposable = autorunSelfDisposable(reader => {
const state = session.state.read(reader);
if (state !== ChatEditingSessionState.Initial) {
if (!resolved) {
resolved = true;
reader.dispose();
autorunDisposable.dispose();
if (sessionDisposable) {
sessionDisposable.dispose();
}
resolve();
}
}
});
// Listen for session disposal if possible
let sessionDisposable: IDisposable | undefined;
if ('onDidDispose' in session && typeof (session as any).onDidDispose === 'function') {
sessionDisposable = (session as any).onDidDispose(() => {
if (!resolved) {
resolved = true;
autorunDisposable.dispose();
resolve();
}
});
}

Copilot uses AI. Check for mistakes.
initialPosition: editor.getSelection().getStartPosition().delta(-1), /* one line above selection start */
chatModel,
editingSession,
editingSession: chatModel.editingSession!,
Copy link

Copilot AI Nov 17, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Non-null assertion on chatModel.editingSession is unsafe. The chat model doesn't start an editing session automatically; it requires calling startEditingSession() first. This will throw at runtime if editingSession is undefined. Either add a call to chatModel.startEditingSession() before this line or handle the case where it might be undefined.

Copilot uses AI. Check for mistakes.
Comment on lines +150 to +157
public readonly entries: IObservable<readonly IModifiedFileEntry[]> = derived(reader => {
const state = this._state.read(reader);
if (state === ChatEditingSessionState.Disposed || state === ChatEditingSessionState.Initial) {
return [];
} else {
return this._entriesObs.read(reader);
}
});
Copy link

Copilot AI Nov 17, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The entries observable returns an empty array during the Initial state, which means consumers cannot observe entries until initialization completes. This could cause issues if entries are accessed before _init() finishes. Consider documenting this behavior or ensuring consumers use chatEditingSessionIsReady() before accessing entries.

Copilot uses AI. Check for mistakes.
@connor4312 connor4312 merged commit c744395 into main Nov 17, 2025
33 of 34 checks passed
@connor4312 connor4312 deleted the connor4312/rm-async-edit-session branch November 17, 2025 19:17
@connor4312 connor4312 mentioned this pull request Nov 17, 2025
21 tasks
pwang347 pushed a commit that referenced this pull request Nov 18, 2025
Uses the session state to wait in cases where it's needed

Refs #277318
@vs-code-engineering vs-code-engineering bot locked and limited conversation to collaborators Jan 1, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants