botium-core 1.14.0 → 1.14.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (38) hide show
  1. package/dist/botium-cjs.js +302 -94
  2. package/dist/botium-cjs.js.map +1 -1
  3. package/dist/botium-es.js +302 -94
  4. package/dist/botium-es.js.map +1 -1
  5. package/package.json +19 -19
  6. package/src/Capabilities.js +2 -0
  7. package/src/scripting/BotiumError.js +40 -3
  8. package/src/scripting/Convo.js +139 -28
  9. package/src/scripting/ScriptingMemory.js +7 -0
  10. package/src/scripting/ScriptingProvider.js +79 -30
  11. package/src/scripting/logichook/LogicHookConsts.js +5 -2
  12. package/src/scripting/logichook/LogicHookUtils.js +8 -6
  13. package/src/scripting/logichook/logichooks/ConditionalBusinessHoursLogicHook.js +1 -1
  14. package/src/scripting/logichook/logichooks/ConditionalCapabilityValueBasedLogicHook.js +1 -1
  15. package/src/scripting/logichook/logichooks/ConditionalJsonPathBasedLogicHook.js +1 -1
  16. package/src/scripting/logichook/logichooks/ConditionalTimeBasedLogicHook.js +1 -1
  17. package/src/scripting/logichook/logichooks/ConvoStepParametersLogicHook.js +6 -0
  18. package/src/scripting/logichook/logichooks/OrderedListToButtonLogicHook.js +37 -0
  19. package/test/convo/fillAndApplyScriptingMemory.spec.js +11 -0
  20. package/test/logichooks/orderedListToButton.spec.js +35 -0
  21. package/test/scripting/asserters/convoStepParameters.spec.js +140 -0
  22. package/test/scripting/asserters/convos/TEXT_GOOD.convo.txt +6 -0
  23. package/test/scripting/asserters/convos/convo_step_parameter_matchmode_failed.convo.txt +8 -0
  24. package/test/scripting/asserters/convos/convo_step_parameter_retry_asserters_all_good.convo.txt +9 -0
  25. package/test/scripting/asserters/convos/convo_step_parameter_retry_asserters_botium_timeout.convo.txt +9 -0
  26. package/test/scripting/asserters/convos/convo_step_parameter_retry_asserters_good.convo.txt +9 -0
  27. package/test/scripting/asserters/convos/convo_step_parameter_retry_asserters_good_global.convo.txt +9 -0
  28. package/test/scripting/asserters/convos/convo_step_parameter_retry_main_and_asserter.convo.txt +10 -0
  29. package/test/scripting/asserters/convos/convo_step_parameter_retry_main_botium_timeout.convo.txt +9 -0
  30. package/test/scripting/asserters/convos/convo_step_parameter_retry_main_but_no_button.convo.txt +10 -0
  31. package/test/scripting/asserters/convos/convo_step_parameter_retry_main_good.convo.txt +9 -0
  32. package/test/scripting/asserters/convos/convo_step_parameter_retry_main_good_begin.convo.txt +11 -0
  33. package/test/scripting/logichooks/convos/conditional_steps_multiple_condition_groups_no_assertion.convo.txt +6 -6
  34. package/test/scripting/logichooks/convos/conditional_steps_multiple_mandatory_condition_groups.convo.txt +20 -0
  35. package/test/scripting/logichooks/convos/conditional_steps_multiple_optional_condition_groups.convo.txt +20 -0
  36. package/test/scripting/logichooks/customConditionalStepLogicHook.spec.js +16 -0
  37. package/test/scripting/matching/matchingmode.spec.js +4 -1
  38. package/test/scripting/scriptingProvider.spec.js +38 -12
package/dist/botium-es.js CHANGED
@@ -35,7 +35,7 @@ import express from 'express';
35
35
  import bodyParser from 'body-parser';
36
36
 
37
37
  var name = "botium-core";
38
- var version$1 = "1.14.0";
38
+ var version$1 = "1.14.3";
39
39
  var description = "The Selenium for Chatbots";
40
40
  var main = "index.js";
41
41
  var module = "dist/botium-es.js";
@@ -66,12 +66,12 @@ var bugs = {
66
66
  };
67
67
  var homepage = "https://www.botium.ai";
