wingbot 3.75.9-alpha.6 → 3.76.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.
@@ -0,0 +1,4 @@
1
+ {
2
+ "version": 1,
3
+ "goals": {}
4
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wingbot",
3
- "version": "3.75.9-alpha.6",
3
+ "version": "3.76.0",
4
4
  "description": "Enterprise Messaging Bot Conversation Engine",
5
5
  "main": "index.js",
6
6
  "type": "commonjs",
@@ -39,7 +39,7 @@
39
39
  "homepage": "https://github.com/wingbot.ai/wingbot#readme",
40
40
  "devDependencies": {
41
41
  "@types/mocha": "^10.0.10",
42
- "@wingbotai/wingbot-ai-orchestrator": "^2.13.3",
42
+ "@wingbotai/wingbot-ai-orchestrator": "^2.13.4",
43
43
  "cpy-cli": "^5.0.0",
44
44
  "eslint": "^8.56.0",
45
45
  "eslint-config-airbnb": "^19.0.4",
@@ -76,4 +76,4 @@
76
76
  "axios": "^1.6.4",
77
77
  "handlebars": "^4.0.0"
78
78
  }
79
- }
79
+ }
@@ -12,19 +12,46 @@ const path = require('path');
12
12
  const Router = require('./Router');
13
13
  const Plugins = require('./Plugins');
14
14
  const Ai = require('./Ai');
15
+ const LLMRouter = require('./LLMRouter');
15
16
  const expected = require('./resolvers/expected');
16
17
  const bounce = require('./resolvers/bounce');
17
18
  const { cachedTranslatedCompilator } = require('./resolvers/utils');
18
19
  const defaultResourceMap = require('./defaultResourceMap');
19
20
  const { shouldExecuteResolver } = require('./resolvers/resolverTags');
21
+ const getCondition = require('./utils/getCondition');
22
+ const compileWithState = require('./utils/compileWithState');
20
23
 
21
24
  const MESSAGE_RESOLVER_NAME = 'botbuild.message';
22
25
  const PLUGIN_RESOLVER_NAME = 'botbuild.customCode';
23
26
 
27
+ const designerApiUrl = process.env.DESIGNER_API_URL || 'https://api.wingbot.ai';
28
+
24
29
  /** @typedef {import('./resolvers/bounce').BounceAllow} BounceAllow */
25
30
  /** @typedef {import('./resolvers/bounce').BounceReturn} BounceReturn */
31
+ /** @typedef {import('./LLMRouter').RouteCondition} RouteCondition */
32
+ /** @typedef {import('./utils/getCondition').ConditionDefinition} ConditionDefinition */
33
+ /** @typedef {import('./utils/customCondition').EditableCondition} EditableCondition */
26
34
 
27
35
  /** @typedef {import('./Router').BaseConfiguration} BaseConfiguration */
36
+ /** @typedef {'global'|'local'} LLMRoutingScope */
37
+ /** @typedef {'fallback'|'keepAllow'} BlockLlmRoutingBounce */
38
+
39
+ /**
40
+ * @typedef {ConditionDefinition & {
41
+ * scope?: LLMRoutingScope,
42
+ * classificationDescription?: string,
43
+ * editableCondition?: EditableCondition
44
+ * }} RouteLlmRouting
45
+ */
46
+
47
+ /**
48
+ * @typedef {{
49
+ * prompt?: string,
50
+ * scope?: LLMRoutingScope,
51
+ * bounce?: BlockLlmRoutingBounce
52
+ * }} BlockLlmRouting
53
+ */
54
+
28
55
  /**
29
56
  * @typedef {object} BuildInfo
30
57
  * @prop {boolean} [expectedToAddResolver]
@@ -65,6 +92,7 @@ const PLUGIN_RESOLVER_NAME = 'botbuild.customCode';
65
92
  * @prop {BounceAllow} [bounceAllowedTo]
66
93
  * @prop {BounceReturn} [bounceReturn]
67
94
  * @prop {boolean} [isEntryPoint]
95
+ * @prop {RouteLlmRouting} [llmRouting]
68
96
  */
69
97
 
