import { useState, useMemo } from 'react'; import ChatList from './components/ChatList'; import ChatWindow from './components/ChatWindow'; import Settings from './components/Settings'; import useLocalStorage from './hooks/useLocalStorage'; function App() { const [profiles, setProfiles] = useLocalStorage('profiles', [ { id: 'default', name: 'Default Profile', apiEndpoint: '', apiKey: '', model: 'DeepSeek-R1' } ]); const [summarizationProfile, setSummarizationProfile] = useLocalStorage('summarizationProfile', { id: 'default-summarization-profile', name: 'Summarization Profile', apiEndpoint: '', apiKey: '', model: 'DeepSeek-R1' }); const [mcpServers, setMcpServers] = useLocalStorage('mcpServers', [], { disableCache: false }); // 过滤出正在运行的 MCP 服务器 const activeMcpServers = useMemo(() => { console.log('Filtering active MCP servers:', mcpServers); return mcpServers.filter(server => !server.isBuiltIn || server.isRunning); }, [mcpServers]); const [activeProfileId, setActiveProfileId] = useLocalStorage('activeProfileId', 'default'); const [chats, setChats] = useLocalStorage('chats', []); const [currentChatId, setCurrentChatId] = useState(null); const [error, setError] = useState(null); const [loading, setLoading] = useState(false); const [showSettings, setShowSettings] = useState(false); const [sidebarCollapsed, setSidebarCollapsed] = useState(false); const [showProfileDropdown, setShowProfileDropdown] = useState(false); const [mobileMenuOpen, setMobileMenuOpen] = useState(false); const [streamingChats, setStreamingChats] = useState(new Set()); const activeProfile = profiles.find(p => p.id === activeProfileId) || profiles[0]; const createNewChat = () => { // 生成一个新的聊天ID,确保它是唯一的 const newChatId = Date.now(); console.log(`Creating new chat with ID: ${newChatId}`); const newChat = { id: newChatId, title: 'New Conversation', messages: [] }; // 使用函数式更新来确保我们使用最新的聊天列表 setChats(prevChats => { // 检查是否已经存在相同 ID 的聊天,避免重复 const chatExists = prevChats.some(chat => chat.id === newChatId); if (chatExists) { console.log(`Chat with ID ${newChatId} already exists, not creating duplicate`); return prevChats; } console.log(`Adding new chat to chats array, current count: ${prevChats.length}, new count: ${prevChats.length + 1}`); return [...prevChats, newChat]; }); // 设置当前聊天ID setCurrentChatId(newChatId); }; const deleteChat = (chatId) => { console.log(`Deleting chat with ID: ${chatId}`); // 使用函数式更新来确保我们使用最新的聊天列表 setChats(prevChats => { const filteredChats = prevChats.filter(chat => chat.id !== chatId); console.log(`Removed chat, previous count: ${prevChats.length}, new count: ${filteredChats.length}`); return filteredChats; }); // 如果删除的是当前活动的聊天,则将当前聊天ID设置为空 if (currentChatId === chatId) { console.log(`Deleted chat was the current active chat, setting currentChatId to null`); setCurrentChatId(null); } }; const toggleSettings = () => { setShowSettings(!showSettings); }; const toggleSidebar = () => { setSidebarCollapsed(!sidebarCollapsed); // 在移动设备上,如果侧边栏是展开的,点击收起按钮也应该关闭移动菜单 if (window.innerWidth <= 768 && !sidebarCollapsed) { setMobileMenuOpen(false); } }; const toggleMobileMenu = () => { setMobileMenuOpen(!mobileMenuOpen); // 如果侧边栏是收起的,则展开它 if (sidebarCollapsed) { setSidebarCollapsed(false); } }; // 添加聊天到正在流式传输的列表 const addStreamingChat = (chatId) => { setStreamingChats(prev => { const newSet = new Set(prev); newSet.add(chatId); return newSet; }); }; // 从正在流式传输的列表中移除聊天 const removeStreamingChat = (chatId) => { setStreamingChats(prev => { const newSet = new Set(prev); newSet.delete(chatId); return newSet; }); }; // 检查聊天是否正在流式传输 const isStreamingChat = (chatId) => { return streamingChats.has(chatId); }; const toggleProfileDropdown = () => { setShowProfileDropdown(!showProfileDropdown); }; const handleProfileSelect = (profileId) => { setActiveProfileId(profileId); setShowProfileDropdown(false); }; return (
{/* Modern Enterprise Header */}
{/* Brand Section */}

Thinking Model Client

Enterprise AI Assistant

{/* Controls Section */}
{/* Profile Selector */}
{showProfileDropdown && (
Select Profile
{profiles.map(profile => ( ))}
)}
{/* Settings Button */}

Conversations

c.id === currentChatId)} onSelectChat={setCurrentChatId} onDeleteChat={deleteChat} onCreateNewChat={createNewChat} collapsed={sidebarCollapsed} isStreamingChat={isStreamingChat} />
{/* Floating expand button that appears when sidebar is collapsed */}
{currentChatId ? ( c.id === currentChatId)} profile={activeProfile} summarizationProfile={summarizationProfile} onUpdateChat={(updatedChat) => { setChats(chats.map(c => c.id === updatedChat.id ? updatedChat : c )); }} onCreateNewChat={createNewChat} addStreamingChat={addStreamingChat} removeStreamingChat={removeStreamingChat} isStreamingChat={isStreamingChat} allChats={chats} currentChatId={currentChatId} mcpServers={activeMcpServers} /> ) : (

Welcome to Thinking Model Client

Start a new conversation or select an existing one.

)}
{showSettings && (
{ setProfiles(newProfiles); // Ensure the active profile still exists, otherwise select the first one if (!newProfiles.some(p => p.id === activeProfileId)) { setActiveProfileId(newProfiles[0]?.id || null); } }} onSaveSummarizationProfile={setSummarizationProfile} summarizationProfile={summarizationProfile} mcpServers={mcpServers} onSaveMcpServers={setMcpServers} onChangeActiveProfile={setActiveProfileId} onCloseSettings={() => setShowSettings(false)} />
)} {error && (
Error: {error}
)} {loading && (
Loading...
)}
); } export default App;