import { useState, useEffect } from 'react'; function Settings({ profiles, activeProfileId, onSaveProfiles, onChangeActiveProfile, onCloseSettings, onSaveSummarizationProfile, summarizationProfile, mcpServers, onSaveMcpServers }) { const [localProfiles, setLocalProfiles] = useState(profiles); const [localSummarizationProfile, setLocalSummarizationProfile] = useState(summarizationProfile || { id: 'default-summarization-profile', apiEndpoint: '', apiKey: '', model: 'DeepSeek-R1' }); const [localMcpServers, setLocalMcpServers] = useState(mcpServers || []); // 当 mcpServers 变化时更新本地状态 useEffect(() => { console.log('mcpServers changed:', mcpServers); setLocalMcpServers(mcpServers || []); }, [mcpServers]); const [editingProfileId, setEditingProfileId] = useState(activeProfileId); const [editingMcpServerId, setEditingMcpServerId] = useState(null); const [isHintExpanded, setIsHintExpanded] = useState(false); const [isMcpHintExpanded, setIsMcpHintExpanded] = useState(false); const [builtInServers, setBuiltInServers] = useState([]); const [isLoadingServers, setIsLoadingServers] = useState(false); const [serverTestResult, setServerTestResult] = useState(null); const [isTestingConnection, setIsTestingConnection] = useState(false); const editingProfile = localProfiles.find(p => p.id === editingProfileId) || localProfiles[0]; const editingMcpServer = localMcpServers.find(s => s.id === editingMcpServerId) || null; // 获取可用的内置 MCP 服务器 useEffect(() => { const fetchBuiltInServers = async () => { setIsLoadingServers(true); try { console.log('Fetching built-in MCP servers...'); const response = await fetch('/api/mcp/servers/available', { method: 'GET', headers: { 'Cache-Control': 'no-cache', 'Pragma': 'no-cache' } }); if (response.ok) { const data = await response.json(); console.log('Received built-in MCP servers:', data); setBuiltInServers(data.servers || []); } else { console.error('Failed to fetch built-in MCP servers:', response.status, response.statusText); // 尝试读取错误消息 const errorText = await response.text(); console.error('Error details:', errorText); } } catch (error) { console.error('Error fetching built-in MCP servers:', error); } finally { setIsLoadingServers(false); } }; fetchBuiltInServers(); // 每 5 秒刷新一次服务器状态 const intervalId = setInterval(fetchBuiltInServers, 5000); // 清理定时器 return () => clearInterval(intervalId); }, []); const handleProfileChange = (updatedProfile) => { setLocalProfiles(localProfiles.map(p => p.id === updatedProfile.id ? updatedProfile : p )); }; const handleSummarizationProfileChange = (updatedProfile) => { setLocalSummarizationProfile(updatedProfile); }; const handleMcpServerChange = (updatedServer) => { setLocalMcpServers(localMcpServers.map(s => s.id === updatedServer.id ? updatedServer : s )); }; const handleAddProfile = () => { const newId = `profile-${Date.now()}`; const newProfile = { id: newId, name: `New Profile ${localProfiles.length + 1}`, apiEndpoint: '', apiKey: '', model: 'DeepSeek-R1' }; const updatedProfiles = [...localProfiles, newProfile]; setLocalProfiles(updatedProfiles); setEditingProfileId(newId); }; const handleDeleteProfile = (profileId) => { if (localProfiles.length <= 1) { alert("Cannot delete the last profile"); return; } const updatedProfiles = localProfiles.filter(p => p.id !== profileId); setLocalProfiles(updatedProfiles); if (editingProfileId === profileId) { setEditingProfileId(updatedProfiles[0].id); } }; // 测试 MCP 服务器连接 const testMcpServerConnection = async (endpoint, authToken) => { if (!endpoint) return; setIsTestingConnection(true); setServerTestResult(null); try { const response = await fetch('/api/mcp/servers/test-connection', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ endpoint, authToken }) }); const result = await response.json(); setServerTestResult(result); return result.success; } catch (error) { console.error('Error testing MCP server connection:', error); setServerTestResult({ success: false, message: `Connection error: ${error.message}`, error: error.message }); return false; } finally { setIsTestingConnection(false); } }; // 启动内置 MCP 服务器 const startBuiltInServer = async (serverId) => { try { const response = await fetch('/api/mcp/servers/start', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ serverId }) }); const result = await response.json(); if (result.success) { // 检查是否已经添加了这个服务器 const existingServer = localMcpServers.find(s => s.isBuiltIn && s.builtInId === serverId ); if (!existingServer) { // 添加到本地 MCP 服务器列表 const builtInServer = builtInServers.find(s => s.id === serverId); const newServer = { id: `built-in-${serverId}-${Date.now()}`, name: builtInServer ? builtInServer.name : `Built-in Server ${serverId}`, endpoint: result.endpoint, authToken: '', description: builtInServer ? builtInServer.description : 'Built-in MCP server', isBuiltIn: true, builtInId: serverId, isRunning: true }; const updatedServers = [...localMcpServers, newServer]; setLocalMcpServers(updatedServers); setEditingMcpServerId(newServer.id); } else { // 更新现有服务器的端点 const updatedServers = localMcpServers.map(s => s.id === existingServer.id ? { ...s, endpoint: result.endpoint, isRunning: true } : s ); setLocalMcpServers(updatedServers); setEditingMcpServerId(existingServer.id); } // 刷新内置服务器列表 const response = await fetch('/api/mcp/servers/available'); if (response.ok) { const data = await response.json(); setBuiltInServers(data.servers || []); } return true; } else { console.error('Failed to start built-in MCP server:', result.error); return false; } } catch (error) { console.error('Error starting built-in MCP server:', error); return false; } }; // 停止内置 MCP 服务器 const stopBuiltInServer = async (serverId) => { try { const response = await fetch('/api/mcp/servers/stop', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ serverId }) }); const result = await response.json(); if (result.success) { // 更新内置服务器的状态 const updatedServers = localMcpServers.map(s => s.isBuiltIn && s.builtInId === serverId ? { ...s, isRunning: false } : s ); setLocalMcpServers(updatedServers); // 刷新内置服务器列表 const response = await fetch('/api/mcp/servers/available'); if (response.ok) { const data = await response.json(); setBuiltInServers(data.servers || []); } return true; } else { console.error('Failed to stop built-in MCP server:', result.error); return false; } } catch (error) { console.error('Error stopping built-in MCP server:', error); return false; } }; const handleAddMcpServer = () => { const newId = `mcp-server-${Date.now()}`; const newServer = { id: newId, name: `MCP Server ${localMcpServers.length + 1}`, endpoint: '', authToken: '', description: '', isBuiltIn: false }; const updatedServers = [...localMcpServers, newServer]; setLocalMcpServers(updatedServers); setEditingMcpServerId(newId); }; const handleDeleteMcpServer = (serverId) => { const updatedServers = localMcpServers.filter(s => s.id !== serverId); setLocalMcpServers(updatedServers); if (editingMcpServerId === serverId) { setEditingMcpServerId(updatedServers.length > 0 ? updatedServers[0].id : null); } }; const handleSubmit = (e) => { e.preventDefault(); onSaveProfiles(localProfiles); onSaveSummarizationProfile(localSummarizationProfile); if (onSaveMcpServers) { onSaveMcpServers(localMcpServers); } onChangeActiveProfile(editingProfileId); onCloseSettings(); }; return (

Settings

Chat Profiles

{localProfiles.map(profile => (
setEditingProfileId(profile.id)} > {profile.name} {localProfiles.length > 1 && ( )}
))}
{editingProfile && (

Edit Chat Profile: {editingProfile.name}

handleProfileChange({ ...editingProfile, name: e.target.value })} placeholder="Enter profile name" />
handleProfileChange({ ...editingProfile, apiEndpoint: e.target.value })} placeholder="Enter API endpoint" />

