import { ChatContext } from '@/app/chat-context'; import { IChatDialogueMessageSchema } from '@/types/chat'; import { CheckOutlined, ClockCircleOutlined, CloseOutlined, CodeOutlined, LoadingOutlined, RobotOutlined, UserOutlined, } from '@ant-design/icons'; import { GPTVis } from '@antv/gpt-vis'; import { Tag } from 'antd'; import classNames from 'classnames'; import { PropsWithChildren, ReactNode, memo, useContext, useMemo } from 'react'; import rehypeRaw from 'rehype-raw'; import remarkGfm from 'remark-gfm'; import { renderModelIcon } from '../header/model-selector'; import markdownComponents from './config'; interface Props { content: Omit & { context: | string | { template_name: string; template_introduce: string; }; }; isChartChat?: boolean; onLinkClick?: () => void; } type MarkdownComponent = Parameters['0']['components']; type DBGPTView = { name: string; status: 'todo' | 'runing' | 'failed' | 'completed' | (string & {}); result?: string; err_msg?: string; }; const pluginViewStatusMapper: Record = { todo: { bgClass: 'bg-gray-500', icon: , }, runing: { bgClass: 'bg-blue-500', icon: , }, failed: { bgClass: 'bg-red-500', icon: , }, completed: { bgClass: 'bg-green-500', icon: , }, }; function formatMarkdownVal(val: string) { return val .replaceAll('\\n', '\n') .replace(/]+)>/gi, '') .replace(/]+)>/gi, ''); } function ChatContent({ children, content, isChartChat, onLinkClick }: PropsWithChildren) { const { scene } = useContext(ChatContext); const { context, model_name, role } = content; const isRobot = role === 'view'; const { relations, value, cachePluginContext } = useMemo<{ relations: string[]; value: string; cachePluginContext: DBGPTView[]; }>(() => { if (typeof context !== 'string') { return { relations: [], value: '', cachePluginContext: [], }; } const [value, relation] = context.split('\trelations:'); const relations = relation ? relation.split(',') : []; const cachePluginContext: DBGPTView[] = []; let cacheIndex = 0; const result = value.replace(/]*>[^<]*<\/dbgpt-view>/gi, matchVal => { try { const pluginVal = matchVal.replaceAll('\n', '\\n').replace(/<[^>]*>|<\/[^>]*>/gm, ''); const pluginContext = JSON.parse(pluginVal) as DBGPTView; const replacement = `${cacheIndex}`; cachePluginContext.push({ ...pluginContext, result: formatMarkdownVal(pluginContext.result ?? ''), }); cacheIndex++; return replacement; } catch (e) { console.log((e as any).message, e); return matchVal; } }); return { relations, cachePluginContext, value: result, }; }, [context]); const extraMarkdownComponents = useMemo( () => ({ 'custom-view'({ children }) { const index = +children.toString(); if (!cachePluginContext[index]) { return children; } const { name, status, err_msg, result } = cachePluginContext[index]; const { bgClass, icon } = pluginViewStatusMapper[status] ?? {}; return (
{name} {icon}
{result ? (
{result ?? ''}
) : (
{err_msg}
)}
); }, }), [context, cachePluginContext], ); if (!isRobot && !context) return
; return (
{isRobot ? renderModelIcon(model_name) || : }
{/* User Input */} {!isRobot && typeof context === 'string' && context} {/* Render Report */} {isRobot && isChartChat && typeof context === 'object' && (
{`[${context.template_name}]: `} {context.template_introduce || 'More Details'}
)} {/* Markdown */} {isRobot && typeof context === 'string' && ( {formatMarkdownVal(value)} )} {!!relations?.length && (
{relations?.map((value, index) => ( {value} ))}
)}
{children}
); } export default memo(ChatContent);