11import { Fragment , ReactNode , useEffect , useMemo , useRef , useState } from "react" ;
2- import { VuiButtonSecondary , VuiContextProvider , VuiFlexContainer , VuiFlexItem , VuiSpacer } from "../vui" ;
2+ import {
3+ VuiButtonSecondary ,
4+ VuiContextProvider ,
5+ VuiFlexContainer ,
6+ VuiFlexItem ,
7+ VuiSpacer ,
8+ VuiTopicButton
9+ } from "../vui" ;
310import { QueryInput } from "./QueryInput" ;
411import { ChatItem } from "./ChatItem" ;
512import { useChat } from "../useChat" ;
613import { Loader } from "./Loader" ;
714import { MinimizeIcon } from "./Icons" ;
815import { FactualConsistencyBadge } from "./FactualConsistencyBadge" ;
916import { ExampleQuestions } from "./exampleQuestions/ExampleQuestions" ;
10- import { RerankerId , SummaryLanguage } from "types" ;
17+ import { AgenticConfiguration , ChatActionOption , RerankerId , SummaryLanguage } from "types" ;
1118
1219const inputSizeToQueryInputSize = {
1320 large : "l" ,
@@ -66,6 +73,13 @@ export interface Props {
6673
6774 // Enables streaming responses from the API. Defaults to true.
6875 enableStreaming ?: boolean ;
76+
77+ // Enables the chatbot to modify its behavior by sending requests to an agentic service.
78+ agenticConfiguration ?: AgenticConfiguration ;
79+
80+ // A string that allows the Vectara platform to track where chat requests are coming from.
81+ // This could be an application name, for example.
82+ requestSource ?: string ;
6983}
7084
7185/**
@@ -91,6 +105,8 @@ export const ChatView = ({
91105 rerankerId,
92106 lambda,
93107 enableStreaming = true ,
108+ agenticConfiguration,
109+ requestSource
94110} : Props ) => {
95111 const [ isOpen , setIsOpen ] = useState < boolean > ( isInitiallyOpen ?? false ) ;
96112 const [ query , setQuery ] = useState < string > ( "" ) ;
@@ -105,7 +121,9 @@ export const ChatView = ({
105121 summaryPromptName,
106122 rerankerId,
107123 lambda,
108- enableStreaming
124+ enableStreaming,
125+ agenticConfiguration,
126+ requestSource
109127 } ) ;
110128
111129 const appLayoutRef = useRef < HTMLDivElement > ( null ) ;
@@ -150,38 +168,66 @@ export const ChatView = ({
150168
151169 const historyItems = useMemo (
152170 ( ) =>
153- messageHistory . map ( ( turn , index ) => {
154- const { question, answer, results, factualConsistencyScore } = turn ;
155- const onRetry =
156- hasError && index === messageHistory . length - 1
157- ? ( ) => sendMessage ( { query : question , isRetry : true } )
158- : undefined ;
159-
160- return (
161- < Fragment key = { index } >
162- < ChatItem
163- question = { question }
164- answer = { answer }
165- searchResults = { results }
166- factualConsistencyScore = {
167- enableFactualConsistencyScore && < FactualConsistencyBadge score = { factualConsistencyScore } />
168- }
169- onRetry = { onRetry }
170- />
171- { index < messageHistory . length - 1 && < VuiSpacer size = "m" /> }
172- </ Fragment >
173- ) ;
171+ messageHistory . map ( ( messageHistoryItem , index ) => {
172+ if ( messageHistoryItem . type === "action" ) {
173+ const { options } = messageHistoryItem ;
174+
175+ return (
176+ < Fragment key = { index } >
177+ < div className = "vrcbChatMessageContainer vrcbChatMessageContainer--actionResponse" >
178+ < VuiFlexContainer spacing = "m" >
179+ { options ?. map ( ( option : ChatActionOption , optionIndex : number ) => (
180+ < VuiTopicButton
181+ key = { `messageHistoryItem-${ index } -actionOption-${ optionIndex } ` }
182+ href = { option . url }
183+ title = { option . label }
184+ onClick = { ( ) => {
185+ if ( option . message ) {
186+ sendMessage ( { query : option . message } ) ;
187+ }
188+ option . onSelect ?.( ) ;
189+ } }
190+ />
191+ ) ) }
192+ </ VuiFlexContainer >
193+ </ div >
194+ </ Fragment >
195+ ) ;
196+ } else {
197+ const { question, answer, results, factualConsistencyScore } = messageHistoryItem ;
198+ const onRetry =
199+ hasError && index === messageHistory . length - 1
200+ ? ( ) => sendMessage ( { query : question , isRetry : true } )
201+ : undefined ;
202+
203+ return (
204+ < Fragment key = { index } >
205+ < ChatItem
206+ question = { question }
207+ answer = { answer }
208+ searchResults = { results }
209+ factualConsistencyScore = {
210+ enableFactualConsistencyScore && < FactualConsistencyBadge score = { factualConsistencyScore } />
211+ }
212+ onRetry = { onRetry }
213+ />
214+ { index < messageHistory . length - 1 && < VuiSpacer size = "m" /> }
215+ </ Fragment >
216+ ) ;
217+ }
174218 } ) ,
175219 [ messageHistory ]
176220 ) ;
177221
178222 const hasContent = isLoading || messageHistory . length > 0 || activeMessage ;
179223 const isRequestDisabled = isLoading || isStreamingResponse || query . trim ( ) . length === 0 ;
180224
181- const onSendQuery = ( queryOverride ?: string ) => {
225+ const onSendQuery = async ( queryOverride ?: string ) => {
182226 if ( isRequestDisabled && ! queryOverride ) return ;
183- sendMessage ( { query : queryOverride ?? query } ) ;
227+
184228 setQuery ( "" ) ;
229+
230+ sendMessage ( { query : queryOverride ?? query } ) ;
185231 } ;
186232
187233 const spacer = historyItems . length === 0 ? null : < VuiSpacer size = { activeMessage ? "m" : "l" } /> ;
0 commit comments