70
98
  /**
@@ -93,6 +121,7 @@ const DUMMY_ROUTE = { id: 0, path: null, resolvers: [] };
93
121
  * @prop {boolean} [disabled]
94
122
  * @prop {string} [blockName]
95
123
  * @prop {string} [blockType]
124
+ * @prop {BlockLlmRouting} [llmRouting]
96
125
  */
97
126
 
98
127
  /**
@@ -173,6 +202,7 @@ const DUMMY_ROUTE = { id: 0, path: null, resolvers: [] };
173
202
  * @prop {NestedLinksMapFactory} [nestedLinksMapFactory]
174
203
  * @prop {object} [BuildRouter]
175
204
  * @prop {Ai} [ai]
205
+ * @prop {LLMRouter} [llmRouter]
176
206
  * @prop {string|number} [resolverId] - only for text messages with random characters
177
207
  */
178
208
 
@@ -198,7 +228,7 @@ class BuildRouter extends Router {
198
228
  * @param {BotConfig|Block} block
199
229
  * @param {Plugins} plugins - custom code blocks resource
200
230
  * @param {BuildRouterContext<C>|Promise<BuildRouterContext<C>>} context - the building context
201
- * @param {fetch} [fetchFn] - override a request function
231
+ * @param {typeof fetch} [fetchFn] - override a request function
202
232
  * @example
203
233
  *
204
234
  * // usage of plugins
@@ -291,7 +321,7 @@ class BuildRouter extends Router {
291
321
  } else if (typeof block.botId === 'string') {
292
322
  this._snapshot = block.snapshot || 'production';
293
323
  this._botId = block.botId;
294
- this._loadBotUrl = `https://api.wingbot.ai/bots/${this._botId}/snapshots/${this._snapshot}/blocks`;
324
+ this._loadBotUrl = `${designerApiUrl}/bots/${this._botId}/snapshots/${this._snapshot}/blocks`;
295
325
  }
296
326
  }
297
327
 
@@ -614,8 +644,16 @@ class BuildRouter extends Router {
614
644
  blockName, blockType, isRoot, staticBlockId
615
645
  } = block;
616
646
 
647
+ const llmRouter = this._createBlockLlmRouter(block);
648
+
617
649
  this._resolvedContext = {
618
- ...this._resolvedContext, blockName, blockType, isRoot, staticBlockId, BuildRouter
650
+ ...this._resolvedContext,
651
+ blockName,
652
+ blockType,
653
+ isRoot,
654
+ staticBlockId,
655
+ BuildRouter,
656
+ llmRouter
619
657
  };
620
658
 
621
659
  const [linksMap, nestedBlocksByStaticId] = this._createLinksMap(block);
@@ -623,6 +661,10 @@ class BuildRouter extends Router {
623
661
  this._linksMap = linksMap;
624
662
  this._nestedLinksMap = null;
625
663
 
664
+ if (llmRouter) {
665
+ this.use(llmRouter);
666
+ }
667
+
626
668
  // @ts-ignore
627
669
  this._buildRoutes(block.routes, nestedBlocksByStaticId);
628
670
 
@@ -816,6 +858,108 @@ class BuildRouter extends Router {
816
858
  });
817
859
  }
818
860
 
