Skip to content

Commit

Permalink
Merge 0ac697d into 26d2382
Browse files Browse the repository at this point in the history
  • Loading branch information
armonge committed Oct 3, 2018
2 parents 26d2382 + 0ac697d commit 371a255
Show file tree
Hide file tree
Showing 67 changed files with 2,479 additions and 1,162 deletions.
4 changes: 2 additions & 2 deletions docs/alexa-reply.rst
@@ -1,12 +1,12 @@
.. _alexa-reply:

The ``reply`` Object
The ``AlexaReply`` Object
====================


.. js:class:: AlexaReply()

The ``reply`` object is used by the framework to render Alexa responses, it takes all of your ``statements``, ``cards`` and ``directives`` and generates a proper json response for Alexa
``AlexaReply`` object is used by the framework to render Alexa responses, it takes all of your ``statements``, ``cards`` and ``directives`` and generates a proper json response for Alexa

.. js:function:: Reply.fulfillIntent(canFulfill)

Expand Down
Empty file removed docs/alexa.rst
Empty file.
4 changes: 2 additions & 2 deletions docs/dialogflow-directives.rst
Expand Up @@ -238,7 +238,7 @@ Media responses let your app play audio content with a playback duration longer
User Information
----------
----------------

`Actions on Google Documentation <https://developers.google.com/actions/assistant/helpers#user_information>`_

Expand All @@ -264,7 +264,7 @@ You can obtain the following user information with this helper:
Date and Time
---------
-------------

`Actions on Google Documentation <https://developers.google.com/actions/assistant/helpers#date_and_time>`

Expand Down
17 changes: 15 additions & 2 deletions docs/voxa-event.rst
Expand Up @@ -25,7 +25,7 @@ The ``voxaEvent`` Object

.. js:attribute:: platform

A string attribute with the name of platform for the current request, it can be ``alexa``, ``dialogFlow`` or ``botframework``
The currently running :ref:`Voxa Platform <voxa-platforms>`

.. js:attribute:: model

Expand All @@ -52,12 +52,25 @@ The ``voxaEvent`` Object

.. js:attribute:: user

A convenience getter to obtain the user from ``session.user`` or ``context.System.user`` in alexa, and ``conv.user.id`` in dialogflow. In other platforms it's also available, you can always count on the ``voxaEvent.user.userId`` being available. If there's an ``accessToken`` it will also be available through ``voxaEvent.user.accessToken``
An object that contains the userId and accessToken if available

.. code-block:: json
{
"userId": "The platform specific userId",
"id": "same as userId",
"accessToken": "available if user has done account linking"
}
..
.. js:attribute:: model

An instance of the :ref:`Voxa App Model <models>`.

.. js:attribute:: log

An instance of `lambda-log <https://www.npmjs.com/package/lambda-log>`_

.. js:function:: supportedInterfaces()

Array of supported interfaces
Expand Down
8 changes: 6 additions & 2 deletions docs/voxa-reply.rst
Expand Up @@ -3,8 +3,7 @@
The ``reply`` Object
====================


.. js:interface:: IVoxaReply()
.. js:class:: IVoxaReply()

The ``reply`` object is used by the framework to render voxa responses, it takes all of your ``statements``, ``cards`` and ``directives`` and generates a proper json response for each platform.

Expand Down Expand Up @@ -41,3 +40,8 @@ The ``reply`` Object
Converts the model object into session attributes

:param event: A Voxa event with session attributes


For the speceific classes used in every platform you can check:

- :ref:`AlexaReply <alexa-reply>`
6 changes: 6 additions & 0 deletions hello-world/hello-world.js
Expand Up @@ -45,6 +45,12 @@ app.onIntent("LaunchIntent", {
flow: "yield"
});

app.onBeforeReplySent(request => {
if (request.platform.name === "dialogflow") {
request.google.conv.user.storage = {};
}
});

