alexa-js / alexa-app Goto Github PK
View Code? Open in Web Editor NEWA framework for Alexa (Amazon Echo) apps using Node.js
Home Page: https://www.youtube.com/watch?v=pzM4jv7k7Rg
License: MIT License
A framework for Alexa (Amazon Echo) apps using Node.js
Home Page: https://www.youtube.com/watch?v=pzM4jv7k7Rg
License: MIT License
The echo expects numbers like "twenty two" but the schema generation is creating them in the format of "twenty-two". I am working around this with regex replacement.
If an intent handler tries to launch an async request and respond to alexa when the async call completes, this doesn't work. The (empty) response is already flushed. The lib should allow for the common need of using async requests in intent requests.
Is anyone using this in combination with https://github.com/alexa/alexa-skills-kit-sdk-for-nodejs?
I really like the local development approach with this but can see some advantages of the alexa-sdk (for example how it handles skill state management is much more advanced than this module).
It seems that the generateUtterances
function is very well contained and is probably useful outside of alexa-app
. Would you be open to moving this to new npm module, say alexa-utterances
?
I'd be happy to pull this out into its' own module if that would be accepted as a PR
I may have not dug into this enough, but just curious if there are any plans for having any sort of top level provider/configurator for controlling the types skills request/responses this framework uses. I know right now this works great with custom skills, but i'd imagine in a similar way we could abstract away the request/response contract for other types of skills as they become made available by Amazon.
Thoughts?
Hi there! This is awesome stuff. I was hoping to incorporate some of this into something I'm working on, but I noticed there wasn't a license. I was wondering if you wouldn't mind adding one to the project so that I could do that and contribute any improvements back upstream. Thanks!
From the docs, it doesn't seem like it's possible to capture an IntentRequest that doesn't match any of the registered Intents.
I think it'd be best to handle it using the same app.intent method, but with a null intent name:
app.intent(null, function(request,response) {
// Stuff to do if we get an unknown Intent!
});
How do I increase timeout response if there is slow internet connection?
I want my pre()
to able to make asynchronous calls before running the request. like this:
app.pre = (request, response, type) ->
getAccessToken request.data.session.user.userId, (er, token) ->
if er or (not token)
response.fail 'Sorry, you must link your device first.'
else
# TODO: proceed to normal intent handler
Is there a way to do asynchronous things in pre?
Schema generation adds extra white space when skipping an optional item. An example would be "fu {bar|} baz" will generate "fu bar baz" and "fu baz" with extra white space where it skipped bar. I am trimming that down with regex replacement but it would be best if skipped pieces of a generated string do not add white space.
I am trying to wrap my head around the idea behind turning the session attributes on the response in to a setter function rather than just neatly exposing the object.
You don't have a getter function set up, so when the user needs to read values from the attributes he can't without going in and accessing request.request.sessionAttributes
anyway.
Since the setter isn't providing any utility, maybe it should be removed and the interface simplified? It seems like it's a setter for setter's sake.
I'm really happy to see there are some new maintainers breathing life into this! I find this library's design far more usable than Amazon's official library.
I started writing a router (alexa-app-router) for use in my own project Mountain Top, on GitHub and published in the Skills store.
I wanted to see if others would find use in this kind of router. I find it far more usable than intents as the main Alexa paradigm. I built it to require minimal configuration, and envision supporting route parameters and more complex use cases in future versions.
As of now, it's bolt-on ready for alexa-app
and doesn't alter the core library behaviors. I plan to continue it solely as an add-on now, though if many people find it useful a link in the official README could give it some visibility. If it proves popular and would fit well in the main library, I'd be happy to donate the code, otherwise I don't think there's a big downside to keeping it separate.
I'm trying to just start a basic application that has a simple input. If I don't provide multiple options per utterance, the utterances()
function fails.
$ cat foo.js
var alexa = require('alexa-app'),
app = new alexa.app('foobar');
app.intent('HelloWorld',
{
"utterances": [
"hello world"
]
},
function(request, response) {
response.say("hello world");
}
);
console.log(app.utterances());
console.log(app.schema());
$ node foo.js
/tmp/node_modules/alexa-app/node_modules/js-combinatorics/combinatorics.js:287
if (!arguments.length) throw new RangeError;
^
RangeError
at cartesianProduct (/tmp/node_modules/alexa-app/node_modules/js-combinatorics/combinatorics.js:287:38)
at generateUtterances (/tmp/node_modules/alexa-app/index.js:360:51)
at /tmp/node_modules/alexa-app/index.js:265:17
at Array.forEach (native)
at utterances (/tmp/node_modules/alexa-app/index.js:264:30)
at Object.<anonymous> (/tmp/foo.js:15:17)
at Module._compile (module.js:456:26)
at Object.Module._extensions..js (module.js:474:10)
at Module.load (module.js:356:32)
at Function.Module._load (module.js:312:12)
at Function.Module.runMain (module.js:497:10)
at startup (node.js:119:16)
at node.js:935:3
The API for including a card has an optional subtitle
argument. But it doesn't seem to do anything. Looking at this forum post, this parameter may have been removed from the Alexa Skills API? The subtitle on cards is now the skill name.
Greetings,
Sorry, but I am unclear on how SSML support works currently
The only success I've had in getting an SSML output is by doing the following
awsResponse.response.response.outputSpeech.type = 'SSML';
awsResponse.response.response.outputSpeech.ssml = awsResponse.response.response.outputSpeech.text;
And manually inserting my own 'say' tags.
Obviously this isn't the ideal way to do it, but there I'm a bit confused on how to actually get an SSML response to work.
No matter what I put in response.say currently, the response type is always 'PlainText'. I noticed that calling clear
can lead to this behavior, but I never call it.
If it makes a difference, my intent and launch handlers are asynchronous
As of right now, the only way to do asynchronous things in the intent handler is to return false and then call res.send(). Although this works and is documented in the readme, it is different from the commonly used design patter of using a callback function as the last parameter. One example would be mocha and the 'done' pattern.
Also since internally the request handler uses a promise it would be nice to be able to return a promise from the intent handler, this would also allow for another commonly used pattern of writing asynchronous code.
Thoughts?
Hey Matt - it looks like Amazon has released the ASK for audio playback. Are you planning to upgrade to accommodate and/or continue dev on this project?
One common thing that I want to do at the beginning of my Alexa apps is to validate that the request has the proper AppID.
It would be nice if there were a way to do validation on a request before it moves forward with the rest of the logic.
I could see you implementing a built-in appID validation feature, or simply provide a way for the module user to provide a validation method that has the opportunity to kill the session with a response before it moves on to the other event types.
I appears that the SSML update to this app introduced an issue where alexa-app is transforming all digits (1, 2, 3) in to the spelled-out version (one, two, three).
It also makes it impossible to use the "say as digits" feature in SSML due to the digits never actually ending up in the string.
Your 'to-ssml.js' function is cleansing the response text of and other tags, which prevents me from adding an tag in between speech. Is there another way to add audio, for example , to the response object?
Hello,
I'm trying to get alexa-app 2.0 working, and I'm stuck at just getting the launch event to fire. The error I'm getting is below. So far I just have a basic alexa-app and on app.launch i'm just console logging a SUCCESS.
It seems that alexa.request is getting json that does NOT contain any session information.
Any ideas on what to try?
Unhandled rejection TypeError: Cannot read property 'new' of undefined
at new alexa.request (/Users/hazlewoo/Repos/quincy-echo/node_modules/alexa-app/index.js:66:26)
at /Users/hazlewoo/Repos/quincy-echo/node_modules/alexa-app/index.js:124:18
at request (/Users/hazlewoo/Repos/quincy-echo/node_modules/alexa-app/index.js:123:10)
at callbacks (/Users/hazlewoo/Repos/quincy-echo/node_modules/express/lib/router/index.js:164:37)
at param (/Users/hazlewoo/Repos/quincy-echo/node_modules/express/lib/router/index.js:138:11)
at pass (/Users/hazlewoo/Repos/quincy-echo/node_modules/express/lib/router/index.js:145:5)
at Router._dispatch (/Users/hazlewoo/Repos/quincy-echo/node_modules/express/lib/router/index.js:173:5)
at Object.router (/Users/hazlewoo/Repos/quincy-echo/node_modules/express/lib/router/index.js:33:10)
at next (/Users/hazlewoo/Repos/quincy-echo/node_modules/express/node_modules/connect/lib/proto.js:194:15)
at Object.staticMiddleware [as handle] (/Users/hazlewoo/Repos/quincy-echo/node_modules/express/node_modules/connect/node_modules/serve-static/index.js:67:61)
at next (/Users/hazlewoo/Repos/quincy-echo/node_modules/express/node_modules/connect/lib/proto.js:194:15)
at cors (/Users/hazlewoo/Repos/quincy-echo/node_modules/cors/lib/index.js:122:7)
at /Users/hazlewoo/Repos/quincy-echo/node_modules/cors/lib/index.js:177:17
I'm working on a skill server written in typescript that utilizes the beauty of async/await. Trouble is, in order make async calls within my intent handlers, something integral to the application, I have to return false before the async call is made. This isn't possible (or at least I haven't figured out a reasonable work around) for me to do in the way I want to write my intents as async/await makes the flow of my program seem procedural to the author. So, instead of returning false outside of the async callback function, the remainder of the code block gets wrapped up into a callback at compile time.
I have gone into the library and switched off the check that calls res.send() should the intent not return false, but I would love to have a configuration option when creating the alexa-app that just says "autoSend: false" or something like that.
Would be happy to write it and submit a pull request. What do you think? Am I missing something? Does this seem like a reasonable feature?
utterances not keeping braces around slot names when generating content.
Also slots are optional, please remove if empty.
From this:
{
"slots": {"date": "AMAZON.DATE", "city": "AMAZON.US_CITY"},
"utterances": [
"what movies are playing {on |} {date}",
"what movies are playing {in|near|around} {city}",
"what movies are playing {in|near|around} {city} {on |} {date}",
"what movies are playing {on |} {date} {in|near|around} {city}"
]
}
Generates this:
{
"intents": [
{
"intent": "AMAZON.HelpIntent",
"slots": []
},
{
"intent": "AMAZON.StopIntent",
"slots": []
},
{
"intent": "AMAZON.CancelIntent",
"slots": []
},
{
"intent": "GetMoviesIntent",
"slots": [
{
"name": "date",
"type": "AMAZON.DATE"
},
{
"name": "city",
"type": "AMAZON.US_CITY"
}
]
}
]
}
GetMoviesIntent what movies are playing on date
GetMoviesIntent what movies are playing date
GetMoviesIntent what movies are playing in city
GetMoviesIntent what movies are playing near city
GetMoviesIntent what movies are playing around city
GetMoviesIntent what movies are playing in city on date
GetMoviesIntent what movies are playing near city on date
GetMoviesIntent what movies are playing around city on date
GetMoviesIntent what movies are playing in city date
GetMoviesIntent what movies are playing near city date
GetMoviesIntent what movies are playing around city date
GetMoviesIntent what movies are playing on date in city
GetMoviesIntent what movies are playing date in city
GetMoviesIntent what movies are playing on date near city
GetMoviesIntent what movies are playing date near city
GetMoviesIntent what movies are playing on date around city
GetMoviesIntent what movies are playing date around city
There are a few verbal responses that can come directly from the alexa-app module, that cannot be configured by the developer. I would prefer to have control over any possible verbal response that comes from my app, so either kicking off an error event that can be implemented or allowing those responses to be configured would be great!
I was banging my head against the wall trying to figure out why alexa-app wasn't seeming to call some of my Intent events correctly.
I finally figured out that alexa-app wraps the event calls in a try-catch, invisibly discarding all exceptions. This makes it hell to develop on!
If I do a check in the app.pre() and it failed, I expect it just response the error message in app.pre() and terminate the request. But turned out, it sent out response in app.pre(), and still keep running the intent request.
Any thoughts?
How to implement some intent to only be triggered if some previous specific intent was fired.
after going through the submission process, we've been rejected because we're not validating the request signature, as per here: https://developer.amazon.com/public/solutions/alexa/alexa-skills-kit/docs/developing-an-alexa-skill-as-a-web-service#Checking%20the%20Signature%20of%20the%20Request
I think alexa-app needs to have this logic. I googled around and couldn't find any node.js examples but there are several php and java based examples out there. This might be a good starting point: http://pastebin.com/d0W9nX60
Right now, all session attributes that come in as the request are automatically copied by alexa-app in to the response. This is only sometimes going to be desirable, and many times absolutely undesirable behavior. At the very least this should be a feature that can be toggled, and I'd suggest making the default be off. Session attributes will often hold state data, and sending along to the next request would complicate things greatly.
I do think there would be more utility in alexa-app persisting the session attributes in a historical manner, such as in an array of previous requests.
You also have a comment saying something about Alexa not doing this automatically being a bug, but that can't be the case. The response is a JSON object you build yourself; there's no concept of Alexa having any control or insight in to how you do that. There is no response object until you make it!
This is nit-picky, but the use of an extensionless eslint is deprecated, and it should be super simple to change.
v1.10.0 introduces the ability to use configuration files in different formats. Instead of the regular .eslintrc file, you can use a JavaScript (.eslintrc.js), a YAML file (.eslintrc.yml or .eslintrc.yaml), or a JSON file (.eslintrc.json). We are formally deprecating use of the .eslintrc extensionless configuration file format in favor the format-specific versions. Don't worry, we'll still support .eslintrc files for a long time, but we'd like to encourage everyone to move to the new file formats as you'll get advantages such as syntax highlighting and error detection with many editors.
(bold added by me)
I've got a feature idea that I am going to implement in to my own fork of this. I'd be happy to submit it as a Pull Request if this is something you'd like!
The feature introduces the idea of "Contexts" which provide another layer of routing for intents. Basically, registered Intents can have one or more "Contexts" associated with them. When a request comes in indicating that it is in a particular context (by way of a private sessionAttribute managed by the module), the actual Intent event that fires will be the one that is for that context.
This sort of thing will be very useful in situations where many different multi-step "conversational" responses are expected. For example, there might be 5 different situations in which Alexa asks the user a yes or no question, and so that same "YesIntent" would need to behave very differently in each. Currently the way to deal with this is:
app.intent("YesIntent", function(req, res) {
if (req.session('question' === "AreYouHappy") {
// User answered "Yes" to "Are you happy?"
} else if (req.session('question' === "IsItRaining") {
// User answered "Yes" to "Is it raining?"
} else if (req.session('question' === "HaveYouEaten") {
// User answered "Yes" to "Have you eaten?"
}
}
But with my proposed implementation, it would be this, which is much easier to understand at a glance what is going on. Not to mention more modular!
app.intent({intent: 'YesIntent', context: 'AreYouHappy'}, function(req, res) {
// User answered "Yes" to "Are you happy?"
}
app.intent({intent: 'YesIntent', context: 'IsItRaining'}, function(req, res) {
// User answered "Yes" to "Is it raining?"
}
app.intent({intent: 'YesIntent', context: 'HaveYouEaten'}, function(req, res) {
// User answered "Yes" to "Have you eaten?"
}
If this were implemented to have fallbacks to handle Intents not found in the specific context as well as allow lists of contexts to be specified for a single event, this could end up being very powerful and easy to use for the developer.
Anyway, I'm starting work on it, but let me know if this is something you'd like PRd here!
Throwing an exception, AWS Lambda will time out on future requests randomly. The handler also needs to call context.fail() upon failure.
there seems to be no attribute to the response.card() function to allow for the insertion of images. Or any card type other than "Simple"
something like this would work?
this.standardCard = function(title, content, smallImageUrl, largeImageUrl){ this.response.response.card = {"type": "Standard", "title": title, "content":SSML.cleanse(content), "image": {"smallImageUrl" smallImageUrl, "largeImageUrl": largeImageUrl} }; }
https://developer.amazon.com/public/solutions/alexa/alexa-skills-kit/docs/providing-home-cards-for-the-amazon-alexa-app
I am sure this is a noob problem (sorry if it is), code in https://github.com/dblock/elderfield. The code works locally just fine, including if I download it from Lambda and run locally, but once on Lambda I get this:
$ apex invoke artsy
⨯ Error: function response: Handler 'handle' missing on module '_apex_index'
It's something in my alexa-app, because if stub that code with an apex hello world example that works. Can't find logs or anything else that helps :(
Halp!
If I don't include an express route explicitly, for example, the code below works:
app.post('/appname', function(req, res) {
res.json({
"version": "1.0",
"response": {
"shouldEndSession": true,
"outputSpeech": {
"type": "SSML",
"ssml": "<speak>Hmm <break time=\"1s\"/> not sure why we misconfigured this skill</speak>"
}
}
});
});
then my node app throws a "There was an error calling the remote endpoint, which returned HTTP 404 : Not Found". I'm using the example code and it doesn't set the endpoint anywhere. What am i doing wrong? (This is more of a clarification than an issue... has to be something I'm doing wrong, although I've literally copied and pasted the example code)
As far as I can tell from code and from testing, this commit has unintentionally dropped support for standard requests. I was testing upgrading to latest in master today to try out the new AudioPlayer features and I found that none of my standard launch or intent requests would go through at all. Started debugging and found on line 155 of index.js that "this.data.context" is undefined and produces a catch error that breaks execution. The JSON structure for AudioPlayer requests includes the context attribute and as such is supported by the commit, but the original support for standard requests which include the session attribute was completely dropped. Not sure how this was overlooked, but should be fixed. I am running an alexa-app-server instance to debug locally. If there is some obvious fix to this that I overlooked than it should probably be documented, but at the least the new commit should support legacy code.
There is a handy parameter in an Alexa request, session.new
, that tells the app that this request represents a brand new session.
I would like to be able to register an event handler for when a new session is started to do certain session setup tasks. Right now the only way to do this would be to check that parameter in every intent handler plus the launch handler and call the same function in each case.
Amazon is now recommending we use custom slot types instead of the "LITERAL" type. More here:
[https://developer.amazon.com/public/solutions/alexa/alexa-skills-kit/docs/alexa-skills-kit-interaction-model-reference#Custom Slot Type Syntax](https://developer.amazon.com/public/solutions/alexa/alexa-skills-kit/docs/alexa-skills-kit-interaction-model-reference#Custom Slot Type Syntax)
Basically, in our utterances we don't put the example variables, so for example:
app.intent("whereIsIntent", {
slots: {
"NAME": "LIST_OF_NAMES",
},
utterances: [
"where is {mom|dad|my brother|my sister|my daughter|my son|NAME}"
],
function (req, res) {
var name = request.slot("NAME");
response.say("I don't know where " + name + "is.");
}
});
The utterances generated should be:
whereIsIntent where is {NAME}
And then perhaps we could use a separate method on the app, along with schema
and utterances
, something like customtype(slotname)
? Which would output the following:
mom
dad
my brother
my sister
my daughter
my son
I still think there is value in your combinatorics stuff, and also perhaps it can be re-evaluated as it seems this is exactly what they are trying to obviate with the custom slot type feature.
Calling response.clear()
completely resets the outputSpeech object on the json response. If one subsequently calls response.say('This was called after clear.')
, the response json will look something like this
...
"outputSpeech": {
"type": "PlainText",
"text": "",
"ssml": "<speak>This was called after clear.</speak>"
}
...
Perhaps when calling response.say()
, the outputSpeech type should be checked or re-assigned.
Hello
Maybe i'm to silly but i can't get sessions to work.
I have to intents. intent1 and intent2.
If intent1 is called i like to set a session var like which = 1, so i have tried to set with response.session('which','1') or request.session('which','1')
If intent2 is now called i like to read this var so i have tried with var sess = response.session('which')
or var req = request.session('which')
I only get 'undefined' or the error 'key not found on session attributes: which [TypeError: Cannot read property 'which' of undefined]'
What i'm doing wrong?
Hi,
I am trying to create a basic alexa-app and upload the zip file to lambda.
I have used generator-lambda to create a basic skeleton.
This is the error I keep on getting
{
"errorMessage": "Cannot read property 'new' of undefined",
"errorType": "TypeError",
"stackTrace": [
"new alexa.request (/var/task/node_modules/alexa-app/index.js:149:29)",
"/var/task/node_modules/alexa-app/index.js:227:21",
"tryCatcher (/var/task/node_modules/alexa-app/node_modules/bluebird/js/main/util.js:26:23)",
"Promise._resolveFromResolver (/var/task/node_modules/alexa-app/node_modules/bluebird/js/main/promise.js:480:31)",
"new Promise (/var/task/node_modules/alexa-app/node_modules/bluebird/js/main/promise.js:70:37)",
"request (/var/task/node_modules/alexa-app/index.js:226:12)",
"handler (/var/task/node_modules/alexa-app/index.js:357:10)"
]
}
app.intent('StartIntent', {
"slots": {
"number" : "NUMBER"
},
"utterances": [
"start {1-100|number}"
]
},
This generates utterances:
StartIntent start {one|number}
StartIntent start {two|number}
StartIntent start {three|number}
This doesn't work in sample utterances.
Error: There was a problem with your request: Incorrect syntax: A value may not be supplied for the slot 'number'. Occurred in sample 'StartIntent start {one|number}' on line 4.
With the new long form audio feature utilizing the audio player directives, how do you extend/add a context object to an intent request?
I can add the directives to the response, but the Alexa Skills Kit needs the request object to look like this:
{
"version": "string",
"session": {
"new": true,
"sessionId": "string",
"application": {
"applicationId": "string"
},
"attributes": {
"string": {}
},
"user": {
"userId": "string",
"accessToken": "string"
}
},
"context": {
"System": {
"application": {
"applicationId": "string"
},
"user": {
"userId": "string",
"accessToken": "string"
},
"device": {
"supportedInterfaces": {
"AudioPlayer": {}
}
}
},
"AudioPlayer": {
"token": "string",
"offsetInMilliseconds": 0,
"playerActivity": "string"
}
},
"request": {}
}
Can you use the app.pre()
or app.post
library features to add the context object seen above?
There's a new card type, called LinkAccount
. It enables authenticating your own oauth2 service with alexa skills:
https://developer.amazon.com/public/solutions/alexa/alexa-skills-kit/docs/linking-an-alexa-user-with-a-user-in-your-system#Adding Account Linking Logic to the Service for Your Skill
It would be nice to support this in alexa-app
. I might send a PR for this if I can find some time.
How can I handle built-in intents like AMAZON.StartOverIntent? When I define it like my custom intents it never seems to fire.
Intent request function calls are in a try-catch block. If an exception occurs, the default response is returned, provided that the response was not modified prior to exception. I see that version 2.0 has better error messages & handling, so i just wanted to verify that this is resolved?
So i want to do a check to see if AccountLinking is setup okay in every pre check and if it's not, return a link card to as the user to setup.
But when I do the following:
res.linkAccount();
res.say("Looks like you need to link your account. Please open the Alexa app for setup.");
response.fail("Account not linked");
it fails completely without sending the linkAccount card or saying my message. If I comment out response.fail it works in that i see my link card and hear my message BUT it goes onto the next step whereas I'd like to return to the user rather than passing them onto the intent.
Is this just something I'm doing wrong?
I have a skill that needs location based services. Ex: "Alexa, what's the nearest store to my location?"
Is there a legit intent or method to reference otherwise I was planning on using the request.connection.remoteAddress value. Does the alexa-app request object support that functionality?
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.