68
68
  var dependencies = {
69
- "@babel/runtime": "^7.22.15",
70
- async: "^3.2.4",
69
+ "@babel/runtime": "^7.23.5",
70
+ async: "^3.2.5",
71
71
  "body-parser": "^1.20.2",
72
72
  boolean: "^3.2.0",
73
73
  bottleneck: "^2.19.5",
74
- "csv-parse": "^5.5.0",
74
+ "csv-parse": "^5.5.3",
75
75
  debug: "^4.3.4",
76
76
  express: "^4.18.2",
77
77
  globby: "11.0.4",
@@ -80,7 +80,7 @@ var dependencies = {
80
80
  "is-json": "^2.0.1",
81
81
  jsonpath: "^1.1.1",
82
82
  lodash: "^4.17.21",
83
- "markdown-it": "^13.0.1",
83
+ "markdown-it": "^14.0.0",
84
84
  "mime-types": "^2.1.35",
85
85
  mkdirp: "^3.0.1",
86
86
  moment: "^2.29.4",
@@ -90,7 +90,7 @@ var dependencies = {
90
90
  "promise.allsettled": "^1.0.7",
91
91
  randomatic: "^3.1.1",
92
92
  request: "^2.88.2",
93
- rimraf: "^5.0.1",
93
+ rimraf: "^5.0.5",
94
94
  "sanitize-filename": "^1.6.3",
95
95
  slugify: "^1.6.6",
96
96
  "socket.io": "^4.7.2",
@@ -98,31 +98,31 @@ var dependencies = {
98
98
  "socketio-auth": "^0.1.1",
99
99
  "swagger-jsdoc": "^6.2.8",
100
100
  "swagger-ui-express": "^5.0.0",
101
- uuid: "^9.0.0",
101
+ uuid: "^9.0.1",
102
102
  "word-error-rate": "0.0.7",
103
103
  "write-yaml": "^1.0.0",
104
104
  xlsx: "^0.18.5",
105
105
  xregexp: "^5.1.1",
106
- yaml: "^2.3.2"
106
+ yaml: "^2.3.4"
107
107
  };
108
108
  var devDependencies = {
109
- "@babel/core": "^7.22.17",
110
- "@babel/node": "^7.22.15",
111
- "@babel/plugin-transform-runtime": "^7.22.15",
112
- "@babel/preset-env": "^7.22.15",
113
- chai: "^4.3.8",
109
+ "@babel/core": "^7.23.5",
110
+ "@babel/node": "^7.22.19",
111
+ "@babel/plugin-transform-runtime": "^7.23.4",
112
+ "@babel/preset-env": "^7.23.5",
113
+ chai: "^4.3.10",
114
114
  "chai-as-promised": "^7.1.1",
115
115
  "cross-env": "^7.0.3",
116
- eslint: "^8.49.0",
116
+ eslint: "^8.55.0",
117
117
  "eslint-config-standard": "^17.1.0",
118
- "eslint-plugin-import": "^2.28.1",
119
- "eslint-plugin-mocha": "^10.1.0",
120
- "eslint-plugin-n": "^16.1.0",
118
+ "eslint-plugin-import": "^2.29.0",
119
+ "eslint-plugin-mocha": "^10.2.0",
120
+ "eslint-plugin-n": "^16.4.0",
121
121
  "eslint-plugin-promise": "^6.1.1",
122
122
  "eslint-plugin-standard": "^4.1.0",
123
123
  mocha: "^10.2.0",
124
- nock: "^13.3.3",
125
- "npm-check-updates": "^16.13.3",
124
+ nock: "^13.4.0",
125
+ "npm-check-updates": "^16.14.11",
126
126
  nyc: "^15.1.0",
127
127
  rollup: "2.79.1",
128
128
  "rollup-plugin-babel": "^4.4.0",
@@ -325,6 +325,8 @@ var Capabilities = {
325
325
  // varnames, testcasenames
326
326
  SCRIPTING_MEMORY_COLUMN_MODE: 'SCRIPTING_MEMORY_COLUMN_MODE',
327
327
  // Botium Lifecycle Hooks
328
+ SCRIPTING_CONVO_STEP_PARAMETERS: 'SCRIPTING_CONVO_STEP_PARAMETERS',
329
+ // Botium Lifecycle Hooks
328
330
  CUSTOMHOOK_ONBUILD: 'CUSTOMHOOK_ONBUILD',
329
331
  CUSTOMHOOK_ONSTART: 'CUSTOMHOOK_ONSTART',
330
332
  CUSTOMHOOK_ONUSERSAYS: 'CUSTOMHOOK_ONUSERSAYS',
@@ -486,6 +488,7 @@ Capabilities.SCRIPTING_UTTEXPANSION_NAMING_UTTERANCE_MAX;
486
488
  Capabilities.SCRIPTING_MEMORYEXPANSION_KEEP_ORIG;
487
489
  Capabilities.SCRIPTING_MEMORY_MATCHING_MODE;
488
490
  Capabilities.SCRIPTING_MEMORY_COLUMN_MODE;
491
+ Capabilities.SCRIPTING_CONVO_STEP_PARAMETERS;
489
492
  Capabilities.CUSTOMHOOK_ONBUILD;
490
493
  Capabilities.CUSTOMHOOK_ONSTART;
491
494
  Capabilities.CUSTOMHOOK_ONUSERSAYS;
@@ -1034,6 +1037,12 @@ var LogicHookConsts = {
1034
1037
  }, {
1035
1038
  name: 'CONDITIONAL_STEP_JSON_PATH_BASED',
1036
1039
  className: 'ConditionalJsonPathBasedLogicHook.js'
1040
+ }, {
1041
+ name: 'CONVO_STEP_PARAMETERS',
1042
+ className: 'ConvoStepParametersLogicHook.js'
1043
+ }, {
1044
+ name: 'ORDERED_LIST_TO_BUTTON',
1045
+ className: 'OrderedListToButtonLogicHook'
1037
1046
  }],
1038
1047
  DEFAULT_USER_INPUTS: [{
1039
1048
  name: 'BUTTON',
@@ -1044,12 +1053,14 @@ var LogicHookConsts = {
1044
1053
  }, {
1045
1054
  name: 'FORM',
1046
1055
  className: 'FormInput'
1047
- }]
1056
+ }],
1057
+ LOGIC_HOOK_EVENTS: ['onConvoBegin', 'onMeStart', 'onMePrepare', 'onMeEnd', 'onBotStart', 'onBotEnd', 'onBotPrepare', 'onConvoEnd']
1048
1058
  };
1049
1059
  LogicHookConsts.LOGIC_HOOK_INCLUDE;
1050
1060
  LogicHookConsts.DEFAULT_ASSERTERS;
1051
1061
  LogicHookConsts.DEFAULT_LOGIC_HOOKS;
1052
1062
  LogicHookConsts.DEFAULT_USER_INPUTS;
1063
+ LogicHookConsts.LOGIC_HOOK_EVENTS;
1053
1064
 
1054
1065
  const debug$m = debug$n('botium-core-asserterUtils');
1055
1066
  const {
@@ -1200,6 +1211,7 @@ var LogicHookUtils_1 = class LogicHookUtils {
1200
1211
  throw new Error(`Logic Hook specification ${ref} ${hookType} (${packageName}) invalid: ${err.message}`);
1201
1212
  }
1202
1213
  }
1214
+ const typeAsText = hookType === 'asserter' ? 'Asserter' : hookType === 'logichook' ? 'Logic Hook' : hookType === 'userinput' ? 'User Input' : 'Unknown';
1203
1215
  if (isClass(src)) {
1204
1216
  try {
1205
1217
  const CheckClass = src;
@@ -1208,7 +1220,7 @@ var LogicHookUtils_1 = class LogicHookUtils {
1208
1220
  ...this.buildScriptContext
1209
1221
  }, this.caps, args);
1210
1222
  } catch (err) {
1211
- throw new Error(`Logic Hook specification ${ref} from class invalid: ${err.message}`);
1223
+ throw new Error(`${typeAsText} specification ${ref} from class invalid: ${err.message}`);
1212
1224
  }
1213
1225
  }
1214
1226
  if (lodash.isFunction(src)) {
@@ -1218,7 +1230,7 @@ var LogicHookUtils_1 = class LogicHookUtils {
1218
1230
  ...this.buildScriptContext
1219
1231
  }, this.caps, args);
1220
1232
  } catch (err) {
1221
- throw new Error(`Logic Hook specification ${ref} from function invalid: ${err.message}`);
1233
+ throw new Error(`${typeAsText} specification ${ref} from function invalid: ${err.message}`);
1222
1234
  }
1223
1235
  }
1224
1236
  if (lodash.isObject(src) && !lodash.isString(src)) {
@@ -1236,7 +1248,7 @@ var LogicHookUtils_1 = class LogicHookUtils {
1236
1248
  }, {});
