VSCode создавался с прицелом на возможность расширения функционала с помощью плагинов. От UI интерфейса до своих AI агентов — почти каждую часть VS Code можно настроить и улучшить с помощью VSCode API. Многие части самого VSCode фактически являются плагинами.
Есть подробная документация по созданию своего плагина, а большое количество "мини-плагинов" с демонстрацией возможностей можно найти в репозитории vscode-extension-samples. Сама dts-ка с описанием API есть в основной репе microsoft/vscode вот тут. Кроме src/vscode-dts/vscode.d.ts в директории еще много других файлов в формате vscode.proposed.*.d.ts. Это экспериментальное API. О нем и пойдет речь в данной статье.
Что и как?
Плагин github-copilot (для inline-подсказок) использует следующие proposed API
// package.json плагина github-copilot { ... "enabledApiProposals": [ "inlineCompletionsAdditions" ], ... }
Это почти все необходимое, чтобы ваш плагин использовал какое-нибудь proposed API. Еще к сорцам плагина необходимо добавить dts-ку соответствующего API. Это удобно делать с помощью пакета @vscode-dts.
Microsoft рекомендует использовать такие расширения только в VSCode Insiders - специальной dev версии VSCode. Это связано с тем, что proposed API не стабильно и может кардинально измениться в следующем релизе VSCode (в статье будет пример).
Использование в привычном VSCode тоже возможно, но есть одно ограничение - ваш VSCode, если его не попросить, не сможет использовать функционал плагина, основанный на proposed API (так не всегда, но об этом позже). Попросить можно так: отредактировать аргументы загрузки самого VSCode, т.е. выполнить команду Preferences: Configure Runtime Arguments и добавить туда
// file .vscode/argv.json { ... "enable-proposed-api": ["<YOUR-EXTENSION-ID>"] }
Ну и главное - расширение, которое использует proposed API, нельзя публиковать в официальный Extensions Marketplace. Придется устанавливать через команду Install from VSIX.
Генерация commit message
Рассмотрим пример того, как расширение github-copilot-chat генерит commit message. Для этого оно использует proposed API под названием contribSourceControlInputBoxMenu. Это API позволяет добавлять кнопку к input блоку в Source Control меню и что-то туда записывать. Выглядит это следующим образом

Фактически это API позволяет работать с scm/inputBox (который скоро будет полностью заменен на SourceControl интерфейс). Использование выглядит очень просто
const repo: git.Repository = ...; repo.inputBox.value = 'My awesome commit message';
В плагине задается следующим образом
// package.json плагина github-copilot-chat { "enabledApiProposals": [ "contribSourceControlInputBoxMenu" ], "contributes": { "commands": [ { "command": "github.copilot.git.generateCommitMessage", "title": "%github.copilot.git.generateCommitMessage%", "icon": "$(sparkle)", "enablement": "!github.copilot.interactiveSession.disabled", "category": "GitHub Copilot" }, ... ], ... }, ... }
Сама кнопка с иконкой $(sparkle) , а при нажатии просто вызывается команда github.copilot.git.generateCommitMessage.
Стабильность
Proposed API - штука не стабильная. Хороший пример - это proposed API под названием interactive. Proposal довольный старый и до версии 1.89.0 позволял добавлять в свой плагин inline чат. Выглядело так

Но теперь этот proposal (как и все чатовые proposals) доступны только с авторизованным github copilot и только как интеграция в github-copilot-chat.
Пример
Напишем игрушечный плагин, который показывает cwd shell-integration терминала при запуске команды. Для этого используем proposed API под названием terminalShellIntegration.
Создадим свой awesome sample проект через yo

