511fd2d2ee agentHost: Claude per-session provider selection (#329331)
* agentHost: add provider-qualified Claude model-selection id codec

Pure precursor for per-session provider selection in the Claude harness.
Mirrors Codex's `@provider=` convention: toClaudeModelSelectionId encodes a
provider + model id into one opaque ModelSelection.id; parseClaudeModelSelection
splits it back, with a bare/malformed/legacy id defaulting to the Copilot
(proxy) provider so nothing needs a data migration. claudeTransportForProvider
maps the token to a transport (anthropic -> native, everything else -> proxy).

Dead code until the merged-catalog + per-session routing core wires it in;
landed first because it's a leaf with zero behavioral risk. Fully unit-tested
with no mocks, mirroring codexModelSelection.test.ts.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* agentHost: add merged-catalog + per-session transport resolvers for Claude

Two pure precursors for per-session provider selection, co-located with the
model-selection id codec and covered by the same test suite:

- mergeClaudeModelCatalogs(proxy, native): flattens the two provider catalogs
  into one picker list, proxy-first (preserving models[0]-is-default), each id
  provider-qualified so a row carries its transport and the same model under
  both providers yields two non-colliding rows. Either side may be empty so one
  source failing to fetch never blanks the other.
- resolveClaudeSessionTransport({ perSessionProviderEnabled, model, defaultMode }):
  the per-session counterpart to the host-global resolver — off, or no model,
  inherits the host default (identical to today); on, the selected model's
  provider decides.

Both are dead code until the flag-gated wiring lands; kept as a separately
reviewable, fully-tested unit.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* agentHost: wire Claude per-session provider flag into the backend read-path

Slice 2a (flag plumbing) + 2b (backend read-path) of per-session provider
selection for the Claude agent host, gated behind the off-by-default
experimentation flag `chat.agentHost.claude.perSessionProvider`.

Flag plumbing (2a): register the boolean setting (APPLICATION scope,
experimental/advanced), its customization-config key, and the forwarder
contribution.

Backend read-path (2b): ClaudeAgent merges the proxy (Copilot-CAPI) and
native (Anthropic) model catalogs into one provider-qualified picker list,
and resolves each session's transport from its selected model's provider
when the flag is on (inheriting the host default when off, or when no model
is selected).

Review fixes folded in:
- A: gate the constructor / hydration model-refresh on the flag so the
  native catalog bootstraps signed-out without a manual refresh.
- B: _resolveParentSession inherits a never-materialized parent's provisional
  model so a forked peer chat keeps its native transport.
- C: a runtime flag toggle re-enumerates and repopulates the merged catalog.
- D: a failing proxy start no longer fails native-default sign-in.
- E: toClaudeSdkModelId strips the `@provider=` qualification before the SDK /
  CAPI boundary — the wrapper is unparseable downstream and would 400 both
  transports whenever the flag is on and a model is explicitly selected.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* agentHost: guard Claude model refresh against a mid-flight per-session provider toggle

The refresh stale-write guards captured only the transport token/mode, not the
per-session provider flag. Because `_startModelRefresh` supersedes an in-flight
refresh as the coalescing target but never cancels it, a false-flip of the flag
mid-refresh left the superseded refresh running; when it settled it published a
stale wrong-mode catalog (merged provider-qualified over the bare single-transport
list the flag-off refresh had already published, or vice versa), clobbering the
correct one.

Capture `_perSessionProviderEnabled` at the start of both `_refreshModelsSingle`
and `_refreshModelsMerged` and bail in the stale-write guard when it moved, so the
superseded refresh drops its result.

Tests: a flag-on→off toggle mid-merge (native half parked on a gate so the merged
refresh is provably still in-flight) asserts the bare single catalog survives the
straggler; and a flag-off regression that a forked peer chat still inherits its
never-materialized parent's explicit model (the inheritance in `_resolveParentSession`
is intentionally not flag-gated).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* agentHost: group Claude models by transport provider in the picker

