/** * 会话存储管理 * 负责会话的 CRUD 操作 */ import type { ModelMessage } from 'ai'; import { SessionStorage, MessageStorage, PartStorage, TodoStorage } from './storage/index.js'; import type { SessionInfo, TodoItem } from './storage/index.js'; import { MessageConverter } from './message-converter.js'; import { generateSessionId } from './id.js'; /** * 会话摘要(用于列表展示) */ export interface SessionSummary { id: string; title: string; workdir: string; messageCount: number; createdAt: string; updatedAt: string; } /** * 运行时会话数据 */ export interface SessionData { id: string; projectId: string; parentId?: string; agentName?: string; createdAt: string; updatedAt: string; workdir: string; title?: string; messages: ModelMessage[]; discoveredTools: string[]; todos: TodoItem[]; } /** * 会话存储管理 */ export class SessionStore { private messageConverter: MessageConverter; constructor() { this.messageConverter = new MessageConverter(); } /** * 创建新会话 */ async create(projectId: string, workdir: string): Promise { const sessionInfo = await SessionStorage.create(projectId, workdir); return { id: sessionInfo.id, projectId: sessionInfo.projectId, createdAt: new Date(sessionInfo.createdAt).toISOString(), updatedAt: new Date(sessionInfo.updatedAt).toISOString(), workdir: sessionInfo.workdir, title: sessionInfo.title, messages: [], discoveredTools: sessionInfo.discoveredTools, todos: [], }; } /** * 加载会话(从存储重建) */ async load(projectId: string, sessionId: string): Promise { const sessionInfo = await SessionStorage.get(projectId, sessionId); if (!sessionInfo) return null; // 加载消息 const messages = await this.messageConverter.loadFromStorage(sessionId); // 加载 todos const todoList = await TodoStorage.get(sessionId); return { id: sessionInfo.id, projectId: sessionInfo.projectId, parentId: sessionInfo.parentId, agentName: sessionInfo.agentName, createdAt: new Date(sessionInfo.createdAt).toISOString(), updatedAt: new Date(sessionInfo.updatedAt).toISOString(), workdir: sessionInfo.workdir, title: sessionInfo.title, messages, discoveredTools: sessionInfo.discoveredTools, todos: todoList?.items || [], }; } /** * 保存会话信息 */ async save(session: SessionData): Promise { const sessionInfo: SessionInfo = { id: session.id, projectId: session.projectId, parentId: session.parentId, agentName: session.agentName, createdAt: new Date(session.createdAt).getTime(), updatedAt: Date.now(), workdir: session.workdir, title: session.title, discoveredTools: session.discoveredTools, stats: { messageCount: session.messages.length, inputTokens: 0, outputTokens: 0, }, }; await SessionStorage.save(sessionInfo); } /** * 同步消息到存储 */ async syncMessages(sessionId: string, messages: ModelMessage[]): Promise { await this.messageConverter.syncToStorage(sessionId, messages); } /** * 更新待办事项 */ async setTodos( sessionId: string, todos: Array<{ content: string; status: 'pending' | 'in_progress' | 'completed' }> ): Promise { const todoList = await TodoStorage.replace(sessionId, todos); return todoList.items; } /** * 列出项目的所有会话 */ async listByProject(projectId: string): Promise { const sessions = await SessionStorage.listByProject(projectId); return this.toSummaries(sessions); } /** * 列出所有会话 */ async listAll(): Promise { const sessions = await SessionStorage.listAll(); return this.toSummaries(sessions); } /** * 删除会话 */ async delete(projectId: string, sessionId: string): Promise { try { // 删除会话的消息和 Parts const messageInfos = await MessageStorage.listBySession(sessionId); for (const msg of messageInfos) { await PartStorage.removeByMessage(msg.id); } await MessageStorage.removeBySession(sessionId); // 删除 todos await TodoStorage.removeBySession(sessionId); // 删除会话信息 await SessionStorage.remove(projectId, sessionId); return true; } catch { return false; } } /** * 创建子会话(用于 Task 工具) */ createChildSession( projectId: string, parentId: string, agentName: string, workdir: string, title?: string ): SessionData { return { id: generateSessionId(), projectId, parentId, agentName, createdAt: new Date().toISOString(), updatedAt: new Date().toISOString(), workdir, title: title || `子任务 (@${agentName})`, messages: [], discoveredTools: [], todos: [], }; } /** * 保存子会话 */ async saveChildSession(session: SessionData): Promise { const sessionInfo: SessionInfo = { id: session.id, projectId: session.projectId, parentId: session.parentId, agentName: session.agentName, createdAt: new Date(session.createdAt).getTime(), updatedAt: Date.now(), workdir: session.workdir, title: session.title, discoveredTools: session.discoveredTools, }; await SessionStorage.save(sessionInfo); } /** * 转换为摘要列表 */ private toSummaries(sessions: SessionInfo[]): SessionSummary[] { return sessions.map((s) => ({ id: s.id, title: s.title || `会话 ${s.id}`, workdir: s.workdir, messageCount: s.stats?.messageCount || 0, createdAt: new Date(s.createdAt).toISOString(), updatedAt: new Date(s.updatedAt).toISOString(), })); } }