|
| 1 | +--- |
| 2 | +title: How to Call GitHub Copilot from a VSCode Extension |
| 3 | +lang: en |
| 4 | +layout: post |
| 5 | +audio: false |
| 6 | +translated: false |
| 7 | +generated: true |
| 8 | +--- |
| 9 | + |
| 10 | +GitHub Copilot is a powerful AI-powered coding assistant integrated into Visual Studio Code (VSCode) and IntelliJ IDEA through their respective plugins. While there’s no public REST API for directly calling Copilot, developers can interact with its capabilities programmatically within a VSCode extension using the VSCode Chat API, Language Model API, or command-based interactions. This blog post walks through creating a VSCode extension that triggers Copilot’s chat functionality with a custom prompt, effectively simulating an “API call” to Copilot, and explains how to leverage Copilot itself to streamline development. |
| 11 | + |
| 12 | +## Understanding Copilot’s Integration in VSCode |
| 13 | + |
| 14 | +GitHub Copilot doesn’t expose a traditional API (e.g., REST endpoints) for direct programmatic access. Instead, its functionality is available through: |
| 15 | +- **VSCode Chat API**: Enables extensions to create custom chat participants that interact with Copilot’s chat system for natural language queries. |
| 16 | +- **VSCode Language Model API**: Allows extensions to access Copilot’s large language models (LLMs) for tasks like code generation or analysis. |
| 17 | +- **VSCode Commands**: Permits triggering Copilot’s built-in features, such as opening the chat window with a predefined prompt. |
| 18 | + |
| 19 | +This guide focuses on using the `workbench.action.chat.open` command to trigger Copilot’s chat interface, as it’s the simplest way to integrate Copilot’s capabilities into an extension. |
| 20 | + |
| 21 | +## Step-by-Step: Building a VSCode Extension to Trigger Copilot Chat |
| 22 | + |
| 23 | +Below is a step-by-step guide to creating a VSCode extension that opens Copilot’s chat window with a custom prompt, effectively “calling” Copilot to process a user-defined query. |
| 24 | + |
| 25 | +### 1. Set Up the VSCode Extension |
| 26 | + |
| 27 | +1. **Scaffold the Project**: |
| 28 | + - Install the Yeoman VSCode extension generator: `npm install -g yo generator-code`. |
| 29 | + - Run `yo code` and select “New Extension (TypeScript)” to create a TypeScript-based extension. |
| 30 | + - Name the extension, e.g., `copilot-api-caller`. |
| 31 | + |
| 32 | +2. **Configure `package.json`**: |
| 33 | + - Define a command to trigger Copilot’s chat. |
| 34 | + - Example `package.json`: |
| 35 | + |
| 36 | +```json |
| 37 | +{ |
| 38 | + "name": "copilot-api-caller", |
| 39 | + "displayName": "Copilot API Caller", |
| 40 | + "description": "Triggers GitHub Copilot Chat with a custom prompt", |
| 41 | + "version": "0.0.1", |
| 42 | + "engines": { |
| 43 | + "vscode": "^1.85.0" |
| 44 | + }, |
| 45 | + "categories": ["Other"], |
| 46 | + "activationEvents": [ |
| 47 | + "onCommand:copilot-api-caller.triggerCopilotChat" |
| 48 | + ], |
| 49 | + "main": "./out/extension.js", |
| 50 | + "contributes": { |
| 51 | + "commands": [ |
| 52 | + { |
| 53 | + "command": "copilot-api-caller.triggerCopilotChat", |
| 54 | + "title": "Trigger Copilot Chat" |
| 55 | + } |
| 56 | + ] |
| 57 | + }, |
| 58 | + "scripts": { |
| 59 | + "vscode:prepublish": "npm run compile", |
| 60 | + "compile": "tsc -p ./", |
| 61 | + "watch": "tsc -watch -p ./" |
| 62 | + }, |
| 63 | + "devDependencies": { |
| 64 | + "@types/vscode": "^1.85.0", |
| 65 | + "@types/node": "^20.2.5", |
| 66 | + "typescript": "^5.1.3" |
| 67 | + } |
| 68 | +} |
| 69 | +``` |
| 70 | + |
| 71 | + - **Using Copilot**: While editing `package.json`, Copilot may suggest fields like `contributes.commands` or `activationEvents` as you type. Accept these with `Tab` to speed up setup. |
| 72 | + |
| 73 | +### 2. Write the Extension Code |
| 74 | + |
| 75 | +Create the extension logic to register a command that opens Copilot’s chat with a user-provided prompt. |
| 76 | + |
| 77 | +- **File**: `src/extension.ts` |
| 78 | +- **Code**: |
| 79 | + |
| 80 | +```typescript |
| 81 | +import * as vscode from 'vscode'; |
| 82 | + |
| 83 | +export function activate(context: vscode.ExtensionContext) { |
| 84 | + // Register the command to trigger Copilot Chat |
| 85 | + let disposable = vscode.commands.registerCommand('copilot-api-caller.triggerCopilotChat', async () => { |
| 86 | + // Get user input for the prompt |
| 87 | + const prompt = await vscode.window.showInputBox({ |
| 88 | + prompt: 'Enter your query for GitHub Copilot', |
| 89 | + placeHolder: 'e.g., Write a JavaScript function to sort an array' |
| 90 | + }); |
| 91 | + |
| 92 | + if (prompt) { |
| 93 | + try { |
| 94 | + // Execute the command to open Copilot Chat with the prompt |
| 95 | + await vscode.commands.executeCommand('workbench.action.chat.open', prompt); |
| 96 | + vscode.window.showInformationMessage('Sent prompt to Copilot Chat!'); |
| 97 | + } catch (error) { |
| 98 | + vscode.window.showErrorMessage(`Failed to trigger Copilot Chat: ${error}`); |
| 99 | + } |
| 100 | + } |
| 101 | + }); |
| 102 | + |
| 103 | + context.subscriptions.push(disposable); |
| 104 | +} |
| 105 | + |
| 106 | +export function deactivate() {} |
| 107 | +``` |
| 108 | + |
| 109 | +- **How It Works**: |
| 110 | + - Registers a command `copilot-api-caller.triggerCopilotChat`. |
| 111 | + - Prompts the user for a query (e.g., “Write a Python function to reverse a string”). |
| 112 | + - Uses `vscode.commands.executeCommand('workbench.action.chat.open', prompt)` to open Copilot’s chat window with the prompt. |
| 113 | +- **Using Copilot**: In VSCode, type `import * as vscode` and Copilot will suggest the full import. Add a comment like `// Register a command to open Copilot Chat`, and Copilot may propose the `vscode.commands.registerCommand` structure. For the command execution, type `// Open Copilot Chat with a prompt`, and Copilot might suggest the `executeCommand` call. |
| 114 | + |
| 115 | +### 3. Enhance with Context (Optional) |
| 116 | + |
| 117 | +To make the extension more powerful, include context from the editor, such as selected code, to provide Copilot with additional information. |
| 118 | + |
| 119 | +- **Modified Code** (`src/extension.ts`): |
| 120 | + |
| 121 | +```typescript |
| 122 | +import * as vscode from 'vscode'; |
| 123 | + |
| 124 | +export function activate(context: vscode.ExtensionContext) { |
| 125 | + let disposable = vscode.commands.registerCommand('copilot-api-caller.triggerCopilotChat', async () => { |
| 126 | + // Get selected text from the active editor |
| 127 | + const editor = vscode.window.activeTextEditor; |
| 128 | + let context = ''; |
| 129 | + if (editor) { |
| 130 | + const selection = editor.selection; |
| 131 | + context = editor.document.getText(selection); |
| 132 | + } |
| 133 | + |
| 134 | + // Prompt for user input |
| 135 | + const prompt = await vscode.window.showInputBox({ |
| 136 | + prompt: 'Enter your query for GitHub Copilot', |
| 137 | + placeHolder: 'e.g., Explain this code', |
| 138 | + value: context ? `Regarding this code: \n\`\`\`\n${context}\n\`\`\`\n` : '' |
| 139 | + }); |
| 140 | + |
| 141 | + if (prompt) { |
| 142 | + try { |
| 143 | + await vscode.commands.executeCommand('workbench.action.chat.open', prompt); |
| 144 | + vscode.window.showInformationMessage('Sent prompt to Copilot Chat!'); |
| 145 | + } catch (error) { |
| 146 | + vscode.window.showErrorMessage(`Failed to trigger Copilot Chat: ${error}`); |
| 147 | + } |
| 148 | + } |
| 149 | + }); |
| 150 | + |
| 151 | + context.subscriptions.push(disposable); |
| 152 | +} |
| 153 | + |
| 154 | +export function deactivate() {} |
| 155 | +``` |
| 156 | + |
| 157 | +- **How It Works**: |
| 158 | + - Retrieves selected text from the active editor and includes it as context in the prompt. |
| 159 | + - Pre-fills the input box with the selected code, formatted as a Markdown code block. |
| 160 | + - Sends the combined prompt to Copilot’s chat interface. |
| 161 | +- **Using Copilot**: Comment `// Get selected text from editor`, and Copilot may suggest `vscode.window.activeTextEditor`. For formatting, type `// Format code as markdown`, and Copilot might propose the triple-backtick syntax. |
| 162 | + |
| 163 | +### 4. Test the Extension |
| 164 | + |
| 165 | +1. Press `F5` in VSCode to launch the Extension Development Host. |
| 166 | +2. Open the Command Palette (`Ctrl+Shift+P` or `Cmd+Shift+P`) and run `Trigger Copilot Chat`. |
| 167 | +3. Enter a prompt (e.g., “Generate a REST API client in TypeScript”) or select code and run the command. |
| 168 | +4. Verify that Copilot’s chat window opens with your prompt and provides a response. |
| 169 | +5. **Using Copilot**: If errors occur, add a comment like `// Handle errors for command execution`, and Copilot may suggest try-catch blocks or error messages. |
| 170 | + |
| 171 | +### 5. Advanced: Using the VSCode Chat API |
| 172 | + |
| 173 | +For more control, use the VSCode Chat API to create a custom chat participant that integrates with Copilot’s language models, allowing natural language processing within your extension. |
| 174 | + |
| 175 | +- **Example Code** (`src/extension.ts`): |
| 176 | + |
| 177 | +```typescript |
| 178 | +import * as vscode from 'vscode'; |
| 179 | + |
| 180 | +export function activate(context: vscode.ExtensionContext) { |
| 181 | + // Register a chat participant |
| 182 | + const participant = vscode.chat.createChatParticipant('copilot-api-caller.myParticipant', async (request, context, stream, token) => { |
| 183 | + stream.markdown('Processing your query...\n'); |
| 184 | + // Use the Language Model API to generate a response |
| 185 | + const model = await vscode.lm.selectChatModels({ family: 'gpt-4' })[0]; |
| 186 | + if (model) { |
| 187 | + const response = await model.sendRequest([{ text: request.prompt }], {}, token); |
| 188 | + for await (const chunk of response.stream) { |
| 189 | + stream.markdown(chunk); |
| 190 | + } |
| 191 | + } else { |
| 192 | + stream.markdown('No suitable model available.'); |
| 193 | + } |
| 194 | + }); |
| 195 | + |
| 196 | + participant.iconPath = new vscode.ThemeIcon('sparkle'); |
| 197 | + context.subscriptions.push(participant); |
| 198 | +} |
| 199 | + |
| 200 | +export function deactivate() {} |
| 201 | +``` |
| 202 | + |
| 203 | +- **How It Works**: |
| 204 | + - Creates a chat participant (`@copilot-api-caller.myParticipant`) invocable in the Copilot Chat view. |
| 205 | + - Uses the Language Model API to access Copilot’s `gpt-4` model (or another available model) to process the prompt. |
| 206 | + - Streams the response back to the chat view. |
| 207 | +- **Using Copilot**: Comment `// Create a chat participant for Copilot`, and Copilot may suggest the `vscode.chat.createChatParticipant` structure. For the Language Model API, comment `// Access Copilot’s LLM`, and Copilot might propose `vscode.lm.selectChatModels`. |
| 208 | + |
| 209 | +### 6. Package and Deploy |
| 210 | + |
| 211 | +1. Install `vsce`: `npm install -g @vscode/vsce`. |
| 212 | +2. Run `vsce package` to create a `.vsix` file. |
| 213 | +3. Install the extension in VSCode via the Extensions view or share the `.vsix` file with others. |
| 214 | +4. **Using Copilot**: Add a comment like `// Add script to package extension` in `package.json`, and Copilot may suggest the `vscode:prepublish` script. |
| 215 | + |
| 216 | +## Leveraging Copilot During Development |
| 217 | + |
| 218 | +GitHub Copilot can significantly speed up extension development: |
| 219 | +- **Code Suggestions**: As you type in `src/extension.ts`, Copilot suggests imports, command registrations, and error handling. For example, typing `vscode.commands.` prompts suggestions like `registerCommand`. |
| 220 | +- **Prompt Engineering**: Use clear comments like `// Trigger Copilot Chat with a user prompt` to guide Copilot’s suggestions. Refine comments if suggestions are inaccurate. |
| 221 | +- **Debugging**: If the extension fails, add comments like `// Log error details`, and Copilot may suggest `console.log` or `vscode.window.showErrorMessage`. |
| 222 | + |
| 223 | +## Limitations |
| 224 | + |
| 225 | +- **No Direct API Access**: Copilot doesn’t expose a public REST API. The VSCode Chat and Language Model APIs are the primary programmatic interfaces. |
| 226 | +- **Authentication**: Users must have an active Copilot subscription (free or paid) and be signed into VSCode with a GitHub account. |
| 227 | +- **Chat API Scope**: The Chat API is limited to the chat interface; direct access to Copilot’s code completion engine is not available programmatically. |
| 228 | +- **Environment**: Ensure the extension complies with any organizational policies regarding custom VSCode extensions. |
| 229 | + |
| 230 | +## Conclusion |
| 231 | + |
| 232 | +By using VSCode’s command system or Chat API, developers can effectively “call” GitHub Copilot from a custom extension, enabling programmatic interaction with its AI capabilities. The example above demonstrates triggering Copilot’s chat with a custom prompt, enhanced with editor context, and provides a foundation for more advanced integrations using the Language Model API. With Copilot’s assistance during development, creating such extensions becomes faster and more intuitive. |
| 233 | + |
| 234 | +For further exploration, consider experimenting with the Chat API for custom participants or integrating additional editor context for richer prompts. Happy coding! |
0 commit comments