quiet-memo 0.2.0__tar.gz

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 (52) hide show
  1. quiet_memo-0.2.0/.github/workflows/workflow.yml +31 -0
  2. quiet_memo-0.2.0/.gitignore +17 -0
  3. quiet_memo-0.2.0/PKG-INFO +219 -0
  4. quiet_memo-0.2.0/README.md +196 -0
  5. quiet_memo-0.2.0/config.example.toml +20 -0
  6. quiet_memo-0.2.0/pyproject.toml +44 -0
  7. quiet_memo-0.2.0/src/quiet_memo/__init__.py +3 -0
  8. quiet_memo-0.2.0/src/quiet_memo/__main__.py +4 -0
  9. quiet_memo-0.2.0/src/quiet_memo/agent/__init__.py +0 -0
  10. quiet_memo-0.2.0/src/quiet_memo/agent/context.py +258 -0
  11. quiet_memo-0.2.0/src/quiet_memo/agent/runtime.py +303 -0
  12. quiet_memo-0.2.0/src/quiet_memo/agent/session.py +193 -0
  13. quiet_memo-0.2.0/src/quiet_memo/agent/tools.py +301 -0
  14. quiet_memo-0.2.0/src/quiet_memo/app/__init__.py +0 -0
  15. quiet_memo-0.2.0/src/quiet_memo/app/cli.py +547 -0
  16. quiet_memo-0.2.0/src/quiet_memo/app/server.py +78 -0
  17. quiet_memo-0.2.0/src/quiet_memo/infra/__init__.py +0 -0
  18. quiet_memo-0.2.0/src/quiet_memo/infra/config.py +177 -0
  19. quiet_memo-0.2.0/src/quiet_memo/infra/gitops.py +100 -0
  20. quiet_memo-0.2.0/src/quiet_memo/infra/providers.py +218 -0
  21. quiet_memo-0.2.0/src/quiet_memo/infra/tokens.py +60 -0
  22. quiet_memo-0.2.0/src/quiet_memo/llm/__init__.py +28 -0
  23. quiet_memo-0.2.0/src/quiet_memo/llm/client.py +146 -0
  24. quiet_memo-0.2.0/src/quiet_memo/llm/commit_summary.py +61 -0
  25. quiet_memo-0.2.0/src/quiet_memo/llm/summarizer.py +72 -0
  26. quiet_memo-0.2.0/src/quiet_memo/memory/__init__.py +0 -0
  27. quiet_memo-0.2.0/src/quiet_memo/memory/audit.py +16 -0
  28. quiet_memo-0.2.0/src/quiet_memo/memory/detect.py +54 -0
  29. quiet_memo-0.2.0/src/quiet_memo/memory/extractor.py +117 -0
  30. quiet_memo-0.2.0/src/quiet_memo/memory/models.py +81 -0
  31. quiet_memo-0.2.0/src/quiet_memo/memory/policy.py +21 -0
  32. quiet_memo-0.2.0/src/quiet_memo/memory/queue.py +53 -0
  33. quiet_memo-0.2.0/src/quiet_memo/memory/service.py +301 -0
  34. quiet_memo-0.2.0/src/quiet_memo/memory/store.py +277 -0
  35. quiet_memo-0.2.0/src/quiet_memo/retrieval/__init__.py +4 -0
  36. quiet_memo-0.2.0/src/quiet_memo/retrieval/base.py +21 -0
  37. quiet_memo-0.2.0/src/quiet_memo/retrieval/keyword.py +65 -0
  38. quiet_memo-0.2.0/tests/conftest.py +22 -0
  39. quiet_memo-0.2.0/tests/test_agent.py +181 -0
  40. quiet_memo-0.2.0/tests/test_cli.py +73 -0
  41. quiet_memo-0.2.0/tests/test_context.py +124 -0
  42. quiet_memo-0.2.0/tests/test_detect.py +47 -0
  43. quiet_memo-0.2.0/tests/test_extractor.py +35 -0
  44. quiet_memo-0.2.0/tests/test_policy.py +27 -0
  45. quiet_memo-0.2.0/tests/test_queue.py +42 -0
  46. quiet_memo-0.2.0/tests/test_search.py +40 -0
  47. quiet_memo-0.2.0/tests/test_server.py +64 -0
  48. quiet_memo-0.2.0/tests/test_service.py +117 -0
  49. quiet_memo-0.2.0/tests/test_session.py +71 -0
  50. quiet_memo-0.2.0/tests/test_setup.py +63 -0
  51. quiet_memo-0.2.0/tests/test_store.py +72 -0
  52. quiet_memo-0.2.0/uv.lock +3249 -0
