@gongfu/memory
Version:
Intelligent memory layer for Gongfu using mem0
1,679 lines (1,674 loc) • 57.2 kB
JavaScript
import { Memory } from '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 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();
memories.forEach((mem