Skip to content

sessions: fix: guard chat grid neighbor lookup before layout - #331617

Merged
Ulugbek Abdullaev (ulugbekna) merged 3 commits into
microsoft:mainfrom
ulugbekna:ulugbekna/agents/insiders-agents-window-chat-focus-bug
Aug 19, 2026
Merged

sessions: fix: guard chat grid neighbor lookup before layout#331617
Ulugbek Abdullaev (ulugbekna) merged 3 commits into
microsoft:mainfrom
ulugbekna:ulugbekna/agents/insiders-agents-window-chat-focus-bug

Conversation

@ulugbekna

@ulugbekna Ulugbek Abdullaev (ulugbekna) commented Aug 19, 2026

Copy link
Copy Markdown
Contributor

Fixes #331616

What changed

This change tracks whether the current Agents window session grid has completed its first layout. Reconciliation uses logical group order until geometric neighbor queries are safe.

It also adds a regression test for opening and focusing a session whose active chat is a child chat with a parentChat.

User-visible failure

Opening an affected session could leave the chat area partially initialized:

  • The main chat tab was visible.
  • No tab was active.
  • The active child chat tab was missing.
  • The Start a parallel conversation composer was rendered and focused.

Clicking the visible main tab repaired the view and caused the remaining chat tab to appear.

Root cause

ChatGroupsView.setSession previously created and attached a new SerializableGrid, installed an autorun that synchronously invoked _reconcile, and only then called _applyLayout.

When the outer ChatGroupsView had already been laid out and the session's active chat had a parentChat, reconciliation attempted to place the child beside its parent. _findAdjacentGroup called SerializableGrid.getNeighborViews, but the new grid had not received its first layout() call and threw:

Can't call getNeighborViews before first layout

The main chat had already been assigned before the exception. Since those observable writes were not rolled back, the UI retained the main tab while failing to assign or activate the child chat, producing the partial state above.

Why this fix

The current grid resets a _gridDidLayout flag when the session changes and sets it after layout() completes. _findAdjacentGroup only calls getNeighborViews once that flag is true; before then it uses its existing logical group-order fallback.

This retains the original reconcile-before-layout ordering, so the resolved chat view is laid out once and the transient parallel-conversation composer is not laid out before being replaced.

The change does not add exception handling or a focus-specific workaround.

Validation

  • Added a regression covering an already-laid-out view with an active child chat, including the replacement chat view's layout and document-scoped focus.
  • The regression records layout calls: one for the resolved chat and zero for the transient composer.
  • All 13 ChatGroupsView unit tests pass.
  • Targeted ESLint passes.
  • Client TypeScript type-check passes.
  • git diff --check passes.
  • Manual end-to-end verification on macOS against the fixed source build:
    • Created a session with a main chat and active parallel child chat, switched away, and reopened it.
    • Both tabs were present, the child was active and rendered, focus was inside its chat input, and the parallel-conversation composer was absent.
    • The renderer log contained no Can't call getNeighborViews before first layout error.

Apply the existing outer layout to a newly created session grid before synchronous reconciliation can query adjacent views. Add coverage for opening and focusing a session whose active chat is a child chat.

Fixes microsoft#331616

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: b53c514c-a525-410f-94bc-213bc6bdaaf1
@vs-code-engineering

Copy link
Copy Markdown
Contributor

📬 CODENOTIFY

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

Benjamin Christopher Simmonds (@benibenj)

Matched files:

  • src/vs/sessions/browser/parts/chatGroupsView.ts

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Warning

Copilot couldn't run its full agentic review because it didn't start before the timeout. Make sure your repository has a runner available, or add a copilot-code-review.yml file specifying one with the runs-on attribute. See the docs for more details.

This PR fixes a session-opening race where chat reconciliation ran before the session grid’s first layout, causing adjacent-view queries to throw and leaving the chat UI partially initialized when the active chat is a child chat.

Changes:

  • Call _applyLayout() before installing the synchronous reconciliation autorun to ensure the grid has performed its first layout.
  • Add a regression test that opens and focuses a session whose active chat is a child chat with a parentChat.
Show a summary per file
File Description
src/vs/sessions/browser/parts/chatGroupsView.ts Reorders layout vs. reconciliation setup to ensure grid layout invariants before adjacent-view queries.
src/vs/sessions/test/browser/chatGroupsView.test.ts Adds a regression test covering an already-laid-out view opening a session with an active child chat.

Review details

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

  • Files reviewed: 2/2 changed files
  • Comments generated: 2
  • Review effort level: Lite

Comment thread src/vs/sessions/browser/parts/chatGroupsView.ts
Comment thread src/vs/sessions/test/browser/chatGroupsView.test.ts
Assert that reconciliation lays out the replacement chat view and scope the focus check to the view owner document.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: b53c514c-a525-410f-94bc-213bc6bdaaf1
@ulugbekna

Ulugbek Abdullaev (ulugbekna) commented Aug 19, 2026

Copy link
Copy Markdown
Contributor Author

Manual E2E verification re-run on macOS against the performance-safe fixed source build (145d46d7af3):

  1. Created a session with a main chat and a committed parallel child chat.
  2. Left the child active, switched to another session, then reopened the child-active session from the Sessions list.
  3. Verified two chat tabs were present, the child tab had both the active class and aria-selected=true, and the child transcript was visible.
  4. Verified the parallel-conversation composer was absent.
  5. Verified document.activeElement was the native-edit-context inside the rendered child chat, and that focused view contained the child transcript.
  6. Confirmed the renderer log did not contain Can't call getNeighborViews before first layout.

This exercises the same session-switch path and active-child prerequisite as the original failure.

The focused regression additionally records layout calls: the resolved chat is laid out once and the transient parallel-composer view is laid out zero times.

Track layout for the current session grid so initial reconciliation uses logical group order until geometric neighbor queries are safe. Preserve reconcile-before-layout ordering and cover that the transient composer receives no layout calls.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: b53c514c-a525-410f-94bc-213bc6bdaaf1
@ulugbekna Ulugbek Abdullaev (ulugbekna) changed the title sessions: fix: lay out chat grid before reconciliation sessions: fix: guard chat grid neighbor lookup before layout Aug 19, 2026
@ulugbekna
Ulugbek Abdullaev (ulugbekna) merged commit 2c79ffb into microsoft:main Aug 19, 2026
27 checks passed
@vs-code-engineering vs-code-engineering Bot added this to the 1.135.0 milestone Aug 19, 2026
Dileep Yavanmandha (dileepyavan) pushed a commit that referenced this pull request Aug 19, 2026
* sessions: fix: lay out chat grid before reconciliation

Apply the existing outer layout to a newly created session grid before synchronous reconciliation can query adjacent views. Add coverage for opening and focusing a session whose active chat is a child chat.

Fixes #331616

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: b53c514c-a525-410f-94bc-213bc6bdaaf1

* sessions: test: verify active child layout and focus

Assert that reconciliation lays out the replacement chat view and scope the focus check to the view owner document.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: b53c514c-a525-410f-94bc-213bc6bdaaf1

* sessions: fix: guard chat grid neighbor lookup before layout

Track layout for the current session grid so initial reconciliation uses logical group order until geometric neighbor queries are safe. Preserve reconcile-before-layout ordering and cover that the transient composer receives no layout calls.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: b53c514c-a525-410f-94bc-213bc6bdaaf1

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: b53c514c-a525-410f-94bc-213bc6bdaaf1
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Agents window opens the parallel conversation composer instead of the active child chat

3 participants