1237
1249
  return hookObject;
1238
1250
  } catch (err) {
1239
- throw new Error(`Logic Hook specification ${ref} ${hookType} from provided src (${util.inspect(src)}) invalid: ${err.message}`);
1251
+ throw new Error(`${typeAsText} specification ${ref} ${hookType} from provided src (${util.inspect(src)}) invalid: ${err.message}`);
1240
1252
  }
1241
1253
  }
1242
1254
  if (lodash.isString(src)) {
@@ -1297,7 +1309,7 @@ var LogicHookUtils_1 = class LogicHookUtils {
1297
1309
  try {
1298
1310
  return tryLoadFromSource(tryLoadFile, tryLoad.tryLoadAsserterByName);
1299
1311
  } catch (err) {
1300
- loadErr.push(`Logic Hook specification ${ref} ${hookType} from "${src}" invalid: ${err.message} `);
1312
+ loadErr.push(`${typeAsText} specification ${ref} ${hookType} from "${src}" invalid: ${err.message} `);
1301
1313
  }
1302
1314
  }
1303
1315
  }
@@ -1306,13 +1318,13 @@ var LogicHookUtils_1 = class LogicHookUtils {
1306
1318
  try {
1307
1319
  return tryLoadFromSource(tryLoad.tryLoadPackageName, tryLoad.tryLoadAsserterByName);
1308
1320
  } catch (err) {
1309
- loadErr.push(`Logic Hook specification ${ref} ${hookType} from "${src}" invalid: ${err.message} `);
1321
+ loadErr.push(`${typeAsText} specification ${ref} ${hookType} from "${src}" invalid: ${err.message} `);
1310
1322
  }
1311
1323
  }
1312
1324
  }
1313
1325
  loadErr.forEach(debug$m);
1314
1326
  }
1315
- throw new Error(`Logic Hook specification ${ref} ${hookType} from "${util.inspect(src)}" invalid : no loader available`);
1327
+ throw new Error(`${typeAsText} specification ${ref} ${hookType} from "${util.inspect(src)}" invalid : no loader available`);
1316
1328
  }
1317
1329
  };
1318
1330
 
@@ -2205,6 +2217,44 @@ const BotiumError$4 = class BotiumError extends Error {
2205
2217
  return null;
2206
2218
  }
2207
2219
  }
2220
+ hasError({
2221
+ type,
2222
+ source
2223
+ }) {
2224
+ if (this.context) {
2225
+ const errArr = lodash.isArray(this.context) ? this.context : [this.context];
2226
+ for (const err of errArr) {
2227
+ if (err.type === 'list') {
2228
+ for (const internal of err.errors) {
2229
+ if ((!type || internal.type === type) && (!source || internal.source === source)) {
2230
+ return true;
2231
+ }
2232
+ }
2233
+ }
2234
+ if ((!type || err.type === type) && (!source || err.source === source)) {
2235
+ return true;
2236
+ }
2237
+ }
2238
+ } else {
2239
+ return false;
2240
+ }
2241
+ }
2242
+ toArray() {
2243
+ if (this.context) {
2244
+ let result = [];
2245
+ const errArr = lodash.isArray(this.context) ? this.context : [this.context];
2246
+ for (const err of errArr) {
2247
+ if (err.type === 'list') {
2248
+ result = result.concat(err.errors);
2249
+ } else {
2250
+ result.push(err);
2251
+ }
2252
+ }
2253
+ return result;
2254
+ } else {
2255
+ return [];
2256
+ }
2257
+ }
2208
2258
  };
2209
2259
  const _getChildErrorsFromContext = context => {
2210
2260
  if (context && context.errors && lodash.isArray(context.errors)) {
@@ -2212,12 +2262,16 @@ const _getChildErrorsFromContext = context => {
2212
2262
  }
2213
2263
  return false;
2214
2264
  };
2215
- const botiumErrorFromErr$2 = (message, err) => {
2265
+ const botiumErrorFromErr$2 = (message, err, context = {}) => {
2216
2266
  if (err instanceof BotiumError$4) {
2217
- return new BotiumError$4(message, err.context, true);
2267
+ return new BotiumError$4(message, {
2268
+ ...err.context,
2269
+ ...context
2270
+ }, true);
2218
2271
  } else {
2219
2272
  return new BotiumError$4(message, {
2220
- err
2273
+ err,
2274
+ ...context
2221
2275
  }, true);
2222
2276
  }
2223
2277
  };
@@ -2492,6 +2546,13 @@ const _apply = (scriptingMemory, str, caps, mockMsg) => {
2492
2546
  return arg;
2493
2547
  }
2494
2548
  });
2549
+ args = args.map(arg => {
2550
+ const argStr = `${arg}`;
2551
+ if (argStr.startsWith('$')) {
2552
+ return scriptingMemory[argStr.substring(1)] || arg;
2553
+ }
2554
+ return arg;
2555
+ });
2495
2556
  str = str.replace(match, SCRIPTING_FUNCTIONS$1[key].handler(caps, ...args, mockMsg));
