UNPKG

voxa-cli

Version:
320 lines 13.3 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); /* * Copyright (c) 2018 Rain Agency <contact@rain.agency> * Author: Rain Agency <contact@rain.agency> * * Permission is hereby granted, free of charge, to any person obtaining a copy of * this software and associated documentation files (the "Software"), to deal in * the Software without restriction, including without limitation the rights to * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of * the Software, and to permit persons to whom the Software is furnished to do so, * subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all * copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /* tslint:disable:no-empty no-submodule-imports */ const lodash_1 = __importDefault(require("lodash")); const v5_1 = __importDefault(require("uuid/v5")); const DialogflowDefault_1 = require("./DialogflowDefault"); const Schema_1 = require("./Schema"); const NAMESPACE = "dialogflow"; // https://developers.google.com/actions/localization/languages-locales const LOCALES = lodash_1.default([ "en-US", "en-AU", "en-CA", "en-IN", "en-GB", "de-DE", "fr-FR", "fr-CA", "ja-JP", "ko-KR", "es-ES", "es-US", "es-MX", "pt-BR", "it-IT", "ru-RU", "hi-IN", "th-TH", "id-ID", "da-DK", "no-NO", "nl-NL", "sv-SE", "ko-KR", "ru-RU", "hi-IN", "th-TH", "id-ID" ]) .uniq() .value(); const LANG_BUT_LOCALE = lodash_1.default(LOCALES) .map(item => item.split("-")[0]) // es, en, du etc. .uniq() .value(); const AVAILABLE_LOCALES = LANG_BUT_LOCALE.concat(LOCALES); class DialogflowSchema extends Schema_1.Schema { constructor(voxaSheets, interactionOptions) { super(NAMESPACE, AVAILABLE_LOCALES, voxaSheets, interactionOptions); this.environment = "staging"; this.builtIntents = []; } validate() { } build(locale, environment) { this.buildIntent(locale, environment); this.buildUtterances(locale, environment); this.buildEntities(locale, environment); this.buildPackage(environment); this.buildAgent(locale, environment); } buildPackage(environment) { const file = { path: this.buildFilePath(environment, "package.json"), content: { version: "1.0.0" } }; this.fileContent.push(file); } getLocale(locale) { locale = locale.toLowerCase(); const localesNotAttachedToParentLang = ["pt-br"]; if (localesNotAttachedToParentLang.find(item => locale === item)) { return locale; } return locale.split("-")[0]; } buildAgent(locale, environment) { const intents = this.builtIntents; const invocation = lodash_1.default.find(this.invocations, { locale, environment }); const invocationName = lodash_1.default.get(invocation, "name", "Skill with no name"); const intentsByPlatformAndEnvironments = this.intentsByPlatformAndEnvironments(locale, environment); const startIntents = lodash_1.default(intentsByPlatformAndEnvironments) .filter({ startIntent: true }) .map(intent => { const startIntent = findIntent(intent.name, intents); if (startIntent) { return { intentId: lodash_1.default.get(startIntent, "id"), signInRequired: !!lodash_1.default.get(startIntent, "signInRequired") }; } }) .compact() .value(); const endIntentIds = lodash_1.default(intentsByPlatformAndEnvironments) .filter({ endIntent: true }) .map(intent => { const filteredIntent = findIntent(intent.name, intents); return lodash_1.default.get(filteredIntent, "id"); }) .compact() .value(); const supportedLanguages = lodash_1.default(this.invocations) .filter({ environment }) .map("locale") .uniq() .value(); const language = this.getLocale(locale); const agent = lodash_1.default.merge(lodash_1.default.cloneDeep(DialogflowDefault_1.AGENT), lodash_1.default.cloneDeep(this.mergeManifest(environment)), lodash_1.default.cloneDeep({ description: invocationName, language, supportedLanguages, googleAssistant: { project: lodash_1.default.kebabCase(invocationName), startIntents, endIntentIds } })); const file = { path: this.buildFilePath(environment, "agent.json"), content: agent }; this.fileContent.push(file); } buildUtterances(locale, environment) { const intentsByPlatformAndEnvironments = this.intentsByPlatformAndEnvironments(locale, environment); locale = this.getLocale(locale); intentsByPlatformAndEnvironments.map((rawIntent) => { let { name, samples, events } = rawIntent; const { slotsDefinition } = rawIntent; name = name.replace("AMAZON.", ""); const builtInIntentSamples = lodash_1.default.get(DialogflowDefault_1.BUILT_IN_INTENTS, name, []); samples = lodash_1.default(samples) .concat(builtInIntentSamples) .uniq() .value(); events = name === "LaunchIntent" ? ["WELCOME", "GOOGLE_ASSISTANT_WELCOME"] : events; events = events.map((eventName) => ({ name: eventName })); const parameters = lodash_1.default(slotsDefinition) .filter(slot => this.filterByPlatform(slot)) .map(slot => ({ dataType: lodash_1.default.includes(slot.type, "@sys.") ? slot.type : `@${slot.type}`, name: slot.name, value: `$${slot.name}`, isList: false, required: slot.required })) .value(); const resultSamples = samples.map(sample => { const data = lodash_1.default.chain(sample) .replace(/{([^}]+)}/g, (match, inner) => { return `|{${inner}}|`; }) .split("|") .map(text => { const element = {}; const isTemplate = lodash_1.default.includes(text, "{") && lodash_1.default.includes(text, "}"); const alias = text.replace("{", "").replace("}", ""); const slot = lodash_1.default.find(parameters, { name: text }); if (isTemplate && slot) { const slotMeta = slot.dataType.includes("@sys.") ? slot.dataType : `@${lodash_1.default.kebabCase(slot.dataType)}`; lodash_1.default.set(element, "meta", slotMeta); lodash_1.default.set(element, "alias", alias); } if (!lodash_1.default.isEmpty(text)) { lodash_1.default.set(element, "text", text); lodash_1.default.set(element, "userDefined", isTemplate); } lodash_1.default.set(element, "id", hashObj(element)); return lodash_1.default.isEmpty(lodash_1.default.omit(element, ["id"])) ? null : element; }) .compact() .value(); return { data, isTemplate: false, count: 0, updated: 0 }; }); if (!lodash_1.default.isEmpty(resultSamples)) { const file = { path: this.buildFilePath(environment, "intents", `${name}_usersays_${locale}.json`), content: resultSamples }; this.fileContent.push(file); } }); } buildIntent(locale, environment) { const intentsByPlatformAndEnvironments = this.intentsByPlatformAndEnvironments(locale, environment); locale = this.getLocale(locale); this.builtIntents = intentsByPlatformAndEnvironments.map((rawIntent) => { let { name, events } = rawIntent; const { parameterName, parameterValue } = rawIntent; const { webhookForSlotFilling, slotsDefinition, responses, webhookUsed } = rawIntent; name = name.replace("AMAZON.", ""); const fallbackIntent = name === "FallbackIntent"; const action = fallbackIntent ? "input.unknown" : name; events = name === "LaunchIntent" ? ["WELCOME", "GOOGLE_ASSISTANT_WELCOME"] : events; events = events.map((eventName) => ({ name: eventName })); // tslint:disable-next-line: prefer-const let parameters = lodash_1.default(slotsDefinition) .filter(slot => this.filterByPlatform(slot)) .map(slot => ({ dataType: lodash_1.default.includes(slot.type, "@sys.") ? slot.type : `@${lodash_1.default.kebabCase(slot.type)}`, name: slot.name.replace("{", "").replace("}", ""), value: `$${slot.name.replace("{", "").replace("}", "")}`, isList: false, required: slot.required })) .value(); if (parameterName && parameterValue) { parameters.push({ dataType: "", name: parameterName, value: parameterValue, isList: false, required: false }); } const messages = []; if (responses.length > 0) { messages.push({ type: 0, lang: locale, speech: responses }); } const intent = { name, auto: true, contexts: [], responses: [ { resetContexts: false, action, affectedContexts: [], parameters, messages, defaultResponsePlatforms: {}, speech: [] } ], priority: 500000, webhookUsed, webhookForSlotFilling, fallbackIntent, events }; lodash_1.default.set(intent, "id", hashObj(intent)); const file = { path: this.buildFilePath(environment, "intents", `${intent.name}.json`), content: intent }; this.fileContent.push(file); return intent; }); } buildEntities(locale, environment) { const localeEntity = this.getLocale(locale); this.getSlotsByIntentsDefinition(locale, environment) .filter(slot => !lodash_1.default.includes(slot.name, "@sys.")) .forEach(rawSlot => { const { name, values } = rawSlot; const slotName = lodash_1.default.kebabCase(name); const slotContent = { name: slotName, isOverridable: true, isEnum: false, automatedExpansion: false }; lodash_1.default.set(slotContent, "id", hashObj(slotContent)); const fileDef = { path: this.buildFilePath(environment, "entities", `${slotName}.json`), content: slotContent }; const fileValue = { path: this.buildFilePath(environment, "entities", `${slotName}_entries_${localeEntity}.json`), content: values }; this.fileContent.push(fileDef, fileValue); }); } buildFilePath(...names) { return super.buildFilePath(this.interactionOptions.speechPath, this.NAMESPACE, ...names); } } exports.DialogflowSchema = DialogflowSchema; function hashObj(obj) { return v5_1.default(JSON.stringify(obj), v5_1.default.DNS); } function findIntent(name, intents) { const intentName = name.replace("AMAZON.", ""); return lodash_1.default.find(intents, i => i.name === name || i.name === intentName); } //# sourceMappingURL=DialogflowSchema.js.map