Connor Peet
90d · built 2026-09-08
Performance
What Connor Peet shipped in the selected window, measured in ETV, and how it compares with the 90 days before it.
Effective capacity
+5.1engineers
delivers like 6.1 (6.1x pre-AI)
Output (ETV)
105.6ETV
+89.3% vs 55.8 prior
Features share
32.7%
−12.7 pp vs prior window
Fixes share
21.6%
−0.6 pp vs prior window
Work mix
32.7% Features8.9% Maintenance35.7% Tests1.1% Docs21.6% Fixes
155 commits over 90 days, ending 2026-09-08.
Where this dev ranks
Percentile against the global top-100 leaderboard (all-time totals).
- By commits
- Top 30 %
- By Features share
- Top 33 %
Daily performance
Daily ETV, stacked by Features, Maintenance, Tests, Docs and Fixes.
Repository spread
Where this developer's commits land. Concentrated work (top1 > 80%) vs polymath spread (top1 < 30%).
Most impactful commits
Top 10 by ETV in the last 90 days.
- 4.6ETVtunnels: host the agent host with the code-tunnel CLI (#330480) * tunnels: host the agent host with the code-tunnel CLI Replaces the TypeScript dev-tunnels SDK hosting path with the `code-tunnel` binary, and gives the shared process a single owner for the tunnel process. The editor no longer creates, adopts, or reconciles dev tunnels itself: the CLI owns naming, reuse, and lifetime, and the editor supplies only intent. - Adds `--agent-host-only` to `code tunnel`, which serves the agent-host port without the control port, so remote session sharing does not also grant full remote editor access. - Adds `--delegate-to-editor`, which pins the selection gateway to the live editor agent host and stops it from starting a dedicated agent host. A dedicated host behind an editor-bound tunnel outlives the tunnel and cannot be reached. Clients that do not send `delegatedInstanceId`, which includes older editors and every background reconnect, get the bound host instead of an error. - Adds `--user-data-dir` to `code tunnel`. The gateway read the platform default registry, so it could not see the editor agent host in portable, custom, or development installations. - Adds a machine-readable status stream, enabled with `VSCODE_CLI_MACHINE_STATUS`, and removes the matching of human-readable output. The editor matched a string the CLI no longer prints, so Remote Tunnel Access never became connected. - Makes registry liveness require a reachable endpoint, not only a running process ID. Operating systems reuse process IDs, so a dead entry could look alive and be selected in preference to the live one. - Adds `TunnelProcessCoordinator`, which owns the single tunnel process, the tunnel name, and the CLI login. Both services previously started their own process with the same name, which made the CLI fall back to a random name, and both logged in to the same credential store. - Stops the editor from connecting to the tunnel that it hosts. - Raises the Windows stack size for development builds only. The default 1MB main thread stack overflows before `code tunnel` finishes starting. Fixes https://github.com/microsoft/vscode/issues/319297 Fixes https://github.com/microsoft/vscode/issues/329985 (Commit message generated by Copilot) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * cli: fix clippy lints and a registry read race on Windows CI runs `cargo clippy -- -D warnings` without `--all-targets`, so lib-only warnings fail the build. Fix the four it reported: - use `?` instead of a match in `get_tunnel_web_url` - drop a redundant rebinding of `delegate_to_editor` - group `serve()`'s agent-host parameters into `AgentHostServeOptions` - box both `GatewayTargetWs` variants (boxing only the larger one just inverts the imbalance) Separately, `read_registry` failed intermittently on Windows with `PermissionDenied`. A file removed by a concurrent prune stays listed in the directory until its last handle closes, and opening it in that window fails with `PermissionDenied` rather than the `NotFound` the code already handled. The error propagated out of `read_entry_file` and aborted the whole read, so one unreadable entry hid every other endpoint. Per-entry read and directory-enumeration failures are now logged and skipped instead. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * tunnels: address review feedback on CLI-hosted tunnels Four fixes from PR review: - Agent host sharing hard-rejected every non-GitHub request, but `remote.tunnels.access.enableMicrosoftAuth` still exposes Microsoft accounts and the renderer prefers them when enabled. Carry `authProvider` through to `tunnel user login` instead of hard-coding GitHub. - The pending service uninstall lived in one queued generation, so a concurrent sharing update could preempt the reconcile that owed it and leave the tunnel service installed. Persist it on the coordinator until an uninstall succeeds. - `getTunnelName()` is also called while access is inactive, to compare the name this machine would use against a previously used one. Returning the running tunnel's name yielded undefined and permanently skipped the remote-extension recommendation. Expose the coordinator's intended name. - Machine-status events were written straight to the emitting process's stdout, so when the editor attached to an existing tunnel the singleton server's token errors never reached it and token expiry was never surfaced. Events are now always generated, relayed to attached clients over a new singleton notification, and printed only where a process-global stdout toggle is set. Also converts a runtime protocol-version assertion added by this branch into a const assertion, which `clippy --all-targets` rejects as an assertion on a constant. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>github.com-microsoft-vscode · 3f5e8628 · 2026-08-12
- 3.7ETVagentHost: adopt AHP 1.0.0 breaking changes (#331999) * agentHost: adopt AHP 1.0.0 breaking changes Syncs the generated protocol types to AHP 1.0.0 and adopts the breaking changes in the agent host, the workbench chat session handler, and the Agents window provider. - Removes session-level forking. `CreateSessionParams.fork` and `SessionForkSource` no longer exist, so the fork configuration, its service plumbing, and the protocol forwarding are deleted. The editor-window Fork Conversation gesture now forks into a peer chat of the same session, which is how the Agents window already behaved. Chat-level forking does not change. - Moves `ChatInputRequestPurpose` into the request `_meta` bag. The protocol no longer models the purpose, so a new helper writes and reads it. This keeps the ask-user telemetry and the elicitation classification. - Replaces the terminal `exitCode` field with an explicit running/exited lifecycle. An exit without an exit code is now correctly an exit. - Supplies the owning chat URI on each `TerminalSessionClaim`. The Copilot session runtime gives the chat URI to the shell tools, the non-pty output streams, and the local bang command, and the workbench records the owning chat for each observed terminal. - Renames `SessionLifecycle.CreationFailed` to `SessionLifecycle.Failed`. - Replaces the annotation `turnId` with an `origin` that holds the session, the chat, and the turn. Also corrects the persistence check, which discarded restored annotations. - Adds `MethodNotFound` handlers for the new automation commands. This host does not advertise the automation capability. - Corrects the test data that omitted the turn duration. The chat reducer now calculates `modifiedAt` from that duration instead of the local clock. (Commit message generated by Copilot) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * sessions: correct the artifact location helper name The image carousel entries called rtifactLocation, but the helper is named sessionArtifactLocation. This broke the build on main. (Commit message generated by Copilot) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * agentHost: address review feedback on the AHP 1.0.0 adoption - Carries an explicit `hasExited` signal through `IChatTerminalOutputSource`. A command can now exit without an exit code, so chat must not read completion from the optional code. - Rejects `session/workingDirectoryReplaced`. The action is client-dispatchable, but no provider advertises `primaryReplacement` and the host applies no backend side effect. - Migrates annotations that were persisted before the origin change. Their records hold a top-level `turnId`, which the new check discarded as invalid. - Derives the owning session for a shell terminal claim from the chat URI. The shell manager is constructed with a chat URI for a peer chat, so its own scope URI is not the session. - Sends real timestamps from the end-to-end turn helpers. The chat reducer now calculates `modifiedAt` from the turn, so a fixed past `startedAt` made a peer chat look stale and removed its edits from the session changeset. (Commit message generated by Copilot) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * agentHost: correct turn data in the protocol integration tests The chat reducer now calculates `modifiedAt` from the turn action instead of the local clock, so turn data that was previously ignored must be correct. - Sends a real `startedAt` from the shared turn helper. A fixed past timestamp made a completed turn look older than the session that contains it. - Supplies the required `duration` when the cancellation test cancels a turn. Without it the reducer calculates an invalid date, throws, and the cancellation never applies. (Commit message generated by Copilot) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * agentHost: repair the merge of the AHP 1.0.0 adoption The merge of main dropped a test helper call and did not apply the terminal lifecycle change to the tests that main added, which broke the compile and one unit test. - Restores `createTestAgentService` in the peer chat title test. The merge replaced it with a direct constructor call, whose arguments no longer match. - Sets the terminal lifecycle on the two reconnect tests that main added. (Commit message generated by Copilot) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>github.com-microsoft-vscode · aa1d29a9 · 2026-08-21
- 3.6ETVagentHost: add a chat contribution model for cross-cutting behavior (#332150) * agentHost: add a chat contribution model for turn lifecycle side effects Adds a registry-driven contribution surface to the agent host so cross-cutting behaviors become self-contained modules instead of branches inlined in AgentSideEffects. The surface mirrors the existing LocalChatCommandRegistry pattern so both registries read the same way. This is the first step of an incremental extraction; the backlog is tracked in chatContributions/TODO.md. - Adds IAgentHostChatContribution with an optional onTurnEnd hook, a global registry, and a dispatcher that isolates a failing contribution so one cannot break the others. - Orders contributions by an explicit `order` field, with ties keeping registration order. - Models the terminal outcome as a TurnEndReason discriminated union, because successful, cancelled, and failed turns deliberately run different side effects and only the error case carries detail. - Extracts the mark-unread behavior out of AgentSideEffects into a markUnread contribution, replacing its three call sites for turn completion, cancellation, and error. - Gives every contribution its own subfolder so it can grow to multiple files without churn. - Adds dispatcher unit tests for ordering, failure isolation, reason propagation, and optional hooks. The existing agentSideEffects suite is unchanged and still passes, which is the proof that the extraction preserves behavior. (Commit message generated by Copilot) * agentHost: move turn-end side effects into chat contributions Extracts the remaining behaviors from AgentSideEffects._runTurnCompleteSideEffects into self-contained contributions. The method now only normalizes the session URI and dispatches the turn end, and _captureTurnCheckpointAndRefresh is no longer necessary because the error path reports its outcome through the same hook. - Adds checkpointAndChangeset, queueDrain, gitRefresh, and titleRefinement contributions, each in its own subfolder. - Selects side effects from the TurnEndReason union to keep the previous behavior: checkpoints and changesets run for successful and failed turns, while queue draining, the git refresh notification, and title refinement run only for successful turns. A cancelled turn must not start the next queued message. - Declares an explicit order on every contribution, because registration order is only a tiebreak and must not be used to sequence side effects. - Extends the contribution context with the checkpoint, changeset, and configuration services, plus narrow callbacks for queue draining, the host refresh notification, and title refinement. - Adds a regression test that asserts the built-in contributions run in the original sequence. The existing agentSideEffects suite is unchanged and still passes, which is the proof that the extraction preserves behavior. (Commit message generated by Copilot) * agentHost: contribute host instructions through a send hook Moves the four host instructions that AgentSideEffects._sendTurnMessage built inline into contributions behind a new contributeSend hook. The send path now collects instructions from the registry instead of testing each feature flag in place. Instructions still travel to the providers on IAgentChatContext, which all three harnesses already support, so no provider changes are necessary. - Adds markdownPlanRichLinks, artifactTools, chatSurface, and renameInstruction contributions, each in its own subfolder with an explicit order that keeps the previous instruction sequence. - Makes contributeSend asynchronous, because the rename instruction reads persisted title metadata, and awaits the contributions in order so the send waits for their instructions. - Isolates a failing contribution so it cannot stop the message. - Keeps an empty instruction list absent from the send context instead of sending an empty array. - Adds a regression test that asserts the built-in send contributions run in the original sequence, because instruction order changes model behavior silently. The existing agentSideEffects suite is unchanged and still passes, which is the proof that the extraction preserves behavior. (Commit message generated by Copilot) * agentHost: register chat contributions as a service Replaces the global chat contribution registry, which modules filled through import side effects, with an IAgentHostChatContributions service that createAgentService fills explicitly. The service follows the same shape as IAgentHostChangesetOperationService, so both contribution surfaces read the same way. This also lets AgentService reach the contributions, which the planned turn hydration hook needs. - Adds the IAgentHostChatContributions interface with a registerContribution method that returns a disposable, and its implementation. - Creates contributions through the instantiation service, so each one injects the services it needs instead of reading a context object that the side effects assembled by hand. - Bridges the few operations that AgentSideEffects still owns, such as queue draining and title refinement, through a narrow host interface. A contribution logs and does nothing when no host is registered. - Registers every built-in contribution from one exported list that the composition root and both test helpers share, so a new contribution appears in the ordering tests automatically. - Moves ownership to the composition root. AgentSideEffects receives the service and no longer disposes it. - Keeps the explicit order on every contribution, because registration order must not sequence side effects. (Commit message generated by Copilot) * agentHost: hydrate restored turns through contributions Moves the two enrichment stages that AgentService._getChatMessages performed inline into contributions behind a new onHydrateTurns hook. The method now calls the provider and then the contributions, so AgentService no longer carries the turn usage and worktree logic. - Adds persistedTurnUsage and worktreeAnnouncement contributions, each with an explicit order that keeps the previous sequence. - Passes the whole turn list to each contribution, because reading persisted usage takes one database query for the list and the planned side chat migration must find a boundary across it. - Threads the turns through the contributions in order, so each one receives the output of the one before it. - Returns the previous turns when a contribution fails, because losing the history of a chat is worse than losing an enrichment. - Registers the contributions service before AgentService so it can be injected, and reaches the late bound worktree isolation through the host bridge. (Commit message generated by Copilot) * agentHost: give chat contributions managed per-chat state Adds a per-contribution context with memento storage so contributions keep state that the service evicts with its owning chat or session. Without this, moving the URI keyed maps out of AgentSideEffects would add one cleanup method per contribution, which is worse than the eight maps and ten manual cleanup calls that exist today. - Adds createChatMementoKey and createSessionMementoKey. A key carries the value type, a debug name, a factory for the first value, and optional extra key segments that the caller must supply at the access site. - Adds a single memento accessor that returns a settable observable and selects chat or session storage from the key. The container owns every observable, so a future debug view can show all state for a chat. - Evicts mementos when a chat or session is disposed, and cascades session disposal to the chats of that session. AgentService taps the service at its chat disposal, session disposal, and idle eviction paths. - Registers contributions by constructor so the service can pass each one its own context. The public method stays generic over the injected services and the implementation uses the concrete constructor signature, which registers every built-in without a cast. - Removes the instance id from contributions. The service reads the static id from the constructor and reports it when a contribution fails. (Commit message generated by Copilot) * agentHost: move queue, admission, and title work into chat contributions Continues moving cross-cutting behavior out of AgentSideEffects. The queue contribution now owns queued turn admission, and the bespoke host bridge that existed because these collaborators were not injectable is down from seven members to two. - Gives QueueDrainContribution the queued sender state, the pending message actions, steering synchronization, the drain guards, and the whole admission sequence up to the send. The host only performs the send, which the direct turn path shares. - Removes clearQueuedMessageSenders and both of its call sites, because memento eviction already clears the sender state when a chat is disposed. - Promotes the session title controller, the telemetry reporter, the turn tracker, and the local command dispatcher to services that the composition root owns, and adds a provider locator so a contribution can find the agent for a session without the protocol facing service exposing it. - Builds worktree isolation in createAgentService before the contributions are registered, so the worktree contribution injects it instead of reaching through the bridge. - Merges the title refinement and rename instruction contributions into one session title contribution, which also takes over the SessionTitleChanged handling from AgentSideEffects. - Widens the git refresh contribution into a GitHub references contribution that attaches both the pull request after a turn and the references in a user message. - Adds an onAction hook for client dispatched actions, a narrow onUserMessage hook that fires where the previous callback did, and shared turn telemetry helpers. Behavior is unchanged. The queued path still does not attach GitHub references from a user message, which the notes record as a gap that closes when turn admission is unified. (Commit message generated by Copilot) * agentHost: report local command turns through the turn end hook Removes the onTurnConsumable hook. It existed only so a host handled local command could let the queue drain, and it had one caller and one implementer. Completing a local command is a turn ending, so it now reports through the same hook as every other outcome. - Adds a localCommand variant to TurnEndReason and dispatches turnEnd from the local command tail instead of the removed hook. - Drains the queue for a successful turn or a local command. - Excludes local commands from marking a session unread, which keeps the previous behavior. The other turn end contributions already select the outcomes they act on, so they ignore the new variant. - Changes the checkpoint contribution to name the outcomes it acts on rather than the one it skips, so a later variant cannot enable it by accident. - Adds a test asserting that a local command drains the queue and runs no other turn end contribution. This also removes the last reason local commands are structurally special, which makes moving them onto an incoming request hook simpler later. (Commit message generated by Copilot) * agentHost: attach GitHub references from the outgoing turn hook Merges the onUserMessage hook into the send pipeline. The two hooks were the same lifecycle stage split by history: onUserMessage saw the text but only on the direct admission path, while the send hook ran for both paths but could not see the message. - Adds the message to IOutgoingTurn, which both admission paths already carry. - Renames contributeSend to onOutgoingTurn, because the hook is a stage that may contribute rather than a contributor, and removes onUserMessage. - Moves the GitHub reference attachment into that hook. This changes behavior in three ways, each intended: - A queued message now attaches its GitHub references. The previous hook ran only on direct admission, so a message sent while a turn was running skipped attachment. The notes recorded this as a gap; the merge closes it. - A message refused because the chat is read only or the session is archived no longer attaches references, because the guard returns before the hook runs. - A turn that fails to find a provider no longer attaches references either, for the same reason. The last two follow from attaching references to messages that are actually sent, and both are covered by tests. (Commit message generated by Copilot) * agentHost: address chat contribution review feedback Fixes three problems raised in review of the chat contribution model. - Adds deleteMemento to the contribution context and uses it for the queued sender state. Setting a memento to undefined only changed its value, so a memento keyed by message id kept one entry for every message a chat had ever queued until the chat was disposed. Keys with extra segments now have a way to release entries, which the container previously lacked. - Checks the contribution id before constructing an instance when registering. The previous guard tested the registration map for an instance that had just been created, so it could never report a repeat registration and the constructor of a contribution registered twice ran twice. - Describes what onTurnEnd actually covers. It fires from the agent signal path and from local command completion, but not for a client dispatched cancellation or for the failures that report ChatError directly. Those call sites match the ones the previous mark unread logic had, so behavior is unchanged, but the previous comment claimed every terminal outcome. The notes record this as a gap that unifying admission closes. Adds tests for the memento deletion and the registration guard. (Commit message generated by Copilot)github.com-microsoft-vscode · 0178ca54 · 2026-08-24
- 3.5ETVinline chat: add experimental Agent Host backend (#331874) * inline chat: add experimental Agent Host backend Adds an experiment-gated (`chat.inlineChat.agentHost.enabled`, default off) Agent Host backend for editor inline chat, following the terminal chat migration. When disabled, inline chat behaves exactly as before. Because the Agent Host writes files directly to disk rather than streaming edits, review UI is hydrated from before/after snapshots instead: - `InlineChatSessionResolver` picks the Agent Host or the legacy local session, falling back on any failure and treating cancellation as cancellation rather than fallback. - `IChatEditReviewSession` is extracted as a narrow supertype of `IChatEditingSession` so a surface can supply reviewable entries without implementing checkpoints, storage, streaming edits or multi-diff. `editingSessionsObs` is typed to it, keeping editor-level review UI (decorations, hunk keep/undo, accessibility) working. - `InlineChatEditReviewSession` implements only that surface. It saves and snapshots the target, locks it read-only for the turn, and reuses `ChatEditingModifiedDocumentEntry` so diffing and hunk review come for free. Turns are bracketed with `startExternalEdit`/`stopExternalEdit` so disk-driven model reloads render in real time and stay cumulative across follow-up turns. - `IFilesConfigurationService.updateReadonly` accepts an `IMarkdownString` so a programmatic lock can explain itself instead of offering the generic "set writeable" affordance. Notebooks and untitled documents deliberately stay on the legacy path. Also fixes a pre-existing leak where every non-local session was written to the chat history index regardless of location, so throwaway inline (and terminal) sessions appeared in the session list. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * inline chat: track off-target agent edits in real time The Agent Host emits an `externalEdit` progress part as each tool call completes, so files the agent touches outside the inline-chat target can be discovered during the turn rather than only at its end. `InlineChatEditReviewSession` now watches the response for those parts and creates a review entry as soon as one appears, seeding its baseline from the part's `beforeContentUri`. That baseline is the only trustworthy "before" for an off-target file: the agent writes to disk before announcing the edit, so reading current content would silently yield an empty diff. Entries enter external-edit mode so subsequent disk reloads keep their diffs live, matching the target file. `endTurn` keeps its sweep as an idempotent safety net. Deletes and renames are skipped — neither maps cleanly onto a single-URI `IModifiedFileEntry`. Fixes two attribution races that would drop agent edits from the diff: - A newly created entry was published through `entries` before external-edit mode was on, so an observer could see it and a disk reload could land in that window and be rebased into the baseline as a user edit. - An off-target entry carried over from an earlier turn only re-entered external-edit mode once its part arrived, but the disk write precedes the announcement. All tracked entries now enter external-edit mode at `beginTurn`. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * inline chat: add experimental Agent Host backend Adds an Agent Host backend for editor inline chat. The setting `chat.inlineChat.agentHost.enabled` controls it and is off by default. When the setting is off, inline chat operates as before. The Agent Host writes files to disk. It does not stream edits into the editor. Inline chat therefore builds its review UI from before/after snapshots. - Adds `InlineChatSessionResolver`. It selects the Agent Host session or the legacy local session. It falls back to the legacy session on failure. It does not fall back when the user cancels. - Extracts `IChatEditReviewSession` as a supertype of `IChatEditingSession`. A surface can supply reviewable entries without checkpoints, storage, streaming edits, or multi-diff. Editor review UI, such as decorations and keep/undo, continues to operate. - Adds `InlineChatEditReviewSession`. It saves and snapshots the target file, makes the file read-only for the turn, and reuses `ChatEditingModifiedDocumentEntry`. Diff decorations and hunk review operate without new diff code. - Shows diff decorations in real time. Each turn starts and stops external-edit mode, so disk reloads count as agent edits. The diff stays cumulative across turns. - Tracks the files that the agent edits outside the target file. The Agent Host announces each edit when a tool call completes. The baseline content comes from that edit. - Lets `IFilesConfigurationService.updateReadonly` accept an `IMarkdownString`. A programmatic lock can then show its own reason. - Shows the current agent operation in the inline input placeholder. - Keeps notebooks and untitled documents on the legacy path. Makes throwaway (ephemeral) sessions start and run more quickly: - Disables MCP servers, subagents, and custom agents for these sessions. - Skips the turn-start checkpoint. This work is on the critical path of each turn. - Skips title generation and the rename instruction. The title is never shown. - Adds `enabledForEphemeralSessions` to server tool definitions. A tool must opt in before an ephemeral session receives it. Also keeps throwaway sessions out of the session lists. The host no longer sends `root/sessionAdded` for an ephemeral session. The chat history index no longer stores an external session from a transient surface. (Commit message generated by Copilot) * inline chat: address review feedback and fixture failures - Adds `getEditingSession` to the two component fixture mocks of `IChatEditingService`. The chat widget now calls this method, so the fixtures failed to render. - Cancels the turn when the pre-turn save is cancelled. The buffer stays dirty in that case, so the end-of-turn revert discarded the unsaved work of the user. - Records a created off-target file with `ChatEditKind.Created`. A rejection then deletes the file instead of leaving empty content on disk. - Cancels the request when turn preparation fails. Before this change the agent could write files while the file was not read-only and no review baseline existed. - Examines the session map again after the Agent Host resolves. Before this change two controllers for one file could each create a session. - Corrects the comment about custom agents for ephemeral sessions. The SDK can still find agents in the plugin directories. (Commit message generated by Copilot) --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>github.com-microsoft-vscode · 9b82522c · 2026-08-20
- 3.2ETVAgent Host: surface remote connection state in sessions (#334111) * Agent Host: surface remote connection state in sessions A session backed by an unreachable remote host previously spun forever with no explanation and no way to recover. Surface that state and make it actionable: - Derive a session-scoped `remoteConnectionStatus` from the provider so the chat surface can react to connection state, not just host-scoped UI. - Add machine-readable transport failure reasons so a stopped host is distinguishable from an unreachable one. - Show a centered recovery state with a Start action when a session has no visible transcript, and a quiet inline banner when a rendered transcript drops mid-use. - Report live bootstrap progress ("Downloading server (24%)") while a connect is in flight, via a shared progress parser. - Split WSL startup, idle, and ceiling timeouts so a cold VM boot is not mistaken for a hung connection. - Gate terminal launches on host availability and re-resolve chat content when a provider registers late. Collect the connection concerns in ChatGroupView behind a single SessionRemoteConnection, expressing state as observables with one derived resolving which surface is visible. Read-only remains a peer of connection state rather than part of it, since a read-only chat can also be reconnecting. The quiet-reconnect delay is now a deadline, so re-arming is idempotent instead of relying on a guard field. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Agent Host: auto-start a stopped remote host from the recovery surface Adds an opt-in, kind-scoped policy that starts a stopped remote agent host instead of waiting for the user to press Start. Providers expose it through `IAgentHostAutoConnect` (label, observable value, setter) and choose how it is backed; WSL backs it with `chat.agentHost.wsl.autoStart`. The recovery screen and the inline banner both render the checkbox and live connect progress. The Start action is never rendered while an automatic start is pending: the content derivation itself returns the connecting presentation, so this holds structurally rather than depending on autorun ordering. Two ordering bugs surfaced while building this. A connect that resolved without reaching the host cleared the in-flight attempt and re-opened the automatic gate, spinning forever behind a permanent "Waiting for agent host connection...". The gate is now latched per outage and released once the host is reachable, so a mid-session drop still gets its own attempt while an ineffective connect does not retrigger. The service fired its connection-change notification from inside a failing dial, before clearing the in-flight marker. A consumer dialing from that notification joined the dial that had just failed, so nothing reconnected and its `waitForConnection` never settled. The marker is now cleared before notifying; `_connectTo` clears by identity, so a dial started from the notification survives. Both are covered by regression tests that reproduce the original hangs. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Agent Host: show reconnect backoff and offer a manual retry While a protocol client waits out its exponential backoff the banner now reads "Reconnecting to <host> in 5s" and counts down, with a Try Now action that skips the remaining delay. Try Now accelerates the client's in-place retry rather than redialling, so the outbox and session state survive. It falls back to a fresh dial only when there is no client to accelerate, which happens now that a rejected factory retains a client-less entry. The backoff deadline travels on the `reconnecting` status. The client stays in that state across rounds, so the deadline is refreshed through a dedicated `onDidScheduleReconnect` event rather than by re-firing the connection-state event: consumers of that event do real work per transition, and repeating it each round would have unclear blast radius. Also offers a Retry action on the generic "Cannot reach <host>" state, on both the banner and the centered recovery surface. A tunnel that dies is usually transient. This stays manual: unlike a stopped WSL distro there is nothing local to start, so retrying automatically would only hammer an unreachable endpoint. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Agent Host: address review feedback on remote connection state Retaining a disconnected entry turned `connections` from a liveness list into a status catalog, but three consumers still read presence as "connected": cloud sandbox negative reconciliation would never tear down a failed environment, and the cloud sandbox and Dev Container connect-failure paths would skip their cleanup and leak a staged connection. Each now tests the status. Documented the broadened semantics on the interface and removed an orphaned JSDoc block for an accessor that no longer exists. Reverted a stray `1.0.0` entry in the supported-protocol list. It broke the registry's documented first-entry invariant against `PROTOCOL_VERSION` and the handshake test, and had nothing to do with this work. `setSession` now writes in one transaction. These observable writes notify autoruns synchronously, so clearing the gates while the previous session was still selected could start the host being switched away from. The banner explains an incompatible host instead of staying silent. Once a transcript is rendered the centered recovery state is skipped, leaving the banner as the only surface, so suppressing it meant no explanation at all. Accessibility: the banner's live region now announces dedicated text rather than its visible text, so a per-second countdown no longer queues an utterance per tick, and connect progress is announced as it advances. Bootstrap progress discards a queued report before publishing an immediate one. If the event loop stalled past the throttle interval, the stale pending value could land after the newer one and make displayed progress run backwards. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Agent Host: describe the automatic-start latch scope accurately Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Agent Host: assign the session connection in the constructor Its field initializer read _instantiationService, a parameter property of the same class, which class-field semantics initialize after field initializers run. Caught by define-class-fields-check. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>github.com-microsoft-vscode · dc85eaf9 · 2026-09-03
- 3.1ETVAgent host: run `!`-prefixed chat messages as terminal commands (#324270) - Add a "bang command" feature: in any chat agent, a message starting with `!` runs as a terminal command (via the existing agent-host terminal/shell integration) instead of being sent to the model. The host emits a transcript-only tool-call response for the command. - Persist host-injected "local turns" (`!command` and `/rename`) so they survive reload; fork/truncate/rename resolve them to the preceding concrete SDK turn. Handled uniformly per-chat (default, peer and subagent chats). - Refactor local command handling into a pluggable `LocalChatCommandRegistry` with self-contained `AgentHostLocalCommands` dispatcher, extracting the logic out of `AgentSideEffects`. Add `renameLocalCommand` and `bangLocalCommand`. - Extract shared helpers: `shellCommandExecution` (agent-agnostic shell exec core) and `persistSessionMetadata`. - Fix peer-chat truncation routing: `truncateSession` now takes the chat URI and routes peer chats to their own backing session. - Fix truncate no-op after forking into a second peer chat: `SessionDataService` keyed every peer chat of a session onto one data dir/DB (chat id lives in the URI authority, which `AgentSession.id` dropped), so a second fork's `vacuumInto` failed with "output file already exists" and the forked chat never inherited its turn event IDs. Key now includes the authority; both fork copy sites also clear any stale target DB first. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>github.com-microsoft-vscode · 710b8c0c · 2026-07-04
- 3.1ETVagentHost: lazily restore peer chats (#329071) * agentHost: lazily restore peer chats Keep restored peer chats as state-manager-owned entries and materialize their SDK histories only when content is requested. Consolidate per-session resume, sequencing, and teardown coordination so distinct peers can resume concurrently without racing session disposal. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * agentHost: preserve peer restore failures Propagate known peer-session resume failures so lazy chat hydration remains retryable instead of committing an empty history. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>github.com-microsoft-vscode · aa23e75a · 2026-08-05
- 2.4ETVagentHost: scope client customizations to session working directories (#330378) The synthetic vscode-synced-customization plugin was keyed only by session type, so one bundle identity was shared by every session of a provider and resolved against whatever workspace folder happened to be ambient. In the Agents window the ambient folder is swapped on every active-session change, so switching sessions re-resolved and re-published customizations to every live session and leaked one repository's files into sessions running in another. Customization state is now keyed by the session's working-directory set. Scopes are refcounted and shared by sessions with identical roots, so each repository gets a stable bundle authority and nonce and the agent host's plugin cache stops re-materializing on every switch. Prompt enumeration takes an explicit root instead of reading the ambient workspace. Publishing is consolidated into a single debounced per-session reconciler, replacing four separate dispatch sites that each compared against not-yet-updated session state and produced redundant actions. Publishing is gated on the scope having resolved so a freshly acquired scope cannot transiently wipe the host's customizations, an identical payload is never re-sent, and undefined-valued keys are omitted from published payloads so a value round-tripped through the wire compares equal to the one that produced it.github.com-microsoft-vscode · c14ff798 · 2026-08-12
- 2.4ETVAgent-host MCP authentication + accurate/persisted MCP auth state (#323968) * wip on mcp auth through AH * Preserve live MCP server state across customization re-syncs The Agents window showed a connected GitHub MCP server flipping back to 'Starting' when navigating away from and back to a session. A client re-subscribe re-published the session's customizations, and the SessionCustomizationsChanged full-replace reset each MCP entry's state to the 'Starting' default baked into makeMcpServerCustomization. - Skip no-op customization re-syncs in SessionPluginController.sync so an identical re-publish (e.g. navigating back) does no work. - SessionPluginController now overlays live MCP runtime state/channel onto every published customization via _projectForPublish, so a genuine single-customization change no longer resets otherwise-unchanged MCP servers. The overlay is driven by an ISettableObservable kept up to date by the session from McpCustomizationController. - McpCustomizationController._live is now an observable and exposes runtimeStates as a derived; mutations are batched in transactions. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Persist agent-host MCP auth and improve auth-required prompts - Key remembered MCP auth on a stable id (session authority + server name + resource URL) instead of the unstable customization id, so grants survive reloads and don't require re-auth. - Record agent-host metadata (authority + host label) on allowed MCP servers and surface agent-host servers in their own section of the Manage Trusted MCP Servers picker instead of filtering them out. - Make the auth-required chat prompt reactive: servers is now an observable so servers whose auth requirement surfaces later join the existing prompt, and the part marks itself used once hidden so later requirements re-prompt. - Show an 'Authenticating <server>...' progress state while each server auths. - Drop the never-serialized mcpAuthenticationRequired part from the serialized response-part unions. - Add unit tests for the stable-id helper, agentHost metadata persistence, and query-service exposure. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Address CI failure and Copilot review on MCP auth prompt - Don't emit an empty mcpAuthenticationRequired progress part (was adding a stray part and breaking AgentHostChatContribution tool-progress tests). - Guard the async auth filter with a run id so out-of-order completions can't overwrite a newer server list. - Group agent-host servers in the Manage Trusted MCP Servers picker by stable authority (sorted by label) instead of label, which could collide. - Scope the authenticate link to the #authenticate target and give it button semantics (role=button, cleared href). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>github.com-microsoft-vscode · 17c6cd48 · 2026-07-02
- 2.2ETVremote tunnels: unify agent window access (#333886) * remote tunnels: unify agent window access Use one Remote Tunnel Access state for the editor and Agents window. - Route the Agents window toggle through the Remote Tunnel commands. - Use GitHub authentication without extra pickers or service installation. - Keep tunnel rename UI and synchronize tunnel status across both surfaces. - Remove separate Agent Host tunnel hosting services and process modes. - Preserve web discovery with a browser-safe Remote Tunnel service. (Commit message generated by Copilot) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * remote tunnels: fix agent window initialization Prevent early command execution and false connection notifications in the Agents window. - Register the titlebar action after Remote Tunnel commands are available. - Seed the initial sharing state before enabling transition notifications. - Add tests for initial snapshots and status events during initialization. (Commit message generated by Copilot) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>github.com-microsoft-vscode · aa56e4e2 · 2026-09-02