@@ -15,6 +15,82 @@ interface ConversationData extends ConversationInfo {
1515 agentStatus ?: AgentExecutionStatus ;
1616}
1717
18+ // Utility function to extract displayable content from events
19+ const getEventDisplayContent = ( event : Event ) : { title : string ; content : string ; details ?: any } => {
20+ switch ( event . kind ) {
21+ case 'MessageEvent' :
22+ const messageEvent = event as any ;
23+ const message = messageEvent . llm_message ;
24+ if ( message && message . content && Array . isArray ( message . content ) ) {
25+ const textContent = message . content
26+ . filter ( ( c : any ) => c . type === 'text' )
27+ . map ( ( c : any ) => c . text )
28+ . join ( ' ' ) ;
29+ return {
30+ title : `Message from ${ messageEvent . source || 'unknown' } ` ,
31+ content : textContent || 'No text content' ,
32+ details : message
33+ } ;
34+ }
35+ return {
36+ title : `Message from ${ messageEvent . source || 'unknown' } ` ,
37+ content : 'No message content available' ,
38+ details : messageEvent
39+ } ;
40+
41+ case 'ActionEvent' :
42+ const actionEvent = event as any ;
43+ const action = actionEvent . action ;
44+ return {
45+ title : `Action: ${ action ?. kind || 'Unknown Action' } ` ,
46+ content : action ?. command || action ?. content || JSON . stringify ( action , null , 2 ) ,
47+ details : action
48+ } ;
49+
50+ case 'ObservationEvent' :
51+ const obsEvent = event as any ;
52+ return {
53+ title : `Observation: ${ obsEvent . tool_name || 'Unknown Tool' } ` ,
54+ content : typeof obsEvent . observation === 'string'
55+ ? obsEvent . observation
56+ : JSON . stringify ( obsEvent . observation , null , 2 ) ,
57+ details : obsEvent . observation
58+ } ;
59+
60+ case 'AgentErrorEvent' :
61+ const errorEvent = event as any ;
62+ return {
63+ title : `Error: ${ errorEvent . tool_name || 'Unknown Tool' } ` ,
64+ content : typeof errorEvent . observation === 'string'
65+ ? errorEvent . observation
66+ : JSON . stringify ( errorEvent . observation , null , 2 ) ,
67+ details : errorEvent . observation
68+ } ;
69+
70+ case 'SystemPromptEvent' :
71+ const sysEvent = event as any ;
72+ return {
73+ title : 'System Prompt' ,
74+ content : sysEvent . system_prompt ?. text || 'System prompt updated' ,
75+ details : sysEvent . system_prompt
76+ } ;
77+
78+ case 'PauseEvent' :
79+ return {
80+ title : 'Agent Paused' ,
81+ content : 'Agent execution was paused' ,
82+ details : null
83+ } ;
84+
85+ default :
86+ return {
87+ title : event . kind || 'Unknown Event' ,
88+ content : JSON . stringify ( event , null , 2 ) ,
89+ details : event
90+ } ;
91+ }
92+ } ;
93+
1894export const ConversationManager : React . FC = ( ) => {
1995 const { settings } = useSettings ( ) ;
2096 const [ conversations , setConversations ] = useState < ConversationData [ ] > ( [ ] ) ;
@@ -23,6 +99,7 @@ export const ConversationManager: React.FC = () => {
2399 const [ manager , setManager ] = useState < SDKConversationManager | null > ( null ) ;
24100 const [ selectedConversationId , setSelectedConversationId ] = useState < string | null > ( null ) ;
25101 const [ messageInput , setMessageInput ] = useState ( '' ) ;
102+ const [ showAllEvents , setShowAllEvents ] = useState ( false ) ;
26103
27104 // Get selected conversation data
28105 const selectedConversation = conversations . find ( c => c . id === selectedConversationId ) ;
@@ -472,31 +549,93 @@ export const ConversationManager: React.FC = () => {
472549 </ div >
473550
474551 < div className = "bg-white dark:bg-gray-800 rounded-lg p-4 border border-gray-200 dark:border-gray-700" >
475- < h4 className = "text-base font-semibold text-gray-900 dark:text-white mb-3" > Events & Messages </ h4 >
552+ < div className = "flex justify-between items-center mb-3" >
553+ < h4 className = "text-base font-semibold text-gray-900 dark:text-white" > Events & Messages </ h4 >
554+ { selectedConversation . events && selectedConversation . events . length > 1 && (
555+ < button
556+ onClick = { ( ) => setShowAllEvents ( ! showAllEvents ) }
557+ className = "text-sm text-indigo-600 dark:text-indigo-400 hover:text-indigo-800 dark:hover:text-indigo-300 font-medium transition-colors duration-200"
558+ >
559+ { showAllEvents ? '▼ Show Recent Only' : `▶ Show All (${ selectedConversation . events . length } )` }
560+ </ button >
561+ ) }
562+ </ div >
476563 < div className = "max-h-64 overflow-y-auto space-y-3" >
477564 { selectedConversation . events && selectedConversation . events . length > 0 ? (
478- selectedConversation . events . map ( ( event , index ) => (
479- < div key = { index } className = "border border-gray-200 dark:border-gray-700 rounded-lg p-3 bg-gray-50 dark:bg-gray-900" >
480- < div className = "flex justify-between items-center mb-2" >
481- < span className = "text-sm font-medium text-indigo-600 dark:text-indigo-400 bg-indigo-50 dark:bg-indigo-900/30 px-2 py-1 rounded" >
482- { event . type }
483- </ span >
484- < span className = "text-xs text-gray-500 dark:text-gray-400" >
485- { event . timestamp ? new Date ( event . timestamp ) . toLocaleTimeString ( ) : '' }
486- </ span >
487- </ div >
488- { event . message && (
489- < div className = "text-sm text-gray-900 dark:text-white mb-2 p-2 bg-white dark:bg-gray-800 rounded border border-gray-200 dark:border-gray-700" >
490- { event . message }
565+ ( ( ) => {
566+ // Sort events by timestamp (most recent first)
567+ const sortedEvents = [ ...selectedConversation . events ] . sort ( ( a , b ) =>
568+ new Date ( b . timestamp ) . getTime ( ) - new Date ( a . timestamp ) . getTime ( )
569+ ) ;
570+
571+ // Show only the most recent event unless expanded
572+ const eventsToShow = showAllEvents ? sortedEvents : sortedEvents . slice ( 0 , 1 ) ;
573+
574+ return eventsToShow . map ( ( event , index ) => {
575+ const displayContent = getEventDisplayContent ( event ) ;
576+ const isRecent = index === 0 && ! showAllEvents ;
577+
578+ return (
579+ < div
580+ key = { event . id || index }
581+ className = { `border border-gray-200 dark:border-gray-700 rounded-lg p-3 bg-gray-50 dark:bg-gray-900 ${
582+ isRecent ? 'ring-2 ring-indigo-200 dark:ring-indigo-800' : ''
583+ } `}
584+ >
585+ < div className = "flex justify-between items-center mb-2" >
586+ < div className = "flex items-center gap-2" >
587+ < span className = "text-sm font-medium text-indigo-600 dark:text-indigo-400 bg-indigo-50 dark:bg-indigo-900/30 px-2 py-1 rounded" >
588+ { event . kind }
589+ </ span >
590+ { event . source && (
591+ < span className = "text-xs text-gray-500 dark:text-gray-400 bg-gray-100 dark:bg-gray-800 px-2 py-1 rounded" >
592+ { event . source }
593+ </ span >
594+ ) }
595+ { isRecent && (
596+ < span className = "text-xs text-green-600 dark:text-green-400 bg-green-50 dark:bg-green-900/30 px-2 py-1 rounded font-medium" >
597+ Latest
598+ </ span >
599+ ) }
600+ </ div >
601+ < span className = "text-xs text-gray-500 dark:text-gray-400" >
602+ { event . timestamp ? new Date ( event . timestamp ) . toLocaleTimeString ( ) : '' }
603+ </ span >
604+ </ div >
605+
606+ < div className = "text-sm font-medium text-gray-900 dark:text-white mb-2" >
607+ { displayContent . title }
608+ </ div >
609+
610+ { displayContent . content && (
611+ < div className = "text-sm text-gray-700 dark:text-gray-300 mb-2 p-2 bg-white dark:bg-gray-800 rounded border border-gray-200 dark:border-gray-700" >
612+ < div className = "max-h-32 overflow-y-auto" >
613+ { displayContent . content . length > 200 ? (
614+ < >
615+ { displayContent . content . substring ( 0 , 200 ) }
616+ < span className = "text-gray-500 dark:text-gray-400" > ... (truncated)</ span >
617+ </ >
618+ ) : (
619+ displayContent . content
620+ ) }
621+ </ div >
622+ </ div >
623+ ) }
624+
625+ { displayContent . details && (
626+ < details className = "mt-2" >
627+ < summary className = "text-xs text-gray-500 dark:text-gray-400 cursor-pointer hover:text-gray-700 dark:hover:text-gray-300" >
628+ Show raw data
629+ </ summary >
630+ < div className = "text-xs text-gray-600 dark:text-gray-400 font-mono bg-gray-100 dark:bg-gray-800 p-2 rounded border border-gray-200 dark:border-gray-700 overflow-x-auto mt-1" >
631+ < pre > { JSON . stringify ( displayContent . details , null , 2 ) } </ pre >
632+ </ div >
633+ </ details >
634+ ) }
491635 </ div >
492- ) }
493- { event . content && (
494- < div className = "text-xs text-gray-600 dark:text-gray-400 font-mono bg-gray-100 dark:bg-gray-800 p-2 rounded border border-gray-200 dark:border-gray-700 overflow-x-auto" >
495- < pre > { JSON . stringify ( event . content , null , 2 ) } </ pre >
496- </ div >
497- ) }
498- </ div >
499- ) )
636+ ) ;
637+ } ) ;
638+ } ) ( )
500639 ) : (
501640 < div className = "text-center py-4 text-gray-500 dark:text-gray-400" > No events yet</ div >
502641 ) }
0 commit comments