Розробники витрачають години на пошук у документації та написання шаблонного коду. Наше AI-розширення вбудовується прямо в редактор і прискорює рутинні завдання у 2–3 рази. За 5+ років досвіду наша команда розробила понад 20 успішних інструментів з інтеграцією LLM — від простого автодоповнення до повноцінних чат-панелей з контекстом проекту. Інтеграція з API Anthropic та OpenAI дозволяє гнучко вибирати модель під задачу, а стрімінг через client.messages.stream() дає перші токени за 200–300 мс. Середня вартість одного пояснення коду через Claude Haiku — близько $0.25, а генерація тестів через GPT-4o mini — $0.15 за 1K токенів. Вартість розробки базового розширення — від $2000, з повним функціоналом — від $5000.
Одна з частих проблем — затримка при генерації. Ми використовуємо стрімінг, перші токени з'являються за 200–300 мс. P99 latency для коротких запитів — менше 1.5 с. Щоб знизити галюцинації, додаємо контекст із активного файлу та few-shot приклади — це зменшує кількість невірних підказок на 40%. В результаті розробник отримує релевантні пропозиції без необхідності перевіряти кожне. Економія часу дозволяє скоротити витрати на розробку на 30–50%.
Які проблеми вирішуємо?
- Затримки при генерації — моделі з низькою затримкою (Claude Haiku, GPT-4o mini), стрімінг та debounce 300 мс.
- Галюцинації — контекст проекту, few-shot, кастомні промпти під ваш стек (Django, React, FastAPI).
- Інтеграція з Extension API — типові помилки: пропущений cleanup у
deactivate(), витоки у WebView. Ми опрацьовуємо це на код-рев'ю. - Публікація у Marketplace — підготовка іконок, опис, тестування на різних версіях VS Code (1–2 дні).
Як ми це робимо?
Стек: TypeScript, VS Code Extension API, Anthropic SDK / OpenAI SDK. Для inline completion використовуємо InlineCompletionItemProvider, для чату — WebView з acquireVsCodeApi(). Для підвищення продуктивності застосовуємо асинхронний event loop з non-blocking I/O для потокової передачі токенів. Всі виклики LLM асинхронні, з повторними спробами при таймаутах. Нижче — порівняння моделей для різних завдань.
| Завдання | Рекомендована модель | Затримка p99 | Вартість за 1K токенів |
|---|---|---|---|
| Explain code | Claude Haiku 4 | ~0.8 с | ~$0.25 |
| Refactor | Claude Sonnet 4 | ~1.2 с | ~$3.0 |
| Generate tests | GPT-4o mini | ~1.0 с | ~$0.15 |
| Chat history | GPT-4o | ~2.0 с | ~$5.0 |
| Підхід | Гнучкість | Продуктивність | Складність розробки |
|---|---|---|---|
| Вбудовані моделі VS Code | Низька | Висока | Низька |
| API LLM (наша реалізація) | Висока | Середня (залежить від моделі) | Середня |
| Локальний LLM через ONNX | Середня | Низька (залежить від GPU) | Висока |
Кастомне розширення краще готового в 2–3 рази за рахунок налаштування під стек. Порівняно з готовими розширеннями, наше кастомне рішення знижує затримку в 1.5 рази.
VS Code Extension API надає багаті можливості для інтеграції AI-сервісів. Документація
Приклад конфігурації для OpenAI
{
"aiAssistant.model": "gpt-4o-mini",
"aiAssistant.apiKey": "sk-..."
}
Чому кастомне розширення краще готового?
Готові рішення з Marketplace часто не знають специфіку вашого стеку. Ми налаштовуємо промпти під ваші бібліотеки та додаємо code actions для конкретних помилок. Наприклад, розширення може автоматично пропонувати try/except для блоків із ризиком винятків. Це скорочує час код-рев'ю у 2–3 рази.
Що входить у роботу?
- Вихідний код розширення з документацією.
- Інтеграція з вашою LLM (безкоштовні ключі не надаємо).
- Налаштування CI/CD для публікації.
- Підтримка протягом 1 місяця після здачі.
Як влаштований провайдер inline completion?
Провайдер реалізує інтерфейс InlineCompletionItemProvider. При кожному введенні символу надсилається запит до LLM з контекстом поточного файлу. Ми використовуємо debounce 300 мс та кешуємо результати для однакових контекстів. Це дозволяє тримати latency p99 нижче 1.5 с.
Структура розширення
Код нижче — конфігурація для чотирьох команд та code actions.
{
"name": "ai-dev-assistant",
"displayName": "AI Dev Assistant",
"engines": { "vscode": "^1.85.0" },
"activationEvents": ["onStartupFinished"],
"contributes": {
"commands": [
{ "command": "aiAssistant.explainCode", "title": "AI: Explain Code" },
{ "command": "aiAssistant.refactor", "title": "AI: Refactor Selection" },
{ "command": "aiAssistant.generateTests", "title": "AI: Generate Tests" },
{ "command": "aiAssistant.openChat", "title": "AI: Open Chat" }
],
"keybindings": [
{ "command": "aiAssistant.explainCode", "key": "ctrl+shift+e", "when": "editorTextFocus" }
],
"configuration": {
"title": "AI Assistant",
"properties": {
"aiAssistant.apiKey": {
"type": "string",
"description": "Anthropic API Key"
},
"aiAssistant.model": {
"type": "string",
"default": "claude-haiku-4-5",
"enum": ["claude-haiku-4-5", "claude-sonnet-4-5"]
}
}
}
},
"main": "./out/extension.js"
}
Основний файл розширення
import * as vscode from 'vscode';
import Anthropic from '@anthropic-ai/sdk';
let client: Anthropic;
export function activate(context: vscode.ExtensionContext) {
const config = vscode.workspace.getConfiguration('aiAssistant');
client = new Anthropic({ apiKey: config.get('apiKey') || '' });
context.subscriptions.push(
vscode.commands.registerCommand('aiAssistant.explainCode', explainSelectedCode)
);
// ... інші команди
}
async function explainSelectedCode() {
const editor = vscode.window.activeTextEditor;
if (!editor) return;
const selection = editor.selection;
const selectedText = editor.document.getText(selection);
if (!selectedText) {
vscode.window.showWarningMessage('Виберіть код для пояснення');
return;
}
await vscode.window.withProgress(
{ location: vscode.ProgressLocation.Notification, title: 'AI аналізує код...' },
async () => {
const response = await client.messages.create({
model: 'claude-haiku-4-5',
max_tokens: 1024,
messages: [{
role: 'user',
content: `Поясни цей код коротко та зрозуміло:\n\`\`\`\n${selectedText}\n\`\`\``
}]
});
const explanation = response.content[0].type === 'text' ? response.content[0].text : '';
const outputChannel = vscode.window.createOutputChannel('AI Assistant');
outputChannel.appendLine('=== AI Пояснення ===');
outputChannel.appendLine(explanation);
outputChannel.show();
}
);
}
Chat Panel
class ChatPanel {
private static currentPanel?: ChatPanel;
private readonly panel: vscode.WebviewPanel;
static createOrShow(extensionUri: vscode.Uri) {
if (ChatPanel.currentPanel) {
ChatPanel.currentPanel.panel.reveal();
return;
}
const panel = vscode.window.createWebviewPanel(
'aiChat', 'AI Chat', vscode.ViewColumn.Beside,
{ enableScripts: true }
);
ChatPanel.currentPanel = new ChatPanel(panel, extensionUri);
}
constructor(panel: vscode.WebviewPanel, extensionUri: vscode.Uri) {
this.panel = panel;
this.panel.webview.html = this.getWebviewContent();
this.panel.webview.onDidReceiveMessage(async message => {
if (message.type === 'chat') {
const stream = await client.messages.stream({
model: 'claude-sonnet-4-5',
max_tokens: 2048,
messages: message.history,
});
for await (const chunk of stream.textStream) {
this.panel.webview.postMessage({ type: 'token', text: chunk });
}
this.panel.webview.postMessage({ type: 'done' });
}
});
}
private getWebviewContent(): string {
return `<!DOCTYPE html>
<html>
<head><style>/* styles */</style></head>
<body>
<div id="messages"></div>
<input type="text" id="input" placeholder="Задайте питання..." />
<button onclick="sendMessage()">Відправити</button>
<script>
const vscode = acquireVsCodeApi();
const history = [];
function sendMessage() {
const input = document.getElementById('input');
history.push({ role: 'user', content: input.value });
vscode.postMessage({ type: 'chat', history });
input.value = '';
}
window.addEventListener('message', event => {
const msg = event.data;
if (msg.type === 'token') {
// Append token
}
});
</script>
</body>
</html>`;
}
}
Code Actions Provider
class AICodeActionProvider implements vscode.CodeActionProvider {
provideCodeActions(
document: vscode.TextDocument,
range: vscode.Range,
): vscode.CodeAction[] {
const actions: vscode.CodeAction[] = [];
const selectedText = document.getText(range);
if (!selectedText) return actions;
const explainAction = new vscode.CodeAction('AI: Пояснити', vscode.CodeActionKind.RefactorRewrite);
explainAction.command = { command: 'aiAssistant.explainCode', title: 'Пояснити' };
actions.push(explainAction);
return actions;
}
}
Процес роботи
- Аналітика — вивчаємо ваші сценарії, вибираємо модель LLM.
- Проектування — проектуємо команди, WebView, провайдери.
- Розробка — пишемо код на TypeScript, налаштовуємо API-клієнти.
- Тестування — тестуємо на реальних проектах, заміряємо latency.
- Публікація — публікуємо у VS Code Marketplace, налаштовуємо CI/CD.
Терміни орієнтовно
- Базові команди (explain, refactor): 3–5 днів.
- Chat panel з WebView: 1 тиждень.
- Inline completion provider: 1–2 тижні.
- Публікація у Marketplace: 1–2 дні.
Типові помилки при самостійній розробці
- Використання
activate()без викликуcontext.subscriptions.push()— команди не реєструються. - Ігнорування
dispose()для WebView — витік пам'яті. - Відсутність fallback при недоступності API — користувач бачить порожній екран.
Замовляйте AI-розширення під ключ — ми оцінимо ваш проект за 1 день. Замовте розробку AI-розширення, яке буде працювати саме під ваші завдання. Досвід нашої команди — 5+ років, гарантуємо якість та підтримку протягом 30 днів після публікації. Розкажіть про свій проект — ми запропонуємо оптимальну архітектуру розширення. Вартість включає підтримку 30 днів. Пишіть на пошту або в Telegram — зв'яжіться з нами для оцінки вашого проекту.







