@botonic/plugin-flow-builder 0.21.0-alpha.9 → 0.21.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.
Files changed (100) hide show
  1. package/lib/cjs/action.js +23 -32
  2. package/lib/cjs/action.js.map +1 -1
  3. package/lib/cjs/content-fields/content-fields-base.d.ts +3 -2
  4. package/lib/cjs/content-fields/content-fields-base.js +6 -1
  5. package/lib/cjs/content-fields/content-fields-base.js.map +1 -1
  6. package/lib/cjs/content-fields/flow-button.d.ts +1 -1
  7. package/lib/cjs/content-fields/flow-button.js +7 -5
  8. package/lib/cjs/content-fields/flow-button.js.map +1 -1
  9. package/lib/cjs/content-fields/flow-carousel.d.ts +1 -1
  10. package/lib/cjs/content-fields/flow-carousel.js +4 -5
  11. package/lib/cjs/content-fields/flow-carousel.js.map +1 -1
  12. package/lib/cjs/content-fields/flow-image.d.ts +1 -1
  13. package/lib/cjs/content-fields/flow-image.js +2 -2
  14. package/lib/cjs/content-fields/flow-image.js.map +1 -1
  15. package/lib/cjs/content-fields/flow-text.d.ts +1 -1
  16. package/lib/cjs/content-fields/flow-text.js +3 -3
  17. package/lib/cjs/content-fields/flow-text.js.map +1 -1
  18. package/lib/cjs/content-fields/flow-video.d.ts +8 -0
  19. package/lib/cjs/content-fields/flow-video.js +26 -0
  20. package/lib/cjs/content-fields/flow-video.js.map +1 -0
  21. package/lib/cjs/content-fields/index.d.ts +1 -0
  22. package/lib/cjs/content-fields/index.js +3 -1
  23. package/lib/cjs/content-fields/index.js.map +1 -1
  24. package/lib/cjs/content-fields/types.d.ts +2 -1
  25. package/lib/cjs/flow-builder-models.d.ts +26 -4
  26. package/lib/cjs/flow-builder-models.js +2 -0
  27. package/lib/cjs/flow-builder-models.js.map +1 -1
  28. package/lib/cjs/handoff.d.ts +2 -1
  29. package/lib/cjs/handoff.js +21 -14
  30. package/lib/cjs/handoff.js.map +1 -1
  31. package/lib/cjs/helpers.d.ts +6 -0
  32. package/lib/cjs/helpers.js +27 -0
  33. package/lib/cjs/helpers.js.map +1 -0
  34. package/lib/cjs/index.d.ts +10 -11
  35. package/lib/cjs/index.js +45 -42
  36. package/lib/cjs/index.js.map +1 -1
  37. package/lib/cjs/types.d.ts +13 -0
  38. package/lib/cjs/types.js +9 -0
  39. package/lib/cjs/types.js.map +1 -0
  40. package/lib/cjs/utils.d.ts +3 -0
  41. package/lib/cjs/utils.js +19 -1
  42. package/lib/cjs/utils.js.map +1 -1
  43. package/lib/esm/action.js +24 -33
  44. package/lib/esm/action.js.map +1 -1
  45. package/lib/esm/content-fields/content-fields-base.d.ts +3 -2
  46. package/lib/esm/content-fields/content-fields-base.js +6 -1
  47. package/lib/esm/content-fields/content-fields-base.js.map +1 -1
  48. package/lib/esm/content-fields/flow-button.d.ts +1 -1
  49. package/lib/esm/content-fields/flow-button.js +7 -5
  50. package/lib/esm/content-fields/flow-button.js.map +1 -1
  51. package/lib/esm/content-fields/flow-carousel.d.ts +1 -1
  52. package/lib/esm/content-fields/flow-carousel.js +4 -5
  53. package/lib/esm/content-fields/flow-carousel.js.map +1 -1
  54. package/lib/esm/content-fields/flow-image.d.ts +1 -1
  55. package/lib/esm/content-fields/flow-image.js +2 -2
  56. package/lib/esm/content-fields/flow-image.js.map +1 -1
  57. package/lib/esm/content-fields/flow-text.d.ts +1 -1
  58. package/lib/esm/content-fields/flow-text.js +3 -3
  59. package/lib/esm/content-fields/flow-text.js.map +1 -1
  60. package/lib/esm/content-fields/flow-video.d.ts +8 -0
  61. package/lib/esm/content-fields/flow-video.js +21 -0
  62. package/lib/esm/content-fields/flow-video.js.map +1 -0
  63. package/lib/esm/content-fields/index.d.ts +1 -0
  64. package/lib/esm/content-fields/index.js +1 -0
  65. package/lib/esm/content-fields/index.js.map +1 -1
  66. package/lib/esm/content-fields/types.d.ts +2 -1
  67. package/lib/esm/flow-builder-models.d.ts +26 -4
  68. package/lib/esm/flow-builder-models.js +2 -0
  69. package/lib/esm/flow-builder-models.js.map +1 -1
  70. package/lib/esm/handoff.d.ts +2 -1
  71. package/lib/esm/handoff.js +21 -14
  72. package/lib/esm/handoff.js.map +1 -1
  73. package/lib/esm/helpers.d.ts +6 -0
  74. package/lib/esm/helpers.js +22 -0
  75. package/lib/esm/helpers.js.map +1 -0
  76. package/lib/esm/index.d.ts +10 -11
  77. package/lib/esm/index.js +46 -43
  78. package/lib/esm/index.js.map +1 -1
  79. package/lib/esm/types.d.ts +13 -0
  80. package/lib/esm/types.js +6 -0
  81. package/lib/esm/types.js.map +1 -0
  82. package/lib/esm/utils.d.ts +3 -0
  83. package/lib/esm/utils.js +17 -0
  84. package/lib/esm/utils.js.map +1 -1
  85. package/package.json +3 -3
  86. package/src/action.tsx +29 -35
  87. package/src/content-fields/content-fields-base.ts +12 -3
  88. package/src/content-fields/flow-button.tsx +6 -4
  89. package/src/content-fields/flow-carousel.tsx +4 -5
  90. package/src/content-fields/flow-image.tsx +2 -2
  91. package/src/content-fields/flow-text.tsx +4 -4
  92. package/src/content-fields/flow-video.tsx +22 -0
  93. package/src/content-fields/index.ts +1 -0
  94. package/src/content-fields/types.ts +2 -1
  95. package/src/flow-builder-models.ts +30 -2
  96. package/src/handoff.ts +25 -16
  97. package/src/helpers.ts +39 -0
  98. package/src/index.ts +61 -61
  99. package/src/types.ts +16 -0
  100. package/src/utils.ts +24 -0
