Files
Zos/Skills/@be/be/be/lifecycle.js

237 lines
9.9 KiB
JavaScript

"use strict";
const jibo = require('jibo');
const path = require('path');
let SkillSwitchData;
let SkillLifecycleState;
if (typeof global !== 'undefined' && global && global.be && global.be.constructor) {
SkillSwitchData = global.be.constructor.SkillSwitchData;
SkillLifecycleState = global.be.constructor.SkillLifecycleState;
}
function _interop(m) {
return (m && (m.__esModule || m.default)) ? (m.default || m) : m;
}
// normalize to usable variables
let SkillSwitchDataCtor;
let SkillLifecycleStateObj;
if (SkillSwitchData) {
SkillSwitchDataCtor = _interop(SkillSwitchData);
}
if (SkillLifecycleState) {
SkillLifecycleStateObj = _interop(SkillLifecycleState);
}
if (!SkillSwitchData) {
try {
SkillSwitchData = require(path.join(jibo.utils.PathUtils.findRoot(), 'SkillSwitchData'));
}
catch (e) {
try {
const Root = require(path.join(jibo.utils.PathUtils.findRoot(), 'index.js'));
SkillSwitchData = (Root && (Root.SkillSwitchData || (Root.default && Root.default.SkillSwitchData))) || undefined;
}
catch (e2) { }
}
}
if (!SkillLifecycleState) {
try {
SkillLifecycleState = require(path.join(jibo.utils.PathUtils.findRoot(), 'SkillLifecycleState'));
}
catch (e) {
try {
const Root = require(path.join(jibo.utils.PathUtils.findRoot(), 'index.js'));
SkillLifecycleState = (Root && (Root.SkillLifecycleState || (Root.default && Root.default.SkillLifecycleState))) || undefined;
}
catch (e2) { }
}
}
exports.selectFirstSkill = function (callback) {
const kbm = jibo.kb.createModel('/skills-config');
kbm.loadRoot((loadRootErr, rootNode) => {
if (loadRootErr) {
this.log.warn("error loading /skills-config root", loadRootErr);
}
jibo.secureTransferService.hasBackupData((backupErr, hasBackupData) => {
if (backupErr) {
this.log.warn("error when checking if backup data exists", backupErr);
}
jibo.errors.getCurrentErrorId((err, currentErrorId) => {
if (err) {
this.log.warn("error when checking for current error id", err);
}
let nextSkill = this.idle;
let nextSkillLaunchOptions = {};
let firstTime = false;
if (!loadRootErr) {
firstTime = !rootNode.data.hasAlreadyLaunchedFirstContact;
}
else {
this.log.info(`error reading the hasAlreadyLaunchedFirstContact property from the KB. assuming first time is false`);
}
this.log.info(`selectFirstSkill parameter readout: Skills config load error: ${loadRootErr}, first time: ${firstTime}, has backup data: ${hasBackupData}, skip restore: ${this.packageInfo.jibo.debug.skipRestore}, current error id: ${currentErrorId}`);
if (currentErrorId) {
nextSkill = this.skills['@be/settings'];
nextSkillLaunchOptions = { nlu: { entities: { errorId: currentErrorId } } };
}
else if (firstTime) {
if (backupErr && !this.packageInfo.jibo.debug.skipRestore) {
setTimeout(this.selectFirstSkill.bind(this, callback), 2000);
return;
}
else if (hasBackupData && !this.packageInfo.jibo.debug.skipRestore) {
nextSkill = this.restoreSkill;
}
else {
nextSkill = this.firstSkill;
}
}
callback(nextSkill, nextSkillLaunchOptions, currentErrorId, firstTime);
});
});
});
};
exports.launchFirstSkill = function (firstSkill, firstSkillLaunchOptions, firstErrorId, firstTime) {
this.log.debug('launching first skill');
const firstSkillHasOpened = () => {
if (firstErrorId) {
document.getElementById('splash').style.display = 'none';
}
else {
document.getElementById('splash').remove();
this.enableSkillSwitching();
}
this.initDoneCallback();
};
let firstSkillRedirectToken = this.redirect(new (SkillSwitchDataCtor || SkillSwitchData)(firstSkill, firstSkillLaunchOptions));
firstSkillRedirectToken.onState((SkillLifecycleStateObj || SkillLifecycleState).SKILL_OPENED, firstSkillHasOpened);
if (firstErrorId) {
const onErrorResolved = () => {
if (firstTime) {
document.getElementById('splash').style.display = 'block';
}
this.selectFirstSkill((nextSkill, nextSkillLaunchOptions, currentErrorId) => {
let nextSkillRedirectToken = this.redirect(new (SkillSwitchDataCtor || SkillSwitchData)(nextSkill, nextSkillLaunchOptions));
if (currentErrorId) {
nextSkillRedirectToken.onState((SkillLifecycleStateObj || SkillLifecycleState).LIFECYCLE_ENDED, onErrorResolved);
nextSkillRedirectToken.onState((SkillLifecycleStateObj || SkillLifecycleState).SKILL_OPENED, () => {
document.getElementById('splash').style.display = 'none';
});
}
else {
nextSkillRedirectToken.onState((SkillLifecycleStateObj || SkillLifecycleState).SKILL_OPENED, () => {
document.getElementById('splash').remove();
this.enableSkillSwitching();
});
}
});
};
firstSkillRedirectToken.onState(SkillLifecycleState.default.LIFECYCLE_ENDED, onErrorResolved);
}
};
exports.enableSkillSwitching = function () {
jibo.globalEvents.skillRelaunch.on(data => {
const skillName = data.match.skillID;
this.redirect(new (SkillSwitchDataCtor || SkillSwitchData)(this.skills[skillName], data));
});
jibo.action.setSkillSwitchHandler((skillName, skillData) => {
return new Promise((resolve) => {
const skill = this.skills[skillName];
let redirectToken = this.redirect(new (SkillSwitchDataCtor || SkillSwitchData)(skill, skillData));
let resolved = false;
redirectToken.onState((SkillLifecycleStateObj || SkillLifecycleState).SKILL_OPENED, () => {
resolved = true;
resolve(jibo.action.types.Status.SUCCEEDED);
});
redirectToken.onState((SkillLifecycleStateObj || SkillLifecycleState).LIFECYCLE_ENDED, () => {
if (!resolved) {
this.log.warn(`Skill lifecycle ended before skill was opened: ${redirectToken.skillLifecycleEndState}`);
}
resolved = true;
resolve(jibo.action.types.Status.FAILED);
});
});
});
};
exports.exit = function (exitingSkill, exitOptions = {}, done = () => { }) {
const skipEoS = !!(exitOptions.noElementsOfSurprise || exitOptions.globalNoMatch);
const currentSkill = this._skillSwitchScheduler.currentSkillRedirectToken ? this._skillSwitchScheduler.currentSkillRedirectToken.skillSwitchData.skill : null;
if (exitingSkill !== currentSkill) {
this.log.warn(`Trying to call Be#exit from non-current skill ${exitingSkill}. Current skill is ${currentSkill}`);
return;
}
if (!skipEoS &&
currentSkill !== this.idle &&
currentSkill !== this.eosSkill &&
!currentSkill.isElementOfSurprise &&
!currentSkill.skipSurprisesExternal) {
let redirectToken = this.redirect(new (SkillSwitchDataCtor || SkillSwitchData)(this.eosSkill, { lastSkill: currentSkill.assetPack }));
redirectToken.addOnSkillLifecycleEnd(done);
}
else {
let redirectToken = this.redirect(new (SkillSwitchDataCtor || SkillSwitchData)(this.idle, { exitOptions }));
redirectToken.addOnSkillLifecycleEnd(done);
}
};
exports.skillRedirect = function (redirectingSkill, name, options) {
const skill = this.skills[name];
const currentSkill = this._skillSwitchScheduler.currentSkillRedirectToken ? this._skillSwitchScheduler.currentSkillRedirectToken.skillSwitchData.skill : null;
if (redirectingSkill !== currentSkill) {
this.log.warn(`Trying to call Be#redirect from non-current skill ${redirectingSkill.assetPack}. Current skill is ${currentSkill.assetPack}`);
return;
}
if (skill) {
this.log.info("REDIRECT: skill redirect: ", name, options);
this.redirect(new (SkillSwitchDataCtor || SkillSwitchData)(skill, options));
}
else {
this.log.error("REDIRECT: skill redirect failed. cannot find skill: ", name, options);
}
};
exports.redirect = function (skillSwitchData) {
return this._skillSwitchScheduler.requestSkillRedirect(skillSwitchData);
};
exports.destroy = function (callback) {
if (document.getElementById('splash')) {
document.getElementById('splash').remove();
}
jibo.globalEvents.skillRelaunch.removeAllListeners();
this._skillSwitchScheduler.destroy()
.then(() => {
let destroySkillPromises = [];
Object.keys(this.skills).forEach((skillId) => {
let destroySkillPromise = new Promise((resolve, reject) => {
try {
this.skills[skillId].destroy((err) => {
jibo.loader.deleteCache(skillId);
if (err) {
reject(err);
}
else {
resolve();
}
});
}
catch (err) {
reject(err);
}
});
destroySkillPromises.push(destroySkillPromise);
});
return Promise.all(destroySkillPromises);
})
.catch((err) => {
this.log.error(err);
})
.then(() => {
callback();
});
};