wingbot 3.26.0-alpha.3 → 3.26.2

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wingbot",
3
- "version": "3.26.0-alpha.3",
3
+ "version": "3.26.2",
4
4
  "description": "Enterprise Messaging Bot Conversation Engine",
5
5
  "main": "index.js",
6
6
  "scripts": {
package/src/AiMatching.js CHANGED
@@ -6,6 +6,18 @@
6
6
  const { replaceDiacritics } = require('./utils/tokenizer');
7
7
  const { vars } = require('./utils/stateVariables');
8
8
 
9
+ /** @typedef {import('handlebars')} Handlebars */
10
+
11
+ /** @type {Handlebars} */
12
+ let handlebars;
13
+ try {
14
+ // @ts-ignore
15
+ handlebars = module.require('handlebars');
16
+ } catch (er) {
17
+ // @ts-ignore
18
+ handlebars = { compile: (text) => () => text };
19
+ }
20
+
9
21
  const FULL_EMOJI_REGEX = /^#((?:[\u2600-\u27bf].?|(?:\ud83c[\udde6-\uddff]){2}|[\ud800-\udbff][\udc00-\udfff])+)$/;
10
22
  const HAS_CLOSING_HASH = /^#(.+)#$/;
11
23
  const ENTITY_REGEX = /^@([^=><!?]+)(\?)?([!=><]{1,2})?([^=><!]+)?$/i;
@@ -46,7 +58,7 @@ const COMPARE = {
46
58
  * @prop {string} entity - the requested entity
47
59
  * @prop {boolean} [optional] - the match is optional
48
60
  * @prop {Compare} [op] - comparison operation
49
- * @prop {string[]|number[]} [compare] - value to compare with
61
+ * @prop {(string|number|Function)[]} [compare] - value to compare
50
62
  */
51
63
 
52
64
  /**
@@ -138,6 +150,17 @@ class AiMatching {
138
150
  return returnIfEmpty;
139
151
  }
140
152
 
153
+ _hbsOrFn (value, cb) {
154
+ if (typeof value === 'string' && value.match(/\{\{.+\}\}/)) {
155
+ const compiler = handlebars.compile(value);
156
+ return (data) => {
157
+ const res = compiler(data);
158
+ return cb(res);
159
+ };
160
+ }
161
+ return cb(value);
162
+ }
163
+
141
164
  _normalizeComparisonArray (compare, op) {
142
165
  const arr = Array.isArray(compare) ? compare : [compare];
143
166
 
@@ -150,7 +173,7 @@ class AiMatching {
150
173
  const [val] = arr;
151
174
 
152
175
  return [
153
- this._normalizeToNumber(val, 0)
176
+ this._hbsOrFn(val, (r) => this._normalizeToNumber(r, 0))
154
177
  ];
155
178
  }
156
179
 
@@ -158,12 +181,12 @@ class AiMatching {
158
181
  const [min, max] = arr;
159
182
 
160
183
  return [
161
- this._normalizeToNumber(min, -Infinity),
162
- this._normalizeToNumber(max, Infinity)
184
+ this._hbsOrFn(min, (r) => this._normalizeToNumber(r, -Infinity)),
185
+ this._hbsOrFn(max, (r) => this._normalizeToNumber(r, Infinity))
163
186
  ];
164
187
  }
165
188
 
166
- return arr.map((cmp) => `${cmp}`);
189
+ return arr.map((cmp) => this._hbsOrFn(cmp, (r) => `${r}`));
167
190
  }
168
191
 
169
192
  _stringOpToOperation (op) {
@@ -227,7 +250,8 @@ class AiMatching {
227
250
 
228
251
  if (rule.op === COMPARE.EQUAL
229
252
  && rule.compare
230
- && rule.compare.length === 1) {
253
+ && rule.compare.length === 1
254
+ && typeof rule.compare[0] !== 'function') {
231
255
 
232
256
  const key = `@${rule.entity}`;
233
257
  const value = rule.compare[0];
@@ -379,13 +403,27 @@ class AiMatching {
379
403
  score: regexpScore - handicap
380
404
  };
381
405
  }
406
+
407
+ let useState;
408
+ if (stateless) {
409
+ useState = {};
410
+ } else if (intents.length === 0) {
411
+ useState = Object.entries(req.state)
412
+ .reduce((o, [k, v]) => {
413
+ if (k.startsWith('@')) {
414
+ return o;
415
+ }
416
+ return Object.assign(o, { [k]: v });
417
+ }, {});
418
+ } else {
419
+ useState = req.state;
420
+ }
421
+
382
422
  const { score, handicap, matched } = this
383
423
  ._entityMatching(
384
424
  entities,
385
425
  reqEntities,
386
- stateless || intents.length === 0
387
- ? {}
388
- : req.state
426
+ useState
389
427
  );
390
428
 
391
429
  const allOptional = entities.every((e) => e.optional);
@@ -519,7 +557,7 @@ class AiMatching {
519
557
  return false;
520
558
  }
521
559
  entityExists = true;
522
- return this._entityIsMatching(wanted.op, wanted.compare, e.value);
560
+ return this._entityIsMatching(wanted.op, wanted.compare, e.value, requestState);
523
561
  });
524
562
 
525
563
  let requestEntity = requestEntities[index];
@@ -543,11 +581,13 @@ class AiMatching {
543
581
  };
544
582
 
545
583
  matching = this
546
- ._entityIsMatching(wanted.op, wanted.compare, requestEntity.value);
584
+ ._entityIsMatching(
585
+ wanted.op, wanted.compare, requestEntity.value, requestState
586
+ );
547
587
  }
548
588
  } else if (!entityExists) {
549
589
  matching = this
550
- ._entityIsMatching(wanted.op, wanted.compare, undefined);
590
+ ._entityIsMatching(wanted.op, wanted.compare, undefined, requestState);
551
591
  }
552
592
 
553
593
  if (!matching && !wanted.optional) {
@@ -600,7 +640,7 @@ class AiMatching {
600
640
  };
601
641
  }
602
642
 
603
- _entityIsMatching (op, compare, value) {
643
+ _entityIsMatching (op, compare, value, requestState) {
604
644
  const operation = op || (typeof compare !== 'undefined' ? COMPARE.EQUAL : null);
605
645
 
606
646
  if (typeof value === 'undefined') {
@@ -609,13 +649,17 @@ class AiMatching {
609
649
  : false;
610
650
  }
611
651
 
652
+ const useCmp = (compare || []).map((c) => (typeof c === 'function'
653
+ ? c(requestState)
654
+ : c));
655
+
612
656
  switch (operation) {
613
657
  case COMPARE.EQUAL:
614
- return compare.length === 0 || compare.includes(`${value}`);
658
+ return useCmp.length === 0 || useCmp.includes(`${value}`);
615
659
  case COMPARE.NOT_EQUAL:
616
- return compare.length !== 0 && !compare.includes(`${value}`);
660
+ return useCmp.length !== 0 && !useCmp.includes(`${value}`);
617
661
  case COMPARE.RANGE: {
618
- const [min, max] = compare;
662
+ const [min, max] = useCmp;
619
663
  const normalized = this._normalizeToNumber(value);
620
664
  if (normalized === null) {
621
665
  return false;
@@ -626,7 +670,7 @@ class AiMatching {
626
670
  case COMPARE.LT:
627
671
  case COMPARE.GTE:
628
672
  case COMPARE.LTE: {
629
- const [cmp] = compare;
673
+ const [cmp] = useCmp;
630
674
  const normalized = this._normalizeToNumber(value);
631
675
  if (normalized === null) {
632
676
  return false;
@@ -194,8 +194,14 @@ class CustomEntityDetectionModel {
194
194
  }
195
195
  }
196
196
 
197
- _escapeRegex (string) {
198
- return string.replace(/[-/\\^$*+?.()|[\]{}]/g, '\\$&');
197
+ _escapeRegex (string, shouldReplaceDiacritics) {
198
+ const ret = string.replace(/[-/\\^$*+?.()|[\]{}]/g, '\\$&');
199
+
200
+ if (!shouldReplaceDiacritics) {
201
+ return ret;
202
+ }
203
+
204
+ return replaceDiacritics(ret);
199
205
  }
200
206
 
201
207
  /**
@@ -284,12 +290,12 @@ class CustomEntityDetectionModel {
284
290
  * @param {string} text
285
291
  * @param {string} [singleEntity]
286
292
  * @param {string[]} expectedEntities
293
+ * @param {DetectedEntity[]} [entities] - previously detected entities to include
287
294
  * @returns {Promise<DetectedEntity[]>}
288
295
  */
289
- async resolveEntities (text, singleEntity = null, expectedEntities = []) {
296
+ async resolveEntities (text, singleEntity = null, expectedEntities = [], entities = []) {
290
297
  const resolved = new Set();
291
298
  let missing = Array.from(this._entityDetectors.keys());
292
- const entities = [];
293
299
 
294
300
  while (missing.length !== 0) {
295
301
  let detect = [];
@@ -426,7 +432,7 @@ class CustomEntityDetectionModel {
426
432
  let replaced = source.replace(/@[A-Z0-9-]+/g, (value) => {
427
433
  const matchingEntities = entities
428
434
  .filter((e) => `@${e.entity.toUpperCase()}` === value)
429
- .map((e) => this._escapeRegex(e.text));
435
+ .map((e) => this._escapeRegex(e.text, options.replaceDiacritics));
430
436
 
431
437
  if (matchingEntities.length === 0) {
432
438
  return value;