@botonic/plugin-flow-builder 0.37.1 → 0.37.2-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 (53) hide show
  1. package/lib/cjs/action/ai-agent.js +9 -4
  2. package/lib/cjs/action/ai-agent.js.map +1 -1
  3. package/lib/cjs/action/fallback.js +6 -2
  4. package/lib/cjs/action/fallback.js.map +1 -1
  5. package/lib/cjs/action/knowledge-bases.js +31 -29
  6. package/lib/cjs/action/knowledge-bases.js.map +1 -1
  7. package/lib/cjs/action/payload.js +2 -2
  8. package/lib/cjs/action/payload.js.map +1 -1
  9. package/lib/cjs/content-fields/flow-ai-agent.d.ts +3 -2
  10. package/lib/cjs/content-fields/flow-ai-agent.js +3 -1
  11. package/lib/cjs/content-fields/flow-ai-agent.js.map +1 -1
  12. package/lib/cjs/content-fields/hubtype-fields/ai-agent.d.ts +6 -0
  13. package/lib/cjs/tracking.d.ts +1 -12
  14. package/lib/cjs/tracking.js +15 -31
  15. package/lib/cjs/tracking.js.map +1 -1
  16. package/lib/cjs/types.d.ts +8 -44
  17. package/lib/cjs/types.js.map +1 -1
  18. package/lib/cjs/user-input/keyword.js +7 -5
  19. package/lib/cjs/user-input/keyword.js.map +1 -1
  20. package/lib/cjs/user-input/smart-intent.js +5 -2
  21. package/lib/cjs/user-input/smart-intent.js.map +1 -1
  22. package/lib/esm/action/ai-agent.js +9 -4
  23. package/lib/esm/action/ai-agent.js.map +1 -1
  24. package/lib/esm/action/fallback.js +8 -4
  25. package/lib/esm/action/fallback.js.map +1 -1
  26. package/lib/esm/action/knowledge-bases.js +33 -31
  27. package/lib/esm/action/knowledge-bases.js.map +1 -1
  28. package/lib/esm/action/payload.js +2 -2
  29. package/lib/esm/action/payload.js.map +1 -1
  30. package/lib/esm/content-fields/flow-ai-agent.d.ts +3 -2
  31. package/lib/esm/content-fields/flow-ai-agent.js +3 -1
  32. package/lib/esm/content-fields/flow-ai-agent.js.map +1 -1
  33. package/lib/esm/content-fields/hubtype-fields/ai-agent.d.ts +6 -0
  34. package/lib/esm/tracking.d.ts +1 -12
  35. package/lib/esm/tracking.js +15 -31
  36. package/lib/esm/tracking.js.map +1 -1
  37. package/lib/esm/types.d.ts +8 -44
  38. package/lib/esm/types.js.map +1 -1
  39. package/lib/esm/user-input/keyword.js +10 -8
  40. package/lib/esm/user-input/keyword.js.map +1 -1
  41. package/lib/esm/user-input/smart-intent.js +8 -5
  42. package/lib/esm/user-input/smart-intent.js.map +1 -1
  43. package/package.json +2 -2
  44. package/src/action/ai-agent.ts +12 -2
  45. package/src/action/fallback.ts +9 -4
  46. package/src/action/knowledge-bases.ts +47 -43
  47. package/src/action/payload.ts +3 -3
  48. package/src/content-fields/flow-ai-agent.tsx +6 -4
  49. package/src/content-fields/hubtype-fields/ai-agent.ts +7 -0
  50. package/src/tracking.ts +14 -35
  51. package/src/types.ts +19 -52
  52. package/src/user-input/keyword.ts +11 -9
  53. package/src/user-input/smart-intent.ts +9 -5
@@ -1,4 +1,11 @@
1
- import { BotContext, ResolvedPlugins } from '@botonic/core'
1
+ import {
2
+ BotContext,
3
+ EventAction,
4
+ EventKnowledgeBase,
5
+ KnowledgebaseFailReason,
6
+ KnowledgeBasesResponse,
7
+ ResolvedPlugins,
8
+ } from '@botonic/core'
2
9
 