@@ -0,0 +1,31 @@
1
+ name: publish
2
+
3
+ on:
4
+ release:
5
+ types: [published]
6
+ workflow_dispatch:
7
+
8
+ permissions:
9
+ contents: read
10
+
11
+ jobs:
12
+ publish:
13
+ runs-on: ubuntu-latest
14
+ environment:
15
+ name: pypi
16
+ url: https://pypi.org/p/quiet-memo
17
+ permissions:
18
+ id-token: write
19
+ contents: read
20
+ steps:
21
+ - uses: actions/checkout@v4
22
+
23
+ - uses: astral-sh/setup-uv@v6
24
+ with:
25
+ python-version: "3.12"
26
+
27
+ - name: Build
28
+ run: uv build
29
+
30
+ - name: Publish to PyPI
31
+ uses: pypa/gh-action-pypi-publish@release/v1
@@ -0,0 +1,17 @@
1
+ __pycache__/
2
+ *.py[cod]
3
+ .venv/
4
+ .pytest_cache/
5
+ .idea/
6
+ .demo/
7
+ dist/
8
+ build/
9
+ *.egg-info/
10
+ quiet-memo.toml
11
+ demo_vault/
12
+ .env
13
+ .env.*
14
+ *.pem
15
+ *.key
16
+ sessions/
17
+ vault/
@@ -0,0 +1,219 @@
1
+ Metadata-Version: 2.5
2
+ Name: quiet-memo
3
+ Version: 0.2.0
4
+ Summary: Quiet-first personal memory: silent writes to local Markdown, powered by Git and MCP
5
+ Author: Shardkiht
6
+ License: MIT
7
+ Keywords: agent,git,markdown,mcp,memory
8
+ Requires-Python: >=3.12
9
+ Requires-Dist: fastmcp>=2.12
10
+ Requires-Dist: jieba>=0.42
11
+ Requires-Dist: keyring>=25.5
12
+ Requires-Dist: litellm>=1.60
13
+ Requires-Dist: openai>=1.60
14
+ Requires-Dist: prompt-toolkit>=3.0
15
+ Requires-Dist: pydantic>=2.9
16
+ Requires-Dist: pyyaml>=6.0
17
+ Requires-Dist: questionary>=2.0
18
+ Requires-Dist: rank-bm25>=0.2.2
19
+ Requires-Dist: rich>=13.9
20
+ Requires-Dist: tiktoken>=0.8
21
+ Requires-Dist: typer>=0.15
22
+ Description-Content-Type: text/markdown
23
+
24
+ # quiet-memo
25
+
26
+ 安静的个人记忆库:从日常对话中抽取**你本人**的事实、偏好和计划,默认无感写入本地 Markdown;低置信、冲突或敏感内容才进入待确认队列。
27
+
28
+ - **本地优先**:Markdown 是唯一事实来源,Git 负责版本与审计。
29
+ - **默认静默**:可信内容直接落盘,不逐条打断;只在必要时提醒。
30
+ - **完整 Agent**:交互式对话、会话持久化、上下文压缩、工具循环。
31
+ - **多模型**:LiteLLM 统一接入 DeepSeek、硅基流动、百炼、OpenRouter、OpenAI 等。
32
+ - **可回滚**:每次提交自动生成中文总结,供本人审阅。
33
+
34
+ ## 快速开始
35
+
36
+ 需要 Python 3.12+、uv、git。
37
+
38
+ ```bash
39
+ uv sync
40
+
41
+ # 交互式选择供应商,API Key 存入系统凭据(不写配置文件)
42
+ uv run qm setup
43
+
44
+ # 开始对话
45
+ uv run qm chat
46
+ ```
47
+
48
+ `qm setup` 会写入 `quiet-memo.toml`,初始化记忆库,并可选做一次连接测试。Key 也可以用环境变量提供,环境变量优先于 keyring:
49
+
50
+ ```bash
51
+ export DEEPSEEK_API_KEY=sk-...
52
+ ```
53
+
54
+ 手动配置示例:
55
+
56
+ ```toml
57
+ vault = "C:/Users/you/.quiet-memo/vault"
58
+ confidence_threshold = 0.8
59
+ auto_push = false
60
+
61
+ [llm]
62
+ provider = "deepseek" # litellm provider:deepseek/siliconflow/dashscope/openrouter/openai/custom
63
+ base_url = "https://api.deepseek.com/v1"
64
+ model = "deepseek-chat"
65
+ api_key_env = "DEEPSEEK_API_KEY"
66
+ fallbacks = [] # 例如 ["openai/gpt-4o-mini"]
67
+ num_retries = 2
68
+ temperature = 0.1
69
+ timeout = 60.0
70
+
71
+ [chat]
72
+ context_window = 32000
73
+ reserve_output_tokens = 1500
74
+ keep_recent_tokens = 6000
75
+ compact_threshold = 0.8
76
+ max_tool_steps = 8
77
+ tool_timeout = 60.0
78
+ auto_recall = 3
79
+ extract_on_exit = true
80
+ ```
81
+
82
+ Windows Git Bash 下如果中文输出乱码,加 `export PYTHONUTF8=1`。
83
+
84
+ ## 对话 Agent
85
+
86
+ `qm chat` 是完整的多轮 Agent,不是一次性问答:
87
+
88
+ - 每轮自动检索相关长期记忆,注入上下文。
89
+ - 模型可调用 `recall / memorize / correct / forget / review_pending / list_topics`。
90
+ - 会话持久化为 `sessions/<id>.jsonl`,可 `qm chat --resume <id>` 恢复。
91
+ - 退出时抽取本轮尚未沉淀的用户陈述。
92
+ - 记忆条目记录 `session` 和 `message` 来源,可追溯到原始对话。
93
+
94
+ 会话内命令:
95
+
96
+ | 命令 | 作用 |
97
+ | --- | --- |
98
+ | `/new` | 结束当前会话并新建 |
99
+ | `/sessions` | 列出历史会话 |
100
+ | `/resume <id>` | 恢复会话 |
101
+ | `/compact` | 立即压缩上下文 |
102
+ | `/summary` | 查看当前会话摘要 |
103
+ | `/status` | 会话、token、待确认状态 |
104
+ | `/rename <title>` | 重命名会话 |
105
+ | `/recall <query>` | 直接检索记忆 |
106
+ | `/remember <text>` | 直接抽取写入 |
107
+ | `/pending` | 查看待确认候选 |
108
+ | `/exit` | 退出 |
109
+
110
+ ### 上下文压缩
111
+
112
+ 当估算 token 超过预算的 `compact_threshold` 时:
113
+
114
+ 1. 按 `keep_recent_tokens` 保留最近对话(以用户消息为边界)。
115
+ 2. 把即将被淘汰的用户陈述送入记忆抽取,先沉淀到 Markdown。
116
+ 3. 用 LLM 把旧对话压缩成摘要,持久化为 `summary` 记录。
117
+ 4. 下一轮只带“摘要 + 最近原文 + 新消息”。
118
+
119
+ 摘要记录包含 `covered_records`,恢复会话时不会重复发送已被压缩的历史。压缩失败时回退为抽取式摘要,不阻塞对话。
120
+
121
+ ## 命令行
122
+
123
+ ```bash
124
+ # 从一段对话抽取并静默写入
125
+ uv run qm memorize "我最近在找市区的房子,预算 4000 以内,不接受合租"
126
+
127
+ # 直接记录(不调用 LLM)
128
+ uv run qm note "喝咖啡偏好清淡、像茶的风味" --topic preferences --title 偏好
129
+
130
+ # 检索 / 查看待确认 / 确认或拒绝
131
+ uv run qm recall "市区"
132
+ uv run qm pending
133
+ uv run qm approve p-20261022-140312-a1b2
134
+ uv run qm reject p-20261022-140312-c3d4
135
+
136
+ # 会话与提交
137
+ uv run qm sessions
138
+ uv run qm status
139
+ uv run qm commit --no-push
140
+ uv run qm history
141
+ ```
142
+
143
+ ### 接入 MCP
144
+
145
+ ```bash
146
+ uv run qm serve --vault ~/.quiet-memo/vault
147
+ ```
148
+
149
+ MCP 客户端配置:
150
+
151
+ ```json
152
+ {
153
+ "mcpServers": {
154
+ "quiet-memo": {
155
+ "command": "uv",
156
+ "args": ["run", "--directory", "C:/path/to/quiet-memo", "qm", "serve"]
157
+ }
158
+ }
159
+ }
160
+ ```
161
+
162
+ 暴露工具:`memorize`、`note`、`recall`、`review_pending`、`approve`、`reject`、`list_topics`、`history`、`commit`、`status`。
163
+
164
+ ## 写入规则
165
+
166
+ | 情况 | 行为 |
167
+ | --- | --- |
168
+ | 置信度 ≥ 阈值、非敏感、无冲突 | 直接写入 |
169
+ | 置信度低于阈值 | 进入待确认队列 |
170
+ | 数值/否定/高相似度冲突 | 进入待确认队列,保留冲突条目 ID |
171
+ | 敏感内容 | 进入待确认队列 |
172
+ | 密码、验证码、API Key | 直接拦截,不落盘 |
173
+ | 文本完全重复 | 跳过 |
174
+
175
+ 记忆按主题存为 `memories/<topic>.md`,条目带稳定 ID、状态、时间戳、来源和置信度:
176
+
177
+ ```markdown
178
+ - <!-- id=mem-20261022-194250-8f1e; status=active --> 2026-10-22T19:42:50 — 在找市区的房子 (source: session:s-... , confidence: 0.95, session: s-..., message: m-...)
179
+ ```
180
+
181
+ 更正采用“新条目 + `supersedes`”,旧条目状态改为 `superseded`;删除是软删除 `deleted`,操作写入 `.quiet-memo/audit.jsonl`,Git 可回滚。
182
+
183
+ ## 结构
184
+
185
+ ```text
186
+ src/quiet_memo/
187
+ ├── app/ cli.py, server.py # 入口:Typer CLI / FastMCP
188
+ ├── agent/ runtime.py, context.py, tools.py, session.py
189
+ │ # Agent 循环、压缩、工具、会话
190
+ ├── memory/ service.py, store.py, models.py, queue.py,
191
+ │ policy.py, detect.py, extractor.py, audit.py
192
+ │ # 记忆领域与写入裁决
193
+ ├── retrieval/ base.py, keyword.py # Retriever 接口 + BM25
194
+ ├── llm/ client.py, summarizer.py, commit_summary.py
195
+ │ # LiteLLM 适配、会话/提交摘要
196
+ └── infra/ config.py, providers.py, gitops.py, tokens.py
197
+ # 配置、供应商、Git、token
198
+ ```
199
+
200
+ 依赖方向:`app → agent → memory → retrieval → infra`,`memory/agent → llm → infra`。
201
+
202
+ - 检索当前是 jieba 分词 + rank-bm25;`Retriever` 是接口,后续可接向量/混合检索。
203
+ - token 预算用 tiktoken 估算,离线失败时回退字符估算。
204
+ - 会话压缩、记忆裁决、来源链是自研核心;模型适配交给 LiteLLM,供应商选择与密码输入用 questionary,Key 用 keyring。
205
+
206
+ ## 测试
207
+
208
+ ```bash
209
+ uv run pytest
210
+ ```
211
+
212
+ 当前 59 个测试,覆盖存储、队列、冲突检测、检索、抽取解析、会话、上下文压缩、Agent 工具循环、MCP 和 CLI。LLM 路径用固定抽取器和假模型测试;未接真实 API Key 时不声称已完成线上验证。
213
+
214
+ ## Roadmap
215
+
216
+ - 20+ 条抽取/冲突/检索评测用例与指标
217
+ - 真实模型 dogfood 与成本统计
218
+ - 向量/混合检索实现(替换 `Retriever`)
219
+ - 每日定时提交守护进程
@@ -0,0 +1,196 @@
1
+ # quiet-memo
2
+
3
+ 安静的个人记忆库:从日常对话中抽取**你本人**的事实、偏好和计划,默认无感写入本地 Markdown;低置信、冲突或敏感内容才进入待确认队列。
4
+
5
+ - **本地优先**:Markdown 是唯一事实来源,Git 负责版本与审计。
6
+ - **默认静默**:可信内容直接落盘,不逐条打断;只在必要时提醒。
7
+ - **完整 Agent**:交互式对话、会话持久化、上下文压缩、工具循环。
8
+ - **多模型**:LiteLLM 统一接入 DeepSeek、硅基流动、百炼、OpenRouter、OpenAI 等。
9
+ - **可回滚**:每次提交自动生成中文总结,供本人审阅。
10
+
11
+ ## 快速开始
12
+
13
+ 需要 Python 3.12+、uv、git。
14
+
15
+ ```bash
16
+ uv sync
17
+
18
+ # 交互式选择供应商,API Key 存入系统凭据(不写配置文件)
19
+ uv run qm setup
20
+
21
+ # 开始对话
22
+ uv run qm chat
23
+ ```
24
+
25
+ `qm setup` 会写入 `quiet-memo.toml`,初始化记忆库,并可选做一次连接测试。Key 也可以用环境变量提供,环境变量优先于 keyring:
26
+
27
+ ```bash
28
+ export DEEPSEEK_API_KEY=sk-...
29
+ ```
30
+
31
+ 手动配置示例:
32
+
33
+ ```toml
34
+ vault = "C:/Users/you/.quiet-memo/vault"
35
+ confidence_threshold = 0.8
36
+ auto_push = false
37
+
38
+ [llm]
39
+ provider = "deepseek" # litellm provider:deepseek/siliconflow/dashscope/openrouter/openai/custom
40
+ base_url = "https://api.deepseek.com/v1"
41
+ model = "deepseek-chat"
42
+ api_key_env = "DEEPSEEK_API_KEY"
43
+ fallbacks = [] # 例如 ["openai/gpt-4o-mini"]
44
+ num_retries = 2
45
+ temperature = 0.1
46
+ timeout = 60.0
47
+
48
+ [chat]
49
+ context_window = 32000
50
+ reserve_output_tokens = 1500
51
+ keep_recent_tokens = 6000
52
+ compact_threshold = 0.8
53
+ max_tool_steps = 8
54
+ tool_timeout = 60.0
55
+ auto_recall = 3
56
+ extract_on_exit = true
57
+ ```
58
+
59
+ Windows Git Bash 下如果中文输出乱码,加 `export PYTHONUTF8=1`。
60
+
61
+ ## 对话 Agent
62
+
63
+ `qm chat` 是完整的多轮 Agent,不是一次性问答:
64
+
65
+ - 每轮自动检索相关长期记忆,注入上下文。
66
+ - 模型可调用 `recall / memorize / correct / forget / review_pending / list_topics`。
67
+ - 会话持久化为 `sessions/<id>.jsonl`,可 `qm chat --resume <id>` 恢复。
68
+ - 退出时抽取本轮尚未沉淀的用户陈述。
69
+ - 记忆条目记录 `session` 和 `message` 来源,可追溯到原始对话。
70
+
71
+ 会话内命令:
72
+
73
+ | 命令 | 作用 |
74
+ | --- | --- |
75
+ | `/new` | 结束当前会话并新建 |
76
+ | `/sessions` | 列出历史会话 |
77
+ | `/resume <id>` | 恢复会话 |
78
+ | `/compact` | 立即压缩上下文 |
79
+ | `/summary` | 查看当前会话摘要 |
80
+ | `/status` | 会话、token、待确认状态 |
81
+ | `/rename <title>` | 重命名会话 |
82
+ | `/recall <query>` | 直接检索记忆 |
83
+ | `/remember <text>` | 直接抽取写入 |
84
+ | `/pending` | 查看待确认候选 |
85
+ | `/exit` | 退出 |
86
+
87
+ ### 上下文压缩
88
+
89
+ 当估算 token 超过预算的 `compact_threshold` 时:
90
+
91
+ 1. 按 `keep_recent_tokens` 保留最近对话(以用户消息为边界)。
92
+ 2. 把即将被淘汰的用户陈述送入记忆抽取,先沉淀到 Markdown。
93
+ 3. 用 LLM 把旧对话压缩成摘要,持久化为 `summary` 记录。
94
+ 4. 下一轮只带“摘要 + 最近原文 + 新消息”。
95
+
96
+ 摘要记录包含 `covered_records`,恢复会话时不会重复发送已被压缩的历史。压缩失败时回退为抽取式摘要,不阻塞对话。
97
+
98
+ ## 命令行
99
+
100
+ ```bash
101
+ # 从一段对话抽取并静默写入
102
+ uv run qm memorize "我最近在找市区的房子,预算 4000 以内,不接受合租"
103
+
104
+ # 直接记录(不调用 LLM)
105
+ uv run qm note "喝咖啡偏好清淡、像茶的风味" --topic preferences --title 偏好
106
+
107
+ # 检索 / 查看待确认 / 确认或拒绝
108
+ uv run qm recall "市区"
109
+ uv run qm pending
110
+ uv run qm approve p-20261022-140312-a1b2
111
+ uv run qm reject p-20261022-140312-c3d4
112
+
113
+ # 会话与提交
114
+ uv run qm sessions
115
+ uv run qm status
116
+ uv run qm commit --no-push
117
+ uv run qm history
118
+ ```
119
+
120
+ ### 接入 MCP
121
+
122
+ ```bash
123
+ uv run qm serve --vault ~/.quiet-memo/vault
124
+ ```
125
+
126
+ MCP 客户端配置:
127
+
128
+ ```json
129
+ {
130
+ "mcpServers": {
131
+ "quiet-memo": {
132
+ "command": "uv",
133
+ "args": ["run", "--directory", "C:/path/to/quiet-memo", "qm", "serve"]
134
+ }
135
+ }
136
+ }
137
+ ```
138
+
139
+ 暴露工具:`memorize`、`note`、`recall`、`review_pending`、`approve`、`reject`、`list_topics`、`history`、`commit`、`status`。
140
+
141
+ ## 写入规则
142
+
143
+ | 情况 | 行为 |
144
+ | --- | --- |
145
+ | 置信度 ≥ 阈值、非敏感、无冲突 | 直接写入 |
146
+ | 置信度低于阈值 | 进入待确认队列 |
147
+ | 数值/否定/高相似度冲突 | 进入待确认队列,保留冲突条目 ID |
148
+ | 敏感内容 | 进入待确认队列 |
149
+ | 密码、验证码、API Key | 直接拦截,不落盘 |
150
+ | 文本完全重复 | 跳过 |
151
+
152
+ 记忆按主题存为 `memories/<topic>.md`,条目带稳定 ID、状态、时间戳、来源和置信度:
153
+
154
+ ```markdown
155
+ - <!-- id=mem-20261022-194250-8f1e; status=active --> 2026-10-22T19:42:50 — 在找市区的房子 (source: session:s-... , confidence: 0.95, session: s-..., message: m-...)
156
+ ```
157
+
158
+ 更正采用“新条目 + `supersedes`”,旧条目状态改为 `superseded`;删除是软删除 `deleted`,操作写入 `.quiet-memo/audit.jsonl`,Git 可回滚。
159
+
160
+ ## 结构
161
+
162
+ ```text
163
+ src/quiet_memo/
164
+ ├── app/ cli.py, server.py # 入口:Typer CLI / FastMCP
165
+ ├── agent/ runtime.py, context.py, tools.py, session.py
166
+ │ # Agent 循环、压缩、工具、会话
167
+ ├── memory/ service.py, store.py, models.py, queue.py,
168
+ │ policy.py, detect.py, extractor.py, audit.py
169
+ │ # 记忆领域与写入裁决
170
+ ├── retrieval/ base.py, keyword.py # Retriever 接口 + BM25
171
+ ├── llm/ client.py, summarizer.py, commit_summary.py
172
+ │ # LiteLLM 适配、会话/提交摘要
173
+ └── infra/ config.py, providers.py, gitops.py, tokens.py
174
+ # 配置、供应商、Git、token
175
+ ```
176
+
177
+ 依赖方向:`app → agent → memory → retrieval → infra`,`memory/agent → llm → infra`。
178
+
179
+ - 检索当前是 jieba 分词 + rank-bm25;`Retriever` 是接口,后续可接向量/混合检索。
180
+ - token 预算用 tiktoken 估算,离线失败时回退字符估算。
181
+ - 会话压缩、记忆裁决、来源链是自研核心;模型适配交给 LiteLLM,供应商选择与密码输入用 questionary,Key 用 keyring。
182
+
183
+ ## 测试
184
+
185
+ ```bash
186
+ uv run pytest
187
+ ```
188
+
189
+ 当前 59 个测试,覆盖存储、队列、冲突检测、检索、抽取解析、会话、上下文压缩、Agent 工具循环、MCP 和 CLI。LLM 路径用固定抽取器和假模型测试;未接真实 API Key 时不声称已完成线上验证。
190
+
191
+ ## Roadmap
192
+
193
+ - 20+ 条抽取/冲突/检索评测用例与指标
194
+ - 真实模型 dogfood 与成本统计
195
+ - 向量/混合检索实现(替换 `Retriever`)
196
+ - 每日定时提交守护进程
@@ -0,0 +1,20 @@
1
+ # quiet-memo 配置示例
2
+ # 默认读取顺序:$QUIET_MEMO_CONFIG → ./quiet-memo.toml → ~/.config/quiet-memo/config.toml
3
+
4
+ # 记忆库位置(Markdown + Git)。环境变量 QUIET_MEMO_VAULT 可覆盖。
5
+ vault = "~/.quiet-memo/vault"
6
+
7
+ # 低于该置信度的候选不直接写入,进入待确认队列。
8
+ confidence_threshold = 0.8
9
+
10
+ # 提交后是否自动 push(需要已配置 remote)。
11
+ auto_push = false
12
+
13
+ [llm]
14
+ # 任意 OpenAI 兼容接口。DeepSeek 示例:
15
+ base_url = "https://api.deepseek.com/v1"
16
+ model = "deepseek-chat"
17
+ # 只写环境变量名,不写 Key 本身。
18
+ api_key_env = "DEEPSEEK_API_KEY"
19
+ temperature = 0.1
20
+ timeout = 60.0
@@ -0,0 +1,44 @@
1
+ [project]
2
+ name = "quiet-memo"
3
+ version = "0.2.0"
4
+ description = "Quiet-first personal memory: silent writes to local Markdown, powered by Git and MCP"
5
+ readme = "README.md"
6
+ requires-python = ">=3.12"
7
+ license = { text = "MIT" }
8
+ authors = [{ name = "Shardkiht" }]
9
+ keywords = ["memory", "mcp", "markdown", "git", "agent"]
10
+ dependencies = [
11
+ "fastmcp>=2.12",
12
+ "jieba>=0.42",
13
+ "keyring>=25.5",
14
+ "litellm>=1.60",
15
+ "openai>=1.60",
16
+ "prompt-toolkit>=3.0",
17
+ "pydantic>=2.9",
18
+ "pyyaml>=6.0",
19
+ "questionary>=2.0",
20
+ "rank-bm25>=0.2.2",
21
+ "rich>=13.9",
22
+ "tiktoken>=0.8",
23
+ "typer>=0.15",
24
+ ]
25
+
26
+ [project.scripts]
27
+ qm = "quiet_memo.app.cli:app"
28
+
29
+ [dependency-groups]
30
+ dev = [
31
+ "pytest>=8.3",
32
+ "pytest-asyncio>=0.24",
33
+ ]
34
+
35
+ [build-system]
36
+ requires = ["hatchling"]
37
+ build-backend = "hatchling.build"
38
+
39
+ [tool.hatch.build.targets.wheel]
40
+ packages = ["src/quiet_memo"]
41
+
42
+ [tool.pytest.ini_options]
43
+ testpaths = ["tests"]
44
+ asyncio_mode = "auto"
@@ -0,0 +1,3 @@
1
+ """quiet-memo: silent-first personal memory on local Markdown + Git."""
2
+
3
+ __version__ = "0.2.0"
@@ -0,0 +1,4 @@
1
+ from .app.cli import main
2
+
3
+ if __name__ == "__main__":
4
+ main()
File without changes