app.onState("likesVoxa?", request => {
if (!request.intent) {
throw new Error("Not an intent request");
Expand Down
2 changes: 1 addition & 1 deletion hello-world/hello-world.spec.js
Expand Up @@ -128,7 +128,7 @@ describe("Hello World", () => {

expect(lambdaCallbackResult).to.deep.equal({
body:
'{"outputContexts":[{"name":"projects/project/agent/sessions/1525973454075/contexts/attributes","lifespanCount":10000,"parameters":{"attributes":"{\\"model\\":{},\\"state\\":\\"likesVoxa?\\"}"}}],"fulfillmentText":"<speak>Welcome to this voxa app, are you enjoying voxa so far?</speak>","source":"google","payload":{"google":{"expectUserResponse":true,"isSsml":true,"richResponse":{"items":[{"simpleResponse":{"textToSpeech":"<speak>Welcome to this voxa app, are you enjoying voxa so far?</speak>"}}]}}}}',
'{"outputContexts":[{"name":"projects/project/agent/sessions/1525973454075/contexts/attributes","lifespanCount":10000,"parameters":{"attributes":"{\\"model\\":{},\\"state\\":\\"likesVoxa?\\"}"}}],"fulfillmentText":"<speak>Welcome to this voxa app, are you enjoying voxa so far?</speak>","source":"google","payload":{"google":{"expectUserResponse":true,"isSsml":true,"richResponse":{"items":[{"simpleResponse":{"textToSpeech":"<speak>Welcome to this voxa app, are you enjoying voxa so far?</speak>"}}]},"resetUserStorage":true}}}',
headers: {
"Content-Type": "application/json; charset=utf-8"
},
Expand Down
7 changes: 3 additions & 4 deletions package.json
Expand Up @@ -33,21 +33,21 @@
"dependencies": {
"@types/aws-lambda": "^8.10.6",
"@types/bluebird": "^3.5.18",
"@types/debug": "^0.0.30",
"@types/i18next": "^8.4.2",
"@types/lambda-log": "^2.0.0",
"@types/lodash": "^4.14.88",
"@types/node": "^8.0.58",
"@types/request-promise": "^4.1.39",
"@types/tedious": "^1.8.32",
"@types/url-join": "^0.8.2",
"@types/uuid": "^3.4.3",
"actions-on-google": "2",
"ask-sdk-model": "^1.4.0-beta.1",
"ask-sdk-model": "1.4.0-beta.1",
"azure-functions-ts-essentials": "^1.3.2",
"bluebird": "^3.5.1",
"botbuilder": "^3.13.1",
"debug": "^3.1.0",
"i18next": "^9.0.1",
"lambda-log": "^2.0.0",
"lodash": "^4.13.1",
"request": "^2.83.0",
"request-promise": "^4.2.2",
Expand All @@ -61,7 +61,6 @@
"@types/mocha": "^2.2.45",
"@types/nock": "^9.3.0",
"@types/simple-mock": "^0.0.27",
"botbuilder-azure": "^3.1.0",
"chai": "^4.1.2",
"chai-as-promised": "^7.1.1",
"coveralls": "^3.0.1",
Expand Down
56 changes: 37 additions & 19 deletions src/StateMachine/StateMachine.ts
Expand Up @@ -21,7 +21,6 @@
*/

import * as bluebird from "bluebird";
import * as debug from "debug";
import * as _ from "lodash";

import { UnhandledState, UnknownState } from "../errors";
Expand All @@ -35,8 +34,6 @@ import {
SystemTransition,
} from "./transitions";

const log: debug.IDebugger = debug("voxa");

export type IStateMachineCb = (
event: IVoxaEvent,
reply: IVoxaReply,
Expand Down Expand Up @@ -69,7 +66,7 @@ export class StateMachine {

constructor(config: IStateMachineConfig) {
this.validateConfig(config);
this.states = config.states;
this.states = _.cloneDeep(config.states);
this.onBeforeStateChangedCallbacks = config.onBeforeStateChanged || [];
this.onAfterStateChangeCallbacks = config.onAfterStateChanged || [];
this.onUnhandledStateCallbacks = config.onUnhandledState || [];
Expand All @@ -92,6 +89,11 @@ export class StateMachine {
}
}

/**
* If the state didn't return a transition and
* there's no global handler for the intent
* we use the onUnhandledState handler
*/
public async checkOnUnhandledState(
voxaEvent: IVoxaEvent,
voxaReply: IVoxaReply,
Expand All @@ -102,7 +104,7 @@ export class StateMachine {
}

if (!transition || _.isEmpty(transition)) {
log("Running onUnhandledStateCallbacks");
voxaEvent.log.debug("Running onUnhandledStateCallbacks");
const onUnhandledStateTransitions = await bluebird.mapSeries(
this.onUnhandledStateCallbacks,
(fn: IUnhandledStateCb) => this.runCallbacks(fn, voxaEvent),
Expand Down Expand Up @@ -133,7 +135,7 @@ export class StateMachine {
reply: IVoxaReply,
transition: ITransition,
): Promise<ITransition> {
log("Checking entry fallback");
voxaEvent.log.debug("Checking entry fallback");
if (!isState(this.currentState)) {
throw new Error("this.currentState is not a state");
}
Expand All @@ -144,7 +146,7 @@ export class StateMachine {
throw new Error("Running the state machine without an intent");
}

log(
voxaEvent.log.debug(
`No reply for ${voxaEvent.intent.name} in [${
this.currentState.name
}]. Trying [entry].`,
Expand All @@ -169,13 +171,15 @@ export class StateMachine {
throw new Error("this.currentState is not a state");
}

log(`${this.currentState.name} transition resulted in`, transition);
log("Running onAfterStateChangeCallbacks");
voxaEvent.log.debug(`${this.currentState.name} transition resulted in`, {
transition,
});
voxaEvent.log.debug("Running onAfterStateChangeCallbacks");
await bluebird.mapSeries(this.onAfterStateChangeCallbacks, (fn) => {
return fn(voxaEvent, reply, transition);
});

log("Transition is now", transition);
voxaEvent.log.debug("Transition is now", { transition });
return transition;
}

Expand All @@ -186,7 +190,7 @@ export class StateMachine {
): Promise<ITransition> {
this.currentState = this.getCurrentState(
currentStateName,
voxaEvent.platform,
voxaEvent.platform.name,
);
this.runOnBeforeStateChanged(voxaEvent, reply);

Expand All @@ -197,9 +201,21 @@ export class StateMachine {
reply.terminate();
}

transition = await this.checkForEntryFallback(voxaEvent, reply, transition);
transition = await this.checkOnUnhandledState(voxaEvent, reply, transition);
transition = await this.onAfterStateChanged(voxaEvent, reply, transition);
transition = await this.checkForEntryFallback(
voxaEvent,
reply,
_.cloneDeep(transition),
);
transition = await this.checkOnUnhandledState(
voxaEvent,
reply,
_.cloneDeep(transition),
);
transition = await this.onAfterStateChanged(
voxaEvent,
reply,
_.cloneDeep(transition),
);
const sysTransition = new SystemTransition(transition);
const to = this.getFinalTransition(sysTransition, voxaEvent, reply);

Expand Down Expand Up @@ -249,12 +265,14 @@ export class StateMachine {
return fromState.to;
}

log(`Running simpleTransition for ${this.currentState.name}`);
voxaEvent.log.debug(
`Running simpleTransition for ${this.currentState.name}`,
);
const to = this.getDestinationStateName(fromState, voxaEvent.intent.name);
return this.simpleTransition(
voxaEvent.intent,
this.currentState,
voxaEvent.platform,
voxaEvent.platform.name,
to,
);
}
Expand Down Expand Up @@ -314,7 +332,7 @@ export class StateMachine {
reply: IVoxaReply,
) {
const onBeforeState = this.onBeforeStateChangedCallbacks;
log("Running onBeforeStateChanged");
voxaEvent.log.debug("Running onBeforeStateChanged");

await bluebird.mapSeries(onBeforeState, (fn: IOnBeforeStateChangedCB) => {
if (!isState(this.currentState)) {
Expand All @@ -335,13 +353,13 @@ export class StateMachine {
if (_.isString(sysTransition.to)) {
if (
!this.states.core[sysTransition.to] &&
!_.get(this.states, [voxaEvent.platform, sysTransition.to])
!_.get(this.states, [voxaEvent.platform.name, sysTransition.to])
) {
throw new UnknownState(sysTransition.to);
}

to =
_.get(this.states, [voxaEvent.platform, sysTransition.to]) ||
_.get(this.states, [voxaEvent.platform.name, sysTransition.to]) ||
this.states.core[sysTransition.to];
Object.assign(sysTransition, { to });

Expand Down

0 comments on commit 371a255

Please sign in to comment.