botium-core 1.13.16 → 1.13.17
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.
- package/dist/botium-cjs.js +203 -172
- package/dist/botium-cjs.js.map +1 -1
- package/dist/botium-es.js +202 -171
- package/dist/botium-es.js.map +1 -1
- package/package.json +23 -23
- package/src/BotDriver.js +4 -6
- package/src/Capabilities.js +1 -3
- package/src/Events.js +1 -0
- package/src/containers/BaseContainer.js +4 -5
- package/src/containers/PluginConnectorContainer.js +0 -4
- package/src/scripting/Convo.js +1 -27
- package/src/scripting/ScriptingProvider.js +102 -51
- package/src/scripting/helper.js +9 -2
- package/src/scripting/logichook/asserter/WerAsserter.js +53 -6
- package/test/security/allowUnsafe.spec.js +20 -10
- package/test/security/convos/withscriptingmemoryfunction.convo.txt +1 -0
- package/test/convo/retryconvo.spec.js +0 -134
package/dist/botium-es.js
CHANGED
|
@@ -2,7 +2,7 @@ import util from 'util';
|
|
|
2
2
|
import fs from 'fs';
|
|
3
3
|
import path from 'path';
|
|
4
4
|
import async from 'async';
|
|
5
|
-
import rimraf from 'rimraf';
|
|
5
|
+
import rimraf$2 from 'rimraf';
|
|
6
6
|
import mkdirp from 'mkdirp';
|
|
7
7
|
import sanitizeFilename from 'sanitize-filename';
|
|
8
8
|
import moment from 'moment';
|
|
@@ -37,7 +37,7 @@ import express from 'express';
|
|
|
37
37
|
import bodyParser from 'body-parser';
|
|
38
38
|
|
|
39
39
|
var name = "botium-core";
|
|
40
|
-
var version$1 = "1.13.
|
|
40
|
+
var version$1 = "1.13.17";
|
|
41
41
|
var description = "The Selenium for Chatbots";
|
|
42
42
|
var main = "index.js";
|
|
43
43
|
var module = "dist/botium-es.js";
|
|
@@ -69,66 +69,66 @@ var bugs = {
|
|
|
69
69
|
};
|
|
70
70
|
var homepage = "https://www.botium.ai";
|
|
71
71
|
var dependencies = {
|
|
72
|
-
"@babel/runtime": "^7.
|
|
72
|
+
"@babel/runtime": "^7.21.5",
|
|
73
73
|
async: "^3.2.4",
|
|
74
|
-
"body-parser": "^1.20.
|
|
74
|
+
"body-parser": "^1.20.2",
|
|
75
75
|
boolean: "^3.2.0",
|
|
76
76
|
bottleneck: "^2.19.5",
|
|
77
|
-
"csv-parse": "^5.3.
|
|
77
|
+
"csv-parse": "^5.3.10",
|
|
78
78
|
debug: "^4.3.4",
|
|
79
79
|
esprima: "^4.0.1",
|
|
80
80
|
express: "^4.18.2",
|
|
81
81
|
globby: "11.0.4",
|
|
82
|
-
ioredis: "^5.2
|
|
82
|
+
ioredis: "^5.3.2",
|
|
83
83
|
"is-class": "^0.0.9",
|
|
84
84
|
"is-json": "^2.0.1",
|
|
85
85
|
jsonpath: "^1.1.1",
|
|
86
86
|
lodash: "^4.17.21",
|
|
87
87
|
"markdown-it": "^13.0.1",
|
|
88
88
|
"mime-types": "^2.1.35",
|
|
89
|
-
mkdirp: "^
|
|
89
|
+
mkdirp: "^3.0.1",
|
|
90
90
|
moment: "^2.29.4",
|
|
91
91
|
mustache: "^4.2.0",
|
|
92
92
|
"promise-retry": "^2.0.1",
|
|
93
93
|
"promise.allsettled": "^1.0.6",
|
|
94
94
|
randomatic: "^3.1.1",
|
|
95
95
|
request: "^2.88.2",
|
|
96
|
-
rimraf: "^
|
|
96
|
+
rimraf: "^5.0.0",
|
|
97
97
|
"sanitize-filename": "^1.6.3",
|
|
98
|
-
slugify: "^1.6.
|
|
99
|
-
"socket.io": "^4.
|
|
100
|
-
"socket.io-client": "^4.
|
|
98
|
+
slugify: "^1.6.6",
|
|
99
|
+
"socket.io": "^4.6.1",
|
|
100
|
+
"socket.io-client": "^4.6.1",
|
|
101
101
|
"socketio-auth": "^0.1.1",
|
|
102
|
-
"swagger-jsdoc": "^6.2.
|
|
103
|
-
"swagger-ui-express": "^4.6.
|
|
102
|
+
"swagger-jsdoc": "^6.2.8",
|
|
103
|
+
"swagger-ui-express": "^4.6.3",
|
|
104
104
|
uuid: "^9.0.0",
|
|
105
|
-
vm2: "^3.9.
|
|
105
|
+
vm2: "^3.9.17",
|
|
106
106
|
"word-error-rate": "0.0.7",
|
|
107
107
|
"write-yaml": "^1.0.0",
|
|
108
108
|
xlsx: "^0.18.5",
|
|
109
109
|
xregexp: "^5.1.1",
|
|
110
|
-
yaml: "^2.
|
|
110
|
+
yaml: "^2.2.2"
|
|
111
111
|
};
|
|
112
112
|
var devDependencies = {
|
|
113
|
-
"@babel/core": "^7.
|
|
114
|
-
"@babel/node": "^7.20.
|
|
115
|
-
"@babel/plugin-transform-runtime": "^7.
|
|
116
|
-
"@babel/preset-env": "^7.
|
|
113
|
+
"@babel/core": "^7.21.8",
|
|
114
|
+
"@babel/node": "^7.20.7",
|
|
115
|
+
"@babel/plugin-transform-runtime": "^7.21.4",
|
|
116
|
+
"@babel/preset-env": "^7.21.5",
|
|
117
117
|
chai: "^4.3.7",
|
|
118
118
|
"chai-as-promised": "^7.1.1",
|
|
119
119
|
"cross-env": "^7.0.3",
|
|
120
|
-
eslint: "^8.
|
|
120
|
+
eslint: "^8.40.0",
|
|
121
121
|
"eslint-config-standard": "^17.0.0",
|
|
122
|
-
"eslint-plugin-import": "^2.
|
|
122
|
+
"eslint-plugin-import": "^2.27.5",
|
|
123
123
|
"eslint-plugin-mocha": "^10.1.0",
|
|
124
|
-
"eslint-plugin-n": "^15.
|
|
124
|
+
"eslint-plugin-n": "^15.7.0",
|
|
125
125
|
"eslint-plugin-promise": "^6.1.1",
|
|
126
126
|
"eslint-plugin-standard": "^4.1.0",
|
|
127
127
|
"license-checker": "^25.0.1",
|
|
128
128
|
"license-compatibility-checker": "^0.3.5",
|
|
129
129
|
mocha: "^10.2.0",
|
|
130
|
-
nock: "^13.
|
|
131
|
-
"npm-check-updates": "^16.
|
|
130
|
+
nock: "^13.3.1",
|
|
131
|
+
"npm-check-updates": "^16.10.12",
|
|
132
132
|
nyc: "^15.1.0",
|
|
133
133
|
rollup: "2.79.1",
|
|
134
134
|
"rollup-plugin-babel": "^4.4.0",
|
|
@@ -339,9 +339,7 @@ var Capabilities = {
|
|
|
339
339
|
RATELIMIT_USERSAYS_MINTIME: 'RATELIMIT_USERSAYS_MINTIME',
|
|
340
340
|
RATELIMIT_BOTTLENECK_FN: 'RATELIMIT_BOTTLENECK_FN',
|
|
341
341
|
SECURITY_ALLOW_UNSAFE: 'SECURITY_ALLOW_UNSAFE',
|
|
342
|
-
PRECOMPILERS: 'PRECOMPILERS'
|
|
343
|
-
// RETRY
|
|
344
|
-
RETRY_CONVO_ASYNC: 'RETRY_CONVO_ASYNC'
|
|
342
|
+
PRECOMPILERS: 'PRECOMPILERS'
|
|
345
343
|
};
|
|
346
344
|
Capabilities.PROJECTNAME;
|
|
347
345
|
Capabilities.TESTSESSIONNAME;
|
|
@@ -494,7 +492,6 @@ Capabilities.RATELIMIT_USERSAYS_MINTIME;
|
|
|
494
492
|
Capabilities.RATELIMIT_BOTTLENECK_FN;
|
|
495
493
|
Capabilities.SECURITY_ALLOW_UNSAFE;
|
|
496
494
|
Capabilities.PRECOMPILERS;
|
|
497
|
-
Capabilities.RETRY_CONVO_ASYNC;
|
|
498
495
|
|
|
499
496
|
var Source = {
|
|
500
497
|
LOCALPATH: 'LOCALPATH',
|
|
@@ -815,6 +812,7 @@ var Events = {
|
|
|
815
812
|
CONTAINER_CLEANED: 'CONTAINER_CLEANED',
|
|
816
813
|
CONTAINER_CLEAN_ERROR: 'CONTAINER_CLEAN_ERROR',
|
|
817
814
|
BOT_CONNECTED: 'BOT_CONNECTED',
|
|
815
|
+
CONVO_STEP_NEXT: 'CONVO_STEP_NEXT',
|
|
818
816
|
// Chatbot Events
|
|
819
817
|
MESSAGE_SENTTOBOT: 'MESSAGE_SENTTOBOT',
|
|
820
818
|
MESSAGE_SENDTOBOT_ERROR: 'MESSAGE_SENDTOBOT_ERROR',
|
|
@@ -838,6 +836,7 @@ Events.CONTAINER_CLEANING;
|
|
|
838
836
|
Events.CONTAINER_CLEANED;
|
|
839
837
|
Events.CONTAINER_CLEAN_ERROR;
|
|
840
838
|
Events.BOT_CONNECTED;
|
|
839
|
+
Events.CONVO_STEP_NEXT;
|
|
841
840
|
Events.MESSAGE_SENTTOBOT;
|
|
842
841
|
Events.MESSAGE_SENDTOBOT_ERROR;
|
|
843
842
|
Events.MESSAGE_RECEIVEDFROMBOT;
|
|
@@ -2181,7 +2180,7 @@ const linesToScriptingMemories$2 = (lines, columnMode = null) => {
|
|
|
2181
2180
|
}
|
|
2182
2181
|
return scriptingMemories;
|
|
2183
2182
|
};
|
|
2184
|
-
const calculateWer$
|
|
2183
|
+
const calculateWer$2 = (str, pattern) => {
|
|
2185
2184
|
const _prepareString = (str, remWildcard = false) => {
|
|
2186
2185
|
if (remWildcard) return str.replace(/[.,/#!$%^&;:*{}=\-_`~()]/g, '').toLowerCase();
|
|
2187
2186
|
return str.replace(/[.,/#!$%^&;:{}=\-_`~()]/g, '').toLowerCase();
|
|
@@ -2204,6 +2203,11 @@ const calculateWer$1 = (str, pattern) => {
|
|
|
2204
2203
|
const botMessage = _prepareString(str);
|
|
2205
2204
|
const botMessageWords = botMessage.split(' ').map(bm => bm.trim());
|
|
2206
2205
|
const utt = _prepareString(utterance);
|
|
2206
|
+
|
|
2207
|
+
// if no wildcards, just calculate WER
|
|
2208
|
+
if (utt.indexOf('*') === -1) return wordErrorRate.wordErrorRate(botMessage, utt).toFixed(2);
|
|
2209
|
+
|
|
2210
|
+
// if there are wildcards, calculate WER for each wildcard part
|
|
2207
2211
|
const errors = [];
|
|
2208
2212
|
for (let wildcardPart of utt.split('*')) {
|
|
2209
2213
|
let wer = 1;
|
|
@@ -2223,7 +2227,7 @@ const calculateWer$1 = (str, pattern) => {
|
|
|
2223
2227
|
}
|
|
2224
2228
|
}
|
|
2225
2229
|
if (lodash.isNil(subsetPhraseFound)) {
|
|
2226
|
-
throw new Error('Word Error Asserter:
|
|
2230
|
+
throw new Error('Word Error Asserter: When using wild cards, please make sure that the length of the asserter text is smaller than the bot message!');
|
|
2227
2231
|
}
|
|
2228
2232
|
errors.push(_getErrors(_getWords(wildcardPart), _getWords(subsetPhraseFound)));
|
|
2229
2233
|
}
|
|
@@ -2236,6 +2240,7 @@ const calculateWer$1 = (str, pattern) => {
|
|
|
2236
2240
|
debug$l(`Word Error Rate Asserter - Compared Bot Message '${botMessage}' / '${utt}': ${(errCount / allCount).toFixed(2)}`);
|
|
2237
2241
|
return (errCount / allCount).toFixed(2);
|
|
2238
2242
|
};
|
|
2243
|
+
const toPercent$1 = s => `${(s * 100).toFixed(0)}%`;
|
|
2239
2244
|
var helper = {
|
|
2240
2245
|
normalizeText: normalizeText$1,
|
|
2241
2246
|
splitStringInNonEmptyLines: splitStringInNonEmptyLines$1,
|
|
@@ -2250,7 +2255,8 @@ var helper = {
|
|
|
2250
2255
|
validateSender: validateSender$1,
|
|
2251
2256
|
validateConvo: validateConvo$2,
|
|
2252
2257
|
linesToScriptingMemories: linesToScriptingMemories$2,
|
|
2253
|
-
calculateWer: calculateWer$
|
|
2258
|
+
calculateWer: calculateWer$2,
|
|
2259
|
+
toPercent: toPercent$1
|
|
2254
2260
|
};
|
|
2255
2261
|
|
|
2256
2262
|
const debug$k = debug$n('botium-core-ScriptingMemory');
|
|
@@ -2590,45 +2596,7 @@ ScriptingMemory.extractVarNames;
|
|
|
2590
2596
|
ScriptingMemory.RESERVED_WORDS;
|
|
2591
2597
|
ScriptingMemory.SCRIPTING_FUNCTIONS;
|
|
2592
2598
|
|
|
2593
|
-
const debug$j = debug$n('botium-core-
|
|
2594
|
-
var RetryHelper_1 = class RetryHelper {
|
|
2595
|
-
constructor(caps, section, options = {}) {
|
|
2596
|
-
this.retryErrorPatterns = [];
|
|
2597
|
-
const onErrorRegexp = caps[`RETRY_${section.toUpperCase()}_ONERROR_REGEXP`] || [];
|
|
2598
|
-
if (onErrorRegexp) {
|
|
2599
|
-
if (lodash.isArray(onErrorRegexp)) {
|
|
2600
|
-
onErrorRegexp.forEach(r => {
|
|
2601
|
-
if (lodash.isString(r)) this.retryErrorPatterns.push(new RegExp(r, 'i'));else this.retryErrorPatterns.push(r);
|
|
2602
|
-
});
|
|
2603
|
-
} else if (lodash.isString(onErrorRegexp)) {
|
|
2604
|
-
this.retryErrorPatterns.push(new RegExp(onErrorRegexp, 'i'));
|
|
2605
|
-
} else {
|
|
2606
|
-
this.retryErrorPatterns.push(onErrorRegexp);
|
|
2607
|
-
}
|
|
2608
|
-
}
|
|
2609
|
-
|
|
2610
|
-
// to turn on retries, NUMRETRIES or ONERROR_REGEXP has to be set
|
|
2611
|
-
this.retrySettings = {
|
|
2612
|
-
retries: caps[`RETRY_${section.toUpperCase()}_NUMRETRIES`] || (!lodash.isNil(options.numRetries) ? options.numRetries : this.retryErrorPatterns.length === 0 ? 0 : 1),
|
|
2613
|
-
factor: caps[`RETRY_${section.toUpperCase()}_FACTOR`] || (lodash.isNil(options.factor) ? 1 : options.factor),
|
|
2614
|
-
minTimeout: caps[`RETRY_${section.toUpperCase()}_MINTIMEOUT`] || (lodash.isNil(options.minTimeout) ? 1000 : options.minTimeout)
|
|
2615
|
-
};
|
|
2616
|
-
if (this.retrySettings.retries > 0) {
|
|
2617
|
-
debug$j(`Retry for ${section} is enabled. Settings: ${JSON.stringify(this.retrySettings)} Patterns: ${JSON.stringify(this.retryErrorPatterns.map(r => r.toString()))}`);
|
|
2618
|
-
}
|
|
2619
|
-
}
|
|
2620
|
-
shouldRetry(err) {
|
|
2621
|
-
if (!err) return false;
|
|
2622
|
-
if (this.retryErrorPatterns.length === 0) return true;
|
|
2623
|
-
const errString = util.inspect(err);
|
|
2624
|
-
for (const re of this.retryErrorPatterns) {
|
|
2625
|
-
if (errString.match(re)) return true;
|
|
2626
|
-
}
|
|
2627
|
-
return false;
|
|
2628
|
-
}
|
|
2629
|
-
};
|
|
2630
|
-
|
|
2631
|
-
const debug$i = debug$n('botium-core-Convo');
|
|
2599
|
+
const debug$j = debug$n('botium-core-Convo');
|
|
2632
2600
|
const {
|
|
2633
2601
|
BotiumError: BotiumError$4,
|
|
2634
2602
|
botiumErrorFromErr: botiumErrorFromErr$1,
|
|
@@ -2782,10 +2750,10 @@ class TranscriptError extends Error {
|
|
|
2782
2750
|
class Convo$6 {
|
|
2783
2751
|
constructor(context, fromJson = {}) {
|
|
2784
2752
|
if (fromJson instanceof Convo$6) {
|
|
2785
|
-
debug$
|
|
2753
|
+
debug$j('Illegal state!!! Parameter should be a JSON, but it is a Convo');
|
|
2786
2754
|
} else if (fromJson.beginAsserter) {
|
|
2787
2755
|
// beginAsserter is one of the fields which are lost
|
|
2788
|
-
debug$
|
|
2756
|
+
debug$j('Illegal state!!! Parameter should be a native JSON, but looks as a Convo converted to JSON');
|
|
2789
2757
|
}
|
|
2790
2758
|
this.scriptingEvents = context.scriptingEvents;
|
|
2791
2759
|
this.context = context;
|
|
@@ -2830,30 +2798,6 @@ class Convo$6 {
|
|
|
2830
2798
|
return this.header.toString() + (this.sourceTag ? ` (${util.inspect(this.sourceTag)})` : '') + ': ' + this.conversation.map(c => c.toString()).join(' | ');
|
|
2831
2799
|
}
|
|
2832
2800
|
async Run(container) {
|
|
2833
|
-
if (container.caps.RETRY_CONVO_ASYNC) {
|
|
2834
|
-
return this.RunImpl(container).catch(err => {
|
|
2835
|
-
debug$i(`Convo failed with error "${err.message || JSON.stringify(err)}".`);
|
|
2836
|
-
throw err;
|
|
2837
|
-
});
|
|
2838
|
-
} else {
|
|
2839
|
-
const retryHelper = new RetryHelper_1(container.caps, 'CONVO');
|
|
2840
|
-
return promiseRetry(async (retry, number) => {
|
|
2841
|
-
const retryRemaining = retryHelper.retrySettings.retries - number + 1;
|
|
2842
|
-
return this.RunImpl(container).catch(err => {
|
|
2843
|
-
if (retryHelper.shouldRetry(err)) {
|
|
2844
|
-
debug$i(`Convo failed with error "${err.message || JSON.stringify(err)}". Retry ${retryRemaining > 0 ? 'enabled' : 'disabled'} (remaining #${retryRemaining}/${retryHelper.retrySettings.retries}, criterion matches)`);
|
|
2845
|
-
retry(err);
|
|
2846
|
-
} else {
|
|
2847
|
-
if (retryHelper.retryErrorPatterns.length > 0) {
|
|
2848
|
-
debug$i(`Convo failed with error "${err.message || JSON.stringify(err)}". Retry 'disabled' (remaining (#${retryRemaining}/${retryHelper.retrySettings.retries}), criterion does not match)`);
|
|
2849
|
-
}
|
|
2850
|
-
throw err;
|
|
2851
|
-
}
|
|
2852
|
-
});
|
|
2853
|
-
}, retryHelper.retrySettings);
|
|
2854
|
-
}
|
|
2855
|
-
}
|
|
2856
|
-
async RunImpl(container) {
|
|
2857
2801
|
const transcript = new Transcript({
|
|
2858
2802
|
steps: [],
|
|
2859
2803
|
attachments: [],
|
|
@@ -2959,6 +2903,7 @@ class Convo$6 {
|
|
|
2959
2903
|
for (let i = 0; i < this.conversation.length; i++) {
|
|
2960
2904
|
const convoStep = this.conversation[i];
|
|
2961
2905
|
const currentStepIndex = i;
|
|
2906
|
+
container.eventEmitter.emit(Events.CONVO_STEP_NEXT, container, convoStep, i);
|
|
2962
2907
|
skipTranscriptStep = false;
|
|
2963
2908
|
const transcriptStep = new TranscriptStep({
|
|
2964
2909
|
expected: new BotiumMockMessage_1(convoStep),
|
|
@@ -3018,7 +2963,7 @@ class Convo$6 {
|
|
|
3018
2963
|
});
|
|
3019
2964
|
await this._checkBotRepliesConsumed(container);
|
|
3020
2965
|
const coreMsg = lodash.omit(removeBuffers(meMsg), ['sourceData']);
|
|
3021
|
-
debug$
|
|
2966
|
+
debug$j(`${this.header.name}/${convoStep.stepTag}: user says (cleaned by binary and base64 data and sourceData) ${JSON.stringify(coreMsg, null, 2)}`);
|
|
3022
2967
|
await new Promise(resolve => {
|
|
3023
2968
|
if (container.caps.SIMULATE_WRITING_SPEED && meMsg.messageText && meMsg.messageText.length) {
|
|
3024
2969
|
setTimeout(() => resolve(), container.caps.SIMULATE_WRITING_SPEED * meMsg.messageText.length);
|
|
@@ -3054,7 +2999,7 @@ class Convo$6 {
|
|
|
3054
2999
|
});
|
|
3055
3000
|
continue;
|
|
3056
3001
|
} else {
|
|
3057
|
-
debug$
|
|
3002
|
+
debug$j(`${this.header.name}/${convoStep.stepTag}: message not found in #me section, message not sent to container ${util.inspect(convoStep)}`);
|
|
3058
3003
|
transcriptStep.botEnd = new Date();
|
|
3059
3004
|
await this.scriptingEvents.onMeEnd({
|
|
3060
3005
|
convo: this,
|
|
@@ -3070,7 +3015,7 @@ class Convo$6 {
|
|
|
3070
3015
|
} catch (err) {
|
|
3071
3016
|
transcriptStep.botEnd = new Date();
|
|
3072
3017
|
const failErr = botiumErrorFromErr$1(`${this.header.name}/${convoStep.stepTag}: error sending to bot - ${err.message || err}`, err);
|
|
3073
|
-
debug$
|
|
3018
|
+
debug$j(failErr);
|
|
3074
3019
|
try {
|
|
3075
3020
|
this.scriptingEvents.fail && this.scriptingEvents.fail(failErr);
|
|
3076
3021
|
} catch (failErr) {}
|
|
@@ -3083,7 +3028,7 @@ class Convo$6 {
|
|
|
3083
3028
|
waitForBotSays = true;
|
|
3084
3029
|
}
|
|
3085
3030
|
try {
|
|
3086
|
-
debug$
|
|
3031
|
+
debug$j(`${this.header.name} wait for bot ${convoStep.channel || ''}`);
|
|
3087
3032
|
await this.scriptingEvents.onBotStart({
|
|
3088
3033
|
convo: this,
|
|
3089
3034
|
convoStep,
|
|
@@ -3099,11 +3044,11 @@ class Convo$6 {
|
|
|
3099
3044
|
transcriptStep.botEnd = new Date();
|
|
3100
3045
|
transcriptStep.actual = new BotiumMockMessage_1(botMsg);
|
|
3101
3046
|
const coreMsg = lodash.omit(removeBuffers(botMsg), ['sourceData']);
|
|
3102
|
-
debug$
|
|
3047
|
+
debug$j(`${this.header.name}: bot says (cleaned by binary and base64 data and sourceData) ${JSON.stringify(coreMsg, null, 2)}`);
|
|
3103
3048
|
} catch (err) {
|
|
3104
3049
|
transcriptStep.botEnd = new Date();
|
|
3105
3050
|
const failErr = botiumErrorFromErr$1(`${this.header.name}/${convoStep.stepTag}: error waiting for bot - ${err.message}`, err);
|
|
3106
|
-
debug$
|
|
3051
|
+
debug$j(failErr);
|
|
3107
3052
|
try {
|
|
3108
3053
|
this.scriptingEvents.fail && this.scriptingEvents.fail(failErr, lastMeConvoStep);
|
|
3109
3054
|
} catch (failErr) {}
|
|
@@ -3122,11 +3067,11 @@ class Convo$6 {
|
|
|
3122
3067
|
if (prepared) {
|
|
3123
3068
|
transcriptStep.actual = new BotiumMockMessage_1(botMsg);
|
|
3124
3069
|
const coreMsg = lodash.omit(removeBuffers(botMsg), ['sourceData']);
|
|
3125
|
-
debug$
|
|
3070
|
+
debug$j(`${this.header.name}: onBotPrepare (cleaned by binary and base64 data and sourceData) ${JSON.stringify(coreMsg, null, 2)}`);
|
|
3126
3071
|
}
|
|
3127
3072
|
} catch (err) {
|
|
3128
3073
|
const failErr = botiumErrorFromErr$1(`${this.header.name}/${convoStep.stepTag}: onBotPrepare error - ${err.message || err}`, err);
|
|
3129
|
-
debug$
|
|
3074
|
+
debug$j(failErr);
|
|
3130
3075
|
try {
|
|
3131
3076
|
this.scriptingEvents.fail && this.scriptingEvents.fail(failErr, lastMeConvoStep);
|
|
3132
3077
|
} catch (failErr) {}
|
|
@@ -3134,7 +3079,7 @@ class Convo$6 {
|
|
|
3134
3079
|
}
|
|
3135
3080
|
if (!botMsg || !botMsg.messageText && !botMsg.media && !botMsg.buttons && !botMsg.cards && !botMsg.sourceData && !botMsg.nlp) {
|
|
3136
3081
|
const failErr = new BotiumError$4(`${this.header.name}/${convoStep.stepTag}: bot says nothing`);
|
|
3137
|
-
debug$
|
|
3082
|
+
debug$j(failErr);
|
|
3138
3083
|
try {
|
|
3139
3084
|
this.scriptingEvents.fail && this.scriptingEvents.fail(failErr, lastMeConvoStep);
|
|
3140
3085
|
} catch (failErr) {}
|
|
@@ -3215,7 +3160,7 @@ class Convo$6 {
|
|
|
3215
3160
|
continue;
|
|
3216
3161
|
}
|
|
3217
3162
|
const failErr = botiumErrorFromErr$1(`${this.header.name}/${convoStep.stepTag}: assertion error - ${err.message || err}`, err);
|
|
3218
|
-
debug$
|
|
3163
|
+
debug$j(failErr);
|
|
3219
3164
|
try {
|
|
3220
3165
|
this.scriptingEvents.fail && this.scriptingEvents.fail(failErr, lastMeConvoStep);
|
|
3221
3166
|
} catch (failErr) {}
|
|
@@ -3236,7 +3181,7 @@ class Convo$6 {
|
|
|
3236
3181
|
}
|
|
3237
3182
|
} else {
|
|
3238
3183
|
const failErr = new BotiumError$4(`${this.header.name}/${convoStep.stepTag}: invalid sender - ${util.inspect(convoStep.sender)}`);
|
|
3239
|
-
debug$
|
|
3184
|
+
debug$j(failErr);
|
|
3240
3185
|
try {
|
|
3241
3186
|
this.scriptingEvents.fail && this.scriptingEvents.fail(failErr);
|
|
3242
3187
|
} catch (failErr) {}
|
|
@@ -3442,7 +3387,7 @@ class Convo$6 {
|
|
|
3442
3387
|
throw new BotiumError$4(`Cant find partial convo with name ${includeLogicHook} (available partial convos: ${Object.keys(partialConvos).join(',')})`);
|
|
3443
3388
|
}
|
|
3444
3389
|
_getEffectiveConversationRecursive(partialConvo.conversation, [...parentPConvos, includeLogicHook], result, true);
|
|
3445
|
-
debug$
|
|
3390
|
+
debug$j(`Partial convo ${includeLogicHook} included`);
|
|
3446
3391
|
});
|
|
3447
3392
|
});
|
|
3448
3393
|
return result;
|
|
@@ -3463,10 +3408,48 @@ var Convo_1 = {
|
|
|
3463
3408
|
TranscriptError
|
|
3464
3409
|
};
|
|
3465
3410
|
|
|
3411
|
+
const debug$i = debug$n('botium-core-RetryHelper');
|
|
3412
|
+
var RetryHelper_1 = class RetryHelper {
|
|
3413
|
+
constructor(caps, section, options = {}) {
|
|
3414
|
+
this.retryErrorPatterns = [];
|
|
3415
|
+
const onErrorRegexp = caps[`RETRY_${section.toUpperCase()}_ONERROR_REGEXP`] || [];
|
|
3416
|
+
if (onErrorRegexp) {
|
|
3417
|
+
if (lodash.isArray(onErrorRegexp)) {
|
|
3418
|
+
onErrorRegexp.forEach(r => {
|
|
3419
|
+
if (lodash.isString(r)) this.retryErrorPatterns.push(new RegExp(r, 'i'));else this.retryErrorPatterns.push(r);
|
|
3420
|
+
});
|
|
3421
|
+
} else if (lodash.isString(onErrorRegexp)) {
|
|
3422
|
+
this.retryErrorPatterns.push(new RegExp(onErrorRegexp, 'i'));
|
|
3423
|
+
} else {
|
|
3424
|
+
this.retryErrorPatterns.push(onErrorRegexp);
|
|
3425
|
+
}
|
|
3426
|
+
}
|
|
3427
|
+
|
|
3428
|
+
// to turn on retries, NUMRETRIES or ONERROR_REGEXP has to be set
|
|
3429
|
+
this.retrySettings = {
|
|
3430
|
+
retries: caps[`RETRY_${section.toUpperCase()}_NUMRETRIES`] || (!lodash.isNil(options.numRetries) ? options.numRetries : this.retryErrorPatterns.length === 0 ? 0 : 1),
|
|
3431
|
+
factor: caps[`RETRY_${section.toUpperCase()}_FACTOR`] || (lodash.isNil(options.factor) ? 1 : options.factor),
|
|
3432
|
+
minTimeout: caps[`RETRY_${section.toUpperCase()}_MINTIMEOUT`] || (lodash.isNil(options.minTimeout) ? 1000 : options.minTimeout)
|
|
3433
|
+
};
|
|
3434
|
+
if (this.retrySettings.retries > 0) {
|
|
3435
|
+
debug$i(`Retry for ${section} is enabled. Settings: ${JSON.stringify(this.retrySettings)} Patterns: ${JSON.stringify(this.retryErrorPatterns.map(r => r.toString()))}`);
|
|
3436
|
+
}
|
|
3437
|
+
}
|
|
3438
|
+
shouldRetry(err) {
|
|
3439
|
+
if (!err) return false;
|
|
3440
|
+
if (this.retryErrorPatterns.length === 0) return true;
|
|
3441
|
+
const errString = util.inspect(err);
|
|
3442
|
+
for (const re of this.retryErrorPatterns) {
|
|
3443
|
+
if (errString.match(re)) return true;
|
|
3444
|
+
}
|
|
3445
|
+
return false;
|
|
3446
|
+
}
|
|
3447
|
+
};
|
|
3448
|
+
|
|
3466
3449
|
const {
|
|
3467
3450
|
toString,
|
|
3468
3451
|
quoteRegexpString,
|
|
3469
|
-
calculateWer
|
|
3452
|
+
calculateWer: calculateWer$1
|
|
3470
3453
|
} = helper;
|
|
3471
3454
|
const _normalize = botresponse => {
|
|
3472
3455
|
if (lodash.isUndefined(botresponse) || lodash.isNil(botresponse)) return '';
|
|
@@ -3534,7 +3517,7 @@ const wer = () => (botresponse, utterance, args) => {
|
|
|
3534
3517
|
botresponse = _normalize(botresponse || '');
|
|
3535
3518
|
utterance = toString(utterance || '');
|
|
3536
3519
|
const threshold = [',', '.'].find(p => `${args[0]}`.includes(p)) ? parseFloat(args[0]) : parseInt(args[0]) / 100;
|
|
3537
|
-
return calculateWer(botresponse, utterance) <= threshold;
|
|
3520
|
+
return calculateWer$1(botresponse, utterance) <= threshold;
|
|
3538
3521
|
};
|
|
3539
3522
|
const getMatchFunction$1 = matchingMode => {
|
|
3540
3523
|
if (matchingMode === 'regexp' || matchingMode === 'regexpIgnoreCase') {
|
|
@@ -5328,6 +5311,10 @@ const {
|
|
|
5328
5311
|
const {
|
|
5329
5312
|
getMatchFunction
|
|
5330
5313
|
} = MatchFunctions;
|
|
5314
|
+
const {
|
|
5315
|
+
calculateWer,
|
|
5316
|
+
toPercent
|
|
5317
|
+
} = helper;
|
|
5331
5318
|
const globPattern = '**/+(*.convo.txt|*.utterances.txt|*.pconvo.txt|*.scriptingmemory.txt|*.xlsx|*.xlsm|*.convo.csv|*.pconvo.csv|*.utterances.csv|*.yaml|*.yml|*.json|*.md|*.markdown)';
|
|
5332
5319
|
const skipPattern = /^skip[.\-_]/i;
|
|
5333
5320
|
const p = (retryHelper, fn) => {
|
|
@@ -5588,29 +5575,51 @@ var ScriptingProvider_1 = class ScriptingProvider {
|
|
|
5588
5575
|
const found = lodash.find(tomatch, utt => this.matchFn(botresponse, utt, this.caps[Capabilities.SCRIPTING_MATCHING_MODE_ARGS]));
|
|
5589
5576
|
const asserterType = this.caps[Capabilities.SCRIPTING_MATCHING_MODE] === 'wer' ? 'Word Error Rate Asserter' : 'Text Match Asserter';
|
|
5590
5577
|
if (lodash.isNil(found)) {
|
|
5591
|
-
|
|
5592
|
-
|
|
5593
|
-
|
|
5594
|
-
|
|
5595
|
-
|
|
5596
|
-
|
|
5597
|
-
|
|
5598
|
-
|
|
5599
|
-
|
|
5600
|
-
|
|
5601
|
-
|
|
5602
|
-
|
|
5603
|
-
|
|
5604
|
-
|
|
5605
|
-
|
|
5606
|
-
|
|
5607
|
-
|
|
5608
|
-
|
|
5609
|
-
|
|
5610
|
-
|
|
5611
|
-
|
|
5612
|
-
}
|
|
5613
|
-
|
|
5578
|
+
if (this.caps[Capabilities.SCRIPTING_MATCHING_MODE] === 'wer') {
|
|
5579
|
+
const wer = calculateWer(botresponse, tomatch[0]);
|
|
5580
|
+
const werArgs = this.caps[Capabilities.SCRIPTING_MATCHING_MODE_ARGS];
|
|
5581
|
+
const threshold = [',', '.'].find(p => `${werArgs[0]}`.includes(p)) ? parseFloat(werArgs[0]) : parseInt(werArgs[0]) / 100;
|
|
5582
|
+
const message = `${stepTag}: Word Error Rate (${toPercent(wer)}) higher than accepted (${toPercent(threshold)})`;
|
|
5583
|
+
throw new BotiumError$2(message, {
|
|
5584
|
+
type: 'asserter',
|
|
5585
|
+
source: asserterType,
|
|
5586
|
+
params: {
|
|
5587
|
+
matchingMode: this.caps[Capabilities.SCRIPTING_MATCHING_MODE],
|
|
5588
|
+
args: this.caps[Capabilities.SCRIPTING_MATCHING_MODE_ARGS] || null
|
|
5589
|
+
},
|
|
5590
|
+
context: {
|
|
5591
|
+
stepTag
|
|
5592
|
+
},
|
|
5593
|
+
cause: {
|
|
5594
|
+
expected: `<=${toPercent(threshold)} (${tomatch})`,
|
|
5595
|
+
actual: `${toPercent(wer)} (${botresponse})`
|
|
5596
|
+
}
|
|
5597
|
+
});
|
|
5598
|
+
} else {
|
|
5599
|
+
let message = `${stepTag}: Bot response `;
|
|
5600
|
+
message += meMsg ? `(on ${meMsg}) ` : '';
|
|
5601
|
+
message += botresponse ? '"' + botresponse + '"' : '<no response>';
|
|
5602
|
+
message += ' expected to match ';
|
|
5603
|
+
message += tomatch && tomatch.length > 1 ? 'one of ' : '';
|
|
5604
|
+
message += `${tomatch.map(e => e ? '"' + e + '"' : '<any response>').join(', ')}`;
|
|
5605
|
+
throw new BotiumError$2(message, {
|
|
5606
|
+
type: 'asserter',
|
|
5607
|
+
source: asserterType,
|
|
5608
|
+
params: {
|
|
5609
|
+
matchingMode: this.caps[Capabilities.SCRIPTING_MATCHING_MODE],
|
|
5610
|
+
args: this.caps[Capabilities.SCRIPTING_MATCHING_MODE_ARGS] || null
|
|
5611
|
+
},
|
|
5612
|
+
context: {
|
|
5613
|
+
stepTag
|
|
5614
|
+
},
|
|
5615
|
+
cause: {
|
|
5616
|
+
expected: tomatch,
|
|
5617
|
+
actual: botresponse,
|
|
5618
|
+
matchingMode: this.caps[Capabilities.SCRIPTING_MATCHING_MODE],
|
|
5619
|
+
args: this.caps[Capabilities.SCRIPTING_MATCHING_MODE_ARGS] || null
|
|
5620
|
+
}
|
|
5621
|
+
});
|
|
5622
|
+
}
|
|
5614
5623
|
}
|
|
5615
5624
|
},
|
|
5616
5625
|
assertBotNotResponse: (botresponse, nottomatch, stepTag, meMsg) => {
|
|
@@ -5621,30 +5630,52 @@ var ScriptingProvider_1 = class ScriptingProvider {
|
|
|
5621
5630
|
const found = lodash.find(nottomatch, utt => this.matchFn(botresponse, utt, this.caps[Capabilities.SCRIPTING_MATCHING_MODE_ARGS]));
|
|
5622
5631
|
const asserterType = this.caps[Capabilities.SCRIPTING_MATCHING_MODE] === 'wer' ? 'Word Error Rate Asserter' : 'Text Match Asserter';
|
|
5623
5632
|
if (!lodash.isNil(found)) {
|
|
5624
|
-
|
|
5625
|
-
|
|
5626
|
-
|
|
5627
|
-
|
|
5628
|
-
|
|
5629
|
-
|
|
5630
|
-
|
|
5631
|
-
|
|
5632
|
-
|
|
5633
|
-
|
|
5634
|
-
|
|
5635
|
-
|
|
5636
|
-
|
|
5637
|
-
|
|
5638
|
-
|
|
5639
|
-
|
|
5640
|
-
|
|
5641
|
-
|
|
5642
|
-
|
|
5643
|
-
|
|
5644
|
-
|
|
5645
|
-
|
|
5646
|
-
}
|
|
5647
|
-
|
|
5633
|
+
if (this.caps[Capabilities.SCRIPTING_MATCHING_MODE] === 'wer') {
|
|
5634
|
+
const wer = calculateWer(botresponse, nottomatch[0]);
|
|
5635
|
+
const werArgs = this.caps[Capabilities.SCRIPTING_MATCHING_MODE_ARGS];
|
|
5636
|
+
const threshold = [',', '.'].find(p => `${werArgs[0]}`.includes(p)) ? parseFloat(werArgs[0]) : parseInt(werArgs[0]) / 100;
|
|
5637
|
+
const message = `${stepTag}: Word Error Rate (${toPercent(wer)}) lower than accepted (${toPercent(threshold)})`;
|
|
5638
|
+
throw new BotiumError$2(message, {
|
|
5639
|
+
type: 'asserter',
|
|
5640
|
+
source: asserterType,
|
|
5641
|
+
params: {
|
|
5642
|
+
matchingMode: this.caps[Capabilities.SCRIPTING_MATCHING_MODE],
|
|
5643
|
+
args: this.caps[Capabilities.SCRIPTING_MATCHING_MODE_ARGS] || null
|
|
5644
|
+
},
|
|
5645
|
+
context: {
|
|
5646
|
+
stepTag
|
|
5647
|
+
},
|
|
5648
|
+
cause: {
|
|
5649
|
+
expected: `>=${toPercent(threshold)} (${nottomatch})`,
|
|
5650
|
+
actual: `${toPercent(wer)} (${botresponse})`
|
|
5651
|
+
}
|
|
5652
|
+
});
|
|
5653
|
+
} else {
|
|
5654
|
+
let message = `${stepTag}: Bot response `;
|
|
5655
|
+
message += meMsg ? `(on ${meMsg}) ` : '';
|
|
5656
|
+
message += botresponse ? '"' + botresponse + '"' : '<no response>';
|
|
5657
|
+
message += ' expected NOT to match ';
|
|
5658
|
+
message += nottomatch && nottomatch.length > 1 ? 'one of ' : '';
|
|
5659
|
+
message += `${nottomatch.map(e => e ? '"' + e + '"' : '<any response>').join(', ')}`;
|
|
5660
|
+
throw new BotiumError$2(message, {
|
|
5661
|
+
type: 'asserter',
|
|
5662
|
+
source: asserterType,
|
|
5663
|
+
params: {
|
|
5664
|
+
matchingMode: this.caps[Capabilities.SCRIPTING_MATCHING_MODE],
|
|
5665
|
+
args: this.caps[Capabilities.SCRIPTING_MATCHING_MODE_ARGS] || null
|
|
5666
|
+
},
|
|
5667
|
+
context: {
|
|
5668
|
+
stepTag
|
|
5669
|
+
},
|
|
5670
|
+
cause: {
|
|
5671
|
+
not: true,
|
|
5672
|
+
expected: nottomatch,
|
|
5673
|
+
actual: botresponse,
|
|
5674
|
+
matchingMode: this.caps[Capabilities.SCRIPTING_MATCHING_MODE],
|
|
5675
|
+
args: this.caps[Capabilities.SCRIPTING_MATCHING_MODE_ARGS] || null
|
|
5676
|
+
}
|
|
5677
|
+
});
|
|
5678
|
+
}
|
|
5648
5679
|
}
|
|
5649
5680
|
},
|
|
5650
5681
|
fail: null
|
|
@@ -7115,6 +7146,9 @@ var Queue_1 = class Queue {
|
|
|
7115
7146
|
}
|
|
7116
7147
|
};
|
|
7117
7148
|
|
|
7149
|
+
const {
|
|
7150
|
+
rimraf: rimraf$1
|
|
7151
|
+
} = rimraf$2;
|
|
7118
7152
|
const debug$7 = debug$n('botium-connector-BaseContainer');
|
|
7119
7153
|
const {
|
|
7120
7154
|
executeHook: executeHook$1,
|
|
@@ -7247,10 +7281,7 @@ var BaseContainer_1 = class BaseContainer {
|
|
|
7247
7281
|
}, rimraffed => {
|
|
7248
7282
|
if (this.caps[Capabilities.CLEANUPTEMPDIR]) {
|
|
7249
7283
|
debug$7(`Cleanup rimrafing temp dir ${this.tempDirectory}`);
|
|
7250
|
-
rimraf(this.tempDirectory
|
|
7251
|
-
if (err) debug$7(`Cleanup temp dir ${this.tempDirectory} failed: ${util.inspect(err)}`);
|
|
7252
|
-
rimraffed();
|
|
7253
|
-
});
|
|
7284
|
+
rimraf$1(this.tempDirectory).catch(err => debug$7(`Cleanup temp dir ${this.tempDirectory} failed: ${util.inspect(err)}`)).finally(() => rimraffed());
|
|
7254
7285
|
} else {
|
|
7255
7286
|
rimraffed();
|
|
7256
7287
|
}
|
|
@@ -8641,13 +8672,9 @@ const {
|
|
|
8641
8672
|
var PluginConnectorContainer_1 = class PluginConnectorContainer extends BaseContainer_1 {
|
|
8642
8673
|
async Validate() {
|
|
8643
8674
|
await super.Validate();
|
|
8644
|
-
const setAsync = isAsync => {
|
|
8645
|
-
this.caps.RETRY_CONVO_ASYNC = isAsync;
|
|
8646
|
-
};
|
|
8647
8675
|
this.pluginInstance = tryLoadPlugin(this.caps[Capabilities.CONTAINERMODE], this.caps[Capabilities.PLUGINMODULEPATH], {
|
|
8648
8676
|
container: this,
|
|
8649
8677
|
queueBotSays: msg => this._QueueBotSays(msg),
|
|
8650
|
-
setAsync: isAsync => setAsync(isAsync),
|
|
8651
8678
|
bottleneck: this.bottleneck,
|
|
8652
8679
|
eventEmitter: this.eventEmitter,
|
|
8653
8680
|
caps: this.caps,
|
|
@@ -8778,15 +8805,21 @@ var PluginConnectorContainer_1 = class PluginConnectorContainer extends BaseCont
|
|
|
8778
8805
|
}
|
|
8779
8806
|
};
|
|
8780
8807
|
|
|
8781
|
-
var require$$
|
|
8808
|
+
var require$$4 = getCjsExportFromNamespace(_package$1);
|
|
8782
8809
|
|
|
8810
|
+
const {
|
|
8811
|
+
rimraf
|
|
8812
|
+
} = rimraf$2;
|
|
8813
|
+
const {
|
|
8814
|
+
mkdirpSync
|
|
8815
|
+
} = mkdirp;
|
|
8783
8816
|
const {
|
|
8784
8817
|
boolean
|
|
8785
8818
|
} = boolean$1;
|
|
8786
8819
|
const debug$1 = debug$n('botium-core-BotDriver');
|
|
8787
8820
|
const {
|
|
8788
8821
|
version
|
|
8789
|
-
} = require$$
|
|
8822
|
+
} = require$$4;
|
|
8790
8823
|
var BotDriver_1 = class BotDriver {
|
|
8791
8824
|
constructor(caps = {}, sources = {}, envs = {}) {
|
|
8792
8825
|
this.eventEmitter = new events();
|
|
@@ -8876,7 +8909,7 @@ var BotDriver_1 = class BotDriver {
|
|
|
8876
8909
|
}, tempDirectoryCreated => {
|
|
8877
8910
|
tempDirectory = path.resolve(process.cwd(), this.caps[Capabilities.TEMPDIR], sanitizeFilename(`${this.caps[Capabilities.PROJECTNAME]} ${moment().format('YYYYMMDD HHmmss')} ${randomatic('Aa0', 5)}`));
|
|
8878
8911
|
try {
|
|
8879
|
-
|
|
8912
|
+
mkdirpSync(tempDirectory);
|
|
8880
8913
|
tempDirectoryCreated();
|
|
8881
8914
|
} catch (err) {
|
|
8882
8915
|
tempDirectoryCreated(new Error(`Unable to create temp directory ${tempDirectory}: ${err.message}`));
|
|
@@ -8904,9 +8937,7 @@ var BotDriver_1 = class BotDriver {
|
|
|
8904
8937
|
debug$1(`BotDriver Build error: ${err}`);
|
|
8905
8938
|
this.eventEmitter.emit(Events.CONTAINER_BUILD_ERROR, err);
|
|
8906
8939
|
if (tempDirectory) {
|
|
8907
|
-
rimraf(tempDirectory
|
|
8908
|
-
if (err) debug$1(`Cleanup temp dir ${tempDirectory} failed: ${util.inspect(err)}`);
|
|
8909
|
-
});
|
|
8940
|
+
rimraf(tempDirectory).catch(err => debug$1(`Cleanup temp dir ${tempDirectory} failed: ${util.inspect(err)}`));
|
|
8910
8941
|
}
|
|
8911
8942
|
return reject(err);
|
|
8912
8943
|
}
|