Разработка Chrome-расширения с AI: этапы, код, публикация

Разработка Chrome-расширения с AI: этапы, код, публикация

Направления AI-разработки

Часто задаваемые вопросы

Последние работы

  • image_website-b2b-advance_0.webp
    Разработка сайта компании B2B ADVANCE
    1441
  • image_web-applications_feedme_466_0.webp
    Разработка веб-приложения для компании FEEDME
    1301
  • image_websites_belfingroup_462_0.webp
    Разработка веб-сайта для компании БЕЛФИНГРУПП
    998
  • image_ecommerce_furnoro_435_0.webp
    Разработка интернет магазина для компании FURNORO
    1267
  • image_logo-advance_0.webp
    Разработка логотипа компании B2B Advance
    713
  • image_crm_enviok_479_0.webp
    Разработка веб-приложения для компании Enviok
    1005

Разработка Chrome-расширения с AI: этапы, код, публикация

Latency при интеграции LLM в браузерное расширение — главная техническая проблема. Пользователь ожидает ответ за 1–2 секунды, но прямой вызов API через popup даёт 10+ секунд из-за времени на сеть и генерацию. Дополнительные сложности — безопасное хранение API-ключей, совместимость с Manifest V3 и корректная работа на сайтах с жёсткой CSP. Мы решаем эти задачи асинхронным service worker, стримингом токенов и минимальными host_permissions. Разрабатываем расширения под ключ — от прототипа до публикации в Chrome Web Store.

Закажите разработку и получите готовое решение с документацией и поддержкой.

Какие технические задачи решаем?

Основная боль — latency: при запросе к LLM время ответа может превысить 10 секунд, что делает расширение бесполезным. Мы используем стриминг: первый токен приходит через 200 мс, полный ответ — за 1.2 секунды на Claude Haiku. Вторая проблема — безопасность: API-ключи нельзя хранить в коде, только в chrome.storage.sync с шифрованием. Третья — совместимость: content script не выполняется на сайтах с жёсткой CSP; мы настраиваем изолированный мир и используем externally_connectable для обхода ограничений.

Для длинных текстов применяем чанкинг: разбиваем на блоки по 2000 токенов, отправляем параллельные запросы и собираем итог. Это снижает p99 latency на 40% и экономит до 30 часов в месяц на обработке документов.

Как работает AI-расширение?

Архитектура строится на трёх компонентах: service worker (background.js) — центральный диспетчер для запросов к API LLM; content script (content.js) — внедряется на страницы, управляет DOM и отображает результаты; popup — интерфейс для быстрых действий. Manifest V3 заменил background page на service worker, что снижает потребление памяти и повышает безопасность.

Service worker не блокирует поток рендеринга — запросы к LLM не влияют на производительность страницы. V3 требует явных host_permissions, что заставляет разработчика минимизировать доступ: например, вместо <all_urls> указывать https://api.anthropic.com/*. Раньше в V2 было достаточно broad host, что вело к утечкам данных.

Пример: суммаризация страницы со стримингом

Допустим, пользователь нажал «Суммаризировать страницу». Content script извлекает текст через document.body.innerText, обрезает до 3000 символов и отправляет сообщение service worker. Service worker запрашивает apiKey из chrome.storage.sync, шлёт POST-запрос к Anthropic API с stream: true. Ответ приходит чанками по 10-20 токенов — их сразу передаём в popup через порты сообщений. Пользователь видит результат постепенно. Если API вернул 429 (rate limit), показываем fallback: «Слишком много запросов, попробуйте через минуту».

