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