botium-core 1.13.15 → 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 +221 -173
- package/dist/botium-cjs.js.map +1 -1
- package/dist/botium-es.js +213 -166
- package/dist/botium-es.js.map +1 -1
- package/index.js +2 -0
- package/package.json +23 -23
- package/src/BotDriver.js +4 -6
- package/src/Events.js +1 -0
- package/src/containers/BaseContainer.js +4 -5
- package/src/scripting/Convo.js +1 -20
- package/src/scripting/ScriptingProvider.js +102 -51
- package/src/scripting/helper.js +11 -4
- package/src/scripting/logichook/asserter/WerAsserter.js +53 -6
- package/test/scripting/txt/decompile.spec.js +27 -0
- 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",
|
|
@@ -812,6 +812,7 @@ var Events = {
|
|
|
812
812
|
CONTAINER_CLEANED: 'CONTAINER_CLEANED',
|
|
813
813
|
CONTAINER_CLEAN_ERROR: 'CONTAINER_CLEAN_ERROR',
|
|
814
814
|
BOT_CONNECTED: 'BOT_CONNECTED',
|
|
815
|
+
CONVO_STEP_NEXT: 'CONVO_STEP_NEXT',
|
|
815
816
|
// Chatbot Events
|
|
816
817
|
MESSAGE_SENTTOBOT: 'MESSAGE_SENTTOBOT',
|
|
817
818
|
MESSAGE_SENDTOBOT_ERROR: 'MESSAGE_SENDTOBOT_ERROR',
|
|
@@ -835,6 +836,7 @@ Events.CONTAINER_CLEANING;
|
|
|
835
836
|
Events.CONTAINER_CLEANED;
|
|
836
837
|
Events.CONTAINER_CLEAN_ERROR;
|
|
837
838
|
Events.BOT_CONNECTED;
|
|
839
|
+
Events.CONVO_STEP_NEXT;
|
|
838
840
|
Events.MESSAGE_SENTTOBOT;
|
|
839
841
|
Events.MESSAGE_SENDTOBOT_ERROR;
|
|
840
842
|
Events.MESSAGE_RECEIVEDFROMBOT;
|
|
@@ -1722,10 +1724,10 @@ const toString$3 = value => {
|
|
|
1722
1724
|
return '' + value;
|
|
1723
1725
|
};
|
|
1724
1726
|
const flatString = str => {
|
|
1725
|
-
return str
|
|
1727
|
+
return toString$3(str).split('\n').map(s => s.trim()).join(' ') || '';
|
|
1726
1728
|
};
|
|
1727
1729
|
const _formatAppendArgs = args => {
|
|
1728
|
-
return args
|
|
1730
|
+
return args && args.length > 0 && lodash.isArray(args) && ` ${args.map(a => lodash.isString(a) ? a.replace(/\|/g, '\\|') : `${a}`).join('|')}` || '';
|
|
1729
1731
|
};
|
|
1730
1732
|
const _parseArgs = str => {
|
|
1731
1733
|
return str && str.length > 0 && str.replace(/\\\|/g, '###ESCAPESPLIT###').split('|').map(s => s.replace(/###ESCAPESPLIT###/g, '|').trim()) || [];
|
|
@@ -2178,7 +2180,7 @@ const linesToScriptingMemories$2 = (lines, columnMode = null) => {
|
|
|
2178
2180
|
}
|
|
2179
2181
|
return scriptingMemories;
|
|
2180
2182
|
};
|
|
2181
|
-
const calculateWer$
|
|
2183
|
+
const calculateWer$2 = (str, pattern) => {
|
|
2182
2184
|
const _prepareString = (str, remWildcard = false) => {
|
|
2183
2185
|
if (remWildcard) return str.replace(/[.,/#!$%^&;:*{}=\-_`~()]/g, '').toLowerCase();
|
|
2184
2186
|
return str.replace(/[.,/#!$%^&;:{}=\-_`~()]/g, '').toLowerCase();
|
|
@@ -2201,6 +2203,11 @@ const calculateWer$1 = (str, pattern) => {
|
|
|
2201
2203
|
const botMessage = _prepareString(str);
|
|
2202
2204
|
const botMessageWords = botMessage.split(' ').map(bm => bm.trim());
|
|
2203
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
|
|
2204
2211
|
const errors = [];
|
|
2205
2212
|
for (let wildcardPart of utt.split('*')) {
|
|
2206
2213
|
let wer = 1;
|
|
@@ -2220,7 +2227,7 @@ const calculateWer$1 = (str, pattern) => {
|
|
|
2220
2227
|
}
|
|
2221
2228
|
}
|
|
2222
2229
|
if (lodash.isNil(subsetPhraseFound)) {
|
|
2223
|
-
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!');
|
|
2224
2231
|
}
|
|
2225
2232
|
errors.push(_getErrors(_getWords(wildcardPart), _getWords(subsetPhraseFound)));
|
|
2226
2233
|
}
|
|
@@ -2233,6 +2240,7 @@ const calculateWer$1 = (str, pattern) => {
|
|
|
2233
2240
|
debug$l(`Word Error Rate Asserter - Compared Bot Message '${botMessage}' / '${utt}': ${(errCount / allCount).toFixed(2)}`);
|
|
2234
2241
|
return (errCount / allCount).toFixed(2);
|
|
2235
2242
|
};
|
|
2243
|
+
const toPercent$1 = s => `${(s * 100).toFixed(0)}%`;
|
|
2236
2244
|
var helper = {
|
|
2237
2245
|
normalizeText: normalizeText$1,
|
|
2238
2246
|
splitStringInNonEmptyLines: splitStringInNonEmptyLines$1,
|
|
@@ -2247,7 +2255,8 @@ var helper = {
|
|
|
2247
2255
|
validateSender: validateSender$1,
|
|
2248
2256
|
validateConvo: validateConvo$2,
|
|
2249
2257
|
linesToScriptingMemories: linesToScriptingMemories$2,
|
|
2250
|
-
calculateWer: calculateWer$
|
|
2258
|
+
calculateWer: calculateWer$2,
|
|
2259
|
+
toPercent: toPercent$1
|
|
2251
2260
|
};
|
|
2252
2261
|
|
|
2253
2262
|
const debug$k = debug$n('botium-core-ScriptingMemory');
|
|
@@ -2587,45 +2596,7 @@ ScriptingMemory.extractVarNames;
|
|
|
2587
2596
|
ScriptingMemory.RESERVED_WORDS;
|
|
2588
2597
|
ScriptingMemory.SCRIPTING_FUNCTIONS;
|
|
2589
2598
|
|
|
2590
|
-
const debug$j = debug$n('botium-core-
|
|
2591
|
-
var RetryHelper_1 = class RetryHelper {
|
|
2592
|
-
constructor(caps, section, options = {}) {
|
|
2593
|
-
this.retryErrorPatterns = [];
|
|
2594
|
-
const onErrorRegexp = caps[`RETRY_${section.toUpperCase()}_ONERROR_REGEXP`] || [];
|
|
2595
|
-
if (onErrorRegexp) {
|
|
2596
|
-
if (lodash.isArray(onErrorRegexp)) {
|
|
2597
|
-
onErrorRegexp.forEach(r => {
|
|
2598
|
-
if (lodash.isString(r)) this.retryErrorPatterns.push(new RegExp(r, 'i'));else this.retryErrorPatterns.push(r);
|
|
2599
|
-
});
|
|
2600
|
-
} else if (lodash.isString(onErrorRegexp)) {
|
|
2601
|
-
this.retryErrorPatterns.push(new RegExp(onErrorRegexp, 'i'));
|
|
2602
|
-
} else {
|
|
2603
|
-
this.retryErrorPatterns.push(onErrorRegexp);
|
|
2604
|
-
}
|
|
2605
|
-
}
|
|
2606
|
-
|
|
2607
|
-
// to turn on retries, NUMRETRIES or ONERROR_REGEXP has to be set
|
|
2608
|
-
this.retrySettings = {
|
|
2609
|
-
retries: caps[`RETRY_${section.toUpperCase()}_NUMRETRIES`] || (!lodash.isNil(options.numRetries) ? options.numRetries : this.retryErrorPatterns.length === 0 ? 0 : 1),
|
|
2610
|
-
factor: caps[`RETRY_${section.toUpperCase()}_FACTOR`] || (lodash.isNil(options.factor) ? 1 : options.factor),
|
|
2611
|
-
minTimeout: caps[`RETRY_${section.toUpperCase()}_MINTIMEOUT`] || (lodash.isNil(options.minTimeout) ? 1000 : options.minTimeout)
|
|
2612
|
-
};
|
|
2613
|
-
if (this.retrySettings.retries > 0) {
|
|
2614
|
-
debug$j(`Retry for ${section} is enabled. Settings: ${JSON.stringify(this.retrySettings)} Patterns: ${JSON.stringify(this.retryErrorPatterns.map(r => r.toString()))}`);
|
|
2615
|
-
}
|
|
2616
|
-
}
|
|
2617
|
-
shouldRetry(err) {
|
|
2618
|
-
if (!err) return false;
|
|
2619
|
-
if (this.retryErrorPatterns.length === 0) return true;
|
|
2620
|
-
const errString = util.inspect(err);
|
|
2621
|
-
for (const re of this.retryErrorPatterns) {
|
|
2622
|
-
if (errString.match(re)) return true;
|
|
2623
|
-
}
|
|
2624
|
-
return false;
|
|
2625
|
-
}
|
|
2626
|
-
};
|
|
2627
|
-
|
|
2628
|
-
const debug$i = debug$n('botium-core-Convo');
|
|
2599
|
+
const debug$j = debug$n('botium-core-Convo');
|
|
2629
2600
|
const {
|
|
2630
2601
|
BotiumError: BotiumError$4,
|
|
2631
2602
|
botiumErrorFromErr: botiumErrorFromErr$1,
|
|
@@ -2779,10 +2750,10 @@ class TranscriptError extends Error {
|
|
|
2779
2750
|
class Convo$6 {
|
|
2780
2751
|
constructor(context, fromJson = {}) {
|
|
2781
2752
|
if (fromJson instanceof Convo$6) {
|
|
2782
|
-
debug$
|
|
2753
|
+
debug$j('Illegal state!!! Parameter should be a JSON, but it is a Convo');
|
|
2783
2754
|
} else if (fromJson.beginAsserter) {
|
|
2784
2755
|
// beginAsserter is one of the fields which are lost
|
|
2785
|
-
debug$
|
|
2756
|
+
debug$j('Illegal state!!! Parameter should be a native JSON, but looks as a Convo converted to JSON');
|
|
2786
2757
|
}
|
|
2787
2758
|
this.scriptingEvents = context.scriptingEvents;
|
|
2788
2759
|
this.context = context;
|
|
@@ -2827,23 +2798,6 @@ class Convo$6 {
|
|
|
2827
2798
|
return this.header.toString() + (this.sourceTag ? ` (${util.inspect(this.sourceTag)})` : '') + ': ' + this.conversation.map(c => c.toString()).join(' | ');
|
|
2828
2799
|
}
|
|
2829
2800
|
async Run(container) {
|
|
2830
|
-
const retryHelper = new RetryHelper_1(container.caps, 'CONVO');
|
|
2831
|
-
return promiseRetry(async (retry, number) => {
|
|
2832
|
-
return this.RunImpl(container).catch(err => {
|
|
2833
|
-
const retryRemaining = retryHelper.retrySettings.retries - number + 1;
|
|
2834
|
-
if (retryHelper.shouldRetry(err)) {
|
|
2835
|
-
debug$i(`Convo failed with error "${err.message || JSON.stringify(err)}". Retry ${retryRemaining > 0 ? 'enabled' : 'disabled'} (remaining #${retryRemaining}/${retryHelper.retrySettings.retries}, criterion matches)`);
|
|
2836
|
-
retry(err);
|
|
2837
|
-
} else {
|
|
2838
|
-
if (retryHelper.retryErrorPatterns.length > 0) {
|
|
2839
|
-
debug$i(`Convo failed with error "${err.message || JSON.stringify(err)}". Retry 'disabled' (remaining (#${retryRemaining}/${retryHelper.retrySettings.retries}), criterion does not match)`);
|
|
2840
|
-
}
|
|
2841
|
-
throw err;
|
|
2842
|
-
}
|
|
2843
|
-
});
|
|
2844
|
-
}, retryHelper.retrySettings);
|
|
2845
|
-
}
|
|
2846
|
-
async RunImpl(container) {
|
|
2847
2801
|
const transcript = new Transcript({
|
|
2848
2802
|
steps: [],
|
|
2849
2803
|
attachments: [],
|
|
@@ -2949,6 +2903,7 @@ class Convo$6 {
|
|
|
2949
2903
|
for (let i = 0; i < this.conversation.length; i++) {
|
|
2950
2904
|
const convoStep = this.conversation[i];
|
|
2951
2905
|
const currentStepIndex = i;
|
|
2906
|
+
container.eventEmitter.emit(Events.CONVO_STEP_NEXT, container, convoStep, i);
|
|
2952
2907
|
skipTranscriptStep = false;
|
|
2953
2908
|
const transcriptStep = new TranscriptStep({
|
|
2954
2909
|
expected: new BotiumMockMessage_1(convoStep),
|
|
@@ -3008,7 +2963,7 @@ class Convo$6 {
|
|
|
3008
2963
|
});
|
|
3009
2964
|
await this._checkBotRepliesConsumed(container);
|
|
3010
2965
|
const coreMsg = lodash.omit(removeBuffers(meMsg), ['sourceData']);
|
|
3011
|
-
debug$
|
|
2966
|
+
debug$j(`${this.header.name}/${convoStep.stepTag}: user says (cleaned by binary and base64 data and sourceData) ${JSON.stringify(coreMsg, null, 2)}`);
|
|
3012
2967
|
await new Promise(resolve => {
|
|
3013
2968
|
if (container.caps.SIMULATE_WRITING_SPEED && meMsg.messageText && meMsg.messageText.length) {
|
|
3014
2969
|
setTimeout(() => resolve(), container.caps.SIMULATE_WRITING_SPEED * meMsg.messageText.length);
|
|
@@ -3044,7 +2999,7 @@ class Convo$6 {
|
|
|
3044
2999
|
});
|
|
3045
3000
|
continue;
|
|
3046
3001
|
} else {
|
|
3047
|
-
debug$
|
|
3002
|
+
debug$j(`${this.header.name}/${convoStep.stepTag}: message not found in #me section, message not sent to container ${util.inspect(convoStep)}`);
|
|
3048
3003
|
transcriptStep.botEnd = new Date();
|
|
3049
3004
|
await this.scriptingEvents.onMeEnd({
|
|
3050
3005
|
convo: this,
|
|
@@ -3060,7 +3015,7 @@ class Convo$6 {
|
|
|
3060
3015
|
} catch (err) {
|
|
3061
3016
|
transcriptStep.botEnd = new Date();
|
|
3062
3017
|
const failErr = botiumErrorFromErr$1(`${this.header.name}/${convoStep.stepTag}: error sending to bot - ${err.message || err}`, err);
|
|
3063
|
-
debug$
|
|
3018
|
+
debug$j(failErr);
|
|
3064
3019
|
try {
|
|
3065
3020
|
this.scriptingEvents.fail && this.scriptingEvents.fail(failErr);
|
|
3066
3021
|
} catch (failErr) {}
|
|
@@ -3073,7 +3028,7 @@ class Convo$6 {
|
|
|
3073
3028
|
waitForBotSays = true;
|
|
3074
3029
|
}
|
|
3075
3030
|
try {
|
|
3076
|
-
debug$
|
|
3031
|
+
debug$j(`${this.header.name} wait for bot ${convoStep.channel || ''}`);
|
|
3077
3032
|
await this.scriptingEvents.onBotStart({
|
|
3078
3033
|
convo: this,
|
|
3079
3034
|
convoStep,
|
|
@@ -3089,11 +3044,11 @@ class Convo$6 {
|
|
|
3089
3044
|
transcriptStep.botEnd = new Date();
|
|
3090
3045
|
transcriptStep.actual = new BotiumMockMessage_1(botMsg);
|
|
3091
3046
|
const coreMsg = lodash.omit(removeBuffers(botMsg), ['sourceData']);
|
|
3092
|
-
debug$
|
|
3047
|
+
debug$j(`${this.header.name}: bot says (cleaned by binary and base64 data and sourceData) ${JSON.stringify(coreMsg, null, 2)}`);
|
|
3093
3048
|
} catch (err) {
|
|
3094
3049
|
transcriptStep.botEnd = new Date();
|
|
3095
3050
|
const failErr = botiumErrorFromErr$1(`${this.header.name}/${convoStep.stepTag}: error waiting for bot - ${err.message}`, err);
|
|
3096
|
-
debug$
|
|
3051
|
+
debug$j(failErr);
|
|
3097
3052
|
try {
|
|
3098
3053
|
this.scriptingEvents.fail && this.scriptingEvents.fail(failErr, lastMeConvoStep);
|
|
3099
3054
|
} catch (failErr) {}
|
|
@@ -3112,11 +3067,11 @@ class Convo$6 {
|
|
|
3112
3067
|
if (prepared) {
|
|
3113
3068
|
transcriptStep.actual = new BotiumMockMessage_1(botMsg);
|
|
3114
3069
|
const coreMsg = lodash.omit(removeBuffers(botMsg), ['sourceData']);
|
|
3115
|
-
debug$
|
|
3070
|
+
debug$j(`${this.header.name}: onBotPrepare (cleaned by binary and base64 data and sourceData) ${JSON.stringify(coreMsg, null, 2)}`);
|
|
3116
3071
|
}
|
|
3117
3072
|
} catch (err) {
|
|
3118
3073
|
const failErr = botiumErrorFromErr$1(`${this.header.name}/${convoStep.stepTag}: onBotPrepare error - ${err.message || err}`, err);
|
|
3119
|
-
debug$
|
|
3074
|
+
debug$j(failErr);
|
|
3120
3075
|
try {
|
|
3121
3076
|
this.scriptingEvents.fail && this.scriptingEvents.fail(failErr, lastMeConvoStep);
|
|
3122
3077
|
} catch (failErr) {}
|
|
@@ -3124,7 +3079,7 @@ class Convo$6 {
|
|
|
3124
3079
|
}
|
|
3125
3080
|
if (!botMsg || !botMsg.messageText && !botMsg.media && !botMsg.buttons && !botMsg.cards && !botMsg.sourceData && !botMsg.nlp) {
|
|
3126
3081
|
const failErr = new BotiumError$4(`${this.header.name}/${convoStep.stepTag}: bot says nothing`);
|
|
3127
|
-
debug$
|
|
3082
|
+
debug$j(failErr);
|
|
3128
3083
|
try {
|
|
3129
3084
|
this.scriptingEvents.fail && this.scriptingEvents.fail(failErr, lastMeConvoStep);
|
|
3130
3085
|
} catch (failErr) {}
|
|
@@ -3205,7 +3160,7 @@ class Convo$6 {
|
|
|
3205
3160
|
continue;
|
|
3206
3161
|
}
|
|
3207
3162
|
const failErr = botiumErrorFromErr$1(`${this.header.name}/${convoStep.stepTag}: assertion error - ${err.message || err}`, err);
|
|
3208
|
-
debug$
|
|
3163
|
+
debug$j(failErr);
|
|
3209
3164
|
try {
|
|
3210
3165
|
this.scriptingEvents.fail && this.scriptingEvents.fail(failErr, lastMeConvoStep);
|
|
3211
3166
|
} catch (failErr) {}
|
|
@@ -3226,7 +3181,7 @@ class Convo$6 {
|
|
|
3226
3181
|
}
|
|
3227
3182
|
} else {
|
|
3228
3183
|
const failErr = new BotiumError$4(`${this.header.name}/${convoStep.stepTag}: invalid sender - ${util.inspect(convoStep.sender)}`);
|
|
3229
|
-
debug$
|
|
3184
|
+
debug$j(failErr);
|
|
3230
3185
|
try {
|
|
3231
3186
|
this.scriptingEvents.fail && this.scriptingEvents.fail(failErr);
|
|
3232
3187
|
} catch (failErr) {}
|
|
@@ -3432,7 +3387,7 @@ class Convo$6 {
|
|
|
3432
3387
|
throw new BotiumError$4(`Cant find partial convo with name ${includeLogicHook} (available partial convos: ${Object.keys(partialConvos).join(',')})`);
|
|
3433
3388
|
}
|
|
3434
3389
|
_getEffectiveConversationRecursive(partialConvo.conversation, [...parentPConvos, includeLogicHook], result, true);
|
|
3435
|
-
debug$
|
|
3390
|
+
debug$j(`Partial convo ${includeLogicHook} included`);
|
|
3436
3391
|
});
|
|
3437
3392
|
});
|
|
3438
3393
|
return result;
|
|
@@ -3453,10 +3408,48 @@ var Convo_1 = {
|
|
|
3453
3408
|
TranscriptError
|
|
3454
3409
|
};
|
|
3455
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
|
+
|
|
3456
3449
|
const {
|
|
3457
3450
|
toString,
|
|
3458
3451
|
quoteRegexpString,
|
|
3459
|
-
calculateWer
|
|
3452
|
+
calculateWer: calculateWer$1
|
|
3460
3453
|
} = helper;
|
|
3461
3454
|
const _normalize = botresponse => {
|
|
3462
3455
|
if (lodash.isUndefined(botresponse) || lodash.isNil(botresponse)) return '';
|
|
@@ -3524,7 +3517,7 @@ const wer = () => (botresponse, utterance, args) => {
|
|
|
3524
3517
|
botresponse = _normalize(botresponse || '');
|
|
3525
3518
|
utterance = toString(utterance || '');
|
|
3526
3519
|
const threshold = [',', '.'].find(p => `${args[0]}`.includes(p)) ? parseFloat(args[0]) : parseInt(args[0]) / 100;
|
|
3527
|
-
return calculateWer(botresponse, utterance) <= threshold;
|
|
3520
|
+
return calculateWer$1(botresponse, utterance) <= threshold;
|
|
3528
3521
|
};
|
|
3529
3522
|
const getMatchFunction$1 = matchingMode => {
|
|
3530
3523
|
if (matchingMode === 'regexp' || matchingMode === 'regexpIgnoreCase') {
|
|
@@ -5318,6 +5311,10 @@ const {
|
|
|
5318
5311
|
const {
|
|
5319
5312
|
getMatchFunction
|
|
5320
5313
|
} = MatchFunctions;
|
|
5314
|
+
const {
|
|
5315
|
+
calculateWer,
|
|
5316
|
+
toPercent
|
|
5317
|
+
} = helper;
|
|
5321
5318
|
const globPattern = '**/+(*.convo.txt|*.utterances.txt|*.pconvo.txt|*.scriptingmemory.txt|*.xlsx|*.xlsm|*.convo.csv|*.pconvo.csv|*.utterances.csv|*.yaml|*.yml|*.json|*.md|*.markdown)';
|
|
5322
5319
|
const skipPattern = /^skip[.\-_]/i;
|
|
5323
5320
|
const p = (retryHelper, fn) => {
|
|
@@ -5578,29 +5575,51 @@ var ScriptingProvider_1 = class ScriptingProvider {
|
|
|
5578
5575
|
const found = lodash.find(tomatch, utt => this.matchFn(botresponse, utt, this.caps[Capabilities.SCRIPTING_MATCHING_MODE_ARGS]));
|
|
5579
5576
|
const asserterType = this.caps[Capabilities.SCRIPTING_MATCHING_MODE] === 'wer' ? 'Word Error Rate Asserter' : 'Text Match Asserter';
|
|
5580
5577
|
if (lodash.isNil(found)) {
|
|
5581
|
-
|
|
5582
|
-
|
|
5583
|
-
|
|
5584
|
-
|
|
5585
|
-
|
|
5586
|
-
|
|
5587
|
-
|
|
5588
|
-
|
|
5589
|
-
|
|
5590
|
-
|
|
5591
|
-
|
|
5592
|
-
|
|
5593
|
-
|
|
5594
|
-
|
|
5595
|
-
|
|
5596
|
-
|
|
5597
|
-
|
|
5598
|
-
|
|
5599
|
-
|
|
5600
|
-
|
|
5601
|
-
|
|
5602
|
-
}
|
|
5603
|
-
|
|
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
|
+
}
|
|
5604
5623
|
}
|
|
5605
5624
|
},
|
|
5606
5625
|
assertBotNotResponse: (botresponse, nottomatch, stepTag, meMsg) => {
|
|
@@ -5611,30 +5630,52 @@ var ScriptingProvider_1 = class ScriptingProvider {
|
|
|
5611
5630
|
const found = lodash.find(nottomatch, utt => this.matchFn(botresponse, utt, this.caps[Capabilities.SCRIPTING_MATCHING_MODE_ARGS]));
|
|
5612
5631
|
const asserterType = this.caps[Capabilities.SCRIPTING_MATCHING_MODE] === 'wer' ? 'Word Error Rate Asserter' : 'Text Match Asserter';
|
|
5613
5632
|
if (!lodash.isNil(found)) {
|
|
5614
|
-
|
|
5615
|
-
|
|
5616
|
-
|
|
5617
|
-
|
|
5618
|
-
|
|
5619
|
-
|
|
5620
|
-
|
|
5621
|
-
|
|
5622
|
-
|
|
5623
|
-
|
|
5624
|
-
|
|
5625
|
-
|
|
5626
|
-
|
|
5627
|
-
|
|
5628
|
-
|
|
5629
|
-
|
|
5630
|
-
|
|
5631
|
-
|
|
5632
|
-
|
|
5633
|
-
|
|
5634
|
-
|
|
5635
|
-
|
|
5636
|
-
}
|
|
5637
|
-
|
|
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
|
+
}
|
|
5638
5679
|
}
|
|
5639
5680
|
},
|
|
5640
5681
|
fail: null
|
|
@@ -7105,6 +7146,9 @@ var Queue_1 = class Queue {
|
|
|
7105
7146
|
}
|
|
7106
7147
|
};
|
|
7107
7148
|
|
|
7149
|
+
const {
|
|
7150
|
+
rimraf: rimraf$1
|
|
7151
|
+
} = rimraf$2;
|
|
7108
7152
|
const debug$7 = debug$n('botium-connector-BaseContainer');
|
|
7109
7153
|
const {
|
|
7110
7154
|
executeHook: executeHook$1,
|
|
@@ -7237,10 +7281,7 @@ var BaseContainer_1 = class BaseContainer {
|
|
|
7237
7281
|
}, rimraffed => {
|
|
7238
7282
|
if (this.caps[Capabilities.CLEANUPTEMPDIR]) {
|
|
7239
7283
|
debug$7(`Cleanup rimrafing temp dir ${this.tempDirectory}`);
|
|
7240
|
-
rimraf(this.tempDirectory
|
|
7241
|
-
if (err) debug$7(`Cleanup temp dir ${this.tempDirectory} failed: ${util.inspect(err)}`);
|
|
7242
|
-
rimraffed();
|
|
7243
|
-
});
|
|
7284
|
+
rimraf$1(this.tempDirectory).catch(err => debug$7(`Cleanup temp dir ${this.tempDirectory} failed: ${util.inspect(err)}`)).finally(() => rimraffed());
|
|
7244
7285
|
} else {
|
|
7245
7286
|
rimraffed();
|
|
7246
7287
|
}
|
|
@@ -8764,15 +8805,21 @@ var PluginConnectorContainer_1 = class PluginConnectorContainer extends BaseCont
|
|
|
8764
8805
|
}
|
|
8765
8806
|
};
|
|
8766
8807
|
|
|
8767
|
-
var require$$
|
|
8808
|
+
var require$$4 = getCjsExportFromNamespace(_package$1);
|
|
8768
8809
|
|
|
8810
|
+
const {
|
|
8811
|
+
rimraf
|
|
8812
|
+
} = rimraf$2;
|
|
8813
|
+
const {
|
|
8814
|
+
mkdirpSync
|
|
8815
|
+
} = mkdirp;
|
|
8769
8816
|
const {
|
|
8770
8817
|
boolean
|
|
8771
8818
|
} = boolean$1;
|
|
8772
8819
|
const debug$1 = debug$n('botium-core-BotDriver');
|
|
8773
8820
|
const {
|
|
8774
8821
|
version
|
|
8775
|
-
} = require$$
|
|
8822
|
+
} = require$$4;
|
|
8776
8823
|
var BotDriver_1 = class BotDriver {
|
|
8777
8824
|
constructor(caps = {}, sources = {}, envs = {}) {
|
|
8778
8825
|
this.eventEmitter = new events();
|
|
@@ -8862,7 +8909,7 @@ var BotDriver_1 = class BotDriver {
|
|
|
8862
8909
|
}, tempDirectoryCreated => {
|
|
8863
8910
|
tempDirectory = path.resolve(process.cwd(), this.caps[Capabilities.TEMPDIR], sanitizeFilename(`${this.caps[Capabilities.PROJECTNAME]} ${moment().format('YYYYMMDD HHmmss')} ${randomatic('Aa0', 5)}`));
|
|
8864
8911
|
try {
|
|
8865
|
-
|
|
8912
|
+
mkdirpSync(tempDirectory);
|
|
8866
8913
|
tempDirectoryCreated();
|
|
8867
8914
|
} catch (err) {
|
|
8868
8915
|
tempDirectoryCreated(new Error(`Unable to create temp directory ${tempDirectory}: ${err.message}`));
|
|
@@ -8890,9 +8937,7 @@ var BotDriver_1 = class BotDriver {
|
|
|
8890
8937
|
debug$1(`BotDriver Build error: ${err}`);
|
|
8891
8938
|
this.eventEmitter.emit(Events.CONTAINER_BUILD_ERROR, err);
|
|
8892
8939
|
if (tempDirectory) {
|
|
8893
|
-
rimraf(tempDirectory
|
|
8894
|
-
if (err) debug$1(`Cleanup temp dir ${tempDirectory} failed: ${util.inspect(err)}`);
|
|
8895
|
-
});
|
|
8940
|
+
rimraf(tempDirectory).catch(err => debug$1(`Cleanup temp dir ${tempDirectory} failed: ${util.inspect(err)}`));
|
|
8896
8941
|
}
|
|
8897
8942
|
return reject(err);
|
|
8898
8943
|
}
|
|
@@ -9247,6 +9292,7 @@ var botiumCore = {
|
|
|
9247
9292
|
InboundProxy: proxy,
|
|
9248
9293
|
HookUtils: HookUtils,
|
|
9249
9294
|
TranscriptUtils: TranscriptUtils,
|
|
9295
|
+
RetryHelper: RetryHelper_1,
|
|
9250
9296
|
BotiumMockRichMessageTypes: BotiumMockRichMessageTypes,
|
|
9251
9297
|
BotiumError: BotiumError_1.BotiumError,
|
|
9252
9298
|
ScriptingConstants: Constants,
|
|
@@ -9268,13 +9314,14 @@ var botiumCore_7 = botiumCore.Source;
|
|
|
9268
9314
|
var botiumCore_8 = botiumCore.InboundProxy;
|
|
9269
9315
|
var botiumCore_9 = botiumCore.HookUtils;
|
|
9270
9316
|
var botiumCore_10 = botiumCore.TranscriptUtils;
|
|
9271
|
-
var botiumCore_11 = botiumCore.
|
|
9272
|
-
var botiumCore_12 = botiumCore.
|
|
9273
|
-
var botiumCore_13 = botiumCore.
|
|
9274
|
-
var botiumCore_14 = botiumCore.
|
|
9275
|
-
var botiumCore_15 = botiumCore.
|
|
9276
|
-
var botiumCore_16 = botiumCore.
|
|
9277
|
-
var botiumCore_17 = botiumCore.
|
|
9317
|
+
var botiumCore_11 = botiumCore.RetryHelper;
|
|
9318
|
+
var botiumCore_12 = botiumCore.BotiumMockRichMessageTypes;
|
|
9319
|
+
var botiumCore_13 = botiumCore.BotiumError;
|
|
9320
|
+
var botiumCore_14 = botiumCore.ScriptingConstants;
|
|
9321
|
+
var botiumCore_15 = botiumCore.ScriptingMemory;
|
|
9322
|
+
var botiumCore_16 = botiumCore.ScriptingProvider;
|
|
9323
|
+
var botiumCore_17 = botiumCore.LogicHookConstants;
|
|
9324
|
+
var botiumCore_18 = botiumCore.Lib;
|
|
9278
9325
|
|
|
9279
|
-
export { botiumCore_1 as BotDriver,
|
|
9326
|
+
export { botiumCore_1 as BotDriver, botiumCore_13 as BotiumError, botiumCore_12 as BotiumMockRichMessageTypes, botiumCore_2 as Capabilities, botiumCore_3 as Defaults, botiumCore_4 as Enums, botiumCore_5 as Events, botiumCore_9 as HookUtils, botiumCore_8 as InboundProxy, botiumCore_18 as Lib, botiumCore_17 as LogicHookConstants, botiumCore_6 as Plugins, botiumCore_11 as RetryHelper, botiumCore_14 as ScriptingConstants, botiumCore_15 as ScriptingMemory, botiumCore_16 as ScriptingProvider, botiumCore_7 as Source, botiumCore_10 as TranscriptUtils, botiumCore as default };
|
|
9280
9327
|
//# sourceMappingURL=botium-es.js.map
|