agent host: eagerly create sessions when a folder is picked (#313841)
* agent host: eagerly create sessions when a folder is picked
Previously the agent-host backend session was only created when the user
sent their first message. Move creation up to folder-pick time so the
new-chat view interacts with a real session URI throughout: model
selections, session-config picks, etc. all dispatch against a known
session, and the chat handler avoids a duplicate createSession round-trip
on the user's first send.
This is particularly in advance of support for completions, which necessarily
are derived in the context of a workspace, agent customizations, etc. While
the work for these new 'provisional sessions' is trending towards gnarly
internally, the protocol is kept pretty clean with the only change being
semantic guidance that sessions with no messages should be garbage collected.
To make eager creation cheap, sessions are ephemeral in the agent
until the first message lands — no SDK session, no worktree, no on-disk
metadata. Materialization happens inside `sendMessage` and fires
`onDidMaterializeSession`, at which point the agent service emits the
deferred `notify/sessionAdded` and transitions lifecycle to `Ready`.
Switching workspaces or closing the new-chat view disposes the
provisional record (`disposeSession` over the wire); a 30s server-side
empty-session GC backstops crashes and dropped disconnects.
The new-session bookkeeping in the sessions provider previously lived
across 11 loose `_currentNewSession*` fields and 4 keyed-by-sessionId
maps. Bundle them into a single `NewSession` class held as a
`MutableDisposable` — assigning a new value automatically tears down
the previous one (subscription release + disposeSession RPC).
Subtle wire-ordering note: `NewSession.eagerCreate` awaits
`createSession` *before* opening the state subscription. Reversing the
order races the wire — the server sees `subscribe` for an unknown
session, returns `AHP_SESSION_NOT_FOUND`, and the client subscription
enters an unrecoverable error state. New unit tests pin the ordering
and the bail-out behaviour for workspace-switch-mid-flight.
---
Architecture (provisional → real session):
```mermaid
sequenceDiagram
participant U as User
participant SP as SessionsProvider
participant H as ChatHandler
participant A as Agent (CopilotAgent)
participant S as StateManager
U->>SP: pick folder
SP->>A: createSession(uri)
A->>S: createSession(emitNotification=false)
Note over A: provisional record<br/>(no SDK, no worktree, no DB)
SP-->>U: session.resource
U->>SP: pick model / config (optional)
SP->>A: SessionModelChanged / SessionConfigChanged
Note over A: updates provisional record
U->>H: send first message
H->>A: sendMessage()
A->>A: _materializeProvisional<br/>(create worktree,<br/> SDK session, persist DB)
A->>S: onDidMaterializeSession
S-->>U: notify/sessionAdded
S->>S: SessionReady
U-)SP: switch workspace
SP->>A: disposeSession (old uri)
Note over A: drops provisional record<br/>cancels worktree creation
```
* review C
Connor Peet committed
8309b22051c226cca9c3485fd282e93df6339eca
Parent: 96e4e9e
Committed by GitHub <noreply@github.com>
on 5/2/2026, 3:29:53 AM