import markdownComponents, { markdownPlugins, preprocessLaTeX } from '@/components/chat/chat-content/config'; import { IChatDialogueMessageSchema } from '@/types/chat'; import { STORAGE_USERINFO_KEY } from '@/utils/constants/index'; import { CheckOutlined, ClockCircleOutlined, CloseOutlined, CodeOutlined, CopyOutlined, LoadingOutlined, } from '@ant-design/icons'; import { GPTVis } from '@antv/gpt-vis'; import { message } from 'antd'; import classNames from 'classnames'; import Image from 'next/image'; import { useSearchParams } from 'next/navigation'; import React, { memo, useMemo } from 'react'; import { useTranslation } from 'react-i18next'; import Feedback from './Feedback'; import RobotIcon from './RobotIcon'; const UserIcon: React.FC = () => { const user = JSON.parse(localStorage.getItem(STORAGE_USERINFO_KEY) ?? ''); if (!user.avatar_url) { return (
{user?.nick_name}
); } return ( {user?.nick_name} ); }; type DBGPTView = { name: string; status: 'todo' | 'runing' | 'failed' | 'completed' | (string & {}); result?: string; err_msg?: string; }; type MarkdownComponent = Parameters['0']['components']; 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: , }, }; const formatMarkdownVal = (val: string) => { return val .replaceAll('\\n', '\n') .replace(/]+)>/gi, '') .replace(/]+)>/gi, ''); }; const formatMarkdownValForAgent = (val: string) => { return val?.replace(/]+)>/gi, '
').replace(/]+)>/gi, ''); }; const ChatContent: React.FC<{ content: Omit & { context: | string | { template_name: string; template_introduce: string; }; }; onLinkClick: () => void; }> = ({ content, onLinkClick }) => { const { t } = useTranslation(); const searchParams = useSearchParams(); const scene = searchParams?.get('scene') ?? ''; const { context, model_name, role, thinking } = content; const isRobot = useMemo(() => role === 'view', [role]); const { 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 ? (
{preprocessLaTeX(result ?? '')}
) : (
{err_msg}
)}
); }, }), [cachePluginContext], ); return (
{/* icon */}
{isRobot ? : }
{/* 用户提问 */} {!isRobot && (
{typeof context === 'string' && context}
{typeof context === 'string' && context.trim() && (
)}
)} {/* ai回答 */} {isRobot && (
{typeof context === 'object' && (
{`[${context.template_name}]: `} {context.template_introduce || 'More Details'}
)} {typeof context === 'string' && scene === 'chat_agent' && ( {preprocessLaTeX(formatMarkdownValForAgent(value))} )} {typeof context === 'string' && scene !== 'chat_agent' && (
{preprocessLaTeX(formatMarkdownVal(value))}
)} {/* 正在思考 */} {thinking && !context && (
{t('thinking')}
)}
{/* 用户反馈 */}
)}
); }; export default memo(ChatContent);