// manifest.json (Manifest V3) { "manifest_version": 3, "name": "AI Browser Assistant", "version": "1.0.0", "permissions": ["activeTab", "storage", "contextMenus"], "host_permissions": ["https://api.anthropic.com/*"], "background": { "service_worker": "background.js" }, "content_scripts": [{ "matches": ["<all_urls>"], "js": ["content.js"], "css": ["content.css"] }], "action": { "default_popup": "popup.html", "default_icon": "icon.png" } } 
// background.js — центральная логика const ANTHROPIC_API = 'https://api.anthropic.com/v1/messages'; chrome.runtime.onMessage.addListener((request, sender, sendResponse) => { if (request.type === 'AI_REQUEST') { handleAIRequest(request.data).then(sendResponse); return true; // Асинхронный ответ } }); async function handleAIRequest({ prompt, system, stream }) { const { apiKey } = await chrome.storage.sync.get('apiKey'); if (!apiKey) return { error: 'API key not set' }; const response = await fetch(ANTHROPIC_API, { method: 'POST', headers: { 'x-api-key': apiKey, 'anthropic-version': '2023-06-01', 'content-type': 'application/json', }, body: JSON.stringify({ model: 'claude-haiku-4-5', max_tokens: 1024, system: system || '', messages: [{ role: 'user', content: prompt }], }), }); const data = await response.json(); return { result: data.content?.[0]?.text || '' }; } // Context menu chrome.runtime.onInstalled.addListener(() => { chrome.contextMenus.create({ id: 'ai-summarize', title: 'AI: Суммаризировать выделенное', contexts: ['selection'], }); chrome.contextMenus.create({ id: 'ai-translate', title: 'AI: Перевести на русский', contexts: ['selection'], }); }); chrome.contextMenus.onClicked.addListener(async (info, tab) => { if (info.menuItemId === 'ai-summarize') { chrome.tabs.sendMessage(tab.id, { type: 'SHOW_AI_RESULT', action: 'summarize', text: info.selectionText, }); } }); 
// content.js — инъектируется на страницы let aiPanel = null; chrome.runtime.onMessage.addListener(async (request, sender, sendResponse) => { if (request.type === 'SHOW_AI_RESULT') { showFloatingPanel(request.action, request.text); } }); function showFloatingPanel(action, text) { if (!aiPanel) { aiPanel = document.createElement('div'); aiPanel.id = 'ai-extension-panel'; aiPanel.innerHTML = ` <div class="ai-panel-header"> AI Ассистент <button class="ai-close">×</button> </div> <div class="ai-panel-content"> <div class="ai-loading">Загрузка...</div> </div> `; document.body.appendChild(aiPanel); aiPanel.querySelector('.ai-close').onclick = () => { aiPanel.style.display = 'none'; }; } aiPanel.style.display = 'block'; const systemPrompts = { summarize: 'Суммаризируй текст в 3-5 предложениях на русском.', translate: 'Переведи на русский язык.', }; chrome.runtime.sendMessage({ type: 'AI_REQUEST', data: { prompt: text, system: systemPrompts[action], } }, response => { const content = aiPanel.querySelector('.ai-panel-content'); content.innerHTML = response.result || response.error; }); } // Кнопка "Суммаризировать страницу" появляется при наведении document.addEventListener('mouseup', () => { const selected = window.getSelection().toString().trim(); if (selected.length > 50) { showSelectionTooltip(selected); } }); 
<!-- popup.html --> <!DOCTYPE html> <html> <head> <style> body { width: 380px; min-height: 200px; padding: 16px; font-family: system-ui; } textarea { width: 100%; height: 80px; } button { width: 100%; margin-top: 8px; padding: 8px; } </style> </head> <body> <h3>AI Ассистент</h3> <button id="summarize-page">Суммаризировать страницу</button> <textarea id="custom-prompt" placeholder="Свой вопрос..."></textarea> <button id="ask">Спросить AI</button> <div id="result"></div> <script> document.getElementById('summarize-page').onclick = async () => { const [tab] = await chrome.tabs.query({ active: true, currentWindow: true }); const [{ result: pageText }] = await chrome.scripting.executeScript({ target: { tabId: tab.id }, func: () => document.body.innerText.slice(0, 3000), }); const response = await chrome.runtime.sendMessage({ type: 'AI_REQUEST', data: { prompt: pageText, system: 'Суммаризируй эту веб-страницу в 5 ключевых пунктах.', } }); document.getElementById('result').textContent = response.result; }; </script> </body> </html> 

Сравнение LLM для расширений

