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
+85 -2
View File
@@ -18,6 +18,16 @@ import {
} from './ws.js';
import { handleSSE, getSSEStats } from './sse.js';
import { getSessionManager } from './session/manager.js';
import { initCore, isCoreAvailable, getAgentStats } from './agent/index.js';
import {
authMiddleware,
initAuth,
getAuthConfig,
generateToken,
addToken,
setAuthEnabled,
maskToken,
} from './auth/index.js';
// 创建 Hono 应用
const app = new Hono();
@@ -36,15 +46,26 @@ app.use(
})
);
// 健康检查
// 认证中间件 (在 CORS 之后)
app.use('*', authMiddleware);
// 健康检查 (跳过认证)
app.get('/health', (c) => {
const sessionManager = getSessionManager();
const wsStats = getConnectionStats();
const sseStats = getSSEStats();
const authConfig = getAuthConfig();
return c.json({
status: 'ok',
timestamp: new Date().toISOString(),
agent: {
coreAvailable: isCoreAvailable(),
},
auth: {
enabled: authConfig.enabled,
tokenCount: authConfig.tokens.length,
},
stats: {
sessions: sessionManager.count(),
websocket: wsStats,
@@ -119,6 +140,10 @@ app.onError((err, c) => {
export interface ServerOptions {
port?: number;
host?: string;
/** 是否启用认证 (远程模式自动启用) */
auth?: boolean;
/** 预设的 token */
token?: string;
}
/**
@@ -135,12 +160,51 @@ export function createServer(options: ServerOptions = {}) {
};
}
/**
* 初始化服务器(加载 core 模块等)
*/
export async function initServer(options: ServerOptions = {}): Promise<void> {
// 尝试加载 core 模块
const coreLoaded = await initCore();
if (coreLoaded) {
console.log('[Server] Core module initialized');
} else {
console.warn('[Server] Core module not available, running in limited mode');
}
// 初始化认证
const { host = '127.0.0.1', auth, token } = options;
const isRemote = host !== '127.0.0.1' && host !== 'localhost';
const authEnabled = auth !== undefined ? auth : isRemote;
initAuth({
enabled: authEnabled,
tokens: [],
skipPaths: ['/health', '/api/health'],
});
// 如果启用认证,生成或使用提供的 token
if (authEnabled) {
const serverToken = token || generateToken();
addToken(serverToken);
console.log(`[Auth] Authentication enabled`);
console.log(`[Auth] Token: ${serverToken}`);
}
}
/**
* 启动服务器 (Bun 环境)
*/
export function startServer(options: ServerOptions = {}): void {
export async function startServer(options: ServerOptions = {}): Promise<void> {
const { port = 3000, host = '127.0.0.1' } = options;
// 初始化
await initServer(options);
const coreStatus = isCoreAvailable() ? '✅ Core loaded' : '⚠️ Core not available';
const authConfig = getAuthConfig();
const authStatus = authConfig.enabled ? '🔐 Enabled' : '🔓 Disabled';
console.log(`
╔════════════════════════════════════════════╗
║ AI Assistant Server ║
@@ -149,6 +213,8 @@ export function startServer(options: ServerOptions = {}): void {
║ WebSocket: ws://${host}:${port}/api/ws/:sessionId
║ SSE: http://${host}:${port}/api/sessions/:id/events
║ Health: http://${host}:${port}/health
║ Agent: ${coreStatus}
║ Auth: ${authStatus}
╚════════════════════════════════════════════╝
`);
@@ -170,4 +236,21 @@ export {
emitFileChangeEvent,
} from './sse.js';
export { broadcastToSession } from './ws.js';
export {
initCore,
isCoreAvailable,
getAgentStats,
processMessage,
cancelProcessing,
} from './agent/index.js';
export {
initAuth,
getAuthConfig,
generateToken,
addToken,
removeToken,
setAuthEnabled,
validateToken,
maskToken,
} from './auth/index.js';
export * from './types.js';