@botonic/plugin-flow-builder 0.34.0 → 0.34.2-alpha.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.
- package/lib/cjs/action/first-interaction.d.ts +1 -1
- package/lib/cjs/action/first-interaction.js +26 -28
- package/lib/cjs/action/first-interaction.js.map +1 -1
- package/lib/cjs/action/index.d.ts +1 -4
- package/lib/cjs/action/knowledge-bases.js +19 -17
- package/lib/cjs/action/knowledge-bases.js.map +1 -1
- package/lib/cjs/index.d.ts +2 -2
- package/lib/cjs/index.js +7 -4
- package/lib/cjs/index.js.map +1 -1
- package/lib/cjs/tracking.js.map +1 -1
- package/lib/cjs/types.d.ts +6 -0
- package/lib/cjs/types.js.map +1 -1
- package/lib/cjs/user-input/index.js +22 -15
- package/lib/cjs/user-input/index.js.map +1 -1
- package/lib/cjs/user-input/intent.js +7 -0
- package/lib/cjs/user-input/intent.js.map +1 -1
- package/lib/cjs/user-input/keyword.js +2 -0
- package/lib/cjs/user-input/keyword.js.map +1 -1
- package/lib/cjs/user-input/smart-intent.js +2 -0
- package/lib/cjs/user-input/smart-intent.js.map +1 -1
- package/lib/cjs/utils.d.ts +3 -0
- package/lib/cjs/utils.js +19 -1
- package/lib/cjs/utils.js.map +1 -1
- package/lib/esm/action/first-interaction.d.ts +1 -1
- package/lib/esm/action/first-interaction.js +26 -28
- package/lib/esm/action/first-interaction.js.map +1 -1
- package/lib/esm/action/index.d.ts +1 -4
- package/lib/esm/action/knowledge-bases.js +20 -18
- package/lib/esm/action/knowledge-bases.js.map +1 -1
- package/lib/esm/index.d.ts +2 -2
- package/lib/esm/index.js +7 -4
- package/lib/esm/index.js.map +1 -1
- package/lib/esm/tracking.js.map +1 -1
- package/lib/esm/types.d.ts +6 -0
- package/lib/esm/types.js.map +1 -1
- package/lib/esm/user-input/index.js +23 -16
- package/lib/esm/user-input/index.js.map +1 -1
- package/lib/esm/user-input/intent.js +7 -0
- package/lib/esm/user-input/intent.js.map +1 -1
- package/lib/esm/user-input/keyword.js +2 -0
- package/lib/esm/user-input/keyword.js.map +1 -1
- package/lib/esm/user-input/smart-intent.js +2 -0
- package/lib/esm/user-input/smart-intent.js.map +1 -1
- package/lib/esm/utils.d.ts +3 -0
- package/lib/esm/utils.js +16 -1
- package/lib/esm/utils.js.map +1 -1
- package/package.json +1 -1
- package/src/action/first-interaction.ts +31 -42
- package/src/action/knowledge-bases.ts +38 -36
- package/src/content-fields/hubtype-fields/intent.ts +1 -0
- package/src/index.ts +9 -4
- package/src/tracking.ts +0 -1
- package/src/types.ts +7 -0
- package/src/user-input/index.ts +33 -21
- package/src/user-input/intent.ts +8 -0
- package/src/user-input/keyword.ts +3 -0
- package/src/user-input/smart-intent.ts +5 -0
- package/src/utils.ts +27 -1
|
@@ -8,7 +8,7 @@ import {
|
|
|
8
8
|
import { HtNodeWithContent } from '../content-fields/hubtype-fields/nodes'
|
|
9
9
|
import { EventAction, KnowledgebaseFailReason, trackEvent } from '../tracking'
|
|
10
10
|
import { KnowledgeBaseFunction, KnowledgeBaseResponse } from '../types'
|
|
11
|
-
import { inputHasTextData } from '../utils'
|
|
11
|
+
import { inputHasTextData, isKnowledgeBasesAllowed } from '../utils'
|
|
12
12
|
import { FlowBuilderContext } from './index'
|
|
13
13
|
|
|
14
14
|
export async function getContentsByKnowledgeBase({
|
|
@@ -17,46 +17,48 @@ export async function getContentsByKnowledgeBase({
|
|
|
17
17
|
request,
|
|
18
18
|
resolvedLocale,
|
|
19
19
|
}: FlowBuilderContext): Promise<FlowContent[]> {
|
|
20
|
-
|
|
20
|
+
if (isKnowledgeBasesAllowed(request)) {
|
|
21
|
+
const startNodeKnowledgeBaseFlow = cmsApi.getStartNodeKnowledgeBaseFlow()
|
|
21
22
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
const contents = await flowBuilderPlugin.getContentsByNode(
|
|
27
|
-
startNodeKnowledgeBaseFlow,
|
|
28
|
-
resolvedLocale
|
|
29
|
-
)
|
|
23
|
+
if (!startNodeKnowledgeBaseFlow) {
|
|
24
|
+
return []
|
|
25
|
+
}
|
|
30
26
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
27
|
+
const contents = await flowBuilderPlugin.getContentsByNode(
|
|
28
|
+
startNodeKnowledgeBaseFlow,
|
|
29
|
+
resolvedLocale
|
|
30
|
+
)
|
|
34
31
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
32
|
+
const knowledgeBaseContent = contents.find(
|
|
33
|
+
content => content instanceof FlowKnowledgeBase
|
|
34
|
+
) as FlowKnowledgeBase
|
|
38
35
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
).flow_id
|
|
36
|
+
if (!knowledgeBaseContent) {
|
|
37
|
+
return contents
|
|
38
|
+
}
|
|
43
39
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
40
|
+
const sourceIds = knowledgeBaseContent.sourcesData.map(source => source.id)
|
|
41
|
+
const flowId = cmsApi.getNodeById<HtNodeWithContent>(
|
|
42
|
+
knowledgeBaseContent.id
|
|
43
|
+
).flow_id
|
|
44
|
+
|
|
45
|
+
if (
|
|
46
|
+
flowBuilderPlugin.getKnowledgeBaseResponse &&
|
|
47
|
+
inputHasTextData(request.input) &&
|
|
48
|
+
sourceIds.length > 0
|
|
49
|
+
) {
|
|
50
|
+
const contentsWithKnowledgeResponse =
|
|
51
|
+
await getContentsWithKnowledgeResponse(
|
|
52
|
+
flowBuilderPlugin.getKnowledgeBaseResponse,
|
|
53
|
+
request,
|
|
54
|
+
contents,
|
|
55
|
+
knowledgeBaseContent,
|
|
56
|
+
flowId
|
|
57
|
+
)
|
|
58
|
+
|
|
59
|
+
if (contentsWithKnowledgeResponse) {
|
|
60
|
+
return contentsWithKnowledgeResponse
|
|
61
|
+
}
|
|
60
62
|
}
|
|
61
63
|
}
|
|
62
64
|
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { HtBaseNode, HtInputLocale, HtTextLocale } from './common'
|
|
2
2
|
import { HtNodeWithContentType } from './node-types'
|
|
3
3
|
|
|
4
|
+
// TODO: Remove this because frontend no allow create intents babel
|
|
4
5
|
export interface HtIntentNode extends HtBaseNode {
|
|
5
6
|
type: HtNodeWithContentType.INTENT
|
|
6
7
|
content: {
|
package/src/index.ts
CHANGED
|
@@ -34,6 +34,7 @@ import { DEFAULT_FUNCTIONS } from './functions'
|
|
|
34
34
|
import {
|
|
35
35
|
BotonicPluginFlowBuilderOptions,
|
|
36
36
|
FlowBuilderJSONVersion,
|
|
37
|
+
InShadowingConfig,
|
|
37
38
|
KnowledgeBaseFunction,
|
|
38
39
|
PayloadParamsBase,
|
|
39
40
|
TrackEventFunction,
|
|
@@ -54,12 +55,13 @@ export default class BotonicPluginFlowBuilder implements Plugin {
|
|
|
54
55
|
public trackEvent?: TrackEventFunction
|
|
55
56
|
public getKnowledgeBaseResponse?: KnowledgeBaseFunction
|
|
56
57
|
public smartIntentsConfig: SmartIntentsInferenceConfig
|
|
58
|
+
public inShadowing: InShadowingConfig
|
|
57
59
|
|
|
58
60
|
// TODO: Rethink how we construct FlowBuilderApi to be simpler
|
|
59
61
|
public jsonVersion: FlowBuilderJSONVersion
|
|
60
62
|
public apiUrl: string
|
|
61
63
|
|
|
62
|
-
constructor(
|
|
64
|
+
constructor(options: BotonicPluginFlowBuilderOptions) {
|
|
63
65
|
this.apiUrl = options.apiUrl || FLOW_BUILDER_API_URL_PROD
|
|
64
66
|
this.jsonVersion = options.jsonVersion || FlowBuilderJSONVersion.LATEST
|
|
65
67
|
this.flow = options.flow
|
|
@@ -73,6 +75,11 @@ export default class BotonicPluginFlowBuilder implements Plugin {
|
|
|
73
75
|
}
|
|
74
76
|
const customFunctions = options.customFunctions || {}
|
|
75
77
|
this.functions = { ...DEFAULT_FUNCTIONS, ...customFunctions }
|
|
78
|
+
this.inShadowing = {
|
|
79
|
+
allowKeywords: options.inShadowing?.allowKeywords || false,
|
|
80
|
+
allowSmartIntents: options.inShadowing?.allowSmartIntents || false,
|
|
81
|
+
allowKnowledgeBases: options.inShadowing?.allowKnowledgeBases || false,
|
|
82
|
+
}
|
|
76
83
|
}
|
|
77
84
|
|
|
78
85
|
resolveFlowUrl(request: PluginPreRequest): string {
|
|
@@ -93,9 +100,7 @@ export default class BotonicPluginFlowBuilder implements Plugin {
|
|
|
93
100
|
})
|
|
94
101
|
|
|
95
102
|
const checkUserTextInput =
|
|
96
|
-
inputHasTextData(request.input) &&
|
|
97
|
-
!request.input.payload &&
|
|
98
|
-
!request.session.is_first_interaction
|
|
103
|
+
inputHasTextData(request.input) && !request.input.payload
|
|
99
104
|
|
|
100
105
|
if (checkUserTextInput) {
|
|
101
106
|
const locale = this.getLocale(request.session)
|
package/src/tracking.ts
CHANGED
package/src/types.ts
CHANGED
|
@@ -3,6 +3,12 @@ import { ActionRequest } from '@botonic/react'
|
|
|
3
3
|
|
|
4
4
|
import { HtFlowBuilderData } from './content-fields/hubtype-fields'
|
|
5
5
|
|
|
6
|
+
export interface InShadowingConfig {
|
|
7
|
+
allowKeywords: boolean
|
|
8
|
+
allowSmartIntents: boolean
|
|
9
|
+
allowKnowledgeBases: boolean
|
|
10
|
+
}
|
|
11
|
+
|
|
6
12
|
export interface BotonicPluginFlowBuilderOptions {
|
|
7
13
|
apiUrl?: string
|
|
8
14
|
jsonVersion?: FlowBuilderJSONVersion
|
|
@@ -13,6 +19,7 @@ export interface BotonicPluginFlowBuilderOptions {
|
|
|
13
19
|
trackEvent?: TrackEventFunction
|
|
14
20
|
getKnowledgeBaseResponse?: KnowledgeBaseFunction
|
|
15
21
|
smartIntentsConfig?: { numSmartIntentsToUse: number }
|
|
22
|
+
inShadowing?: Partial<InShadowingConfig>
|
|
16
23
|
}
|
|
17
24
|
|
|
18
25
|
export type TrackEventFunction = (
|
package/src/user-input/index.ts
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { INPUT } from '@botonic/core'
|
|
2
1
|
import { ActionRequest } from '@botonic/react'
|
|
3
2
|
|
|
4
3
|
import { FlowBuilderApi } from '../api'
|
|
@@ -7,7 +6,11 @@ import {
|
|
|
7
6
|
HtKeywordNode,
|
|
8
7
|
HtSmartIntentNode,
|
|
9
8
|
} from '../content-fields/hubtype-fields'
|
|
10
|
-
import {
|
|
9
|
+
import {
|
|
10
|
+
inputHasTextData,
|
|
11
|
+
isKeywordsAllowed,
|
|
12
|
+
isSmartIntentsAllowed,
|
|
13
|
+
} from '../utils'
|
|
11
14
|
import { getIntentNodeByInput } from './intent'
|
|
12
15
|
import { KeywordMatcher } from './keyword'
|
|
13
16
|
import { SmartIntentsApi, SmartIntentsInferenceConfig } from './smart-intent'
|
|
@@ -19,29 +22,38 @@ export async function getNodeByUserInput(
|
|
|
19
22
|
smartIntentsConfig: SmartIntentsInferenceConfig
|
|
20
23
|
): Promise<HtSmartIntentNode | HtIntentNode | HtKeywordNode | undefined> {
|
|
21
24
|
if (inputHasTextData(request.input)) {
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
25
|
+
if (isKeywordsAllowed(request)) {
|
|
26
|
+
const keywordMatcher = new KeywordMatcher({
|
|
27
|
+
cmsApi,
|
|
28
|
+
locale,
|
|
29
|
+
request,
|
|
30
|
+
})
|
|
31
|
+
const keywordNode = await keywordMatcher.getNodeByInput(
|
|
32
|
+
request.input.data!
|
|
33
|
+
)
|
|
34
|
+
if (keywordNode) {
|
|
35
|
+
return keywordNode
|
|
36
|
+
}
|
|
30
37
|
}
|
|
31
38
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
39
|
+
if (isSmartIntentsAllowed(request)) {
|
|
40
|
+
const smartIntentsApi = new SmartIntentsApi(
|
|
41
|
+
cmsApi,
|
|
42
|
+
request,
|
|
43
|
+
smartIntentsConfig
|
|
44
|
+
)
|
|
45
|
+
const smartIntentNode = await smartIntentsApi.getNodeByInput()
|
|
46
|
+
if (smartIntentNode) {
|
|
47
|
+
return smartIntentNode
|
|
48
|
+
}
|
|
40
49
|
}
|
|
41
50
|
|
|
42
|
-
|
|
43
|
-
if (
|
|
44
|
-
|
|
51
|
+
// TODO: Remove this because frontend no allow create intents babel
|
|
52
|
+
if (isSmartIntentsAllowed(request)) {
|
|
53
|
+
const intentNode = await getIntentNodeByInput(cmsApi, locale, request)
|
|
54
|
+
if (intentNode) {
|
|
55
|
+
return intentNode
|
|
56
|
+
}
|
|
45
57
|
}
|
|
46
58
|
}
|
|
47
59
|
|
package/src/user-input/intent.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { NluType } from '@botonic/core'
|
|
1
2
|
import { ActionRequest } from '@botonic/react'
|
|
2
3
|
|
|
3
4
|
import { FlowBuilderApi } from '../api'
|
|
@@ -15,6 +16,13 @@ export async function getIntentNodeByInput(
|
|
|
15
16
|
await trackIntentEvent(request, intentNode)
|
|
16
17
|
|
|
17
18
|
if (isIntentValid(intentNode, request, cmsApi)) {
|
|
19
|
+
const targetPayload = cmsApi.getPayload(intentNode.target)
|
|
20
|
+
|
|
21
|
+
request.input.nluResolution = {
|
|
22
|
+
type: NluType.Keyword,
|
|
23
|
+
matchedValue: intentNode.content.title,
|
|
24
|
+
payload: targetPayload,
|
|
25
|
+
}
|
|
18
26
|
return intentNode
|
|
19
27
|
}
|
|
20
28
|
}
|
|
@@ -36,9 +36,12 @@ export class KeywordMatcher {
|
|
|
36
36
|
if (!keywordNode || !this.matchedKeyword) {
|
|
37
37
|
return undefined
|
|
38
38
|
}
|
|
39
|
+
const targetPayload = this.cmsApi.getPayload(keywordNode.target)
|
|
40
|
+
|
|
39
41
|
this.request.input.nluResolution = {
|
|
40
42
|
type: NluType.Keyword,
|
|
41
43
|
matchedValue: this.matchedKeyword,
|
|
44
|
+
payload: targetPayload,
|
|
42
45
|
}
|
|
43
46
|
await this.trackKeywordEvent()
|
|
44
47
|
return keywordNode
|
|
@@ -46,11 +46,15 @@ export class SmartIntentsApi {
|
|
|
46
46
|
smartIntentNode =>
|
|
47
47
|
smartIntentNode.content.title === response.data.smart_intent_title
|
|
48
48
|
)
|
|
49
|
+
|
|
49
50
|
if (smartIntentNode) {
|
|
51
|
+
const targetPayload = this.cmsApi.getPayload(smartIntentNode.target)
|
|
50
52
|
this.currentRequest.input.nluResolution = {
|
|
51
53
|
type: NluType.SmartIntent,
|
|
52
54
|
matchedValue: smartIntentNode.content.title,
|
|
55
|
+
payload: targetPayload,
|
|
53
56
|
}
|
|
57
|
+
|
|
54
58
|
await trackEvent(this.currentRequest, EventAction.IntentSmart, {
|
|
55
59
|
nluIntentSmartTitle: response.data.smart_intent_title,
|
|
56
60
|
nluIntentSmartNumUsed: response.data.smart_intents_used.length,
|
|
@@ -60,6 +64,7 @@ export class SmartIntentsApi {
|
|
|
60
64
|
flowId: smartIntentNode.flow_id,
|
|
61
65
|
flowNodeId: smartIntentNode.id,
|
|
62
66
|
})
|
|
67
|
+
|
|
63
68
|
return smartIntentNode
|
|
64
69
|
}
|
|
65
70
|
} catch (e) {
|
package/src/utils.ts
CHANGED
|
@@ -1,7 +1,12 @@
|
|
|
1
1
|
import { INPUT, Input, Session } from '@botonic/core'
|
|
2
2
|
import { ActionRequest } from '@botonic/react'
|
|
3
3
|
|
|
4
|
-
import {
|
|
4
|
+
import { getFlowBuilderPlugin } from './helpers'
|
|
5
|
+
import {
|
|
6
|
+
BotonicPluginFlowBuilderOptions,
|
|
7
|
+
InShadowingConfig,
|
|
8
|
+
ProcessEnvNodeEnvs,
|
|
9
|
+
} from './types'
|
|
5
10
|
|
|
6
11
|
function getAccessTokenFromSession(session: Session): string {
|
|
7
12
|
if (!session._access_token) {
|
|
@@ -51,3 +56,24 @@ function resolveObjectKey(object: any, key: string): any {
|
|
|
51
56
|
export function inputHasTextData(input: Input): boolean {
|
|
52
57
|
return input.data !== undefined && input.type === INPUT.TEXT
|
|
53
58
|
}
|
|
59
|
+
|
|
60
|
+
function isNluAllowed(
|
|
61
|
+
request: ActionRequest,
|
|
62
|
+
nluFlag: keyof InShadowingConfig
|
|
63
|
+
): boolean {
|
|
64
|
+
const shadowing = Boolean(request.session._shadowing)
|
|
65
|
+
const flowBuilderPlugin = getFlowBuilderPlugin(request.plugins)
|
|
66
|
+
return !shadowing || (shadowing && flowBuilderPlugin.inShadowing[nluFlag])
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
export function isKeywordsAllowed(request: ActionRequest): boolean {
|
|
70
|
+
return isNluAllowed(request, 'allowKeywords')
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
export function isSmartIntentsAllowed(request: ActionRequest): boolean {
|
|
74
|
+
return isNluAllowed(request, 'allowSmartIntents')
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
export function isKnowledgeBasesAllowed(request: ActionRequest): boolean {
|
|
78
|
+
return isNluAllowed(request, 'allowKnowledgeBases')
|
|
79
|
+
}
|