Skip to main content
Glama
conversation.ts6.93 kB
/** * 专家多轮对话模块 * 支持与特定专家进行多轮对话 */ import type { ChatMessage, ModelAdapter } from '../adapters/base.js'; import type { ModelTier } from './tech-lead.js'; /** 对话消息 */ export interface ConversationMessage { role: 'user' | 'assistant'; content: string; timestamp: string; } /** 对话会话 */ export interface ConversationSession { /** 会话 ID */ id: string; /** 专家 ID */ expertId: string; /** 专家名称 */ expertName: string; /** 专家角色描述 */ expertRole: string; /** 模型级别 */ tier: ModelTier; /** 对话历史 */ messages: ConversationMessage[]; /** 创建时间 */ createdAt: string; /** 最后活动时间 */ lastActiveAt: string; /** 是否活跃 */ active: boolean; } /** * 专家对话管理器 */ export class ExpertConversation { private sessions: Map<string, ConversationSession> = new Map(); private readonly maxHistoryLength: number; constructor(maxHistoryLength = 20) { this.maxHistoryLength = maxHistoryLength; } /** * 创建新的对话会话 */ createSession(params: { expertId: string; expertName: string; expertRole: string; tier: ModelTier; }): ConversationSession { const id = this.generateId(); const now = new Date().toISOString(); const session: ConversationSession = { id, expertId: params.expertId, expertName: params.expertName, expertRole: params.expertRole, tier: params.tier, messages: [], createdAt: now, lastActiveAt: now, active: true, }; this.sessions.set(id, session); return session; } /** * 获取会话 */ getSession(sessionId: string): ConversationSession | undefined { return this.sessions.get(sessionId); } /** * 发送消息并获取回复 */ async chat( sessionId: string, message: string, adapter: ModelAdapter ): Promise<string> { const session = this.sessions.get(sessionId); if (!session) { throw new Error(`会话 ${sessionId} 不存在`); } if (!session.active) { throw new Error(`会话 ${sessionId} 已关闭`); } // 添加用户消息 session.messages.push({ role: 'user', content: message, timestamp: new Date().toISOString(), }); // 构建聊天消息 const chatMessages: ChatMessage[] = [ { role: 'system', content: session.expertRole }, ...session.messages.map(m => ({ role: m.role as 'user' | 'assistant', content: m.content, })), ]; // 获取回复 const response = await adapter.chat(chatMessages); // 添加助手回复 session.messages.push({ role: 'assistant', content: response, timestamp: new Date().toISOString(), }); // 限制历史长度 if (session.messages.length > this.maxHistoryLength * 2) { session.messages = session.messages.slice(-this.maxHistoryLength * 2); } session.lastActiveAt = new Date().toISOString(); return response; } /** * 关闭会话 */ closeSession(sessionId: string): boolean { const session = this.sessions.get(sessionId); if (!session) return false; session.active = false; return true; } /** * 重新激活会话 */ reopenSession(sessionId: string): boolean { const session = this.sessions.get(sessionId); if (!session) return false; session.active = true; session.lastActiveAt = new Date().toISOString(); return true; } /** * 获取会话历史 */ getHistory(sessionId: string): ConversationMessage[] { const session = this.sessions.get(sessionId); return session ? [...session.messages] : []; } /** * 清除会话历史 */ clearHistory(sessionId: string): boolean { const session = this.sessions.get(sessionId); if (!session) return false; session.messages = []; return true; } /** * 删除会话 */ deleteSession(sessionId: string): boolean { return this.sessions.delete(sessionId); } /** * 列出所有活跃会话 */ listActiveSessions(): ConversationSession[] { return Array.from(this.sessions.values()) .filter(s => s.active) .sort((a, b) => new Date(b.lastActiveAt).getTime() - new Date(a.lastActiveAt).getTime() ); } /** * 列出所有会话 */ listAllSessions(): ConversationSession[] { return Array.from(this.sessions.values()) .sort((a, b) => new Date(b.lastActiveAt).getTime() - new Date(a.lastActiveAt).getTime() ); } /** * 格式化会话列表 */ formatSessionList(): string { const sessions = this.listAllSessions(); if (sessions.length === 0) { return '暂无对话会话'; } const lines = ['## 💬 专家对话会话\n']; for (const session of sessions) { const statusEmoji = session.active ? '🟢' : '⚪'; const date = new Date(session.lastActiveAt).toLocaleString(); const msgCount = session.messages.length; lines.push(`- ${statusEmoji} **${session.expertName}** (\`${session.id}\`)`); lines.push(` 消息数: ${msgCount} | 最后活动: ${date}`); lines.push(''); } lines.push('使用 `expert_chat` 工具继续对话'); return lines.join('\n'); } /** * 格式化单个会话 */ formatSession(sessionId: string): string { const session = this.sessions.get(sessionId); if (!session) { return `会话 ${sessionId} 不存在`; } const lines = [ `## 💬 与 ${session.expertName} 的对话`, `**会话 ID**: \`${session.id}\``, `**状态**: ${session.active ? '活跃' : '已关闭'}`, `**消息数**: ${session.messages.length}`, '', '### 对话历史', '', ]; for (const msg of session.messages.slice(-10)) { // 最近 10 条 const role = msg.role === 'user' ? '👤 你' : `🤖 ${session.expertName}`; const time = new Date(msg.timestamp).toLocaleTimeString(); lines.push(`**${role}** (${time}):`); lines.push(msg.content.slice(0, 200) + (msg.content.length > 200 ? '...' : '')); lines.push(''); } return lines.join('\n'); } /** * 清理不活跃的会话 */ cleanupInactive(olderThanMinutes = 60): number { const cutoff = Date.now() - olderThanMinutes * 60 * 1000; let deleted = 0; for (const [id, session] of this.sessions) { if (!session.active) { const lastActive = new Date(session.lastActiveAt).getTime(); if (lastActive < cutoff) { this.sessions.delete(id); deleted++; } } } return deleted; } private generateId(): string { return `conv-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 6)}`; } } /** 全局对话管理器 */ export const globalConversation = new ExpertConversation();

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/7836246/claude-team-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server