wingbot 3.71.5 → 3.72.0

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.
Files changed (152) hide show
  1. package/.babelrc +0 -0
  2. package/.github/workflows/deploy.yml +2 -2
  3. package/.github/workflows/pullRequest.yml +2 -2
  4. package/LICENSE +0 -0
  5. package/README.md +0 -0
  6. package/index.js +0 -0
  7. package/jsconfig.json +0 -0
  8. package/package.json +1 -1
  9. package/plugins/ai.wingbot.clearMessageSequences/plugin.js +0 -0
  10. package/plugins/ai.wingbot.conditionIfGoBackPossible/plugin.js +0 -0
  11. package/plugins/ai.wingbot.disambiguation/plugin.js +0 -0
  12. package/plugins/ai.wingbot.goBack/plugin.js +0 -0
  13. package/plugins/ai.wingbot.goToLastBreadcrumb/plugin.js +0 -0
  14. package/plugins/ai.wingbot.ifImageDetected/plugin.js +0 -0
  15. package/plugins/ai.wingbot.ifStickerDetected/plugin.js +0 -0
  16. package/plugins/ai.wingbot.jumpBack/plugin.js +0 -0
  17. package/plugins/ai.wingbot.jumpTo/plugin.js +0 -0
  18. package/plugins/ai.wingbot.keepInInteraction/plugin.js +0 -0
  19. package/plugins/ai.wingbot.keepInInteractionJustOnce/plugin.js +0 -0
  20. package/plugins/ai.wingbot.keepPreviousHandlers/plugin.js +0 -0
  21. package/plugins/ai.wingbot.keepPreviousHandlersJustOnce/plugin.js +0 -0
  22. package/plugins/ai.wingbot.oneTimeNotificationRequest/plugin.js +0 -0
  23. package/plugins/ai.wingbot.openai/plugin.js +0 -0
  24. package/plugins/ai.wingbot.passThreadToBot/plugin.js +0 -0
  25. package/plugins/ai.wingbot.persona/plugin.js +0 -0
  26. package/plugins/ai.wingbot.putABreadcrumb/plugin.js +0 -0
  27. package/plugins/ai.wingbot.regexp/plugin.js +0 -0
  28. package/plugins/ai.wingbot.setState/plugin.js +0 -0
  29. package/plugins/ai.wingbot.setStateFromInput/plugin.js +0 -0
  30. package/plugins/ai.wingbot.slotsContinue/plugin.js +0 -0
  31. package/plugins/ai.wingbot.slotsRegister/plugin.js +0 -0
  32. package/plugins/ai.wingbot.stopResponding/plugin.js +0 -0
  33. package/plugins/ai.wingbot.trackingEvent/plugin.js +0 -0
  34. package/plugins/ai.wingbot.upload/plugin.js +0 -0
  35. package/plugins/ai.wingbot.waitASecond/plugin.js +0 -0
  36. package/plugins/index.js +0 -0
  37. package/plugins/plugins.json +0 -0
  38. package/src/Ai.js +44 -3
  39. package/src/AiMatching.js +66 -40
  40. package/src/BatchConversationTester.js +0 -0
  41. package/src/BotApp.js +0 -0
  42. package/src/BotAppSender.js +0 -0
  43. package/src/BuildRouter.js +2 -0
  44. package/src/CallbackAuditLog.js +0 -0
  45. package/src/ChatGpt.js +0 -0
  46. package/src/ConversationTester.js +0 -0
  47. package/src/LLM.js +184 -3
  48. package/src/LLMMockProvider.js +0 -0
  49. package/src/LLMSession.js +90 -3
  50. package/src/MockAiModel.js +0 -0
  51. package/src/OrchestratorClient.js +0 -0
  52. package/src/Plugins.js +0 -0
  53. package/src/Processor.js +1 -1
  54. package/src/ReducerWrapper.js +0 -0
  55. package/src/Request.js +0 -0
  56. package/src/Responder.js +142 -11
  57. package/src/ReturnSender.js +4 -4
  58. package/src/Router.js +0 -0
  59. package/src/RouterWrap.js +0 -0
  60. package/src/SecurityMiddleware.js +0 -0
  61. package/src/Tester.js +44 -2
  62. package/src/analytics/GA4.js +0 -0
  63. package/src/analytics/consts.js +0 -0
  64. package/src/analytics/onInteractionHandler.js +0 -0
  65. package/src/defaultResourceMap.js +0 -0
  66. package/src/features.js +0 -0
  67. package/src/flags.js +0 -0
  68. package/src/fuzzy/factoryFuzzySearch.js +0 -0
  69. package/src/fuzzy/fuzzyUtils.js +0 -0
  70. package/src/fuzzy/index.js +0 -0
  71. package/src/fuzzy/levenshtein.js +0 -0
  72. package/src/fuzzy/normalize.js +0 -0
  73. package/src/fuzzy/prepareFuzzyIndex.js +0 -0
  74. package/src/graphApi/GraphApi.js +0 -0
  75. package/src/graphApi/WingbotApiConnector.js +0 -0
  76. package/src/graphApi/apiAuthorizer.js +0 -0
  77. package/src/graphApi/conversationTestApi.js +0 -0
  78. package/src/graphApi/conversationsApi.js +0 -0
  79. package/src/graphApi/index.js +0 -0
  80. package/src/graphApi/postBackApi.js +0 -0
  81. package/src/graphApi/schema.gql +0 -0
  82. package/src/graphApi/validateBotApi.js +0 -0
  83. package/src/notifications/Notifications.js +0 -0
  84. package/src/notifications/NotificationsStorage.js +0 -0
  85. package/src/notifications/api/index.js +0 -0
  86. package/src/notifications/api/notificationsApiFactory.js +0 -0
  87. package/src/notifications/index.js +0 -0
  88. package/src/resolvers/bounce.js +0 -0
  89. package/src/resolvers/button.js +0 -0
  90. package/src/resolvers/carousel.js +0 -0
  91. package/src/resolvers/contextMessage.js +21 -4
  92. package/src/resolvers/expected.js +0 -0
  93. package/src/resolvers/expectedInput.js +0 -0
  94. package/src/resolvers/hbs.js +0 -0
  95. package/src/resolvers/include.js +0 -0
  96. package/src/resolvers/index.js +0 -0
  97. package/src/resolvers/media.js +0 -0
  98. package/src/resolvers/message.js +54 -4
  99. package/src/resolvers/passThread.js +0 -0
  100. package/src/resolvers/path.js +0 -0
  101. package/src/resolvers/plugin.js +0 -0
  102. package/src/resolvers/postback.js +0 -0
  103. package/src/resolvers/resolverTags.js +0 -0
  104. package/src/resolvers/setState.js +0 -0
  105. package/src/resolvers/skip.js +0 -0
  106. package/src/resolvers/subscribtions.js +0 -0
  107. package/src/resolvers/utils.js +14 -5
  108. package/src/systemEntities/email.js +0 -0
  109. package/src/systemEntities/index.js +0 -0
  110. package/src/systemEntities/phone.js +0 -0
  111. package/src/systemEntities/regexps.js +0 -0
  112. package/src/templates/BaseTemplate.js +0 -0
  113. package/src/templates/ButtonTemplate.js +0 -0
  114. package/src/templates/GenericTemplate.js +0 -0
  115. package/src/templates/ListTemplate.js +0 -0
  116. package/src/templates/ReceiptTemplate.js +0 -0
  117. package/src/testTools/AnyResponseAssert.js +0 -0
  118. package/src/testTools/PromptAssert.js +184 -0
  119. package/src/testTools/ResponseAssert.js +0 -0
  120. package/src/testTools/asserts.js +42 -4
  121. package/src/testTools/index.js +0 -0
  122. package/src/tools/MemoryBotConfigStorage.js +0 -0
  123. package/src/tools/MemoryChatLogStorage.js +0 -0
  124. package/src/tools/MemoryStateStorage.js +0 -0
  125. package/src/tools/bufferloader.js +0 -0
  126. package/src/tools/index.js +0 -0
  127. package/src/tools/routeToEvents.js +0 -0
  128. package/src/transcript/extractText.js +0 -0
  129. package/src/transcript/textBodyFromTranscript.js +0 -0
  130. package/src/transcript/transcriptFromHistory.js +0 -0
  131. package/src/utils/ai.js +0 -0
  132. package/src/utils/compileWithState.js +0 -0
  133. package/src/utils/customCondition.js +14 -1
  134. package/src/utils/customFn.js +0 -0
  135. package/src/utils/datetime.js +0 -0
  136. package/src/utils/deepMapTools.js +0 -0
  137. package/src/utils/generateToken.js +0 -0
  138. package/src/utils/getCondition.js +16 -4
  139. package/src/utils/getUpdate.js +4 -4
  140. package/src/utils/headersToAuditMeta.js +0 -0
  141. package/src/utils/index.js +0 -0
  142. package/src/utils/pathUtils.js +0 -0
  143. package/src/utils/quickReplies.js +0 -0
  144. package/src/utils/slots.js +0 -0
  145. package/src/utils/stateData.js +2 -0
  146. package/src/utils/stateVariables.js +0 -0
  147. package/src/utils/tokenizer.js +0 -0
  148. package/src/utils/wrapPluginFunction.js +0 -0
  149. package/src/wingbot/CachedModel.js +0 -0
  150. package/src/wingbot/CustomEntityDetectionModel.js +0 -0
  151. package/src/wingbot/WingbotModel.js +0 -0
  152. package/src/wingbot/index.js +0 -0
