@synth-coder/memhub 0.2.2 → 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.
Files changed (116) hide show
  1. package/.factory/commands/opsx-apply.md +150 -0
  2. package/.factory/commands/opsx-archive.md +155 -0
  3. package/.factory/commands/opsx-explore.md +171 -0
  4. package/.factory/commands/opsx-propose.md +104 -0
  5. package/.factory/skills/openspec-apply-change/SKILL.md +156 -0
  6. package/.factory/skills/openspec-archive-change/SKILL.md +114 -0
  7. package/.factory/skills/openspec-explore/SKILL.md +288 -0
  8. package/.factory/skills/openspec-propose/SKILL.md +110 -0
  9. package/.github/workflows/ci.yml +48 -12
  10. package/.github/workflows/release.yml +67 -0
  11. package/AGENTS.md +158 -17
  12. package/README.md +147 -66
  13. package/README.zh-CN.md +75 -23
  14. package/dist/src/cli/agents/claude-code.d.ts +5 -0
  15. package/dist/src/cli/agents/claude-code.d.ts.map +1 -0
  16. package/dist/src/cli/agents/claude-code.js +14 -0
  17. package/dist/src/cli/agents/claude-code.js.map +1 -0
  18. package/dist/src/cli/agents/cline.d.ts +5 -0
  19. package/dist/src/cli/agents/cline.d.ts.map +1 -0
  20. package/dist/src/cli/agents/cline.js +14 -0
  21. package/dist/src/cli/agents/cline.js.map +1 -0
  22. package/dist/src/cli/agents/codex.d.ts +5 -0
  23. package/dist/src/cli/agents/codex.d.ts.map +1 -0
  24. package/dist/src/cli/agents/codex.js +14 -0
  25. package/dist/src/cli/agents/codex.js.map +1 -0
  26. package/dist/src/cli/agents/cursor.d.ts +5 -0
  27. package/dist/src/cli/agents/cursor.d.ts.map +1 -0
  28. package/dist/src/cli/agents/cursor.js +14 -0
  29. package/dist/src/cli/agents/cursor.js.map +1 -0
  30. package/dist/src/cli/agents/factory-droid.d.ts +5 -0
  31. package/dist/src/cli/agents/factory-droid.d.ts.map +1 -0
  32. package/dist/src/cli/agents/factory-droid.js +14 -0
  33. package/dist/src/cli/agents/factory-droid.js.map +1 -0
  34. package/dist/src/cli/agents/gemini-cli.d.ts +5 -0
  35. package/dist/src/cli/agents/gemini-cli.d.ts.map +1 -0
  36. package/dist/src/cli/agents/gemini-cli.js +14 -0
  37. package/dist/src/cli/agents/gemini-cli.js.map +1 -0
  38. package/dist/src/cli/agents/index.d.ts +14 -0
  39. package/dist/src/cli/agents/index.d.ts.map +1 -0
  40. package/dist/src/cli/agents/index.js +30 -0
  41. package/dist/src/cli/agents/index.js.map +1 -0
  42. package/dist/src/cli/agents/windsurf.d.ts +5 -0
  43. package/dist/src/cli/agents/windsurf.d.ts.map +1 -0
  44. package/dist/src/cli/agents/windsurf.js +14 -0
  45. package/dist/src/cli/agents/windsurf.js.map +1 -0
  46. package/dist/src/cli/index.d.ts +8 -0
  47. package/dist/src/cli/index.d.ts.map +1 -0
  48. package/dist/src/cli/index.js +168 -0
  49. package/dist/src/cli/index.js.map +1 -0
  50. package/dist/src/cli/init.d.ts +34 -0
  51. package/dist/src/cli/init.d.ts.map +1 -0
  52. package/dist/src/cli/init.js +160 -0
  53. package/dist/src/cli/init.js.map +1 -0
  54. package/dist/src/cli/instructions.d.ts +29 -0
  55. package/dist/src/cli/instructions.d.ts.map +1 -0
  56. package/dist/src/cli/instructions.js +141 -0
  57. package/dist/src/cli/instructions.js.map +1 -0
  58. package/dist/src/cli/types.d.ts +22 -0
  59. package/dist/src/cli/types.d.ts.map +1 -0
  60. package/dist/src/cli/types.js +86 -0
  61. package/dist/src/cli/types.js.map +1 -0
  62. package/dist/src/contracts/schemas.js.map +1 -1
  63. package/dist/src/server/mcp-server.d.ts +8 -0
  64. package/dist/src/server/mcp-server.d.ts.map +1 -1
  65. package/dist/src/server/mcp-server.js +30 -16
  66. package/dist/src/server/mcp-server.js.map +1 -1
  67. package/dist/src/services/embedding-service.d.ts.map +1 -1
  68. package/dist/src/services/embedding-service.js +1 -1
  69. package/dist/src/services/embedding-service.js.map +1 -1
  70. package/dist/src/services/memory-service.d.ts +1 -0
  71. package/dist/src/services/memory-service.d.ts.map +1 -1
  72. package/dist/src/services/memory-service.js +125 -82
  73. package/dist/src/services/memory-service.js.map +1 -1
  74. package/dist/src/storage/markdown-storage.d.ts.map +1 -1
  75. package/dist/src/storage/markdown-storage.js +1 -1
  76. package/dist/src/storage/markdown-storage.js.map +1 -1
  77. package/dist/src/storage/vector-index.d.ts.map +1 -1
  78. package/dist/src/storage/vector-index.js +4 -5
  79. package/dist/src/storage/vector-index.js.map +1 -1
  80. package/docs/README.md +21 -0
  81. package/docs/mcp-tools.md +136 -0
  82. package/docs/user-guide.md +182 -0
  83. package/package.json +22 -19
  84. package/src/cli/agents/claude-code.ts +14 -0
  85. package/src/cli/agents/cline.ts +14 -0
  86. package/src/cli/agents/codex.ts +14 -0
  87. package/src/cli/agents/cursor.ts +14 -0
  88. package/src/cli/agents/factory-droid.ts +14 -0
  89. package/src/cli/agents/gemini-cli.ts +14 -0
  90. package/src/cli/agents/index.ts +36 -0
  91. package/src/cli/agents/windsurf.ts +14 -0
  92. package/src/cli/index.ts +192 -0
  93. package/src/cli/init.ts +218 -0
  94. package/src/cli/instructions.ts +156 -0
  95. package/src/cli/types.ts +112 -0
  96. package/src/contracts/mcp.ts +1 -1
  97. package/src/contracts/schemas.ts +4 -4
  98. package/src/contracts/types.ts +4 -4
  99. package/src/server/mcp-server.ts +36 -29
  100. package/src/services/embedding-service.ts +80 -80
  101. package/src/services/memory-service.ts +142 -107
  102. package/src/storage/markdown-storage.ts +1 -9
  103. package/src/storage/vector-index.ts +117 -118
  104. package/test/cli/init.test.ts +380 -0
  105. package/test/server/mcp-server.test.ts +45 -3
  106. package/test/services/memory-service.test.ts +16 -4
  107. package/test/storage/frontmatter-parser.test.ts +1 -1
  108. package/test/storage/markdown-storage.test.ts +19 -10
  109. package/test/storage/vector-index.test.ts +129 -133
  110. package/test/utils/slugify.test.ts +5 -1
  111. package/docs/architecture.md +0 -349
  112. package/docs/contracts.md +0 -119
  113. package/docs/prompt-template.md +0 -79
  114. package/docs/proposals/mcp-typescript-sdk-refactor.md +0 -568
  115. package/docs/proposals/proposal-close-gates.md +0 -58
  116. package/docs/tool-calling-policy.md +0 -107
