@@ -6,6 +6,7 @@ import { Link as RouterLink, useHistory } from 'react-router-dom';
66import remarkGfm from 'remark-gfm' ;
77import YAML from 'yaml' ;
88import { LogsButton , YamlDisplay } from './components' ;
9+ import MCPFormattedMessage from './components/chat/MCPFormattedMessage' ;
910import { getHeadlampLink } from './utils/promptLinkHelper' ;
1011import { parseKubernetesYAML } from './utils/SampleYamlLibrary' ;
1112
@@ -87,6 +88,8 @@ const parseLogsButtonData = (content: string, logsButtonIndex: number): ParseRes
8788interface ContentRendererProps {
8889 content : string ;
8990 onYamlDetected ?: ( yaml : string , resourceType : string ) => void ;
91+ promptWidth ?: string ; // Add width prop
92+ onRetryTool ?: ( toolName : string , args : Record < string , any > ) => void ;
9093}
9194
9295// Table wrapper component with show more functionality - moved outside to preserve state
@@ -96,7 +99,14 @@ const TableWrapper: React.FC<{ children: React.ReactNode }> = React.memo(({ chil
9699
97100 // Extract table rows from children
98101 const tableElement = React . Children . only ( children ) as React . ReactElement ;
99- const tbody = React . Children . toArray ( tableElement . props . children ) . find (
102+ const tableChildren = tableElement . props . children ;
103+
104+ if ( ! tableChildren ) {
105+ // No children found, return table as is
106+ return < Box sx = { { overflowX : 'auto' , width : '100%' , mb : 2 } } > { children } </ Box > ;
107+ }
108+
109+ const tbody = React . Children . toArray ( tableChildren ) . find (
100110 ( child : any ) => child ?. type === 'tbody' || child ?. props ?. component === 'tbody'
101111 ) ;
102112
@@ -106,7 +116,8 @@ const TableWrapper: React.FC<{ children: React.ReactNode }> = React.memo(({ chil
106116 }
107117
108118 const tbodyElement = tbody as React . ReactElement ;
109- const rows = React . Children . toArray ( tbodyElement . props . children ) ;
119+ const tbodyChildren = tbodyElement . props . children ;
120+ const rows = tbodyChildren ? React . Children . toArray ( tbodyChildren ) : [ ] ;
110121 const hasMoreRows = rows . length > maxRows ;
111122 const visibleRows = showAll ? rows : rows . slice ( 0 , maxRows ) ;
112123
@@ -117,7 +128,7 @@ const TableWrapper: React.FC<{ children: React.ReactNode }> = React.memo(({ chil
117128
118129 // Clone the table with the limited tbody
119130 const limitedTable = React . cloneElement ( tableElement , {
120- children : React . Children . map ( tableElement . props . children , ( child : any ) => {
131+ children : React . Children . map ( tableChildren , ( child : any ) => {
121132 if ( child ?. type === 'tbody' || child ?. props ?. component === 'tbody' ) {
122133 return limitedTbody ;
123134 }
@@ -276,7 +287,7 @@ markdownComponents.li.displayName = 'MarkdownLi';
276287markdownComponents . blockquote . displayName = 'MarkdownBlockquote' ;
277288
278289const ContentRenderer : React . FC < ContentRendererProps > = React . memo (
279- ( { content, onYamlDetected } ) => {
290+ ( { content, onYamlDetected, onRetryTool } ) => {
280291 const history = useHistory ( ) ;
281292 // Create code component that has access to onYamlDetected
282293 const CodeComponent = React . useMemo ( ( ) => {
@@ -531,7 +542,18 @@ const ContentRenderer: React.FC<ContentRendererProps> = React.memo(
531542 const processedContent = useMemo ( ( ) => {
532543 if ( ! content ) return null ;
533544
534- // First, check if content is a JSON response with error or success keys
545+ // First, check if content is a formatted MCP output (pure JSON)
546+ try {
547+ const parsed = JSON . parse ( content . trim ( ) ) ;
548+ if ( parsed . formatted && parsed . mcpOutput ) {
549+ // This is a formatted MCP output, use our specialized component
550+ return < MCPFormattedMessage content = { content } isAssistant onRetryTool = { onRetryTool } /> ;
551+ }
552+ } catch ( error ) {
553+ // Not JSON or not formatted MCP output, continue with normal processing
554+ }
555+
556+ // Second, check if content is a JSON response with error or success keys
535557 const jsonParseResult = parseJsonContent ( content . trim ( ) ) ;
536558 if ( jsonParseResult . success ) {
537559 const parsedContent = jsonParseResult . data ;
@@ -563,8 +585,8 @@ const ContentRenderer: React.FC<ContentRendererProps> = React.memo(
563585 < Box
564586 component = "pre"
565587 sx = { {
566- backgroundColor : theme => theme . palette . grey [ 100 ] ,
567- color : theme => theme . palette . grey [ 900 ] ,
588+ backgroundColor : ( theme : any ) => theme . palette . grey [ 100 ] ,
589+ color : ( theme : any ) => theme . palette . grey [ 900 ] ,
568590 padding : 2 ,
569591 borderRadius : 1 ,
570592 overflowX : 'auto' ,
@@ -640,7 +662,7 @@ const ContentRenderer: React.FC<ContentRendererProps> = React.memo(
640662 { content }
641663 </ ReactMarkdown >
642664 ) ;
643- } , [ content , onYamlDetected , processUnformattedYaml ] ) ;
665+ } , [ content , onYamlDetected , onRetryTool , processUnformattedYaml ] ) ;
644666
645667 return (
646668 < Box sx = { { width : '100%' , overflowWrap : 'break-word' , wordWrap : 'break-word' } } >
@@ -652,7 +674,8 @@ const ContentRenderer: React.FC<ContentRendererProps> = React.memo(
652674 // Only re-render if content or onYamlDetected actually changed
653675 return (
654676 prevProps . content === nextProps . content &&
655- prevProps . onYamlDetected === nextProps . onYamlDetected
677+ prevProps . onYamlDetected === nextProps . onYamlDetected &&
678+ prevProps . onRetryTool === nextProps . onRetryTool
656679 ) ;
657680 }
658681) ;
0 commit comments