/** * Chat Page */ import { useEffect, useRef } from 'react'; import { WifiOff, MessageSquare, Settings, FolderOpen, Terminal, Plug, Zap, Bot, History, Server } from 'lucide-react'; import { motion, AnimatePresence } from 'framer-motion'; import { toast } from 'sonner'; import { useChat, ChatMessage, TypingIndicator, ChatInput, PermissionDialog, ContextUsage, } from '@ai-assistant/ui'; interface ChatPageProps { sessionId: string; onSessionNotFound?: () => void; onSessionUpdated?: (sessionId: string, name: string) => void; responsive?: boolean; // 工具栏按钮 showFileBrowser?: boolean; onToggleFileBrowser?: () => void; onOpenConfig?: () => void; onOpenCommands?: () => void; onOpenMCP?: () => void; onOpenHooks?: () => void; onOpenAgents?: () => void; onOpenCheckpoints?: () => void; onOpenProviders?: () => void; } export function ChatPage({ sessionId, onSessionNotFound, onSessionUpdated, responsive = false, showFileBrowser, onToggleFileBrowser, onOpenConfig, onOpenCommands, onOpenMCP, onOpenHooks, onOpenAgents, onOpenCheckpoints, onOpenProviders, }: ChatPageProps) { const { messages, isConnected, isLoading, streamingMessage, sendMessage, cancelProcessing, permissionRequest, allowPermission, denyPermission, agentMode, autoApprove, setAgentMode, setAutoApprove, } = useChat({ sessionId, onError: (error) => { console.error('Chat error:', error); }, onSessionNotFound, onSessionUpdated, onConfigError: (error) => { toast.error(error.message, { duration: 10000, action: onOpenProviders ? { label: '去配置', onClick: onOpenProviders, } : undefined, }); }, }); const messagesEndRef = useRef(null); // 自动滚动到底部 useEffect(() => { messagesEndRef.current?.scrollIntoView({ behavior: 'smooth' }); }, [messages, streamingMessage]); // 空状态组件 const EmptyState = () => (

Start a conversation

Ask me anything about coding, debugging, or software development.

{['Help me debug this code', 'Explain this function', 'Write a test'].map((suggestion) => ( sendMessage(suggestion)} className="px-3 py-1.5 bg-surface-subtle hover:bg-surface-muted rounded-full text-sm text-fg-secondary transition-colors" > "{suggestion}" ))}
); // 连接状态指示器 const ConnectionStatus = () => (
{isConnected ? ( Connected ) : (
Disconnected
)}
); return (
{/* Header */}

Chat

{/* 上下文使用情况 - 紧凑模式 */} {sessionId && ( )} {/* 连接状态 */} {/* 工具栏按钮 */} {(onOpenConfig || onToggleFileBrowser || onOpenCommands || onOpenMCP || onOpenHooks || onOpenAgents || onOpenCheckpoints || onOpenProviders) && (
{/* Checkpoints 按钮 */} {onOpenCheckpoints && ( )} {/* Providers 按钮 */} {onOpenProviders && ( )} {/* Agents 按钮 */} {onOpenAgents && ( )} {/* Hooks 按钮 */} {onOpenHooks && ( )} {/* MCP 按钮 */} {onOpenMCP && ( )} {/* 命令按钮 */} {onOpenCommands && ( )} {/* 配置按钮 */} {onOpenConfig && ( )} {/* 文件浏览器按钮 - 仅桌面端显示 */} {onToggleFileBrowser && ( )}
)}
{/* Messages */}
{messages.length === 0 && !isLoading && } {messages.map((message) => ( ))} {/* 流式消息 - 复用 ChatMessage 组件 */} {streamingMessage && ( )} {isLoading && !streamingMessage && }
{/* Input */} {/* Permission Dialog */} {permissionRequest && ( allowPermission(requestId, remember)} onDeny={(requestId, remember) => denyPermission(requestId, remember)} responsive={responsive} /> )}
); }