# Добавление новой платформы Добавление нового сайта с чатом состоит из двух отдельных слоёв: 1. **Адаптер сайта**, `catalog/sites//site.json`, учит Voyager распознавать сайт и находить реплики пользователя, реплики ассистента, поле ввода, боковую панель и маркеры темы. 2. **Плагин** в `catalog/sites//plugins//` решает одну задачу пользователя на этом сайте, например ширину чтения или исправление отображения. `site.json` содержит `id` (совпадает с именем каталога), `label`, `matches`, `selectors`, `theme`, `brandColor`, `capabilities`, а также необязательные `conversationIdPattern` и `turnKeyAttributes`. `turnKeyAttributes` задаёт атрибуты, которые сохраняют идентичность сообщения пользователя при повторной отрисовке страницы; отслеживание отправки (его используют Activity папок и метки времени таймлайна) работает только на сайте, который задаёт его вместе с `composer`, `userTurn` и `conversationIdPattern`. `validateSiteAdapterData` в `src/features/plugins/sites/siteAdapterData.ts` проверяет этот файл, а `bun run catalog:build` проверяет каждый сайт и плагин перед публикацией. Каждая платформа плагинов задаётся данными. Сейчас платформы такие: ChatGPT, Claude, DeepSeek и Kimi. Gemini и AI Studio остаются нативными поверхностями Voyager, и у них тоже есть свой `site.json` (`catalog/sites/gemini/` и `catalog/sites/aistudio/`), но он поставляется внутри пакета и никогда не публикуется в удалённом каталоге. Все пять адаптеров (`adapters/gemini.ts`, `aistudio.ts`, `claude.ts`, `chatgpt.ts` и `deepseek.ts`) — однострочные обёртки над своим `site.json`: правьте JSON, а не TypeScript. Публикуемый каталог по хостам несёт и данные сайта, поэтому исправление селекторов в `site.json` может дойти до пользователей без выпуска расширения. Новому сайту всё равно нужен адаптер, потому что ему также требуются разрешение на доступ к хосту и регистрация content script, которые поставляются внутри пакета. Для новой платформы, например DeepSeek, держите работу над адаптером в рамках контракта платформы. Поместите `site.json`, обязательные тесты селекторов и минимальную документацию, объясняющую поддержку, в одно законченное изменение. Реестр сайтов сам подхватывает новый адаптер из файла, поэтому список регистрации редактировать не нужно. Не добавляйте новый сайт под каждый плагин. После принятия адаптера последующие плагины можно отправлять отдельными сфокусированными изменениями. Если несколько изменений зависят друг от друга, полезна цепочка связанных PR (stacked PR): каждая следующая ветка основана на предыдущей, и каждый PR показывает только свою инкрементальную функцию. Цепочка всё равно должна следовать тому же правилу области: одна понятная цель пользователя на PR, с нужными тестами и очисткой. Поддержка сайта не требует интеграции с API модели. Не добавляйте статические content scripts или обязательные разрешения на хост для новой платформы; для сайтов, которым нужен только плагин, используйте существующий поток опциональных разрешений и динамической регистрации. Этот путь зависит от версии браузера. Chrome и Edge поддерживают поток, которым пользуется расширение. Firefox требует версии 128 или новее для опциональных разрешений на хост, а Safari — версии 16.4 или новее для динамической регистрации content script. В старых поддерживаемых версиях браузеров popup может правильно отказаться включать плагин для пользовательского сайта, потому что нужные API не могут обеспечить постоянное разрешение. Не обходите это, добавляя широкое статическое разрешение на хост без одобрения мейнтейнеров.