Веб-компоненты чата

Интерфейс чата Wippy доступен как набор компонуемых пользовательских элементов, поэтому любой микрофронтенд (или любая страница, работающая в дочернем контексте) может встроить живой чат Wippy по имени тега — без Vue, без импортов, без регистрации. Они оборачивают те же компоненты, что использует собственный чат хоста (единый источник истины), опираясь на тот же слой данных ChatTransportSessionManager.

Это готовые элементы, которые вы потребляете: в отличие от веб-компонента, который вы создаёте сами, их не нужно ни писать, ни регистрировать. Хост делает их доступными по тегу в каждом дочернем контексте (см. Как они загружаются).

Используйте их, когда нужна поверхность чата внутри вашей собственной страницы или панели. Чтобы вместо этого императивно открыть собственную панель чата хоста, используйте host.startChat(token) / host.openSession(sessionUUID) из @wippy-fe/proxy (см. Proxy API).

Элементы

Тег Что отображает Ключевые атрибуты События
<wippy-chat> Полный чат — заголовок + сообщения + ввод session-id, start-token, agent, show-selector, hide-header session-started, error
<wippy-chat-messages> Только список сообщений session-id
<wippy-chat-input> Только поле ввода session-id
<wippy-session-selector> Выбор сессии active-session-id select

Каждый элемент также принимает два атрибута оформления на уровне экземпляра — custom-css и css-variables — они описаны в разделе Оформление.

Как они загружаются

Элементы чата поставляются ровно так же, как <wippy-loading>: крошечная оболочка @wippy-fe/chat.js (~21 КБ) автоматически регистрирует все четыре тега и вставляется в каждый дочерний контекст через массив scripts хоста (рядом с loading.js и proxy.js). Поэтому теги доступны по имени в любом дочернем микрофронтенде без какой-либо регистрации в приложении — вам не нужно устанавливать пакет или вызывать customElements.define().

Тяжёлые внутренности — дерево Vue плюс PrimeVue, Shiki и рендерер markdown (~2 МБ) — вынесены в отдельный чанк chat-internals.[hash].js и лениво загружаются при первом монтировании. Пока чанк загружается, элемент показывает заглушку <wippy-loading>; при неудачной загрузке — <wippy-error>. Страницы, которые никогда не используют теги чата, никогда не платят за эти внутренности.

<wippy-chat>

