引言
2024年6月,VS Code 团队发布了重要更新,允许扩展开发者直接使用 GitHub Copilot 的能力。这意味着你可以在自己的扩展中集成 AI 对话、代码生成等功能,无需从零搭建 AI 基础设施。
官方资料来源:
一、两种集成方式
1.1 Chat Participant API
适用场景: 需要在 Copilot Chat 面板中添加自定义命令
核心概念:
- Chat Participant - 在聊天界面中注册一个
@your-extension参与者 - Slash Commands - 支持
/command形式的子命令 - Follow-ups - 可以返回建议的后续问题
基础示例:
typescript
import * as vscode from 'vscode';
export function activate(context: vscode.ExtensionContext) {
// 注册 Chat Participant
const participant = vscode.chat.createChatParticipant(
'myextension.helper',
async (request, context, stream, token) => {
// 处理用户输入
const userMessage = request.prompt;
// 返回响应
stream.markdown(`你问了: ${userMessage}\n\n`);
stream.markdown('这是我的回答...');
// 返回建议的后续问题
return {
followUp: [
{ prompt: '告诉我更多细节', label: '📖 详细说明' },
{ prompt: '给我一个例子', label: '💡 示例代码' }
]
};
}
);
context.subscriptions.push(participant);
}
使用方式:
用户在 Copilot Chat 中输入 @myextension 你的问题
1.2 Language Model API
适用场景: 需要在扩展内部调用 AI 模型(不显示在 Chat 面板)
核心能力:
- 直接调用 GPT-4 / GPT-3.5 等模型
- 支持流式响应
- 可以传递上下文(代码、文件内容等)
基础示例:
typescript
import * as vscode from 'vscode';
async function generateCode(prompt: string) {
// 获取可用的语言模型
const models = await vscode.lm.selectChatModels({
vendor: 'copilot',
family: 'gpt-4'
});
if (models.length === 0) {
throw new Error('No Copilot model available');
}
const model = models[0];
// 构建消息
const messages = [
vscode.LanguageModelChatMessage.User(prompt)
];
// 发送请求
const response = await model.sendRequest(messages, {}, new vscode.CancellationTokenSource().token);
// 处理流式响应
let fullText = '';
for await (const chunk of response.text) {
fullText += chunk;
}
return fullText;
}
二、实战案例:代码审查助手
结合两种 API,实现一个智能代码审查扩展:
2.1 注册 Chat Participant
typescript
const reviewer = vscode.chat.createChatParticipant(
'codereview.assistant',
async (request, context, stream, token) => {
const command = request.command; // 获取 slash command
if (command === 'review') {
await reviewCurrentFile(stream, token);
} else if (command === 'explain') {
await explainSelection(stream, token);
} else {
stream.markdown('支持的命令:\n- `/review` - 审查当前文件\n- `/explain` - 解释选中代码');
}
}
);
// 注册 slash commands
reviewer.iconPath = vscode.Uri.file(path.join(context.extensionPath, 'icon.png'));
reviewer.followupProvider = {
provideFollowups(result, context, token) {
return [
{ prompt: '修复这些问题', label: '🔧 自动修复' },
{ prompt: '解释第一个问题', label: '❓ 详细说明' }
];
}
};
2.2 调用 Language Model 进行审查
typescript
async function reviewCurrentFile(stream: vscode.ChatResponseStream, token: vscode.CancellationToken) {
const editor = vscode.window.activeTextEditor;
if (!editor) {
stream.markdown('❌ 请先打开一个文件');
return;
}
const code = editor.document.getText();
const language = editor.document.languageId;
stream.progress('正在分析代码...');
// 调用 Language Model
const models = await vscode.lm.selectChatModels({ vendor: 'copilot' });
const model = models[0];
const messages = [
vscode.LanguageModelChatMessage.User(
`请审查以下 ${language} 代码,指出潜在问题:\n\n\`\`\`${language}\n${code}\n\`\`\``
)
];
const response = await model.sendRequest(messages, {}, token);
// 流式输出结果
stream.markdown('## 审查结果\n\n');
for await (const chunk of response.text) {
stream.markdown(chunk);
}
}
三、最佳实践
3.1 权限和依赖
在 package.json 中声明:
json
{
"enabledApiProposals": [
"chatParticipant",
"languageModels"
],
"contributes": {
"chatParticipants": [
{
"id": "codereview.assistant",
"name": "Code Reviewer",
"description": "智能代码审查助手",
"commands": [
{
"name": "review",
"description": "审查当前文件"
},
{
"name": "explain",
"description": "解释选中代码"
}
]
}
]
}
}
3.2 错误处理
typescript
try {
const models = await vscode.lm.selectChatModels({ vendor: 'copilot' });
if (models.length === 0) {
stream.markdown('⚠️ 未检测到 GitHub Copilot,请先安装并登录');
return;
}
// ... 调用模型
} catch (error) {
if (error instanceof vscode.LanguageModelError) {
stream.markdown(`❌ AI 调用失败: ${error.message}`);
}
}
3.3 上下文管理
利用 ChatContext 获取对话历史:
typescript
async (request, context, stream, token) => {
// 获取之前的对话
const history = context.history;
const messages = history.map(msg => {
if (msg instanceof vscode.ChatRequestTurn) {
return vscode.LanguageModelChatMessage.User(msg.prompt);
} else {
return vscode.LanguageModelChatMessage.Assistant(msg.response.markdown);
}
});
// 添加当前问题
messages.push(vscode.LanguageModelChatMessage.User(request.prompt));
// 发送给模型
const response = await model.sendRequest(messages, {}, token);
}
四、进阶技巧
4.1 工具调用(Tool/Function Calling)
typescript
const tools: vscode.LanguageModelChatTool[] = [
{
name: 'searchCode',
description: '在工作区中搜索代码',
inputSchema: {
type: 'object',
properties: {
query: { type: 'string', description: '搜索关键词' }
}
}
}
];
const response = await model.sendRequest(messages, { tools }, token);
// 处理工具调用
for await (const part of response.stream) {
if (part instanceof vscode.LanguageModelToolCallPart) {
const result = await executeToolCall(part.name, part.input);
// 将结果返回给模型继续对话
}
}
4.2 自定义模型选择
typescript
// 优先使用 GPT-4,降级到 GPT-3.5
const models = await vscode.lm.selectChatModels({
vendor: 'copilot',
family: 'gpt-4'
});
const model = models[0] || (await vscode.lm.selectChatModels({
vendor: 'copilot',
family: 'gpt-3.5-turbo'
}))[0];
五、调试和测试
5.1 本地测试
- 按
F5启动扩展开发主机 - 在新窗口中打开 Copilot Chat
- 输入
@your-extension测试
5.2 日志输出
typescript
const outputChannel = vscode.window.createOutputChannel('My Extension');
outputChannel.appendLine(`User prompt: ${request.prompt}`);
outputChannel.appendLine(`Model response: ${fullText}`);
六、发布和分发
6.1 发布到 Marketplace
bash
# 安装 vsce
npm install -g @vscode/vsce
# 打包
vsce package
# 发布
vsce publish
6.2 注意事项
- 扩展需要用户安装 GitHub Copilot 才能使用
- 在 README 中明确说明依赖关系
- 提供降级方案(如果 Copilot 不可用)
总结
VS Code 的 Chat 和 Language Model API 让扩展开发者能够轻松集成 AI 能力:
- Chat Participant 适合面向用户的对话式交互
- Language Model API 适合后台的 AI 处理
- 两者可以结合使用,打造强大的智能扩展
参考资料: