memleaf 0.1.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 (90) hide show
  1. memleaf-0.1.0/CHANGELOG.md +32 -0
  2. memleaf-0.1.0/IMPLEMENTATION_PLAN.md +143 -0
  3. memleaf-0.1.0/LICENSE +21 -0
  4. memleaf-0.1.0/MANIFEST.in +12 -0
  5. memleaf-0.1.0/PKG-INFO +423 -0
  6. memleaf-0.1.0/README.en.md +405 -0
  7. memleaf-0.1.0/README.md +404 -0
  8. memleaf-0.1.0/RELEASE_CHECKLIST.md +37 -0
  9. memleaf-0.1.0/RELEASE_NOTES_v0.1.md +49 -0
  10. memleaf-0.1.0/V2_IMPLEMENTATION_PLAN.md +94 -0
  11. memleaf-0.1.0/examples/README.md +19 -0
  12. memleaf-0.1.0/examples/basic_usage.py +85 -0
  13. memleaf-0.1.0/examples/mcp_stdio.ndjson +2 -0
  14. memleaf-0.1.0/install.sh +375 -0
  15. memleaf-0.1.0/integrations/hermes/memleaf/README.md +44 -0
  16. memleaf-0.1.0/integrations/hermes/memleaf/__init__.py +1839 -0
  17. memleaf-0.1.0/integrations/hermes/memleaf/plugin.yaml +6 -0
  18. memleaf-0.1.0/pyproject.toml +31 -0
  19. memleaf-0.1.0/setup.cfg +4 -0
  20. memleaf-0.1.0/src/memleaf/__init__.py +35 -0
  21. memleaf-0.1.0/src/memleaf/adapters/__init__.py +15 -0
  22. memleaf-0.1.0/src/memleaf/adapters/antigravity.py +352 -0
  23. memleaf-0.1.0/src/memleaf/adapters/base.py +746 -0
  24. memleaf-0.1.0/src/memleaf/adapters/codex.py +460 -0
  25. memleaf-0.1.0/src/memleaf/adapters/hermes.py +710 -0
  26. memleaf-0.1.0/src/memleaf/budget.py +123 -0
  27. memleaf-0.1.0/src/memleaf/capture.py +311 -0
  28. memleaf-0.1.0/src/memleaf/cli.py +360 -0
  29. memleaf-0.1.0/src/memleaf/compaction.py +878 -0
  30. memleaf-0.1.0/src/memleaf/config.py +164 -0
  31. memleaf-0.1.0/src/memleaf/frontmatter.py +403 -0
  32. memleaf-0.1.0/src/memleaf/host_events.py +1327 -0
  33. memleaf-0.1.0/src/memleaf/inbox.py +292 -0
  34. memleaf-0.1.0/src/memleaf/index.py +275 -0
  35. memleaf-0.1.0/src/memleaf/llm/__init__.py +43 -0
  36. memleaf-0.1.0/src/memleaf/llm/base.py +349 -0
  37. memleaf-0.1.0/src/memleaf/llm/claude_compatible.py +31 -0
  38. memleaf-0.1.0/src/memleaf/llm/gemini.py +35 -0
  39. memleaf-0.1.0/src/memleaf/llm/openai_compatible.py +127 -0
  40. memleaf-0.1.0/src/memleaf/llm/router.py +172 -0
  41. memleaf-0.1.0/src/memleaf/locking.py +134 -0
  42. memleaf-0.1.0/src/memleaf/mcp_server.py +979 -0
  43. memleaf-0.1.0/src/memleaf/memory_writer.py +437 -0
  44. memleaf-0.1.0/src/memleaf/model_discovery.py +746 -0
  45. memleaf-0.1.0/src/memleaf/models.py +285 -0
  46. memleaf-0.1.0/src/memleaf/native_index.py +776 -0
  47. memleaf-0.1.0/src/memleaf/processing.py +2029 -0
  48. memleaf-0.1.0/src/memleaf/prompts.py +306 -0
  49. memleaf-0.1.0/src/memleaf/redaction.py +41 -0
  50. memleaf-0.1.0/src/memleaf/retrieval.py +377 -0
  51. memleaf-0.1.0/src/memleaf/retrieval_gate.py +604 -0
  52. memleaf-0.1.0/src/memleaf/scope_maintenance.py +480 -0
  53. memleaf-0.1.0/src/memleaf/scope_state.py +328 -0
  54. memleaf-0.1.0/src/memleaf/service.py +1420 -0
  55. memleaf-0.1.0/src/memleaf/validation.py +794 -0
  56. memleaf-0.1.0/src/memleaf/vault.py +247 -0
  57. memleaf-0.1.0/src/memleaf.egg-info/PKG-INFO +423 -0
  58. memleaf-0.1.0/src/memleaf.egg-info/SOURCES.txt +88 -0
  59. memleaf-0.1.0/src/memleaf.egg-info/dependency_links.txt +1 -0
  60. memleaf-0.1.0/src/memleaf.egg-info/entry_points.txt +3 -0
  61. memleaf-0.1.0/src/memleaf.egg-info/top_level.txt +1 -0
  62. memleaf-0.1.0/tests/__init__.py +0 -0
  63. memleaf-0.1.0/tests/test_admission_noise.py +785 -0
  64. memleaf-0.1.0/tests/test_context_budget.py +259 -0
  65. memleaf-0.1.0/tests/test_hermes_provider.py +1153 -0
  66. memleaf-0.1.0/tests/test_host_events.py +790 -0
  67. memleaf-0.1.0/tests/test_install.py +427 -0
  68. memleaf-0.1.0/tests/test_maintenance_v2.py +595 -0
  69. memleaf-0.1.0/tests/test_model_discovery.py +207 -0
  70. memleaf-0.1.0/tests/test_retrieval_gate.py +184 -0
  71. memleaf-0.1.0/tests/test_retrieval_v2.py +202 -0
  72. memleaf-0.1.0/tests/test_stage_a.py +374 -0
  73. memleaf-0.1.0/tests/test_stage_b1.py +1063 -0
  74. memleaf-0.1.0/tests/test_stage_b2a.py +1185 -0
  75. memleaf-0.1.0/tests/test_stage_b2b.py +582 -0
  76. memleaf-0.1.0/tests/test_stage_b3a_commit.py +418 -0
  77. memleaf-0.1.0/tests/test_stage_b3a_contract.py +283 -0
  78. memleaf-0.1.0/tests/test_stage_b3b_native_context.py +294 -0
  79. memleaf-0.1.0/tests/test_stage_b3b_native_index.py +268 -0
  80. memleaf-0.1.0/tests/test_stage_b3b_scope.py +339 -0
  81. memleaf-0.1.0/tests/test_stage_b3c_retrieval.py +302 -0
  82. memleaf-0.1.0/tests/test_stage_b3d_scope_maintenance.py +579 -0
  83. memleaf-0.1.0/tests/test_stage_c1_mcp.py +758 -0
  84. memleaf-0.1.0/tests/test_stage_c2_init.py +776 -0
  85. memleaf-0.1.0/tests/test_stage_c3_packaging.py +123 -0
  86. memleaf-0.1.0/tests/test_v2_gate_limits.py +207 -0
  87. memleaf-0.1.0/tests/test_v2_host_flow.py +160 -0
  88. memleaf-0.1.0/tests/test_v2_mcp_flow.py +445 -0
  89. memleaf-0.1.0/tests/test_v2_nomatch_semantics.py +106 -0
  90. memleaf-0.1.0/tests/test_v2_search_gate_acceptance.py +147 -0