2496
2557
  } else {
2497
2558
  str = str.replace(match, SCRIPTING_FUNCTIONS$1[key].handler(caps));
@@ -2869,8 +2930,54 @@ class Convo$6 {
2869
2930
  let botMsg = null;
2870
2931
  let waitForBotSays = true;
2871
2932
  let skipTranscriptStep = false;
2872
- for (let i = 0; i < this.conversation.length; i++) {
2933
+ let conditionalGroupId = null;
2934
+ let conditionMetInGroup = false;
2935
+ let globalConvoStepParameters = container.caps[Capabilities.SCRIPTING_CONVO_STEP_PARAMETERS] || {};
2936
+ let retryBotMessageTimeoutEnd = null;
2937
+ let retryBotMessageConvoId = null;
2938
+ let retryBotMessageDropBotResponse = false;
2939
+ for (let i = 0; i < this.conversation.length; i = retryBotMessageDropBotResponse ? i : i + 1) {
2940
+ retryBotMessageDropBotResponse = false;
2873
2941
  const convoStep = this.conversation[i];
2942
+ const rawConvoStepParameters = convoStep.logicHooks.find(lh => lh.name === 'CONVO_STEP_PARAMETERS')?.args;
2943
+ let convoStepParameters = {};
2944
+ if (rawConvoStepParameters && rawConvoStepParameters.length) {
2945
+ let params;
2946
+ if (rawConvoStepParameters[0].trim().startsWith('{')) {
2947
+ try {
2948
+ params = JSON.parse(rawConvoStepParameters[0]);
2949
+ } catch (e) {
2950
+ debug$j(`${this.header.name}/${convoStep.stepTag}: Failed to parse convo step parameters from JSON ${rawConvoStepParameters[0]}`);
2951
+ }
2952
+ }
2953
+ if (!params || !Object.keys(params).length) {
2954
+ params = {};
2955
+ for (const param of rawConvoStepParameters) {
2956
+ const semicolon = param.indexOf(':');
2957
+ if (semicolon) {
2958
+ try {
2959
+ const name = param.substring(0, semicolon);
2960
+ const value = param.substring(semicolon + 1);
2961
+ params[name] = value;
2962
+ } catch (e) {
2963
+ debug$j(`${this.header.name}/${convoStep.stepTag}: Failed to parse convo step parameter from arg ${param}`);
2964
+ }
2965
+ }
2966
+ }
2967
+ }
2968
+ if (convoStep.sender === 'begin') {
2969
+ globalConvoStepParameters = Object.assign({}, globalConvoStepParameters || {}, params);
2970
+ } else {
2971
+ convoStepParameters = Object.assign({}, globalConvoStepParameters || {}, params);
2972
+ }
2973
+ } else {
2974
+ if (convoStep.sender !== 'begin') {
2975
+ convoStepParameters = globalConvoStepParameters;
2976
+ }
2977
+ }
2978
+ if (Object.keys(convoStepParameters).length) {
2979
+ debug$j(`${this.header.name}: using convo step parameters ${JSON.stringify(convoStepParameters)}`);
2980
+ }
2874
2981
  const currentStepIndex = i;
2875
2982
  container.eventEmitter.emit(Events.CONVO_STEP_NEXT, container, convoStep, i);
2876
2983
  skipTranscriptStep = false;
@@ -2934,8 +3041,8 @@ class Convo$6 {
2934
3041
  const coreMsg = lodash.omit(removeBuffers(meMsg), ['sourceData']);
2935
3042
  debug$j(`${this.header.name}/${convoStep.stepTag}: user says (cleaned by binary and base64 data and sourceData) ${JSON.stringify(coreMsg, null, 2)}`);
2936
3043
  await new Promise(resolve => {
2937
- if (container.caps.SIMULATE_WRITING_SPEED && meMsg.messageText && meMsg.messageText.length) {
2938
- setTimeout(() => resolve(), container.caps.SIMULATE_WRITING_SPEED * meMsg.messageText.length);
3044
+ if (container.caps[Capabilities.SIMULATE_WRITING_SPEED] && meMsg.messageText && meMsg.messageText.length) {
3045
+ setTimeout(() => resolve(), container.caps[Capabilities.SIMULATE_WRITING_SPEED] * meMsg.messageText.length);
2939
3046
  } else {
2940
3047
  resolve();
2941
3048
  }
@@ -2991,7 +3098,6 @@ class Convo$6 {
2991
3098
  throw failErr;
2992
3099
  }
2993
3100
  } else if (convoStep.sender === 'bot') {
2994
- const previousWaitForBotSays = waitForBotSays;
2995
3101
  if (waitForBotSays) {
2996
3102
  botMsg = null;
2997
3103
  } else {
@@ -3048,20 +3154,36 @@ class Convo$6 {
3048
3154
  throw failErr;
3049
3155
  }
3050
3156
  if (convoStep.conditional) {
3051
- const nextConvoStep = this.conversation[i + 1];
3052
- if (!previousWaitForBotSays) {
3053
- skipTranscriptStep = true;
3054
- }
3055
3157
  waitForBotSays = false;
3158
+ let endOfConditionalGroup = false;
3159
+ conditionalGroupId = convoStep.logicHooks.find(lh => lh.name.startsWith('CONDITIONAL_STEP')).args[1];
3160
+ const nextConvoStep = this.conversation[i + 1];
3056
3161
  if (!nextConvoStep || nextConvoStep.sender !== 'bot' || !nextConvoStep.logicHooks || !nextConvoStep.logicHooks.some(lh => lh.name.toUpperCase().startsWith('CONDITIONAL_STEP'))) {
3057
- waitForBotSays = true;
3162
+ endOfConditionalGroup = true;
3058
3163
  } else {
3059
- const conditionalLogicHook = convoStep.logicHooks.find(lh => lh.name.startsWith('CONDITIONAL_STEP'));
3060
3164
  const nextConditionalLogicHook = nextConvoStep.logicHooks.find(lh => lh.name.startsWith('CONDITIONAL_STEP'));
3061
- waitForBotSays = conditionalLogicHook.args[1] !== nextConditionalLogicHook.args[1];
3165
+ endOfConditionalGroup = conditionalGroupId !== nextConditionalLogicHook.args[1];
3062
3166
  }
3063
- if (convoStep.conditional.skip) {
3167
+ if (convoStep.conditional.skip || conditionMetInGroup) {
3168
+ skipTranscriptStep = true;
3169
+ if (endOfConditionalGroup && !conditionMetInGroup && !convoStep.optional) {
3170
+ const failErr = new BotiumError$2(`${this.header.name}/${convoStep.stepTag}: Non of the conditions are met in ${conditionalGroupId ? `'${conditionalGroupId}' ` : ''}condition group`);
3171
+ debug$j(failErr);
3172
+ throw failErr;
3173
+ }
3174
+ if (endOfConditionalGroup) {
3175
+ waitForBotSays = !convoStep.optional;
3176
+ conditionalGroupId = undefined;
3177
+ conditionMetInGroup = false;
3178
+ }
3064
3179
  continue;
3180
+ } else {
3181
+ conditionMetInGroup = true;
3182
+ if (endOfConditionalGroup) {
3183
+ waitForBotSays = !convoStep.optional;
3184
+ conditionalGroupId = undefined;
3185
+ conditionMetInGroup = false;
3186
+ }
3065
3187
  }
3066
3188
  }
3067
3189
  if (!botMsg || !botMsg.messageText && !botMsg.media && !botMsg.buttons && !botMsg.cards && !botMsg.sourceData && !botMsg.nlp) {
@@ -3074,10 +3196,29 @@ class Convo$6 {
3074
3196
  }
3075
3197
  const isErrorHandledWithOptionConvoStep = err => {
3076
3198
  const nextConvoStep = this.conversation[i + 1];
3199
+ const retryConfig = convoStepParameters?.ignoreNotMatchedBotResponses;
3200
+ const retryOn = convoStep.sender === 'bot' && retryConfig && retryConfig.timeout && retryConfig.mainAsserter;
3077
3201
  if (convoStep.optional && nextConvoStep && nextConvoStep.sender === 'bot') {
3202
+ if (retryOn) {
3203
+ debug$j(`${this.header.name}/${convoStep.stepTag}: Retry failed asserter is ignored on optional convo`);
3204
+ }
3078
3205
  waitForBotSays = false;
3079
3206
  skipTranscriptStep = true;
3080
3207
  return true;
3208
+ } else if (retryOn) {
3209
+ if (!retryBotMessageTimeoutEnd || retryBotMessageConvoId !== convoStep.stepTag) {
3210
+ retryBotMessageTimeoutEnd = transcriptStep.stepBegin.getTime() + +retryConfig.timeout;
3211
+ retryBotMessageConvoId = convoStep.stepTag;
3212
+ }
3213
+ const now = new Date().getTime();
3214
+ const timeoutRemaining = retryBotMessageTimeoutEnd - now;
3215
+ if (timeoutRemaining > 0) {
3216
+ debug$j(`${this.header.name}/${convoStep.stepTag}: Convo step retry on, timeout remaining: ${timeoutRemaining}, error: "${err.message}"`);
3217
+ retryBotMessageDropBotResponse = true;
3218
+ return false;
3219
+ } else {
3220
+ debug$j(`${this.header.name}/${convoStep.stepTag}: Convo step retry on, but timeout is over. error: "${err.message}"`);
3221
+ }
3081
3222
  }
3082
3223
  if (container.caps[Capabilities.SCRIPTING_ENABLE_MULTIPLE_ASSERT_ERRORS]) {
3083
3224
  assertErrors.push(err);
@@ -3095,7 +3236,7 @@ class Convo$6 {
3095
3236
  const tomatch = this._resolveUtterancesToMatch(container, Object.assign({}, scriptingMemoryUpdate, scriptingMemory), messageText, botMsg);
3096
3237
  if (convoStep.not) {
3097
3238
  try {
3098
- this.scriptingEvents.assertBotNotResponse(response, tomatch, `${this.header.name}/${convoStep.stepTag}`, lastMeConvoStep);
3239
+ this.scriptingEvents.assertBotNotResponse(response, tomatch, `${this.header.name}/${convoStep.stepTag}`, lastMeConvoStep, convoStepParameters);
3099
3240
  } catch (err) {
3100
3241
  if (isErrorHandledWithOptionConvoStep(err)) {
3101
3242
  continue;
@@ -3103,7 +3244,7 @@ class Convo$6 {
3103
3244
  }
3104
3245
  } else {
3105
3246
  try {
3106
- this.scriptingEvents.assertBotResponse(response, tomatch, `${this.header.name}/${convoStep.stepTag}`, lastMeConvoStep);
3247
+ this.scriptingEvents.assertBotResponse(response, tomatch, `${this.header.name}/${convoStep.stepTag}`, lastMeConvoStep, convoStepParameters);
3107
3248
  } catch (err) {
3108
3249
  if (isErrorHandledWithOptionConvoStep(err)) {
3109
3250
  continue;
@@ -3112,7 +3253,7 @@ class Convo$6 {
3112
3253
  }
3113
3254
  } else if (convoStep.sourceData) {
3114
3255
  try {
3115
- this._compareObject(container, scriptingMemory, convoStep, botMsg.sourceData, convoStep.sourceData, botMsg);
3256
+ this._compareObject(container, scriptingMemory, convoStep, botMsg.sourceData, convoStep.sourceData, botMsg, convoStepParameters);
3116
3257
  } catch (err) {
3117
3258
  if (isErrorHandledWithOptionConvoStep(err)) {
3118
3259
  continue;
@@ -3146,19 +3287,42 @@ class Convo$6 {
3146
3287
  skipTranscriptStep = true;
3147
3288
  continue;
3148
3289
  }
3149
- const failErr = botiumErrorFromErr$1(`${this.header.name}/${convoStep.stepTag}: assertion error - ${err.message || err}`, err);
3150
- debug$j(failErr);
3151
- try {
3152
- this.scriptingEvents.fail && this.scriptingEvents.fail(failErr, lastMeConvoStep);
3153
- } catch (failErr) {}
3154
- if (container.caps[Capabilities.SCRIPTING_ENABLE_MULTIPLE_ASSERT_ERRORS] && err instanceof BotiumError$2) {
3155
- assertErrors.push(err);
3290
+ const errors = err.toArray ? err.toArray() : [];
3291
+ const retryConfig = convoStepParameters?.ignoreNotMatchedBotResponses;
3292
+ const retryOn = convoStep.sender === 'bot' && retryConfig && retryConfig.timeout && errors.length && errors.filter(({
3293
+ type,
3294
+ source,
3295
+ asserter
3296
+ }) => type === 'asserter' && (retryConfig.allAsserters || retryConfig.asserters && retryConfig.asserters.includes(asserter))).length;
3297
+ if (retryOn && (!retryBotMessageTimeoutEnd || retryBotMessageConvoId !== convoStep.stepTag)) {
3298
+ retryBotMessageTimeoutEnd = transcriptStep.stepBegin.getTime() + +retryConfig.timeout;
3299
+ retryBotMessageConvoId = convoStep.stepTag;
3300
+ }
3301
+ const now = new Date().getTime();
3302
+ const timeoutRemaining = retryOn && retryBotMessageTimeoutEnd - now;
3303
+ if (retryOn && timeoutRemaining > 0) {
3304
+ debug$j(`${this.header.name}/${convoStep.stepTag}: Convo step retry on, timeout remaining: ${timeoutRemaining}, error: "${err.message}"`);
3305
+ retryBotMessageDropBotResponse = true;
3156
3306
  } else {
3157
- throw failErr;
3307
+ if (retryOn && timeoutRemaining <= 0) {
3308
+ debug$j(`${this.header.name}/${convoStep.stepTag}: Convo step retry on, but timeout is over. error: "${err.message}"`);
3309
+ }
3310
+ const failErr = botiumErrorFromErr$1(`${this.header.name}/${convoStep.stepTag}: assertion error - ${err.message || err}`, err);
3311
+ debug$j(failErr);
3312
+ try {
3313
+ this.scriptingEvents.fail && this.scriptingEvents.fail(failErr, lastMeConvoStep);
3314
+ } catch (failErr) {}
3315
+ if (container.caps[Capabilities.SCRIPTING_ENABLE_MULTIPLE_ASSERT_ERRORS] && err instanceof BotiumError$2) {
3316
+ assertErrors.push(err);
3317
+ } else {
3318
+ throw failErr;
3319
+ }
3158
3320
  }
3159
3321
  }
3160
3322
  if (container.caps[Capabilities.SCRIPTING_ENABLE_MULTIPLE_ASSERT_ERRORS]) {
3161
3323
  if (assertErrors.length > 0) {
3324
+ // this has no effect, but logically it has to be false
3325
+ retryBotMessageDropBotResponse = false;
3162
3326
  throw botiumErrorFromList$1(assertErrors, {});
3163
3327
  }
3164
3328
  } else {
@@ -3218,7 +3382,7 @@ class Convo$6 {
3218
3382
  }
3219
3383
  }
3220
3384
  }
3221
- _compareObject(container, scriptingMemory, convoStep, result, expected, botMsg) {
3385
+ _compareObject(container, scriptingMemory, convoStep, result, expected, botMsg, convoStepParameters) {
3222
3386
  if (expected === null || expected === undefined) return;
3223
3387
  if (lodash.isArray(expected)) {
3224
3388
  if (!lodash.isArray(result)) {
@@ -3228,12 +3392,12 @@ class Convo$6 {
3228
3392
  throw new BotiumError$2(`${this.header.name}/${convoStep.stepTag}: bot response expected array length ${expected.length}, got ${result.length}`);
3229
3393
  }
3230
3394
  for (let i = 0; i < expected.length; i++) {
3231
- this._compareObject(container, scriptingMemory, convoStep, result[i], expected[i]);
3395
+ this._compareObject(container, scriptingMemory, convoStep, result[i], expected[i], null, convoStepParameters);
3232
3396
  }
3233
3397
  } else if (lodash.isObject(expected)) {
3234
3398
  lodash.forOwn(expected, (value, key) => {
3235
3399
  if (Object.prototype.hasOwnProperty.call(result, key)) {
3236
- this._compareObject(container, scriptingMemory, convoStep, result[key], expected[key]);
3400
+ this._compareObject(container, scriptingMemory, convoStep, result[key], expected[key], null, convoStepParameters);
3237
3401
  } else {
3238
3402
  throw new BotiumError$2(`${this.header.name}/${convoStep.stepTag}: bot response "${result}" missing expected property: ${key}`);
3239
3403
  }
@@ -3242,7 +3406,7 @@ class Convo$6 {
3242
3406
  ScriptingMemory.fill(container, scriptingMemory, result, expected, this.scriptingEvents);
3243
3407
  const response = this._checkNormalizeText(container, result);
3244
3408
  const tomatch = this._resolveUtterancesToMatch(container, scriptingMemory, expected, botMsg);
3245
- this.scriptingEvents.assertBotResponse(response, tomatch, `${this.header.name}/${convoStep.stepTag}`);
3409
+ this.scriptingEvents.assertBotResponse(response, tomatch, `${this.header.name}/${convoStep.stepTag}`, null, convoStepParameters);
3246
3410
  }
3247
3411
  }
3248
3412
  GetScriptingMemoryAllVariables(container) {
@@ -3302,7 +3466,7 @@ class Convo$6 {
3302
3466
  }, []);
3303
3467
  }
3304
3468
  _checkBotRepliesConsumed(container) {
3305
- if (container.caps.SCRIPTING_FORCE_BOT_CONSUMED) {
3469
+ if (container.caps[Capabilities.SCRIPTING_FORCE_BOT_CONSUMED]) {
3306
3470
  const queueLength = container._QueueLength();
3307
3471
  if (queueLength === 1) {
3308
3472
  throw new Error('There is an unread bot reply in queue');
@@ -5346,7 +5510,7 @@ var ScriptingProvider_1 = class ScriptingProvider {
5346
5510
  }) => {
5347
5511
  return this._createLogicHookPromises({
5348
5512
  hookType: 'onConvoBegin',
5349
- logicHooks: convo.beginLogicHook || [],
5513
+ logicHooks: convo?.beginLogicHook || [],
5350
5514
  convo,
5351
5515
  convoStep,
5352
5516
  scriptingMemory,
@@ -5361,7 +5525,7 @@ var ScriptingProvider_1 = class ScriptingProvider {
5361
5525
  }) => {
5362
5526
  return this._createLogicHookPromises({
5363
5527
  hookType: 'onConvoEnd',
5364
- logicHooks: convo.endLogicHook || [],
5528
+ logicHooks: convo?.endLogicHook || [],
5365
5529
  convo,
5366
5530
  convoStep,
5367
5531
  scriptingMemory,
@@ -5376,7 +5540,7 @@ var ScriptingProvider_1 = class ScriptingProvider {
5376
5540
  }) => {
5377
5541
  return this._createLogicHookPromises({
5378
5542
  hookType: 'onMeStart',
5379
- logicHooks: convoStep.logicHooks || [],
5543
+ logicHooks: convoStep?.logicHooks || [],
5380
5544
  convo,
5381
5545
  convoStep,
5382
5546
  scriptingMemory,
@@ -5391,7 +5555,7 @@ var ScriptingProvider_1 = class ScriptingProvider {
5391
5555
  }) => {
5392
5556
  return this._createLogicHookPromises({
5393
5557
  hookType: 'onMePrepare',
5394
- logicHooks: convoStep.logicHooks || [],
5558
+ logicHooks: convoStep?.logicHooks || [],
5395
5559
  convo,
5396
5560
  convoStep,
5397
5561
  scriptingMemory,
@@ -5406,7 +5570,7 @@ var ScriptingProvider_1 = class ScriptingProvider {
5406
5570
  }) => {
5407
5571
  return this._createLogicHookPromises({
5408
5572
  hookType: 'onMeEnd',
5409
- logicHooks: convoStep.logicHooks || [],
5573
+ logicHooks: convoStep?.logicHooks || [],
5410
5574
  convo,
5411
5575
  convoStep,
5412
5576
  scriptingMemory,
@@ -5421,7 +5585,7 @@ var ScriptingProvider_1 = class ScriptingProvider {
5421
5585
  }) => {
5422
5586
  return this._createLogicHookPromises({
5423
5587
  hookType: 'onBotStart',
5424
- logicHooks: convoStep.logicHooks || [],
5588
+ logicHooks: convoStep?.logicHooks || [],
5425
5589
  convo,
5426
5590
  convoStep,
5427
5591
  scriptingMemory,
@@ -5436,7 +5600,7 @@ var ScriptingProvider_1 = class ScriptingProvider {
5436
5600
  }) => {
5437
5601
  return this._createLogicHookPromises({
5438
5602
  hookType: 'onBotPrepare',
5439
- logicHooks: convoStep.logicHooks || [],
5603
+ logicHooks: convoStep?.logicHooks || [],
5440
5604
  convo,
5441
5605
  convoStep,
5442
5606
  scriptingMemory,
@@ -5451,7 +5615,7 @@ var ScriptingProvider_1 = class ScriptingProvider {
5451
5615
  }) => {
5452
5616
  return this._createLogicHookPromises({
5453
5617
  hookType: 'onBotEnd',
5454
- logicHooks: convoStep.logicHooks || [],
5618
+ logicHooks: convoStep?.logicHooks || [],
5455
5619
  convo,
5456
5620
  convoStep,
5457
5621
  scriptingMemory,
@@ -5466,7 +5630,7 @@ var ScriptingProvider_1 = class ScriptingProvider {
5466
5630
  }) => {
5467
5631
  return this._createAsserterPromises({
5468
5632
  asserterType: 'assertConvoBegin',
5469
- asserters: convo.beginAsserter || [],
5633
+ asserters: convo?.beginAsserter || [],
5470
5634
  convo,
5471
5635
  convoStep,
5472
5636
  scriptingMemory,
@@ -5481,7 +5645,7 @@ var ScriptingProvider_1 = class ScriptingProvider {
5481
5645
  }) => {
5482
5646
  return this._createAsserterPromises({
5483
5647
  asserterType: 'assertConvoStep',
5484
- asserters: convoStep.asserters || [],
5648
+ asserters: convoStep?.asserters || [],
5485
5649
  convo,
5486
5650
  convoStep,
5487
5651
  scriptingMemory,
@@ -5496,7 +5660,7 @@ var ScriptingProvider_1 = class ScriptingProvider {
5496
5660
  }) => {
5497
5661
  return this._createAsserterPromises({
5498
5662
  asserterType: 'assertConvoEnd',
5499
- asserters: convo.endAsserter || [],
5663
+ asserters: convo?.endAsserter || [],
5500
5664
  convo,
5501
5665
  convoStep,
5502
5666
  scriptingMemory,
@@ -5525,12 +5689,13 @@ var ScriptingProvider_1 = class ScriptingProvider {
5525
5689
  resolveEmptyIfUnknown
5526
5690
  });
5527
5691
  },
5528
- assertBotResponse: (botresponse, tomatch, stepTag, meMsg) => {
5692
+ assertBotResponse: (botresponse, tomatch, stepTag, meMsg, convoStepParameters) => {
5529
5693
  if (!lodash.isArray(tomatch)) {
5530
5694
  tomatch = [tomatch];
5531
5695
  }
5532
5696
  debug$9(`assertBotResponse ${stepTag} ${meMsg ? `(${meMsg}) ` : ''}BOT: ${botresponse} = ${tomatch} ...`);
5533
- const found = lodash.find(tomatch, utt => this.matchFn(botresponse, utt, this.caps[Capabilities.SCRIPTING_MATCHING_MODE_ARGS]));
5697
+ const matchFn = convoStepParameters.matchingMode ? getMatchFunction(convoStepParameters.matchingMode) || this.matchFn : this.matchFn;
5698
+ const found = lodash.find(tomatch, utt => matchFn(botresponse, utt, this.caps[Capabilities.SCRIPTING_MATCHING_MODE_ARGS]));
5534
5699
  const asserterType = this.caps[Capabilities.SCRIPTING_MATCHING_MODE] === 'wer' ? 'Word Error Rate Asserter' : 'Text Match Asserter';
5535
5700
  if (lodash.isNil(found)) {
5536
5701
  if (this.caps[Capabilities.SCRIPTING_MATCHING_MODE] === 'wer') {
@@ -5580,12 +5745,13 @@ var ScriptingProvider_1 = class ScriptingProvider {
5580
5745
  }
5581
5746
  }
5582
5747
  },
5583
- assertBotNotResponse: (botresponse, nottomatch, stepTag, meMsg) => {
5748
+ assertBotNotResponse: (botresponse, nottomatch, stepTag, meMsg, convoStepParameters) => {
5584
5749
  if (!lodash.isArray(nottomatch)) {
5585
5750
  nottomatch = [nottomatch];
5586
5751
  }
5587
5752
  debug$9(`assertBotNotResponse ${stepTag} ${meMsg ? `(${meMsg}) ` : ''}BOT: ${botresponse} != ${nottomatch} ...`);
5588
- const found = lodash.find(nottomatch, utt => this.matchFn(botresponse, utt, this.caps[Capabilities.SCRIPTING_MATCHING_MODE_ARGS]));
5753
+ const matchFn = convoStepParameters.matchingMode ? getMatchFunction(convoStepParameters.matchingMode) || this.matchFn : this.matchFn;
5754
+ const found = lodash.find(nottomatch, utt => matchFn(botresponse, utt, this.caps[Capabilities.SCRIPTING_MATCHING_MODE_ARGS]));
5589
5755
  const asserterType = this.caps[Capabilities.SCRIPTING_MATCHING_MODE] === 'wer' ? 'Word Error Rate Asserter' : 'Text Match Asserter';
5590
5756
  if (!lodash.isNil(found)) {
5591
5757
  if (this.caps[Capabilities.SCRIPTING_MATCHING_MODE] === 'wer') {
@@ -5659,6 +5825,22 @@ var ScriptingProvider_1 = class ScriptingProvider {
5659
5825
  assertConvoStep: 'assertNotConvoStep',
5660
5826
  assertConvoEnd: 'assertNotConvoEnd'
5661
5827
  };
5828
+ const updateExceptionContext = (promise, asserter) => {
5829
+ const updateError = err => {
5830
+ if (err instanceof BotiumError$1) {
5831
+ if (!err.context) {
5832
+ err.context = {};
5833
+ }
5834
+ err.context.asserter = asserter.name;
5835
+ throw err;
5836
+ } else {
5837
+ throw botiumErrorFromErr(lodash.isString(err) ? err : err.message, err, {
5838
+ asserter: asserter.name
5839
+ });
5840
+ }
5841
+ };
5842
+ return promise.catch(err => updateError(err));
5843
+ };
5662
5844
  const callAsserter = (asserterSpec, asserter, params) => {
5663
5845
  if (asserterSpec.not) {
5664
5846
  const notAsserterType = mapNot[asserterType];
@@ -5682,24 +5864,36 @@ var ScriptingProvider_1 = class ScriptingProvider {
5682
5864
  return p(this.retryHelperAsserter, () => asserter[asserterType](params));
5683
5865
  }
5684
5866
  };
5685
- const convoAsserter = asserters.filter(a => this.asserters[a.name][asserterType]).map(a => callAsserter(a, this.asserters[a.name], {
5686
- convo,
5687
- convoStep,
5688
- scriptingMemory,
5689
- container,
5690
- args: ScriptingMemory.applyToArgs(a.args, scriptingMemory, container.caps, rest.botMsg),
5691
- isGlobal: false,
5692
- ...rest
5693
- }));
5694
- const globalAsserter = Object.values(this.globalAsserter).filter(a => a[asserterType]).map(a => p(this.retryHelperAsserter, () => a[asserterType]({
5695
- convo,
5696
- convoStep,
5697
- scriptingMemory,
5698
- container,
5699
- args: [],
5700
- isGlobal: true,
5701
- ...rest
5702
- })));
5867
+ const convoAsserter = asserters.filter(a => this.asserters[a.name][asserterType]).map(a => ({
5868
+ asserter: a,
5869
+ promise: callAsserter(a, this.asserters[a.name], {
5870
+ convo,
5871
+ convoStep,
5872
+ scriptingMemory,
5873
+ container,
5874
+ args: ScriptingMemory.applyToArgs(a.args, scriptingMemory, container.caps, rest.botMsg),
5875
+ isGlobal: false,
5876
+ ...rest
5877
+ })
5878
+ })).map(({
5879
+ promise,
5880
+ asserter
5881
+ }) => updateExceptionContext(promise, asserter));
5882
+ const globalAsserter = Object.values(this.globalAsserter).filter(a => a[asserterType]).map(a => ({
5883
+ asserter: a,
5884
+ promise: p(this.retryHelperAsserter, () => a[asserterType]({
5885
+ convo,
5886
+ convoStep,
5887
+ scriptingMemory,
5888
+ container,
5889
+ args: [],
5890
+ isGlobal: true,
5891
+ ...rest
5892
+ }))
5893
+ })).map(({
5894
+ promise,
5895
+ asserter
5896
+ }) => updateExceptionContext(promise, asserter));
5703
5897
  const allPromises = [...convoAsserter, ...globalAsserter];
5704
5898
  if (this.caps[Capabilities.SCRIPTING_ENABLE_MULTIPLE_ASSERT_ERRORS]) {
5705
5899
  return Promise.allSettled(allPromises).then(results => {
@@ -5725,7 +5919,8 @@ var ScriptingProvider_1 = class ScriptingProvider {
5725
5919
  if (hookType !== 'onMeStart' && hookType !== 'onMePrepare' && hookType !== 'onMeEnd' && hookType !== 'onBotStart' && hookType !== 'onBotPrepare' && hookType !== 'onBotEnd' && hookType !== 'onConvoBegin' && hookType !== 'onConvoEnd') {
5726
5920
  throw Error(`Unknown hookType ${hookType}`);
5727
5921
  }
5728
- const convoStepPromises = (logicHooks || []).filter(l => this.logicHooks[l.name][hookType]).map(l => p(this.retryHelperLogicHook, () => this.logicHooks[l.name][hookType]({
5922
+ const localHooks = (logicHooks || []).filter(l => this.logicHooks[l.name][hookType]);
5923
+ const convoStepPromises = localHooks.map(l => p(this.retryHelperLogicHook, () => this.logicHooks[l.name][hookType]({
5729
5924
  convo,
5730
5925
  convoStep,
5731
5926
  scriptingMemory,
@@ -5734,7 +5929,8 @@ var ScriptingProvider_1 = class ScriptingProvider {
5734
5929
  isGlobal: false,
5735
5930
  ...rest
5736
5931
  })));
5737
- const globalPromises = Object.values(this.globalLogicHook).filter(l => l[hookType]).map(l => p(this.retryHelperLogicHook, () => l[hookType]({
5932
+ const globalHooks = Object.values(this.globalLogicHook).filter(l => l[hookType]);
5933
+ const globalPromises = globalHooks.map(l => p(this.retryHelperLogicHook, () => l[hookType]({
5738
5934
  convo,
5739
5935
  convoStep,
5740
5936
  scriptingMemory,
@@ -5744,7 +5940,14 @@ var ScriptingProvider_1 = class ScriptingProvider {
5744
5940
  ...rest
5745
5941
  })));
5746
5942
  const allPromises = [...convoStepPromises, ...globalPromises];
5747
- if (allPromises.length > 0) return Promise.all(allPromises).then(() => true);
5943
+ if (allPromises.length > 0) {
5944
+ return Promise.all(allPromises).then(() => {
5945
+ return {
5946
+ // just returning some humanreadable
5947
+ hooks: [...localHooks, ...globalHooks].map(h => h.name || h.context?.ref || JSON.stringify(h))
5948
+ };
5949
+ });
5950
+ }
5748
5951
  return Promise.resolve(false);
5749
5952
  }
5750
5953
  _createUserInputPromises({
@@ -5754,7 +5957,7 @@ var ScriptingProvider_1 = class ScriptingProvider {
5754
5957
  container,
5755
5958
  ...rest
5756
5959
  }) {
5757
- const convoStepPromises = (convoStep.userInputs || []).filter(ui => this.userInputs[ui.name]).map(ui => p(this.retryHelperUserInput, () => this.userInputs[ui.name].setUserInput({
5960
+ const convoStepPromises = (convoStep?.userInputs || []).filter(ui => this.userInputs[ui.name]).map(ui => p(this.retryHelperUserInput, () => this.userInputs[ui.name].setUserInput({
5758
5961
  convo,
5759
5962
  convoStep,
5760
5963
  scriptingMemory,
@@ -5816,6 +6019,11 @@ var ScriptingProvider_1 = class ScriptingProvider {
5816
6019
  }
5817
6020
  };
5818
6021
  }
6022
+
6023
+ // Livechat, and crawler using logichooks too. So they need script context
6024
+ BuildScriptContext() {
6025
+ return this._buildScriptContext();
6026
+ }
5819
6027
  Build() {
5820
6028
  const CompilerXlsx = CompilerXlsx_1;
5821
6029
  this.compilers[Constants.SCRIPTING_FORMAT_XSLX] = new CompilerXlsx(this._buildScriptContext(), this.caps);