fix(honcho): save_config refuses to rewrite a honcho.json that does not parse

hermes memory setup writes through HonchoMemoryProvider.save_config, which
merged the new values over {} when the existing file could not be parsed
and then replaced the file. same wipe as the oauth and cli write paths,
through a different door. it now reads through _read_config_strict and
raises, so the caller sees the error and the file stays as it was.
This commit is contained in:
Erosika
2026-09-04 15:37:02 -04:00
committed by kshitij
parent f87c915bf8
commit 06e73dde64
2 changed files with 29 additions and 3 deletions
+6 -3
View File
@@ -166,11 +166,14 @@ class HonchoMemoryProvider(DialecticMixin, MemoryProvider):
return False
def save_config(self, values, hermes_home):
"""Merge ``values`` into $HERMES_HOME/honcho.json (Honcho SDK native format)."""
"""Merge ``values`` into $HERMES_HOME/honcho.json (Honcho SDK native format).
A file that exists but does not parse raises instead of being replaced by ``values`` alone."""
from pathlib import Path
from utils import atomic_json_write, read_json_or_empty
from utils import atomic_json_write
from plugins.memory.honcho.oauth import _read_config_strict
config_path = Path(hermes_home) / "honcho.json"
atomic_json_write(config_path, {**read_json_or_empty(config_path), **values}, mode=0o600)
existing = _read_config_strict(config_path)
atomic_json_write(config_path, {**existing, **values}, mode=0o600)
def get_config_schema(self):
return [
+23
View File
@@ -204,3 +204,26 @@ class TestProfileKeyIsolationWarning:
host='hermes', config_path=config_path,
)
assert not any('NOT inherited' in r.message for r in caplog.records)
def test_save_config_refuses_to_replace_a_file_that_does_not_parse(tmp_path, monkeypatch):
"""A corrupt honcho.json must not be rewritten from the new values alone."""
import pytest
from plugins.memory.honcho import HonchoMemoryProvider
config_path = tmp_path / "honcho.json"
config_path.write_text("{ not json")
provider = HonchoMemoryProvider()
with pytest.raises(ValueError):
provider.save_config({"api_key": "hc-test-key"}, str(tmp_path))
assert config_path.read_text() == "{ not json"
def test_save_config_merges_into_a_parseable_file(tmp_path):
from plugins.memory.honcho import HonchoMemoryProvider
config_path = tmp_path / "honcho.json"
config_path.write_text(json.dumps({"hosts": {"other": {"apiKey": "keep-me"}}}))
HonchoMemoryProvider().save_config({"api_key": "hc-test-key"}, str(tmp_path))
data = json.loads(config_path.read_text())
assert data["hosts"]["other"]["apiKey"] == "keep-me" and data["api_key"] == "hc-test-key"