Connor Peet
90d · built 2026-08-09
90-day totals
- Commits
- 143
- Grow
- 34.8
- Maintenance
- 18.2
- Fixes
- 22.0
- Total ETV
- 75
Where this dev ranks
Percentile against the global top-100 leaderboard (all-time totals).
- By commits
- Top 31 %
- By Growth share
- Top 14 %
30-day trajectory
Last 30 days vs. the 30 days before. Up arrows on Growth and ETV mean improvement; up arrow on Fixes share means more time on fixes (worse).
↑+77.4 %
vs 31 prior
↑+17.2 pp
recent vs prior
↑+8.0 pp
recent vs prior
Daily performance
Daily ETV, stacked by Growth, Maintenance and Fixes.
Work-mix over time
Share of Growth / Maintenance / Fixes over a rolling 7-day window. Reads as 'where is effort flowing right now'.
Repository spread
Where this developer's commits land. Concentrated work (top1 > 80%) vs polymath spread (top1 < 30%).
Most impactful commits
Top 20 by ETV in the 90-day window.
- 3.4ETVFix Copilot AH plugin sync errors on reconnection (#320193) * Fix Copilot AH plugin sync errors on reconnection (#319744) Two-part fix for #319744: 1. AHPFileSystemProvider gets a brief reconnection grace window. Per- authority entries keep a stack of connections (newest = active) and hold open requests across a transient disconnect. Watchers auto-reattach across reconnects via a class-level connection-change event. New tests cover reconnect grace, fallback to prior connection, immediate reject for never-registered authorities, and watch reattach across disconnect / late attach. 2. Plugin controller is split into two: - PluginController (shared, process-wide): host customizations, parsing helpers, and the IAgentPluginManager. - SessionPluginController (per CopilotAgentSession): client customizations, session-discovered on-disk customizations, and per-session enablement overrides. Publishes SessionActions directly via onDidPublish — no more clientId-based cross-session routing. ActiveClient is now Disposable, owns its SessionPluginController, and forwards publish events into the session's progress stream. setCustomizationEnabled fans out to every session controller, matching Claude's per-session model. sendMessage retries any previously-failed client customization sync so a transient connection drop during reconnection doesn't pin the error. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Address Copilot review feedback - agentHostFileSystemProvider: fix _getConnection race by re-checking state after subscribing - agentHostFileSystemProvider: explicit void on fire-and-forget reattach() calls in watch() - copilotAgent: remove duplicate JSDoc block on PluginController Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Use timeout(0) instead of setImmediate in browser-runnable tests setImmediate is not available in WebKit, causing macOS / Browser CI unit tests to fail. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>github.com-microsoft-vscode · bad33e15 · 2026-06-06
- 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.4ETVagent-host: add WSL connection support (#319971) * agent-host: add WSL connection support Add WSL-based remote agent host connections as a third connection type alongside SSH and dev tunnels. On Windows, users can pick "WSL..." in the Remote group of the session workspace picker, choose an installed WSL 2 distro, and the agent host is launched inside that distro. Connected distros are persisted as remembered entries and auto-reconnected on startup -- but only when WSL is already running, we never auto-boot a shut-down distro. - New IPC contract `IWSLRemoteAgentHostService` / `IWSLRemoteAgentHostMainService` mirrors the SSH shape. A shared `RelayTransport` base is extracted from `SSHRelayTransport` so SSH and WSL share the IPC relay pump. - Shared-process service spawns `wsl.exe -d <distro> -e bash -lc <bootstrap>`, reuses the SSH CLI install layout helpers verbatim (`~/.vscode-server/cli/...`), parses the `ws://127.0.0.1:PORT?tkn=...` URL the agent host prints, opens a local WebSocket, and pumps frames over IPC. Retries the open on ECONNREFUSED/AggregateError to ride out WSL 2's localhost-forwarding setup delay on first connect. - Contribution layer adds `WSLReconnectState` mirroring `SSHReconnectState` and extracts a shared `_attemptManagedReconnect` template so SSH and WSL share retry-loop logic (status transitions, incompatible short-circuit, cached-session unpublish on failure). WSL retries are gated on `wsl --list --running` so a stopped distro is never auto-booted. - New "WSL..." action gated on `isWindows && chat.remoteAgentHostsEnabled`; surfaces install docs (`aka.ms/vscode-remote/wsl/install-wsl`) when WSL is missing or no WSL 2 distro is installed. The "Select..." button stays enabled even while a distro is stopped -- explicit user click overrides the never-auto-boot rule and boots the distro on demand. - Workspace picker scopes `resolveWorkspace` to the matching connection authority so a folder picked from one agent host is no longer attributed to another. - New `canConnectOnDemand` provider capability keeps `Select...` enabled while disconnected/connecting for providers with a connect-on-demand hook; concurrent on-demand clicks join the in-flight reconnect promise instead of returning early with a misleading toast. - New parser tests for `wsl --list --verbose` / `--running` output and the `wsl.exe` UTF-8 / UTF-16LE decode heuristic. Fixes https://github.com/microsoft/vscode/issues/307568 (Commit message generated by Copilot) * agent-host: fix test URI authorities for resolveWorkspace scoping Tests in remoteAgentHostSessionsProvider.test.ts used hardcoded `vscode-agent-host://auth/...` URIs but the provider's connectionAuthority is derived from the configured address (default `localhost:4321` -> `localhost__4321`). After tightening `resolveWorkspace` to only claim URIs whose authority matches its own (Linux/Browser CI failure on PR #319971), these tests started failing. Update the URI authorities to match the actual default.github.com-microsoft-vscode · f4839fb2 · 2026-06-04
- 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
- 1.9ETVagentHost: adopt OTEL log channel, support logs from remote agent hosts (#317876) Wires up the new `channels-otlp/` protocol so the agent host's `ILogService` is mirrored over an `ahp-otlp://logs/{level}` channel and surfaced as a per-host Output channel in the workbench. - Add `OtlpLogEmitter` / `OtlpEmitterLogger` (`platform/agentHost/common/otlp/`). `LogService` is constructed with the OTLP logger as a secondary sink in both `agentHostMain.ts` and `agentHostServerMain.ts` so every log call fans out to subscribers. - `ProtocolServerHandler` advertises `telemetry.logs` in `InitializeResult`, routes `subscribe`/`unsubscribe` on `ahp-otlp:` channels through a typed `ChannelSubscription` union, canonicalises the channel URI per-level, and broadcasts `otlp/exportLogs` notifications filtered per subscriber severity. - `RemoteAgentHostProtocolClient` stores the full `InitializeResult`, adds `subscribeStateless` and `onDidReceiveOtlpLogs`. - New `RemoteAgentHostLogForwarder` in the workbench layer registers an `Agent Host (${host})` Output channel via `IOutputChannelRegistry`, subscribes at the workbench's `ILogService` level (re-subscribes on change), and appends decoded records. Constructed from `remoteAgentHost.contribution.ts::_setupConnection` so it covers WebSocket, SSH and tunnel paths. Local agent host IPC logging is unchanged. - Existing remote IPC traffic channel renamed to `Agent Host IPC (${host})` to disambiguate from the new OTLP-derived channel. - Move `UriTemplate` from `workbench/contrib/mcp/common/` to `base/common/` so the forwarder can use it for `{level}` expansion. Tests: 8 unit tests for the emitter, 7 for the server-side OTLP routing (including URI canonicalisation), 3 integration tests for the end-to-end wire flow, and the existing protocol/handshake/reconnect suites. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>github.com-microsoft-vscode · 3400e0f7 · 2026-05-21
- 1.8ETVchat: ask side questions from selected responses (#327465) * chat: ask side questions from selected responses Reuse the feedback input affordance in the Agents window to create side chats from selected assistant markdown, with accessible pending state and Agent Host context coverage. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * chat: address side question review feedback Preserve accessible labels and multiline input behavior, guard stale async UI completion after navigation, and normalize side-chat orchestration APIs. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>github.com-microsoft-vscode · f6af01a8 · 2026-07-25
- 1.6ETVagentHost: cancel late callbacks during abort (#327427) * agentHost: cancel late callbacks during abort Keep Copilot SDK callbacks from parking after an accepted steering message races with abort, allowing replacement turns and follow-ups to proceed. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * agentHost: refresh abort state after async work Read abort state through a method so TypeScript does not retain stale enum narrowing across awaits. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * agentHost: guard abort callbacks centrally and race the abort token Replaces the per-call-site abort checks added in the previous two commits with a single guard applied where the SDK interaction handlers are already wired, and fixes two hangs and a staleness race found along the way. - Abort state is now a CancellationTokenSource rather than a two-value enum. A token captured at handler entry stays cancelled even after send()/onIdle installs a fresh source, so an in-flight handler can no longer resume past a reset and return a real result for an aborted turn. - _guarded(handler, cancelled, label) wraps each handler in _createRuntimeAdapter() and the client SDK tool handlers, replacing 11 inline checks. It races the captured token so a callback that parks its deferred after the abort sweep resolves instead of hanging forever, which previously left the SDK without a response for exit_plan_mode, MCP auth and permission requests. The synchronous pre-check keeps the already-cancelled path off the shortcutEvent macrotask, and the post-race check still catches handlers that win that macrotask. - dispose() now begins an abort so in-flight races settle rather than losing their listener to the token source teardown. - The hand-rolled pending-request maps move onto PendingRequestRegistry, which grows optional per-entry metadata (register/registerAndFire meta, getMetadata, entries, respondWhere, has). Cleanup collapses to a single _cancelAllPendingInteractions() shared by abort and dispose. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>github.com-microsoft-vscode · 847b9dc5 · 2026-07-27
- 1.6ETVagent host: fix blank response after aborting a turn with a queued message (#322228) * agent host: fix blank response after aborting a turn with a queued message When a running turn was aborted while a follow-up message was queued, the Copilot SDK's asynchronous terminal `session.idle` (delivered after the abort teardown) completed the wrong turn: the queued message's send() had already reassigned the session's current turn id, so the stale idle emitted an empty ChatTurnComplete for the freshly-started turn and orphaned its real response and pending permission prompt. Read the SDK's authoritative `IdleData.aborted` flag, and replace the scattered per-turn fields (turn id, usage counter, streaming part-id maps) with a single CopilotTurn object carrying an explicit lifecycle state (pending | running | completed | aborted). A turn is pending between send() and the first SDK event and running thereafter; an abort's idle tears down a running turn (the client's ChatTurnCancelled finalizes it) and leaves a pending queued turn open, so the next turn's response is no longer orphaned. Steering turns are marked running on creation since they are promoted mid-loop. Also assert that cancelling a turn intentionally does not drain queued messages (they stay for manual dequeue), and keep the subagent routing map session-scoped since background subagents can outlive a turn. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * agent host: address PR review feedback - Log an error and drop markdown/reasoning deltas emitted with no active turn (previously a no-op set that re-allocated a part per delta). - Split the abort-idle trace message by turn state (running turns are torn down, not left open). - Tidy a test title to sentence case. - Give delta/plan-mode mapping tests an active turn instead of relying on the old emit-without-a-turn behavior; assert the new drop+log behavior. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>github.com-microsoft-vscode · 0c5ea498 · 2026-06-21
- 1.6ETVagentHost: replace AgentHostEditingSession with direct externalEdit progress part (#318053) The legacy AgentHostEditingSession (844 LOC) only existed to translate completed tool-call file edits into a markdownContent/codeblockUri/textEdit cluster that CollapsedCodeBlock would then re-derive into a diff pill by asking the editing session for stats it had just been handed. The agent host protocol already exposes FileEdit.diff and before/after content URIs up-front, so cut out the round-trip: - New IChatExternalEdit progress part carries uri, editKind, originalUri, beforeContentUri, afterContentUri, and diff stats directly. - stateToProgressAdapter.completedToolCallToEditParts emits one IChatExternalEdit per FileEdit, wrapping every URI via toAgentHostUri so remote sessions resolve through the agent host file system provider. - Extract ChatEditPillElement base class from CollapsedCodeBlock — same DOM / styling, no editing-session coupling. New ChatExternalEditContentPart extends it and renders a static pill from the progress data. - ChatThinkingContentPart.appendItem now accepts IChatExternalEdit metadata directly (via the new ChatThinkingItemMetadata alias); it derives the title (Created/Deleted/Renamed/Edited <filename>) and the pencil icon without any synthesized markdown. Diff stats bubble up through onDidChangeDiff (fired on a microtask so subscribers attach first). - AgentHostSnapshotController (~330 LOC) replaces the legacy editing session: implements IChatEditingSession but only restoreSnapshot, requestDisablement, and snapshot URIs do real work. Everything else is a no-op so the chat-level Restore-to-checkpoint UI keeps working without dragging in the full diff pipeline. - ChatChangesSummaryPart is intentionally skipped for agent host responses — per-file pills already convey the change counts inline. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>github.com-microsoft-vscode · 5bb22231 · 2026-05-23
- 1.5ETVWire up MCP App support for agent-host sessions (#321016) * working, in theory * finish up * review commentsgithub.com-microsoft-vscode · a3634cd2 · 2026-06-11
- 1.5ETVplugins: support new agent plugin spec (#327032) * plugins: support new agent plugin spec Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * plugins: address review feedback Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>github.com-microsoft-vscode · ff4f272b · 2026-07-23
- 1.4ETVagentHost: support attaching virtual resources (untitled, notebook cells) (#320040) * agentHost: support attaching virtual resources (untitled, notebook cells) Consolidates the agent host's permission and virtual-resource services into a single `IAgentHostResourceService` that owns the gated FS surface (`list`/`read`/`write`/`del`/`move`/`copy`/`resolve`/`mkdir`), the permission policy, and an `ITextModelService`-backed fallback for content that isn't on disk. Both the in-process local channel and the remote protocol client's reverse-RPC handler now reduce to a thin wire adapter that dispatches frames to the same service. - Adds a single `IAgentHostResourceService` (platform decorator + types, workbench implementation) replacing `IAgentHostPermissionService` and `IAgentHostVirtualResourceProvider`. - `read`, `write`, and `resolve` (stat) transparently fall back to `ITextModelService` when `IFileService` cannot satisfy the request, so attached untitled documents and notebook cells round-trip end to end. - `AgentHostClientResourceChannel` (local in-process) and `RemoteAgentHostProtocolClient._handleReverseRequest` (remote) shrink to thin adapters that translate JSON-RPC frames into service calls and surface `AgentHostResourcePermissionError` as `PermissionDenied` frames so the host's standard `resourceRequest` -> retry loop still works. - Local agent host short-circuits the permission gate (sentinel address `'local'`): the utility process already has the renderer's FS access, so gating it adds no security and would just produce unprompted denials. - `createAgentHostClientResourceConnection` now exposes `resourceRequest`, completing the local prompt/retry loop. - `agentClientUri` preserves `query` and `fragment` across the round trip and uses a `!` scheme-slot marker to faithfully round-trip opaque-path URIs such as `untitled:Untitled-1`. Fixes https://github.com/microsoft/vscode/issues/319802 (Commit message generated by Copilot) * Address Copilot review and update tests for virtual-resource attachmentsgithub.com-microsoft-vscode · c1c20ad0 · 2026-06-05
- 1.3ETVagentHost: run the agent host on the remote server (#329706) * agentHost: run the agent host on the remote server The agent-host harness never appeared in the session-type picker when connected to a remote (Codespaces, Remote-SSH, Dev Containers, WSL). Two independent gaps caused this. 1. The REH server only spawned an agent host when launched with `--agent-host-port` / `--agent-host-path`, and only bridged renderers when `--agent-host-bridge-*` was set. The Rust CLI's `code tunnel` sidecar is the only caller that passes those flags, so every other remote registered `UnavailableAgentHostChannel`: the renderer's connect rejected, root state never arrived, and no agent chat session types were registered. The server now self-provisions an agent host when no flags are given, listening on a per-server random socket path guarded by a random connection token. It starts lazily on the first renderer connect, so servers where chat is never used pay nothing and remote auto-shutdown idle timers are unaffected. Startup only reports success once the agent host confirms its listener is bound, so the first connect can't race the socket into existence. 2. The agent host chat contributions were registered only from the desktop workbench, even though the web workbench already wired up `EditorRemoteAgentHostServiceClient` and enables the agent host whenever a remote authority is present. They now live in the browser layer and are shared by web and desktop, which is what makes the Codespaces browser client work. Gating is unchanged: the agent host is offered only when a real server-backed remote exists, so serverless web stays dark. Also stop forwarding the client-resolved default shell to a remote agent host. Sending a client's shell path to a server of a different platform is wrong; the agent host resolves its own shell when the key is absent. Fixes #326125 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * agentHost: address review feedback on remote server startup - Keep the caller's `ensureStarted()` pending across automatic retries. Rejecting while a retry was still in flight made a transient first-spawn failure fatal for the window, since the protocol client treats a failure during connect as terminal and never sees the later successful start. - Register the crash handler only after startup fully succeeds. An exit during startup already rejects the pending readiness request, so the retry loop now owns that case exclusively; previously both paths could fire and start two replacement processes while burning the budget twice. - Cache only the in-flight endpoint resolution in `AgentHostChannel`. Resolution is `ensureStarted()` on the lazy server path, so retaining a resolved endpoint meant a later reconnect dialed a dead socket instead of restarting the host. - Remove a stale socket before spawning. Unix sockets outlive the process that bound them, so a crashed agent host left its path behind and every restart failed to bind with EADDRINUSE, exhausting the retry budget without recovering. Also document that the agent host starts once a chat-enabled remote window loads rather than on first session use: the contribution injects IAgentHostService, which connects from its constructor. That matches the pre-existing desktop behaviour; the server-side laziness is about servers with no connected renderer. Tests waited a single microtask for startup, which the readiness await made insufficient; they now wait for the real signal. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>github.com-microsoft-vscode · 5fb9376d · 2026-08-08
- 1.3ETVFix blocked agent host sessions from nested subagent client tools (#323815) * Fix blocked agent host sessions from nested subagent client tools Nested (depth >= 2) subagents were never observed by the renderer, so a client-owned tool called deep in the subagent tree (e.g. the `problems` tool via a subagent-of-a-subagent) never ran and the session hung in "Input Needed" with no visible prompt. Two root causes, fixed on both sides: - Renderer: `tryObserveSubagent` required the subagent-discovery content block before subscribing to a child chat. It now observes as soon as the tool is a known subagent-spawning tool that is running, deriving the child chat URI from the tool id alone — robust and depth-independent. - Agent host: `subagent_started` carried no parent context, so the discovery content block was dispatched on the top-level chat instead of the immediate parent subagent chat (a no-op there). Threaded `parentToolCallId` through the signal (copilot + claude adapters) so the block routes to the immediate parent chat via a flat one-hop lookup at any nesting depth. Also keeps producing the session-level `inputNeeded` state for other clients (with tests), though the renderer no longer consumes it. Fixes #323738 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix test type narrowing and clarify subagent observation comment - Narrow ToolCallState to Running before reading .content in the 3-level nested routing test (fixes Compile & Hygiene TS error). - Reword the tryObserveSubagent comment to frame content-block-less observation as robustness (older/misrouting hosts, restored snapshots) rather than current agent-host behavior, which this PR fixes. Addresses Copilot review feedback. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix flaky wait in nested subagent tests The level-2 and content-block-less nested subagent tests polled for the client tool's local invocation, then immediately asserted its completion was dispatched — but completion lands one or more microtasks later, and deeper nesting adds async hops, so it raced on slower CI (Webkit). Poll for the dispatched ChatToolCallComplete instead (implies invocation already happened). Verified locally with runTests. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>github.com-microsoft-vscode · 50055f97 · 2026-07-01
- 1.3ETVagentHost: drive tool execution from the session input queue (#328989) * agentHost: drive tool execution from the session input queue Subagent tool calls could stall indefinitely. A user reported 16 subagents running overnight that "keep stalling and dying for no apparent reason", needing the main agent to repeatedly repair them. Log analysis found 16 permission requests that were never answered, and 80 subagent chat channels unsubscribed ~12ms after a single provider error. The cause is structural rather than a single bug. Answering a tool call was owned by the per-turn chat observer: it rendered the call AND invoked the tool AND dispatched the outcome. So anything that tore down an observer -- a provider error disposing the parent turn's store, a turn ending, a reconnect, or simply never observing a subagent chat -- left the agent blocked on an obligation nobody was left to answer. Invert the relationship. The protocol already maintains SessionState.inputNeeded: a session-level queue of every outstanding blocker, each entry self-sufficient so a client can answer it without subscribing to the owning chat. It is a derived projection recomputed from tool-call status, so it is a set that can be re-read rather than a stream that can be missed. Make that queue the driver: - A session-level watcher owns all four blocker kinds and is the single caller of invokeTool. Chat observers only render. - One shared ChatToolInvocation per call, created by whichever side arrives first, so the card an observer renders in its subagent group is the same object the watcher executes. - Claimed calls run with chat context so confirmations render inline. Unclaimed non-confirmable calls run headlessly. Unclaimed confirmable calls wait for an observer, then deny rather than surface a modal nobody can see. - Chat input requests and MCP authentication get the same treatment; both could previously stall with no surface at all. This removes the class rather than the instances: an obligation is now answered because the session says it is outstanding, not because some particular observer happened to still be alive. Also stop counting toolClientExecution entries as user-blocking. That entry means a client is running the tool, not that a user was asked, so it must not raise InputNeeded -- otherwise every client tool call flags the session as needing input for its whole duration, and an approved call keeps presenting as blocked. Mirrors microsoft/agent-host-protocol#380. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * agentHost: share one input-needed watcher per backend session Sibling resources (default, peer and subagent chats) can be open against the same backend session at once, and each installed its own session-level watcher over the same inputNeeded queue. Each had independent per-request state, so one client-tool request executed the tool once per open resource; _resolveToolCall only deduplicates the eventual dispatch, long after the tool's side effects have already run N times. Ref-count a single watcher per backend session instead, keeping it alive while any sibling holds a reference. The resource-to-backend mapping is recorded at install time rather than resolved during teardown, when provisional session state may already be gone. The claim registry now records which observer is rendering a request, so a claimed tool executes with that observer's chat context instead of whichever sibling happened to install the watcher. Also reattach the withInputNeededStatus documentation, which described the old "any non-empty queue" rule and had come loose from its function. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>github.com-microsoft-vscode · 180ee1eb · 2026-08-04
- 1.2ETVFix agent host MCP server state and add per-server diagnostics (#326384) * Fix agent host MCP server state and add per-server diagnostics Discovered MCP servers were seeded as `Starting` before any SDK had attempted to start them, and failures were only visible as a coarse status. This corrects the lifecycle state and adds diagnostics. - Seed `makeMcpServerCustomization` as `Stopped` instead of `Starting`; a declared-but-unstarted server has not begun connecting. - The Copilot SDK emits no live "starting" signal on initial connect (servers settle inside a blocking init phase and `rpc.mcp.list` blocks until settled), so drive `Starting` optimistically from the workbench at the two real start triggers: sending a message (`_markEnabledMcpServersStarting`) and the disable->enable flip. Added `McpCustomizationController.markStarting` (skips Ready/AuthRequired/Starting). - Log structured MCP lifecycle records (loaded/statusChanged/inventory) through the agent host's existing OTLP log stream with `OtelData` attributes, deduplicated by SDK status; failures log at error with the failure detail preserved in `McpServerErrorState`. - Give each `(session, MCP server)` its own hidden Output channel that records lifecycle transitions; "Show Output" reveals it. - Encapsulate the channel: `showMcpServerLog(sessionResource, serverId)` resolves and reveals internally; removed `logOutputChannelId` from the public `IAgentHostMcpServer` surface and the now-dead `getLogOutputChannelId` provider plumbing. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Address PR review: reliable MCP diagnostics + optimistic Start fixes - Record MCP diagnostics from state-change events over a tracked set of sessions rather than as a side effect of `getMcpServers`, so a failure and a later recovery are both captured even without a UI re-query. - Key the per-server log registry by the full session resource plus the raw customization id (not the UI-facing scoped id, whose authority is empty for Agents-window resources and would mix histories across sessions). - Use an injective, filesystem-safe channel id (SHA1 hex of the composite key) so distinct servers can't collapse onto one logger/dedup entry. - Dispose each session's loggers and Output channel registrations when the session goes away (session dispose / removal / provisional backend swap), fixing the logger/file-handle leak. - Route the explicit Start/Restart (`startMcpServer`) through `markStarting` so it shows Starting during the SDK's blocking reconnect, and always reconcile via a trailing inventory refresh (try/finally) so a rejected enable can't leave the UI stuck at Starting -- same fix applied to the enable path in `_reconcileMcpServerEnablement`. - Add coverage for the explicit-start optimistic Starting behavior. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix CI: stub ILoggerService/IOutputService in customization service test The MCP diagnostics registry now resolves `ILoggerService`/`IOutputService` lazily when `record` runs (via the new eager state recording). The enablement unit test instantiated the abstract service against a bare `TestInstantiationService`, so `getMcpServers` threw `this._loggerService.createLogger is not a function`. Stub both services (NullLoggerService + a minimal IOutputService) in the test harness. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>github.com-microsoft-vscode · 2a8e7fc4 · 2026-07-17
- 1.2ETVFix WSL remote agent host lifecycle (#320498) * Fix WSL remote agent host lifecycle Move WSL agent host providers to in-memory cached distro state, reconnect running distros through a dedicated contribution, and allow recent WSL workspaces to connect on demand with progress. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix WSL reconnect provider indentation Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix workspace picker notification service wiring Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix web workspace picker import order Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * fix --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>github.com-microsoft-vscode · a1ffdd33 · 2026-06-08
- 1.1ETVchat: keep the Ask Question widget anchored to its selection while scrolling (#328470) * chat: keep the Ask Question widget anchored to its selection while scrolling - Pins the transcript while text is selected or the question widget is open. A streaming response that scrolls itself to the bottom would otherwise drag the text out from under the selection the user is in the middle of making. - Converts the list's auto-scroll suppression from a boolean setter to a ref-counted hold. A boolean does not compose, so finishing a request edit would silently release a selection's suppression; holds let both features suppress concurrently. - Follows the transcript's own scroll event instead of a DOM scroll listener. The transcript is a virtualized list that scrolls by transform and never fires a DOM scroll event, so the widget previously stayed pinned where the selection used to be. - Confines the widget to the scrollable message area rather than the whole chat view, so it parks at the top or bottom edge of the transcript instead of drifting over the chat input. - Skips unrendered subtrees when resolving the selection endpoints. The transcript contains `<style>` elements and display:none metadata that a line selection spans but the user cannot see, which put the endpoint outside the response markdown and stopped triple-click from ever opening the widget. (Commit message generated by Copilot) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * chat: scope the auto-scroll hold to the transcript - Restricts the hold to selections inside the scrollable transcript. Selecting text elsewhere in the chat view (a banner, the input) says nothing about wanting the transcript to hold still. - Repairs the ChatListRenderer test stub, which still modelled the removed `suppressAutoScroll` boolean and broke once request editing started acquiring a hold. - Makes a hold's disposable idempotent so a double-dispose releases one hold instead of decrementing past it and cancelling another caller's. (Commit message generated by Copilot) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * chat: harden selection handling against virtualization and hidden nodes - Dismisses the affordance when the captured range stops covering anything. Removing a row re-homes any live range onto the surviving parent, so a virtualized-away selection still looks attached while anchoring to nothing, leaving the transcript pinned indefinitely. - Keeps `display: contents` wrappers in the endpoint walk. They have no box of their own, so a visibility check reports them as invisible even though their descendants render, and pruning them dropped valid text. - Respects the hold when a request is added, closing the one automatic scroll path that could still move the transcript out from under a selection. - Extracts the ref-counted hold into `AutoScrollHolds` so its composition and idempotent release are covered directly. (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 · 8a1d44aa · 2026-07-31
- 1.1ETVAdopt response-part input requests (#326203) * Adopt response-part input requests Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Address input request review feedback Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Keep input request conversion in adapter Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>github.com-microsoft-vscode · 77f74446 · 2026-07-16