feat: 完善 Server 层并添加 CLI 和 Web 前端
Server 层增强: - 添加 Agent 适配层,支持动态加载 core 模块 - 实现 Token 认证机制,支持本地/远程模式 - WebSocket 集成 Agent 实时对话 CLI 模块 (packages/cli): - serve 命令启动 HTTP Server - attach 命令连接远程 Server - API Client 封装 Web 前端 (packages/web): - React 18 + Vite + Tailwind CSS - 会话管理侧边栏 - WebSocket 实时聊天界面 - 流式消息显示
This commit is contained in:
@@ -0,0 +1,90 @@
|
||||
/**
|
||||
* Chat Page
|
||||
*/
|
||||
|
||||
import { useEffect, useRef } from 'react';
|
||||
import { Wifi, WifiOff } from 'lucide-react';
|
||||
import { useChat } from '../hooks/useChat';
|
||||
import { ChatMessage, StreamingMessage, TypingIndicator } from '../components/ChatMessage';
|
||||
import { ChatInput } from '../components/ChatInput';
|
||||
|
||||
interface ChatPageProps {
|
||||
sessionId: string;
|
||||
}
|
||||
|
||||
export function ChatPage({ sessionId }: ChatPageProps) {
|
||||
const {
|
||||
messages,
|
||||
isConnected,
|
||||
isLoading,
|
||||
streamingContent,
|
||||
sendMessage,
|
||||
cancelProcessing,
|
||||
} = useChat({
|
||||
sessionId,
|
||||
onError: (error) => {
|
||||
console.error('Chat error:', error);
|
||||
},
|
||||
});
|
||||
|
||||
const messagesEndRef = useRef<HTMLDivElement>(null);
|
||||
|
||||
// 自动滚动到底部
|
||||
useEffect(() => {
|
||||
messagesEndRef.current?.scrollIntoView({ behavior: 'smooth' });
|
||||
}, [messages, streamingContent]);
|
||||
|
||||
return (
|
||||
<div className="flex-1 flex flex-col h-screen">
|
||||
{/* Header */}
|
||||
<div className="flex items-center justify-between px-6 py-3 border-b border-gray-700 bg-gray-800">
|
||||
<h1 className="text-lg font-medium">Chat</h1>
|
||||
<div className="flex items-center gap-2 text-sm">
|
||||
{isConnected ? (
|
||||
<>
|
||||
<Wifi size={16} className="text-green-500" />
|
||||
<span className="text-green-500">Connected</span>
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<WifiOff size={16} className="text-red-500" />
|
||||
<span className="text-red-500">Disconnected</span>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Messages */}
|
||||
<div className="flex-1 overflow-y-auto p-6">
|
||||
<div className="max-w-4xl mx-auto space-y-4">
|
||||
{messages.length === 0 && !isLoading && (
|
||||
<div className="text-center py-20">
|
||||
<h2 className="text-2xl font-semibold mb-2">Start a conversation</h2>
|
||||
<p className="text-gray-400">
|
||||
Type a message below to begin chatting with your AI assistant.
|
||||
</p>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{messages.map((message) => (
|
||||
<ChatMessage key={message.id} message={message} />
|
||||
))}
|
||||
|
||||
{streamingContent && <StreamingMessage content={streamingContent} />}
|
||||
|
||||
{isLoading && !streamingContent && <TypingIndicator />}
|
||||
|
||||
<div ref={messagesEndRef} />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Input */}
|
||||
<ChatInput
|
||||
onSend={sendMessage}
|
||||
onCancel={cancelProcessing}
|
||||
isLoading={isLoading}
|
||||
disabled={!isConnected}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user