@botonic/plugin-flow-builder 0.56.1 → 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 +2 -2
  2. package/lib/cjs/api.js +17 -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 -67
  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 +2 -2
  38. package/lib/esm/api.js +17 -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 -67
  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 +19 -19
  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 -117
  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,113 +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
- if (this.cmsApi.isPushFlowPayload(request.input.payload)) {
110
- request.session.is_first_interaction = false
111
- }
112
-
113
- this.resolveWhatsappContactRequestPayload(request)
114
-
115
- const checkUserTextInput =
116
- inputHasTextOrTranscript(request.input) && !request.input.payload
117
-
118
- if (checkUserTextInput) {
119
- const resolvedLocale = this.cmsApi.getResolvedLocale()
120
- const nextPayload = await getNextPayloadByUserInput(
121
- this.cmsApi,
122
- resolvedLocale,
123
- request as unknown as ActionRequest,
124
- this.smartIntentsConfig
125
- )
126
- request.input.payload = nextPayload
127
- }
128
-
129
- await this.updateRequestBeforeRoutes(request)
130
- }
131
-
132
- private resolveWhatsappContactRequestPayload(
133
- request: PluginPreRequest
134
- ): void {
135
- if (
136
- request.input.type !== INPUT.CONTACT ||
137
- request.input.origin !== WhatsappInputOrigin.ContactRequest
138
- ) {
139
- return
140
- }
141
-
142
- const whatsappRequestContactInfoNode =
143
- this.cmsApi.getWhatsappRequestContactInfoNode()
144
-
145
- if (whatsappRequestContactInfoNode) {
146
- request.input.payload = this.cmsApi.getPayload(
147
- whatsappRequestContactInfoNode.content.button.target
148
- )
149
- }
150
-
151
- this.cmsApi.removeWhatsappRequestContactId()
152
- }
153
-
154
- private convertWhatsappAiAgentEmptyPayloads(request: PluginPreRequest): void {
155
- if (request.session.user.provider === PROVIDER.WHATSAPP) {
156
- const shouldUseReferral =
157
- request.input.referral &&
158
- request.input.payload?.startsWith(EMPTY_PAYLOAD)
159
-
160
- if (shouldUseReferral) {
161
- request.input.type = INPUT.TEXT
162
- request.input.data = request.input.referral
163
- }
164
- }
165
- }
166
-
167
- private async updateRequestBeforeRoutes(
168
- request: PluginPreRequest
169
- ): Promise<void> {
170
- this.cmsApi.removeCaptureUserInputId()
171
- if (request.input.payload) {
172
- request.input.payload = this.removeSourceSuffix(request.input.payload)
173
-
174
- if (this.cmsApi.isBotAction(request.input.payload)) {
175
- const cmsBotAction = this.cmsApi.getNodeById<HtBotActionNode>(
176
- request.input.payload
177
- )
178
-
179
- request.input.payload =
180
- this.cmsApi.createPayloadWithParams(cmsBotAction)
181
-
182
- // Re-execute convertWhatsappAiAgentEmptyPayloads function to handle
183
- // the case that a BotAction has a payload equals to EMPTY_PAYLOAD
184
- this.convertWhatsappAiAgentEmptyPayloads(request)
185
- }
186
- }
187
- }
188
-
189
- private removeSourceSuffix(payload: string): string {
190
- return payload.split(SOURCE_INFO_SEPARATOR)[0]
95
+ const botContextManager = new BotContextManager(
96
+ this.cmsApi,
97
+ this.smartIntentsConfig
98
+ )
99
+ await botContextManager.updateBeforeRoutes(botContext)
191
100
  }
192
101
 
193
- post(request: PluginPreRequest): void {
194
- request.input.nluResolution = undefined
195
- 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
196
105
  }
197
106
 
198
107
  async getContentsByContentID(
@@ -218,7 +127,7 @@ export default class BotonicPluginFlowBuilder implements Plugin {
218
127
 
219
128
  async getStartContents(): Promise<FlowContent[]> {
220
129
  const startNode = this.cmsApi.getStartNode()
221
- this.currentRequest.session.flow_thread_id = uuidv7()
130
+ this.botContext.session.flow_thread_id = uuidv7()
222
131
  return await this.getContentsByNode(startNode)
223
132
  }
224
133
 
@@ -235,7 +144,7 @@ export default class BotonicPluginFlowBuilder implements Plugin {
235
144
  ) {
236
145
  const customFunctionResolver = new CustomFunction(
237
146
  this.functions,
238
- this.currentRequest,
147
+ this.botContext,
239
148
  resolvedLocale
240
149
  )
241
150
  const targetId = await customFunctionResolver.call(node)
@@ -243,7 +152,7 @@ export default class BotonicPluginFlowBuilder implements Plugin {
243
152
  }
244
153
 
245
154
  const flowFactory = new FlowFactory(
246
- this.currentRequest,
155
+ this.botContext,
247
156
  this.cmsApi,
248
157
  resolvedLocale
249
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 {