botium-core 1.15.6 → 1.15.9
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 +49 -8
- package/dist/botium-cjs.js.map +1 -1
- package/dist/botium-es.js +49 -8
- package/dist/botium-es.js.map +1 -1
- package/package.json +1 -1
- package/src/BotDriver.js +2 -2
- package/src/Capabilities.js +9 -0
- package/src/containers/plugins/SimpleRestContainer.js +30 -4
- package/src/scripting/ScriptingProvider.js +10 -1
- package/test/connectors/simplerest.spec.js +78 -0
- package/test/driver/capabilities.spec.js +9 -0
package/package.json
CHANGED
package/src/BotDriver.js
CHANGED
|
@@ -241,8 +241,8 @@ module.exports = class BotDriver {
|
|
|
241
241
|
if (_.isString(newCaps[capKey])) {
|
|
242
242
|
try {
|
|
243
243
|
caps[capKey] = JSON.parse(newCaps[capKey])
|
|
244
|
-
if (_.isFinite(
|
|
245
|
-
caps[capKey] =
|
|
244
|
+
if (_.isFinite(Number(newCaps[capKey]))) {
|
|
245
|
+
caps[capKey] = newCaps[capKey].toString()
|
|
246
246
|
}
|
|
247
247
|
} catch (err) {
|
|
248
248
|
caps[capKey] = newCaps[capKey]
|
package/src/Capabilities.js
CHANGED
|
@@ -111,6 +111,15 @@ module.exports = {
|
|
|
111
111
|
SIMPLEREST_NLP_LIST_JSONPATH: 'SIMPLEREST_NLP_LIST_JSONPATH',
|
|
112
112
|
SIMPLEREST_NLP_LIST_INTENT_JSONPATH: 'SIMPLEREST_NLP_LIST_INTENT_JSONPATH',
|
|
113
113
|
SIMPLEREST_NLP_LIST_CONFIDENCE_JSONPATH: 'SIMPLEREST_NLP_LIST_CONFIDENCE_JSONPATH',
|
|
114
|
+
/**
|
|
115
|
+
* Single response can contain a list of messages. This capability defines how to merge the list into a single message.
|
|
116
|
+
* It can be 'OFF' (default), 'MERGE_TEXT'
|
|
117
|
+
* @type {string}
|
|
118
|
+
* @default 'OFF'
|
|
119
|
+
* @description Merge message list into single message
|
|
120
|
+
*/
|
|
121
|
+
SIMPLEREST_MESSAGE_LIST_MERGE: 'SIMPLEREST_MESSAGE_LIST_MERGE',
|
|
122
|
+
|
|
114
123
|
// Script Compiler
|
|
115
124
|
SCRIPTING_TXT_EOL: 'SCRIPTING_TXT_EOL',
|
|
116
125
|
// ROW_PER_MESSAGE or QUESTION_ANSWER
|
|
@@ -369,7 +369,7 @@ module.exports = class SimpleRestContainer {
|
|
|
369
369
|
return
|
|
370
370
|
}
|
|
371
371
|
|
|
372
|
-
|
|
372
|
+
let result = []
|
|
373
373
|
if (isFromUser) {
|
|
374
374
|
const _extractFrom = (root, jsonPaths, acceptFn = null) => {
|
|
375
375
|
const result = []
|
|
@@ -402,6 +402,11 @@ module.exports = class SimpleRestContainer {
|
|
|
402
402
|
jsonPathRoots.push(body)
|
|
403
403
|
}
|
|
404
404
|
|
|
405
|
+
if (jsonPathRoots.length === 0 && !this.caps[Capabilities.SIMPLEREST_IGNORE_EMPTY]) {
|
|
406
|
+
debug(`found empty body, and processed because of SIMPLEREST_IGNORE_EMPTY capability: ${util.inspect(body)}`)
|
|
407
|
+
result.push({ messageText: '', sourceData: body })
|
|
408
|
+
}
|
|
409
|
+
|
|
405
410
|
for (const jsonPathRoot of jsonPathRoots) {
|
|
406
411
|
const _retrieveMedia = (jsonPathMediaRoot, jsonPathsMedia) => {
|
|
407
412
|
const retrievedMedia = []
|
|
@@ -590,8 +595,13 @@ module.exports = class SimpleRestContainer {
|
|
|
590
595
|
const beforeHookKeys = Object.keys(botMsg)
|
|
591
596
|
await executeHook(this.caps, this.responseHook, Object.assign({ botMsg, botMsgRoot: jsonPathRoot }, this.view))
|
|
592
597
|
const afterHookKeys = Object.keys(botMsg)
|
|
593
|
-
if (beforeHookKeys.length !== afterHookKeys.length || !!(botMsg.messageText && botMsg.messageText.length > 0) || botMsg.media.length > 0 || botMsg.buttons.length > 0 || botMsg.cards.length > 0 || botMsg.nlp
|
|
598
|
+
if (beforeHookKeys.length !== afterHookKeys.length || !!(botMsg.messageText && botMsg.messageText.length > 0) || botMsg.media.length > 0 || botMsg.buttons.length > 0 || botMsg.cards.length > 0 || botMsg.nlp) {
|
|
599
|
+
result.push(botMsg)
|
|
600
|
+
} else if (!this.caps[Capabilities.SIMPLEREST_IGNORE_EMPTY]) {
|
|
601
|
+
debug(`found empty message, and processed because of SIMPLEREST_IGNORE_EMPTY capability: ${util.inspect(botMsg)}`)
|
|
594
602
|
result.push(botMsg)
|
|
603
|
+
} else {
|
|
604
|
+
debug(`found empty message, and ignored because of SIMPLEREST_IGNORE_EMPTY capability: ${util.inspect(botMsg)}`)
|
|
595
605
|
}
|
|
596
606
|
}
|
|
597
607
|
}
|
|
@@ -604,6 +614,23 @@ module.exports = class SimpleRestContainer {
|
|
|
604
614
|
|
|
605
615
|
setTimeout(() => this._doRequest({ messageText: '' }, true, true), 0)
|
|
606
616
|
}
|
|
617
|
+
|
|
618
|
+
if (this.caps[Capabilities.SIMPLEREST_MESSAGE_LIST_MERGE] === 'MERGE_TEXT') {
|
|
619
|
+
const isTextMsg = (msg) => msg.messageText && (!msg.media || msg.media.length === 0) && (!msg.buttons || msg.buttons.length === 0) && (!msg.cards || msg.cards.length === 0)
|
|
620
|
+
|
|
621
|
+
result = result.reduce((acc, currentMsg) => {
|
|
622
|
+
if (acc.length > 0) {
|
|
623
|
+
const last = acc[acc.length - 1]
|
|
624
|
+
if (isTextMsg(last)) {
|
|
625
|
+
currentMsg.messageText = [last.messageText, currentMsg.messageText].filter(t => t).join('\n')
|
|
626
|
+
acc[acc.length - 1] = currentMsg
|
|
627
|
+
return acc
|
|
628
|
+
}
|
|
629
|
+
}
|
|
630
|
+
acc.push(currentMsg)
|
|
631
|
+
return acc
|
|
632
|
+
}, [])
|
|
633
|
+
}
|
|
607
634
|
return result
|
|
608
635
|
}
|
|
609
636
|
|
|
@@ -620,8 +647,7 @@ module.exports = class SimpleRestContainer {
|
|
|
620
647
|
fetch(requestOptions.uri, requestOptions).then(async (bodyRaw) => {
|
|
621
648
|
let body
|
|
622
649
|
try {
|
|
623
|
-
|
|
624
|
-
if (contentType && contentType.includes('application/json')) {
|
|
650
|
+
if (bodyRaw?.headers?.get('content-type') && bodyRaw.headers.get('content-type').includes('application/json')) {
|
|
625
651
|
try {
|
|
626
652
|
body = await bodyRaw.json()
|
|
627
653
|
} catch (err) {
|
|
@@ -377,7 +377,15 @@ module.exports = class ScriptingProvider {
|
|
|
377
377
|
throw Error(`Unknown hookType ${hookType}`)
|
|
378
378
|
}
|
|
379
379
|
|
|
380
|
-
|
|
380
|
+
let localHooks = (logicHooks || []).filter(l => this.logicHooks[l.name][hookType])
|
|
381
|
+
// Scripting memory file are injected via SET_SCRIPTING_MEMORY in the BEGIN step
|
|
382
|
+
// But there might be other logic hooks that need the scripting memory variables
|
|
383
|
+
// Order is important (SET_SCRIPTING_MEMORY in begin can be because the user added it,
|
|
384
|
+
// or because the scripting memory file added it. User one has to be the last one.
|
|
385
|
+
localHooks = [
|
|
386
|
+
...localHooks.filter(l => l.name === 'SET_SCRIPTING_MEMORY'),
|
|
387
|
+
...localHooks.filter(l => l.name !== 'SET_SCRIPTING_MEMORY')
|
|
388
|
+
]
|
|
381
389
|
|
|
382
390
|
const convoStepPromises = localHooks
|
|
383
391
|
.map(l => p(this.retryHelperLogicHook, () => this.logicHooks[l.name][hookType]({
|
|
@@ -385,6 +393,7 @@ module.exports = class ScriptingProvider {
|
|
|
385
393
|
convoStep,
|
|
386
394
|
scriptingMemory,
|
|
387
395
|
container,
|
|
396
|
+
// Do this more sensitve for SET_SCRIPTING_MEMORY? It can have scripting variables in the args
|
|
388
397
|
args: ScriptingMemory.applyToArgs(l.args, scriptingMemory, container.caps, rest.botMsg),
|
|
389
398
|
isGlobal: false,
|
|
390
399
|
...rest
|
|
@@ -810,6 +810,7 @@ describe('connectors.simplerest', function () {
|
|
|
810
810
|
|
|
811
811
|
await container.Clean()
|
|
812
812
|
})
|
|
813
|
+
|
|
813
814
|
it('should parse jsonmessage from sourcedata if it enabled', async function () {
|
|
814
815
|
const msgJSON = {
|
|
815
816
|
sourceData: {
|
|
@@ -837,6 +838,7 @@ describe('connectors.simplerest', function () {
|
|
|
837
838
|
|
|
838
839
|
await container.Clean()
|
|
839
840
|
})
|
|
841
|
+
|
|
840
842
|
it('should fall back to text message if using jsonmessage from sourcedata is enabled, but sourcedata is not set', async function () {
|
|
841
843
|
const myCaps = Object.assign({}, myCapsPost)
|
|
842
844
|
myCaps[Capabilities.SIMPLEREST_BODY_FROM_JSON] = true
|
|
@@ -855,6 +857,7 @@ describe('connectors.simplerest', function () {
|
|
|
855
857
|
|
|
856
858
|
await container.Clean()
|
|
857
859
|
})
|
|
860
|
+
|
|
858
861
|
it('should handle somehow if jsonmessage from sourcedata is enabled, and booth json, and text are set in the user message (impossible state)', async function () {
|
|
859
862
|
// this is not a valid state. In case there is a json as message in a convo.txt, text parser parses it into the sourceData field, and keeps messageText empty
|
|
860
863
|
const msgTextAndJSONIllegal = {
|
|
@@ -903,6 +906,81 @@ describe('connectors.simplerest', function () {
|
|
|
903
906
|
await container.Clean()
|
|
904
907
|
})
|
|
905
908
|
|
|
909
|
+
it('should merge text responses', async function () {
|
|
910
|
+
const myCaps = Object.assign({}, myCapsGet, {
|
|
911
|
+
[Capabilities.SIMPLEREST_BODY_JSONPATH]: '$.responses[*]',
|
|
912
|
+
[Capabilities.SIMPLEREST_RESPONSE_JSONPATH]: '$.text',
|
|
913
|
+
[Capabilities.SIMPLEREST_BUTTONS_JSONPATH]: '$.buttons[*]',
|
|
914
|
+
[Capabilities.SIMPLEREST_BUTTONS_TEXT_SUBJSONPATH]: '$.text',
|
|
915
|
+
[Capabilities.SIMPLEREST_MEDIA_JSONPATH]: '$.media[*]',
|
|
916
|
+
[Capabilities.SIMPLEREST_MESSAGE_LIST_MERGE]: 'MERGE_TEXT'
|
|
917
|
+
})
|
|
918
|
+
const driver = new BotDriver(myCaps)
|
|
919
|
+
const container = await driver.Build()
|
|
920
|
+
await container.Start()
|
|
921
|
+
const msgs = await container.pluginInstance._processBodyAsyncImpl({
|
|
922
|
+
responses: [
|
|
923
|
+
{ text: 'text 1' },
|
|
924
|
+
{ text: 'text 2' },
|
|
925
|
+
{ text: 'text 3', buttons: [{ text: 'button' }] },
|
|
926
|
+
{ text: 'text 4' },
|
|
927
|
+
{ media: ['some.jpg'] },
|
|
928
|
+
{ text: 'text 5' },
|
|
929
|
+
{ text: 'text 6' }
|
|
930
|
+
]
|
|
931
|
+
}, {}, true)
|
|
932
|
+
|
|
933
|
+
assert.exists(msgs)
|
|
934
|
+
assert.equal(msgs.length, 3)
|
|
935
|
+
assert.equal(msgs[0].messageText, 'text 1\ntext 2\ntext 3')
|
|
936
|
+
assert.exists(msgs[0].buttons)
|
|
937
|
+
assert.equal(msgs[0].buttons.length, 1)
|
|
938
|
+
assert.equal(msgs[0].media.length, 0)
|
|
939
|
+
assert.equal(msgs[1].messageText, 'text 4')
|
|
940
|
+
assert.equal(msgs[1].buttons.length, 0)
|
|
941
|
+
assert.equal(msgs[1].media.length, 1)
|
|
942
|
+
assert.equal(msgs[2].messageText, 'text 5\ntext 6')
|
|
943
|
+
assert.equal(msgs[2].buttons.length, 0)
|
|
944
|
+
assert.equal(msgs[2].media.length, 0)
|
|
945
|
+
await container.Clean()
|
|
946
|
+
})
|
|
947
|
+
|
|
948
|
+
it('should not merge text responses', async function () {
|
|
949
|
+
const myCaps = Object.assign({}, myCapsGet, {
|
|
950
|
+
[Capabilities.SIMPLEREST_BODY_JSONPATH]: '$.responses[*]',
|
|
951
|
+
[Capabilities.SIMPLEREST_RESPONSE_JSONPATH]: '$.text',
|
|
952
|
+
[Capabilities.SIMPLEREST_BUTTONS_JSONPATH]: '$.buttons[*]',
|
|
953
|
+
[Capabilities.SIMPLEREST_BUTTONS_TEXT_SUBJSONPATH]: '$.text',
|
|
954
|
+
[Capabilities.SIMPLEREST_MEDIA_JSONPATH]: '$.media[*]'
|
|
955
|
+
})
|
|
956
|
+
const driver = new BotDriver(myCaps)
|
|
957
|
+
const container = await driver.Build()
|
|
958
|
+
await container.Start()
|
|
959
|
+
const msgs = await container.pluginInstance._processBodyAsyncImpl({
|
|
960
|
+
responses: [
|
|
961
|
+
{ text: 'text 1' },
|
|
962
|
+
{ text: 'text 2' },
|
|
963
|
+
{ text: 'text 3', buttons: [{ text: 'button' }] },
|
|
964
|
+
{ text: 'text 4' },
|
|
965
|
+
{ media: ['some.jpg'] },
|
|
966
|
+
{ text: 'text 5' },
|
|
967
|
+
{ text: 'text 6' }
|
|
968
|
+
]
|
|
969
|
+
}, {}, true)
|
|
970
|
+
|
|
971
|
+
assert.exists(msgs)
|
|
972
|
+
assert.equal(msgs.length, 7)
|
|
973
|
+
assert.equal(msgs[0].messageText, 'text 1')
|
|
974
|
+
assert.equal(msgs[1].messageText, 'text 2')
|
|
975
|
+
assert.equal(msgs[2].messageText, 'text 3')
|
|
976
|
+
assert.equal(msgs[3].messageText, 'text 4')
|
|
977
|
+
assert.equal(msgs[4].messageText, '')
|
|
978
|
+
assert.equal(msgs[5].messageText, 'text 5')
|
|
979
|
+
assert.equal(msgs[6].messageText, 'text 6')
|
|
980
|
+
|
|
981
|
+
await container.Clean()
|
|
982
|
+
})
|
|
983
|
+
|
|
906
984
|
it('should ignore empty response', async function () {
|
|
907
985
|
const myCaps = Object.assign({}, myCapsGet, {
|
|
908
986
|
[Capabilities.SIMPLEREST_BODY_JSONPATH]: '$.responses[*]',
|
|
@@ -75,6 +75,15 @@ describe('driver.capabilities', function () {
|
|
|
75
75
|
assert.isString(driver.caps.CAP_STRING_1)
|
|
76
76
|
assert.isString(driver.caps.CAP_STRING_2)
|
|
77
77
|
})
|
|
78
|
+
it('should merge string caps when there are numbers', function () {
|
|
79
|
+
const myCaps = {
|
|
80
|
+
CAP_STRING_1: 'Test',
|
|
81
|
+
CAP_STRING_2: '1234567892343434344'
|
|
82
|
+
}
|
|
83
|
+
const driver = new BotDriver(myCaps)
|
|
84
|
+
assert.strictEqual(driver.caps.CAP_STRING_1, myCaps.CAP_STRING_1)
|
|
85
|
+
assert.strictEqual(driver.caps.CAP_STRING_2, myCaps.CAP_STRING_2)
|
|
86
|
+
})
|
|
78
87
|
it('should merge boolean envs', function () {
|
|
79
88
|
process.env.BOTIUM_SIMPLEREST_PING_PROCESS_RESPONSE = 'NO'
|
|
80
89
|
const driver = new BotDriver()
|