wingbot 3.69.8 → 3.70.0-alpha.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/index.js +0 -2
- package/jsconfig.json +2 -2
- package/package.json +3 -2
- package/src/BuildRouter.js +4 -1
- package/src/LLM.js +1 -1
- package/src/LLMMockProvider.js +17 -10
- package/src/LLMSession.js +5 -4
- package/src/Responder.js +67 -17
- package/src/resolvers/contextMessage.js +39 -0
- package/src/resolvers/index.js +2 -0
- package/src/resolvers/message.js +32 -5
- package/src/resolvers/utils.js +1 -1
package/index.js
CHANGED
package/jsconfig.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"compilerOptions": {
|
|
3
3
|
"module": "commonjs",
|
|
4
|
-
"lib": ["es2019", "es2020.promise", "es2020.bigint", "es2020.string"],
|
|
4
|
+
"lib": ["es2019", "es2020.promise", "es2020.bigint", "es2020.string", "dom"],
|
|
5
5
|
"target": "ESNext",
|
|
6
6
|
"allowSyntheticDefaultImports": true,
|
|
7
7
|
"checkJs": true,
|
|
@@ -14,4 +14,4 @@
|
|
|
14
14
|
"doc",
|
|
15
15
|
"docs"
|
|
16
16
|
]
|
|
17
|
-
}
|
|
17
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "wingbot",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.70.0-alpha.5",
|
|
4
4
|
"description": "Enterprise Messaging Bot Conversation Engine",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"type": "commonjs",
|
|
@@ -37,6 +37,7 @@
|
|
|
37
37
|
},
|
|
38
38
|
"homepage": "https://github.com/wingbot.ai/wingbot#readme",
|
|
39
39
|
"devDependencies": {
|
|
40
|
+
"@types/mocha": "^10.0.10",
|
|
40
41
|
"cpy-cli": "^5.0.0",
|
|
41
42
|
"eslint": "^8.56.0",
|
|
42
43
|
"eslint-config-airbnb": "^19.0.4",
|
|
@@ -69,4 +70,4 @@
|
|
|
69
70
|
"axios": "^1.6.4",
|
|
70
71
|
"handlebars": "^4.0.0"
|
|
71
72
|
}
|
|
72
|
-
}
|
|
73
|
+
}
|
package/src/BuildRouter.js
CHANGED
|
@@ -571,8 +571,10 @@ class BuildRouter extends Router {
|
|
|
571
571
|
};
|
|
572
572
|
|
|
573
573
|
const [linksMap, nestedBlocksByStaticId] = this._createLinksMap(block);
|
|
574
|
+
// @ts-ignore
|
|
574
575
|
this._linksMap = linksMap;
|
|
575
576
|
|
|
577
|
+
// @ts-ignore
|
|
576
578
|
this._buildRoutes(block.routes, nestedBlocksByStaticId);
|
|
577
579
|
|
|
578
580
|
this._configTs = setConfigTimestamp;
|
|
@@ -582,9 +584,10 @@ class BuildRouter extends Router {
|
|
|
582
584
|
}
|
|
583
585
|
|
|
584
586
|
/**
|
|
587
|
+
*
|
|
588
|
+
* returns {[LinksMap, BlockMap]}
|
|
585
589
|
*
|
|
586
590
|
* @param {Block} block
|
|
587
|
-
* @returns {[LinksMap, BlockMap]}
|
|
588
591
|
*/
|
|
589
592
|
_createLinksMap (block) {
|
|
590
593
|
const { linksMap: prevLinksMap, blocks = [] } = this._resolvedContext;
|
package/src/LLM.js
CHANGED
|
@@ -8,7 +8,7 @@ const { PHONE_REGEX, EMAIL_REGEX } = require('./systemEntities/regexps');
|
|
|
8
8
|
/** @typedef {import('./Responder')} Responder */
|
|
9
9
|
/** @typedef {import('./Responder').Persona} Persona */
|
|
10
10
|
/** @typedef {import('./Router').BaseConfiguration} BaseConfiguration */
|
|
11
|
-
/** @typedef {import('./LLMSession').LLMMessage} LLMMessage */
|
|
11
|
+
/** @typedef {import('./LLMSession').LLMMessage<any>} LLMMessage */
|
|
12
12
|
/** @typedef {import('./LLMSession').LLMRole} LLMRole */
|
|
13
13
|
/** @typedef {import('./LLMSession')} LLMSession */
|
|
14
14
|
/** @typedef {import('./transcript/transcriptFromHistory').Transcript} Transcript */
|
package/src/LLMMockProvider.js
CHANGED
|
@@ -38,20 +38,27 @@ class LLMMockProvider {
|
|
|
38
38
|
if (prompt.length === 0) {
|
|
39
39
|
throw new Error('Empty prompt');
|
|
40
40
|
}
|
|
41
|
-
const stats = prompt.reduce((o, m) => Object.assign(o, {
|
|
42
|
-
|
|
43
|
-
}), { system: 0, assistant: 0, user: 0 });
|
|
44
|
-
|
|
45
|
-
const statsText = JSON.stringify(stats)
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
const message = this._sequence[this._index];
|
|
49
|
-
this._index = (this._index + 1) % this._sequence.length;
|
|
41
|
+
// const stats = prompt.reduce((o, m) => Object.assign(o, {
|
|
42
|
+
// [m.role]: (o[m.role] || 0) + 1
|
|
43
|
+
// }), { system: 0, assistant: 0, user: 0 });
|
|
44
|
+
//
|
|
45
|
+
// const statsText = JSON.stringify(stats)
|
|
46
|
+
// .replace(/"/g, '');
|
|
47
|
+
//
|
|
48
|
+
/// / const message = this._sequence[this._index];
|
|
49
|
+
/// / this._index = (this._index + 1) % this._sequence.length;
|
|
50
|
+
//
|
|
51
|
+
// return {
|
|
52
|
+
// role: LLM.ROLE_ASSISTANT,
|
|
53
|
+
// finishReason: 'length',
|
|
54
|
+
// eslint-disable-next-line max-len
|
|
55
|
+
// content: `${statsText} > ${LLMMockProvider.DEFAULT_MODEL}: ${prompt.map((m) => m.content).join(' ')}`
|
|
56
|
+
// };
|
|
50
57
|
|
|
51
58
|
return {
|
|
52
59
|
role: LLM.ROLE_ASSISTANT,
|
|
53
60
|
finishReason: 'length',
|
|
54
|
-
content: `${
|
|
61
|
+
content: `${options.model || LLMMockProvider.DEFAULT_MODEL}:${prompt.map((m) => m.content).join(' ')}`
|
|
55
62
|
};
|
|
56
63
|
}
|
|
57
64
|
|
package/src/LLMSession.js
CHANGED
|
@@ -35,7 +35,7 @@ class LLMSession {
|
|
|
35
35
|
/**
|
|
36
36
|
*
|
|
37
37
|
* @param {LLM} llm
|
|
38
|
-
* @param {LLMMessage[]} [chat]
|
|
38
|
+
* @param {LLMMessage<any>[]} [chat]
|
|
39
39
|
* @param {SendCallback} [onSend]
|
|
40
40
|
*/
|
|
41
41
|
constructor (llm, chat = [], onSend = () => {}) {
|
|
@@ -43,7 +43,7 @@ class LLMSession {
|
|
|
43
43
|
|
|
44
44
|
this._onSend = onSend;
|
|
45
45
|
|
|
46
|
-
/** @type {LLMMessage[]} */
|
|
46
|
+
/** @type {LLMMessage<any>[]} */
|
|
47
47
|
this._chat = chat;
|
|
48
48
|
|
|
49
49
|
this._generatedIndex = null;
|
|
@@ -63,6 +63,7 @@ class LLMSession {
|
|
|
63
63
|
}
|
|
64
64
|
|
|
65
65
|
_mergeSystem () {
|
|
66
|
+
/** @type {LLMMessage<any>[]} */
|
|
66
67
|
const sysMessages = [];
|
|
67
68
|
|
|
68
69
|
const otherMessages = this._chat.filter((message) => {
|
|
@@ -81,7 +82,7 @@ class LLMSession {
|
|
|
81
82
|
|
|
82
83
|
const content = sysMessages.reduce((reduced, current, i) => {
|
|
83
84
|
if (i === 0) {
|
|
84
|
-
return current.content;
|
|
85
|
+
return current.content || '';
|
|
85
86
|
}
|
|
86
87
|
if (!reduced.match(promptRegex)) {
|
|
87
88
|
return `${reduced}\n\n${current.content}`;
|
|
@@ -189,7 +190,7 @@ class LLMSession {
|
|
|
189
190
|
/**
|
|
190
191
|
*
|
|
191
192
|
* @param {LLMProviderOptions} [options={}]
|
|
192
|
-
* @returns {Promise<LLMMessage
|
|
193
|
+
* @returns {Promise<LLMMessage<any>>}
|
|
193
194
|
*/
|
|
194
195
|
async generate (options = {}) {
|
|
195
196
|
const result = await this._llm.generate(this, options);
|
package/src/Responder.js
CHANGED
|
@@ -103,6 +103,16 @@ Object.freeze(ExpectedInput);
|
|
|
103
103
|
* @prop {string} [name]
|
|
104
104
|
*/
|
|
105
105
|
|
|
106
|
+
/**
|
|
107
|
+
* @callback PromptGetter
|
|
108
|
+
* @param {Responder} res
|
|
109
|
+
* @returns {string|Promise<string>}
|
|
110
|
+
*/
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* @typedef {PromptGetter|string} PromptSource
|
|
114
|
+
*/
|
|
115
|
+
|
|
106
116
|
const PERSONA_DEFAULT = '_default';
|
|
107
117
|
|
|
108
118
|
/**
|
|
@@ -227,7 +237,7 @@ class Responder {
|
|
|
227
237
|
|
|
228
238
|
this.LLM_CTX_DEFAULT = 'default';
|
|
229
239
|
|
|
230
|
-
/** @type {Map<string,string[]>} */
|
|
240
|
+
/** @type {Map<string,(PromptSource|Promise<string>)[]>} */
|
|
231
241
|
this._llmContext = new Map([
|
|
232
242
|
[this.LLM_CTX_DEFAULT, []]
|
|
233
243
|
]);
|
|
@@ -235,36 +245,48 @@ class Responder {
|
|
|
235
245
|
|
|
236
246
|
/**
|
|
237
247
|
*
|
|
238
|
-
* @param {
|
|
248
|
+
* @param {PromptSource} systemPrompt
|
|
239
249
|
* @param {string} contextType
|
|
240
250
|
* @returns {this}
|
|
241
251
|
*/
|
|
242
252
|
llmAddSystemPrompt (systemPrompt, contextType = this.LLM_CTX_DEFAULT) {
|
|
243
|
-
if (!systemPrompt
|
|
253
|
+
if (!systemPrompt) {
|
|
244
254
|
return this;
|
|
245
255
|
}
|
|
246
256
|
if (!this._llmContext.has(contextType)) {
|
|
247
257
|
// @todo make it array of messages / maybe keep it in a single array
|
|
248
258
|
this._llmContext.set(contextType, []);
|
|
249
259
|
}
|
|
250
|
-
this._llmContext.get(contextType).push(systemPrompt
|
|
260
|
+
this._llmContext.get(contextType).push(systemPrompt);
|
|
261
|
+
|
|
251
262
|
return this;
|
|
252
263
|
}
|
|
253
264
|
|
|
254
|
-
llmSession (contextType = this.LLM_CTX_DEFAULT) {
|
|
255
|
-
const
|
|
256
|
-
|
|
265
|
+
async llmSession (contextType = this.LLM_CTX_DEFAULT) {
|
|
266
|
+
const system = await this._getSystemContentForType(contextType);
|
|
267
|
+
|
|
268
|
+
const chat = system.map((content) => ({ role: LLM.ROLE_SYSTEM, content }));
|
|
257
269
|
|
|
258
270
|
return new LLMSession(this.llm, chat, this._llmSend.bind(this));
|
|
259
271
|
}
|
|
260
272
|
|
|
273
|
+
async _replaceAsync (str, regex, asyncFn) {
|
|
274
|
+
const promises = [];
|
|
275
|
+
str.replace(regex, (full, ...args) => {
|
|
276
|
+
promises.push(asyncFn(full, ...args));
|
|
277
|
+
return full;
|
|
278
|
+
});
|
|
279
|
+
const data = await Promise.all(promises);
|
|
280
|
+
return str.replace(regex, () => data.shift());
|
|
281
|
+
}
|
|
282
|
+
|
|
261
283
|
/**
|
|
262
284
|
*
|
|
263
285
|
* @param {string} contextType
|
|
264
286
|
* @param {string[]} [callStack]
|
|
265
|
-
* @returns {string[]}
|
|
287
|
+
* @returns {Promise<string[]>}
|
|
266
288
|
*/
|
|
267
|
-
_getSystemContentForType (contextType, callStack = []) {
|
|
289
|
+
async _getSystemContentForType (contextType, callStack = []) {
|
|
268
290
|
if (new Set(callStack).size < callStack.length) {
|
|
269
291
|
throw new Error(`Circular reference detected: contextType -> ${callStack}`);
|
|
270
292
|
}
|
|
@@ -273,10 +295,28 @@ class Responder {
|
|
|
273
295
|
return [];
|
|
274
296
|
}
|
|
275
297
|
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
298
|
+
/** @type {Promise<string>[]} */
|
|
299
|
+
const promiseStrings = this._llmContext.get(contextType)
|
|
300
|
+
.map(async (p) => (typeof p === 'function' ? p(this) : p));
|
|
301
|
+
this._llmContext.set(contextType, promiseStrings);
|
|
302
|
+
|
|
303
|
+
const resolved = await Promise.all(
|
|
304
|
+
promiseStrings
|
|
305
|
+
.map(async (promiseString) => {
|
|
306
|
+
const s = await promiseString;
|
|
307
|
+
|
|
308
|
+
const replaced = await this._replaceAsync(s.trim(), /\$\{([a-zA-Z0-9\s]+)\}/g, async (str, reqType) => {
|
|
309
|
+
const nested = await this
|
|
310
|
+
._getSystemContentForType(reqType, [...callStack, contextType]);
|
|
311
|
+
|
|
312
|
+
return nested.join('\n\n');
|
|
313
|
+
});
|
|
314
|
+
|
|
315
|
+
return replaced.trim();
|
|
316
|
+
})
|
|
317
|
+
);
|
|
318
|
+
|
|
319
|
+
return resolved;
|
|
280
320
|
}
|
|
281
321
|
|
|
282
322
|
async llmSessionWithHistory (contextType = this.LLM_CTX_DEFAULT) {
|
|
@@ -286,8 +326,10 @@ class Responder {
|
|
|
286
326
|
transcriptLength
|
|
287
327
|
} = this.llm.configuration;
|
|
288
328
|
|
|
289
|
-
const systems =
|
|
290
|
-
|
|
329
|
+
const [systems, transcript] = await Promise.all([
|
|
330
|
+
this._getSystemContentForType(contextType),
|
|
331
|
+
this.getTranscript(transcriptLength, transcriptFlag)
|
|
332
|
+
]);
|
|
291
333
|
|
|
292
334
|
const chat = [
|
|
293
335
|
...systems.map((content) => ({ role: LLM.ROLE_SYSTEM, content })),
|
|
@@ -658,12 +700,18 @@ class Responder {
|
|
|
658
700
|
this.routePath = routePath;
|
|
659
701
|
}
|
|
660
702
|
|
|
703
|
+
/**
|
|
704
|
+
* @typedef {object} MessageOptions
|
|
705
|
+
* @prop {boolean} [disableAutoTyping]
|
|
706
|
+
*/
|
|
707
|
+
|
|
661
708
|
/**
|
|
662
709
|
* Send text as a response
|
|
663
710
|
*
|
|
664
711
|
* @param {string} text - text to send to user, can contain placeholders (%s)
|
|
665
712
|
* @param {Object.<string,string|QuickReply>|QuickReply[]} [replies] - quick replies
|
|
666
713
|
* @param {VoiceControl} [voice] - voice control data
|
|
714
|
+
* @param {MessageOptions} [options={}]
|
|
667
715
|
* @returns {this}
|
|
668
716
|
*
|
|
669
717
|
* @example
|
|
@@ -685,7 +733,7 @@ class Responder {
|
|
|
685
733
|
* }
|
|
686
734
|
* ]);
|
|
687
735
|
*/
|
|
688
|
-
text (text, replies = null, voice = null) {
|
|
736
|
+
text (text, replies = null, voice = null, options = {}) {
|
|
689
737
|
const messageData = {
|
|
690
738
|
message: {
|
|
691
739
|
text: this._t(text)
|
|
@@ -735,7 +783,9 @@ class Responder {
|
|
|
735
783
|
}
|
|
736
784
|
}
|
|
737
785
|
|
|
738
|
-
|
|
786
|
+
if (!options.disableAutoTyping) {
|
|
787
|
+
this._autoTypingIfEnabled(messageData.message.text);
|
|
788
|
+
}
|
|
739
789
|
this.send(messageData);
|
|
740
790
|
return this;
|
|
741
791
|
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* @author Vojtech Jedlicka
|
|
3
|
+
*/
|
|
4
|
+
'use strict';
|
|
5
|
+
|
|
6
|
+
const Router = require('../Router');
|
|
7
|
+
// eslint-disable-next-line no-unused-vars
|
|
8
|
+
const Responder = require('../Responder');
|
|
9
|
+
const { getLanguageText } = require('./utils');
|
|
10
|
+
const compileWithState = require('../utils/compileWithState');
|
|
11
|
+
|
|
12
|
+
/** @typedef {import('../BuildRouter').BotContext<any>} BotContext */
|
|
13
|
+
/** @typedef {import('../Router').Resolver<any>} Resolver */
|
|
14
|
+
/** @typedef {import('./utils').Translations} Translations */
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
*
|
|
18
|
+
* @param {object} params
|
|
19
|
+
* @param {Translations} params.context
|
|
20
|
+
* @param {string} [params.type]
|
|
21
|
+
* @param {BotContext} context
|
|
22
|
+
* @returns {Resolver}
|
|
23
|
+
*/
|
|
24
|
+
// eslint-disable-next-line no-unused-vars
|
|
25
|
+
function contextMessage (params, context) {
|
|
26
|
+
|
|
27
|
+
return async (req, res) => {
|
|
28
|
+
res.llmAddSystemPrompt((r) => {
|
|
29
|
+
const translated = getLanguageText(params.context, req.state.lang);
|
|
30
|
+
const translatedText = Array.isArray(translated) ? translated[0] : translated;
|
|
31
|
+
const statefulPrompt = compileWithState(req, r, translatedText);
|
|
32
|
+
return statefulPrompt;
|
|
33
|
+
}, params.type);
|
|
34
|
+
|
|
35
|
+
return Router.CONTINUE;
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
module.exports = contextMessage;
|
package/src/resolvers/index.js
CHANGED
|
@@ -17,10 +17,12 @@ const subscribtions = require('./subscribtions');
|
|
|
17
17
|
const setState = require('./setState');
|
|
18
18
|
const expectedInput = require('./expectedInput');
|
|
19
19
|
const skip = require('./skip');
|
|
20
|
+
const contextMessage = require('./contextMessage');
|
|
20
21
|
|
|
21
22
|
module.exports = {
|
|
22
23
|
path,
|
|
23
24
|
message,
|
|
25
|
+
contextMessage,
|
|
24
26
|
include,
|
|
25
27
|
postback,
|
|
26
28
|
expected,
|
package/src/resolvers/message.js
CHANGED
|
@@ -270,12 +270,23 @@ function selectTranslation (resolverId, params, texts, data) {
|
|
|
270
270
|
];
|
|
271
271
|
}
|
|
272
272
|
|
|
273
|
-
/** @typedef {import('../BuildRouter').BotContext} BotContext */
|
|
274
|
-
/** @typedef {import('../Router').Resolver} Resolver */
|
|
273
|
+
/** @typedef {import('../BuildRouter').BotContext<any>} BotContext */
|
|
274
|
+
/** @typedef {import('../Router').Resolver<any>} Resolver */
|
|
275
275
|
|
|
276
276
|
/**
|
|
277
277
|
*
|
|
278
278
|
* @param {object} params
|
|
279
|
+
* @param {any} params.text
|
|
280
|
+
* @param {boolean} [params.hasCondition]
|
|
281
|
+
* @param {string} [params.conditionFn]
|
|
282
|
+
* @param {string} [params.conditionDesc]
|
|
283
|
+
* @param {boolean} [params.hasEditableCondition]
|
|
284
|
+
* @param {any} [params.editableCondition]
|
|
285
|
+
* @param {string} [params.mode]
|
|
286
|
+
* @param {string} [params.persist]
|
|
287
|
+
* @param {any[]} [params.replies]
|
|
288
|
+
* @param {"message" | "prompt"} [params.type]
|
|
289
|
+
* @param {string} [params.llmContextType]
|
|
279
290
|
* @param {BotContext} context
|
|
280
291
|
* @returns {Resolver}
|
|
281
292
|
*/
|
|
@@ -284,6 +295,7 @@ function message (params, context = {}) {
|
|
|
284
295
|
// @ts-ignore
|
|
285
296
|
isLastIndex, isLastMessage, linksMap, configuration, resolverId
|
|
286
297
|
} = context;
|
|
298
|
+
|
|
287
299
|
if (typeof params.text !== 'string' && !Array.isArray(params.text)) {
|
|
288
300
|
throw new Error('Message should be a text!');
|
|
289
301
|
}
|
|
@@ -294,7 +306,6 @@ function message (params, context = {}) {
|
|
|
294
306
|
throw new Error('Replies should be an array');
|
|
295
307
|
}
|
|
296
308
|
|
|
297
|
-
// compile condition
|
|
298
309
|
let condition;
|
|
299
310
|
|
|
300
311
|
const ret = isLastIndex ? Router.END : Router.CONTINUE;
|
|
@@ -303,10 +314,11 @@ function message (params, context = {}) {
|
|
|
303
314
|
* @param {Request} req
|
|
304
315
|
* @param {Responder} res
|
|
305
316
|
*/
|
|
306
|
-
return (req, res) => {
|
|
317
|
+
return async (req, res) => {
|
|
307
318
|
if (condition === undefined) {
|
|
308
319
|
condition = getCondition(params, context, 'Message condition');
|
|
309
320
|
}
|
|
321
|
+
|
|
310
322
|
if (quickReplies === undefined) {
|
|
311
323
|
if (params.replies && params.replies.length > 0) {
|
|
312
324
|
quickReplies = parseReplies(params.replies, linksMap, context);
|
|
@@ -324,7 +336,8 @@ function message (params, context = {}) {
|
|
|
324
336
|
data.lang
|
|
325
337
|
);
|
|
326
338
|
|
|
327
|
-
|
|
339
|
+
// eslint-disable-next-line prefer-const
|
|
340
|
+
let [text, seqState] = selectTranslation(
|
|
328
341
|
resolverId,
|
|
329
342
|
params,
|
|
330
343
|
supportedText.translations,
|
|
@@ -403,6 +416,20 @@ function message (params, context = {}) {
|
|
|
403
416
|
};
|
|
404
417
|
}
|
|
405
418
|
|
|
419
|
+
if (params.type === 'prompt') {
|
|
420
|
+
const session = await res.llmSessionWithHistory(params.llmContextType);
|
|
421
|
+
|
|
422
|
+
const response = await session.systemPrompt(text)
|
|
423
|
+
.debug()
|
|
424
|
+
.generate();
|
|
425
|
+
|
|
426
|
+
// if (!response.content) {
|
|
427
|
+
// // no response?
|
|
428
|
+
// }
|
|
429
|
+
|
|
430
|
+
text = response.content;
|
|
431
|
+
}
|
|
432
|
+
|
|
406
433
|
res.text(text, sendReplies, voiceControl);
|
|
407
434
|
|
|
408
435
|
if (isLastMessage && !req.actionData()._resolverTag) {
|
package/src/resolvers/utils.js
CHANGED
|
@@ -62,7 +62,7 @@ function isTextObjectEmpty (text) {
|
|
|
62
62
|
* @param {Translations} translations
|
|
63
63
|
* @param {string} [lang]
|
|
64
64
|
* @param {boolean} [disableDefaulting] - it will try to find translation for other language
|
|
65
|
-
* @returns {null|string}
|
|
65
|
+
* @returns {null|string|string[]}
|
|
66
66
|
*/
|
|
67
67
|
function getLanguageText (translations, lang = null, disableDefaulting = false) {
|
|
68
68
|
let foundText;
|