wingbot 3.69.7 → 3.70.0-alpha.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.
@@ -0,0 +1,228 @@
1
+ /**
2
+ * @author David Menger
3
+ */
4
+ 'use strict';
5
+
6
+ const LLM = require('./LLM');
7
+
8
+ /** @typedef {import('./Responder').QuickReply} QuickReply */
9
+ /** @typedef {'user'|'assistant'} LLMChatRole */
10
+ /** @typedef {'system'} LLMSystemRole */
11
+ /** @typedef {LLMChatRole|LLMSystemRole|string} LLMRole */
12
+ /** @typedef {import('./LLM').LLMProviderOptions} LLMProviderOptions */
13
+
14
+ /** @typedef {'stop'|'length'|'tool_calls'|'content_filter'} LLMFinishReason */
15
+
16
+ /**
17
+ * @template {LLMRole} [R=LLMRole]
18
+ * @typedef {object} LLMMessage
19
+ * @prop {R} role
20
+ * @prop {string} content
21
+ * @prop {LLMFinishReason} [finishReason]
22
+ */
23
+
24
+ /**
25
+ * @callback SendCallback
26
+ * @param {LLMMessage[]} messages
27
+ * @param {QuickReply[]} quickReplies
28
+ */
29
+
30
+ /**
31
+ * @class LLMSession
32
+ */
33
+ class LLMSession {
34
+
35
+ /**
36
+ *
37
+ * @param {LLM} llm
38
+ * @param {LLMMessage<any>[]} [chat]
39
+ * @param {SendCallback} [onSend]
40
+ */
41
+ constructor (llm, chat = [], onSend = () => {}) {
42
+ this._llm = llm;
43
+
44
+ this._onSend = onSend;
45
+
46
+ /** @type {LLMMessage<any>[]} */
47
+ this._chat = chat;
48
+
49
+ this._generatedIndex = null;
50
+
51
+ this._sort();
52
+ }
53
+
54
+ _sort (what = this._chat) {
55
+ what.sort((a, z) => {
56
+ if (a.role === z.role
57
+ || (a.role !== LLM.ROLE_SYSTEM && z.role !== LLM.ROLE_SYSTEM)) {
58
+ return 0;
59
+ }
60
+ return a.role === LLM.ROLE_SYSTEM ? -1 : 1;
61
+ });
62
+ return what;
63
+ }
64
+
65
+ _mergeSystem () {
66
+ /** @type {LLMMessage<any>[]} */
67
+ const sysMessages = [];
68
+
69
+ const otherMessages = this._chat.filter((message) => {
70
+ if (message.role !== LLM.ROLE_SYSTEM) {
71
+ return true;
72
+ }
73
+ sysMessages.push(message);
74
+ return false;
75
+ });
76
+
77
+ if (sysMessages.length === 0) {
78
+ return otherMessages;
79
+ }
80
+
81
+ const promptRegex = /\$\{prompt\(\)\}/g;
82
+
83
+ const content = sysMessages.reduce((reduced, current, i) => {
84
+ if (i === 0) {
85
+ return current.content || '';
86
+ }
87
+ if (!reduced.match(promptRegex)) {
88
+ return `${reduced}\n\n${current.content}`;
89
+ }
90
+ return reduced.replace(promptRegex, current.content).trim();
91
+ }, '')
92
+ .replace(promptRegex, '')
93
+ .trim();
94
+
95
+ return [
96
+ {
97
+ role: LLM.ROLE_SYSTEM, content
98
+ },
99
+ ...otherMessages
100
+ ];
101
+ }
102
+
103
+ /**
104
+ * @returns {LLMMessage[]}
105
+ */
106
+ toArray () {
107
+ return this._mergeSystem();
108
+ }
109
+
110
+ /**
111
+ *
112
+ * @param {LLMMessage} msg
113
+ * @returns {string}
114
+ */
115
+ _msgPrefix (msg) {
116
+ switch (msg.role) {
117
+ case LLM.ROLE_SYSTEM:
118
+ return '-';
119
+ case LLM.ROLE_ASSISTANT:
120
+ return msg.content ? '<' : '#';
121
+ case LLM.ROLE_USER:
122
+ return '>';
123
+ default:
124
+ return '*';
125
+ }
126
+ }
127
+
128
+ /**
129
+ *
130
+ * @param {LLMMessage[]} [messages]
131
+ * @returns {string}
132
+ */
133
+ toString (messages = this._chat) {
134
+ if (messages.length === 0) {
135
+ return '[<empty>]';
136
+ }
137
+ return messages.map((m) => {
138
+ switch (m.role) {
139
+ case LLM.ROLE_SYSTEM:
140
+ return `--- system ---\n${m.content}\n--------------`;
141
+ default:
142
+ return `${this._msgPrefix(m)} ${m.content}`;
143
+ }
144
+ })
145
+ .join('\n');
146
+ }
147
+
148
+ toJSON () {
149
+ return this.toArray();
150
+ }
151
+
152
+ /**
153
+ *
154
+ * @param {boolean} [needRaw=false]
155
+ * @returns {this}
156
+ */
157
+ debug (needRaw = false) {
158
+ // eslint-disable-next-line no-console
159
+ console.log('LLMSession#debug\n', this.toString(
160
+ needRaw ? this._chat : this.toArray()
161
+ ));
162
+ return this;
163
+ }
164
+
165
+ /**
166
+ *
167
+ * @param {LLMMessage} message
168
+ * @returns {this}
169
+ */
170
+ push (message) {
171
+ // if its system, append it on top
172
+ this._chat.push(message);
173
+ return this;
174
+ }
175
+
176
+ /**
177
+ *
178
+ * @param {string} content
179
+ * @returns {this}
180
+ */
181
+ systemPrompt (content) {
182
+ this.push({
183
+ role: LLM.ROLE_SYSTEM,
184
+ content
185
+ });
186
+ this._sort();
187
+ return this;
188
+ }
189
+
190
+ /**
191
+ *
192
+ * @param {LLMProviderOptions} [options={}]
193
+ * @returns {Promise<LLMMessage<any>>}
194
+ */
195
+ async generate (options = {}) {
196
+ const result = await this._llm.generate(this, options);
197
+
198
+ this._generatedIndex = this._chat.length;
199
+ this._chat.push(result);
200
+
201
+ return result;
202
+ }
203
+
204
+ /**
205
+ *
206
+ * @param {QuickReply[]} quickReplies
207
+ * @returns {this}
208
+ */
209
+ send (quickReplies = undefined) {
210
+ if (!this._generatedIndex) {
211
+ // eslint-disable-next-line no-console
212
+ console.log('LLMSession', this.toString());
213
+ throw new Error('LLMSession: no message to send');
214
+ }
215
+
216
+ let messages = this._chat.splice(this._generatedIndex);
217
+ messages = messages.flatMap((msg) => LLM.toMessages(msg));
218
+ this._generatedIndex = null;
219
+ this._chat.push(...messages);
220
+
221
+ this._onSend(messages, quickReplies);
222
+
223
+ return this;
224
+ }
225
+
226
+ }
227
+
228
+ module.exports = LLMSession;
package/src/Processor.js CHANGED
@@ -11,6 +11,8 @@ const Request = require('./Request');
11
11
  const Ai = require('./Ai');
