/** * 主页面 - 聊天界面 * * 集成 json-render 生成式 UI * 支持动态渲染 MCP 工具调用结果 * 支持组件交互事件(ActionProvider) * * 更新:ChatMessage 现在支持 markdown 混排渲染, * JSON 代码块会就地渲染为 json-render 组件 */ 'use client'; import React, { useState, useCallback, useRef } from 'react'; import { useChat } from '@/lib/hooks'; import ChatInput from '@/components/ChatInput'; import ChatMessage from '@/components/ChatMessage'; import Header from '@/components/Header'; import JsonRenderer from '@/components/JsonRenderer'; import { ActionProvider } from '@/lib/action-context'; import type { ComponentSpec } from '@/lib/json-render-catalog'; // 消息类型 interface Message { role: 'user' | 'assistant'; content: string; } // 静态欢迎组件 spec const WELCOME_SPEC: ComponentSpec = { type: 'card', title: '欢迎使用 AI MCP Web UI', className: 'bg-gradient-to-br from-blue-50 to-purple-50 dark:from-blue-900/20 dark:to-purple-900/20 border-blue-200 dark:border-blue-800', children: [ { type: 'text', content: '这是一个通用的 AI 助手界面,可以连接多个 MCP 服务器,提供强大的工具调用能力。', variant: 'body', className: 'mb-4' }, { type: 'heading', level: 'h3', text: '可用的 MCP 服务器', className: 'mb-2 mt-4 text-gray-800 dark:text-gray-200' }, { type: 'stack', direction: 'column', spacing: 1, className: 'mb-4', children: [ { type: 'text', content: '🌐 Novel Translator MCP - 文本翻译工具', variant: 'body', className: 'text-sm text-gray-600 dark:text-gray-400' }, { type: 'text', content: '📚 Novel Platform User MCP - 小说阅读功能', variant: 'body', className: 'text-sm text-gray-600 dark:text-gray-400' }, { type: 'text', content: '⚙️ Novel Platform Admin MCP - 平台管理功能', variant: 'body', className: 'text-sm text-gray-600 dark:text-gray-400' } ] }, { type: 'heading', level: 'h3', text: '快速开始', className: 'mb-3 mt-6 text-gray-800 dark:text-gray-200' }, { type: 'suggestion-buttons', suggestions: [ { label: '翻译一段文本', message: '请帮我把以下英文翻译成中文:Hello, how are you?', icon: '🌐' }, { label: '查看小说列表', message: '请帮我获取小说列表', icon: '📚' }, { label: '获取平台统计', message: '请帮我获取平台统计数据', icon: '📊' }, { label: '查看 MCP 状态', message: '请帮我检查所有 MCP 服务器的连接状态', icon: '🔍' } ] } ] }; export default function Home() { const [history, setHistory] = useState([]); const { sendMessage, isLoading, response, error, abort, specs } = useChat(); const pendingMessageRef = useRef(null); // 当加载完成时,将完整的助手消息添加到历史记录 React.useEffect(() => { console.log('[useEffect] Triggered:', { isLoading, pendingMessage: pendingMessageRef.current, responseLength: response?.length || 0, responsePreview: response?.substring(0, 100), hasError: !!error, }); // 添加新消息(加载完成且有待处理消息) if (!isLoading && pendingMessageRef.current) { const assistantMessage: Message = { role: 'assistant', content: response || (error ? `⚠️ ${error}` : ''), }; console.log('[useEffect] Adding assistant message to history:', assistantMessage); setHistory((prev) => [...prev, assistantMessage]); pendingMessageRef.current = null; } }, [isLoading, response, error]); const handleSend = async (message: string) => { // 添加用户消息到历史记录 setHistory((prev) => [...prev, { role: 'user', content: message }]); pendingMessageRef.current = message; // 开始流式对话(不等待完成,由 useEffect 处理完成后的消息) sendMessage(message, history); }; const handleAbort = useCallback(() => { abort(); // 将当前的部分响应添加到历史记录 if (pendingMessageRef.current && response) { setHistory((prev) => [ ...prev, { role: 'assistant', content: response, }, ]); pendingMessageRef.current = null; } }, [abort, response]); // 创建 action context 用于组件交互 const actionContext = useCallback(() => ({ sendMessage: handleSend, }), [handleSend]); return (
{/* 聊天区域 */}
{history.length === 0 ? ( // 空状态:显示静态欢迎组件
) : ( // 使用 ActionProvider 包装整个消息区域,使 ChatMessage 内部的 JsonRenderer 可以访问 ActionContext
{history.map((msg, idx) => { console.log(`[Render] Message ${idx}:`, msg); return ( ); })} {isLoading && response && ( )} {error && (

{error}

)}
)}
{/* 工具调用面板 - 仅在桌面端显示侧边栏 */} {/* 暂时隐藏,因为工具调用结果现在在 ChatMessage 中渲染 */} {/* {isLoading && ( )} */}
); }