TypeScript framework to build cross-platform voice applications (alexa, google home, ...).
But even if you are currently not interested in deploying your voice application to multiple voice assistants, you possibly still should take a look at AssistantJS. On one hand obviously because you never know if your platform requirements may change in future. On the other hand, you probably don't want to miss some of the AssistantJS development features:
assistant s
, backend by express) or generate nlu configurations (assistant g
).@needs
decorator to express dependent entities. AssistantJS will automatically manage prompting for this entity, so you can focus on your real business.Install AssistantJS using npm as a global module:
npm i --global assistant-source
Check out these resources to get started:
Just to give you a first insight into AssistantJS, this is one of the states implemented in our video tutorial:
@injectable()
// Need account linking? Just add @authenticate(OAuthStrategy) over here!
export class MainState extends ApplicationState {
/* Invoked by saying "Launch/Talk to my bus application" */
invokeGenericIntent(machine: Transitionable) {
this.prompt(this.t());
}
/* "Whats the next bus to train station?" */
@needs("target") // Tell AssistantJS to wait for entity "target"
async busRouteIntent(machine: Transitionable) {
await machine.transitionTo("BusOrderState");
const usersTarget = this.entities.get("target") as string;
this.prompt(this.t({target: usersTarget}));
}
}
Wondering about the empty this.t()
calls? Translation keys are matched by applying simple convention over configuration rules. Try to find them out on your own by taking a look at the corresponding translation file:
{
"mainState": {
"invokeGenericIntent": {
"alexa": "Welcome, Alexa user!",
"google": [
"Welcome, Google user!",
"Nice to have you here, Googler!"
]
},
"busRouteIntent": [
"{Love to help you!|} The next bus to {{target}} arrives in {{minutes}} minutes. Do you want me to buy a ticket?"
],
"helpGenericIntent": "Currently, you can only ask for busses. Try it out!"
},
"busOrderState": {
"yesGenericIntent": "{Allright|Okay}! Just sent a ticket to your smartphone!",
"noGenericIntent": "Cancelled, but maybe next time!",
"helpGenericIntent": "Say \"yes\" to buy a ticket, or \"no\" otherwise."
},
}
As you can see, AssistantJS supports you in building more varied voice applications per default. Just use our template syntax ({Allright|Okay}
) or pass all alternatives in an array. Thanks to our convention over configuration rulesets, we are greeting google assistant users different than alexa users. We could even greet them device-specific thanks to these conventions. Oh, and as you can see, inheriting intents (like the helpGenericIntent
above) from other states (here: ApplicationState
) is also possible.
This is what a test (yes, you can test all assistantjs applications without hassle) for the MainState's invokeGenericIntent
could look like:
describe("MainState", function () {
beforeEach(function(this: ThisContext) {
this.specHelper.prepareSpec(this.defaultSpecOptions);
});
describe("on platform = alexa", function() {
beforeEach(function() {
this.platforms.current = this.platforms.alexa;
});
describe("invokeGenericIntent", function() {
beforeEach(async function() {
await this.specHelper.prepareIntentCall(this.platforms.current, "invokeGenericIntent");
this.responseResults = await this.specHelper.runMachineAndGetResults("MainState");
});
it("greets the user", function() {
expect(this.responseResults.voiceMessage!.text).toEqual("Welcome, Alexa user!")
});
it("waits for an answer", function() {
expect(this.responseResults.shouldSessionEnd).toBeFalsy();
});
});
});
});