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:
2025-12-12 11:22:25 +08:00
parent 5e32375f0e
commit 168996a475
35 changed files with 4028 additions and 52 deletions
+74
View File
@@ -0,0 +1,74 @@
/**
* App Component
*/
import { useState, useEffect } from 'react';
import { Sidebar } from './components/Sidebar';
import { ChatPage } from './pages/Chat';
import { listSessions, createSession, type Session } from './api/client';
export function App() {
const [currentSessionId, setCurrentSessionId] = useState<string | null>(null);
const [isInitializing, setIsInitializing] = useState(true);
// 初始化:加载或创建会话
useEffect(() => {
async function init() {
try {
const { data: sessions } = await listSessions();
if (sessions.length > 0) {
// 选择最近的会话
setCurrentSessionId(sessions[0].id);
} else {
// 创建新会话
const { data: newSession } = await createSession();
setCurrentSessionId(newSession.id);
}
} catch (error) {
console.error('Failed to initialize:', error);
} finally {
setIsInitializing(false);
}
}
init();
}, []);
const handleSelectSession = (id: string) => {
setCurrentSessionId(id);
};
const handleCreateSession = (session: Session) => {
setCurrentSessionId(session.id);
};
if (isInitializing) {
return (
<div className="h-screen flex items-center justify-center bg-gray-900">
<div className="text-center">
<div className="w-8 h-8 border-2 border-primary-500 border-t-transparent rounded-full animate-spin mx-auto mb-4" />
<p className="text-gray-400">Initializing...</p>
</div>
</div>
);
}
return (
<div className="h-screen flex bg-gray-900">
<Sidebar
currentSessionId={currentSessionId}
onSelectSession={handleSelectSession}
onCreateSession={handleCreateSession}
/>
{currentSessionId ? (
<ChatPage key={currentSessionId} sessionId={currentSessionId} />
) : (
<div className="flex-1 flex items-center justify-center">
<p className="text-gray-400">Select or create a session</p>
</div>
)}
</div>
);
}