memory-pulse-mcp-server 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts","../../storage/src/sqlite-storage.ts","../../core/src/types.ts","../../storage/src/schema.ts","../../storage/src/cache.ts","../../storage/src/postgresql-storage.ts"],"sourcesContent":["#!/usr/bin/env node\nimport { Server } from '@modelcontextprotocol/sdk/server/index.js';\nimport { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';\nimport {\n CallToolRequestSchema,\n ListToolsRequestSchema,\n ListResourcesRequestSchema,\n ReadResourceRequestSchema,\n ListPromptsRequestSchema,\n GetPromptRequestSchema,\n Tool,\n} from '@modelcontextprotocol/sdk/types.js';\nimport { SQLiteStorage, PostgreSQLStorage } from '@emp/storage';\nimport type {\n IStorage,\n DecisionContext,\n SolutionContext,\n SessionContext,\n SearchFilters,\n TimelineOptions,\n RelationsOptions,\n} from '@emp/core';\n\n/**\n * Memory Pulse (记忆脉搏) MCP Server\n *\n * 提供以下工具:\n * - mpulse_store: 智能存储\n * - mpulse_store_decision: 存储决策\n * - mpulse_store_solution: 存储解决方案\n * - mpulse_store_session: 存储会话\n * - mpulse_recall: 检索记忆\n * - mpulse_timeline: 时间线视图\n * - mpulse_relations: 关系链查询\n */\n\nconst server = new Server(\n {\n name: 'elb-memory-pulse',\n version: '0.1.0',\n },\n {\n capabilities: {\n tools: {},\n resources: {},\n prompts: {},\n },\n }\n);\n\n// 存储类型:sqlite(默认) 或 postgresql\nconst storageType = process.env.MEMORY_STORAGE || 'sqlite';\n\n// 初始化存储\nfunction createStorage(): IStorage {\n if (storageType === 'postgresql') {\n const databaseUrl = process.env.DATABASE_URL;\n if (!databaseUrl) {\n console.error('错误: 使用 PostgreSQL 存储需要设置 DATABASE_URL 环境变量');\n process.exit(1);\n }\n console.error(`Memory Pulse 使用 PostgreSQL 存储: ${databaseUrl.replace(/:[^:@]+@/, ':****@')}`);\n return new PostgreSQLStorage(databaseUrl);\n }\n\n // SQLite 存储(默认)\n const dbPath = process.env.MEMORY_DB_PATH || './memory.db';\n console.error(`Memory Pulse 使用 SQLite 存储: ${dbPath}`);\n return new SQLiteStorage(dbPath);\n}\n\nconst storage = createStorage();\n\n// 定义工具列表\nconst tools: Tool[] = [\n {\n name: 'mpulse_store',\n description: '智能存储记忆,AI 自动分类和结构化',\n inputSchema: {\n type: 'object',\n properties: {\n content: {\n type: 'string',\n description: 'AI 总结的内容',\n },\n rawContext: {\n type: 'object',\n description: '完整原始数据(不压缩)',\n },\n projectId: {\n type: 'string',\n description: '项目 ID',\n },\n type: {\n type: 'string',\n enum: ['decision', 'solution', 'config', 'code', 'error', 'session'],\n description: '记忆类型(可选,不填则默认为 code)',\n },\n tags: {\n type: 'array',\n items: { type: 'string' },\n description: '标签',\n },\n sessionId: {\n type: 'string',\n description: '会话 ID(可选)',\n },\n },\n required: ['content', 'rawContext', 'projectId'],\n },\n },\n {\n name: 'mpulse_store_decision',\n description: '存储架构决策(强制字段,防止 AI 偷懒)',\n inputSchema: {\n type: 'object',\n properties: {\n question: {\n type: 'string',\n description: '决策问题',\n },\n options: {\n type: 'array',\n items: {\n type: 'object',\n properties: {\n name: { type: 'string' },\n pros: { type: 'array', items: { type: 'string' } },\n cons: { type: 'array', items: { type: 'string' } },\n },\n required: ['name', 'pros', 'cons'],\n },\n description: '考虑的选项',\n },\n chosen: {\n type: 'string',\n description: '选择的方案',\n },\n reason: {\n type: 'string',\n description: '选择理由',\n },\n projectId: {\n type: 'string',\n description: '项目 ID',\n },\n tags: {\n type: 'array',\n items: { type: 'string' },\n description: '标签',\n },\n sessionId: {\n type: 'string',\n description: '会话 ID(可选)',\n },\n },\n required: ['question', 'options', 'chosen', 'reason', 'projectId'],\n },\n },\n {\n name: 'mpulse_store_solution',\n description: '存储问题解决方案',\n inputSchema: {\n type: 'object',\n properties: {\n problem: {\n type: 'string',\n description: '问题描述',\n },\n rootCause: {\n type: 'string',\n description: '根因分析',\n },\n solution: {\n type: 'string',\n description: '解决方案',\n },\n prevention: {\n type: 'string',\n description: '如何预防',\n },\n relatedIssues: {\n type: 'array',\n items: { type: 'string' },\n description: '关联问题',\n },\n projectId: {\n type: 'string',\n description: '项目 ID',\n },\n tags: {\n type: 'array',\n items: { type: 'string' },\n description: '标签',\n },\n sessionId: {\n type: 'string',\n description: '会话 ID(可选)',\n },\n artifacts: {\n type: 'object',\n description: '相关文件(代码片段等)',\n },\n },\n required: ['problem', 'rootCause', 'solution', 'projectId'],\n },\n },\n {\n name: 'mpulse_store_session',\n description: '存储会话总结(会话结束时调用)',\n inputSchema: {\n type: 'object',\n properties: {\n summary: {\n type: 'string',\n description: '本次会话总结',\n },\n decisions: {\n type: 'array',\n items: { type: 'string' },\n description: '本次做出的决策',\n },\n unfinishedTasks: {\n type: 'array',\n items: { type: 'string' },\n description: '未完成的任务',\n },\n nextSteps: {\n type: 'array',\n items: { type: 'string' },\n description: '下次从哪继续',\n },\n projectId: {\n type: 'string',\n description: '项目 ID',\n },\n sessionId: {\n type: 'string',\n description: '会话 ID',\n },\n },\n required: ['summary', 'projectId', 'sessionId'],\n },\n },\n {\n name: 'mpulse_recall',\n description: '检索记忆(多策略:精确、全文、语义)',\n inputSchema: {\n type: 'object',\n properties: {\n query: {\n type: 'string',\n description: '查询内容',\n },\n projectId: {\n type: 'string',\n description: '项目 ID',\n },\n type: {\n type: 'string',\n enum: ['decision', 'solution', 'config', 'code', 'error', 'session'],\n description: '记忆类型',\n },\n tags: {\n type: 'array',\n items: { type: 'string' },\n description: '标签过滤',\n },\n strategy: {\n type: 'string',\n enum: ['exact', 'fulltext', 'semantic'],\n description: '检索策略',\n },\n limit: {\n type: 'number',\n description: '返回数量',\n },\n },\n required: ['query'],\n },\n },\n {\n name: 'mpulse_timeline',\n description: '查看项目的时间线视图',\n inputSchema: {\n type: 'object',\n properties: {\n projectId: {\n type: 'string',\n description: '项目 ID',\n },\n dateRange: {\n type: 'array',\n items: { type: 'string' },\n description: '日期范围 [start, end]',\n },\n type: {\n type: 'string',\n enum: ['decision', 'solution', 'config', 'code', 'error', 'session'],\n description: '记忆类型',\n },\n limit: {\n type: 'number',\n description: '返回数量',\n },\n offset: {\n type: 'number',\n description: '分页偏移',\n },\n },\n required: ['projectId'],\n },\n },\n {\n name: 'mpulse_relations',\n description: '查询记忆的关系链',\n inputSchema: {\n type: 'object',\n properties: {\n memoryId: {\n type: 'string',\n description: '记忆 ID',\n },\n depth: {\n type: 'number',\n description: '递归深度',\n },\n },\n required: ['memoryId'],\n },\n },\n];\n\n// 注册工具列表\nserver.setRequestHandler(ListToolsRequestSchema, async () => ({\n tools,\n}));\n\n// 注册资源列表\nserver.setRequestHandler(ListResourcesRequestSchema, async () => ({\n resources: [\n {\n uri: 'memory://projects',\n name: '所有项目记忆',\n description: '列出所有项目 ID',\n mimeType: 'application/json',\n },\n ],\n}));\n\n// 处理资源读取\nserver.setRequestHandler(ReadResourceRequestSchema, async (request) => {\n const uri = request.params.uri;\n\n try {\n // memory://projects - 列出所有项目\n if (uri === 'memory://projects') {\n // 查询所有记忆,按项目分组\n const allMemories = await storage.recall({ query: '', limit: 10000 });\n const projects = new Set(allMemories.memories.map((m) => m.meta.projectId));\n\n return {\n contents: [\n {\n uri,\n mimeType: 'application/json',\n text: JSON.stringify(\n {\n projects: Array.from(projects),\n total: projects.size,\n },\n null,\n 2\n ),\n },\n ],\n };\n }\n\n // memory://project/{projectId} - 列出项目的所有记忆\n const projectMatch = uri.match(/^memory:\\/\\/project\\/(.+)$/);\n if (projectMatch) {\n const projectId = decodeURIComponent(projectMatch[1]);\n const result = await storage.recall({ query: '', projectId, limit: 1000 });\n\n return {\n contents: [\n {\n uri,\n mimeType: 'application/json',\n text: JSON.stringify(\n {\n projectId,\n memories: result.memories,\n total: result.total,\n },\n null,\n 2\n ),\n },\n ],\n };\n }\n\n // memory://memory/{memoryId} - 获取单个记忆详情\n const memoryMatch = uri.match(/^memory:\\/\\/memory\\/(.+)$/);\n if (memoryMatch) {\n const memoryId = decodeURIComponent(memoryMatch[1]);\n // 使用 getRelations 获取单个记忆(depth=0 不递归)\n const result = await storage.getRelations({ memoryId, depth: 0 });\n\n return {\n contents: [\n {\n uri,\n mimeType: 'application/json',\n text: JSON.stringify(result.memory, null, 2),\n },\n ],\n };\n }\n\n // memory://session/{sessionId} - 列出会话的所有记忆\n const sessionMatch = uri.match(/^memory:\\/\\/session\\/(.+)$/);\n if (sessionMatch) {\n const sessionId = decodeURIComponent(sessionMatch[1]);\n const result = await storage.recall({ query: '', sessionId, limit: 1000 });\n\n return {\n contents: [\n {\n uri,\n mimeType: 'application/json',\n text: JSON.stringify(\n {\n sessionId,\n memories: result.memories,\n total: result.total,\n },\n null,\n 2\n ),\n },\n ],\n };\n }\n\n throw new Error(`Unknown resource URI: ${uri}`);\n } catch (error) {\n throw new Error(\n `Failed to read resource ${uri}: ${error instanceof Error ? error.message : String(error)}`\n );\n }\n});\n\n// 注册提示词列表\nserver.setRequestHandler(ListPromptsRequestSchema, async () => ({\n prompts: [\n {\n name: 'analyze-decision',\n description: '分析项目中的架构决策',\n arguments: [\n {\n name: 'projectId',\n description: '项目 ID',\n required: true,\n },\n ],\n },\n {\n name: 'summarize-session',\n description: '总结会话中的工作内容',\n arguments: [\n {\n name: 'sessionId',\n description: '会话 ID',\n required: true,\n },\n ],\n },\n {\n name: 'find-related',\n description: '查找与特定主题相关的记忆',\n arguments: [\n {\n name: 'topic',\n description: '主题关键词',\n required: true,\n },\n {\n name: 'projectId',\n description: '项目 ID(可选)',\n required: false,\n },\n ],\n },\n {\n name: 'review-project',\n description: '回顾项目的发展历程',\n arguments: [\n {\n name: 'projectId',\n description: '项目 ID',\n required: true,\n },\n {\n name: 'type',\n description: '记忆类型(可选:decision, solution, session)',\n required: false,\n },\n ],\n },\n ],\n}));\n\n// 处理提示词获取\nserver.setRequestHandler(GetPromptRequestSchema, async (request) => {\n const { name, arguments: args } = request.params;\n\n if (!args) {\n throw new Error('Missing required arguments');\n }\n\n try {\n switch (name) {\n case 'analyze-decision': {\n const projectId = (args as any).projectId;\n const decisions = await storage.recall({\n query: '',\n projectId,\n type: 'decision' as any,\n limit: 100,\n });\n\n return {\n messages: [\n {\n role: 'user',\n content: {\n type: 'text',\n text: `请分析项目 \"${projectId}\" 中的架构决策。\n\n找到了 ${decisions.total} 个决策记录:\n\n${decisions.memories\n .map((m, idx) => {\n const data = m.content.data as any;\n return `\n${idx + 1}. ${data.question || m.content.summary}\n 选择:${data.chosen || '未知'}\n 理由:${data.reason || '未提供'}\n 时间:${m.meta.timestamp}\n`;\n })\n .join('\\n')}\n\n请总结:\n1. 主要的技术选型有哪些?\n2. 决策的演进趋势如何?\n3. 是否存在可能的技术债务?\n4. 有哪些值得记录的经验教训?`,\n },\n },\n ],\n };\n }\n\n case 'summarize-session': {\n const sessionId = (args as any).sessionId;\n const memories = await storage.recall({\n query: '',\n sessionId,\n limit: 100,\n });\n\n return {\n messages: [\n {\n role: 'user',\n content: {\n type: 'text',\n text: `请总结会话 \"${sessionId}\" 的工作内容。\n\n会话包含 ${memories.total} 条记忆:\n\n${memories.memories\n .map((m, idx) => `${idx + 1}. [${m.meta.type}] ${m.content.summary}`)\n .join('\\n')}\n\n请生成一个简洁的工作总结,包括:\n1. 主要完成的任务\n2. 做出的重要决策\n3. 遇到的问题和解决方案\n4. 未完成的任务(如有)\n5. 下一步计划建议`,\n },\n },\n ],\n };\n }\n\n case 'find-related': {\n const topic = (args as any).topic;\n const projectId = (args as any).projectId;\n const related = await storage.recall({\n query: topic,\n projectId,\n limit: 20,\n });\n\n return {\n messages: [\n {\n role: 'user',\n content: {\n type: 'text',\n text: `查找与 \"${topic}\" 相关的记忆${projectId ? `(项目:${projectId})` : ''}。\n\n找到 ${related.total} 条相关记忆:\n\n${related.memories\n .map(\n (m, idx) => `\n${idx + 1}. ${m.content.summary}\n 类型:${m.meta.type}\n 项目:${m.meta.projectId}\n 时间:${m.meta.timestamp}\n`\n )\n .join('\\n')}\n\n请分析这些记忆之间的关联性,并提供:\n1. 这些记忆围绕什么主题?\n2. 是否存在演进关系?\n3. 有哪些有价值的经验可以复用?`,\n },\n },\n ],\n };\n }\n\n case 'review-project': {\n const projectId = (args as any).projectId;\n const type = (args as any).type;\n const timeline = await storage.getTimeline({\n projectId,\n type: type as any,\n limit: 100,\n });\n\n return {\n messages: [\n {\n role: 'user',\n content: {\n type: 'text',\n text: `回顾项目 \"${projectId}\" 的发展历程${type ? `(类型:${type})` : ''}。\n\n时间线包含 ${timeline.total} 条记录:\n\n${timeline.entries\n .map((entry, idx) => {\n const m = entry.memory;\n return `${idx + 1}. [${new Date(m.meta.timestamp).toLocaleDateString()}] ${m.content.summary}`;\n })\n .join('\\n')}\n\n请生成项目回顾报告,包括:\n1. 项目起源和初始目标\n2. 关键里程碑和决策点\n3. 遇到的挑战和解决方案\n4. 当前状态和未来方向\n5. 经验总结和改进建议`,\n },\n },\n ],\n };\n }\n\n default:\n throw new Error(`Unknown prompt: ${name}`);\n }\n } catch (error) {\n throw new Error(\n `Failed to generate prompt ${name}: ${error instanceof Error ? error.message : String(error)}`\n );\n }\n});\n\n// 处理工具调用\nserver.setRequestHandler(CallToolRequestSchema, async (request) => {\n const { name, arguments: args } = request.params;\n\n // MCP SDK 保证 args 存在且类型正确(通过 inputSchema 验证)\n if (!args) {\n throw new Error('Missing required arguments');\n }\n\n try {\n switch (name) {\n case 'mpulse_store': {\n const result = await storage.store({\n content: (args as any).content,\n rawContext: (args as any).rawContext,\n projectId: (args as any).projectId,\n type: (args as any).type,\n tags: (args as any).tags,\n sessionId: (args as any).sessionId,\n });\n return {\n content: [\n {\n type: 'text',\n text: JSON.stringify(result, null, 2),\n },\n ],\n };\n }\n\n case 'mpulse_store_decision': {\n const decisionParams: DecisionContext & {\n projectId: string;\n tags?: string[];\n sessionId?: string;\n } = {\n question: (args as any).question,\n options: (args as any).options,\n chosen: (args as any).chosen,\n reason: (args as any).reason,\n projectId: (args as any).projectId,\n tags: (args as any).tags,\n sessionId: (args as any).sessionId,\n };\n const result = await storage.storeDecision(decisionParams);\n return {\n content: [\n {\n type: 'text',\n text: JSON.stringify(result, null, 2),\n },\n ],\n };\n }\n\n case 'mpulse_store_solution': {\n const solutionParams: SolutionContext & {\n projectId: string;\n tags?: string[];\n sessionId?: string;\n artifacts?: Record<string, string>;\n } = {\n problem: (args as any).problem,\n rootCause: (args as any).rootCause,\n solution: (args as any).solution,\n prevention: (args as any).prevention,\n relatedIssues: (args as any).relatedIssues,\n projectId: (args as any).projectId,\n tags: (args as any).tags,\n sessionId: (args as any).sessionId,\n artifacts: (args as any).artifacts,\n };\n const result = await storage.storeSolution(solutionParams);\n return {\n content: [\n {\n type: 'text',\n text: JSON.stringify(result, null, 2),\n },\n ],\n };\n }\n\n case 'mpulse_store_session': {\n const sessionParams: SessionContext & {\n projectId: string;\n sessionId: string;\n } = {\n summary: (args as any).summary,\n decisions: (args as any).decisions,\n unfinishedTasks: (args as any).unfinishedTasks,\n nextSteps: (args as any).nextSteps,\n projectId: (args as any).projectId,\n sessionId: (args as any).sessionId,\n };\n const result = await storage.storeSession(sessionParams);\n return {\n content: [\n {\n type: 'text',\n text: JSON.stringify(result, null, 2),\n },\n ],\n };\n }\n\n case 'mpulse_recall': {\n const filters: SearchFilters = {\n query: (args as any).query,\n projectId: (args as any).projectId,\n type: (args as any).type,\n tags: (args as any).tags,\n strategy: (args as any).strategy,\n limit: (args as any).limit,\n };\n const result = await storage.recall(filters);\n return {\n content: [\n {\n type: 'text',\n text: JSON.stringify(result, null, 2),\n },\n ],\n };\n }\n\n case 'mpulse_timeline': {\n const options: TimelineOptions = {\n projectId: (args as any).projectId,\n dateRange: (args as any).dateRange,\n type: (args as any).type,\n limit: (args as any).limit,\n offset: (args as any).offset,\n };\n const result = await storage.getTimeline(options);\n return {\n content: [\n {\n type: 'text',\n text: JSON.stringify(result, null, 2),\n },\n ],\n };\n }\n\n case 'mpulse_relations': {\n const options: RelationsOptions = {\n memoryId: (args as any).memoryId,\n depth: (args as any).depth,\n };\n const result = await storage.getRelations(options);\n return {\n content: [\n {\n type: 'text',\n text: JSON.stringify(result, null, 2),\n },\n ],\n };\n }\n\n default:\n throw new Error(`Unknown tool: ${name}`);\n }\n } catch (error) {\n return {\n content: [\n {\n type: 'text',\n text: `Error: ${error instanceof Error ? error.message : String(error)}`,\n },\n ],\n isError: true,\n };\n }\n});\n\n// 启动服务器\nasync function main() {\n const transport = new StdioServerTransport();\n await server.connect(transport);\n console.error('Memory Pulse (记忆脉搏) MCP Server running on stdio');\n}\n\nmain().catch((error) => {\n console.error('Fatal error:', error);\n process.exit(1);\n});\n","import Database from 'better-sqlite3';\nimport { nanoid } from 'nanoid';\nimport {\n type IStorage,\n type SearchFilters,\n type SearchResult,\n type TimelineOptions,\n type TimelineResult,\n type TimelineEntry,\n type RelationsOptions,\n type RelationNode,\n MemoryType,\n SearchStrategy,\n type Memory,\n type DecisionContext,\n type SolutionContext,\n type SessionContext,\n} from '@emp/core';\nimport { initSchema } from './schema.js';\nimport { LRUCache } from './cache.js';\n\n/**\n * SQLite存储实现\n */\nexport class SQLiteStorage implements IStorage {\n private db: Database.Database;\n private cache: LRUCache | null;\n\n constructor(dbPath: string = ':memory:', options?: { enableCache?: boolean; cacheSize?: number }) {\n this.db = new Database(dbPath);\n this.db.pragma('journal_mode = WAL'); // 性能优化:Write-Ahead Logging\n this.db.pragma('foreign_keys = ON');\n initSchema(this.db); // 初始化Schema\n\n // 初始化缓存(默认启用,容量100)\n this.cache = options?.enableCache !== false ? new LRUCache(options?.cacheSize || 100) : null;\n }\n\n /**\n * 通用存储方法\n */\n async store(params: {\n content: string;\n rawContext: Record<string, unknown>;\n projectId: string;\n type?: MemoryType;\n tags?: string[];\n sessionId?: string;\n relations?: {\n replaces?: string[];\n relatedTo?: string[];\n impacts?: string[];\n derivedFrom?: string;\n };\n }): Promise<{ id: string; success: boolean }> {\n const id = `mem_${nanoid()}`;\n const timestamp = new Date().toISOString();\n const memoryType = params.type || MemoryType.CODE;\n\n const stmt = this.db.prepare(`\n INSERT INTO memories (\n id, projectId, sessionId, timestamp, type, tags,\n summary, data, replaces, relatedTo, impacts, derivedFrom,\n context, keywords, fullText, createdAt, updatedAt\n ) VALUES (\n ?, ?, ?, ?, ?, ?,\n ?, ?, ?, ?, ?, ?,\n ?, ?, ?, ?, ?\n )\n `);\n\n stmt.run(\n id,\n params.projectId,\n params.sessionId || null,\n timestamp,\n memoryType,\n params.tags ? JSON.stringify(params.tags) : null,\n params.content, // summary\n JSON.stringify(params.rawContext), // data\n params.relations?.replaces ? JSON.stringify(params.relations.replaces) : null,\n params.relations?.relatedTo ? JSON.stringify(params.relations.relatedTo) : null,\n params.relations?.impacts ? JSON.stringify(params.relations.impacts) : null,\n params.relations?.derivedFrom || null,\n JSON.stringify(params.rawContext), // context\n params.tags ? JSON.stringify(params.tags) : null, // keywords\n params.content, // fullText\n timestamp,\n timestamp\n );\n\n // 失效相关缓存\n if (this.cache) {\n this.cache.invalidateProject(params.projectId);\n }\n\n return { id, success: true };\n }\n\n /**\n * 存储决策记忆\n */\n async storeDecision(\n params: DecisionContext & {\n projectId: string;\n tags?: string[];\n sessionId?: string;\n relations?: {\n replaces?: string[];\n relatedTo?: string[];\n impacts?: string[];\n derivedFrom?: string;\n };\n }\n ): Promise<{ id: string; success: boolean }> {\n const id = `mem_${nanoid()}`;\n const timestamp = new Date().toISOString();\n const summary = `[决策] ${params.question}`;\n const fullText = `${params.question} ${params.options.map((o) => o.name).join(' ')} ${params.reason}`;\n const keywords = [...(params.tags || []), ...params.options.map((o) => o.name), params.chosen];\n\n const stmt = this.db.prepare(`\n INSERT INTO memories (\n id, projectId, sessionId, timestamp, type, tags,\n summary, data, replaces, relatedTo, impacts, derivedFrom,\n context, keywords, fullText, createdAt, updatedAt\n ) VALUES (\n ?, ?, ?, ?, ?, ?,\n ?, ?, ?, ?, ?, ?,\n ?, ?, ?, ?, ?\n )\n `);\n\n stmt.run(\n id,\n params.projectId,\n params.sessionId || null,\n timestamp,\n MemoryType.DECISION,\n params.tags ? JSON.stringify(params.tags) : null,\n summary,\n JSON.stringify({}), // data为空\n params.relations?.replaces ? JSON.stringify(params.relations.replaces) : null,\n params.relations?.relatedTo ? JSON.stringify(params.relations.relatedTo) : null,\n params.relations?.impacts ? JSON.stringify(params.relations.impacts) : null,\n params.relations?.derivedFrom || null,\n JSON.stringify({\n question: params.question,\n options: params.options,\n chosen: params.chosen,\n reason: params.reason,\n }),\n JSON.stringify(keywords),\n fullText,\n timestamp,\n timestamp\n );\n\n // 失效相关缓存\n if (this.cache) {\n this.cache.invalidateProject(params.projectId);\n }\n\n return { id, success: true };\n }\n\n /**\n * 存储解决方案记忆\n */\n async storeSolution(\n params: SolutionContext & {\n projectId: string;\n tags?: string[];\n sessionId?: string;\n artifacts?: Record<string, string>;\n relations?: {\n replaces?: string[];\n relatedTo?: string[];\n impacts?: string[];\n derivedFrom?: string;\n };\n }\n ): Promise<{ id: string; success: boolean }> {\n const id = `mem_${nanoid()}`;\n const timestamp = new Date().toISOString();\n const summary = `[方案] ${params.problem}`;\n const fullText = `${params.problem} ${params.rootCause} ${params.solution} ${params.prevention || ''} ${params.relatedIssues?.join(' ') || ''}`;\n const keywords = [...(params.tags || []), ...(params.relatedIssues || [])];\n\n const stmt = this.db.prepare(`\n INSERT INTO memories (\n id, projectId, sessionId, timestamp, type, tags,\n summary, data, replaces, relatedTo, impacts, derivedFrom,\n context, keywords, fullText, createdAt, updatedAt\n ) VALUES (\n ?, ?, ?, ?, ?, ?,\n ?, ?, ?, ?, ?, ?,\n ?, ?, ?, ?, ?\n )\n `);\n\n stmt.run(\n id,\n params.projectId,\n params.sessionId || null,\n timestamp,\n MemoryType.SOLUTION,\n params.tags ? JSON.stringify(params.tags) : null,\n summary,\n JSON.stringify(params.artifacts || {}),\n params.relations?.replaces ? JSON.stringify(params.relations.replaces) : null,\n params.relations?.relatedTo ? JSON.stringify(params.relations.relatedTo) : null,\n params.relations?.impacts ? JSON.stringify(params.relations.impacts) : null,\n params.relations?.derivedFrom || null,\n JSON.stringify({\n problem: params.problem,\n rootCause: params.rootCause,\n solution: params.solution,\n prevention: params.prevention,\n relatedIssues: params.relatedIssues,\n }),\n JSON.stringify(keywords),\n fullText,\n timestamp,\n timestamp\n );\n\n // 失效相关缓存\n if (this.cache) {\n this.cache.invalidateProject(params.projectId);\n }\n\n return { id, success: true };\n }\n\n /**\n * 存储会话记忆\n */\n async storeSession(\n params: SessionContext & {\n projectId: string;\n sessionId?: string;\n }\n ): Promise<{ id: string; success: boolean }> {\n const id = `mem_${nanoid()}`;\n const timestamp = new Date().toISOString();\n const summary = `[会话] ${params.summary}`;\n const fullText = `${params.summary} ${params.decisions?.join(' ') || ''} ${params.unfinishedTasks?.join(' ') || ''} ${params.nextSteps?.join(' ') || ''}`;\n const keywords = [...(params.decisions || []), ...(params.unfinishedTasks || [])];\n\n const stmt = this.db.prepare(`\n INSERT INTO memories (\n id, projectId, sessionId, timestamp, type, tags,\n summary, data, replaces, relatedTo, impacts, derivedFrom,\n context, keywords, fullText, createdAt, updatedAt\n ) VALUES (\n ?, ?, ?, ?, ?, ?,\n ?, ?, ?, ?, ?, ?,\n ?, ?, ?, ?, ?\n )\n `);\n\n stmt.run(\n id,\n params.projectId,\n params.sessionId || id, // 使用当前id作为sessionId\n timestamp,\n MemoryType.SESSION,\n null, // tags\n summary,\n JSON.stringify({}),\n null, // replaces\n null, // relatedTo\n null, // impacts\n null, // derivedFrom\n JSON.stringify({\n summary: params.summary,\n decisions: params.decisions,\n unfinishedTasks: params.unfinishedTasks,\n nextSteps: params.nextSteps,\n }),\n JSON.stringify(keywords),\n fullText,\n timestamp,\n timestamp\n );\n\n // 失效相关缓存\n if (this.cache) {\n this.cache.invalidateProject(params.projectId);\n }\n\n return { id, success: true };\n }\n\n /**\n * 检索记忆\n */\n async recall(filters: SearchFilters): Promise<SearchResult> {\n const startTime = Date.now();\n\n // 检查缓存\n if (this.cache) {\n const cacheKey = LRUCache.generateKey(filters);\n const cached = this.cache.get(cacheKey);\n if (cached) {\n return cached; // 缓存命中,直接返回\n }\n }\n\n const strategy = filters.strategy || SearchStrategy.AUTO;\n const limit = filters.limit || 10;\n const offset = filters.offset || 0;\n\n let actualStrategy: SearchStrategy;\n let results: Memory[];\n let dbStartTime: number;\n let dbEndTime: number;\n let parseStartTime: number;\n\n // 策略选择\n const strategyStartTime = Date.now();\n\n // L1: 精确匹配(优先)\n if (strategy === SearchStrategy.EXACT || strategy === SearchStrategy.AUTO) {\n dbStartTime = Date.now();\n results = this.exactSearch(filters, limit, offset);\n dbEndTime = Date.now();\n actualStrategy = SearchStrategy.EXACT;\n\n // 如果L1找不到结果,降级到L2全文搜索\n if (results.length === 0 && strategy === SearchStrategy.AUTO) {\n dbStartTime = Date.now();\n results = this.fulltextSearch(filters, limit, offset);\n dbEndTime = Date.now();\n actualStrategy = SearchStrategy.FULLTEXT;\n }\n }\n // L2: 全文搜索\n else if (strategy === SearchStrategy.FULLTEXT) {\n dbStartTime = Date.now();\n results = this.fulltextSearch(filters, limit, offset);\n dbEndTime = Date.now();\n actualStrategy = SearchStrategy.FULLTEXT;\n }\n // L3: 语义检索(暂未实现)\n else {\n dbStartTime = Date.now();\n results = this.fulltextSearch(filters, limit, offset);\n dbEndTime = Date.now();\n actualStrategy = SearchStrategy.FULLTEXT;\n }\n\n const strategyTime = Date.now() - strategyStartTime;\n const took = Date.now() - startTime;\n\n // 计算解析时间(总时间 - 数据库时间)\n const dbTime = dbEndTime - dbStartTime;\n const parseTime = took - dbTime - strategyTime;\n\n const result: SearchResult = {\n memories: results,\n total: results.length,\n strategy: actualStrategy,\n took,\n metrics: {\n dbTime,\n parseTime: Math.max(0, parseTime), // 确保非负\n strategyTime,\n cacheHit: false, // 数据库查询,标记为未命中\n },\n };\n\n // 写入缓存\n if (this.cache) {\n const cacheKey = LRUCache.generateKey(filters);\n this.cache.set(cacheKey, result);\n }\n\n return result;\n }\n\n /**\n * L1: 精确匹配检索\n */\n private exactSearch(filters: SearchFilters, limit: number, offset: number): Memory[] {\n let sql = 'SELECT * FROM memories WHERE 1=1';\n const params: any[] = [];\n\n if (filters.projectId) {\n sql += ' AND projectId = ?';\n params.push(filters.projectId);\n }\n\n if (filters.type) {\n sql += ' AND type = ?';\n params.push(filters.type);\n }\n\n if (filters.sessionId) {\n sql += ' AND sessionId = ?';\n params.push(filters.sessionId);\n }\n\n // 精确匹配:在summary或fullText中查找完整query\n if (filters.query) {\n sql += ' AND (summary LIKE ? OR fullText LIKE ?)';\n params.push(`%${filters.query}%`, `%${filters.query}%`);\n }\n\n sql += ' ORDER BY timestamp DESC LIMIT ? OFFSET ?';\n params.push(limit, offset);\n\n const stmt = this.db.prepare(sql);\n const rows = stmt.all(...params) as any[];\n\n return rows.map(this.rowToMemory);\n }\n\n /**\n * L2: 全文搜索(FTS5)\n */\n private fulltextSearch(filters: SearchFilters, limit: number, offset: number): Memory[] {\n // 先不用FTS5,退化为LIKE查询\n // TODO: 调试FTS5后再启用\n let sql = 'SELECT * FROM memories WHERE 1=1';\n const params: any[] = [];\n\n if (filters.projectId) {\n sql += ' AND projectId = ?';\n params.push(filters.projectId);\n }\n\n if (filters.type) {\n sql += ' AND type = ?';\n params.push(filters.type);\n }\n\n if (filters.sessionId) {\n sql += ' AND sessionId = ?';\n params.push(filters.sessionId);\n }\n\n if (filters.query) {\n // 使用LIKE实现简单的全文搜索\n sql += ' AND (summary LIKE ? OR fullText LIKE ?)';\n params.push(`%${filters.query}%`, `%${filters.query}%`);\n }\n\n sql += ' ORDER BY timestamp DESC LIMIT ? OFFSET ?';\n params.push(limit, offset);\n\n const stmt = this.db.prepare(sql);\n const rows = stmt.all(...params) as any[];\n\n return rows.map(this.rowToMemory);\n }\n\n /**\n * 获取时间线\n */\n async getTimeline(options: TimelineOptions): Promise<TimelineResult> {\n let sql = 'SELECT * FROM memories WHERE projectId = ?';\n const params: any[] = [options.projectId];\n\n if (options.type) {\n sql += ' AND type = ?';\n params.push(options.type);\n }\n\n if (options.dateRange) {\n sql += ' AND timestamp >= ? AND timestamp <= ?';\n params.push(options.dateRange[0], options.dateRange[1]);\n }\n\n sql += ' ORDER BY timestamp DESC';\n\n if (options.limit) {\n sql += ' LIMIT ?';\n params.push(options.limit);\n }\n\n if (options.offset) {\n sql += ' OFFSET ?';\n params.push(options.offset);\n }\n\n const stmt = this.db.prepare(sql);\n const rows = stmt.all(...params) as any[];\n const memories = rows.map(this.rowToMemory);\n\n const entries: TimelineEntry[] = memories.map((memory, index) => ({\n memory,\n prevMemoryId: index > 0 ? memories[index - 1].meta.id : undefined,\n nextMemoryId: index < memories.length - 1 ? memories[index + 1].meta.id : undefined,\n }));\n\n return {\n entries,\n total: entries.length,\n };\n }\n\n /**\n * 获取关系链\n */\n async getRelations(options: RelationsOptions): Promise<RelationNode> {\n const memory = await this.getById(options.memoryId);\n if (!memory) {\n throw new Error(`Memory ${options.memoryId} not found`);\n }\n\n const depth = options.depth || 1;\n const relatedNodes: RelationNode[] = [];\n\n if (depth > 0) {\n // 查找所有相关记忆\n const relatedIds = [\n ...(memory.relations.replaces || []),\n ...(memory.relations.relatedTo || []),\n ...(memory.relations.impacts || []),\n ];\n\n if (memory.relations.derivedFrom) {\n relatedIds.push(memory.relations.derivedFrom);\n }\n\n for (const relatedId of relatedIds) {\n const relatedMemory = await this.getById(relatedId);\n if (relatedMemory) {\n // 递归查询关系链\n let nestedRelated: RelationNode[] | undefined = undefined;\n if (depth > 1) {\n const nestedResult = await this.getRelations({\n memoryId: relatedId,\n depth: depth - 1,\n });\n nestedRelated = nestedResult.related;\n }\n\n relatedNodes.push({\n memory: relatedMemory,\n related: nestedRelated,\n });\n }\n }\n }\n\n return {\n memory,\n related: relatedNodes.length > 0 ? relatedNodes : undefined,\n };\n }\n\n /**\n * 删除记忆\n */\n async delete(memoryId: string): Promise<{ success: boolean }> {\n // 先查询 projectId 用于缓存失效\n if (this.cache) {\n const memory = this.db.prepare('SELECT projectId FROM memories WHERE id = ?').get(memoryId) as {\n projectId: string;\n } | undefined;\n if (memory) {\n this.cache.invalidateProject(memory.projectId);\n }\n }\n\n const stmt = this.db.prepare('DELETE FROM memories WHERE id = ?');\n const result = stmt.run(memoryId);\n return { success: result.changes > 0 };\n }\n\n /**\n * 更新记忆\n */\n async update(memoryId: string, updates: Partial<Memory>): Promise<{ success: boolean }> {\n const fields: string[] = [];\n const params: any[] = [];\n\n if (updates.content) {\n if (updates.content.summary) {\n fields.push('summary = ?');\n params.push(updates.content.summary);\n }\n if (updates.content.data !== undefined) {\n fields.push('data = ?');\n params.push(JSON.stringify(updates.content.data));\n }\n }\n\n if (updates.meta?.tags) {\n fields.push('tags = ?');\n params.push(JSON.stringify(updates.meta.tags));\n }\n\n if (updates.relations) {\n if (updates.relations.replaces) {\n fields.push('replaces = ?');\n params.push(JSON.stringify(updates.relations.replaces));\n }\n if (updates.relations.relatedTo) {\n fields.push('relatedTo = ?');\n params.push(JSON.stringify(updates.relations.relatedTo));\n }\n if (updates.relations.impacts) {\n fields.push('impacts = ?');\n params.push(JSON.stringify(updates.relations.impacts));\n }\n if (updates.relations.derivedFrom) {\n fields.push('derivedFrom = ?');\n params.push(updates.relations.derivedFrom);\n }\n }\n\n if (fields.length === 0) {\n return { success: false };\n }\n\n fields.push('updatedAt = ?');\n params.push(new Date().toISOString());\n params.push(memoryId);\n\n const sql = `UPDATE memories SET ${fields.join(', ')} WHERE id = ?`;\n const stmt = this.db.prepare(sql);\n const result = stmt.run(...params);\n\n // 失效相关缓存\n if (this.cache && result.changes > 0) {\n const memory = this.db.prepare('SELECT projectId FROM memories WHERE id = ?').get(memoryId) as {\n projectId: string;\n } | undefined;\n if (memory) {\n this.cache.invalidateProject(memory.projectId);\n }\n }\n\n return { success: result.changes > 0 };\n }\n\n /**\n * 根据 ID 获取单个记忆\n */\n async getById(id: string): Promise<Memory | null> {\n const stmt = this.db.prepare('SELECT * FROM memories WHERE id = ?');\n const row = stmt.get(id) as any;\n return row ? this.rowToMemory(row) : null;\n }\n\n /**\n * 将数据库行转换为Memory对象\n */\n private rowToMemory(row: any): Memory {\n return {\n meta: {\n id: row.id,\n projectId: row.projectId,\n sessionId: row.sessionId,\n timestamp: row.timestamp,\n type: row.type as MemoryType,\n tags: row.tags ? JSON.parse(row.tags) : [],\n version: row.version,\n },\n content: {\n summary: row.summary,\n data: row.data ? JSON.parse(row.data) : {},\n },\n relations: {\n replaces: row.replaces ? JSON.parse(row.replaces) : undefined,\n relatedTo: row.relatedTo ? JSON.parse(row.relatedTo) : undefined,\n impacts: row.impacts ? JSON.parse(row.impacts) : undefined,\n derivedFrom: row.derivedFrom || undefined,\n },\n searchable: {\n keywords: row.keywords ? JSON.parse(row.keywords) : [],\n fullText: row.fullText,\n },\n createdAt: row.createdAt,\n updatedAt: row.updatedAt,\n };\n }\n\n /**\n * 关闭数据库连接\n */\n close(): void {\n this.db.close();\n }\n}\n","/**\n * 记忆类型枚举\n */\nexport enum MemoryType {\n /** 架构决策 */\n DECISION = 'decision',\n /** 问题解决方案 */\n SOLUTION = 'solution',\n /** 配置信息 */\n CONFIG = 'config',\n /** 代码实现 */\n CODE = 'code',\n /** 错误记录 */\n ERROR = 'error',\n /** 会话总结 */\n SESSION = 'session',\n}\n\n/**\n * 检索策略枚举\n */\nexport enum SearchStrategy {\n /** L1: 精确匹配(WHERE + 索引) */\n EXACT = 'exact',\n /** L2: 全文搜索(FTS5/Meilisearch) */\n FULLTEXT = 'fulltext',\n /** L3: 语义检索(Embedding 相似度) */\n SEMANTIC = 'semantic',\n /** 自动选择最优策略 */\n AUTO = 'auto',\n}\n\n/**\n * 关系类型\n */\nexport type RelationType = 'replaces' | 'relatedTo' | 'impacts' | 'derivedFrom';\n","import type Database from 'better-sqlite3';\n\n/**\n * 初始化数据库Schema\n */\nexport function initSchema(db: Database.Database): void {\n // 1. 创建memories主表\n db.exec(`\n CREATE TABLE IF NOT EXISTS memories (\n id TEXT PRIMARY KEY,\n projectId TEXT NOT NULL,\n sessionId TEXT,\n timestamp TEXT NOT NULL,\n type TEXT NOT NULL,\n tags TEXT, -- JSON数组: [\"tag1\", \"tag2\"]\n version INTEGER DEFAULT 1,\n\n -- content\n summary TEXT NOT NULL,\n data TEXT, -- JSON对象\n\n -- relations\n replaces TEXT, -- JSON数组\n relatedTo TEXT, -- JSON数组\n impacts TEXT, -- JSON数组\n derivedFrom TEXT,\n\n -- context(特定类型的上下文数据)\n context TEXT, -- JSON对象\n\n -- searchable\n keywords TEXT, -- JSON数组\n fullText TEXT,\n\n -- 时间戳\n createdAt TEXT NOT NULL,\n updatedAt TEXT NOT NULL,\n\n -- 索引字段\n UNIQUE(id)\n );\n `);\n\n // 2. 创建索引\n db.exec(`\n -- 项目ID索引(频繁按项目查询)\n CREATE INDEX IF NOT EXISTS idx_memories_projectId ON memories(projectId);\n\n -- 会话ID索引\n CREATE INDEX IF NOT EXISTS idx_memories_sessionId ON memories(sessionId);\n\n -- 类型索引\n CREATE INDEX IF NOT EXISTS idx_memories_type ON memories(type);\n\n -- 时间戳索引(用于时间线查询)\n CREATE INDEX IF NOT EXISTS idx_memories_timestamp ON memories(timestamp DESC);\n\n -- 复合索引(项目+类型)- 用于按项目和类型过滤\n CREATE INDEX IF NOT EXISTS idx_memories_project_type ON memories(projectId, type);\n\n -- 复合索引(项目+时间)- 用于项目时间线查询,性能提升显著\n CREATE INDEX IF NOT EXISTS idx_memories_project_timestamp ON memories(projectId, timestamp DESC);\n\n -- 复合索引(项目+类型+时间)- 用于按项目和类型过滤的时间线\n CREATE INDEX IF NOT EXISTS idx_memories_project_type_timestamp ON memories(projectId, type, timestamp DESC);\n\n -- 部分索引(仅索引有会话的记忆)- 减少索引大小\n CREATE INDEX IF NOT EXISTS idx_memories_session_active ON memories(sessionId, timestamp DESC)\n WHERE sessionId IS NOT NULL;\n `);\n\n // 3. 创建FTS5全文搜索表\n db.exec(`\n CREATE VIRTUAL TABLE IF NOT EXISTS memories_fts USING fts5(\n summary,\n fullText,\n tokenize = 'unicode61'\n );\n `);\n\n // 4. 创建触发器,自动同步FTS表\n db.exec(`\n -- 插入触发器\n CREATE TRIGGER IF NOT EXISTS memories_fts_insert AFTER INSERT ON memories BEGIN\n INSERT INTO memories_fts(rowid, summary, fullText)\n VALUES (new.rowid, new.summary, new.fullText);\n END;\n\n -- 更新触发器\n CREATE TRIGGER IF NOT EXISTS memories_fts_update AFTER UPDATE ON memories BEGIN\n UPDATE memories_fts\n SET summary = new.summary, fullText = new.fullText\n WHERE rowid = new.rowid;\n END;\n\n -- 删除触发器\n CREATE TRIGGER IF NOT EXISTS memories_fts_delete AFTER DELETE ON memories BEGIN\n DELETE FROM memories_fts WHERE rowid = old.rowid;\n END;\n `);\n}\n","import type { SearchResult, SearchFilters } from '@emp/core';\n\n/**\n * LRU 缓存节点\n */\ninterface CacheNode {\n key: string;\n value: SearchResult;\n prev: CacheNode | null;\n next: CacheNode | null;\n}\n\n/**\n * LRU(Least Recently Used)缓存\n * 用于缓存热点查询,提升检索性能\n */\nexport class LRUCache {\n private capacity: number;\n private cache: Map<string, CacheNode>;\n private head: CacheNode | null;\n private tail: CacheNode | null;\n private hits: number;\n private misses: number;\n\n constructor(capacity: number = 100) {\n this.capacity = capacity;\n this.cache = new Map();\n this.head = null;\n this.tail = null;\n this.hits = 0;\n this.misses = 0;\n }\n\n /**\n * 生成缓存 key\n */\n static generateKey(filters: SearchFilters): string {\n const parts = [\n filters.query || '',\n filters.projectId || '',\n filters.type || '',\n filters.sessionId || '',\n filters.strategy || '',\n filters.limit || '',\n filters.offset || '',\n (filters.tags || []).sort().join(','),\n ];\n return parts.join('|');\n }\n\n /**\n * 获取缓存\n */\n get(key: string): SearchResult | null {\n const node = this.cache.get(key);\n if (!node) {\n this.misses++;\n return null;\n }\n\n // 移到链表头部(最近使用)\n this.moveToHead(node);\n this.hits++;\n\n // 标记为缓存命中\n return {\n ...node.value,\n metrics: {\n dbTime: node.value.metrics?.dbTime || 0,\n parseTime: node.value.metrics?.parseTime || 0,\n strategyTime: node.value.metrics?.strategyTime,\n cacheHit: true,\n },\n };\n }\n\n /**\n * 设置缓存\n */\n set(key: string, value: SearchResult): void {\n let node = this.cache.get(key);\n\n if (node) {\n // 更新已存在的节点\n node.value = value;\n this.moveToHead(node);\n } else {\n // 创建新节点\n node = {\n key,\n value,\n prev: null,\n next: null,\n };\n\n this.cache.set(key, node);\n this.addToHead(node);\n\n // 超出容量,删除最少使用的\n if (this.cache.size > this.capacity) {\n const removed = this.removeTail();\n if (removed) {\n this.cache.delete(removed.key);\n }\n }\n }\n }\n\n /**\n * 清空缓存\n */\n clear(): void {\n this.cache.clear();\n this.head = null;\n this.tail = null;\n this.hits = 0;\n this.misses = 0;\n }\n\n /**\n * 失效指定项目的所有缓存\n */\n invalidateProject(projectId: string): void {\n const keysToDelete: string[] = [];\n\n for (const [key, _] of this.cache) {\n if (key.includes(`|${projectId}|`)) {\n keysToDelete.push(key);\n }\n }\n\n for (const key of keysToDelete) {\n const node = this.cache.get(key);\n if (node) {\n this.removeNode(node);\n this.cache.delete(key);\n }\n }\n }\n\n /**\n * 获取缓存统计\n */\n getStats() {\n const total = this.hits + this.misses;\n return {\n size: this.cache.size,\n capacity: this.capacity,\n hits: this.hits,\n misses: this.misses,\n hitRate: total > 0 ? this.hits / total : 0,\n };\n }\n\n // ========== 双向链表操作 ==========\n\n private addToHead(node: CacheNode): void {\n node.next = this.head;\n node.prev = null;\n\n if (this.head) {\n this.head.prev = node;\n }\n\n this.head = node;\n\n if (!this.tail) {\n this.tail = node;\n }\n }\n\n private removeNode(node: CacheNode): void {\n if (node.prev) {\n node.prev.next = node.next;\n } else {\n this.head = node.next;\n }\n\n if (node.next) {\n node.next.prev = node.prev;\n } else {\n this.tail = node.prev;\n }\n }\n\n private moveToHead(node: CacheNode): void {\n this.removeNode(node);\n this.addToHead(node);\n }\n\n private removeTail(): CacheNode | null {\n const node = this.tail;\n if (node) {\n this.removeNode(node);\n }\n return node;\n }\n}\n","import { PrismaClient, Prisma } from '@prisma/client';\nimport { nanoid } from 'nanoid';\nimport {\n type IStorage,\n type SearchFilters,\n type SearchResult,\n type TimelineOptions,\n type TimelineResult,\n type TimelineEntry,\n type RelationsOptions,\n type RelationNode,\n MemoryType,\n SearchStrategy,\n type Memory,\n type DecisionContext,\n type SolutionContext,\n type SessionContext,\n} from '@emp/core';\nimport { LRUCache } from './cache.js';\n\n/**\n * PostgreSQL存储实现(云版)\n * 使用Prisma ORM + PostgreSQL全文搜索\n */\nexport class PostgreSQLStorage implements IStorage {\n private prisma: PrismaClient;\n private cache: LRUCache | null;\n\n constructor(databaseUrl?: string, options?: { enableCache?: boolean; cacheSize?: number }) {\n this.prisma = new PrismaClient({\n datasources: databaseUrl\n ? {\n db: { url: databaseUrl },\n }\n : undefined,\n });\n\n // 初始化缓存(默认启用,容量100)\n this.cache = options?.enableCache !== false ? new LRUCache(options?.cacheSize || 100) : null;\n }\n\n /**\n * 通用存储方法\n */\n async store(params: {\n content: string;\n rawContext: Record<string, unknown>;\n projectId: string;\n type?: MemoryType;\n tags?: string[];\n sessionId?: string;\n relations?: {\n replaces?: string[];\n relatedTo?: string[];\n impacts?: string[];\n derivedFrom?: string;\n };\n }): Promise<{ id: string; success: boolean }> {\n const id = `mem_${nanoid()}`;\n const timestamp = new Date();\n const memoryType = params.type || MemoryType.CODE;\n\n await this.prisma.memory.create({\n data: {\n id,\n projectId: params.projectId,\n sessionId: params.sessionId || null,\n timestamp,\n type: memoryType,\n tags: params.tags || [],\n summary: params.content,\n data: params.rawContext as any,\n replaces: params.relations?.replaces || [],\n relatedTo: params.relations?.relatedTo || [],\n impacts: params.relations?.impacts || [],\n derivedFrom: params.relations?.derivedFrom || null,\n context: params.rawContext as any,\n keywords: params.tags || [],\n fullText: params.content,\n },\n });\n\n // 失效相关缓存\n if (this.cache) {\n this.cache.invalidateProject(params.projectId);\n }\n\n return { id, success: true };\n }\n\n /**\n * 存储决策记忆\n */\n async storeDecision(\n params: DecisionContext & {\n projectId: string;\n tags?: string[];\n sessionId?: string;\n relations?: {\n replaces?: string[];\n relatedTo?: string[];\n impacts?: string[];\n derivedFrom?: string;\n };\n }\n ): Promise<{ id: string; success: boolean }> {\n const id = `mem_${nanoid()}`;\n const timestamp = new Date();\n const summary = `[决策] ${params.question}`;\n const fullText = `${params.question} ${params.options.map((o) => o.name).join(' ')} ${params.reason}`;\n const keywords = [...(params.tags || []), ...params.options.map((o) => o.name), params.chosen];\n\n await this.prisma.memory.create({\n data: {\n id,\n projectId: params.projectId,\n sessionId: params.sessionId || null,\n timestamp,\n type: MemoryType.DECISION,\n tags: params.tags || [],\n summary,\n data: {},\n replaces: params.relations?.replaces || [],\n relatedTo: params.relations?.relatedTo || [],\n impacts: params.relations?.impacts || [],\n derivedFrom: params.relations?.derivedFrom || null,\n context: {\n question: params.question,\n analysis: params.analysis,\n options: params.options,\n chosen: params.chosen,\n reason: params.reason,\n } as any,\n keywords,\n fullText,\n },\n });\n\n // 失效相关缓存\n if (this.cache) {\n this.cache.invalidateProject(params.projectId);\n }\n\n return { id, success: true };\n }\n\n /**\n * 存储解决方案记忆\n */\n async storeSolution(\n params: SolutionContext & {\n projectId: string;\n tags?: string[];\n sessionId?: string;\n artifacts?: Record<string, string>;\n relations?: {\n replaces?: string[];\n relatedTo?: string[];\n impacts?: string[];\n derivedFrom?: string;\n };\n }\n ): Promise<{ id: string; success: boolean }> {\n const id = `mem_${nanoid()}`;\n const timestamp = new Date();\n const summary = `[方案] ${params.problem}`;\n const fullText = `${params.problem} ${params.rootCause} ${params.solution} ${params.prevention || ''} ${params.relatedIssues?.join(' ') || ''}`;\n const keywords = [...(params.tags || []), ...(params.relatedIssues || [])];\n\n await this.prisma.memory.create({\n data: {\n id,\n projectId: params.projectId,\n sessionId: params.sessionId || null,\n timestamp,\n type: MemoryType.SOLUTION,\n tags: params.tags || [],\n summary,\n data: (params.artifacts || {}) as any,\n replaces: params.relations?.replaces || [],\n relatedTo: params.relations?.relatedTo || [],\n impacts: params.relations?.impacts || [],\n derivedFrom: params.relations?.derivedFrom || null,\n context: {\n problem: params.problem,\n rootCause: params.rootCause,\n solution: params.solution,\n prevention: params.prevention,\n relatedIssues: params.relatedIssues,\n } as any,\n keywords,\n fullText,\n },\n });\n\n // 失效相关缓存\n if (this.cache) {\n this.cache.invalidateProject(params.projectId);\n }\n\n return { id, success: true };\n }\n\n /**\n * 存储会话记忆\n */\n async storeSession(\n params: SessionContext & {\n projectId: string;\n sessionId?: string;\n }\n ): Promise<{ id: string; success: boolean }> {\n const id = `mem_${nanoid()}`;\n const timestamp = new Date();\n const summary = `[会话] ${params.summary}`;\n const fullText = `${params.summary} ${params.decisions?.join(' ') || ''} ${params.unfinishedTasks?.join(' ') || ''} ${params.nextSteps?.join(' ') || ''}`;\n const keywords = [...(params.decisions || []), ...(params.unfinishedTasks || [])];\n\n await this.prisma.memory.create({\n data: {\n id,\n projectId: params.projectId,\n sessionId: params.sessionId || id,\n timestamp,\n type: MemoryType.SESSION,\n tags: [],\n summary,\n data: {},\n replaces: [],\n relatedTo: [],\n impacts: [],\n derivedFrom: null,\n context: {\n summary: params.summary,\n decisions: params.decisions,\n unfinishedTasks: params.unfinishedTasks,\n nextSteps: params.nextSteps,\n } as any,\n keywords,\n fullText,\n },\n });\n\n // 失效相关缓存\n if (this.cache) {\n this.cache.invalidateProject(params.projectId);\n }\n\n return { id, success: true };\n }\n\n /**\n * 检索记忆\n */\n async recall(filters: SearchFilters): Promise<SearchResult> {\n const startTime = Date.now();\n\n // 检查缓存\n if (this.cache) {\n const cacheKey = LRUCache.generateKey(filters);\n const cached = this.cache.get(cacheKey);\n if (cached) {\n return cached; // 缓存命中,直接返回\n }\n }\n\n const strategy = filters.strategy || SearchStrategy.AUTO;\n const limit = filters.limit || 10;\n const offset = filters.offset || 0;\n\n let actualStrategy: SearchStrategy;\n let results: Memory[];\n let dbStartTime: number;\n let dbEndTime: number;\n\n // 策略选择\n const strategyStartTime = Date.now();\n\n // L1: 精确匹配(优先)\n if (strategy === SearchStrategy.EXACT || strategy === SearchStrategy.AUTO) {\n dbStartTime = Date.now();\n results = await this.exactSearch(filters, limit, offset);\n dbEndTime = Date.now();\n actualStrategy = SearchStrategy.EXACT;\n\n // 如果L1找不到结果,降级到L2全文搜索\n if (results.length === 0 && strategy === SearchStrategy.AUTO) {\n dbStartTime = Date.now();\n results = await this.fulltextSearch(filters, limit, offset);\n dbEndTime = Date.now();\n actualStrategy = SearchStrategy.FULLTEXT;\n }\n }\n // L2: 全文搜索\n else if (strategy === SearchStrategy.FULLTEXT) {\n dbStartTime = Date.now();\n results = await this.fulltextSearch(filters, limit, offset);\n dbEndTime = Date.now();\n actualStrategy = SearchStrategy.FULLTEXT;\n }\n // L3: 语义检索(暂未实现)\n else {\n dbStartTime = Date.now();\n results = await this.fulltextSearch(filters, limit, offset);\n dbEndTime = Date.now();\n actualStrategy = SearchStrategy.FULLTEXT;\n }\n\n const strategyTime = Date.now() - strategyStartTime;\n const took = Date.now() - startTime;\n\n // 计算解析时间(总时间 - 数据库时间)\n const dbTime = dbEndTime - dbStartTime;\n const parseTime = took - dbTime - strategyTime;\n\n const result: SearchResult = {\n memories: results,\n total: results.length,\n strategy: actualStrategy,\n took,\n metrics: {\n dbTime,\n parseTime: Math.max(0, parseTime), // 确保非负\n strategyTime,\n cacheHit: false, // 数据库查询,标记为未命中\n },\n };\n\n // 写入缓存\n if (this.cache) {\n const cacheKey = LRUCache.generateKey(filters);\n this.cache.set(cacheKey, result);\n }\n\n return result;\n }\n\n /**\n * L1: 精确匹配检索\n */\n private async exactSearch(\n filters: SearchFilters,\n limit: number,\n offset: number\n ): Promise<Memory[]> {\n const where: Prisma.MemoryWhereInput = {};\n\n if (filters.projectId) {\n where.projectId = filters.projectId;\n }\n\n if (filters.type) {\n where.type = filters.type;\n }\n\n if (filters.sessionId) {\n where.sessionId = filters.sessionId;\n }\n\n if (filters.query) {\n where.OR = [\n { summary: { contains: filters.query, mode: 'insensitive' } },\n { fullText: { contains: filters.query, mode: 'insensitive' } },\n ];\n }\n\n const rows = await this.prisma.memory.findMany({\n where,\n orderBy: { timestamp: 'desc' },\n take: limit,\n skip: offset,\n });\n\n return rows.map(this.rowToMemory);\n }\n\n /**\n * L2: 全文搜索(PostgreSQL)\n */\n private async fulltextSearch(\n filters: SearchFilters,\n limit: number,\n offset: number\n ): Promise<Memory[]> {\n // 使用PostgreSQL的ILIKE进行简单全文搜索\n // 生产环境可以使用pg_trgm或to_tsvector实现更强大的搜索\n const where: Prisma.MemoryWhereInput = {};\n\n if (filters.projectId) {\n where.projectId = filters.projectId;\n }\n\n if (filters.type) {\n where.type = filters.type;\n }\n\n if (filters.sessionId) {\n where.sessionId = filters.sessionId;\n }\n\n if (filters.query) {\n where.OR = [\n { summary: { contains: filters.query, mode: 'insensitive' } },\n { fullText: { contains: filters.query, mode: 'insensitive' } },\n ];\n }\n\n const rows = await this.prisma.memory.findMany({\n where,\n orderBy: { timestamp: 'desc' },\n take: limit,\n skip: offset,\n });\n\n return rows.map(this.rowToMemory);\n }\n\n /**\n * 获取时间线\n */\n async getTimeline(options: TimelineOptions): Promise<TimelineResult> {\n const where: Prisma.MemoryWhereInput = {\n projectId: options.projectId,\n };\n\n if (options.type) {\n where.type = options.type;\n }\n\n if (options.dateRange) {\n where.timestamp = {\n gte: new Date(options.dateRange[0]),\n lte: new Date(options.dateRange[1]),\n };\n }\n\n const memories = await this.prisma.memory.findMany({\n where,\n orderBy: { timestamp: 'desc' },\n take: options.limit,\n skip: options.offset,\n });\n\n const converted = memories.map(this.rowToMemory);\n\n const entries: TimelineEntry[] = converted.map((memory, index) => ({\n memory,\n prevMemoryId: index > 0 ? converted[index - 1].meta.id : undefined,\n nextMemoryId: index < converted.length - 1 ? converted[index + 1].meta.id : undefined,\n }));\n\n return {\n entries,\n total: entries.length,\n };\n }\n\n /**\n * 获取关系链\n */\n async getRelations(options: RelationsOptions): Promise<RelationNode> {\n const memory = await this.getMemoryById(options.memoryId);\n if (!memory) {\n throw new Error(`Memory ${options.memoryId} not found`);\n }\n\n const depth = options.depth || 1;\n const relatedNodes: RelationNode[] = [];\n\n if (depth > 0) {\n // 查找所有相关记忆\n const relatedIds = [\n ...(memory.relations.replaces || []),\n ...(memory.relations.relatedTo || []),\n ...(memory.relations.impacts || []),\n ];\n\n if (memory.relations.derivedFrom) {\n relatedIds.push(memory.relations.derivedFrom);\n }\n\n for (const relatedId of relatedIds) {\n const relatedMemory = await this.getMemoryById(relatedId);\n if (relatedMemory) {\n // 递归查询关系链\n let nestedRelated: RelationNode[] | undefined = undefined;\n if (depth > 1) {\n const nestedResult = await this.getRelations({\n memoryId: relatedId,\n depth: depth - 1,\n });\n nestedRelated = nestedResult.related;\n }\n\n relatedNodes.push({\n memory: relatedMemory,\n related: nestedRelated,\n });\n }\n }\n }\n\n return {\n memory,\n related: relatedNodes.length > 0 ? relatedNodes : undefined,\n };\n }\n\n /**\n * 根据 ID 获取单个记忆\n */\n async getById(id: string): Promise<Memory | null> {\n const row = await this.prisma.memory.findUnique({\n where: { id },\n });\n return row ? this.rowToMemory(row) : null;\n }\n\n /**\n * 删除记忆\n */\n async delete(memoryId: string): Promise<{ success: boolean }> {\n try {\n // 先查询 projectId 用于缓存失效\n if (this.cache) {\n const memory = await this.prisma.memory.findUnique({\n where: { id: memoryId },\n select: { projectId: true },\n });\n if (memory) {\n this.cache.invalidateProject(memory.projectId);\n }\n }\n\n await this.prisma.memory.delete({\n where: { id: memoryId },\n });\n return { success: true };\n } catch (error) {\n return { success: false };\n }\n }\n\n /**\n * 更新记忆\n */\n async update(memoryId: string, updates: Partial<Memory>): Promise<{ success: boolean }> {\n try {\n const data: Prisma.MemoryUpdateInput = {};\n\n if (updates.content) {\n if (updates.content.summary) {\n data.summary = updates.content.summary;\n }\n if (updates.content.data !== undefined) {\n data.data = updates.content.data as any;\n }\n }\n\n if (updates.meta?.tags) {\n data.tags = updates.meta.tags;\n }\n\n if (updates.relations) {\n if (updates.relations.replaces) {\n data.replaces = updates.relations.replaces;\n }\n if (updates.relations.relatedTo) {\n data.relatedTo = updates.relations.relatedTo;\n }\n if (updates.relations.impacts) {\n data.impacts = updates.relations.impacts;\n }\n if (updates.relations.derivedFrom) {\n data.derivedFrom = updates.relations.derivedFrom;\n }\n }\n\n if (Object.keys(data).length === 0) {\n return { success: false };\n }\n\n await this.prisma.memory.update({\n where: { id: memoryId },\n data,\n });\n\n // 失效相关缓存\n if (this.cache) {\n const memory = await this.prisma.memory.findUnique({\n where: { id: memoryId },\n select: { projectId: true },\n });\n if (memory) {\n this.cache.invalidateProject(memory.projectId);\n }\n }\n\n return { success: true };\n } catch (error) {\n return { success: false };\n }\n }\n\n /**\n * 根据ID获取记忆\n */\n private async getMemoryById(id: string): Promise<Memory | null> {\n const row = await this.prisma.memory.findUnique({\n where: { id },\n });\n return row ? this.rowToMemory(row) : null;\n }\n\n /**\n * 将Prisma行转换为Memory对象\n */\n private rowToMemory(row: any): Memory {\n return {\n meta: {\n id: row.id,\n projectId: row.projectId,\n sessionId: row.sessionId,\n timestamp: row.timestamp.toISOString(),\n type: row.type as MemoryType,\n tags: row.tags || [],\n version: row.version,\n },\n content: {\n summary: row.summary,\n data: (row.data || {}) as Record<string, unknown>,\n },\n relations: {\n replaces: row.replaces || undefined,\n relatedTo: row.relatedTo || undefined,\n impacts: row.impacts || undefined,\n derivedFrom: row.derivedFrom || undefined,\n },\n searchable: {\n keywords: row.keywords || [],\n fullText: row.fullText,\n },\n createdAt: row.createdAt.toISOString(),\n updatedAt: row.updatedAt.toISOString(),\n };\n }\n\n /**\n * 关闭数据库连接\n */\n async close(): Promise<void> {\n await this.prisma.$disconnect();\n }\n}\n"],"mappings":"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","names":["MemoryType","SearchStrategy","nanoid","nanoid"]}
package/package.json ADDED
@@ -0,0 +1,57 @@
1
+ {
2
+ "name": "memory-pulse-mcp-server",
3
+ "version": "0.1.0",
4
+ "description": "Memory Pulse - 精准、结构化的 AI 上下文记忆系统 MCP Server",
5
+ "type": "module",
6
+ "main": "./dist/index.js",
7
+ "types": "./dist/index.d.ts",
8
+ "bin": {
9
+ "memory-pulse-mcp": "./dist/index.js"
10
+ },
11
+ "files": [
12
+ "dist",
13
+ "README.md"
14
+ ],
15
+ "keywords": [
16
+ "mcp",
17
+ "memory",
18
+ "ai",
19
+ "context",
20
+ "claude",
21
+ "model-context-protocol"
22
+ ],
23
+ "author": "jiahui",
24
+ "license": "MIT",
25
+ "repository": {
26
+ "type": "git",
27
+ "url": "https://github.com/jiahuidegit/memory-mcp-server.git"
28
+ },
29
+ "homepage": "https://github.com/jiahuidegit/memory-mcp-server#readme",
30
+ "bugs": {
31
+ "url": "https://github.com/jiahuidegit/memory-mcp-server/issues"
32
+ },
33
+ "dependencies": {
34
+ "@modelcontextprotocol/sdk": "^1.0.4",
35
+ "better-sqlite3": "^11.0.0",
36
+ "nanoid": "^5.0.9"
37
+ },
38
+ "optionalDependencies": {
39
+ "@prisma/client": "^6.0.0"
40
+ },
41
+ "devDependencies": {
42
+ "@types/better-sqlite3": "^7.6.12",
43
+ "tsup": "^8.0.0",
44
+ "typescript": "^5.6.0",
45
+ "vitest": "^2.0.0",
46
+ "@emp/core": "0.1.0",
47
+ "@emp/storage": "0.1.0"
48
+ },
49
+ "scripts": {
50
+ "build": "tsup",
51
+ "build:tsc": "tsc",
52
+ "dev": "tsup --watch",
53
+ "test": "vitest",
54
+ "typecheck": "tsc --noEmit",
55
+ "clean": "rm -rf dist"
56
+ }
57
+ }