Разбирать детально структуру не будем, разберем только package.json и src/extension.ts
// package.json { "name": "awesomesample", "displayName": "awesomeSample", "publisher": "awesomePublisher", ... "activationEvents": [ "onStartupFinished" ], "enabledApiProposals": [ "terminalShellIntegration" ], ... }
Чтобы использовать proposed API сначала установим @vscode/dts
> npm i @vscode/dts
, а затем запустим
> npx vscode-dts dev Downloading vscode.proposed.terminalShellIntegration.d.ts To: /Users/d.artyushin/Documents/habr/github-copilot-proposed-api/awesomesample/vscode.proposed.terminalShellIntegration.d.ts From: https://raw.githubusercontent.com/microsoft/vscode/main/src/vscode-dts/vscode.proposed.terminalShellIntegration.d.ts Read more about proposed API at: https://code.visualstudio.com/api/advanced-topics/using-proposed-api
В корне проекта должен появиться файл vscode.proposed.terminalShellIntegration.d.ts с описанием доступного API. Используем его
// src/extension.ts import * as vscode from 'vscode'; export function activate(context: vscode.ExtensionContext) { // подписываемся на запуск команды в т��рминале const terminalCwd = vscode.window.onDidStartTerminalShellExecution((event) => { // event имеет тип vscode.TerminalShellExecutionStartEvent // если shellIntegration есть, то у него берем поле cwd const currentCwd = event.terminal.shellIntegration?.cwd; if (currentCwd === undefined) { vscode.window.showInformationMessage('No found cwd :('); } else { vscode.window.showInformationMessage(`Cwd is ${currentCwd}`); } }); context.subscriptions.push(terminalCwd); } export function deactivate() {}
Нужно не забыть добавить в argv.json строку (попробуйте сначала запустить плагин без этого)
// .vscode/argv.json { ... // Enable proposed API features. "enable-proposed-api": ["awesomePublisher.awesomesample"], }
Наконец, запускаем плагин и пробуем команду ls в zsh и bash:


Proposed API в плагинах Copilot
Обычно github тестирует свои новые API на плагине github-copilot-chat. Вот пример
// package.json плагина github-copilot-chat { ... "enabledApiProposals": [ "interactive", "terminalDataWriteEvent", "terminalExecuteCommandEvent", "terminalSelection", "terminalQuickFixProvider", "chatParticipantAdditions", "defaultChatParticipant", "embeddings", "chatVariableResolver", "chatProvider", "mappedEditsProvider", "aiRelatedInformation", "codeActionAI", "findTextInFiles", "textSearchProvider", "commentReveal", "contribSourceControlInputBoxMenu", "contribCommentEditorActionsMenu", "contribCommentThreadAdditionalMenu", "contribCommentsViewThreadMenus", "newSymbolNamesProvider", "findFiles2", "extensionsAny", "authLearnMore", "testObserver", "aiTextSearchProvider", "documentFiltersExclusive", "chatParticipantPrivate", "lmTools" ], ... }
Справедливый вопрос: "Как тогда github публикует свои плагины в Extension Marketplace?". В исходном коде VSCode можно найти следующий код
... // NEW world - product.json spells out what proposals each extension can use if (productService.extensionEnabledApiProposals) { for (const [k, value] of Object.entries(productService.extensionEnabledApiProposals)) { const key = ExtensionIdentifier.toKey(k); const proposalNames = value.filter(name => { if (!allApiProposals[<ApiProposalName>name]) { _logService.warn(`Via 'product.json#extensionEnabledApiProposals' extension '${key}' wants API proposal '${name}' but that proposal DOES NOT EXIST. Likely, the proposal has been finalized (check 'vscode.d.ts') or was abandoned.`); return false; } return true; }); this._productEnabledExtensions.set(key, proposalNames); } } } updateEnabledApiProposals(extensions: IExtensionDescription[]): void { for (const extension of extensions) { this.doUpdateEnabledApiProposals(extension); } } ...
Коммент в коде говорит сам за себя. Файл product.json после установки VSCode находится по пути (для MacOS) /Applications/Visual Studio Code.app/Contents/Resources/app/product.json . Там для "важных" расширений как раз указаны доступные proposal API
{ ... "extensionEnabledApiProposals": { ... "GitHub.copilot": [ "inlineCompletionsAdditions" ], "GitHub.copilot-nightly": [ "inlineCompletionsAdditions" ], "GitHub.copilot-chat": [ "interactive", "terminalDataWriteEvent", "terminalExecuteCommandEvent", "terminalSelection", "terminalQuickFixProvider", "chatParticipantAdditions", "defaultChatParticipant", "embeddings", "chatVariableResolver", "chatProvider", "mappedEditsProvider", "aiRelatedInformation", "codeActionAI", "findTextInFiles", "textSearchProvider", "commentReveal", "contribSourceControlInputBoxMenu", "contribCommentEditorActionsMenu", "contribCommentThreadAdditionalMenu", "contribCommentsViewThreadMenus", "newSymbolNamesProvider", "findFiles2", "extensionsAny", "authLearnMore", "testObserver", "aiTextSearchProvider", "documentFiltersExclusive", "chatParticipantPrivate", "lmTools" ], ... }
Себе (или пользователям) вы тоже можете обновлять этот файл, чтобы избегать манипуляций с argv.
Заключение
Заключение очень простое - учитывайте нюансы и используйте VSCode proposed API, там много клевого и полезного :) Так же призываю следить за Release Notes новых версий VSCode - там всегда есть раздел Proposed APIs.