package/.babelrc CHANGED
File without changes
@@ -15,7 +15,7 @@ jobs:
15
15
 
16
16
  strategy:
17
17
  matrix:
18
- node-version: [16.x]
18
+ node-version: [20.x]
19
19
 
20
20
  steps:
21
21
 
@@ -23,7 +23,7 @@ jobs:
23
23
  uses: actions/checkout@v2
24
24
 
25
25
  - name: Node.js ${{ matrix.node-version }} setup
26
- uses: actions/setup-node@v2
26
+ uses: actions/setup-node@v3
27
27
  with:
28
28
  node-version: ${{ matrix.node-version }}
29
29
  cache: 'npm'
@@ -11,7 +11,7 @@ jobs:
11
11
 
12
12
  strategy:
13
13
  matrix:
14
- node-version: [16.x]
14
+ node-version: [20.x]
15
15
 
16
16
  steps:
17
17
 
@@ -19,7 +19,7 @@ jobs:
19
19
  uses: actions/checkout@v2
20
20
 
21
21
  - name: Node.js ${{ matrix.node-version }} setup
22
- uses: actions/setup-node@v2
22
+ uses: actions/setup-node@v3
23
23
  with:
24
24
  node-version: ${{ matrix.node-version }}
25
25
  cache: 'npm'
