wingbot 3.75.9-alpha.6 → 3.76.1-alpha.1
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 +2 -2
- package/src/BuildRouter.js +152 -5
- package/src/ChatGpt.js +10 -2
- package/src/GlobalIntents.js +6 -1
- package/src/LLMDispatcher.js +25 -4
- package/src/LLMRouter.js +54 -10
- package/src/Request.js +1 -0
- package/src/prompt.js +1 -1
- package/src/utils/compileWithState.js +3 -2
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "wingbot",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.76.1-alpha.1",
|
|
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.
|
|
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",
|
package/src/BuildRouter.js
CHANGED
|
@@ -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 =
|
|
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,
|
|
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 (
|
|
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);
|
package/src/ChatGpt.js
CHANGED
|
@@ -31,6 +31,7 @@ const LLM = require('./LLM');
|
|
|
31
31
|
* @prop {string} [apiVersion]
|
|
32
32
|
* @prop {string} [apiKey] // for microsoft services
|
|
33
33
|
* @prop {string} [authorization] // for chat gpt api
|
|
34
|
+
* @prop {number} [timeout=15000] - request timeout in ms; set to 0 to disable
|
|
34
35
|
*/
|
|
35
36
|
|
|
36
37
|
/** @typedef {'gpt-3.5-turbo'|'gpt-4'|'gpt-4-32k'|'gpt-3.5-turbo-16k'|string} ChatGPTModel */
|
|
@@ -189,11 +190,13 @@ class ChatGpt {
|
|
|
189
190
|
openAiEndpoint = 'https://api.openai.com/v1',
|
|
190
191
|
apiKey,
|
|
191
192
|
authorization,
|
|
193
|
+
timeout = 15000,
|
|
192
194
|
...rest
|
|
193
195
|
} = options;
|
|
194
196
|
|
|
195
197
|
this._apiKey = apiKey;
|
|
196
198
|
this._authorization = authorization;
|
|
199
|
+
this._timeout = timeout;
|
|
197
200
|
|
|
198
201
|
this._fetch = fetch;
|
|
199
202
|
|
|
@@ -446,14 +449,19 @@ class ChatGpt {
|
|
|
446
449
|
? { 'api-key': this._apiKey }
|
|
447
450
|
: { Authorization: `Bearer ${this._authorization}` })
|
|
448
451
|
},
|
|
449
|
-
body: JSON.stringify(body)
|
|
452
|
+
body: JSON.stringify(body),
|
|
453
|
+
...(this._timeout > 0 ? { timeout: this._timeout } : {})
|
|
450
454
|
});
|
|
451
455
|
|
|
452
456
|
({ status, statusText } = response);
|
|
453
457
|
|
|
454
458
|
responseText = await response.text();
|
|
455
459
|
/** @type {ChatGPTResponse} */
|
|
456
|
-
|
|
460
|
+
try {
|
|
461
|
+
responseData = JSON.parse(responseText);
|
|
462
|
+
} catch {
|
|
463
|
+
throw new Error(`Chat GPT ${status} (non-JSON): ${responseText.slice(0, 200)}`);
|
|
464
|
+
}
|
|
457
465
|
|
|
458
466
|
if (status !== 200
|
|
459
467
|
|| !Array.isArray(responseData.choices)) {
|
package/src/GlobalIntents.js
CHANGED
|
@@ -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 }
|
package/src/LLMDispatcher.js
CHANGED
|
@@ -72,10 +72,11 @@ class LLMDispatcher {
|
|
|
72
72
|
nlpMatchers: [],
|
|
73
73
|
giByAction: new Map(),
|
|
74
74
|
globals: {
|
|
75
|
-
actionListString:
|
|
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 {
|
|
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
|
-
/** @
|
|
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 =
|
|
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
|
-
|
|
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:
|
|
384
|
+
globals: {
|
|
385
|
+
...preparedGlobals,
|
|
386
|
+
...(typeof keepUserInInteractionsWithBounceAllowed === 'boolean'
|
|
387
|
+
? { keepUserInInteractionsWithBounceAllowed }
|
|
388
|
+
: {})
|
|
389
|
+
}
|
|
346
390
|
};
|
|
347
391
|
}
|
|
348
392
|
|
package/src/Request.js
CHANGED
package/src/prompt.js
CHANGED
|
@@ -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
|
|