botium-core 1.13.1 → 1.13.4
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/.eslintrc.js +6 -3
- package/dist/botium-cjs.js +291 -86
- package/dist/botium-cjs.js.map +1 -1
- package/dist/botium-es.js +290 -86
- package/dist/botium-es.js.map +1 -1
- package/package.json +3 -1
- package/src/Capabilities.js +4 -1
- package/src/Defaults.js +4 -0
- package/src/containers/plugins/SimpleRestContainer.js +23 -16
- package/src/grid/inbound/proxy.js +2 -1
- package/src/mocks/BotiumMockScripting.js +1 -0
- package/src/scripting/Convo.js +16 -10
- package/src/scripting/MatchFunctions.js +10 -0
- package/src/scripting/ScriptingProvider.js +162 -69
- package/src/scripting/logichook/LogicHookConsts.js +1 -1
- package/src/scripting/logichook/asserter/WerAsserter.js +59 -0
- package/src/scripting/logichook/logichooks/UpdateCustomLogicHook.js +3 -2
- package/test/compiler/compilercsv.spec.js +104 -3
- package/test/compiler/compilerjson.spec.js +0 -2
- package/test/compiler/compilerxlsx.spec.js +1 -1
- package/test/compiler/convos/csv/utterances_liveperson2.csv +12 -0
- package/test/connectors/simplerest.spec.js +1012 -969
- package/test/convo/fillAndApplyScriptingMemory.spec.js +804 -785
- package/test/convo/partialconvo.spec.js +345 -339
- package/test/driver/capabilities.spec.js +156 -151
- package/test/logichooks/hookfromsrc.spec.js +79 -73
- package/test/plugins/plugins.spec.js +44 -42
- package/test/scripting/asserters/buttonsAsserter.spec.js +257 -240
- package/test/scripting/asserters/cardsAsserter.spec.js +214 -212
- package/test/scripting/asserters/convos/wer_threshold_nok.yml +7 -0
- package/test/scripting/asserters/convos/wer_threshold_ok.yml +7 -0
- package/test/scripting/asserters/intentConfidenceAsserter.spec.js +34 -35
- package/test/scripting/asserters/jsonpathAsserter.spec.js +307 -308
- package/test/scripting/asserters/mediaAsserter.spec.js +236 -234
- package/test/scripting/asserters/werAsserter.spec.js +51 -0
- package/test/scripting/logichooks/setClearScriptingMemory.spec.js +202 -192
- package/test/scripting/matching/matchingmode.spec.js +306 -258
- package/test/scripting/scriptingProvider.spec.js +720 -630
- package/test/scripting/scriptingmemory/fillScriptingMemoryFromFile.spec.js +299 -281
- package/test/scripting/scriptingmemory/useScriptingMemoryForAssertion.spec.js +94 -80
- package/test/scripting/userinputs/defaultUserInputs.spec.js +233 -127
- package/test/scripting/userinputs/mediaInputConvos.spec.js +409 -403
- package/test/scripting/utteranceexpansion/associateByIndex.spec.js +259 -0
- package/test/scripting/utteranceexpansion/convos/associate_utterances_by_index.json +33 -0
- package/test/scripting/utteranceexpansion/convos/media.convo.txt +19 -0
- package/test/scripting/utteranceexpansion/files/step0voice0.wav +0 -0
- package/test/scripting/utteranceexpansion/files/step0voice1.wav +0 -0
- package/test/scripting/utteranceexpansion/files/step0voice2.wav +0 -0
- package/test/scripting/utteranceexpansion/files/step1voice0.wav +0 -0
- package/test/scripting/utteranceexpansion/files/step2voice0.wav +0 -0
- package/test/scripting/utteranceexpansion/files/step2voice1.wav +0 -0
- package/test/scripting/utteranceexpansion/files/step2voice2.wav +0 -0
- package/test/scripting/utteranceexpansion/files/step2voice4.wav +0 -0
- package/test/scripting/utteranceexpansion/files/step2voice5.wav +0 -0
- package/test/security/allowUnsafe.spec.js +274 -268
- package/test/utils.spec.js +40 -38
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "botium-core",
|
|
3
|
-
"version": "1.13.
|
|
3
|
+
"version": "1.13.4",
|
|
4
4
|
"description": "The Selenium for Chatbots",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"module": "dist/botium-es.js",
|
|
@@ -66,6 +66,7 @@
|
|
|
66
66
|
"swagger-ui-express": "^4.4.0",
|
|
67
67
|
"uuid": "^8.3.2",
|
|
68
68
|
"vm2": "^3.9.10",
|
|
69
|
+
"word-error-rate": "0.0.7",
|
|
69
70
|
"write-yaml": "^1.0.0",
|
|
70
71
|
"xlsx": "^0.18.5",
|
|
71
72
|
"xregexp": "^5.1.1",
|
|
@@ -82,6 +83,7 @@
|
|
|
82
83
|
"eslint": "^8.19.0",
|
|
83
84
|
"eslint-config-standard": "^17.0.0",
|
|
84
85
|
"eslint-plugin-import": "^2.26.0",
|
|
86
|
+
"eslint-plugin-mocha": "^10.1.0",
|
|
85
87
|
"eslint-plugin-n": "^15.2.4",
|
|
86
88
|
"eslint-plugin-promise": "^6.0.0",
|
|
87
89
|
"eslint-plugin-standard": "^4.1.0",
|
package/src/Capabilities.js
CHANGED
|
@@ -126,12 +126,15 @@ module.exports = {
|
|
|
126
126
|
SCRIPTING_ENABLE_MULTIPLE_ASSERT_ERRORS: 'SCRIPTING_ENABLE_MULTIPLE_ASSERT_ERRORS',
|
|
127
127
|
SCRIPTING_ENABLE_SKIP_ASSERT_ERRORS: 'SCRIPTING_ENABLE_SKIP_ASSERT_ERRORS',
|
|
128
128
|
SCRIPTING_FORCE_BOT_CONSUMED: 'SCRIPTING_FORCE_BOT_CONSUMED',
|
|
129
|
-
// regexp, regexpIgnoreCase, wildcard, wildcardIgnoreCase, wildcardExact, wildcardExactIgnoreCase, include, includeIgnoreCase, equals, equalsIgnoreCase
|
|
129
|
+
// regexp, regexpIgnoreCase, wildcard, wildcardIgnoreCase, wildcardExact, wildcardExactIgnoreCase, include, includeIgnoreCase, equals, equalsIgnoreCase, wer
|
|
130
130
|
SCRIPTING_MATCHING_MODE: 'SCRIPTING_MATCHING_MODE',
|
|
131
|
+
SCRIPTING_MATCHING_MODE_ARGS: 'SCRIPTING_MATCHING_MODE_ARGS',
|
|
131
132
|
// all, first, random
|
|
132
133
|
SCRIPTING_UTTEXPANSION_MODE: 'SCRIPTING_UTTEXPANSION_MODE',
|
|
133
134
|
SCRIPTING_UTTEXPANSION_RANDOM_COUNT: 'SCRIPTING_UTTEXPANSION_RANDOM_COUNT',
|
|
134
135
|
SCRIPTING_UTTEXPANSION_INCOMPREHENSION: 'SCRIPTING_UTTEXPANSION_INCOMPREHENSION',
|
|
136
|
+
SCRIPTING_UTTEXPANSION_INCOMPREHENSIONINTENTS: 'SCRIPTING_UTTEXPANSION_INCOMPREHENSIONINTENTS',
|
|
137
|
+
SCRIPTING_UTTEXPANSION_INCOMPREHENSIONUTTS: 'SCRIPTING_UTTEXPANSION_INCOMPREHENSIONUTTS',
|
|
135
138
|
SCRIPTING_UTTEXPANSION_USENAMEASINTENT: 'SCRIPTING_UTTEXPANSION_USENAMEASINTENT',
|
|
136
139
|
// justLineTag, utterance
|
|
137
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,
|
|
@@ -42,7 +42,7 @@ module.exports = class SimpleRestContainer {
|
|
|
42
42
|
return qr[0]
|
|
43
43
|
})
|
|
44
44
|
for (const event of sortedEvents) {
|
|
45
|
-
setTimeout(() => this._processBodyAsync(event.body, true, !!this.caps[Capabilities.SIMPLEREST_INBOUND_UPDATE_CONTEXT]), 0)
|
|
45
|
+
setTimeout(() => this._processBodyAsync(event.body, event.headers, true, !!this.caps[Capabilities.SIMPLEREST_INBOUND_UPDATE_CONTEXT]), 0)
|
|
46
46
|
}
|
|
47
47
|
}, debounceTimeout)
|
|
48
48
|
}
|
|
@@ -142,13 +142,13 @@ module.exports = class SimpleRestContainer {
|
|
|
142
142
|
(pingComplete) => {
|
|
143
143
|
if (this.caps[Capabilities.SIMPLEREST_PING_URL]) {
|
|
144
144
|
this._makeCall('SIMPLEREST_PING')
|
|
145
|
-
.then(body => {
|
|
145
|
+
.then(({ body, headers }) => {
|
|
146
146
|
if (this.caps[Capabilities.SIMPLEREST_PING_UPDATE_CONTEXT] || this.caps[Capabilities.SIMPLEREST_PING_PROCESS_RESPONSE]) {
|
|
147
147
|
return this._parseResponseBody(body)
|
|
148
148
|
.then(body => {
|
|
149
149
|
if (body) {
|
|
150
150
|
debug(`Ping Uri ${this.caps[Capabilities.SIMPLEREST_PING_URL]} returned JSON response: ${botiumUtils.shortenJsonString(body)}`)
|
|
151
|
-
return this._processBodyAsync(body, !!this.caps[Capabilities.SIMPLEREST_PING_PROCESS_RESPONSE], !!this.caps[Capabilities.SIMPLEREST_PING_UPDATE_CONTEXT])
|
|
151
|
+
return this._processBodyAsync(body, headers, !!this.caps[Capabilities.SIMPLEREST_PING_PROCESS_RESPONSE], !!this.caps[Capabilities.SIMPLEREST_PING_UPDATE_CONTEXT])
|
|
152
152
|
} else {
|
|
153
153
|
debug(`Ping Uri ${this.caps[Capabilities.SIMPLEREST_PING_URL]} didn't return JSON response, ignoring it.`)
|
|
154
154
|
}
|
|
@@ -178,13 +178,13 @@ module.exports = class SimpleRestContainer {
|
|
|
178
178
|
this.processInbound = true
|
|
179
179
|
if (this.caps[Capabilities.SIMPLEREST_START_URL]) {
|
|
180
180
|
this._makeCall('SIMPLEREST_START')
|
|
181
|
-
.then(body => {
|
|
181
|
+
.then(({ body, headers }) => {
|
|
182
182
|
if (this.caps[Capabilities.SIMPLEREST_START_UPDATE_CONTEXT] || this.caps[Capabilities.SIMPLEREST_START_PROCESS_RESPONSE]) {
|
|
183
183
|
return this._parseResponseBody(body)
|
|
184
184
|
.then(body => {
|
|
185
185
|
if (body) {
|
|
186
186
|
debug(`Start Uri ${this.caps[Capabilities.SIMPLEREST_START_URL]} returned JSON response: ${botiumUtils.shortenJsonString(body)}`)
|
|
187
|
-
return this._processBodyAsync(body, !!this.caps[Capabilities.SIMPLEREST_START_PROCESS_RESPONSE], !!this.caps[Capabilities.SIMPLEREST_START_UPDATE_CONTEXT])
|
|
187
|
+
return this._processBodyAsync(body, headers, !!this.caps[Capabilities.SIMPLEREST_START_PROCESS_RESPONSE], !!this.caps[Capabilities.SIMPLEREST_START_UPDATE_CONTEXT])
|
|
188
188
|
} else {
|
|
189
189
|
debug(`Start Uri ${this.caps[Capabilities.SIMPLEREST_START_URL]} didn't return JSON response, ignoring it.`)
|
|
190
190
|
}
|
|
@@ -235,10 +235,10 @@ module.exports = class SimpleRestContainer {
|
|
|
235
235
|
}
|
|
236
236
|
|
|
237
237
|
// Separated just for better module testing
|
|
238
|
-
async _processBodyAsync (body, isFromUser, updateContext) {
|
|
238
|
+
async _processBodyAsync (body, headers, isFromUser, updateContext) {
|
|
239
239
|
const p = async () => {
|
|
240
240
|
try {
|
|
241
|
-
const results = await this._processBodyAsyncImpl(body, isFromUser, updateContext)
|
|
241
|
+
const results = await this._processBodyAsyncImpl(body, headers, isFromUser, updateContext)
|
|
242
242
|
if (results) {
|
|
243
243
|
for (const result of results) {
|
|
244
244
|
setTimeout(() => this.queueBotSays(result), 0)
|
|
@@ -266,7 +266,8 @@ module.exports = class SimpleRestContainer {
|
|
|
266
266
|
}
|
|
267
267
|
|
|
268
268
|
// Separated just for better module testing
|
|
269
|
-
async _processBodyAsyncImpl (body, isFromUser, updateContext) {
|
|
269
|
+
async _processBodyAsyncImpl (body, headers, isFromUser, updateContext) {
|
|
270
|
+
this.view.response = { body, headers }
|
|
270
271
|
if (updateContext) {
|
|
271
272
|
const mergeMode = this.caps[Capabilities.SIMPLEREST_CONTEXT_MERGE_OR_REPLACE]
|
|
272
273
|
const jsonPathsContext = getAllCapValues(Capabilities.SIMPLEREST_CONTEXT_JSONPATH, this.caps)
|
|
@@ -451,7 +452,7 @@ module.exports = class SimpleRestContainer {
|
|
|
451
452
|
}
|
|
452
453
|
|
|
453
454
|
if (body) {
|
|
454
|
-
debug(`got response code: ${response.statusCode}, body: ${botiumUtils.shortenJsonString(body)}`)
|
|
455
|
+
debug(`got response code: ${response.statusCode}, body: ${botiumUtils.shortenJsonString(body)}, headers: ${botiumUtils.shortenJsonString(response.headers)}`)
|
|
455
456
|
this._storeCookiesFromResponse(response)
|
|
456
457
|
try {
|
|
457
458
|
body = await this._parseResponseBody(body)
|
|
@@ -463,7 +464,7 @@ module.exports = class SimpleRestContainer {
|
|
|
463
464
|
}
|
|
464
465
|
|
|
465
466
|
if (body) {
|
|
466
|
-
this._processBodyAsync(body, isFromUser, updateContext).then(() => resolve(this)).then(() => this._emptyWaitProcessQueue())
|
|
467
|
+
this._processBodyAsync(body, response.headers, isFromUser, updateContext).then(() => resolve(this)).then(() => this._emptyWaitProcessQueue())
|
|
467
468
|
} else {
|
|
468
469
|
debug('ignoring response body (no string and no JSON object)')
|
|
469
470
|
resolve(this)
|
|
@@ -520,6 +521,9 @@ module.exports = class SimpleRestContainer {
|
|
|
520
521
|
try {
|
|
521
522
|
requestOptions.body = this._getMustachedCap(Capabilities.SIMPLEREST_BODY_TEMPLATE, !bodyRaw)
|
|
522
523
|
requestOptions.json = !bodyRaw
|
|
524
|
+
if (requestOptions.json && (!requestOptions.body || Object.keys(requestOptions.body).length === 0)) {
|
|
525
|
+
debug(`warning: requestOptions.body content seems to be empty - ${requestOptions.body} - capability: "${this.caps[Capabilities.SIMPLEREST_BODY_TEMPLATE]}"`)
|
|
526
|
+
}
|
|
523
527
|
} catch (err) {
|
|
524
528
|
throw new Error(`composing body from SIMPLEREST_BODY_TEMPLATE failed (${err.message})`)
|
|
525
529
|
}
|
|
@@ -596,9 +600,9 @@ module.exports = class SimpleRestContainer {
|
|
|
596
600
|
debug(`_waitForUrlResponse success on url check ${pingConfig.uri}: ${response.statusCode}/${response.statusMessage}`)
|
|
597
601
|
this._storeCookiesFromResponse(response)
|
|
598
602
|
if (debug.enabled && body) {
|
|
599
|
-
debug(botiumUtils.shortenJsonString(body))
|
|
603
|
+
debug(`body: ${botiumUtils.shortenJsonString(body)}, headers: ${botiumUtils.shortenJsonString(response.headers)}`)
|
|
600
604
|
}
|
|
601
|
-
return body
|
|
605
|
+
return { body, headers: response.headers }
|
|
602
606
|
}
|
|
603
607
|
}
|
|
604
608
|
}
|
|
@@ -635,7 +639,10 @@ module.exports = class SimpleRestContainer {
|
|
|
635
639
|
try {
|
|
636
640
|
return JSON.parse(raw)
|
|
637
641
|
} catch (err) {
|
|
638
|
-
|
|
642
|
+
if (debug.enabled) {
|
|
643
|
+
debug(`JSON parsing failed (${err.message}) for: ${botiumUtils.shortenJsonString(raw)}`)
|
|
644
|
+
}
|
|
645
|
+
throw new Error(`JSON parsing failed - try to use {{#fnc.jsonify}}{{xxx}}{{/fnc.jsonify}} to escape JSON special characters (ERR: ${err.message})`)
|
|
639
646
|
}
|
|
640
647
|
} else {
|
|
641
648
|
return raw
|
|
@@ -673,7 +680,7 @@ module.exports = class SimpleRestContainer {
|
|
|
673
680
|
this.inboundEvents.push(event)
|
|
674
681
|
this._processOrderedInboundEventsArrayAsync()
|
|
675
682
|
} else {
|
|
676
|
-
setTimeout(() => this._processBodyAsync(event.body, true, !!this.caps[Capabilities.SIMPLEREST_INBOUND_UPDATE_CONTEXT]), 0)
|
|
683
|
+
setTimeout(() => this._processBodyAsync(event.body, event.headers, true, !!this.caps[Capabilities.SIMPLEREST_INBOUND_UPDATE_CONTEXT]), 0)
|
|
677
684
|
}
|
|
678
685
|
}
|
|
679
686
|
|
|
@@ -797,7 +804,7 @@ module.exports = class SimpleRestContainer {
|
|
|
797
804
|
debug(botiumUtils.shortenJsonString(body))
|
|
798
805
|
}
|
|
799
806
|
} else if (body) {
|
|
800
|
-
debug(`_runPolling: got response code: ${response.statusCode}, body: ${botiumUtils.shortenJsonString(body)}`)
|
|
807
|
+
debug(`_runPolling: got response code: ${response.statusCode}, body: ${botiumUtils.shortenJsonString(body)}, headers: ${botiumUtils.shortenJsonString(response.headers)}`)
|
|
801
808
|
this._storeCookiesFromResponse(response)
|
|
802
809
|
try {
|
|
803
810
|
body = await this._parseResponseBody(body)
|
|
@@ -806,7 +813,7 @@ module.exports = class SimpleRestContainer {
|
|
|
806
813
|
return
|
|
807
814
|
}
|
|
808
815
|
if (body) {
|
|
809
|
-
setTimeout(() => this._processBodyAsync(body, true, !!this.caps[Capabilities.SIMPLEREST_POLL_UPDATE_CONTEXT]), 0)
|
|
816
|
+
setTimeout(() => this._processBodyAsync(body, response.headers, true, !!this.caps[Capabilities.SIMPLEREST_POLL_UPDATE_CONTEXT]), 0)
|
|
810
817
|
} else {
|
|
811
818
|
debug('_runPolling: ignoring response body (no string and no JSON object)')
|
|
812
819
|
}
|
|
@@ -29,7 +29,8 @@ const setupEndpoints = ({ app, endpoint, middleware, processEvent }) => {
|
|
|
29
29
|
processEvent({
|
|
30
30
|
originalUrl: req.originalUrl,
|
|
31
31
|
originalMethod: req.method,
|
|
32
|
-
body: req.body
|
|
32
|
+
body: req.body,
|
|
33
|
+
headers: req.headers
|
|
33
34
|
})
|
|
34
35
|
res.status(200).json({}).end()
|
|
35
36
|
} else {
|
package/src/scripting/Convo.js
CHANGED
|
@@ -91,9 +91,9 @@ class ConvoStep {
|
|
|
91
91
|
'#' + this.sender +
|
|
92
92
|
' - ' + (this.optional ? '?' : '') + (this.not ? '!' : '') +
|
|
93
93
|
(this.messageText || '') +
|
|
94
|
-
(this.asserters && this.asserters.length > 0 ? ' ' + this.asserters.map(a => a.toString()).join('
|
|
95
|
-
(this.logicHooks && this.logicHooks.length > 0 ? ' ' + this.logicHooks.map(l => l.toString()).join('
|
|
96
|
-
(this.userInputs && this.userInputs.length > 0 ? ' ' + this.userInputs.map(u => u.toString()).join('
|
|
94
|
+
(this.asserters && this.asserters.length > 0 ? ' ' + this.asserters.map(a => a.toString()).join(' ') : '') +
|
|
95
|
+
(this.logicHooks && this.logicHooks.length > 0 ? ' ' + this.logicHooks.map(l => l.toString()).join(' ') : '') +
|
|
96
|
+
(this.userInputs && this.userInputs.length > 0 ? ' ' + this.userInputs.map(u => u.toString()).join(' ') : '')
|
|
97
97
|
}
|
|
98
98
|
}
|
|
99
99
|
|
|
@@ -119,7 +119,7 @@ class Transcript {
|
|
|
119
119
|
}
|
|
120
120
|
}
|
|
121
121
|
|
|
122
|
-
class TranscriptAttachment {
|
|
122
|
+
class TranscriptAttachment {
|
|
123
123
|
constructor (fromJson = {}) {
|
|
124
124
|
this.name = fromJson.name
|
|
125
125
|
this.mimeType = fromJson.mimeType
|
|
@@ -714,9 +714,15 @@ class Convo {
|
|
|
714
714
|
}
|
|
715
715
|
}
|
|
716
716
|
|
|
717
|
-
module
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
717
|
+
module.exports = {
|
|
718
|
+
Convo,
|
|
719
|
+
ConvoHeader,
|
|
720
|
+
ConvoStep,
|
|
721
|
+
ConvoStepAssert,
|
|
722
|
+
ConvoStepLogicHook,
|
|
723
|
+
ConvoStepUserInput,
|
|
724
|
+
Transcript,
|
|
725
|
+
TranscriptAttachment,
|
|
726
|
+
TranscriptStep,
|
|
727
|
+
TranscriptError
|
|
728
|
+
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
const _ = require('lodash')
|
|
2
|
+
const speechScorer = require('word-error-rate')
|
|
2
3
|
|
|
3
4
|
const { toString, quoteRegexpString } = require('./helper')
|
|
4
5
|
|
|
@@ -79,6 +80,12 @@ const equals = (ignoreCase) => (botresponse, utterance) => {
|
|
|
79
80
|
return botresponse === utterance
|
|
80
81
|
}
|
|
81
82
|
|
|
83
|
+
const wer = () => (botresponse, utterance, args) => {
|
|
84
|
+
botresponse = _normalize(botresponse || '')
|
|
85
|
+
utterance = toString(utterance || '')
|
|
86
|
+
return speechScorer.wordErrorRate(botresponse, utterance) <= args[0]
|
|
87
|
+
}
|
|
88
|
+
|
|
82
89
|
const getMatchFunction = (matchingMode) => {
|
|
83
90
|
if (matchingMode === 'regexp' || matchingMode === 'regexpIgnoreCase') {
|
|
84
91
|
return regexp(matchingMode === 'regexpIgnoreCase')
|
|
@@ -90,6 +97,8 @@ const getMatchFunction = (matchingMode) => {
|
|
|
90
97
|
return include(matchingMode === 'includeIgnoreCase' || matchingMode === 'includeLowerCase')
|
|
91
98
|
} else if (matchingMode === 'equals' || matchingMode === 'equalsIgnoreCase') {
|
|
92
99
|
return equals(matchingMode === 'equalsIgnoreCase')
|
|
100
|
+
} else if (matchingMode === 'wer') {
|
|
101
|
+
return wer()
|
|
93
102
|
} else {
|
|
94
103
|
return equals(false)
|
|
95
104
|
}
|
|
@@ -101,5 +110,6 @@ module.exports = {
|
|
|
101
110
|
wildcardExact,
|
|
102
111
|
include,
|
|
103
112
|
equals,
|
|
113
|
+
wer,
|
|
104
114
|
getMatchFunction
|
|
105
115
|
}
|
|
@@ -134,7 +134,8 @@ module.exports = class ScriptingProvider {
|
|
|
134
134
|
tomatch = [tomatch]
|
|
135
135
|
}
|
|
136
136
|
debug(`assertBotResponse ${stepTag} ${meMsg ? `(${meMsg}) ` : ''}BOT: ${botresponse} = ${tomatch} ...`)
|
|
137
|
-
const found = _.find(tomatch, (utt) => this.matchFn(botresponse, utt))
|
|
137
|
+
const found = _.find(tomatch, (utt) => this.matchFn(botresponse, utt, this.caps[Capabilities.SCRIPTING_MATCHING_MODE_ARGS]))
|
|
138
|
+
const asserterType = this.caps[Capabilities.SCRIPTING_MATCHING_MODE] === 'wer' ? 'WerAsserter' : 'TextMatchAsserter'
|
|
138
139
|
if (_.isNil(found)) {
|
|
139
140
|
let message = `${stepTag}: Bot response `
|
|
140
141
|
message += meMsg ? `(on ${meMsg}) ` : ''
|
|
@@ -146,7 +147,7 @@ module.exports = class ScriptingProvider {
|
|
|
146
147
|
message,
|
|
147
148
|
{
|
|
148
149
|
type: 'asserter',
|
|
149
|
-
source:
|
|
150
|
+
source: asserterType,
|
|
150
151
|
context: {
|
|
151
152
|
stepTag
|
|
152
153
|
},
|
|
@@ -164,7 +165,8 @@ module.exports = class ScriptingProvider {
|
|
|
164
165
|
nottomatch = [nottomatch]
|
|
165
166
|
}
|
|
166
167
|
debug(`assertBotNotResponse ${stepTag} ${meMsg ? `(${meMsg}) ` : ''}BOT: ${botresponse} != ${nottomatch} ...`)
|
|
167
|
-
const found = _.find(nottomatch, (utt) => this.matchFn(botresponse, utt))
|
|
168
|
+
const found = _.find(nottomatch, (utt) => this.matchFn(botresponse, utt, this.caps[Capabilities.SCRIPTING_MATCHING_MODE_ARGS]))
|
|
169
|
+
const asserterType = this.caps[Capabilities.SCRIPTING_MATCHING_MODE] === 'wer' ? 'WerAsserter' : 'TextMatchAsserter'
|
|
168
170
|
if (!_.isNil(found)) {
|
|
169
171
|
let message = `${stepTag}: Bot response `
|
|
170
172
|
message += meMsg ? `(on ${meMsg}) ` : ''
|
|
@@ -176,7 +178,7 @@ module.exports = class ScriptingProvider {
|
|
|
176
178
|
message,
|
|
177
179
|
{
|
|
178
180
|
type: 'asserter',
|
|
179
|
-
source:
|
|
181
|
+
source: asserterType,
|
|
180
182
|
context: {
|
|
181
183
|
stepTag
|
|
182
184
|
},
|
|
@@ -401,7 +403,7 @@ module.exports = class ScriptingProvider {
|
|
|
401
403
|
}
|
|
402
404
|
|
|
403
405
|
Match (botresponse, utterance) {
|
|
404
|
-
return this.matchFn(botresponse, utterance)
|
|
406
|
+
return this.matchFn(botresponse, utterance, this.caps[Capabilities.SCRIPTING_MATCHING_MODE_ARGS])
|
|
405
407
|
}
|
|
406
408
|
|
|
407
409
|
Compile (scriptBuffer, scriptFormat, scriptType) {
|
|
@@ -768,31 +770,79 @@ module.exports = class ScriptingProvider {
|
|
|
768
770
|
this._sortConvos()
|
|
769
771
|
}
|
|
770
772
|
|
|
771
|
-
ExpandUtterancesToConvos ({ useNameAsIntent, incomprehensionUtt } = {}) {
|
|
773
|
+
ExpandUtterancesToConvos ({ useNameAsIntent, incomprehensionIntents, incomprehensionUtts, incomprehensionUtt } = {}) {
|
|
772
774
|
const expandedConvos = []
|
|
773
775
|
|
|
774
776
|
if (_.isUndefined(useNameAsIntent)) {
|
|
775
777
|
useNameAsIntent = !!this.caps[Capabilities.SCRIPTING_UTTEXPANSION_USENAMEASINTENT]
|
|
776
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
|
+
}
|
|
777
785
|
if (_.isUndefined(incomprehensionUtt)) {
|
|
778
786
|
incomprehensionUtt = this.caps[Capabilities.SCRIPTING_UTTEXPANSION_INCOMPREHENSION]
|
|
779
787
|
}
|
|
780
788
|
|
|
781
|
-
if (
|
|
782
|
-
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)`)
|
|
783
791
|
}
|
|
784
|
-
if (
|
|
785
|
-
|
|
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
|
+
}
|
|
786
804
|
}
|
|
787
805
|
|
|
788
806
|
if (useNameAsIntent) {
|
|
789
807
|
debug('ExpandUtterancesToConvos - Using utterance name as NLU intent')
|
|
790
|
-
}
|
|
791
|
-
|
|
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)`)
|
|
792
814
|
}
|
|
793
815
|
|
|
794
816
|
_.keys(this.utterances).filter(u => u !== incomprehensionUtt).forEach(uttName => {
|
|
795
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
|
+
|
|
796
846
|
expandedConvos.push(new Convo(this._buildScriptContext(), {
|
|
797
847
|
header: {
|
|
798
848
|
name: utt.name,
|
|
@@ -809,31 +859,7 @@ module.exports = class ScriptingProvider {
|
|
|
809
859
|
messageText: utt.name,
|
|
810
860
|
stepTag: 'Step 1 - tell utterance'
|
|
811
861
|
},
|
|
812
|
-
|
|
813
|
-
? {
|
|
814
|
-
sender: 'bot',
|
|
815
|
-
asserters: [
|
|
816
|
-
{
|
|
817
|
-
name: 'INTENT',
|
|
818
|
-
args: [utt.name]
|
|
819
|
-
}
|
|
820
|
-
],
|
|
821
|
-
stepTag: 'Step 2 - check intent',
|
|
822
|
-
not: false
|
|
823
|
-
}
|
|
824
|
-
: incomprehensionUtt
|
|
825
|
-
? {
|
|
826
|
-
sender: 'bot',
|
|
827
|
-
messageText: incomprehensionUtt,
|
|
828
|
-
stepTag: 'Step 2 - check incomprehension',
|
|
829
|
-
not: true
|
|
830
|
-
}
|
|
831
|
-
: {
|
|
832
|
-
sender: 'bot',
|
|
833
|
-
messageText: '',
|
|
834
|
-
stepTag: 'Step 2 - check bot response',
|
|
835
|
-
not: false
|
|
836
|
-
}
|
|
862
|
+
responseStep
|
|
837
863
|
],
|
|
838
864
|
sourceTag: Object.assign({}, utt.sourceTag, { origUttName: utt.name })
|
|
839
865
|
}))
|
|
@@ -859,9 +885,10 @@ module.exports = class ScriptingProvider {
|
|
|
859
885
|
* @param currentConvo
|
|
860
886
|
* @param convoStepIndex
|
|
861
887
|
* @param convoStepsStack list of ConvoSteps
|
|
888
|
+
* @param context {width: }
|
|
862
889
|
* @private
|
|
863
890
|
*/
|
|
864
|
-
_expandConvo (expandedConvos, currentConvo, convoStepIndex = 0, convoStepsStack = []) {
|
|
891
|
+
_expandConvo (expandedConvos, currentConvo, convoStepIndex = 0, convoStepsStack = [], context = {}) {
|
|
865
892
|
const utterancePostfix = (lineTag, uttOrUserInput) => {
|
|
866
893
|
const naming = this.caps[Capabilities.SCRIPTING_UTTEXPANSION_NAMING_MODE] || Defaults.capabilities[Capabilities.SCRIPTING_UTTEXPANSION_NAMING_MODE]
|
|
867
894
|
if (naming === 'justLineTag') {
|
|
@@ -881,7 +908,7 @@ module.exports = class ScriptingProvider {
|
|
|
881
908
|
if (currentStep.sender === 'bot' || currentStep.sender === 'begin' || currentStep.sender === 'end') {
|
|
882
909
|
const currentStepsStack = convoStepsStack.slice()
|
|
883
910
|
currentStepsStack.push(_.cloneDeep(currentStep))
|
|
884
|
-
this._expandConvo(expandedConvos, currentConvo, convoStepIndex + 1, currentStepsStack)
|
|
911
|
+
this._expandConvo(expandedConvos, currentConvo, convoStepIndex + 1, currentStepsStack, context)
|
|
885
912
|
} else if (currentStep.sender === 'me') {
|
|
886
913
|
let useUnexpanded = true
|
|
887
914
|
if (currentStep.messageText) {
|
|
@@ -898,29 +925,61 @@ module.exports = class ScriptingProvider {
|
|
|
898
925
|
}
|
|
899
926
|
if (this.utterances[uttName]) {
|
|
900
927
|
const allutterances = this.utterances[uttName].utterances
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
sampleutterances = allutterances
|
|
906
|
-
.map(x => ({ x, r: Math.random() }))
|
|
907
|
-
.sort((a, b) => a.r - b.r)
|
|
908
|
-
.map(a => a.x)
|
|
909
|
-
.slice(0, this.caps[Capabilities.SCRIPTING_UTTEXPANSION_RANDOM_COUNT])
|
|
928
|
+
const processSampleUtterances = (sampleutterances, myContext) => {
|
|
929
|
+
sampleutterances.forEach((utt, index) => {
|
|
930
|
+
processSampleUtterance(utt, sampleutterances.length, index, Object.assign({ indexExpansionModeIndex: index }, myContext || context))
|
|
931
|
+
})
|
|
910
932
|
}
|
|
911
|
-
|
|
912
|
-
const lineTag = `${index + 1}`.padStart(`${
|
|
933
|
+
const processSampleUtterance = (sampleutterance, length, index, myContext) => {
|
|
934
|
+
const lineTag = `${index + 1}`.padStart(`${length}`.length, '0')
|
|
913
935
|
const currentStepsStack = convoStepsStack.slice()
|
|
914
936
|
if (uttArgs) {
|
|
915
|
-
|
|
937
|
+
sampleutterance = util.format(sampleutterance, ...uttArgs)
|
|
916
938
|
}
|
|
917
|
-
currentStepsStack.push(Object.assign(_.cloneDeep(currentStep), { messageText:
|
|
939
|
+
currentStepsStack.push(Object.assign(_.cloneDeep(currentStep), { messageText: sampleutterance }))
|
|
918
940
|
const currentConvoLabeled = _.cloneDeep(currentConvo)
|
|
919
|
-
Object.assign(currentConvoLabeled.header, { name: `${currentConvo.header.name}/${uttName}-${utterancePostfix(lineTag,
|
|
941
|
+
Object.assign(currentConvoLabeled.header, { name: `${currentConvo.header.name}/${uttName}-${utterancePostfix(lineTag, sampleutterance)}` })
|
|
920
942
|
if (!currentConvoLabeled.sourceTag) currentConvoLabeled.sourceTag = {}
|
|
921
943
|
if (!currentConvoLabeled.sourceTag.origConvoName) currentConvoLabeled.sourceTag.origConvoName = currentConvo.header.name
|
|
922
|
-
this._expandConvo(expandedConvos, currentConvoLabeled, convoStepIndex + 1, currentStepsStack)
|
|
923
|
-
}
|
|
944
|
+
this._expandConvo(expandedConvos, currentConvoLabeled, convoStepIndex + 1, currentStepsStack, myContext || context)
|
|
945
|
+
}
|
|
946
|
+
if (this.caps[Capabilities.SCRIPTING_UTTEXPANSION_MODE] === 'index') {
|
|
947
|
+
if (_.isNil(context.indexExpansionModeWidth)) {
|
|
948
|
+
// executed for the first found utterance
|
|
949
|
+
processSampleUtterances(allutterances, Object.assign({}, context, { indexExpansionModeWidth: allutterances.length }))
|
|
950
|
+
} else {
|
|
951
|
+
if (_.isNil(context.indexExpansionModeIndex)) {
|
|
952
|
+
throw new Error('indexExpansionModeIndex must be set!')
|
|
953
|
+
}
|
|
954
|
+
// executing the current 'thread', if current utterance has no example to current index, fallback to the last one
|
|
955
|
+
const localIndex = Math.min(context.indexExpansionModeIndex, allutterances.length - 1)
|
|
956
|
+
if (localIndex < context.indexExpansionModeIndex && context.indexExpansionModeIndex === context.indexExpansionModeWidth - 1) {
|
|
957
|
+
debug(`While expanding convos by index found in utterance "${uttName}" less examples (${allutterances.length}) as expected (${context.indexExpansionModeWidth})`)
|
|
958
|
+
}
|
|
959
|
+
const myContext = Object.assign({}, context, { indexExpansionModeWidth: Math.max(allutterances.length, context.indexExpansionModeWidth) })
|
|
960
|
+
processSampleUtterance(allutterances[localIndex], allutterances.length, localIndex, myContext)
|
|
961
|
+
if (allutterances.length > context.indexExpansionModeWidth && context.indexExpansionModeIndex + 1 === context.indexExpansionModeWidth) {
|
|
962
|
+
debug(`While expanding convos by index found in utterance "${uttName}" more examples (${allutterances.length}) as expected (${context.indexExpansionModeWidth})`)
|
|
963
|
+
for (let i = context.indexExpansionModeWidth; i < allutterances.length; i++) {
|
|
964
|
+
// if we found a utterance with more examples as any utterances before, we have to start new 'thread'
|
|
965
|
+
const myContext = Object.assign({}, context, { indexExpansionModeWidth: allutterances.length, indexExpansionModeIndex: i })
|
|
966
|
+
processSampleUtterance(allutterances[i], allutterances.length, i, myContext)
|
|
967
|
+
}
|
|
968
|
+
}
|
|
969
|
+
}
|
|
970
|
+
} else {
|
|
971
|
+
if (this.caps[Capabilities.SCRIPTING_UTTEXPANSION_MODE] === 'first') {
|
|
972
|
+
processSampleUtterances([allutterances[0]])
|
|
973
|
+
} else if (this.caps[Capabilities.SCRIPTING_UTTEXPANSION_MODE] === 'random') {
|
|
974
|
+
processSampleUtterances(allutterances
|
|
975
|
+
.map(x => ({ x, r: Math.random() }))
|
|
976
|
+
.sort((a, b) => a.r - b.r)
|
|
977
|
+
.map(a => a.x)
|
|
978
|
+
.slice(0, this.caps[Capabilities.SCRIPTING_UTTEXPANSION_RANDOM_COUNT]))
|
|
979
|
+
} else {
|
|
980
|
+
processSampleUtterances(allutterances)
|
|
981
|
+
}
|
|
982
|
+
}
|
|
924
983
|
useUnexpanded = false
|
|
925
984
|
}
|
|
926
985
|
}
|
|
@@ -930,18 +989,14 @@ module.exports = class ScriptingProvider {
|
|
|
930
989
|
if (userInput && userInput.expandConvo) {
|
|
931
990
|
const expandedUserInputs = userInput.expandConvo({ convo: currentConvo, convoStep: currentStep, args: ui.args })
|
|
932
991
|
if (expandedUserInputs && expandedUserInputs.length > 0) {
|
|
933
|
-
let sampleinputs = expandedUserInputs
|
|
934
|
-
|
|
935
|
-
sampleinputs
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
.map(x => ({ x, r: Math.random() }))
|
|
939
|
-
.sort((a, b) => a.r - b.r)
|
|
940
|
-
.map(a => a.x)
|
|
941
|
-
.slice(0, this.caps[Capabilities.SCRIPTING_UTTEXPANSION_RANDOM_COUNT])
|
|
992
|
+
// let sampleinputs = expandedUserInputs
|
|
993
|
+
const processSampleInputs = (sampleinputs, myContext, uiIndex) => {
|
|
994
|
+
sampleinputs.forEach((input, index) => {
|
|
995
|
+
processSampleInput(input, sampleinputs.length, index, Object.assign({ indexExpansionModeIndex: index }, myContext || context), uiIndex)
|
|
996
|
+
})
|
|
942
997
|
}
|
|
943
|
-
|
|
944
|
-
const lineTag = `${index + 1}`.padStart(`${
|
|
998
|
+
const processSampleInput = (sampleinput, length, index, myContext, uiIndex) => {
|
|
999
|
+
const lineTag = `${index + 1}`.padStart(`${length}`.length, '0')
|
|
945
1000
|
const currentStepsStack = convoStepsStack.slice()
|
|
946
1001
|
const currentStepMod = _.cloneDeep(currentStep)
|
|
947
1002
|
currentStepMod.userInputs[uiIndex] = sampleinput
|
|
@@ -949,8 +1004,46 @@ module.exports = class ScriptingProvider {
|
|
|
949
1004
|
currentStepsStack.push(currentStepMod)
|
|
950
1005
|
const currentConvoLabeled = _.cloneDeep(currentConvo)
|
|
951
1006
|
Object.assign(currentConvoLabeled.header, { name: `${currentConvo.header.name}/${ui.name}-${utterancePostfix(lineTag, (sampleinput.args && sampleinput.args.length) ? sampleinput.args.join(', ') : 'no-args')}` })
|
|
952
|
-
this._expandConvo(expandedConvos, currentConvoLabeled, convoStepIndex + 1, currentStepsStack)
|
|
953
|
-
}
|
|
1007
|
+
this._expandConvo(expandedConvos, currentConvoLabeled, convoStepIndex + 1, currentStepsStack, myContext || context)
|
|
1008
|
+
}
|
|
1009
|
+
if (this.caps[Capabilities.SCRIPTING_UTTEXPANSION_MODE] === 'index') {
|
|
1010
|
+
if (_.isNil(context.indexExpansionModeWidth)) {
|
|
1011
|
+
processSampleInputs(expandedUserInputs, Object.assign({}, context, { indexExpansionModeWidth: expandedUserInputs.length }), uiIndex)
|
|
1012
|
+
} else {
|
|
1013
|
+
if (_.isNil(context.indexExpansionModeIndex)) {
|
|
1014
|
+
throw new Error('indexExpansionModeIndex must be set!')
|
|
1015
|
+
}
|
|
1016
|
+
// executing the current 'thread', if current utterance has no example to current index, fallback to the last one
|
|
1017
|
+
const localIndex = Math.min(context.indexExpansionModeIndex, expandedUserInputs.length - 1)
|
|
1018
|
+
if (localIndex < context.indexExpansionModeIndex && context.indexExpansionModeIndex === context.indexExpansionModeWidth - 1) {
|
|
1019
|
+
debug(`While expanding convos by index found user input "${ui.name}, ${ui.args}" less examples (${expandedUserInputs.length}) as expected (${context.indexExpansionModeWidth})`)
|
|
1020
|
+
}
|
|
1021
|
+
const myContext = Object.assign({}, context, { indexExpansionModeWidth: Math.max(expandedUserInputs.length, context.indexExpansionModeWidth) })
|
|
1022
|
+
processSampleInput(expandedUserInputs[localIndex], expandedUserInputs.length, localIndex, myContext, uiIndex)
|
|
1023
|
+
if (expandedUserInputs.length > context.indexExpansionModeWidth && context.indexExpansionModeIndex + 1 === context.indexExpansionModeWidth) {
|
|
1024
|
+
debug(`While expanding convos by index found user input "${ui.name}, ${ui.args}" more examples (${expandedUserInputs.length}) as expected (${context.indexExpansionModeWidth})`)
|
|
1025
|
+
for (let i = context.indexExpansionModeWidth; i < expandedUserInputs.length; i++) {
|
|
1026
|
+
const myContext = Object.assign({}, context, { indexExpansionModeWidth: expandedUserInputs.length, indexExpansionModeIndex: i })
|
|
1027
|
+
processSampleInput(expandedUserInputs[i], expandedUserInputs.length, i, myContext, uiIndex)
|
|
1028
|
+
}
|
|
1029
|
+
}
|
|
1030
|
+
}
|
|
1031
|
+
} else {
|
|
1032
|
+
if (this.caps[Capabilities.SCRIPTING_UTTEXPANSION_MODE] === 'first') {
|
|
1033
|
+
processSampleInputs([expandedUserInputs[0]], context, uiIndex)
|
|
1034
|
+
} else if (this.caps[Capabilities.SCRIPTING_UTTEXPANSION_MODE] === 'random') {
|
|
1035
|
+
processSampleInputs(expandedUserInputs
|
|
1036
|
+
.map(x => ({
|
|
1037
|
+
x,
|
|
1038
|
+
r: Math.random()
|
|
1039
|
+
}))
|
|
1040
|
+
.sort((a, b) => a.r - b.r)
|
|
1041
|
+
.map(a => a.x)
|
|
1042
|
+
.slice(0, this.caps[Capabilities.SCRIPTING_UTTEXPANSION_RANDOM_COUNT]), context, uiIndex)
|
|
1043
|
+
} else {
|
|
1044
|
+
processSampleInputs(expandedUserInputs, context, uiIndex)
|
|
1045
|
+
}
|
|
1046
|
+
}
|
|
954
1047
|
useUnexpanded = false
|
|
955
1048
|
}
|
|
956
1049
|
}
|
|
@@ -959,7 +1052,7 @@ module.exports = class ScriptingProvider {
|
|
|
959
1052
|
if (useUnexpanded) {
|
|
960
1053
|
const currentStepsStack = convoStepsStack.slice()
|
|
961
1054
|
currentStepsStack.push(_.cloneDeep(currentStep))
|
|
962
|
-
this._expandConvo(expandedConvos, currentConvo, convoStepIndex + 1, currentStepsStack)
|
|
1055
|
+
this._expandConvo(expandedConvos, currentConvo, convoStepIndex + 1, currentStepsStack, context)
|
|
963
1056
|
}
|
|
964
1057
|
}
|
|
965
1058
|
} else {
|
|
@@ -45,7 +45,7 @@ module.exports = {
|
|
|
45
45
|
{ name: 'TEXT_EQUALS_IC', className: 'TextEqualsAnyICAsserter' },
|
|
46
46
|
{ name: 'TEXT', className: 'TextEqualsAnyAsserter' },
|
|
47
47
|
{ name: 'TEXT_IC', className: 'TextEqualsAnyICAsserter' },
|
|
48
|
-
|
|
48
|
+
{ name: 'TEXT_WER', className: 'WerAsserter' },
|
|
49
49
|
{ name: 'BOT_CONSUMED', className: 'BotRepliesConsumedAsserter' },
|
|
50
50
|
{ name: 'BOT_UNCONSUMED_COUNT', className: 'BotRepliesUnconsumedCountAsserter' }
|
|
51
51
|
],
|