Skip to content

Repository files navigation

Snips Toolkit

Everything you need in order to write Snips actions.

Setup

npm i snips-toolkit

Then use it in your package.json file scripts.

"scripts": {
"build": "snips-toolkit build",
"dev": "snips-toolkit dev",
"test": "snips-toolkit test '^.*\\.spec\\.[jt]s$'",
"launch": "snips-toolkit run"
}

Assumes that your action is structured in the following way by default:

.
├── src # sources folder| └── index.[jt]s # the action code entry point|
├── dist # the action build output folder|
├── tests # tests folder| └── *.spec.[tj]s # any number of test files|
├── package.json # with an extra "sandbox" key, highlighted lower in the documentation|
├── config.ini # action configuration file|
└── assets
└── i18n # internationalization folder
└── <locale>.json # translation file for a given language

Command line

snips-toolkit --help

Displays a help message and exits.

snips-toolkit build

Builds your action to ./dist/index.js using webpack.

This command will warn if your action code uses node.js native modules, and they will be automatically added to your package.json file under the sandbox key.

// Example:"sandbox": [
"fs",
"http",
"https",
"os",
"path",
"stream",
"tty",
"url",
"util",
"zlib"
]

snips-toolkit dev

Automatically rebuilds and run the Snips action on file change.

You can debug the action by connecting a debugger to the 9229 port. Check the node.js website for more details.

Use the -c/--config-path if you need to use custom hermes options. Use the -ns/--no-sandbox to disable the sandbox.

snips-toolkit test [files]

Runs your test suite with jest.

Use the -s/--sandbox flag to run the tests in a sandboxed environment.

snips-toolkit run

Runs your Snips action.

Use the -c/--config-path if you need to use custom hermes options. Use the -ns/--no-sandbox to disable the sandbox.

Utils

import { config } from 'snips-toolkit'

Initialize once by calling .init, then use .get to retrieve the configuration.

// Reads the configuration file located at `./config.ini`.config.init()
// Get the configuration.constconfiguration=config.get()

Depends on node.js modules fs, path.

import { i18n } from 'snips-toolkit'

Initialize once by calling .init.

Uses the i18next library under the hood.

// Reads the `./assets/i18n/en.json` translation file and initializes an i18next instance.awaiti18n.init('en')
// Get a translation. (see https://www.i18next.com/overview/api#t)consttranslation=i18n.translate(keys,options)
// Get the translation for an error message.// Assumes that the translation file contains the key 'error.<error message>'.consterrorTranslation=awaiti18n.errorMessage(error)
// Get a random translation for a given key.// Assumes that the translation file maps an array of possible translations to the key.consttranslation=i18n.randomTranslation(keys,options)

Depends on node.js modules fs, path.

import { http } from 'snips-toolkit'

An http client using wretch.

constpokeapi=http('https://pokeapi.co/api/v2')constbulbasaur=awaitpokeapi.url('/pokemon/1').get().json()

Depends on node.js modules http, https, stream, zlib, url.

import { logger } from 'snips-toolkit'

A logger using debug.

// Enables error printing. You can use * as a wildcard.logger.enable('error')
// Logs to <actionName>:errorlogger.debug('error')// Logs to <actionName>:infologger.info('info')// Logs to <actionName>:debuglogger.error('debug')

Depends on node.js modules tty, util, os.

import { handler } from 'snips-toolkit'

Utilities for handling hermes callbacks.

// Wrap a dialogue handler to gracefully capture and log errors.handler.wrap((msg,flow)=>{// ... //})

Depends on internal modules i18n, logger.

import { message } from 'snips-toolkit'

Utilities for parsing hermes messages.

// Get slots matching the slot name.constmySlot=message.getSlotsByName(// The message instancemsg,// The slot name'mySlotName',{// If true, returns only the slot with the highest confidence.onlyMostConfident: true,// If specified, returns only slots having a confidence higher than this threshold.threshold: 0.5})
// Calculates the ASR confidence.constconfidence=message.getAsrConfidence(msg)

import { camelize } from 'snips-toolkit'

Camelcase utilities using the camelcase package.

// Camelize a stringconstcamelizedKey=camelize(key)
// Returns a cloned object having camelized keys.constcamelizedObject=camelizeKeys(object)

Hermes configuration

In order to pass custom hermes options, you can use the -c flag to specify the path to a configuration file.

For instance, if you are using an mqtt broker running on a different machine, you could add options in a file named hermes_config.json.

{
"address": "ip:port"
}

And add the -c flag in the package.json file.

"scripts": {
"dev": "snips-toolkit dev -c ./hermes_config.json",
"launch": "snips-toolkit run -c ./hermes_config.json"
}

Unit tests

During unit tests, your action code is run is parallel with the tests and i18n/http utils are mocked.

Mocks

http

You can use the provided SnipsToolkit.mock.http global function to override http calls automatically during tests.

// Place this code in the root of the test file to mock.SnipsToolkit.mock.http(fetchMock=>{// Define as many mocks as you need.// See http://www.wheresrhys.co.uk/fetch-mock for API detailsfetchMock.mock('https://my.super.api/route',{hello: "world"})})

i18n

The i18n.translate output is not the translation but a stringified JSON reprensentation of the key/options.

This call:

// This call:i18n.translate('pokemon.info',{name: 'Pikachu',weight: 10,height: 20})

Returns when mocked: (in stringified form)

{
"key": "pokemon.info",
"options": {
"name": "Pikachu",
"weight": 10,
"height": 20
}
}

globals

You can use the provided SnipsToolkit.mock.globals global function to override or define global variables.

SnipsToolkit.mock.globals(globals=>{// Mocks the Date object in a crude way.constBackupedDate=global.DateconstfreezedTime=1550835788763constmockedDate=functionDate(arg: string|number|Date){returnnewBackupedDate(arg||freezedTime)}mockedDate.now=()=>freezedTimemockedDate.parse=BackupedDate.parsemockedDate.UTC=BackupedDate.UTC// Assign the mocked Date to the globals objectglobals.Date=mockedDate})

Session

To simulate dialogue session rounds, you can use the Session helper that will pass hermes messages between your test and action code.

import{Test}from'snips-toolkit'/* ... */// Initialize a session instanceconstsession=newTest.Session()// Publish an intent message that is expected by the action code to start a sessionawaitsession.start({intentName: 'pokemon_details',input: 'Give me the details for Pokemon 1',slots: [// Function that creates a custom slot, omitted for the sake of brevity.createPokemonIdSlot('1')]})// Expect the action code to publish a continue session message// and reply with the following intent message (here we simulate a confirmation message)constcontinuation=awaitsession.continue({intentName: 'pokemon_confirm',input: 'Yes please'})// Expect the action to end the session and retrieve the end session message valueconstendSessionMessage=awaitsession.end()// Extract the key/options of the TTS spoken by the end session messageconst{ key, options }=JSON.parse(endSessionMessage.text||'')// Assert that the values are correctexpect(key).toBe('pokemon.info')expect(options.name).toBe('bulbasaur')expect(options.weight).toBe(69)expect(options.height).toBe(7)

About

Everything you need in order to write Snips actions in javascript / typescript.

Resources

Stars

9 stars

Watchers

21 watching

Forks

Releases

Packages

Used by

Contributors

Languages