feat: 重构为 Monorepo 架构并实现 HTTP Server

架构变更:
- 采用 pnpm workspaces 实现 Monorepo 结构
- 将现有代码迁移到 packages/core
- 新增 packages/server HTTP 服务层

Server 功能:
- REST API: 会话管理、工具管理、配置管理
- WebSocket: 实时双向通信支持
- SSE: 服务端事件推送
- Hono + Bun 作为运行时

API 端点:
- GET/POST /api/sessions - 会话 CRUD
- GET/POST /api/sessions/:id/messages - 消息管理
- GET /api/sessions/:id/events - SSE 事件流
- WS /api/ws/:sessionId - WebSocket 连接
- GET/POST /api/tools - 工具管理
- GET/PUT /api/config - 配置管理
This commit is contained in:
2025-12-12 10:42:20 +08:00
parent 59dbed926e
commit 5e32375f0e
301 changed files with 3281 additions and 43 deletions
+255
View File
@@ -0,0 +1,255 @@
import type { ModelMessage } from 'ai';
import type { SessionData, Todo, SessionSummary } from './types.js';
import { SessionStorage, sessionStorage } from './storage.js';
/**
* 会话管理器
* 提供高级会话操作接口
*/
export class SessionManager {
private storage: SessionStorage;
private currentSession: SessionData | null = null;
private autoSaveInterval: ReturnType<typeof setInterval> | null = null;
constructor(storage?: SessionStorage) {
this.storage = storage || sessionStorage;
}
/**
* 初始化 - 尝试恢复或创建新会话
*/
async init(workdir: string): Promise<SessionData> {
// 尝试加载当前会话
const existing = await this.storage.loadCurrentSession();
if (existing && existing.workdir === workdir) {
// 同一工作目录,恢复会话
this.currentSession = existing;
} else {
// 不同目录或无会话,归档旧会话并创建新的
if (existing) {
await this.storage.archiveCurrentSession();
}
this.currentSession = this.createNewSession(workdir);
await this.save();
}
// 启动自动保存
this.startAutoSave();
return this.currentSession;
}
/**
* 创建新会话
*/
private createNewSession(workdir: string): SessionData {
return {
id: this.storage.generateSessionId(),
createdAt: new Date().toISOString(),
updatedAt: new Date().toISOString(),
workdir,
messages: [],
discoveredTools: [],
todos: [],
};
}
/**
* 获取当前会话
*/
getSession(): SessionData | null {
return this.currentSession;
}
/**
* 保存当前会话
*/
async save(): Promise<void> {
if (this.currentSession) {
await this.storage.saveCurrentSession(this.currentSession);
}
}
/**
* 添加消息
*/
async addMessage(message: ModelMessage): Promise<void> {
if (!this.currentSession) return;
this.currentSession.messages.push(message);
await this.save();
}
/**
* 批量设置消息(用于同步整个对话历史)
*/
async setMessages(messages: ModelMessage[]): Promise<void> {
if (!this.currentSession) return;
this.currentSession.messages = messages;
await this.save();
}
/**
* 获取对话历史
*/
getMessages(): ModelMessage[] {
return this.currentSession?.messages || [];
}
/**
* 设置已发现的工具
*/
async setDiscoveredTools(tools: string[]): Promise<void> {
if (!this.currentSession) return;
this.currentSession.discoveredTools = tools;
await this.save();
}
/**
* 获取已发现的工具
*/
getDiscoveredTools(): string[] {
return this.currentSession?.discoveredTools || [];
}
/**
* 更新待办事项
*/
async setTodos(todos: Todo[]): Promise<void> {
if (!this.currentSession) return;
this.currentSession.todos = todos;
await this.save();
}
/**
* 获取待办事项
*/
getTodos(): Todo[] {
return this.currentSession?.todos || [];
}
/**
* 清空当前会话并创建新会话
*/
async newSession(workdir?: string): Promise<SessionData> {
// 归档当前会话
if (this.currentSession && this.currentSession.messages.length > 0) {
await this.storage.archiveCurrentSession();
}
// 创建新会话
const newWorkdir = workdir || this.currentSession?.workdir || process.cwd();
this.currentSession = this.createNewSession(newWorkdir);
await this.save();
return this.currentSession;
}
/**
* 创建子会话(用于 Task 工具)
* @param parentId 父会话 ID
* @param agentName 关联的 Agent 名称
* @param title 会话标题
*/
createChildSession(parentId: string, agentName: string, title?: string): SessionData {
const workdir = this.currentSession?.workdir || process.cwd();
const childSession: SessionData = {
id: this.storage.generateSessionId(),
parentId,
agentName,
createdAt: new Date().toISOString(),
updatedAt: new Date().toISOString(),
workdir,
title: title || `子任务 (@${agentName})`,
messages: [],
discoveredTools: [],
todos: [],
};
return childSession;
}
/**
* 保存子会话
*/
async saveChildSession(session: SessionData): Promise<void> {
await this.storage.saveSession(session);
}
/**
* 获取当前会话 ID
*/
getSessionId(): string | undefined {
return this.currentSession?.id;
}
/**
* 恢复指定会话
*/
async restoreSession(sessionId: string): Promise<SessionData | null> {
const session = await this.storage.loadSession(sessionId);
if (!session) return null;
// 归档当前会话
if (this.currentSession && this.currentSession.messages.length > 0) {
await this.storage.archiveCurrentSession();
}
this.currentSession = session;
await this.save();
return session;
}
/**
* 列出历史会话
*/
async listSessions(): Promise<SessionSummary[]> {
return this.storage.listSessions();
}
/**
* 删除历史会话
*/
async deleteSession(sessionId: string): Promise<boolean> {
return this.storage.deleteSession(sessionId);
}
/**
* 启动自动保存(每 30 秒)
*/
private startAutoSave(): void {
if (this.autoSaveInterval) return;
this.autoSaveInterval = setInterval(async () => {
await this.save();
}, 30000);
}
/**
* 停止自动保存
*/
stopAutoSave(): void {
if (this.autoSaveInterval) {
clearInterval(this.autoSaveInterval);
this.autoSaveInterval = null;
}
}
/**
* 关闭管理器(保存并停止自动保存)
*/
async close(): Promise<void> {
this.stopAutoSave();
await this.save();
}
/**
* 清理旧会话
*/
async cleanup(keepCount?: number): Promise<number> {
return this.storage.cleanupOldSessions(keepCount);
}
}
// 导出默认实例
export const sessionManager = new SessionManager();