memleaf 0.2.20__tar.gz → 0.2.21__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.
- {memleaf-0.2.20 → memleaf-0.2.21}/CHANGELOG.md +6 -0
- {memleaf-0.2.20/src/memleaf.egg-info → memleaf-0.2.21}/PKG-INFO +3 -3
- {memleaf-0.2.20 → memleaf-0.2.21}/README.en.md +8 -7
- {memleaf-0.2.20 → memleaf-0.2.21}/README.md +2 -2
- {memleaf-0.2.20 → memleaf-0.2.21}/pyproject.toml +1 -1
- {memleaf-0.2.20 → memleaf-0.2.21}/src/memleaf/__init__.py +1 -1
- {memleaf-0.2.20 → memleaf-0.2.21}/src/memleaf/adapters/hermes.py +3 -2
- {memleaf-0.2.20 → memleaf-0.2.21}/src/memleaf/hermes_provider/plugin.yaml +1 -1
- {memleaf-0.2.20 → memleaf-0.2.21}/src/memleaf/installer.py +7 -4
- {memleaf-0.2.20 → memleaf-0.2.21/src/memleaf.egg-info}/PKG-INFO +3 -3
- {memleaf-0.2.20 → memleaf-0.2.21}/tests/test_pypi_install.py +9 -2
- {memleaf-0.2.20 → memleaf-0.2.21}/tests/test_stage_c1_mcp.py +1 -1
- {memleaf-0.2.20 → memleaf-0.2.21}/tests/test_stage_c3_packaging.py +1 -1
- {memleaf-0.2.20 → memleaf-0.2.21}/IMPLEMENTATION_PLAN.md +0 -0
- {memleaf-0.2.20 → memleaf-0.2.21}/LICENSE +0 -0
- {memleaf-0.2.20 → memleaf-0.2.21}/MANIFEST.in +0 -0
- {memleaf-0.2.20 → memleaf-0.2.21}/RELEASE_CHECKLIST.md +0 -0
- {memleaf-0.2.20 → memleaf-0.2.21}/examples/README.md +0 -0
- {memleaf-0.2.20 → memleaf-0.2.21}/examples/basic_usage.py +0 -0
- {memleaf-0.2.20 → memleaf-0.2.21}/examples/mcp_stdio.ndjson +0 -0
- {memleaf-0.2.20 → memleaf-0.2.21}/install.ps1 +0 -0
- {memleaf-0.2.20 → memleaf-0.2.21}/install.sh +0 -0
- {memleaf-0.2.20 → memleaf-0.2.21}/setup.cfg +0 -0
- {memleaf-0.2.20 → memleaf-0.2.21}/src/memleaf/__main__.py +0 -0
- {memleaf-0.2.20 → memleaf-0.2.21}/src/memleaf/adapters/__init__.py +0 -0
- {memleaf-0.2.20 → memleaf-0.2.21}/src/memleaf/adapters/antigravity.py +0 -0
- {memleaf-0.2.20 → memleaf-0.2.21}/src/memleaf/adapters/base.py +0 -0
- {memleaf-0.2.20 → memleaf-0.2.21}/src/memleaf/adapters/codex.py +0 -0
- {memleaf-0.2.20 → memleaf-0.2.21}/src/memleaf/budget.py +0 -0
- {memleaf-0.2.20 → memleaf-0.2.21}/src/memleaf/capture.py +0 -0
- {memleaf-0.2.20 → memleaf-0.2.21}/src/memleaf/cli.py +0 -0
- {memleaf-0.2.20 → memleaf-0.2.21}/src/memleaf/compaction.py +0 -0
- {memleaf-0.2.20 → memleaf-0.2.21}/src/memleaf/config.py +0 -0
- {memleaf-0.2.20 → memleaf-0.2.21}/src/memleaf/credentials.py +0 -0
- {memleaf-0.2.20 → memleaf-0.2.21}/src/memleaf/frontmatter.py +0 -0
- {memleaf-0.2.20 → memleaf-0.2.21}/src/memleaf/hermes_provider/README.md +0 -0
- {memleaf-0.2.20 → memleaf-0.2.21}/src/memleaf/hermes_provider/__init__.py +0 -0
- {memleaf-0.2.20 → memleaf-0.2.21}/src/memleaf/host_events.py +0 -0
- {memleaf-0.2.20 → memleaf-0.2.21}/src/memleaf/host_runtime.py +0 -0
- {memleaf-0.2.20 → memleaf-0.2.21}/src/memleaf/inbox.py +0 -0
- {memleaf-0.2.20 → memleaf-0.2.21}/src/memleaf/index.py +0 -0
- {memleaf-0.2.20 → memleaf-0.2.21}/src/memleaf/llm/__init__.py +0 -0
- {memleaf-0.2.20 → memleaf-0.2.21}/src/memleaf/llm/base.py +0 -0
- {memleaf-0.2.20 → memleaf-0.2.21}/src/memleaf/llm/claude_compatible.py +0 -0
- {memleaf-0.2.20 → memleaf-0.2.21}/src/memleaf/llm/gemini.py +0 -0
- {memleaf-0.2.20 → memleaf-0.2.21}/src/memleaf/llm/openai_compatible.py +0 -0
- {memleaf-0.2.20 → memleaf-0.2.21}/src/memleaf/llm/router.py +0 -0
- {memleaf-0.2.20 → memleaf-0.2.21}/src/memleaf/locking.py +0 -0
- {memleaf-0.2.20 → memleaf-0.2.21}/src/memleaf/mcp_server.py +0 -0
- {memleaf-0.2.20 → memleaf-0.2.21}/src/memleaf/memory_writer.py +0 -0
- {memleaf-0.2.20 → memleaf-0.2.21}/src/memleaf/model_discovery.py +0 -0
- {memleaf-0.2.20 → memleaf-0.2.21}/src/memleaf/models.py +0 -0
- {memleaf-0.2.20 → memleaf-0.2.21}/src/memleaf/native_index.py +0 -0
- {memleaf-0.2.20 → memleaf-0.2.21}/src/memleaf/native_registration.py +0 -0
- {memleaf-0.2.20 → memleaf-0.2.21}/src/memleaf/processing.py +0 -0
- {memleaf-0.2.20 → memleaf-0.2.21}/src/memleaf/prompts.py +0 -0
- {memleaf-0.2.20 → memleaf-0.2.21}/src/memleaf/redaction.py +0 -0
- {memleaf-0.2.20 → memleaf-0.2.21}/src/memleaf/retrieval.py +0 -0
- {memleaf-0.2.20 → memleaf-0.2.21}/src/memleaf/retrieval_gate.py +0 -0
- {memleaf-0.2.20 → memleaf-0.2.21}/src/memleaf/scope_maintenance.py +0 -0
- {memleaf-0.2.20 → memleaf-0.2.21}/src/memleaf/scope_state.py +0 -0
- {memleaf-0.2.20 → memleaf-0.2.21}/src/memleaf/service.py +0 -0
- {memleaf-0.2.20 → memleaf-0.2.21}/src/memleaf/validation.py +0 -0
- {memleaf-0.2.20 → memleaf-0.2.21}/src/memleaf/vault.py +0 -0
- {memleaf-0.2.20 → memleaf-0.2.21}/src/memleaf.egg-info/SOURCES.txt +0 -0
- {memleaf-0.2.20 → memleaf-0.2.21}/src/memleaf.egg-info/dependency_links.txt +0 -0
- {memleaf-0.2.20 → memleaf-0.2.21}/src/memleaf.egg-info/entry_points.txt +0 -0
- {memleaf-0.2.20 → memleaf-0.2.21}/src/memleaf.egg-info/top_level.txt +0 -0
- {memleaf-0.2.20 → memleaf-0.2.21}/tests/__init__.py +0 -0
- {memleaf-0.2.20 → memleaf-0.2.21}/tests/test_admission_noise.py +0 -0
- {memleaf-0.2.20 → memleaf-0.2.21}/tests/test_codex_install.py +0 -0
- {memleaf-0.2.20 → memleaf-0.2.21}/tests/test_codex_native_cli.py +0 -0
- {memleaf-0.2.20 → memleaf-0.2.21}/tests/test_context_budget.py +0 -0
- {memleaf-0.2.20 → memleaf-0.2.21}/tests/test_credential_safety.py +0 -0
- {memleaf-0.2.20 → memleaf-0.2.21}/tests/test_cross_host_acceptance.py +0 -0
- {memleaf-0.2.20 → memleaf-0.2.21}/tests/test_cross_turn_dedupe_regressions.py +0 -0
- {memleaf-0.2.20 → memleaf-0.2.21}/tests/test_extraction_quality_regressions.py +0 -0
- {memleaf-0.2.20 → memleaf-0.2.21}/tests/test_global_todo_acceptance.py +0 -0
- {memleaf-0.2.20 → memleaf-0.2.21}/tests/test_global_todo_retrieval.py +0 -0
- {memleaf-0.2.20 → memleaf-0.2.21}/tests/test_hermes_native_registration.py +0 -0
- {memleaf-0.2.20 → memleaf-0.2.21}/tests/test_hermes_provider.py +0 -0
- {memleaf-0.2.20 → memleaf-0.2.21}/tests/test_hermes_stdio_transport.py +0 -0
- {memleaf-0.2.20 → memleaf-0.2.21}/tests/test_host_events.py +0 -0
- {memleaf-0.2.20 → memleaf-0.2.21}/tests/test_host_runtime_contract.py +0 -0
- {memleaf-0.2.20 → memleaf-0.2.21}/tests/test_install.py +0 -0
- {memleaf-0.2.20 → memleaf-0.2.21}/tests/test_maintenance_v2.py +0 -0
- {memleaf-0.2.20 → memleaf-0.2.21}/tests/test_model_discovery.py +0 -0
- {memleaf-0.2.20 → memleaf-0.2.21}/tests/test_retrieval_gate.py +0 -0
- {memleaf-0.2.20 → memleaf-0.2.21}/tests/test_retrieval_v2.py +0 -0
- {memleaf-0.2.20 → memleaf-0.2.21}/tests/test_session_lineage.py +0 -0
- {memleaf-0.2.20 → memleaf-0.2.21}/tests/test_stage_a.py +0 -0
- {memleaf-0.2.20 → memleaf-0.2.21}/tests/test_stage_b1.py +0 -0
- {memleaf-0.2.20 → memleaf-0.2.21}/tests/test_stage_b2a.py +0 -0
- {memleaf-0.2.20 → memleaf-0.2.21}/tests/test_stage_b2b.py +0 -0
- {memleaf-0.2.20 → memleaf-0.2.21}/tests/test_stage_b3a_commit.py +0 -0
- {memleaf-0.2.20 → memleaf-0.2.21}/tests/test_stage_b3a_contract.py +0 -0
- {memleaf-0.2.20 → memleaf-0.2.21}/tests/test_stage_b3b_native_context.py +0 -0
- {memleaf-0.2.20 → memleaf-0.2.21}/tests/test_stage_b3b_native_index.py +0 -0
- {memleaf-0.2.20 → memleaf-0.2.21}/tests/test_stage_b3b_scope.py +0 -0
- {memleaf-0.2.20 → memleaf-0.2.21}/tests/test_stage_b3c_retrieval.py +0 -0
- {memleaf-0.2.20 → memleaf-0.2.21}/tests/test_stage_b3d_scope_maintenance.py +0 -0
- {memleaf-0.2.20 → memleaf-0.2.21}/tests/test_stage_c2_init.py +0 -0
- {memleaf-0.2.20 → memleaf-0.2.21}/tests/test_todo_state_recovery.py +0 -0
- {memleaf-0.2.20 → memleaf-0.2.21}/tests/test_update_target_recovery.py +0 -0
- {memleaf-0.2.20 → memleaf-0.2.21}/tests/test_upgrade_preserves_vault.py +0 -0
- {memleaf-0.2.20 → memleaf-0.2.21}/tests/test_v2_gate_limits.py +0 -0
- {memleaf-0.2.20 → memleaf-0.2.21}/tests/test_v2_host_flow.py +0 -0
- {memleaf-0.2.20 → memleaf-0.2.21}/tests/test_v2_mcp_flow.py +0 -0
- {memleaf-0.2.20 → memleaf-0.2.21}/tests/test_v2_nomatch_semantics.py +0 -0
- {memleaf-0.2.20 → memleaf-0.2.21}/tests/test_v2_search_gate_acceptance.py +0 -0
|
@@ -2,6 +2,12 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to memleaf are documented here.
|
|
4
4
|
|
|
5
|
+
## 0.2.21 — 2026-09-03
|
|
6
|
+
|
|
7
|
+
- Fix `memleaf install` for Hermes after the 12th MCP tool was added: the installer now uses the adapter's canonical tool-count constant instead of a stale private `11`.
|
|
8
|
+
- Add a regression invariant that compares the Hermes installer count with the actual public MCP tool tuple, preventing future tool additions from silently breaking installation self-checks.
|
|
9
|
+
- Correct the English README's stale 11-tool and 3-memory/6000-character descriptions so the published documentation matches the v0.2 retrieval contract.
|
|
10
|
+
|
|
5
11
|
## 0.2.20 — 2026-09-03
|
|
6
12
|
|
|
7
13
|
- Add `list_todos` for complete active todo retrieval across all scopes with stable pagination, date/status filtering, and current-turn retrieval gating.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: memleaf
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.21
|
|
4
4
|
Summary: A local-first Markdown memory core for AI agents
|
|
5
5
|
Author: memleaf contributors
|
|
6
6
|
License-Expression: MIT
|
|
@@ -23,8 +23,8 @@ Dynamic: license-file
|
|
|
23
23
|
|
|
24
24
|
[English](README.en.md) · [PyPI](https://pypi.org/project/memleaf/) · [GitHub](https://github.com/miffyblueboo/memleaf)
|
|
25
25
|
|
|
26
|
-
> **当前版本:0.2.
|
|
27
|
-
> 核心库、Vault、stdio MCP Server、初始化 CLI、模型路由、提炼流程、受控检索协议和宿主适配器已经实现。memleaf 0.2.
|
|
26
|
+
> **当前版本:0.2.21。**
|
|
27
|
+
> 核心库、Vault、stdio MCP Server、初始化 CLI、模型路由、提炼流程、受控检索协议和宿主适配器已经实现。memleaf 0.2.21 通过 PyPI 分发。
|
|
28
28
|
> **当前版本支持 Hermes 和 Codex。** Antigravity(反重力)不检测、不安装、不配置。
|
|
29
29
|
|
|
30
30
|
## 项目定位
|
|
@@ -4,8 +4,8 @@
|
|
|
4
4
|
|
|
5
5
|
[中文](README.md) · [PyPI](https://pypi.org/project/memleaf/) · [GitHub](https://github.com/miffyblueboo/memleaf)
|
|
6
6
|
|
|
7
|
-
> **Version: 0.2.
|
|
8
|
-
> The core library, Vault, stdio MCP server, initialization CLI, model routing, memory extraction, controlled retrieval protocol, and host adapters are implemented. memleaf 0.2.
|
|
7
|
+
> **Version: 0.2.21.**
|
|
8
|
+
> The core library, Vault, stdio MCP server, initialization CLI, model routing, memory extraction, controlled retrieval protocol, and host adapters are implemented. memleaf 0.2.21 is distributed through PyPI.
|
|
9
9
|
> **The current release supports Hermes and Codex.** Antigravity is not detected, installed, or configured.
|
|
10
10
|
|
|
11
11
|
## Project scope
|
|
@@ -55,7 +55,7 @@ Current limits:
|
|
|
55
55
|
- Scope Map: at most 20 items and approximately 2,000 characters per page;
|
|
56
56
|
- search candidates: at most 20 items and approximately 4,000 characters per page;
|
|
57
57
|
- one read page: at most 2,000 body characters;
|
|
58
|
-
- managed turn:
|
|
58
|
+
- managed turn: all relevant memories may be read; `read_count` and `read_chars` are audit-only and do not block valid reads;
|
|
59
59
|
- `retrieval_id` must belong to the current turn, and a successful `search` is required before `read`;
|
|
60
60
|
- `found`, `no_match`, and tool errors are distinct states; an error must not be reported as no match;
|
|
61
61
|
- `context()` and Python `search(view="full")` remain available for compatibility, but are not part of the automatic retrieval path.
|
|
@@ -141,12 +141,12 @@ Both installation paths automatically:
|
|
|
141
141
|
4. Activate `memory.provider=memleaf`.
|
|
142
142
|
5. Configure the memleaf MCP entry through Hermes' official CLI.
|
|
143
143
|
6. Configure MCP lazy/idle lifecycle settings.
|
|
144
|
-
7. Verify that the MCP server exposes all
|
|
144
|
+
7. Verify that the MCP server exposes all 12 tools.
|
|
145
145
|
8. Record the local Agent integration status.
|
|
146
146
|
|
|
147
147
|
Restart Hermes after installation.
|
|
148
148
|
|
|
149
|
-
If Hermes cannot be detected, no complete model route can be configured, Provider activation fails, or the
|
|
149
|
+
If Hermes cannot be detected, no complete model route can be configured, Provider activation fails, or the 12-tool MCP verification fails, the installer returns an explicit failure rather than reporting an incomplete integration as successful.
|
|
150
150
|
|
|
151
151
|
The repository `install.sh` remains for source development, offline source installation, and troubleshooting. Normal PyPI users do not need to run it.
|
|
152
152
|
|
|
@@ -243,7 +243,7 @@ python -m memleaf.mcp_server --vault "$HOME/.memleaf"
|
|
|
243
243
|
|
|
244
244
|
Without `--vault`, the server uses `~/.memleaf`; `MEMLEAF_VAULT` can also specify the Vault. In normal use the server does not need to be kept running manually: Hermes or Codex starts it on demand. stdout contains only JSON-RPC messages so logs do not corrupt the protocol stream.
|
|
245
245
|
|
|
246
|
-
The server currently exposes
|
|
246
|
+
The server currently exposes 12 tools:
|
|
247
247
|
|
|
248
248
|
| Tool | Purpose |
|
|
249
249
|
| --- | --- |
|
|
@@ -251,6 +251,7 @@ The server currently exposes 11 tools:
|
|
|
251
251
|
| `context` | Compatibility directory; not used by the automatic retrieval path |
|
|
252
252
|
| `scope_catalog` | Return Scopes, parents, and aliases without memory bodies |
|
|
253
253
|
| `search` | Return a bounded candidate directory and `found`/`no_match` status |
|
|
254
|
+
| `list_todos` | Enumerate current todo memories across scopes with status/date filters and pagination |
|
|
254
255
|
| `read` | Read a selected memory body in pages using the current `retrieval_id` |
|
|
255
256
|
| `process` | Process complete inbox turns under the admission rules |
|
|
256
257
|
| `remember` | Create or update memory after an explicit request |
|
|
@@ -259,7 +260,7 @@ The server currently exposes 11 tools:
|
|
|
259
260
|
| `rebuild_index` | Rebuild local derived indexes |
|
|
260
261
|
| `stats` | Return Vault counts and diagnostic statistics |
|
|
261
262
|
|
|
262
|
-
Search results are clues; a title alone is not a business fact. Managed retrieval must use the same `retrieval_id` for `search → read`. Tool errors, Scope conflicts, and
|
|
263
|
+
Search results are clues; a title alone is not a business fact. Managed retrieval must use the same `retrieval_id` for `search → read`. Tool errors, Scope conflicts, retrieval-turn violations, and read page/version errors must be handled as such.
|
|
263
264
|
|
|
264
265
|
## Python API
|
|
265
266
|
|
|
@@ -4,8 +4,8 @@
|
|
|
4
4
|
|
|
5
5
|
[English](README.en.md) · [PyPI](https://pypi.org/project/memleaf/) · [GitHub](https://github.com/miffyblueboo/memleaf)
|
|
6
6
|
|
|
7
|
-
> **当前版本:0.2.
|
|
8
|
-
> 核心库、Vault、stdio MCP Server、初始化 CLI、模型路由、提炼流程、受控检索协议和宿主适配器已经实现。memleaf 0.2.
|
|
7
|
+
> **当前版本:0.2.21。**
|
|
8
|
+
> 核心库、Vault、stdio MCP Server、初始化 CLI、模型路由、提炼流程、受控检索协议和宿主适配器已经实现。memleaf 0.2.21 通过 PyPI 分发。
|
|
9
9
|
> **当前版本支持 Hermes 和 Codex。** Antigravity(反重力)不检测、不安装、不配置。
|
|
10
10
|
|
|
11
11
|
## 项目定位
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"""Local-first Markdown memory core for AI agents."""
|
|
2
2
|
|
|
3
|
-
__version__ = "0.2.
|
|
3
|
+
__version__ = "0.2.21"
|
|
4
4
|
|
|
5
5
|
from .config import DEFAULT_CONFIG, default_config, load_config, save_config
|
|
6
6
|
from .frontmatter import FrontmatterError, dump_frontmatter, dump_yaml, load_yaml, parse_frontmatter
|
|
@@ -24,7 +24,8 @@ from .base import (
|
|
|
24
24
|
|
|
25
25
|
|
|
26
26
|
_MCP_IDLE_TIMEOUT_SECONDS = 60
|
|
27
|
-
|
|
27
|
+
MCP_EXPECTED_TOOL_COUNT = 12
|
|
28
|
+
_MCP_EXPECTED_TOOL_COUNT = MCP_EXPECTED_TOOL_COUNT
|
|
28
29
|
|
|
29
30
|
|
|
30
31
|
def hermes_home_for_platform(
|
|
@@ -417,7 +418,7 @@ class HermesAdapter:
|
|
|
417
418
|
self,
|
|
418
419
|
detection: Detection | None = None,
|
|
419
420
|
*,
|
|
420
|
-
expected_tools: int =
|
|
421
|
+
expected_tools: int = MCP_EXPECTED_TOOL_COUNT,
|
|
421
422
|
) -> bool:
|
|
422
423
|
"""Run the official MCP test and require the expected tool count."""
|
|
423
424
|
|
|
@@ -19,14 +19,17 @@ from typing import Any
|
|
|
19
19
|
from . import __version__
|
|
20
20
|
from .adapters.base import update_agents_index
|
|
21
21
|
from .adapters.codex import CodexAdapter
|
|
22
|
-
from .adapters.hermes import
|
|
22
|
+
from .adapters.hermes import (
|
|
23
|
+
HermesAdapter,
|
|
24
|
+
MCP_EXPECTED_TOOL_COUNT,
|
|
25
|
+
hermes_home_for_platform,
|
|
26
|
+
)
|
|
23
27
|
from .cli import _home_from_environment, _prepare_model_route
|
|
24
28
|
from .locking import atomic_write_json
|
|
25
29
|
from .native_registration import ensure_hermes_native_sources
|
|
26
30
|
from .vault import Vault
|
|
27
31
|
|
|
28
32
|
|
|
29
|
-
_EXPECTED_TOOLS = 11
|
|
30
33
|
_PROVIDER_VERSION_RE = re.compile(r"^version:\s*([^\s#]+)\s*(?:#.*)?$", re.MULTILINE)
|
|
31
34
|
|
|
32
35
|
|
|
@@ -401,14 +404,14 @@ def install_hermes(*, vault_path: Path | None = None) -> dict[str, Any]:
|
|
|
401
404
|
"provider": str(provider_path),
|
|
402
405
|
"model": model,
|
|
403
406
|
}
|
|
404
|
-
if not adapter.test_mcp(detection, expected_tools=
|
|
407
|
+
if not adapter.test_mcp(detection, expected_tools=MCP_EXPECTED_TOOL_COUNT):
|
|
405
408
|
update_agents_index(
|
|
406
409
|
vault.agents_index_path,
|
|
407
410
|
{"hermes": {"mcp_status": "failed", "mcp_availability": "unavailable"}},
|
|
408
411
|
)
|
|
409
412
|
return {
|
|
410
413
|
"status": "failure",
|
|
411
|
-
"reason": "Hermes MCP test did not confirm
|
|
414
|
+
"reason": f"Hermes MCP test did not confirm {MCP_EXPECTED_TOOL_COUNT} tools",
|
|
412
415
|
"core_version": core_version,
|
|
413
416
|
"provider_version": provider_version,
|
|
414
417
|
"vault": str(vault.root),
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: memleaf
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.21
|
|
4
4
|
Summary: A local-first Markdown memory core for AI agents
|
|
5
5
|
Author: memleaf contributors
|
|
6
6
|
License-Expression: MIT
|
|
@@ -23,8 +23,8 @@ Dynamic: license-file
|
|
|
23
23
|
|
|
24
24
|
[English](README.en.md) · [PyPI](https://pypi.org/project/memleaf/) · [GitHub](https://github.com/miffyblueboo/memleaf)
|
|
25
25
|
|
|
26
|
-
> **当前版本:0.2.
|
|
27
|
-
> 核心库、Vault、stdio MCP Server、初始化 CLI、模型路由、提炼流程、受控检索协议和宿主适配器已经实现。memleaf 0.2.
|
|
26
|
+
> **当前版本:0.2.21。**
|
|
27
|
+
> 核心库、Vault、stdio MCP Server、初始化 CLI、模型路由、提炼流程、受控检索协议和宿主适配器已经实现。memleaf 0.2.21 通过 PyPI 分发。
|
|
28
28
|
> **当前版本支持 Hermes 和 Codex。** Antigravity(反重力)不检测、不安装、不配置。
|
|
29
29
|
|
|
30
30
|
## 项目定位
|
|
@@ -8,7 +8,8 @@ import unittest
|
|
|
8
8
|
from unittest import mock
|
|
9
9
|
|
|
10
10
|
from memleaf import __version__, cli
|
|
11
|
-
from memleaf.adapters.hermes import HermesAdapter
|
|
11
|
+
from memleaf.adapters.hermes import HermesAdapter, MCP_EXPECTED_TOOL_COUNT
|
|
12
|
+
from memleaf.mcp_server import _TOOLS
|
|
12
13
|
from memleaf.installer import (
|
|
13
14
|
_copy_provider,
|
|
14
15
|
_hermes_home,
|
|
@@ -21,6 +22,12 @@ from memleaf.installer import (
|
|
|
21
22
|
|
|
22
23
|
|
|
23
24
|
class PyPIInstallTests(unittest.TestCase):
|
|
25
|
+
def test_hermes_installer_tool_count_matches_public_mcp_contract(self) -> None:
|
|
26
|
+
from memleaf import installer
|
|
27
|
+
|
|
28
|
+
self.assertEqual(MCP_EXPECTED_TOOL_COUNT, len(_TOOLS))
|
|
29
|
+
self.assertEqual(installer.MCP_EXPECTED_TOOL_COUNT, len(_TOOLS))
|
|
30
|
+
|
|
24
31
|
def test_packaged_provider_can_be_copied_without_importing_hermes(self) -> None:
|
|
25
32
|
with tempfile.TemporaryDirectory(prefix="memleaf-pypi-provider-") as temporary:
|
|
26
33
|
hermes_home = Path(temporary) / ".hermes"
|
|
@@ -81,7 +88,7 @@ class PyPIInstallTests(unittest.TestCase):
|
|
|
81
88
|
|
|
82
89
|
self.assertTrue(target.is_dir())
|
|
83
90
|
self.assertFalse(target.is_symlink())
|
|
84
|
-
self.assertIn("version: 0.2.
|
|
91
|
+
self.assertIn("version: 0.2.21", (target / "plugin.yaml").read_text(encoding="utf-8"))
|
|
85
92
|
|
|
86
93
|
def test_windows_hermes_paths_follow_official_native_layout(self) -> None:
|
|
87
94
|
with tempfile.TemporaryDirectory(prefix="memleaf-win-paths-") as temporary:
|
|
@@ -104,7 +104,7 @@ class StageC1MCPTest(unittest.TestCase):
|
|
|
104
104
|
testcase.assertEqual(result["resultType"], "complete")
|
|
105
105
|
testcase.assertEqual(
|
|
106
106
|
result["_meta"]["io.modelcontextprotocol/serverInfo"],
|
|
107
|
-
{"name": "memleaf", "version": "0.2.
|
|
107
|
+
{"name": "memleaf", "version": "0.2.21"},
|
|
108
108
|
)
|
|
109
109
|
return result
|
|
110
110
|
|
|
@@ -24,7 +24,7 @@ class StageC3PackagingTests(unittest.TestCase):
|
|
|
24
24
|
|
|
25
25
|
def test_project_metadata_and_version_export(self) -> None:
|
|
26
26
|
self.assertEqual(self.project["name"], "memleaf")
|
|
27
|
-
self.assertEqual(self.project["version"], "0.2.
|
|
27
|
+
self.assertEqual(self.project["version"], "0.2.21")
|
|
28
28
|
self.assertEqual(self.project["requires-python"], ">=3.11")
|
|
29
29
|
self.assertEqual(self.project["dependencies"], [])
|
|
30
30
|
self.assertEqual(self.project["license"], "MIT")
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|