import { useState, useRef } from 'react' import { Send, Square, MessageSquare, Cpu, Search as SearchIcon, Sparkles, Bot, User, Loader2, CheckCircle2, AlertCircle, ChevronDown, ShieldCheck, Terminal, Zap } from 'lucide-react' import clsx from 'clsx' const MODELS = [ { id: "deepseek-chat", name: "deepseek-chat", icon: MessageSquare, desc: "通用高智商模型 (V3)", color: "text-amber-500" }, { id: "deepseek-reasoner", name: "deepseek-reasoner", icon: Cpu, desc: "深度推理/思维链 (R1)", color: "text-amber-600" }, ]; export default function ApiTester({ config, onMessage, authFetch }) { const [model, setModel] = useState('deepseek-chat') const [message, setMessage] = useState('Hello, please introduce yourself in one sentence.') const [apiKey, setApiKey] = useState('') const [selectedAccount, setSelectedAccount] = useState('') const [response, setResponse] = useState(null) const [loading, setLoading] = useState(false) const [streamingContent, setStreamingContent] = useState('') const [streamingThinking, setStreamingThinking] = useState('') const [isStreaming, setIsStreaming] = useState(false) const abortControllerRef = useRef(null) const [sidebarOpen, setSidebarOpen] = useState(false) const [configExpanded, setConfigExpanded] = useState(false) const apiFetch = authFetch || fetch const accounts = config.accounts || [] const stopGeneration = () => { if (abortControllerRef.current) { abortControllerRef.current.abort() abortControllerRef.current = null } setLoading(false) setIsStreaming(false) } const directTest = async () => { if (loading) return setLoading(true) setIsStreaming(true) setResponse(null) setStreamingContent('') setStreamingThinking('') abortControllerRef.current = new AbortController() try { const key = apiKey || (config.keys?.[0] || '') if (!key) { onMessage('error', '请提供 API 密钥') setLoading(false) setIsStreaming(false) return } const res = await fetch('/v1/chat/completions', { method: 'POST', headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${key}`, }, body: JSON.stringify({ model, messages: [{ role: 'user', content: message }], stream: true, }), signal: abortControllerRef.current.signal, }) if (!res.ok) { const data = await res.json() setResponse({ success: false, error: data.error?.message || '请求失败' }) onMessage('error', data.error?.message || '请求失败') setLoading(false) setIsStreaming(false) return } setResponse({ success: true, status_code: res.status }) const reader = res.body.getReader() const decoder = new TextDecoder() let buffer = '' while (true) { const { done, value } = await reader.read() if (done) break buffer += decoder.decode(value, { stream: true }) const lines = buffer.split('\n') buffer = lines.pop() || '' for (const line of lines) { const trimmed = line.trim() if (!trimmed || !trimmed.startsWith('data: ')) continue const dataStr = trimmed.slice(6) if (dataStr === '[DONE]') continue try { const json = JSON.parse(dataStr) const choice = json.choices?.[0] if (choice?.delta) { const delta = choice.delta if (delta.reasoning_content) { setStreamingThinking(prev => prev + delta.reasoning_content) } if (delta.content) { setStreamingContent(prev => prev + delta.content) } } } catch (e) { console.error('Invalid JSON hunk:', dataStr, e) } } } } catch (e) { if (e.name === 'AbortError') { onMessage('info', '已停止生成') } else { onMessage('error', 'Network error: ' + e.message) setResponse({ error: e.message, success: false }) } } finally { setLoading(false) setIsStreaming(false) abortControllerRef.current = null } } const sendTest = async () => { if (selectedAccount) { setLoading(true) setResponse(null) try { const res = await apiFetch('/admin/accounts/test', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ identifier: selectedAccount, model, message, }), }) const data = await res.json() setResponse({ success: data.success, status_code: res.status, response: data, account: selectedAccount, }) if (data.success) { onMessage('success', `${selectedAccount}: Test Success (${data.response_time}ms)`) } else { onMessage('error', `${selectedAccount}: ${data.message}`) } } catch (e) { onMessage('error', 'Network error: ' + e.message) setResponse({ error: e.message }) } finally { setLoading(false) } return } directTest() } return (