@@ -0,0 +1,32 @@
1
+ # Changelog
2
+
3
+ All notable changes to memleaf are documented here.
4
+
5
+ ## 0.1.0 — 2026-08-28 (GitHub tag: v0.1)
6
+
7
+ - Added the local-first, dependency-free Markdown vault core with capture,
8
+ memory creation, deterministic search/context retrieval, statistics, and
9
+ rebuildable indexes.
10
+ - Added safe vault paths, file locking/atomic writes, frontmatter handling, and
11
+ secret redaction for captured text.
12
+ - Added model-backed admission, extraction, state updates with history,
13
+ compaction, retryable processing, and scope-aware maintenance without adding
14
+ runtime dependencies.
15
+ - Added the `memleaf` initialization CLI and the `memleaf-mcp` stdio entry
16
+ point.
17
+ - Added the v2 Scope Map → directory search → bounded read protocol, including
18
+ per-turn retrieval state, pagination, and read budgets.
19
+ - Added a Hermes-native MemoryProvider plus MCP setup. v0.1 supports only
20
+ Hermes; Codex and Antigravity are not detected, configured, or scanned for models.
21
+ - Added packaging metadata, examples, offline local installation, and CI for
22
+ Python 3.11–3.13.
23
+
24
+ This version is intended for source installation from GitHub and is not a PyPI
25
+ release. Host behavior still depends on supported local Agent versions, user
26
+ trust/authorization, and an available model route.
27
+
28
+ ## Planned
29
+
30
+ - v0.2: add Codex support.
31
+ - Gradually support more Agent tools through their official integration and
32
+ authorization mechanisms. These are plans, not delivered v0.1 capabilities.
@@ -0,0 +1,143 @@
1
+ # memleaf v0.1 实施计划
2
+
3
+ 基线:历史 v74 设计。`README.md` 与 `README.en.md` 作为对外行为契约;实现不得把 README 中尚未完成的目标描述成已发布能力。
4
+
5
+ 发布范围更新(2026-08-28):v0.1 仅 Hermes。下文 Codex/反重力适配记录仅为历史,不属于本版安装或验收范围。
6
+
7
+ 2026-08-28 已批准的新检索与维护方案见 [v2 实施计划](V2_IMPLEMENTATION_PLAN.md)。其 Scope-only 注入、每轮 search、按需 read 和候选级维护规则取代下文旧的 3 项目录自动注入方案;旧条目保留为历史验收记录,不代表运行目录已部署新版。
8
+
9
+ ## 实施原则
10
+
11
+ - Python 3.11+,核心运行时仅使用标准库。
12
+ - `knowledge/` Markdown 是真实数据源;JSON 索引必须可重建。
13
+ - MCP 为薄适配层,业务逻辑只存在于 core。
14
+ - 所有写入采用同目录临时文件、`fsync`、原子替换;并发写通过 vault 锁串行化。
15
+ - 处理成功前不推进轮次水位,不清理 inbox;模型失败必须可重试。
16
+ - `memleaf init` 是一次性安装/配置入口,不引入常驻进程。
17
+ - 保持 v74 计划文档骨架,仅在实现事实发生变化时做最小补充;README 同样只做必要更新。
18
+ - 用户决策(2026-08-25):推荐源码和运行根固定为 `$HOME/memleaf`,不增加 `work` 层;从其他物理目录运行 `install.sh` 必须安全失败,只有显式设置 `MEMLEAF_INSTALL_ROOT` 才允许隔离测试/开发。
19
+ - 用户决策(2026-08-25):只有可靠检测到 `hermes` 可执行文件时,才安装并激活官方外部 `MemoryProvider`;未检测到时不创建 Hermes provider 插件或配置,只输出诊断。
20
+ - 用户决策(2026-08-28):v0.1 命令安装和 `memleaf init` 仅接入 Hermes;Codex、Antigravity 保留兼容代码但不检测、不配置、不扫描模型,`--all` 也不得绕过该边界。
21
+ - 已审核方案(2026-08-27):自动 `context` 只返回记忆目录(ID、短标题、项目),最多 3 项,整个自动注入不超过 600 字符;不返回正文、来源或正文摘录。MCP `search` 默认返回目录,显式完整查询保留兼容;模型按需 `read`,长正文分段读取。目录曝光不计命中,正文实际读取才计命中;不改变 process 候选提炼、scope、状态更新/history 或 Markdown 存储语义。
22
+ - 用户决策(2026-08-25):当前只做本地完整测试,不提交、不推送、不发布 Git/PyPI。
23
+
24
+ ## 阶段 A:本地核心纵切
25
+
26
+ 交付:可安装包、vault 初始化、受限 YAML/frontmatter、事件捕获与脱敏、Markdown 记忆 CRUD、索引重建、标签/全文/作用域检索、forget、统计。
27
+
28
+ 建议模块:
29
+
30
+ ```text
31
+ src/memleaf/
32
+ ├── __init__.py
33
+ ├── config.py
34
+ ├── models.py
35
+ ├── vault.py
36
+ ├── frontmatter.py
37
+ ├── redaction.py
38
+ ├── locking.py
39
+ ├── capture.py
40
+ ├── index.py
41
+ ├── retrieval.py
42
+ └── service.py
43
+ ```
44
+
45
+ 验收:
46
+
47
+ - 相同 `event_id` 重复 capture 不产生重复事件;同 session 恢复后可追加新轮次。
48
+ - 用户预先声明“不记录”的文本不进入 inbox;常见密钥、Cookie、私钥等在落盘前被脱敏。
49
+ - 标签多命中采用并集,随后按 scope 继承/覆盖过滤;标签无命中时才全文回退。
50
+ - `include_history=false` 不读取历史区;todo 默认仅返回 active。
51
+ - `forget_memory` 精确目标直接删除且不进 history;`forget_about` 含糊时只返回候选,不误删。
52
+ - 手工修改/删除 Markdown 后,`rebuild_index()` 只反映当前文件系统状态。
53
+ - 并发 capture 不丢事件,损坏索引可重建。
54
+
55
+ ## 阶段 B:记忆处理与模型路由
56
+
57
+ 交付:候选提取、逐条 gate、summarize、remember、当前状态更新、history、处理水位、24 小时清理、压缩、Model Router。
58
+
59
+ 建议模块:
60
+
61
+ ```text
62
+ src/memleaf/
63
+ ├── prompts.py
64
+ ├── processing.py
65
+ ├── memory_writer.py
66
+ ├── compaction.py
67
+ └── llm/
68
+ ├── base.py
69
+ ├── router.py
70
+ ├── openai_compatible.py
71
+ ├── claude_compatible.py
72
+ └── gemini.py
73
+ ```
74
+
75
+ 验收:
76
+
77
+ - 一个完整轮次可生成 0~N 条原子记忆;assistant 未经用户确认的建议不能写成事实。
78
+ - 显式 remember 跳过 worth gate,但仍执行整理、查重和 scope 归属。
79
+ - 同一事实重复处理不重复写;状态变化时旧版本进入 history,新版本成为唯一活跃状态。
80
+ - 任一模型调用、解析、knowledge 写入或索引更新失败时不推进水位、不删除 inbox。
81
+ - 成功轮次经过 24 小时安全期后,仅在下一次自然触发时清理。
82
+ - 达到阈值时只选低优先级约 30% 为候选;原始记忆移入 history,不做机械删除。
83
+ - `api` 模式覆盖 OpenAI-compatible、Claude-compatible、Gemini;新安装按用户决策将密钥直接写入权限为 `0600` 的本地配置,旧 `api_key_env` 仅兼容读取。
84
+ - `host` 使用显式注入的宿主回调;stdio MCP 无宿主回调时返回可诊断的不可用状态,`auto` 仅在已配置 API 时回退,禁止静默选择未知远程模型。
85
+
86
+ ## 阶段 C:MCP、初始化与宿主适配
87
+
88
+ 交付:按需 stdio MCP、一次性 init CLI、Codex/Hermes 探测与配置适配器、兼容保留的 Antigravity 适配器、示例、CI 与打包。
89
+
90
+ 建议模块:
91
+
92
+ ```text
93
+ src/memleaf/
94
+ ├── mcp_server.py
95
+ ├── cli.py
96
+ └── adapters/
97
+ ├── base.py
98
+ ├── codex.py
99
+ ├── hermes.py
100
+ └── antigravity.py
101
+ ```
102
+
103
+ MCP tools:`capture`、`context`、`search`、`read`、`process`、`remember`、`forget_memory`、`forget_about`、`rebuild_index`、`stats`。
104
+
105
+ 验收:
106
+
107
+ - `python -m memleaf.mcp_server` 可通过 stdio 完成 initialize、tools/list、tools/call;stdout 只输出协议消息,日志写 stderr/文件。
108
+ - 每个 MCP tool 只是 core API 的参数校验和结果封装,不复制业务规则。
109
+ - `memleaf init --all --defaults` 可重复执行且不重复写配置。
110
+ - Codex 适配遵循官方当前配置:本地 STDIO server 通过命令启动,配置位于用户级或受信任项目级 `config.toml`;自动修改外部配置前先备份并采用原子写入。
111
+ - Codex/Hermes 只在真机探测结果可靠时自动配置;Antigravity 在 v0.1 不检测、不配置(包括 `--all`),仅保留兼容适配器代码。
112
+ - 构建 wheel/sdist、全量单元测试、MCP 端到端 smoke test 均通过。
113
+
114
+ ## 待办与问题记录:Hermes 重连后自动捕获与提炼中断
115
+
116
+ - 状态:Hermes 已验证连续多轮自动 capture→process→knowledge 写入;30 秒模型请求超时、gate/summarize 契约与白名单校验诊断、DeepSeek 结构抽取与空内容有限重试自动化修复完成。下一次真实 cron 禁用验收与干净 HOME 安装验收仍待执行;历史缺失轮次不会自动回填。
117
+ - 真实验收曾覆盖首轮 gate+summarize 成功写入,以及后续模型空内容时保留 inbox 和处理水位;当前 `diagnostic_logging=false` 且不会默认创建诊断文件。
118
+ - 现象:`auto_process=true`,首段对话捕获了 5 个完整轮次(10 个事件),但 Hermes 在 14:39、14:41、14:43 完成的后续轮次没有继续写入 inbox;`knowledge/` 和 `history/` 均未生成记忆。
119
+ - 证据:目标 inbox 文件最后更新于 14:30:13;`_index/processed.json` 仍停留在第 1 轮 `processing`,没有成功处理水位;Hermes 日志记录 14:19:59 的 `auto-process failed`。Hermes 自身模型请求均成功,MCP `stats` 入口可用。
120
+ - 初步根因:Hermes provider 的 MCP 超时配置为 5 秒,首轮处理在超时后留下未清理的 processing 标记;随后 UI/provider 重连后的完整可见轮次未恢复自动捕获/处理。当前 provider 对底层 MCP 异常只记录摘要,无法直接区分超时与重连生命周期故障。
121
+ - [x] 修复 MCP 调用超时、失败重试和 processing 标记恢复,确保模型处理较慢时 inbox 与水位仍可安全重试。短请求默认仍为 5 秒,`process` 独立使用默认 300 秒(上限 900 秒);超时会关闭坏 MCP 子进程,下一次调用重建连接;processing marker 写入 `owner_pid`,死亡 owner 立即恢复,旧 marker 仅保留 10 分钟兼容窗口。
122
+ - [x] 确保 Hermes UI/provider 重连或恢复同一 session 后,每个完整可见轮次仍会捕获并触发自动提炼。`on_turn_start` 的 turn number 与 user+assistant 可见文本短哈希共同组成 turn_id;provider 仅保留有界 user 指纹队列,重复完整轮次复用相同 ID 幂等;`on_session_switch` 只在 reset/rewound 时清理旧会话状态。
123
+ - [x] 增加可诊断日志,记录 capture/process 的阶段、耗时和错误类型,但不得记录对话正文或密钥。覆盖 initialize/stats/capture_user/capture_assistant/process/context,并区分 TimeoutError、MCP tool error 与子进程退出。
124
+ - [x] 修复自动提炼模型调用的内部 HTTP 30 秒超时与不安全错误透传:`llm.request_timeout` 默认 120 秒、范围 1~240 秒;失败按安全 code/stage 透传到 MCP、日志和 processing marker,失败后保留 inbox、不推进水位并可重试。
125
+ - [x] 修复 DeepSeek/OpenAI JSON mode 与 gate/summarize 契约:受支持 provider 使用 JSON mode 和固定 `max_tokens`;DeepSeek gate/summarize 关闭 thinking 以避免结构抽取被推理预算占用,严格契约失败最多重试一次,空内容额外允许第 3 次;最终失败仅透传白名单 `validation_reason`、`attempt_count`,不记录模型原始输出。
126
+ - [x] 对齐 gate/summarize 的类型、scope、todo、证据 event_key 与 reason 约束;失败增加白名单 `validation_detail`,并支持默认关闭、开启后有界 `logs/model-diagnostics.jsonl` 的结构统计诊断,不记录 prompt、正文、字段值、密钥、URL 或异常文本。
127
+ - [x] 按 Hermes lifecycle 同时识别 `platform` 与 `agent_context`:`platform=cron` 以及 `agent_context=cron/flush/subagent` 不召回、不捕获、不执行 process;正常 primary 交互会话保持原行为。
128
+ - [x] 保留已有 Hermes cron 历史数据;上述边界只阻断后续非用户会话污染,不删除或回填既有记录。
129
+ - [x] 连续多轮 Hermes 交互自动 capture→process→knowledge 已由隔离真机会话验证。
130
+ - [ ] 在干净 HOME 完成安装验收,确认上述自动链路无需手工调用 `process`/`remember`。
131
+ - [ ] 用下一次真实 Hermes cron 运行验证其不再触发 context、capture 或 process,且不影响正常交互会话。
132
+
133
+ 阶段自动化曾覆盖完整 unittest、compileall 与 diff 检查,包括慢 process 超时边界、结构化输出重试、模型错误分类、重连、进程恢复、白名单诊断、敏感日志和宿主 Hook 状态。最终发布结论以当前 CI 和发布审计为准。
134
+
135
+ ## 本任务状态:Codex 自动宿主 Hook;Antigravity 兼容代码暂不启用
136
+
137
+ - [x] 保持 v74 Core API、MCP 与 vault 数据骨架不变;新增共用 host-event 入口,复用 capture/context/process。
138
+ - [x] 可靠检测到 Codex 时由 `init` 默认配置 Hook;配置合并可重复、先备份、原子写入,命令使用安装解释器绝对路径。Hermes 使用其原生 provider/MCP 接入。
139
+ - [x] 保留 Codex/Antigravity 可见内容 host-event 兼容代码;v0.1 `init`/安装不检测、不配置 Antigravity,过滤与幂等逻辑不改变 Core/MCP 骨架。
140
+ - [x] 正常 Stop 同步 process;失败保留 inbox 与待处理状态,Hook 错误不阻塞宿主结束。
141
+ - [x] 使用脱敏合成 fixture 完成定向与全量单元测试;Codex 真机已验证可见捕获、process 与 context 调用链。安装后 Codex 状态先为 `pending_user_review`,用户需打开 `/hooks` 审核;首个合法成功 Hook 后记录 `active`/`trusted`。
142
+ - [x] Antigravity 适配器及其官方 Hook 解析代码继续保留作兼容性测试,但 v0.1 安装不会写入 Antigravity MCP/Hook 配置,也不会声称其已接入。
143
+ - [ ] Codex 非空跨宿主记忆召回专项验收;Antigravity 接入与真实宿主 E2E 延后到后续版本。
memleaf-0.1.0/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 memleaf contributors
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.
@@ -0,0 +1,12 @@
1
+ include CHANGELOG.md
2
+ include LICENSE
3
+ include install.sh
4
+ include README.md
5
+ include README.en.md
6
+ include RELEASE_CHECKLIST.md
7
+ include RELEASE_NOTES_v0.1.md
8
+ include IMPLEMENTATION_PLAN.md
9
+ include V2_IMPLEMENTATION_PLAN.md
10
+ recursive-include tests *.py
11
+ recursive-include examples *.md *.ndjson *.py
12
+ recursive-include integrations/hermes/memleaf *.md *.py *.yaml
memleaf-0.1.0/PKG-INFO ADDED
@@ -0,0 +1,423 @@
1
+ Metadata-Version: 2.4
2
+ Name: memleaf
3
+ Version: 0.1.0
4
+ Summary: A local-first Markdown memory core for AI agents
5
+ Author: memleaf contributors
6
+ License-Expression: MIT
7
+ Keywords: ai-agents,local-first,markdown,memory
8
+ Classifier: Intended Audience :: Developers
9
+ Classifier: Programming Language :: Python :: 3
10
+ Classifier: Programming Language :: Python :: 3 :: Only
11
+ Classifier: Programming Language :: Python :: 3.11
12
+ Classifier: Programming Language :: Python :: 3.12
13
+ Classifier: Programming Language :: Python :: 3.13
14
+ Classifier: Topic :: Software Development :: Libraries
15
+ Requires-Python: >=3.11
16
+ Description-Content-Type: text/markdown
17
+ License-File: LICENSE
18
+ Dynamic: license-file
19
+
20
+ # 冥想盆 · memleaf
21
+
22
+ > 一个本地优先、Markdown 驱动、面向多个 AI Agent 的共享记忆核心。
23
+
24
+ [English](README.en.md) · [GitHub](https://github.com/miffyblueboo/memleaf)
25
+
26
+ > **当前版本:v0.1(Python 包版本 0.1.0)。**
27
+ > 核心库、Vault、stdio MCP Server、初始化 CLI、模型路由、提炼流程、受控检索协议和宿主适配器已经实现。当前尚未发布到 PyPI。
28
+ > **v0.1 仅支持 Hermes。** Codex 与反重力不检测、不安装、不配置,也不扫描其模型配置。
29
+
30
+ ## 项目定位
31
+
32
+ memleaf 把 AI Agent 的长期记忆保存为用户自己拥有的本地 Markdown 文件,并让多个 Agent 共享同一个 Vault。
33
+
34
+ - 不依赖向量数据库、embedding 服务或常驻后台;
35
+ - 不要求 memleaf 账号、云端服务、云同步或遥测;
36
+ - `knowledge/` 中的 Markdown 是当前有效记忆的事实来源;
37
+ - 可用 Obsidian、VS Code、Vim 等普通工具直接查看和编辑;
38
+ - 通过本地 stdio MCP 提供主动检索、读取、记忆维护等能力;
39
+ - 核心运行时只使用 Python 标准库,要求 Python 3.11 或更高版本。
40
+
41
+ memleaf 不会把整个 Vault 或整段历史对话自动塞进模型上下文。当前 v2 自动路径采用“Scope Map → 候选目录 → 受控读取正文”的流程。
42
+
43
+ ## 当前工作流
44
+
45
+ ```text
46
+ 可见的 user/assistant 对话
47
+
48
+ ├─ capture:脱敏后写入 inbox/<source>/<session>.md
49
+
50
+ ├─ 自动检索入口:只注入有界 Scope Map
51
+ │ │
52
+ │ └─ Agent 选择 Scope 和 Query
53
+ │ └─ search:返回候选目录
54
+ │ └─ read:按需读取少量关键正文
55
+
56
+ └─ process / remember:由模型判断并写入 knowledge/
57
+ └─ 状态更新时旧版本进入 history/
58
+ ```
59
+
60
+ ### 自动注入和检索
61
+
62
+ 自动注入只包含 Scope 的标识、父级和别名,以及检索协议提示;不包含记忆 ID、标题、正文或全量历史。Scope Map 单页最多 20 项、约 2000 字符。
63
+
64
+ 正常用户消息的推荐链路是:
65
+
66
+ 1. Agent 使用当前完整会话和 Scope Map 选择检索范围与查询词;
67
+ 2. 至少调用一次 `search`;
68
+ 3. `search` 只返回候选的 `memory_id`、标题和 Scope,不直接返回正文;
69
+ 4. 只有需要引用事实时,才使用同一轮返回的 `retrieval_id` 调用 `read`;
70
+ 5. 根据读取到的关键记忆回答,不把所有候选全部读完。
71
+
72
+ 当前限制:
73
+
74
+ - Scope Map 最多 20 项、约 2000 字符;
75
+ - search 候选单页最多 20 项、约 4000 字符;
76
+ - read 单页正文最多 2000 字符;
77
+ - 受管理轮次最多读取 3 个不同记忆、累计 6000 个正文字符;
78
+ - `retrieval_id` 必须属于当前轮次,且必须先有成功的 `search` 才能 `read`;
79
+ - `found`、`no_match` 和工具错误是不同状态,错误不能被伪装成无匹配;
80
+ - 旧版 `context()` 和 Python `search(view="full")` 仍为兼容接口,但不属于新的自动注入路径。
81
+
82
+ Hermes 使用原生 MemoryProvider 维护生命周期,并通过 MCP 获取 Scope Map;Hermes 的检索门控是 Soft Gate,不能宣称阻止所有未检索回答。
83
+
84
+ ## 记忆提炼规则
85
+
86
+ memleaf 不把每句话都保存为记忆。处理一轮完整的 user + assistant 可见文本时,模型先判断是否存在明确的未来复用价值:
87
+
88
+ - `CREATE`:没有相关现存记忆,创建一条原子、可独立理解的记忆;
89
+ - `UPDATE`:同一未来用途的现存记忆需要更新,沿用原 `memory_id`;旧内容进入 `history/`;
90
+ - `NO_CHANGE`:只是重复、查询、临时状态、测试、审计、诊断或没有稳定复用价值,不新增记忆。
91
+
92
+ 额外约束:
93
+
94
+ - 通常一轮产生 0~1 条记忆,而不是按句子拆分;
95
+ - 新记忆必须有稳定标题、完整正文和合理 Scope;
96
+ - 项目、负责人等归属不明确时延后记录,不猜测为 `global`;
97
+ - 相同未来用途优先 UPDATE/NO_CHANGE,不重复 CREATE;
98
+ - 用户显式要求保存时可调用 `remember`,但仍会整理、校验和去重;
99
+ - 模型、解析、写入或索引失败时保留 inbox 和处理水位,后续可重试;
100
+ - 自动清理有 24 小时安全期,不会因为一次处理失败就删除原始捕获。
101
+
102
+ ## 安装
103
+
104
+ 当前版本从 GitHub 源码安装,尚未发布到 PyPI。新安装使用以下命令;已有源码目录时跳过 `git clone`,先确认源码为 v0.1。默认路径是 `$HOME/memleaf`,不增加 `work` 层:
105
+
106
+ ```bash
107
+ git clone --branch v0.1 --depth 1 https://github.com/miffyblueboo/memleaf.git "$HOME/memleaf"
108
+ cd "$HOME/memleaf"
109
+ ./install.sh
110
+ ```
111
+
112
+ 默认安装位置:
113
+
114
+ ```text
115
+ $HOME/memleaf/ # 源码和可编辑安装目录
116
+ $HOME/memleaf/.venv/ # memleaf 虚拟环境
117
+ $HOME/.local/bin/memleaf # 用户级命令入口
118
+ $HOME/.local/bin/memleaf-mcp
119
+ $HOME/.memleaf/ # 数据 Vault,与源码目录分离
120
+ ```
121
+
122
+ 安装脚本不会创建额外的 `work` 层。它使用标准库在独立虚拟环境中链接源码、生成命令入口,不依赖 pip/setuptools,也不升级用户其他 Python 包。支持 macOS/Linux;自动查找 Python 3.11+,找不到时可用 `MEMLEAF_PYTHON=/path/to/python3 ./install.sh` 指定。
123
+
124
+ 如果只是对非标准源码目录做隔离测试,必须显式指定当前源码目录:
125
+
126
+ ```bash
127
+ MEMLEAF_INSTALL_ROOT="$PWD" ./install.sh
128
+ ```
129
+
130
+ ### 安装时的宿主配置
131
+
132
+ `install.sh` 会先初始化 `$HOME/.memleaf`,仅接入 Hermes;如果检测到可执行的 Hermes,则继续完成两条彼此独立的接入链:
133
+
134
+ 1. 安装并激活 Hermes 官方原生 `MemoryProvider` 插件;
135
+ 2. 通过 Hermes 官方 MCP CLI 配置 `memleaf`,并验证 MCP Server 能发现 11 个工具。
136
+
137
+ Hermes 相关路径:
138
+
139
+ ```text
140
+ $HOME/.hermes/plugins/memleaf/ # 用户级 provider 插件
141
+ $HOME/.hermes/memleaf.json # Vault、绝对 MCP 命令和超时配置
142
+ ```
143
+
144
+ 安装后请重启 Hermes。若安装时找不到完整可调用的聊天模型路由,交互终端会要求补充模型配置并直接写入 Vault 配置文件;非交互执行会明确返回失败,不会伪造成功状态。
145
+
146
+ Codex 和 Antigravity(反重力)不属于 v0.1 范围:安装和 `memleaf init --all` 均不检测、不修改它们的 MCP、Hook 或模型配置。已有安装保持原样;源码中的兼容适配器不代表本版支持接入。
147
+
148
+ ### 初始化命令
149
+
150
+ 先查看计划变更:
151
+
152
+ ```bash
153
+ memleaf init --dry-run --json
154
+ ```
155
+
156
+ 确认后初始化:
157
+
158
+ ```bash
159
+ memleaf init --all --defaults
160
+ ```
161
+
162
+ 常用选项:
163
+
164
+ ```bash
165
+ memleaf init --vault /path/to/vault
166
+ memleaf init --no-hermes
167
+ memleaf init --no-model-discovery
168
+ memleaf init --json
169
+ ```
170
+
171
+ `--no-codex` 和 `--no-antigravity` 为兼容保留的无操作参数。宿主配置只会在检测证据可靠、结构可识别且没有冲突时修改;修改前会创建备份,未知或冲突配置保持不变。
172
+
173
+ ## Hermes 使用方式
174
+
175
+ Hermes 的原生 Provider 和 MCP Server 是两个不同入口,但共用同一个 `$HOME/.memleaf`:
176
+
177
+ - Provider 负责自动捕获可见的 Hermes user/assistant 轮次,并在完整轮次后触发 `process`;
178
+ - Provider 只提供 Scope Map,不直接注入记忆正文;
179
+ - Agent 需要通过 MCP `search` 找到候选,再用当前 `retrieval_id` 调用 `read`;
180
+ - MCP 仍用于主动 `search`、`remember`、`forget` 和维护操作;
181
+ - MCP 连接失败时会关闭坏连接,后续请求可重建连接;
182
+ - `process` 使用已发现或用户配置的模型路由执行准入判断和记忆整理;失败数据保留在 inbox 中;
183
+ - cron、flush、subagent 等非主用户会话不会自动召回、捕获或处理。
184
+
185
+ 安装完成后可检查:
186
+
187
+ ```bash
188
+ hermes memory status
189
+ ```
190
+
191
+ 正常重启 Hermes 后,原生 Provider 和 MCP 应分别显示可用。安装脚本只在 Hermes 可执行文件存在时修改 Hermes 配置;没有 Hermes 时会跳过该部分并给出提示。
192
+
193
+ ## MCP Server
194
+
195
+ 直接运行本地 stdio Server:
196
+
197
+ ```bash
198
+ memleaf-mcp --vault "$HOME/.memleaf"
199
+ ```
200
+
201
+ 也可以使用模块入口:
202
+
203
+ ```bash
204
+ python -m memleaf.mcp_server --vault "$HOME/.memleaf"
205
+ ```
206
+
207
+ 不传 `--vault` 时默认使用 `~/.memleaf`;也可以设置 `MEMLEAF_VAULT`。正常情况下不需要手工常驻,Hermes 会按需启动它。stdout 只输出 JSON-RPC,日志不会污染协议通道。
208
+
209
+ 当前提供 11 个工具:
210
+
211
+ | 工具 | 用途 |
212
+ | --- | --- |
213
+ | `capture` | 捕获一条明确传入的可见对话事件到 inbox |
214
+ | `context` | 旧版兼容的有界轻量目录,不用于 v2 自动注入 |
215
+ | `scope_catalog` | 返回 Scope、父级和别名,不返回具体记忆正文 |
216
+ | `search` | 返回有界候选目录和 `found`/`no_match` 状态 |
217
+ | `read` | 使用当前 `retrieval_id` 分页读取选中的记忆正文 |
218
+ | `process` | 处理完整 inbox 轮次并按准入规则提炼 |
219
+ | `remember` | 用户明确要求时创建或更新记忆 |
220
+ | `forget_memory` | 按精确 ID 删除一条记忆 |
221
+ | `forget_about` | 忘记明确主题;有歧义时只返回候选 |
222
+ | `rebuild_index` | 重建可重建的本地派生索引 |
223
+ | `stats` | 返回 Vault 计数和诊断统计 |
224
+
225
+ `search` 的候选只是线索,标题不能单独作为事实依据。受管理检索必须使用同一轮的 `retrieval_id` 完成 `search → read`;工具错误、Scope 冲突或读取预算耗尽都应如实处理。
226
+
227
+ ## Python API
228
+
229
+ 核心库没有第三方运行时依赖:
230
+
231
+ ```python
232
+ from pathlib import Path
233
+
234
+ from memleaf import Memleaf
235
+
236
+ service = Memleaf.initialize(Path("~/.memleaf").expanduser())
237
+
238
+ memory = service.create_memory(
239
+ title="用户偏好",
240
+ body="用户偏好使用本地 Markdown 保存长期记忆。",
241
+ tags=["preference", "memleaf"],
242
+ scopes=["global"],
243
+ type="preference",
244
+ )
245
+
246
+ for item in service.search("Markdown"):
247
+ print(item.memory_id, item.title)
248
+ ```
249
+
250
+ 常用接口:
251
+
252
+ ```text
253
+ capture() 捕获可见事件
254
+ process() 处理完整 inbox 轮次,需要模型路由
255
+ remember() 显式保存,需要模型路由
256
+ create_memory() 直接创建一条 Markdown 记忆
257
+ search() 本地检索,不更新命中统计
258
+ context() 兼容接口,返回轻量目录
259
+ read() / read_page() 读取记忆或分页正文
260
+ forget_memory()
261
+ forget_about()
262
+ rebuild_index()
263
+ stats()
264
+ compact() 按阈值整理低优先级记忆,需要模型路由
265
+ ```
266
+
267
+ 离线示例默认使用临时 Vault,不写入 `~/.memleaf`,也不访问网络:
268
+
269
+ ```bash
270
+ python examples/basic_usage.py
271
+ python examples/basic_usage.py --vault /path/to/your/vault
272
+ ```
273
+
274
+ MCP stdio 示例:
275
+
276
+ ```bash
277
+ python -m memleaf.mcp_server --vault /path/to/your/vault \
278
+ < examples/mcp_stdio.ndjson
279
+ ```
280
+
281
+ ## 模型路由
282
+
283
+ 捕获、索引、目录检索和读取可离线运行;`process()`、`remember()` 和 `compact()` 需要可用的模型能力。
284
+
285
+ `llm.mode` 支持:
286
+
287
+ - `auto`:优先使用显式注入的 host backend,失败后回退到完整 API 路由;
288
+ - `host`:只使用 Python API 显式传入的宿主回调;
289
+ - `api`:只使用本地配置的 HTTP API。
290
+
291
+ `memleaf init` 仅从 Hermes 的可读取配置中寻找完整的聊天模型路由,过滤非聊天模型,并确定性选择轻量模型作为提炼模型。未发现可用路由时复用已有的有效 memleaf 配置;要保留自选路由并跳过扫描,使用 `--no-model-discovery`。不能调用的 OAuth-only 或只有模型名的配置不会被误判为可用。
292
+
293
+ API 配置示例:
294
+
295
+ ```yaml
296
+ llm:
297
+ mode: api
298
+ provider: deepseek
299
+ protocol: openai
300
+ base_url: https://api.deepseek.com/v1
301
+ api_key: your-api-key
302
+ model: your-chat-model
303
+ request_timeout: 120
304
+ diagnostic_logging: false
305
+ ```
306
+
307
+ 也兼容 `api_key_env` 配置。当前新路由可以把 API key 直接写入 Vault 的 `config.yaml`;文件权限为 `0600`,日志和状态输出不会打印 key。若使用第三方或云端模型,提炼所需的输入会按用户选择的模型调用链发送;这不是 memleaf 的云同步。
308
+
309
+ 支持的 HTTP 协议包括 OpenAI Chat Completions、Claude Messages、Gemini `generateContent` 及对应兼容端点。
310
+
311
+ `llm.diagnostic_logging` 默认关闭。开启后只写入有界的结构统计,不保存 prompt、模型正文、字段值、密钥、URL 或异常正文。
312
+
313
+ ## 原生记忆源
314
+
315
+ 可以在 `config.yaml` 中声明 Agent 自己维护的文本或 Markdown 文件作为只读原生源:
316
+
317
+ ```yaml
318
+ native_sources:
319
+ hermes_notes:
320
+ agent: hermes
321
+ path: /absolute/path/to/hermes-notes.md
322
+ share: true
323
+ enabled: true
324
+ format: markdown
325
+ ```
326
+
327
+ 规则如下:
328
+
329
+ - 原生文件是源事实,memleaf 不修改它,也不会默认复制到 `knowledge/`;
330
+ - 每个源必须是唯一文件,当前单文件上限为 5 MiB;
331
+ - `share: true` 时允许其他 Agent 读取;否则仅源所属 Agent 可访问;
332
+ - memleaf 建立有界索引,读取正文前会重新校验源文件当前内容;
333
+ - 文件内容变化后会刷新索引,失效或缺失不会伪造旧正文。
334
+
335
+ ## Vault 目录
336
+
337
+ 默认 Vault 是 `$HOME/.memleaf`,也可以通过 `--vault` 或配置指定本地目录:
338
+
339
+ ```text
340
+ $HOME/.memleaf/
341
+ ├── config.yaml # Vault、Agent、模型和处理配置
342
+ ├── README.md # Vault 说明
343
+ ├── inbox/ # 脱敏后的原始可见对话捕获
344
+ │ └── <source>/<session>.md
345
+ ├── knowledge/ # 当前有效记忆,Markdown 是事实来源
346
+ │ └── <memory_id>.md
347
+ ├── history/ # 更新或压缩前的历史版本
348
+ │ └── <memory_id>--<version>.md
349
+ ├── _index/
350
+ │ ├── tags.json # 标签、别名、关键词和链接索引
351
+ │ ├── processed.json # 处理水位和幂等状态
352
+ │ ├── native_sources.json # 原生源只读索引
353
+ │ ├── agents.json # 宿主检测和配置状态
354
+ │ ├── host_ingest.json # 宿主生命周期游标
355
+ │ ├── retrieval_gate.json # 有界检索轮次账本,不含查询或正文
356
+ │ ├── retrieval_gate.lock
357
+ │ ├── vault.lock
358
+ │ └── compaction.json # 压缩事务恢复账本
359
+ └── logs/ # 仅 diagnostic_logging=true 时创建
360
+ └── model-diagnostics.jsonl # 有界结构诊断,不含模型正文
361
+ ```
362
+
363
+ `knowledge/` 和 `history/` 是可读数据;`_index/` 主要是派生索引或运行状态。删除或直接修改 `_index/` 可能丢失处理水位、Hook 游标或当前检索账本;需要重建时优先使用 `rebuild_index()`。
364
+
365
+ 默认目录尽量使用 `0700`,文件默认明文保存。memleaf 没有内置加密层,请自行保护 Vault、备份和模型调用凭证。
366
+
367
+ ## 隐私与安全边界
368
+
369
+ - 捕获默认只接收调用方明确传入的 user/assistant 可见文本;不捕获 system prompt、developer prompt、隐藏推理、原始工具输出或附件全文;
370
+ - 捕获落盘前尽力脱敏常见 API key、Bearer token、Cookie、JWT 和私钥,但脱敏不是加密,也不能保证识别所有敏感信息;
371
+ - 路径校验、符号链接检查、Vault 锁、同目录临时文件、fsync 和原子替换用于保护本地写入;
372
+ - memleaf 不主动上传整个 Vault,也没有托管后台、遥测或账号系统;
373
+ - 选择 API/云端模型后,模型处理输入会离开本机并发送给该提供方;
374
+ - 旧版 `context()` 或无宿主绑定的客户端只能获得单页边界,不能宣称 v2 的跨轮硬预算。
375
+
376
+ ## 开发与验证
377
+
378
+ 要求 Python 3.11+。本地运行测试:
379
+
380
+ ```bash
381
+ PYTHONPATH=src python3.11 -m unittest discover -s tests -p 'test_*.py' -v
382
+ python3.11 -m compileall -q src tests examples
383
+ git diff --check
384
+ ```
385
+
386
+ GitHub Actions 已配置 Python 3.11、3.12、3.13 测试,以及 wheel/source distribution 构建和源码包独立测试;配置不等于远端运行已通过。构建发行包需要 `build`:
387
+
388
+ ```bash
389
+ python -m pip install build
390
+ python -m build --wheel --sdist
391
+ ```
392
+
393
+ ## 后续计划
394
+
395
+ - **v0.2:增加 Codex 支持**,延续共享 Vault、Scope Map 和按需读取的设计。
396
+ - 后续将逐步支持更多 Agent 工具;每个宿主遵循其官方接入与授权规范,通过验收后再开放。
397
+ - 这些是后续计划,不属于 v0.1 已交付能力,暂不承诺具体日期。
398
+
399
+ ## 当前边界
400
+
401
+ 以下内容不应被 README 或安装结果误解为已交付能力:
402
+
403
+ - 尚未发布 PyPI 正式包;
404
+ - v0.1 仅支持 Hermes;Codex 和 Antigravity(反重力)不检测、不安装、不配置;
405
+ - Hermes 的检索门控是 Soft Gate,不保证阻止所有未检索回答;
406
+ - 没有模型路由时只能捕获和检索,不能完成自动提炼、显式记忆或压缩;
407
+ - 真实宿主长期运行效果仍取决于本机 Agent 版本、配置、重启和模型可用性;
408
+ - 不提供 Obsidian 插件、Web 管理界面、云同步或透明加密层;
409
+ - `history/` 的批量清理不会被普通检索自动执行,删除操作需要明确调用维护接口。
410
+
411
+ 设计和阶段性实施记录:
412
+
413
+ - [v0.1 发布检查](RELEASE_CHECKLIST.md)
414
+ - [V2 实施计划](V2_IMPLEMENTATION_PLAN.md)
415
+ - [历史实现计划](IMPLEMENTATION_PLAN.md)
416
+ - [示例说明](examples/README.md)
417
+
418
+ ## License
419
+
420
+ MIT,见 [LICENSE](LICENSE)。
421
+
422
+ **memleaf**
423
+ *Your memories, in files you own.*