12
12
  const ReturnSender = require('./ReturnSender');
13
13
  const { prepareState, mergeState, isUserInteraction } = require('./utils/stateVariables');
14
+ const LLM = require('./LLM');
15
+ const LLMMockProvider = require('./LLMMockProvider');
14
16
 
15
17
  /** @typedef {import('./wingbot/CustomEntityDetectionModel').Intent} Intent */
16
18
  /** @typedef {import('./ReducerWrapper')} ReducerWrapper */
@@ -19,6 +21,7 @@ const { prepareState, mergeState, isUserInteraction } = require('./utils/stateVa
19
21
  /** @typedef {import('./analytics/consts').TrackingCategory} TrackingCategory */
20
22
  /** @typedef {import('./analytics/consts').TrackingType} TrackingType */
21
23
  /** @typedef {import('./analytics/consts').ResponseFlag} ResponseFlag */
24
+ /** @typedef {import('./LLM').LLMConfiguration} LLMConfiguration */
22
25
 
23
26
  /**
24
27
  * @typedef {object} AutoTypingConfig
@@ -110,6 +113,7 @@ const { prepareState, mergeState, isUserInteraction } = require('./utils/stateVa
110
113
  * @prop {string} [apiUrl] - Url for calling orchestrator API
111
114
  * @prop {Function} [fetch] - Fetch function for calling orchestrator API
112
115
  * @prop {number} [sessionDuration] - Session duration for analytic purposes
116
+ * @prop {LLMConfiguration} [llm] - LLM model configuration
113
117
  * @prop {Preloader<R>} [preloader]
114
118
  */
115
119
 
@@ -401,14 +405,19 @@ class Processor extends EventEmitter {
401
405
  return { status: 304 };
402
406
  }
403
407
 
408
+ const llm = new LLM({
409
+ provider: new LLMMockProvider(),
410
+ ...this.options.llm
411
+ });
412
+
404
413
  const result = await this
405
- ._dispatch(message, pageId, messageSender, responderData, preloadPromise);
414
+ ._dispatch(message, pageId, messageSender, responderData, preloadPromise, llm);
406
415
 
407
416
  messageSender.defer(preloadPromise, this.options.log);
408
417
  return result;
409
418
  }
