Skip to content

Conversation

@osortega
Copy link
Contributor

No description provided.

Copilot AI review requested due to automatic review settings November 27, 2025 00:33
@osortega osortega self-assigned this Nov 27, 2025
@vs-code-engineering
Copy link

vs-code-engineering bot commented Nov 27, 2025

📬 CODENOTIFY

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

@bpasero

Matched files:

  • src/vs/workbench/contrib/chat/browser/agentSessions/localAgentSessionsProvider.ts
  • src/vs/workbench/contrib/chat/browser/chatSessions/chatSessionTracker.ts
  • src/vs/workbench/contrib/chat/browser/chatSessions/view/chatSessionsView.ts
  • src/vs/workbench/contrib/chat/browser/chatSessions/view/sessionsTreeRenderer.ts
  • src/vs/workbench/contrib/chat/browser/chatSessions/view/sessionsViewPane.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 removes the ChatSessionTracker class and refactors session change tracking to be centralized in ChatSessionsService. The tracker previously monitored editor groups and local chat sessions, emitting change events. This functionality is now handled by registering model progress listeners directly in the ChatSessionsService constructor via an autorun that watches chat models.

Key changes:

  • Centralized model progress listener registration in ChatSessionsService using autorun
  • Removed ChatSessionTracker class and its usage throughout the codebase
  • Simplified LocalAgentsSessionsProvider by removing local event listening logic
  • Updated SessionsDataSource to no longer integrate hybrid sessions

Reviewed changes

Copilot reviewed 9 out of 9 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
src/vs/workbench/contrib/chat/browser/chatSessions/chatSessionTracker.ts Deleted the entire ChatSessionTracker class
src/vs/workbench/contrib/chat/browser/chatSessions.contribution.ts Added autorun to register model progress listeners; refactored registerModelProgressListener to accept models iterable instead of individual model
src/vs/workbench/contrib/chat/browser/chatSessions/view/chatSessionsView.ts Removed ChatSessionTracker instantiation and usage
src/vs/workbench/contrib/chat/browser/chatSessions/view/sessionsViewPane.ts Removed ChatSessionTracker parameter and LocalAgentsSessionsProvider-specific event listener
src/vs/workbench/contrib/chat/browser/chatSessions/view/sessionsTreeRenderer.ts Removed ChatSessionTracker parameter and hybrid session integration logic
src/vs/workbench/contrib/chat/browser/agentSessions/localAgentSessionsProvider.ts Removed local model listener registration logic
src/vs/workbench/contrib/chat/common/chatSessionsService.ts Updated interface signature for registerModelProgressListener
src/vs/workbench/contrib/chat/test/common/mockChatSessionsService.ts Updated mock implementation signature
src/vs/workbench/contrib/chat/test/browser/localAgentSessionsProvider.test.ts Removed tests for the deleted event handling functionality

@dmitrivMS
Copy link
Contributor

Copilot seems to have good points, and CI is red...

osortega and others added 3 commits November 26, 2025 18:40
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
DonJayamanne
DonJayamanne previously approved these changes Dec 1, 2025
DonJayamanne
DonJayamanne previously approved these changes Dec 2, 2025
Copy link
Member

@roblourens roblourens left a comment

Choose a reason for hiding this comment

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

Should there also be a change in LocalAgentsSessionsProvider for it to just watch local models?

meganrogge
meganrogge previously approved these changes Dec 2, 2025
@meganrogge
Copy link
Contributor

@osortega CI failing

Yoyokrazy
Yoyokrazy previously approved these changes Dec 2, 2025
@Yoyokrazy Yoyokrazy dismissed their stale review December 2, 2025 22:34

missed the changes requested from rob

disposables.add(autorun(reader => {
const models = this._chatService.chatModels.read(reader);
const onProgress = this._chatSessionsService.registerModelProgressListener(Array.from(models), chatSessionType);
disposables.add(onProgress(() => {
Copy link
Member

Choose a reason for hiding this comment

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

You are re-adding a new event listener every time the autorun runs - I don't think that what you want, the listeners will accumulate over time

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Good catch, fixed it

Copy link
Member

@roblourens roblourens Dec 3, 2025

Choose a reason for hiding this comment

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

I think this is still an issue? It's adding a new disposable on every autorun iteration and they accumulate over time

@osortega osortega requested a review from roblourens December 3, 2025 00:32
@osortega osortega enabled auto-merge (squash) December 3, 2025 00:45
Copy link
Member

@roblourens roblourens left a comment

Choose a reason for hiding this comment

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

Does this fix a bug or is it just code cleanup?

}
this._registeredModels.add(model);
public registerModelProgressListener(models: IChatModel[], type: string): Event<void> {
const changeEmitter = this._register(new Emitter<void>());
Copy link
Member

Choose a reason for hiding this comment

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

This is still very funky overall to me. Someone can call the service and create disposables that stick around forever and have no way to be disposed. They should be owned by the calling method. We can merge it as long as it's not leaking but we just still need to revisit this for next month.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@roblourens we can collect all disposables and return it to the caller but does that mean that the caller needs to listen to onDispose for each model and know when to dispose the model specific disposables?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I think I understand what you meant, pushed a fix so that the caller has access to the disposables.
The function also adds disposables that listens to the disposae event of each model

for (const model of models) {
if (model.sessionResource.scheme === type && !this._registeredModels.has(model)) {
this._registeredModels.add(model);
const modelDisposables = this._register(new DisposableStore());
Copy link
Member

Choose a reason for hiding this comment

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

We can't register modelDisposables on the class if it has an independent lifecycle (which it does because it tracks the model and you clear it below). Doing this creates a memory leak because the reference to the DisposableStore and everything it touches will be retained by the ChatSessionsService forever.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Changed it so that it returns the disposable store to the caller

@osortega osortega requested a review from roblourens December 3, 2025 03:56
Copy link
Member

@connor4312 connor4312 left a comment

Choose a reason for hiding this comment

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

some code-level things you probably want to fix

// Use autorun to listen for state changes
this._register(autorunSelfDisposable(reader => {
const state = toolInvocation.state.read(reader);
const listeners = new ResourceMap<IDisposable>();
Copy link
Member

Choose a reason for hiding this comment

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

I think we actually want to return a DisposableStore containing both the autorunIterableDelta and something like

store.add(toDisposable(() => {
  for (const listener of listeners) { listener.dispose(); }
}));

otherwise they might get orphaned

connor4312
connor4312 previously approved these changes Dec 4, 2025
@osortega osortega dismissed roblourens’s stale review December 4, 2025 01:10

Comments addressed and already approved

rebornix
rebornix previously approved these changes Dec 4, 2025
@osortega osortega merged commit de38b37 into main Dec 4, 2025
28 checks passed
@osortega osortega deleted the osortega/remove-chat-session-tracker branch December 4, 2025 01:59
@vs-code-engineering vs-code-engineering bot locked and limited conversation to collaborators Jan 20, 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.

10 participants