Install lsp plugin - #9782
Install lsp plugin#9782dibarbet wants to merge 7 commits into
Conversation
fa37bbb to
df12ab7
Compare
df12ab7 to
06d21a6
Compare
There was a problem hiding this comment.
Copilot review overview
🟡 Changes recommended
New user-facing strings/settings were added without propagating them to the checked-in locale bundles (package.nls.* and l10n/bundle.l10n.*), which will leave translations incomplete.
Get a fresh assessment by requesting another Copilot review.
Review effort: Lite
Findings: 3
Open (3)
What changed in this PR
Adds an automatic installer for the GitHub Copilot “dotnet” plugin (from dotnet-agent-skills) to the C# extension, including Copilot CLI discovery/execution support, telemetry, user messaging, tests, and documentation so the feature is observable and user-controllable.
Changes:
- Introduces Copilot CLI discovery + execution helpers and a
.NET pluginauto-install flow with caching/telemetry. - Wires the installer into extension activation and adds unit tests covering install, caching, failure, timeout, and cancellation paths.
- Documents the feature and adds a user setting to disable auto-install.
| File | Description |
|---|---|
| test/lsptoolshost/unitTests/dotnetPlugin.test.ts | Unit tests for plugin auto-install behavior, caching, and failure/timeout/cancel flows. |
| test/lsptoolshost/unitTests/copilotCli.test.ts | Unit tests for Copilot CLI discovery, execution, and plugin list parsing. |
| src/shared/telemetryEventNames.ts | Adds telemetry event names for plugin install success/failure reporting. |
| src/shared/copilot/dotnetPlugin.ts | Implements the auto-install + caching + telemetry + user notification logic. |
| src/shared/copilot/copilotCli.ts | Implements CLI discovery (standalone/app) + execFile wrapper + inventory parsing. |
| src/main.ts | Starts plugin registration/installation during activation (non-test extension mode). |
| README.md | Adds a link to the new Copilot .NET plugin documentation. |
| package.nls.json | Adds localized string key for the new auto-install setting description. |
| package.json | Adds the dotnet.copilotDotnetPlugin.enableAutoInstall setting contribution. |
| l10n/bundle.l10n.json | Adds localized UI strings used by the install notification. |
| docs/readme.md | Adds doc index entry for Copilot .NET plugin install/removal. |
| docs/Copilot-Dotnet-Plugin.md | Adds end-user documentation for install rationale, disabling, uninstall, and troubleshooting. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
| To uninstall make sure all Copilot / VSCode instances are closed, then: | ||
| 1. For the Copilot CLI, run `copilot plugin uninstall dotnet@dotnet-agent-skills` | ||
| 2. For the GitHub Copilot App, go to `Customize`, select the `Plugins` tab and right click to uninstall the `dotnet` plugin from `dotnet-agent-skills` |
| channel: DotnetPluginHost['channel'] | ||
| ): void { | ||
| const host: DotnetPluginHost = { context, reporter, channel }; | ||
| const controller = new AbortController(); |
There was a problem hiding this comment.
Looks like AbortController is used instead of CancellationTokenSource so that we can return a cancellation reason.
| } | ||
| } | ||
|
|
||
| function blockedReason(): Outcome | undefined { |
| finishInstallation(host, result); | ||
| } | ||
|
|
||
| function finishInstallation(host: DotnetPluginHost, result: InstallResult): void { |
| return undefined; | ||
| } | ||
|
|
||
| function readCache(context: DotnetPluginHost['context']): Cache | undefined { |
| return cache?.extensionVersion === context.extension.packageJSON.version ? cache : undefined; | ||
| } | ||
|
|
||
| function deadline(signal: AbortSignal): { signal: AbortSignal; done: () => void } { |
There was a problem hiding this comment.
Feel like this would be cleaner if it were done where we create the controller. We already add hook extension disabled from there.
| } | ||
| } | ||
|
|
||
| function enabledOutcome(plugins: CopilotPlugin[]): CachedOutcome { |
| return { signal: AbortSignal.any([signal, timer.signal]), done: () => clearTimeout(handle) }; | ||
| } | ||
|
|
||
| async function listPlugins(cli: CopilotCli, signal: AbortSignal): Promise<CopilotPlugin[]> { |
| * Installs only when automatic installation and AI are enabled, the workspace is trusted, Copilot is available, | ||
| * and no existing or conflicting .NET plugin is found. Stable results are cached per extension version. | ||
| */ | ||
| export async function installDotnetPlugin(host: DotnetPluginHost, signal: AbortSignal): Promise<void> { |
There was a problem hiding this comment.
Feel like this should be merged with registerDotnetPlugin. The separation seems to exist only for testing purposes.

No description provided.