botium-core 1.13.4 → 1.13.5
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 +242 -82
- package/dist/botium-cjs.js.map +1 -1
- package/dist/botium-es.js +242 -82
- package/dist/botium-es.js.map +1 -1
- package/package.json +19 -19
- package/src/scripting/CompilerXlsx.js +1 -0
- package/src/scripting/ScriptingMemory.js +41 -2
- package/src/scripting/ScriptingProvider.js +150 -52
- package/src/scripting/helper.js +2 -0
- package/src/scripting/logichook/userinput/MediaInput.js +2 -1
- package/test/compiler/compilercsv.spec.js +9 -2
- package/test/compiler/convos/csv/utterances_variable_row_len.csv +1 -1
- package/test/convo/fillAndApplyScriptingMemory.spec.js +64 -4
- package/test/convo/transcript.spec.js +9 -0
- package/test/scripting/asserters/intentConfidenceAsserter.spec.js +3 -7
- package/test/scripting/scriptingProvider.spec.js +156 -4
- package/test/scripting/utteranceexpansion/associateByIndex.spec.js +15 -15
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "botium-core",
|
|
3
|
-
"version": "1.13.
|
|
3
|
+
"version": "1.13.5",
|
|
4
4
|
"description": "The Selenium for Chatbots",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"module": "dist/botium-es.js",
|
|
@@ -32,7 +32,7 @@
|
|
|
32
32
|
},
|
|
33
33
|
"homepage": "https://www.botium.ai",
|
|
34
34
|
"dependencies": {
|
|
35
|
-
"@babel/runtime": "^7.
|
|
35
|
+
"@babel/runtime": "^7.19.0",
|
|
36
36
|
"async": "^3.2.4",
|
|
37
37
|
"body-parser": "^1.20.0",
|
|
38
38
|
"boolean": "^3.2.0",
|
|
@@ -42,7 +42,7 @@
|
|
|
42
42
|
"esprima": "^4.0.1",
|
|
43
43
|
"express": "^4.18.1",
|
|
44
44
|
"globby": "11.0.4",
|
|
45
|
-
"ioredis": "^5.
|
|
45
|
+
"ioredis": "^5.2.3",
|
|
46
46
|
"is-class": "^0.0.9",
|
|
47
47
|
"is-json": "^2.0.1",
|
|
48
48
|
"jsonpath": "^1.1.1",
|
|
@@ -59,13 +59,13 @@
|
|
|
59
59
|
"rimraf": "^3.0.2",
|
|
60
60
|
"sanitize-filename": "^1.6.3",
|
|
61
61
|
"slugify": "^1.6.5",
|
|
62
|
-
"socket.io": "^4.5.
|
|
63
|
-
"socket.io-client": "^4.5.
|
|
62
|
+
"socket.io": "^4.5.2",
|
|
63
|
+
"socket.io-client": "^4.5.2",
|
|
64
64
|
"socketio-auth": "^0.1.1",
|
|
65
|
-
"swagger-jsdoc": "^6.2.
|
|
66
|
-
"swagger-ui-express": "^4.
|
|
67
|
-
"uuid": "^
|
|
68
|
-
"vm2": "^3.9.
|
|
65
|
+
"swagger-jsdoc": "^6.2.5",
|
|
66
|
+
"swagger-ui-express": "^4.5.0",
|
|
67
|
+
"uuid": "^9.0.0",
|
|
68
|
+
"vm2": "^3.9.11",
|
|
69
69
|
"word-error-rate": "0.0.7",
|
|
70
70
|
"write-yaml": "^1.0.0",
|
|
71
71
|
"xlsx": "^0.18.5",
|
|
@@ -73,27 +73,27 @@
|
|
|
73
73
|
"yaml": "^2.1.1"
|
|
74
74
|
},
|
|
75
75
|
"devDependencies": {
|
|
76
|
-
"@babel/core": "^7.
|
|
77
|
-
"@babel/node": "^7.
|
|
78
|
-
"@babel/plugin-transform-runtime": "^7.
|
|
79
|
-
"@babel/preset-env": "^7.
|
|
76
|
+
"@babel/core": "^7.19.3",
|
|
77
|
+
"@babel/node": "^7.19.1",
|
|
78
|
+
"@babel/plugin-transform-runtime": "^7.19.1",
|
|
79
|
+
"@babel/preset-env": "^7.19.3",
|
|
80
80
|
"chai": "^4.3.6",
|
|
81
81
|
"chai-as-promised": "^7.1.1",
|
|
82
82
|
"cross-env": "^7.0.3",
|
|
83
|
-
"eslint": "^8.
|
|
83
|
+
"eslint": "^8.24.0",
|
|
84
84
|
"eslint-config-standard": "^17.0.0",
|
|
85
85
|
"eslint-plugin-import": "^2.26.0",
|
|
86
86
|
"eslint-plugin-mocha": "^10.1.0",
|
|
87
|
-
"eslint-plugin-n": "^15.
|
|
88
|
-
"eslint-plugin-promise": "^6.0.
|
|
87
|
+
"eslint-plugin-n": "^15.3.0",
|
|
88
|
+
"eslint-plugin-promise": "^6.0.1",
|
|
89
89
|
"eslint-plugin-standard": "^4.1.0",
|
|
90
90
|
"license-checker": "^25.0.1",
|
|
91
91
|
"license-compatibility-checker": "^0.3.5",
|
|
92
92
|
"mocha": "^10.0.0",
|
|
93
|
-
"nock": "^13.2.
|
|
94
|
-
"npm-check-updates": "^
|
|
93
|
+
"nock": "^13.2.9",
|
|
94
|
+
"npm-check-updates": "^16.3.4",
|
|
95
95
|
"nyc": "^15.1.0",
|
|
96
|
-
"rollup": "^2.
|
|
96
|
+
"rollup": "^2.79.1",
|
|
97
97
|
"rollup-plugin-babel": "^4.4.0",
|
|
98
98
|
"rollup-plugin-commonjs": "^10.1.0",
|
|
99
99
|
"rollup-plugin-json": "^4.0.0",
|
|
@@ -256,6 +256,7 @@ module.exports = class CompilerXlsx extends CompilerBase {
|
|
|
256
256
|
if (!convo.header.name) {
|
|
257
257
|
convo.header.name = `${convo.header.sheetname}-${this.colnames[convo.header.colindex]}${formatRowIndex(convo.header.rowindex)}`
|
|
258
258
|
}
|
|
259
|
+
// it is not used anymore?
|
|
259
260
|
convo.header.sort = convo.header.name
|
|
260
261
|
scriptResults.push(convo)
|
|
261
262
|
})
|
|
@@ -73,6 +73,32 @@ const SCRIPTING_FUNCTIONS_RAW = {
|
|
|
73
73
|
return Date.now()
|
|
74
74
|
},
|
|
75
75
|
|
|
76
|
+
$tomorrow: (pattern) => {
|
|
77
|
+
if (pattern) {
|
|
78
|
+
return moment().add(1, 'day').format(pattern)
|
|
79
|
+
}
|
|
80
|
+
return moment().add(1, 'day').toDate().toLocaleDateString()
|
|
81
|
+
},
|
|
82
|
+
$yesterday: (pattern) => {
|
|
83
|
+
if (pattern) {
|
|
84
|
+
return moment().subtract(1, 'day').format(pattern)
|
|
85
|
+
}
|
|
86
|
+
return moment().subtract(1, 'day').toDate().toLocaleDateString()
|
|
87
|
+
},
|
|
88
|
+
|
|
89
|
+
$date_add: (amount, unit, pattern) => {
|
|
90
|
+
if (pattern) {
|
|
91
|
+
return moment().add(amount, unit).format(pattern)
|
|
92
|
+
}
|
|
93
|
+
return moment().add(amount, unit).toDate().toLocaleDateString()
|
|
94
|
+
},
|
|
95
|
+
$date_subtract: (amount, unit, pattern) => {
|
|
96
|
+
if (pattern) {
|
|
97
|
+
return moment().subtract(amount, unit).format(pattern)
|
|
98
|
+
}
|
|
99
|
+
return moment().subtract(amount, unit).toDate().toLocaleDateString()
|
|
100
|
+
},
|
|
101
|
+
|
|
76
102
|
$year: () => {
|
|
77
103
|
return new Date().getFullYear()
|
|
78
104
|
},
|
|
@@ -168,7 +194,8 @@ const SCRIPTING_FUNCTIONS_RAW = {
|
|
|
168
194
|
require: false,
|
|
169
195
|
env: caps[Capabilities.SECURITY_ALLOW_UNSAFE] ? process.env : {},
|
|
170
196
|
sandbox: {
|
|
171
|
-
caps
|
|
197
|
+
caps,
|
|
198
|
+
moment
|
|
172
199
|
}
|
|
173
200
|
})
|
|
174
201
|
return vm.run(`module.exports = (${code})`)
|
|
@@ -246,7 +273,19 @@ const _apply = (scriptingMemory, str, caps, mockMsg) => {
|
|
|
246
273
|
for (const match of matches) {
|
|
247
274
|
if (match.indexOf('(') > 0) {
|
|
248
275
|
const arg = match.substring(match.indexOf('(') + 1, match.lastIndexOf(')')).replace(/\\\)/g, ')')
|
|
249
|
-
|
|
276
|
+
let args = [arg]
|
|
277
|
+
if (SCRIPTING_FUNCTIONS[key].numberOfArguments > 1) {
|
|
278
|
+
args = arg.split(',')
|
|
279
|
+
}
|
|
280
|
+
args = args.map(arg => {
|
|
281
|
+
arg = arg.trim()
|
|
282
|
+
if (arg.startsWith('"') && arg.endsWith('"')) {
|
|
283
|
+
return arg.substring(1, arg.length - 1)
|
|
284
|
+
} else {
|
|
285
|
+
return arg
|
|
286
|
+
}
|
|
287
|
+
})
|
|
288
|
+
str = str.replace(match, SCRIPTING_FUNCTIONS[key].handler(caps, ...args, mockMsg))
|
|
250
289
|
} else {
|
|
251
290
|
str = str.replace(match, SCRIPTING_FUNCTIONS[key].handler(caps))
|
|
252
291
|
}
|
|
@@ -868,27 +868,68 @@ module.exports = class ScriptingProvider {
|
|
|
868
868
|
this._sortConvos()
|
|
869
869
|
}
|
|
870
870
|
|
|
871
|
-
ExpandConvos () {
|
|
871
|
+
ExpandConvos (options = {}) {
|
|
872
|
+
options = Object.assign({
|
|
873
|
+
// use skip and keep, or justHeader
|
|
874
|
+
justHeader: false,
|
|
875
|
+
// drop unwanted convos
|
|
876
|
+
convoFilter: null
|
|
877
|
+
}, options)
|
|
878
|
+
const context = { count: 0 }
|
|
872
879
|
const expandedConvos = []
|
|
873
880
|
debug(`ExpandConvos - Using utterances expansion mode: ${this.caps[Capabilities.SCRIPTING_UTTEXPANSION_MODE]}`)
|
|
874
881
|
this.convos.forEach((convo) => {
|
|
875
882
|
convo.expandPartialConvos()
|
|
876
|
-
this._expandConvo(
|
|
883
|
+
for (const expanded of this._expandConvo(convo, options, context)) {
|
|
884
|
+
expanded.header.assertionCount = this.GetAssertionCount(expanded)
|
|
885
|
+
if (options.justHeader) {
|
|
886
|
+
const ConvoWithOnlyHeader = {
|
|
887
|
+
header: {
|
|
888
|
+
name: expanded.header.name,
|
|
889
|
+
assertionCount: expanded.header.assertionCount
|
|
890
|
+
}
|
|
891
|
+
}
|
|
892
|
+
expandedConvos.push(ConvoWithOnlyHeader)
|
|
893
|
+
} else {
|
|
894
|
+
expandedConvos.push(expanded)
|
|
895
|
+
}
|
|
896
|
+
}
|
|
877
897
|
})
|
|
878
898
|
this.convos = expandedConvos
|
|
879
|
-
|
|
899
|
+
if (!options.justHeader) {
|
|
900
|
+
this._sortConvos()
|
|
901
|
+
} else {
|
|
902
|
+
this._updateConvos()
|
|
903
|
+
}
|
|
904
|
+
}
|
|
905
|
+
|
|
906
|
+
ExpandConvosIterable (options = {}) {
|
|
907
|
+
options = Object.assign({
|
|
908
|
+
// drop unwanted convos
|
|
909
|
+
convoFilter: null
|
|
910
|
+
}, options)
|
|
911
|
+
debug(`ExpandConvos - Using utterances expansion mode: ${this.caps[Capabilities.SCRIPTING_UTTEXPANSION_MODE]}`)
|
|
912
|
+
// creating a nested generator, calling the other.
|
|
913
|
+
// We hope this.convos does not changes while this iterator is used
|
|
914
|
+
const _convosIterable = function * (options) {
|
|
915
|
+
const context = { count: 0 }
|
|
916
|
+
for (const convo of this.convos) {
|
|
917
|
+
convo.expandPartialConvos()
|
|
918
|
+
yield * this._expandConvo(convo, options, context)
|
|
919
|
+
}
|
|
920
|
+
}.bind(this)
|
|
921
|
+
|
|
922
|
+
this.convosIterable = _convosIterable(options)
|
|
880
923
|
}
|
|
881
924
|
|
|
882
925
|
/**
|
|
883
|
-
*
|
|
884
|
-
* @param expandedConvos
|
|
926
|
+
* This is a generator function with yield
|
|
885
927
|
* @param currentConvo
|
|
886
928
|
* @param convoStepIndex
|
|
887
929
|
* @param convoStepsStack list of ConvoSteps
|
|
888
|
-
* @param context {width: }
|
|
889
930
|
* @private
|
|
890
931
|
*/
|
|
891
|
-
_expandConvo (
|
|
932
|
+
* _expandConvo (currentConvo, options, context, convoStepIndex = 0, convoStepsStack = []) {
|
|
892
933
|
const utterancePostfix = (lineTag, uttOrUserInput) => {
|
|
893
934
|
const naming = this.caps[Capabilities.SCRIPTING_UTTEXPANSION_NAMING_MODE] || Defaults.capabilities[Capabilities.SCRIPTING_UTTEXPANSION_NAMING_MODE]
|
|
894
935
|
if (naming === 'justLineTag') {
|
|
@@ -908,7 +949,7 @@ module.exports = class ScriptingProvider {
|
|
|
908
949
|
if (currentStep.sender === 'bot' || currentStep.sender === 'begin' || currentStep.sender === 'end') {
|
|
909
950
|
const currentStepsStack = convoStepsStack.slice()
|
|
910
951
|
currentStepsStack.push(_.cloneDeep(currentStep))
|
|
911
|
-
this._expandConvo(
|
|
952
|
+
yield * this._expandConvo(currentConvo, options, context, convoStepIndex + 1, currentStepsStack)
|
|
912
953
|
} else if (currentStep.sender === 'me') {
|
|
913
954
|
let useUnexpanded = true
|
|
914
955
|
if (currentStep.messageText) {
|
|
@@ -925,28 +966,32 @@ module.exports = class ScriptingProvider {
|
|
|
925
966
|
}
|
|
926
967
|
if (this.utterances[uttName]) {
|
|
927
968
|
const allutterances = this.utterances[uttName].utterances
|
|
928
|
-
const processSampleUtterances = (sampleutterances, myContext)
|
|
929
|
-
sampleutterances.
|
|
930
|
-
processSampleUtterance(
|
|
931
|
-
}
|
|
969
|
+
const processSampleUtterances = function * (sampleutterances, myContext) {
|
|
970
|
+
for (let index = 0; index < sampleutterances.length; index++) {
|
|
971
|
+
yield * processSampleUtterance(sampleutterances[index], sampleutterances.length, index, Object.assign({ indexExpansionModeIndex: index }, myContext || context))
|
|
972
|
+
}
|
|
932
973
|
}
|
|
933
|
-
const processSampleUtterance = (sampleutterance, length, index, myContext)
|
|
934
|
-
const lineTag = `${index + 1}`.padStart(`${length}`.length, '0')
|
|
974
|
+
const processSampleUtterance = function * (sampleutterance, length, index, myContext) {
|
|
935
975
|
const currentStepsStack = convoStepsStack.slice()
|
|
936
976
|
if (uttArgs) {
|
|
937
977
|
sampleutterance = util.format(sampleutterance, ...uttArgs)
|
|
938
978
|
}
|
|
939
979
|
currentStepsStack.push(Object.assign(_.cloneDeep(currentStep), { messageText: sampleutterance }))
|
|
940
980
|
const currentConvoLabeled = _.cloneDeep(currentConvo)
|
|
941
|
-
|
|
981
|
+
if (length > 1) {
|
|
982
|
+
const lineTag = `${index + 1}`.padStart(`${length}`.length, '0')
|
|
983
|
+
Object.assign(currentConvoLabeled.header, { name: `${currentConvo.header.name}/${uttName}-${utterancePostfix(lineTag, sampleutterance)}` })
|
|
984
|
+
}
|
|
942
985
|
if (!currentConvoLabeled.sourceTag) currentConvoLabeled.sourceTag = {}
|
|
943
986
|
if (!currentConvoLabeled.sourceTag.origConvoName) currentConvoLabeled.sourceTag.origConvoName = currentConvo.header.name
|
|
944
|
-
this._expandConvo(
|
|
945
|
-
}
|
|
946
|
-
if (
|
|
987
|
+
yield * this._expandConvo(currentConvoLabeled, options, myContext || context, convoStepIndex + 1, currentStepsStack)
|
|
988
|
+
}.bind(this)
|
|
989
|
+
if (allutterances.length === 1) {
|
|
990
|
+
yield * processSampleUtterances([allutterances[0]], context)
|
|
991
|
+
} else if (this.caps[Capabilities.SCRIPTING_UTTEXPANSION_MODE] === 'index') {
|
|
947
992
|
if (_.isNil(context.indexExpansionModeWidth)) {
|
|
948
993
|
// executed for the first found utterance
|
|
949
|
-
processSampleUtterances(allutterances, Object.assign({}, context, { indexExpansionModeWidth: allutterances.length }))
|
|
994
|
+
yield * processSampleUtterances(allutterances, Object.assign({}, context, { indexExpansionModeWidth: allutterances.length }))
|
|
950
995
|
} else {
|
|
951
996
|
if (_.isNil(context.indexExpansionModeIndex)) {
|
|
952
997
|
throw new Error('indexExpansionModeIndex must be set!')
|
|
@@ -957,58 +1002,67 @@ module.exports = class ScriptingProvider {
|
|
|
957
1002
|
debug(`While expanding convos by index found in utterance "${uttName}" less examples (${allutterances.length}) as expected (${context.indexExpansionModeWidth})`)
|
|
958
1003
|
}
|
|
959
1004
|
const myContext = Object.assign({}, context, { indexExpansionModeWidth: Math.max(allutterances.length, context.indexExpansionModeWidth) })
|
|
960
|
-
processSampleUtterance(allutterances[localIndex], allutterances.length, localIndex, myContext)
|
|
1005
|
+
yield * processSampleUtterance(allutterances[localIndex], allutterances.length, localIndex, myContext)
|
|
961
1006
|
if (allutterances.length > context.indexExpansionModeWidth && context.indexExpansionModeIndex + 1 === context.indexExpansionModeWidth) {
|
|
962
1007
|
debug(`While expanding convos by index found in utterance "${uttName}" more examples (${allutterances.length}) as expected (${context.indexExpansionModeWidth})`)
|
|
963
1008
|
for (let i = context.indexExpansionModeWidth; i < allutterances.length; i++) {
|
|
964
1009
|
// if we found a utterance with more examples as any utterances before, we have to start new 'thread'
|
|
965
1010
|
const myContext = Object.assign({}, context, { indexExpansionModeWidth: allutterances.length, indexExpansionModeIndex: i })
|
|
966
|
-
processSampleUtterance(allutterances[i], allutterances.length, i, myContext)
|
|
1011
|
+
yield * processSampleUtterance(allutterances[i], allutterances.length, i, myContext)
|
|
967
1012
|
}
|
|
968
1013
|
}
|
|
969
1014
|
}
|
|
970
1015
|
} else {
|
|
971
1016
|
if (this.caps[Capabilities.SCRIPTING_UTTEXPANSION_MODE] === 'first') {
|
|
972
|
-
processSampleUtterances([allutterances[0]])
|
|
1017
|
+
yield * processSampleUtterances([allutterances[0]], context)
|
|
973
1018
|
} else if (this.caps[Capabilities.SCRIPTING_UTTEXPANSION_MODE] === 'random') {
|
|
974
|
-
processSampleUtterances(allutterances
|
|
1019
|
+
yield * processSampleUtterances(allutterances
|
|
975
1020
|
.map(x => ({ x, r: Math.random() }))
|
|
976
1021
|
.sort((a, b) => a.r - b.r)
|
|
977
1022
|
.map(a => a.x)
|
|
978
|
-
.slice(0, this.caps[Capabilities.SCRIPTING_UTTEXPANSION_RANDOM_COUNT]))
|
|
1023
|
+
.slice(0, this.caps[Capabilities.SCRIPTING_UTTEXPANSION_RANDOM_COUNT]), context)
|
|
979
1024
|
} else {
|
|
980
|
-
processSampleUtterances(allutterances)
|
|
1025
|
+
yield * processSampleUtterances(allutterances, context)
|
|
981
1026
|
}
|
|
982
1027
|
}
|
|
983
1028
|
useUnexpanded = false
|
|
984
1029
|
}
|
|
985
1030
|
}
|
|
986
1031
|
if (currentStep.userInputs && currentStep.userInputs.length > 0) {
|
|
987
|
-
currentStep.userInputs.
|
|
1032
|
+
for (let uiIndex = 0; uiIndex < currentStep.userInputs.length; uiIndex++) {
|
|
1033
|
+
const ui = currentStep.userInputs[uiIndex]
|
|
988
1034
|
const userInput = this.userInputs[ui.name]
|
|
989
1035
|
if (userInput && userInput.expandConvo) {
|
|
990
1036
|
const expandedUserInputs = userInput.expandConvo({ convo: currentConvo, convoStep: currentStep, args: ui.args })
|
|
991
1037
|
if (expandedUserInputs && expandedUserInputs.length > 0) {
|
|
992
1038
|
// let sampleinputs = expandedUserInputs
|
|
993
|
-
const processSampleInputs = (sampleinputs, myContext, uiIndex)
|
|
994
|
-
sampleinputs.
|
|
995
|
-
processSampleInput(
|
|
996
|
-
}
|
|
1039
|
+
const processSampleInputs = function * (sampleinputs, myContext, uiIndex) {
|
|
1040
|
+
for (let index = 0; index < sampleinputs.length; index++) {
|
|
1041
|
+
yield * processSampleInput(sampleinputs[index], sampleinputs.length, index, Object.assign({ indexExpansionModeIndex: index }, myContext || context), uiIndex)
|
|
1042
|
+
}
|
|
997
1043
|
}
|
|
998
|
-
const processSampleInput = (sampleinput, length, index, myContext, uiIndex)
|
|
999
|
-
const lineTag = `${index + 1}`.padStart(`${length}`.length, '0')
|
|
1044
|
+
const processSampleInput = function * (sampleinput, length, index, myContext, uiIndex) {
|
|
1000
1045
|
const currentStepsStack = convoStepsStack.slice()
|
|
1001
1046
|
const currentStepMod = _.cloneDeep(currentStep)
|
|
1002
1047
|
currentStepMod.userInputs[uiIndex] = sampleinput
|
|
1003
1048
|
|
|
1004
1049
|
currentStepsStack.push(currentStepMod)
|
|
1005
1050
|
const currentConvoLabeled = _.cloneDeep(currentConvo)
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1051
|
+
if (length > 1) {
|
|
1052
|
+
if (sampleinput.convoPostfix) {
|
|
1053
|
+
Object.assign(currentConvoLabeled.header, { name: `${currentConvo.header.name}/${ui.name}-${sampleinput.convoPostfix}` })
|
|
1054
|
+
} else {
|
|
1055
|
+
const lineTag = `${index + 1}`.padStart(`${length}`.length, '0')
|
|
1056
|
+
Object.assign(currentConvoLabeled.header, { name: `${currentConvo.header.name}/${ui.name}-${utterancePostfix(lineTag, (sampleinput.args && sampleinput.args.length) ? sampleinput.args.join(', ') : 'no-args')}` })
|
|
1057
|
+
}
|
|
1058
|
+
}
|
|
1059
|
+
yield * this._expandConvo(currentConvoLabeled, options, myContext || context, convoStepIndex + 1, currentStepsStack)
|
|
1060
|
+
}.bind(this)
|
|
1061
|
+
if (expandedUserInputs.length === 1) {
|
|
1062
|
+
yield * processSampleInputs([expandedUserInputs[0]], context, uiIndex)
|
|
1063
|
+
} else if (this.caps[Capabilities.SCRIPTING_UTTEXPANSION_MODE] === 'index') {
|
|
1010
1064
|
if (_.isNil(context.indexExpansionModeWidth)) {
|
|
1011
|
-
processSampleInputs(expandedUserInputs, Object.assign({}, context, { indexExpansionModeWidth: expandedUserInputs.length }), uiIndex)
|
|
1065
|
+
yield * processSampleInputs(expandedUserInputs, Object.assign({}, context, { indexExpansionModeWidth: expandedUserInputs.length }), uiIndex)
|
|
1012
1066
|
} else {
|
|
1013
1067
|
if (_.isNil(context.indexExpansionModeIndex)) {
|
|
1014
1068
|
throw new Error('indexExpansionModeIndex must be set!')
|
|
@@ -1019,20 +1073,20 @@ module.exports = class ScriptingProvider {
|
|
|
1019
1073
|
debug(`While expanding convos by index found user input "${ui.name}, ${ui.args}" less examples (${expandedUserInputs.length}) as expected (${context.indexExpansionModeWidth})`)
|
|
1020
1074
|
}
|
|
1021
1075
|
const myContext = Object.assign({}, context, { indexExpansionModeWidth: Math.max(expandedUserInputs.length, context.indexExpansionModeWidth) })
|
|
1022
|
-
processSampleInput(expandedUserInputs[localIndex], expandedUserInputs.length, localIndex, myContext, uiIndex)
|
|
1076
|
+
yield * processSampleInput(expandedUserInputs[localIndex], expandedUserInputs.length, localIndex, myContext, uiIndex)
|
|
1023
1077
|
if (expandedUserInputs.length > context.indexExpansionModeWidth && context.indexExpansionModeIndex + 1 === context.indexExpansionModeWidth) {
|
|
1024
1078
|
debug(`While expanding convos by index found user input "${ui.name}, ${ui.args}" more examples (${expandedUserInputs.length}) as expected (${context.indexExpansionModeWidth})`)
|
|
1025
1079
|
for (let i = context.indexExpansionModeWidth; i < expandedUserInputs.length; i++) {
|
|
1026
1080
|
const myContext = Object.assign({}, context, { indexExpansionModeWidth: expandedUserInputs.length, indexExpansionModeIndex: i })
|
|
1027
|
-
processSampleInput(expandedUserInputs[i], expandedUserInputs.length, i, myContext, uiIndex)
|
|
1081
|
+
yield * processSampleInput(expandedUserInputs[i], expandedUserInputs.length, i, myContext, uiIndex)
|
|
1028
1082
|
}
|
|
1029
1083
|
}
|
|
1030
1084
|
}
|
|
1031
1085
|
} else {
|
|
1032
1086
|
if (this.caps[Capabilities.SCRIPTING_UTTEXPANSION_MODE] === 'first') {
|
|
1033
|
-
processSampleInputs([expandedUserInputs[0]], context, uiIndex)
|
|
1087
|
+
yield * processSampleInputs([expandedUserInputs[0]], context, uiIndex)
|
|
1034
1088
|
} else if (this.caps[Capabilities.SCRIPTING_UTTEXPANSION_MODE] === 'random') {
|
|
1035
|
-
processSampleInputs(expandedUserInputs
|
|
1089
|
+
yield * processSampleInputs(expandedUserInputs
|
|
1036
1090
|
.map(x => ({
|
|
1037
1091
|
x,
|
|
1038
1092
|
r: Math.random()
|
|
@@ -1041,35 +1095,49 @@ module.exports = class ScriptingProvider {
|
|
|
1041
1095
|
.map(a => a.x)
|
|
1042
1096
|
.slice(0, this.caps[Capabilities.SCRIPTING_UTTEXPANSION_RANDOM_COUNT]), context, uiIndex)
|
|
1043
1097
|
} else {
|
|
1044
|
-
processSampleInputs(expandedUserInputs, context, uiIndex)
|
|
1098
|
+
yield * processSampleInputs(expandedUserInputs, context, uiIndex)
|
|
1045
1099
|
}
|
|
1046
1100
|
}
|
|
1047
1101
|
useUnexpanded = false
|
|
1048
1102
|
}
|
|
1049
1103
|
}
|
|
1050
|
-
}
|
|
1104
|
+
}
|
|
1051
1105
|
}
|
|
1052
1106
|
if (useUnexpanded) {
|
|
1053
1107
|
const currentStepsStack = convoStepsStack.slice()
|
|
1054
1108
|
currentStepsStack.push(_.cloneDeep(currentStep))
|
|
1055
|
-
this._expandConvo(
|
|
1109
|
+
yield * this._expandConvo(currentConvo, options, context, convoStepIndex + 1, currentStepsStack)
|
|
1056
1110
|
}
|
|
1057
1111
|
}
|
|
1058
1112
|
} else {
|
|
1059
|
-
|
|
1113
|
+
const expanded = Object.assign(_.cloneDeep(currentConvo), { conversation: _.cloneDeep(convoStepsStack) })
|
|
1114
|
+
if (!options.convoFilter || options.convoFilter(expanded)) {
|
|
1115
|
+
context.count++
|
|
1116
|
+
const logPerEntry = context.count < 10 ? 1 : context.count < 100 ? 10 : context.count < 1000 ? 100 : context.count < 10000 ? 1000 : 10000
|
|
1117
|
+
if (context.count % logPerEntry === 0) {
|
|
1118
|
+
debug(`Convo #${context.count} expanded (${expanded.header.name})`)
|
|
1119
|
+
}
|
|
1120
|
+
yield expanded
|
|
1121
|
+
}
|
|
1060
1122
|
}
|
|
1061
1123
|
}
|
|
1062
1124
|
|
|
1063
1125
|
_sortConvos () {
|
|
1064
1126
|
this.convos = _.sortBy(this.convos, [(convo) => convo.header.sort || convo.header.name])
|
|
1127
|
+
this._updateConvos()
|
|
1128
|
+
}
|
|
1129
|
+
|
|
1130
|
+
_updateConvos () {
|
|
1065
1131
|
let i = 0
|
|
1066
1132
|
this.convos.forEach((convo) => {
|
|
1067
|
-
convo
|
|
1068
|
-
|
|
1069
|
-
convo.header.projectname
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
convo.header.testsessionname
|
|
1133
|
+
if (convo) {
|
|
1134
|
+
convo.header.order = ++i
|
|
1135
|
+
if (!convo.header.projectname) {
|
|
1136
|
+
convo.header.projectname = this.caps[Capabilities.PROJECTNAME]
|
|
1137
|
+
}
|
|
1138
|
+
if (!convo.header.testsessionname) {
|
|
1139
|
+
convo.header.testsessionname = this.caps[Capabilities.TESTSESSIONNAME]
|
|
1140
|
+
}
|
|
1073
1141
|
}
|
|
1074
1142
|
})
|
|
1075
1143
|
}
|
|
@@ -1080,7 +1148,11 @@ module.exports = class ScriptingProvider {
|
|
|
1080
1148
|
} else if (convos) {
|
|
1081
1149
|
this.convos.push(convos)
|
|
1082
1150
|
}
|
|
1083
|
-
this.
|
|
1151
|
+
if (this.convos.filter(c => _.isNil(c))) {
|
|
1152
|
+
this._updateConvos()
|
|
1153
|
+
} else {
|
|
1154
|
+
this._sortConvos()
|
|
1155
|
+
}
|
|
1084
1156
|
}
|
|
1085
1157
|
|
|
1086
1158
|
AddUtterances (utterances) {
|
|
@@ -1334,4 +1406,30 @@ module.exports = class ScriptingProvider {
|
|
|
1334
1406
|
...lines,
|
|
1335
1407
|
'}'].join('\r\n')
|
|
1336
1408
|
}
|
|
1409
|
+
|
|
1410
|
+
GetAssertionCount (convo) {
|
|
1411
|
+
if (!convo) {
|
|
1412
|
+
return 0
|
|
1413
|
+
}
|
|
1414
|
+
let counter = 0
|
|
1415
|
+
for (const step of convo.conversation) {
|
|
1416
|
+
if (step.sender === 'bot') {
|
|
1417
|
+
let stepCounter = step.asserters ? step.asserters.length : 0
|
|
1418
|
+
if (step.messageText) {
|
|
1419
|
+
stepCounter++
|
|
1420
|
+
}
|
|
1421
|
+
stepCounter = stepCounter === 0 ? 1 : stepCounter
|
|
1422
|
+
counter += stepCounter
|
|
1423
|
+
}
|
|
1424
|
+
}
|
|
1425
|
+
|
|
1426
|
+
if (convo.convoBegin && convo.convoBegin.asserters) {
|
|
1427
|
+
counter += convo.convoBegin.asserters.length
|
|
1428
|
+
}
|
|
1429
|
+
|
|
1430
|
+
if (convo.convoEnd && convo.convoEnd.asserters) {
|
|
1431
|
+
counter += convo.convoEnd.asserters.length
|
|
1432
|
+
}
|
|
1433
|
+
return counter === 0 ? 1 : counter
|
|
1434
|
+
}
|
|
1337
1435
|
}
|
package/src/scripting/helper.js
CHANGED
|
@@ -437,6 +437,8 @@ const convoStepToLines = (step) => {
|
|
|
437
437
|
lines.push('MEDIA ' + step.media[0].mediaUri)
|
|
438
438
|
} else if (step.messageText) {
|
|
439
439
|
lines.push(step.messageText)
|
|
440
|
+
} else if (step.sourceData) {
|
|
441
|
+
lines.push(JSON.stringify(step.sourceData, null, 2))
|
|
440
442
|
}
|
|
441
443
|
step.userInputs && step.userInputs.forEach((userInput) => {
|
|
442
444
|
lines.push(userInput.name + _formatAppendArgs(userInput.args))
|
|
@@ -15,8 +15,15 @@ const buildContext = () => {
|
|
|
15
15
|
AddConvos: (c) => {
|
|
16
16
|
result.convos = result.convos.concat(c)
|
|
17
17
|
},
|
|
18
|
-
AddUtterances: (
|
|
19
|
-
|
|
18
|
+
AddUtterances: (utteranceStructsToAdd) => {
|
|
19
|
+
for (const utteranceStructToAdd of utteranceStructsToAdd) {
|
|
20
|
+
const existing = result.utterances.find(entry => entry.name === utteranceStructToAdd.name)
|
|
21
|
+
if (existing) {
|
|
22
|
+
existing.utterances = existing.utterances.concat(utteranceStructToAdd.utterances)
|
|
23
|
+
} else {
|
|
24
|
+
result.utterances.push(utteranceStructToAdd)
|
|
25
|
+
}
|
|
26
|
+
}
|
|
20
27
|
},
|
|
21
28
|
convos: [],
|
|
22
29
|
utterances: []
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
const path = require('path')
|
|
2
|
+
const moment = require('moment')
|
|
2
3
|
const assert = require('chai').assert
|
|
3
4
|
const BotDriver = require('../../').BotDriver
|
|
4
5
|
const Capabilities = require('../../').Capabilities
|
|
@@ -695,6 +696,39 @@ describe('convo.fillAndApplyScriptingMemory', function () {
|
|
|
695
696
|
assert(result.length === 13, '$timestap is invalid')
|
|
696
697
|
})
|
|
697
698
|
|
|
699
|
+
it('tomorrow without format', async function () {
|
|
700
|
+
const result = ScriptingMemory.apply(
|
|
701
|
+
{ caps: CAPS_ENABLE_SCRIPTING_MEMORY },
|
|
702
|
+
{},
|
|
703
|
+
'$tomorrow'
|
|
704
|
+
)
|
|
705
|
+
assert.equal(result, moment().add(1, 'day').toDate().toLocaleDateString())
|
|
706
|
+
})
|
|
707
|
+
it('tomorrow with format', async function () {
|
|
708
|
+
const result = ScriptingMemory.apply(
|
|
709
|
+
{ caps: CAPS_ENABLE_SCRIPTING_MEMORY },
|
|
710
|
+
{},
|
|
711
|
+
'$tomorrow(YYYY.MM.DD)'
|
|
712
|
+
)
|
|
713
|
+
assert.equal(result, moment().add(1, 'day').format('YYYY.MM.DD'))
|
|
714
|
+
})
|
|
715
|
+
it('yesterday without format', async function () {
|
|
716
|
+
const result = ScriptingMemory.apply(
|
|
717
|
+
{ caps: CAPS_ENABLE_SCRIPTING_MEMORY },
|
|
718
|
+
{},
|
|
719
|
+
'$yesterday'
|
|
720
|
+
)
|
|
721
|
+
assert.equal(result, moment().subtract(1, 'day').toDate().toLocaleDateString())
|
|
722
|
+
})
|
|
723
|
+
it('yesterday with format', async function () {
|
|
724
|
+
const result = ScriptingMemory.apply(
|
|
725
|
+
{ caps: CAPS_ENABLE_SCRIPTING_MEMORY },
|
|
726
|
+
{},
|
|
727
|
+
'$yesterday(YYYY.MM.DD)'
|
|
728
|
+
)
|
|
729
|
+
assert.equal(result, moment().subtract(1, 'day').format('YYYY.MM.DD'))
|
|
730
|
+
})
|
|
731
|
+
|
|
698
732
|
it('year', async function () {
|
|
699
733
|
const result = ScriptingMemory.apply(
|
|
700
734
|
{ caps: CAPS_ENABLE_SCRIPTING_MEMORY },
|
|
@@ -703,7 +737,7 @@ describe('convo.fillAndApplyScriptingMemory', function () {
|
|
|
703
737
|
)
|
|
704
738
|
|
|
705
739
|
const year = parseInt(result)
|
|
706
|
-
assert(year
|
|
740
|
+
assert.equal(year, new Date().getFullYear(), '$year invalid')
|
|
707
741
|
})
|
|
708
742
|
|
|
709
743
|
it('month', async function () {
|
|
@@ -712,8 +746,7 @@ describe('convo.fillAndApplyScriptingMemory', function () {
|
|
|
712
746
|
{},
|
|
713
747
|
'$month'
|
|
714
748
|
)
|
|
715
|
-
|
|
716
|
-
assert(result.length >= 2 && result.length <= 10, '$month invalid')
|
|
749
|
+
assert.equal(result, moment().format('MMMM'), '$month invalid')
|
|
717
750
|
})
|
|
718
751
|
it('month_MM', async function () {
|
|
719
752
|
const result = ScriptingMemory.apply(
|
|
@@ -733,7 +766,7 @@ describe('convo.fillAndApplyScriptingMemory', function () {
|
|
|
733
766
|
)
|
|
734
767
|
|
|
735
768
|
const dayOfMonth = parseInt(result)
|
|
736
|
-
assert(dayOfMonth >= 1 && dayOfMonth <= 35, 'day_of_month invalid')
|
|
769
|
+
assert(dayOfMonth >= 1 && dayOfMonth <= 35, '$day_of_month invalid')
|
|
737
770
|
})
|
|
738
771
|
|
|
739
772
|
it('day_of_week', async function () {
|
|
@@ -746,6 +779,25 @@ describe('convo.fillAndApplyScriptingMemory', function () {
|
|
|
746
779
|
assert(result.length >= 2 && result.length <= 20, '$day_of_week invalid')
|
|
747
780
|
})
|
|
748
781
|
|
|
782
|
+
it('date_add', async function () {
|
|
783
|
+
const result = ScriptingMemory.apply(
|
|
784
|
+
{ caps: CAPS_ENABLE_SCRIPTING_MEMORY },
|
|
785
|
+
{},
|
|
786
|
+
'$date_add(1, "day", YYYY.MM.DD)'
|
|
787
|
+
)
|
|
788
|
+
|
|
789
|
+
assert.equal(result, moment().add(1, 'day').format('YYYY.MM.DD'))
|
|
790
|
+
})
|
|
791
|
+
it('date_subtract', async function () {
|
|
792
|
+
const result = ScriptingMemory.apply(
|
|
793
|
+
{ caps: CAPS_ENABLE_SCRIPTING_MEMORY },
|
|
794
|
+
{},
|
|
795
|
+
'$date_subtract(1, "month", YYYY.MM.DD)'
|
|
796
|
+
)
|
|
797
|
+
|
|
798
|
+
assert.equal(result, moment().subtract(1, 'month').format('YYYY.MM.DD'))
|
|
799
|
+
})
|
|
800
|
+
|
|
749
801
|
it('random', async function () {
|
|
750
802
|
const result = ScriptingMemory.apply(
|
|
751
803
|
{ caps: CAPS_ENABLE_SCRIPTING_MEMORY },
|
|
@@ -813,6 +865,14 @@ describe('convo.fillAndApplyScriptingMemory', function () {
|
|
|
813
865
|
)
|
|
814
866
|
assert.equal(result, 'botium')
|
|
815
867
|
})
|
|
868
|
+
it('func with moment', async function () {
|
|
869
|
+
const result = ScriptingMemory.apply(
|
|
870
|
+
{ caps: CAPS_ENABLE_SCRIPTING_MEMORY },
|
|
871
|
+
{},
|
|
872
|
+
'$func(moment(\\).subtract(1, "month"\\).startOf("month"\\).format("DD.MM.YYYY"\\))'
|
|
873
|
+
)
|
|
874
|
+
assert.equal(result, moment().subtract(1, 'month').startOf('month').format('DD.MM.YYYY'))
|
|
875
|
+
})
|
|
816
876
|
it('environment variable', async function () {
|
|
817
877
|
process.env.MY_VAR_VALUE = 'botium'
|
|
818
878
|
const result = ScriptingMemory.apply(
|