Skip to content

agentHost: detach an archived chat's folders from its session - #341782

Merged
Sandeep Somavarapu (sandy081) merged 4 commits into
mainfrom
sandy081/agents/archiving-a-chat-should-unattach-the-chat-s
Oct 15, 2026
Merged

Sandeep Somavarapu (sandy081) merged 4 commits into
mainfrom
sandy081/agents/archiving-a-chat-should-unattach-the-chat-s

Conversation

@sandy081

Copy link
Copy Markdown
Member

Archiving a chat now detaches its folders from the session's aggregate workspace, and unarchiving the chat attaches them back.

What changed

  • Agent host (ChatArchiveContribution → AgentService.setArchivedChatWorkspaceAttached): when a chat's archived state changes, its folders are removed from or re-added to the session workspace, and the result is persisted.
    • A folder stays attached when it is the session's primary folder or another unarchived chat uses it, including a chat that inherits the complete session workspace.
    • The chat keeps its own folders. Worktrees are never deleted; worktree ownership and cleanup are based on the session's worktree records, not its folder list.
    • Restoring a session no longer re-adds folders of archived chats.
  • Agents window: new Developer: Update Session Folders with Chats action. It re-applies the archived state of archived chats in unarchived sessions so existing sessions, archived before this change, get their folders detached. Loading a session does not repair a folder that is in its persisted folder list.

Testing

  • Unit tests: agentService.test.ts covers archive/unarchive for a chat in another folder (primary is never detached), the repair path, and a chat in its own worktree (detached without deletion). chatContributions.test.ts covers the contribution calls.
  • ./scripts/test.sh for the affected src/vs/platform/agentHost/test/node suites: passed. npm run typecheck-client, npm run precommit (hygiene), npm run eslint on changed files, and npm run valid-layers-check: passed.
  • Live in an isolated Agents window (Copilot CLI provider):
    • Reproduced the bug with the previous build, then verified archive detaches and unarchive re-attaches with this change, for both a folder chat and a worktree chat (worktree remains on disk, a turn still runs in it after unarchive).
    • Verified the developer action repairs a session archived with the previous build.
    • No new errors or warnings in the agent host log during these steps.

Not covered

  • Claude and Codex providers were not exercised live; the code path is gated on the provider's multiple-working-directories capability.
  • Against an agent host without this change, the developer action reports success without changing anything.

Archiving a chat removes its folders from the aggregate session workspace and unarchiving attaches them back. Folders that are the session's primary or still used by another unarchived chat stay attached, and worktrees are never deleted. Restoring a session no longer re-adds archived chats' folders.

Adds a Developer: Update Session Folders with Chats action to repair sessions whose chats were archived before this change.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI balanced review requested due to automatic review settings October 15, 2026 14:15
@sandy081 Sandeep Somavarapu (sandy081) added this to the 1.143.0 milestone Oct 15, 2026
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

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.

🟡 Changes recommended

Unresolved workspace consistency issues affect concurrent chat creation, inherited folder restoration, and archived-chat details.

1 open finding
What changed in this PR

Updates Agent Host chat archiving to detach unused folders from the session workspace while retaining chat folders and worktrees.

Changes:

  • Detaches folders on archive and reattaches them on unarchive.
  • Adds a developer action to repair previously archived chats.
  • Adds archive/worktree tests and updates service stubs.
File Description
src/​vs/​sessions/​contrib/​sessions/​browser/​updateSessionFoldersAction.ts Adds the repair action.
src/​vs/​sessions/​contrib/​sessions/​browser/​sessions.contribution.ts Registers the action.
src/​vs/​platform/​agentHost/​test/​node/​chatContributions.test.ts Verifies workspace contribution calls.
src/​vs/​platform/​agentHost/​test/​node/​agentSideEffects.test.ts Registers the service stub.
src/​vs/​platform/​agentHost/​test/​node/​agentService.test.ts Tests detachment, reattachment, repair, and worktree preservation.
src/​vs/​platform/​agentHost/​test/​node/​agentHostTurnTelemetry.test.ts Registers the service stub.
src/​vs/​platform/​agentHost/​test/​node/​agentHostTurnHangTelemetry.test.ts Registers the service stub.
src/​vs/​platform/​agentHost/​test/​node/​agentHostToolCallTelemetry.test.ts Registers the service stub.
src/​vs/​platform/​agentHost/​node/​chatContributions/​chatArchive/​chatArchiveContribution.ts Triggers workspace updates on archive changes.
src/​vs/​platform/​agentHost/​node/​chatContributions/​chatArchive/​archivedChatWorkspaceService.ts Defines the workspace attachment service contract.
src/​vs/​platform/​agentHost/​node/​agentServiceComposition.ts Wires the service to AgentService.
src/​vs/​platform/​agentHost/​node/​agentService.ts Implements attachment changes, persistence, and restore filtering.