package/LICENSE CHANGED
File without changes
package/README.md CHANGED
File without changes
package/index.js CHANGED
File without changes
package/jsconfig.json CHANGED
File without changes
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wingbot",
3
- "version": "3.71.5",
3
+ "version": "3.72.0",
4
4
  "description": "Enterprise Messaging Bot Conversation Engine",
5
5
  "main": "index.js",
6
6
  "type": "commonjs",
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
package/plugins/index.js CHANGED
File without changes
File without changes
package/src/Ai.js CHANGED
@@ -41,8 +41,10 @@ let uq = 1;
41
41
 
42
42
  /** @typedef {import('./Request').IntentAction} IntentAction */
43
43
  /** @typedef {import('./Request')} Request */
44
+ /** @typedef {import('./Request').TextAlternative} TextAlternative */
44
45
  /** @typedef {import('./Responder')} Responder */
45
46
  /** @typedef {import('./Router').Resolver} Resolver */
47
+ /** @typedef {import('./utils/stateData').IStateRequest} IStateRequest */
46
48
  /** @typedef {import('./wingbot/CachedModel').Result} Result */
47
49
  /** @typedef {import('./wingbot/CustomEntityDetectionModel').Phrases} Phrases */
48
50
  /** @typedef {import('./wingbot/CustomEntityDetectionModel').EntityDetector} EntityDetector */