With per-session provider selection on, the merged catalog now stamps each
model's `provider` with its transport token (`copilot` for the Copilot-CAPI
proxy, `anthropic` for the user's own Anthropic account) alongside the
provider-qualified id, so the chat model picker — which buckets by
`provider` — splits Claude into a Copilot group and an Anthropic group. The
same model offered by both transports yields two distinct, separately
selectable rows.

- common/claudeProviders.ts (new): the two transport-provider tokens live in
  one `common` module so the backend that stamps `model.provider` and the
  frontend vendor descriptor that names the group are a single,
  compile-checked source of truth rather than two literals that can drift.
- claudeModelSelection.ts: `withQualifiedProvider` re-stamps each model's
  `provider` with its transport token; re-exports the tokens for node callers.
- agentHostChatContribution.ts: register the `anthropic` group vendor
  (localized "Anthropic"), mirroring the Codex `chatgpt` second-vendor
  registration, so the native group resolves a clean label. Copilot-routed
  Claude models keep grouping under the global `copilot` vendor. Dormant while
  the flag is off — no Claude model carries the `anthropic` provider then.
- claudeAgent.ts: correct the stale `toAgentModelInfo` doc — the picker
  *groups* (does not filter) by `provider`.

Flag-off path is unchanged: the single-catalog refresh still stamps the
harness provider and no second vendor is registered.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* agentHost: live per-session provider switching, unconditional

Complete the Claude per-session provider feature. Switching a live
session's model to one on a different transport now re-routes the running
subprocess, and the feature ships unconditionally (no experimental flag).

Live provider switch:
- Refactor IMaterializeContext.transport into a resolveTransport callback so
  the transport is re-resolved inside materialize and on every rebuild — a
  provider switch re-routes the rebuilt subprocess onto the new transport.
- A cross-transport model change defers via a pending-switch flag; the next
  send() rebuilds onto the newly-selected transport and commits it once the
  new subprocess is live. Same-transport changes still hot-swap in place.

Remove the experimental flag:
- Delete chat.agentHost.claude.perSessionProvider, revert the generic flag
  plumbing, and delete the setting-to-root-config forwarder contribution.
- Collapse the per-session-provider gates in claudeAgent.ts to always-on and
  remove the now-dead members.
- Drop the perSessionProviderEnabled parameter from
  resolveClaudeSessionTransport; bare/legacy ids still resume on the host
  default transport with no migration.
- Add modelProviders to the e2e CLAUDE_CONFIG and de-flag the unit tests.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* agentHost: simplify Claude per-session transport resolution

Follow-up cleanup on the per-session-provider read-path, now that the
feature is unconditional and the single-catalog path is gone.

- Collapse the cached `_transportMode` and its reactive
  `_resolveTransportMode`/`_applyTransportModeChange` machinery into a
  read-on-demand `_defaultTransportMode()`. The host default is only the
  fallback for model-less / bare-id sessions, so it needs no caching or
  config/sign-in re-resolve — the next session reads live availability.
- `authenticate()`: a Copilot proxy-start failure is now uniformly soft.
  GitHub sign-in still succeeds and both `_githubToken` and `_proxyHandle`
  stay uncommitted, so a retry re-attempts `start()`; a Copilot-routed
  model re-drives sign-in on its first send. Drops the native/proxy
  default special-casing and the mid-flight transport-mode flip.
- Replace `IMaterializeContext.resolveTransport` (a callback the session
  re-invoked on every rebuild) with a `transport` value the agent pins at
  materialize. A per-session provider switch is pushed in through `send`'s
  new `switchTransport` (staged in `_pendingSwitchTransport`); ordinary and
  SDK-recover rebuilds reuse the materialized transport. A throwing guard
  replaces the defensive re-resolve.
- Move cross-transport switch detection into `ClaudeAgentSession.setModel`
  (the session owns it); drop the agent-computed `deferForTransportSwitch`
  option and expose `hasPendingTransportSwitch` in place of `transportKind`.
- Inline the one-off `_settledCatalog` helper into `_refreshModels` and drop
  the `_refreshModels` -> `_refreshModelsMerged` forwarder.
