alexa-sdkとask-sdk。新しいASK SDKへの移行準備
先日Alexa Skills KitのSDK(Node.js)のバージョン2がリリースされました。Now Available: Version 2 of the ASK Software Development Kit […]
目次
先日Alexa Skills KitのSDK(Node.js)のバージョン2がリリースされました。
Now Available: Version 2 of the ASK Software Development Kit for Node.js
かなり破壊的な変更が入っていますので、現状のalexa-sdkを使われている方向けに状況を整理します。
ポイント1:V1とV2はパッケージ名が別
最新バージョンということなのでnpmでインストールすれば良いのかと思いましたが、そもそも落としてくるパッケージ名が別になっています。
// Version 1
$ npm i -S alexa-sdk
// Version 2
$ npm i -S ask-sdk
ポイント2:パッケージが分割された
これまではsdk1つに全ての機能が用意されていました。しかしv2からは、必要な機能だけ利用する形でパッケージの軽量化が可能になっています。
// 全部入り
$ npm i -S ask-sdk
// 実質上と同じ
$ npm i -S ask-sdk-core ask-sdk-model ask-sdk-dynamodb-persistence-adapter
alexa-sdkの各機能を以下のように分割している様子です。
- ask-sdk-core: コア部分(必須)
 - ask-sdk-model: 対話モデル部分など
 - ask-sdk-dynamodb-persistence-adapter: DynamoDBとの連携部分
 
ポイント3:v1コードもそのまま利用できる(アダプター必須)
すでにスキルを開発されている場合、v2に全部マイグレしようというのはかなりつらみがあります。
しかし幸いにもv1 / v2コードが混ざっても大丈夫なようにアダプターが用意されていました。
アダプターをインストール
$ npm install -S ask-sdk-v1adapter ask-sdk
requireをアダプターに変更
// const Alexa = require('alexa-sdk');
const Alexa = require('ask-sdk-v1adapter');
混ぜても大丈夫なので、順次マイグレーションしていく
'use strict';
const Alexa = require('ask-sdk-v1adapter');
exports.handler = function(event, context, callback) {
    const alexa = Alexa.handler(event, context);
    alexa.registerHandlers(handlers);
    alexa.registerV2Handlers(HelpIntentHandler); // New API functions for registering v2 request handlers
    alexa.execute();
};
const handlers = {
    'LaunchRequest': function () {
        this.emit('SayHello');
    },
    'HelloWorldIntent': function () {
        this.emit('SayHello');
    },
    'SayHello': function () {
        this.response.speak('Hello World!');
        this.emit(':responseReady');
    },
    'AMAZON.CancelIntent': function () {
        this.response.speak('Goodbye!');
        this.emit(':responseReady');
    },
    'AMAZON.StopIntent': function () {
        this.response.speak('See you later!');
        this.emit(':responseReady');
    }
};
// HelpIntentHandler re-written following v2 request handler interface
const HelpIntentHandler = {
    canHandle : function({requestEnvelope}) {
        return requestEnvelope.request.type === 'IntentRequest'
        && requestEvelope.request.intent.name === 'AMAZON.HelpIntent';
    },
    handle : function({responseBuilder}){
        const speechOutput = 'This is the Hello World Sample Skill. ';
        const reprompt = 'Say hello, to hear me speak.';
        return responseBuilder.speak(speechOutput)
                              .reprompt(reprompt)
                              .getResponse();
    },
};
ポイント4:このブログで紹介しているテストはだいたい死ぬ
平たくいうと、alexa-conversationが現状未対応です。2018/04/22時点で最終更新が数ヶ月前のままなので、もしかするとメンテナンスされないままかもしれません。
$ npm test
> [email protected] test /develop/alexa/test
>  ./node_modules/mocha/bin/_mocha tests/*.js
(node:36453) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 2): TypeError: Cannot read property 'System' of undefined
(node:36453) DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
  Executing conversation: Test Conversation
とりあえずServerless Frameworkのsls invoke localを使うことでローカルテストはできそうでした。
$ sls invoke local -f hello -d "{
  'session': {
    'new': true,
    'sessionId': 'amzn1.echo-api.session.[unique-value-here]',
    'attributes': {},
    'user': {
      'userId': 'amzn1.ask.account.[unique-value-here]'
    },
    'application': {
      'applicationId': 'amzn1.ask.skill.f35b1223-1ed1-4283-a207-0e5d0fd2ff05'
    }
  },
  'version': '1.0',
  'request': {
    'locale': 'en-US',
    'timestamp': '2016-10-27T18:21:44Z',
    'type': 'LaunchRequest',
    'requestId': 'amzn1.echo-api.request.[unique-value-here]'
  },
  'context': {
    'AudioPlayer': {
      'playerActivity': 'IDLE'
    },
    'System': {
      'device': {
        'supportedInterfaces': {
          'AudioPlayer': {}
        }
      },
      'application': {
        'applicationId': 'amzn1.ask.skill.f35b1223-1ed1-4283-a207-0e5d0fd2ff05'
      },
      'user': {
        'userId': 'amzn1.ask.account.[unique-value-here]'
      }
    }
  }
}"
{
    "version": "1.0",
    "response": {
        "outputSpeech": {
            "type": "SSML",
            "ssml": "<speak>Sorry, I can't understand the command. Please say again.</speak>"
        },
        "reprompt": {
            "outputSpeech": {
                "type": "SSML",
                "ssml": "<speak>Sorry, I can't understand the command. Please say again.</speak>"
            }
        },
        "shouldEndSession": false
    },
    "userAgent": "ask-node/2.0.1 Node/v7.4.0"
}
LambdaをInvokeした返り値をテストすれば良い(はず)なので、ユニットテスト等についても改めてまとめます。