API Endpoint format examples:

  • Ends with / → /chat/completions will be appended
  • Ends with # → # will be removed
  • Other cases → /v1/chat/completions will be appended
handleProfileChange({ ...editingProfile, apiKey: e.target.value })} placeholder="Enter your API key" />
handleProfileChange({ ...editingProfile, model: e.target.value })} placeholder="Enter model name (e.g., DeepSeek-R1)" />
)}

Summarization Profile

handleSummarizationProfileChange({ ...localSummarizationProfile, apiEndpoint: e.target.value })} placeholder="Enter API endpoint" />
handleSummarizationProfileChange({ ...localSummarizationProfile, apiKey: e.target.value })} placeholder="Enter your API key" />
handleSummarizationProfileChange({ ...localSummarizationProfile, model: e.target.value })} placeholder="Enter model name (e.g., DeepSeek-R1)" />
{/* MCP Servers Section */}

MCP Servers

{/* Built-in MCP Servers */}

Built-in MCP Servers

{isLoadingServers ? (
Loading built-in servers...
) : builtInServers.length > 0 ? ( builtInServers.map(server => { // 检查这个内置服务器是否已经添加到用户的服务器列表中 const isAdded = localMcpServers.some(s => s.isBuiltIn && s.builtInId === server.id); return (
{server.name} {server.isRunning ? 'Running' : 'Stopped'}
{isAdded ? ( ) : ( )} {server.isRunning ? ( ) : ( )}
); }) ) : (

No built-in MCP servers available.

)}
{/* User-added MCP Servers */}

Your MCP Servers

{localMcpServers.map(server => (
setEditingMcpServerId(server.id)} > {server.name} {server.isBuiltIn && server.isRunning && ( Running )} {server.isBuiltIn && !server.isRunning && ( Stopped )}
))} {localMcpServers.length === 0 && (

No MCP servers added yet. Add a server to enable Model Context Protocol capabilities.

)}
{editingMcpServer && (

Edit MCP Server: {editingMcpServer.name}

handleMcpServerChange({ ...editingMcpServer, name: e.target.value })} placeholder="Enter server name" disabled={editingMcpServer.isBuiltIn} />
handleMcpServerChange({ ...editingMcpServer, endpoint: e.target.value })} placeholder="Enter MCP server endpoint URL" disabled={editingMcpServer.isBuiltIn} />
{serverTestResult && (
{serverTestResult.message} {serverTestResult.success && serverTestResult.tools && (

Available tools: {serverTestResult.tools.length}

    {serverTestResult.tools.map((tool, index) => (
  • {tool.name} - {tool.description}
  • ))}
)}
)}
handleMcpServerChange({ ...editingMcpServer, authToken: e.target.value })} placeholder="Enter authentication token (if required)" disabled={editingMcpServer.isBuiltIn} />