@@ -18,11 +18,11 @@ export class FlowCarousel extends ContentFieldsBase {
18
18
  return newCarousel
19
19
  }
20
20
 
21
- toBotonic(index: number): JSX.Element {
21
+ toBotonic(id: string): JSX.Element {
22
22
  return (
23
- <Carousel key={index}>
24
- {this.elements.map((element, eIndex) => (
25
- <Element key={eIndex}>
23
+ <Carousel key={id}>
24
+ {this.elements.map(element => (
25
+ <Element key={`${id}-${element.id}`}>
26
26
  <Pic src={element.image} />
27
27
  <Title style=''>{element.title}</Title>
28
28
  <Subtitle style=''>{element.subtitle}</Subtitle>
@@ -33,7 +33,6 @@ export class FlowCarousel extends ContentFieldsBase {
33
33
  >
34
34
  {element.buttons?.text}
35
35
  </Button>
36
- ,
37
36
  </Element>
38
37
  ))}
39
38
  </Carousel>
@@ -15,7 +15,7 @@ export class FlowImage extends ContentFieldsBase {
15
15
  return newImage
16
16
  }
17
17
 
18
- toBotonic(index: number): JSX.Element {
19
- return <Image src={this.src} key={index} />
18
+ toBotonic(id: string): JSX.Element {
19
+ return <Image key={id} src={this.src} />
20
20
  }
21
21
  }
@@ -22,12 +22,12 @@ export class FlowText extends ContentFieldsBase {
22
22
  return newText
23
23
  }
24
24
 
25
- toBotonic(index: number): JSX.Element {
25
+ toBotonic(id: string): JSX.Element {
26
26
  return (
27
- <Text key={index}>
27
+ <Text key={id}>
28
28
  {this.text}
29
- {this.buttons.map((button, index) =>
30
- button.renderButton(index, this.buttonStyle)
29
+ {this.buttons.map(button =>
30
+ button.renderButton(button.id, this.buttonStyle)
31
31
  )}
32
32
  </Text>
33
33
  )
@@ -0,0 +1,22 @@
1
+ import { Video } from '@botonic/react'
2
+ import React from 'react'
3
+
4
+ import { VideoNode } from '../flow-builder-models'
5
+ import { ContentFieldsBase } from './content-fields-base'
6
+
7
+ export class FlowVideo extends ContentFieldsBase {
8
+ public src = ''
9
+ public code = ''
10
+
11
+ static fromHubtypeCMS(component: VideoNode, locale: string): FlowVideo {
12
+ const newVideo = new FlowVideo(component.id)
13
+ newVideo.code = component.code
14
+ newVideo.src = this.getVideoByLocale(locale, component.content.video)
15
+ return newVideo
16
+ }
17
+
18
+ toBotonic(id: string): JSX.Element {
19
+ // @ts-ignore
20
+ return <Video key={id} src={this.src} />
21
+ }
22
+ }
@@ -4,4 +4,5 @@ export { FlowCarousel } from './flow-carousel'
4
4
  export { FlowElement } from './flow-element'
5
5
  export { FlowImage } from './flow-image'
6
6
  export { FlowText } from './flow-text'
7
+ export { FlowVideo } from './flow-video'
7
8
  export type { FlowContent } from './types'
@@ -1,5 +1,6 @@
1
1
  import { FlowCarousel } from './flow-carousel'
2
2
  import { FlowImage } from './flow-image'
3
3
  import { FlowText } from './flow-text'
4
+ import { FlowVideo } from './flow-video'
4
5
 
5
- export type FlowContent = FlowText | FlowImage | FlowCarousel
6
+ export type FlowContent = FlowText | FlowImage | FlowCarousel | FlowVideo
@@ -18,6 +18,8 @@ export enum NodeType {
18
18
  URL = 'url',
19
19
  PAYLOAD = 'payload',
20
20
  FUNCTION = 'function',
21
+ FALLBACK = 'fallback',
22
+ VIDEO = 'video',
21
23
  }
22
24
 
23
25
  export interface BaseNode {
@@ -67,8 +69,8 @@ export interface Button {
67
69
  text: TextLocale[]
68
70
  target?: NodeLink
69
71
  hidden: string
70
- url?: UrlLocale
71
- payload?: PayloadLocale
72
+ url?: UrlLocale[]
73
+ payload?: PayloadLocale[]
72
74
  }
73
75
 
74
76
  export interface TextNodeContent {
@@ -207,6 +209,30 @@ export interface FunctionNode extends Node {
207
209
  content: FunctionNodeContent
208
210
  }
209
211
 
212
+ export interface FallbackNodeContent {
213
+ first_message: NodeLink
214
+ second_message: NodeLink
215
+ }
216
+ export interface FallbackNode extends Node {
217
+ type: NodeType.FALLBACK
218
+ content: FallbackNodeContent
219
+ }
220
+
221
+ export interface VideoLocale {
222
+ url: string
223
+ is_embedded?: boolean
224
+ locale: string
225
+ }
226
+
227
+ export interface VideoNodeContent {
228
+ video: VideoLocale[]
229
+ }
230
+
231
+ export interface VideoNode extends Node {
232
+ type: NodeType.VIDEO
233
+ content: VideoNodeContent
234
+ }
235
+
210
236
  export type NodeComponent =
211
237
  | TextNode
212
238
  | ImageNode
@@ -218,3 +244,5 @@ export type NodeComponent =
218
244
  | StartNode
219
245
  | PayloadNode
220
246
  | FunctionNode
247
+ | FallbackNode
248
+ | VideoNode
package/src/handoff.ts CHANGED
@@ -1,28 +1,37 @@
1
1
  import { HandOffBuilder } from '@botonic/core'
2
2
  import { ActionRequest } from '@botonic/react'
3
3
 
4
+ import { HandoffNode } from './flow-builder-models'
5
+ import { getFlowBuilderPlugin } from './helpers'
6
+
4
7
  export async function doHandoff(
5
8
  request: ActionRequest,
6
- queue: string,
7
- note?: string,
8
- agentEmail?: string
9
+ locale: string,
10
+ handoffNode: HandoffNode
9
11
  ): Promise<void> {
12
+ const flowBuilderPlugin = getFlowBuilderPlugin(request.plugins)
13
+ const handoffTargetNode = await flowBuilderPlugin.getHandoffContent(
14
+ handoffNode.target?.id
15
+ )
10
16
  // @ts-ignore
11
- const flowBuilderPlugin = request.plugins.hubtypeFlowBuilder as any
12
- const handoffContent = await flowBuilderPlugin.getHandoffContent()
17
+ const handOffBuilder = new HandOffBuilder(request.session) // handOffBuilder.withQueue(handoffNode.content.queue)
18
+ const handoffQueues = handoffNode.content.queue
19
+ const queueFound = handoffQueues.find(q => q.locale === locale)
20
+ if (queueFound) handOffBuilder.withQueue(queueFound.id)
21
+ // TODO: Retrieve params from FlowBuilder
22
+ // const handoffParams = {
23
+ // agentEmail: 'test@gmail.com',
24
+ // note: 'This is a note that will be attached to the case as a reminder',
25
+ // }
13
26
 
14
- // @ts-ignore
15
- const handOffBuilder = new HandOffBuilder(request.session)
16
- handOffBuilder.withQueue(queue)
27
+ // if (handoffParams.note) {
28
+ // handOffBuilder.withNote(handoffParams.note)
29
+ // }
17
30
 
18
- if (note) {
19
- handOffBuilder.withNote(note)
20
- }
31
+ // if (handoffParams.agentEmail) {
32
+ // handOffBuilder.withAgentEmail(handoffParams.agentEmail)
33
+ // }
21
34
 
22
- if (agentEmail) {
23
- handOffBuilder.withAgentEmail(agentEmail)
24
- }
25
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
26
- handOffBuilder.withOnFinishPayload(handoffContent.target?.id!)
35
+ handOffBuilder.withOnFinishPayload(handoffTargetNode.id)
27
36
  await handOffBuilder.handOff()
28
37
  }
package/src/helpers.ts ADDED
@@ -0,0 +1,39 @@
1
+ import { Plugin } from '@botonic/core'
2
+ import BotonicPluginFlowBuilder from './index'
3
+ import { NodeComponent } from './flow-builder-models'
4
+
5
+ const FLOW_BUILDER_PLUGIN_NAME = 'BotonicPluginFlowBuilder'
6
+
7
+ export function getFlowBuilderPlugin(plugins: {
8
+ [id: string]: Plugin
9
+ }): BotonicPluginFlowBuilder {
10
+ const flowBuilderPlugin = Object.values(plugins).find(
11
+ // @ts-ignore
12
+ plugin => plugin.name === FLOW_BUILDER_PLUGIN_NAME
13
+ ) as BotonicPluginFlowBuilder
14
+ if (!flowBuilderPlugin)
15
+ throw new Error(
16
+ `You must include '@botonic/plugin-flow-builder' in your plugins file.`
17
+ )
18
+ return flowBuilderPlugin
19
+ }
20
+
21
+ export async function updateButtonUrls(
22
+ hubtypeContent: any,
23
+ contentKey: string,
24
+ getContentFn: any
25
+ ): Promise<void> {
26
+ if (hubtypeContent.content[contentKey]) {
27
+ for (const i in hubtypeContent.content[contentKey]) {
28
+ const button = hubtypeContent.content[contentKey][i].button
29
+ if (button.url) {
30
+ for (const j in button.url) {
31
+ button.url[j] = {
32
+ ...button.url[j],
33
+ ...(await getContentFn(button.url[j].id)),
34
+ }
35
+ }
36
+ }
37
+ }
38
+ }
39
+ }
package/src/index.ts CHANGED
@@ -12,8 +12,10 @@ import {
12
12
  FlowContent,
13
13
  FlowImage,
14
14
  FlowText,
15
+ FlowVideo,
15
16
  } from './content-fields'
16
17
  import {
18
+ FallbackNode,
17
19
  FlowBuilderData,
18
20
  FunctionNode,
19
21
  HandoffNode,
@@ -24,42 +26,37 @@ import {
24
26
  StartNode,
25
27
  } from './flow-builder-models'
26
28
  import { DEFAULT_FUNCTIONS } from './functions'
27
-
28
- export type BotonicPluginFlowBuilderOptions = {
29
- flowUrl: string
30
- flow?: FlowBuilderData
31
- customFunctions?: Record<any, any>
32
- getLocale: (session: Session) => string
33
- getAccessToken: () => string
34
- }
29
+ import { BotonicPluginFlowBuilderOptions } from './types'
30
+ import { resolveGetAccessToken } from './utils'
31
+ import { updateButtonUrls } from './helpers'
35
32
 
36
33
  export default class BotonicPluginFlowBuilder implements Plugin {
37
34
  private flowUrl: string
38
35
  private flow: Promise<FlowBuilderData> | FlowBuilderData
39
36
  private functions: Record<any, any>
40
37
  private currentRequest: PluginPreRequest
41
- private getAccessToken: () => string
38
+ private getAccessToken: (session: Session) => string
42
39
  public getLocale: (session: Session) => string
43
40
 
44
41
  constructor(readonly options: BotonicPluginFlowBuilderOptions) {
45
42
  this.getLocale = options.getLocale
46
- this.getAccessToken = options.getAccessToken
43
+ this.getAccessToken = resolveGetAccessToken(options)
47
44
  this.flowUrl = options.flowUrl
48
- this.flow = options.flow || this.readFlowContent()
45
+ if (options.flow) this.flow = options.flow
49
46
  const customFunctions = options.customFunctions || {}
50
47
  this.functions = { ...DEFAULT_FUNCTIONS, ...customFunctions }
51
48
  }
52
49
 
53
- async readFlowContent(): Promise<FlowBuilderData> {
54
- const response = await axios.get(this.flowUrl, {
55
- headers: { Authorization: `Bearer ${this.getAccessToken()}` },
50
+ async readFlowContent(session: Session): Promise<FlowBuilderData> {
51
+ const { data } = await axios.get(this.flowUrl, {
52
+ headers: { Authorization: `Bearer ${this.getAccessToken(session)}` },
56
53
  })
57
- return response.data
54
+ return data
58
55
  }
59
56
 
60
57
  async pre(request: PluginPreRequest): Promise<void> {
61
58
  this.currentRequest = request
62
- this.flow = this.readFlowContent()
59
+ this.flow = await this.readFlowContent(this.currentRequest.session)
63
60
  }
64
61
 
65
62
  async post(_request: PluginPostRequest): Promise<void> {}
@@ -71,10 +68,12 @@ export default class BotonicPluginFlowBuilder implements Plugin {
71
68
  return content
72
69
  }
73
70
 
74
- async getHandoffContent(): Promise<HandoffNode> {
71
+ async getHandoffContent(
72
+ handoffTargetId: string | undefined
73
+ ): Promise<HandoffNode> {
75
74
  const flow = await this.flow
76
75
  const content = flow.nodes.find(
77
- node => node.type === NodeType.HANDOFF
76
+ node => node.id === handoffTargetId
78
77
  ) as HandoffNode
79
78
  if (!content) throw Error(`Handoff node not found`)
80
79
  return content
@@ -91,6 +90,8 @@ export default class BotonicPluginFlowBuilder implements Plugin {
91
90
  return FlowImage.fromHubtypeCMS(hubtypeContent, locale)
92
91
  case NodeType.CAROUSEL:
93
92
  return FlowCarousel.fromHubtypeCMS(hubtypeContent, locale)
93
+ case NodeType.VIDEO:
94
+ return FlowVideo.fromHubtypeCMS(hubtypeContent, locale)
94
95
  default:
95
96
  return undefined
96
97
  }
@@ -98,46 +99,35 @@ export default class BotonicPluginFlowBuilder implements Plugin {
98
99
 
99
100
  async getStartId(): Promise<string> {
100
101
  const flow = await this.flow
101
- const startNode = flow.nodes.find(node => node.type === NodeType.START_UP)
102
- if (!startNode) {
103
- throw new Error('start-up id must be defined')
104
- }
105
- return (startNode as StartNode).target.id
102
+ const startNode = flow.nodes.find(
103
+ node => node.type === NodeType.START_UP
104
+ ) as StartNode | undefined
105
+ if (!startNode) throw new Error('start-up id must be defined')
106
+ return startNode.target.id
106
107
  }
107
108
 
109
+ async getFallbackId(alternate: boolean): Promise<string> {
110
+ const flow = await this.flow
111
+ const fallbackNode = flow.nodes.find(
112
+ node => node.type === NodeType.FALLBACK
113
+ ) as FallbackNode | undefined
114
+ if (!fallbackNode) throw new Error('fallback node must be defined')
115
+ const fallbackFirstMessage = fallbackNode.content.first_message
116
+ const fallbackSecondMessage = fallbackNode.content.second_message
117
+ if (!fallbackSecondMessage) return fallbackFirstMessage.id
118
+ return alternate ? fallbackFirstMessage.id : fallbackSecondMessage.id
119
+ }
108
120
  async getContents(
109
121
  id: string,
110
122
  locale: string,
111
123
  prevContents?: FlowContent[]
112
- ): Promise<FlowContent[]> {
124
+ ): Promise<{ contents: FlowContent[]; handoffNode: HandoffNode }> {
113
125
  const contents = prevContents || []
114
126
  const hubtypeContent: any = await this.getContent(id)
115
- if (hubtypeContent.content.elements) {
116
- for (const i in hubtypeContent.content.elements) {
117
- const button = hubtypeContent.content.elements[i].button
118
- if (button.url) {
119
- for (const j in button.url) {
120
- button.url[j] = {
121
- ...button.url[j],
122
- ...(await this.getContent(button.url[j].id)),
123
- }
124
- }
125
- }
126
- }
127
- }
128
- if (hubtypeContent.content.buttons) {
129
- for (const i in hubtypeContent.content.buttons) {
130
- const button = hubtypeContent.content.buttons[i]
131
- if (button.url) {
132
- for (const j in button.url) {
133
- button.url[j] = {
134
- ...button.url[j],
135
- ...(await this.getContent(button.url[j].id)),
136
- }
137
- }
138
- }
139
- }
140
- }
127
+ const isHandoff = hubtypeContent.type === NodeType.HANDOFF
128
+ // TODO: Create function to populate these buttons
129
+ await updateButtonUrls(hubtypeContent, 'elements', this.getContent)
130
+ await updateButtonUrls(hubtypeContent, 'buttons', this.getContent)
141
131
  const content = await this.getFlowContent(hubtypeContent, locale)
142
132
  if (hubtypeContent.type === NodeType.FUNCTION) {
143
133
  const targetId = await this.callFunction(hubtypeContent, locale)
@@ -151,10 +141,10 @@ export default class BotonicPluginFlowBuilder implements Plugin {
151
141
  }
152
142
  // execute function
153
143
  // return this.getContents(function result_mapping target, locale, contents)
154
- return contents
144
+ return { contents, handoffNode: isHandoff && hubtypeContent }
155
145
  }
156
146
 
157
- async getPayloadByInput(
147
+ async getPayloadByIntent(
158
148
  input: Input,
159
149
  locale: string
160
150
  ): Promise<string | undefined> {
@@ -163,14 +153,17 @@ export default class BotonicPluginFlowBuilder implements Plugin {
163
153
  const intents = flow.nodes.filter(
164
154
  node => node.type === NodeType.INTENT
165
155
  ) as IntentNode[]
166
- if (input.intent) {
167
- const matchedIntents = intents.filter(node =>
168
- //@ts-ignore
169
- this.hasIntent(node, input.intent, locale)
156
+ const inputIntent = input.intent
157
+ const inputConfidence = input.confidence
158
+ if (inputIntent) {
159
+ const matchedIntentNode = intents.find(
160
+ node =>
161
+ inputIntent &&
162
+ this.hasIntent(node, inputIntent, locale) &&
163
+ inputConfidence &&
164
+ this.hasMetConfidenceThreshold(node, inputConfidence)
170
165
  )
171
- if (matchedIntents.length > 0) {
172
- return matchedIntents[0].target?.id
173
- }
166
+ return matchedIntentNode?.target?.id
174
167
  }
175
168
  } catch (error) {
176
169
  console.error('Error getting payload by input: ', error)
@@ -180,10 +173,17 @@ export default class BotonicPluginFlowBuilder implements Plugin {
180
173
  }
181
174
 
182
175
  hasIntent(node: IntentNode, intent: string, locale: string): boolean {
183
- const result = node.content.intents.find(
176
+ return node.content.intents.some(
184
177
  i => i.locale === locale && i.values.includes(intent)
185
178
  )
186
- return Boolean(result)
179
+ }
180
+
181
+ hasMetConfidenceThreshold(
182
+ node: IntentNode,
183
+ predictedConfidence: number
184
+ ): boolean {
185
+ const nodeConfidence = node.content.confidence / 100
186
+ return predictedConfidence >= nodeConfidence
187
187
  }
188
188
 
189
189
  async getPayloadByKeyword(
package/src/types.ts ADDED
@@ -0,0 +1,16 @@
1
+ import { Session } from '@botonic/core'
2
+
3
+ import { FlowBuilderData } from './flow-builder-models'
4
+
5
+ export interface BotonicPluginFlowBuilderOptions {
6
+ flowUrl: string
7
+ flow?: FlowBuilderData
8
+ customFunctions?: Record<any, any>
9
+ getLocale: (session: Session) => string
10
+ getAccessToken: () => string
11
+ }
12
+
13
+ export enum ProcessEnvNodeEnvs {
14
+ PRODUCTION = 'production',
15
+ DEVELOPMENT = 'development',
16
+ }
package/src/utils.ts CHANGED
@@ -1,3 +1,7 @@
1
+ import { Session } from '@botonic/core'
2
+
3
+ import { BotonicPluginFlowBuilderOptions, ProcessEnvNodeEnvs } from './types'
4
+
1
5
  export function getWebpackEnvVar(
2
6
  webpackEnvVar: string | false,
3
7
  name: string,
@@ -9,3 +13,23 @@ export function getWebpackEnvVar(
9
13
  defaultValue
10
14
  )
11
15
  }
16
+
17
+ function getAccessTokenFromSession(session: Session): string {
18
+ if (!session._access_token) {
19
+ throw new Error('No access token found in session')
20
+ }
21
+ return session._access_token
22
+ }
23
+
24
+ export function resolveGetAccessToken(
25
+ options: BotonicPluginFlowBuilderOptions
26
+ ): (session: Session) => string {
27
+ switch (process.env.NODE_ENV) {
28
+ case ProcessEnvNodeEnvs.PRODUCTION:
29
+ return getAccessTokenFromSession
30
+ case ProcessEnvNodeEnvs.DEVELOPMENT:
31
+ return options.getAccessToken
32
+ default:
33
+ throw new Error('No method defined for getting access token')
34
+ }
35
+ }