Как я сделал расширение для навигации по длинным AI-чатам

7 мин чтения
Расширение для Chrome
Категория: Инструменты

Я часто использую AI-чаты для ресёрча: в транспорте, перед сном, чтобы набросать идеи. Проходит время — и я уже не помню, где именно в длинном чате задавал нужный вопрос. Начинается бесконечный скролл. Это раздражало меня достаточно долго, чтобы в итоге я решил это починить.

Проблема

Если вы активно пользуетесь ChatGPT, Claude или Perplexity, то наверняка сталкивались с этим: длинный чат превращается в бесконечную простыню. Вы помните, что где-то в начале задавали важный вопрос — но чтобы найти его, нужно скроллить минуту-две. Браузерный Ctrl+F ищет по всему тексту, включая ответы ИИ, и не очень помогает когда нужно найти именно ваше сообщение.

Нативной навигации по сообщениям ни в одной из платформ нет. Мне хотелось простую вещь: список моих сообщений сбоку, клик — и страница прыгает к нужному месту.

Решение: AI Chat Messages Toolkit

Я сделал Chrome-расширение, которое решает именно эту задачу. Оно добавляет боковую панель и кнопку в тулбаре браузера. В них отображается список всех ваших сообщений в текущем чате — первые 10 слов каждого, чтобы было понятно, о чём речь. Кликаете на любое — страница плавно скроллится к нему и на секунду подсвечивает нужный блок.

Поддерживаются пять платформ: ChatGPT, Claude, Perplexity, Gemini и Microsoft Copilot.

Никаких серверов, никакой аналитики, ничего никуда не отправляется — всё работает локально прямо в браузере.

Технические детали

Manifest V3 и контентные скрипты

Расширение построено на Manifest V3 — актуальном стандарте Chrome-расширений. Пять скриптов инжектируются на страницу в строгом порядке:

config.js → utils.js → messages.js → panel.js → content.js

Порядок важен: каждый следующий файл использует функции из предыдущих. Поскольку модули ES в контентных скриптах не поддерживаются в полной мере, все утилиты живут в глобальном скоупе и доступны между файлами без импортов.

Адаптация под каждую платформу

Главная техническая сложность — у каждой AI-платформы своя DOM-структура, и она периодически меняется. Для каждого сайта в config.js описан конфиг с CSS-селекторами:

'chatgpt.com': {
  messageContainerSelector: '[data-turn="user"]',
  textSelector: '.whitespace-pre-wrap',
  editCounterSelector: '[aria-label="Previous response"] + div',
  extractText: (el) => el.textContent
}

Когда платформа обновляет вёрстку, достаточно поправить один селектор в конфиге — остальная логика остаётся нетронутой. Это позволяет поддерживать пять совершенно разных сайтов, не дублируя код.

Отслеживание изменений через MutationObserver

AI-чаты — это SPA (Single Page Application). Новые сообщения появляются без перезагрузки страницы, а переходы между чатами не вызывают навигацию в классическом смысле. Чтобы список сообщений всегда был актуальным, используется два механизма.

MutationObserver следит за DOM и реагирует только на появление элементов, соответствующих messageContainerSelector. Мутации внутри самой панели расширения игнорируются, чтобы не создавать бесконечный цикл обновлений.

Перехват history API — для отслеживания SPA-навигации оборачиваются нативные методы history.pushState и history.replaceState:

const originalPushState = history.pushState;
history.pushState = function(...args) {
  originalPushState.apply(history, args);
  setTimeout(() => {
    if (detectChatChange()) {
      scheduleUpdate();
      setupMessageObserver();
    }
  }, 500);
};

Обновления дебаунсятся с задержкой 300 мс, чтобы не перегружать браузер при быстром изменении DOM.

Попап и контентный скрипт: общение через сообщения

Попап тулбара и контентный скрипт живут в разных контекстах и не имеют прямого доступа к переменным друг друга. Они общаются через chrome.runtime.sendMessage / chrome.tabs.sendMessage:

  • Попап отправляет getUserMessages → контентный скрипт возвращает массив сообщений
  • Попап отправляет scrollToMessage с индексом → контентный скрипт скроллит страницу
  • Контентный скрипт отправляет messagesChanged → попап обновляет список

Это стандартная модель общения в Chrome-расширениях, но важно правильно обрабатывать случаи, когда вкладка ещё не инициализировала контентный скрипт — иначе попап будет крашиться при первом открытии.

Локализация на 18 языков

Все строки интерфейса хранятся в _locales/<lang>/messages.json и загружаются через chrome.i18n.getMessage(). Расширение доступно на 18 языках: английский, русский, украинский, немецкий, французский, испанский, польский, итальянский и другие. Chrome подхватывает нужный язык автоматически по настройкам браузера.

Лендинг и продвижение

Параллельно я сделал лендинг с описанием основных фич. Это было нужно по нескольким причинам: при регистрации в Chrome Web Store требуется указать сайт, политику приватности и контакт для обратной связи. Плюс хотелось попробовать как-то продвинуть расширение.

Добавил страницу поддержки проекта — но пока туда особо никто не заходит. Это честно.

Где взять

Расширение доступно в Chrome Web Store и работает во всех Chromium-браузерах: Chrome, Edge, Brave.

Подробнее о функциях можно почитать на лендинге расширения.

Если вы тоже тонете в длинных AI-чатах — попробуйте. Мне самому оно реально помогает каждый день.