Адаптер веб-интерфейса демона
Цель
Веб-чат и веб-терминальные клиенты должны использовать 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 является опциональной и выполняется только в клиентах, которые её импортируют.
- Удалённый код демона TUI (spike) не следует рассматривать как миграцию продукта.
Последующие шаги
- Добавить локальный
/webPOC, обслуживаемый демоном, или эквивалентное веб-приложение с тем же источником. - Создать первоклассные рендереры чата и терминала на основе блоков транскрипта.
- Добавлять более насыщенные типизированные события только там, где существующие события демона слишком низкоуровневы для стабильного поведения UI в браузере.
- Рассмотреть выделенный пакет
@qwen-code/daemon-ui-core, если потребители, не использующие SDK, нуждаются в ядре UI как независимой зависимости.