UNPKG

@restnfeel/agentc-starter-kit

Version:

한국어 기업용 CMS 모듈 - Task Master AI와 함께 빠르게 웹사이트를 구현할 수 있는 재사용 가능한 컴포넌트 시스템

206 lines (204 loc) 7.23 kB
class ConversationContextManager { constructor(config = {}) { this.conversations = new Map(); this.config = { maxMessages: 20, maxTokens: 4000, retainSystemMessages: true, contextTimeoutMs: 30 * 60 * 1000, // 30 minutes ...config, }; } createConversation(id, systemPrompt) { const context = { id, messages: [], createdAt: new Date(), updatedAt: new Date(), metadata: {}, }; if (systemPrompt) { context.messages.push({ id: this.generateMessageId(), role: "system", content: systemPrompt, timestamp: new Date(), }); } this.conversations.set(id, context); return context; } getConversation(id) { const conversation = this.conversations.get(id); if (!conversation) { return null; } // Check if conversation has expired if (this.config.contextTimeoutMs) { const now = Date.now(); const lastUpdate = conversation.updatedAt.getTime(); if (now - lastUpdate > this.config.contextTimeoutMs) { this.conversations.delete(id); return null; } } return conversation; } addMessage(conversationId, message) { let conversation = this.getConversation(conversationId); if (!conversation) { // Create new conversation if it doesn't exist conversation = this.createConversation(conversationId); } const chatMessage = { ...message, id: this.generateMessageId(), timestamp: new Date(), }; conversation.messages.push(chatMessage); conversation.updatedAt = new Date(); // Trim conversation if it exceeds limits this.trimConversation(conversation); return chatMessage; } updateMessage(conversationId, messageId, updates) { const conversation = this.getConversation(conversationId); if (!conversation) { return false; } const messageIndex = conversation.messages.findIndex((msg) => msg.id === messageId); if (messageIndex === -1) { return false; } conversation.messages[messageIndex] = { ...conversation.messages[messageIndex], ...updates, updatedAt: new Date(), }; conversation.updatedAt = new Date(); return true; } getConversationHistory(conversationId, lastN) { const conversation = this.getConversation(conversationId); if (!conversation) { return []; } const messages = conversation.messages; if (lastN && lastN > 0) { return messages.slice(-lastN); } return messages; } getConversationSummary(conversationId) { const conversation = this.getConversation(conversationId); if (!conversation) { return null; } const summary = { totalMessages: conversation.messages.length, userMessages: 0, assistantMessages: 0, systemMessages: 0, totalTokens: 0, }; for (const message of conversation.messages) { switch (message.role) { case "user": summary.userMessages++; break; case "assistant": summary.assistantMessages++; break; case "system": summary.systemMessages++; break; } // Simple token estimation (4 chars ≈ 1 token) summary.totalTokens += Math.ceil(message.content.length / 4); } return summary; } clearConversation(conversationId) { return this.conversations.delete(conversationId); } getAllConversations() { return Array.from(this.conversations.values()); } cleanupExpiredConversations() { if (!this.config.contextTimeoutMs) { return 0; } const now = Date.now(); let cleaned = 0; for (const [id, conversation] of this.conversations) { const lastUpdate = conversation.updatedAt.getTime(); if (now - lastUpdate > this.config.contextTimeoutMs) { this.conversations.delete(id); cleaned++; } } return cleaned; } trimConversation(conversation) { const messages = conversation.messages; // Separate system messages from conversation messages const systemMessages = messages.filter((msg) => msg.role === "system"); const conversationMessages = messages.filter((msg) => msg.role !== "system"); // Trim by message count if (conversationMessages.length > this.config.maxMessages) { const keepCount = this.config.maxMessages; conversationMessages.splice(0, conversationMessages.length - keepCount); } // Trim by token count if specified if (this.config.maxTokens) { let totalTokens = 0; const trimmedMessages = []; // Count tokens from the end (most recent messages) for (let i = conversationMessages.length - 1; i >= 0; i--) { const messageTokens = Math.ceil(conversationMessages[i].content.length / 4); if (totalTokens + messageTokens <= this.config.maxTokens) { trimmedMessages.unshift(conversationMessages[i]); totalTokens += messageTokens; } else { break; } } conversationMessages.splice(0, conversationMessages.length, ...trimmedMessages); } // Reconstruct conversation with system messages if (this.config.retainSystemMessages) { conversation.messages = [...systemMessages, ...conversationMessages]; } else { conversation.messages = conversationMessages; } } generateMessageId() { return `msg_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`; } // Update conversation metadata updateConversationMetadata(conversationId, metadata) { const conversation = this.getConversation(conversationId); if (!conversation) { return false; } conversation.metadata = { ...conversation.metadata, ...metadata }; conversation.updatedAt = new Date(); return true; } // Get statistics getManagerStats() { let totalMessages = 0; for (const conversation of this.conversations.values()) { totalMessages += conversation.messages.length; } return { totalConversations: this.conversations.size, totalMessages, config: this.config, }; } } export { ConversationContextManager }; //# sourceMappingURL=context-manager.js.map