Недавно Cбер запустил Салют — семейство виртуальных ассистентов, которые работают на разных платформах. Мы в SberDevices, кроме самого ассистента, занимаемся разработкой инструментов, позволяющих любому разработчику удобно создавать навыки, которые называются смартапы. Кроме общеизвестных диалоговых сценариев в формате чата — ChatApp, можно создавать смартапы в формате веб-приложения на любых известных веб-технологиях — Canvas App. О том, как создать простейший смартап такого типа, и пойдет сегодня речь.  Canvas App — стандартное веб-приложение в привычном понимании, которое запускается и работает внутри WebView, но есть свои особенности. Как это работает по шагам: Пользователь произносит ключевую фразу, например «Салют, какие у меня задачи на сегодня». Голосовой запрос приходит в NLP-платформу, где разбирается на фонемы, там же определяется его эмоциональный окрас и т.д.. В БД зарегистрированных смартапов находится тот, которому соответствует активационная фраза. Регистрация происходит через SmartApp Studio и доступна всем разработчикам без исключения. Во время регистрации смартапа в SmartApp Studio разработчик указывает два эндпоинта: один для веб-приложения, второй для сценарного бэкенда. Именно их достанет из БД NLP-платформа, когда найдет соответствующий смартап. В эндпоинт сценарного бэкенда будет отправлено сообщение с распознанной активационной фразой. Формат сообщений подробно описан в документации SmartApp API. Эндпоинт веб-приложения будет указан для загрузки в WebView. Ответ от сценарного бэкенда придёт в веб-приложение в качестве JS-события, подписавшись на которое, можно управлять веб-приложением. Предмет нашего разговора – веб-приложение. Делать будем смартап для ведения тудушек. Поскольку SmartApp Studio предоставляет онлайн-среду разработки сценариев, не будем подробно на этом останавливаться, а воспользуемся форком готового сценария, который в качестве примера доступен на GitHub. В одной из следующих статей расскажем, как написать такой сценарий на NodeJS. В SmartApp Graph/IDE, той самой онлайн-среде, в качестве источника можно указать git-репозиторий, чем мы и воспользуемся, чтобы получить эндпоинт до сценарного бэкенда. Далее его надо указать при регистрации нашего смартапа в SmartApp Studio. В качестве эндпоинта веб-приложения укажем любой известный веб-ресурс, например, sberdevices.ru. Позже поменяем на URL нашего веб-приложения. Для примера будем делать веб-приложение на React. К React нет никакой привязки и пример ниже может быть написан на чём угодно. Для нетерпеливых выложили конечный результат на GitHub. Итак, что мы хотим от приложения: добавлять задачи;  выполнять задачи; удалять задачи; и все это голосом, но не сразу.  Для создания базового проекта воспользуемся CRA.  > npx create-react-app todo-canvas-app  Для реализации UI нам понадобится как минимум пара компонентов и форма.   Дальше нам надо сделать базовую логику нашего приложения. Пользоваться будем стандартными средствами React, используя useReducer.  Далее будем диспатчить экшены их обработчиков на форме.  Запускаем и проверяем. npm start Когда наше приложение базово работает, можно добавить немного магии голосового управления. Для этого надо установить Assistant Client — библиотеку для взаимодействия с виртуальным ассистентом. npm i @sberdevices/assistant-client В момент открытия WebView платформа инжектит JS API для взаимодействия с ассистентом. Это биндиги до нативных методов платформы. Assistant Client — обёртка, которая в дев-режиме позволяет отлаживать взаимодействие с ассистентом в браузере, а в продакшене предоставляет удобный для веб-приложений API. Идём в app.js и там же, где наш основной редюсер, создаем инстанс Assistant Client. Судя по коду выше, нужен некий токен. Токен обеспечивает авторизацию сообщений в NLP-платформе. Токен автоматически приклеивается к сообщениям, когда смартап запускается на устройстве, но в нашем случае это браузер, поэтому токен надо передать вручную. Токен генерируется автоматически для каждого разработчика в SmartApp Studio. После этого перезапустим наше приложение. Теперь мы видим панельку ассистента с лавашаром и текстовым полем. Лавашар это такое визуальное представление ассистента. По нажатию на лавашар включится микрофон и вы сможете отправить команду ассистенту так же, как вы бы это сделали, запуская смартап на устройстве. Относитесь к этому не как к эмулятору, а как к дев-тулзам, в продакшене всё это за нас будет делать платформа. Те же самые команды вы можете посылать не только голосом, но и текстом, используя текстовое поле рядом с лавашаром, чтобы не будить своих домашних по ночам. Ассистент присылает структурированные команды в формате JSON. Полное описание формата можно найти в документации Assistant Client на GitHub. Теперь подпишем наши экшены на команды от ассистента. Для этого в коде нашего сценария определены специальные интенты — ключевые слова в фразах, которые может говорить пользователь. Разные интенты генерируют разные команды веб-приложению. Сохраняем, запускаем — ничего не работает. Не волнуйтесь, так и должно быть. Я приоткрою завесу того, как на самом деле работает магия.  Дело в том, что ваш сценарий сам по себе только лишь по фразе пользователя не может узнать то, что у вас сейчас на экране. Чтобы эта магия работала, к каждому голосовому запросу необходимо клеить стейт веб-приложения. Тут мы приходим к осознанию, что сценарный бэкенд получает на вход не только разобранную фразу, но и данные с экрана — стейт. Задача сценария провести пользователя к следующему шагу по этим двум параметрам, отправив команду веб-приложению на изменение стейта. Можно мыслить себе это как голосовой аналог клика. Разница лишь в том, что элемент управления для такого клика в интерфейсе может и не существовать физически. Например, если бы мы делали интернет-магазин, то кнопку добавления в корзину можно было бы и опустить в пользу голосовой команды «Афина, добавь в корзину красные туфли». Для того, чтобы это было удобно делать из веб-приложения, в Assistant Client есть API для передачи состояния — getState. В нашем случае стейт – это список тудушек и некоторая мета-информация. Дополним код инициализации Asisstant Client. И передадим стейт в обработку ассистенту. Формат стейта также описан в документации Asisstant Client. Из кода выше видим появление мета-информации в виде нумерации. Зачем? Согласитесь, тудухи могут быть довольными длинными и иногда удобнее было бы говорить «Джой, я сделал первую задачу» вместо полного заголовка. Но погодите, как это работает? Где единичка превращается в «первую»? Эту магию кастования натуральных фраз, которые мы привыкли использовать в повседневной речи, в машинный формат делает за нас NLP-платформа. То же самое происходит, например, с командами навигации. Тудух может скопиться достаточное количество, чтобы они не влезли в экран. Само собой, мы хотим уметь скроллить экран, чтобы иметь возможность прочитать всё, что скопилось. На устройствах, где нет тач-интерфейса, например, на SberBox, мы можем скроллить пультом ДУ или голосом. Нажатия кнопок на пульте превращаются в события нажатий на стрелки клавиатуры на window, но что делать с голосом? Голосовые паттерны навигации встроены в NLP-платформу, и разработчику сценария ничего не надо делать самому. А для разработчика веб-приложения достаточно подписаться на специальный тип команд, приходящих от ассистента через Assistant Client. Все вариации навигационных фраз будут кастится в конечное число навигационных команд. Их всего пять: UP, DOWN, LEFT, RIGHT, BACK. Перезапускаем наше приложение и пробуем после нажатия на лавашар сказать: «Напомни купить коту корм». И вуаля! Если у вас есть устройство под рукой, то можно проверить работу смартапа на нём. Для этого не обязательно его публиковать или деплоить куда-либо. Достаточно создать тоннель с локального хоста, например, с помощью ngrok. ngrok http 3000 Полученный URL с https указываем в SmartApp Studio, сохраняем черновик и говорим ассистенту: «Сбер, какие у меня задачи на сегодня?». Это cработает, если вы залогинены под одним и тем же SberID на устройстве и в SmartApp Studio. Черновики по-умолчанию доступны к запуску на устройствах разработчика. Смысл статьи — в наглядной демонстрации того, как голосовое управление прозрачным образом можно интегрировать не только в специально для этого созданные приложения, но и в уже существующие. Например, если у вас уже есть рабочий веб-сервис, то научить его работать на платформе Салют не составит большого труда.  Этот короткое интро — скорее, обзор возможностей на искусственном примере. Как сделать смартап с компонентами, оплатой, автотестами, обязательно расскажем в следующих статьях. Спасибо за внимание, ещё увидимся! По всем вопросам разработки смартапов можно обращаться в сообщество разработчиков SmartMarket в телеграмме.  Разработчик интерфейсов