fix(memory): migration checks provider presence in the home being migrated
This commit is contained in:
@@ -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. "
|
||||
|
||||
@@ -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] = []
|
||||
|
||||
Reference in New Issue
Block a user