Реактивное управление сессией требует Web Host 1.0.51 или новее. Зафиксируйте соответствующее семейство пакетов @wippy-fe/* версии 0.0.51+; более старые вставляемые элементы чата надёжно поддерживают только первичное монтирование.

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

Атрибут Тип По умолчанию Описание
session-id string Отобразить эту существующую сессию (UUID сессии).
start-token string Стартовый токен агента; запускает новую сессию при монтировании, если session-id не задан.
agent string Имя (или заголовок) агента, предварительно выбираемого в пустом состоянии, когда сессия не открыта.
show-selector boolean false Отображать встроенный селектор сессий в заголовке.
hide-header boolean false Скрыть строку заголовка с агентом/моделью (для компактных встраиваний).

События (диспетчеризуются как CustomEvent на элементе; читайте event.detail):

Событие detail Когда
session-started { sessionId: string } Сессия запущена — из start-token при монтировании либо действием пользователя.
error { message: string } Инициализация сессии не удалась (например, неверный start-token).
<!-- Запустить новую сессию по стартовому токену агента -->
<wippy-chat start-token="agent-start-token" agent="researcher"></wippy-chat>

<!-- Закрепить существующую сессию -->
<wippy-chat session-id="019eb2ae-1234-5678-abcd-ef1234567890"></wippy-chat>

<!-- Встроенный селектор, без строки заголовка -->
<wippy-chat show-selector hide-header></wippy-chat>
document.querySelector('wippy-chat')
  .addEventListener('session-started', (e) => {
    console.log('session:', e.detail.sessionId)
  })

Реактивное управление без перемонтирования

Держите один смонтированный элемент <wippy-chat> и обновляйте его атрибуты. Изменённый session-id открывает эту сессию на месте. Установка session-id="" или удаление ранее управляемого атрибута — это явный переход Новый чат: он очищает и закреплённую, и общую активную сессию. Элемент, у которого session-id никогда не было, остаётся управляемым селектором; отсутствие атрибута при первом монтировании не является командой очистки.

Когда присутствует start-token, очистка session-id снова запускает сессию из этого токена. Смена токена также запускает сессию на месте. Элемент использует токен один раз на каждый хост пользовательского элемента, поэтому переподключение или перемещение того же элемента не воспроизводит запуск повторно. Если более новый токен, управляемая сессия, ручной выбор или отключение вытесняют запуск в процессе, устаревший результат не может заменить текущую сессию; любая сессия, созданная с опозданием, закрывается.

const chat = document.querySelector('wippy-chat')

chat.setAttribute('session-id', existingSessionId)

// Новый чат с агентом. Замена элемента не требуется.
chat.setAttribute('start-token', agentStartToken)
chat.removeAttribute('session-id')

Резолверы компонентов управляемой вёрстки обновляют и удаляют props на существующем пользовательском элементе. Они перемонтируют его только при смене tagName, сохраняя поле ввода чата, позицию прокрутки и принадлежащее элементу состояние жизненного цикла между обновлениями панели.

<wippy-chat-messages> и <wippy-chat-input>

Список сообщений и поле ввода как отдельные элементы, чтобы вы могли скомпоновать их сами. Каждый принимает один session-id; без явного session-id они следуют за общей активной сессией, заданной элементом <wippy-session-selector>. Ни один из них не порождает событий.

<!-- Собственная вёрстка: сообщения сверху, поле ввода снизу -->
<div style="display:flex; flex-direction:column; height:100%;">
  <wippy-chat-messages session-id="019eb2ae-…"></wippy-chat-messages>
  <wippy-chat-input    session-id="019eb2ae-…"></wippy-chat-input>
</div>

<wippy-session-selector>

Выбор сессии. Он задаёт общую активную сессию, за которой следуют другие элементы.

Атрибут Тип По умолчанию Описание
active-session-id string Подсветить эту сессию как активную.

Событие:

Событие detail Когда
select { sessionId: string } Пользователь выбирает сессию. Выбранная сессия становится общей активной сессией.
<wippy-session-selector></wippy-session-selector>
document.querySelector('wippy-session-selector')
  .addEventListener('select', (e) => {
    console.log('picked:', e.detail.sessionId)
  })

Композиция и общая сессия

Элементы без явного session-id следуют за выбором <wippy-session-selector> через общий activeSessionId менеджера. Поэтому селектор плюс чат (или селектор плюс отдельные список сообщений и поле ввода) на одной странице остаются синхронными — выберите сессию в селекторе, и остальные обновятся. Элементы, у которых есть явный session-id (или start-token), закреплены и игнорируют селектор.

<!-- Селектор + чат: чат следует за выбранной сессией -->
<wippy-session-selector></wippy-session-selector>
<wippy-chat></wippy-chat>

<!-- Селектор + раздельные список сообщений и поле ввода, все следуют за селектором -->
<wippy-session-selector></wippy-session-selector>
<wippy-chat-messages></wippy-chat-messages>
<wippy-chat-input></wippy-chat-input>

<!-- Закреплённый чат рядом с управляемым селектором -->
<wippy-chat session-id="019eb2ae-…"></wippy-chat>  <!-- игнорирует селектор -->
<wippy-chat></wippy-chat>                            <!-- следует за селектором -->

Оформление

Каждый элемент отображается в shadow root, поэтому стили страницы-хоста не проникают внутрь и не утекают наружу. Тему задают два механизма:

  • Наследуемые CSS-переменные. Пользовательские свойства темы (--p-primary-*, --p-text-color, …) наследуются через границу shadow DOM из темы хоста, поэтому чат бесплатно подхватывает активную палитру и тёмный/светлый режим. Стили на основе селекторов (PrimeVue, markdown, Tailwind) собраны в таблицу chat-elements.css и вставляются в shadow root. PrimeVuePlugin перенаправляет цель Portal по умолчанию (body/null) на закреплённый оверлейный слой внутри владеющего shadow root. Не задавайте appendTo: 'self' по привычке: это явное согласие на инлайн-размещение, которое может обрезать содержимое внутри прокручиваемых Dialog или Drawer. Всплывающие уведомления делегируются нативному toast хоста через прокси, а не отображаются в shadow DOM.
  • Переопределения на уровне экземпляра. Каждый элемент принимает два атрибута:
Атрибут Тип Эффект
custom-css string Сырой CSS, добавляемый последним в shadow root элемента, поэтому он побеждает по порядку.
css-variables object (JSON) Переопределения CSS-переменных для экземпляра, применяемые к :host. Ключи могут опускать ведущие --.
<wippy-chat
  session-id="019eb2ae-…"
  custom-css=".message-item { max-width: 80%; }"
></wippy-chat>

Опустить css-variables — обычный путь, уважающий фасад. Переопределения цветов на уровне экземпляра предназначены для намеренной изоляции при встраивании, а не для рутинной перекраски.

Полную модель оформления — семантические переменные, переключение тёмной/светлой темы и то, как хост вставляет CSS в shadow DOM, — см. в Оформление: веб-компоненты.

Рантайм-обвязка

Внутри дочернего контекста Web Host элементам не нужна настройка. Аутентификация и конфигурация приходят из глобальных переменных прокси, которые хост уже вставляет (window.__WIPPY_APP_CONFIG__ / window.__WIPPY_APP_API__); REST и WebSocket используют URL сред из конфигурации. Достаточно поместить тег чата на страницу — оболочка его регистрирует, внутренности лениво загружаются, и чат подключается с существующей сессией дочернего контекста.

Смотрите также