* chat plugins: add policy-backed enabledPlugins / marketplaces / strictMarketplaces settings Adds three new chat.plugins.* settings, each policy-backed: - chat.plugins.enabledPlugins (policy: objectChatEnabledPlugins) mapping plugin IDs (`<plugin>@<marketplace>`) to enable/disable. - chat.plugins.marketplaces (policy: array ofChatPluginMarketplaces) marketplace references (GitHub shorthand or Git URI). User entries survive alongside policy entries. - chat.plugins.strictMarketplaces (policy: ChatStrictMarketplaces) boolean restricting trust to listed marketplaces only. All three are gated on `tags: ['experimental']`. Consumers (plugin discovery, install, URL handler, marketplace service, quick-pick action) now read via `inspect()` so default + user + policy layers all flow through. A shared `readConfiguredMarketplaces` helper in marketplaceReference.ts dedups the inspect pattern across 5 sites. Adds three matching fields to IPolicyData so the policy framework has slots to fill in once the wiring lands; until then they're undefined and behave like an empty policy (no-op). Plugin discovery now distinguishes filesystem-path entries (removable from UI) from enterprise plugin IDs (non-removable) via a single shared loop; `IAgentPlugin.remove` is optional accordingly. build/lib/policies/policyData.jsonc regenerated for the new policy keys. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * policy: implement ADR-002 enterprise managed_settings fetch & policy wiring Wires the previously-added chat.plugins.* policy slots to the new `/copilot_internal/managed_settings` endpoint on the authenticated Copilot host. Core behavior in DefaultAccountProvider: - Fetches managed_settings alongside entitlements; shares the 1-hour cache used by other account-policy fetches. - Silent fallback to local-only policy on any non-2xx, network error, parse error, or missing managedSettingsUrl. - Rate-limit-aware: backs off all /copilot_internal/* calls when the endpoint signals 429, 403 + X-RateLimit-Remaining: 0, or any non-2xx with Retry-After. - adaptManagedSettings flattens the API's structured extraKnownMarketplaces map into the existing string-array shape that chat.plugins.marketplaces consumes; tolerates malformed entries and unknown response keys (forward-compatible). - Telemetry: emits `defaultaccount:managedSettings:fetch` (owner: joshspicer) with an `outcome` bucket (ok / no-response / parse-error / status:NNN) and a `rateLimitBackoffActive` flag. Surface area: - IDefaultAccountProvider/Service expose managedSettingsFetchStatus and managedSettingsFetchedAt; ManagedSettingsFetchStatus is a named union. - Developer: Policy Diagnostics shows a Managed Settings section with the URL status, last-fetched timestamp, and a JSON dump of the applied managed-settings policy slice. - product.json adds a managedSettingsUrl key (populated via distro). Refactor: `readHeader` and `retryAfterFromHeaders` are moved to `platform/request/common/request.ts` so githubRepoFetcher.ts and this new code share one implementation. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * bump distro to 36d906669669f12466c6912bd65d9eeb47c6522d Pulls in managedSettingsUrl from microsoft/vscode-distro#1422. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * update policyData * policy: address PR review feedback - Restore historical default for chat.plugins.marketplaces (['github/copilot-plugins', 'github/awesome-copilot#marketplace']) so existing users don't lose the two built-in marketplaces on update. Regenerate policyData.jsonc accordingly. - Seed _managedSettingsFetchStatus = 'ok' on cache-hit so Policy Diagnostics reports the applied state after a process restart that warm-starts from cached policyData (instead of stuck at 'not yet fetched'). - Scope the <plugin>@<marketplace> ID-resolution rule to the enterprise ChatEnabledPlugins setting only. User-typed entries in chat.pluginLocations that happen to contain '@' are now treated as filesystem paths, as a user would expect, not silently rewritten to ~/.copilot/installed-plugins/<x>/<y>/. Split _resolvePluginPath into a path-only resolver and a dedicated _resolveEnterprisePluginId. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * policy: revert unnecessary _pluginLocationsConfig refactor chat.pluginLocations has no policy slot, so observableConfigValue (which uses getValue() under the hood) is functionally equivalent to the hand-rolled inspect() version. Reverting reduces diff thechurn inspect-based observable is now used only for _enterpriseEnabledPluginsConfig where the default+user+policy merge actually matters. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * policy: split managed marketplaces into dedicated policy-only setting Adds chat.plugins.extraMarketplaces (ChatExtraMarketplaces policy, included: false so it's hidden from the Settings UI). This receives the 'extraKnownMarketplaces' payload from the managed_settings API. Restores chat.plugins.marketplaces to its pre-PR shape: no policy slot, no inspect()-juggling required in consumers, no risk of accidentally clobbering user data. Users write to chat.plugins.marketplaces; the enterprise writes to chat.plugins.extraMarketplaces; the effective set is the union. Consumer simplifications: - readConfiguredMarketplaces returns { userValues, extraValues, two getValue() reads, no inspect() needed.effectiveValues } - Write-back is now just [...userValues, refValue] in all three sites. - 'Manage Plugin Marketplaces' still surfaces the 'managed by enterprise policy' badge by checking ref membership in extraValues. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * policy: tidy managed_settings code paths - fetchMarketplacePlugins: drop the over-engineered pre-dedup-by-string; parseMarketplaceReferences already dedups by canonical id. - agentPluginServiceImpl: pass source.remove directly to _toPlugin instead of wrapping in a null-asserted closure. - adaptManagedSettings: use a Set for flatten-and-dedup (insertion order is preserved). - getDefaultAccountFromAuthenticatedSessions: spread merge instead of three explicit field assignments. - developerActions: collapse the 'ok' branch into the catch-all backtick wrap; same behavior, less code. - marketplaceReference.ts: tighter JSDoc on IConfiguredMarketplaces. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * policy: enforce ChatEnabledPlugins and strict-marketplace gates at discovery Previously the enterprise-managed policy values were delivered into the policy framework but not a plugin already installed locallyenforced (e.g. via the marketplace discovery path) would remain active even when the policy excluded it or strict-marketplace mode rejected its source. Adds policy enforcement on AgentPluginService.plugins, applied after discovery dedup/sort and gated by two observables: - ChatEnabledPlugins policy: when set, filters the surfaced plugin set to only those whose '<name>@<marketplace>' ID appears in the policy map with value true. Plugins without a marketplace provenance (filesystem entries from chat.pluginLocations) are unaffected. - ChatStrictMarketplaces: when on, filters out plugins whose source marketplace is not trusted. Trust is sourced ONLY from chat.plugins.extraMarketplaces (the policy-only user-setslot) entries in chat.plugins.marketplaces do NOT grant trust under strict mode. This matches the ADR-002 semantics: strict mode hands full marketplace control to the enterprise. Also updates the chat.plugins.strictMarketplaces description text to match the new behavior (was still pointing at the user setting). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * policy: extract managed_settings adapter to dedicated helper Moves IManagedSettingsResponse and adaptManagedSettings out of defaultAccount.ts and into a new managedSettings.ts in the same folder. Adapter is a pure transformation function with no service dependencies, so it belongs in its own file alongside the HTTP/wiring code. Renames the test file to managedSettings.test.ts to match what it actually tests and tightens the suite name. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * policy: tidy enforcement filter and sync strict-marketplace policy description Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * policy: show policy-blocked plugins as disabled instead of hiding them Blocked plugins (ChatEnabledPlugins / strict marketplaces) now stay visible but are forced disabled via their enablement observable, and the enable affordance notifies the user instead of re-enabling. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * policy: enforce enabledPlugins/strictMarketplaces for Copilot-CLI plugins CLI-installed plugins under `~/.copilot/installed-plugins/<marketplace>/<plugin>/` have no `fromMarketplace` metadata, so they previously bypassed enterprise policy. Derive their identity from the install-path bucket (matching the convention used by `_resolveEnterprisePluginId`) so enabledPlugins gating applies, and add a bucket-name heuristic for strict marketplaces. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * log raw managed_settings response at trace level Helps debug schema drift / unknown server fields that get dropped by adaptManagedSettings(). Trace-only so it's off by default. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * improve managed_settings warning for missing repo/url When a github source is missing 'repo' or a git source is missing 'url', emit a specific warning naming the missing field instead of the misleading 'unknown source type' message. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * preserve marketplace name through managed_settings policy delivery The managed_settings adapter previously flattened extraKnownMarketplaces entries to bare "<owner>/<repo>" or "<url>" strings, losing the marketplace name. That broke enabledPlugins matching because plugin IDs are keyed as "<plugin>@<marketplace-name>" but our parsed reference's displayLabel was derived from the URL/repo instead. Changes: - adapter now emits { name, source } objects preserving the full shape - IPolicyData.extraKnownMarketplaces accepts string | object entries - parseMarketplaceReferences gains object-handling, using name as displayLabel - workspacePluginSettingsService shares the object parser - policy schema relaxed to allow object items Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * policy: clarify chat.plugins.enabledPlugins description The previous 'Merged with entries from chat.pluginLocations' was misleading: the two settings use different key namespaces (plugin IDs vs filesystem paths) and the enabledPlugins policy also acts as an allowlist that gates marketplace-discovered not a symmetric merge.plugins Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * policy: add description for chat.plugins.extraMarketplaces The setting was missing a markdownDescription, so the Settings UI card rendered empty when shown under 'Managed by organization'. Also updated the policy localization to mention the new { name, source } object form. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * policy: shorten chat.plugins.extraMarketplaces description Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * policy: drop policy name from extraMarketplaces description Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * policy: re-fetch plugin marketplaces when ExtraMarketplaces policy changes pluginMarketplaceService.onDidChangeMarketplaces only listened for PluginsEnabled and PluginMarketplaces config changes, so the ExtraMarketplaces values delivered by the ChatExtraMarketplaces policy never triggered a the union was stale until the next user editrefetch to chat.plugins.marketplaces or a workspace-trust change. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * policy: extract IExtraKnownMarketplaceEntry to base/common/managedSettings Move the enterprise-managed marketplace entry type out of defaultAccount.ts into a dedicated managedSettings.ts so the type lives alongside other managed-settings-specific code. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * policy: cleanup pass - Sync policyData.jsonc ChatExtraMarketplaces description with the source declaration in chat.shared.contribution.ts (object-form entries were missing from the policy artifact). - Reorder Event import in agentPluginServiceImpl.ts to keep base/common imports alphabetical. - Fix stale doc reference (COPILOT_CLI_INSTALLED_PLUGINS_DIR -> the function it actually mirrors). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * policy: accept host-only git URLs in extraKnownMarketplaces ADR-002 describes the `git` source `url` as a free-form `(string)` the example happens to be a full clone URL, but the schema doesn't require a repo path. Our marketplace-URI parser was rejecting host-only HTTPS endpoints (e.g. `https://plugins.internal.example.com`), so enterprise policy entries with marketplace-registry-style URLs were silently dropped before they ever reached the UI. Relax `parseUriMarketplaceReference` to accept host-only URLs and treat them as a marketplace endpoint identified by host alone. The canonical id becomes `git:<host>/` so distinct hosts still dedupe correctly. Existing path-aware behavior is preserved unchanged. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * policy: fix string entry guard in extraKnownMarketplaces policy.value; fix test cloneUrl expectation - Handle string-typed entries in extraKnownMarketplaces (IPolicyData allows string | IExtraKnownMarketplaceEntry) - Fix test expectation: URI.parse normalizes host-only URLs to include trailing slash Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * policy: read extraMarketplaces dict and convert to nested entry shape The setting schema is now `{ [name]: url-or-shorthand }` (object), so readConfiguredMarketplaces must convert each entry to the nested IExtraMarketplaceObjectEntry shape that parseMarketplaceReferences expects. Uses a regex to detect GitHub shorthand (owner/repo[#ref]) vs URI. TypeError in CI: 'extraValues is not iterable' on [...userValues, ...extraValues]. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * policy: extract extraKnownMarketplacesToConfigDict helper + add regression tests for Settings Editor display Extract the policy.value conversion for ChatExtraMarketplaces out of chat.shared.contribution.ts into a reusable, unit-testable helper. The helper converts the IExtraKnownMarketplaceEntry[] policy payload into the { [name]: url-or-shorthand } dict that: - the Settings Editor's ComplexObject renderer can display inline as key/value rows (instead of just 'Edit in settings.json'), and - readConfiguredMarketplaces reverses back into IExtraMarketplaceObjectEntry[] so parseMarketplaceReferences preserves displayLabel = name. Tests added: undefined owner/repo owner/repo#ref raw URL (+ optional #ref) parseMarketplaceReferences flow (the regression test that catches the 'extraValues is not iterable' bug we just hit in CI) - schema-shape: chat.plugins.extraMarketplaces is registered with type=object + additionalProperties.type=['string'], the exact shape the Settings Editor requires to render as ComplexObject Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * policy: stop spurious 'invalid marketplace entry' warnings for object-form entries url dict, policy entries always reach the marketplace fetcher as IExtraMarketplaceObjectEntry objects (not strings). The validation loop was only accepting strings, producing a 'Ignoring invalid marketplace entry: [object Object]' debug log for every valid policy entry. Validate using parseMarketplaceObjectEntry for object values so the warning fires only for genuinely-unparseable entries. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * policy: drop schema-shape test that double-registered chat contribution commands The schema-shape test for chat.plugins.extraMarketplaces imported the full chat.shared.contribution module to populate the configuration registry. This re-registered commands (already registered by the workbench under test), producing 'Cannot register two commands with the same id: workbench.action.chat.markHelpful' and cascading disposable leaks in unrelated suites (EditorService, WorkingCopyBackupTracker). The other 5 tests (extraKnownMarketplacesToConfigDict + end-to-end round trip) cover the actual behavior that broke; the schema shape is exercised implicitly by the round-trip test. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * policy: normalize github.com URI/SSH refs to the GitHub shorthand canonical id Plugin marketplace trust under strict mode compares canonicalId. A plugin discovered from 'https://github.com/microsoft/vscode-team-kit.git' was being blocked even though 'microsoft/vscode-team-kit' was in the trusted list, because the URI parser produced 'git:github.com/microsoft/vscode-team-kit.git' while the shorthand parser produced 'github:microsoft/vscode-team-kit'. When parseUriMarketplaceReference / parseScpMarketplaceReference detect a github.com authority, emit the same canonical id form the shorthand parser uses so all three forms (shorthand, https URI, SCP) collapse to a single trusted reference. Existing dedup test now expects 1 entry instead of 2; ref-distinction test collapses the https+#ref entry with its shorthand sibling. Added a focused regression test asserting all four forms produce identical canonical ids. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * update policy * fix dupe policy export --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.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 Visual Studio Code's 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 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 code base, 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.