@@ -137,7 +139,7 @@ class Ai {
137
139
  * The prefix translator - for request-specific prefixes
138
140
  *
139
141
  * @param {string} defaultModel
140
- * @param {Request} req
142
+ * @param {IStateRequest} req
141
143
  */
142
144
  this.getPrefix = (defaultModel, req) => req.state.lang || defaultModel; // eslint-disable-line
143
145
 
@@ -857,11 +859,22 @@ class Ai {
857
859
  .filter((alt) => alt.score >= this.sttScoreThreshold)
858
860
  .slice(0, this.sttMaxAlternatives);
859
861
 
860
- const altMax = Math.max(0, ...texts.map((t) => t.score));
862
+ return this._queryModelWithTexts(model, texts, req);
863
+ }
864
+
865
+ /**
866
+ *
867
+ * @param {CustomEntityDetectionModel} model
868
+ * @param {TextAlternative[]} texts
869
+ * @param {Request} [req]
870
+ * @returns {Promise<Result>}
871
+ */
872
+ async _queryModelWithTexts (model, texts, req = null) {
861
873
  const altKoef = (1 - this.confidence);
874
+ const altMax = Math.max(0, ...texts.map((t) => t.score));
862
875
 
863
876
  const results = await Promise.all(
864
- texts.map(({ text, score }) => model
877
+ texts.map(({ text, score = 1 }) => model
865
878
  .resolve(this.textFilter(text), req)
866
879
  .then((res) => ({
867
880
  ...res,
@@ -910,6 +923,34 @@ class Ai {
910
923
  };
911
924
  }
912
925
 
926
+ /**
927
+ *
928
+ * @param {string} text
929
+ * @param {string|IStateRequest} langOrReq
930
+ * @returns {Promise<Result>}
931
+ */
932
+ async queryModel (text, langOrReq = this.DEFAULT_PREFIX) {
933
+ let model;
934
+
935
+ if (typeof langOrReq === 'string') {
936
+ model = this._keyworders.has(langOrReq)
937
+ ? this._keyworders.get(langOrReq)
938
+ : this._keyworders.get(this.DEFAULT_PREFIX);
939
+ } else {
940
+ model = this._getModelForRequest(langOrReq);
941
+ }
942
+
943
+ if (!model) {
944
+ return {
945
+ text,
946
+ intents: [],
947
+ entities: []
948
+ };
949
+ }
950
+
951
+ return this._queryModelWithTexts(model, [{ text, score: 1 }]);
952
+ }
953
+
913
954
  /**
914
955
  *
915
956
  * @param {IntentAction[]} aiActions
package/src/AiMatching.js CHANGED
@@ -3,11 +3,12 @@
3
3
  */
4
4
  'use strict';
5
5
 
6
- const { replaceDiacritics } = require('./utils/tokenizer');
6
+ const { replaceDiacritics, tokenize } = require('./utils/tokenizer');
7
7
  const { vars } = require('./utils/stateVariables');
8
8
  const stateData = require('./utils/stateData');
9
9
 
10
10
  /** @typedef {import('handlebars')} Handlebars */
11
+ /** @typedef {import('./Ai').Result} Result */
11
12
 
12
13
  /** @type {Handlebars} */
13
14
  let handlebars;
@@ -66,16 +67,18 @@ const COMPARE = {
66
67
 
67
68
  /**
68
69
  * @typedef {object} Entity
69
- * @param {string} entity
70
- * @param {string} value
71
- * @param {number} score
70
+ * @prop {string} entity
71
+ * @prop {string} value
72
+ * @prop {number} score
73
+ * @prop {number} [start]
74
+ * @prop {number} [end]
72
75
  */
73
76
 
74
77
  /**
75
78
  * @typedef {object} Intent
76
- * @param {string} [intent]
77
- * @param {number} score
78
- * @param {Entity[]} [entities]
79
+ * @prop {string} [intent]
80
+ * @prop {number} score
81
+ * @prop {Entity[]} [entities]
79
82
  */
80
83
 
81
84
  /**
@@ -461,35 +464,35 @@ class AiMatching {
461
464
  }
462
465
 
463
466
  /**
464
- * Calculate a matching score of preprocessed rule against the request
465
467
  *
466
- * @param {AIRequest} req
468
+ * @param {string} text
467
469
  * @param {PreprocessorOutput} rule
468
- * @param {boolean} [stateless]
469
- * @param {Entity[]} [reqEntities]
470
- * @param {boolean} [noEntityThreshold]
470
+ * @param {Result} nlpResult
471
+ * @param {{}} state
471
472
  * @returns {Intent|null}
472
473
  */
473
- match (req, rule, stateless = false, reqEntities = req.entities, noEntityThreshold = false) {
474
- const { regexps, intents, entities } = rule;
474
+ matchText (text, rule, nlpResult, state = {}) {
475
+ return this._match(text, rule, state, nlpResult, true);
476
+ }
475
477
 
476
- const noIntentHandicap = req.intents.length === 0 ? 0 : this.redundantIntentHandicap;
477
- const regexpScore = this._matchRegexp(req, regexps, noIntentHandicap);
478
- const textLength = req.text().trim().length;
478
+ _match (text, rule, useState, nlpResult, stateless = false, noEntityThreshold = false) {
479
+ let state = useState;
479
480
 
480
- let useState;
481
- if (stateless || intents.length === 0) {
482
- useState = Object.entries(stateData(req))
483
- .reduce((o, [k, v]) => {
484
- if (k.startsWith('@')) {
485
- return o;
486
- }
487
- return Object.assign(o, { [k]: v });
488
- }, {});
489
- } else {
490
- useState = stateData(req);
481
+ if (stateless) {
482
+ state = Object.fromEntries(
483
+ Object.entries(state)
484
+ .filter(([k]) => !k.startsWith('@'))
485
+ );
491
486
  }
492
487
 
488
+ const { regexps, intents, entities } = rule;
489
+ const { entities: reqEntities = [], intents: reqIntents = [] } = nlpResult;
490
+ const tokenized = tokenize(text) || text.trim();
491
+
492
+ const noIntentHandicap = reqIntents.length === 0 ? 0 : this.redundantIntentHandicap;
493
+ const regexpScore = this._matchRegexp(text, tokenized, regexps, noIntentHandicap);
494
+ const textLength = text.length;
495
+
493
496
  if (regexpScore !== 0 || (intents.length === 0 && regexps.length === 0)) {
494
497
 
495
498
  if (entities.length === 0) {
@@ -511,7 +514,7 @@ class AiMatching {
511
514
  textLength,
512
515
  entities,
513
516
  reqEntities,
514
- useState,
517
+ state,
515
518
  undefined,
516
519
  undefined,
517
520
  noEntityThreshold
@@ -563,7 +566,7 @@ class AiMatching {
563
566
  };
564
567
  }
565
568
 
566
- if (!req.intents || req.intents.length === 0) {
569
+ if (reqIntents.length === 0) {
567
570
  return null;
568
571
  }
569
572
 
@@ -572,15 +575,15 @@ class AiMatching {
572
575
  intents
573
576
  .reduce((total, wanted) => {
574
577
  let max = total;
575
- for (const requestIntent of req.intents) {
578
+ for (const requestIntent of reqIntents) {
576
579
  const { score, entities: matchedEntities } = this
577
580
  ._intentMatchingScore(
578
581
  textLength,
579
582
  wanted,
580
583
  requestIntent,
581
584
  entities,
582
- req,
583
- useState,
585
+ reqEntities,
586
+ state,
584
587
  noEntityThreshold
585
588
  );
586
589
 
@@ -602,6 +605,27 @@ class AiMatching {
602
605
  return winningIntent;
603
606
  }
604
607
 
608
+ /**
609
+ * Calculate a matching score of preprocessed rule against the request
610
+ *
611
+ * @param {AIRequest} req
612
+ * @param {PreprocessorOutput} rule
613
+ * @param {boolean} [stateless]
614
+ * @param {Entity[]} [reqEntities]
615
+ * @param {boolean} [noEntityThreshold]
616
+ * @returns {Intent|null}
617
+ */
618
+ match (req, rule, stateless = false, reqEntities = req.entities, noEntityThreshold = false) {
619
+ const { intents } = rule;
620
+
621
+ const state = stateData(req);
622
+
623
+ return this._match(req.text(), rule, state, {
624
+ intents: req.intents,
625
+ entities: reqEntities
626
+ }, stateless || intents.length === 0, noEntityThreshold);
627
+ }
628
+
605
629
  _getMultiMatchGain (entitiesScore, matchedCount, fromState = 0) {
606
630
  return (this.multiMatchGain * entitiesScore) ** Math.max(matchedCount - fromState, 0);
607
631
  }
@@ -613,7 +637,7 @@ class AiMatching {
613
637
  * @param {string} wantedIntent
614
638
  * @param {Intent} requestIntent
615
639
  * @param {EntityExpression[]} wantedEntities
616
- * @param {AIRequest} req
640
+ * @param {Entity[]} reqEntities
617
641
  * @param {object} useState
618
642
  * @param {boolean} [noEntityThreshold]
619
643
  * @returns {{score:number,entities:Entity[]}}
@@ -623,7 +647,7 @@ class AiMatching {
623
647
  wantedIntent,
624
648
  requestIntent,
625
649
  wantedEntities,
626
- req,
650
+ reqEntities,
627
651
  useState,
628
652
  noEntityThreshold = false
629
653
  ) {
@@ -631,7 +655,7 @@ class AiMatching {
631
655
  return { score: 0, entities: [] };
632
656
  }
633
657
 
634
- const useEntities = requestIntent.entities || req.entities;
658
+ const useEntities = requestIntent.entities || reqEntities;
635
659
 
636
660
  if (wantedEntities.length === 0) {
637
661
  return {
@@ -651,7 +675,7 @@ class AiMatching {
651
675
  requestIntent.entities
652
676
  ? (x) => Math.atan((x - 0.76) * 40) / Math.atan((1 - 0.76) * 40)
653
677
  : (x) => x,
654
- req.entities,
678
+ reqEntities,
655
679
  noEntityThreshold
656
680
  );
657
681
 
@@ -941,18 +965,20 @@ class AiMatching {
941
965
 
942
966
  /**
943
967
  *
944
- * @param {AIRequest} req
968
+ * @param {string} text
969
+ * @param {string} tokenized
945
970
  * @param {RegexpComparator[]} regexps
946
971
  * @param {number} noIntentHandicap
947
972
  * @returns {number}
948
973
  */
949
- _matchRegexp (req, regexps, noIntentHandicap) {
974
+ _matchRegexp (text, tokenized, regexps, noIntentHandicap) {
950
975
  if (regexps.length === 0) {
951
976
  return 0;
952
977
  }
953
978
 
954
979
  const scores = regexps.map(({ r, t, f }) => {
955
- const m = req.text(t).match(r);
980
+ const txt = t ? tokenized : text;
981
+ const m = txt.match(r);
956
982
 
957
983
  if (!m) {
958
984
  return 0;
File without changes
package/src/BotApp.js CHANGED
File without changes
File without changes
@@ -162,6 +162,7 @@ const DUMMY_ROUTE = { id: 0, path: null, resolvers: [] };
162
162
  * @prop {Block[]} [blocks]
163
163
  * @prop {NestedLinksMapFactory} [nestedLinksMapFactory]
164
164
  * @prop {object} [BuildRouter]
165
+ * @prop {Ai} [ai]
165
166
  * @prop {string|number} [resolverId] - only for text messages with random characters
166
167
  */
167
168
 
@@ -928,6 +929,7 @@ class BuildRouter extends Router {
928
929
  return resolvers.map((resolver, i) => {
929
930
 
930
931
  const context = {
932
+ ai: Ai.ai,
931
933
  ...this._resolvedContext,
932
934
  isLastIndex: lastIndex === i && !buildInfo.expectedToAddResolver,
933
935
  isLastMessage: lastMessageIndex === i && !buildInfo.notLastMessage,
File without changes
package/src/ChatGpt.js CHANGED
File without changes
File without changes