410
419
 
411
- async _dispatch (message, pageId, messageSender, responderData, preloadPromise) {
420
+ async _dispatch (message, pageId, messageSender, responderData, preloadPromise, llm) {
412
421
  let req;
413
422
  let res;
414
423
  let state;
@@ -418,7 +427,14 @@ class Processor extends EventEmitter {
418
427
  ({
419
428
  req, res, data, state
420
429
  } = await this
421
- ._processMessage(message, pageId, messageSender, responderData, preloadPromise));
430
+ ._processMessage(
431
+ message,
432
+ pageId,
433
+ messageSender,
434
+ responderData,
435
+ llm,
436
+ preloadPromise
437
+ ));
422
438
 
423
439
  messageSender.defer(this._emitInteractionEvent(req, res, messageSender, state, data));
424
440
 
@@ -548,6 +564,7 @@ class Processor extends EventEmitter {
548
564
  pageId,
549
565
  messageSender,
550
566
  responderData,
567
+ llm,
551
568
  preloadPromise = null,
552
569
  senderMeta = null
553
570
  ) {
@@ -664,13 +681,13 @@ class Processor extends EventEmitter {
664
681
  _sts: sessionTs,
665
682
  _snew: sessionCreated
666
683
  });
667
- } else {
684
+ } /* else {
668
685
  Object.assign(state, {
669
686
  _snew: false
670
687
  });
671
- }
688
+ } */
672
689
 
673
- prepareState(state, fromEvent, state._snew);
690
+ prepareState(state, fromEvent, state._snew && fromEvent);
674
691
 
675
692
  const features = [
676
693
  ...(this.options.features || []),
@@ -690,7 +707,8 @@ class Processor extends EventEmitter {
690
707
  options,
691
708
  responderData,
692
709
  configuration,
693
- senderMeta
710
+ senderMeta,
711
+ llm
694
712
  );
695
713
  const postBack = this._createPostBack(postbackAcumulator, req, res, features);
696
714
 
@@ -852,6 +870,7 @@ class Processor extends EventEmitter {
852
870
  pageId,
853
871
  messageSender,
854
872
  responderData,
873
+ llm,
855
874
  res.senderMeta
856
875
  );
857
876
 
@@ -949,6 +968,7 @@ class Processor extends EventEmitter {
949
968
  pageId,
950
969
  messageSender,
951
970
  responderData,
971
+ llm,
952
972
  senderMeta
953
973
  ) {
954
974
  return postbackAcumulator.reduce((promise, postback) => promise
@@ -966,6 +986,7 @@ class Processor extends EventEmitter {
966
986
  pageId,
967
987
  messageSender,
968
988
  responderData,
989
+ llm,
969
990
  null,
970
991
  senderMeta
971
992
  );
package/src/Responder.js CHANGED
@@ -17,6 +17,8 @@ const {
17
17
  FEATURE_PHRASES
18
18
  } = require('./features');
19
19
  const transcriptFromHistory = require('./transcript/transcriptFromHistory');
20
+ const LLM = require('./LLM');
21
+ const LLMSession = require('./LLMSession');
20
22
 
21
23
  const TYPE_RESPONSE = 'RESPONSE';
22
24
  const TYPE_UPDATE = 'UPDATE';
@@ -28,8 +30,11 @@ const EXCEPTION_HOPCOUNT_THRESHOLD = 5;
28
30
  /** @typedef {import('./ReturnSender').SendOptions} SendOptions */
29
31
  /** @typedef {import('./ReturnSender').TextFilter} TextFilter */
30
32
  /** @typedef {import('./analytics/consts').TrackingCategory} TrackingCategory */
31
- /** @typedef {import('./analytics/consts').TrackingType} TrackingType */
32
33
  /** @typedef {import('./transcript/transcriptFromHistory').Transcript} Transcript */
34
+ /** @typedef {import('./analytics/consts').TrackingType} TrackingType */
35
+
36
+ /** @typedef {import('./LLM').LLMConfiguration} LLMConfiguration */
37
+ /** @typedef {import('./LLMSession').LLMMessage} LLMMessage */
33
38
 
34
39
  /**
35
40
  * @enum {string} ExpectedInput
@@ -98,6 +103,16 @@ Object.freeze(ExpectedInput);
98
103
  * @prop {string} [name]
99
104
  */
100
105
 
106
+ /**
107
+ * @callback PromptGetter
108
+ * @param {Responder} res
109
+ * @returns {string|Promise<string>}
110
+ */
111
+
112
+ /**
113
+ * @typedef {PromptGetter|string} PromptSource
114
+ */
115
+
101
116
  const PERSONA_DEFAULT = '_default';
102
117
 
103
118
  /**
@@ -114,12 +129,14 @@ class Responder {
114
129
  options = {},
115
130
  data = {},
116
131
  configuration = {},
117
- senderMeta = null
132
+ senderMeta = null,
133
+ llm = null
118
134
  ) {
119
135
  this._messageSender = messageSender;
120
136
  this._senderId = senderId;
121
137
  this._pageId = options.pageId;
122
138
  this.token = token;
139
+
123
140
  this._configuration = configuration;
124
141
 
125
142
  /**
@@ -214,20 +231,156 @@ class Responder {
214
231
 
215
232
  /** @type {SendOptions} */
216
233
  this._nextMessageSendOptions = null;
234
+
235
+ /** @type {LLM} */
236
+ this.llm = llm;
237
+
238
+ this.LLM_CTX_DEFAULT = 'default';
239
+
240
+ /** @type {Map<string,(PromptSource|Promise<string>)[]>} */
241
+ this._llmContext = new Map([
242
+ [this.LLM_CTX_DEFAULT, []]
243
+ ]);
244
+ }
245
+
246
+ /**
247
+ *
248
+ * @param {PromptSource} systemPrompt
249
+ * @param {string} contextType
250
+ * @returns {this}
251
+ */
252
+ llmAddSystemPrompt (systemPrompt, contextType = this.LLM_CTX_DEFAULT) {
253
+ if (!systemPrompt) {
254
+ return this;
255
+ }
256
+ if (!this._llmContext.has(contextType)) {
257
+ // @todo make it array of messages / maybe keep it in a single array
258
+ this._llmContext.set(contextType, []);
259
+ }
260
+ this._llmContext.get(contextType).push(systemPrompt);
261
+
262
+ return this;
263
+ }
264
+
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 }));
269
+
270
+ return new LLMSession(this.llm, chat, this._llmSend.bind(this));
271
+ }
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
+
283
+ /**
284
+ *
285
+ * @param {string} contextType
286
+ * @param {string[]} [callStack]
287
+ * @returns {Promise<string[]>}
288
+ */
289
+ async _getSystemContentForType (contextType, callStack = []) {
290
+ if (new Set(callStack).size < callStack.length) {
291
+ throw new Error(`Circular reference detected: contextType -> ${callStack}`);
292
+ }
293
+
294
+ if (!this._llmContext.has(contextType)) {
295
+ return [];
296
+ }
297
+
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;
320
+ }
321
+
322
+ async llmSessionWithHistory (contextType = this.LLM_CTX_DEFAULT) {
323
+ const {
324
+ transcriptAnonymize,
325
+ transcriptFlag,
326
+ transcriptLength
327
+ } = this.llm.configuration;
328
+
329
+ const [systems, transcript] = await Promise.all([
330
+ this._getSystemContentForType(contextType),
331
+ this.getTranscript(transcriptLength, transcriptFlag)
332
+ ]);
333
+
334
+ const chat = [
335
+ ...systems.map((content) => ({ role: LLM.ROLE_SYSTEM, content })),
336
+ ...LLM.anonymizeTranscript(transcript, transcriptAnonymize)
337
+ ];
338
+
339
+ return new LLMSession(this.llm, chat, this._llmSend.bind(this));
340
+ }
341
+
342
+ /**
343
+ *
344
+ * @param {LLMMessage[]} messages
345
+ * @param {QuickReply[]} quickReplies
346
+ */
347
+ _llmSend (messages, quickReplies) {
348
+ this.setFlag(LLM.GPT_FLAG);
349
+
350
+ const { persona } = this.llm.configuration;
351
+
352
+ if (typeof persona === 'string') {
353
+ this.setPersona({ name: persona });
354
+ } else if (persona) {
355
+ this.setPersona(persona);
356
+ }
357
+
358
+ messages.forEach((m, i) => {
359
+ const addQuickReply = i === (messages.length - 1);
360
+ this.text(m.content, addQuickReply ? quickReplies : null);
361
+ });
362
+
363
+ if (persona) {
364
+ this.setPersona({ name: null });
365
+ }
217
366
  }
