fix(memory): migration checks provider presence in the home being migrated

This commit is contained in:
teknium1
2026-09-18 00:14:45 -07:00
committed by Teknium
parent 5cee761d54
commit ffa105c7ae
2 changed files with 28 additions and 5 deletions

View File

@@ -32,10 +32,17 @@ def configured_provider(home: Path) -> str:
return str(memory.get("provider") or "").strip()
def provider_present(name: str) -> bool:
"""True when the provider resolves anywhere Hermes looks (bundled, user dir, entry point)."""
def provider_present(name: str, home: Path) -> bool:
"""True when the provider resolves anywhere Hermes looks for *home* (bundled, that home's user
plugins, entry point). The lookup reads the active home, so it is bound explicitly: the update
hook walks several profile homes from one process."""
from plugins.memory import find_provider_dir
return find_provider_dir(name) is not None
from hermes_constants import reset_hermes_home_override, set_hermes_home_override
token = set_hermes_home_override(home)
try:
return find_provider_dir(name) is not None
finally:
reset_hermes_home_override(token)
def catalog_source(name: str) -> Optional[str]:
@@ -53,7 +60,7 @@ def migrate_home(home: Path, *, install: Callable[[str], dict], say: Callable[[s
update or the agent down with it.
"""
name = configured_provider(home)
if not name or provider_present(name):
if not name or provider_present(name, home):
return None
if catalog_source(name) is None:
say(f" ⚠ Memory provider '{name}' is configured but not installed and not in the plugin catalog. "

View File

@@ -12,7 +12,7 @@ from hermes_cli import memory_provider_migration as mig
def home(tmp_path, monkeypatch):
monkeypatch.setenv("HERMES_HOME", str(tmp_path))
(tmp_path / "config.yaml").write_text("memory:\n provider: honcho\n honcho:\n workspace: keep-me\n")
monkeypatch.setattr(mig, "provider_present", lambda name: (tmp_path / "plugins" / name).is_dir())
monkeypatch.setattr(mig, "provider_present", lambda name, home: (home / "plugins" / name).is_dir())
return tmp_path
@@ -35,6 +35,22 @@ def test_missing_provider_installs_its_catalog_plugin_and_keeps_config(home, mon
assert calls == ["honcho"]
def test_presence_is_checked_in_the_home_being_migrated(tmp_path, monkeypatch):
"""The update hook walks several profile homes from one process; a provider installed in profile B
must count as present for B even when the process-level home (A) lacks it. Real lookup, no mock."""
a, b = tmp_path / "a", tmp_path / "b"
for h in (a, b):
h.mkdir(); (h / "config.yaml").write_text("memory:\n provider: twin\n")
(b / "plugins" / "twin").mkdir(parents=True)
(b / "plugins" / "twin" / "__init__.py").write_text("class Twin(MemoryProvider): ...\n")
monkeypatch.setenv("HERMES_HOME", str(a))
monkeypatch.setattr(mig, "catalog_source", lambda name: name)
installs: list[Path] = []
assert mig.migrate_home(b, install=lambda n: installs.append(b) or {"ok": True}, say=lambda s: None) is None
assert installs == []
assert mig.migrate_home(a, install=lambda n: installs.append(a) or {"ok": True}, say=lambda s: None) == "twin"
def test_provider_unknown_to_catalog_is_reported_not_installed(home, monkeypatch):
monkeypatch.setattr(mig, "catalog_source", lambda name: None)
said: list[str] = []