861
+ /**
862
+ * @param {Block} block
863
+ * @returns {LLMRouter|null}
864
+ */
865
+ _createBlockLlmRouter (block) {
866
+ const { llmRouting } = block;
867
+
868
+ if (!llmRouting || !llmRouting.prompt || !llmRouting.prompt.trim()) {
869
+ return null;
870
+ }
871
+
872
+ const routeResolver = LLMRouter.defaultRoute(
873
+ async (resolvedData) => compileWithState(null, null, llmRouting.prompt, resolvedData)
874
+ );
875
+ const options = llmRouting.bounce === 'keepAllow'
876
+ ? { keepUserInInteractionsWithBounceAllowed: true }
877
+ : {};
878
+
879
+ return llmRouting.scope === 'local'
880
+ ? new LLMRouter(routeResolver, options)
881
+ : LLMRouter.global(routeResolver, options);
882
+ }
883
+
884
+ /**
885
+ * @param {TransformedRoute} route
886
+ * @returns {RouteCondition|null}
887
+ */
888
+ _createLlmRouteCondition (route) {
889
+ const { llmRouting } = route;
890
+
891
+ if (!llmRouting || !llmRouting.hasCondition) {
892
+ return null;
893
+ }
894
+
895
+ // TODO: what if the configuration is promise? Is this the way to properly get rid of it?
896
+ /** @type {C} */
897
+ const configuration = this._configuration instanceof Promise
898
+ ? null
899
+ : this._configuration;
900
+
901
+ const condition = getCondition(llmRouting, {
902
+ ai: Ai.ai,
903
+ ...this._resolvedContext,
904
+ configuration,
905
+ linksMap: this._linksMap
906
+ }, `LLM routing condition "${route.path || route.id}"`);
907
+
908
+ return (state, req = null) => {
909
+ const useReq = req
910
+ ? Object.assign(Object.create(req), { state })
911
+ : {
912
+ state,
913
+ configuration,
914
+ text: () => '',
915
+ actionData: () => ({})
916
+ };
917
+
918
+ if (typeof useReq.text !== 'function') {
919
+ useReq.text = () => '';
920
+ }
921
+ if (typeof useReq.actionData !== 'function') {
922
+ useReq.actionData = () => ({});
923
+ }
924
+
925
+ return condition(useReq, null);
926
+ };
927
+ }
928
+
929
+ /**
930
+ * @param {TransformedRoute} route
931
+ * @returns {import('./GlobalIntents').MatchingResolver|null}
932
+ */
933
+ _createLlmRouteResolver (route) {
934
+ const { llmRouting } = route;
935
+
936
+ if (!llmRouting
937
+ || !llmRouting.classificationDescription
938
+ || !llmRouting.classificationDescription.trim()) {
939
+ return null;
940
+ }
941
+
942
+ /** @type {import('./LLMRouter').RouteOptions} */
943
+ const options = {};
944
+ const condition = this._createLlmRouteCondition(route);
945
+
946
+ if (condition) {
947
+ options.condition = condition;
948
+ }
949
+
950
+ if (llmRouting.scope === 'local') {
951
+ const { llmRouter } = this._resolvedContext;
952
+
953
+ if (!llmRouter) {
954
+ throw new Error(`Local LLM routing requires block.llmRouting prompt on block "${this._resolvedContext.blockName || ''}"`);
955
+ }
956
+
957
+ return llmRouter.route(route.path, llmRouting.classificationDescription, options);
958
+ }
959
+
960
+ return LLMRouter.route(route.path, llmRouting.classificationDescription, options);
961
+ }
962
+
819
963
  /**
820
964
  *
821
965
  * @param {TransformedRoute} route
@@ -829,8 +973,9 @@ class BuildRouter extends Router {
829
973
 
830
974
  if (!route.isFallback) {
831
975
  let aiResolver = null;
976
+ const llmResolver = this._createLlmRouteResolver(route);
832
977
 
833
- if (route.aiTags && route.aiTags.length) {
978
+ if (!llmResolver && route.aiTags && route.aiTags.length) {
834
979
  let aiTitle = null;
835
980
 
836
981
  if (route.aiTitle) {
@@ -846,7 +991,9 @@ class BuildRouter extends Router {
846
991
  }
847
992
  }
848
993
 
849
- if (aiResolver && route.isResponder) {
994
+ if (llmResolver) {
995
+ resolvers.push(llmResolver);
996
+ } else if (aiResolver && route.isResponder) {
850
997
  resolvers.push(route.path, aiResolver);
851
998
  } else if (aiResolver) {
852
999
  resolvers.push(aiResolver);
@@ -8,6 +8,7 @@
8
8
  /** @typedef {import('./AiMatching').Entity} Entity */
9
9
  /** @typedef {import('./LLMDispatcher').ILLMRouter} ILLMRouter */
10
10
  /** @typedef {import('./LLMRouter').GILLMExtension} GILLMExtension */
11
+ /** @typedef {import('./LLMRouter').RouteCondition} RouteCondition */
11
12
 
12
13
  let uq = 1;
13
14
 
@@ -39,6 +40,7 @@ let uq = 1;
39
40
  * @prop {object} [meta]
40
41
  * @prop {string} [classification]
41
42
  * @prop {ILLMRouter} [router]
43
+ * @prop {RouteCondition} [condition]
42
44
  */