🧠 Review effort: Balanced


💡 Configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

…ached

An archived chat's folders are detached from the session workspace, so projecting the chat's scope onto the session workspace dropped its workspace and with it the folder, branch, and pull request details. Archived chats now resolve their detached folders on their own.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@rwoll

Copy link
Copy Markdown
Member

Heads-up Sandeep Somavarapu (@sandy081): the test archiving a peer chat in its own worktree detaches the worktree without deleting it failed in Windows Electron-Unit on #341682 after merging main. After unarchive, the session still reported only the primary folder rather than primary + peer worktree; the retained worktree record matched. This test hunk is unchanged by our PR.

The snapshot helper waits a fixed timeout(10) before reading the working-directory state, so an asynchronous reconciliation race is a plausible cause, not yet independently reproduced. An observable-state wait would avoid assuming reconciliation completes within 10 ms. Failure log: https://github.com/microsoft/vscode/actions/runs/38804564918/job/116662427645

Flagging separately from the panel fix, which passed in this run. No CI rerun was triggered.

🤖 Authored with GitHub Copilot on behalf of Ross Wollman (@rwoll).

Sandeep Somavarapu (sandy081) added a commit that referenced this pull request Oct 15, 2026
…#341882)

Archiving or unarchiving a peer chat updates the session workspace
asynchronously, one update at a time per session, and each update persists the
session's folders before the next starts. The tests from #341782 slept 10ms
instead of waiting for these updates, so when persisting the detached worktree
took longer, as on Windows CI, the unarchive had not attached it back yet.

Wait for the queued updates instead, and hold the archive's persistence while
unarchiving so the worktree test covers the slow case deterministically.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Sandeep Somavarapu (sandy081) added a commit that referenced this pull request Oct 21, 2026
… chats use (#343275)

* agentHost: skip git spawn for missing working directories

getRepositoryRoot spawned 'git rev-parse --show-toplevel' with cwd set to
the working directory even when that folder had been deleted. The resulting
'spawn git ENOENT' has empty stderr, so it was never negatively cached and
was re-probed and re-logged on every refresh.

Check that the directory exists before spawning git and return undefined
quietly without caching, so a worktree recreated at the same path is
picked up by the next lookup. A spawn ENOENT for a directory that vanished
after the check is handled the same way.

* agentHost: limit session changes to the folders of chats in use

The Branch summary computed and watched every folder any chat of a session
ever had, including archived chats and the folders subagents are pinned to
(often deleted worktrees). Each git-state refresh re-armed every one of
those owners through refreshBranchChangeset, which clears what is known
about an unavailable owner, so a session with many archived chats and
subagents kept recomputing and re-broadcasting changeset status.

Move the 'only chats in use count' rule (#341782, #341885) out of
AgentService into getChatsInUse and apply it to the Branch summary owners,
the summary working directories and the coordinator's branch summary
subscriptions. AgentService behavior is unchanged. The default chat is
always kept.

Also stop two ways a round restarts itself: do not dispatch a changeset
status that is already current, and do not recompute an owner whose
computation already ended in an error from the summary update; an explicit
refresh still retries it.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* agentHost: reconcile the branch summary when a chat is archived or unarchived

The branch summary subscribes to the folders of the chats in use only, but
nothing re-evaluated that set when a chat's archived state changed. Archiving
left the chat's changeset and file watcher subscribed, and unarchiving left it
unobserved until an unrelated refresh.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* agentHost: drop explanatory inline comments added with the missing-folder and in-use fixes

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* agentHost: name the missing-directory and spawn ENOENT checks for what they detect

Review feedback: _isDirectory returned true for stat failures other than ENOENT/ENOTDIR, and isSpawnNotFoundError also matched a missing working directory. Rename them to _isMissingDirectory (true only when the path is definitely not a directory) and isSpawnEnoentError. No behavior change.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
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.

4 participants