@@ -1,349 +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. **简单优先**: 不使用数据库,避免复杂的迁移和锁定问题
12
- 4. **契约先行**: 接口和类型定义先于实现
13
- 5. **测试驱动**: 严格遵循 TDD (红-绿-重构)
14
-
15
- ## 系统架构
16
-
17
- ```
18
- ┌─────────────────────────────────────────────────────────────┐
19
- │ MCP Client │
20
- │ (Claude Desktop, etc.) │
21
- └──────────────────────┬──────────────────────────────────────┘
22
- │ stdio
23
-
24
- ┌─────────────────────────────────────────────────────────────┐
25
- │ MemHub MCP Server │
26
- │ ┌──────────────┐ ┌──────────────┐ ┌──────────────────┐ │
27
- │ │ MCP Router │ │ Services │ │ Storage Layer │ │
28
- │ │ │ │ │ │ │ │
29
- │ │ - list_tools │ │ - create │ │ - read memory │ │
30
- │ │ - call_tool │ │ - read │ │ - write memory │ │
31
- │ │ │ │ - update │ │ - search index │ │
32
- │ │ │ │ - delete │ │ - list memories │ │
33
- │ │ │ │ - search │ │ │ │
34
- │ └──────────────┘ └──────────────┘ └──────────────────┘ │
35
- └──────────────────────┬──────────────────────────────────────┘
36
-
37
-
38
- ┌─────────────────────────────────────────────────────────────┐
39
- │ Markdown Storage │
40
- │ ┌─────────────────────────────────────────────────────┐ │
41
- │ │ YYYY-MM-DD-title-slug.md │ │
42
- │ │ ───────────────────────── │ │
43
- │ │ --- │ │
44
- │ │ id: uuid-v4 │ │
45
- │ │ created_at: ISO8601 │ │
46
- │ │ updated_at: ISO8601 │ │
47
- │ │ tags: [tag1, tag2] │ │
48
- │ │ category: string │ │
49
- │ │ importance: 1-5 │ │
50
- │ │ --- │ │
51
- │ │ │ │
52
- │ │ # Title │ │
53
- │ │ │ │
54
- │ │ Markdown content body... │ │
55
- │ │ │ │
56
- │ └─────────────────────────────────────────────────────┘ │
57
- └─────────────────────────────────────────────────────────────┘
58
- ```
59
-
60
- ## 核心组件
61
-
62
- ### 1. MCP Server (src/server/mcp-server.ts)
63
-
64
- - 入口点,处理 stdio 通信
65
- - 实现 MCP 协议的生命周期管理
66
- - 路由工具调用到对应的服务
67
-
68
- ### 2. Services (src/services/)
69
-
70
- 业务逻辑层,包含:
71
-
72
- - **MemoryService**: 记忆 CRUD 操作
73
- - **SearchService**: 搜索和过滤
74
- - **IndexService**: 索引管理(可选,用于性能)
75
-
76
- ### 3. Storage Layer (src/storage/)
77
-
78
- 数据持久化层:
79
-
80
- - **MarkdownStorage**: Markdown 文件读写
81
- - **FrontMatterParser**: YAML Front Matter 解析
82
- - **FileSystem**: 文件系统抽象(便于测试)
83
-
84
- ### 4. Contracts (src/contracts/)
85
-
86
- 类型定义和 Zod 契约:
87
-
88
- - **types.ts**: TypeScript 类型
89
- - **schemas.ts**: Zod 验证模式
90
- - **mcp.ts**: MCP 协议相关类型
91
-
92
- ## 数据模型
93
-
94
- ### Memory Entry (记忆条目)
95
-
96
- ```typescript
97
- interface Memory {
98
- // Identity
99
- id: string; // UUID v4
100
-
101
- // Metadata (YAML Front Matter)
102
- createdAt: string; // ISO 8601
103
- updatedAt: string; // ISO 8601
104
- tags: string[]; // 标签数组
105
- category: string; // 分类
106
- importance: number; // 1-5 重要性等级
107
-
108
- // Content (Markdown Body)
109
- title: string; // Markdown H1 标题
110
- content: string; // Markdown 正文
111
- }
112
- ```
113
-
114
- ### File Naming Convention
115
-
116
- ```
117
- {YYYY-MM-DD}-{title-slug}.md
118
-
119
- Examples:
120
- - 2024-03-15-project-kickoff.md
121
- - 2024-03-20-meeting-notes.md
122
- ```
123
-
124
- ### Markdown Format
125
-
126
- ```markdown
127
- ---
128
- id: '550e8400-e29b-41d4-a716-446655440000'
129
- created_at: '2024-03-15T10:30:00Z'
130
- updated_at: '2024-03-15T14:20:00Z'
131
- tags:
132
- - project
133
- - planning
134
- category: 'work'
135
- importance: 4
136
- ---
137
-
138
- # Project Kickoff
139
-
140
- Today we started the new project...
141
-
142
- ## Key Decisions
143
-
144
- - Decision 1
145
- - Decision 2
146
- ```
147
-
148
- ## MCP Tools
149
-
150
- ### 1. `memory_create`
151
-
152
- 创建新记忆条目。
153
-
154
- **Input:**
155
-
156
- - title: string (required)
157
- - content: string (required)
158
- - tags?: string[]
159
- - category?: string
160
- - importance?: number (1-5, default: 3)
161
-
162
- **Output:**
163
-
164
- - id: string
165
- - filePath: string
166
-
167
- ### 2. `memory_read`
168
-
169
- 读取记忆条目。
170
-
171
- **Input:**
172
-
173
- - id: string (required)
174
-
175
- **Output:**
176
-
177
- - Memory object
178
-
179
- ### 3. `memory_update`
180
-
181
- 更新记忆条目。
182
-
183
- **Input:**
184
-
185
- - id: string (required)
186
- - title?: string
187
- - content?: string
188
- - tags?: string[]
189
- - category?: string
190
- - importance?: number
191
-
192
- **Output:**
193
-
194
- - updated Memory object
195
-
196
- ### 4. `memory_delete`
197
-
198
- 删除记忆条目。
199
-
200
- **Input:**
201
-
202
- - id: string (required)
203
-
204
- **Output:**
205
-
206
- - success: boolean
207
-
208
- ### 5. `memory_list`
209
-
210
- 列出记忆条目(支持过滤和分页)。
211
-
212
- **Input:**
213
-
214
- - category?: string
215
- - tags?: string[]
216
- - fromDate?: string (ISO 8601)
217
- - toDate?: string (ISO 8601)
218
- - limit?: number (default: 20, max: 100)
219
- - offset?: number (default: 0)
220
-
221
- **Output:**
222
-
223
- - memories: Memory[]
224
- - total: number
225
- - hasMore: boolean
226
-
227
- ### 6. `memory_search`
228
-
229
- 全文搜索记忆。
230
-
231
- **Input:**
232
-
233
- - query: string (required)
234
- - limit?: number (default: 10)
235
-
236
- **Output:**
237
-
238
- - results: SearchResult[]
239
- - memory: Memory
240
- - score: number
241
- - matches: string[]
242
-
243
- ### 7. `memory_get_categories`
244
-
245
- 获取所有分类。
246
-
247
- **Output:**
248
-
249
- - categories: string[]
250
-
251
- ### 8. `memory_get_tags`
252
-
253
- 获取所有标签。
254
-
255
- **Output:**
256
-
257
- - tags: string[]
258
-
259
- ## 错误处理
260
-
261
- 所有错误使用标准 MCP 错误格式:
262
-
263
- ```typescript
264
- interface McpError {
265
- code: number; // MCP error code
266
- message: string; // Human readable message
267
- data?: unknown; // Additional context
268
- }
269
- ```
270
-
271
- 错误码定义:
272
-
273
- - `INVALID_PARAMS`: 参数验证失败
274
- - `NOT_FOUND`: 记忆条目不存在
275
- - `STORAGE_ERROR`: 存储操作失败
276
- - `INTERNAL_ERROR`: 内部错误
277
-
278
- ## 配置
279
-
280
- 通过环境变量配置:
281
-
282
- ```bash
283
- MEMHUB_STORAGE_PATH=/path/to/memories # 存储目录,默认: ./memories
284
- MEMHUB_LOG_LEVEL=info # 日志级别: debug, info, warn, error
285
- ```
286
-
287
- ## 技术栈
288
-
289
- - **Runtime**: Node.js 18+
290
- - **Language**: TypeScript 5.3+
291
- - **Protocol**: MCP (Model Context Protocol)
292
- - **Transport**: stdio
293
- - **Validation**: Zod
294
- - **Testing**: Vitest (覆盖率 >= 80%)
295
- - **Linting**: ESLint + Prettier
296
-
297
- ## 目录结构
298
-
299
- ```
300
- memhub/
301
- ├── docs/
302
- │ ├── architecture.md # 本文档
303
- │ └── contracts.md # 契约文档
304
- ├── src/
305
- │ ├── contracts/ # 类型和契约
306
- │ │ ├── types.ts
307
- │ │ ├── schemas.ts
308
- │ │ └── mcp.ts
309
- │ ├── server/ # MCP Server
310
- │ │ └── mcp-server.ts
311
- │ ├── services/ # 业务逻辑
312
- │ │ ├── memory-service.ts
313
- │ │ └── search-service.ts
314
- │ ├── storage/ # 存储层
315
- │ │ ├── markdown-storage.ts
316
- │ │ └── frontmatter-parser.ts
317
- │ └── utils/ # 工具函数
318
- │ └── file-system.ts
319
- ├── test/ # 测试
320
- │ ├── unit/
321
- │ ├── integration/
322
- │ └── fixtures/
323
- ├── .github/
324
- │ └── workflows/
325
- │ └── ci.yml # CI 配置
326
- ├── package.json
327
- ├── tsconfig.json
328
- ├── vitest.config.ts
329
- ├── .eslintrc.cjs
330
- ├── .prettierrc
331
- └── README.md
332
- ```
333
-
334
- ## 开发流程
335
-
336
- 1. **设计**: 先写架构文档和契约
337
- 2. **契约**: 定义 TypeScript 类型和 Zod Schema
338
- 3. **测试**: 编写红色测试(先失败)
339
- 4. **实现**: 编写最小实现使测试通过(绿色)
340
- 5. **重构**: 优化代码结构
341
- 6. **重复**: 循环 3-5 步
342
-
343
- ## 质量门禁
344
-
345
- - ✅ ESLint 无错误
346
- - ✅ Prettier 格式化检查通过
347
- - ✅ TypeScript 严格类型检查通过
348
- - ✅ 单元测试全部通过
349
- - ✅ 代码覆盖率 >= 80%
package/docs/contracts.md DELETED
@@ -1,119 +0,0 @@
1
- # MemHub 契约文档(vNext)
2
-
3
- 当前对外 MCP 工具仅保留两项:
4
-
5
- 1. `memory_load`(首轮)
6
- 2. `memory_update`(末轮)
7
-
8
- 目标是形成稳定闭环:**先读 STM,再回写 STM**。
9
-
10
- ---
11
-
12
- ## 1) memory_load
13
-
14
- 用于用户输入后第一轮主动加载短期记忆。
15
-
16
- ### 输入
17
-
18
- ```ts
19
- interface MemoryLoadInput {
20
- id?: string; // 指定单条记忆
21
- sessionId?: string; // 会话 UUID
22
- date?: string; // YYYY-MM-DD
23
- query?: string; // 文本检索
24
- category?: string;
25
- tags?: string[];
26
- limit?: number; // 默认 20
27
- scope?: 'stm' | 'all'; // 默认 stm
28
- }
29
- ```
30
-
31
- ### 输出
32
-
33
- ```ts
34
- interface MemoryLoadOutput {
35
- items: Memory[];
36
- total: number;
37
- }
38
- ```
39
-
40
- ---
41
-
42
- ## 2) memory_update
43
-
44
- 用于本轮结束前主动回写记忆。
45
-
46
- ### 输入
47
-
48
- ```ts
49
- type EntryType = 'decision' | 'preference' | 'knowledge' | 'todo' | 'state_change';
50
-
51
- interface MemoryUpdateInput {
52
- id?: string; // 有 id 则更新;无 id 则追加
53
- sessionId?: string; // 无则服务端自动生成并返回
54
- mode?: 'append' | 'upsert'; // 默认 append
55
- entryType?: EntryType;
56
- title?: string;
57
- content: string; // 必填
58
- tags?: string[];
59
- category?: string;
60
- importance?: number; // 1-5
61
- }
62
- ```
63
-
64
- ### 输出
65
-
66
- ```ts
67
- interface MemoryUpdateOutput {
68
- id: string;
69
- sessionId: string;
70
- filePath: string;
71
- created: boolean;
72
- updated: boolean;
73
- memory: Memory;
74
- }
75
- ```
76
-
77
- ---
78
-
79
- ## Memory 数据模型
80
-
81
- ```ts
82
- interface Memory {
83
- id: string;
84
- createdAt: string;
85
- updatedAt: string;
86
- sessionId?: string;
87
- entryType?: EntryType;
88
- tags: string[];
89
- category: string;
90
- importance: number;
91
- title: string;
92
- content: string;
93
- }
94
- ```
95
-
96
- ---
97
-
98
- ## 存储路径契约(并发安全)
99
-
100
- 为避免多个 CLI 同日写入冲突,采用分层目录:
101
-
102
- ```text
103
- {storageRoot}/YYYY-MM-DD/{session_uuid}/{timestamp}-{slug}.md
104
- ```
105
-
106
- 例如:
107
-
108
- ```text
109
- memories/2026-03-03/550e8400-e29b-41d4-a716-446655440111/2026-03-03T16-40-12-123Z-task-summary.md
110
- ```
111
-
112
- ---
113
-
114
- ## 调用策略契约(强建议)
115
-
116
- - 用户输入后第一轮:调用 `memory_load`
117
- - 最终输出前最后一轮:调用 `memory_update`
118
-
119
- 详细策略见:`docs/tool-calling-policy.md`
@@ -1,79 +0,0 @@
1
- # Prompt Template for Coding Agents (MemHub STM Loop)
2
-
3
- Use this template in Codex / Claude Code / OpenCode system prompt or task preamble.
4
-
5
- ---
6
-
7
- ## System Rule: STM Closed Loop
8
-
9
- You are connected to MemHub MCP.
10
-
11
- ### Mandatory tool-calling behavior
12
-
13
- 1. **First round after receiving user prompt**: call `memory_load`.
14
- 2. **Final round before sending final answer**: call `memory_update`.
15
-
16
- Do not skip these two calls unless tool is unavailable.
17
-
18
- ---
19
-
20
- ## Tool usage policy
21
-
22
- ### On first round (`memory_load`)
23
-
24
- Call with the most specific context available:
25
-
26
- ```json
27
- {
28
- "sessionId": "<session-uuid-if-known>",
29
- "scope": "stm",
30
- "limit": 20
31
- }
32
- ```
33
-
34
- If task is date-scoped, add `date: "YYYY-MM-DD"`.
35
- If task is keyword-driven, add `query`.
36
-
37
- ### On final round (`memory_update`)
38
-
39
- Write only high-value context likely reused in next 3 turns:
40
-
41
- - decisions
42
- - preference changes
43
- - constraints
44
- - task state changes
45
- - reusable conclusions
46
-
47
- Example:
48
-
49
- ```json
50
- {
51
- "sessionId": "<session-uuid-if-known>",
52
- "mode": "append",
53
- "entryType": "decision",
54
- "title": "Storage architecture decision",
55
- "content": "Use date/session_uuid nested markdown storage to avoid multi-CLI collision.",
56
- "tags": ["architecture", "storage", "stm"],
57
- "category": "engineering",
58
- "importance": 4
59
- }
60
- ```
61
-
62
- ---
63
-
64
- ## Minimal execution checklist
65
-
66
- - [ ] First tool call is `memory_load`
67
- - [ ] Final tool call is `memory_update`
68
- - [ ] `memory_update` content is concise and reusable
69
- - [ ] No sensitive secrets in memory payload
70
-
71
- ---
72
-
73
- ## Failure fallback
74
-
75
- If tool call fails:
76
-
77
- 1. continue task execution
78
- 2. mention memory tool failure briefly in internal reasoning/logs
79
- 3. still provide final user answer