11import { useTranslation } from 'react-i18next' ;
2- import React , { useEffect , useRef , useState } from 'react' ;
2+ import React , { useCallback , useEffect , useRef , useState } from 'react' ;
33import { useRecoilValue } from 'recoil' ;
44import { FlexBox , Icon , Text , TextArea } from '@ui5/webcomponents-react' ;
5- import Message , {
6- ErrorType ,
7- ErrResponse ,
8- MessageChunk ,
9- } from './Message/Message' ;
5+ import Message from './Message/Message' ;
106import Bubbles from './Bubbles/Bubbles' ;
117import ErrorMessage from './ErrorMessage/ErrorMessage' ;
128import { sessionIDState } from 'state/companion/sessionIDAtom' ;
@@ -16,25 +12,21 @@ import getFollowUpQuestions from 'components/KymaCompanion/api/getFollowUpQuesti
1612import getChatResponse from 'components/KymaCompanion/api/getChatResponse' ;
1713import { usePromptSuggestions } from 'components/KymaCompanion/hooks/usePromptSuggestions' ;
1814import { AIError } from '../KymaCompanion' ;
15+ import ContextLabel from './ContextLabel/ContextLabel' ;
16+ import {
17+ Author ,
18+ ChatGroup ,
19+ ErrResponse ,
20+ ErrorType ,
21+ MessageChunk ,
22+ Message as MessageType ,
23+ chatGroupHelpers ,
24+ } from './types' ;
1925import './Chat.scss' ;
2026
21- enum Author {
22- USER = 'user' ,
23- AI = 'ai' ,
24- }
25-
26- export interface MessageType {
27- author : Author ;
28- messageChunks : MessageChunk [ ] ;
29- isLoading : boolean ;
30- suggestions ?: string [ ] ;
31- suggestionsLoading ?: boolean ;
32- hasError ?: boolean | undefined ;
33- }
34-
3527type ChatProps = {
36- chatHistory : MessageType [ ] ;
37- setChatHistory : React . Dispatch < React . SetStateAction < MessageType [ ] > > ;
28+ chatHistory : ChatGroup [ ] ;
29+ setChatHistory : React . Dispatch < React . SetStateAction < ChatGroup [ ] > > ;
3830 loading : boolean ;
3931 setLoading : React . Dispatch < React . SetStateAction < boolean > > ;
4032 isReset : boolean ;
@@ -66,62 +58,54 @@ export const Chat = ({
6658 initialSuggestionsLoading,
6759 currentResource,
6860 } = usePromptSuggestions ( isReset , setIsReset , {
69- skip : chatHistory . length > 1 ,
61+ skip :
62+ chatHistory . reduce ( ( count , group ) => count + group . messages . length , 0 ) >
63+ 1 ,
7064 } ) ;
7165
72- const addMessage = ( { author, messageChunks, isLoading } : MessageType ) => {
73- setChatHistory ( prevItems =>
74- prevItems . concat ( { author, messageChunks, isLoading } ) ,
66+ const getCurrentContext = useCallback ( ( ) => {
67+ if ( ! currentResource . resourceType ) return undefined ;
68+ return currentResource . resourceName
69+ ? `${ currentResource . resourceType } - ${ currentResource . resourceName } `
70+ : currentResource . resourceType ;
71+ } , [ currentResource ] ) ;
72+
73+ const addMessage = ( message : MessageType ) => {
74+ const currentContext = getCurrentContext ( ) ;
75+ setChatHistory ( prevGroups =>
76+ chatGroupHelpers . addMessage ( prevGroups , message , currentContext ) ,
7577 ) ;
7678 } ;
7779
7880 const updateLatestMessage = ( updates : Partial < MessageType > ) => {
79- setChatHistory ( prevMessages => {
80- if ( prevMessages . length === 0 ) return prevMessages ;
81-
82- const [ latestMessage ] = prevMessages . slice ( - 1 ) ;
83- return prevMessages . slice ( 0 , - 1 ) . concat ( {
84- ...latestMessage ,
85- ...updates ,
86- } ) ;
87- } ) ;
81+ setChatHistory ( prevGroups =>
82+ chatGroupHelpers . updateLatestMessage ( prevGroups , updates ) ,
83+ ) ;
8884 } ;
8985
9086 const concatMsgToLatestMessage = (
9187 response : MessageChunk ,
9288 isLoading : boolean ,
9389 ) => {
94- setChatHistory ( prevMessages => {
95- const [ latestMessage ] = prevMessages . slice ( - 1 ) ;
96- return prevMessages . slice ( 0 , - 1 ) . concat ( {
97- ...latestMessage ,
98- messageChunks : latestMessage . messageChunks . concat ( response ) ,
90+ setChatHistory ( prevGroups =>
91+ chatGroupHelpers . concatMsgToLatestMessage (
92+ prevGroups ,
93+ response ,
9994 isLoading ,
100- } ) ;
101- } ) ;
95+ ) ,
96+ ) ;
10297 } ;
10398
10499 const removeLastMessage = ( ) => {
105- setChatHistory ( prevMessages => prevMessages . slice ( 0 , - 1 ) ) ;
100+ setChatHistory ( prevGroups =>
101+ chatGroupHelpers . removeLastMessage ( prevGroups ) ,
102+ ) ;
106103 } ;
107104
108105 const setErrorOnLastUserMsg = ( ) => {
109- setChatHistory ( prevMessages => {
110- const lastUserMsgIdx = prevMessages . findLastIndex ( msg => {
111- return msg . author === 'user' ;
112- } ) ;
113- if ( lastUserMsgIdx === - 1 ) {
114- return prevMessages ;
115- }
116-
117- return prevMessages . map ( ( msg , idx ) => {
118- if ( idx === lastUserMsgIdx ) {
119- msg . hasError = true ;
120- msg . isLoading = false ;
121- }
122- return msg ;
123- } ) ;
124- } ) ;
106+ setChatHistory ( prevGroups =>
107+ chatGroupHelpers . setErrorOnLastUserMsg ( prevGroups ) ,
108+ ) ;
125109 } ;
126110
127111 const handleChatResponse = ( response : MessageChunk ) => {
@@ -220,11 +204,7 @@ export const Chat = ({
220204 } ;
221205
222206 const retryPreviousPrompt = ( ) => {
223- const lastUserMsgIdx = chatHistory . findLastIndex (
224- v => v . author === Author . USER ,
225- ) ;
226- const previousPrompt = chatHistory . at ( lastUserMsgIdx ) ?. messageChunks [ 0 ] . data
227- . answer . content ;
207+ const previousPrompt = chatGroupHelpers . findLastUserPrompt ( chatHistory ) ;
228208 if ( previousPrompt ) {
229209 removeLastMessage ( ) ;
230210 sendPrompt ( previousPrompt ) ;
@@ -234,6 +214,7 @@ export const Chat = ({
234214 const sendPrompt = ( query : string ) => {
235215 setError ( { message : null , displayRetry : false } ) ;
236216 setLoading ( true ) ;
217+
237218 addMessage ( {
238219 author : Author . USER ,
239220 messageChunks : [
@@ -285,8 +266,18 @@ export const Chat = ({
285266 } ;
286267
287268 useEffect ( ( ) => {
288- if ( chatHistory . length === 1 ) {
269+ const totalMessageCount = chatHistory . reduce (
270+ ( count , group ) => count + group . messages . length ,
271+ 0 ,
272+ ) ;
273+
274+ if ( totalMessageCount === 1 ) {
289275 if ( initialSuggestionsLoading ) {
276+ // Update the context of the first group
277+ const currentContext = getCurrentContext ( ) ;
278+ setChatHistory ( prevGroups =>
279+ chatGroupHelpers . updateFirstGroupContext ( prevGroups , currentContext ) ,
280+ ) ;
290281 updateLatestMessage ( {
291282 messageChunks : [
292283 {
@@ -335,37 +326,52 @@ export const Chat = ({
335326 className = "chat-container"
336327 >
337328 < div
338- className = "chat-list sap-margin-x-tiny sap-margin-top-small "
329+ className = "chat-list sap-margin-x-tiny sap-margin-top-tiny "
339330 ref = { containerRef }
340331 >
341- { chatHistory . map ( ( message , index ) => {
342- const isLast = index === chatHistory . length - 1 ;
343- return message . author === Author . AI ? (
344- < React . Fragment key = { index } >
345- < Message
346- author = { message . author }
347- messageChunks = { message . messageChunks }
348- isLoading = { message . isLoading }
349- hasError = { message ?. hasError ?? false }
350- isLatestMessage = { isLast }
351- />
352- { isLast && ! message . isLoading && (
353- < Bubbles
354- onClick = { sendPrompt }
355- suggestions = { message . suggestions }
356- isLoading = { message . suggestionsLoading ?? false }
357- />
332+ { chatHistory . map ( ( group , groupIndex ) => {
333+ const isLastGroup = groupIndex === chatHistory . length - 1 ;
334+
335+ return (
336+ < div key = { groupIndex } className = "context-group" >
337+ { group . context && (
338+ < ContextLabel labelText = { group . context . labelText } />
358339 ) }
359- </ React . Fragment >
360- ) : (
361- < Message
362- author = { Author . USER }
363- key = { index }
364- messageChunks = { message . messageChunks }
365- isLoading = { message . isLoading }
366- hasError = { message ?. hasError ?? false }
367- isLatestMessage = { isLast }
368- />
340+ < div className = "message-context" >
341+ { group . messages . map ( ( message , messageIndex ) => {
342+ const isLastMessage =
343+ isLastGroup && messageIndex === group . messages . length - 1 ;
344+
345+ return message . author === Author . AI ? (
346+ < React . Fragment key = { `${ groupIndex } -${ messageIndex } ` } >
347+ < Message
348+ author = { message . author }
349+ messageChunks = { message . messageChunks }
350+ isLoading = { message . isLoading }
351+ hasError = { message . hasError ?? false }
352+ isLatestMessage = { isLastMessage }
353+ />
354+ { isLastMessage && ! message . isLoading && (
355+ < Bubbles
356+ onClick = { sendPrompt }
357+ suggestions = { message . suggestions }
358+ isLoading = { message . suggestionsLoading ?? false }
359+ />
360+ ) }
361+ </ React . Fragment >
362+ ) : (
363+ < Message
364+ author = { Author . USER }
365+ key = { `${ groupIndex } -${ messageIndex } ` }
366+ messageChunks = { message . messageChunks }
367+ isLoading = { message . isLoading }
368+ hasError = { message . hasError ?? false }
369+ isLatestMessage = { isLastMessage }
370+ />
371+ ) ;
372+ } ) }
373+ </ div >
374+ </ div >
369375 ) ;
370376 } ) }
371377 { error . message && (
0 commit comments