@botonic/plugin-flow-builder 0.57.0-rslib-esm.1 → 0.58.0-alpha-new-stack.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/action/ai-agent-from-user-input.js +8 -0
- package/lib/action/ai-agent-from-user-input.js.map +1 -1
- package/lib/action/first-interaction.js +10 -0
- package/lib/action/first-interaction.js.map +1 -1
- package/lib/action/get-contents.js +5 -2
- package/lib/action/get-contents.js.map +1 -1
- package/lib/action/index.js +8 -1
- package/lib/action/index.js.map +1 -1
- package/lib/api.d.ts +8 -3
- package/lib/api.js +37 -13
- package/lib/api.js.map +1 -1
- package/lib/bot-context-manager.d.ts +17 -0
- package/lib/bot-context-manager.js +101 -0
- package/lib/bot-context-manager.js.map +1 -0
- package/lib/constants.d.ts +2 -1
- package/lib/constants.js +4 -3
- package/lib/constants.js.map +1 -1
- package/lib/content-fields/contact-reasons-conditional-matcher.d.ts +4 -0
- package/lib/content-fields/contact-reasons-conditional-matcher.js +10 -0
- package/lib/content-fields/contact-reasons-conditional-matcher.js.map +1 -0
- package/lib/content-fields/flow-ai-agent-base.js +7 -1
- package/lib/content-fields/flow-ai-agent-base.js.map +1 -1
- package/lib/content-fields/flow-ai-agent-router.js +2 -1
- package/lib/content-fields/flow-ai-agent-router.js.map +1 -1
- package/lib/content-fields/flow-ai-agent.js +2 -1
- package/lib/content-fields/flow-ai-agent.js.map +1 -1
- package/lib/content-fields/flow-contact-reasons-conditional.d.ts +14 -0
- package/lib/content-fields/flow-contact-reasons-conditional.js +68 -0
- package/lib/content-fields/flow-contact-reasons-conditional.js.map +1 -0
- package/lib/content-fields/flow-do-nothing.d.ts +9 -0
- package/lib/content-fields/flow-do-nothing.js +33 -0
- package/lib/content-fields/flow-do-nothing.js.map +1 -0
- package/lib/content-fields/flow-handoff.d.ts +7 -1
- package/lib/content-fields/flow-handoff.js +41 -3
- package/lib/content-fields/flow-handoff.js.map +1 -1
- package/lib/content-fields/flow-whatsapp-request-contact-info.d.ts +2 -1
- package/lib/content-fields/flow-whatsapp-request-contact-info.js +11 -0
- package/lib/content-fields/flow-whatsapp-request-contact-info.js.map +1 -1
- package/lib/content-fields/hubtype-fields/contact-reasons-conditional.d.ts +16 -0
- package/lib/content-fields/hubtype-fields/contact-reasons-conditional.js +4 -0
- package/lib/content-fields/hubtype-fields/contact-reasons-conditional.js.map +1 -0
- package/lib/content-fields/hubtype-fields/do-nothing.d.ts +6 -0
- package/lib/content-fields/hubtype-fields/do-nothing.js +4 -0
- package/lib/content-fields/hubtype-fields/do-nothing.js.map +1 -0
- package/lib/content-fields/hubtype-fields/handoff.d.ts +11 -1
- package/lib/content-fields/hubtype-fields/handoff.js +7 -1
- package/lib/content-fields/hubtype-fields/handoff.js.map +1 -1
- package/lib/content-fields/hubtype-fields/index.d.ts +1 -0
- package/lib/content-fields/hubtype-fields/index.js +2 -0
- package/lib/content-fields/hubtype-fields/index.js.map +1 -1
- package/lib/content-fields/hubtype-fields/node-types.d.ts +3 -1
- package/lib/content-fields/hubtype-fields/node-types.js +2 -0
- package/lib/content-fields/hubtype-fields/node-types.js.map +1 -1
- package/lib/content-fields/hubtype-fields/nodes.d.ts +3 -1
- package/lib/content-fields/hubtype-fields/nodes.js.map +1 -1
- package/lib/content-fields/hubtype-fields/whatsapp-request-contact-info.d.ts +2 -0
- package/lib/content-fields/hubtype-fields/whatsapp-request-contact-info.js.map +1 -1
- package/lib/content-fields/index.d.ts +4 -2
- package/lib/content-fields/index.js +6 -0
- package/lib/content-fields/index.js.map +1 -1
- package/lib/flow-factory.js +5 -1
- package/lib/flow-factory.js.map +1 -1
- package/lib/index.d.ts +5 -8
- package/lib/index.js +17 -55
- package/lib/index.js.map +1 -1
- package/lib/types.d.ts +2 -2
- package/lib/types.js.map +1 -1
- package/lib/utils/hubtype-assistant-content.d.ts +1 -0
- package/lib/utils/hubtype-assistant-content.js +13 -0
- package/lib/utils/hubtype-assistant-content.js.map +1 -1
- package/package.json +4 -4
- package/src/action/ai-agent-from-user-input.ts +7 -0
- package/src/action/first-interaction.ts +6 -0
- package/src/action/get-contents.ts +17 -2
- package/src/action/index.tsx +7 -0
- package/src/api.ts +52 -15
- package/src/bot-context-manager.ts +153 -0
- package/src/constants.ts +2 -1
- package/src/content-fields/contact-reasons-conditional-matcher.ts +24 -0
- package/src/content-fields/flow-ai-agent-base.tsx +12 -1
- package/src/content-fields/flow-ai-agent-router.tsx +1 -0
- package/src/content-fields/flow-ai-agent.tsx +1 -0
- package/src/content-fields/flow-contact-reasons-conditional.tsx +90 -0
- package/src/content-fields/flow-do-nothing.tsx +29 -0
- package/src/content-fields/flow-handoff.tsx +54 -7
- package/src/content-fields/flow-whatsapp-request-contact-info.tsx +19 -1
- package/src/content-fields/hubtype-fields/contact-reasons-conditional.ts +18 -0
- package/src/content-fields/hubtype-fields/do-nothing.ts +7 -0
- package/src/content-fields/hubtype-fields/handoff.ts +17 -1
- package/src/content-fields/hubtype-fields/index.ts +1 -0
- package/src/content-fields/hubtype-fields/node-types.ts +2 -0
- package/src/content-fields/hubtype-fields/nodes.ts +4 -0
- package/src/content-fields/hubtype-fields/whatsapp-request-contact-info.ts +2 -0
- package/src/content-fields/index.ts +6 -0
- package/src/flow-factory.ts +11 -0
- package/src/index.ts +26 -88
- package/src/types.ts +1 -2
- package/src/utils/hubtype-assistant-content.ts +14 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils/hubtype-assistant-content.js","sources":["../../src/utils/hubtype-assistant-content.ts"],"sourcesContent":["import { WhatsappCTAUrlHeaderType } from '@botonic/react'\nimport type { FlowContent } from '../content-fields'\nimport type { FlowButton } from '../content-fields/flow-button'\nimport { FlowCarousel } from '../content-fields/flow-carousel'\nimport { FlowImage } from '../content-fields/flow-image'\nimport { FlowText } from '../content-fields/flow-text'\nimport { FlowVideo } from '../content-fields/flow-video'\nimport { FlowWhatsappCtaUrlButtonNode } from '../content-fields/flow-whatsapp-cta-url-button'\nimport { FlowWhatsappTemplate } from '../content-fields/flow-whatsapp-template'\nimport { HtButtonStyle } from '../content-fields/hubtype-fields'\nimport { FlowWhatsappButtonList } from '../content-fields/whatsapp-button-list/flow-whatsapp-button-list'\n\n// biome-ignore lint/complexity/noStaticOnlyClass: namespace-like adapter with private static helpers\nexport class HubtypeAssistantContent {\n static adapt(content: FlowContent): string {\n if (content instanceof FlowText) {\n return HubtypeAssistantContent.formatFlowTextContent(content)\n }\n if (content instanceof FlowCarousel) {\n return HubtypeAssistantContent.formatCarouselContent(content)\n }\n if (content instanceof FlowImage) {\n return content.src ? `[Image]\\n${content.src}` : '[Image]'\n }\n if (content instanceof FlowVideo) {\n return content.src ? `[Video]\\n${content.src}` : '[Video]'\n }\n if (content instanceof FlowWhatsappButtonList) {\n return HubtypeAssistantContent.formatWhatsappButtonListContent(content)\n }\n if (content instanceof FlowWhatsappCtaUrlButtonNode) {\n return HubtypeAssistantContent.formatWhatsappCtaContent(content)\n }\n if (content instanceof FlowWhatsappTemplate) {\n return HubtypeAssistantContent.formatWhatsappTemplateContent(content)\n }\n return ''\n }\n\n private static quickReplyLabel(button: FlowButton): string {\n const buttonText = button.text?.trim()\n if (buttonText) {\n return buttonText\n }\n\n return button.payload || 'Option'\n }\n\n private static persistentButtonLabel(button: FlowButton): string {\n return button.text?.trim() || 'Button'\n }\n\n private static carouselButtonLabel(button: FlowButton): string {\n return button.text?.trim() || 'Action'\n }\n\n private static formatFlowTextContent(text: FlowText): string {\n const body = text.text?.trim() ?? ''\n const buttons = text.buttons\n\n if (!body && buttons.length === 0) {\n return ''\n }\n\n if (buttons.length === 0) {\n return text.text\n }\n\n const isQuickReply = text.buttonStyle === HtButtonStyle.QUICK_REPLY\n const blockTitle = isQuickReply ? 'Quick replies:' : 'Buttons:'\n const lines = buttons.map((button, i) => {\n const label = isQuickReply\n ? HubtypeAssistantContent.quickReplyLabel(button)\n : HubtypeAssistantContent.persistentButtonLabel(button)\n return ` [${i + 1}] ${label}`\n })\n\n const block = [blockTitle, ...lines].join('\\n')\n if (!body) {\n return block\n }\n\n return `${body}\\n\\n${block}`\n }\n\n private static formatCarouselContent(carousel: FlowCarousel): string {\n const elements = carousel.elements\n const n = elements.length\n const mainText = (carousel.whatsappText ?? '').trim()\n\n if (n === 0) {\n return mainText\n }\n\n let header: string\n if (!mainText) {\n header = `Carousel displayed with ${n} items:`\n } else if (mainText.endsWith(':')) {\n header = mainText\n } else {\n header = `${mainText}\\nCarousel with ${n} items:`\n }\n\n const itemLines = elements.map((element, index) => {\n const title = element.title?.trim() || 'Item'\n const subtitle = element.subtitle?.trim()\n const subtitlePart = subtitle ? ` - ${subtitle}` : ''\n const btnLabels: string[] = []\n if (element.button) {\n btnLabels.push(\n HubtypeAssistantContent.carouselButtonLabel(element.button)\n )\n }\n const btnPart = btnLabels.length > 0 ? ` [${btnLabels.join(', ')}]` : ''\n\n return ` ${index + 1}. \"${title}\"${subtitlePart}${btnPart}`\n })\n\n return [header, ...itemLines].join('\\n')\n }\n\n private static formatWhatsappButtonListContent(\n list: FlowWhatsappButtonList\n ): string {\n const body = list.text?.trim() ?? ''\n const hasSections = list.sections.some(s => s.rows.length > 0)\n\n if (!body && !hasSections) {\n return '[WhatsApp Button List]'\n }\n\n const parts: string[] = []\n if (body) {\n parts.push(body)\n }\n\n if (hasSections) {\n const sectionBlocks = list.sections.map(section => {\n const rowLines = section.rows.map(row => {\n const rowTitle = row.title?.trim() ?? ''\n const rowDescription = row.description?.trim() ?? ''\n if (!rowTitle && !rowDescription) {\n return ' - '\n }\n if (!rowTitle) {\n return ` - ${rowDescription}`\n }\n if (!rowDescription) {\n return ` - ${rowTitle}`\n }\n return ` - ${rowTitle}: ${rowDescription}`\n })\n const rowsText = rowLines.join('\\n')\n\n const sectionTitle = section.title?.trim()\n if (sectionTitle) {\n return `${sectionTitle}:\\n${rowsText}`\n }\n\n return rowsText\n })\n parts.push(sectionBlocks.join('\\n'))\n }\n\n return parts.join('\\n\\n')\n }\n\n private static formatWhatsappCtaContent(\n cta: FlowWhatsappCtaUrlButtonNode\n ): string {\n const hasStructuredData =\n (cta.headerType === WhatsappCTAUrlHeaderType.Text &&\n !!cta.header?.trim()) ||\n cta.text?.trim() ||\n cta.footer?.trim() ||\n cta.displayText?.trim() ||\n cta.url\n\n if (!hasStructuredData) {\n return cta.text?.trim() || '[WhatsApp CTA Button]'\n }\n\n const lines: string[] = []\n if (\n cta.headerType === WhatsappCTAUrlHeaderType.Text &&\n cta.header?.trim()\n ) {\n lines.push(cta.header.trim())\n }\n if (cta.text?.trim()) {\n lines.push(cta.text.trim())\n }\n if (cta.footer?.trim()) {\n lines.push(cta.footer.trim())\n }\n const ctaLine = `[${cta.displayText || ''}]${cta.url ? ` (${cta.url})` : ''}`\n lines.push(ctaLine)\n\n return lines.join('\\n')\n }\n\n private static formatWhatsappTemplateContent(\n template: FlowWhatsappTemplate\n ): string {\n const { name, language } = template.htWhatsappTemplate\n return `WhatsApp Template: ${name} (${language})`\n }\n}\n"],"names":["WhatsappCTAUrlHeaderType","FlowCarousel","FlowImage","FlowText","FlowVideo","FlowWhatsappCtaUrlButtonNode","FlowWhatsappTemplate","HtButtonStyle","FlowWhatsappButtonList","HubtypeAssistantContent","content","button","buttonText","text","body","buttons","isQuickReply","blockTitle","lines","i","label","block","carousel","elements","n","mainText","header","itemLines","element","index","title","subtitle","subtitlePart","btnLabels","btnPart","list","hasSections","s","parts","sectionBlocks","section","rowLines","row","rowTitle","rowDescription","rowsText","sectionTitle","cta","hasStructuredData","ctaLine","template","name","language"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"utils/hubtype-assistant-content.js","sources":["../../src/utils/hubtype-assistant-content.ts"],"sourcesContent":["import { WhatsappCTAUrlHeaderType } from '@botonic/react'\nimport type { FlowContent } from '../content-fields'\nimport type { FlowButton } from '../content-fields/flow-button'\nimport { FlowCarousel } from '../content-fields/flow-carousel'\nimport { FlowImage } from '../content-fields/flow-image'\nimport { FlowText } from '../content-fields/flow-text'\nimport { FlowVideo } from '../content-fields/flow-video'\nimport { FlowWhatsappCtaUrlButtonNode } from '../content-fields/flow-whatsapp-cta-url-button'\nimport { FlowWhatsappRequestContactInfoNode } from '../content-fields/flow-whatsapp-request-contact-info'\nimport { FlowWhatsappTemplate } from '../content-fields/flow-whatsapp-template'\nimport { HtButtonStyle } from '../content-fields/hubtype-fields'\nimport { FlowWhatsappButtonList } from '../content-fields/whatsapp-button-list/flow-whatsapp-button-list'\n\n// biome-ignore lint/complexity/noStaticOnlyClass: namespace-like adapter with private static helpers\nexport class HubtypeAssistantContent {\n static adapt(content: FlowContent): string {\n if (content instanceof FlowText) {\n return HubtypeAssistantContent.formatFlowTextContent(content)\n }\n if (content instanceof FlowCarousel) {\n return HubtypeAssistantContent.formatCarouselContent(content)\n }\n if (content instanceof FlowImage) {\n return content.src ? `[Image]\\n${content.src}` : '[Image]'\n }\n if (content instanceof FlowVideo) {\n return content.src ? `[Video]\\n${content.src}` : '[Video]'\n }\n if (content instanceof FlowWhatsappButtonList) {\n return HubtypeAssistantContent.formatWhatsappButtonListContent(content)\n }\n if (content instanceof FlowWhatsappCtaUrlButtonNode) {\n return HubtypeAssistantContent.formatWhatsappCtaContent(content)\n }\n if (content instanceof FlowWhatsappTemplate) {\n return HubtypeAssistantContent.formatWhatsappTemplateContent(content)\n }\n if (content instanceof FlowWhatsappRequestContactInfoNode) {\n return HubtypeAssistantContent.formatRequestContactInfoContent(content)\n }\n return ''\n }\n\n private static quickReplyLabel(button: FlowButton): string {\n const buttonText = button.text?.trim()\n if (buttonText) {\n return buttonText\n }\n\n return button.payload || 'Option'\n }\n\n private static persistentButtonLabel(button: FlowButton): string {\n return button.text?.trim() || 'Button'\n }\n\n private static carouselButtonLabel(button: FlowButton): string {\n return button.text?.trim() || 'Action'\n }\n\n private static formatFlowTextContent(text: FlowText): string {\n const body = text.text?.trim() ?? ''\n const buttons = text.buttons\n\n if (!body && buttons.length === 0) {\n return ''\n }\n\n if (buttons.length === 0) {\n return text.text\n }\n\n const isQuickReply = text.buttonStyle === HtButtonStyle.QUICK_REPLY\n const blockTitle = isQuickReply ? 'Quick replies:' : 'Buttons:'\n const lines = buttons.map((button, i) => {\n const label = isQuickReply\n ? HubtypeAssistantContent.quickReplyLabel(button)\n : HubtypeAssistantContent.persistentButtonLabel(button)\n return ` [${i + 1}] ${label}`\n })\n\n const block = [blockTitle, ...lines].join('\\n')\n if (!body) {\n return block\n }\n\n return `${body}\\n\\n${block}`\n }\n\n private static formatCarouselContent(carousel: FlowCarousel): string {\n const elements = carousel.elements\n const n = elements.length\n const mainText = (carousel.whatsappText ?? '').trim()\n\n if (n === 0) {\n return mainText\n }\n\n let header: string\n if (!mainText) {\n header = `Carousel displayed with ${n} items:`\n } else if (mainText.endsWith(':')) {\n header = mainText\n } else {\n header = `${mainText}\\nCarousel with ${n} items:`\n }\n\n const itemLines = elements.map((element, index) => {\n const title = element.title?.trim() || 'Item'\n const subtitle = element.subtitle?.trim()\n const subtitlePart = subtitle ? ` - ${subtitle}` : ''\n const btnLabels: string[] = []\n if (element.button) {\n btnLabels.push(\n HubtypeAssistantContent.carouselButtonLabel(element.button)\n )\n }\n const btnPart = btnLabels.length > 0 ? ` [${btnLabels.join(', ')}]` : ''\n\n return ` ${index + 1}. \"${title}\"${subtitlePart}${btnPart}`\n })\n\n return [header, ...itemLines].join('\\n')\n }\n\n private static formatWhatsappButtonListContent(\n list: FlowWhatsappButtonList\n ): string {\n const body = list.text?.trim() ?? ''\n const hasSections = list.sections.some(s => s.rows.length > 0)\n\n if (!body && !hasSections) {\n return '[WhatsApp Button List]'\n }\n\n const parts: string[] = []\n if (body) {\n parts.push(body)\n }\n\n if (hasSections) {\n const sectionBlocks = list.sections.map(section => {\n const rowLines = section.rows.map(row => {\n const rowTitle = row.title?.trim() ?? ''\n const rowDescription = row.description?.trim() ?? ''\n if (!rowTitle && !rowDescription) {\n return ' - '\n }\n if (!rowTitle) {\n return ` - ${rowDescription}`\n }\n if (!rowDescription) {\n return ` - ${rowTitle}`\n }\n return ` - ${rowTitle}: ${rowDescription}`\n })\n const rowsText = rowLines.join('\\n')\n\n const sectionTitle = section.title?.trim()\n if (sectionTitle) {\n return `${sectionTitle}:\\n${rowsText}`\n }\n\n return rowsText\n })\n parts.push(sectionBlocks.join('\\n'))\n }\n\n return parts.join('\\n\\n')\n }\n\n private static formatWhatsappCtaContent(\n cta: FlowWhatsappCtaUrlButtonNode\n ): string {\n const hasStructuredData =\n (cta.headerType === WhatsappCTAUrlHeaderType.Text &&\n !!cta.header?.trim()) ||\n cta.text?.trim() ||\n cta.footer?.trim() ||\n cta.displayText?.trim() ||\n cta.url\n\n if (!hasStructuredData) {\n return cta.text?.trim() || '[WhatsApp CTA Button]'\n }\n\n const lines: string[] = []\n if (\n cta.headerType === WhatsappCTAUrlHeaderType.Text &&\n cta.header?.trim()\n ) {\n lines.push(cta.header.trim())\n }\n if (cta.text?.trim()) {\n lines.push(cta.text.trim())\n }\n if (cta.footer?.trim()) {\n lines.push(cta.footer.trim())\n }\n const ctaLine = `[${cta.displayText || ''}]${cta.url ? ` (${cta.url})` : ''}`\n lines.push(ctaLine)\n\n return lines.join('\\n')\n }\n\n private static formatWhatsappTemplateContent(\n template: FlowWhatsappTemplate\n ): string {\n const { name, language } = template.htWhatsappTemplate\n return `WhatsApp Template: ${name} (${language})`\n }\n\n private static formatRequestContactInfoContent(\n requestContactInfo: FlowWhatsappRequestContactInfoNode\n ): string {\n const body = requestContactInfo.text?.trim() ?? ''\n if (!body) {\n return '[WhatsApp Request Contact Info]'\n }\n return requestContactInfo.text\n }\n}\n"],"names":["WhatsappCTAUrlHeaderType","FlowCarousel","FlowImage","FlowText","FlowVideo","FlowWhatsappCtaUrlButtonNode","FlowWhatsappRequestContactInfoNode","FlowWhatsappTemplate","HtButtonStyle","FlowWhatsappButtonList","HubtypeAssistantContent","content","button","buttonText","text","body","buttons","isQuickReply","blockTitle","lines","i","label","block","carousel","elements","n","mainText","header","itemLines","element","index","title","subtitle","subtitlePart","btnLabels","btnPart","list","hasSections","s","parts","sectionBlocks","section","rowLines","row","rowTitle","rowDescription","rowsText","sectionTitle","cta","hasStructuredData","ctaLine","template","name","language","requestContactInfo"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"type": "module",
|
|
3
3
|
"name": "@botonic/plugin-flow-builder",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.58.0-alpha-new-stack.0",
|
|
5
5
|
"main": "./lib/index.js",
|
|
6
6
|
"module": "./lib/index.js",
|
|
7
7
|
"description": "Use Flow Builder to show your contents",
|
|
8
8
|
"scripts": {
|
|
9
9
|
"build": "rslib build --no-env",
|
|
10
10
|
"build:watch": "rslib build --watch --no-env",
|
|
11
|
-
"test": "
|
|
11
|
+
"test": "vitest run --coverage",
|
|
12
12
|
"cloc": "../../scripts/qa/cloc-package.sh .",
|
|
13
13
|
"prepublishOnly": "npm run build && npm run test && npm run lint",
|
|
14
14
|
"lint": "biome check --write src/ tests/",
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
"format": "biome format --write src/ tests/"
|
|
17
17
|
},
|
|
18
18
|
"dependencies": {
|
|
19
|
-
"@botonic/react": "0.
|
|
19
|
+
"@botonic/react": "0.58.0-alpha-new-stack.0",
|
|
20
20
|
"axios": "^1.18.1",
|
|
21
21
|
"uuid": "^10.0.0"
|
|
22
22
|
},
|
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
"README.md"
|
|
35
35
|
],
|
|
36
36
|
"engines": {
|
|
37
|
-
"node": ">=22.
|
|
37
|
+
"node": ">=22.23.2",
|
|
38
38
|
"npm": ">=10.0.0"
|
|
39
39
|
},
|
|
40
40
|
"keywords": [
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { NluType } from '@botonic/core'
|
|
1
2
|
import type { FlowContent } from '../content-fields/index'
|
|
2
3
|
import { splitAiAgentContents } from '../utils/ai-agent'
|
|
3
4
|
import type { FlowBuilderContext } from './context'
|
|
@@ -46,5 +47,11 @@ export async function getContentsByAiAgentFromUserInput({
|
|
|
46
47
|
}
|
|
47
48
|
}
|
|
48
49
|
|
|
50
|
+
request.input.nluResolution = {
|
|
51
|
+
type: NluType.AiAgent,
|
|
52
|
+
matchedValue: 'ai-agent-from-user-input',
|
|
53
|
+
payload: undefined,
|
|
54
|
+
}
|
|
55
|
+
|
|
49
56
|
return contents
|
|
50
57
|
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { NluType } from '@botonic/core'
|
|
1
2
|
import type { FlowBuilderApi } from '../api'
|
|
2
3
|
import { MAIN_FLOW_NAME } from '../constants'
|
|
3
4
|
import {
|
|
@@ -51,6 +52,11 @@ export async function getContentsByFirstInteraction(
|
|
|
51
52
|
if (request.input.nluResolution || inputHasTextOrTranscript(request.input)) {
|
|
52
53
|
const contentsByUserInput = await getContentsByUserInput(context)
|
|
53
54
|
|
|
55
|
+
if (request.input.nluResolution?.type === NluType.AiAgent) {
|
|
56
|
+
const startContents = await flowBuilderPlugin.getStartContents()
|
|
57
|
+
return [...startContents, ...contentsByUserInput]
|
|
58
|
+
}
|
|
59
|
+
|
|
54
60
|
return [...firstInteractionContents, ...contentsByUserInput]
|
|
55
61
|
}
|
|
56
62
|
|
|
@@ -1,4 +1,9 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
type BotContext,
|
|
3
|
+
INPUT,
|
|
4
|
+
type Input,
|
|
5
|
+
WhatsappInputOrigin,
|
|
6
|
+
} from '@botonic/core'
|
|
2
7
|
import { EMPTY_PAYLOAD } from '../constants'
|
|
3
8
|
import type { FlowContent } from '../content-fields'
|
|
4
9
|
import { inputHasTextOrTranscript } from '../utils/input'
|
|
@@ -35,7 +40,10 @@ export async function getContents(
|
|
|
35
40
|
return await getContentsByFallback(context)
|
|
36
41
|
}
|
|
37
42
|
|
|
38
|
-
if (
|
|
43
|
+
if (
|
|
44
|
+
inputHasTextOrTranscript(botContext.input) ||
|
|
45
|
+
isContactRequested(botContext.input)
|
|
46
|
+
) {
|
|
39
47
|
const aiAgentContents = await getContentsByAiAgentFromUserInput(context)
|
|
40
48
|
if (aiAgentContents.length > 0) {
|
|
41
49
|
return aiAgentContents
|
|
@@ -44,3 +52,10 @@ export async function getContents(
|
|
|
44
52
|
|
|
45
53
|
return await getContentsByFallback(context)
|
|
46
54
|
}
|
|
55
|
+
|
|
56
|
+
function isContactRequested(input: Input) {
|
|
57
|
+
return (
|
|
58
|
+
input.type === INPUT.CONTACT &&
|
|
59
|
+
input.origin === WhatsappInputOrigin.ContactRequest
|
|
60
|
+
)
|
|
61
|
+
}
|
package/src/action/index.tsx
CHANGED
|
@@ -11,8 +11,10 @@ import {
|
|
|
11
11
|
FlowAiAgent,
|
|
12
12
|
FlowAiAgentRouter,
|
|
13
13
|
type FlowContent,
|
|
14
|
+
FlowWhatsappRequestContactInfoNode,
|
|
14
15
|
} from '../content-fields'
|
|
15
16
|
import { splitAiAgentContents } from '../utils/ai-agent'
|
|
17
|
+
import { getFlowBuilderPlugin } from '../utils/get-flow-builder-plugin'
|
|
16
18
|
import { getFlowBuilderActionContext } from './context'
|
|
17
19
|
import { getContentsByFirstInteraction } from './first-interaction'
|
|
18
20
|
import { getContents } from './get-contents'
|
|
@@ -65,6 +67,11 @@ export class FlowBuilderAction extends React.Component<FlowBuilderActionProps> {
|
|
|
65
67
|
}
|
|
66
68
|
|
|
67
69
|
await content.processContent(botContext)
|
|
70
|
+
|
|
71
|
+
if (content instanceof FlowWhatsappRequestContactInfoNode) {
|
|
72
|
+
const flowBuilderPlugin = getFlowBuilderPlugin(botContext.plugins)
|
|
73
|
+
flowBuilderPlugin.cmsApi.setWhatsappRequestContactId(content.id)
|
|
74
|
+
}
|
|
68
75
|
}
|
|
69
76
|
|
|
70
77
|
return contents
|
package/src/api.ts
CHANGED
|
@@ -1,7 +1,12 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { BotContext } from '@botonic/core'
|
|
2
2
|
import axios from 'axios'
|
|
3
3
|
|
|
4
|
-
import {
|
|
4
|
+
import {
|
|
5
|
+
AI_AGENTS_FLOW_NAME,
|
|
6
|
+
PUSH_FLOW_PAYLOAD,
|
|
7
|
+
SEPARATOR,
|
|
8
|
+
UUID_REGEXP,
|
|
9
|
+
} from './constants'
|
|
5
10
|
import {
|
|
6
11
|
type HtBotActionNode,
|
|
7
12
|
type HtCaptureUserInputNode,
|
|
@@ -18,6 +23,7 @@ import {
|
|
|
18
23
|
type HtRatingButton,
|
|
19
24
|
type HtRatingNode,
|
|
20
25
|
type HtSmartIntentNode,
|
|
26
|
+
type HtWhatsappRequestContactInfoNode,
|
|
21
27
|
} from './content-fields/hubtype-fields'
|
|
22
28
|
import {
|
|
23
29
|
type FlowBuilderApiOptions,
|
|
@@ -30,7 +36,7 @@ export class FlowBuilderApi {
|
|
|
30
36
|
url: string
|
|
31
37
|
flowUrl: string
|
|
32
38
|
flow: HtFlowBuilderData
|
|
33
|
-
|
|
39
|
+
botContext: BotContext
|
|
34
40
|
|
|
35
41
|
private constructor() {}
|
|
36
42
|
|
|
@@ -38,12 +44,12 @@ export class FlowBuilderApi {
|
|
|
38
44
|
const newApi = new FlowBuilderApi()
|
|
39
45
|
|
|
40
46
|
newApi.url = options.url
|
|
41
|
-
newApi.
|
|
47
|
+
newApi.botContext = options.botContext
|
|
42
48
|
// TODO: Refactor later to combine logic from `FlowBuilderApi.create`, `resolveFlowUrl` and `getAccessToken` to be in one place
|
|
43
49
|
if (process.env.NODE_ENV === ProcessEnvNodeEnvs.DEVELOPMENT) {
|
|
44
50
|
await newApi.updateSessionWithUserInfo(options.accessToken)
|
|
45
51
|
}
|
|
46
|
-
const updatedRequest = newApi.
|
|
52
|
+
const updatedRequest = newApi.botContext
|
|
47
53
|
newApi.flowUrl = options.flowUrl.replace(
|
|
48
54
|
'{bot_id}',
|
|
49
55
|
updatedRequest.session.bot.id
|
|
@@ -64,8 +70,8 @@ export class FlowBuilderApi {
|
|
|
64
70
|
const response = await axios.get(url, {
|
|
65
71
|
headers: { Authorization: `Bearer ${token}` },
|
|
66
72
|
})
|
|
67
|
-
this.
|
|
68
|
-
this.
|
|
73
|
+
this.botContext.session.organization_id = response.data.organization_id
|
|
74
|
+
this.botContext.session.bot.id = response.data.bot_id
|
|
69
75
|
}
|
|
70
76
|
|
|
71
77
|
getNodeByFlowId(id: string): HtNodeWithContent {
|
|
@@ -259,23 +265,23 @@ export class FlowBuilderApi {
|
|
|
259
265
|
}
|
|
260
266
|
|
|
261
267
|
getCaptureUserInputId(): string | undefined {
|
|
262
|
-
return this.
|
|
268
|
+
return this.botContext.session.capture_user_input?.node_id
|
|
263
269
|
}
|
|
264
270
|
|
|
265
271
|
setCaptureUserInputId(id: string): void {
|
|
266
|
-
if (this.
|
|
267
|
-
this.
|
|
272
|
+
if (this.botContext.session.capture_user_input) {
|
|
273
|
+
this.botContext.session.capture_user_input.node_id = id
|
|
268
274
|
}
|
|
269
|
-
this.
|
|
275
|
+
this.botContext.session.capture_user_input = { node_id: id }
|
|
270
276
|
}
|
|
271
277
|
|
|
272
278
|
removeCaptureUserInputId(): void {
|
|
273
|
-
this.
|
|
279
|
+
this.botContext.session.capture_user_input = undefined
|
|
274
280
|
}
|
|
275
281
|
|
|
276
282
|
setUserExtraDataVariable(key: string, value: string): void {
|
|
277
|
-
if (this.
|
|
278
|
-
this.
|
|
283
|
+
if (this.botContext.session.user.extra_data) {
|
|
284
|
+
this.botContext.session.user.extra_data[key] = value
|
|
279
285
|
}
|
|
280
286
|
}
|
|
281
287
|
|
|
@@ -287,14 +293,45 @@ export class FlowBuilderApi {
|
|
|
287
293
|
return this.getNodeById<HtCaptureUserInputNode>(captureUserInputId)
|
|
288
294
|
}
|
|
289
295
|
|
|
296
|
+
getSessionWhatsappRequestContactId(): string | undefined {
|
|
297
|
+
return this.botContext.session.whatsapp_request_contact?.id
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
setWhatsappRequestContactId(id: string): void {
|
|
301
|
+
if (this.botContext.session.whatsapp_request_contact) {
|
|
302
|
+
this.botContext.session.whatsapp_request_contact.id = id
|
|
303
|
+
}
|
|
304
|
+
this.botContext.session.whatsapp_request_contact = { id }
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
removeWhatsappRequestContactId(): void {
|
|
308
|
+
this.botContext.session.whatsapp_request_contact = undefined
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
getWhatsappRequestContactInfoNode():
|
|
312
|
+
| HtWhatsappRequestContactInfoNode
|
|
313
|
+
| undefined {
|
|
314
|
+
const whatsappRequestContactId = this.getSessionWhatsappRequestContactId()
|
|
315
|
+
if (!whatsappRequestContactId) {
|
|
316
|
+
return undefined
|
|
317
|
+
}
|
|
318
|
+
return this.getNodeById<HtWhatsappRequestContactInfoNode>(
|
|
319
|
+
whatsappRequestContactId
|
|
320
|
+
)
|
|
321
|
+
}
|
|
322
|
+
|
|
290
323
|
getResolvedLocale(): string {
|
|
291
324
|
const flowLocales = this.flow.locales
|
|
292
325
|
const defaultLocaleCode = this.flow.default_locale_code
|
|
293
326
|
|
|
294
327
|
return new FlowLocale(
|
|
295
|
-
this.
|
|
328
|
+
this.botContext,
|
|
296
329
|
flowLocales,
|
|
297
330
|
defaultLocaleCode
|
|
298
331
|
).resolve()
|
|
299
332
|
}
|
|
333
|
+
|
|
334
|
+
isPushFlowPayload(payload?: string): boolean {
|
|
335
|
+
return payload?.startsWith(PUSH_FLOW_PAYLOAD) ?? false
|
|
336
|
+
}
|
|
300
337
|
}
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
import {
|
|
2
|
+
type BotContext,
|
|
3
|
+
INPUT,
|
|
4
|
+
PROVIDER,
|
|
5
|
+
WhatsappInputOrigin,
|
|
6
|
+
} from '@botonic/core'
|
|
7
|
+
|
|
8
|
+
import type { FlowBuilderApi } from './api'
|
|
9
|
+
import {
|
|
10
|
+
EMPTY_PAYLOAD,
|
|
11
|
+
ON_CLOSE_HANDOFF_PAYLOAD,
|
|
12
|
+
SEPARATOR,
|
|
13
|
+
SOURCE_INFO_SEPARATOR,
|
|
14
|
+
} from './constants'
|
|
15
|
+
import { FlowHandoff } from './content-fields'
|
|
16
|
+
import {
|
|
17
|
+
type HtBotActionNode,
|
|
18
|
+
type HtHandoffNode,
|
|
19
|
+
HtNodeWithContentType,
|
|
20
|
+
} from './content-fields/hubtype-fields'
|
|
21
|
+
import { getNextPayloadByUserInput } from './user-input'
|
|
22
|
+
import type { SmartIntentsInferenceConfig } from './user-input/smart-intent'
|
|
23
|
+
import { inputHasTextOrTranscript } from './utils/input'
|
|
24
|
+
|
|
25
|
+
export class BotContextManager {
|
|
26
|
+
constructor(
|
|
27
|
+
private readonly cmsApi: FlowBuilderApi,
|
|
28
|
+
private readonly smartIntentsConfig: SmartIntentsInferenceConfig
|
|
29
|
+
) {}
|
|
30
|
+
|
|
31
|
+
async prepareInputForRoutes(botContext: BotContext): Promise<void> {
|
|
32
|
+
// When AI Agent is executed in Whatsapp, button payloads come as referral and must be converted to text being processed by the agent.
|
|
33
|
+
this.convertWhatsappAiAgentEmptyPayloads(botContext)
|
|
34
|
+
|
|
35
|
+
// If the payload is a push-flow payload, set first interaction to false
|
|
36
|
+
this.updateFirstInteractionOnPushFlowPayload(botContext)
|
|
37
|
+
|
|
38
|
+
this.resolveWhatsappContactRequestPayload(botContext)
|
|
39
|
+
this.resolveOnCloseHandoffPayload(botContext)
|
|
40
|
+
|
|
41
|
+
await this.resolvePayloadFromUserTextInput(botContext)
|
|
42
|
+
|
|
43
|
+
this.cmsApi.removeCaptureUserInputId()
|
|
44
|
+
this.removePayloadSourceSuffix(botContext)
|
|
45
|
+
this.resolveBotActionPayload(botContext)
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
private async updateFirstInteractionOnPushFlowPayload(
|
|
49
|
+
botContext: BotContext
|
|
50
|
+
): Promise<void> {
|
|
51
|
+
if (this.cmsApi.isPushFlowPayload(botContext.input.payload)) {
|
|
52
|
+
botContext.session.is_first_interaction = false
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
private async resolvePayloadFromUserTextInput(
|
|
57
|
+
botContext: BotContext
|
|
58
|
+
): Promise<void> {
|
|
59
|
+
const checkUserTextInput =
|
|
60
|
+
inputHasTextOrTranscript(botContext.input) && !botContext.input.payload
|
|
61
|
+
|
|
62
|
+
if (!checkUserTextInput) {
|
|
63
|
+
return
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
const resolvedLocale = this.cmsApi.getResolvedLocale()
|
|
67
|
+
const nextPayload = await getNextPayloadByUserInput(
|
|
68
|
+
this.cmsApi,
|
|
69
|
+
resolvedLocale,
|
|
70
|
+
botContext,
|
|
71
|
+
this.smartIntentsConfig
|
|
72
|
+
)
|
|
73
|
+
botContext.input.payload = nextPayload
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
private resolveWhatsappContactRequestPayload(botContext: BotContext): void {
|
|
77
|
+
if (
|
|
78
|
+
botContext.input.type !== INPUT.CONTACT ||
|
|
79
|
+
botContext.input.origin !== WhatsappInputOrigin.ContactRequest
|
|
80
|
+
) {
|
|
81
|
+
return
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
const whatsappRequestContactInfoNode =
|
|
85
|
+
this.cmsApi.getWhatsappRequestContactInfoNode()
|
|
86
|
+
|
|
87
|
+
if (whatsappRequestContactInfoNode) {
|
|
88
|
+
botContext.input.payload = this.cmsApi.getPayload(
|
|
89
|
+
whatsappRequestContactInfoNode.content.button.target
|
|
90
|
+
)
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
this.cmsApi.removeWhatsappRequestContactId()
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
private resolveOnCloseHandoffPayload(botContext: BotContext): void {
|
|
97
|
+
if (botContext.input.payload?.startsWith(ON_CLOSE_HANDOFF_PAYLOAD)) {
|
|
98
|
+
const handoffNodeId = botContext.input.payload.split(SEPARATOR)[1]
|
|
99
|
+
const handoffNode = this.cmsApi.getNodeById<HtHandoffNode>(handoffNodeId)
|
|
100
|
+
if (handoffNode && handoffNode.type === HtNodeWithContentType.HANDOFF) {
|
|
101
|
+
const flowHandoff = FlowHandoff.fromHubtypeCMS(
|
|
102
|
+
handoffNode,
|
|
103
|
+
this.cmsApi.getResolvedLocale(),
|
|
104
|
+
this.cmsApi
|
|
105
|
+
)
|
|
106
|
+
botContext.input.payload = flowHandoff.resolveOnClosePayload(botContext)
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
private convertWhatsappAiAgentEmptyPayloads(botContext: BotContext): void {
|
|
112
|
+
if (botContext.session.user.provider === PROVIDER.WHATSAPP) {
|
|
113
|
+
const shouldUseReferral =
|
|
114
|
+
botContext.input.referral &&
|
|
115
|
+
botContext.input.payload?.startsWith(EMPTY_PAYLOAD)
|
|
116
|
+
|
|
117
|
+
if (shouldUseReferral) {
|
|
118
|
+
botContext.input.type = INPUT.TEXT
|
|
119
|
+
botContext.input.data = botContext.input.referral
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
private removePayloadSourceSuffix(botContext: BotContext): void {
|
|
125
|
+
if (botContext.input.payload) {
|
|
126
|
+
botContext.input.payload = this.removeSourceSuffix(
|
|
127
|
+
botContext.input.payload
|
|
128
|
+
)
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
private resolveBotActionPayload(botContext: BotContext): void {
|
|
133
|
+
if (
|
|
134
|
+
botContext.input.payload &&
|
|
135
|
+
this.cmsApi.isBotAction(botContext.input.payload)
|
|
136
|
+
) {
|
|
137
|
+
const cmsBotAction = this.cmsApi.getNodeById<HtBotActionNode>(
|
|
138
|
+
botContext.input.payload
|
|
139
|
+
)
|
|
140
|
+
|
|
141
|
+
botContext.input.payload =
|
|
142
|
+
this.cmsApi.createPayloadWithParams(cmsBotAction)
|
|
143
|
+
|
|
144
|
+
// Re-execute convertWhatsappAiAgentEmptyPayloads function to handle
|
|
145
|
+
// the case that a BotAction has a payload equals to EMPTY_PAYLOAD
|
|
146
|
+
this.convertWhatsappAiAgentEmptyPayloads(botContext)
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
private removeSourceSuffix(payload: string): string {
|
|
151
|
+
return payload.split(SOURCE_INFO_SEPARATOR)[0]
|
|
152
|
+
}
|
|
153
|
+
}
|
package/src/constants.ts
CHANGED
|
@@ -2,7 +2,6 @@ export const FLOW_BUILDER_API_URL_PROD =
|
|
|
2
2
|
process.env.HUBTYPE_API_URL || 'https://api.hubtype.com'
|
|
3
3
|
export const SEPARATOR = '|'
|
|
4
4
|
export const SOURCE_INFO_SEPARATOR = `${SEPARATOR}source_`
|
|
5
|
-
export const EMPTY_PAYLOAD = 'fb-empty-payload'
|
|
6
5
|
export const VARIABLE_PATTERN_GLOBAL = /{([^{}]+)}/g
|
|
7
6
|
export const ACCESS_TOKEN_VARIABLE_KEY = '_access_token'
|
|
8
7
|
export const REG_EXP_PATTERN = /^\/(.*)\/([gimyus]*)$/
|
|
@@ -10,6 +9,8 @@ export const UUID_REGEXP =
|
|
|
10
9
|
/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i
|
|
11
10
|
|
|
12
11
|
/* ********** PAYLOADS ********** */
|
|
12
|
+
export const EMPTY_PAYLOAD = 'fb-empty-payload'
|
|
13
|
+
export const ON_CLOSE_HANDOFF_PAYLOAD = 'fb-on-close-handoff'
|
|
13
14
|
export const AGENT_RATING_PAYLOAD = 'agent-rating'
|
|
14
15
|
export const PUSH_FLOW_PAYLOAD = 'push-flow'
|
|
15
16
|
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { HubtypeCaseContactReason } from '@botonic/core'
|
|
2
|
+
|
|
3
|
+
import type { HtContactReasonBranch } from './hubtype-fields/contact-reasons-conditional'
|
|
4
|
+
|
|
5
|
+
export function contactReasonMatchesBranch(
|
|
6
|
+
sessionContactReason: HubtypeCaseContactReason,
|
|
7
|
+
branch: HtContactReasonBranch
|
|
8
|
+
): boolean {
|
|
9
|
+
return (
|
|
10
|
+
sessionContactReason.project_id === branch.project_id &&
|
|
11
|
+
sessionContactReason.name === branch.name
|
|
12
|
+
)
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export function findMatchingContactReasonBranch(
|
|
16
|
+
sessionContactReasons: HubtypeCaseContactReason[],
|
|
17
|
+
contactReasonBranches: HtContactReasonBranch[]
|
|
18
|
+
): HtContactReasonBranch | undefined {
|
|
19
|
+
return contactReasonBranches.find(branch =>
|
|
20
|
+
sessionContactReasons.some(sessionContactReason =>
|
|
21
|
+
contactReasonMatchesBranch(sessionContactReason, branch)
|
|
22
|
+
)
|
|
23
|
+
)
|
|
24
|
+
}
|
|
@@ -16,6 +16,7 @@ import { HubtypeAssistantContent } from '../utils/hubtype-assistant-content'
|
|
|
16
16
|
import { ContentFieldsBase } from './content-fields-base'
|
|
17
17
|
import { FlowCarousel } from './flow-carousel'
|
|
18
18
|
import { FlowText } from './flow-text'
|
|
19
|
+
import { FlowWhatsappRequestContactInfoNode } from './flow-whatsapp-request-contact-info'
|
|
19
20
|
import type { HtInputGuardrailRule, HtNodeWithContent } from './hubtype-fields'
|
|
20
21
|
import type { FlowContent } from './index'
|
|
21
22
|
|
|
@@ -89,6 +90,16 @@ export abstract class FlowAiAgentBase extends ContentFieldsBase {
|
|
|
89
90
|
)
|
|
90
91
|
}
|
|
91
92
|
|
|
93
|
+
if (message.type === OutputMessageType.RequestContactInfo) {
|
|
94
|
+
this.jsxElements.push(
|
|
95
|
+
FlowWhatsappRequestContactInfoNode.fromAIAgent(
|
|
96
|
+
this.id,
|
|
97
|
+
message,
|
|
98
|
+
botContext
|
|
99
|
+
)
|
|
100
|
+
)
|
|
101
|
+
}
|
|
102
|
+
|
|
92
103
|
if (message.type === FlowBuilderOutputMessageType.FlowBuilderContent) {
|
|
93
104
|
const flowContents = await this.getFlowContentsByContentId(
|
|
94
105
|
botContext,
|
|
@@ -107,7 +118,7 @@ export abstract class FlowAiAgentBase extends ContentFieldsBase {
|
|
|
107
118
|
botContext: BotContext,
|
|
108
119
|
previousContents?: FlowContent[]
|
|
109
120
|
): Promise<void> {
|
|
110
|
-
if (this.
|
|
121
|
+
if (!this.aiAgentResponse) {
|
|
111
122
|
await this.resolveAIAgentResponse(botContext, previousContents)
|
|
112
123
|
}
|
|
113
124
|
if (this.jsxElements.length === 0) {
|
|
@@ -194,6 +194,7 @@ export class FlowAiAgentRouter extends FlowAiAgentBase {
|
|
|
194
194
|
inputGuardrailsTriggered: [],
|
|
195
195
|
outputGuardrailsTriggered:
|
|
196
196
|
this.aiAgentResponse?.outputGuardrailsTriggered ?? [],
|
|
197
|
+
doNothing: this.aiAgentResponse?.doNothing ?? false,
|
|
197
198
|
}
|
|
198
199
|
const { action, ...specialistEventArgs } = specialistEvent
|
|
199
200
|
await trackEvent(botContext, action, specialistEventArgs)
|
|
@@ -94,6 +94,7 @@ export class FlowAiAgent extends FlowAiAgentBase {
|
|
|
94
94
|
this.aiAgentResponse?.inputGuardrailsTriggered ?? [],
|
|
95
95
|
outputGuardrailsTriggered: [], //aiAgentResponse.outputGuardrailsTriggered,
|
|
96
96
|
error: this.aiAgentResponse?.error ?? false,
|
|
97
|
+
doNothing: this.aiAgentResponse?.doNothing ?? false,
|
|
97
98
|
}
|
|
98
99
|
const { action, ...eventArgs } = event
|
|
99
100
|
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import {
|
|
2
|
+
type BotContext,
|
|
3
|
+
EventAction,
|
|
4
|
+
type EventConditionalContactReasons,
|
|
5
|
+
} from '@botonic/core'
|
|
6
|
+
|
|
7
|
+
import {
|
|
8
|
+
getCommonFlowContentEventArgsForContentId,
|
|
9
|
+
trackEvent,
|
|
10
|
+
} from '../tracking'
|
|
11
|
+
import { findMatchingContactReasonBranch } from './contact-reasons-conditional-matcher'
|
|
12
|
+
import { ContentFieldsBase } from './content-fields-base'
|
|
13
|
+
import type { HtNodeLink } from './hubtype-fields/common'
|
|
14
|
+
import type {
|
|
15
|
+
HtContactReasonBranch,
|
|
16
|
+
HtContactReasonsNode,
|
|
17
|
+
} from './hubtype-fields/contact-reasons-conditional'
|
|
18
|
+
|
|
19
|
+
export class FlowContactReasonsConditional extends ContentFieldsBase {
|
|
20
|
+
public contactReasons: HtContactReasonBranch[] = []
|
|
21
|
+
public conditionalResult: string = ''
|
|
22
|
+
public defaultTarget: HtNodeLink
|
|
23
|
+
|
|
24
|
+
static fromHubtypeCMS(
|
|
25
|
+
component: HtContactReasonsNode,
|
|
26
|
+
botContext: BotContext
|
|
27
|
+
): FlowContactReasonsConditional {
|
|
28
|
+
const newContactReasonsConditional = new FlowContactReasonsConditional(
|
|
29
|
+
component.id
|
|
30
|
+
)
|
|
31
|
+
newContactReasonsConditional.contactReasons =
|
|
32
|
+
component.content.contact_reasons
|
|
33
|
+
newContactReasonsConditional.defaultTarget =
|
|
34
|
+
component.content.default_target
|
|
35
|
+
newContactReasonsConditional.setFollowUp(botContext)
|
|
36
|
+
return newContactReasonsConditional
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
private setFollowUp(botContext: BotContext): void {
|
|
40
|
+
const sessionContactReasons =
|
|
41
|
+
botContext.session._hubtype_case_contact_reasons
|
|
42
|
+
|
|
43
|
+
const matchingBranch = sessionContactReasons
|
|
44
|
+
? findMatchingContactReasonBranch(
|
|
45
|
+
sessionContactReasons,
|
|
46
|
+
this.contactReasons
|
|
47
|
+
)
|
|
48
|
+
: undefined
|
|
49
|
+
|
|
50
|
+
if (matchingBranch) {
|
|
51
|
+
this.conditionalResult = matchingBranch.name
|
|
52
|
+
this.followUp = matchingBranch.target
|
|
53
|
+
} else {
|
|
54
|
+
this.conditionalResult = 'default'
|
|
55
|
+
this.followUp = this.defaultTarget
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
async trackFlow(botContext: BotContext): Promise<void> {
|
|
60
|
+
const { flowThreadId, flowId, flowName, flowNodeId, flowNodeContentId } =
|
|
61
|
+
getCommonFlowContentEventArgsForContentId(botContext, this.id)
|
|
62
|
+
const eventContactReasonsConditional: EventConditionalContactReasons = {
|
|
63
|
+
action: EventAction.ConditionalContactReasons,
|
|
64
|
+
flowThreadId,
|
|
65
|
+
flowId,
|
|
66
|
+
flowName,
|
|
67
|
+
flowNodeId,
|
|
68
|
+
flowNodeContentId,
|
|
69
|
+
flowNodeIsMeaningful: false,
|
|
70
|
+
contactReasons:
|
|
71
|
+
botContext.session._hubtype_case_contact_reasons?.map(
|
|
72
|
+
contactReason => contactReason.name
|
|
73
|
+
) || [],
|
|
74
|
+
result: this.conditionalResult,
|
|
75
|
+
}
|
|
76
|
+
const { action, ...eventArgs } = eventContactReasonsConditional
|
|
77
|
+
await trackEvent(botContext, action, eventArgs)
|
|
78
|
+
return
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
async processContent(botContext: BotContext): Promise<void> {
|
|
82
|
+
await this.filterContent(botContext, this)
|
|
83
|
+
await this.trackFlow(botContext)
|
|
84
|
+
return
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
toBotonic() {
|
|
88
|
+
return <></>
|
|
89
|
+
}
|
|
90
|
+
}
|