3
10
  import {
4
11
  DISABLED_MEMORY_LENGTH,
@@ -6,8 +13,9 @@ import {
6
13
  FlowKnowledgeBase,
7
14
  } from '../content-fields'
8
15
  import { HtNodeWithContent } from '../content-fields/hubtype-fields/nodes'
9
- import { EventAction, KnowledgebaseFailReason, trackEvent } from '../tracking'
10
- import { KnowledgeBaseFunction, KnowledgeBaseResponse } from '../types'
16
+ import { getFlowBuilderPlugin } from '../helpers'
17
+ import { trackEvent } from '../tracking'
18
+ import { KnowledgeBaseFunction } from '../types'
11
19
  import { inputHasTextData, isKnowledgeBasesAllowed } from '../utils'
12
20
  import { FlowBuilderContext } from './index'
13
21
 
@@ -37,9 +45,6 @@ export async function getContentsByKnowledgeBase({
37
45
  }
38
46
 
39
47
  const sourceIds = knowledgeBaseContent.sourcesData.map(source => source.id)
40
- const flowId = cmsApi.getNodeById<HtNodeWithContent>(
41
- knowledgeBaseContent.id
42
- ).flow_id
43
48
 
44
49
  if (
45
50
  flowBuilderPlugin.getKnowledgeBaseResponse &&
@@ -51,8 +56,7 @@ export async function getContentsByKnowledgeBase({
51
56
  flowBuilderPlugin.getKnowledgeBaseResponse,
52
57
  request,
53
58
  contents,
54
- knowledgeBaseContent,
55
- flowId
59
+ knowledgeBaseContent
56
60
  )
57
61
 
58
62
  if (contentsWithKnowledgeResponse) {
@@ -70,8 +74,7 @@ async function getContentsWithKnowledgeResponse<
70
74
  getKnowledgeBaseResponse: KnowledgeBaseFunction<T>,
71
75
  request: BotContext<T>,
72
76
  contents: FlowContent[],
73
- knowledgeBaseContent: FlowKnowledgeBase,
74
- flowId: string
77
+ knowledgeBaseContent: FlowKnowledgeBase
75
78
  ): Promise<FlowContent[] | undefined> {
76
79
  const sourceIds = knowledgeBaseContent.sourcesData.map(source => source.id)
77
80
  const instructions = knowledgeBaseContent.instructions
@@ -87,12 +90,7 @@ async function getContentsWithKnowledgeResponse<
87
90
  messageId,
88
91
  memoryLength
89
92
  )
90
- await trackKnowledgeBase(
91
- knowledgeBaseResponse,
92
- request,
93
- knowledgeBaseContent,
94
- flowId
95
- )
93
+ await trackKnowledgeBase(knowledgeBaseResponse, request, knowledgeBaseContent)
96
94
 
97
95
  if (
98
96
  !knowledgeBaseResponse.hasKnowledge ||
@@ -106,7 +104,7 @@ async function getContentsWithKnowledgeResponse<
106
104
 
107
105
  function updateContentsWithResponse(
108
106
  contents: FlowContent[],
109
- response: KnowledgeBaseResponse
107
+ response: KnowledgeBasesResponse
110
108
  ): FlowContent[] {
111
109
  return contents.map(content => {
112
110
  if (content instanceof FlowKnowledgeBase) {
@@ -119,38 +117,44 @@ function updateContentsWithResponse(
119
117
  }
120
118
 
121
119
  async function trackKnowledgeBase(
122
- response: KnowledgeBaseResponse,
120
+ response: KnowledgeBasesResponse,
123
121
  request: BotContext,
124
- knowledgeBaseContent: FlowKnowledgeBase,
125
- flowId: string
122
+ knowledgeBaseContent: FlowKnowledgeBase
126
123
  ) {
127
- const sourceIds = knowledgeBaseContent.sourcesData.map(source => source.id)
128
- const knowledgebaseInferenceId = response.inferenceId
129
- const knowledgebaseSourcesIds = sourceIds
130
- const knowledgebaseChunksIds = response.chunkIds
131
- const knowledgebaseMessageId = request.input.message_id
132
- const flowThreadId = request.session.flow_thread_id
133
- const flowNodeId = knowledgeBaseContent.id
124
+ const flowBuilderPlugin = getFlowBuilderPlugin(request.plugins)
125
+ const flowId = flowBuilderPlugin.cmsApi.getNodeById<HtNodeWithContent>(
126
+ knowledgeBaseContent.id
127
+ ).flow_id
134
128
 
135
- let knowledgebaseFailReason: KnowledgebaseFailReason | undefined
129
+ const getKnowledgeFailReason = (): KnowledgebaseFailReason | undefined => {
130
+ let knowledgebaseFailReason: KnowledgebaseFailReason | undefined
136
131
 
137
- if (!response.isFaithful) {
138
- knowledgebaseFailReason = KnowledgebaseFailReason.Hallucination
132
+ if (!response.isFaithful) {
133
+ knowledgebaseFailReason = KnowledgebaseFailReason.Hallucination
134
+ }
135
+
136
+ if (!response.hasKnowledge) {
137
+ knowledgebaseFailReason = KnowledgebaseFailReason.NoKnowledge
138
+ }
139
+ return knowledgebaseFailReason
139
140
  }
140
141
 
141
- if (!response.hasKnowledge) {
142
- knowledgebaseFailReason = KnowledgebaseFailReason.NoKnowledge
142
+ const event: EventKnowledgeBase = {
143
+ action: EventAction.Knowledgebase,
144
+ knowledgebaseInferenceId: response.inferenceId,
145
+ knowledgebaseFailReason: getKnowledgeFailReason(),
146
+ knowledgebaseSourcesIds: knowledgeBaseContent.sourcesData.map(
147
+ source => source.id
148
+ ),
149
+ knowledgebaseChunksIds: response.chunkIds,
150
+ knowledgebaseMessageId: request.input.message_id,
151
+ userInput: request.input.data as string,
152
+ flowThreadId: request.session.flow_thread_id as string,
153
+ flowId: flowId,
154
+ flowNodeId: knowledgeBaseContent.id,
143
155
  }
144
156
 
145
- await trackEvent(request, EventAction.Knowledgebase, {
146
- knowledgebaseInferenceId,
147
- knowledgebaseFailReason,
148
- knowledgebaseSourcesIds,
149
- knowledgebaseChunksIds,
150
- knowledgebaseMessageId,
151
- userInput: request.input.data,
152
- flowThreadId,
153
- flowId,
154
- flowNodeId,
155
- })
157
+ const { action, ...eventArgs } = event
158
+
159
+ await trackEvent(request, action, eventArgs)
156
160
  }
@@ -1,10 +1,10 @@
1
- import { storeCaseRating } from '@botonic/core'
1
+ import { EventAction, EventFeedback, storeCaseRating } from '@botonic/core'
2
2
  import { v7 as uuid } from 'uuid'
3
3
 
4
4
  import { AGENT_RATING_PAYLOAD, SEPARATOR } from '../constants'
5
5
  import { FlowContent } from '../content-fields'
6
6
  import { HtNodeWithContent } from '../content-fields/hubtype-fields'
7
- import { EventAction, trackEvent } from '../tracking'
7
+ import { trackEvent } from '../tracking'
8
8
  import { FlowBuilderContext } from './index'
9
9
 
10
10
  export async function getContentsByPayload(
@@ -45,7 +45,7 @@ async function resolveRatingPayload(
45
45
  const possibleValues = ratingNode.content.buttons.map(button => button.value)
46
46
 
47
47
  if (request.session._hubtype_case_id) {
48
- const event = {
48
+ const event: EventFeedback = {
49
49
  action: EventAction.FeedbackCase,
50
50
  feedbackTargetId: request.session._hubtype_case_id,
51
51
  feedbackGroupId: uuid().toString(),
@@ -1,16 +1,17 @@
1
+ import { AgenticOutputMessage } from '@botonic/core'
1
2
  import { Button, Carousel, Text } from '@botonic/react'
2
3
 
3
4
  import { SOURCE_INFO_SEPARATOR } from '../constants'
4
- import { AgenticOutputMessage } from '../types'
5
5
  import { ContentFieldsBase } from './content-fields-base'
6
6
  import { FlowElement } from './flow-element'
7
- import { HtAiAgentNode } from './hubtype-fields/ai-agent'
7
+ import { HtAiAgentNode, HtInputGuardrailRule } from './hubtype-fields/ai-agent'
8
8
 
9
9
  export class FlowAiAgent extends ContentFieldsBase {
10
10
  public code: string = ''
11
11
  public name: string = ''
12
12
  public instructions: string = ''
13
13
  public activeTools?: { name: string }[]
14
+ public inputGuardrailRules: HtInputGuardrailRule[]
14
15
 
15
16
  public responses: AgenticOutputMessage[] = []
16
17
 
@@ -19,14 +20,15 @@ export class FlowAiAgent extends ContentFieldsBase {
19
20
  newAiAgent.name = component.content.name
20
21
  newAiAgent.instructions = component.content.instructions
21
22
  newAiAgent.activeTools = component.content.active_tools
22
-
23
+ newAiAgent.inputGuardrailRules =
24
+ component.content.input_guardrail_rules || []
23
25
  return newAiAgent
24
26
  }
25
27
 
26
28
  toBotonic(id: string): JSX.Element {
27
29
  return (
28
30
  <>
29
- {this.responses.map(response => {
31
+ {this.responses.map((response: AgenticOutputMessage) => {
30
32
  if (response.type === 'text') {
31
33
  return <Text key={id}>{response.content.text}</Text>
32
34
  }
@@ -1,11 +1,18 @@
1
1
  import { HtBaseNode } from './common'
2
2
  import { HtNodeWithContentType } from './node-types'
3
3
 
4
+ export interface HtInputGuardrailRule {
5
+ name: string
6
+ description: string
7
+ is_active: boolean
8
+ }
9
+
4
10
  export interface HtAiAgentNode extends HtBaseNode {
5
11
  type: HtNodeWithContentType.AI_AGENT
6
12
  content: {
7
13
  name: string
8
14
  instructions: string
9
15
  active_tools?: { name: string }[]
16
+ input_guardrail_rules?: HtInputGuardrailRule[]
10
17
  }
11
18
  }
package/src/tracking.ts CHANGED
@@ -1,3 +1,4 @@
1
+ import { EventAction, EventFlow } from '@botonic/core'
1
2
  import { ActionRequest } from '@botonic/react'
2
3
  import { v7 as uuidv7 } from 'uuid'
3
4
 
@@ -8,20 +9,6 @@ import {
8
9
  } from './content-fields/hubtype-fields'
9
10
  import { getFlowBuilderPlugin } from './helpers'
10
11
 
11
- export enum EventAction {
12
- FlowNode = 'flow_node',
13
- Keyword = 'nlu_keyword',
14
- IntentSmart = 'nlu_intent_smart',
15
- Knowledgebase = 'knowledgebase',
16
- Fallback = 'fallback',
17
- FeedbackCase = 'feedback_case',
18
- }
19
-
20
- export enum KnowledgebaseFailReason {
21
- NoKnowledge = 'no_knowledge',
22
- Hallucination = 'hallucination',
23
- }
24
-
25
12
  export async function trackEvent(
26
13
  request: ActionRequest,
27
14
  eventAction: EventAction,
@@ -43,37 +30,29 @@ export async function trackFlowContent(
43
30
  for (const content of contents) {
44
31
  const nodeContent = cmsApi.getNodeById<HtNodeWithContent>(content.id)
45
32
  if (nodeContent.type !== HtNodeWithContentType.KNOWLEDGE_BASE) {
46
- const eventArgs = getContentEventArgs(request, {
47
- code: nodeContent.code,
48
- flowId: nodeContent.flow_id,
49
- flowName: flowBuilderPlugin.getFlowName(nodeContent.flow_id),
50
- id: nodeContent.id,
51
- isMeaningful: nodeContent.is_meaningful ?? false,
52
- })
53
- await trackEvent(request, EventAction.FlowNode, eventArgs)
33
+ const event = getContentEventArgs(request, nodeContent)
34
+ const { action, ...eventArgs } = event
35
+ await trackEvent(request, action, eventArgs)
54
36
  }
55
37
  }
56
38
  }
57
39
 
58
40
  function getContentEventArgs(
59
41
  request: ActionRequest,
60
- contentInfo: {
61
- code: string
62
- flowId: string
63
- flowName: string
64
- id: string
65
- isMeaningful: boolean
66
- }
67
- ) {
42
+ nodeContent: HtNodeWithContent
43
+ ): EventFlow {
44
+ const flowBuilderPlugin = getFlowBuilderPlugin(request.plugins)
45
+ const flowName = flowBuilderPlugin.getFlowName(nodeContent.flow_id)
68
46
  const flowThreadId = request.session.flow_thread_id ?? uuidv7()
69
47
  request.session.flow_thread_id = flowThreadId
70
48
 
71
49
  return {
50
+ action: EventAction.FlowNode,
72
51
  flowThreadId,
73
- flowId: contentInfo.flowId,
74
- flowName: contentInfo.flowName,
75
- flowNodeId: contentInfo.id,
76
- flowNodeContentId: contentInfo.code,
77
- flowNodeIsMeaningful: contentInfo.isMeaningful,
52
+ flowId: nodeContent.flow_id,
53
+ flowName: flowName,
54
+ flowNodeId: nodeContent.id,
55
+ flowNodeContentId: nodeContent.code,
56
+ flowNodeIsMeaningful: nodeContent.is_meaningful ?? false,
78
57
  }
79
58
  }
package/src/types.ts CHANGED
@@ -1,4 +1,14 @@
1
- import { BotContext, PluginPreRequest, ResolvedPlugins } from '@botonic/core'
1
+ import {
2
+ AgenticOutputMessage,
3
+ BotContext,
4
+ CarouselMessage,
5
+ InferenceResponse,
6
+ KnowledgeBasesResponse,
7
+ PluginPreRequest,
8
+ ResolvedPlugins,
9
+ TextMessage,
10
+ TextWithButtonsMessage,
11
+ } from '@botonic/core'
2
12
 
3
13
  import { FlowContent } from './content-fields'
4
14
  import { HtFlowBuilderData } from './content-fields/hubtype-fields'
@@ -45,7 +55,7 @@ export type KnowledgeBaseFunction<
45
55
  instructions: string,
46
56
  messageId: string,
47
57
  memoryLength: number
48
- ) => Promise<KnowledgeBaseResponse>
58
+ ) => Promise<KnowledgeBasesResponse>
49
59
 
50
60
  export type AiAgentFunction<
51
61
  TPlugins extends ResolvedPlugins = ResolvedPlugins,
@@ -53,12 +63,18 @@ export type AiAgentFunction<
53
63
  > = (
54
64
  request: BotContext<TPlugins, TExtraData>,
55
65
  aiAgentArgs: AiAgentArgs
56
- ) => Promise<AgenticOutputMessage[] | undefined>
66
+ ) => Promise<InferenceResponse>
67
+
68
+ export interface GuardrailRule {
69
+ name: string
70
+ description: string
71
+ }
57
72
 
58
73
  export interface AiAgentArgs {
59
74
  name: string
60
75
  instructions: string
61
76
  activeTools?: { name: string }[]
77
+ inputGuardrailRules?: GuardrailRule[]
62
78
  }
63
79
  export type ContentFilter<
64
80
  TPlugins extends ResolvedPlugins = ResolvedPlugins,
@@ -86,14 +102,6 @@ export enum FlowBuilderJSONVersion {
86
102
  LATEST = 'latest',
87
103
  }
88
104
 
89
- export interface KnowledgeBaseResponse {
90
- inferenceId: string
91
- hasKnowledge: boolean
92
- isFaithful: boolean
93
- chunkIds: string[]
94
- answer: string
95
- }
96
-
97
105
  export interface SmartIntentResponse {
98
106
  data: {
99
107
  smart_intent_title: string
@@ -108,44 +116,3 @@ export interface SmartIntentResponse {
108
116
  export interface PayloadParamsBase {
109
117
  followUpContentID?: string
110
118
  }
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
@@ -1,4 +1,4 @@
1
- import { NluType } from '@botonic/core'
1
+ import { EventAction, EventKeyword, NluType } from '@botonic/core'
2
2
  import { ActionRequest } from '@botonic/react'
3
3
 
4
4
  import { FlowBuilderApi } from '../api'
@@ -7,7 +7,7 @@ import {
7
7
  HtKeywordNode,
8
8
  HtNodeWithContent,
9
9
  } from '../content-fields/hubtype-fields'
10
- import { EventAction, trackEvent } from '../tracking'
10
+ import { trackEvent } from '../tracking'
11
11
 
12
12
  interface KeywordProps {
13
13
  cmsApi: FlowBuilderApi
@@ -101,15 +101,17 @@ export class KeywordMatcher {
101
101
  }
102
102
 
103
103
  private async trackKeywordEvent() {
104
- const eventArgs = {
105
- nluKeywordName: this.matchedKeyword,
104
+ const event: EventKeyword = {
105
+ action: EventAction.Keyword,
106
+ flowThreadId: this.request.session.flow_thread_id as string,
107
+ flowNodeId: this.keywordNodeId as string,
108
+ flowId: this.flowId as string,
109
+ nluKeywordName: this.matchedKeyword as string,
106
110
  nluKeywordIsRegex: this.isRegExp,
107
111
  nluKeywordMessageId: this.request.input.message_id,
108
- userInput: this.request.input.data,
109
- flowThreadId: this.request.session.flow_thread_id,
110
- flowId: this.flowId,
111
- flowNodeId: this.keywordNodeId,
112
+ userInput: this.request.input.data as string,
112
113
  }
113
- await trackEvent(this.request, EventAction.Keyword, eventArgs)
114
+ const { action, ...eventArgs } = event
115
+ await trackEvent(this.request, action, eventArgs)
114
116
  }
115
117
  }
@@ -1,11 +1,11 @@
1
- import { NluType } from '@botonic/core'
1
+ import { EventAction, EventIntentSmart, NluType } from '@botonic/core'
2
2
  import { ActionRequest } from '@botonic/react'
3
3
  import axios from 'axios'
4
4
 
5
5
  import { FlowBuilderApi } from '../api'
6
6
  import { HtSmartIntentNode } from '../content-fields/hubtype-fields/smart-intent'
7
7
  import { getFlowBuilderPlugin } from '../helpers'
8
- import { EventAction, trackEvent } from '../tracking'
8
+ import { trackEvent } from '../tracking'
9
9
  import { SmartIntentResponse } from '../types'
10
10
 
11
11
  export interface SmartIntentsInferenceParams {
@@ -55,15 +55,19 @@ export class SmartIntentsApi {
55
55
  payload: targetPayload,
56
56
  }
57
57
 
58
- await trackEvent(this.currentRequest, EventAction.IntentSmart, {
58
+ const event: EventIntentSmart = {
59
+ action: EventAction.IntentSmart,
59
60
  nluIntentSmartTitle: response.data.smart_intent_title,
60
61
  nluIntentSmartNumUsed: response.data.smart_intents_used.length,
61
62
  nluIntentSmartMessageId: this.currentRequest.input.message_id,
62
63
  userInput: this.currentRequest.input.data,
63
- flowThreadId: this.currentRequest.session.flow_thread_id,
64
+ flowThreadId: this.currentRequest.session.flow_thread_id as string,
64
65
  flowId: smartIntentNode.flow_id,
65
66
  flowNodeId: smartIntentNode.id,
66
- })
67
+ }
68
+ const { action, ...eventArgs } = event
69
+
70
+ await trackEvent(this.currentRequest, action, eventArgs)
67
71
 
68
72
  return smartIntentNode
69
73
  }