* 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>
Visual Studio Code - Open Source ("Code - OSS")
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
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:
- Submit bugs and feature requests, and help us verify them as they are checked in
- Review source code changes
- Review the documentation and make pull requests for anything from typos to new content.
If you are interested in fixing issues and contributing directly to the codebase, please see the document How to Contribute, which covers the following:
- How to build and run from source
- The development workflow, including debugging and running tests
- Coding guidelines
- Submitting pull requests
- Finding an issue to work on
- Contributing to translations
Feedback
- Ask a question on Stack Overflow
- Request a new feature
- Upvote popular feature requests
- File an issue
- Connect with the extension author community on GitHub Discussions or Slack
- Follow @code and let us know what you think!
See our wiki for a description of each of these channels and information on some other available community-driven channels.
Related Projects
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.