Skip to content
ShaerWare edited this page Mar 3, 2026 · 7 revisions

Widget (Веб-виджеты)

Настройка мультиинстансных чат-виджетов для встраивания на веб-сайты.

Скриншот

Widget

Концепция

Виджет — это чат-окно, которое встраивается на любой сайт одним <script> тегом:

  • Посетители сайта общаются с ИИ-ассистентом
  • Каждый виджет имеет независимые настройки AI, TTS и внешнего вида
  • Виджет можно отключить удалённо без переразвёртывания сайта
  • Все сообщения сохраняются в системе с привязкой к виджету

Список виджетов

Левая панель отображает все инстансы:

Элемент Описание
Индикатор Зелёный = включён, серый = отключён
Название Имя виджета
Действия Настройки / Удалить

Создание виджета

  1. Нажмите "Создать виджет"
  2. Введите название (из него генерируется slug-ID)
  3. Настройте параметры (см. ниже)
  4. Сохраните
  5. Скопируйте код для вставки на сайт

Настройки виджета

Конфигурация организована по вкладкам:

Основные (Settings)

Параметр Описание
Название Имя инстанса
Описание Описание виджета
Enabled Включить/отключить виджет

Внешний вид (Appearance)

Параметр Описание По умолчанию
Заголовок Текст в шапке чат-окна AI Ассистент
Приветствие Первое сообщение бота Здравствуйте! Чем могу помочь?
Placeholder Текст в поле ввода Введите сообщение...
Цвет Основной цвет (hex). 6 пресетов + произвольный #c2410c
Позиция Кнопка чата: right или left right

Домены (Domains)

Параметр Описание
Allowed Domains Список доменов, на которых работает виджет
Tunnel URL Переопределение API URL (для ngrok/Cloudflare Tunnel)

Правила доменов:

  • Пустой список = виджет работает на любом домене
  • Проверка по подстроке: example.com разрешает www.example.com, shop.example.com
  • Проверяется на стороне сервера при загрузке widget.js

AI настройки

Параметр Описание
LLM Backend vllm, gemini или cloud:{provider_id}
Персона anna или marina
System Prompt Кастомный системный промпт
LLM Params JSON с параметрами: temperature, max_tokens

TTS настройки

Параметр Описание
Engine xtts, piper или openvoice
Voice ID голоса (anna, marina)
Preset Опциональный пресет TTS

RAG (База знаний)

Параметр Описание
RAG Mode all — все коллекции, selected — выбранные, none — отключить
Коллекции Multi-select чекбоксы для выбора коллекций знаний (при mode=selected)

Настройки RAG определяют, какие документы из базы знаний (Wiki RAG) будут подставляться в контекст LLM при ответах виджета. Подробнее о коллекциях: Wiki-RAG.

Rate Limiting

Параметр Описание По умолчанию
Rate Limit Count Максимум сообщений за период 5
Rate Limit Hours Период в часах 5

Код для вставки (Code)

Вкладка автоматически генерирует HTML-сниппет для вставки на сайт. Кнопка "Копировать" копирует код в буфер обмена.

Тест (Test)

Встроенный тестовый чат прямо в админ-панели:

  • Использует AI/TTS настройки именно этого виджета
  • Создаёт временную сессию
  • Позволяет проверить поведение перед размещением на сайте

Код для встраивания

Формат

<script>
  window.aiChatSettings = {
    apiUrl: 'https://your-server.com',
    instanceId: 'sales-widget',
    title: 'Sales Assistant',
    greeting: 'Чем могу помочь?',
    placeholder: 'Введите сообщение...',
    primaryColor: '#c2410c',
    position: 'right'
  };
</script>
<script src="https://your-server.com/widget.js?instance=sales-widget"></script>

Размещение

Вставьте код перед закрывающим тегом </body> на вашем сайте.

Несколько виджетов на разных страницах

Каждый виджет имеет свой instanceId и изолированную сессию:

<!-- На странице продаж -->
<script src="https://api.example.com/widget.js?instance=sales"></script>

<!-- На странице поддержки -->
<script src="https://api.example.com/widget.js?instance=support"></script>

Как работает виджет

Загрузка

1. Браузер запрашивает GET /widget.js?instance={id}
2. Сервер загружает конфиг инстанса из БД
3. Проверяет домен запроса по allowed_domains
4. Инжектит window.aiChatSettings в JS-код
5. Возвращает полный виджет-скрипт с CORS-заголовками

Runtime-проверка статуса

6. JS выполняет GET /widget/status?instance={id}  (публичный, без auth)
7. Если enabled=true → рендерит кнопку чата
8. Если enabled=false → ничего не показывает

Это позволяет отключить виджет удалённо — при следующей загрузке страницы кнопка чата исчезнет.

Отправка сообщений

9.  Пользователь нажимает кнопку → окно чата
10. Первое сообщение → POST /admin/chat/sessions
    (source=widget, source_id={instance_id})
11. Каждое сообщение → POST /admin/chat/sessions/{id}/stream
    с widget_instance_id → бэкенд использует AI/TTS конфиг виджета
12. Ответ стримится через SSE: {type: "chunk", content: "..."}

Сессии (Replain-style persistence)

Виджет сохраняет историю чата при переходе между страницами:

  • Session ID хранится в cookie (SameSite=None; Secure, 30 дней) и localStorage (cookie-first, localStorage-fallback)
  • При загрузке страницы preloadHistory() запрашивает сессию через GET /widget/chat/session/{id} (публичный, без auth, source="widget")
  • Состояние open/closed отслеживается в sessionStorage — если чат был открыт, он auto-opens на следующей странице
  • clearSession() очищает cookie + localStorage + sessionStorage

Публичный JS API

После загрузки виджета доступен глобальный объект:

window.aiChat = {
  open(),         // Открыть окно чата
  close(),        // Закрыть окно чата
  clearSession()  // Очистить сессию
};

Адаптивный дизайн

  • Desktop: кнопка 60x60px, окно 380x520px
  • Mobile (<=480px): полноэкранный режим
  • CSS-переменные: --ai-primary, --ai-primary-hover

API эндпоинты

Управление инстансами

Метод Endpoint Описание
GET /admin/widget/instances Список всех инстансов
POST /admin/widget/instances Создать инстанс
GET /admin/widget/instances/{id} Конфиг инстанса
PUT /admin/widget/instances/{id} Обновить инстанс
DELETE /admin/widget/instances/{id} Удалить инстанс

Публичные (без авторизации)

Метод Endpoint Описание
GET /widget.js?instance={id} Динамический JS-скрипт виджета
GET /widget/status?instance={id} Проверка enabled-статуса
GET /widget/chat/session/{id} Загрузка истории сессии

RBAC

  • Admin — видит и управляет всеми виджетами в workspace
  • User/Web — только свои виджеты (owner_id)
  • Guest — только чтение

Все CRUD-эндпоинты фильтруются по workspace_id из JWT. Публичные эндпоинты (widget.js, /widget/status, /widget/chat/session/{id}) не фильтруются — работают без JWT-контекста.

Безопасность

Механизм Описание
Проверка доменов allowed_domains проверяются server-side при загрузке widget.js
CORS /widget.js возвращает Access-Control-Allow-Origin: *
Изоляция сессий Каждый виджет имеет отдельную сессию в localStorage
Fail-open Если /widget/status недоступен — виджет всё равно рендерится

Models | Telegram

Clone this wiki locally