botium-core 1.13.3 → 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 +315 -107
- package/dist/botium-cjs.js.map +1 -1
- package/dist/botium-es.js +315 -107
- package/dist/botium-es.js.map +1 -1
- package/package.json +19 -19
- package/src/Capabilities.js +2 -0
- package/src/Defaults.js +4 -0
- package/src/mocks/BotiumMockScripting.js +1 -0
- package/src/scripting/CompilerXlsx.js +1 -0
- package/src/scripting/ScriptingMemory.js +41 -2
- package/src/scripting/ScriptingProvider.js +206 -84
- 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 +213 -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",
|
package/src/Capabilities.js
CHANGED
|
@@ -133,6 +133,8 @@ module.exports = {
|
|
|
133
133
|
SCRIPTING_UTTEXPANSION_MODE: 'SCRIPTING_UTTEXPANSION_MODE',
|
|
134
134
|
SCRIPTING_UTTEXPANSION_RANDOM_COUNT: 'SCRIPTING_UTTEXPANSION_RANDOM_COUNT',
|
|
135
135
|
SCRIPTING_UTTEXPANSION_INCOMPREHENSION: 'SCRIPTING_UTTEXPANSION_INCOMPREHENSION',
|
|
136
|
+
SCRIPTING_UTTEXPANSION_INCOMPREHENSIONINTENTS: 'SCRIPTING_UTTEXPANSION_INCOMPREHENSIONINTENTS',
|
|
137
|
+
SCRIPTING_UTTEXPANSION_INCOMPREHENSIONUTTS: 'SCRIPTING_UTTEXPANSION_INCOMPREHENSIONUTTS',
|
|
136
138
|
SCRIPTING_UTTEXPANSION_USENAMEASINTENT: 'SCRIPTING_UTTEXPANSION_USENAMEASINTENT',
|
|
137
139
|
// justLineTag, utterance
|
|
138
140
|
SCRIPTING_UTTEXPANSION_NAMING_MODE: 'SCRIPTING_UTTEXPANSION_NAMING_MODE',
|
package/src/Defaults.js
CHANGED
|
@@ -49,6 +49,10 @@ module.exports = {
|
|
|
49
49
|
[Capabilities.SCRIPTING_UTTEXPANSION_RANDOM_COUNT]: 1,
|
|
50
50
|
[Capabilities.SCRIPTING_UTTEXPANSION_NAMING_MODE]: 'justLineTag',
|
|
51
51
|
[Capabilities.SCRIPTING_UTTEXPANSION_NAMING_UTTERANCE_MAX]: '16',
|
|
52
|
+
[Capabilities.SCRIPTING_UTTEXPANSION_INCOMPREHENSION]: null,
|
|
53
|
+
[Capabilities.SCRIPTING_UTTEXPANSION_INCOMPREHENSIONINTENTS]: [],
|
|
54
|
+
[Capabilities.SCRIPTING_UTTEXPANSION_INCOMPREHENSIONUTTS]: [],
|
|
55
|
+
[Capabilities.SCRIPTING_UTTEXPANSION_USENAMEASINTENT]: false,
|
|
52
56
|
[Capabilities.SCRIPTING_MEMORYEXPANSION_KEEP_ORIG]: false,
|
|
53
57
|
[Capabilities.SCRIPTING_ENABLE_SKIP_ASSERT_ERRORS]: false,
|
|
54
58
|
[Capabilities.SCRIPTING_FORCE_BOT_CONSUMED]: false,
|
|
@@ -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
|
}
|
|
@@ -770,31 +770,79 @@ module.exports = class ScriptingProvider {
|
|
|
770
770
|
this._sortConvos()
|
|
771
771
|
}
|
|
772
772
|
|
|
773
|
-
ExpandUtterancesToConvos ({ useNameAsIntent, incomprehensionUtt } = {}) {
|
|
773
|
+
ExpandUtterancesToConvos ({ useNameAsIntent, incomprehensionIntents, incomprehensionUtts, incomprehensionUtt } = {}) {
|
|
774
774
|
const expandedConvos = []
|
|
775
775
|
|
|
776
776
|
if (_.isUndefined(useNameAsIntent)) {
|
|
777
777
|
useNameAsIntent = !!this.caps[Capabilities.SCRIPTING_UTTEXPANSION_USENAMEASINTENT]
|
|
778
778
|
}
|
|
779
|
+
if (_.isUndefined(incomprehensionIntents)) {
|
|
780
|
+
incomprehensionIntents = this.caps[Capabilities.SCRIPTING_UTTEXPANSION_INCOMPREHENSIONINTENTS]
|
|
781
|
+
}
|
|
782
|
+
if (_.isUndefined(incomprehensionUtts)) {
|
|
783
|
+
incomprehensionUtts = this.caps[Capabilities.SCRIPTING_UTTEXPANSION_INCOMPREHENSIONUTTS]
|
|
784
|
+
}
|
|
779
785
|
if (_.isUndefined(incomprehensionUtt)) {
|
|
780
786
|
incomprehensionUtt = this.caps[Capabilities.SCRIPTING_UTTEXPANSION_INCOMPREHENSION]
|
|
781
787
|
}
|
|
782
788
|
|
|
783
|
-
if (
|
|
784
|
-
throw new Error(
|
|
789
|
+
if (incomprehensionUtt && (!incomprehensionUtts || incomprehensionUtts.length === 0) && !this.utterances[incomprehensionUtt]) {
|
|
790
|
+
throw new Error(`ExpandUtterancesToConvos - incomprehension utterance '${incomprehensionUtt}' undefined (and no user examples given)`)
|
|
785
791
|
}
|
|
786
|
-
if (
|
|
787
|
-
|
|
792
|
+
if (incomprehensionUtts && incomprehensionUtts.length > 0) {
|
|
793
|
+
if (!incomprehensionUtt) {
|
|
794
|
+
incomprehensionUtt = 'UTT_INCOMPREHENSION'
|
|
795
|
+
}
|
|
796
|
+
if (this.utterances[incomprehensionUtt]) {
|
|
797
|
+
this.utterances[incomprehensionUtt].utterances.push(...incomprehensionUtts)
|
|
798
|
+
} else {
|
|
799
|
+
this.utterances[incomprehensionUtt] = {
|
|
800
|
+
name: incomprehensionUtt,
|
|
801
|
+
utterances: [...incomprehensionUtts]
|
|
802
|
+
}
|
|
803
|
+
}
|
|
788
804
|
}
|
|
789
805
|
|
|
790
806
|
if (useNameAsIntent) {
|
|
791
807
|
debug('ExpandUtterancesToConvos - Using utterance name as NLU intent')
|
|
792
|
-
}
|
|
793
|
-
|
|
808
|
+
}
|
|
809
|
+
if (incomprehensionIntents && incomprehensionIntents.length > 0) {
|
|
810
|
+
debug(`ExpandUtterancesToConvos - Using ${incomprehensionIntents.length} incomprehension NLU intent(s)`)
|
|
811
|
+
}
|
|
812
|
+
if (incomprehensionUtt) {
|
|
813
|
+
debug(`ExpandUtterancesToConvos - Using incomprehension utterance expansion mode: ${incomprehensionUtt}, ${this.utterances[incomprehensionUtt].utterances.length} user example(s)`)
|
|
794
814
|
}
|
|
795
815
|
|
|
796
816
|
_.keys(this.utterances).filter(u => u !== incomprehensionUtt).forEach(uttName => {
|
|
797
817
|
const utt = this.utterances[uttName]
|
|
818
|
+
|
|
819
|
+
const responseStep = {
|
|
820
|
+
sender: 'bot',
|
|
821
|
+
messageText: '',
|
|
822
|
+
asserters: [],
|
|
823
|
+
stepTag: 'Step 2 - check bot response',
|
|
824
|
+
not: false
|
|
825
|
+
}
|
|
826
|
+
if (useNameAsIntent) {
|
|
827
|
+
responseStep.asserters.push({
|
|
828
|
+
name: 'INTENT',
|
|
829
|
+
args: [utt.name]
|
|
830
|
+
})
|
|
831
|
+
}
|
|
832
|
+
if (incomprehensionIntents && incomprehensionIntents.length > 0) {
|
|
833
|
+
incomprehensionIntents.forEach(ii => {
|
|
834
|
+
responseStep.asserters.push({
|
|
835
|
+
name: 'INTENT',
|
|
836
|
+
args: [ii],
|
|
837
|
+
not: true
|
|
838
|
+
})
|
|
839
|
+
})
|
|
840
|
+
}
|
|
841
|
+
if (incomprehensionUtt) {
|
|
842
|
+
responseStep.messageText = incomprehensionUtt
|
|
843
|
+
responseStep.not = true
|
|
844
|
+
}
|
|
845
|
+
|
|
798
846
|
expandedConvos.push(new Convo(this._buildScriptContext(), {
|
|
799
847
|
header: {
|
|
800
848
|
name: utt.name,
|
|
@@ -811,31 +859,7 @@ module.exports = class ScriptingProvider {
|
|
|
811
859
|
messageText: utt.name,
|
|
812
860
|
stepTag: 'Step 1 - tell utterance'
|
|
813
861
|
},
|
|
814
|
-
|
|
815
|
-
? {
|
|
816
|
-
sender: 'bot',
|
|
817
|
-
asserters: [
|
|
818
|
-
{
|
|
819
|
-
name: 'INTENT',
|
|
820
|
-
args: [utt.name]
|
|
821
|
-
}
|
|
822
|
-
],
|
|
823
|
-
stepTag: 'Step 2 - check intent',
|
|
824
|
-
not: false
|
|
825
|
-
}
|
|
826
|
-
: incomprehensionUtt
|
|
827
|
-
? {
|
|
828
|
-
sender: 'bot',
|
|
829
|
-
messageText: incomprehensionUtt,
|
|
830
|
-
stepTag: 'Step 2 - check incomprehension',
|
|
831
|
-
not: true
|
|
832
|
-
}
|
|
833
|
-
: {
|
|
834
|
-
sender: 'bot',
|
|
835
|
-
messageText: '',
|
|
836
|
-
stepTag: 'Step 2 - check bot response',
|
|
837
|
-
not: false
|
|
838
|
-
}
|
|
862
|
+
responseStep
|
|
839
863
|
],
|
|
840
864
|
sourceTag: Object.assign({}, utt.sourceTag, { origUttName: utt.name })
|
|
841
865
|
}))
|
|
@@ -844,27 +868,68 @@ module.exports = class ScriptingProvider {
|
|
|
844
868
|
this._sortConvos()
|
|
845
869
|
}
|
|
846
870
|
|
|
847
|
-
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 }
|
|
848
879
|
const expandedConvos = []
|
|
849
880
|
debug(`ExpandConvos - Using utterances expansion mode: ${this.caps[Capabilities.SCRIPTING_UTTEXPANSION_MODE]}`)
|
|
850
881
|
this.convos.forEach((convo) => {
|
|
851
882
|
convo.expandPartialConvos()
|
|
852
|
-
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
|
+
}
|
|
853
897
|
})
|
|
854
898
|
this.convos = expandedConvos
|
|
855
|
-
|
|
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)
|
|
856
923
|
}
|
|
857
924
|
|
|
858
925
|
/**
|
|
859
|
-
*
|
|
860
|
-
* @param expandedConvos
|
|
926
|
+
* This is a generator function with yield
|
|
861
927
|
* @param currentConvo
|
|
862
928
|
* @param convoStepIndex
|
|
863
929
|
* @param convoStepsStack list of ConvoSteps
|
|
864
|
-
* @param context {width: }
|
|
865
930
|
* @private
|
|
866
931
|
*/
|
|
867
|
-
_expandConvo (
|
|
932
|
+
* _expandConvo (currentConvo, options, context, convoStepIndex = 0, convoStepsStack = []) {
|
|
868
933
|
const utterancePostfix = (lineTag, uttOrUserInput) => {
|
|
869
934
|
const naming = this.caps[Capabilities.SCRIPTING_UTTEXPANSION_NAMING_MODE] || Defaults.capabilities[Capabilities.SCRIPTING_UTTEXPANSION_NAMING_MODE]
|
|
870
935
|
if (naming === 'justLineTag') {
|
|
@@ -884,7 +949,7 @@ module.exports = class ScriptingProvider {
|
|
|
884
949
|
if (currentStep.sender === 'bot' || currentStep.sender === 'begin' || currentStep.sender === 'end') {
|
|
885
950
|
const currentStepsStack = convoStepsStack.slice()
|
|
886
951
|
currentStepsStack.push(_.cloneDeep(currentStep))
|
|
887
|
-
this._expandConvo(
|
|
952
|
+
yield * this._expandConvo(currentConvo, options, context, convoStepIndex + 1, currentStepsStack)
|
|
888
953
|
} else if (currentStep.sender === 'me') {
|
|
889
954
|
let useUnexpanded = true
|
|
890
955
|
if (currentStep.messageText) {
|
|
@@ -901,28 +966,32 @@ module.exports = class ScriptingProvider {
|
|
|
901
966
|
}
|
|
902
967
|
if (this.utterances[uttName]) {
|
|
903
968
|
const allutterances = this.utterances[uttName].utterances
|
|
904
|
-
const processSampleUtterances = (sampleutterances, myContext)
|
|
905
|
-
sampleutterances.
|
|
906
|
-
processSampleUtterance(
|
|
907
|
-
}
|
|
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
|
+
}
|
|
908
973
|
}
|
|
909
|
-
const processSampleUtterance = (sampleutterance, length, index, myContext)
|
|
910
|
-
const lineTag = `${index + 1}`.padStart(`${length}`.length, '0')
|
|
974
|
+
const processSampleUtterance = function * (sampleutterance, length, index, myContext) {
|
|
911
975
|
const currentStepsStack = convoStepsStack.slice()
|
|
912
976
|
if (uttArgs) {
|
|
913
977
|
sampleutterance = util.format(sampleutterance, ...uttArgs)
|
|
914
978
|
}
|
|
915
979
|
currentStepsStack.push(Object.assign(_.cloneDeep(currentStep), { messageText: sampleutterance }))
|
|
916
980
|
const currentConvoLabeled = _.cloneDeep(currentConvo)
|
|
917
|
-
|
|
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
|
+
}
|
|
918
985
|
if (!currentConvoLabeled.sourceTag) currentConvoLabeled.sourceTag = {}
|
|
919
986
|
if (!currentConvoLabeled.sourceTag.origConvoName) currentConvoLabeled.sourceTag.origConvoName = currentConvo.header.name
|
|
920
|
-
this._expandConvo(
|
|
921
|
-
}
|
|
922
|
-
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') {
|
|
923
992
|
if (_.isNil(context.indexExpansionModeWidth)) {
|
|
924
993
|
// executed for the first found utterance
|
|
925
|
-
processSampleUtterances(allutterances, Object.assign({}, context, { indexExpansionModeWidth: allutterances.length }))
|
|
994
|
+
yield * processSampleUtterances(allutterances, Object.assign({}, context, { indexExpansionModeWidth: allutterances.length }))
|
|
926
995
|
} else {
|
|
927
996
|
if (_.isNil(context.indexExpansionModeIndex)) {
|
|
928
997
|
throw new Error('indexExpansionModeIndex must be set!')
|
|
@@ -933,58 +1002,67 @@ module.exports = class ScriptingProvider {
|
|
|
933
1002
|
debug(`While expanding convos by index found in utterance "${uttName}" less examples (${allutterances.length}) as expected (${context.indexExpansionModeWidth})`)
|
|
934
1003
|
}
|
|
935
1004
|
const myContext = Object.assign({}, context, { indexExpansionModeWidth: Math.max(allutterances.length, context.indexExpansionModeWidth) })
|
|
936
|
-
processSampleUtterance(allutterances[localIndex], allutterances.length, localIndex, myContext)
|
|
1005
|
+
yield * processSampleUtterance(allutterances[localIndex], allutterances.length, localIndex, myContext)
|
|
937
1006
|
if (allutterances.length > context.indexExpansionModeWidth && context.indexExpansionModeIndex + 1 === context.indexExpansionModeWidth) {
|
|
938
1007
|
debug(`While expanding convos by index found in utterance "${uttName}" more examples (${allutterances.length}) as expected (${context.indexExpansionModeWidth})`)
|
|
939
1008
|
for (let i = context.indexExpansionModeWidth; i < allutterances.length; i++) {
|
|
940
1009
|
// if we found a utterance with more examples as any utterances before, we have to start new 'thread'
|
|
941
1010
|
const myContext = Object.assign({}, context, { indexExpansionModeWidth: allutterances.length, indexExpansionModeIndex: i })
|
|
942
|
-
processSampleUtterance(allutterances[i], allutterances.length, i, myContext)
|
|
1011
|
+
yield * processSampleUtterance(allutterances[i], allutterances.length, i, myContext)
|
|
943
1012
|
}
|
|
944
1013
|
}
|
|
945
1014
|
}
|
|
946
1015
|
} else {
|
|
947
1016
|
if (this.caps[Capabilities.SCRIPTING_UTTEXPANSION_MODE] === 'first') {
|
|
948
|
-
processSampleUtterances([allutterances[0]])
|
|
1017
|
+
yield * processSampleUtterances([allutterances[0]], context)
|
|
949
1018
|
} else if (this.caps[Capabilities.SCRIPTING_UTTEXPANSION_MODE] === 'random') {
|
|
950
|
-
processSampleUtterances(allutterances
|
|
1019
|
+
yield * processSampleUtterances(allutterances
|
|
951
1020
|
.map(x => ({ x, r: Math.random() }))
|
|
952
1021
|
.sort((a, b) => a.r - b.r)
|
|
953
1022
|
.map(a => a.x)
|
|
954
|
-
.slice(0, this.caps[Capabilities.SCRIPTING_UTTEXPANSION_RANDOM_COUNT]))
|
|
1023
|
+
.slice(0, this.caps[Capabilities.SCRIPTING_UTTEXPANSION_RANDOM_COUNT]), context)
|
|
955
1024
|
} else {
|
|
956
|
-
processSampleUtterances(allutterances)
|
|
1025
|
+
yield * processSampleUtterances(allutterances, context)
|
|
957
1026
|
}
|
|
958
1027
|
}
|
|
959
1028
|
useUnexpanded = false
|
|
960
1029
|
}
|
|
961
1030
|
}
|
|
962
1031
|
if (currentStep.userInputs && currentStep.userInputs.length > 0) {
|
|
963
|
-
currentStep.userInputs.
|
|
1032
|
+
for (let uiIndex = 0; uiIndex < currentStep.userInputs.length; uiIndex++) {
|
|
1033
|
+
const ui = currentStep.userInputs[uiIndex]
|
|
964
1034
|
const userInput = this.userInputs[ui.name]
|
|
965
1035
|
if (userInput && userInput.expandConvo) {
|
|
966
1036
|
const expandedUserInputs = userInput.expandConvo({ convo: currentConvo, convoStep: currentStep, args: ui.args })
|
|
967
1037
|
if (expandedUserInputs && expandedUserInputs.length > 0) {
|
|
968
1038
|
// let sampleinputs = expandedUserInputs
|
|
969
|
-
const processSampleInputs = (sampleinputs, myContext, uiIndex)
|
|
970
|
-
sampleinputs.
|
|
971
|
-
processSampleInput(
|
|
972
|
-
}
|
|
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
|
+
}
|
|
973
1043
|
}
|
|
974
|
-
const processSampleInput = (sampleinput, length, index, myContext, uiIndex)
|
|
975
|
-
const lineTag = `${index + 1}`.padStart(`${length}`.length, '0')
|
|
1044
|
+
const processSampleInput = function * (sampleinput, length, index, myContext, uiIndex) {
|
|
976
1045
|
const currentStepsStack = convoStepsStack.slice()
|
|
977
1046
|
const currentStepMod = _.cloneDeep(currentStep)
|
|
978
1047
|
currentStepMod.userInputs[uiIndex] = sampleinput
|
|
979
1048
|
|
|
980
1049
|
currentStepsStack.push(currentStepMod)
|
|
981
1050
|
const currentConvoLabeled = _.cloneDeep(currentConvo)
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
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') {
|
|
986
1064
|
if (_.isNil(context.indexExpansionModeWidth)) {
|
|
987
|
-
processSampleInputs(expandedUserInputs, Object.assign({}, context, { indexExpansionModeWidth: expandedUserInputs.length }), uiIndex)
|
|
1065
|
+
yield * processSampleInputs(expandedUserInputs, Object.assign({}, context, { indexExpansionModeWidth: expandedUserInputs.length }), uiIndex)
|
|
988
1066
|
} else {
|
|
989
1067
|
if (_.isNil(context.indexExpansionModeIndex)) {
|
|
990
1068
|
throw new Error('indexExpansionModeIndex must be set!')
|
|
@@ -995,20 +1073,20 @@ module.exports = class ScriptingProvider {
|
|
|
995
1073
|
debug(`While expanding convos by index found user input "${ui.name}, ${ui.args}" less examples (${expandedUserInputs.length}) as expected (${context.indexExpansionModeWidth})`)
|
|
996
1074
|
}
|
|
997
1075
|
const myContext = Object.assign({}, context, { indexExpansionModeWidth: Math.max(expandedUserInputs.length, context.indexExpansionModeWidth) })
|
|
998
|
-
processSampleInput(expandedUserInputs[localIndex], expandedUserInputs.length, localIndex, myContext, uiIndex)
|
|
1076
|
+
yield * processSampleInput(expandedUserInputs[localIndex], expandedUserInputs.length, localIndex, myContext, uiIndex)
|
|
999
1077
|
if (expandedUserInputs.length > context.indexExpansionModeWidth && context.indexExpansionModeIndex + 1 === context.indexExpansionModeWidth) {
|
|
1000
1078
|
debug(`While expanding convos by index found user input "${ui.name}, ${ui.args}" more examples (${expandedUserInputs.length}) as expected (${context.indexExpansionModeWidth})`)
|
|
1001
1079
|
for (let i = context.indexExpansionModeWidth; i < expandedUserInputs.length; i++) {
|
|
1002
1080
|
const myContext = Object.assign({}, context, { indexExpansionModeWidth: expandedUserInputs.length, indexExpansionModeIndex: i })
|
|
1003
|
-
processSampleInput(expandedUserInputs[i], expandedUserInputs.length, i, myContext, uiIndex)
|
|
1081
|
+
yield * processSampleInput(expandedUserInputs[i], expandedUserInputs.length, i, myContext, uiIndex)
|
|
1004
1082
|
}
|
|
1005
1083
|
}
|
|
1006
1084
|
}
|
|
1007
1085
|
} else {
|
|
1008
1086
|
if (this.caps[Capabilities.SCRIPTING_UTTEXPANSION_MODE] === 'first') {
|
|
1009
|
-
processSampleInputs([expandedUserInputs[0]], context, uiIndex)
|
|
1087
|
+
yield * processSampleInputs([expandedUserInputs[0]], context, uiIndex)
|
|
1010
1088
|
} else if (this.caps[Capabilities.SCRIPTING_UTTEXPANSION_MODE] === 'random') {
|
|
1011
|
-
processSampleInputs(expandedUserInputs
|
|
1089
|
+
yield * processSampleInputs(expandedUserInputs
|
|
1012
1090
|
.map(x => ({
|
|
1013
1091
|
x,
|
|
1014
1092
|
r: Math.random()
|
|
@@ -1017,35 +1095,49 @@ module.exports = class ScriptingProvider {
|
|
|
1017
1095
|
.map(a => a.x)
|
|
1018
1096
|
.slice(0, this.caps[Capabilities.SCRIPTING_UTTEXPANSION_RANDOM_COUNT]), context, uiIndex)
|
|
1019
1097
|
} else {
|
|
1020
|
-
processSampleInputs(expandedUserInputs, context, uiIndex)
|
|
1098
|
+
yield * processSampleInputs(expandedUserInputs, context, uiIndex)
|
|
1021
1099
|
}
|
|
1022
1100
|
}
|
|
1023
1101
|
useUnexpanded = false
|
|
1024
1102
|
}
|
|
1025
1103
|
}
|
|
1026
|
-
}
|
|
1104
|
+
}
|
|
1027
1105
|
}
|
|
1028
1106
|
if (useUnexpanded) {
|
|
1029
1107
|
const currentStepsStack = convoStepsStack.slice()
|
|
1030
1108
|
currentStepsStack.push(_.cloneDeep(currentStep))
|
|
1031
|
-
this._expandConvo(
|
|
1109
|
+
yield * this._expandConvo(currentConvo, options, context, convoStepIndex + 1, currentStepsStack)
|
|
1032
1110
|
}
|
|
1033
1111
|
}
|
|
1034
1112
|
} else {
|
|
1035
|
-
|
|
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
|
+
}
|
|
1036
1122
|
}
|
|
1037
1123
|
}
|
|
1038
1124
|
|
|
1039
1125
|
_sortConvos () {
|
|
1040
1126
|
this.convos = _.sortBy(this.convos, [(convo) => convo.header.sort || convo.header.name])
|
|
1127
|
+
this._updateConvos()
|
|
1128
|
+
}
|
|
1129
|
+
|
|
1130
|
+
_updateConvos () {
|
|
1041
1131
|
let i = 0
|
|
1042
1132
|
this.convos.forEach((convo) => {
|
|
1043
|
-
convo
|
|
1044
|
-
|
|
1045
|
-
convo.header.projectname
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
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
|
+
}
|
|
1049
1141
|
}
|
|
1050
1142
|
})
|
|
1051
1143
|
}
|
|
@@ -1056,7 +1148,11 @@ module.exports = class ScriptingProvider {
|
|
|
1056
1148
|
} else if (convos) {
|
|
1057
1149
|
this.convos.push(convos)
|
|
1058
1150
|
}
|
|
1059
|
-
this.
|
|
1151
|
+
if (this.convos.filter(c => _.isNil(c))) {
|
|
1152
|
+
this._updateConvos()
|
|
1153
|
+
} else {
|
|
1154
|
+
this._sortConvos()
|
|
1155
|
+
}
|
|
1060
1156
|
}
|
|
1061
1157
|
|
|
1062
1158
|
AddUtterances (utterances) {
|
|
@@ -1310,4 +1406,30 @@ module.exports = class ScriptingProvider {
|
|
|
1310
1406
|
...lines,
|
|
1311
1407
|
'}'].join('\r\n')
|
|
1312
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
|
+
}
|
|
1313
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))
|