218
367
 
219
368
  _findPersonaConfiguration (name) {
369
+ // @ts-ignore
220
370
  if (!name || !this._configuration.persona) {
221
371
  return null;
222
372
  }
373
+ // @ts-ignore
223
374
  if (!this._configuration._cachedPersonas) {
224
- // eslint-disable-next-line no-param-reassign
375
+ // @ts-ignore
225
376
  this._configuration._cachedPersonas = new Map(
377
+ // @ts-ignore
226
378
  Object.entries(this._configuration.persona)
227
379
  .map(([k, v]) => [k === PERSONA_DEFAULT ? k : tokenize(k), v])
228
380
  );
229
381
  }
230
382
  const nameKey = name === PERSONA_DEFAULT ? PERSONA_DEFAULT : tokenize(name);
383
+ // @ts-ignore
231
384
  return this._configuration._cachedPersonas.get(nameKey);
232
385
  }
233
386
 
@@ -252,16 +405,16 @@ class Responder {
252
405
  */
253
406
  async getTranscript (limit = 10, onlyFlag = null, skipThisTurnaround = false) {
254
407
  const { chatLogStorage, timestamp } = this._messageSender;
255
- if (!chatLogStorage) {
256
- return [];
408
+ let transcript = [];
409
+ if (chatLogStorage) {
410
+ transcript = await transcriptFromHistory(
411
+ chatLogStorage,
412
+ this._senderId,
413
+ this._pageId,
414
+ limit,
415
+ onlyFlag
416
+ );
257
417
  }
258
- const transcript = await transcriptFromHistory(
259
- chatLogStorage,
260
- this._senderId,
261
- this._pageId,
262
- limit,
263
- onlyFlag
264
- );
265
418
  if (!skipThisTurnaround) {
266
419
  const { responseTexts = [], requestTexts = [] } = this._messageSender;
267
420
  transcript.push(...requestTexts.map((text) => ({
@@ -547,12 +700,18 @@ class Responder {
547
700
  this.routePath = routePath;
548
701
  }
549
702
 
703
+ /**
704
+ * @typedef {object} MessageOptions
705
+ * @prop {boolean} [disableAutoTyping]
706
+ */
707
+
550
708
  /**
551
709
  * Send text as a response
552
710
  *
553
711
  * @param {string} text - text to send to user, can contain placeholders (%s)
554
712
  * @param {Object.<string,string|QuickReply>|QuickReply[]} [replies] - quick replies
555
713
  * @param {VoiceControl} [voice] - voice control data
714
+ * @param {MessageOptions} [options={}]
556
715
  * @returns {this}
557
716
  *
558
717
  * @example
@@ -574,7 +733,7 @@ class Responder {
574
733
  * }
575
734
  * ]);
576
735
  */
577
- text (text, replies = null, voice = null) {
736
+ text (text, replies = null, voice = null, options = {}) {
578
737
  const messageData = {
579
738
  message: {
580
739
  text: this._t(text)
@@ -624,7 +783,9 @@ class Responder {
624
783
  }
625
784
  }
626
785
 
627
- this._autoTypingIfEnabled(messageData.message.text);
786
+ if (!options.disableAutoTyping) {
787
+ this._autoTypingIfEnabled(messageData.message.text);
788
+ }
628
789
  this.send(messageData);
629
790
  return this;
630
791
  }
@@ -11,6 +11,7 @@ const extractText = require('./transcript/extractText');
11
11
  /** @typedef {import('./Request')} Request */
12
12
  /** @typedef {import('./Responder')} Responder */
13
13
  /** @typedef {import('./Processor').TrackingObject} TrackingObject */
14
+ /** @typedef {import('./LLMContext').LLMMessage} LLMMessage */
14
15
 
15
16
  /**
16
17
  * @callback GetInteractions
package/src/Tester.js CHANGED
@@ -18,6 +18,7 @@ const ResponseAssert = require('./testTools/ResponseAssert');
18
18
  const Router = require('./Router'); // eslint-disable-line no-unused-vars
19
19
  const ReducerWrapper = require('./ReducerWrapper'); // eslint-disable-line no-unused-vars
20
20
  const { FEATURE_TEXT } = require('./features');
21
+ const LLMMockProvider = require('./LLMMockProvider');
21
22
 
22
23
  /** @typedef {import('./Processor').ProcessorOptions<Router>} ProcessorOptions */
23
24
 
@@ -100,6 +101,10 @@ class Tester {
100
101
  log,
101
102
  // @ts-ignore
102
103
  loadUsers: false,
104
+ llm: {
105
+ provider: new LLMMockProvider(),
106
+ ...processorOptions.llm
107
+ },
103
108
  ...processorOptions
104
109
  }));
105
110
 
@@ -28,8 +28,8 @@ function button (params, context) {
28
28
  buttons = [],
29
29
  text = null
30
30
  } = params;
31
- const compiledText = cachedTranslatedCompilator(text);
32
31
 
32
+ const compiledText = cachedTranslatedCompilator(text);
33
33
  const condition = getCondition(params, context, 'button');
34
34
 
35
35
  const ret = isLastIndex ? Router.END : Router.CONTINUE;
@@ -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;