@botonic/plugin-flow-builder 0.36.0 → 0.37.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.
- package/lib/cjs/action/ai-agent.js +6 -10
- package/lib/cjs/action/ai-agent.js.map +1 -1
- package/lib/cjs/action/index.js +4 -0
- package/lib/cjs/action/index.js.map +1 -1
- package/lib/cjs/action/payload.d.ts +1 -1
- package/lib/cjs/action/payload.js +46 -3
- package/lib/cjs/action/payload.js.map +1 -1
- package/lib/cjs/api.d.ts +3 -1
- package/lib/cjs/api.js +15 -0
- package/lib/cjs/api.js.map +1 -1
- package/lib/cjs/constants.d.ts +1 -0
- package/lib/cjs/constants.js +4 -1
- package/lib/cjs/constants.js.map +1 -1
- package/lib/cjs/content-fields/flow-ai-agent.d.ts +2 -1
- package/lib/cjs/content-fields/flow-ai-agent.js +15 -2
- package/lib/cjs/content-fields/flow-ai-agent.js.map +1 -1
- package/lib/cjs/content-fields/flow-button.d.ts +8 -0
- package/lib/cjs/content-fields/flow-button.js +15 -0
- package/lib/cjs/content-fields/flow-button.js.map +1 -1
- package/lib/cjs/content-fields/flow-element.d.ts +9 -0
- package/lib/cjs/content-fields/flow-element.js +12 -0
- package/lib/cjs/content-fields/flow-element.js.map +1 -1
- package/lib/cjs/content-fields/flow-rating.d.ts +15 -0
- package/lib/cjs/content-fields/flow-rating.js +56 -0
- package/lib/cjs/content-fields/flow-rating.js.map +1 -0
- package/lib/cjs/content-fields/hubtype-fields/index.d.ts +1 -0
- package/lib/cjs/content-fields/hubtype-fields/index.js +1 -0
- package/lib/cjs/content-fields/hubtype-fields/index.js.map +1 -1
- package/lib/cjs/content-fields/hubtype-fields/node-types.d.ts +2 -1
- package/lib/cjs/content-fields/hubtype-fields/node-types.js +1 -0
- package/lib/cjs/content-fields/hubtype-fields/node-types.js.map +1 -1
- package/lib/cjs/content-fields/hubtype-fields/nodes.d.ts +2 -1
- package/lib/cjs/content-fields/hubtype-fields/rating.d.ts +23 -0
- package/lib/cjs/content-fields/hubtype-fields/rating.js +9 -0
- package/lib/cjs/content-fields/hubtype-fields/rating.js.map +1 -0
- package/lib/cjs/content-fields/index.d.ts +3 -2
- package/lib/cjs/content-fields/index.js +3 -1
- package/lib/cjs/content-fields/index.js.map +1 -1
- package/lib/cjs/content-fields/whatsapp-button-list/flow-whatsapp-button-list-section.d.ts +1 -1
- package/lib/cjs/content-fields/whatsapp-button-list/flow-whatsapp-button-list-section.js +1 -1
- package/lib/cjs/content-fields/whatsapp-button-list/flow-whatsapp-button-list-section.js.map +1 -1
- package/lib/cjs/content-fields/whatsapp-button-list/flow-whatsapp-button-list.d.ts +1 -1
- package/lib/cjs/content-fields/whatsapp-button-list/flow-whatsapp-button-list.js +1 -1
- package/lib/cjs/content-fields/whatsapp-button-list/flow-whatsapp-button-list.js.map +1 -1
- package/lib/cjs/index.d.ts +1 -0
- package/lib/cjs/index.js +4 -0
- package/lib/cjs/index.js.map +1 -1
- package/lib/cjs/tracking.d.ts +2 -1
- package/lib/cjs/tracking.js +1 -0
- package/lib/cjs/tracking.js.map +1 -1
- package/lib/cjs/types.d.ts +36 -7
- package/lib/cjs/types.js.map +1 -1
- package/lib/esm/action/ai-agent.js +5 -9
- package/lib/esm/action/ai-agent.js.map +1 -1
- package/lib/esm/action/index.js +4 -0
- package/lib/esm/action/index.js.map +1 -1
- package/lib/esm/action/payload.d.ts +1 -1
- package/lib/esm/action/payload.js +46 -3
- package/lib/esm/action/payload.js.map +1 -1
- package/lib/esm/api.d.ts +3 -1
- package/lib/esm/api.js +15 -0
- package/lib/esm/api.js.map +1 -1
- package/lib/esm/constants.d.ts +1 -0
- package/lib/esm/constants.js +3 -0
- package/lib/esm/constants.js.map +1 -1
- package/lib/esm/content-fields/flow-ai-agent.d.ts +2 -1
- package/lib/esm/content-fields/flow-ai-agent.js +17 -4
- package/lib/esm/content-fields/flow-ai-agent.js.map +1 -1
- package/lib/esm/content-fields/flow-button.d.ts +8 -0
- package/lib/esm/content-fields/flow-button.js +15 -0
- package/lib/esm/content-fields/flow-button.js.map +1 -1
- package/lib/esm/content-fields/flow-element.d.ts +9 -0
- package/lib/esm/content-fields/flow-element.js +12 -0
- package/lib/esm/content-fields/flow-element.js.map +1 -1
- package/lib/esm/content-fields/flow-rating.d.ts +15 -0
- package/lib/esm/content-fields/flow-rating.js +52 -0
- package/lib/esm/content-fields/flow-rating.js.map +1 -0
- package/lib/esm/content-fields/hubtype-fields/index.d.ts +1 -0
- package/lib/esm/content-fields/hubtype-fields/index.js +1 -0
- package/lib/esm/content-fields/hubtype-fields/index.js.map +1 -1
- package/lib/esm/content-fields/hubtype-fields/node-types.d.ts +2 -1
- package/lib/esm/content-fields/hubtype-fields/node-types.js +1 -0
- package/lib/esm/content-fields/hubtype-fields/node-types.js.map +1 -1
- package/lib/esm/content-fields/hubtype-fields/nodes.d.ts +2 -1
- package/lib/esm/content-fields/hubtype-fields/rating.d.ts +23 -0
- package/lib/esm/content-fields/hubtype-fields/rating.js +6 -0
- package/lib/esm/content-fields/hubtype-fields/rating.js.map +1 -0
- package/lib/esm/content-fields/index.d.ts +3 -2
- package/lib/esm/content-fields/index.js +2 -1
- package/lib/esm/content-fields/index.js.map +1 -1
- package/lib/esm/content-fields/whatsapp-button-list/flow-whatsapp-button-list-section.d.ts +1 -1
- package/lib/esm/content-fields/whatsapp-button-list/flow-whatsapp-button-list-section.js +1 -1
- package/lib/esm/content-fields/whatsapp-button-list/flow-whatsapp-button-list-section.js.map +1 -1
- package/lib/esm/content-fields/whatsapp-button-list/flow-whatsapp-button-list.d.ts +1 -1
- package/lib/esm/content-fields/whatsapp-button-list/flow-whatsapp-button-list.js +1 -1
- package/lib/esm/content-fields/whatsapp-button-list/flow-whatsapp-button-list.js.map +1 -1
- package/lib/esm/index.d.ts +1 -0
- package/lib/esm/index.js +5 -1
- package/lib/esm/index.js.map +1 -1
- package/lib/esm/tracking.d.ts +2 -1
- package/lib/esm/tracking.js +1 -0
- package/lib/esm/tracking.js.map +1 -1
- package/lib/esm/types.d.ts +36 -7
- package/lib/esm/types.js.map +1 -1
- package/package.json +2 -2
- package/src/action/ai-agent.ts +7 -14
- package/src/action/index.tsx +4 -0
- package/src/action/payload.ts +56 -6
- package/src/api.ts +28 -0
- package/src/constants.ts +4 -0
- package/src/content-fields/flow-ai-agent.tsx +43 -3
- package/src/content-fields/flow-button.tsx +22 -0
- package/src/content-fields/flow-element.tsx +21 -0
- package/src/content-fields/flow-rating.tsx +92 -0
- package/src/content-fields/hubtype-fields/index.ts +1 -0
- package/src/content-fields/hubtype-fields/node-types.ts +1 -0
- package/src/content-fields/hubtype-fields/nodes.ts +2 -0
- package/src/content-fields/hubtype-fields/rating.ts +26 -0
- package/src/content-fields/index.ts +4 -0
- package/src/content-fields/whatsapp-button-list/flow-whatsapp-button-list-section.tsx +1 -1
- package/src/content-fields/whatsapp-button-list/flow-whatsapp-button-list.tsx +1 -1
- package/src/index.ts +7 -0
- package/src/tracking.ts +1 -0
- package/src/types.ts +43 -8
package/src/action/ai-agent.ts
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { FlowContent } from '../content-fields'
|
|
2
2
|
import { FlowAiAgent } from '../content-fields/flow-ai-agent'
|
|
3
|
-
import { AiAgentResponse } from '../types'
|
|
4
3
|
import { FlowBuilderContext } from './index'
|
|
5
4
|
|
|
6
5
|
export async function getContentsByAiAgent({
|
|
@@ -16,6 +15,7 @@ export async function getContentsByAiAgent({
|
|
|
16
15
|
|
|
17
16
|
const contents =
|
|
18
17
|
await flowBuilderPlugin.getContentsByNode(startNodeAiAgentFlow)
|
|
18
|
+
|
|
19
19
|
const aiAgentContent = contents.find(
|
|
20
20
|
content => content instanceof FlowAiAgent
|
|
21
21
|
) as FlowAiAgent
|
|
@@ -33,22 +33,15 @@ export async function getContentsByAiAgent({
|
|
|
33
33
|
}
|
|
34
34
|
)
|
|
35
35
|
|
|
36
|
-
if (!aiAgentResponse
|
|
36
|
+
if (!aiAgentResponse) {
|
|
37
37
|
return []
|
|
38
38
|
}
|
|
39
39
|
|
|
40
|
-
|
|
41
|
-
|
|
40
|
+
if (aiAgentResponse.length === 1 && aiAgentResponse[0].type === 'exit') {
|
|
41
|
+
return []
|
|
42
|
+
}
|
|
42
43
|
|
|
43
|
-
|
|
44
|
-
contents: FlowContent[],
|
|
45
|
-
aiAgentResponse: AiAgentResponse
|
|
46
|
-
): FlowContent[] {
|
|
47
|
-
return contents.map(content => {
|
|
48
|
-
if (content instanceof FlowAiAgent) {
|
|
49
|
-
content.text = aiAgentResponse.content || ''
|
|
50
|
-
}
|
|
44
|
+
aiAgentContent.responses = aiAgentResponse
|
|
51
45
|
|
|
52
|
-
|
|
53
|
-
})
|
|
46
|
+
return contents
|
|
54
47
|
}
|
package/src/action/index.tsx
CHANGED
|
@@ -125,6 +125,10 @@ async function getContents(
|
|
|
125
125
|
return []
|
|
126
126
|
}
|
|
127
127
|
|
|
128
|
+
if (request.input.payload?.startsWith('do-nothing')) {
|
|
129
|
+
request.input.payload = undefined
|
|
130
|
+
}
|
|
131
|
+
|
|
128
132
|
if (request.input.payload || contentID) {
|
|
129
133
|
const contentsByPayload = await getContentsByPayload(context)
|
|
130
134
|
if (contentsByPayload.length > 0) {
|
package/src/action/payload.ts
CHANGED
|
@@ -1,13 +1,20 @@
|
|
|
1
|
+
import { storeCaseRating } from '@botonic/core'
|
|
2
|
+
import { v7 as uuid } from 'uuid'
|
|
3
|
+
|
|
4
|
+
import { AGENT_RATING_PAYLOAD, SEPARATOR } from '../constants'
|
|
1
5
|
import { FlowContent } from '../content-fields'
|
|
2
6
|
import { HtNodeWithContent } from '../content-fields/hubtype-fields'
|
|
7
|
+
import { EventAction, trackEvent } from '../tracking'
|
|
3
8
|
import { FlowBuilderContext } from './index'
|
|
4
9
|
|
|
5
|
-
export async function getContentsByPayload(
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
request,
|
|
9
|
-
|
|
10
|
-
|
|
10
|
+
export async function getContentsByPayload(
|
|
11
|
+
context: FlowBuilderContext
|
|
12
|
+
): Promise<FlowContent[]> {
|
|
13
|
+
const { cmsApi, flowBuilderPlugin, request, contentID } = context
|
|
14
|
+
if (request.input.payload?.startsWith(AGENT_RATING_PAYLOAD)) {
|
|
15
|
+
return await resolveRatingPayload(context)
|
|
16
|
+
}
|
|
17
|
+
|
|
11
18
|
const id = contentID
|
|
12
19
|
? cmsApi.getNodeByContentID(contentID)?.id
|
|
13
20
|
: request.input.payload
|
|
@@ -19,3 +26,46 @@ export async function getContentsByPayload({
|
|
|
19
26
|
|
|
20
27
|
return []
|
|
21
28
|
}
|
|
29
|
+
|
|
30
|
+
async function resolveRatingPayload(
|
|
31
|
+
context: FlowBuilderContext
|
|
32
|
+
): Promise<FlowContent[]> {
|
|
33
|
+
const { cmsApi, flowBuilderPlugin, request } = context
|
|
34
|
+
|
|
35
|
+
if (!request.input.payload) {
|
|
36
|
+
return []
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
const id = request.input.payload
|
|
40
|
+
const buttonId = id?.split(SEPARATOR)[1]
|
|
41
|
+
const ratingNode = cmsApi.getRatingNodeByButtonId(buttonId)
|
|
42
|
+
const ratingButton = cmsApi.getRatingButtonById(ratingNode, buttonId)
|
|
43
|
+
const { target, text, value } = ratingButton
|
|
44
|
+
const possibleOptions = ratingNode.content.buttons.map(button => button.text)
|
|
45
|
+
const possibleValues = ratingNode.content.buttons.map(button => button.value)
|
|
46
|
+
|
|
47
|
+
if (request.session._hubtype_case_id) {
|
|
48
|
+
const event = {
|
|
49
|
+
action: EventAction.FeedbackCase,
|
|
50
|
+
feedbackTargetId: request.session._hubtype_case_id,
|
|
51
|
+
feedbackGroupId: uuid().toString(),
|
|
52
|
+
possibleOptions,
|
|
53
|
+
possibleValues,
|
|
54
|
+
option: text,
|
|
55
|
+
value,
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
await storeCaseRating(request.session, value)
|
|
59
|
+
await trackEvent(request, EventAction.FeedbackCase, event)
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
const targetNode = target
|
|
63
|
+
? cmsApi.getNodeById<HtNodeWithContent>(target.id)
|
|
64
|
+
: undefined
|
|
65
|
+
|
|
66
|
+
if (targetNode) {
|
|
67
|
+
return await flowBuilderPlugin.getContentsByNode(targetNode)
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
return []
|
|
71
|
+
}
|
package/src/api.ts
CHANGED
|
@@ -19,6 +19,8 @@ import {
|
|
|
19
19
|
HtNodeWithContentType,
|
|
20
20
|
HtNodeWithoutContentType,
|
|
21
21
|
HtPayloadNode,
|
|
22
|
+
HtRatingButton,
|
|
23
|
+
HtRatingNode,
|
|
22
24
|
} from './content-fields/hubtype-fields'
|
|
23
25
|
import { HtSmartIntentNode } from './content-fields/hubtype-fields/smart-intent'
|
|
24
26
|
import { FlowBuilderApiOptions, ProcessEnvNodeEnvs } from './types'
|
|
@@ -80,6 +82,32 @@ export class FlowBuilderApi {
|
|
|
80
82
|
return node as T
|
|
81
83
|
}
|
|
82
84
|
|
|
85
|
+
getRatingNodeByButtonId(id: string): HtRatingNode {
|
|
86
|
+
const ratingNodes = this.flow.nodes.filter(
|
|
87
|
+
node => node.type === HtNodeWithContentType.RATING
|
|
88
|
+
) as HtRatingNode[]
|
|
89
|
+
const ratingNode = ratingNodes.find(node =>
|
|
90
|
+
node.content.buttons.some(button => button.id === id)
|
|
91
|
+
) as HtRatingNode | undefined
|
|
92
|
+
|
|
93
|
+
if (!ratingNode) {
|
|
94
|
+
throw Error(`Rating node with button id: '${id}' not found`)
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
return ratingNode
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
getRatingButtonById(ratingNode: HtRatingNode, id: string): HtRatingButton {
|
|
101
|
+
const ratingButton = ratingNode.content.buttons.find(
|
|
102
|
+
button => button.id === id
|
|
103
|
+
) as HtRatingButton | undefined
|
|
104
|
+
if (!ratingButton) {
|
|
105
|
+
throw Error(`Rating button with id: '${id}' not found`)
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
return ratingButton
|
|
109
|
+
}
|
|
110
|
+
|
|
83
111
|
getNodeByContentID(contentID: string): HtNodeComponent {
|
|
84
112
|
const content = this.flow.nodes.find(node =>
|
|
85
113
|
'code' in node ? node.code === contentID : false
|
package/src/constants.ts
CHANGED
|
@@ -8,6 +8,10 @@ export const REG_EXP_PATTERN = /^\/(.*)\/([gimyus]*)$/
|
|
|
8
8
|
export const UUID_REGEXP =
|
|
9
9
|
/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i
|
|
10
10
|
|
|
11
|
+
/* ********** PAYLOADS ********** */
|
|
12
|
+
export const AGENT_RATING_PAYLOAD = 'agent-rating'
|
|
13
|
+
|
|
14
|
+
/* ********** FLOW NAMES ********** */
|
|
11
15
|
export const MAIN_FLOW_NAME = 'Main'
|
|
12
16
|
export const KNOWLEDGE_BASE_FLOW_NAME = 'Knowledge base'
|
|
13
17
|
export const AI_AGENTS_FLOW_NAME = 'AI Agents'
|
|
@@ -1,6 +1,9 @@
|
|
|
1
|
-
import { Text } from '@botonic/react'
|
|
1
|
+
import { Button, Carousel, Text } from '@botonic/react'
|
|
2
2
|
|
|
3
|
+
import { SOURCE_INFO_SEPARATOR } from '../constants'
|
|
4
|
+
import { AgenticOutputMessage } from '../types'
|
|
3
5
|
import { ContentFieldsBase } from './content-fields-base'
|
|
6
|
+
import { FlowElement } from './flow-element'
|
|
4
7
|
import { HtAiAgentNode } from './hubtype-fields/ai-agent'
|
|
5
8
|
|
|
6
9
|
export class FlowAiAgent extends ContentFieldsBase {
|
|
@@ -8,7 +11,8 @@ export class FlowAiAgent extends ContentFieldsBase {
|
|
|
8
11
|
public name: string = ''
|
|
9
12
|
public instructions: string = ''
|
|
10
13
|
public activeTools?: { name: string }[]
|
|
11
|
-
|
|
14
|
+
|
|
15
|
+
public responses: AgenticOutputMessage[] = []
|
|
12
16
|
|
|
13
17
|
static fromHubtypeCMS(component: HtAiAgentNode): FlowAiAgent {
|
|
14
18
|
const newAiAgent = new FlowAiAgent(component.id)
|
|
@@ -20,6 +24,42 @@ export class FlowAiAgent extends ContentFieldsBase {
|
|
|
20
24
|
}
|
|
21
25
|
|
|
22
26
|
toBotonic(id: string): JSX.Element {
|
|
23
|
-
return
|
|
27
|
+
return (
|
|
28
|
+
<>
|
|
29
|
+
{this.responses.map(response => {
|
|
30
|
+
if (response.type === 'text') {
|
|
31
|
+
return <Text key={id}>{response.content.text}</Text>
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
if (response.type === 'textWithButtons') {
|
|
35
|
+
return (
|
|
36
|
+
<Text key={id}>
|
|
37
|
+
{response.content.text}
|
|
38
|
+
{response.content.buttons.map((button, buttonIndex) => (
|
|
39
|
+
<Button
|
|
40
|
+
key={buttonIndex}
|
|
41
|
+
payload={`do-nothing${SOURCE_INFO_SEPARATOR}${buttonIndex}`}
|
|
42
|
+
>
|
|
43
|
+
{button}
|
|
44
|
+
</Button>
|
|
45
|
+
))}
|
|
46
|
+
</Text>
|
|
47
|
+
)
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
if (response.type === 'carousel') {
|
|
51
|
+
return (
|
|
52
|
+
<Carousel key={id}>
|
|
53
|
+
{response.content.elements.map(element =>
|
|
54
|
+
FlowElement.fromAIAgent(id, element).toBotonic(id)
|
|
55
|
+
)}
|
|
56
|
+
</Carousel>
|
|
57
|
+
)
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
return <></>
|
|
61
|
+
})}
|
|
62
|
+
</>
|
|
63
|
+
)
|
|
24
64
|
}
|
|
25
65
|
}
|
|
@@ -5,6 +5,7 @@ import { FlowBuilderApi } from '../api'
|
|
|
5
5
|
import { SOURCE_INFO_SEPARATOR } from '../constants'
|
|
6
6
|
import { ContentFieldsBase } from './content-fields-base'
|
|
7
7
|
import { HtButton, HtButtonStyle, HtUrlNode } from './hubtype-fields'
|
|
8
|
+
import { HtRatingButton } from './hubtype-fields/rating'
|
|
8
9
|
|
|
9
10
|
export class FlowButton extends ContentFieldsBase {
|
|
10
11
|
public text = ''
|
|
@@ -34,6 +35,27 @@ export class FlowButton extends ContentFieldsBase {
|
|
|
34
35
|
return newButton
|
|
35
36
|
}
|
|
36
37
|
|
|
38
|
+
static fromAIAgent(button: {
|
|
39
|
+
id: string
|
|
40
|
+
text: string
|
|
41
|
+
payload?: string
|
|
42
|
+
url?: string
|
|
43
|
+
}): FlowButton {
|
|
44
|
+
const newButton = new FlowButton(button.id)
|
|
45
|
+
newButton.text = button.text
|
|
46
|
+
newButton.payload = button.payload
|
|
47
|
+
newButton.url = button.url
|
|
48
|
+
return newButton
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
static fromRating(button: HtRatingButton): FlowButton {
|
|
52
|
+
const newButton = new FlowButton(button.id)
|
|
53
|
+
newButton.text = button.text
|
|
54
|
+
newButton.payload = button.payload
|
|
55
|
+
newButton.target = button.target?.id
|
|
56
|
+
return newButton
|
|
57
|
+
}
|
|
58
|
+
|
|
37
59
|
static getUrlId(cmsButton: HtButton, locale: string): string | undefined {
|
|
38
60
|
return cmsButton.url.find(url => url.locale === locale)?.id
|
|
39
61
|
}
|
|
@@ -30,6 +30,27 @@ export class FlowElement extends ContentFieldsBase {
|
|
|
30
30
|
return newElement
|
|
31
31
|
}
|
|
32
32
|
|
|
33
|
+
static fromAIAgent(
|
|
34
|
+
id: string,
|
|
35
|
+
element: {
|
|
36
|
+
title: string
|
|
37
|
+
subtitle: string
|
|
38
|
+
image: string
|
|
39
|
+
button: { text: string; url: string }
|
|
40
|
+
}
|
|
41
|
+
) {
|
|
42
|
+
const newElement = new FlowElement(id)
|
|
43
|
+
newElement.title = element.title
|
|
44
|
+
newElement.subtitle = element.subtitle
|
|
45
|
+
newElement.image = element.image
|
|
46
|
+
newElement.button = FlowButton.fromAIAgent({
|
|
47
|
+
id: '',
|
|
48
|
+
text: element.button.text,
|
|
49
|
+
url: element.button.url,
|
|
50
|
+
})
|
|
51
|
+
return newElement
|
|
52
|
+
}
|
|
53
|
+
|
|
33
54
|
toBotonic(parentId: string): JSX.Element {
|
|
34
55
|
return (
|
|
35
56
|
<Element key={`${parentId}-${this.id}`}>
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import { isDev, isWebchat, isWhatsapp } from '@botonic/core'
|
|
2
|
+
import {
|
|
3
|
+
ActionRequest,
|
|
4
|
+
CustomRatingMessage,
|
|
5
|
+
Text,
|
|
6
|
+
WhatsappButtonList,
|
|
7
|
+
} from '@botonic/react'
|
|
8
|
+
|
|
9
|
+
import { getFlowBuilderPlugin } from '../helpers'
|
|
10
|
+
import { ContentFieldsBase } from './content-fields-base'
|
|
11
|
+
import { FlowButton } from './flow-button'
|
|
12
|
+
import { HtRatingNode, RatingType } from './hubtype-fields'
|
|
13
|
+
|
|
14
|
+
export class FlowRating extends ContentFieldsBase {
|
|
15
|
+
public code = ''
|
|
16
|
+
public text = ''
|
|
17
|
+
public sendButtonText = ''
|
|
18
|
+
public ratingType = RatingType.Stars
|
|
19
|
+
public buttons: FlowButton[] = []
|
|
20
|
+
public openListButtonText = ''
|
|
21
|
+
|
|
22
|
+
static fromHubtypeCMS(cmsText: HtRatingNode, locale: string): FlowRating {
|
|
23
|
+
const newRating = new FlowRating(cmsText.id)
|
|
24
|
+
newRating.code = cmsText.code
|
|
25
|
+
newRating.text = this.getTextByLocale(locale, cmsText.content.text)
|
|
26
|
+
newRating.sendButtonText = this.getTextByLocale(
|
|
27
|
+
locale,
|
|
28
|
+
cmsText.content.send_button_text
|
|
29
|
+
)
|
|
30
|
+
newRating.ratingType = cmsText.content.rating_type
|
|
31
|
+
newRating.buttons = cmsText.content.buttons.map(button =>
|
|
32
|
+
FlowButton.fromRating(button)
|
|
33
|
+
)
|
|
34
|
+
newRating.openListButtonText = this.getTextByLocale(
|
|
35
|
+
locale,
|
|
36
|
+
cmsText.content.open_list_button_text
|
|
37
|
+
)
|
|
38
|
+
|
|
39
|
+
return newRating
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
toBotonic(id: string, request: ActionRequest): JSX.Element {
|
|
43
|
+
const flowBuilderPlugin = getFlowBuilderPlugin(request.plugins)
|
|
44
|
+
const customRatingMessageEnabled =
|
|
45
|
+
flowBuilderPlugin.customRatingMessageEnabled
|
|
46
|
+
|
|
47
|
+
if (isWhatsapp(request.session)) {
|
|
48
|
+
return (
|
|
49
|
+
<WhatsappButtonList
|
|
50
|
+
body={this.text}
|
|
51
|
+
button={this.openListButtonText}
|
|
52
|
+
sections={[
|
|
53
|
+
{
|
|
54
|
+
rows: this.buttons.map(button => ({
|
|
55
|
+
id: button.payload as string,
|
|
56
|
+
title: button.text,
|
|
57
|
+
})),
|
|
58
|
+
},
|
|
59
|
+
]}
|
|
60
|
+
/>
|
|
61
|
+
)
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
if (
|
|
65
|
+
(isWebchat(request.session) || isDev(request.session)) &&
|
|
66
|
+
customRatingMessageEnabled
|
|
67
|
+
) {
|
|
68
|
+
const payloads = this.buttons
|
|
69
|
+
.map(button => button.payload)
|
|
70
|
+
.slice()
|
|
71
|
+
.reverse()
|
|
72
|
+
|
|
73
|
+
return (
|
|
74
|
+
<CustomRatingMessage
|
|
75
|
+
payloads={payloads}
|
|
76
|
+
messageText={this.text}
|
|
77
|
+
buttonText={this.sendButtonText}
|
|
78
|
+
ratingType={this.ratingType}
|
|
79
|
+
/>
|
|
80
|
+
)
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
return (
|
|
84
|
+
<Text key={id}>
|
|
85
|
+
{this.text}
|
|
86
|
+
{this.buttons.map((button, buttonIndex) =>
|
|
87
|
+
button.renderButton(buttonIndex)
|
|
88
|
+
)}
|
|
89
|
+
</Text>
|
|
90
|
+
)
|
|
91
|
+
}
|
|
92
|
+
}
|
|
@@ -9,6 +9,7 @@ import { HtImageNode } from './image'
|
|
|
9
9
|
import { HtKeywordNode } from './keyword'
|
|
10
10
|
import { HtKnowledgeBaseNode } from './knowledge-base'
|
|
11
11
|
import { HtPayloadNode } from './payload'
|
|
12
|
+
import { HtRatingNode } from './rating'
|
|
12
13
|
import { HtSmartIntentNode } from './smart-intent'
|
|
13
14
|
import { HtTextNode } from './text'
|
|
14
15
|
import { HtUrlNode } from './url'
|
|
@@ -31,6 +32,7 @@ export type HtNodeWithContent =
|
|
|
31
32
|
| HtKnowledgeBaseNode
|
|
32
33
|
| HtBotActionNode
|
|
33
34
|
| HtAiAgentNode
|
|
35
|
+
| HtRatingNode
|
|
34
36
|
|
|
35
37
|
export type HtNodeWithoutContent = HtUrlNode | HtPayloadNode | HtGoToFlow
|
|
36
38
|
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { HtBaseNode, HtNodeLink, HtTextLocale } from './common'
|
|
2
|
+
import { HtNodeWithContentType } from './node-types'
|
|
3
|
+
|
|
4
|
+
export enum RatingType {
|
|
5
|
+
Stars = 'stars',
|
|
6
|
+
Smileys = 'smileys',
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export interface HtRatingButton {
|
|
10
|
+
id: string
|
|
11
|
+
text: string
|
|
12
|
+
payload: string
|
|
13
|
+
value: number
|
|
14
|
+
target?: HtNodeLink
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export interface HtRatingNode extends HtBaseNode {
|
|
18
|
+
type: HtNodeWithContentType.RATING
|
|
19
|
+
content: {
|
|
20
|
+
text: HtTextLocale[]
|
|
21
|
+
buttons: HtRatingButton[]
|
|
22
|
+
rating_type: RatingType
|
|
23
|
+
send_button_text: HtTextLocale[]
|
|
24
|
+
open_list_button_text: HtTextLocale[]
|
|
25
|
+
}
|
|
26
|
+
}
|
|
@@ -7,10 +7,12 @@ import {
|
|
|
7
7
|
DISABLED_MEMORY_LENGTH,
|
|
8
8
|
FlowKnowledgeBase,
|
|
9
9
|
} from './flow-knowledge-base'
|
|
10
|
+
import { FlowRating } from './flow-rating'
|
|
10
11
|
import { FlowText } from './flow-text'
|
|
11
12
|
import { FlowVideo } from './flow-video'
|
|
12
13
|
import { FlowWhatsappCtaUrlButtonNode } from './flow-whatsapp-cta-url-button'
|
|
13
14
|
import { FlowWhatsappButtonList } from './whatsapp-button-list/flow-whatsapp-button-list'
|
|
15
|
+
|
|
14
16
|
export { ContentFieldsBase } from './content-fields-base'
|
|
15
17
|
export { FlowButton } from './flow-button'
|
|
16
18
|
export { FlowElement } from './flow-element'
|
|
@@ -21,6 +23,7 @@ export {
|
|
|
21
23
|
FlowHandoff,
|
|
22
24
|
FlowImage,
|
|
23
25
|
FlowKnowledgeBase,
|
|
26
|
+
FlowRating,
|
|
24
27
|
FlowText,
|
|
25
28
|
FlowVideo,
|
|
26
29
|
FlowWhatsappButtonList,
|
|
@@ -38,5 +41,6 @@ export type FlowContent =
|
|
|
38
41
|
| FlowKnowledgeBase
|
|
39
42
|
| FlowBotAction
|
|
40
43
|
| FlowAiAgent
|
|
44
|
+
| FlowRating
|
|
41
45
|
|
|
42
46
|
export { DISABLED_MEMORY_LENGTH }
|
|
@@ -4,8 +4,8 @@ import {
|
|
|
4
4
|
} from '@botonic/react'
|
|
5
5
|
|
|
6
6
|
import { FlowBuilderApi } from '../../api'
|
|
7
|
+
import { ContentFieldsBase } from '../content-fields-base'
|
|
7
8
|
import { HtWhatsappButtonListSection } from '../hubtype-fields'
|
|
8
|
-
import { ContentFieldsBase } from './../content-fields-base'
|
|
9
9
|
import { FlowWhatsappButtonListRow } from './flow-whatsapp-button-list-row'
|
|
10
10
|
|
|
11
11
|
export class FlowWhatsappButtonListSection extends ContentFieldsBase {
|
|
@@ -2,8 +2,8 @@ import { WhatsappButtonList } from '@botonic/react'
|
|
|
2
2
|
import React from 'react'
|
|
3
3
|
|
|
4
4
|
import { FlowBuilderApi } from '../../api'
|
|
5
|
+
import { ContentFieldsBase } from '../content-fields-base'
|
|
5
6
|
import { HtWhatsappButtonListNode } from '../hubtype-fields'
|
|
6
|
-
import { ContentFieldsBase } from './../content-fields-base'
|
|
7
7
|
import { FlowWhatsappButtonListSection } from './flow-whatsapp-button-list-section'
|
|
8
8
|
|
|
9
9
|
export class FlowWhatsappButtonList extends ContentFieldsBase {
|
package/src/index.ts
CHANGED
|
@@ -21,6 +21,7 @@ import {
|
|
|
21
21
|
FlowHandoff,
|
|
22
22
|
FlowImage,
|
|
23
23
|
FlowKnowledgeBase,
|
|
24
|
+
FlowRating,
|
|
24
25
|
FlowText,
|
|
25
26
|
FlowVideo,
|
|
26
27
|
FlowWhatsappButtonList,
|
|
@@ -69,6 +70,7 @@ export default class BotonicPluginFlowBuilder implements Plugin {
|
|
|
69
70
|
// TODO: Rethink how we construct FlowBuilderApi to be simpler
|
|
70
71
|
public jsonVersion: FlowBuilderJSONVersion
|
|
71
72
|
public apiUrl: string
|
|
73
|
+
public customRatingMessageEnabled: boolean
|
|
72
74
|
|
|
73
75
|
constructor(options: BotonicPluginFlowBuilderOptions<ResolvedPlugins, any>) {
|
|
74
76
|
this.apiUrl = options.apiUrl || FLOW_BUILDER_API_URL_PROD
|
|
@@ -90,6 +92,8 @@ export default class BotonicPluginFlowBuilder implements Plugin {
|
|
|
90
92
|
allowKnowledgeBases: options.inShadowing?.allowKnowledgeBases || false,
|
|
91
93
|
}
|
|
92
94
|
this.contentFilters = options.contentFilters || []
|
|
95
|
+
this.customRatingMessageEnabled =
|
|
96
|
+
options.customRatingMessageEnabled || false
|
|
93
97
|
}
|
|
94
98
|
|
|
95
99
|
resolveFlowUrl(request: PluginPreRequest): string {
|
|
@@ -240,6 +244,9 @@ export default class BotonicPluginFlowBuilder implements Plugin {
|
|
|
240
244
|
case HtNodeWithContentType.AI_AGENT:
|
|
241
245
|
return FlowAiAgent.fromHubtypeCMS(hubtypeContent)
|
|
242
246
|
|
|
247
|
+
case HtNodeWithContentType.RATING:
|
|
248
|
+
return FlowRating.fromHubtypeCMS(hubtypeContent, locale)
|
|
249
|
+
|
|
243
250
|
case HtNodeWithContentType.BOT_ACTION:
|
|
244
251
|
return FlowBotAction.fromHubtypeCMS(hubtypeContent, locale, this.cmsApi)
|
|
245
252
|
|
package/src/tracking.ts
CHANGED
package/src/types.ts
CHANGED
|
@@ -24,6 +24,7 @@ export interface BotonicPluginFlowBuilderOptions<
|
|
|
24
24
|
smartIntentsConfig?: { numSmartIntentsToUse: number }
|
|
25
25
|
inShadowing?: Partial<InShadowingConfig>
|
|
26
26
|
contentFilters?: ContentFilter<TPlugins, TExtraData>[]
|
|
27
|
+
customRatingMessageEnabled?: boolean
|
|
27
28
|
}
|
|
28
29
|
|
|
29
30
|
export type TrackEventFunction<
|
|
@@ -52,7 +53,7 @@ export type AiAgentFunction<
|
|
|
52
53
|
> = (
|
|
53
54
|
request: BotContext<TPlugins, TExtraData>,
|
|
54
55
|
aiAgentArgs: AiAgentArgs
|
|
55
|
-
) => Promise<
|
|
56
|
+
) => Promise<AgenticOutputMessage[] | undefined>
|
|
56
57
|
|
|
57
58
|
export interface AiAgentArgs {
|
|
58
59
|
name: string
|
|
@@ -93,13 +94,6 @@ export interface KnowledgeBaseResponse {
|
|
|
93
94
|
answer: string
|
|
94
95
|
}
|
|
95
96
|
|
|
96
|
-
export interface AiAgentResponse {
|
|
97
|
-
role: string
|
|
98
|
-
content?: string
|
|
99
|
-
toolName?: string
|
|
100
|
-
toolOutput?: string | null
|
|
101
|
-
}
|
|
102
|
-
|
|
103
97
|
export interface SmartIntentResponse {
|
|
104
98
|
data: {
|
|
105
99
|
smart_intent_title: string
|
|
@@ -114,3 +108,44 @@ export interface SmartIntentResponse {
|
|
|
114
108
|
export interface PayloadParamsBase {
|
|
115
109
|
followUpContentID?: string
|
|
116
110
|
}
|
|
111
|
+
|
|
112
|
+
export interface OutputBaseMessage {
|
|
113
|
+
type: 'text' | 'textWithButtons' | 'carousel' | 'exit'
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
export interface TextMessage extends OutputBaseMessage {
|
|
117
|
+
type: 'text'
|
|
118
|
+
content: {
|
|
119
|
+
text: string
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
export interface TextWithButtonsMessage extends OutputBaseMessage {
|
|
124
|
+
type: 'textWithButtons'
|
|
125
|
+
content: {
|
|
126
|
+
text: string
|
|
127
|
+
buttons: string[]
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
export interface CarouselMessage extends OutputBaseMessage {
|
|
132
|
+
type: 'carousel'
|
|
133
|
+
content: {
|
|
134
|
+
elements: {
|
|
135
|
+
title: string
|
|
136
|
+
subtitle: string
|
|
137
|
+
image: string
|
|
138
|
+
button: { text: string; url: string }
|
|
139
|
+
}[]
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
export interface ExitMessage extends OutputBaseMessage {
|
|
144
|
+
type: 'exit'
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
export type AgenticOutputMessage =
|
|
148
|
+
| TextMessage
|
|
149
|
+
| TextWithButtonsMessage
|
|
150
|
+
| CarouselMessage
|
|
151
|
+
| ExitMessage
|