Адаптер Web UI демона
Цель
Клиенты веб-чата и веб-терминала должны использовать qwen serve через HTTP/SSE API демона и отображать транскрипт на стороне клиента. Нативные локальные интеграции TUI, каналов и IDE пока сохраняют свои существующие пути по умолчанию.
Общий контракт UI
Используйте экспорты TypeScript SDK для UI демона в качестве общей границы:
import {
DaemonClient,
DaemonSessionClient,
createDaemonTranscriptStore,
normalizeDaemonEvent,
} from '@qwen-code/sdk/daemon';Разделение следующее:
DaemonClientобрабатывает HTTP-маршруты демона.DaemonSessionClientотвечает за создание/присоединение сессии и повторное воспроизведение SSE.normalizeDaemonEvent()нормализует сетевые события демона в события UI.createDaemonTranscriptStore()сводит события UI в блоки транскрипта.
React-клиенты могут использовать опциональную привязку @qwen-code/webui:
import {
DaemonSessionProvider,
useDaemonActions,
useDaemonConnection,
useDaemonPendingPermissions,
useDaemonTranscriptBlocks,
} from '@qwen-code/webui';Минимальная структура React:
function App() {
return (
<DaemonSessionProvider baseUrl="http://127.0.0.1:4170">
<Transcript />
<PromptBox />
</DaemonSessionProvider>
);
}
function Transcript() {
const blocks = useDaemonTranscriptBlocks();
return blocks.map((block) => <RenderBlock key={block.id} block={block} />);
}Провайдер создает или присоединяет сессию демона, подписывается на SSE, сохраняет последний идентификатор события в DaemonSessionClient и по умолчанию переподключает поток. Вызывающие могут отключить это с помощью autoReconnect={false} для тестов или пользовательского управления подключением.
Формы развертывания в браузере
Локальный POC с одним источником
Страница, обслуживаемая демоном, может вызывать демон напрямую, так как страница и API имеют один источник. Это предпочтительная форма раннего POC для локальной проверки веб-чата и веб-терминала.
Удаленный веб-чат / веб-терминал
Продуктовое удаленное веб-приложение обычно должно общаться с внешним бэкендом (BFF). BFF управляет URL демона, токеном, маршрутизацией рабочего пространства и метаданными сессии, а затем передает безопасные для браузера события приложения в браузер. Это предотвращает хранение токенов-носителей в браузере и позволяет развертыванию решать, к какому демону/рабочему пространству пользователю разрешен доступ.
Локальный браузер с локальным демоном
Отдельный локальный сервер разработки имеет кросс-доменный источник относительно qwen serve; он должен либо проксировать маршруты демона через тот же источник, либо обслуживаться демоном. Демон намеренно отклоняет произвольные запросы Origin от браузера.
Обязанности рендеринга
Общая модель транскрипта семантическая, а не визуальная. UI-клиенты решают, как отображать:
- блоки сообщений пользователя и ассистента
- свернутые блоки мыслей
- карточки состояния инструментов
- блоки вывода оболочки
- элементы управления запросами разрешений
- блоки состояния/ошибок/отладки
Веб-терминал — это нативный семантический рендерер для браузера. Он должен выглядеть и ощущаться как терминал: моноширинный макет, прокрутка назад, ввод команд, сочетания клавиш и потоковые блоки, но он не является низкоуровневым PTY-прокси и не требует серверного Ink-рендеринга.
Безопасность слияния
- Нативный TUI
qwenостается прямым и неизменным. - Пути
--acp, каналов и IDE остаются по умолчанию неизменными. - Основной UI SDK является аддитивным.
- Привязка React для WebUI является опциональной и выполняется только в клиентах, которые ее импортируют.
- Удаленный spike-код TUI демона не следует рассматривать как миграцию продукта.
Дальнейшие шаги
- Добавить локальный POC
/web, обслуживаемый демоном, или эквивалентное веб-приложение с тем же источником. - Создать первоклассные рендереры чата и терминала на основе блоков транскрипта.
- Добавлять более богатые типизированные события только там, где существующие события демона слишком низкоуровневые для стабильного поведения браузерного UI.
- Рассмотреть выделенный пакет
@qwen-code/daemon-ui-core, если потребителям, не использующим SDK, требуется основной UI как независимая зависимость.