@synth-coder/memhub 0.2.3 → 0.2.4
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.
- package/.eslintrc.cjs +45 -45
- package/.factory/commands/opsx-apply.md +150 -150
- package/.factory/commands/opsx-archive.md +155 -155
- package/.factory/commands/opsx-explore.md +171 -171
- package/.factory/commands/opsx-propose.md +104 -104
- package/.factory/skills/openspec-apply-change/SKILL.md +156 -156
- package/.factory/skills/openspec-archive-change/SKILL.md +114 -114
- package/.factory/skills/openspec-explore/SKILL.md +288 -288
- package/.factory/skills/openspec-propose/SKILL.md +110 -110
- package/.github/workflows/ci.yml +110 -74
- package/.github/workflows/release.yml +67 -0
- package/.iflow/commands/opsx-apply.md +152 -152
- package/.iflow/commands/opsx-archive.md +157 -157
- package/.iflow/commands/opsx-explore.md +173 -173
- package/.iflow/commands/opsx-propose.md +106 -106
- package/.iflow/skills/openspec-apply-change/SKILL.md +156 -156
- package/.iflow/skills/openspec-archive-change/SKILL.md +114 -114
- package/.iflow/skills/openspec-explore/SKILL.md +288 -288
- package/.iflow/skills/openspec-propose/SKILL.md +110 -110
- package/.prettierrc +11 -11
- package/AGENTS.md +167 -169
- package/README.md +276 -195
- package/README.zh-CN.md +245 -193
- package/dist/src/cli/agents/claude-code.d.ts +5 -0
- package/dist/src/cli/agents/claude-code.d.ts.map +1 -0
- package/dist/src/cli/agents/claude-code.js +14 -0
- package/dist/src/cli/agents/claude-code.js.map +1 -0
- package/dist/src/cli/agents/cline.d.ts +5 -0
- package/dist/src/cli/agents/cline.d.ts.map +1 -0
- package/dist/src/cli/agents/cline.js +14 -0
- package/dist/src/cli/agents/cline.js.map +1 -0
- package/dist/src/cli/agents/codex.d.ts +5 -0
- package/dist/src/cli/agents/codex.d.ts.map +1 -0
- package/dist/src/cli/agents/codex.js +14 -0
- package/dist/src/cli/agents/codex.js.map +1 -0
- package/dist/src/cli/agents/cursor.d.ts +5 -0
- package/dist/src/cli/agents/cursor.d.ts.map +1 -0
- package/dist/src/cli/agents/cursor.js +14 -0
- package/dist/src/cli/agents/cursor.js.map +1 -0
- package/dist/src/cli/agents/factory-droid.d.ts +5 -0
- package/dist/src/cli/agents/factory-droid.d.ts.map +1 -0
- package/dist/src/cli/agents/factory-droid.js +14 -0
- package/dist/src/cli/agents/factory-droid.js.map +1 -0
- package/dist/src/cli/agents/gemini-cli.d.ts +5 -0
- package/dist/src/cli/agents/gemini-cli.d.ts.map +1 -0
- package/dist/src/cli/agents/gemini-cli.js +14 -0
- package/dist/src/cli/agents/gemini-cli.js.map +1 -0
- package/dist/src/cli/agents/index.d.ts +14 -0
- package/dist/src/cli/agents/index.d.ts.map +1 -0
- package/dist/src/cli/agents/index.js +30 -0
- package/dist/src/cli/agents/index.js.map +1 -0
- package/dist/src/cli/agents/windsurf.d.ts +5 -0
- package/dist/src/cli/agents/windsurf.d.ts.map +1 -0
- package/dist/src/cli/agents/windsurf.js +14 -0
- package/dist/src/cli/agents/windsurf.js.map +1 -0
- package/dist/src/cli/index.d.ts +8 -0
- package/dist/src/cli/index.d.ts.map +1 -0
- package/dist/src/cli/index.js +168 -0
- package/dist/src/cli/index.js.map +1 -0
- package/dist/src/cli/init.d.ts +34 -0
- package/dist/src/cli/init.d.ts.map +1 -0
- package/dist/src/cli/init.js +160 -0
- package/dist/src/cli/init.js.map +1 -0
- package/dist/src/cli/instructions.d.ts +29 -0
- package/dist/src/cli/instructions.d.ts.map +1 -0
- package/dist/src/cli/instructions.js +141 -0
- package/dist/src/cli/instructions.js.map +1 -0
- package/dist/src/cli/types.d.ts +22 -0
- package/dist/src/cli/types.d.ts.map +1 -0
- package/dist/src/cli/types.js +86 -0
- package/dist/src/cli/types.js.map +1 -0
- package/dist/src/contracts/mcp.js +34 -34
- package/dist/src/contracts/schemas.js.map +1 -1
- package/dist/src/server/mcp-server.d.ts.map +1 -1
- package/dist/src/server/mcp-server.js +7 -14
- package/dist/src/server/mcp-server.js.map +1 -1
- package/dist/src/services/embedding-service.d.ts.map +1 -1
- package/dist/src/services/embedding-service.js +1 -1
- package/dist/src/services/embedding-service.js.map +1 -1
- package/dist/src/services/memory-service.d.ts.map +1 -1
- package/dist/src/services/memory-service.js.map +1 -1
- package/dist/src/storage/markdown-storage.d.ts.map +1 -1
- package/dist/src/storage/markdown-storage.js +1 -1
- package/dist/src/storage/markdown-storage.js.map +1 -1
- package/dist/src/storage/vector-index.d.ts.map +1 -1
- package/dist/src/storage/vector-index.js +4 -5
- package/dist/src/storage/vector-index.js.map +1 -1
- package/docs/README.md +21 -0
- package/docs/mcp-tools.md +136 -0
- package/docs/user-guide.md +182 -0
- package/package.json +61 -59
- package/src/cli/agents/claude-code.ts +14 -0
- package/src/cli/agents/cline.ts +14 -0
- package/src/cli/agents/codex.ts +14 -0
- package/src/cli/agents/cursor.ts +14 -0
- package/src/cli/agents/factory-droid.ts +14 -0
- package/src/cli/agents/gemini-cli.ts +14 -0
- package/src/cli/agents/index.ts +36 -0
- package/src/cli/agents/windsurf.ts +14 -0
- package/src/cli/index.ts +192 -0
- package/src/cli/init.ts +218 -0
- package/src/cli/instructions.ts +156 -0
- package/src/cli/types.ts +112 -0
- package/src/contracts/index.ts +12 -12
- package/src/contracts/mcp.ts +223 -223
- package/src/contracts/schemas.ts +307 -307
- package/src/contracts/types.ts +410 -410
- package/src/index.ts +8 -8
- package/src/server/index.ts +5 -5
- package/src/server/mcp-server.ts +169 -186
- package/src/services/embedding-service.ts +114 -114
- package/src/services/index.ts +5 -5
- package/src/services/memory-service.ts +656 -663
- package/src/storage/frontmatter-parser.ts +243 -243
- package/src/storage/index.ts +6 -6
- package/src/storage/markdown-storage.ts +228 -236
- package/src/storage/vector-index.ts +159 -160
- package/src/utils/index.ts +5 -5
- package/src/utils/slugify.ts +63 -63
- package/test/cli/init.test.ts +380 -0
- package/test/contracts/schemas.test.ts +313 -313
- package/test/contracts/types.test.ts +21 -21
- package/test/frontmatter-parser-more.test.ts +94 -94
- package/test/server/mcp-server.test.ts +211 -210
- package/test/services/memory-service-edge.test.ts +248 -248
- package/test/services/memory-service.test.ts +291 -279
- package/test/storage/frontmatter-parser.test.ts +223 -223
- package/test/storage/markdown-storage.test.ts +226 -217
- package/test/storage/storage-edge.test.ts +238 -238
- package/test/storage/vector-index.test.ts +149 -153
- package/test/utils/slugify-edge.test.ts +94 -94
- package/test/utils/slugify.test.ts +72 -68
- package/tsconfig.json +25 -25
- package/tsconfig.test.json +8 -8
- package/vitest.config.ts +29 -29
- package/docs/architecture-diagrams.md +0 -368
- package/docs/architecture.md +0 -381
- package/docs/contracts.md +0 -190
- package/docs/prompt-template.md +0 -33
- package/docs/proposals/mcp-typescript-sdk-refactor.md +0 -568
- package/docs/proposals/proposal-close-gates.md +0 -58
- package/docs/tool-calling-policy.md +0 -101
- package/docs/vector-search.md +0 -306
package/docs/architecture.md
DELETED
|
@@ -1,381 +0,0 @@
|
|
|
1
|
-
# MemHub 架构设计文档
|
|
2
|
-
|
|
3
|
-
## 概述
|
|
4
|
-
|
|
5
|
-
MemHub 是一个基于 Git 友好的记忆存储系统,使用 Markdown 格式存储记忆条目,通过 YAML Front Matter 存储元数据。它实现了 MCP (Model Context Protocol) Server,通过 stdio 进行通信,并集成了向量语义搜索功能以提供更智能的记忆检索。
|
|
6
|
-
|
|
7
|
-
## 设计原则
|
|
8
|
-
|
|
9
|
-
1. **Git 友好**: 所有数据以纯文本 Markdown 文件存储,天然支持版本控制
|
|
10
|
-
2. **人类可读**: 记忆条目可以直接用文本编辑器打开阅读
|
|
11
|
-
3. **简单优先**: Markdown 作为唯一数据源,向量索引仅为搜索缓存
|
|
12
|
-
4. **契约先行**: 接口和类型定义先于实现
|
|
13
|
-
5. **测试驱动**: 严格遵循 TDD (红-绿-重构)
|
|
14
|
-
6. **混合搜索**: 支持基于元数据的过滤和基于向量的语义搜索
|
|
15
|
-
7. **懒加载**: 向量模型和索引按需加载,降低启动成本
|
|
16
|
-
|
|
17
|
-
## 系统架构
|
|
18
|
-
|
|
19
|
-
```
|
|
20
|
-
┌─────────────────────────────────────────────────────────────┐
|
|
21
|
-
│ MCP Client │
|
|
22
|
-
│ (Claude Desktop, etc.) │
|
|
23
|
-
└──────────────────────┬──────────────────────────────────────┘
|
|
24
|
-
│ stdio
|
|
25
|
-
▼
|
|
26
|
-
┌─────────────────────────────────────────────────────────────┐
|
|
27
|
-
│ MemHub MCP Server │
|
|
28
|
-
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────────┐ │
|
|
29
|
-
│ │ MCP Router │ │ Services │ │ Storage Layer │ │
|
|
30
|
-
│ │ │ │ │ │ │ │
|
|
31
|
-
│ │ - list_tools │ │ - memoryLoad │ │ - MarkdownStorage│ │
|
|
32
|
-
│ │ - call_tool │ │ - memoryUpdate│ │ - FrontMatter │ │
|
|
33
|
-
│ │ │ │ │ │ - VectorIndex │ │
|
|
34
|
-
│ │ │ │ │ │ - EmbeddingSvc │ │
|
|
35
|
-
│ └──────────────┘ └──────────────┘ └──────────────────┘ │
|
|
36
|
-
└──────────────────────┬──────────────────────────────────────┘
|
|
37
|
-
│
|
|
38
|
-
▼
|
|
39
|
-
┌─────────────────────────────────────────────────────────────┐
|
|
40
|
-
│ Storage Layer │
|
|
41
|
-
│ ┌────────────────────┐ ┌────────────────────────┐ │
|
|
42
|
-
│ │ Markdown Storage │ │ Vector Search Cache │ │
|
|
43
|
-
│ │ (Source of Truth) │ │ (LanceDB) │ │
|
|
44
|
-
│ │ │ │ │ │
|
|
45
|
-
│ │ YYYY-MM-DD/ │ │ .lancedb/ │ │
|
|
46
|
-
│ │ session_uuid/ │◄──────►│ - 384-dim vectors │ │
|
|
47
|
-
│ │ title-slug.md │ │ - Cosine distance │ │
|
|
48
|
-
│ │ │ │ - Rebuildable │ │
|
|
49
|
-
│ └────────────────────┘ └────────────────────────┘ │
|
|
50
|
-
└─────────────────────────────────────────────────────────────┘
|
|
51
|
-
│
|
|
52
|
-
▼
|
|
53
|
-
┌─────────────────────────────────────────────────────────────┐
|
|
54
|
-
│ Embedding Service │
|
|
55
|
-
│ ┌─────────────────────────────────────────────────────┐ │
|
|
56
|
-
│ │ ONNX Model (all-MiniLM-L6-v2) │ │
|
|
57
|
-
│ │ - 384-dimension output │ │
|
|
58
|
-
│ │ - Cached at ~/.cache/huggingface │ │
|
|
59
|
-
│ │ - Lazy initialization │ │
|
|
60
|
-
│ └─────────────────────────────────────────────────────┘ │
|
|
61
|
-
└─────────────────────────────────────────────────────────────┘
|
|
62
|
-
```
|
|
63
|
-
|
|
64
|
-
## 核心组件
|
|
65
|
-
|
|
66
|
-
### 1. MCP Server (src/server/mcp-server.ts)
|
|
67
|
-
|
|
68
|
-
- 入口点,处理 stdio 通信
|
|
69
|
-
- 实现 MCP 协议的生命周期管理
|
|
70
|
-
- 路由工具调用到 MemoryService
|
|
71
|
-
- 支持 `MEMHUB_STORAGE_PATH` 和 `MEMHUB_VECTOR_SEARCH` 环境变量
|
|
72
|
-
|
|
73
|
-
### 2. Services (src/services/)
|
|
74
|
-
|
|
75
|
-
业务逻辑层,包含:
|
|
76
|
-
|
|
77
|
-
- **MemoryService**: 统一的记忆管理服务
|
|
78
|
-
- `memoryLoad()`: 加载记忆(支持向量搜索和元数据过滤)
|
|
79
|
-
- `memoryUpdate()`: 创建或更新记忆(自动维护向量索引)
|
|
80
|
-
- **EmbeddingService**: 文本嵌入服务(单例模式)
|
|
81
|
-
- 基于 `@xenova/transformers` 的 ONNX 模型
|
|
82
|
-
- 输出 384 维归一化向量
|
|
83
|
-
- 首次使用时下载并缓存到 `~/.cache/huggingface`
|
|
84
|
-
|
|
85
|
-
### 3. Storage Layer (src/storage/)
|
|
86
|
-
|
|
87
|
-
数据持久化层:
|
|
88
|
-
|
|
89
|
-
- **MarkdownStorage**: Markdown 文件读写(唯一数据源)
|
|
90
|
-
- **FrontMatterParser**: YAML Front Matter 解析和序列化
|
|
91
|
-
- **VectorIndex**: LanceDB 向量索引(搜索缓存,可重建)
|
|
92
|
-
|
|
93
|
-
### 4. Contracts (src/contracts/)
|
|
94
|
-
|
|
95
|
-
类型定义和 Zod 契约:
|
|
96
|
-
|
|
97
|
-
- **types.ts**: TypeScript 类型定义
|
|
98
|
-
- **schemas.ts**: Zod 验证模式
|
|
99
|
-
- **mcp.ts**: MCP 工具定义和描述
|
|
100
|
-
|
|
101
|
-
## 数据模型
|
|
102
|
-
|
|
103
|
-
### Memory Entry (记忆条目)
|
|
104
|
-
|
|
105
|
-
```typescript
|
|
106
|
-
interface Memory {
|
|
107
|
-
// Identity
|
|
108
|
-
id: string; // UUID v4
|
|
109
|
-
|
|
110
|
-
// Metadata (YAML Front Matter)
|
|
111
|
-
createdAt: string; // ISO 8601
|
|
112
|
-
updatedAt: string; // ISO 8601
|
|
113
|
-
sessionId?: string; // 会话 UUID(并发隔离)
|
|
114
|
-
entryType?: EntryType; // 记忆类型
|
|
115
|
-
tags: string[]; // 标签数组
|
|
116
|
-
category: string; // 分类
|
|
117
|
-
importance: number; // 1-5 重要性等级
|
|
118
|
-
|
|
119
|
-
// Content (Markdown Body)
|
|
120
|
-
title: string; // Markdown H1 标题
|
|
121
|
-
content: string; // Markdown 正文
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
type EntryType = 'preference' | 'decision' | 'context' | 'fact';
|
|
125
|
-
```
|
|
126
|
-
|
|
127
|
-
### File Naming Convention
|
|
128
|
-
|
|
129
|
-
```
|
|
130
|
-
memories/YYYY-MM-DD/session_uuid/timestamp-title-slug.md
|
|
131
|
-
|
|
132
|
-
Examples:
|
|
133
|
-
- memories/2026-03-03/550e8400-e29b-41d4-a716-446655440111/2026-03-03T16-40-12-123Z-task-summary.md
|
|
134
|
-
- memories/2026-03-04/a1b2c3d4-e5f6-7890-abcd-ef1234567890/2026-03-04T10-15-30-456Z-architecture-decision.md
|
|
135
|
-
```
|
|
136
|
-
|
|
137
|
-
**并发安全设计:**
|
|
138
|
-
|
|
139
|
-
- 同一天按 `session_uuid` 分桶,避免多 CLI 写入冲突
|
|
140
|
-
- 每条记录独立文件,支持并发读写
|
|
141
|
-
- 文件路径包含时间戳,保证唯一性
|
|
142
|
-
|
|
143
|
-
### Markdown Format
|
|
144
|
-
|
|
145
|
-
```markdown
|
|
146
|
-
---
|
|
147
|
-
id: '550e8400-e29b-41d4-a716-446655440000'
|
|
148
|
-
created_at: '2026-03-03T08:00:00.000Z'
|
|
149
|
-
updated_at: '2026-03-03T08:00:00.000Z'
|
|
150
|
-
session_id: 'a1b2c3d4-e5f6-7890-abcd-ef1234567890'
|
|
151
|
-
entry_type: 'decision'
|
|
152
|
-
tags:
|
|
153
|
-
- architecture
|
|
154
|
-
- vector-search
|
|
155
|
-
category: 'engineering'
|
|
156
|
-
importance: 4
|
|
157
|
-
---
|
|
158
|
-
|
|
159
|
-
# Integrate Vector Semantic Search
|
|
160
|
-
|
|
161
|
-
Add LanceDB-based vector search with local ONNX embedding model.
|
|
162
|
-
|
|
163
|
-
## Key Decisions
|
|
164
|
-
|
|
165
|
-
- Use all-MiniLM-L6-v2 model (384-dim output)
|
|
166
|
-
- Store vectors in `.lancedb/` alongside markdown files
|
|
167
|
-
- Vector index is rebuildable from markdown source
|
|
168
|
-
```
|
|
169
|
-
|
|
170
|
-
## MCP Tools
|
|
171
|
-
|
|
172
|
-
MemHub 使用简化的 2-tool 接口,形成「先加载 STM,再回写 STM」的闭环。
|
|
173
|
-
|
|
174
|
-
### 1. `memory_load`
|
|
175
|
-
|
|
176
|
-
统一记忆加载接口,用于用户输入后第一轮主动加载短期记忆。
|
|
177
|
-
|
|
178
|
-
**Input:**
|
|
179
|
-
|
|
180
|
-
```typescript
|
|
181
|
-
interface MemoryLoadInput {
|
|
182
|
-
id?: string; // 指定单条记忆 ID
|
|
183
|
-
query?: string; // 语义搜索查询(启用向量搜索)
|
|
184
|
-
category?: string; // 分类过滤
|
|
185
|
-
tags?: string[]; // 标签过滤
|
|
186
|
-
limit?: number; // 返回数量限制(默认 20)
|
|
187
|
-
}
|
|
188
|
-
```
|
|
189
|
-
|
|
190
|
-
**Output:**
|
|
191
|
-
|
|
192
|
-
```typescript
|
|
193
|
-
interface MemoryLoadOutput {
|
|
194
|
-
items: Memory[]; // 记忆条目数组
|
|
195
|
-
total: number; // 总数
|
|
196
|
-
}
|
|
197
|
-
```
|
|
198
|
-
|
|
199
|
-
**行为特性:**
|
|
200
|
-
|
|
201
|
-
- 当提供 `query` 时,使用向量语义搜索(需要 `MEMHUB_VECTOR_SEARCH=true`)
|
|
202
|
-
- 当提供 `tags`、`category`、`date` 时,使用元数据过滤
|
|
203
|
-
- 支持组合条件(先向量搜索再过滤)
|
|
204
|
-
- 向量搜索失败时自动降级为文本搜索
|
|
205
|
-
|
|
206
|
-
### 2. `memory_update`
|
|
207
|
-
|
|
208
|
-
统一记忆回写接口,用于本轮结束前主动回写记忆。
|
|
209
|
-
|
|
210
|
-
**Input:**
|
|
211
|
-
|
|
212
|
-
```typescript
|
|
213
|
-
type EntryType = 'preference' | 'decision' | 'context' | 'fact';
|
|
214
|
-
|
|
215
|
-
interface MemoryUpdateInput {
|
|
216
|
-
id?: string; // 有则更新,无则创建
|
|
217
|
-
sessionId?: string; // 无则服务端自动生成并返回
|
|
218
|
-
mode?: 'append' | 'upsert'; // 默认 append
|
|
219
|
-
entryType?: EntryType; // 记忆类型
|
|
220
|
-
title?: string; // 标题(Markdown H1)
|
|
221
|
-
content: string; // 内容(必填,Markdown)
|
|
222
|
-
tags?: string[]; // 标签
|
|
223
|
-
category?: string; // 分类
|
|
224
|
-
importance?: number; // 重要性 1-5(默认 3)
|
|
225
|
-
}
|
|
226
|
-
```
|
|
227
|
-
|
|
228
|
-
**Output:**
|
|
229
|
-
|
|
230
|
-
```typescript
|
|
231
|
-
interface MemoryUpdateOutput {
|
|
232
|
-
id: string; // 记忆 ID
|
|
233
|
-
sessionId: string; // 会话 ID
|
|
234
|
-
filePath: string; // 存储路径
|
|
235
|
-
created: boolean; // 是否新建
|
|
236
|
-
updated: boolean; // 是否更新
|
|
237
|
-
memory: Memory; // 完整记忆对象
|
|
238
|
-
}
|
|
239
|
-
```
|
|
240
|
-
|
|
241
|
-
**行为特性:**
|
|
242
|
-
|
|
243
|
-
- 自动生成 UUID 和时间戳
|
|
244
|
-
- 自动维护向量索引(后台异步)
|
|
245
|
-
- 支持并发安全:按 `YYYY-MM-DD/session_uuid/` 分目录存储
|
|
246
|
-
- 向量索引失败不影响 Markdown 写入
|
|
247
|
-
|
|
248
|
-
## 错误处理
|
|
249
|
-
|
|
250
|
-
所有错误使用标准 MCP 错误格式:
|
|
251
|
-
|
|
252
|
-
```typescript
|
|
253
|
-
interface McpError {
|
|
254
|
-
code: number; // MCP error code
|
|
255
|
-
message: string; // Human readable message
|
|
256
|
-
data?: unknown; // Additional context
|
|
257
|
-
}
|
|
258
|
-
```
|
|
259
|
-
|
|
260
|
-
错误码定义:
|
|
261
|
-
|
|
262
|
-
- `INVALID_PARAMS`: 参数验证失败
|
|
263
|
-
- `NOT_FOUND`: 记忆条目不存在
|
|
264
|
-
- `STORAGE_ERROR`: 存储操作失败
|
|
265
|
-
- `INTERNAL_ERROR`: 内部错误
|
|
266
|
-
|
|
267
|
-
## 配置
|
|
268
|
-
|
|
269
|
-
通过环境变量配置:
|
|
270
|
-
|
|
271
|
-
```bash
|
|
272
|
-
MEMHUB_STORAGE_PATH=/path/to/memories # 存储目录,默认: ./memories
|
|
273
|
-
MEMHUB_LOG_LEVEL=info # 日志级别: debug, info, warn, error
|
|
274
|
-
MEMHUB_VECTOR_SEARCH=true # 启用向量搜索,默认: true
|
|
275
|
-
```
|
|
276
|
-
|
|
277
|
-
## 向量搜索架构
|
|
278
|
-
|
|
279
|
-
### 设计原则
|
|
280
|
-
|
|
281
|
-
1. **Markdown 为准**: Markdown 文件是唯一数据源,向量索引仅为搜索缓存
|
|
282
|
-
2. **可重建性**: 向量索引可随时从 Markdown 文件重建
|
|
283
|
-
3. **懒加载**: ONNX 模型和 LanceDB 按需加载,降低启动成本
|
|
284
|
-
4. **降级友好**: 向量搜索失败不影响基本功能
|
|
285
|
-
|
|
286
|
-
### Embedding 服务
|
|
287
|
-
|
|
288
|
-
- **模型**: Xenova/all-MiniLM-L6-v2 (~23MB)
|
|
289
|
-
- **输出维度**: 384
|
|
290
|
-
- **缓存位置**: `~/.cache/huggingface/`
|
|
291
|
-
- **单例模式**: 全局共享一个模型实例
|
|
292
|
-
|
|
293
|
-
### Vector Index
|
|
294
|
-
|
|
295
|
-
- **存储**: LanceDB (`.lancedb/` 目录)
|
|
296
|
-
- **距离度量**: Cosine distance
|
|
297
|
-
- **索引字段**:
|
|
298
|
-
- `id`: 记忆 UUID
|
|
299
|
-
- `vector`: 384 维浮点向量
|
|
300
|
-
- `title`, `category`, `tags`, `importance`: 元数据过滤
|
|
301
|
-
|
|
302
|
-
### 搜索流程
|
|
303
|
-
|
|
304
|
-
1. **Query Embedding**: 将查询文本转换为 384 维向量
|
|
305
|
-
2. **Vector Search**: 在 LanceDB 中查找最相似的向量
|
|
306
|
-
3. **Metadata Filter**: 可选地按 tags/category/date 过滤
|
|
307
|
-
4. **Ranking**: 按距离排序(距离越小越相似)
|
|
308
|
-
5. **Result Loading**: 从 Markdown 文件加载完整记忆内容
|
|
309
|
-
|
|
310
|
-
## 技术栈
|
|
311
|
-
|
|
312
|
-
- **Runtime**: Node.js 18+
|
|
313
|
-
- **Language**: TypeScript 5.9+
|
|
314
|
-
- **Protocol**: MCP (Model Context Protocol) via @modelcontextprotocol/sdk
|
|
315
|
-
- **Transport**: stdio
|
|
316
|
-
- **Storage**:
|
|
317
|
-
- **Markdown**: 纯文本存储(唯一数据源)
|
|
318
|
-
- **Vector DB**: LanceDB (基于 Apache Arrow)
|
|
319
|
-
- **AI/ML**:
|
|
320
|
-
- **Embedding**: @xenova/transformers (all-MiniLM-L6-v2 ONNX 模型)
|
|
321
|
-
- **Vector Dimension**: 384
|
|
322
|
-
- **Validation**: Zod 3.25+
|
|
323
|
-
- **Testing**: Vitest (覆盖率 >= 80%)
|
|
324
|
-
- **Linting**: ESLint + Prettier
|
|
325
|
-
|
|
326
|
-
## 目录结构
|
|
327
|
-
|
|
328
|
-
```
|
|
329
|
-
memhub/
|
|
330
|
-
├── docs/
|
|
331
|
-
│ ├── architecture.md # 本文档
|
|
332
|
-
│ ├── architecture-diagrams.md # 架构图(Mermaid)
|
|
333
|
-
│ ├── contracts.md # 契约文档
|
|
334
|
-
│ ├── tool-calling-policy.md # 工具调用策略
|
|
335
|
-
│ └── prompt-template.md # Agent Prompt 模板
|
|
336
|
-
├── src/
|
|
337
|
-
│ ├── contracts/ # 类型和契约
|
|
338
|
-
│ │ ├── types.ts
|
|
339
|
-
│ │ ├── schemas.ts
|
|
340
|
-
│ │ └── mcp.ts
|
|
341
|
-
│ ├── server/ # MCP Server
|
|
342
|
-
│ │ └── mcp-server.ts
|
|
343
|
-
│ ├── services/ # 业务逻辑
|
|
344
|
-
│ │ ├── memory-service.ts
|
|
345
|
-
│ │ └── embedding-service.ts
|
|
346
|
-
│ ├── storage/ # 存储层
|
|
347
|
-
│ │ ├── markdown-storage.ts
|
|
348
|
-
│ │ ├── frontmatter-parser.ts
|
|
349
|
-
│ │ └── vector-index.ts
|
|
350
|
-
│ └── utils/ # 工具函数
|
|
351
|
-
│ └── slugify.ts
|
|
352
|
-
├── test/ # 测试
|
|
353
|
-
│ ├── unit/
|
|
354
|
-
│ └── integration/
|
|
355
|
-
├── .github/
|
|
356
|
-
│ └── workflows/
|
|
357
|
-
│ └── ci.yml # CI 配置
|
|
358
|
-
├── package.json
|
|
359
|
-
├── tsconfig.json
|
|
360
|
-
├── vitest.config.ts
|
|
361
|
-
├── .eslintrc.cjs
|
|
362
|
-
├── .prettierrc
|
|
363
|
-
└── README.md
|
|
364
|
-
```
|
|
365
|
-
|
|
366
|
-
## 开发流程
|
|
367
|
-
|
|
368
|
-
1. **设计**: 先写架构文档和契约
|
|
369
|
-
2. **契约**: 定义 TypeScript 类型和 Zod Schema
|
|
370
|
-
3. **测试**: 编写红色测试(先失败)
|
|
371
|
-
4. **实现**: 编写最小实现使测试通过(绿色)
|
|
372
|
-
5. **重构**: 优化代码结构
|
|
373
|
-
6. **重复**: 循环 3-5 步
|
|
374
|
-
|
|
375
|
-
## 质量门禁
|
|
376
|
-
|
|
377
|
-
- ✅ ESLint 无错误
|
|
378
|
-
- ✅ Prettier 格式化检查通过
|
|
379
|
-
- ✅ TypeScript 严格类型检查通过
|
|
380
|
-
- ✅ 单元测试全部通过
|
|
381
|
-
- ✅ 代码覆盖率 >= 80%
|
package/docs/contracts.md
DELETED
|
@@ -1,190 +0,0 @@
|
|
|
1
|
-
# MemHub 契约文档(v0.2.0)
|
|
2
|
-
|
|
3
|
-
当前对外 MCP 工具采用简化的 2-tool 接口:
|
|
4
|
-
|
|
5
|
-
1. `memory_load`(首轮):统一记忆加载接口
|
|
6
|
-
2. `memory_update`(末轮):统一记忆回写接口
|
|
7
|
-
|
|
8
|
-
目标是形成稳定闭环:**先读 STM,再回写 STM**。
|
|
9
|
-
|
|
10
|
-
## 核心特性
|
|
11
|
-
|
|
12
|
-
- **向量语义搜索**: 支持基于 query 的语义相似度搜索
|
|
13
|
-
- **元数据过滤**: 支持按 tags、category、date 过滤
|
|
14
|
-
- **混合搜索**: 可组合向量搜索和元数据过滤
|
|
15
|
-
- **并发安全**: 按 session_uuid 分目录存储,支持多 CLI 并发
|
|
16
|
-
|
|
17
|
-
---
|
|
18
|
-
|
|
19
|
-
## 1) memory_load
|
|
20
|
-
|
|
21
|
-
用于用户输入后第一轮主动加载短期记忆。支持向量语义搜索和元数据过滤。
|
|
22
|
-
|
|
23
|
-
### 输入
|
|
24
|
-
|
|
25
|
-
```ts
|
|
26
|
-
interface MemoryLoadInput {
|
|
27
|
-
id?: string; // 指定单条记忆 ID(优先级最高)
|
|
28
|
-
query?: string; // 语义搜索查询(启用向量搜索)
|
|
29
|
-
category?: string; // 分类过滤
|
|
30
|
-
tags?: string[]; // 标签过滤
|
|
31
|
-
limit?: number; // 返回数量限制,默认 20
|
|
32
|
-
}
|
|
33
|
-
```
|
|
34
|
-
|
|
35
|
-
### 行为说明
|
|
36
|
-
|
|
37
|
-
1. **向量搜索** (当提供 `query` 时):
|
|
38
|
-
- 使用 ONNX 模型将 query 转换为 384 维向量
|
|
39
|
-
- 在 LanceDB 中搜索最相似的向量
|
|
40
|
-
- 返回按相似度排序的结果
|
|
41
|
-
|
|
42
|
-
2. **元数据过滤** (当提供 `tags`、`category`、`date` 时):
|
|
43
|
-
- 在文件系统中扫描匹配的 Markdown 文件
|
|
44
|
-
- 解析 YAML Front Matter 进行过滤
|
|
45
|
-
- 支持多条件组合
|
|
46
|
-
|
|
47
|
-
3. **混合模式**:
|
|
48
|
-
- 先进行向量搜索获取候选集
|
|
49
|
-
- 再按元数据条件过滤
|
|
50
|
-
- 结合相似度得分和匹配度排序
|
|
51
|
-
|
|
52
|
-
4. **降级处理**:
|
|
53
|
-
- 向量搜索失败时自动降级为文本搜索
|
|
54
|
-
- 保证基本功能可用
|
|
55
|
-
|
|
56
|
-
### 输出
|
|
57
|
-
|
|
58
|
-
```ts
|
|
59
|
-
interface MemoryLoadOutput {
|
|
60
|
-
items: Memory[];
|
|
61
|
-
total: number;
|
|
62
|
-
}
|
|
63
|
-
```
|
|
64
|
-
|
|
65
|
-
---
|
|
66
|
-
|
|
67
|
-
## 2) memory_update
|
|
68
|
-
|
|
69
|
-
用于本轮结束前主动回写记忆。自动维护 Markdown 文件和向量索引。
|
|
70
|
-
|
|
71
|
-
### 输入
|
|
72
|
-
|
|
73
|
-
```ts
|
|
74
|
-
type EntryType = 'preference' | 'decision' | 'context' | 'fact';
|
|
75
|
-
|
|
76
|
-
interface MemoryUpdateInput {
|
|
77
|
-
id?: string; // 有则更新;无则创建新记录
|
|
78
|
-
sessionId?: string; // 无则服务端自动生成并返回
|
|
79
|
-
mode?: 'append' | 'upsert'; // 默认 append
|
|
80
|
-
entryType?: EntryType; // 记忆类型
|
|
81
|
-
title?: string; // 标题(Markdown H1)
|
|
82
|
-
content: string; // 内容(必填,Markdown 格式)
|
|
83
|
-
tags?: string[]; // 标签数组
|
|
84
|
-
category?: string; // 分类
|
|
85
|
-
importance?: number; // 重要性 1-5,默认 3
|
|
86
|
-
}
|
|
87
|
-
```
|
|
88
|
-
|
|
89
|
-
### 行为说明
|
|
90
|
-
|
|
91
|
-
1. **Markdown 写入** (同步):
|
|
92
|
-
- 生成或更新 Markdown 文件
|
|
93
|
-
- 路径格式: `YYYY-MM-DD/session_uuid/timestamp-title-slug.md`
|
|
94
|
-
- 写入 YAML Front Matter 和 Markdown 正文
|
|
95
|
-
|
|
96
|
-
2. **向量索引更新** (异步):
|
|
97
|
-
- 使用 Embedding 服务生成 384 维向量
|
|
98
|
-
- 在 LanceDB 中 upsert 向量记录
|
|
99
|
-
- 包含元数据字段用于过滤
|
|
100
|
-
|
|
101
|
-
3. **并发安全**:
|
|
102
|
-
- 按 `session_uuid` 分目录,避免多 CLI 冲突
|
|
103
|
-
- 文件名包含时间戳,保证唯一性
|
|
104
|
-
|
|
105
|
-
4. **容错处理**:
|
|
106
|
-
- 向量索引失败不影响 Markdown 写入
|
|
107
|
-
- 记录错误日志,不中断主流程
|
|
108
|
-
|
|
109
|
-
### 输出
|
|
110
|
-
|
|
111
|
-
```ts
|
|
112
|
-
interface MemoryUpdateOutput {
|
|
113
|
-
id: string;
|
|
114
|
-
sessionId: string;
|
|
115
|
-
filePath: string;
|
|
116
|
-
created: boolean;
|
|
117
|
-
updated: boolean;
|
|
118
|
-
memory: Memory;
|
|
119
|
-
}
|
|
120
|
-
```
|
|
121
|
-
|
|
122
|
-
---
|
|
123
|
-
|
|
124
|
-
## Memory 数据模型
|
|
125
|
-
|
|
126
|
-
```ts
|
|
127
|
-
type EntryType = 'preference' | 'decision' | 'context' | 'fact';
|
|
128
|
-
|
|
129
|
-
interface Memory {
|
|
130
|
-
id: string; // UUID v4
|
|
131
|
-
createdAt: string; // ISO 8601
|
|
132
|
-
updatedAt: string; // ISO 8601
|
|
133
|
-
sessionId?: string; // 会话 UUID
|
|
134
|
-
entryType?: EntryType; // 记忆类型
|
|
135
|
-
tags: string[]; // 标签数组
|
|
136
|
-
category: string; // 分类
|
|
137
|
-
importance: number; // 1-5
|
|
138
|
-
title: string; // Markdown H1 标题
|
|
139
|
-
content: string; // Markdown 正文
|
|
140
|
-
}
|
|
141
|
-
```
|
|
142
|
-
|
|
143
|
-
### EntryType 说明
|
|
144
|
-
|
|
145
|
-
- **preference**: 用户偏好和习惯
|
|
146
|
-
- **decision**: 技术决策及其理由
|
|
147
|
-
- **context**: 项目和环境信息
|
|
148
|
-
- **fact**: 客观知识和事实
|
|
149
|
-
|
|
150
|
-
---
|
|
151
|
-
|
|
152
|
-
## 存储路径契约(并发安全)
|
|
153
|
-
|
|
154
|
-
为避免多个 CLI 同日写入冲突,采用分层目录:
|
|
155
|
-
|
|
156
|
-
```text
|
|
157
|
-
{storageRoot}/YYYY-MM-DD/{session_uuid}/{timestamp}-{slug}.md
|
|
158
|
-
```
|
|
159
|
-
|
|
160
|
-
例如:
|
|
161
|
-
|
|
162
|
-
```text
|
|
163
|
-
memories/2026-03-03/550e8400-e29b-41d4-a716-446655440111/2026-03-03T16-40-12-123Z-task-summary.md
|
|
164
|
-
```
|
|
165
|
-
|
|
166
|
-
### 向量索引存储
|
|
167
|
-
|
|
168
|
-
向量数据存储在独立的 LanceDB 目录中:
|
|
169
|
-
|
|
170
|
-
```text
|
|
171
|
-
{storageRoot}/.lancedb/
|
|
172
|
-
├── versions/
|
|
173
|
-
├── manifest.json
|
|
174
|
-
└── ...
|
|
175
|
-
```
|
|
176
|
-
|
|
177
|
-
**重要特性**:
|
|
178
|
-
|
|
179
|
-
- Markdown 文件是唯一数据源
|
|
180
|
-
- 向量索引可随时从 Markdown 重建
|
|
181
|
-
- 删除 `.lancedb/` 目录不影响数据完整性
|
|
182
|
-
|
|
183
|
-
---
|
|
184
|
-
|
|
185
|
-
## 调用策略契约(强建议)
|
|
186
|
-
|
|
187
|
-
- 用户输入后第一轮:调用 `memory_load`
|
|
188
|
-
- 最终输出前最后一轮:调用 `memory_update`
|
|
189
|
-
|
|
190
|
-
详细策略见:`docs/tool-calling-policy.md`
|
package/docs/prompt-template.md
DELETED
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
# Prompt Template for Coding Agents (MemHub)
|
|
2
|
-
|
|
3
|
-
## Why Memory Matters
|
|
4
|
-
|
|
5
|
-
You have access to persistent memory across conversations. Use it wisely:
|
|
6
|
-
|
|
7
|
-
- **Remember preferences** — Learn what the user likes and avoid repeating mistakes
|
|
8
|
-
- **Recall decisions** — Build on past reasoning instead of starting from scratch
|
|
9
|
-
- **Store context** — Project knowledge that survives session boundaries
|
|
10
|
-
|
|
11
|
-
## When to Use
|
|
12
|
-
|
|
13
|
-
### `memory_load`
|
|
14
|
-
|
|
15
|
-
Call when you need context from past conversations:
|
|
16
|
-
- User references something from before
|
|
17
|
-
- You're unsure about user preferences
|
|
18
|
-
- A decision needs historical context
|
|
19
|
-
|
|
20
|
-
Don't call for simple, self-contained tasks.
|
|
21
|
-
|
|
22
|
-
### `memory_update`
|
|
23
|
-
|
|
24
|
-
Call when you discover something worth remembering:
|
|
25
|
-
- User expresses a preference
|
|
26
|
-
- You made a significant decision with reasoning
|
|
27
|
-
- Project context changed
|
|
28
|
-
|
|
29
|
-
Don't call for temporary or one-time information.
|
|
30
|
-
|
|
31
|
-
## Principle
|
|
32
|
-
|
|
33
|
-
Memory should feel natural — triggered by context, not by schedule. When in doubt, ask: "Would future me benefit from knowing this?"
|