├── cypress
├── fixtures
│ └── example.json
├── tsconfig.json
├── plugins
│ └── index.js
├── support
│ └── helpers
│ │ ├── clientMethods.helpers.ts
│ │ └── socket.helpers.ts
└── integration
│ ├── createAssistantWeb.spec.ts
│ ├── initializeAssistantSDK.spec.ts
│ ├── disableDubbing.spec.ts
│ ├── greetings.spec.ts
│ ├── sendAction.spec.ts
│ └── refreshToken.spec.ts
├── .eslintignore
├── cypress.json
├── examples
├── todo-canvas-app
│ ├── .env.sample
│ ├── cypress.json
│ ├── src
│ │ ├── react-app-env.d.ts
│ │ ├── global.d.ts
│ │ ├── index.css
│ │ ├── setupTests.ts
│ │ ├── reportWebVitals.ts
│ │ ├── index.tsx
│ │ ├── App.css
│ │ ├── store.ts
│ │ └── App.tsx
│ ├── public
│ │ ├── robots.txt
│ │ ├── favicon.ico
│ │ ├── logo192.png
│ │ ├── logo512.png
│ │ ├── manifest.json
│ │ └── index.html
│ ├── cypress
│ │ ├── tsconfig.json
│ │ ├── plugins
│ │ │ └── index.js
│ │ └── integration
│ │ │ └── sample.spec.ts
│ ├── tsconfig.json
│ ├── README.md
│ └── package.json
└── umd-example
│ ├── README.md
│ └── index.html
├── .prettierignore
├── .npmrc
├── .lintstagedrc
├── .huskyrc.json
├── .editorconfig
├── .commitlintrc.json
├── .prettierrc
├── src
├── declarations.d.ts
├── index.ts
├── createRecoveryStateRepository.ts
├── record
│ ├── record-downloader.ts
│ ├── console-logger.ts
│ ├── recorder.ts
│ ├── online-player.ts
│ ├── createMockWsCreator.ts
│ ├── callback-recorder.ts
│ ├── index.tsx
│ ├── offline-player.ts
│ └── mock-recorder.ts
├── nanoobservable.ts
├── NativePanel
│ ├── fonts.ts
│ ├── components
│ │ ├── Bubble.tsx
│ │ ├── VoiceTouch.tsx
│ │ ├── TextInput.tsx
│ │ ├── Suggests.tsx
│ │ └── KeyboardTouch.tsx
│ ├── styles.tsx
│ ├── NativePanelStyles.ts
│ └── NativePanel.tsx
├── assistantSdk
│ ├── voice
│ │ ├── recognizers
│ │ │ ├── mtt
│ │ │ │ └── index.proto
│ │ │ ├── musicRecognizer.ts
│ │ │ ├── speechRecognizer.ts
│ │ │ └── asr
│ │ │ │ └── index.proto
│ │ ├── player
│ │ │ ├── trackCollection.ts
│ │ │ ├── chunkQueue.ts
│ │ │ ├── voicePlayer.ts
│ │ │ └── trackStream.ts
│ │ ├── listener
│ │ │ ├── voiceListener.ts
│ │ │ └── navigatorAudioProvider.ts
│ │ └── audioContext.ts
│ ├── README.md
│ ├── client
│ │ ├── transport.ts
│ │ ├── client.ts
│ │ └── methods.ts
│ └── meta.ts
├── nanoevents.ts
├── appInitialData.ts
├── createAssistantDev.ts
├── proto
│ └── index.proto
├── mock.ts
└── debug.ts
├── global.d.ts
├── .gitignore
├── tsconfig.json
├── .github
└── workflows
│ └── release.yml
├── rollup.config.js
├── .eslintrc.js
└── package.json
/cypress/fixtures/example.json:
--------------------------------------------------------------------------------
1 | {
2 | }
3 |
--------------------------------------------------------------------------------
/.eslintignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | dist
3 | *.js
4 | *.d.ts
5 | examples
6 |
--------------------------------------------------------------------------------
/cypress.json:
--------------------------------------------------------------------------------
1 | {
2 | "projectId": "ac6epj",
3 | "video": false
4 | }
5 |
--------------------------------------------------------------------------------
/examples/todo-canvas-app/.env.sample:
--------------------------------------------------------------------------------
1 | REACT_APP_TOKEN=
2 | REACT_APP_SMARTAPP=
3 |
--------------------------------------------------------------------------------
/examples/todo-canvas-app/cypress.json:
--------------------------------------------------------------------------------
1 | {
2 | "baseUrl": "http://localhost:3000"
3 | }
4 |
--------------------------------------------------------------------------------
/examples/todo-canvas-app/src/react-app-env.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 |
--------------------------------------------------------------------------------
/.prettierignore:
--------------------------------------------------------------------------------
1 | /node_modules/
2 | /package.json
3 | /package-lock.json
4 | /dist
5 | README.md
6 |
--------------------------------------------------------------------------------
/.npmrc:
--------------------------------------------------------------------------------
1 | @sberdevices:registry=https://registry.npmjs.org/
2 | //registry.npmjs.org/:_authToken=${NPM_REGISTRY_TOKEN}
3 |
--------------------------------------------------------------------------------
/examples/todo-canvas-app/public/robots.txt:
--------------------------------------------------------------------------------
1 | # https://www.robotstxt.org/robotstxt.html
2 | User-agent: *
3 | Disallow:
4 |
--------------------------------------------------------------------------------
/.lintstagedrc:
--------------------------------------------------------------------------------
1 | {
2 | "src/*.{js,jsx,ts,tsx}": [
3 | "eslint --fix",
4 | "pretty-quick --staged"
5 | ],
6 | }
--------------------------------------------------------------------------------
/examples/todo-canvas-app/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sberdevices/assistant-client/HEAD/examples/todo-canvas-app/public/favicon.ico
--------------------------------------------------------------------------------
/examples/todo-canvas-app/public/logo192.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sberdevices/assistant-client/HEAD/examples/todo-canvas-app/public/logo192.png
--------------------------------------------------------------------------------
/examples/todo-canvas-app/public/logo512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sberdevices/assistant-client/HEAD/examples/todo-canvas-app/public/logo512.png
--------------------------------------------------------------------------------
/.huskyrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "hooks": {
3 | "pre-commit": "lint-staged",
4 | "commit-msg": "commitlint -E HUSKY_GIT_PARAMS"
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/examples/todo-canvas-app/src/global.d.ts:
--------------------------------------------------------------------------------
1 | export declare global {
2 | interface Window {
3 | Cypress?: Record;
4 | }
5 | }
6 |
--------------------------------------------------------------------------------
/examples/todo-canvas-app/src/index.css:
--------------------------------------------------------------------------------
1 | * {
2 | box-sizing: border-box;
3 | font-family: sans-serif;
4 | }
5 |
6 | html,
7 | body {
8 | margin: 0;
9 | padding: 0;
10 | }
11 |
--------------------------------------------------------------------------------
/.editorconfig:
--------------------------------------------------------------------------------
1 | root = true
2 |
3 | [*]
4 | charset = utf-8
5 | end_of_line = lf
6 | indent_size = 4
7 | indent_style = space
8 | insert_final_newline = true
9 | max_line_length = 120
10 | trim_trailing_whitespace = true
11 |
12 | [*.{json,md,yaml,yml}]
13 | indent_size = 2
14 |
--------------------------------------------------------------------------------
/.commitlintrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": ["@commitlint/config-conventional"],
3 | "rules": {
4 | "subject-case": [0],
5 | "type-enum": [2, "always", ["build", "ci", "chore", "feat", "fix", "docs", "style", "perf", "refactor", "test", "revert", "breaking"]]
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/examples/todo-canvas-app/src/setupTests.ts:
--------------------------------------------------------------------------------
1 | // jest-dom adds custom jest matchers for asserting on DOM nodes.
2 | // allows you to do things like:
3 | // expect(element).toHaveTextContent(/react/i)
4 | // learn more: https://github.com/testing-library/jest-dom
5 | import '@testing-library/jest-dom';
6 |
--------------------------------------------------------------------------------
/cypress/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../tsconfig.json",
3 | "compilerOptions": {
4 | "noEmit": false,
5 | "types": [
6 | "cypress"
7 | ]
8 | },
9 | "include": [
10 | "../node_modules/cypress",
11 | "../*/*.ts"
12 | ]
13 | }
14 |
--------------------------------------------------------------------------------
/.prettierrc:
--------------------------------------------------------------------------------
1 | {
2 | "parser": "typescript",
3 | "arrowParens": "always",
4 | "printWidth": 120,
5 | "jsxBracketSameLine": false,
6 | "jsxSingleQuote": false,
7 | "endOfLine": "auto",
8 | "semi": true,
9 | "singleQuote": true,
10 | "tabWidth": 4,
11 | "trailingComma": "all"
12 | }
13 |
--------------------------------------------------------------------------------
/examples/todo-canvas-app/cypress/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../tsconfig.json",
3 | "compilerOptions": {
4 | "noEmit": false,
5 | "types": [
6 | "cypress"
7 | ]
8 | },
9 | "include": [
10 | "../node_modules/cypress",
11 | "../*/*.ts"
12 | ]
13 | }
14 |
--------------------------------------------------------------------------------
/src/declarations.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 |
3 | declare module '*.svg' {
4 | export const ReactComponent: React.FunctionComponent>;
5 | export default ReactComponent;
6 | }
7 |
8 | declare module '*.png' {
9 | const content: string;
10 | export default content;
11 | }
12 |
--------------------------------------------------------------------------------
/global.d.ts:
--------------------------------------------------------------------------------
1 | import { AssistantWindow } from './src/typings';
2 |
3 | export declare global {
4 | // eslint-disable-next-line @typescript-eslint/no-empty-interface
5 | interface Window extends AssistantWindow {}
6 |
7 | interface Window {
8 | __ASSISTANT_CLIENT__: { version: string };
9 | webkitAudioContext?: new () => AudioContext;
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | ##### OS FILES
2 | .DS_Store
3 | .history
4 |
5 | ##### Editors
6 | .*.swp
7 | .idea
8 | .vscode
9 | .vs
10 | *.iml
11 | *.sublime-project
12 | *.sublime-workspace
13 |
14 | ##### BUILD
15 | node_modules/
16 | cypress/videos/
17 | npm-debug.log
18 | dist/
19 | esm/
20 | umd/
21 | *.tsbuildinfo
22 | build/
23 |
24 | # cypress
25 | cypress/screenshots/
26 | cypress/videos/
27 |
28 | .cache
29 | .env
30 |
--------------------------------------------------------------------------------
/src/index.ts:
--------------------------------------------------------------------------------
1 | export * from './createAssistant';
2 | export * from './createAssistantDev';
3 | export {
4 | AssistantEvent,
5 | AppEvent,
6 | VpsEvent,
7 | ActionCommandEvent,
8 | AssistantEvents as AssistantClientEvents,
9 | createAssistant as createAssistantClient,
10 | } from './assistantSdk/assistant';
11 | export { createNavigatorAudioProvider } from './assistantSdk/voice/listener/navigatorAudioProvider';
12 |
--------------------------------------------------------------------------------
/examples/todo-canvas-app/src/reportWebVitals.ts:
--------------------------------------------------------------------------------
1 | import { ReportHandler } from 'web-vitals';
2 |
3 | const reportWebVitals = (onPerfEntry?: ReportHandler) => {
4 | if (onPerfEntry && onPerfEntry instanceof Function) {
5 | import('web-vitals').then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => {
6 | getCLS(onPerfEntry);
7 | getFID(onPerfEntry);
8 | getFCP(onPerfEntry);
9 | getLCP(onPerfEntry);
10 | getTTFB(onPerfEntry);
11 | });
12 | }
13 | }
14 |
15 | export default reportWebVitals;
16 |
--------------------------------------------------------------------------------
/examples/todo-canvas-app/src/index.tsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import ReactDOM from "react-dom";
3 | import "./index.css";
4 | import { App } from "./App";
5 | import reportWebVitals from "./reportWebVitals";
6 |
7 | ReactDOM.render(
8 |
9 |
10 | ,
11 | document.getElementById("root")
12 | );
13 |
14 | // If you want to start measuring performance in your app, pass a function
15 | // to log results (for example: reportWebVitals(console.log))
16 | // or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
17 | reportWebVitals();
18 |
--------------------------------------------------------------------------------
/src/createRecoveryStateRepository.ts:
--------------------------------------------------------------------------------
1 | const prefix = 'recovery_';
2 |
3 | export const createRecoveryStateRepository = () => {
4 | const get = (key: string): unknown => {
5 | const value = localStorage.getItem(`${prefix}${key}`);
6 |
7 | return value ? JSON.parse(value) : null;
8 | };
9 | const set = (key: string, state: unknown) => {
10 | state && localStorage.setItem(`${prefix}${key}`, JSON.stringify(state));
11 | };
12 | const remove = (key: string) => {
13 | localStorage.removeItem(`${prefix}${key}`);
14 | };
15 |
16 | return { get, set, remove };
17 | };
18 |
--------------------------------------------------------------------------------
/examples/todo-canvas-app/public/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "short_name": "React App",
3 | "name": "Create React App Sample",
4 | "icons": [
5 | {
6 | "src": "favicon.ico",
7 | "sizes": "64x64 32x32 24x24 16x16",
8 | "type": "image/x-icon"
9 | },
10 | {
11 | "src": "logo192.png",
12 | "type": "image/png",
13 | "sizes": "192x192"
14 | },
15 | {
16 | "src": "logo512.png",
17 | "type": "image/png",
18 | "sizes": "512x512"
19 | }
20 | ],
21 | "start_url": ".",
22 | "display": "standalone",
23 | "theme_color": "#000000",
24 | "background_color": "#ffffff"
25 | }
26 |
--------------------------------------------------------------------------------
/src/record/record-downloader.ts:
--------------------------------------------------------------------------------
1 | import { RecordSaver } from '../typings';
2 |
3 | export const createRecordDownloader = (): RecordSaver => {
4 | return {
5 | save: (record: object) => {
6 | const dataStr = `data:text/json;charset=utf-8,${encodeURIComponent(JSON.stringify(record))}`;
7 | const anchor = document.createElement('a');
8 | anchor.setAttribute('href', dataStr);
9 | anchor.setAttribute('download', 'assistant-log.json');
10 | document.body.appendChild(anchor);
11 | anchor.click();
12 | anchor.remove();
13 | },
14 | };
15 | };
16 |
--------------------------------------------------------------------------------
/examples/todo-canvas-app/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "es5",
4 | "lib": [
5 | "dom",
6 | "dom.iterable",
7 | "esnext"
8 | ],
9 | "allowJs": true,
10 | "skipLibCheck": true,
11 | "esModuleInterop": true,
12 | "allowSyntheticDefaultImports": true,
13 | "strict": true,
14 | "forceConsistentCasingInFileNames": true,
15 | "noFallthroughCasesInSwitch": true,
16 | "module": "esnext",
17 | "moduleResolution": "node",
18 | "resolveJsonModule": true,
19 | "isolatedModules": true,
20 | "noEmit": true,
21 | "jsx": "react-jsx"
22 | },
23 | "include": [
24 | "src"
25 | ]
26 | }
27 |
--------------------------------------------------------------------------------
/src/record/console-logger.ts:
--------------------------------------------------------------------------------
1 | /* eslint-disable no-console */
2 | import { ClientLogger } from '../typings';
3 |
4 | export type ConsoleLoggerCreator = (level?: 'debug' | 'log') => ClientLogger;
5 |
6 | export const createConsoleLogger: ConsoleLoggerCreator = (level = 'debug') => (entry) => {
7 | switch (entry.type) {
8 | case 'init': {
9 | console[level]('Initialize', entry.params);
10 |
11 | break;
12 | }
13 | case 'incoming': {
14 | console[level]('Received message', entry.message);
15 |
16 | break;
17 | }
18 | case 'outcoming': {
19 | console[level]('Sended message', entry.message);
20 |
21 | break;
22 | }
23 | default: {
24 | break;
25 | }
26 | }
27 | };
28 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compileOnSave": true,
3 | "compilerOptions": {
4 | "jsx": "react",
5 | "target": "ES5",
6 | "lib": ["ES2020.Promise", "esnext.asynciterable", "DOM"],
7 | "declaration": true,
8 | "declarationMap": true,
9 | "composite": false,
10 | "strict": true,
11 | "strictNullChecks": true,
12 | "noUnusedLocals": true,
13 | "noUnusedParameters": true,
14 | "noImplicitReturns": true,
15 | "noFallthroughCasesInSwitch": true,
16 | "moduleResolution": "node",
17 | "esModuleInterop": true,
18 | "resolveJsonModule": true,
19 | "skipLibCheck": true,
20 | "skipDefaultLibCheck": true,
21 | "rootDir": "src",
22 | "allowJs": true
23 | },
24 | "include": ["src", "global.d.ts"],
25 | "exclude": ["**/tests/**/*", "**/dist/**/*"]
26 | }
27 |
--------------------------------------------------------------------------------
/src/nanoobservable.ts:
--------------------------------------------------------------------------------
1 | import { createNanoEvents } from './nanoevents';
2 |
3 | export type ObserverFunc = (data: T) => void;
4 |
5 | interface Events {
6 | next: ObserverFunc;
7 | }
8 |
9 | export interface Observer {
10 | next: ObserverFunc;
11 | }
12 |
13 | export interface Observable {
14 | subscribe: (observer: Observer) => { unsubscribe: () => void };
15 | }
16 |
17 | export const createNanoObservable = (observerFunc: (observer: Observer) => void): Observable => {
18 | const { on, emit } = createNanoEvents>();
19 |
20 | const subscribe = ({ next }: Observer) => {
21 | const unsubscribe = on('next', next);
22 | return { unsubscribe };
23 | };
24 |
25 | observerFunc({
26 | next: (data: T) => {
27 | emit('next', data);
28 | },
29 | });
30 |
31 | return {
32 | subscribe,
33 | };
34 | };
35 |
--------------------------------------------------------------------------------
/src/NativePanel/fonts.ts:
--------------------------------------------------------------------------------
1 | const FONTS_CDN = 'https://cdn-app.sberdevices.ru/shared-static/0.0.0/fonts/SBSansText/';
2 |
3 | export const fontFace = `
4 | @font-face {
5 | font-family: 'SB Sans Text';
6 | src: local('SB Sans Text Medium'), local('SBSansText-Medium'), url('${FONTS_CDN}SBSansText-Medium.woff2') format('woff2'), url('${FONTS_CDN}SBSansText-Medium.woff') format('woff');
7 | font-weight: 500;
8 | font-style: normal;
9 | }
10 |
11 | @font-face {
12 | font-family: 'SB Sans Text';
13 | src: local('SB Sans Text Regular'), local('SBSansText-Regular'), url('${FONTS_CDN}SBSansText-Regular.woff2') format('woff2'), url('${FONTS_CDN}SBSansText-Regular.woff') format('woff');
14 | font-weight: 400;
15 | font-style: normal;
16 | }
17 | `;
18 |
19 | export const fontFamily500 = `
20 | font-family: 'SB Sans Text';
21 | font-weight: 500;
22 | `;
23 |
24 | export const fontFamily400 = `
25 | font-family: 'SB Sans Text';
26 | font-weight: 400;
27 | `;
28 |
--------------------------------------------------------------------------------
/examples/umd-example/README.md:
--------------------------------------------------------------------------------
1 | # umd-example
2 |
3 | Это небольшое Todo приложение (добавление, выполнение и удаление задач. [См. видео](https://youtu.be/P-o2rwHhARo)) демонстрирует пример взаимодействия с [Assistant Client](https://github.com/sberdevices/assistant-client).Голосовой помощник интегрирован с помощью подключения umd-сборки в теге
23 |
24 |
25 |
26 |
27 | Мой список дел:
28 |
29 |
85 |
86 |