Проблема

Часто использую ChatGPT и другие нейросети для работы: обсуждаю идеи, пишу код, прошу объяснить сложные темы. В итоге в чате накапливаются сотни сообщений. И тут начинается хаос:

Нужно найти функцию, которую обсуждали утром? 5 минут скролла вверх в поисках нужного места — и я уже потерял нить разговора. Приходится начинать заново.

Отдельная боль — потеря контекста моделью. Пишешь код, а модель внезапно «забывает» техническое задание из начала диалога. ChatGPT просто обрезает контекст, а понимаешь это только спустя 10 минут потраченного времени.

В голове крутилась идея, как это исправить. Минутный поиск готовых решений не дал, поэтому сделал собственное расширение.

Что сделал

ThreadLine — расширение для Firefox (скоро Chrome), которое добавляет:

1. Визуальную карту чата — справа появляется полоска с точками. Каждая точка = сообщение. Навёл мышку → видишь начало текста. Кликнул → прыгнул к сообщению.

2. Счётчик токенов — показывает сколько контекста использовано (например "Context: 45% (58k tokens)"). Когда приближаешься к лимиту — предупреждает.

3. Работает везде — ChatGPT, Claude, Gemini, DeepSeek. Один раз установил, работает на всех платформах.

С чем столкнулся

1. каждый сайт устроен по-своему

ChatGPT хранит сообщения в элементах с классом data-message-author-role. Claude использует data-test-render-count. Gemini вообще что-то своё.

Первая идея: хардкод для каждой платформы. Работает, но при каждом редизайне всё ломается.

Вторая идея (рабочая): сделал конфиг с настройками для каждого сайта + универсальный fallback. Если платформа неизвестна, расширение просто ищет все блоки с текстом длиннее 30 символов. Грубо, но работает.

const platformConfig = {
  'chat.openai.com': {
    messageSelector: '[data-message-author-role]'
  },
  'claude.ai': {
    messageSelector: '[data-test-render-count]'
  }
  // Если платформы нет в списке — ищем универсально
};

2. сообщения появляются постепенно

Все AI-чаты — одностраничные приложения. Когда ChatGPT печатает ответ, он добавляет по одному слову в секунду. Каждое слово = изменение на странице.

Первая попытка: проверять изменения каждые 100 миллисекунд. Браузер начал тормозить — слишком часто пересчитывает.

Решение: использовал MutationObserver + задержка в полсекунды. Только когда прошло 500 мс после последнего изменения — обновляю карту сообщений.

const observer = new MutationObserver(() => {
  // Если уже запланировано обновление — ничего не делаем
  if (debounce) return;
 
  // Подождём 500ms, вдруг ещё изменения будут
  debounce = setTimeout(() => {
    updateMessages(); // Обновляем список сообщений
  }, 500);
});

3. подсчёт токенов

У каждой AI-модели свой способ считать токены. GPT считает так, Claude — иначе, Gemini — третий вариант. Чтобы считать точно, нужно отправлять текст на сервер OpenAI/Anthropic. Но это значит отправлять приватные данные пользователя куда-то.

Решение: считаю примерно. Где-то встречал примерное соотношение:

- Обычный текст: делим количество символов на 4
- Код внутри строки: делим на 4 и умножаем на 1.2
- Блоки кода: делим на 4 и умножаем на 2

Для русского языка коэффициент выше .

Точность ±20 %, но для практики достаточно — главное понять "близок ли я к лимиту или нет".

4. платформы меняют классы

Выпустил расширение. Через неделю проверяю - не работает на DeepSeek.

Оказалось, они обновили дизайн и сменили классы элементов. Все мои селекторы сломались.

Теперь делаю так: пробую новый класс → не нашёл → пробую старый → не нашёл → использую универсальный поиск.

5. безопасность

Firefox AMO проверяет расширения на безопасность. При первой загрузке получил warning на использование innerHTML с динамическими данными. Вариант решения (в планах): переписать на createElement + textContent. Сложнее, но безопаснее.

Результат

Расширение работает. Установил его неделю назад и доволен. Нашёл нужное сообщение за 2 секунды вместо 5 минут — бесценно.

Функции:

  • Визуальная карта всех сообщений,

  • Счётчик токенов с предупреждениями,

  • Закладки для важных сообщений,

  • Поиск по диалогу,

  • Много идей для развития.

Скриншот с расширением
Скриншот с расширением

Размер: ~15KB. 

Код: 1000 строк чистого JavaScript, без библиотек.

Ссылка на расширение: Firefox Add-ons