botium-core 1.15.8 → 1.15.10
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 +147 -8
- package/dist/botium-cjs.js.map +1 -1
- package/dist/botium-es.js +147 -8
- package/dist/botium-es.js.map +1 -1
- package/package.json +1 -1
- package/src/BotDriver.js +2 -2
- package/src/helpers/TranscriptUtils.js +66 -0
- package/src/scripting/Convo.js +9 -0
- package/src/scripting/ScriptingProvider.js +46 -6
- package/src/scripting/logichook/userinput/MediaInput.js +10 -2
- package/test/driver/capabilities.spec.js +9 -0
package/dist/botium-cjs.js
CHANGED
|
@@ -77,7 +77,7 @@ var express__default = /*#__PURE__*/_interopDefaultLegacy(express);
|
|
|
77
77
|
var bodyParser__default = /*#__PURE__*/_interopDefaultLegacy(bodyParser);
|
|
78
78
|
|
|
79
79
|
var name = "botium-core";
|
|
80
|
-
var version$1 = "1.15.
|
|
80
|
+
var version$1 = "1.15.10";
|
|
81
81
|
var description = "The Selenium for Chatbots";
|
|
82
82
|
var main = "index.js";
|
|
83
83
|
var module$1 = "dist/botium-es.js";
|
|
@@ -3039,6 +3039,7 @@ class Convo$6 {
|
|
|
3039
3039
|
}
|
|
3040
3040
|
async runConversation(container, scriptingMemory, transcript) {
|
|
3041
3041
|
const transcriptSteps = [];
|
|
3042
|
+
transcript.steps = transcriptSteps;
|
|
3042
3043
|
try {
|
|
3043
3044
|
let lastMeConvoStep = null;
|
|
3044
3045
|
let botMsg = null;
|
|
@@ -3223,6 +3224,21 @@ class Convo$6 {
|
|
|
3223
3224
|
throw failErr;
|
|
3224
3225
|
}
|
|
3225
3226
|
} else if (convoStep.sender === 'bot') {
|
|
3227
|
+
if (this.scriptingEvents.executeBotStep) {
|
|
3228
|
+
const executeBotStepResult = await this.scriptingEvents.executeBotStep({
|
|
3229
|
+
convo: this,
|
|
3230
|
+
convoStep,
|
|
3231
|
+
container,
|
|
3232
|
+
scriptingMemory,
|
|
3233
|
+
transcript,
|
|
3234
|
+
transcriptStep,
|
|
3235
|
+
transcriptSteps
|
|
3236
|
+
});
|
|
3237
|
+
if (executeBotStepResult) {
|
|
3238
|
+
skipTranscriptStep = true;
|
|
3239
|
+
continue;
|
|
3240
|
+
}
|
|
3241
|
+
}
|
|
3226
3242
|
if (waitForBotSays) {
|
|
3227
3243
|
botMsg = null;
|
|
3228
3244
|
} else {
|
|
@@ -5796,6 +5812,31 @@ var ScriptingProvider_1 = class ScriptingProvider {
|
|
|
5796
5812
|
...rest
|
|
5797
5813
|
});
|
|
5798
5814
|
},
|
|
5815
|
+
executeBotStep: ({
|
|
5816
|
+
convo,
|
|
5817
|
+
convoStep,
|
|
5818
|
+
container,
|
|
5819
|
+
scriptingMemory,
|
|
5820
|
+
...rest
|
|
5821
|
+
}) => {
|
|
5822
|
+
const logicHooks = convoStep?.logicHooks || [];
|
|
5823
|
+
const executeBotStepHooks = logicHooks.filter(l => this.logicHooks[l.name] && typeof this.logicHooks[l.name].executeBotStep === 'function');
|
|
5824
|
+
if (executeBotStepHooks.length > 1) {
|
|
5825
|
+
throw new Error(`${convo?.header?.name}/${convoStep?.stepTag}: Multiple logic hooks implement executeBotStep: ${executeBotStepHooks.map(l => l.name).join(', ')}. Only one is allowed per step.`);
|
|
5826
|
+
}
|
|
5827
|
+
if (executeBotStepHooks.length === 1) {
|
|
5828
|
+
const lh = executeBotStepHooks[0];
|
|
5829
|
+
return this.logicHooks[lh.name].executeBotStep({
|
|
5830
|
+
convo,
|
|
5831
|
+
convoStep,
|
|
5832
|
+
scriptingMemory,
|
|
5833
|
+
container,
|
|
5834
|
+
args: ScriptingMemory.applyToArgs(lh.args, scriptingMemory, container.caps),
|
|
5835
|
+
...rest
|
|
5836
|
+
});
|
|
5837
|
+
}
|
|
5838
|
+
return null;
|
|
5839
|
+
},
|
|
5799
5840
|
assertConvoBegin: ({
|
|
5800
5841
|
convo,
|
|
5801
5842
|
convoStep,
|
|
@@ -6097,12 +6138,18 @@ var ScriptingProvider_1 = class ScriptingProvider {
|
|
|
6097
6138
|
if (hookType !== 'onMeStart' && hookType !== 'onMePrepare' && hookType !== 'onMeEnd' && hookType !== 'onBotStart' && hookType !== 'onBotPrepare' && hookType !== 'onBotEnd' && hookType !== 'onConvoBegin' && hookType !== 'onConvoEnd') {
|
|
6098
6139
|
throw Error(`Unknown hookType ${hookType}`);
|
|
6099
6140
|
}
|
|
6100
|
-
|
|
6141
|
+
let localHooks = (logicHooks || []).filter(l => this.logicHooks[l.name][hookType]);
|
|
6142
|
+
// Scripting memory file are injected via SET_SCRIPTING_MEMORY in the BEGIN step
|
|
6143
|
+
// But there might be other logic hooks that need the scripting memory variables
|
|
6144
|
+
// Order is important (SET_SCRIPTING_MEMORY in begin can be because the user added it,
|
|
6145
|
+
// or because the scripting memory file added it. User one has to be the last one.
|
|
6146
|
+
localHooks = [...localHooks.filter(l => l.name === 'SET_SCRIPTING_MEMORY'), ...localHooks.filter(l => l.name !== 'SET_SCRIPTING_MEMORY')];
|
|
6101
6147
|
const convoStepPromises = localHooks.map(l => p(this.retryHelperLogicHook, () => this.logicHooks[l.name][hookType]({
|
|
6102
6148
|
convo,
|
|
6103
6149
|
convoStep,
|
|
6104
6150
|
scriptingMemory,
|
|
6105
6151
|
container,
|
|
6152
|
+
// Do this more sensitve for SET_SCRIPTING_MEMORY? It can have scripting variables in the args
|
|
6106
6153
|
args: ScriptingMemory.applyToArgs(l.args, scriptingMemory, container.caps, rest.botMsg),
|
|
6107
6154
|
isGlobal: false,
|
|
6108
6155
|
...rest
|
|
@@ -6192,6 +6239,7 @@ var ScriptingProvider_1 = class ScriptingProvider {
|
|
|
6192
6239
|
onBotStart: this.scriptingEvents.onBotStart.bind(this),
|
|
6193
6240
|
onBotPrepare: this.scriptingEvents.onBotPrepare.bind(this),
|
|
6194
6241
|
onBotEnd: this.scriptingEvents.onBotEnd.bind(this),
|
|
6242
|
+
executeBotStep: this.scriptingEvents.executeBotStep.bind(this),
|
|
6195
6243
|
setUserInput: this.scriptingEvents.setUserInput.bind(this),
|
|
6196
6244
|
fail: this.scriptingEvents.fail && this.scriptingEvents.fail.bind(this)
|
|
6197
6245
|
}
|
|
@@ -6712,7 +6760,11 @@ var ScriptingProvider_1 = class ScriptingProvider {
|
|
|
6712
6760
|
// use skip and keep, or justHeader
|
|
6713
6761
|
justHeader: false,
|
|
6714
6762
|
// drop unwanted convos
|
|
6715
|
-
convoFilter: null
|
|
6763
|
+
convoFilter: null,
|
|
6764
|
+
mediaInput: {
|
|
6765
|
+
// MESSAGE_TEXT_FROM_FILENAME or MESSAGE_TEXT_FROM_TRANSCRIPTION or falsy
|
|
6766
|
+
messageTextMode: null
|
|
6767
|
+
}
|
|
6716
6768
|
}, options);
|
|
6717
6769
|
const expandedConvos = [];
|
|
6718
6770
|
// The globalContext is going to keep the data even if the Object.assign which happening to create the myContext in _expandConvo function
|
|
@@ -6750,7 +6802,11 @@ var ScriptingProvider_1 = class ScriptingProvider {
|
|
|
6750
6802
|
ExpandConvosIterable(options = {}) {
|
|
6751
6803
|
options = Object.assign({
|
|
6752
6804
|
// drop unwanted convos
|
|
6753
|
-
convoFilter: null
|
|
6805
|
+
convoFilter: null,
|
|
6806
|
+
mediaInput: {
|
|
6807
|
+
// MESSAGE_TEXT_FROM_FILENAME or MESSAGE_TEXT_FROM_TRANSCRIPTION or falsy
|
|
6808
|
+
messageTextMode: null
|
|
6809
|
+
}
|
|
6754
6810
|
}, options);
|
|
6755
6811
|
// The globalContext is going to keep the data even if the Object.assign which happening to create the myContext in _expandConvo function
|
|
6756
6812
|
const context = {
|
|
@@ -6897,7 +6953,8 @@ var ScriptingProvider_1 = class ScriptingProvider {
|
|
|
6897
6953
|
const expandedUserInputs = userInput.expandConvo({
|
|
6898
6954
|
convo: currentConvo,
|
|
6899
6955
|
convoStep: currentStep,
|
|
6900
|
-
args: ui.args
|
|
6956
|
+
args: ui.args,
|
|
6957
|
+
options
|
|
6901
6958
|
});
|
|
6902
6959
|
if (expandedUserInputs && expandedUserInputs.length > 0) {
|
|
6903
6960
|
// let sampleinputs = expandedUserInputs
|
|
@@ -6909,9 +6966,16 @@ var ScriptingProvider_1 = class ScriptingProvider {
|
|
|
6909
6966
|
}
|
|
6910
6967
|
};
|
|
6911
6968
|
const processSampleInput = function* (sampleinput, length, index, myContext, uiIndex) {
|
|
6969
|
+
const {
|
|
6970
|
+
messageText,
|
|
6971
|
+
...userInput
|
|
6972
|
+
} = sampleinput;
|
|
6912
6973
|
const currentStepsStack = convoStepsStack.slice();
|
|
6913
6974
|
const currentStepMod = lodash__default["default"].cloneDeep(currentStep);
|
|
6914
|
-
currentStepMod.userInputs[uiIndex] =
|
|
6975
|
+
currentStepMod.userInputs[uiIndex] = userInput;
|
|
6976
|
+
if (messageText) {
|
|
6977
|
+
currentStepMod.messageText = messageText;
|
|
6978
|
+
}
|
|
6915
6979
|
currentStepsStack.push(currentStepMod);
|
|
6916
6980
|
const currentConvoLabeled = lodash__default["default"].cloneDeep(currentConvo);
|
|
6917
6981
|
if (length > 1) {
|
|
@@ -9571,8 +9635,8 @@ var BotDriver_1 = class BotDriver {
|
|
|
9571
9635
|
if (lodash__default["default"].isString(newCaps[capKey])) {
|
|
9572
9636
|
try {
|
|
9573
9637
|
caps[capKey] = JSON.parse(newCaps[capKey]);
|
|
9574
|
-
if (lodash__default["default"].isFinite(
|
|
9575
|
-
caps[capKey] =
|
|
9638
|
+
if (lodash__default["default"].isFinite(Number(newCaps[capKey]))) {
|
|
9639
|
+
caps[capKey] = newCaps[capKey].toString();
|
|
9576
9640
|
}
|
|
9577
9641
|
} catch (err) {
|
|
9578
9642
|
caps[capKey] = newCaps[capKey];
|
|
@@ -9831,6 +9895,79 @@ Plugins.PLUGIN_TYPE_LOGICHOOK;
|
|
|
9831
9895
|
Plugins.PLUGIN_TYPE_USERINPUT;
|
|
9832
9896
|
Plugins.TYPE_TO_PREFIX;
|
|
9833
9897
|
|
|
9898
|
+
const {
|
|
9899
|
+
parse: csvParseSync
|
|
9900
|
+
} = sync__default["default"];
|
|
9901
|
+
|
|
9902
|
+
/**
|
|
9903
|
+
* Find transcription for an audio file: .txt same base name, or transcript.csv in parent dirs.
|
|
9904
|
+
* @param {string} baseDir - Base directory for resolving paths
|
|
9905
|
+
* @param {string} audioFile - Relative path to audio file
|
|
9906
|
+
* @param {object} [options] - Optional: { csvCache: {}, onError: (msg) => {} }
|
|
9907
|
+
* @returns {string|null} Transcription text or null
|
|
9908
|
+
*/
|
|
9909
|
+
var findTranscription = (baseDir, audioFile, options = {}) => {
|
|
9910
|
+
const {
|
|
9911
|
+
csvCache = {},
|
|
9912
|
+
onError
|
|
9913
|
+
} = options;
|
|
9914
|
+
const transcriptionFilename = `${audioFile.substring(0, audioFile.lastIndexOf('.'))}.txt`;
|
|
9915
|
+
const transcriptionFilenameAbs = path__default["default"].resolve(baseDir, transcriptionFilename);
|
|
9916
|
+
try {
|
|
9917
|
+
if (fs__default["default"].existsSync(transcriptionFilenameAbs)) {
|
|
9918
|
+
return fs__default["default"].readFileSync(transcriptionFilenameAbs, {
|
|
9919
|
+
encoding: 'utf-8'
|
|
9920
|
+
}).trim();
|
|
9921
|
+
}
|
|
9922
|
+
} catch (err) {
|
|
9923
|
+
if (onError) onError(`Transcription File ${transcriptionFilenameAbs} not readable: ${err.message}`);
|
|
9924
|
+
throw new Error(`Reading transcription file ${transcriptionFilename} for ${audioFile} failed`);
|
|
9925
|
+
}
|
|
9926
|
+
if (csvCache[audioFile]) {
|
|
9927
|
+
return csvCache[audioFile];
|
|
9928
|
+
}
|
|
9929
|
+
const audioFileComponents = audioFile.split('/');
|
|
9930
|
+
for (let parentIndex = audioFileComponents.length - 1; parentIndex >= 0; parentIndex--) {
|
|
9931
|
+
const csvDirectory = audioFileComponents.slice(0, parentIndex);
|
|
9932
|
+
const csvFilename = path__default["default"].join(...csvDirectory, 'transcript.csv');
|
|
9933
|
+
const csvFilenameAbs = path__default["default"].resolve(baseDir, csvFilename);
|
|
9934
|
+
try {
|
|
9935
|
+
if (fs__default["default"].existsSync(csvFilenameAbs)) {
|
|
9936
|
+
const records = csvParseSync(fs__default["default"].readFileSync(csvFilenameAbs, {
|
|
9937
|
+
encoding: 'utf-8'
|
|
9938
|
+
}).trim(), {
|
|
9939
|
+
columns: ['filename', 'transcription'],
|
|
9940
|
+
delimiter: [',', ';', ':', '\t'],
|
|
9941
|
+
trim: true,
|
|
9942
|
+
skip_empty_lines: true
|
|
9943
|
+
});
|
|
9944
|
+
if (records && records.length > 0) {
|
|
9945
|
+
for (const record of records) {
|
|
9946
|
+
const fnKey = path__default["default"].join(...csvDirectory, record.filename);
|
|
9947
|
+
csvCache[fnKey] = record.transcription;
|
|
9948
|
+
}
|
|
9949
|
+
}
|
|
9950
|
+
}
|
|
9951
|
+
} catch (err) {
|
|
9952
|
+
if (onError) onError(`Transcription CSV File ${csvFilenameAbs} not readable: ${err.message}`);
|
|
9953
|
+
throw new Error(`Reading transcription CSV file for ${csvFilename} failed`);
|
|
9954
|
+
}
|
|
9955
|
+
if (csvCache[audioFile]) {
|
|
9956
|
+
return csvCache[audioFile];
|
|
9957
|
+
}
|
|
9958
|
+
}
|
|
9959
|
+
return null;
|
|
9960
|
+
};
|
|
9961
|
+
|
|
9962
|
+
/**
|
|
9963
|
+
* Derive transcription text from audio filename (basename without extension, underscores/hyphens → spaces).
|
|
9964
|
+
* @param {string} audioFile - Path or filename of audio file
|
|
9965
|
+
* @returns {string}
|
|
9966
|
+
*/
|
|
9967
|
+
var transcriptionFromFilename = audioFile => {
|
|
9968
|
+
const filename = path__default["default"].basename(audioFile, path__default["default"].extname(audioFile));
|
|
9969
|
+
return filename.split(/[_-]+/).join(' ');
|
|
9970
|
+
};
|
|
9834
9971
|
var hasWaitForBotTimeout = transciptError => {
|
|
9835
9972
|
if (!transciptError) {
|
|
9836
9973
|
return false;
|
|
@@ -9842,6 +9979,8 @@ var hasWaitForBotTimeout = transciptError => {
|
|
|
9842
9979
|
return str.indexOf(': error waiting for bot - Bot did not respond within') > 0;
|
|
9843
9980
|
};
|
|
9844
9981
|
var TranscriptUtils = {
|
|
9982
|
+
findTranscription: findTranscription,
|
|
9983
|
+
transcriptionFromFilename: transcriptionFromFilename,
|
|
9845
9984
|
hasWaitForBotTimeout: hasWaitForBotTimeout
|
|
9846
9985
|
};
|
|
9847
9986
|
|