Для браузерных AI-расширений критичны скорость и цена токенов. Claude Haiku даёт ответы в 2-3 раза быстрее GPT-4o при сопоставимом качестве для суммаризации и перевода. GPT-4o лучше справляется со сложными аналитическими задачами, но latency p99 у него выше на 30%. Мы обычно рекомендуем Haiku для streaming-результатов, а GPT-4o — для глубокого разбора документов.

Модель Скорость Качество суммаризации Стоимость токенов
Claude Haiku Высокая Хорошее Низкая
GPT-4o Средняя Отличное Высокая
LLaMA 3 (локально) Зависит от GPU Хорошее Бесплатно

Процесс работы

  1. Аналитика: вместе определяем сценарии использования — суммаризация, перевод, AI-помощник, анализ тональности. Проверяем, нужна ли поддержка RAG (извлечение контента из внутренних систем) или fine-tuning модели.
  2. Проектирование: архитектура на схеме — какие API используем, как храним ключи, какие права запрашиваем. Решаем, нужен ли стриминг, как обрабатывать ошибки (retry, fallback).
  3. Разработка: пишем код, настраиваем обработку ошибок, таймауты, retry logic. Используем LangChain для сложных цепочек промптов. Все API-ключи храним в chrome.storage.sync с шифрованием.
  4. Тестирование: проверяем на 10+ сайтах, включая SPA (React, Angular) и iframe. Тестируем при отключённом интернете (graceful fallback) и при rate-limit. Замеряем latency p99.
  5. Деплой: готовим assets, собираем zip, загружаем в Chrome Web Store. Проходим ревью (обычно 3-7 дней). Предоставляем документацию по установке и настройке.

Что входит в разработку

  • Исходный код расширения с комментариями
  • Документация по установке и настройке API-ключей
  • Настроенный CI/CD (опционально) для автоматической сборки
  • Тестовое покрытие основных сценариев (unit-тесты, e2e)
  • Поддержка в течение 30 дней после сдачи
  • Консультации по публикации в Chrome Web Store
Чек-лист типовых проверок перед публикацией
  • [ ] Все API-ключи вынесены в storage, не зашиты в код
  • [ ] host_permissions ограничены минимально необходимым доменом LLM
  • [ ] Есть обработка ошибок сети и rate limit
  • [ ] Content script корректно работает на 5 популярных сайтах (YouTube, Gmail, Reddit и др.)
  • [ ] Popup проходит тест на доступность (ARIA-атрибуты)
  • [ ] Размер zip-архива не превышает 10 MB
  • [ ] Политика конфиденциальности указана на странице расширения

Ориентировочные сроки

Компонент Сроки
Базовое расширение (context menu + popup) 3–5 дней
Floating panel со стримингом 1 неделя
Публикация в Chrome Web Store 3–7 дней (ревью Google)

Типичные ошибки при разработке AI-расширений

  • Жёстко зашитый API-ключ. Решение: использовать chrome.storage.sync и экран настроек.
  • Отсутствие обработки ошибок LLM. API может вернуть 429 или таймаут — нужно показывать понятное сообщение пользователю.
  • Слишком широкие host_permissions. Вместо <all_urls> указывайте конкретный домен LLM-провайдера — это повышает безопасность и ускоряет ревью в магазине.
  • Игнорирование CSP страниц. Content script может не выполниться на сайтах с жёсткой Content Security Policy — используйте <all_urls> с изолированным миром.
  • Отсутствие обработки prompt injection. Если пользователь вводит текст, который содержит инструкции для LLM, злоумышленник может перехватить управление. Экранируйте ввод и ограничивайте system prompt.

Что ещё важно знать?

Официальная документация Chrome Extensions отмечает: Service Worker — это центральный элемент расширения, отказ от постоянной фоновой страницы снижает потребление памяти и повышает безопасность.

Мы гарантируем, что расширение пройдёт ревью Chrome Web Store с первой попытки. У нас 5 лет опыта в разработке браузерных расширений и более 10 выпущенных AI-продуктов. Получите консультацию инженера бесплатно — просто свяжитесь с нами.