@morningljn/mnemo 0.1.2
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/LICENSE +21 -0
- package/README.md +156 -0
- package/README_zh.md +156 -0
- package/banner.png +0 -0
- package/dist/init.d.ts +10 -0
- package/dist/init.js +138 -0
- package/dist/init.js.map +1 -0
- package/dist/retriever.d.ts +70 -0
- package/dist/retriever.js +689 -0
- package/dist/retriever.js.map +1 -0
- package/dist/schema.d.ts +1 -0
- package/dist/schema.js +62 -0
- package/dist/schema.js.map +1 -0
- package/dist/security.d.ts +15 -0
- package/dist/security.js +116 -0
- package/dist/security.js.map +1 -0
- package/dist/server.d.ts +2 -0
- package/dist/server.js +150 -0
- package/dist/server.js.map +1 -0
- package/dist/store.d.ts +122 -0
- package/dist/store.js +696 -0
- package/dist/store.js.map +1 -0
- package/dist/types.d.ts +72 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/package.json +46 -0
- package/src/init.ts +157 -0
- package/src/retriever.ts +806 -0
- package/src/schema.ts +61 -0
- package/src/security.ts +132 -0
- package/src/server.ts +172 -0
- package/src/store.ts +805 -0
- package/src/types.ts +81 -0
- package/tests/retriever.test.ts +55 -0
- package/tests/security.test.ts +30 -0
- package/tests/store.test.ts +104 -0
- package/tsconfig.json +16 -0
- package/vitest.config.ts +10 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 ArtLjn
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
<p align="center">
|
|
2
|
+
<img src="./banner.png" alt="mnemo" width="600">
|
|
3
|
+
</p>
|
|
4
|
+
|
|
5
|
+
<p align="center">
|
|
6
|
+
<a href="./README_zh.md">简体中文</a> | <strong>English</strong>
|
|
7
|
+
</p>
|
|
8
|
+
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
## Why mnemo?
|
|
12
|
+
|
|
13
|
+
AI coding assistants forget everything between sessions. `CLAUDE.md` stores static rules, but it can't search or reason over accumulated knowledge.
|
|
14
|
+
|
|
15
|
+
mnemo gives your AI assistant a **searchable, structured memory layer** that persists across sessions:
|
|
16
|
+
|
|
17
|
+
- **Search by meaning** — FTS5 full-text search + Jaccard reranking + bilingual expansion
|
|
18
|
+
- **Trust scoring** — facts gain or lose trust over time based on feedback and decay
|
|
19
|
+
- **Entity graph** — automatic entity extraction with multi-hop relationship queries
|
|
20
|
+
- **Contradiction detection** — finds conflicting facts and demotes the older one
|
|
21
|
+
- **Auto-dedup** — three-layer deduplication prevents duplicate facts
|
|
22
|
+
|
|
23
|
+
## Quick Start
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
# Install
|
|
27
|
+
npm install -g @artljn/mnemo
|
|
28
|
+
|
|
29
|
+
# One-command setup (register MCP + write rules + set permissions)
|
|
30
|
+
mnemo-init
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
That's it. Restart your AI assistant and it will have persistent memory.
|
|
34
|
+
|
|
35
|
+
### Manual Setup
|
|
36
|
+
|
|
37
|
+
If you prefer manual configuration:
|
|
38
|
+
|
|
39
|
+
**1. Register MCP server:**
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
claude mcp add mnemo -- mnemo
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
**2. Add memory rules to `~/.claude/CLAUDE.md`:**
|
|
46
|
+
|
|
47
|
+
```markdown
|
|
48
|
+
# Memory System
|
|
49
|
+
|
|
50
|
+
You have mnemo memory tools (fact_store / fact_feedback). Rules:
|
|
51
|
+
|
|
52
|
+
## Rule 1: Search before answering
|
|
53
|
+
After receiving a user message, call `fact_store(action="search", query="<keywords from user message>")`.
|
|
54
|
+
Extract keywords from the user's actual message — do NOT use a fixed template.
|
|
55
|
+
|
|
56
|
+
## Rule 2: Write on request
|
|
57
|
+
When user says "remember", call `fact_store(action="add", content="...", category="...")`.
|
|
58
|
+
Search first to avoid duplicates. Categories: identity / coding_style / tool_pref / workflow / general.
|
|
59
|
+
|
|
60
|
+
## Rule 3: Feedback
|
|
61
|
+
When a memory was useful, call `fact_feedback(action="helpful", fact_id=...)`.
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
**3. Allow tools in `~/.claude/settings.json`:**
|
|
65
|
+
|
|
66
|
+
```json
|
|
67
|
+
{
|
|
68
|
+
"permissions": {
|
|
69
|
+
"allow": [
|
|
70
|
+
"mcp__mnemo__fact_store",
|
|
71
|
+
"mcp__mnemo__fact_feedback"
|
|
72
|
+
]
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
### Codex
|
|
78
|
+
|
|
79
|
+
Add to your Codex MCP configuration:
|
|
80
|
+
|
|
81
|
+
```json
|
|
82
|
+
{
|
|
83
|
+
"mcpServers": {
|
|
84
|
+
"mnemo": {
|
|
85
|
+
"command": "mnemo"
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
## Tools
|
|
92
|
+
|
|
93
|
+
### `fact_store`
|
|
94
|
+
|
|
95
|
+
The primary tool for reading and writing structured facts. Supports 9 actions:
|
|
96
|
+
|
|
97
|
+
| Action | Description | Key Parameters |
|
|
98
|
+
|--------|-------------|----------------|
|
|
99
|
+
| `add` | Add a new fact (auto-deduplicates; merges if similar exists) | `content`, `category`, `tags` |
|
|
100
|
+
| `search` | Keyword search with FTS5 + Jaccard reranking | `query`, `category`, `min_trust`, `limit` |
|
|
101
|
+
| `probe` | Find all facts about a specific entity | `entity`, `min_trust`, `limit` |
|
|
102
|
+
| `related` | Find facts related to an entity through shared context | `entity`, `min_trust`, `limit` |
|
|
103
|
+
| `reason` | Multi-entity reasoning: find facts connected to all given entities | `entities`, `min_trust`, `limit` |
|
|
104
|
+
| `contradict` | Detect pairs of facts that share entities but conflict in content | `limit` |
|
|
105
|
+
| `update` | Update an existing fact's content, tags, category, or trust score | `fact_id`, `content`, `tags`, `category`, `trust_delta` |
|
|
106
|
+
| `remove` | Delete a fact by ID | `fact_id` |
|
|
107
|
+
| `list` | Browse facts sorted by trust score | `category`, `min_trust`, `limit` |
|
|
108
|
+
|
|
109
|
+
### `fact_feedback`
|
|
110
|
+
|
|
111
|
+
Rate a fact after use. Good facts rise, bad facts decay.
|
|
112
|
+
|
|
113
|
+
| Action | Effect |
|
|
114
|
+
|--------|--------|
|
|
115
|
+
| `helpful` | +0.05 trust |
|
|
116
|
+
| `unhelpful` | -0.10 trust |
|
|
117
|
+
|
|
118
|
+
## Architecture
|
|
119
|
+
|
|
120
|
+
```
|
|
121
|
+
┌───────────────────┐ stdio ┌────────────┐ SQLite ┌─────────────────────┐
|
|
122
|
+
│ MCP Client │◄─────────►│ mnemo │◄───────────►│ ~/.mnemo/facts.db │
|
|
123
|
+
│ (Claude / Codex) │ JSON │ server │ │ │
|
|
124
|
+
└───────────────────┘ └─────┬──────┘ │ Tables: │
|
|
125
|
+
│ │ facts │
|
|
126
|
+
┌──────┴──────┐ │ entities │
|
|
127
|
+
│ │ │ fact_entities │
|
|
128
|
+
│ Retriever │ Security │ Indexes: │
|
|
129
|
+
│ (search, │ (PII scan, │ facts_fts (FTS5) │
|
|
130
|
+
│ probe, │ injection │ idx_facts_trust │
|
|
131
|
+
│ reason) │ detection)│ idx_facts_category│
|
|
132
|
+
└─────────────┘ └─────────────────────┘
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
## Categories
|
|
136
|
+
|
|
137
|
+
| Category | Description | Decay Rate |
|
|
138
|
+
|----------|-------------|------------|
|
|
139
|
+
| `identity` | User identity: name, role, preferences | 0.02/week |
|
|
140
|
+
| `coding_style` | Coding conventions, naming, formatting | 0.03/week |
|
|
141
|
+
| `tool_pref` | Tool and framework preferences | 0.03/week |
|
|
142
|
+
| `workflow` | Development workflow, CI/CD, git practices | 0.02/week |
|
|
143
|
+
| `general` | General knowledge and other facts | 0.03/week |
|
|
144
|
+
|
|
145
|
+
## Development
|
|
146
|
+
|
|
147
|
+
```bash
|
|
148
|
+
npm install
|
|
149
|
+
npm test # run tests with vitest
|
|
150
|
+
npm run build # compile TypeScript
|
|
151
|
+
npm start # start MCP server
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
## License
|
|
155
|
+
|
|
156
|
+
[MIT](./LICENSE)
|
package/README_zh.md
ADDED
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
<p align="center">
|
|
2
|
+
<img src="./banner.png" alt="mnemo" width="600">
|
|
3
|
+
</p>
|
|
4
|
+
|
|
5
|
+
<p align="center">
|
|
6
|
+
<strong>简体中文</strong> | <a href="./README.md">English</a>
|
|
7
|
+
</p>
|
|
8
|
+
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
## 为什么需要 mnemo?
|
|
12
|
+
|
|
13
|
+
AI 编程助手在会话结束后会忘记所有内容。`CLAUDE.md` 只能存储静态规则,无法搜索或推理积累的知识。
|
|
14
|
+
|
|
15
|
+
mnemo 为你的 AI 助手提供**可搜索、结构化的记忆层**,跨会话持久化:
|
|
16
|
+
|
|
17
|
+
- **语义搜索** — FTS5 全文检索 + Jaccard 重排序 + 中英双语扩展
|
|
18
|
+
- **信任评分** — 事实随时间根据反馈和衰减获得或失去信任
|
|
19
|
+
- **实体图谱** — 自动实体抽取,支持多跳关联查询
|
|
20
|
+
- **矛盾检测** — 发现冲突事实并降级较旧的那条
|
|
21
|
+
- **自动去重** — 三层去重机制(实体重叠、Jaccard 相似度、包含检测)
|
|
22
|
+
|
|
23
|
+
## 快速开始
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
# 安装
|
|
27
|
+
npm install -g @artljn/mnemo
|
|
28
|
+
|
|
29
|
+
# 一键配置(注册 MCP + 写入规则 + 设置权限)
|
|
30
|
+
mnemo-init
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
重启你的 AI 助手即可拥有持久记忆。
|
|
34
|
+
|
|
35
|
+
### 手动配置
|
|
36
|
+
|
|
37
|
+
如果你更喜欢手动配置:
|
|
38
|
+
|
|
39
|
+
**1. 注册 MCP 服务器:**
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
claude mcp add mnemo -- mnemo
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
**2. 在 `~/.claude/CLAUDE.md` 中添加记忆规则:**
|
|
46
|
+
|
|
47
|
+
```markdown
|
|
48
|
+
# 记忆系统
|
|
49
|
+
|
|
50
|
+
你有 mnemo 记忆工具(fact_store / fact_feedback)。规则:
|
|
51
|
+
|
|
52
|
+
## 规则 1:回复前搜索
|
|
53
|
+
收到用户消息后,调用 `fact_store(action="search", query="<用户消息的关键词>")`。
|
|
54
|
+
必须从用户消息中动态提取关键词,不要用固定模板。
|
|
55
|
+
|
|
56
|
+
## 规则 2:按需写入
|
|
57
|
+
用户说"记住"时,调用 `fact_store(action="add", content="...", category="...")`。
|
|
58
|
+
先搜索避免重复。类别:identity / coding_style / tool_pref / workflow / general。
|
|
59
|
+
|
|
60
|
+
## 规则 3:反馈强化
|
|
61
|
+
记忆有用时,调用 `fact_feedback(action="helpful", fact_id=...)`。
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
**3. 在 `~/.claude/settings.json` 中允许工具:**
|
|
65
|
+
|
|
66
|
+
```json
|
|
67
|
+
{
|
|
68
|
+
"permissions": {
|
|
69
|
+
"allow": [
|
|
70
|
+
"mcp__mnemo__fact_store",
|
|
71
|
+
"mcp__mnemo__fact_feedback"
|
|
72
|
+
]
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
### Codex
|
|
78
|
+
|
|
79
|
+
添加到你的 Codex MCP 配置:
|
|
80
|
+
|
|
81
|
+
```json
|
|
82
|
+
{
|
|
83
|
+
"mcpServers": {
|
|
84
|
+
"mnemo": {
|
|
85
|
+
"command": "mnemo"
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
## 工具
|
|
92
|
+
|
|
93
|
+
### `fact_store`
|
|
94
|
+
|
|
95
|
+
读写结构化事实的主工具,支持 9 种操作:
|
|
96
|
+
|
|
97
|
+
| 操作 | 说明 | 关键参数 |
|
|
98
|
+
|------|------|----------|
|
|
99
|
+
| `add` | 添加事实(自动去重,相似则合并) | `content`、`category`、`tags` |
|
|
100
|
+
| `search` | 关键词搜索(FTS5 + Jaccard 重排序) | `query`、`category`、`min_trust`、`limit` |
|
|
101
|
+
| `probe` | 查找某实体的所有事实 | `entity`、`min_trust`、`limit` |
|
|
102
|
+
| `related` | 通过共享上下文查找关联事实 | `entity`、`min_trust`、`limit` |
|
|
103
|
+
| `reason` | 多实体推理:查找与所有给定实体相关的事实 | `entities`、`min_trust`、`limit` |
|
|
104
|
+
| `contradict` | 检测共享实体但内容冲突的事实对 | `limit` |
|
|
105
|
+
| `update` | 更新事实的内容、标签、类别或信任分 | `fact_id`、`content`、`tags`、`category`、`trust_delta` |
|
|
106
|
+
| `remove` | 按 ID 删除事实 | `fact_id` |
|
|
107
|
+
| `list` | 按信任分浏览事实 | `category`、`min_trust`、`limit` |
|
|
108
|
+
|
|
109
|
+
### `fact_feedback`
|
|
110
|
+
|
|
111
|
+
使用事实后评分。好事实上升,坏事实下降。
|
|
112
|
+
|
|
113
|
+
| 操作 | 效果 |
|
|
114
|
+
|------|------|
|
|
115
|
+
| `helpful` | +0.05 信任 |
|
|
116
|
+
| `unhelpful` | -0.10 信任 |
|
|
117
|
+
|
|
118
|
+
## 架构
|
|
119
|
+
|
|
120
|
+
```
|
|
121
|
+
┌───────────────────┐ stdio ┌────────────┐ SQLite ┌─────────────────────┐
|
|
122
|
+
│ MCP Client │◄─────────►│ mnemo │◄───────────►│ ~/.mnemo/facts.db │
|
|
123
|
+
│ (Claude / Codex) │ JSON │ server │ │ │
|
|
124
|
+
└───────────────────┘ └─────┬──────┘ │ 数据表: │
|
|
125
|
+
│ │ facts │
|
|
126
|
+
┌──────┴──────┐ │ entities │
|
|
127
|
+
│ │ │ fact_entities │
|
|
128
|
+
│ Retriever │ Security │ 索引: │
|
|
129
|
+
│ (搜索、 │ (PII 扫描、 │ facts_fts (FTS5) │
|
|
130
|
+
│ 探测、 │ 注入检测) │ idx_facts_trust │
|
|
131
|
+
│ 推理) │ │ idx_facts_category│
|
|
132
|
+
└─────────────┘ └─────────────────────┘
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
## 类别
|
|
136
|
+
|
|
137
|
+
| 类别 | 说明 | 衰减率 |
|
|
138
|
+
|------|------|--------|
|
|
139
|
+
| `identity` | 用户身份:姓名、角色、偏好 | 0.02/周 |
|
|
140
|
+
| `coding_style` | 编码规范、命名、格式化 | 0.03/周 |
|
|
141
|
+
| `tool_pref` | 工具和框架偏好 | 0.03/周 |
|
|
142
|
+
| `workflow` | 开发工作流、CI/CD、Git 实践 | 0.02/周 |
|
|
143
|
+
| `general` | 通用知识和其他事实 | 0.03/周 |
|
|
144
|
+
|
|
145
|
+
## 开发
|
|
146
|
+
|
|
147
|
+
```bash
|
|
148
|
+
npm install
|
|
149
|
+
npm test # 运行测试(vitest)
|
|
150
|
+
npm run build # 编译 TypeScript
|
|
151
|
+
npm start # 启动 MCP 服务器
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
## 许可证
|
|
155
|
+
|
|
156
|
+
[MIT](./LICENSE)
|
package/banner.png
ADDED
|
Binary file
|
package/dist/init.d.ts
ADDED
package/dist/init.js
ADDED
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* mnemo init — 一键配置 mnemo 记忆系统
|
|
4
|
+
*
|
|
5
|
+
* 执行:
|
|
6
|
+
* 1. claude mcp add mnemo — 注册 MCP 服务器
|
|
7
|
+
* 2. ~/.claude/CLAUDE.md — 写入记忆使用规则
|
|
8
|
+
* 3. ~/.claude/settings.json — 添加 MCP 工具权限
|
|
9
|
+
*/
|
|
10
|
+
import { execSync } from 'node:child_process';
|
|
11
|
+
import { existsSync, readFileSync, writeFileSync, mkdirSync } from 'node:fs';
|
|
12
|
+
import { join } from 'node:path';
|
|
13
|
+
import { homedir } from 'node:os';
|
|
14
|
+
const CLAUDE_DIR = join(homedir(), '.claude');
|
|
15
|
+
const CLAUDE_MD_PATH = join(CLAUDE_DIR, 'CLAUDE.md');
|
|
16
|
+
const SETTINGS_PATH = join(CLAUDE_DIR, 'settings.json');
|
|
17
|
+
const MEMORY_RULES = `
|
|
18
|
+
# 记忆系统使用规则
|
|
19
|
+
|
|
20
|
+
你有 mnemo 记忆工具(fact_store / fact_feedback),必须按以下规则使用:
|
|
21
|
+
|
|
22
|
+
## 规则 1:搜索记忆(每次回复前)
|
|
23
|
+
收到用户消息后,你必须先调用 \`fact_store(action="search", query="<用户消息的关键词>")\` 检索相关记忆。
|
|
24
|
+
query 必须从用户消息中提取关键词,不要用固定模板。例如:
|
|
25
|
+
- 用户说"我叫什么" → query="姓名 名字 叫什么"
|
|
26
|
+
- 用户说"我喜欢什么语言" → query="编程语言 偏好 喜欢"
|
|
27
|
+
搜索后根据结果自然回复,不要说"根据记忆"。
|
|
28
|
+
|
|
29
|
+
## 规则 2:写入记忆
|
|
30
|
+
用户说"记住"、"记下来"时,调用 \`fact_store(action="add", content="...", category="...")\`。
|
|
31
|
+
- 先 search 检查是否已有相似事实,有则 update
|
|
32
|
+
- category:identity / coding_style / tool_pref / workflow / general
|
|
33
|
+
|
|
34
|
+
## 规则 3:反馈强化
|
|
35
|
+
成功使用某条记忆时,调用 \`fact_feedback(action="helpful", fact_id=...)\`。
|
|
36
|
+
`;
|
|
37
|
+
const MCP_TOOLS = [
|
|
38
|
+
'mcp__mnemo__fact_store',
|
|
39
|
+
'mcp__mnemo__fact_feedback',
|
|
40
|
+
];
|
|
41
|
+
function log(msg) {
|
|
42
|
+
console.log(`\x1b[36m[mnemo]\x1b[0m ${msg}`);
|
|
43
|
+
}
|
|
44
|
+
function ok(msg) {
|
|
45
|
+
console.log(`\x1b[32m✓\x1b[0m ${msg}`);
|
|
46
|
+
}
|
|
47
|
+
function warn(msg) {
|
|
48
|
+
console.log(`\x1b[33m!\x1b[0m ${msg}`);
|
|
49
|
+
}
|
|
50
|
+
function fail(msg) {
|
|
51
|
+
console.log(`\x1b[31m✗\x1b[0m ${msg}`);
|
|
52
|
+
}
|
|
53
|
+
// -- Step 1: Register MCP server --
|
|
54
|
+
function registerMcp(scope = 'user') {
|
|
55
|
+
log('注册 MCP 服务器...');
|
|
56
|
+
try {
|
|
57
|
+
execSync(`claude mcp add --scope ${scope} mnemo -- mnemo`, {
|
|
58
|
+
stdio: 'pipe',
|
|
59
|
+
timeout: 15000,
|
|
60
|
+
});
|
|
61
|
+
ok('MCP 服务器已注册 (claude mcp list 查看)');
|
|
62
|
+
}
|
|
63
|
+
catch (err) {
|
|
64
|
+
const stderr = err.stderr?.toString() || '';
|
|
65
|
+
if (stderr.includes('already exists') || stderr.includes('already registered')) {
|
|
66
|
+
warn('MCP 服务器已存在,跳过注册');
|
|
67
|
+
}
|
|
68
|
+
else {
|
|
69
|
+
fail(`注册失败: ${stderr.slice(0, 200)}`);
|
|
70
|
+
fail('请手动运行: claude mcp add mnemo -- mnemo');
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
// -- Step 2: Write CLAUDE.md --
|
|
75
|
+
function writeClaudeMd() {
|
|
76
|
+
log('配置记忆使用规则...');
|
|
77
|
+
mkdirSync(CLAUDE_DIR, { recursive: true });
|
|
78
|
+
let existing = '';
|
|
79
|
+
if (existsSync(CLAUDE_MD_PATH)) {
|
|
80
|
+
existing = readFileSync(CLAUDE_MD_PATH, 'utf-8');
|
|
81
|
+
if (existing.includes('mnemo 记忆工具')) {
|
|
82
|
+
warn('CLAUDE.md 已包含 mnemo 规则,跳过');
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
const merged = existing
|
|
87
|
+
? existing.trimEnd() + '\n' + MEMORY_RULES
|
|
88
|
+
: MEMORY_RULES.trimStart();
|
|
89
|
+
writeFileSync(CLAUDE_MD_PATH, merged);
|
|
90
|
+
ok(`记忆规则已写入 ${CLAUDE_MD_PATH}`);
|
|
91
|
+
}
|
|
92
|
+
// -- Step 3: Update settings.json permissions --
|
|
93
|
+
function updatePermissions() {
|
|
94
|
+
log('配置工具权限...');
|
|
95
|
+
mkdirSync(CLAUDE_DIR, { recursive: true });
|
|
96
|
+
let settings = {};
|
|
97
|
+
if (existsSync(SETTINGS_PATH)) {
|
|
98
|
+
try {
|
|
99
|
+
settings = JSON.parse(readFileSync(SETTINGS_PATH, 'utf-8'));
|
|
100
|
+
}
|
|
101
|
+
catch {
|
|
102
|
+
warn('settings.json 解析失败,将覆盖');
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
if (!settings.permissions)
|
|
106
|
+
settings.permissions = {};
|
|
107
|
+
if (!settings.permissions.allow)
|
|
108
|
+
settings.permissions.allow = [];
|
|
109
|
+
let added = 0;
|
|
110
|
+
for (const tool of MCP_TOOLS) {
|
|
111
|
+
if (!settings.permissions.allow.includes(tool)) {
|
|
112
|
+
settings.permissions.allow.push(tool);
|
|
113
|
+
added++;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
if (added === 0) {
|
|
117
|
+
warn('权限已配置,跳过');
|
|
118
|
+
return;
|
|
119
|
+
}
|
|
120
|
+
writeFileSync(SETTINGS_PATH, JSON.stringify(settings, null, 2) + '\n');
|
|
121
|
+
ok(`已添加 ${added} 个工具权限到 ${SETTINGS_PATH}`);
|
|
122
|
+
}
|
|
123
|
+
// -- Main --
|
|
124
|
+
function main() {
|
|
125
|
+
const args = process.argv.slice(2);
|
|
126
|
+
const scope = args.includes('--project') ? 'project' : 'user';
|
|
127
|
+
console.log('');
|
|
128
|
+
console.log('\x1b[1m mnemo init — 一键配置记忆系统\x1b[0m');
|
|
129
|
+
console.log('');
|
|
130
|
+
registerMcp(scope);
|
|
131
|
+
writeClaudeMd();
|
|
132
|
+
updatePermissions();
|
|
133
|
+
console.log('');
|
|
134
|
+
ok('配置完成!重启 Claude Code 即可使用记忆系统。');
|
|
135
|
+
console.log('');
|
|
136
|
+
}
|
|
137
|
+
main();
|
|
138
|
+
//# sourceMappingURL=init.js.map
|
package/dist/init.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"init.js","sourceRoot":"","sources":["../src/init.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 混合检索管线。
|
|
3
|
+
* 移植自 Ocean CLI FactRetriever,使用 better-sqlite3。
|
|
4
|
+
*
|
|
5
|
+
* 管线:FTS5 候选集 → Jaccard 重排序 → 信任评分加权 → 时间衰减
|
|
6
|
+
* 高级检索:probe/related/reason 基于 fact_entities 关联表
|
|
7
|
+
* 矛盾检测:实体重叠 + 内容差异
|
|
8
|
+
*/
|
|
9
|
+
import type { ScoredFact, Contradiction, SearchOptions, ContradictOptions, RetrieverOptions } from './types.js';
|
|
10
|
+
import { MemoryStore } from './store.js';
|
|
11
|
+
export declare class FactRetriever {
|
|
12
|
+
private store;
|
|
13
|
+
private db;
|
|
14
|
+
private ftsWeight;
|
|
15
|
+
private jaccardWeight;
|
|
16
|
+
private halfLifeDays;
|
|
17
|
+
/** category → 高频 tag 集合(从事实库自动学习,惰性初始化) */
|
|
18
|
+
private _categoryTagMap;
|
|
19
|
+
/** 中英术语对列表(从事实库自动学习,惰性初始化) */
|
|
20
|
+
private _cnEnPairs;
|
|
21
|
+
constructor(store: MemoryStore, options?: RetrieverOptions);
|
|
22
|
+
/** 主搜索:FTS5 → LIKE → 字符交叉 → 分类推断 → Jaccard → 信任评分 → 时间衰减 */
|
|
23
|
+
search(query: string, options?: SearchOptions): ScoredFact[];
|
|
24
|
+
/** 实体探测:查询某实体关联的所有事实 */
|
|
25
|
+
probe(entity: string, options?: SearchOptions): ScoredFact[];
|
|
26
|
+
/** 实体关联:查找与某实体共享上下文的其他事实 */
|
|
27
|
+
related(entity: string, options?: SearchOptions): ScoredFact[];
|
|
28
|
+
/** 多实体推理:查找同时关联多个实体的事实 */
|
|
29
|
+
reason(entities: string[], options?: SearchOptions): ScoredFact[];
|
|
30
|
+
/** 矛盾检测:实体重叠 + 内容差异 */
|
|
31
|
+
contradict(options?: ContradictOptions): Contradiction[];
|
|
32
|
+
/** Stage 1: FTS5 候选集 */
|
|
33
|
+
private ftsCandidates;
|
|
34
|
+
/** 简单分词:空格/下划线/中英文标点分割 + 小写 + 中文 bigram */
|
|
35
|
+
private tokenize;
|
|
36
|
+
/** Jaccard 相似度 */
|
|
37
|
+
private jaccardSimilarity;
|
|
38
|
+
/** Containment: a 中有多少比例的 token 出现在 b 中(不对称,衡量"查询被事实覆盖"的程度) */
|
|
39
|
+
private containmentScore;
|
|
40
|
+
/** 时间衰减: 0.5^(ageDays / halfLifeDays) */
|
|
41
|
+
private temporalDecay;
|
|
42
|
+
/** 判断查询是否为个人/身份相关(应触发 trust fallback) */
|
|
43
|
+
private isPersonalQuery;
|
|
44
|
+
/** Trust fallback — 查询无法匹配任何事实时,按信任评分返回 top-N */
|
|
45
|
+
private trustFallback;
|
|
46
|
+
/** LIKE fallback — FTS5 失败或中文查询时使用 */
|
|
47
|
+
private likeFallback;
|
|
48
|
+
/** 中文字符级 fallback — FTS5 和 LIKE 都失败时,用单字交叉匹配 */
|
|
49
|
+
private charOverlapFallback;
|
|
50
|
+
/** 分类推断 fallback — 根据查询关键词推断 category,返回该分类的高信任事实 */
|
|
51
|
+
private categoryInferFallback;
|
|
52
|
+
/** 从事实库自动学习 category → tag 映射(惰性初始化 + 缓存) */
|
|
53
|
+
private getCategoryTagMap;
|
|
54
|
+
/**
|
|
55
|
+
* 从事实库自动学习中英术语对(惰性初始化 + 缓存)。
|
|
56
|
+
* 两个来源:
|
|
57
|
+
* 1. 种子表:极小的核心 IT 术语对照(稳定不变,覆盖高频查询)
|
|
58
|
+
* 2. 事实库提取:括号注释/分隔符关联的高置信翻译对(自动增长)
|
|
59
|
+
* 歧义对(一个中文对应多个英文)自动丢弃。
|
|
60
|
+
*/
|
|
61
|
+
private getCnEnPairs;
|
|
62
|
+
/** 添加候选对到 map */
|
|
63
|
+
private addPair;
|
|
64
|
+
/** 查询双语扩展:基于事实库自动学习的术语对照,将查询中的术语翻译为对端语言 */
|
|
65
|
+
private expandQueryBilingually;
|
|
66
|
+
/** 从查询内容推断 category — 基于事实库自动学习的 tag 映射 */
|
|
67
|
+
private inferCategory;
|
|
68
|
+
/** 检索追踪:递增 retrieval_count + top3 信任刷新(重置衰减时钟) */
|
|
69
|
+
private trackRetrieval;
|
|
70
|
+
}
|