botbuilder-dialogs-adaptive
Version:
Rule system for the Microsoft BotBuilder dialog system.
186 lines • 7.67 kB
JavaScript
;
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.OnCondition = void 0;
const actionChangeType_1 = require("../actionChangeType");
const actionScope_1 = require("../actions/actionScope");
const adaptiveDialog_1 = require("../adaptiveDialog");
const converters_1 = require("../converters");
const adaptive_expressions_1 = require("adaptive-expressions");
const botbuilder_dialogs_1 = require("botbuilder-dialogs");
/**
* Actions triggered when condition is true.
*/
class OnCondition extends botbuilder_dialogs_1.Configurable {
/**
* @protected
* Gets the action scope.
*
* @returns The scope obtained from the action.
*/
get actionScope() {
if (!this._actionScope) {
this._actionScope = new actionScope_1.ActionScope(this.actions);
}
return this._actionScope;
}
/**
* Create a new `OnCondition` instance.
*
* @param condition (Optional) The condition which needs to be met for the actions to be executed.
* @param actions (Optional) The actions to add to the plan when the rule constraints are met.
*/
constructor(condition, actions = []) {
super();
this._extraConstraints = [];
/**
* Gets or sets the actions to add to the plan when the rule constraints are met.
*/
this.actions = [];
/**
* Get or sets the rule priority expression where 0 is the highest and less than 0 is ignored.
*/
this.priority = new adaptive_expressions_1.NumberExpression(0.0);
this.condition = condition ? new adaptive_expressions_1.BoolExpression(condition) : undefined;
this.actions = actions;
}
/**
* @param property The key of the conditional selector configuration.
* @returns The converter for the selector configuration.
*/
getConverter(property) {
switch (property) {
case 'condition':
return new adaptive_expressions_1.BoolExpressionConverter();
case 'actions':
return converters_1.DialogListConverter;
case 'priority':
return new adaptive_expressions_1.NumberExpressionConverter();
default:
return super.getConverter(property);
}
}
/**
* Get the cached expression for this condition.
*
* @returns Cached expression used to evaluate this condition.
*/
getExpression() {
if (!this._fullConstraint) {
this._fullConstraint = this.createExpression();
}
return this._fullConstraint;
}
/**
* Compute the current value of the priority expression and return it.
*
* @param actionContext Context to use for evaluation.
* @returns Computed priority.
*/
currentPriority(actionContext) {
const { value: priority, error } = this.priority.tryGetValue(actionContext.state);
if (error) {
return -1;
}
return priority;
}
/**
* Add external condition to the OnCondition
*
* @param condition External constraint to add, it will be AND'ed to all other constraints.
*/
addExternalCondition(condition) {
if (condition) {
try {
const parser = new adaptive_expressions_1.ExpressionParser();
this._extraConstraints.push(parser.parse(condition));
this._fullConstraint = undefined;
}
catch (err) {
throw Error(`Invalid constraint expression: ${condition}, ${err.toString()}`);
}
}
}
/**
* Method called to execute the condition's actions.
*
* @param actionContext Context.
* @returns A promise with plan change list.
*/
execute(actionContext) {
return __awaiter(this, void 0, void 0, function* () {
if (this.runOnce) {
const count = actionContext.state.getValue(botbuilder_dialogs_1.DialogPath.eventCounter);
actionContext.state.setValue(`${adaptiveDialog_1.AdaptiveDialog.conditionTracker}.${this.id}.lastRun`, count);
}
return [this.onCreateChangeList(actionContext)];
});
}
/**
* Get child dialog dependencies so they can be added to the containers dialogset.
*
* @returns A list of [Dialog](xref:botbuilder-dialogs.Dialog).
*/
getDependencies() {
return [this.actionScope];
}
/**
* Create the expression for this condition.
*
* @returns {Expression} Expression used to evaluate this rule.
*/
createExpression() {
var _a;
const allExpressions = [];
if (this.condition) {
allExpressions.push(this.condition.toExpression());
}
if ((_a = this._extraConstraints) === null || _a === void 0 ? void 0 : _a.length) {
allExpressions.push(...this._extraConstraints);
}
if (this.runOnce) {
const evaluator = new adaptive_expressions_1.ExpressionEvaluator(`runOnce${this.id}`, (_expression, state, _) => {
const basePath = `${adaptiveDialog_1.AdaptiveDialog.conditionTracker}.${this.id}.`;
const lastRun = state.getValue(basePath + 'lastRun');
const paths = state.getValue(basePath + 'paths');
const changed = state.anyPathChanged(lastRun, paths);
return { value: changed, error: undefined };
}, adaptive_expressions_1.ReturnType.Boolean, adaptive_expressions_1.FunctionUtils.validateUnary);
allExpressions.push(new adaptive_expressions_1.Expression(adaptive_expressions_1.ExpressionType.Ignore, adaptive_expressions_1.Expression.lookup(adaptive_expressions_1.ExpressionType.Ignore), new adaptive_expressions_1.Expression(evaluator.type, evaluator)));
}
if (allExpressions.length) {
return adaptive_expressions_1.Expression.andExpression(...allExpressions);
}
return new adaptive_expressions_1.Constant(true);
}
/**
* @protected
* Called when a change list is created.
* @param actionContext [ActionContext](xref:botbuilder-dialogs-adaptive.ActionContext) to use for evaluation.
* @param dialogOptions Optional. Object with dialog options.
* @returns An [ActionChangeList](xref:botbuilder-dialogs-adaptive.ActionChangeList) with the list of actions.
*/
onCreateChangeList(actionContext, dialogOptions) {
const actionState = {
dialogId: this.actionScope.id,
options: dialogOptions,
dialogStack: [],
};
const changeList = {
changeType: actionChangeType_1.ActionChangeType.insertActions,
actions: [actionState],
};
return changeList;
}
}
exports.OnCondition = OnCondition;
OnCondition.$kind = 'Microsoft.OnCondition';
//# sourceMappingURL=onCondition.js.map