@@ -23,7 +23,7 @@ import { useAtomValue } from 'jotai';
2323import { clientSettingsAtom } from '../../atoms/settingsState' ;
2424import { hostAtom } from '../../atoms/hostAtom' ;
2525import { serviceAtom } from '../../atoms/serviceAtom' ;
26- import { llmIsLoadingAtom } from '../../atoms/llmAtom' ;
26+ import { llmIsLoadingAtom , llmHistoryAtom , llmCurrentHistoryIndexAtom } from '../../atoms/llmAtom' ;
2727
2828// Helpers
2929import {
@@ -42,9 +42,10 @@ import doomguyImage from './Doomguy.png';
4242 Doomguy will be bloody at >= 4 services down
4343*/
4444
45- const Doomguy = ( { scaleCss, style } : {
45+ const Doomguy = ( { scaleCss, style, showBalloon = true } : {
4646 scaleCss ?: string ,
47- style ?: React . CSSProperties
47+ style ?: React . CSSProperties ,
48+ showBalloon ?: boolean
4849} ) => {
4950
5051 const smileClasses = [ 'doomguy20' , 'doomguy21' , 'doomguy22' , 'doomguy23' ] ;
@@ -58,21 +59,50 @@ const Doomguy = ({ scaleCss, style }: {
5859 const hostState = useAtomValue ( hostAtom ) ;
5960 const serviceState = useAtomValue ( serviceAtom ) ;
6061 const llmIsLoading = useAtomValue ( llmIsLoadingAtom ) ;
62+ const llmHistory = useAtomValue ( llmHistoryAtom ) ;
63+ const llmCurrentHistoryIndex = useAtomValue ( llmCurrentHistoryIndexAtom ) ;
64+
65+ // Get the current history item for shortResponse and color
66+ const currentHistoryItem = llmHistory [ llmCurrentHistoryIndex ] ;
67+ const llmShortResponse = currentHistoryItem ?. shortResponse || '' ;
68+ const llmHistoryColor = currentHistoryItem ?. color || 'green' ;
6169
6270 const [ clicked , setClicked ] = useState ( false ) ; // Clicking his face will temporarily make him angry
6371 const [ thinkingFrame , setThinkingFrame ] = useState ( thinkingAnimation [ 0 ] ) ;
6472
6573 // Calculate filtered counts using useMemo for performance
66- const howManyDown = useMemo ( ( ) => {
74+ // howManyDown includes hosts down + service warnings + service criticals (used for concerned/angry)
75+ // howManyDownBloody excludes service warnings (used for bloody mode threshold)
76+ const { howManyDown, howManyDownBloody } = useMemo ( ( ) => {
6777 const filteredHosts = filterHostStateArray ( hostState . stateArray , clientSettings ) ;
6878 const filteredServices = filterServiceStateArray ( serviceState . stateArray , clientSettings ) ;
6979
7080 const hostDownCount = countFilteredHostStates ( filteredHosts ) ;
7181 const serviceDownCount = countFilteredServiceStates ( filteredServices ) ;
7282
73- return hostDownCount + serviceDownCount . warning + serviceDownCount . critical ;
83+ return {
84+ howManyDown : hostDownCount + serviceDownCount . warning + serviceDownCount . critical ,
85+ howManyDownBloody : hostDownCount + serviceDownCount . critical , // excludes warnings for bloody mode
86+ } ;
7487 } , [ hostState . stateArray , serviceState . stateArray , clientSettings ] ) ;
7588
89+ // Map the LLM history color to CSS color
90+ const speechBalloonColor = useMemo ( ( ) => {
91+ switch ( llmHistoryColor ) {
92+ case 'red' :
93+ return '#FD7272' ;
94+ case 'orange' :
95+ return 'orange' ;
96+ case 'yellow' :
97+ return 'yellow' ;
98+ case 'gray' :
99+ return 'gray' ;
100+ case 'green' :
101+ default :
102+ return 'lime' ;
103+ }
104+ } , [ llmHistoryColor ] ) ;
105+
76106 // Animate Doomguy while thinking
77107 useEffect ( ( ) => {
78108 if ( ! llmIsLoading ) {
@@ -92,10 +122,11 @@ const Doomguy = ({ scaleCss, style }: {
92122 classes = smileClasses ;
93123 } else if ( howManyDown === 0 ) {
94124 classes = happyClasses ;
95- } else if ( howManyDown >= clientSettings . doomguyAngryAt && howManyDown < clientSettings . doomguyBloodyAt ) {
96- classes = angryClasses ;
97- } else if ( howManyDown >= clientSettings . doomguyBloodyAt ) {
125+ } else if ( howManyDownBloody >= clientSettings . doomguyBloodyAt ) {
126+ // Check bloody first (uses count excluding warnings)
98127 classes = bloodyClasses ;
128+ } else if ( howManyDown >= clientSettings . doomguyAngryAt ) {
129+ classes = angryClasses ;
99130 } else {
100131 classes = happyClasses ;
101132 }
@@ -134,6 +165,11 @@ const Doomguy = ({ scaleCss, style }: {
134165
135166 return (
136167 < div className = "doomguy-wrap" style = { style } >
168+ { showBalloon && llmShortResponse && ! llmIsLoading && (
169+ < div className = "doomguy-speech-balloon" style = { { color : speechBalloonColor } } >
170+ { llmShortResponse }
171+ </ div >
172+ ) }
137173 < div style = { transformCss } className = { doomguyClass } onClick = { clickedDoomguy } >
138174 </ div >
139175 { llmIsLoading && < div className = "doomguy-thinking" > thinking</ div > }
0 commit comments