memleaf 0.2.20__tar.gz → 0.2.22__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.22}/CHANGELOG.md +20 -0
- {memleaf-0.2.20/src/memleaf.egg-info → memleaf-0.2.22}/PKG-INFO +3 -3
- {memleaf-0.2.20 → memleaf-0.2.22}/README.en.md +8 -7
- {memleaf-0.2.20 → memleaf-0.2.22}/README.md +2 -2
- {memleaf-0.2.20 → memleaf-0.2.22}/pyproject.toml +1 -1
- {memleaf-0.2.20 → memleaf-0.2.22}/src/memleaf/__init__.py +1 -1
- {memleaf-0.2.20 → memleaf-0.2.22}/src/memleaf/adapters/hermes.py +3 -2
- {memleaf-0.2.20 → memleaf-0.2.22}/src/memleaf/hermes_provider/__init__.py +8 -2
- {memleaf-0.2.20 → memleaf-0.2.22}/src/memleaf/hermes_provider/plugin.yaml +1 -1
- {memleaf-0.2.20 → memleaf-0.2.22}/src/memleaf/installer.py +7 -4
- {memleaf-0.2.20 → memleaf-0.2.22}/src/memleaf/processing.py +509 -46
- {memleaf-0.2.20 → memleaf-0.2.22}/src/memleaf/validation.py +2 -1
- {memleaf-0.2.20 → memleaf-0.2.22/src/memleaf.egg-info}/PKG-INFO +3 -3
- {memleaf-0.2.20 → memleaf-0.2.22}/tests/test_hermes_provider.py +5 -0
- {memleaf-0.2.20 → memleaf-0.2.22}/tests/test_pypi_install.py +9 -2
- {memleaf-0.2.20 → memleaf-0.2.22}/tests/test_stage_c1_mcp.py +1 -1
- {memleaf-0.2.20 → memleaf-0.2.22}/tests/test_stage_c3_packaging.py +1 -1
- {memleaf-0.2.20 → memleaf-0.2.22}/tests/test_todo_state_recovery.py +126 -0
- {memleaf-0.2.20 → memleaf-0.2.22}/tests/test_update_target_recovery.py +134 -0
- {memleaf-0.2.20 → memleaf-0.2.22}/IMPLEMENTATION_PLAN.md +0 -0
- {memleaf-0.2.20 → memleaf-0.2.22}/LICENSE +0 -0
- {memleaf-0.2.20 → memleaf-0.2.22}/MANIFEST.in +0 -0
- {memleaf-0.2.20 → memleaf-0.2.22}/RELEASE_CHECKLIST.md +0 -0
- {memleaf-0.2.20 → memleaf-0.2.22}/examples/README.md +0 -0
- {memleaf-0.2.20 → memleaf-0.2.22}/examples/basic_usage.py +0 -0
- {memleaf-0.2.20 → memleaf-0.2.22}/examples/mcp_stdio.ndjson +0 -0
- {memleaf-0.2.20 → memleaf-0.2.22}/install.ps1 +0 -0
- {memleaf-0.2.20 → memleaf-0.2.22}/install.sh +0 -0
- {memleaf-0.2.20 → memleaf-0.2.22}/setup.cfg +0 -0
- {memleaf-0.2.20 → memleaf-0.2.22}/src/memleaf/__main__.py +0 -0
- {memleaf-0.2.20 → memleaf-0.2.22}/src/memleaf/adapters/__init__.py +0 -0
- {memleaf-0.2.20 → memleaf-0.2.22}/src/memleaf/adapters/antigravity.py +0 -0
- {memleaf-0.2.20 → memleaf-0.2.22}/src/memleaf/adapters/base.py +0 -0
- {memleaf-0.2.20 → memleaf-0.2.22}/src/memleaf/adapters/codex.py +0 -0
- {memleaf-0.2.20 → memleaf-0.2.22}/src/memleaf/budget.py +0 -0
- {memleaf-0.2.20 → memleaf-0.2.22}/src/memleaf/capture.py +0 -0
- {memleaf-0.2.20 → memleaf-0.2.22}/src/memleaf/cli.py +0 -0
- {memleaf-0.2.20 → memleaf-0.2.22}/src/memleaf/compaction.py +0 -0
- {memleaf-0.2.20 → memleaf-0.2.22}/src/memleaf/config.py +0 -0
- {memleaf-0.2.20 → memleaf-0.2.22}/src/memleaf/credentials.py +0 -0
- {memleaf-0.2.20 → memleaf-0.2.22}/src/memleaf/frontmatter.py +0 -0
- {memleaf-0.2.20 → memleaf-0.2.22}/src/memleaf/hermes_provider/README.md +0 -0
- {memleaf-0.2.20 → memleaf-0.2.22}/src/memleaf/host_events.py +0 -0
- {memleaf-0.2.20 → memleaf-0.2.22}/src/memleaf/host_runtime.py +0 -0
- {memleaf-0.2.20 → memleaf-0.2.22}/src/memleaf/inbox.py +0 -0
- {memleaf-0.2.20 → memleaf-0.2.22}/src/memleaf/index.py +0 -0
- {memleaf-0.2.20 → memleaf-0.2.22}/src/memleaf/llm/__init__.py +0 -0
- {memleaf-0.2.20 → memleaf-0.2.22}/src/memleaf/llm/base.py +0 -0
- {memleaf-0.2.20 → memleaf-0.2.22}/src/memleaf/llm/claude_compatible.py +0 -0
- {memleaf-0.2.20 → memleaf-0.2.22}/src/memleaf/llm/gemini.py +0 -0
- {memleaf-0.2.20 → memleaf-0.2.22}/src/memleaf/llm/openai_compatible.py +0 -0
- {memleaf-0.2.20 → memleaf-0.2.22}/src/memleaf/llm/router.py +0 -0
- {memleaf-0.2.20 → memleaf-0.2.22}/src/memleaf/locking.py +0 -0
- {memleaf-0.2.20 → memleaf-0.2.22}/src/memleaf/mcp_server.py +0 -0
- {memleaf-0.2.20 → memleaf-0.2.22}/src/memleaf/memory_writer.py +0 -0
- {memleaf-0.2.20 → memleaf-0.2.22}/src/memleaf/model_discovery.py +0 -0
- {memleaf-0.2.20 → memleaf-0.2.22}/src/memleaf/models.py +0 -0
- {memleaf-0.2.20 → memleaf-0.2.22}/src/memleaf/native_index.py +0 -0
- {memleaf-0.2.20 → memleaf-0.2.22}/src/memleaf/native_registration.py +0 -0
- {memleaf-0.2.20 → memleaf-0.2.22}/src/memleaf/prompts.py +0 -0
- {memleaf-0.2.20 → memleaf-0.2.22}/src/memleaf/redaction.py +0 -0
- {memleaf-0.2.20 → memleaf-0.2.22}/src/memleaf/retrieval.py +0 -0
- {memleaf-0.2.20 → memleaf-0.2.22}/src/memleaf/retrieval_gate.py +0 -0
- {memleaf-0.2.20 → memleaf-0.2.22}/src/memleaf/scope_maintenance.py +0 -0
- {memleaf-0.2.20 → memleaf-0.2.22}/src/memleaf/scope_state.py +0 -0
- {memleaf-0.2.20 → memleaf-0.2.22}/src/memleaf/service.py +0 -0
- {memleaf-0.2.20 → memleaf-0.2.22}/src/memleaf/vault.py +0 -0
- {memleaf-0.2.20 → memleaf-0.2.22}/src/memleaf.egg-info/SOURCES.txt +0 -0
- {memleaf-0.2.20 → memleaf-0.2.22}/src/memleaf.egg-info/dependency_links.txt +0 -0
- {memleaf-0.2.20 → memleaf-0.2.22}/src/memleaf.egg-info/entry_points.txt +0 -0
- {memleaf-0.2.20 → memleaf-0.2.22}/src/memleaf.egg-info/top_level.txt +0 -0
- {memleaf-0.2.20 → memleaf-0.2.22}/tests/__init__.py +0 -0
- {memleaf-0.2.20 → memleaf-0.2.22}/tests/test_admission_noise.py +0 -0
- {memleaf-0.2.20 → memleaf-0.2.22}/tests/test_codex_install.py +0 -0
- {memleaf-0.2.20 → memleaf-0.2.22}/tests/test_codex_native_cli.py +0 -0
- {memleaf-0.2.20 → memleaf-0.2.22}/tests/test_context_budget.py +0 -0
- {memleaf-0.2.20 → memleaf-0.2.22}/tests/test_credential_safety.py +0 -0
- {memleaf-0.2.20 → memleaf-0.2.22}/tests/test_cross_host_acceptance.py +0 -0
- {memleaf-0.2.20 → memleaf-0.2.22}/tests/test_cross_turn_dedupe_regressions.py +0 -0
- {memleaf-0.2.20 → memleaf-0.2.22}/tests/test_extraction_quality_regressions.py +0 -0
- {memleaf-0.2.20 → memleaf-0.2.22}/tests/test_global_todo_acceptance.py +0 -0
- {memleaf-0.2.20 → memleaf-0.2.22}/tests/test_global_todo_retrieval.py +0 -0
- {memleaf-0.2.20 → memleaf-0.2.22}/tests/test_hermes_native_registration.py +0 -0
- {memleaf-0.2.20 → memleaf-0.2.22}/tests/test_hermes_stdio_transport.py +0 -0
- {memleaf-0.2.20 → memleaf-0.2.22}/tests/test_host_events.py +0 -0
- {memleaf-0.2.20 → memleaf-0.2.22}/tests/test_host_runtime_contract.py +0 -0
- {memleaf-0.2.20 → memleaf-0.2.22}/tests/test_install.py +0 -0
- {memleaf-0.2.20 → memleaf-0.2.22}/tests/test_maintenance_v2.py +0 -0
- {memleaf-0.2.20 → memleaf-0.2.22}/tests/test_model_discovery.py +0 -0
- {memleaf-0.2.20 → memleaf-0.2.22}/tests/test_retrieval_gate.py +0 -0
- {memleaf-0.2.20 → memleaf-0.2.22}/tests/test_retrieval_v2.py +0 -0
- {memleaf-0.2.20 → memleaf-0.2.22}/tests/test_session_lineage.py +0 -0
- {memleaf-0.2.20 → memleaf-0.2.22}/tests/test_stage_a.py +0 -0
- {memleaf-0.2.20 → memleaf-0.2.22}/tests/test_stage_b1.py +0 -0
- {memleaf-0.2.20 → memleaf-0.2.22}/tests/test_stage_b2a.py +0 -0
- {memleaf-0.2.20 → memleaf-0.2.22}/tests/test_stage_b2b.py +0 -0
- {memleaf-0.2.20 → memleaf-0.2.22}/tests/test_stage_b3a_commit.py +0 -0
- {memleaf-0.2.20 → memleaf-0.2.22}/tests/test_stage_b3a_contract.py +0 -0
- {memleaf-0.2.20 → memleaf-0.2.22}/tests/test_stage_b3b_native_context.py +0 -0
- {memleaf-0.2.20 → memleaf-0.2.22}/tests/test_stage_b3b_native_index.py +0 -0
- {memleaf-0.2.20 → memleaf-0.2.22}/tests/test_stage_b3b_scope.py +0 -0
- {memleaf-0.2.20 → memleaf-0.2.22}/tests/test_stage_b3c_retrieval.py +0 -0
- {memleaf-0.2.20 → memleaf-0.2.22}/tests/test_stage_b3d_scope_maintenance.py +0 -0
- {memleaf-0.2.20 → memleaf-0.2.22}/tests/test_stage_c2_init.py +0 -0
- {memleaf-0.2.20 → memleaf-0.2.22}/tests/test_upgrade_preserves_vault.py +0 -0
- {memleaf-0.2.20 → memleaf-0.2.22}/tests/test_v2_gate_limits.py +0 -0
- {memleaf-0.2.20 → memleaf-0.2.22}/tests/test_v2_host_flow.py +0 -0
- {memleaf-0.2.20 → memleaf-0.2.22}/tests/test_v2_mcp_flow.py +0 -0
- {memleaf-0.2.20 → memleaf-0.2.22}/tests/test_v2_nomatch_semantics.py +0 -0
- {memleaf-0.2.20 → memleaf-0.2.22}/tests/test_v2_search_gate_acceptance.py +0 -0
|
@@ -2,6 +2,26 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to memleaf are documented here.
|
|
4
4
|
|
|
5
|
+
## 0.2.22 — 2026-09-03
|
|
6
|
+
|
|
7
|
+
- Safely split valid multi-project `unscoped` aggregate candidates using only
|
|
8
|
+
project names grounded in each candidate, so one ambiguous fragment no
|
|
9
|
+
longer blocks valid project-local siblings.
|
|
10
|
+
- Persist explicit completion of an existing todo separately from new
|
|
11
|
+
customer rework, preserving immutable targets and making replay idempotent.
|
|
12
|
+
- Require declarative completion language before closing todos, avoiding false
|
|
13
|
+
completion for future actions such as needing to submit, waiting for
|
|
14
|
+
feedback, or being asked to send materials.
|
|
15
|
+
- Keep Hermes from claiming permanent persistence before automatic processing
|
|
16
|
+
succeeds; only a successful explicit remember/update result authorizes that
|
|
17
|
+
claim.
|
|
18
|
+
|
|
19
|
+
## 0.2.21 — 2026-09-03
|
|
20
|
+
|
|
21
|
+
- 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`.
|
|
22
|
+
- 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.
|
|
23
|
+
- Correct the English README's stale 11-tool and 3-memory/6000-character descriptions so the published documentation matches the v0.2 retrieval contract.
|
|
24
|
+
|
|
5
25
|
## 0.2.20 — 2026-09-03
|
|
6
26
|
|
|
7
27
|
- 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.22
|
|
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.22。**
|
|
27
|
+
> 核心库、Vault、stdio MCP Server、初始化 CLI、模型路由、提炼流程、受控检索协议和宿主适配器已经实现。memleaf 0.2.22 通过 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.22.**
|
|
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.22 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.22。**
|
|
8
|
+
> 核心库、Vault、stdio MCP Server、初始化 CLI、模型路由、提炼流程、受控检索协议和宿主适配器已经实现。memleaf 0.2.22 通过 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.22"
|
|
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
|
|
|
@@ -1964,8 +1964,14 @@ class MemleafMemoryProvider(MemoryProvider):
|
|
|
1964
1964
|
"observer only: do not claim a search happened unless the visible tool "
|
|
1965
1965
|
"messages show it. Visible Hermes "
|
|
1966
1966
|
"turns are durably captured into the local memleaf inbox. Automatic "
|
|
1967
|
-
"capture → process
|
|
1968
|
-
"
|
|
1967
|
+
"capture → process runs after your final answer and is authoritative: "
|
|
1968
|
+
"a capture only proves that the inbox received the turn. Until a "
|
|
1969
|
+
"successful explicit remember or update tool result is visible, never "
|
|
1970
|
+
"say that the turn was saved to permanent memory, persisted, or "
|
|
1971
|
+
"记好了/已落库. For automatic handling, say only that you will process "
|
|
1972
|
+
"it through the workflow or that it is recorded in the current "
|
|
1973
|
+
"conversation. If process fails, report that automatic processing "
|
|
1974
|
+
"failed and leave the inbox retryable. Do not use "
|
|
1969
1975
|
"terminal, search_files, read_file, Python, or direct filesystem "
|
|
1970
1976
|
"operations to search or read the memleaf Vault; those tools remain "
|
|
1971
1977
|
"available for ordinary project/wiki files. Do not use direct vault "
|
|
@@ -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),
|