@botonic/plugin-flow-builder 0.56.0 → 0.57.0-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.
Files changed (87) hide show
  1. package/lib/cjs/api.d.ts +3 -2
  2. package/lib/cjs/api.js +20 -17
  3. package/lib/cjs/api.js.map +1 -1
  4. package/lib/cjs/bot-context-manager.d.ts +17 -0
  5. package/lib/cjs/bot-context-manager.js +93 -0
  6. package/lib/cjs/bot-context-manager.js.map +1 -0
  7. package/lib/cjs/constants.d.ts +2 -1
  8. package/lib/cjs/constants.js +3 -2
  9. package/lib/cjs/constants.js.map +1 -1
  10. package/lib/cjs/content-fields/contact-reasons-conditional-matcher.d.ts +4 -0
  11. package/lib/cjs/content-fields/contact-reasons-conditional-matcher.js +12 -0
  12. package/lib/cjs/content-fields/contact-reasons-conditional-matcher.js.map +1 -0
  13. package/lib/cjs/content-fields/flow-contact-reasons-conditional.d.ts +13 -0
  14. package/lib/cjs/content-fields/flow-contact-reasons-conditional.js +45 -0
  15. package/lib/cjs/content-fields/flow-contact-reasons-conditional.js.map +1 -0
  16. package/lib/cjs/content-fields/flow-handoff.d.ts +7 -1
  17. package/lib/cjs/content-fields/flow-handoff.js +38 -3
  18. package/lib/cjs/content-fields/flow-handoff.js.map +1 -1
  19. package/lib/cjs/content-fields/hubtype-fields/contact-reasons-conditional.d.ts +16 -0
  20. package/lib/cjs/content-fields/hubtype-fields/contact-reasons-conditional.js +3 -0
  21. package/lib/cjs/content-fields/hubtype-fields/contact-reasons-conditional.js.map +1 -0
  22. package/lib/cjs/content-fields/hubtype-fields/handoff.d.ts +6 -1
  23. package/lib/cjs/content-fields/hubtype-fields/node-types.d.ts +2 -1
  24. package/lib/cjs/content-fields/hubtype-fields/node-types.js +1 -0
  25. package/lib/cjs/content-fields/hubtype-fields/node-types.js.map +1 -1
  26. package/lib/cjs/content-fields/hubtype-fields/nodes.d.ts +2 -1
  27. package/lib/cjs/content-fields/index.d.ts +3 -2
  28. package/lib/cjs/content-fields/index.js +3 -1
  29. package/lib/cjs/content-fields/index.js.map +1 -1
  30. package/lib/cjs/flow-factory.js +2 -0
  31. package/lib/cjs/flow-factory.js.map +1 -1
  32. package/lib/cjs/index.d.ts +5 -9
  33. package/lib/cjs/index.js +16 -64
  34. package/lib/cjs/index.js.map +1 -1
  35. package/lib/cjs/types.d.ts +2 -2
  36. package/lib/cjs/types.js.map +1 -1
  37. package/lib/esm/api.d.ts +3 -2
  38. package/lib/esm/api.js +20 -17
  39. package/lib/esm/api.js.map +1 -1
  40. package/lib/esm/bot-context-manager.d.ts +17 -0
  41. package/lib/esm/bot-context-manager.js +93 -0
  42. package/lib/esm/bot-context-manager.js.map +1 -0
  43. package/lib/esm/constants.d.ts +2 -1
  44. package/lib/esm/constants.js +3 -2
  45. package/lib/esm/constants.js.map +1 -1
  46. package/lib/esm/content-fields/contact-reasons-conditional-matcher.d.ts +4 -0
  47. package/lib/esm/content-fields/contact-reasons-conditional-matcher.js +12 -0
  48. package/lib/esm/content-fields/contact-reasons-conditional-matcher.js.map +1 -0
  49. package/lib/esm/content-fields/flow-contact-reasons-conditional.d.ts +13 -0
  50. package/lib/esm/content-fields/flow-contact-reasons-conditional.js +45 -0
  51. package/lib/esm/content-fields/flow-contact-reasons-conditional.js.map +1 -0
  52. package/lib/esm/content-fields/flow-handoff.d.ts +7 -1
  53. package/lib/esm/content-fields/flow-handoff.js +38 -3
  54. package/lib/esm/content-fields/flow-handoff.js.map +1 -1
  55. package/lib/esm/content-fields/hubtype-fields/contact-reasons-conditional.d.ts +16 -0
  56. package/lib/esm/content-fields/hubtype-fields/contact-reasons-conditional.js +3 -0
  57. package/lib/esm/content-fields/hubtype-fields/contact-reasons-conditional.js.map +1 -0
  58. package/lib/esm/content-fields/hubtype-fields/handoff.d.ts +6 -1
  59. package/lib/esm/content-fields/hubtype-fields/node-types.d.ts +2 -1
  60. package/lib/esm/content-fields/hubtype-fields/node-types.js +1 -0
  61. package/lib/esm/content-fields/hubtype-fields/node-types.js.map +1 -1
  62. package/lib/esm/content-fields/hubtype-fields/nodes.d.ts +2 -1
  63. package/lib/esm/content-fields/index.d.ts +3 -2
  64. package/lib/esm/content-fields/index.js +3 -1
  65. package/lib/esm/content-fields/index.js.map +1 -1
  66. package/lib/esm/flow-factory.js +2 -0
  67. package/lib/esm/flow-factory.js.map +1 -1
  68. package/lib/esm/index.d.ts +5 -9
  69. package/lib/esm/index.js +16 -64
  70. package/lib/esm/index.js.map +1 -1
  71. package/lib/esm/types.d.ts +2 -2
  72. package/lib/esm/types.js.map +1 -1
  73. package/package.json +2 -2
  74. package/src/api.ts +29 -20
  75. package/src/bot-context-manager.ts +153 -0
  76. package/src/constants.ts +2 -1
  77. package/src/content-fields/contact-reasons-conditional-matcher.ts +24 -0
  78. package/src/content-fields/flow-contact-reasons-conditional.tsx +60 -0
  79. package/src/content-fields/flow-handoff.tsx +49 -7
  80. package/src/content-fields/hubtype-fields/contact-reasons-conditional.ts +18 -0
  81. package/src/content-fields/hubtype-fields/handoff.ts +11 -1
  82. package/src/content-fields/hubtype-fields/node-types.ts +1 -0
  83. package/src/content-fields/hubtype-fields/nodes.ts +2 -0
  84. package/src/content-fields/index.ts +3 -0
  85. package/src/flow-factory.ts +7 -0
  86. package/src/index.ts +26 -113
  87. package/src/types.ts +1 -2