- Drop the now-unused provider-token re-export from `claudeModelSelection`;
  tests import the tokens from `common/claudeProviders` directly.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* agentHost: address Claude per-session provider review feedback

Fixes five review comments on the per-session provider slice:

- Keep IAgentModelInfo.provider as the `claude` routing owner and carry the
  transport/group token in `_meta.modelGroupId`, so a model-selected
  create_session no longer misroutes to a `copilot`/`anthropic` agent that
  the node provider registry can't resolve.
- Drop the agent-host `anthropic` picker vendor that clobbered the Copilot
  extension's shared `anthropic` vendor on dispose; reuse the shared one.
- On a replacement-token proxy start() failure, tear down the stale account
  (handle, token, and merged catalog) instead of leaving it live behind a
  "successful" sign-in that would silently serve the superseded account.
- Guard setModel's cross-transport detection on an explicit provider so a
  bare/legacy id (parser-fallback `copilot`) can't spuriously reroute a
  native session.
- Condense the over-long rematerializer transport-pinning comment.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-07 08:29:20 +00:00
2026-08-04 02:51:43 +00:00
2026-07-12 20:30:31 +00:00

Visual Studio Code - Open Source ("Code - OSS")

Feature Requests Bugs Gitter

The Repository

This repository ("Code - OSS") is where we (Microsoft) develop the Visual Studio Code product together with the community. Not only do we work on code and issues here, but we also publish our roadmap, monthly iteration plans, and our endgame plans. This source code is available to everyone under the standard MIT license.

Visual Studio Code

VS Code in action

Visual Studio Code is a distribution of the Code - OSS repository with Microsoft-specific customizations released under a traditional Microsoft product license.

Visual Studio Code combines the simplicity of a code editor with what developers need for their core edit-build-debug cycle. It provides comprehensive code editing, navigation, and understanding support along with lightweight debugging, a rich extensibility model, and lightweight integration with existing tools.

Visual Studio Code is updated monthly with new features and bug fixes. You can download it for Windows, macOS, and Linux on the Visual Studio Code website. To get the latest releases every day, install the Insiders build.

Contributing

There are many ways in which you can participate in this project, for example:

If you are interested in fixing issues and contributing directly to the codebase, please see the document How to Contribute, which covers the following:

Feedback

See our wiki for a description of each of these channels and information on some other available community-driven channels.

Many of the core components and extensions to VS Code live in their own repositories on GitHub. For example, the node debug adapter and the mono debug adapter repositories are separate from each other. For a complete list, please visit the Related Projects page on our wiki.

Bundled Extensions

VS Code includes a set of built-in extensions located in the extensions folder, including grammars and snippets for many languages. Extensions that provide rich language support (inline suggestions, Go to Definition) for a language have the suffix language-features. For example, the json extension provides coloring for JSON and the json-language-features extension provides rich language support for JSON.

Development Container

This repository includes a Visual Studio Code Dev Containers / GitHub Codespaces development container.

  • For Dev Containers, use the Dev Containers: Clone Repository in Container Volume... command, which creates a Docker volume for better disk I/O on macOS and Windows.

    • If you already have VS Code and Docker installed, you can also click here to get started. This will cause VS Code to automatically install the Dev Containers extension if needed, clone the source code into a container volume, and spin up a dev container for use.
  • For Codespaces, install the GitHub Codespaces extension in VS Code, and use the Codespaces: Create New Codespace command.

Docker / the Codespace should have at least 4 cores and 6 GB of RAM (8 GB recommended) to run a full build. See the development container README for more information.

Code of Conduct

This project has adopted the Microsoft Open Source Code of Conduct. For more information, see the Code of Conduct FAQ or contact opencode@microsoft.com with any additional questions or comments.

License

Copyright (c) Microsoft Corporation. All rights reserved.

Licensed under the MIT license.

S
Description
Visual Studio Code
Readme
2.3 GiB
Languages
TypeScript 79.2%
jsonc 16.6%
CSS 1.4%
JavaScript 0.6%
C 0.6%
Other 1.3%