43
45
 
44
46
  /**
@@ -124,6 +126,7 @@ class GlobalIntents {
124
126
  meta = {},
125
127
  classification = null,
126
128
  router = null,
129
+ condition = null,
127
130
  local = false,
128
131
  keepUserInInteractionsWithBounceAllowed
129
132
  } = {},
@@ -140,6 +143,7 @@ class GlobalIntents {
140
143
  meta,
141
144
  classification,
142
145
  router,
146
+ condition,
143
147
  ...(typeof keepUserInInteractionsWithBounceAllowed === 'boolean'
144
148
  ? { keepUserInInteractionsWithBounceAllowed }
145
149
  : {}
@@ -165,7 +169,7 @@ class GlobalIntents {
165
169
  const {
166
170
  id, matcher = null, action: intentPath, local, title,
167
171
  entitiesSetState = {}, usedEntities, meta = {},
168
- classification = null, router = null,
172
+ classification = null, router = null, condition = null,
169
173
  keepUserInInteractionsWithBounceAllowed,
170
174
  localPath: prevLocalPath
171
175
  } = gi;
@@ -208,6 +212,7 @@ class GlobalIntents {
208
212
  title,
209
213
  classification,
210
214
  router,
215
+ condition,
211
216
  meta: { ...pathContext.globalIntentsMeta, ...meta },
212
217
  ...(typeof keepUserInInteractionsWithBounceAllowed === 'boolean'
213
218
  ? { keepUserInInteractionsWithBounceAllowed }
@@ -72,10 +72,11 @@ class LLMDispatcher {
72
72
  nlpMatchers: [],
73
73
  giByAction: new Map(),
74
74
  globals: {
75
- actionListString: null,
75
+ actionListString: '',
76
76
  actionList: [],
77
77
  router: null,
78
- byAction: new Map()
78
+ byAction: new Map(),
79
+ routes: []
79
80
  },
80
81
  locals: new Map()
81
82
  };
@@ -223,8 +224,8 @@ class LLMDispatcher {
223
224
 
224
225
  /**
225
226
  *
226
- * @param {*} state
227
- * @returns {LLMRoutingCache}
227
+ * @param {{lastAction?: string | null}} state
228
+ * @returns {LLMRoutingCache|null}
228
229
  */
