UNPKG

@gongfu/memory

Version:

Intelligent memory layer for Gongfu using mem0

1,681 lines (1,674 loc) 57.8 kB
'use strict'; var mem0ai = require('mem0ai'); // src/memory-client.ts var MemoryClient = class { client; config; defaultUserId; defaultProjectId; constructor(config) { this.config = config; this.defaultUserId = config.userId || "default"; this.defaultProjectId = config.projectId; this.client = new mem0ai.Memory({ api_key: config.apiKey, ...config.config }); } /** * 添加记忆 */ async add(content, metadata) { const fullMetadata = { userId: this.defaultUserId, projectId: this.defaultProjectId, ...metadata, tags: metadata?.tags || [], createdAt: /* @__PURE__ */ new Date(), updatedAt: /* @__PURE__ */ new Date() }; const result = await this.client.add(content, { user_id: fullMetadata.userId, metadata: this.serializeMetadata(fullMetadata) }); return this.parseMemoryResult(result); } /** * 批量添加记忆 */ async batchAdd(memories) { const results = await Promise.all( memories.map(({ content, metadata }) => this.add(content, metadata)) ); return results; } /** * 搜索记忆 */ async search(query, options) { const searchParams = { query, user_id: options?.filter?.userId || this.defaultUserId, limit: options?.limit || 10 }; if (options?.filter) { searchParams.filters = this.buildFilters(options.filter); } const results = await this.client.search(searchParams); return results.map((result) => ({ memory: this.parseMemoryResult(result), score: result.score || 0, highlights: result.highlights })); } /** * 批量搜索 */ async batchSearch(queries, options) { const results = await Promise.all( queries.map((query) => this.search(query, options)) ); return results; } /** * 获取特定记忆 */ async get(memoryId) { try { const result = await this.client.get(memoryId); return result ? this.parseMemoryResult(result) : null; } catch (error) { console.error("\u83B7\u53D6\u8BB0\u5FC6\u5931\u8D25:", error); return null; } } /** * 更新记忆 */ async update(memoryId, content, metadata) { const existingMemory = await this.get(memoryId); if (!existingMemory) { throw new Error(`\u8BB0\u5FC6\u4E0D\u5B58\u5728: ${memoryId}`); } const updatedMetadata = { ...existingMemory.metadata, ...metadata, updatedAt: /* @__PURE__ */ new Date() }; const result = await this.client.update(memoryId, { data: content, metadata: this.serializeMetadata(updatedMetadata) }); return this.parseMemoryResult(result); } /** * 删除记忆 */ async delete(memoryId) { try { await this.client.delete(memoryId); return true; } catch (error) { console.error("\u5220\u9664\u8BB0\u5FC6\u5931\u8D25:", error); return false; } } /** * 删除所有记忆 */ async deleteAll(filter) { const memories = await this.search("*", { filter, limit: 1e4 }); const deletePromises = memories.map( ({ memory }) => this.delete(memory.id) ); const results = await Promise.all(deletePromises); return results.filter((success) => success).length; } /** * 导出用户记忆 */ async exportUserMemories(userId) { const targetUserId = userId || this.defaultUserId; const memories = await this.search("*", { filter: { userId: targetUserId }, limit: 1e4 }); const byCategory = {}; let oldestDate = /* @__PURE__ */ new Date(); let newestDate = /* @__PURE__ */ new Date(0); memories.forEach(({ memory }) => { const category = memory.metadata.category || "other"; byCategory[category] = (byCategory[category] || 0) + 1; if (memory.createdAt < oldestDate) oldestDate = memory.createdAt; if (memory.createdAt > newestDate) newestDate = memory.createdAt; }); return { version: "1.0", exportedAt: /* @__PURE__ */ new Date(), userId: targetUserId, projectId: this.defaultProjectId, memories: memories.map(({ memory }) => memory), statistics: { totalCount: memories.length, byCategory, dateRange: { oldest: oldestDate, newest: newestDate } } }; } /** * 导入记忆 */ async importMemories(data) { let imported = 0; for (const memory of data.memories) { try { await this.add(memory.content, memory.metadata); imported++; } catch (error) { console.error("\u5BFC\u5165\u8BB0\u5FC6\u5931\u8D25:", error, memory); } } return imported; } /** * 清除用户记忆 */ async clearUserMemories(userId) { return this.deleteAll({ userId: userId || this.defaultUserId }); } /** * 清除项目记忆 */ async clearProjectMemories(projectId) { return this.deleteAll({ projectId: projectId || this.defaultProjectId }); } /** * 获取记忆统计 */ async getStats(filter) { const memories = await this.search("*", { filter, limit: 1e4 }); const byCategory = {}; const byUser = {}; let totalScore = 0; memories.forEach(({ memory, score }) => { const category = memory.metadata.category || "other"; byCategory[category] = (byCategory[category] || 0) + 1; const userId = memory.metadata.userId; byUser[userId] = (byUser[userId] || 0) + 1; totalScore += score; }); return { total: memories.length, byCategory, byUser, averageScore: memories.length > 0 ? totalScore / memories.length : 0 }; } /** * 预热缓存 */ async warmCache(options) { const { userId, categories, limit = 100 } = options; const filter = { userId: userId || this.defaultUserId }; if (categories?.length) { filter.category = categories; } await this.search("*", { filter, limit }); } // ============= 私有方法 ============= /** * 序列化元数据 */ serializeMetadata(metadata) { return { ...metadata, createdAt: metadata.createdAt?.toISOString(), updatedAt: metadata.updatedAt?.toISOString(), lastAccessedAt: metadata.lastAccessedAt?.toISOString() }; } /** * 解析记忆结果 */ parseMemoryResult(result) { const metadata = result.metadata || {}; return { id: result.id || result.memory_id, content: result.memory || result.data || result.content, embedding: result.embedding, metadata: { userId: metadata.userId || this.defaultUserId, projectId: metadata.projectId || this.defaultProjectId, category: metadata.category, tags: metadata.tags || [], ttl: metadata.ttl, importance: metadata.importance, accessCount: metadata.accessCount || 0, lastAccessedAt: metadata.lastAccessedAt ? new Date(metadata.lastAccessedAt) : void 0, createdAt: metadata.createdAt ? new Date(metadata.createdAt) : /* @__PURE__ */ new Date(), updatedAt: metadata.updatedAt ? new Date(metadata.updatedAt) : /* @__PURE__ */ new Date() }, score: result.score, createdAt: new Date(metadata.createdAt || Date.now()), updatedAt: new Date(metadata.updatedAt || Date.now()) }; } /** * 构建过滤器 */ buildFilters(filter) { const filters = {}; if (filter.projectId) { filters.projectId = filter.projectId; } if (filter.category) { filters.category = Array.isArray(filter.category) ? { $in: filter.category } : filter.category; } if (filter.tags?.length) { filters.tags = { $in: filter.tags }; } if (filter.timeRange) { filters.createdAt = {}; if (filter.timeRange.start) { filters.createdAt.$gte = filter.timeRange.start.toISOString(); } if (filter.timeRange.end) { filters.createdAt.$lte = filter.timeRange.end.toISOString(); } } if (filter.importance) { filters.importance = {}; if (filter.importance.min !== void 0) { filters.importance.$gte = filter.importance.min; } if (filter.importance.max !== void 0) { filters.importance.$lte = filter.importance.max; } } return filters; } }; // src/adapters/task-memory.ts var TaskMemoryAdapter = class { memory; userId; projectId; constructor(config) { this.memory = new MemoryClient(config); this.userId = config.userId || "default"; this.projectId = config.projectId; } /** * 学习任务模式 * 记录任务的完成情况,用于未来的智能建议 */ async learnTaskPattern(params) { const { task, outcome } = params; const patternDescription = this.buildTaskPatternDescription(task, outcome); await this.memory.add(patternDescription, { category: "task_pattern", tags: [ ...task.tags || [], task.type, `priority:${task.priority || "normal"}`, `status:${outcome.status}` ], importance: this.calculateImportance(outcome) }); if (outcome.challenges?.length) { for (const challenge of outcome.challenges) { await this.memory.add( `\u4EFB\u52A1 "${task.name}" \u9047\u5230\u7684\u6311\u6218: ${challenge}`, { category: "learning", tags: ["challenge", task.type] } ); } } if (outcome.learnings?.length) { for (const learning of outcome.learnings) { await this.memory.add( `\u4ECE\u4EFB\u52A1 "${task.name}" \u4E2D\u5B66\u5230: ${learning}`, { category: "learning", tags: ["best_practice", task.type] } ); } } } /** * 获取任务建议 * 基于历史记忆提供智能建议 */ async suggestTask(description, context) { const similarPatterns = await this.memory.search(description, { filter: { category: "task_pattern", tags: context?.tags }, limit: 10 }); const suggestion = this.analyzePatterns(similarPatterns, description); const challenges = await this.memory.search(description, { filter: { category: "learning", tags: ["challenge"] }, limit: 5 }); const bestPractices = await this.memory.search(description, { filter: { category: "learning", tags: ["best_practice"] }, limit: 5 }); return { ...suggestion, tips: [ ...challenges.map((r) => `\u6CE8\u610F: ${r.memory.content}`), ...bestPractices.map((r) => `\u5EFA\u8BAE: ${r.memory.content}`) ] }; } /** * 查找相似的历史任务 */ async findSimilarTasks(task, limit = 5) { const query = this.buildTaskQuery(task); const results = await this.memory.search(query, { filter: { category: "task_pattern" }, limit }); return results.map((result) => ({ task: this.extractTaskFromMemory(result.memory.content), similarity: result.score })); } /** * 获取任务完成时间预测 */ async predictTaskTime(task) { const similarTasks = await this.findSimilarTasks(task, 10); if (similarTasks.length === 0) { return { estimated: "\u672A\u77E5", confidence: 0, basedOn: 0 }; } const times = similarTasks.map(({ task: task2 }) => task2.actualTime || task2.estimatedTime).filter(Boolean).map((time) => this.parseTimeToHours(time)); const avgHours = times.reduce((sum, h) => sum + h, 0) / times.length; const estimated = this.formatHours(avgHours); const avgSimilarity = similarTasks.reduce( (sum, { similarity }) => sum + similarity, 0 ) / similarTasks.length; const confidence = Math.min(avgSimilarity * (times.length / 10), 1); return { estimated, confidence, basedOn: times.length }; } /** * 获取任务依赖建议 */ async suggestDependencies(task) { const query = `${task.name || ""} ${task.type || ""} \u4F9D\u8D56 \u524D\u7F6E\u4EFB\u52A1`; const results = await this.memory.search(query, { filter: { category: "task_pattern" }, limit: 10 }); const dependencies = /* @__PURE__ */ new Set(); results.forEach((result) => { const deps = this.extractDependencies(result.memory.content); deps.forEach((dep) => dependencies.add(dep)); }); return Array.from(dependencies); } /** * 记录任务执行反馈 */ async recordFeedback(taskId, feedback) { await this.memory.add( `\u4EFB\u52A1 ${taskId} \u7684\u53CD\u9988: \u51C6\u786E\u5EA6 ${feedback.accuracy}, \u6709\u7528\u6027 ${feedback.helpful ? "\u662F" : "\u5426"}` + (feedback.comments ? `, \u8BC4\u8BBA: ${feedback.comments}` : ""), { category: "feedback", tags: ["task_feedback"], importance: feedback.helpful ? 0.8 : 0.2 } ); } /** * 获取任务统计信息 */ async getTaskStats() { const stats = await this.memory.getStats({ category: "task_pattern" }); const patterns = await this.memory.search("*", { filter: { category: "task_pattern" }, limit: 1e3 }); const byType = {}; const byPriority = {}; let completedCount = 0; patterns.forEach(({ memory }) => { memory.metadata.tags?.forEach((tag) => { if (tag.startsWith("priority:")) { const priority = tag.replace("priority:", ""); byPriority[priority] = (byPriority[priority] || 0) + 1; } if (tag.includes("completed")) { completedCount++; } }); const typeTag = memory.metadata.tags?.find( (tag) => !tag.includes(":") && !tag.includes("completed") ); if (typeTag) { byType[typeTag] = (byType[typeTag] || 0) + 1; } }); return { totalPatterns: stats.total, byType, byPriority, averageCompletionRate: stats.total > 0 ? completedCount / stats.total : 0 }; } // ============= 私有方法 ============= /** * 构建任务模式描述 */ buildTaskPatternDescription(task, outcome) { const parts = [ `\u4EFB\u52A1: ${task.name}`, `\u7C7B\u578B: ${task.type}`, `\u4F18\u5148\u7EA7: ${task.priority || "normal"}`, `\u9884\u4F30\u65F6\u95F4: ${task.estimatedTime || "\u672A\u77E5"}`, `\u5B9E\u9645\u65F6\u95F4: ${outcome.actualTime || task.actualTime || "\u672A\u77E5"}`, `\u7ED3\u679C: ${outcome.status}`, `\u8D28\u91CF: ${outcome.quality || "\u672A\u8BC4\u4F30"}` ]; if (task.tags?.length) { parts.push(`\u6807\u7B7E: ${task.tags.join(", ")}`); } if (task.dependencies?.length) { parts.push(`\u4F9D\u8D56: ${task.dependencies.join(", ")}`); } if (outcome.wouldDoAgain?.length) { parts.push(`\u7ECF\u9A8C: ${outcome.wouldDoAgain.join("; ")}`); } return parts.join("\n"); } /** * 计算记忆重要性 */ calculateImportance(outcome) { let importance = 0.5; if (outcome.status === "completed") { importance += 0.2; } const qualityScores = { excellent: 0.3, good: 0.2, fair: 0.1, poor: -0.1 }; importance += qualityScores[outcome.quality || "fair"] || 0; if (outcome.learnings?.length) { importance += 0.1; } return Math.max(0, Math.min(1, importance)); } /** * 分析模式,生成建议 */ analyzePatterns(patterns, description) { if (patterns.length === 0) { return { estimatedTime: "3d", suggestedPriority: "normal", suggestedTags: [], similarTasks: [], confidence: 0 }; } const priorities = {}; const tags = {}; const times = []; const similarTasks = []; patterns.forEach(({ memory, score }) => { const task = this.extractTaskFromMemory(memory.content); if (task.priority) { priorities[task.priority] = (priorities[task.priority] || 0) + score; } task.tags?.forEach((tag) => { if (!tag.includes(":")) { tags[tag] = (tags[tag] || 0) + score; } }); const time = task.actualTime || task.estimatedTime; if (time) { times.push(this.parseTimeToHours(time)); } if (score > 0.7) { similarTasks.push({ id: task.id, name: task.name, similarity: score }); } }); const suggestedPriority = this.getMostLikely(priorities) || "normal"; const suggestedTags = Object.entries(tags).sort(([, a], [, b]) => b - a).slice(0, 5).map(([tag]) => tag); const estimatedTime = times.length > 0 ? this.formatHours(times.reduce((a, b) => a + b) / times.length) : "3d"; const confidence = Math.min( patterns[0].score * (patterns.length / 10), 1 ); return { estimatedTime, suggestedPriority, suggestedTags, similarTasks: similarTasks.slice(0, 3), confidence }; } /** * 从记忆内容提取任务信息 */ extractTaskFromMemory(content) { const lines = content.split("\n"); const task = { tags: [] }; lines.forEach((line) => { const [key, value] = line.split(": "); switch (key) { case "\u4EFB\u52A1": task.name = value; task.id = `task-${Date.now()}`; break; case "\u7C7B\u578B": task.type = value; break; case "\u4F18\u5148\u7EA7": task.priority = value; break; case "\u9884\u4F30\u65F6\u95F4": task.estimatedTime = value; break; case "\u5B9E\u9645\u65F6\u95F4": task.actualTime = value; break; case "\u6807\u7B7E": task.tags = value.split(", "); break; case "\u4F9D\u8D56": task.dependencies = value.split(", "); break; } }); return task; } /** * 构建任务查询 */ buildTaskQuery(task) { const parts = []; if (task.name) parts.push(task.name); if (task.type) parts.push(`\u7C7B\u578B: ${task.type}`); if (task.tags?.length) parts.push(task.tags.join(" ")); if (task.description) parts.push(task.description); return parts.join(" "); } /** * 解析时间字符串为小时数 */ parseTimeToHours(time) { const match = time.match(/(\d+)([hdwm])/); if (!match) return 8; const [, num, unit] = match; const value = parseInt(num); switch (unit) { case "h": return value; case "d": return value * 8; case "w": return value * 40; case "m": return value * 160; default: return 8; } } /** * 格式化小时数为时间字符串 */ formatHours(hours) { if (hours < 8) return `${Math.round(hours)}h`; if (hours < 40) return `${Math.round(hours / 8)}d`; if (hours < 160) return `${Math.round(hours / 40)}w`; return `${Math.round(hours / 160)}m`; } /** * 提取依赖关系 */ extractDependencies(content) { const deps = []; const lines = content.split("\n"); lines.forEach((line) => { if (line.includes("\u4F9D\u8D56:")) { const depList = line.split("\u4F9D\u8D56:")[1].trim(); deps.push(...depList.split(", ")); } }); return deps; } /** * 获取最可能的选项 */ getMostLikely(scores) { const entries = Object.entries(scores); if (entries.length === 0) return void 0; return entries.reduce((a, b) => a[1] > b[1] ? a : b)[0]; } }; // src/adapters/agent-memory.ts var AgentMemoryAdapter = class { memory; userId; projectId; constructor(config) { this.memory = new MemoryClient(config); this.userId = config.userId || "default"; this.projectId = config.projectId; } /** * 记录 Agent 使用情况 */ async recordUsage(usage) { const { agentId, taskType, performance, userSatisfaction, context } = usage; const usageDescription = [ `Agent: ${agentId}`, `\u4EFB\u52A1\u7C7B\u578B: ${taskType}`, `\u901F\u5EA6: ${performance.speed}`, `\u8D28\u91CF: ${performance.quality}`, `\u51C6\u786E\u5EA6: ${performance.accuracy}`, `\u7528\u6237\u6EE1\u610F\u5EA6: ${userSatisfaction}/5`, context ? `\u4E0A\u4E0B\u6587: ${JSON.stringify(context)}` : "" ].filter(Boolean).join("\n"); await this.memory.add(usageDescription, { category: "agent_usage", tags: [ agentId, taskType, `speed:${performance.speed}`, `quality:${performance.quality}`, `satisfaction:${userSatisfaction}` ], importance: this.calculateUsageImportance(performance, userSatisfaction) }); await this.updateAgentPerformance(agentId, taskType, performance, userSatisfaction); } /** * 推荐合适的 Agent */ async recommendAgents(context, limit = 3) { const query = this.buildContextQuery(context); const results = await this.memory.search(query, { filter: { category: "agent_usage", tags: context.techStack }, limit: 20 }); const agentScores = this.analyzeAgentPerformance(results, context); const recommendations = await Promise.all( agentScores.slice(0, limit).map(async ({ agentId, score, reason }) => { const performance = await this.getAgentPerformance(agentId, context.taskType); return { agentId, score, reason, historicalPerformance: performance }; }) ); return recommendations; } /** * 学习 Agent 协作模式 */ async learnCollaborationPattern(params) { const { agents, taskType, outcome, pattern, context } = params; const patternDescription = [ `\u534F\u4F5C\u6A21\u5F0F: ${pattern}`, `Agents: ${agents.join(" -> ")}`, `\u4EFB\u52A1\u7C7B\u578B: ${taskType}`, `\u7ED3\u679C: ${outcome}`, context ? `\u4E0A\u4E0B\u6587: ${JSON.stringify(context)}` : "" ].filter(Boolean).join("\n"); await this.memory.add(patternDescription, { category: "agent_usage", tags: [ ...agents, taskType, `pattern:${pattern}`, `outcome:${outcome}`, "collaboration" ], importance: outcome === "success" ? 0.9 : 0.3 }); } /** * 获取推荐的协作模式 */ async getCollaborationPatterns(taskType, availableAgents) { const results = await this.memory.search( `\u534F\u4F5C\u6A21\u5F0F ${taskType} ${availableAgents.join(" ")}`, { filter: { category: "agent_usage", tags: ["collaboration"] }, limit: 10 } ); return this.parseCollaborationPatterns(results, availableAgents); } /** * 记录用户反馈 */ async recordFeedback(feedback) { const { agentId, taskId, rating, comment, timestamp } = feedback; await this.memory.add( `Agent ${agentId} \u53CD\u9988: \u8BC4\u5206 ${rating}/5` + (comment ? `, \u8BC4\u8BBA: ${comment}` : "") + `, \u4EFB\u52A1: ${taskId}`, { category: "feedback", tags: [agentId, "agent_feedback", `rating:${rating}`], importance: rating >= 4 ? 0.8 : rating <= 2 ? 0.9 : 0.5 } ); } /** * 获取 Agent 性能统计 */ async getAgentPerformance(agentId, taskType) { const searchQuery = taskType ? `Agent: ${agentId} \u4EFB\u52A1\u7C7B\u578B: ${taskType}` : `Agent: ${agentId}`; const results = await this.memory.search(searchQuery, { filter: { category: "agent_usage", tags: [agentId] }, limit: 100 }); if (results.length === 0) return null; return this.calculatePerformanceMetrics(results); } /** * 获取 Agent 专长 */ async getAgentSpecialties(agentId) { const results = await this.memory.search(`Agent: ${agentId}`, { filter: { category: "agent_usage", tags: [agentId, "quality:high"] }, limit: 50 }); const taskTypes = {}; results.forEach(({ memory }) => { const taskType = this.extractTaskType(memory.content); if (taskType) { taskTypes[taskType] = (taskTypes[taskType] || 0) + 1; } }); return Object.entries(taskTypes).sort(([, a], [, b]) => b - a).slice(0, 5).map(([type]) => type); } /** * 获取 Agent 对比分析 */ async compareAgents(agentIds, taskType) { const comparison = {}; for (const agentId of agentIds) { const performance = await this.getAgentPerformance(agentId, taskType); const specialties = await this.getAgentSpecialties(agentId); const analysis = await this.analyzeAgentStrengthsWeaknesses(agentId); comparison[agentId] = { performance, specialties, ...analysis }; } return comparison; } /** * 获取 Agent 使用趋势 */ async getUsageTrends(agentId, days = 30) { const startDate = /* @__PURE__ */ new Date(); startDate.setDate(startDate.getDate() - days); const results = await this.memory.search(`Agent: ${agentId}`, { filter: { category: "agent_usage", tags: [agentId], timeRange: { start: startDate, end: /* @__PURE__ */ new Date() } }, limit: 1e3 }); return this.calculateUsageTrends(results, days); } // ============= 私有方法 ============= /** * 更新 Agent 性能统计 */ async updateAgentPerformance(agentId, taskType, performance, satisfaction) { const performanceUpdate = [ `Agent ${agentId} \u6027\u80FD\u66F4\u65B0`, `\u4EFB\u52A1\u7C7B\u578B: ${taskType}`, `\u901F\u5EA6: ${performance.speed}`, `\u8D28\u91CF: ${performance.quality}`, `\u51C6\u786E\u5EA6: ${performance.accuracy}`, `\u6EE1\u610F\u5EA6: ${satisfaction}`, `\u65F6\u95F4: ${(/* @__PURE__ */ new Date()).toISOString()}` ].join("\n"); await this.memory.add(performanceUpdate, { category: "agent_usage", tags: [ agentId, taskType, "performance_update" ], importance: 0.7 }); } /** * 计算使用重要性 */ calculateUsageImportance(performance, satisfaction) { let importance = 0.5; const speedScore = { fast: 0.1, normal: 0, slow: -0.1 }; const qualityScore = { high: 0.2, medium: 0.1, low: -0.1 }; importance += speedScore[performance.speed] || 0; importance += qualityScore[performance.quality] || 0; importance += performance.accuracy * 0.2; importance += satisfaction / 5 * 0.2; return Math.max(0, Math.min(1, importance)); } /** * 构建上下文查询 */ buildContextQuery(context) { const parts = [ `\u4EFB\u52A1\u7C7B\u578B: ${context.taskType}`, context.complexity ? `\u590D\u6742\u5EA6: ${context.complexity}` : "", context.techStack?.length ? `\u6280\u672F\u6808: ${context.techStack.join(" ")}` : "", context.requirements?.join(" ") || "" ].filter(Boolean); return parts.join(" "); } /** * 分析 Agent 性能 */ analyzeAgentPerformance(results, context) { const agentScores = {}; results.forEach(({ memory, score }) => { const agentId = this.extractAgentId(memory.content); if (!agentId) return; if (!agentScores[agentId]) { agentScores[agentId] = { totalScore: 0, count: 0, reasons: /* @__PURE__ */ new Set() }; } agentScores[agentId].totalScore += score; agentScores[agentId].count++; if (memory.content.includes("\u8D28\u91CF: high")) { agentScores[agentId].reasons.add("\u5386\u53F2\u8868\u73B0\u4F18\u79C0"); } if (memory.content.includes(`\u4EFB\u52A1\u7C7B\u578B: ${context.taskType}`)) { agentScores[agentId].reasons.add("\u64C5\u957F\u6B64\u7C7B\u4EFB\u52A1"); } }); return Object.entries(agentScores).map(([agentId, data]) => ({ agentId, score: data.totalScore / data.count, reason: Array.from(data.reasons).join(", ") || "\u6709\u4F7F\u7528\u7ECF\u9A8C" })).sort((a, b) => b.score - a.score); } /** * 解析协作模式 */ parseCollaborationPatterns(results, availableAgents) { const patterns = {}; results.forEach(({ memory }) => { const content = memory.content; const agents = this.extractAgentList(content); const pattern = this.extractPattern(content); const outcome = this.extractOutcome(content); const taskType = this.extractTaskType(content); if (!agents.length || !pattern || !taskType) return; const allAvailable = agents.every( (agent) => availableAgents.includes(agent) ); if (!allAvailable) return; const key = `${agents.join("-")}-${pattern}`; if (!patterns[key]) { patterns[key] = { agents, taskType, pattern, successRate: 0, usageCount: 0 }; } patterns[key].usageCount++; if (outcome === "success") { patterns[key].successRate++; } }); return Object.values(patterns).map((pattern) => ({ ...pattern, successRate: pattern.successRate / pattern.usageCount })).sort((a, b) => b.successRate - a.successRate); } /** * 计算性能指标 */ calculatePerformanceMetrics(results) { let totalCount = 0; let successCount = 0; let totalTime = 0; let totalRating = 0; let ratingCount = 0; results.forEach(({ memory }) => { totalCount++; if (memory.content.includes("\u8D28\u91CF: high")) { successCount++; } const rating = this.extractRating(memory.content); if (rating) { totalRating += rating; ratingCount++; } totalTime += 1; }); return { count: totalCount, successRate: totalCount > 0 ? successCount / totalCount : 0, averageTime: totalCount > 0 ? totalTime / totalCount : 0, userRating: ratingCount > 0 ? totalRating / ratingCount : 0, lastUsed: /* @__PURE__ */ new Date() }; } /** * 分析 Agent 优缺点 */ async analyzeAgentStrengthsWeaknesses(agentId) { const pros = /* @__PURE__ */ new Set(); const cons = /* @__PURE__ */ new Set(); const highRated = await this.memory.search(`Agent: ${agentId}`, { filter: { category: "agent_usage", tags: [agentId, "quality:high"] }, limit: 20 }); const lowRated = await this.memory.search(`Agent: ${agentId}`, { filter: { category: "agent_usage", tags: [agentId, "quality:low"] }, limit: 20 }); highRated.forEach(({ memory }) => { if (memory.content.includes("\u901F\u5EA6: fast")) { pros.add("\u54CD\u5E94\u901F\u5EA6\u5FEB"); } if (memory.content.includes("\u51C6\u786E\u5EA6: 0.9") || memory.content.includes("\u51C6\u786E\u5EA6: 1")) { pros.add("\u51C6\u786E\u5EA6\u9AD8"); } }); lowRated.forEach(({ memory }) => { if (memory.content.includes("\u901F\u5EA6: slow")) { cons.add("\u54CD\u5E94\u901F\u5EA6\u6162"); } if (memory.content.includes("\u8D28\u91CF: low")) { cons.add("\u8F93\u51FA\u8D28\u91CF\u4E0D\u7A33\u5B9A"); } }); return { pros: Array.from(pros), cons: Array.from(cons) }; } /** * 计算使用趋势 */ calculateUsageTrends(results, days) { const daily = {}; results.forEach(({ memory }) => { const date = new Date(memory.createdAt).toISOString().split("T")[0]; daily[date] = (daily[date] || 0) + 1; }); const totalUsage = Object.values(daily).reduce((sum, count) => sum + count, 0); const weeklyAverage = totalUsage / days * 7; const dates = Object.keys(daily).sort(); const firstWeek = dates.slice(0, 7).reduce((sum, date) => sum + (daily[date] || 0), 0); const lastWeek = dates.slice(-7).reduce((sum, date) => sum + (daily[date] || 0), 0); let trend = "stable"; if (lastWeek > firstWeek * 1.2) trend = "increasing"; else if (lastWeek < firstWeek * 0.8) trend = "decreasing"; return { daily, weeklyAverage, trend }; } // ============= 提取工具方法 ============= extractAgentId(content) { const match = content.match(/Agent: (\S+)/); return match ? match[1] : null; } extractTaskType(content) { const match = content.match(/任务类型: (\S+)/); return match ? match[1] : null; } extractPattern(content) { const match = content.match(/协作模式: (\S+)/); return match ? match[1] : null; } extractOutcome(content) { const match = content.match(/结果: (\S+)/); return match ? match[1] : null; } extractAgentList(content) { const match = content.match(/Agents: (.+)/); return match ? match[1].split(" -> ").map((s) => s.trim()) : []; } extractRating(content) { const match = content.match(/满意度: (\d+)\/5/); return match ? parseInt(match[1]) : null; } }; // src/adapters/user-preference.ts var UserPreferenceAdapter = class { memory; userId; constructor(config) { this.memory = new MemoryClient(config); this.userId = config.userId || "default"; } /** * 记录用户偏好 */ async recordPreference(params) { const { category, preference, confidence = 0.8 } = params; const description = this.buildPreferenceDescription(category, preference); await this.memory.add(description, { category: "user_preference", tags: [ `preference:${category}`, ...this.extractPreferenceTags(preference) ], importance: confidence }); } /** * 记录工作模式 */ async recordWorkPattern(pattern) { const description = [ "\u5DE5\u4F5C\u6A21\u5F0F\u8BB0\u5F55:", `\u9AD8\u6548\u65F6\u6BB5: ${pattern.productiveHours.join(", ")}`, `\u504F\u597D\u4EFB\u52A1\u7C7B\u578B: ${pattern.preferredTaskTypes.join(", ")}`, `\u4F11\u606F\u9891\u7387: ${pattern.breakFrequency}`, `\u5E73\u5747\u4F1A\u8BDD\u65F6\u957F: ${pattern.averageSessionLength}\u5C0F\u65F6`, `\u504F\u597D\u590D\u6742\u5EA6: ${pattern.preferredComplexity}` ].join("\n"); await this.memory.add(description, { category: "work_pattern", tags: [ "work_pattern", `complexity:${pattern.preferredComplexity}`, ...pattern.preferredTaskTypes.map((type) => `task:${type}`) ], importance: 0.9 }); for (const hour of pattern.productiveHours) { await this.memory.add( `\u9AD8\u6548\u5DE5\u4F5C\u65F6\u6BB5: ${hour}`, { category: "work_pattern", tags: ["productive_hours", hour], importance: 0.8 } ); } } /** * 获取个性化建议 */ async getPersonalizedSuggestions(params) { const { context, currentTime, recentActivity } = params; const preferences = await this.searchRelevantPreferences(context); if (context === "task_scheduling" && currentTime) { const workPattern = await this.getWorkPattern(); return this.generateSchedulingSuggestion(workPattern, currentTime, preferences); } if (context.includes("coding") || context.includes("development")) { const codingStyle = await this.getCodingStyle(); return this.generateCodingSuggestion(codingStyle, preferences); } return this.generateGeneralSuggestion(preferences, recentActivity); } /** * 获取编码风格偏好 */ async getCodingStyle() { const results = await this.memory.search("\u7F16\u7801\u98CE\u683C \u8BED\u8A00 \u6846\u67B6", { filter: { category: "user_preference", tags: ["preference:coding_style"] }, limit: 10 }); if (results.length === 0) return null; return this.mergeCodingPreferences(results); } /** * 获取工作模式 */ async getWorkPattern() { const results = await this.memory.search("\u5DE5\u4F5C\u6A21\u5F0F\u8BB0\u5F55", { filter: { category: "work_pattern" }, limit: 1 }); if (results.length === 0) return null; return this.parseWorkPattern(results[0].memory.content); } /** * 获取 UI 偏好 */ async getUIPreferences() { const results = await this.memory.search("UI \u754C\u9762 \u4E3B\u9898", { filter: { category: "user_preference", tags: ["preference:ui_preference"] }, limit: 5 }); if (results.length === 0) return null; return this.mergeUIPreferences(results); } /** * 获取通知偏好 */ async getNotificationPreferences() { const results = await this.memory.search("\u901A\u77E5 \u63D0\u9192", { filter: { category: "user_preference", tags: ["preference:notification"] }, limit: 5 }); if (results.length === 0) return null; return this.mergeNotificationPreferences(results); } /** * 学习用户行为 */ async learnFromBehavior(params) { const { action, context, timestamp } = params; const pattern = this.analyzeBehaviorPattern(action, context, timestamp); if (pattern) { await this.memory.add( `\u884C\u4E3A\u6A21\u5F0F: ${action} - ${JSON.stringify(pattern)}`, { category: "learning", tags: ["behavior", action], importance: 0.6 } ); } } /** * 获取偏好历史 */ async getPreferenceHistory(category, days = 30) { const startDate = /* @__PURE__ */ new Date(); startDate.setDate(startDate.getDate() - days); const filter = { category: "user_preference", timeRange: { start: startDate, end: /* @__PURE__ */ new Date() } }; if (category) { filter.tags = [`preference:${category}`]; } const results = await this.memory.search("*", { filter, limit: 100 }); return results.map((result) => this.parseUserPreference(result)); } /** * 导出用户偏好配置 */ async exportPreferences() { const [codingStyle, workPattern, uiPreferences, notificationPreferences] = await Promise.all([ this.getCodingStyle(), this.getWorkPattern(), this.getUIPreferences(), this.getNotificationPreferences() ]); const customResults = await this.memory.search("\u504F\u597D", { filter: { category: "user_preference" }, limit: 50 }); const customPreferences = {}; customResults.forEach(({ memory }) => { const category = this.extractPreferenceCategory(memory.content); if (category && !["coding_style", "ui_preference", "notification"].includes(category)) { customPreferences[category] = this.extractPreferenceData(memory.content); } }); return { codingStyle: codingStyle || void 0, workPattern: workPattern || void 0, uiPreferences: uiPreferences || void 0, notificationPreferences: notificationPreferences || void 0, customPreferences }; } /** * 导入用户偏好 */ async importPreferences(preferences) { const promises = []; if (preferences.codingStyle) { promises.push(this.recordPreference({ category: "coding_style", preference: preferences.codingStyle })); } if (preferences.workPattern) { promises.push(this.recordWorkPattern(preferences.workPattern)); } if (preferences.uiPreferences) { promises.push(this.recordPreference({ category: "ui_preference", preference: preferences.uiPreferences })); } if (preferences.notificationPreferences) { promises.push(this.recordPreference({ category: "notification", preference: preferences.notificationPreferences })); } if (preferences.customPreferences) { for (const [category, preference] of Object.entries(preferences.customPreferences)) { promises.push(this.recordPreference({ category, preference })); } } await Promise.all(promises); } // ============= 私有方法 ============= /** * 构建偏好描述 */ buildPreferenceDescription(category, preference) { const categoryLabels = { coding_style: "\u7F16\u7801\u98CE\u683C\u504F\u597D", work_pattern: "\u5DE5\u4F5C\u6A21\u5F0F\u504F\u597D", tool_preference: "\u5DE5\u5177\u504F\u597D", communication: "\u6C9F\u901A\u504F\u597D", ui_preference: "UI\u754C\u9762\u504F\u597D", notification: "\u901A\u77E5\u504F\u597D", other: "\u5176\u4ED6\u504F\u597D" }; const lines = [`${categoryLabels[category]}:`]; for (const [key, value] of Object.entries(preference)) { lines.push(`${key}: ${JSON.stringify(value)}`); } return lines.join("\n"); } /** * 提取偏好标签 */ extractPreferenceTags(preference) { const tags = []; if (preference.language) tags.push(`lang:${preference.language}`); if (preference.framework) tags.push(`framework:${preference.framework}`); if (preference.theme) tags.push(`theme:${preference.theme}`); if (preference.enabled !== void 0) tags.push(`enabled:${preference.enabled}`); return tags; } /** * 搜索相关偏好 */ async searchRelevantPreferences(context) { return this.memory.search(context, { filter: { category: ["user_preference", "work_pattern"] }, limit: 20 }); } /** * 生成调度建议 */ generateSchedulingSuggestion(workPattern, currentTime, preferences) { if (!workPattern) { return { recommendation: "\u5EFA\u8BAE\u5148\u8BB0\u5F55\u60A8\u7684\u5DE5\u4F5C\u6A21\u5F0F\uFF0C\u4EE5\u4FBF\u63D0\u4F9B\u66F4\u51C6\u786E\u7684\u5EFA\u8BAE", context: "task_scheduling", confidence: 0.3, basedOn: [] }; } const isProductiveHour = workPattern.productiveHours.some( (hour) => currentTime.includes(hour.split("-")[0]) ); if (isProductiveHour) { return { recommendation: `\u73B0\u5728\u662F\u60A8\u7684\u9AD8\u6548\u65F6\u6BB5\uFF0C\u5EFA\u8BAE\u5904\u7406${workPattern.preferredComplexity}\u590D\u6742\u5EA6\u7684${workPattern.preferredTaskTypes.join("\u6216")}\u4EFB\u52A1`, context: "task_scheduling", confidence: 0.9, basedOn: preferences.map((p) => p.memory.id), alternativeOptions: [ "\u5982\u679C\u611F\u5230\u75B2\u52B3\uFF0C\u53EF\u4EE5\u5904\u7406\u4E00\u4E9B\u7B80\u5355\u4EFB\u52A1", `\u8BB0\u5F97${workPattern.breakFrequency}` ] }; } return { recommendation: "\u5F53\u524D\u4E0D\u662F\u60A8\u7684\u9AD8\u6548\u65F6\u6BB5\uFF0C\u5EFA\u8BAE\u5904\u7406\u4E00\u4E9B\u7B80\u5355\u7684\u7EF4\u62A4\u6027\u4EFB\u52A1\u6216\u6587\u6863\u5DE5\u4F5C", context: "task_scheduling", confidence: 0.8, basedOn: preferences.map((p) => p.memory.id), alternativeOptions: [ "\u4E5F\u53EF\u4EE5\u5229\u7528\u8FD9\u6BB5\u65F6\u95F4\u8FDB\u884C\u5B66\u4E60\u548C\u89C4\u5212", "\u6216\u8005\u9002\u5F53\u4F11\u606F\uFF0C\u4E3A\u9AD8\u6548\u65F6\u6BB5\u505A\u51C6\u5907" ] }; } /** * 生成编码建议 */ generateCodingSuggestion(codingStyle, preferences) { if (!codingStyle) { return { recommendation: "\u5EFA\u8BAE\u4F7F\u7528 TypeScript \u548C\u73B0\u4EE3\u5316\u7684\u5F00\u53D1\u5DE5\u5177", context: "coding", confidence: 0.4, basedOn: [] }; } const recommendations = []; if (codingStyle.language) { recommendations.push(`\u4F7F\u7528 ${codingStyle.language} \u8FDB\u884C\u5F00\u53D1`); } if (codingStyle.framework) { recommendations.push(`\u91C7\u7528 ${codingStyle.framework} \u6846\u67B6`); } if (codingStyle.testingLibrary) { recommendations.push(`\u4F7F\u7528 ${codingStyle.testingLibrary} \u8FDB\u884C\u6D4B\u8BD5`); } if (codingStyle.lintingRules) { recommendations.push(`\u5E94\u7528 ${codingStyle.lintingRules} \u7EA7\u522B\u7684\u4EE3\u7801\u89C4\u8303`); } return { recommendation: recommendations.join("\uFF0C"), context: "coding", confidence: 0.85, basedOn: preferences.map((p) => p.memory.id) }; } /** * 生成通用建议 */ generateGeneralSuggestion(preferences, recentActivity) { if (preferences.length === 0) { return { recommendation: "\u5F00\u59CB\u4F7F\u7528\u7CFB\u7EDF\uFF0C\u6211\u4F1A\u5B66\u4E60\u60A8\u7684\u504F\u597D\u5E76\u63D0\u4F9B\u4E2A\u6027\u5316\u5EFA\u8BAE", context: "general", confidence: 0.2, basedOn: [] }; } const topPreference = preferences[0]; return { recommendation: `\u57FA\u4E8E\u60A8\u7684\u4F7F\u7528\u4E60\u60EF\uFF0C${this.extractRecommendation(topPreference.memory.content)}`, context: "general", confidence: topPreference.score, basedOn: [topPreference.memory.id] }; } /** * 合并编码偏好 */ mergeCodingPreferences(results) { const merged = { language: "TypeScript" // 默认值 }; results.forEach(({ memory }) => { const prefs = this.extractPreferenceData(memory.content); Object.assign(merged, prefs); }); return merged; } /** * 解析工作模式 */ parseWorkPattern(content) { const lines = content.split("\n"); const pattern = {}; lines.forEach((line) => { if (line.includes("\u9AD8\u6548\u65F6\u6BB5:")) { pattern.productiveHours = line.split(":")[1].trim().split(", "); } else if (line.includes("\u504F\u597D\u4EFB\u52A1\u7C7B\u578B:")) { pattern.preferredTaskTypes = line.split(":")[1].trim().split(", "); } else if (line.includes("\u4F11\u606F\u9891\u7387:")) { pattern.breakFrequency = line.split(":")[1].trim(); } else if (line.includes("\u5E73\u5747\u4F1A\u8BDD\u65F6\u957F:")) { pattern.averageSessionLength = parseFloat(line.match(/(\d+)/)?.[1] || "2"); } else if (line.includes("\u504F\u597D\u590D\u6742\u5EA6:")) { pattern.preferredComplexity = line.split(":")[1].trim(); } }); return pattern; } /** * 合并 UI 偏好 */ mergeUIPreferences(results) { const merged = {}; results.forEach(({ memory }) => { const prefs = this.extractPreferenceData(memory.content); Object.assign(merged, prefs); }); return merged; } /** * 合并通知偏好 */ mergeNotificationPreferences(results) { const merged = { enabled: true }; results.forEach(({ memory }) => { const prefs = this.extractPreferenceData(memory.content); Object.assign(merged, prefs); }); return merged; } /** * 分析行为模式 */ analyzeBehaviorPattern(action, context, timestamp) { const hour = timestamp.getHours(); if (action.includes("task_complete")) { return { productiveHour: `${hour}:00-${hour + 1}:00`, taskType: context.taskType, duration: context.duration }; } if (action.includes("tool_use")) { return { tool: context.tool, frequency: context.frequency, context: context.useCase }; } return null; } /** * 解析用户偏好 */ parseUserPreference(result) { const { memory } = result; const category = this.extractPreferenceCategory(memory.content) || "other"; const preference = this.extractPreferenceData(memory.content); return { category, preference, confidence: result.score, learnedAt: memory.createdAt, lastUpdated: memory.updatedAt }; } /** * 提取偏好分类 */ extractPreferenceCategory(content) { const match = content.match(/(\w+)偏好:/); if (!match) return null; const categoryMap = { "\u7F16\u7801\u98CE\u683C": "coding_style", "\u5DE5\u4F5C\u6A21\u5F0F": "work_pattern", "\u5DE5\u5177": "tool_preference", "\u6C9F\u901A": "communication", "UI\u754C\u9762": "ui_preference", "\u901A\u77E5": "notification" }; return categoryMap[match[1]] || "other"; } /** * 提取偏好数据 */ extractPreferenceData(content) { const data = {}; const lines = content.split("\n").slice(1); lines.forEach((line) => { const [key, value] = line.split(":").map((s) => s.trim()); if (key && value) { try { data[key] = JSON.parse(value); } catch { data[key] = value; } } }); return data; } /** * 提取推荐内容 */ extractRecommendation(content) { return content.split("\n")[0].replace(/.*偏好:/, "").trim(); } }; // src/utils/memory-utils.ts function calculateTextSimilarity(text1, text2) { const words1 = new Set(text1.toLowerCase().split(/\s+/)); const words2 = new Set(text2.toLowerCase().split(/\s+/)); const intersection = new Set([...words1].filter((x) => words2.has(x))); const union = /* @__PURE__ */ new Set([...words1, ...words2]); return union.size > 0 ? intersection.size / union.size : 0; } function sortByRelevance(results) { return [...results].sort((a, b) => b.score - a.score); } function sortByTime(memories, order = "desc") { return [...memories].sort((a, b) => { const timeA = a.updatedAt.getTime(); const timeB = b.updatedAt.getTime(); return order === "desc" ? timeB - timeA : timeA - timeB; }); } function sortByImportance(memories) { return [...memories].sort( (a, b) => (b.metadata.importance || 0) - (a.metadata.importance || 0) ); } function filterExpiredMemories(memories) { const now = Date.now(); return memories.filter((memory) => { if (!memory.metadata.ttl) return true; const expiryTime = memory.createdAt.getTime() + memory.metadata.ttl * 1e3; return expiryTime > now; }); } function groupByCategory(memories) { const grouped = {}; memories.forEach((memory) => { const category = memory.metadata.category || "other"; if (!grouped[category]) { grouped[category] = []; } grouped[category].push(memory); }); return grouped; } function groupByTags(memories) { const grouped = {}; memories.forEach((memory) => { memory.metadata.tags?.forEach((tag) => { if (!grouped[tag]) { grouped[tag] = []; } grouped[tag].push(memory); }); }); return grouped; } function extractKeywords(content, limit = 5) { const words = content.toLowerCase().replace(/[^\w\s\u4e00-\u9fa5]/g, "").split(/\s+/).filter((word) => word.length > 2); const wordCount = {}; words.forEach((word) => { wordCount[word] = (wordCount[word] || 0) + 1; }); return Object.entries(wordCount).sort(([, a], [, b]) => b - a).slice(0, limit).map(([word]) => word); } function mergeSimilarMemories(memories, similarityThreshold = 0.8) { const merged = []; const processed = /* @__PURE__ */ new Set();