package/src/index.ts CHANGED
@@ -1,25 +1,16 @@
1
- import {
2
- INPUT,
3
- type Plugin,
4
- type PluginPreRequest,
5
- PROVIDER,
6
- type ResolvedPlugins,
7
- type Session,
8
- WhatsappInputOrigin,
1
+ import type {
2
+ BotContext,
3
+ Plugin,
4
+ ResolvedPlugins,
5
+ Session,
9
6
  } from '@botonic/core'
10
- import type { ActionRequest } from '@botonic/react'
11
7
  import { v7 as uuidv7 } from 'uuid'
12
8
 
13
9
  import { FlowBuilderApi } from './api'
14
- import {
15
- EMPTY_PAYLOAD,
16
- FLOW_BUILDER_API_URL_PROD,
17
- SEPARATOR,
18
- SOURCE_INFO_SEPARATOR,
19
- } from './constants'
10
+ import { BotContextManager } from './bot-context-manager'
11
+ import { FLOW_BUILDER_API_URL_PROD, SEPARATOR } from './constants'
20
12
  import type { FlowContent } from './content-fields'
21
13
  import {
22
- type HtBotActionNode,
23
14
  type HtFlowBuilderData,
24
15
  type HtNodeWithContent,
25
16
  HtNodeWithContentType,
@@ -36,10 +27,8 @@ import {
36
27
  type RatingSubmittedInfo,
37
28
  type TrackEventFunction,
38
29
  } from './types'
39
- import { getNextPayloadByUserInput } from './user-input'
40
30
  import type { SmartIntentsInferenceConfig } from './user-input/smart-intent'
41
31
  import { resolveGetAccessToken } from './utils/authentication'
42
- import { inputHasTextOrTranscript } from './utils/input'
43
32
 
44
33
  // TODO: Create a proper service to wrap all calls and allow api versioning
45
34
 
@@ -47,7 +36,7 @@ export default class BotonicPluginFlowBuilder implements Plugin {
47
36
  public cmsApi: FlowBuilderApi
48
37
  private flow?: HtFlowBuilderData
49
38
  private functions: Record<any, any>
50
- private currentRequest: PluginPreRequest
39
+ private botContext: BotContext
51
40
  public getAccessToken: (session: Session) => string
52
41
  public trackEvent?: TrackEventFunction
53
42
  public getAiAgentResponse?: AiAgentFunction
@@ -86,109 +75,33 @@ export default class BotonicPluginFlowBuilder implements Plugin {
86
75
  options.disableAIAgentInFirstInteraction || false
87
76
  }
88
77
 
89
- resolveFlowUrl(request: PluginPreRequest): string {
90
- if (request.session.is_test_integration) {
78
+ resolveFlowUrl(botContext: BotContext): string {
79
+ if (botContext.session.is_test_integration) {
91
80
  return `${this.apiUrl}/v1/bot_flows/{bot_id}/versions/${FlowBuilderJSONVersion.DRAFT}/`
92
81
  }
93
82
  return `${this.apiUrl}/v1/bot_flows/{bot_id}/versions/${this.jsonVersion}/`
94
83
  }
95
84
 
96
- async pre(request: PluginPreRequest): Promise<void> {
97
- // When AI Agent is executed in Whatsapp, button payloads come as referral and must be converted to text being processed by the agent.
98
- this.convertWhatsappAiAgentEmptyPayloads(request)
99
-
100
- this.currentRequest = request
85
+ async pre(botContext: BotContext): Promise<void> {
86
+ this.botContext = botContext
101
87
  this.cmsApi = await FlowBuilderApi.create({
102
- flowUrl: this.resolveFlowUrl(request),
88
+ flowUrl: this.resolveFlowUrl(botContext),
103
89
  url: this.apiUrl,
104
90
  flow: this.flow,
105
- accessToken: this.getAccessToken(request.session),
106
- request: this.currentRequest,
91
+ accessToken: this.getAccessToken(botContext.session),
92
+ botContext: this.botContext,
107
93
  })
108
94
 
109
- this.resolveWhatsappContactRequestPayload(request)
110
-
111
- const checkUserTextInput =
112
- inputHasTextOrTranscript(request.input) && !request.input.payload
113
-
114
- if (checkUserTextInput) {
115
- const resolvedLocale = this.cmsApi.getResolvedLocale()
116
- const nextPayload = await getNextPayloadByUserInput(
117
- this.cmsApi,
118
- resolvedLocale,
119
- request as unknown as ActionRequest,
120
- this.smartIntentsConfig
121
- )
122
- request.input.payload = nextPayload
123
- }
124
-
125
- await this.updateRequestBeforeRoutes(request)
126
- }
127
-
128
- private resolveWhatsappContactRequestPayload(
129
- request: PluginPreRequest
130
- ): void {
131
- if (
132
- request.input.type !== INPUT.CONTACT ||
133
- request.input.origin !== WhatsappInputOrigin.ContactRequest
134
- ) {
135
- return
136
- }
137
-
138
- const whatsappRequestContactInfoNode =
139
- this.cmsApi.getWhatsappRequestContactInfoNode()
140
-
141
- if (whatsappRequestContactInfoNode) {
142
- request.input.payload = this.cmsApi.getPayload(
143
- whatsappRequestContactInfoNode.content.button.target
144
- )
145
- }
146
-
147
- this.cmsApi.removeWhatsappRequestContactId()
148
- }
149
-
150
- private convertWhatsappAiAgentEmptyPayloads(request: PluginPreRequest): void {
151
- if (request.session.user.provider === PROVIDER.WHATSAPP) {
152
- const shouldUseReferral =
153
- request.input.referral &&
154
- request.input.payload?.startsWith(EMPTY_PAYLOAD)
155
-
156
- if (shouldUseReferral) {
157
- request.input.type = INPUT.TEXT
158
- request.input.data = request.input.referral
159
- }
160
- }
161
- }
162
-
163
- private async updateRequestBeforeRoutes(
164
- request: PluginPreRequest
165
- ): Promise<void> {
166
- this.cmsApi.removeCaptureUserInputId()
167
- if (request.input.payload) {
168
- request.input.payload = this.removeSourceSuffix(request.input.payload)
169
-
170
- if (this.cmsApi.isBotAction(request.input.payload)) {
171
- const cmsBotAction = this.cmsApi.getNodeById<HtBotActionNode>(
172
- request.input.payload
173
- )
174
-
175
- request.input.payload =
176
- this.cmsApi.createPayloadWithParams(cmsBotAction)
177
-
178
- // Re-execute convertWhatsappAiAgentEmptyPayloads function to handle
179
- // the case that a BotAction has a payload equals to EMPTY_PAYLOAD
180
- this.convertWhatsappAiAgentEmptyPayloads(request)
181
- }
182
- }
183
- }
184
-
185
- private removeSourceSuffix(payload: string): string {
186
- return payload.split(SOURCE_INFO_SEPARATOR)[0]
95
+ const botContextManager = new BotContextManager(
96
+ this.cmsApi,
97
+ this.smartIntentsConfig
98
+ )
99
+ await botContextManager.updateBeforeRoutes(botContext)
187
100
  }
188
101
 
189
- post(request: PluginPreRequest): void {
190
- request.input.nluResolution = undefined
191
- delete request.session.user.system_locale_updated
102
+ post(botContext: BotContext): void {
103
+ botContext.input.nluResolution = undefined
104
+ delete botContext.session.user.system_locale_updated
192
105
  }
193
106
 
194
107
  async getContentsByContentID(
@@ -214,7 +127,7 @@ export default class BotonicPluginFlowBuilder implements Plugin {
214
127
 
215
128
  async getStartContents(): Promise<FlowContent[]> {
216
129
  const startNode = this.cmsApi.getStartNode()
217
- this.currentRequest.session.flow_thread_id = uuidv7()
130
+ this.botContext.session.flow_thread_id = uuidv7()
218
131
  return await this.getContentsByNode(startNode)
219
132
  }
220
133
 
@@ -231,7 +144,7 @@ export default class BotonicPluginFlowBuilder implements Plugin {
231
144
  ) {
232
145
  const customFunctionResolver = new CustomFunction(
233
146
  this.functions,
234
- this.currentRequest,
147
+ this.botContext,
235
148
  resolvedLocale
236
149
  )
237
150
  const targetId = await customFunctionResolver.call(node)
@@ -239,7 +152,7 @@ export default class BotonicPluginFlowBuilder implements Plugin {
239
152
  }
240
153
 
241
154
  const flowFactory = new FlowFactory(
242
- this.currentRequest,
155
+ this.botContext,
243
156
  this.cmsApi,
244
157
  resolvedLocale
245
158
  )
package/src/types.ts CHANGED
@@ -3,7 +3,6 @@ import type {
3
3
  BotContext,
4
4
  GuardrailRule,
5
5
  InferenceResponse,
6
- PluginPreRequest,
7
6
  ResolvedPlugins,
8
7
  } from '@botonic/core'
9
8
  import type { FlowContent } from './content-fields'
@@ -67,7 +66,7 @@ export interface FlowBuilderApiOptions {
67
66
  flowUrl: string
68
67
  flow?: HtFlowBuilderData
69
68
  accessToken: string
70
- request: PluginPreRequest
69
+ botContext: BotContext
71
70
  }
72
71
 
73
72
  export enum ProcessEnvNodeEnvs {