229
230
  _localLLmRoutingForState (state) {
230
231
  const { lastAction } = state;
@@ -251,6 +252,26 @@ class LLMDispatcher {
251
252
  return null;
252
253
  }
253
254
 
255
+ const filteredRoutes = routing.routes
256
+ .filter(({ condition }) => !condition || condition(state, this._req));
257
+
258
+ if (filteredRoutes.length === 0) {
259
+ return {
260
+ ...routing,
261
+ actionList: [],
262
+ actionListString: '',
263
+ byAction: new Map(),
264
+ router
265
+ };
266
+ }
267
+
268
+ if (filteredRoutes.length !== routing.routes.length) {
269
+ return {
270
+ ...LLMRouter._prepareRoutingInput(filteredRoutes),
271
+ router
272
+ };
273
+ }
274
+
254
275
  return {
255
276
  ...routing,
256
277
  router
package/src/LLMRouter.js CHANGED
@@ -17,6 +17,13 @@ const LLMType = require('./LLMType');
17
17
  /** @typedef {import('./prompt').Prompt} Prompt */
18
18
  /** @typedef {import('./Router').RoutingInstruction} RoutingInstruction */
19
19
 
20
+ /**
21
+ * @callback RouteCondition
22
+ * @param {object} state
23
+ * @param {Request} [req]
24
+ * @returns {boolean}
25
+ */
26
+
20
27
  /**
21
28
  * @typedef {object} NLPActionInfo
22
29
  * @prop {MatcherResult} intent
@@ -69,6 +76,12 @@ const LLMType = require('./LLMType');
69
76
  * @prop {LLMAction[]} actionList
70
77
  * @prop {ILLMRouter|null} router
71
78
  * @prop {Map<string, GlobalIntentResolved>} byAction
79
+ * @prop {GlobalIntentResolved[]} routes
80
+ */
81
+
82
+ /**
83
+ * @typedef {object} RouteOptions
84
+ * @prop {RouteCondition} [condition]
72
85
  */
73
86
 
74
87
  /**
@@ -110,7 +123,7 @@ class LLMRouter {
110
123
  this._route = routeResolver;
111
124
  this._global = global;
112
125
 
113
- /** @typedef {GlobalIntentsMap} */
126
+ /** @type {GlobalIntentsMap} */
114
127
  this.globalIntents = new Map();
115
128
 
116
129
  if (global) {
@@ -226,11 +239,13 @@ class LLMRouter {
226
239
  *
227
240
  * @param {string} path
228
241
  * @param {string} classification
242
+ * @param {RouteOptions} [options]
229
243
  * @returns {MatchingResolver}
230
244
  */
231
- route (path, classification) {
245
+ route (path, classification, options = {}) {
232
246
  return GlobalIntents.resolver(path, {
233
247
  classification,
248
+ ...options,
234
249
  router: this._route ? this : null,
235
250
  local: !this._global
236
251
  });
@@ -240,11 +255,13 @@ class LLMRouter {
240
255
  *
241
256
  * @param {string} path
242
257
  * @param {string} classification
258
+ * @param {RouteOptions} [options]
243
259
  * @returns {MatchingResolver}
244
260
  */
245
- static route (path, classification) {
261
+ static route (path, classification, options = {}) {
246
262
  return GlobalIntents.resolver(path, {
247
- classification
263
+ classification,
264
+ ...options
248
265
  });
249
266
  }
250
267
 
@@ -265,13 +282,20 @@ class LLMRouter {
265
282
  const byAction = new Map();
266
283
  let router = null;
267
284
  let keepUserInInteractionsWithBounceAllowed;
285
+ const routableLlm = resolvedLlm.filter((gi) => gi.classification);
268
286
 
269
- const actionList = resolvedLlm.map((gi) => {
287
+ const actionList = routableLlm.map((gi) => {
270
288
  const { action, classification } = gi;
271
289
  byAction.set(LLMRouter._normByAction(gi.action), gi);
272
290
 
291
+ return { action, classification };
292
+ });
293
+
294
+ resolvedLlm.forEach((gi) => {
295
+
273
296
  if (typeof gi.keepUserInInteractionsWithBounceAllowed === 'boolean') {
274
- keepUserInInteractionsWithBounceAllowed = true;
297
+ // eslint-disable-next-line max-len
298
+ keepUserInInteractionsWithBounceAllowed = gi.keepUserInInteractionsWithBounceAllowed;
275
299
  }
276
300
 
277
301
  if (router && router !== gi.router) {
@@ -279,8 +303,6 @@ class LLMRouter {
279
303
  } else {
280
304
  router = gi.router;
281
305
  }
282
-
283
- return { action, classification };
284
306
  });
285
307
 
286
308
  const actionListString = actionList
@@ -294,7 +316,8 @@ class LLMRouter {
294
316
  actionListString,
295
317
  actionList,
296
318
  byAction,
297
- router
319
+ router,
320
+ routes: resolvedLlm
298
321
  };
299
322
  }
300
323
 
@@ -310,6 +333,7 @@ class LLMRouter {
310
333
  const globals = [];
311
334
  /** @type {ILLMRouter} */
312
335
  let router = null;
336
+ let keepUserInInteractionsWithBounceAllowed;
313
337
 
314
338
  for (const gi of globalIntents.values()) {
315
339
  if (!gi.classification
@@ -330,9 +354,24 @@ class LLMRouter {
330
354
  throw new Error(`Detected more than one global router on '${gi.localPath}'. Only single global router allowed.`);
331
355
  }
332
356
  router = gi.router;
357
+
358
+ if (typeof gi.keepUserInInteractionsWithBounceAllowed === 'boolean') {
359
+ // eslint-disable-next-line max-len
360
+ keepUserInInteractionsWithBounceAllowed = gi.keepUserInInteractionsWithBounceAllowed;
361
+ }
333
362
  }
334
363
  }
335
364
 
365
+ const preparedGlobals = globals.length
366
+ ? LLMRouter._prepareRoutingInput(globals)
367
+ : {
368
+ actionListString: '',
369
+ actionList: [],
370
+ byAction: new Map(),
371
+ router: null,
372
+ routes: []
373
+ };
374
+
336
375
  return {
337
376
  router,
338
377
  locals: new Map(
@@ -342,7 +381,12 @@ class LLMRouter {
342
381
  LLMRouter._prepareRoutingInput(locs)
343
382
  ])
344
383
  ),
345
- globals: LLMRouter._prepareRoutingInput(globals)
384
+ globals: {
385
+ ...preparedGlobals,
386
+ ...(typeof keepUserInInteractionsWithBounceAllowed === 'boolean'
387
+ ? { keepUserInInteractionsWithBounceAllowed }
388
+ : {})
389
+ }
346
390
  };
347
391
  }
348
392
 
package/src/Request.js CHANGED
@@ -113,6 +113,7 @@ function makeTimestamp () {
113
113
  * @prop {'file'|'audio'|'video'|'image'|'location'} type
114
114
  * @prop {object} payload
115
115
  * @prop {string} payload.url
116
+ * @prop {string} [payload.name]
116
117
  */
117
118
 
118
119
  /**
package/src/prompt.js CHANGED
@@ -11,7 +11,7 @@ const stateData = require('./utils/stateData');
11
11
 
12
12
  /**
13
13
  * @callback Renderer
14
- * @param {object|Request} req
14
+ * @param {Request} req
15
15
  * @param {Responder} [res]
16
16
  * @returns {Promise<string>}
17
17
  */
@@ -21,6 +21,7 @@ const stateData = require('./stateData');
21
21
  * @param {Request} req
22
22
  * @param {Responder} res
23
23
  * @param {string} template
24
+ * @param {object} forcedData
24
25
  * @returns {string}
25
26
  * @example
26
27
  *
@@ -34,7 +35,7 @@ const stateData = require('./stateData');
34
35
  * };
35
36
  * }
36
37
  */
37
- function compileWithState (req, res, template) {
38
+ function compileWithState (req, res, template, forcedData = null) {
38
39
  if (!template) {
39
40
  return '';
40
41
  }
@@ -44,7 +45,7 @@ function compileWithState (req, res, template) {
44
45
  if (!template.includes('{{')) {
45
46
  return template;
46
47
  }
47
- const data = stateData(req, res);
48
+ const data = forcedData || stateData(req, res);
48
49
  return handlebars.compile(template)(data);
49
50
  }
50
51
 
package/test.json ADDED
@@ -0,0 +1,330 @@
1
+ {
2
+ "nlpModel": null,
3
+ "aiToken": null,
4
+ "locked": false,
5
+ "botId": "d3d638ef-880c-47af-be32-0677fd84daf5",
6
+ "name": "development",
7
+ "url": null,
8
+ "type": null,
9
+ "blocks": [
10
+ {
11
+ "isRoot": true,
12
+ "blockName": "Root",
13
+ "staticBlockId": "AJzahxmkr2V41diCjMdYsZ",
14
+ "routes": [
15
+ {
16
+ "id": "AJzai2BXN2V41diCjMdYsZ",
17
+ "path": "start",
18
+ "name": "Start",
19
+ "skill": null,
20
+ "isEntryPoint": true,
21
+ "isFallback": false,
22
+ "replies": [],
23
+ "resolvers": [
24
+ {
25
+ "type": "botbuild.message",
26
+ "params": {
27
+ "text": [
28
+ {
29
+ "l": "cs",
30
+ "t": [
31
+ "We just started talkin"
32
+ ]
33
+ },
34
+ {
35
+ "l": "en",
36
+ "t": ""
37
+ }
38
+ ],
39
+ "replies": [],
40
+ "type": "message",
41
+ "llmContextType": "default"
42
+ }
43
+ }
44
+ ],
45
+ "aiTags": [],
46
+ "aiTitle": null,
47
+ "aiGlobal": true
48
+ },
49
+ {
50
+ "path": "cars",
51
+ "id": "AHSwFpGqn2VLxPDKVL4XKZ",
52
+ "resolvers": [
53
+ {
54
+ "id": "AHSwFpGqn2VLxPDKVL4XKZ",
55
+ "type": "botbuild.include",
56
+ "params": {
57
+ "staticBlockId": "AHSwFpGqn2VLxPDKVL4XKZ",
58
+ "items": {}
59
+ }
60
+ }
61
+ ]
62
+ },
63
+ {
64
+ "path": "weather",
65
+ "id": "IMb1IDCxl2VMWusudBybZW",
66
+ "resolvers": [
67
+ {
68
+ "id": "IMb1IDCxl2VMWusudBybZW",
69
+ "type": "botbuild.include",
70
+ "params": {
71
+ "staticBlockId": "IMb1IDCxl2VMWusudBybZW",
72
+ "items": {}
73
+ }
74
+ }
75
+ ]
76
+ },
77
+ {
78
+ "id": "AJzaiAz6P2V41diCjMdYsZ",
79
+ "path": "fallback",
80
+ "name": "Fallback",
81
+ "skill": null,
82
+ "isEntryPoint": false,
83
+ "isFallback": true,
84
+ "replies": [],
85
+ "resolvers": [
86
+ {
87
+ "type": "botbuild.message",
88
+ "params": {
89
+ "text": [
90
+ {
91
+ "l": "cs",
92
+ "t": [
93
+ "Sorry, but i don't understand"
94
+ ]
95
+ },
96
+ {
97
+ "l": "en",
98
+ "t": [
99
+ "aaaaa"
100
+ ]
101
+ }
102
+ ],
103
+ "hasCondition": false,
104
+ "replies": [
105
+ {
106
+ "targetRouteId": "AJzai2BXN2V41diCjMdYsZ",
107
+ "title": [
108
+ {
109
+ "l": "cs",
110
+ "t": "Back to Start"
111
+ },
112
+ {
113
+ "l": "en",
114
+ "t": "sefsef"
115
+ }
116
+ ]
117
+ }
118
+ ]
119
+ }
120
+ }
121
+ ]
122
+ }
123
+ ],
124
+ "llmRouting": {
125
+ "prompt": "Use user's last message to decide, if they want's to change context of conversation.\nReturn one of following routing actions:\n\n- `-not-changed-`: context not changed or can't decide\n{{{actionListString}}}",
126
+ "scope": "global",
127
+ "bounce": "fallback"
128
+ }
129
+ },
130
+ {
131
+ "blockName": "cars",
132
+ "staticBlockId": "AHSwFpGqn2VLxPDKVL4XKZ",
133
+ "routes": [
134
+ {
135
+ "id": "96GRoJH3h2VKYdPJ7k12sDM",
136
+ "path": "cars",
137
+ "name": "Cars",
138
+ "skill": "cars",
139
+ "isEntryPoint": true,
140
+ "isFallback": false,
141
+ "replies": [],
142
+ "resolvers": [
143
+ {
144
+ "type": "botbuild.message",
145
+ "params": {
146
+ "text": [
147
+ {
148
+ "l": "cs",
149
+ "t": [
150
+ "We are talking about cars. What would you like to know about cars?"
151
+ ]
152
+ },
153
+ {
154
+ "l": "en",
155
+ "t": ""
156
+ }
157
+ ],
158
+ "replies": [],
159
+ "type": "message",
160
+ "llmContextType": "default"
161
+ }
162
+ }
163
+ ],
164
+ "aiTags": [],
165
+ "aiTitle": null,
166
+ "aiGlobal": true,
167
+ "llmRouting": {
168
+ "scope": "global",
169
+ "classificationDescription": "user wants to talk about cars, or anything car related"
170
+ }
171
+ },
172
+ {
173
+ "id": "7QOQxgYFt2VM9DTyPZpSKs",
174
+ "path": "carburators",
175
+ "name": "carburators",
176
+ "skill": "cars",
177
+ "isEntryPoint": true,
178
+ "isFallback": false,
179
+ "replies": [],
180
+ "resolvers": [
181
+ {
182
+ "type": "botbuild.message",
183
+ "params": {
184
+ "text": [
185
+ {
186
+ "l": "cs",
187
+ "t": [
188
+ "Talk about carburators."
189
+ ]
190
+ },
191
+ {
192
+ "l": "en",
193
+ "t": ""
194
+ }
195
+ ],
196
+ "replies": [],
197
+ "type": "prompt",
198
+ "llmContextType": "default"
199
+ }
200
+ }
201
+ ],
202
+ "aiTags": [],
203
+ "aiTitle": null,
204
+ "aiGlobal": true,
205
+ "llmRouting": {
206
+ "scope": "local",
207
+ "classificationDescription": "when user wants to speak about carburators"
208
+ }
209
+ },
210
+ {
211
+ "id": "9dIsbyWUD2VM9DTyPZpSKs",
212
+ "path": "fallback",
213
+ "name": "Fallback",
214
+ "skill": "cars",
215
+ "isEntryPoint": false,
216
+ "isFallback": true,
217
+ "replies": [],
218
+ "resolvers": [
219
+ {
220
+ "type": "botbuild.message",
221
+ "params": {
222
+ "text": [
223
+ {
224
+ "l": "cs",
225
+ "t": [
226
+ "Answer the users question, or just talk to him based on what he/she said."
227
+ ]
228
+ },
229
+ {
230
+ "l": "en",
231
+ "t": ""
232
+ }
233
+ ],
234
+ "replies": [],
235
+ "type": "prompt",
236
+ "llmContextType": "default"
237
+ }
238
+ },
239
+ {
240
+ "type": "botbuild.message",
241
+ "params": {
242
+ "text": [
243
+ {
244
+ "l": "cs",
245
+ "t": [
246
+ "This was fallbacked"
247
+ ]
248
+ },
249
+ {
250
+ "l": "en",
251
+ "t": ""
252
+ }
253
+ ],
254
+ "replies": [],
255
+ "type": "message",
256
+ "llmContextType": "default"
257
+ }
258
+ }
259
+ ],
260
+ "aiTags": [],
261
+ "aiTitle": [
262
+ {
263
+ "l": "cs",
264
+ "t": ""
265
+ },
266
+ {
267
+ "l": "en",
268
+ "t": ""
269
+ }
270
+ ],
271
+ "aiGlobal": true
272
+ }
273
+ ]
274
+ },
275
+ {
276
+ "blockName": "weather",
277
+ "staticBlockId": "IMb1IDCxl2VMWusudBybZW",
278
+ "routes": [
279
+ {
280
+ "id": "IRs920neD2VMWusudBybZW",
281
+ "path": "weather",
282
+ "name": "weather",
283
+ "skill": "weather",
284
+ "isEntryPoint": true,
285
+ "isFallback": false,
286
+ "replies": [],
287
+ "resolvers": [
288
+ {
289
+ "type": "botbuild.message",
290
+ "params": {
291
+ "text": [
292
+ {
293
+ "l": "cs",
294
+ "t": [
295
+ "We are talking about weather"
296
+ ]
297
+ },
298
+ {
299
+ "l": "en",
300
+ "t": ""
301
+ }
302
+ ],
303
+ "replies": [],
304
+ "type": "message",
305
+ "llmContextType": "default"
306
+ }
307
+ },
308
+ {
309
+ "type": "botbuild.postback",
310
+ "params": {
311
+ "routeId": "AJzai2BXN2V41diCjMdYsZ"
312
+ }
313
+ }
314
+ ],
315
+ "aiTags": [],
316
+ "aiTitle": null,
317
+ "aiGlobal": true,
318
+ "llmRouting": {
319
+ "scope": "global",
320
+ "classificationDescription": "user wants to talk about weather"
321
+ }
322
+ }
323
+ ]
324
+ }
325
+ ],
326
+ "deployedConfiguration": null,
327
+ "lastmod": 1779356722025,
328
+ "id": "development",
329
+ "handlerUrl": null
330
+ }
@@ -1,11 +0,0 @@
1
- {
2
- "permissions": {
3
- "allow": [
4
- "Bash(npx mocha:*)",
5
- "Bash(npx tsc *)",
6
- "Bash(npm test *)",
7
- "Bash(node -e \"const p = require\\('./bot/plugins/BTMLLM'\\); console.log\\('factory type:', typeof p\\); console.log\\('factory name:', p.name\\);\")",
8
- "Bash(grep -n \"prompt\\\\`\\\\|tagged\\\\|render\\\\|compile\\\\|hbs\" /Users/ondrejveres/Wingbot/wingbot-llm/src/prompt.js)"
9
- ]
10
- }
11
- }