UNPKG

mini-claude-code

Version:

Advanced AI-powered coding assistant with streaming responses, context memory, intelligent auto-completion, error handling, test generation, and task planning

366 lines (306 loc) 10.9 kB
const fs = require('fs-extra'); const path = require('path'); class ContextMemory { constructor(storageDir = '.mini-claude-memory') { this.storageDir = storageDir; this.conversationHistory = []; this.userPreferences = {}; this.projectMemory = {}; this.codeSnippets = []; this.sessionId = this.generateSessionId(); this.maxHistorySize = 100; // 最大对话记录数 this.maxCodeSnippets = 50; // 最大代码片段数 // 确保存储目录存在 this.ensureStorageDir(); // 加载已有的记忆 this.loadMemory(); } /** * 生成会话 ID */ generateSessionId() { return `session_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`; } /** * 确保存储目录存在 */ async ensureStorageDir() { try { await fs.ensureDir(this.storageDir); } catch (error) { console.warn('Warning: Could not create memory storage directory:', error.message); } } /** * 加载已有的记忆数据 */ async loadMemory() { try { // 加载对话历史 const historyPath = path.join(this.storageDir, 'conversation_history.json'); if (await fs.pathExists(historyPath)) { const historyData = await fs.readJson(historyPath); this.conversationHistory = historyData.slice(-this.maxHistorySize); } // 加载用户偏好 const preferencesPath = path.join(this.storageDir, 'user_preferences.json'); if (await fs.pathExists(preferencesPath)) { this.userPreferences = await fs.readJson(preferencesPath); } // 加载项目记忆 const projectPath = path.join(this.storageDir, 'project_memory.json'); if (await fs.pathExists(projectPath)) { this.projectMemory = await fs.readJson(projectPath); } // 加载代码片段 const snippetsPath = path.join(this.storageDir, 'code_snippets.json'); if (await fs.pathExists(snippetsPath)) { const snippetsData = await fs.readJson(snippetsPath); this.codeSnippets = snippetsData.slice(-this.maxCodeSnippets); } } catch (error) { console.warn('Warning: Could not load memory data:', error.message); } } /** * 保存记忆数据到磁盘 */ async saveMemory() { try { // 保存对话历史 const historyPath = path.join(this.storageDir, 'conversation_history.json'); await fs.writeJson(historyPath, this.conversationHistory, { spaces: 2 }); // 保存用户偏好 const preferencesPath = path.join(this.storageDir, 'user_preferences.json'); await fs.writeJson(preferencesPath, this.userPreferences, { spaces: 2 }); // 保存项目记忆 const projectPath = path.join(this.storageDir, 'project_memory.json'); await fs.writeJson(projectPath, this.projectMemory, { spaces: 2 }); // 保存代码片段 const snippetsPath = path.join(this.storageDir, 'code_snippets.json'); await fs.writeJson(snippetsPath, this.codeSnippets, { spaces: 2 }); } catch (error) { console.warn('Warning: Could not save memory data:', error.message); } } /** * 添加对话到历史记录 */ async addConversation(userInput, aiResponse, context = {}) { const conversation = { id: `conv_${Date.now()}_${Math.random().toString(36).substr(2, 6)}`, sessionId: this.sessionId, timestamp: new Date().toISOString(), userInput, aiResponse, context: { projectPath: context.projectPath || null, language: context.language || null, framework: context.framework || null, commandType: context.commandType || null } }; this.conversationHistory.push(conversation); // 保持历史记录在限制范围内 if (this.conversationHistory.length > this.maxHistorySize) { this.conversationHistory = this.conversationHistory.slice(-this.maxHistorySize); } // 异步保存 this.saveMemory(); return conversation.id; } /** * 添加代码片段记忆 */ async addCodeSnippet(code, description, language, context = {}) { const snippet = { id: `code_${Date.now()}_${Math.random().toString(36).substr(2, 6)}`, sessionId: this.sessionId, timestamp: new Date().toISOString(), code, description, language, context: { projectPath: context.projectPath || null, framework: context.framework || null, fileType: context.fileType || null }, useCount: 0 }; this.codeSnippets.push(snippet); // 保持代码片段在限制范围内 if (this.codeSnippets.length > this.maxCodeSnippets) { this.codeSnippets = this.codeSnippets.slice(-this.maxCodeSnippets); } this.saveMemory(); return snippet.id; } /** * 更新用户偏好 */ async updateUserPreferences(preferences) { this.userPreferences = { ...this.userPreferences, ...preferences, lastUpdated: new Date().toISOString() }; this.saveMemory(); } /** * 更新项目记忆 */ async updateProjectMemory(projectPath, projectInfo) { this.projectMemory[projectPath] = { ...this.projectMemory[projectPath], ...projectInfo, lastAccessed: new Date().toISOString() }; this.saveMemory(); } /** * 获取相关的对话历史 */ getRelevantHistory(query, maxResults = 5) { const queryLower = query.toLowerCase(); const scoredHistory = this.conversationHistory.map(conv => { let score = 0; // 基于内容相似性评分 if (conv.userInput.toLowerCase().includes(queryLower)) score += 3; if (conv.aiResponse.toLowerCase().includes(queryLower)) score += 2; // 基于时间新近性评分 const daysSince = (Date.now() - new Date(conv.timestamp).getTime()) / (1000 * 60 * 60 * 24); score += Math.max(0, 2 - daysSince / 7); // 一周内的对话有额外分数 // 基于会话相关性评分 if (conv.sessionId === this.sessionId) score += 1; return { ...conv, score }; }); return scoredHistory .filter(conv => conv.score > 0) .sort((a, b) => b.score - a.score) .slice(0, maxResults); } /** * 搜索相关代码片段 */ searchCodeSnippets(query, language = null, maxResults = 3) { const queryLower = query.toLowerCase(); let filteredSnippets = this.codeSnippets; // 按语言过滤 if (language) { filteredSnippets = filteredSnippets.filter(snippet => snippet.language === language ); } const scoredSnippets = filteredSnippets.map(snippet => { let score = 0; // 基于描述相似性评分 if (snippet.description.toLowerCase().includes(queryLower)) score += 3; if (snippet.code.toLowerCase().includes(queryLower)) score += 2; // 基于使用频率评分 score += Math.min(snippet.useCount, 5) * 0.5; // 基于时间新近性评分 const daysSince = (Date.now() - new Date(snippet.timestamp).getTime()) / (1000 * 60 * 60 * 24); score += Math.max(0, 1 - daysSince / 30); // 一个月内的代码有额外分数 return { ...snippet, score }; }); const results = scoredSnippets .filter(snippet => snippet.score > 0) .sort((a, b) => b.score - a.score) .slice(0, maxResults); // 增加使用计数 results.forEach(snippet => { const original = this.codeSnippets.find(s => s.id === snippet.id); if (original) { original.useCount++; } }); return results; } /** * 生成上下文提示词 */ generateContextPrompt(currentQuery, projectInfo = null) { let contextPrompt = ''; // 添加相关历史对话 const relevantHistory = this.getRelevantHistory(currentQuery, 3); if (relevantHistory.length > 0) { contextPrompt += '相关对话历史:\n'; relevantHistory.forEach((conv, index) => { contextPrompt += `${index + 1}. 用户: ${conv.userInput}\n AI: ${conv.aiResponse.substring(0, 200)}...\n\n`; }); } // 添加用户偏好 if (Object.keys(this.userPreferences).length > 0) { contextPrompt += '用户偏好:\n'; if (this.userPreferences.preferredLanguage) { contextPrompt += `- 偏好编程语言: ${this.userPreferences.preferredLanguage}\n`; } if (this.userPreferences.codeStyle) { contextPrompt += `- 代码风格: ${this.userPreferences.codeStyle}\n`; } if (this.userPreferences.responseStyle) { contextPrompt += `- 回答风格: ${this.userPreferences.responseStyle}\n`; } contextPrompt += '\n'; } // 添加项目上下文 if (projectInfo) { contextPrompt += '当前项目信息:\n'; contextPrompt += `- 路径: ${projectInfo.path || '未知'}\n`; contextPrompt += `- 主要语言: ${Object.keys(projectInfo.languages || {}).join(', ') || '未知'}\n`; contextPrompt += `- 框架: ${(projectInfo.frameworks || []).map(f => f.name).join(', ') || '未知'}\n`; contextPrompt += '\n'; } // 添加相关代码片段 const relevantCode = this.searchCodeSnippets(currentQuery, projectInfo?.mainLanguage, 2); if (relevantCode.length > 0) { contextPrompt += '相关代码片段:\n'; relevantCode.forEach((snippet, index) => { contextPrompt += `${index + 1}. ${snippet.description} (${snippet.language}):\n`; contextPrompt += `\`\`\`${snippet.language}\n${snippet.code.substring(0, 300)}\n\`\`\`\n\n`; }); } return contextPrompt; } /** * 清理旧数据 */ async cleanup() { const thirtyDaysAgo = new Date(Date.now() - 30 * 24 * 60 * 60 * 1000); // 清理旧对话 this.conversationHistory = this.conversationHistory.filter(conv => new Date(conv.timestamp) > thirtyDaysAgo ); // 清理不常用的代码片段 this.codeSnippets = this.codeSnippets .filter(snippet => new Date(snippet.timestamp) > thirtyDaysAgo || snippet.useCount > 0 ) .slice(-this.maxCodeSnippets); this.saveMemory(); } /** * 获取记忆统计信息 */ getStats() { return { conversationCount: this.conversationHistory.length, codeSnippetCount: this.codeSnippets.length, userPreferences: Object.keys(this.userPreferences).length, projectsRemembered: Object.keys(this.projectMemory).length, currentSessionId: this.sessionId, storageDir: this.storageDir }; } /** * 重置所有记忆 */ async resetMemory() { this.conversationHistory = []; this.userPreferences = {}; this.projectMemory = {}; this.codeSnippets = []; await this.saveMemory(); } } module.exports = ContextMemory;